resolve python2->python3 issues
[vfc/nfvo/lcm.git] / lcm / pub / nfvi / vim / api / openstack / network.py
1 # Copyright 2016 ZTE Corporation.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #         http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 import logging
16 import sys
17 import traceback
18
19 from neutronclient.common.exceptions import NeutronClientException
20 from neutronclient.common.exceptions import NetworkNotFoundClient
21 from neutronclient.common.exceptions import NotFound as SubnetNotFound
22
23 from lcm.pub.nfvi.vim.api.openstack import neutronbase
24 from lcm.pub.nfvi.vim.lib.syscomm import fun_name
25 from lcm.pub.nfvi.vim.api.openstack import project
26 from lcm.pub.nfvi.vim import const
27 from lcm.pub.nfvi.vim.lib.vimexception import VimException
28
29 logger = logging.getLogger(__name__)
30
31
32 def query_net(auth_info, net_id):
33     neutron = neutronbase.get_neutron_default(fun_name(), auth_info)
34     net = None
35     try:
36         net = neutron.show_network(net_id)["network"]
37         keystone = auth_info["keystone"]
38         tenant = keystone.tenants.get(tenant_id=net["tenant_id"])
39     except NetworkNotFoundClient as e:
40         logger.warn("NetworkNotFoundClient: %s", e.args[0])
41         return [2, e.args[0]]
42     return [0, {
43         "id": net["id"],
44         "name": net["name"],
45         "status": net["status"],
46         "admin_state_up": net["admin_state_up"],
47         "network_type": net["provider:network_type"],
48         "physical_network": net["provider:physical_network"],
49         "segmentation_id": net["provider:segmentation_id"],
50         "tenant_id": net["tenant_id"],
51         "tenant_name": tenant.name,
52         "subnets": net["subnets"],
53         "shared": net["shared"],
54         "router_external": net["router:external"]}
55     ]
56
57
58 def query_nets(auth_info):
59     neutron = neutronbase.get_neutron_default(fun_name(), auth_info)
60     keystone = auth_info["keystone"]
61     tenants_map = {}
62     tenants = keystone.tenants.list()
63     for tenant in tenants:
64         tenants_map[tenant.id] = tenant.name
65
66     nets = neutron.list_networks()
67     return [0, {"networks": [{
68         "id": net["id"],
69         "name": net["name"],
70         "status": net["status"],
71         "admin_state_up": net["admin_state_up"],
72         "network_type": net["provider:network_type"],
73         "physical_network": net["provider:physical_network"],
74         "segmentation_id": net["provider:segmentation_id"],
75         "tenant_id": net["tenant_id"],
76         "tenant_name": tenants_map[net["tenant_id"]] if net["tenant_id"] in tenants_map else "unknown",
77         "subnets": net["subnets"],
78         "shared": net["shared"],
79         "router_external": net["router:external"]
80     } for net in nets["networks"]]}]
81
82
83 def query_subnet(auth_info, subnet_id):
84     neutron = neutronbase.get_neutron_default(fun_name(), auth_info)
85     subnet_info = None
86     try:
87         subnet_info = neutron.show_subnet(subnet_id)["subnet"]
88     except SubnetNotFound as e:
89         logger.warn("SubnetNotFound: %s", e.args[0])
90         return [2, e.args[0]]
91     ret = [0, {}]
92     ret[1]["id"] = subnet_id
93     ret[1]["name"] = subnet_info["name"]
94     ret[1]["status"] = ""
95     ret[1]["ip_version"] = subnet_info["ip_version"]
96     ret[1]["cidr"] = subnet_info["cidr"]
97     ret[1]["allocation_pools"] = subnet_info["allocation_pools"]
98     ret[1]["enable_dhcp"] = subnet_info["enable_dhcp"]
99     ret[1]["gateway_ip"] = subnet_info["gateway_ip"]
100     ret[1]["host_routes"] = subnet_info["host_routes"]
101     ret[1]["dns_nameservers"] = subnet_info["dns_nameservers"]
102     return ret
103
104
105 def query_port(auth_info, port_id):
106     neutron = neutronbase.get_neutron_default(fun_name(), auth_info)
107     port_info = None
108     try:
109         port_info = neutron.show_port(port_id)["port"]
110     except NeutronClientException as e:
111         logger.warn("NeutronClientException: %s", e.args[0])
112         return [2, e.args[0]]
113     ret = [0, {}]
114     ret[1]["id"] = port_id
115     ret[1]["name"] = port_info["name"]
116     ret[1]["network_id"] = port_info["network_id"]
117     ret[1]["tenant_id"] = port_info["tenant_id"]
118     if "fixed_ips" in port_info and port_info["fixed_ips"]:
119         ret[1]["ip"] = port_info["fixed_ips"][0]["ip_address"]
120         ret[1]["subnet_id"] = port_info["fixed_ips"][0]["subnet_id"]
121     else:
122         ret[1]["ip"] = ""
123         ret[1]["subnet_id"] = ""
124     ret[1]["mac_address"] = port_info["mac_address"]
125     ret[1]["status"] = port_info["status"]
126     ret[1]["admin_state_up"] = port_info["admin_state_up"]
127     ret[1]["device_id"] = port_info["device_id"]
128     return ret
129
130
131 def get_subnet_id(neutron, data, network_id):
132     subnet_id = None
133     if "subnet_name" in data and data["subnet_name"]:
134         all_subnets = neutron.list_subnets()
135         filter_subnets = [subnet for subnet in all_subnets["subnets"] if subnet["name"] == data["subnet_name"] and subnet["network_id"] == network_id]
136         count_filter_subnets = len(filter_subnets)
137         if 1 > count_filter_subnets:
138             logger.error("Subnet name(%s) does not exist" % data["subnet_name"])
139             raise VimException("Subnet name(%s) does not exist" % data["subnet_name"])
140         if 1 < count_filter_subnets:
141             for subnet in filter_subnets:
142                 logger.error("subnet_id=%s", subnet["id"])
143             raise VimException("%d subnet(%s) exist in network(%s)"
144                                % (count_filter_subnets, data["subnet_name"], data["network_name"]))
145         subnet_id = filter_subnets[0]['id']
146     else:
147         subnets = neutron.list_subnets()
148         filter_subnets = [subnet for subnet in subnets["subnets"] if subnet["network_id"] == network_id]
149         if filter_subnets:
150             subnet_id = filter_subnets[0]["id"]
151     return subnet_id
152
153
154 def create_port(auth_info, data):
155     tenant_id = project.get_tenant_id(fun_name(), auth_info, data["tenant_name"])
156
157     neutron_admin = neutronbase.get_neutron_default(fun_name(), auth_info)
158     all_nets = neutron_admin.list_networks()
159     filter_nets = [net for net in all_nets['networks'] if net['name'] == data["network_name"]]
160     sel_nets = [net for net in filter_nets if net['tenant_id'] == tenant_id or (net['tenant_id'] != tenant_id and net['shared'])]
161     count_sel_nets = len(sel_nets)
162     if 1 > count_sel_nets:
163         logger.error("Network(%s) does not exist" % data["network_name"])
164         raise VimException("Network(%s) does not exist" % data["network_name"])
165     if 1 < count_sel_nets:
166         for net in sel_nets:
167             logger.error("net_id=%s", net["id"])
168         raise VimException("%d networks(%s) exist in tenant(%s)"
169                            % (count_sel_nets, data["network_name"], data["tenant_name"]))
170     network_id = sel_nets[0]['id']
171     if tenant_id != sel_nets[0]['tenant_id']:
172         neutron = neutronbase.get_neutron_by_tenant_id(fun_name(), auth_info, sel_nets[0]['tenant_id'])
173     else:
174         neutron = neutronbase.get_neutron(fun_name(), auth_info, data["tenant_name"])
175
176     # get subnet id
177     subnet_id = get_subnet_id(neutron_admin, data, network_id)
178
179     # check port
180     port_data = None
181     ports = neutron.list_ports()
182     sel_ports = [port for port in ports['ports'] if port['tenant_id'] == tenant_id and port['network_id'] == network_id]
183     filter_ports = []
184     for port in sel_ports:
185         if port['name'] == data["port_name"] and port['fixed_ips']:
186             for fixed_ip in port['fixed_ips']:
187                 if fixed_ip['subnet_id'] == subnet_id:
188                     filter_ports.append(port)
189                     break
190     count_filter_ports = len(filter_ports)
191     if 1 < count_filter_ports:
192         for port in filter_ports:
193             logger.error("port_id=%s", port["id"])
194         raise VimException("%d port(%s) exist in subnet(%s)"
195                            % (count_filter_ports, data["port_name"], data["subnet_name"]))
196     if 1 == len(filter_ports):
197         logger.debug("Port(%s) is exist!" % data["port_name"])
198         port_data = {'status': filter_ports[0]['status'],
199                      'id': filter_ports[0]['id'],
200                      'name': filter_ports[0]['name'],
201                      'network_id': filter_ports[0]['network_id'],
202                      const.RES_TYPE_KEY: const.RES_TYPE_EXIST}
203         return [0, port_data]
204
205     # create port
206     create_param = {
207         'port': {
208             'name': data["port_name"],
209             'admin_state_up': True,
210             'network_id': network_id,
211             'security_groups': [],
212             'tenant_id': tenant_id
213         }
214     }
215     if "mac_address" in data and data["mac_address"]:
216         create_param['port']['mac_address'] = data["mac_address"]
217     if "vnic_type" in data and data["vnic_type"]:
218         create_param['port']['binding:vnic_type'] = data["vnic_type"]
219     if "bandwidth" in data and data["bandwidth"]:
220         create_param['port']['bandwidth'] = int(data["bandwidth"])
221     if "bond" in data and data["bond"]:
222         create_param['port']['bond'] = int(data["bond"])
223     if "macbond" in data and data["macbond"]:
224         if 'mac_address' in create_param['port']:
225             create_param['port']['mac_address'] += (',' + data["macbond"])
226         else:
227             create_param['port']['mac_address'] = data["macbond"]
228     if "ip" in data and data["ip"]:
229         if subnet_id:
230             create_param['port']['fixed_ips'] = [{"subnet_id": subnet_id, "ip_address": data["ip"]}]
231
232     if "allowed_address_pairs" in data and data["allowed_address_pairs"]:
233         create_param['port']['allowed_address_pairs'] = data["allowed_address_pairs"]
234     logger.info("[%s]call neutron.create_port(%s)" % (fun_name(), str(create_param)))
235     port_created = None
236     try:
237         port_created = neutron.create_port(create_param)
238     except NeutronClientException as ex:
239         logger.info("create_port exception: %s, %s", str(sys.exc_info()), ex.args[0])
240         create_param['port'].pop('security_groups')
241         if 'allowed_address_pairs' in create_param['port']:
242             create_param['port'].pop('allowed_address_pairs')
243         logger.info("[%s]recall neutron.create_port(%s)" % (fun_name(), str(create_param)))
244         port_created = neutron.create_port(create_param)
245     if port_created:
246         port_data = {'status': port_created['port']['status'],
247                      'id': port_created['port']['id'],
248                      'name': port_created['port']['name'],
249                      'network_id': port_created['port']['network_id'],
250                      const.RES_TYPE_KEY: const.RES_TYPE_NEW}
251     return [0, port_data]
252
253
254 def create_network(auth_info, data):
255     neutron = neutronbase.get_neutron(fun_name(), auth_info, data["tenant"])
256     tenant_id = project.get_tenant_id(fun_name(), auth_info, data["tenant"])
257
258     neutron_admin = neutronbase.get_neutron_default(fun_name(), auth_info)
259     all_nets = neutron_admin.list_networks()
260     filter_nets = [net for net in all_nets['networks'] if net['name'] == data["network_name"]]
261     sel_nets = [net for net in filter_nets if net['tenant_id'] == tenant_id or (net['tenant_id'] != tenant_id and net['shared'])]
262     count_sel_nets = len(sel_nets)
263     if 1 < count_sel_nets:
264         for sel_net in sel_nets:
265             logger.info("net_id=%s, net_tenant_id=%s", sel_net["id"], sel_net['tenant_id'])
266         raise VimException("Already %d networks are found with name %s" % (count_sel_nets, data["network_name"]))
267
268     network_data = None
269     if sel_nets:
270         if sel_nets[0]['tenant_id'] != tenant_id:
271             neutron = neutronbase.get_neutron_by_tenant_id(fun_name(), auth_info, sel_nets[0]['tenant_id'])
272         all_subnets = neutron_admin.list_subnets()
273         filter_subnets = [subnet for subnet in all_subnets["subnets"] if subnet["network_id"] == sel_nets[0]["id"]]
274         network_data = {
275             "status": sel_nets[0]["status"],
276             "id": sel_nets[0]["id"],
277             "name": data["network_name"],
278             "provider:segmentation_id": sel_nets[0]["provider:segmentation_id"],
279             "provider:network_type": sel_nets[0]["provider:network_type"],
280             const.RES_TYPE_KEY: const.RES_TYPE_EXIST,
281             "subnet_list": [
282                 {
283                     "id": subnet["id"],
284                     "name": subnet["name"],
285                     const.RES_TYPE_KEY: const.RES_TYPE_EXIST
286                 }for subnet in filter_subnets
287             ]
288         }
289     else:
290         create_params = {
291             'network': {
292                 'name': data["network_name"],
293                 'admin_state_up': True,
294                 'tenant_id': tenant_id,
295                 'shared': "shared" in data and int(data["shared"]) == const.SHARED_NET}}
296         if "mtu" in data and int(data["mtu"]) != const.DEFAULT_MTU:
297             create_params['network']['mtu'] = int(data["mtu"])
298         if "vlan_transparent" in data and int(data["vlan_transparent"]) == const.SUPPORT_VLAN_TRANSPARENT:
299             create_params['network']['vlan-transparent'] = True
300         if "network_type" in data and data['network_type']:
301             create_params['network']['provider:network_type'] = data['network_type']
302         if "segmentation_id" in data and data['segmentation_id']:
303             create_params['network']['provider:segmentation_id'] = int(data['segmentation_id'])
304         if "physical_network" in data and data['physical_network']:
305             create_params['network']['provider:physical_network'] = data['physical_network']
306
307         logger.info("[%s]call neutron.create_network(%s)" % (fun_name(), str(create_params)))
308         network_created = neutron.create_network(create_params)
309         network_data = {"status": network_created['network']['status'],
310                         "id": network_created['network']['id'],
311                         "name": data["network_name"],
312                         "provider:segmentation_id": network_created['network']['provider:segmentation_id'],
313                         "provider:network_type": network_created['network']['provider:network_type'],
314                         const.RES_TYPE_KEY: const.RES_TYPE_NEW,
315                         "subnet_list": []}
316
317     # subnet create
318     exist_subnet_names = [subnet["name"] for subnet in network_data["subnet_list"]]
319     need_rollback, ret_error = False, None
320     if "subnet_list" in data and data["subnet_list"]:
321         for subnet_data in data["subnet_list"]:
322             if subnet_data["subnet_name"] in exist_subnet_names:
323                 continue
324             ret = create_subnet(neutron, network_data["id"], subnet_data)
325             if ret[0] != 0:
326                 need_rollback, ret_error = True, ret
327                 break
328             network_data["subnet_list"].append(ret[1])
329
330     # rollback when failed to create subnet
331     if need_rollback:
332         rollback(neutron_admin, network_data)
333         return ret_error
334
335     return [0, network_data]
336
337
338 def create_subnet(neutron, network_id, data):
339     all_subnets = neutron.list_subnets()
340     filter_subnets = [subnet for subnet in all_subnets["subnets"]
341                       if subnet["network_id"] == network_id and subnet["name"] == data["subnet_name"]]
342     if filter_subnets:
343         return [0, {
344             "id": filter_subnets[0]["id"],
345             "name": data["subnet_name"],
346             const.RES_TYPE_KEY: const.RES_TYPE_EXIST
347         }]
348     try:
349         create_params = {
350             'subnet': {
351                 'network_id': network_id,
352                 'name': data["subnet_name"],
353                 'cidr': data["cidr"],
354                 'ip_version': int(data["ip_version"]) if "ip_version" in data else const.IPV4, }}
355         create_params["subnet"]["enable_dhcp"] = ("enable_dhcp" in data and int(data["enable_dhcp"]) == const.ENABLE_DHCP)
356         if "gateway_ip" in data and data["gateway_ip"]:
357             create_params["subnet"]["gateway_ip"] = data["gateway_ip"]
358         else:
359             create_params["subnet"]["gateway_ip"] = None
360         if "dns_nameservers" in data and data["dns_nameservers"]:
361             create_params["subnet"]["dns_nameservers"] = data["dns_nameservers"]
362         if "allocation_pools" in data and data["allocation_pools"]:
363             create_params["subnet"]["allocation_pools"] = data["allocation_pools"]
364         if "host_routes" in data and data["host_routes"]:
365             create_params["subnet"]["host_routes"] = data["host_routes"]
366
367         logger.info("[%s]call neutron.create_subnet(%s)" % (fun_name(), str(create_params)))
368         subnet_created = neutron.create_subnet(create_params)
369         return [0, {"id": subnet_created["subnet"]["id"],
370                     "name": data["subnet_name"],
371                     const.RES_TYPE_KEY: const.RES_TYPE_NEW}]
372     except Exception as ex:
373         logger.error(traceback.format_exc())
374         logger.error(str(sys.exc_info()))
375         return [1, ex.args[0] if ex.args[0] else str(sys.exc_info())]
376
377
378 def rollback(neutron, network_data):
379     for subnet_data in network_data["subnet_list"]:
380         if subnet_data[const.RES_TYPE_KEY] == const.RES_TYPE_NEW:
381             try:
382                 logger.info("[%s]call neutron.delete_subnet(%s)" % (fun_name(), subnet_data["id"]))
383                 neutron.delete_subnet(subnet_data["subnet_id"])
384             except:
385                 logger.error("[%s]%s", fun_name(), str(sys.exc_info()))
386
387     if network_data and network_data[const.RES_TYPE_KEY] == const.RES_TYPE_NEW:
388         try:
389             logger.info("[%s]call neutron.delete_network(%s)" % (fun_name(), network_data["id"]))
390             neutron.delete_network(network_data["id"])
391         except:
392             logger.error("[%s]%s", fun_name(), str(sys.exc_info()))
393
394
395 def delete_network(auth_info, network_id):
396     neutron = neutronbase.get_neutron_default(fun_name(), auth_info)
397     try:
398         neutron.delete_network(network_id)
399     except Exception as ex:
400         logger.error(traceback.format_exc())
401         msg = ex.args[0] if ex.args[0] else str(sys.exc_info())
402         logger.error(msg)
403         if 404 == ex.status_code:
404             return [0, ex.args[0]]
405         return [1, "Vim exception."]
406     return [0, "Network(%s) is deleted" % network_id]
407
408
409 def delete_subnet(auth_info, subnet_id):
410     neutron = neutronbase.get_neutron_default(fun_name(), auth_info)
411     try:
412         neutron.delete_subnet(subnet_id)
413     except NeutronClientException as e:
414         logger.warn("[%s]NetworkNotFoundClient: %s", fun_name(), e.args[0])
415         return [0, e.args[0]]
416     return [0, "Subnet(%s) is deleted" % subnet_id]
417
418
419 def delete_port(auth_info, port_id):
420     neutron = neutronbase.get_neutron_default(fun_name(), auth_info)
421     try:
422         neutron.delete_port(port_id)
423     except NeutronClientException as e:
424         logger.warn("[%s]NeutronClientException: %s", fun_name(), e.args[0])
425         return [0, e.args[0]]
426     return [0, "Port(%s) is deleted" % port_id]