Fixed missing license headers
[osm/vim-emu.git] / src / emuvim / api / openstack / resources / port.py
1 """
2 Copyright (c) 2017 SONATA-NFV and Paderborn University
3 ALL RIGHTS RESERVED.
4
5 Licensed under the Apache License, Version 2.0 (the "License");
6 you may not use this file except in compliance with the License.
7 You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16
17 Neither the name of the SONATA-NFV, Paderborn University
18 nor the names of its contributors may be used to endorse or promote
19 products derived from this software without specific prior written
20 permission.
21
22 This work has been performed in the framework of the SONATA project,
23 funded by the European Commission under Grant number 671517 through
24 the Horizon 2020 and 5G-PPP programmes. The authors would like to
25 acknowledge the contributions of their colleagues of the SONATA
26 partner consortium (www.sonata-nfv.eu).
27 """
28 import logging
29 import threading
30 import uuid
31
32 lock = threading.Lock()
33 intf_names = dict()
34
35
36 class Port:
37 def __init__(self, name, ip_address=None, mac_address=None, floating_ip=None):
38 self.name = name
39 self.intf_name = None
40 self.id = str(uuid.uuid4())
41 self.template_name = name
42 """
43 ip_address is structured like 10.0.0.1/24
44 """
45 self.ip_address = ip_address
46 self.mac_address = mac_address
47 self.floating_ip = floating_ip
48 self.net_name = None
49
50 def set_name(self, name):
51 """
52 Sets the port name.
53
54 :param name: New port name.
55 :type name: ``str``
56 """
57 if self.name == name:
58 return
59
60 # Delete old interface name
61 global lock
62 lock.acquire()
63 if intf_names[self.intf_name][0] == self.id and intf_names[self.intf_name][1] is False:
64 del intf_names[self.intf_name]
65 lock.release()
66
67 self.name = name
68 # Create new interface name
69 self.create_intf_name()
70
71 def create_intf_name(self):
72 """
73 Creates the interface name, while using the first 4 letters of the port name, the specification, if it is an
74 'in' / 'out' port or something else, and a counter value if the name is already used. The counter starts
75 for each name at 0 and can go up to 999. After creating the name each port will post its interface name
76 into the global dictionary and adding his full name. Thus each port can determine if his desired interface
77 name is already used and choose the next one.
78 """
79 split_name = self.name.split(':')
80 if len(split_name) >= 3:
81 if split_name[2] == 'input' or split_name[2] == 'in':
82 self.intf_name = split_name[0][:4] + '-' + \
83 'in'
84 elif split_name[2] == 'output' or split_name[2] == 'out':
85 self.intf_name = split_name[0][:4] + '-' + \
86 'out'
87 else:
88 self.intf_name = split_name[0][:4] + '-' + \
89 split_name[2][:4]
90 else:
91 self.intf_name = self.name[:9]
92
93 global lock
94 lock.acquire()
95 counter = 0
96 global intf_names
97 intf_len = len(self.intf_name)
98 self.intf_name = self.intf_name + '-' + str(counter)[:4]
99 while self.intf_name in intf_names and counter < 999 and not intf_names[self.intf_name][0] == self.id:
100 counter += 1
101 self.intf_name = self.intf_name[:intf_len] + '-' + str(counter)[:4]
102
103 if counter >= 1000:
104 logging.ERROR("Port %s could not create unique interface name (%s)", self.name, self.intf_name)
105 lock.release()
106 return
107
108 updated = False
109 if self.intf_name in intf_names and intf_names[self.intf_name][0] == self.id:
110 updated = True
111
112 intf_names[self.intf_name] = [self.id, updated]
113 lock.release()
114
115 def get_short_id(self):
116 """
117 Gets a shortened ID which only contains first 6 characters.
118
119 :return: The first 6 characters of the UUID.
120 :rtype: ``str``
121 """
122 return str(self.id)[:6]
123
124 def create_port_dict(self, compute):
125 """
126 Creates the port description dictionary.
127
128 :param compute: Requires the compute resource to determine the used network.
129 :type compute: :class:`heat.compute`
130 :return: Returns the description dictionary.
131 :rtype: ``dict``
132 """
133 port_dict = dict()
134 port_dict["admin_state_up"] = True # TODO is it always true?
135 port_dict["device_id"] = "257614cc-e178-4c92-9c61-3b28d40eca44" # TODO find real values
136 port_dict["device_owner"] = "" # TODO do we have such things?
137 net = compute.find_network_by_name_or_id(self.net_name)
138 port_dict["fixed_ips"] = [
139 {
140 "ip_address": self.ip_address.rsplit('/', 1)[0] if self.ip_address is not None else "",
141 "subnet_id": net.subnet_id if net is not None else ""
142 }
143 ]
144 port_dict["id"] = self.id
145 port_dict["mac_address"] = self.mac_address
146 port_dict["name"] = self.name
147 port_dict["network_id"] = net.id if net is not None else ""
148 port_dict["status"] = "ACTIVE" # TODO do we support inactive port?
149 port_dict["tenant_id"] = "abcdefghijklmnopqrstuvwxyz123456" # TODO find real tenant_id
150 return port_dict
151
152 def compare_attributes(self, other):
153 """
154 Does NOT compare ip_address because this function only exists to check if we can
155 update the IP address without any changes
156
157 :param other: The port to compare with
158 :type other: :class:`heat.resources.port`
159 :return: True if the attributes are the same, else False.
160 :rtype: ``bool``
161 """
162 if other is None:
163 return False
164
165 if self.name == other.name and self.floating_ip == other.floating_ip and \
166 self.net_name == other.net_name:
167 return True
168 return False
169
170 def __eq__(self, other):
171 if other is None:
172 return False
173
174 if self.name == other.name and self.ip_address == other.ip_address and \
175 self.mac_address == other.mac_address and \
176 self.floating_ip == other.floating_ip and \
177 self.net_name == other.net_name:
178 return True
179 return False
180
181 def __hash__(self):
182 return hash((self.name,
183 self.ip_address,
184 self.mac_address,
185 self.floating_ip,
186 self.net_name))
187
188 def __del__(self):
189 global lock
190 lock.acquire()
191 global intf_names
192 if self.intf_name in intf_names and intf_names[self.intf_name][0] == self.id:
193 if intf_names[self.intf_name][1] is False:
194 del intf_names[self.intf_name]
195 else:
196 intf_names[self.intf_name][1] = False
197 lock.release()