1 # Copyright (c) 2017 Cable Television Laboratories, Inc. ("CableLabs")
2 # and others. All rights reserved.
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.
17 from neutronclient.common.exceptions import NotFound
18 from neutronclient.neutron.client import Client
20 from snaps.domain.network import (
21 Port, SecurityGroup, SecurityGroupRule, Router, InterfaceRouter, Subnet,
23 from snaps.domain.project import NetworkQuotas
24 from snaps.domain.vm_inst import FloatingIp
25 from snaps.openstack.utils import keystone_utils
27 __author__ = 'spisarski'
29 logger = logging.getLogger('neutron_utils')
32 Utilities for basic neutron API calls
36 def neutron_client(os_creds):
38 Instantiates and returns a client for communications with OpenStack's
40 :param os_creds: the credentials for connecting to the OpenStack remote API
41 :return: the client object
43 return Client(api_version=os_creds.network_api_version,
44 session=keystone_utils.keystone_session(os_creds),
45 region_name=os_creds.region_name)
48 def create_network(neutron, os_creds, network_settings):
50 Creates a network for OpenStack
51 :param neutron: the client
52 :param os_creds: the OpenStack credentials
53 :param network_settings: A dictionary containing the network configuration
54 and is responsible for creating the network
56 :return: a SNAPS-OO Network domain object if found else None
58 logger.info('Creating network with name ' + network_settings.name)
59 json_body = network_settings.dict_for_neutron(os_creds)
60 os_network = neutron.create_network(body=json_body)
63 network = get_network_by_id(neutron, os_network['network']['id'])
66 for subnet_settings in network_settings.subnet_settings:
69 create_subnet(neutron, subnet_settings, os_creds, network))
72 'Unexpected error creating subnet [%s] for network [%s]',
73 subnet_settings.name, network.name)
75 for subnet in subnets:
76 delete_subnet(neutron, subnet)
78 delete_network(neutron, network)
82 return get_network_by_id(neutron, network.id)
85 def delete_network(neutron, network):
87 Deletes a network for OpenStack
88 :param neutron: the client
89 :param network: a SNAPS-OO Network domain object
91 if neutron and network:
93 for subnet in network.subnets:
94 logger.info('Deleting subnet with name ' + subnet.name)
96 delete_subnet(neutron, subnet)
100 logger.info('Deleting network with name ' + network.name)
101 neutron.delete_network(network.id)
104 def get_network(neutron, keystone, network_settings=None, network_name=None,
107 Returns Network SNAPS-OO domain object the first network found with
108 either the given attributes from the network_settings object if not None,
109 else the query will use just the name from the network_name parameter.
110 When the project_name is included, that will be added to the query filter.
111 :param neutron: the Neutron client
112 :param keystone: the Keystone client
113 :param network_settings: the NetworkConfig object used to create filter
114 :param network_name: the name of the network to retrieve
115 :param project_name: the name of the network's project
116 :return: a SNAPS-OO Network domain object
120 net_filter['name'] = network_settings.name
122 net_filter['name'] = network_name
124 networks = neutron.list_networks(**net_filter)
125 for network, netInsts in networks.items():
126 for inst in netInsts:
128 project = keystone_utils.get_project_by_id(
129 keystone, inst['project_id'])
130 if project and project.name == project_name:
131 return __map_network(neutron, inst)
133 return __map_network(neutron, inst)
136 def __get_os_network_by_id(neutron, network_id):
138 Returns the OpenStack network object (dictionary) with the given ID else
140 :param neutron: the client
141 :param network_id: the id of the network to retrieve
142 :return: a SNAPS-OO Network domain object
144 networks = neutron.list_networks(**{'id': network_id})
145 for network in networks['networks']:
146 if network['id'] == network_id:
150 def get_network_by_id(neutron, network_id):
152 Returns the SNAPS Network domain object for the given ID else None
153 :param neutron: the client
154 :param network_id: the id of the network to retrieve
155 :return: a SNAPS-OO Network domain object
157 os_network = __get_os_network_by_id(neutron, network_id)
159 return __map_network(neutron, os_network)
162 def __map_network(neutron, os_network):
164 Returns the network object (dictionary) with the given ID else None
165 :param neutron: the client
166 :param os_network: the OpenStack Network dict
167 :return: a SNAPS-OO Network domain object
169 subnets = get_subnets_by_network_id(neutron, os_network['id'])
170 os_network['subnets'] = subnets
171 return Network(**os_network)
174 def create_subnet(neutron, subnet_settings, os_creds, network):
176 Creates a network subnet for OpenStack
177 :param neutron: the client
178 :param subnet_settings: A dictionary containing the subnet configuration
179 and is responsible for creating the subnet request
181 :param os_creds: the OpenStack credentials
182 :param network: the network object
183 :return: a SNAPS-OO Subnet domain object
185 if neutron and network and subnet_settings:
186 json_body = {'subnets': [subnet_settings.dict_for_neutron(
187 os_creds, network=network)]}
188 logger.info('Creating subnet with name ' + subnet_settings.name)
189 subnets = neutron.create_subnet(body=json_body)
190 return Subnet(**subnets['subnets'][0])
192 raise NeutronException('Failed to create subnet')
195 def delete_subnet(neutron, subnet):
197 Deletes a network subnet for OpenStack
198 :param neutron: the client
199 :param subnet: a SNAPS-OO Subnet domain object
201 if neutron and subnet:
202 logger.info('Deleting subnet with name ' + subnet.name)
203 neutron.delete_subnet(subnet.id)
206 def get_subnet(neutron, subnet_settings=None, subnet_name=None):
208 Returns the first subnet object that fits the query else None including
209 if subnet_settings or subnet_name parameters are None.
210 :param neutron: the client
211 :param subnet_settings: the subnet settings of the object to retrieve
212 :param subnet_name: the name of the subnet to retrieve
213 :return: a SNAPS-OO Subnet domain object or None
217 sub_filter['name'] = subnet_settings.name
218 sub_filter['cidr'] = subnet_settings.cidr
219 if subnet_settings.gateway_ip:
220 sub_filter['gateway_ip'] = subnet_settings.gateway_ip
222 if subnet_settings.enable_dhcp is not None:
223 sub_filter['enable_dhcp'] = subnet_settings.enable_dhcp
225 if subnet_settings.destination:
226 sub_filter['destination'] = subnet_settings.destination
228 if subnet_settings.nexthop:
229 sub_filter['nexthop'] = subnet_settings.nexthop
231 if subnet_settings.ipv6_ra_mode:
232 sub_filter['ipv6_ra_mode'] = subnet_settings.ipv6_ra_mode
234 if subnet_settings.ipv6_address_mode:
235 sub_filter['ipv6_address_mode'] = subnet_settings.ipv6_address_mode
237 sub_filter['name'] = subnet_name
241 subnets = neutron.list_subnets(**sub_filter)
242 for subnet in subnets['subnets']:
243 return Subnet(**subnet)
246 def get_subnet_by_id(neutron, subnet_id):
248 Returns a SNAPS-OO Subnet domain object for a given ID
249 :param neutron: the OpenStack neutron client
250 :param subnet_id: the subnet ID
251 :return: a Subnet object
253 os_subnet = neutron.show_subnet(subnet_id)
254 if os_subnet and 'subnet' in os_subnet:
255 return Subnet(**os_subnet['subnet'])
258 def get_subnets_by_network(neutron, network):
260 Returns a list of SNAPS-OO Subnet domain objects
261 :param neutron: the OpenStack neutron client
262 :param network: the SNAPS-OO Network domain object
263 :return: a list of Subnet objects
265 return get_subnets_by_network_id(neutron, network.id)
268 def get_subnets_by_network_id(neutron, network_id):
270 Returns a list of SNAPS-OO Subnet domain objects
271 :param neutron: the OpenStack neutron client
272 :param network_id: the subnet's ID
273 :return: a list of Subnet objects
277 os_subnets = neutron.list_subnets(network_id=network_id)
279 for os_subnet in os_subnets['subnets']:
280 out.append(Subnet(**os_subnet))
285 def create_router(neutron, os_creds, router_settings):
287 Creates a router for OpenStack
288 :param neutron: the client
289 :param os_creds: the OpenStack credentials
290 :param router_settings: A dictionary containing the router configuration
291 and is responsible for creating the subnet request
293 :return: a SNAPS-OO Router domain object
296 json_body = router_settings.dict_for_neutron(neutron, os_creds)
297 logger.info('Creating router with name - ' + router_settings.name)
298 os_router = neutron.create_router(json_body)
299 return __map_router(neutron, os_router['router'])
301 logger.error("Failed to create router.")
302 raise NeutronException('Failed to create router')
305 def delete_router(neutron, router):
307 Deletes a router for OpenStack
308 :param neutron: the client
309 :param router: a SNAPS-OO Router domain object
311 if neutron and router:
312 logger.info('Deleting router with name - ' + router.name)
313 neutron.delete_router(router=router.id)
316 def get_router_by_id(neutron, router_id):
318 Returns a router with a given ID, else None if not found
319 :param neutron: the client
320 :param router_id: the Router ID
321 :return: a SNAPS-OO Router domain object
323 router = neutron.show_router(router_id)
325 return __map_router(neutron, router['router'])
328 def get_router(neutron, keystone, router_settings=None, router_name=None,
331 Returns the first router object (dictionary) found the given the settings
332 values if not None, else finds the first with the value of the router_name
334 :param neutron: the Neutron client
335 :param keystone: the Keystone client
336 :param router_settings: the RouterConfig object
337 :param router_name: the name of the network to retrieve
338 :param project_name: the name of the router's project
339 :return: a SNAPS-OO Router domain object
341 router_filter = dict()
343 router_filter['name'] = router_settings.name
344 if router_settings.admin_state_up is not None:
345 router_filter['admin_state_up'] = router_settings.admin_state_up
347 router_filter['name'] = router_name
351 os_routers = neutron.list_routers(**router_filter)
352 for os_router in os_routers['routers']:
354 project = keystone_utils.get_project_by_id(
355 keystone, os_router['project_id'])
356 if project and project.name == project_name:
357 return __map_router(neutron, os_router)
360 def __map_router(neutron, os_router):
362 Takes an OpenStack router instance and maps it to a SNAPS Router domain
364 :param neutron: the neutron client
365 :param os_router: the OpenStack Router object
368 device_ports = neutron.list_ports(
369 **{'device_id': os_router['id']})['ports']
370 port_subnets = list()
372 # Order by create date
373 sorted_ports = sorted(
374 device_ports, key=lambda dev_port: dev_port['created_at'])
376 for port in sorted_ports:
378 for fixed_ip in port['fixed_ips']:
379 subnet = get_subnet_by_id(neutron, fixed_ip['subnet_id'])
380 if subnet and subnet.network_id == port['network_id']:
381 subnets.append(subnet)
382 port_subnets.append((Port(**port), subnets))
384 os_router['port_subnets'] = port_subnets
385 return Router(**os_router)
388 def add_interface_router(neutron, router, subnet=None, port=None):
390 Adds an interface router for OpenStack for either a subnet or port.
391 Exception will be raised if requesting for both.
392 :param neutron: the client
393 :param router: the router object
394 :param subnet: the subnet object
395 :param port: the port object
396 :return: the interface router object
399 raise NeutronException(
400 'Cannot add interface to the router. Both subnet and '
401 'port were sent in. Either or please.')
403 if neutron and router and (router or subnet):
404 logger.info('Adding interface to router with name ' + router.name)
405 os_intf_router = neutron.add_interface_router(
406 router=router.id, body=__create_port_json_body(subnet, port))
407 return InterfaceRouter(**os_intf_router)
409 raise NeutronException(
410 'Unable to create interface router as neutron client,'
411 ' router or subnet were not created')
414 def remove_interface_router(neutron, router, subnet=None, port=None):
416 Removes an interface router for OpenStack
417 :param neutron: the client
418 :param router: the SNAPS-OO Router domain object
419 :param subnet: the subnet object (either subnet or port, not both)
420 :param port: the port object
424 logger.info('Removing router interface from router named ' +
426 neutron.remove_interface_router(
428 body=__create_port_json_body(subnet, port))
429 except NotFound as e:
430 logger.warning('Could not remove router interface. NotFound - %s',
434 logger.warning('Could not remove router interface, No router object')
437 def __create_port_json_body(subnet=None, port=None):
439 Returns the dictionary required for creating and deleting router
440 interfaces. Will only work on a subnet or port object. Will throw and
441 exception if parameters contain both or neither
442 :param subnet: the subnet object
443 :param port: the port object
447 raise NeutronException(
448 'Cannot create JSON body with both subnet and port')
449 if not subnet and not port:
450 raise NeutronException(
451 'Cannot create JSON body without subnet or port')
454 return {"subnet_id": subnet.id}
456 return {"port_id": port.id}
459 def create_port(neutron, os_creds, port_settings):
461 Creates a port for OpenStack
462 :param neutron: the client
463 :param os_creds: the OpenStack credentials
464 :param port_settings: the settings object for port configuration
465 :return: the SNAPS-OO Port domain object
467 json_body = port_settings.dict_for_neutron(neutron, os_creds)
468 logger.info('Creating port for network with name - %s',
469 port_settings.network_name)
470 os_port = neutron.create_port(body=json_body)['port']
471 return Port(**os_port)
474 def delete_port(neutron, port):
476 Removes an OpenStack port
477 :param neutron: the client
478 :param port: the SNAPS-OO Port domain object
480 logger.info('Deleting port with name ' + port.name)
481 neutron.delete_port(port.id)
484 def get_port(neutron, keystone, port_settings=None, port_name=None,
487 Returns the first port object (dictionary) found for the given query
488 :param neutron: the Neutron client
489 :param keystone: the Keystone client
490 :param port_settings: the PortConfig object used for generating the query
491 :param port_name: if port_settings is None, this name is the value to place
493 :param project_name: the associated project name
494 :return: a SNAPS-OO Port domain object
499 if port_settings.name and len(port_settings.name) > 0:
500 port_filter['name'] = port_settings.name
501 if port_settings.admin_state_up:
502 port_filter['admin_state_up'] = port_settings.admin_state_up
503 if port_settings.device_id:
504 port_filter['device_id'] = port_settings.device_id
505 if port_settings.mac_address:
506 port_filter['mac_address'] = port_settings.mac_address
507 if port_settings.project_name:
508 project_name = port_settings.project_name
509 if port_settings.network_name:
510 network = get_network(
511 neutron, keystone, network_name=port_settings.network_name,
512 project_name=project_name)
514 port_filter['network_id'] = network.id
516 port_filter['name'] = port_name
518 ports = neutron.list_ports(**port_filter)
519 for port in ports['ports']:
521 project = keystone_utils.get_project_by_id(
522 keystone, port['project_id'])
523 if project and project.name == project_name:
530 def get_port_by_id(neutron, port_id):
532 Returns a SNAPS-OO Port domain object for the given ID or none if not found
533 :param neutron: the client
534 :param port_id: the to query
535 :return: a SNAPS-OO Port domain object or None
537 port = neutron.show_port(port_id)
539 return Port(**port['port'])
543 def get_ports(neutron, network, ips=None):
545 Returns a list of SNAPS-OO Port objects for all OpenStack Port objects that
546 are associated with the 'network' parameter
547 :param neutron: the client
548 :param network: SNAPS-OO Network domain object
549 :param ips: the IPs to lookup if not None
550 :return: a SNAPS-OO Port domain object or None if not found
553 ports = neutron.list_ports(**{'network_id': network.id})
554 for port in ports['ports']:
556 for fixed_ips in port['fixed_ips']:
557 if ('ip_address' in fixed_ips and
558 fixed_ips['ip_address'] in ips) or ips is None:
559 out.append(Port(**port))
562 out.append(Port(**port))
567 def create_security_group(neutron, keystone, sec_grp_settings):
569 Creates a security group object in OpenStack
570 :param neutron: the Neutron client
571 :param keystone: the Keystone client
572 :param sec_grp_settings: the security group settings
573 :return: a SNAPS-OO SecurityGroup domain object
575 logger.info('Creating security group with name - %s',
576 sec_grp_settings.name)
577 os_group = neutron.create_security_group(
578 sec_grp_settings.dict_for_neutron(keystone))
579 return __map_os_security_group(neutron, os_group['security_group'])
582 def delete_security_group(neutron, sec_grp):
584 Deletes a security group object from OpenStack
585 :param neutron: the client
586 :param sec_grp: the SNAPS SecurityGroup object to delete
588 logger.info('Deleting security group with name - %s', sec_grp.name)
589 neutron.delete_security_group(sec_grp.id)
592 def get_security_group(neutron, keystone, sec_grp_settings=None,
593 sec_grp_name=None, project_name=None):
595 Returns the first security group for a given query. The query gets built
596 from the sec_grp_settings parameter if not None, else only the name of
597 the security group will be used, else if the query parameters are None then
598 None will be returned
599 :param neutron: the neutron client
600 :param keystone: the keystone client
601 :param sec_grp_settings: an instance of SecurityGroupConfig object
602 :param sec_grp_name: the name of security group object to retrieve
603 :param project_name: the name of the project/tentant object that owns the
604 secuity group to retrieve
605 :return: a SNAPS-OO SecurityGroup domain object or None if not found
608 sec_grp_filter = dict()
611 sec_grp_filter['name'] = sec_grp_settings.name
613 if sec_grp_settings.description:
614 sec_grp_filter['description'] = sec_grp_settings.description
615 if sec_grp_settings.project_name:
616 project_name = sec_grp_settings.project_name
618 sec_grp_filter['name'] = sec_grp_name
622 groups = neutron.list_security_groups(**sec_grp_filter)
624 for group in groups['security_groups']:
626 project = keystone_utils.get_project_by_id(
627 keystone, group['tenant_id'])
628 if project and project_name == project.name:
633 return __map_os_security_group(neutron, group)
636 def __map_os_security_group(neutron, os_sec_grp):
638 Creates a SecurityGroup SNAPS domain object from an OpenStack Security
640 :param neutron: the neutron client for performing rule lookups
641 :param os_sec_grp: the OpenStack Security Group dict object
642 :return: a SecurityGroup object
644 os_sec_grp['rules'] = get_rules_by_security_group_id(
645 neutron, os_sec_grp['id'])
646 return SecurityGroup(**os_sec_grp)
649 def get_security_group_by_id(neutron, sec_grp_id):
651 Returns the first security group object of the given name else None
652 :param neutron: the client
653 :param sec_grp_id: the id of the security group to retrieve
654 :return: a SNAPS-OO SecurityGroup domain object or None if not found
656 logger.info('Retrieving security group with ID - ' + sec_grp_id)
658 groups = neutron.list_security_groups(**{'id': sec_grp_id})
659 for group in groups['security_groups']:
660 if group['id'] == sec_grp_id:
661 return __map_os_security_group(neutron, group)
665 def create_security_group_rule(neutron, keystone, sec_grp_rule_settings,
668 Creates a security group rule in OpenStack
669 :param neutron: the neutron client
670 :param keystone: the keystone client
671 :param sec_grp_rule_settings: the security group rule settings
672 :param proj_name: the default project name
673 :return: a SNAPS-OO SecurityGroupRule domain object
675 logger.info('Creating security group to security group - %s',
676 sec_grp_rule_settings.sec_grp_name)
677 os_rule = neutron.create_security_group_rule(
678 sec_grp_rule_settings.dict_for_neutron(neutron, keystone, proj_name))
679 return SecurityGroupRule(**os_rule['security_group_rule'])
682 def delete_security_group_rule(neutron, sec_grp_rule):
684 Deletes a security group rule object from OpenStack
685 :param neutron: the client
686 :param sec_grp_rule: the SNAPS SecurityGroupRule object to delete
688 logger.info('Deleting security group rule with ID - %s',
690 neutron.delete_security_group_rule(sec_grp_rule.id)
693 def get_rules_by_security_group(neutron, sec_grp):
695 Retrieves all of the rules for a given security group
696 :param neutron: the client
697 :param sec_grp: a list of SNAPS SecurityGroupRule domain objects
699 return get_rules_by_security_group_id(neutron, sec_grp.id)
702 def get_rules_by_security_group_id(neutron, sec_grp_id):
704 Retrieves all of the rules for a given security group by it's ID
705 :param neutron: the client
706 :param sec_grp_id: the ID of the associated security group
708 logger.info('Retrieving security group rules associate with the '
709 'security group with ID - %s', sec_grp_id)
711 rules = neutron.list_security_group_rules(
712 **{'security_group_id': sec_grp_id})
713 for rule in rules['security_group_rules']:
714 if rule['security_group_id'] == sec_grp_id:
715 out.append(SecurityGroupRule(**rule))
719 def get_rule_by_id(neutron, sec_grp, rule_id):
721 Returns a SecurityGroupRule object from OpenStack
722 :param neutron: the client
723 :param sec_grp: the SNAPS SecurityGroup domain object
724 :param rule_id: the rule's ID
725 :param sec_grp: a SNAPS SecurityGroupRule domain object
727 rules = neutron.list_security_group_rules(
728 **{'security_group_id': sec_grp.id})
729 for rule in rules['security_group_rules']:
730 if rule['id'] == rule_id:
731 return SecurityGroupRule(**rule)
735 def get_external_networks(neutron):
737 Returns a list of external OpenStack network object/dict for all external
739 :param neutron: the client
740 :return: a list of external networks of Type SNAPS-OO domain class Network
743 for network in neutron.list_networks(
744 **{'router:external': True})['networks']:
745 out.append(__map_network(neutron, network))
749 def get_port_floating_ips(neutron, ports):
751 Returns all of the floating IPs associated with the ports returned in a
752 list of tuples where the port object is in the first position and the
753 floating IP object is in the second
754 :param neutron: the Neutron client
755 :param ports: a list of tuple 2 where index 0 is the port name and index 1
756 is the SNAPS-OO Port object
757 :return: a list of tuple 2 (port_id, SNAPS FloatingIp) objects when ports
758 is not None else a list of FloatingIp objects
761 fips = neutron.list_floatingips()
762 for fip in fips['floatingips']:
763 for port_name, port in ports:
764 if port and port.id == fip['port_id']:
765 out.append((port.id, FloatingIp(**fip)))
770 def get_floating_ips(neutron):
772 Returns a list of all of the floating IPs
773 :param neutron: the Neutron client
776 fips = neutron.list_floatingips()
777 for fip in fips['floatingips']:
778 out.append(FloatingIp(**fip))
782 def create_floating_ip(neutron, keystone, ext_net_name, port_id=None):
784 Returns the floating IP object that was created with this call
785 :param neutron: the Neutron client
786 :param keystone: the Keystone client
787 :param ext_net_name: the name of the external network on which to apply the
789 :param port_id: the ID of the port to which the floating IP will be
791 :return: the SNAPS FloatingIp object
793 logger.info('Creating floating ip to external network - ' + ext_net_name)
794 ext_net = get_network(neutron, keystone, network_name=ext_net_name)
796 body = {'floatingip': {'floating_network_id': ext_net.id}}
798 body['floatingip']['port_id'] = port_id
800 fip = neutron.create_floatingip(body=body)
802 return FloatingIp(id=fip['floatingip']['id'],
803 ip=fip['floatingip']['floating_ip_address'])
805 raise NeutronException(
806 'Cannot create floating IP, external network not found')
809 def get_floating_ip(neutron, floating_ip):
811 Returns a floating IP object that should be identical to the floating_ip
813 :param neutron: the Neutron client
814 :param floating_ip: the SNAPS FloatingIp object
815 :return: hopefully the same floating IP object input
817 logger.debug('Attempting to retrieve existing floating ip with IP - %s',
819 os_fip = __get_os_floating_ip(neutron, floating_ip)
821 return FloatingIp(id=os_fip['id'], ip=os_fip['floating_ip_address'])
824 def __get_os_floating_ip(neutron, floating_ip):
826 Returns an OpenStack floating IP object
828 :param neutron: the Neutron client
829 :param floating_ip: the SNAPS FloatingIp object
830 :return: hopefully the same floating IP object input
832 logger.debug('Attempting to retrieve existing floating ip with IP - %s',
834 fips = neutron.list_floatingips(ip=floating_ip.id)
836 for fip in fips['floatingips']:
837 if fip['id'] == floating_ip.id:
841 def delete_floating_ip(neutron, floating_ip):
843 Responsible for deleting a floating IP
844 :param neutron: the Neutron client
845 :param floating_ip: the SNAPS FloatingIp object
848 logger.debug('Attempting to delete existing floating ip with IP - %s',
850 return neutron.delete_floatingip(floating_ip.id)
853 def get_network_quotas(neutron, project_id):
855 Returns a list of NetworkQuotas objects
856 :param neutron: the neutron client
857 :param project_id: the project's ID of the quotas to lookup
858 :return: an object of type NetworkQuotas or None if not found
860 quota = neutron.show_quota(project_id)
862 return NetworkQuotas(**quota['quota'])
865 def update_quotas(neutron, project_id, network_quotas):
867 Updates the networking quotas for a given project
868 :param neutron: the Neutron client
869 :param project_id: the project's ID that requires quota updates
870 :param network_quotas: an object of type NetworkQuotas containing the
875 update_body['security_group'] = network_quotas.security_group
876 update_body['security_group_rule'] = network_quotas.security_group_rule
877 update_body['floatingip'] = network_quotas.floatingip
878 update_body['network'] = network_quotas.network
879 update_body['port'] = network_quotas.port
880 update_body['router'] = network_quotas.router
881 update_body['subnet'] = network_quotas.subnet
883 return neutron.update_quota(project_id, {'quota': update_body})
886 class NeutronException(Exception):
888 Exception when calls to the Keystone client cannot be served properly