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
267 project = keystone_utils.get_project(
268 keystone, project_name=project_name)
270 sub_filter = {'name': subnet_name, 'project_id': project.id}
271 subnets = neutron.list_subnets(**sub_filter)
272 for subnet in subnets['subnets']:
273 return Subnet(**subnet)
275 sub_filter = {'name': subnet_name}
276 subnets = neutron.list_subnets(**sub_filter)
277 for subnet in subnets['subnets']:
278 return Subnet(**subnet)
281 def get_subnet_by_id(neutron, subnet_id):
283 Returns a SNAPS-OO Subnet domain object for a given ID
284 :param neutron: the OpenStack neutron client
285 :param subnet_id: the subnet ID
286 :return: a Subnet object
288 os_subnet = neutron.show_subnet(subnet_id)
289 if os_subnet and 'subnet' in os_subnet:
290 return Subnet(**os_subnet['subnet'])
293 def get_subnets_by_network(neutron, network):
295 Returns a list of SNAPS-OO Subnet domain objects
296 :param neutron: the OpenStack neutron client
297 :param network: the SNAPS-OO Network domain object
298 :return: a list of Subnet objects
300 return get_subnets_by_network_id(neutron, network.id)
303 def get_subnets_by_network_id(neutron, network_id):
305 Returns a list of SNAPS-OO Subnet domain objects
306 :param neutron: the OpenStack neutron client
307 :param network_id: the subnet's ID
308 :return: a list of Subnet objects
312 os_subnets = neutron.list_subnets(network_id=network_id)
314 for os_subnet in os_subnets['subnets']:
315 out.append(Subnet(**os_subnet))
320 def create_router(neutron, os_creds, router_settings):
322 Creates a router for OpenStack
323 :param neutron: the client
324 :param os_creds: the OpenStack credentials
325 :param router_settings: A dictionary containing the router configuration
326 and is responsible for creating the subnet request
328 :return: a SNAPS-OO Router domain object
331 json_body = router_settings.dict_for_neutron(neutron, os_creds)
332 logger.info('Creating router with name - ' + router_settings.name)
333 os_router = neutron.create_router(json_body)
334 return __map_router(neutron, os_router['router'])
336 logger.error("Failed to create router.")
337 raise NeutronException('Failed to create router')
340 def delete_router(neutron, router):
342 Deletes a router for OpenStack
343 :param neutron: the client
344 :param router: a SNAPS-OO Router domain object
346 if neutron and router:
347 logger.info('Deleting router with name - ' + router.name)
348 neutron.delete_router(router=router.id)
351 def get_router_by_id(neutron, router_id):
353 Returns a router with a given ID, else None if not found
354 :param neutron: the client
355 :param router_id: the Router ID
356 :return: a SNAPS-OO Router domain object
358 router = neutron.show_router(router_id)
360 return __map_router(neutron, router['router'])
363 def get_router(neutron, keystone, router_settings=None, router_name=None,
366 Returns the first router object (dictionary) found the given the settings
367 values if not None, else finds the first with the value of the router_name
369 :param neutron: the Neutron client
370 :param keystone: the Keystone client
371 :param router_settings: the RouterConfig object
372 :param router_name: the name of the network to retrieve
373 :param project_name: the name of the router's project
374 :return: a SNAPS-OO Router domain object
376 router_filter = dict()
378 router_filter['name'] = router_settings.name
379 if router_settings.admin_state_up is not None:
380 router_filter['admin_state_up'] = router_settings.admin_state_up
382 router_filter['name'] = router_name
386 os_routers = neutron.list_routers(**router_filter)
387 for os_router in os_routers['routers']:
389 if 'project_id' in os_router.keys():
390 project = keystone_utils.get_project_by_id(
391 keystone, os_router['project_id'])
393 project = keystone_utils.get_project_by_id(
394 keystone, os_router['tenant_id'])
395 if project and project.name == project_name:
396 return __map_router(neutron, os_router)
399 def __map_router(neutron, os_router):
401 Takes an OpenStack router instance and maps it to a SNAPS Router domain
403 :param neutron: the neutron client
404 :param os_router: the OpenStack Router object
407 device_ports = neutron.list_ports(
408 **{'device_id': os_router['id']})['ports']
409 port_subnets = list()
411 # Order by create date
412 sorted_ports = sorted(
413 device_ports, key=lambda dev_port: dev_port['created_at'])
415 for port in sorted_ports:
417 for fixed_ip in port['fixed_ips']:
418 subnet = get_subnet_by_id(neutron, fixed_ip['subnet_id'])
419 if subnet and subnet.network_id == port['network_id']:
420 subnets.append(subnet)
421 port_subnets.append((Port(**port), subnets))
423 os_router['port_subnets'] = port_subnets
424 return Router(**os_router)
427 def add_interface_router(neutron, router, subnet=None, port=None):
429 Adds an interface router for OpenStack for either a subnet or port.
430 Exception will be raised if requesting for both.
431 :param neutron: the client
432 :param router: the router object
433 :param subnet: the subnet object
434 :param port: the port object
435 :return: the interface router object
438 raise NeutronException(
439 'Cannot add interface to the router. Both subnet and '
440 'port were sent in. Either or please.')
442 if neutron and router and (router or subnet):
443 logger.info('Adding interface to router with name ' + router.name)
444 os_intf_router = neutron.add_interface_router(
445 router=router.id, body=__create_port_json_body(subnet, port))
446 return InterfaceRouter(**os_intf_router)
448 raise NeutronException(
449 'Unable to create interface router as neutron client,'
450 ' router or subnet were not created')
453 def remove_interface_router(neutron, router, subnet=None, port=None):
455 Removes an interface router for OpenStack
456 :param neutron: the client
457 :param router: the SNAPS-OO Router domain object
458 :param subnet: the subnet object (either subnet or port, not both)
459 :param port: the port object
463 logger.info('Removing router interface from router named ' +
465 neutron.remove_interface_router(
467 body=__create_port_json_body(subnet, port))
468 except NotFound as e:
469 logger.warning('Could not remove router interface. NotFound - %s',
473 logger.warning('Could not remove router interface, No router object')
476 def __create_port_json_body(subnet=None, port=None):
478 Returns the dictionary required for creating and deleting router
479 interfaces. Will only work on a subnet or port object. Will throw and
480 exception if parameters contain both or neither
481 :param subnet: the subnet object
482 :param port: the port object
486 raise NeutronException(
487 'Cannot create JSON body with both subnet and port')
488 if not subnet and not port:
489 raise NeutronException(
490 'Cannot create JSON body without subnet or port')
493 return {"subnet_id": subnet.id}
495 return {"port_id": port.id}
498 def create_port(neutron, os_creds, port_settings):
500 Creates a port for OpenStack
501 :param neutron: the client
502 :param os_creds: the OpenStack credentials
503 :param port_settings: the settings object for port configuration
504 :return: the SNAPS-OO Port domain object
506 json_body = port_settings.dict_for_neutron(neutron, os_creds)
507 logger.info('Creating port for network with name - %s',
508 port_settings.network_name)
509 os_port = neutron.create_port(body=json_body)['port']
510 return Port(**os_port)
513 def delete_port(neutron, port):
515 Removes an OpenStack port
516 :param neutron: the client
517 :param port: the SNAPS-OO Port domain object
519 logger.info('Deleting port with name ' + port.name)
520 neutron.delete_port(port.id)
523 def get_port(neutron, keystone, port_settings=None, port_name=None,
526 Returns the first port object (dictionary) found for the given query
527 :param neutron: the Neutron client
528 :param keystone: the Keystone client
529 :param port_settings: the PortConfig object used for generating the query
530 :param port_name: if port_settings is None, this name is the value to place
532 :param project_name: the associated project name
533 :return: a SNAPS-OO Port domain object
538 if port_settings.name and len(port_settings.name) > 0:
539 port_filter['name'] = port_settings.name
540 if port_settings.admin_state_up:
541 port_filter['admin_state_up'] = port_settings.admin_state_up
542 if port_settings.device_id:
543 port_filter['device_id'] = port_settings.device_id
544 if port_settings.mac_address:
545 port_filter['mac_address'] = port_settings.mac_address
546 if port_settings.project_name:
547 project_name = port_settings.project_name
548 if port_settings.network_name:
549 network = get_network(
550 neutron, keystone, network_name=port_settings.network_name,
551 project_name=project_name)
553 port_filter['network_id'] = network.id
555 port_filter['name'] = port_name
557 ports = neutron.list_ports(**port_filter)
558 for port in ports['ports']:
560 if 'project_id' in port.keys():
561 project = keystone_utils.get_project_by_id(
562 keystone, port['project_id'])
564 project = keystone_utils.get_project_by_id(
565 keystone, port['tenant_id'])
566 if project and project.name == project_name:
573 def get_port_by_id(neutron, port_id):
575 Returns a SNAPS-OO Port domain object for the given ID or none if not found
576 :param neutron: the client
577 :param port_id: the to query
578 :return: a SNAPS-OO Port domain object or None
580 port = neutron.show_port(port_id)
582 return Port(**port['port'])
586 def get_ports(neutron, network, ips=None):
588 Returns a list of SNAPS-OO Port objects for all OpenStack Port objects that
589 are associated with the 'network' parameter
590 :param neutron: the client
591 :param network: SNAPS-OO Network domain object
592 :param ips: the IPs to lookup if not None
593 :return: a SNAPS-OO Port domain object or None if not found
596 ports = neutron.list_ports(**{'network_id': network.id})
597 for port in ports['ports']:
599 for fixed_ips in port['fixed_ips']:
600 if ('ip_address' in fixed_ips and
601 fixed_ips['ip_address'] in ips) or ips is None:
602 out.append(Port(**port))
605 out.append(Port(**port))
610 def create_security_group(neutron, keystone, sec_grp_settings):
612 Creates a security group object in OpenStack
613 :param neutron: the Neutron client
614 :param keystone: the Keystone client
615 :param sec_grp_settings: the security group settings
616 :return: a SNAPS-OO SecurityGroup domain object
618 logger.info('Creating security group with name - %s',
619 sec_grp_settings.name)
620 os_group = neutron.create_security_group(
621 sec_grp_settings.dict_for_neutron(keystone))
622 return __map_os_security_group(neutron, os_group['security_group'])
625 def delete_security_group(neutron, sec_grp):
627 Deletes a security group object from OpenStack
628 :param neutron: the client
629 :param sec_grp: the SNAPS SecurityGroup object to delete
631 logger.info('Deleting security group with name - %s', sec_grp.name)
632 neutron.delete_security_group(sec_grp.id)
635 def get_security_group(neutron, keystone, sec_grp_settings=None,
636 sec_grp_name=None, project_name=None):
638 Returns the first security group for a given query. The query gets built
639 from the sec_grp_settings parameter if not None, else only the name of
640 the security group will be used, else if the query parameters are None then
641 None will be returned
642 :param neutron: the neutron client
643 :param keystone: the keystone client
644 :param sec_grp_settings: an instance of SecurityGroupConfig object
645 :param sec_grp_name: the name of security group object to retrieve
646 :param project_name: the name of the project/tentant object that owns the
647 secuity group to retrieve
648 :return: a SNAPS-OO SecurityGroup domain object or None if not found
651 sec_grp_filter = dict()
654 sec_grp_filter['name'] = sec_grp_settings.name
656 if sec_grp_settings.description:
657 sec_grp_filter['description'] = sec_grp_settings.description
658 if sec_grp_settings.project_name:
659 project_name = sec_grp_settings.project_name
661 sec_grp_filter['name'] = sec_grp_name
665 groups = neutron.list_security_groups(**sec_grp_filter)
666 for group in groups['security_groups']:
668 if 'project_id' in group.keys():
669 project = keystone_utils.get_project_by_id(
670 keystone, group['project_id'])
672 project = keystone_utils.get_project_by_id(
673 keystone, group['tenant_id'])
674 if project and project_name == project.name:
675 return __map_os_security_group(neutron, group)
677 return __map_os_security_group(neutron, group)
680 def __map_os_security_group(neutron, os_sec_grp):
682 Creates a SecurityGroup SNAPS domain object from an OpenStack Security
684 :param neutron: the neutron client for performing rule lookups
685 :param os_sec_grp: the OpenStack Security Group dict object
686 :return: a SecurityGroup object
688 os_sec_grp['rules'] = get_rules_by_security_group_id(
689 neutron, os_sec_grp['id'])
690 return SecurityGroup(**os_sec_grp)
693 def get_security_group_by_id(neutron, sec_grp_id):
695 Returns the first security group object of the given name else None
696 :param neutron: the client
697 :param sec_grp_id: the id of the security group to retrieve
698 :return: a SNAPS-OO SecurityGroup domain object or None if not found
700 logger.info('Retrieving security group with ID - ' + sec_grp_id)
702 groups = neutron.list_security_groups(**{'id': sec_grp_id})
703 for group in groups['security_groups']:
704 if group['id'] == sec_grp_id:
705 return __map_os_security_group(neutron, group)
709 def create_security_group_rule(neutron, keystone, sec_grp_rule_settings,
712 Creates a security group rule in OpenStack
713 :param neutron: the neutron client
714 :param keystone: the keystone client
715 :param sec_grp_rule_settings: the security group rule settings
716 :param proj_name: the default project name
717 :return: a SNAPS-OO SecurityGroupRule domain object
719 logger.info('Creating security group to security group - %s',
720 sec_grp_rule_settings.sec_grp_name)
721 os_rule = neutron.create_security_group_rule(
722 sec_grp_rule_settings.dict_for_neutron(neutron, keystone, proj_name))
723 return SecurityGroupRule(**os_rule['security_group_rule'])
726 def delete_security_group_rule(neutron, sec_grp_rule):
728 Deletes a security group rule object from OpenStack
729 :param neutron: the client
730 :param sec_grp_rule: the SNAPS SecurityGroupRule object to delete
732 logger.info('Deleting security group rule with ID - %s',
734 neutron.delete_security_group_rule(sec_grp_rule.id)
737 def get_rules_by_security_group(neutron, sec_grp):
739 Retrieves all of the rules for a given security group
740 :param neutron: the client
741 :param sec_grp: a list of SNAPS SecurityGroupRule domain objects
743 return get_rules_by_security_group_id(neutron, sec_grp.id)
746 def get_rules_by_security_group_id(neutron, sec_grp_id):
748 Retrieves all of the rules for a given security group by it's ID
749 :param neutron: the client
750 :param sec_grp_id: the ID of the associated security group
752 logger.info('Retrieving security group rules associate with the '
753 'security group with ID - %s', sec_grp_id)
755 rules = neutron.list_security_group_rules(
756 **{'security_group_id': sec_grp_id})
757 for rule in rules['security_group_rules']:
758 if rule['security_group_id'] == sec_grp_id:
759 out.append(SecurityGroupRule(**rule))
763 def get_rule_by_id(neutron, sec_grp, rule_id):
765 Returns a SecurityGroupRule object from OpenStack
766 :param neutron: the client
767 :param sec_grp: the SNAPS SecurityGroup domain object
768 :param rule_id: the rule's ID
769 :param sec_grp: a SNAPS SecurityGroupRule domain object
771 rules = neutron.list_security_group_rules(
772 **{'security_group_id': sec_grp.id})
773 for rule in rules['security_group_rules']:
774 if rule['id'] == rule_id:
775 return SecurityGroupRule(**rule)
779 def get_external_networks(neutron):
781 Returns a list of external OpenStack network object/dict for all external
783 :param neutron: the client
784 :return: a list of external networks of Type SNAPS-OO domain class Network
787 for network in neutron.list_networks(
788 **{'router:external': True})['networks']:
789 out.append(__map_network(neutron, network))
793 def get_port_floating_ips(neutron, ports):
795 Returns all of the floating IPs associated with the ports returned in a
796 list of tuples where the port object is in the first position and the
797 floating IP object is in the second
798 :param neutron: the Neutron client
799 :param ports: a list of tuple 2 where index 0 is the port name and index 1
800 is the SNAPS-OO Port object
801 :return: a list of tuple 2 (port_id, SNAPS FloatingIp) objects when ports
802 is not None else a list of FloatingIp objects
805 fips = neutron.list_floatingips()
806 for fip in fips['floatingips']:
807 for port_name, port in ports:
808 if port and port.id == fip['port_id']:
809 out.append((port.id, FloatingIp(**fip)))
814 def get_floating_ips(neutron):
816 Returns a list of all of the floating IPs
817 :param neutron: the Neutron client
820 fips = neutron.list_floatingips()
821 for fip in fips['floatingips']:
822 out.append(FloatingIp(**fip))
826 def create_floating_ip(neutron, keystone, ext_net_name, port_id=None):
828 Returns the floating IP object that was created with this call
829 :param neutron: the Neutron client
830 :param keystone: the Keystone client
831 :param ext_net_name: the name of the external network on which to apply the
833 :param port_id: the ID of the port to which the floating IP will be
835 :return: the SNAPS FloatingIp object
837 logger.info('Creating floating ip to external network - ' + ext_net_name)
838 ext_net = get_network(neutron, keystone, network_name=ext_net_name)
840 body = {'floatingip': {'floating_network_id': ext_net.id}}
842 body['floatingip']['port_id'] = port_id
844 fip = neutron.create_floatingip(body=body)
846 return FloatingIp(id=fip['floatingip']['id'],
847 ip=fip['floatingip']['floating_ip_address'])
849 raise NeutronException(
850 'Cannot create floating IP, external network not found')
853 def get_floating_ip(neutron, floating_ip):
855 Returns a floating IP object that should be identical to the floating_ip
857 :param neutron: the Neutron client
858 :param floating_ip: the SNAPS FloatingIp object
859 :return: hopefully the same floating IP object input
861 logger.debug('Attempting to retrieve existing floating ip with IP - %s',
863 os_fip = __get_os_floating_ip(neutron, floating_ip)
865 return FloatingIp(id=os_fip['id'], ip=os_fip['floating_ip_address'])
868 def __get_os_floating_ip(neutron, floating_ip):
870 Returns an OpenStack floating IP object
872 :param neutron: the Neutron client
873 :param floating_ip: the SNAPS FloatingIp object
874 :return: hopefully the same floating IP object input
876 logger.debug('Attempting to retrieve existing floating ip with IP - %s',
878 fips = neutron.list_floatingips(ip=floating_ip.id)
880 for fip in fips['floatingips']:
881 if fip['id'] == floating_ip.id:
885 def delete_floating_ip(neutron, floating_ip):
887 Responsible for deleting a floating IP
888 :param neutron: the Neutron client
889 :param floating_ip: the SNAPS FloatingIp object
892 logger.debug('Attempting to delete existing floating ip with IP - %s',
894 return neutron.delete_floatingip(floating_ip.id)
897 def get_network_quotas(neutron, project_id):
899 Returns a list of NetworkQuotas objects
900 :param neutron: the neutron client
901 :param project_id: the project's ID of the quotas to lookup
902 :return: an object of type NetworkQuotas or None if not found
904 quota = neutron.show_quota(project_id)
906 return NetworkQuotas(**quota['quota'])
909 def update_quotas(neutron, project_id, network_quotas):
911 Updates the networking quotas for a given project
912 :param neutron: the Neutron client
913 :param project_id: the project's ID that requires quota updates
914 :param network_quotas: an object of type NetworkQuotas containing the
919 update_body['security_group'] = network_quotas.security_group
920 update_body['security_group_rule'] = network_quotas.security_group_rule
921 update_body['floatingip'] = network_quotas.floatingip
922 update_body['network'] = network_quotas.network
923 update_body['port'] = network_quotas.port
924 update_body['router'] = network_quotas.router
925 update_body['subnet'] = network_quotas.subnet
927 return neutron.update_quota(project_id, {'quota': update_body})
930 class NeutronException(Exception):
932 Exception when calls to the Keystone client cannot be served properly