Commit 07df1fec by Arnau Comas Codina

Port Forwarding

parent 5ed6f6b9
Pipeline #1089 failed with stage
in 48 seconds
from openstack.exceptions import ResourceNotFound
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
class OSPortForwardingManager(PortForwardingInterface, OpenStackConnection):
# TODO: init ha d'obtenir el rang de floating ips i els ports forwardings
# actuals per gestionar els rangs de ports lliures/ocupats
# TODO: gestionar els rangs de ports lliures/ocupats i floating ips? aquí o al django o on?
# el delete el podem fer a partir de la ip i no de la instance_id
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
......@@ -19,11 +20,13 @@ class OSPortForwardingManager(PortForwardingInterface, OpenStackConnection):
for floating_ip in self.floating_ips:
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 = [
# 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):
"""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
......@@ -33,10 +36,9 @@ class OSPortForwardingManager(PortForwardingInterface, OpenStackConnection):
project_id = self.openstack.auth['project_id']
# fetch internal Neutron port id of the instance by instance_id
internal_port_object = [item for item in self.openstack.network.ports(
device_id=instance_id)].pop() # pop() is used because returns a list
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.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
floating_ip_id = self.floating_ips[0].id
......@@ -53,7 +55,8 @@ class OSPortForwardingManager(PortForwardingInterface, OpenStackConnection):
description='')
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.
# no es podria compartir? Perquè aquí necessito accedir a funcions del port manager
......@@ -80,15 +83,67 @@ class OSPortForwardingManager(PortForwardingInterface, OpenStackConnection):
# f"/{floating_ip_id}/port_forwardings", data = payload)
#r.json()
def remove_port_forwarding(self, instance_id, internal_port_number):
"""
Removes port forwarding rule
def delete_port_forwarding(self, instance_id, internal_port_number):
""" 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):
""" 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:
def create_port_forwarding(self, instance_id, internal_port_number, protocol):
raise NotImplementedError
def remove_port_forwarding(self, instance_id, internal_port_number):
def delete_port_forwarding(self, instance_id, internal_port_number):
raise NotImplementedError
def list_instance_port_forwardings(self, instance_id):
......
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:
""" From the OpenStack Floating IP source data:
- Releveant attributes are stored
......@@ -34,22 +66,23 @@ class PortForwarding:
- Some methods regarding class representation
"""
def __init__(self, data):
def __init__(self, data, floating_ip_address=''):
self.id = data['id'] # str
self.protocol = data['protocol'] # 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.external_port = data['external_port'] # number
def __repr__(self):
return(
f"PortForwarding({self.internal_ip_address}:{self.internal_port}"
f" -> {self.external_port})")
f" -> {self.external_ip_address}:{self.external_port})")
def __str__(self):
return(
f"PortForwarding({self.internal_ip_address}:{self.internal_port}"
f" -> {self.external_port})")
f" -> {self.external_ip_address}:{self.external_port})")
def JSON(self):
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