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, network_settings=None, network_name=None,
105 project_id=None, os_creds=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_id is included, that will be added to the query filter.
111 :param neutron: the client
112 :param network_settings: the NetworkConfig object used to create filter
113 :param network_name: the name of the network to retrieve
114 :param project_id: the id of the network's project
115 :param os_creds: the OpenStack credentials for retrieving the project
116 :return: a SNAPS-OO Network domain object
120 net_filter['name'] = network_settings.name
122 net_filter['name'] = network_name
124 if network_settings and network_settings.project_name and os_creds:
125 net_filter['project_id'] = keystone_utils.get_project(
126 os_creds=os_creds, project_name=network_settings.project_name).id
128 net_filter['project_id'] = project_id
130 networks = neutron.list_networks(**net_filter)
131 for network, netInsts in networks.items():
132 for inst in netInsts:
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, project_id):
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 :param project_id: the associated project ID
294 :return: a SNAPS-OO Router domain object
297 if router_settings and router_settings.project_name:
298 keystone = keystone_utils.keystone_client(os_creds)
299 project_id = keystone_utils.get_project(
300 keystone=keystone, project_name=router_settings.project_name)
301 json_body = router_settings.dict_for_neutron(
302 neutron, os_creds, project_id)
303 logger.info('Creating router with name - ' + router_settings.name)
304 os_router = neutron.create_router(json_body)
305 return __map_router(neutron, os_router['router'])
307 logger.error("Failed to create router.")
308 raise NeutronException('Failed to create router')
311 def delete_router(neutron, router):
313 Deletes a router for OpenStack
314 :param neutron: the client
315 :param router: a SNAPS-OO Router domain object
317 if neutron and router:
318 logger.info('Deleting router with name - ' + router.name)
319 neutron.delete_router(router=router.id)
322 def get_router_by_id(neutron, router_id):
324 Returns a router with a given ID, else None if not found
325 :param neutron: the client
326 :param router_id: the Router ID
327 :return: a SNAPS-OO Router domain object
329 router = neutron.show_router(router_id)
331 return __map_router(neutron, router['router'])
334 def get_router(neutron, router_settings=None, router_name=None):
336 Returns the first router object (dictionary) found the given the settings
337 values if not None, else finds the first with the value of the router_name
339 :param neutron: the client
340 :param router_settings: the RouterConfig object
341 :param router_name: the name of the network to retrieve
342 :return: a SNAPS-OO Router domain object
344 router_filter = dict()
346 router_filter['name'] = router_settings.name
347 if router_settings.admin_state_up is not None:
348 router_filter['admin_state_up'] = router_settings.admin_state_up
350 router_filter['name'] = router_name
354 routers = neutron.list_routers(**router_filter)
356 for routerInst in routers['routers']:
357 return __map_router(neutron, routerInst)
362 def __map_router(neutron, os_router):
364 Takes an OpenStack router instance and maps it to a SNAPS Router domain
366 :param neutron: the neutron client
367 :param os_router: the OpenStack Router object
370 device_ports = neutron.list_ports(
371 **{'device_id': os_router['id']})['ports']
372 port_subnets = list()
374 # Order by create date
375 sorted_ports = sorted(
376 device_ports, key=lambda dev_port: dev_port['created_at'])
378 for port in sorted_ports:
380 for fixed_ip in port['fixed_ips']:
381 subnet = get_subnet_by_id(neutron, fixed_ip['subnet_id'])
382 if subnet and subnet.network_id == port['network_id']:
383 subnets.append(subnet)
384 port_subnets.append((Port(**port), subnets))
386 os_router['port_subnets'] = port_subnets
387 return Router(**os_router)
390 def add_interface_router(neutron, router, subnet=None, port=None):
392 Adds an interface router for OpenStack for either a subnet or port.
393 Exception will be raised if requesting for both.
394 :param neutron: the client
395 :param router: the router object
396 :param subnet: the subnet object
397 :param port: the port object
398 :return: the interface router object
401 raise NeutronException(
402 'Cannot add interface to the router. Both subnet and '
403 'port were sent in. Either or please.')
405 if neutron and router and (router or subnet):
406 logger.info('Adding interface to router with name ' + router.name)
407 os_intf_router = neutron.add_interface_router(
408 router=router.id, body=__create_port_json_body(subnet, port))
409 return InterfaceRouter(**os_intf_router)
411 raise NeutronException(
412 'Unable to create interface router as neutron client,'
413 ' router or subnet were not created')
416 def remove_interface_router(neutron, router, subnet=None, port=None):
418 Removes an interface router for OpenStack
419 :param neutron: the client
420 :param router: the SNAPS-OO Router domain object
421 :param subnet: the subnet object (either subnet or port, not both)
422 :param port: the port object
426 logger.info('Removing router interface from router named ' +
428 neutron.remove_interface_router(
430 body=__create_port_json_body(subnet, port))
431 except NotFound as e:
432 logger.warning('Could not remove router interface. NotFound - %s',
436 logger.warning('Could not remove router interface, No router object')
439 def __create_port_json_body(subnet=None, port=None):
441 Returns the dictionary required for creating and deleting router
442 interfaces. Will only work on a subnet or port object. Will throw and
443 exception if parameters contain both or neither
444 :param subnet: the subnet object
445 :param port: the port object
449 raise NeutronException(
450 'Cannot create JSON body with both subnet and port')
451 if not subnet and not port:
452 raise NeutronException(
453 'Cannot create JSON body without subnet or port')
456 return {"subnet_id": subnet.id}
458 return {"port_id": port.id}
461 def create_port(neutron, os_creds, port_settings):
463 Creates a port for OpenStack
464 :param neutron: the client
465 :param os_creds: the OpenStack credentials
466 :param port_settings: the settings object for port configuration
467 :return: the SNAPS-OO Port domain object
469 json_body = port_settings.dict_for_neutron(neutron, os_creds)
470 logger.info('Creating port for network with name - %s',
471 port_settings.network_name)
472 os_port = neutron.create_port(body=json_body)['port']
473 return Port(**os_port)
476 def delete_port(neutron, port):
478 Removes an OpenStack port
479 :param neutron: the client
480 :param port: the SNAPS-OO Port domain object
482 logger.info('Deleting port with name ' + port.name)
483 neutron.delete_port(port.id)
486 def get_port(neutron, port_settings=None, port_name=None, project_id=None):
488 Returns the first port object (dictionary) found for the given query
489 :param neutron: the 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_id: the associated project ID
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.network_name:
508 network = get_network(
509 neutron, network_name=port_settings.network_name,
510 project_id=project_id)
512 port_filter['network_id'] = network.id
514 port_filter['name'] = port_name
517 port_filter['project_id'] = project_id
519 ports = neutron.list_ports(**port_filter)
520 for port in ports['ports']:
525 def get_port_by_id(neutron, port_id):
527 Returns a SNAPS-OO Port domain object for the given ID or none if not found
528 :param neutron: the client
529 :param port_id: the to query
530 :return: a SNAPS-OO Port domain object or None
532 port = neutron.show_port(port_id)
534 return Port(**port['port'])
538 def get_ports(neutron, network, ips=None):
540 Returns a list of SNAPS-OO Port objects for all OpenStack Port objects that
541 are associated with the 'network' parameter
542 :param neutron: the client
543 :param network: SNAPS-OO Network domain object
544 :param ips: the IPs to lookup if not None
545 :return: a SNAPS-OO Port domain object or None if not found
548 ports = neutron.list_ports(**{'network_id': network.id})
549 for port in ports['ports']:
551 for fixed_ips in port['fixed_ips']:
552 if ('ip_address' in fixed_ips and
553 fixed_ips['ip_address'] in ips) or ips is None:
554 out.append(Port(**port))
557 out.append(Port(**port))
562 def create_security_group(neutron, keystone, sec_grp_settings, project_id):
564 Creates a security group object in OpenStack
565 :param neutron: the Neutron client
566 :param keystone: the Keystone client
567 :param sec_grp_settings: the security group settings
568 :param project_id: the default project to associated the security group
569 :return: a SNAPS-OO SecurityGroup domain object
571 logger.info('Creating security group with name - %s',
572 sec_grp_settings.name)
573 os_group = neutron.create_security_group(
574 sec_grp_settings.dict_for_neutron(keystone, project_id))
575 return __map_os_security_group(neutron, os_group['security_group'])
578 def delete_security_group(neutron, sec_grp):
580 Deletes a security group object from OpenStack
581 :param neutron: the client
582 :param sec_grp: the SNAPS SecurityGroup object to delete
584 logger.info('Deleting security group with name - %s', sec_grp.name)
585 neutron.delete_security_group(sec_grp.id)
588 def get_security_group(neutron, sec_grp_settings=None, sec_grp_name=None,
591 Returns the first security group for a given query. The query gets built
592 from the sec_grp_settings parameter if not None, else only the name of
593 the security group will be used, else if the query parameters are None then
594 None will be returned
595 :param neutron: the client
596 :param sec_grp_settings: an instance of SecurityGroupConfig object
597 :param sec_grp_name: the name of security group object to retrieve
598 :param project_id: the ID of the project/tentant object that owns the
599 secuity group to retrieve
600 :return: a SNAPS-OO SecurityGroup domain object or None if not found
603 sec_grp_filter = dict()
605 sec_grp_filter['tenant_id'] = project_id
608 sec_grp_filter['name'] = sec_grp_settings.name
610 if sec_grp_settings.description:
611 sec_grp_filter['description'] = sec_grp_settings.description
613 sec_grp_filter['name'] = sec_grp_name
617 groups = neutron.list_security_groups(**sec_grp_filter)
618 for group in groups['security_groups']:
619 return __map_os_security_group(neutron, group)
622 def __map_os_security_group(neutron, os_sec_grp):
624 Creates a SecurityGroup SNAPS domain object from an OpenStack Security
626 :param neutron: the neutron client for performing rule lookups
627 :param os_sec_grp: the OpenStack Security Group dict object
628 :return: a SecurityGroup object
630 os_sec_grp['rules'] = get_rules_by_security_group_id(
631 neutron, os_sec_grp['id'])
632 return SecurityGroup(**os_sec_grp)
635 def get_security_group_by_id(neutron, sec_grp_id):
637 Returns the first security group object of the given name else None
638 :param neutron: the client
639 :param sec_grp_id: the id of the security group to retrieve
640 :return: a SNAPS-OO SecurityGroup domain object or None if not found
642 logger.info('Retrieving security group with ID - ' + sec_grp_id)
644 groups = neutron.list_security_groups(**{'id': sec_grp_id})
645 for group in groups['security_groups']:
646 if group['id'] == sec_grp_id:
647 return __map_os_security_group(neutron, group)
651 def create_security_group_rule(neutron, sec_grp_rule_settings, proj_id):
653 Creates a security group rule in OpenStack
654 :param neutron: the client
655 :param sec_grp_rule_settings: the security group rule settings
656 :param proj_id: the default project to apply to the rule settings
657 :return: a SNAPS-OO SecurityGroupRule domain object
659 logger.info('Creating security group to security group - %s',
660 sec_grp_rule_settings.sec_grp_name)
661 os_rule = neutron.create_security_group_rule(
662 sec_grp_rule_settings.dict_for_neutron(neutron, proj_id))
663 return SecurityGroupRule(**os_rule['security_group_rule'])
666 def delete_security_group_rule(neutron, sec_grp_rule):
668 Deletes a security group rule object from OpenStack
669 :param neutron: the client
670 :param sec_grp_rule: the SNAPS SecurityGroupRule object to delete
672 logger.info('Deleting security group rule with ID - %s',
674 neutron.delete_security_group_rule(sec_grp_rule.id)
677 def get_rules_by_security_group(neutron, sec_grp):
679 Retrieves all of the rules for a given security group
680 :param neutron: the client
681 :param sec_grp: a list of SNAPS SecurityGroupRule domain objects
683 return get_rules_by_security_group_id(neutron, sec_grp.id)
686 def get_rules_by_security_group_id(neutron, sec_grp_id):
688 Retrieves all of the rules for a given security group by it's ID
689 :param neutron: the client
690 :param sec_grp_id: the ID of the associated security group
692 logger.info('Retrieving security group rules associate with the '
693 'security group with ID - %s', sec_grp_id)
695 rules = neutron.list_security_group_rules(
696 **{'security_group_id': sec_grp_id})
697 for rule in rules['security_group_rules']:
698 if rule['security_group_id'] == sec_grp_id:
699 out.append(SecurityGroupRule(**rule))
703 def get_rule_by_id(neutron, sec_grp, rule_id):
705 Returns a SecurityGroupRule object from OpenStack
706 :param neutron: the client
707 :param sec_grp: the SNAPS SecurityGroup domain object
708 :param rule_id: the rule's ID
709 :param sec_grp: a SNAPS SecurityGroupRule domain object
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['id'] == rule_id:
715 return SecurityGroupRule(**rule)
719 def get_external_networks(neutron):
721 Returns a list of external OpenStack network object/dict for all external
723 :param neutron: the client
724 :return: a list of external networks of Type SNAPS-OO domain class Network
727 for network in neutron.list_networks(
728 **{'router:external': True})['networks']:
729 out.append(__map_network(neutron, network))
733 def get_port_floating_ips(neutron, ports):
735 Returns all of the floating IPs associated with the ports returned in a
736 list of tuples where the port object is in the first position and the
737 floating IP object is in the second
738 :param neutron: the Neutron client
739 :param ports: a list of tuple 2 where index 0 is the port name and index 1
740 is the SNAPS-OO Port object
741 :return: a list of tuple 2 (port_id, SNAPS FloatingIp) objects when ports
742 is not None else a list of FloatingIp objects
745 fips = neutron.list_floatingips()
746 for fip in fips['floatingips']:
747 for port_name, port in ports:
748 if port and port.id == fip['port_id']:
749 out.append((port.id, FloatingIp(**fip)))
754 def get_floating_ips(neutron):
756 Returns a list of all of the floating IPs
757 :param neutron: the Neutron client
760 fips = neutron.list_floatingips()
761 for fip in fips['floatingips']:
762 out.append(FloatingIp(**fip))
766 def create_floating_ip(neutron, ext_net_name, port_id=None):
768 Returns the floating IP object that was created with this call
769 :param neutron: the Neutron client
770 :param ext_net_name: the name of the external network on which to apply the
772 :param port_id: the ID of the port to which the floating IP will be
774 :return: the SNAPS FloatingIp object
776 logger.info('Creating floating ip to external network - ' + ext_net_name)
777 ext_net = get_network(neutron, network_name=ext_net_name)
779 body = {'floatingip': {'floating_network_id': ext_net.id}}
781 body['floatingip']['port_id'] = port_id
783 fip = neutron.create_floatingip(body=body)
785 return FloatingIp(id=fip['floatingip']['id'],
786 ip=fip['floatingip']['floating_ip_address'])
788 raise NeutronException(
789 'Cannot create floating IP, external network not found')
792 def get_floating_ip(neutron, floating_ip):
794 Returns a floating IP object that should be identical to the floating_ip
796 :param neutron: the Neutron client
797 :param floating_ip: the SNAPS FloatingIp object
798 :return: hopefully the same floating IP object input
800 logger.debug('Attempting to retrieve existing floating ip with IP - %s',
802 os_fip = __get_os_floating_ip(neutron, floating_ip)
804 return FloatingIp(id=os_fip['id'], ip=os_fip['floating_ip_address'])
807 def __get_os_floating_ip(neutron, floating_ip):
809 Returns an OpenStack floating IP object
811 :param neutron: the Neutron client
812 :param floating_ip: the SNAPS FloatingIp object
813 :return: hopefully the same floating IP object input
815 logger.debug('Attempting to retrieve existing floating ip with IP - %s',
817 fips = neutron.list_floatingips(ip=floating_ip.id)
819 for fip in fips['floatingips']:
820 if fip['id'] == floating_ip.id:
824 def delete_floating_ip(neutron, floating_ip):
826 Responsible for deleting a floating IP
827 :param neutron: the Neutron client
828 :param floating_ip: the SNAPS FloatingIp object
831 logger.debug('Attempting to delete existing floating ip with IP - %s',
833 return neutron.delete_floatingip(floating_ip.id)
836 def get_network_quotas(neutron, project_id):
838 Returns a list of NetworkQuotas objects
839 :param neutron: the neutron client
840 :param project_id: the project's ID of the quotas to lookup
841 :return: an object of type NetworkQuotas or None if not found
843 quota = neutron.show_quota(project_id)
845 return NetworkQuotas(**quota['quota'])
848 def update_quotas(neutron, project_id, network_quotas):
850 Updates the networking quotas for a given project
851 :param neutron: the Neutron client
852 :param project_id: the project's ID that requires quota updates
853 :param network_quotas: an object of type NetworkQuotas containing the
858 update_body['security_group'] = network_quotas.security_group
859 update_body['security_group_rule'] = network_quotas.security_group_rule
860 update_body['floatingip'] = network_quotas.floatingip
861 update_body['network'] = network_quotas.network
862 update_body['port'] = network_quotas.port
863 update_body['router'] = network_quotas.router
864 update_body['subnet'] = network_quotas.subnet
866 return neutron.update_quota(project_id, {'quota': update_body})
869 class NeutronException(Exception):
871 Exception when calls to the Keystone client cannot be served properly