Commit 5b8b9cae by Arnau Comas Codina

Port Forwarding

parent 841e3e1f
Pipeline #1098 failed with stage
in 56 seconds
from openstack.exceptions import ResourceNotFound from openstack.exceptions import BadRequestException
from interface.network.port_forwarding import PortForwardingInterface from interface.network.port_forwarding import PortForwardingInterface
from interface.network.resources import Port, FloatingIP, PortForwarding from interface.network.resources import Port, FloatingIP, PortForwarding
from implementation.utils.connection import OpenStackConnection from implementation.utils.connection import OpenStackConnection
from implementation.utils.decorators import OpenStackError
import logging
import random
# for limiting the ones that can be allocated over floating ips
RESERVED_PORT_NUMBERS = [22, 80, 9696]
class OSPortForwardingManager(PortForwardingInterface, OpenStackConnection): class OSPortForwardingManager(PortForwardingInterface, OpenStackConnection):
...@@ -27,10 +34,14 @@ class OSPortForwardingManager(PortForwardingInterface, OpenStackConnection): ...@@ -27,10 +34,14 @@ class OSPortForwardingManager(PortForwardingInterface, OpenStackConnection):
# PortForwarding(item) for item in self.openstack.network.port_forwardings(self.floating_ips[0].id)] # PortForwarding(item) for item in self.openstack.network.port_forwardings(self.floating_ips[0].id)]
@OpenStackError
def create_port_forwarding(self, instance_id, internal_port_number, protocol): def create_port_forwarding(self, instance_id, internal_port_number, protocol):
"""DUBTE hem de gestionar condicions com ara que no estigui creat ja """DUBTE hem de gestionar condicions com ara que no estigui creat ja
un port forwarding igual, que la floating_ip no estigui activa, que no un port forwarding igual, que la floating_ip no estigui activa, que no
estigui associat a un router, etc.? estigui associat a un router, etc.?
Les floating ips estan separades de la ip on hi ha les apis dels serveis
d'openstack? Perquè en devstack no, i no es pot habilitar un port extern
que ja es faci servir (s'ha de restringir)?
""" """
project_id = self.openstack.auth['project_id'] project_id = self.openstack.auth['project_id']
...@@ -40,50 +51,33 @@ class OSPortForwardingManager(PortForwardingInterface, OpenStackConnection): ...@@ -40,50 +51,33 @@ class OSPortForwardingManager(PortForwardingInterface, OpenStackConnection):
internal_port_id = internal_port_object.id internal_port_id = internal_port_object.id
internal_ip_address = internal_port_object.ip_address internal_ip_address = internal_port_object.ip_address
# recorrer cada floating ip i cridar una funció que ens torni un port lliure o None, sinó crear nova ip # TODO: recorrer cada floating ip i cridar una funció que ens torni un port lliure o None, sinó crear nova ip
floating_ip_id = self.floating_ips[0].id floating_ip_id = self.floating_ips[0].id
external_port = "8000" #get_free_port() from list of ports floating_ip_address = self.floating_ips[0].address
# floating_ip_id = "3179d648-9bb0-4871-854c-efffceb74fb0" #get_floating_ip_id
self.openstack.network.create_port_forwarding( external_port = self.__obtain_free_port_by_floating_ip_id(floating_ip_id)
print(f"PORT {external_port}")
return PortForwarding(self.openstack.network.create_port_forwarding(
floatingip_id=floating_ip_id, floatingip_id=floating_ip_id,
internal_port_id=internal_port_id, internal_port_id=internal_port_id,
internal_ip_address=internal_ip_address, internal_ip_address=internal_ip_address,
internal_port=internal_port_number, internal_port=int(internal_port_number),
external_port=external_port, external_port=external_port,
protocol=protocol, protocol=protocol,
description='') description=''), floating_ip_address)
port_forwardings = [ # more handcrafted alternatives
PortForwarding(item) for item in self.openstack.network.port_forwardings(
self.floating_ips[0].id)] #res = self.openstack.network.post(
# f"/floatingips/{floating_ip_id}/port_forwardings", json=payload)
# DUBTE: l'instància de la connection sempre s'ha d'inicialitzar amb l'objecte auth.
# no es podria compartir? Perquè aquí necessito accedir a funcions del port manager
# (internal_port_id no coincideix amb la instance_id)
# sinó s'haurà de fer a un nivell superior? de cercar-lo i passar-lo per paràmetre aquí
# on ha d'estar aquesta lògica doncs?
payload = {
"port_forwarding": {
"project_id": f"{project_id}",
"protocol": f"{protocol}",
"internal_ip_address": f"{instance_id}",
"internal_port": f"{internal_port_number}",
"internal_port_id": f"{internal_port_id}",
"external_port": f"{external_port}"
}
}
# create a ks client and get token or do a post directly with client
#ks = self.obtain_keystone_client()
#print(ks)
#r = requests.post("http://vm.niif.cloud.bme.hu:18686/v2.0/floatingips" \ #r = requests.post("http://vm.niif.cloud.bme.hu:18686/v2.0/floatingips" \
# f"/{floating_ip_id}/port_forwardings", data = payload) # f"/{floating_ip_id}/port_forwardings", data = payload)
#r.json() #r.json()
@OpenStackError
def delete_port_forwarding(self, instance_id, internal_port_number): def delete_port_forwarding(self, instance_id, internal_port_number):
""" Removes port forwarding rule """ Removes port forwarding rule
""" """
...@@ -97,8 +91,8 @@ class OSPortForwardingManager(PortForwardingInterface, OpenStackConnection): ...@@ -97,8 +91,8 @@ class OSPortForwardingManager(PortForwardingInterface, OpenStackConnection):
floating_ip_id = None floating_ip_id = None
for floating_ip in self.openstack.list_floating_ips(): for floating_ip in self.openstack.list_floating_ips():
for port_forwarding in floating_ip.port_forwardings: for port_forwarding in floating_ip.port_forwardings:
if (port_forwarding.internal_ip_address == internal_ip_address) if ((port_forwarding.internal_ip_address == internal_ip_address)
and (port_forwarding.internal_port == internal_port_number): and (port_forwarding.internal_port == internal_port_number)):
# found # found
floating_ip_id = floating_ip.id floating_ip_id = floating_ip.id
break break
...@@ -107,15 +101,16 @@ class OSPortForwardingManager(PortForwardingInterface, OpenStackConnection): ...@@ -107,15 +101,16 @@ class OSPortForwardingManager(PortForwardingInterface, OpenStackConnection):
# loop again to fetch port forwarding id # loop again to fetch port forwarding id
# because is not contained in objects from the above results # because is not contained in objects from the above results
port_forwarding_id = None port_forwarding_id = None
for port_forwarding in self.openstack.network.floating_ip_port_forwardings(floating_ip_id) for port_forwarding in self.openstack.network.floating_ip_port_forwardings(floating_ip_id):
if (port_forwarding.internal_ip_address == internal_ip_address) if ((port_forwarding.internal_ip_address == internal_ip_address)
and (port_forwarding.internal_port == internal_port_number): and (port_forwarding.internal_port == internal_port_number)):
port_forwarding_id = port_forwarding.id port_forwarding_id = port_forwarding.id
self.openstack.network.delete_port_forwarding( self.openstack.network.delete_port_forwarding(
port_forwarding_id, floating_ip_id) port_forwarding_id, floating_ip_id)
@OpenStackError
def list_instance_port_forwardings(self, instance_id): def list_instance_port_forwardings(self, instance_id):
""" Lists all port forwarding rules defined from a vm instance """ Lists all port forwarding rules defined from a vm instance
""" """
...@@ -147,3 +142,32 @@ class OSPortForwardingManager(PortForwardingInterface, OpenStackConnection): ...@@ -147,3 +142,32 @@ class OSPortForwardingManager(PortForwardingInterface, OpenStackConnection):
internal_port_object = results.pop() internal_port_object = results.pop()
return internal_port_object return internal_port_object
def __obtain_free_port_by_floating_ip_id(self, floating_ip_id):
""" Pot una vm tenir port forwardings en diferents floating ips?
"""
# initialize list with the full range of ports
port_numbers = list(range(1, 2**16))
# remove reserved ones
for reserved in RESERVED_PORT_NUMBERS:
if reserved in port_numbers:
port_numbers.remove(reserved)
# query all current port forwardings from the floating ip
already_allocated_port_numbers = []
for item in self.openstack.network.port_forwardings(floating_ip_id):
already_allocated_port_numbers.append(PortForwarding(item).external_port)
# remove already allocated ports from range list
for allocated in already_allocated_port_numbers:
if allocated in port_numbers:
port_numbers.remove(allocated)
free_port_number = None
if len(port_numbers):
free_port_number = random.choice(port_numbers)
return free_port_number
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment