X-Git-Url: https://osm.etsi.org/gitweb/?a=blobdiff_plain;f=src%2Femuvim%2Fapi%2Fopenstack%2Fresources%2Fport.py;fp=src%2Femuvim%2Fapi%2Fopenstack%2Fresources%2Fport.py;h=a280fb6a447aa3e2f4717cd1873b0016b9079a81;hb=00199782de7042b51927bbbac5540d6f671597bb;hp=0000000000000000000000000000000000000000;hpb=0d8066654408ea1994d599c12c61b13709055a2d;p=osm%2Fvim-emu.git diff --git a/src/emuvim/api/openstack/resources/port.py b/src/emuvim/api/openstack/resources/port.py new file mode 100644 index 0000000..a280fb6 --- /dev/null +++ b/src/emuvim/api/openstack/resources/port.py @@ -0,0 +1,170 @@ +import logging +import threading +import uuid + +lock = threading.Lock() +intf_names = dict() + + +class Port: + def __init__(self, name, ip_address=None, mac_address=None, floating_ip=None): + self.name = name + self.intf_name = None + self.id = str(uuid.uuid4()) + self.template_name = name + """ + ip_address is structured like 10.0.0.1/24 + """ + self.ip_address = ip_address + self.mac_address = mac_address + self.floating_ip = floating_ip + self.net_name = None + + def set_name(self, name): + """ + Sets the port name. + + :param name: New port name. + :type name: ``str`` + """ + if self.name == name: + return + + # Delete old interface name + global lock + lock.acquire() + if intf_names[self.intf_name][0] == self.id and intf_names[self.intf_name][1] is False: + del intf_names[self.intf_name] + lock.release() + + self.name = name + # Create new interface name + self.create_intf_name() + + def create_intf_name(self): + """ + Creates the interface name, while using the first 4 letters of the port name, the specification, if it is an + 'in' / 'out' port or something else, and a counter value if the name is already used. The counter starts + for each name at 0 and can go up to 999. After creating the name each port will post its interface name + into the global dictionary and adding his full name. Thus each port can determine if his desired interface + name is already used and choose the next one. + """ + split_name = self.name.split(':') + if len(split_name) >= 3: + if split_name[2] == 'input' or split_name[2] == 'in': + self.intf_name = split_name[0][:4] + '-' + \ + 'in' + elif split_name[2] == 'output' or split_name[2] == 'out': + self.intf_name = split_name[0][:4] + '-' + \ + 'out' + else: + self.intf_name = split_name[0][:4] + '-' + \ + split_name[2][:4] + else: + self.intf_name = self.name[:9] + + global lock + lock.acquire() + counter = 0 + global intf_names + intf_len = len(self.intf_name) + self.intf_name = self.intf_name + '-' + str(counter)[:4] + while self.intf_name in intf_names and counter < 999 and not intf_names[self.intf_name][0] == self.id: + counter += 1 + self.intf_name = self.intf_name[:intf_len] + '-' + str(counter)[:4] + + if counter >= 1000: + logging.ERROR("Port %s could not create unique interface name (%s)", self.name, self.intf_name) + lock.release() + return + + updated = False + if self.intf_name in intf_names and intf_names[self.intf_name][0] == self.id: + updated = True + + intf_names[self.intf_name] = [self.id, updated] + lock.release() + + def get_short_id(self): + """ + Gets a shortened ID which only contains first 6 characters. + + :return: The first 6 characters of the UUID. + :rtype: ``str`` + """ + return str(self.id)[:6] + + def create_port_dict(self, compute): + """ + Creates the port description dictionary. + + :param compute: Requires the compute resource to determine the used network. + :type compute: :class:`heat.compute` + :return: Returns the description dictionary. + :rtype: ``dict`` + """ + port_dict = dict() + port_dict["admin_state_up"] = True # TODO is it always true? + port_dict["device_id"] = "257614cc-e178-4c92-9c61-3b28d40eca44" # TODO find real values + port_dict["device_owner"] = "" # TODO do we have such things? + net = compute.find_network_by_name_or_id(self.net_name) + port_dict["fixed_ips"] = [ + { + "ip_address": self.ip_address.rsplit('/', 1)[0] if self.ip_address is not None else "", + "subnet_id": net.subnet_id if net is not None else "" + } + ] + port_dict["id"] = self.id + port_dict["mac_address"] = self.mac_address + port_dict["name"] = self.name + port_dict["network_id"] = net.id if net is not None else "" + port_dict["status"] = "ACTIVE" # TODO do we support inactive port? + port_dict["tenant_id"] = "abcdefghijklmnopqrstuvwxyz123456" # TODO find real tenant_id + return port_dict + + def compare_attributes(self, other): + """ + Does NOT compare ip_address because this function only exists to check if we can + update the IP address without any changes + + :param other: The port to compare with + :type other: :class:`heat.resources.port` + :return: True if the attributes are the same, else False. + :rtype: ``bool`` + """ + if other is None: + return False + + if self.name == other.name and self.floating_ip == other.floating_ip and \ + self.net_name == other.net_name: + return True + return False + + def __eq__(self, other): + if other is None: + return False + + if self.name == other.name and self.ip_address == other.ip_address and \ + self.mac_address == other.mac_address and \ + self.floating_ip == other.floating_ip and \ + self.net_name == other.net_name: + return True + return False + + def __hash__(self): + return hash((self.name, + self.ip_address, + self.mac_address, + self.floating_ip, + self.net_name)) + + def __del__(self): + global lock + lock.acquire() + global intf_names + if self.intf_name in intf_names and intf_names[self.intf_name][0] == self.id: + if intf_names[self.intf_name][1] is False: + del intf_names[self.intf_name] + else: + intf_names[self.intf_name][1] = False + lock.release()