Commit 07df1fec by Arnau Comas Codina

Port Forwarding

parent 5ed6f6b9
Pipeline #1089 failed with stage
in 48 seconds
from openstack.exceptions import ResourceNotFound from openstack.exceptions import ResourceNotFound
from interface.network.port_forwarding import PortForwardingInterface from interface.network.port_forwarding import PortForwardingInterface
from interface.network.resources import FloatingIP, PortForwarding from interface.network.resources import Port, FloatingIP, PortForwarding
from implementation.utils.connection import OpenStackConnection from implementation.utils.connection import OpenStackConnection
class OSPortForwardingManager(PortForwardingInterface, OpenStackConnection): class OSPortForwardingManager(PortForwardingInterface, OpenStackConnection):
# TODO: init ha d'obtenir el rang de floating ips i els ports forwardings # TODO: gestionar els rangs de ports lliures/ocupats i floating ips? aquí o al django o on?
# actuals per gestionar els rangs de ports lliures/ocupats # el delete el podem fer a partir de la ip i no de la instance_id
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
...@@ -19,11 +20,13 @@ class OSPortForwardingManager(PortForwardingInterface, OpenStackConnection): ...@@ -19,11 +20,13 @@ class OSPortForwardingManager(PortForwardingInterface, OpenStackConnection):
for floating_ip in self.floating_ips: for floating_ip in self.floating_ips:
items = self.openstack.network.floating_ip_port_forwardings(floating_ip.id) items = self.openstack.network.floating_ip_port_forwardings(floating_ip.id)
floating_ip.port_forwardings = [PortForwarding(item) for item in items] floating_ip.port_forwardings = [
PortForwarding(item, floating_ip.address) for item in items]
#self.port_forwardings = [ #self.port_forwardings = [
# 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)]
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
...@@ -33,10 +36,9 @@ class OSPortForwardingManager(PortForwardingInterface, OpenStackConnection): ...@@ -33,10 +36,9 @@ class OSPortForwardingManager(PortForwardingInterface, OpenStackConnection):
project_id = self.openstack.auth['project_id'] project_id = self.openstack.auth['project_id']
# fetch internal Neutron port id of the instance by instance_id # fetch internal Neutron port id of the instance by instance_id
internal_port_object = [item for item in self.openstack.network.ports( internal_port_object = self.__get_internal_port_object_from_instance_id(instance_id)
device_id=instance_id)].pop() # pop() is used because returns a list
internal_port_id = internal_port_object.id internal_port_id = internal_port_object.id
internal_ip_address = internal_port_object.fixed_ips[0]['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 # 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
...@@ -53,7 +55,8 @@ class OSPortForwardingManager(PortForwardingInterface, OpenStackConnection): ...@@ -53,7 +55,8 @@ class OSPortForwardingManager(PortForwardingInterface, OpenStackConnection):
description='') description='')
port_forwardings = [ port_forwardings = [
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)]
# DUBTE: l'instància de la connection sempre s'ha d'inicialitzar amb l'objecte auth. # 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 # no es podria compartir? Perquè aquí necessito accedir a funcions del port manager
...@@ -80,15 +83,67 @@ class OSPortForwardingManager(PortForwardingInterface, OpenStackConnection): ...@@ -80,15 +83,67 @@ class OSPortForwardingManager(PortForwardingInterface, OpenStackConnection):
# f"/{floating_ip_id}/port_forwardings", data = payload) # f"/{floating_ip_id}/port_forwardings", data = payload)
#r.json() #r.json()
def remove_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
""" """
pass
# fetch internal Neutron port of the instance by instance_id
internal_port_object = self.__get_internal_port_object_from_instance_id(instance_id)
internal_port_id = internal_port_object.id
internal_ip_address = internal_port_object.ip_address
# find floating ip where port forwarding rule is defined
floating_ip_id = None
for floating_ip in self.openstack.list_floating_ips():
for port_forwarding in floating_ip.port_forwardings:
if (port_forwarding.internal_ip_address == internal_ip_address)
and (port_forwarding.internal_port == internal_port_number):
# found
floating_ip_id = floating_ip.id
break
break
# loop again to fetch port forwarding id
# because is not contained in objects from the above results
port_forwarding_id = None
for port_forwarding in self.openstack.network.floating_ip_port_forwardings(floating_ip_id)
if (port_forwarding.internal_ip_address == internal_ip_address)
and (port_forwarding.internal_port == internal_port_number):
port_forwarding_id = port_forwarding.id
self.openstack.network.delete_port_forwarding(
port_forwarding_id, floating_ip_id)
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
# NOTE: shall we return all rules or filtered by floating ip for example? # fetch internal Neutron port id of the instance by instance_id
internal_port_object = self.__get_internal_port_object_from_instance_id(instance_id)
internal_port_id = internal_port_object.id
internal_ip_address = internal_port_object.ip_address
# fetch port forwardings
instance_port_forwardings = []
for floating_ip in self.floating_ips:
for item in self.openstack.network.port_forwardings(floating_ip.id):
if item.internal_ip_address == internal_ip_address:
instance_port_forwardings.append(PortForwarding(item, floating_ip.address))
return instance_port_forwardings
def __get_internal_port_object_from_instance_id(self, instance_id):
""" Fetches Neutron internal port object from instance_id
""" """
pass
# query ports filtered by keyboard arguments (kwargs), returns a list
results = [Port(item) for item in self.openstack.network.ports(
device_id=instance_id)]
# pick the result, we assume the list lenght is 1
internal_port_object = results.pop()
return internal_port_object
...@@ -10,7 +10,7 @@ class PortForwardingInterface: ...@@ -10,7 +10,7 @@ class PortForwardingInterface:
def create_port_forwarding(self, instance_id, internal_port_number, protocol): def create_port_forwarding(self, instance_id, internal_port_number, protocol):
raise NotImplementedError raise NotImplementedError
def remove_port_forwarding(self, instance_id, internal_port_number): def delete_port_forwarding(self, instance_id, internal_port_number):
raise NotImplementedError raise NotImplementedError
def list_instance_port_forwardings(self, instance_id): def list_instance_port_forwardings(self, instance_id):
......
import json import json
class Port:
""" From the OpenStack Port source data:
- Releveant attributes are stored
- Some methods regarding class representation
"""
def __init__(self, data):
self.id = data['id'] # str
self.ip_address = None # see below
self.ipv6_address = None # see below
self.status = data['status'] # str e.g. 'ACTIVE'
self.device_id = data['device_id'] # str
self.created_at = data['created_at'] # str
self.updated_at = data['updated_at'] # str
if len(data['fixed_ips']):
for ip in data['fixed_ips']:
if ':' in ip['ip_address']: # ipv6
self.ipv6_address = data['fixed_ips'][1]['ip_address'] # str
else:
self.ip_address = data['fixed_ips'][0]['ip_address'] # str
def __repr__(self):
return f"Port({self.ip_address})"
def __str__(self):
return f"Port({self.ip_address})"
def JSON(self):
return json.dumps(self.__dict__)
class FloatingIP: class FloatingIP:
""" From the OpenStack Floating IP source data: """ From the OpenStack Floating IP source data:
- Releveant attributes are stored - Releveant attributes are stored
...@@ -34,22 +66,23 @@ class PortForwarding: ...@@ -34,22 +66,23 @@ class PortForwarding:
- Some methods regarding class representation - Some methods regarding class representation
""" """
def __init__(self, data): def __init__(self, data, floating_ip_address=''):
self.id = data['id'] # str self.id = data['id'] # str
self.protocol = data['protocol'] # str self.protocol = data['protocol'] # str
self.internal_ip_address = data['internal_ip_address'] # str self.internal_ip_address = data['internal_ip_address'] # str
self.external_ip_address = floating_ip_address # str
self.internal_port = data['internal_port'] # number self.internal_port = data['internal_port'] # number
self.external_port = data['external_port'] # number self.external_port = data['external_port'] # number
def __repr__(self): def __repr__(self):
return( return(
f"PortForwarding({self.internal_ip_address}:{self.internal_port}" f"PortForwarding({self.internal_ip_address}:{self.internal_port}"
f" -> {self.external_port})") f" -> {self.external_ip_address}:{self.external_port})")
def __str__(self): def __str__(self):
return( return(
f"PortForwarding({self.internal_ip_address}:{self.internal_port}" f"PortForwarding({self.internal_ip_address}:{self.internal_port}"
f" -> {self.external_port})") f" -> {self.external_ip_address}:{self.external_port})")
def JSON(self): def JSON(self):
return json.dumps(self.__dict__) return json.dumps(self.__dict__)
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