1 # Copyright 2016 ZTE Corporation.
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
7 # http://www.apache.org/licenses/LICENSE-2.0
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.
19 from neutronclient.common.exceptions import NeutronClientException
20 from neutronclient.common.exceptions import NetworkNotFoundClient
21 from neutronclient.common.exceptions import NotFound as SubnetNotFound
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
29 logger = logging.getLogger(__name__)
32 def query_net(auth_info, net_id):
33 neutron = neutronbase.get_neutron_default(fun_name(), auth_info)
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])
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"]}
58 def query_nets(auth_info):
59 neutron = neutronbase.get_neutron_default(fun_name(), auth_info)
60 keystone = auth_info["keystone"]
62 tenants = keystone.tenants.list()
63 for tenant in tenants:
64 tenants_map[tenant.id] = tenant.name
66 nets = neutron.list_networks()
67 return [0, {"networks": [{
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"]]}]
83 def query_subnet(auth_info, subnet_id):
84 neutron = neutronbase.get_neutron_default(fun_name(), auth_info)
87 subnet_info = neutron.show_subnet(subnet_id)["subnet"]
88 except SubnetNotFound as e:
89 logger.warn("SubnetNotFound: %s", e.args[0])
92 ret[1]["id"] = subnet_id
93 ret[1]["name"] = subnet_info["name"]
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"]
105 def query_port(auth_info, port_id):
106 neutron = neutronbase.get_neutron_default(fun_name(), auth_info)
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]]
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"]
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"]
131 def get_subnet_id(neutron, data, network_id):
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']
147 subnets = neutron.list_subnets()
148 filter_subnets = [subnet for subnet in subnets["subnets"] if subnet["network_id"] == network_id]
150 subnet_id = filter_subnets[0]["id"]
154 def create_port(auth_info, data):
155 tenant_id = project.get_tenant_id(fun_name(), auth_info, data["tenant_name"])
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:
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'])
174 neutron = neutronbase.get_neutron(fun_name(), auth_info, data["tenant_name"])
177 subnet_id = get_subnet_id(neutron_admin, data, network_id)
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]
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)
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]
208 'name': data["port_name"],
209 'admin_state_up': True,
210 'network_id': network_id,
211 'security_groups': [],
212 'tenant_id': tenant_id
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"])
227 create_param['port']['mac_address'] = data["macbond"]
228 if "ip" in data and data["ip"]:
230 create_param['port']['fixed_ips'] = [{"subnet_id": subnet_id, "ip_address": data["ip"]}]
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)))
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)
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]
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"])
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"]))
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"]]
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,
284 "name": subnet["name"],
285 const.RES_TYPE_KEY: const.RES_TYPE_EXIST
286 }for subnet in filter_subnets
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']
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,
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:
324 ret = create_subnet(neutron, network_data["id"], subnet_data)
326 need_rollback, ret_error = True, ret
328 network_data["subnet_list"].append(ret[1])
330 # rollback when failed to create subnet
332 rollback(neutron_admin, network_data)
335 return [0, network_data]
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"]]
344 "id": filter_subnets[0]["id"],
345 "name": data["subnet_name"],
346 const.RES_TYPE_KEY: const.RES_TYPE_EXIST
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"]
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"]
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())]
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:
382 logger.info("[%s]call neutron.delete_subnet(%s)" % (fun_name(), subnet_data["id"]))
383 neutron.delete_subnet(subnet_data["subnet_id"])
385 logger.error("[%s]%s", fun_name(), str(sys.exc_info()))
387 if network_data and network_data[const.RES_TYPE_KEY] == const.RES_TYPE_NEW:
389 logger.info("[%s]call neutron.delete_network(%s)" % (fun_name(), network_data["id"]))
390 neutron.delete_network(network_data["id"])
392 logger.error("[%s]%s", fun_name(), str(sys.exc_info()))
395 def delete_network(auth_info, network_id):
396 neutron = neutronbase.get_neutron_default(fun_name(), auth_info)
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())
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]
409 def delete_subnet(auth_info, subnet_id):
410 neutron = neutronbase.get_neutron_default(fun_name(), auth_info)
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]
419 def delete_port(auth_info, port_id):
420 neutron = neutronbase.get_neutron_default(fun_name(), auth_info)
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]