1 # Copyright (c) 2015 SONATA-NFV and Paderborn University
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
8 # http://www.apache.org/licenses/LICENSE-2.0
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
16 # Neither the name of the SONATA-NFV, Paderborn University
17 # nor the names of its contributors may be used to endorse or promote
18 # products derived from this software without specific prior written
21 # This work has been performed in the framework of the SONATA project,
22 # funded by the European Commission under Grant number 671517 through
23 # the Horizon 2020 and 5G-PPP programmes. The authors would like to
24 # acknowledge the contributions of their colleagues of the SONATA
25 # partner consortium (www.sonata-nfv.eu).
30 lock
= threading
.Lock()
35 def __init__(self
, name
, ip_address
=None,
36 mac_address
=None, floating_ip
=None):
39 self
.id = str(uuid
.uuid4())
40 self
.template_name
= name
42 ip_address is structured like 10.0.0.1/24
44 self
.ip_address
= ip_address
45 self
.mac_address
= mac_address
46 self
.floating_ip
= floating_ip
49 def set_name(self
, name
):
53 :param name: New port name.
59 # Delete old interface name
62 if intf_names
[self
.intf_name
][0] == self
.id and intf_names
[self
.intf_name
][1] is False:
63 del intf_names
[self
.intf_name
]
67 # Create new interface name
68 self
.create_intf_name()
70 def create_intf_name(self
):
72 Creates the interface name, while using the first 4 letters of the port name, the specification, if it is an
73 'in' / 'out' port or something else, and a counter value if the name is already used. The counter starts
74 for each name at 0 and can go up to 999. After creating the name each port will post its interface name
75 into the global dictionary and adding his full name. Thus each port can determine if his desired interface
76 name is already used and choose the next one.
78 split_name
= self
.name
.split(':')
79 if len(split_name
) >= 3:
80 if split_name
[2] == 'input' or split_name
[2] == 'in':
81 self
.intf_name
= split_name
[0][:4] + '-' + \
83 elif split_name
[2] == 'output' or split_name
[2] == 'out':
84 self
.intf_name
= split_name
[0][:4] + '-' + \
87 self
.intf_name
= split_name
[0][:4] + '-' + \
90 self
.intf_name
= self
.name
[:9]
96 intf_len
= len(self
.intf_name
)
97 self
.intf_name
= self
.intf_name
+ '-' + str(counter
)[:4]
98 while self
.intf_name
in intf_names
and counter
< 999 and not intf_names
[
99 self
.intf_name
][0] == self
.id:
101 self
.intf_name
= self
.intf_name
[:intf_len
] + '-' + str(counter
)[:4]
105 "Port %s could not create unique interface name (%s)", self
.name
, self
.intf_name
)
110 if self
.intf_name
in intf_names
and intf_names
[self
.intf_name
][0] == self
.id:
113 intf_names
[self
.intf_name
] = [self
.id, updated
]
116 def get_short_id(self
):
118 Gets a shortened ID which only contains first 6 characters.
120 :return: The first 6 characters of the UUID.
123 return str(self
.id)[:6]
125 def create_port_dict(self
, compute
):
127 Creates the port description dictionary.
129 :param compute: Requires the compute resource to determine the used network.
130 :type compute: :class:`heat.compute`
131 :return: Returns the description dictionary.
135 port_dict
["admin_state_up"] = True # TODO is it always true?
136 # TODO find real values
137 port_dict
["device_id"] = "257614cc-e178-4c92-9c61-3b28d40eca44"
138 port_dict
["device_owner"] = "" # TODO do we have such things?
139 net
= compute
.find_network_by_name_or_id(self
.net_name
)
140 port_dict
["fixed_ips"] = [
142 "ip_address": self
.ip_address
.rsplit('/', 1)[0] if self
.ip_address
is not None else "",
143 "subnet_id": net
.subnet_id
if net
is not None else ""
146 port_dict
["id"] = self
.id
147 port_dict
["mac_address"] = self
.mac_address
148 port_dict
["name"] = self
.name
149 port_dict
["network_id"] = net
.id if net
is not None else ""
150 port_dict
["status"] = "ACTIVE" # TODO do we support inactive port?
151 # TODO find real tenant_id
152 port_dict
["tenant_id"] = "abcdefghijklmnopqrstuvwxyz123456"
155 def compare_attributes(self
, other
):
157 Does NOT compare ip_address because this function only exists to check if we can
158 update the IP address without any changes
160 :param other: The port to compare with
161 :type other: :class:`heat.resources.port`
162 :return: True if the attributes are the same, else False.
168 if self
.name
== other
.name
and self
.floating_ip
== other
.floating_ip
and \
169 self
.net_name
== other
.net_name
:
173 def __eq__(self
, other
):
177 if self
.name
== other
.name
and self
.ip_address
== other
.ip_address
and \
178 self
.mac_address
== other
.mac_address
and \
179 self
.floating_ip
== other
.floating_ip
and \
180 self
.net_name
== other
.net_name
:
185 return hash((self
.name
,
195 if self
.intf_name
in intf_names
and intf_names
[self
.intf_name
][0] == self
.id:
196 if intf_names
[self
.intf_name
][1] is False:
197 del intf_names
[self
.intf_name
]
199 intf_names
[self
.intf_name
][1] = False