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, session=None):
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 :param session: the keystone session object (optional)
42 :return: the client object
45 session = keystone_utils.keystone_session(os_creds)
46 return Client(api_version=os_creds.network_api_version,
48 region_name=os_creds.region_name)
51 def create_network(neutron, os_creds, network_settings):
53 Creates a network for OpenStack
54 :param neutron: the client
55 :param os_creds: the OpenStack credentials
56 :param network_settings: A dictionary containing the network configuration
57 and is responsible for creating the network
59 :return: a SNAPS-OO Network domain object if found else None
61 logger.info('Creating network with name ' + network_settings.name)
62 json_body = network_settings.dict_for_neutron(os_creds)
63 os_network = neutron.create_network(body=json_body)
66 network = get_network_by_id(neutron, os_network['network']['id'])
69 for subnet_settings in network_settings.subnet_settings:
72 create_subnet(neutron, subnet_settings, os_creds, network))
75 'Unexpected error creating subnet [%s] for network [%s]',
76 subnet_settings.name, network.name)
78 for subnet in subnets:
79 delete_subnet(neutron, subnet)
81 delete_network(neutron, network)
85 return get_network_by_id(neutron, network.id)
88 def delete_network(neutron, network):
90 Deletes a network for OpenStack
91 :param neutron: the client
92 :param network: a SNAPS-OO Network domain object
94 if neutron and network:
96 for subnet in network.subnets:
97 logger.info('Deleting subnet with name ' + subnet.name)
99 delete_subnet(neutron, subnet)
103 logger.info('Deleting network with name ' + network.name)
104 neutron.delete_network(network.id)
107 def get_network(neutron, keystone, network_settings=None, network_name=None,
110 Returns Network SNAPS-OO domain object the first network found with
111 either the given attributes from the network_settings object if not None,
112 else the query will use just the name from the network_name parameter.
113 When the project_name is included, that will be added to the query filter.
114 :param neutron: the Neutron client
115 :param keystone: the Keystone client
116 :param network_settings: the NetworkConfig object used to create filter
117 :param network_name: the name of the network to retrieve
118 :param project_name: the name of the network's project
119 :return: a SNAPS-OO Network domain object
123 net_filter['name'] = network_settings.name
125 net_filter['name'] = network_name
127 networks = neutron.list_networks(**net_filter)
128 for network, netInsts in networks.items():
129 for inst in netInsts:
131 if 'project_id' in inst.keys():
132 project = keystone_utils.get_project_by_id(
133 keystone, inst['project_id'])
135 project = keystone_utils.get_project_by_id(
136 keystone, inst['tenant_id'])
137 if project and project.name == project_name:
138 return __map_network(neutron, inst)
140 return __map_network(neutron, inst)
143 def __get_os_network_by_id(neutron, network_id):
145 Returns the OpenStack network object (dictionary) with the given ID else
147 :param neutron: the client
148 :param network_id: the id of the network to retrieve
149 :return: a SNAPS-OO Network domain object
151 networks = neutron.list_networks(**{'id': network_id})
152 for network in networks['networks']:
153 if network['id'] == network_id:
157 def get_network_by_id(neutron, network_id):
159 Returns the SNAPS Network domain object for the given ID else None
160 :param neutron: the client
161 :param network_id: the id of the network to retrieve
162 :return: a SNAPS-OO Network domain object
164 os_network = __get_os_network_by_id(neutron, network_id)
166 return __map_network(neutron, os_network)
169 def __map_network(neutron, os_network):
171 Returns the network object (dictionary) with the given ID else None
172 :param neutron: the client
173 :param os_network: the OpenStack Network dict
174 :return: a SNAPS-OO Network domain object
176 subnets = get_subnets_by_network_id(neutron, os_network['id'])
177 os_network['subnets'] = subnets
178 return Network(**os_network)
181 def create_subnet(neutron, subnet_settings, os_creds, network):
183 Creates a network subnet for OpenStack
184 :param neutron: the client
185 :param subnet_settings: A dictionary containing the subnet configuration
186 and is responsible for creating the subnet request
188 :param os_creds: the OpenStack credentials
189 :param network: the network object
190 :return: a SNAPS-OO Subnet domain object
192 if neutron and network and subnet_settings:
193 json_body = {'subnets': [subnet_settings.dict_for_neutron(
194 os_creds, network=network)]}
195 logger.info('Creating subnet with name ' + subnet_settings.name)
196 subnets = neutron.create_subnet(body=json_body)
197 return Subnet(**subnets['subnets'][0])
199 raise NeutronException('Failed to create subnet')
202 def delete_subnet(neutron, subnet):
204 Deletes a network subnet for OpenStack
205 :param neutron: the client
206 :param subnet: a SNAPS-OO Subnet domain object
208 if neutron and subnet:
209 logger.info('Deleting subnet with name ' + subnet.name)
210 neutron.delete_subnet(subnet.id)
213 def get_subnet(neutron, network, subnet_settings=None, subnet_name=None):
215 Returns the first subnet object that fits the query else None including
216 if subnet_settings or subnet_name parameters are None.
217 :param neutron: the client
218 :param network: the associated SNAPS-OO Network domain object
219 :param subnet_settings: the subnet settings of the object to retrieve
220 :param subnet_name: the name of the subnet to retrieve
221 :return: a SNAPS-OO Subnet domain object or None
223 sub_filter = {'network_id': network.id}
225 sub_filter['name'] = subnet_settings.name
226 sub_filter['cidr'] = subnet_settings.cidr
227 if subnet_settings.gateway_ip:
228 sub_filter['gateway_ip'] = subnet_settings.gateway_ip
230 if subnet_settings.enable_dhcp is not None:
231 sub_filter['enable_dhcp'] = subnet_settings.enable_dhcp
233 if subnet_settings.destination:
234 sub_filter['destination'] = subnet_settings.destination
236 if subnet_settings.nexthop:
237 sub_filter['nexthop'] = subnet_settings.nexthop
239 if subnet_settings.ipv6_ra_mode:
240 sub_filter['ipv6_ra_mode'] = subnet_settings.ipv6_ra_mode
242 if subnet_settings.ipv6_address_mode:
243 sub_filter['ipv6_address_mode'] = subnet_settings.ipv6_address_mode
245 sub_filter['name'] = subnet_name
249 subnets = neutron.list_subnets(**sub_filter)
250 for subnet in subnets['subnets']:
251 return Subnet(**subnet)
254 def get_subnet_by_name(neutron, keystone, subnet_name, project_name=None):
256 Returns the first subnet object that fits the query else None including
257 if subnet_settings or subnet_name parameters are None.
258 :param neutron: the Neutron client
259 :param keystone: the Keystone client
260 :param subnet_name: the name of the subnet to retrieve
261 :param project_name: the name of the associated project to the subnet to
263 :return: a SNAPS-OO Subnet domain object or None
265 sub_filter = {'name': subnet_name}
266 subnets = neutron.list_subnets(**sub_filter)
267 for subnet in subnets['subnets']:
268 subnet = Subnet(**subnet)
270 project = keystone_utils.get_project_by_id(
271 keystone, subnet.project_id)
278 def get_subnet_by_id(neutron, subnet_id):
280 Returns a SNAPS-OO Subnet domain object for a given ID
281 :param neutron: the OpenStack neutron client
282 :param subnet_id: the subnet ID
283 :return: a Subnet object
285 os_subnet = neutron.show_subnet(subnet_id)
286 if os_subnet and 'subnet' in os_subnet:
287 return Subnet(**os_subnet['subnet'])
290 def get_subnets_by_network(neutron, network):
292 Returns a list of SNAPS-OO Subnet domain objects
293 :param neutron: the OpenStack neutron client
294 :param network: the SNAPS-OO Network domain object
295 :return: a list of Subnet objects
297 return get_subnets_by_network_id(neutron, network.id)
300 def get_subnets_by_network_id(neutron, network_id):
302 Returns a list of SNAPS-OO Subnet domain objects
303 :param neutron: the OpenStack neutron client
304 :param network_id: the subnet's ID
305 :return: a list of Subnet objects
309 os_subnets = neutron.list_subnets(network_id=network_id)
311 for os_subnet in os_subnets['subnets']:
312 out.append(Subnet(**os_subnet))
317 def create_router(neutron, os_creds, router_settings):
319 Creates a router for OpenStack
320 :param neutron: the client
321 :param os_creds: the OpenStack credentials
322 :param router_settings: A dictionary containing the router configuration
323 and is responsible for creating the subnet request
325 :return: a SNAPS-OO Router domain object
328 json_body = router_settings.dict_for_neutron(neutron, os_creds)
329 logger.info('Creating router with name - ' + router_settings.name)
330 os_router = neutron.create_router(json_body)
331 return __map_router(neutron, os_router['router'])
333 logger.error("Failed to create router.")
334 raise NeutronException('Failed to create router')
337 def delete_router(neutron, router):
339 Deletes a router for OpenStack
340 :param neutron: the client
341 :param router: a SNAPS-OO Router domain object
343 if neutron and router:
344 logger.info('Deleting router with name - ' + router.name)
345 neutron.delete_router(router=router.id)
348 def get_router_by_id(neutron, router_id):
350 Returns a router with a given ID, else None if not found
351 :param neutron: the client
352 :param router_id: the Router ID
353 :return: a SNAPS-OO Router domain object
355 router = neutron.show_router(router_id)
357 return __map_router(neutron, router['router'])
360 def get_router(neutron, keystone, router_settings=None, router_name=None,
363 Returns the first router object (dictionary) found the given the settings
364 values if not None, else finds the first with the value of the router_name
366 :param neutron: the Neutron client
367 :param keystone: the Keystone client
368 :param router_settings: the RouterConfig object
369 :param router_name: the name of the network to retrieve
370 :param project_name: the name of the router's project
371 :return: a SNAPS-OO Router domain object
373 router_filter = dict()
375 router_filter['name'] = router_settings.name
376 if router_settings.admin_state_up is not None:
377 router_filter['admin_state_up'] = router_settings.admin_state_up
379 router_filter['name'] = router_name
383 os_routers = neutron.list_routers(**router_filter)
384 for os_router in os_routers['routers']:
386 if 'project_id' in os_router.keys():
387 project = keystone_utils.get_project_by_id(
388 keystone, os_router['project_id'])
390 project = keystone_utils.get_project_by_id(
391 keystone, os_router['tenant_id'])
392 if project and project.name == project_name:
393 return __map_router(neutron, os_router)
396 def __map_router(neutron, os_router):
398 Takes an OpenStack router instance and maps it to a SNAPS Router domain
400 :param neutron: the neutron client
401 :param os_router: the OpenStack Router object
404 device_ports = neutron.list_ports(
405 **{'device_id': os_router['id']})['ports']
406 port_subnets = list()
408 # Order by create date
409 sorted_ports = sorted(
410 device_ports, key=lambda dev_port: dev_port['created_at'])
412 for port in sorted_ports:
414 for fixed_ip in port['fixed_ips']:
415 subnet = get_subnet_by_id(neutron, fixed_ip['subnet_id'])
416 if subnet and subnet.network_id == port['network_id']:
417 subnets.append(subnet)
418 port_subnets.append((Port(**port), subnets))
420 os_router['port_subnets'] = port_subnets
421 return Router(**os_router)
424 def add_interface_router(neutron, router, subnet=None, port=None):
426 Adds an interface router for OpenStack for either a subnet or port.
427 Exception will be raised if requesting for both.
428 :param neutron: the client
429 :param router: the router object
430 :param subnet: the subnet object
431 :param port: the port object
432 :return: the interface router object
435 raise NeutronException(
436 'Cannot add interface to the router. Both subnet and '
437 'port were sent in. Either or please.')
439 if neutron and router and (router or subnet):
440 logger.info('Adding interface to router with name ' + router.name)
441 os_intf_router = neutron.add_interface_router(
442 router=router.id, body=__create_port_json_body(subnet, port))
443 return InterfaceRouter(**os_intf_router)
445 raise NeutronException(
446 'Unable to create interface router as neutron client,'
447 ' router or subnet were not created')
450 def remove_interface_router(neutron, router, subnet=None, port=None):
452 Removes an interface router for OpenStack
453 :param neutron: the client
454 :param router: the SNAPS-OO Router domain object
455 :param subnet: the subnet object (either subnet or port, not both)
456 :param port: the port object
460 logger.info('Removing router interface from router named ' +
462 neutron.remove_interface_router(
464 body=__create_port_json_body(subnet, port))
465 except NotFound as e:
466 logger.warning('Could not remove router interface. NotFound - %s',
470 logger.warning('Could not remove router interface, No router object')
473 def __create_port_json_body(subnet=None, port=None):
475 Returns the dictionary required for creating and deleting router
476 interfaces. Will only work on a subnet or port object. Will throw and
477 exception if parameters contain both or neither
478 :param subnet: the subnet object
479 :param port: the port object
483 raise NeutronException(
484 'Cannot create JSON body with both subnet and port')
485 if not subnet and not port:
486 raise NeutronException(
487 'Cannot create JSON body without subnet or port')
490 return {"subnet_id": subnet.id}
492 return {"port_id": port.id}
495 def create_port(neutron, os_creds, port_settings):
497 Creates a port for OpenStack
498 :param neutron: the client
499 :param os_creds: the OpenStack credentials
500 :param port_settings: the settings object for port configuration
501 :return: the SNAPS-OO Port domain object
503 json_body = port_settings.dict_for_neutron(neutron, os_creds)
504 logger.info('Creating port for network with name - %s',
505 port_settings.network_name)
506 os_port = neutron.create_port(body=json_body)['port']
507 return Port(**os_port)
510 def delete_port(neutron, port):
512 Removes an OpenStack port
513 :param neutron: the client
514 :param port: the SNAPS-OO Port domain object
516 logger.info('Deleting port with name ' + port.name)
517 neutron.delete_port(port.id)
520 def get_port(neutron, keystone, port_settings=None, port_name=None,
523 Returns the first port object (dictionary) found for the given query
524 :param neutron: the Neutron client
525 :param keystone: the Keystone client
526 :param port_settings: the PortConfig object used for generating the query
527 :param port_name: if port_settings is None, this name is the value to place
529 :param project_name: the associated project name
530 :return: a SNAPS-OO Port domain object
535 if port_settings.name and len(port_settings.name) > 0:
536 port_filter['name'] = port_settings.name
537 if port_settings.admin_state_up:
538 port_filter['admin_state_up'] = port_settings.admin_state_up
539 if port_settings.device_id:
540 port_filter['device_id'] = port_settings.device_id
541 if port_settings.mac_address:
542 port_filter['mac_address'] = port_settings.mac_address
543 if port_settings.project_name:
544 project_name = port_settings.project_name
545 if port_settings.network_name:
546 network = get_network(
547 neutron, keystone, network_name=port_settings.network_name,
548 project_name=project_name)
550 port_filter['network_id'] = network.id
552 port_filter['name'] = port_name
554 ports = neutron.list_ports(**port_filter)
555 for port in ports['ports']:
557 if 'project_id' in port.keys():
558 project = keystone_utils.get_project_by_id(
559 keystone, port['project_id'])
561 project = keystone_utils.get_project_by_id(
562 keystone, port['tenant_id'])
563 if project and project.name == project_name:
570 def get_port_by_id(neutron, port_id):
572 Returns a SNAPS-OO Port domain object for the given ID or none if not found
573 :param neutron: the client
574 :param port_id: the to query
575 :return: a SNAPS-OO Port domain object or None
577 port = neutron.show_port(port_id)
579 return Port(**port['port'])
583 def get_ports(neutron, network, ips=None):
585 Returns a list of SNAPS-OO Port objects for all OpenStack Port objects that
586 are associated with the 'network' parameter
587 :param neutron: the client
588 :param network: SNAPS-OO Network domain object
589 :param ips: the IPs to lookup if not None
590 :return: a SNAPS-OO Port domain object or None if not found
593 ports = neutron.list_ports(**{'network_id': network.id})
594 for port in ports['ports']:
596 for fixed_ips in port['fixed_ips']:
597 if ('ip_address' in fixed_ips and
598 fixed_ips['ip_address'] in ips) or ips is None:
599 out.append(Port(**port))
602 out.append(Port(**port))
607 def create_security_group(neutron, keystone, sec_grp_settings):
609 Creates a security group object in OpenStack
610 :param neutron: the Neutron client
611 :param keystone: the Keystone client
612 :param sec_grp_settings: the security group settings
613 :return: a SNAPS-OO SecurityGroup domain object
615 logger.info('Creating security group with name - %s',
616 sec_grp_settings.name)
617 os_group = neutron.create_security_group(
618 sec_grp_settings.dict_for_neutron(keystone))
619 return __map_os_security_group(neutron, os_group['security_group'])
622 def delete_security_group(neutron, sec_grp):
624 Deletes a security group object from OpenStack
625 :param neutron: the client
626 :param sec_grp: the SNAPS SecurityGroup object to delete
628 logger.info('Deleting security group with name - %s', sec_grp.name)
629 neutron.delete_security_group(sec_grp.id)
632 def get_security_group(neutron, keystone, sec_grp_settings=None,
633 sec_grp_name=None, project_name=None):
635 Returns the first security group for a given query. The query gets built
636 from the sec_grp_settings parameter if not None, else only the name of
637 the security group will be used, else if the query parameters are None then
638 None will be returned
639 :param neutron: the neutron client
640 :param keystone: the keystone client
641 :param sec_grp_settings: an instance of SecurityGroupConfig object
642 :param sec_grp_name: the name of security group object to retrieve
643 :param project_name: the name of the project/tentant object that owns the
644 secuity group to retrieve
645 :return: a SNAPS-OO SecurityGroup domain object or None if not found
648 sec_grp_filter = dict()
651 sec_grp_filter['name'] = sec_grp_settings.name
653 if sec_grp_settings.description:
654 sec_grp_filter['description'] = sec_grp_settings.description
655 if sec_grp_settings.project_name:
656 project_name = sec_grp_settings.project_name
658 sec_grp_filter['name'] = sec_grp_name
662 groups = neutron.list_security_groups(**sec_grp_filter)
663 for group in groups['security_groups']:
665 if 'project_id' in group.keys():
666 project = keystone_utils.get_project_by_id(
667 keystone, group['project_id'])
669 project = keystone_utils.get_project_by_id(
670 keystone, group['tenant_id'])
671 if project and project_name == project.name:
672 return __map_os_security_group(neutron, group)
674 return __map_os_security_group(neutron, group)
677 def __map_os_security_group(neutron, os_sec_grp):
679 Creates a SecurityGroup SNAPS domain object from an OpenStack Security
681 :param neutron: the neutron client for performing rule lookups
682 :param os_sec_grp: the OpenStack Security Group dict object
683 :return: a SecurityGroup object
685 os_sec_grp['rules'] = get_rules_by_security_group_id(
686 neutron, os_sec_grp['id'])
687 return SecurityGroup(**os_sec_grp)
690 def get_security_group_by_id(neutron, sec_grp_id):
692 Returns the first security group object of the given name else None
693 :param neutron: the client
694 :param sec_grp_id: the id of the security group to retrieve
695 :return: a SNAPS-OO SecurityGroup domain object or None if not found
697 logger.info('Retrieving security group with ID - ' + sec_grp_id)
699 groups = neutron.list_security_groups(**{'id': sec_grp_id})
700 for group in groups['security_groups']:
701 if group['id'] == sec_grp_id:
702 return __map_os_security_group(neutron, group)
706 def create_security_group_rule(neutron, keystone, sec_grp_rule_settings,
709 Creates a security group rule in OpenStack
710 :param neutron: the neutron client
711 :param keystone: the keystone client
712 :param sec_grp_rule_settings: the security group rule settings
713 :param proj_name: the default project name
714 :return: a SNAPS-OO SecurityGroupRule domain object
716 logger.info('Creating security group to security group - %s',
717 sec_grp_rule_settings.sec_grp_name)
718 os_rule = neutron.create_security_group_rule(
719 sec_grp_rule_settings.dict_for_neutron(neutron, keystone, proj_name))
720 return SecurityGroupRule(**os_rule['security_group_rule'])
723 def delete_security_group_rule(neutron, sec_grp_rule):
725 Deletes a security group rule object from OpenStack
726 :param neutron: the client
727 :param sec_grp_rule: the SNAPS SecurityGroupRule object to delete
729 logger.info('Deleting security group rule with ID - %s',
731 neutron.delete_security_group_rule(sec_grp_rule.id)
734 def get_rules_by_security_group(neutron, sec_grp):
736 Retrieves all of the rules for a given security group
737 :param neutron: the client
738 :param sec_grp: a list of SNAPS SecurityGroupRule domain objects
740 return get_rules_by_security_group_id(neutron, sec_grp.id)
743 def get_rules_by_security_group_id(neutron, sec_grp_id):
745 Retrieves all of the rules for a given security group by it's ID
746 :param neutron: the client
747 :param sec_grp_id: the ID of the associated security group
749 logger.info('Retrieving security group rules associate with the '
750 'security group with ID - %s', sec_grp_id)
752 rules = neutron.list_security_group_rules(
753 **{'security_group_id': sec_grp_id})
754 for rule in rules['security_group_rules']:
755 if rule['security_group_id'] == sec_grp_id:
756 out.append(SecurityGroupRule(**rule))
760 def get_rule_by_id(neutron, sec_grp, rule_id):
762 Returns a SecurityGroupRule object from OpenStack
763 :param neutron: the client
764 :param sec_grp: the SNAPS SecurityGroup domain object
765 :param rule_id: the rule's ID
766 :param sec_grp: a SNAPS SecurityGroupRule domain object
768 rules = neutron.list_security_group_rules(
769 **{'security_group_id': sec_grp.id})
770 for rule in rules['security_group_rules']:
771 if rule['id'] == rule_id:
772 return SecurityGroupRule(**rule)
776 def get_external_networks(neutron):
778 Returns a list of external OpenStack network object/dict for all external
780 :param neutron: the client
781 :return: a list of external networks of Type SNAPS-OO domain class Network
784 for network in neutron.list_networks(
785 **{'router:external': True})['networks']:
786 out.append(__map_network(neutron, network))
790 def get_port_floating_ips(neutron, ports):
792 Returns all of the floating IPs associated with the ports returned in a
793 list of tuples where the port object is in the first position and the
794 floating IP object is in the second
795 :param neutron: the Neutron client
796 :param ports: a list of tuple 2 where index 0 is the port name and index 1
797 is the SNAPS-OO Port object
798 :return: a list of tuple 2 (port_id, SNAPS FloatingIp) objects when ports
799 is not None else a list of FloatingIp objects
802 fips = neutron.list_floatingips()
803 for fip in fips['floatingips']:
804 for port_name, port in ports:
805 if port and port.id == fip['port_id']:
806 out.append((port.id, FloatingIp(**fip)))
811 def get_floating_ips(neutron):
813 Returns a list of all of the floating IPs
814 :param neutron: the Neutron client
817 fips = neutron.list_floatingips()
818 for fip in fips['floatingips']:
819 out.append(FloatingIp(**fip))
823 def create_floating_ip(neutron, keystone, ext_net_name, port_id=None):
825 Returns the floating IP object that was created with this call
826 :param neutron: the Neutron client
827 :param keystone: the Keystone client
828 :param ext_net_name: the name of the external network on which to apply the
830 :param port_id: the ID of the port to which the floating IP will be
832 :return: the SNAPS FloatingIp object
834 logger.info('Creating floating ip to external network - ' + ext_net_name)
835 ext_net = get_network(neutron, keystone, network_name=ext_net_name)
837 body = {'floatingip': {'floating_network_id': ext_net.id}}
839 body['floatingip']['port_id'] = port_id
841 fip = neutron.create_floatingip(body=body)
843 return FloatingIp(id=fip['floatingip']['id'],
844 ip=fip['floatingip']['floating_ip_address'])
846 raise NeutronException(
847 'Cannot create floating IP, external network not found')
850 def get_floating_ip(neutron, floating_ip):
852 Returns a floating IP object that should be identical to the floating_ip
854 :param neutron: the Neutron client
855 :param floating_ip: the SNAPS FloatingIp object
856 :return: hopefully the same floating IP object input
858 logger.debug('Attempting to retrieve existing floating ip with IP - %s',
860 os_fip = __get_os_floating_ip(neutron, floating_ip)
862 return FloatingIp(id=os_fip['id'], ip=os_fip['floating_ip_address'])
865 def __get_os_floating_ip(neutron, floating_ip):
867 Returns an OpenStack floating IP object
869 :param neutron: the Neutron client
870 :param floating_ip: the SNAPS FloatingIp object
871 :return: hopefully the same floating IP object input
873 logger.debug('Attempting to retrieve existing floating ip with IP - %s',
875 fips = neutron.list_floatingips(ip=floating_ip.id)
877 for fip in fips['floatingips']:
878 if fip['id'] == floating_ip.id:
882 def delete_floating_ip(neutron, floating_ip):
884 Responsible for deleting a floating IP
885 :param neutron: the Neutron client
886 :param floating_ip: the SNAPS FloatingIp object
889 logger.debug('Attempting to delete existing floating ip with IP - %s',
891 return neutron.delete_floatingip(floating_ip.id)
894 def get_network_quotas(neutron, project_id):
896 Returns a list of NetworkQuotas objects
897 :param neutron: the neutron client
898 :param project_id: the project's ID of the quotas to lookup
899 :return: an object of type NetworkQuotas or None if not found
901 quota = neutron.show_quota(project_id)
903 return NetworkQuotas(**quota['quota'])
906 def update_quotas(neutron, project_id, network_quotas):
908 Updates the networking quotas for a given project
909 :param neutron: the Neutron client
910 :param project_id: the project's ID that requires quota updates
911 :param network_quotas: an object of type NetworkQuotas containing the
916 update_body['security_group'] = network_quotas.security_group
917 update_body['security_group_rule'] = network_quotas.security_group_rule
918 update_body['floatingip'] = network_quotas.floatingip
919 update_body['network'] = network_quotas.network
920 update_body['port'] = network_quotas.port
921 update_body['router'] = network_quotas.router
922 update_body['subnet'] = network_quotas.subnet
924 return neutron.update_quota(project_id, {'quota': update_body})
927 class NeutronException(Exception):
929 Exception when calls to the Keystone client cannot be served properly