X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=snaps%2Fopenstack%2Futils%2Fneutron_utils.py;h=806bb532868494c12ebad35f6dd93e5a6bc496a3;hb=d5d282dd1ffab96e85332bea580689c3297a25f8;hp=2f8ef7e5b3dd7f8a69c87de97cb3d9042a5ca0e2;hpb=80b70bdcc7a73e0050dae87e4d86159f2fd9b785;p=snaps.git diff --git a/snaps/openstack/utils/neutron_utils.py b/snaps/openstack/utils/neutron_utils.py index 2f8ef7e..806bb53 100644 --- a/snaps/openstack/utils/neutron_utils.py +++ b/snaps/openstack/utils/neutron_utils.py @@ -20,6 +20,7 @@ from neutronclient.neutron.client import Client from snaps.domain.network import ( Port, SecurityGroup, SecurityGroupRule, Router, InterfaceRouter, Subnet, Network) +from snaps.domain.project import NetworkQuotas from snaps.domain.vm_inst import FloatingIp from snaps.openstack.utils import keystone_utils @@ -74,42 +75,45 @@ def delete_network(neutron, network): neutron.delete_network(network.id) -def get_network(neutron, network_name, project_id=None): +def get_network(neutron, network_settings=None, network_name=None, + project_id=None): """ - Returns an object (dictionary) of the first network found with a given name - and project_id (if included) + Returns Network SNAPS-OO domain object the first network found with + either the given attributes from the network_settings object if not None, + else the query will use just the name from the network_name parameter. + When the project_id is included, that will be added to the query filter. :param neutron: the client + :param network_settings: the NetworkSettings object used to create filter :param network_name: the name of the network to retrieve :param project_id: the id of the network's project :return: a SNAPS-OO Network domain object """ net_filter = dict() - if network_name: + if network_settings: + net_filter['name'] = network_settings.name + elif network_name: net_filter['name'] = network_name + if project_id: net_filter['project_id'] = project_id networks = neutron.list_networks(**net_filter) for network, netInsts in networks.items(): for inst in netInsts: - if inst.get('name') == network_name: - return Network(**inst) - return None + return Network(**inst) def get_network_by_id(neutron, network_id): """ - Returns the network object (dictionary) with the given ID + Returns the network object (dictionary) with the given ID else None :param neutron: the client :param network_id: the id of the network to retrieve :return: a SNAPS-OO Network domain object """ networks = neutron.list_networks(**{'id': network_id}) - for network, netInsts in networks.items(): - for inst in netInsts: - if inst.get('id') == network_id: - return Network(**inst) - return None + for network in networks['networks']: + if network['id'] == network_id: + return Network(**network) def create_subnet(neutron, subnet_settings, os_creds, network=None): @@ -144,19 +148,73 @@ def delete_subnet(neutron, subnet): neutron.delete_subnet(subnet.id) -def get_subnet_by_name(neutron, subnet_name): +def get_subnet(neutron, subnet_settings=None, subnet_name=None): """ - Returns the first subnet object (dictionary) found with a given name + Returns the first subnet object that fits the query else None including + if subnet_settings or subnet_name parameters are None. :param neutron: the client - :param subnet_name: the name of the network to retrieve - :return: a SNAPS-OO Subnet domain object + :param subnet_settings: the subnet settings of the object to retrieve + :param subnet_name: the name of the subnet to retrieve + :return: a SNAPS-OO Subnet domain object or None """ - subnets = neutron.list_subnets(**{'name': subnet_name}) - for subnet, subnetInst in subnets.items(): - for inst in subnetInst: - if inst['name'] == subnet_name: - return Subnet(**inst) - return None + sub_filter = dict() + if subnet_settings: + sub_filter['name'] = subnet_settings.name + sub_filter['cidr'] = subnet_settings.cidr + if subnet_settings.gateway_ip: + sub_filter['gateway_ip'] = subnet_settings.gateway_ip + + if subnet_settings.enable_dhcp is not None: + sub_filter['enable_dhcp'] = subnet_settings.enable_dhcp + + if subnet_settings.destination: + sub_filter['destination'] = subnet_settings.destination + + if subnet_settings.nexthop: + sub_filter['nexthop'] = subnet_settings.nexthop + + if subnet_settings.ipv6_ra_mode: + sub_filter['ipv6_ra_mode'] = subnet_settings.ipv6_ra_mode + + if subnet_settings.ipv6_address_mode: + sub_filter['ipv6_address_mode'] = subnet_settings.ipv6_address_mode + elif subnet_name: + sub_filter['name'] = subnet_name + else: + return None + + subnets = neutron.list_subnets(**sub_filter) + for subnet in subnets['subnets']: + return Subnet(**subnet) + + +def get_subnet_by_id(neutron, subnet_id): + """ + Returns a SNAPS-OO Subnet domain object for a given ID + :param neutron: the OpenStack neutron client + :param subnet_id: the subnet ID + :return: a Subnet object + """ + os_subnet = neutron.show_subnet(subnet_id) + if os_subnet and 'subnet' in os_subnet: + return Subnet(**os_subnet['subnet']) + + +def get_subnets_by_network(neutron, network): + """ + Returns a list of SNAPS-OO Subnet domain objects + :param neutron: the OpenStack neutron client + :param network: the SNAPS-OO Network domain object + :return: a list of Subnet objects + """ + out = list() + + os_subnets = neutron.list_subnets(network_id=network.id) + + for os_subnet in os_subnets['subnets']: + out.append(Subnet(**os_subnet)) + + return out def create_router(neutron, os_creds, router_settings): @@ -190,18 +248,41 @@ def delete_router(neutron, router): neutron.delete_router(router=router.id) -def get_router_by_name(neutron, router_name): +def get_router_by_id(neutron, router_id): """ - Returns the first router object (dictionary) found with a given name + Returns a router with a given ID, else None if not found :param neutron: the client + :param router_id: the Router ID + :return: a SNAPS-OO Router domain object + """ + router = neutron.show_router(router_id) + if router: + return Router(**router['router']) + + +def get_router(neutron, router_settings=None, router_name=None): + """ + Returns the first router object (dictionary) found the given the settings + values if not None, else finds the first with the value of the router_name + parameter, else None + :param neutron: the client + :param router_settings: the RouterSettings object :param router_name: the name of the network to retrieve :return: a SNAPS-OO Router domain object """ - routers = neutron.list_routers(**{'name': router_name}) - for router, routerInst in routers.items(): - for inst in routerInst: - if inst.get('name') == router_name: - return Router(**inst) + router_filter = dict() + if router_settings: + router_filter['name'] = router_settings.name + if router_settings.admin_state_up is not None: + router_filter['admin_state_up'] = router_settings.admin_state_up + elif router_name: + router_filter['name'] = router_name + else: + return None + + routers = neutron.list_routers(**router_filter) + for routerInst in routers['routers']: + return Router(**routerInst) return None @@ -304,21 +385,76 @@ def delete_port(neutron, port): neutron.delete_port(port.id) -def get_port_by_name(neutron, port_name): +def get_port(neutron, port_settings=None, port_name=None): """ - Returns the first port object (dictionary) found with a given name + Returns the first port object (dictionary) found for the given query :param neutron: the client - :param port_name: the name of the port to retrieve + :param port_settings: the PortSettings object used for generating the query + :param port_name: if port_settings is None, this name is the value to place + into the query :return: a SNAPS-OO Port domain object """ - ports = neutron.list_ports(**{'name': port_name}) + port_filter = dict() + + if port_settings: + if port_settings.name and len(port_settings.name) > 0: + port_filter['name'] = port_settings.name + if port_settings.admin_state_up: + port_filter['admin_state_up'] = port_settings.admin_state_up + if port_settings.device_id: + port_filter['device_id'] = port_settings.device_id + if port_settings.mac_address: + port_filter['mac_address'] = port_settings.mac_address + if port_settings.network_name: + network = get_network(neutron, + network_name=port_settings.network_name) + port_filter['network_id'] = network.id + elif port_name: + port_filter['name'] = port_name + + ports = neutron.list_ports(**port_filter) for port in ports['ports']: - if port['name'] == port_name: - return Port(name=port['name'], id=port['id'], - ips=port['fixed_ips'], mac_address=port['mac_address']) + return Port(**port) return None +def get_port_by_id(neutron, port_id): + """ + Returns a SNAPS-OO Port domain object for the given ID or none if not found + :param neutron: the client + :param port_id: the to query + :return: a SNAPS-OO Port domain object or None + """ + port = neutron.show_port(port_id) + if port: + return Port(**port['port']) + return None + + +def get_ports(neutron, network, ips=None): + """ + Returns a list of SNAPS-OO Port objects for all OpenStack Port objects that + are associated with the 'network' parameter + :param neutron: the client + :param network: SNAPS-OO Network domain object + :param ips: the IPs to lookup if not None + :return: a SNAPS-OO Port domain object or None if not found + """ + out = list() + ports = neutron.list_ports(**{'network_id': network.id}) + for port in ports['ports']: + if ips: + for fixed_ips in port['fixed_ips']: + if ('ip_address' in fixed_ips and + fixed_ips['ip_address'] in ips) or ips is None: + out.append(Port(**port)) + break + else: + out.append(Port(**port)) + + return out + + def create_security_group(neutron, keystone, sec_grp_settings): """ Creates a security group object in OpenStack @@ -344,20 +480,38 @@ def delete_security_group(neutron, sec_grp): neutron.delete_security_group(sec_grp.id) -def get_security_group(neutron, name): +def get_security_group(neutron, sec_grp_settings=None, sec_grp_name=None, + project_id=None): """ - Returns the first security group object of the given name else None + Returns the first security group for a given query. The query gets built + from the sec_grp_settings parameter if not None, else only the name of + the security group will be used, else if the query parameters are None then + None will be returned :param neutron: the client - :param name: the name of security group object to retrieve + :param sec_grp_settings: an instance of SecurityGroupSettings config object + :param sec_grp_name: the name of security group object to retrieve + :param project_id: the ID of the project/tentant object that owns the + secuity group to retrieve :return: a SNAPS-OO SecurityGroup domain object or None if not found """ - logger.info('Retrieving security group with name - ' + name) - groups = neutron.list_security_groups(**{'name': name}) + sec_grp_filter = dict() + if project_id: + sec_grp_filter['tenant_id'] = project_id + + if sec_grp_settings: + sec_grp_filter['name'] = sec_grp_settings.name + + if sec_grp_settings.description: + sec_grp_filter['description'] = sec_grp_settings.description + elif sec_grp_name: + sec_grp_filter['name'] = sec_grp_name + else: + return None + + groups = neutron.list_security_groups(**sec_grp_filter) for group in groups['security_groups']: - if group['name'] == name: - return SecurityGroup(**group) - return None + return SecurityGroup(**group) def get_security_group_by_id(neutron, sec_grp_id): @@ -448,17 +602,30 @@ def get_external_networks(neutron): return out -def get_floating_ips(neutron): +def get_floating_ips(neutron, ports=None): """ Returns all of the floating IPs + When ports is not None, FIPs returned must be associated with one of the + ports in the list and a tuple 2 where the first element being the port's + ID and the second being the FloatingIp SNAPS-OO domain object. + When ports is None, all known FloatingIp SNAPS-OO domain objects will be + returned in a list :param neutron: the Neutron client - :return: a list of SNAPS FloatingIp objects + :param ports: a list of tuple 2 where index 0 is the port name and index 1 + is the SNAPS-OO Port object + :return: a list of tuple 2 (port_id, SNAPS FloatingIp) objects when ports + is not None else a list of Port objects """ out = list() fips = neutron.list_floatingips() for fip in fips['floatingips']: - out.append(FloatingIp(inst_id=fip['id'], - ip=fip['floating_ip_address'])) + if ports: + for port_name, port in ports: + if port and port.id == fip['port_id']: + out.append((port.id, FloatingIp(**fip))) + break + else: + out.append(FloatingIp(**fip)) return out @@ -472,13 +639,13 @@ def create_floating_ip(neutron, ext_net_name): :return: the SNAPS FloatingIp object """ logger.info('Creating floating ip to external network - ' + ext_net_name) - ext_net = get_network(neutron, ext_net_name) + ext_net = get_network(neutron, network_name=ext_net_name) if ext_net: fip = neutron.create_floatingip( body={'floatingip': {'floating_network_id': ext_net.id}}) - return FloatingIp(inst_id=fip['floatingip']['id'], + return FloatingIp(id=fip['floatingip']['id'], ip=fip['floatingip']['floating_ip_address']) else: raise NeutronException( @@ -497,8 +664,7 @@ def get_floating_ip(neutron, floating_ip): floating_ip.ip) os_fip = __get_os_floating_ip(neutron, floating_ip) if os_fip: - return FloatingIp( - inst_id=os_fip['id'], ip=os_fip['floating_ip_address']) + return FloatingIp(id=os_fip['id'], ip=os_fip['floating_ip_address']) def __get_os_floating_ip(neutron, floating_ip): @@ -530,6 +696,39 @@ def delete_floating_ip(neutron, floating_ip): return neutron.delete_floatingip(floating_ip.id) +def get_network_quotas(neutron, project_id): + """ + Returns a list of all available keypairs + :param neutron: the neutron client + :param project_id: the project's ID of the quotas to lookup + :return: an object of type NetworkQuotas or None if not found + """ + quota = neutron.show_quota(project_id) + if quota: + return NetworkQuotas(**quota['quota']) + + +def update_quotas(neutron, project_id, network_quotas): + """ + Updates the networking quotas for a given project + :param neutron: the Neutron client + :param project_id: the project's ID that requires quota updates + :param network_quotas: an object of type NetworkQuotas containing the + values to update + :return: + """ + update_body = dict() + update_body['security_group'] = network_quotas.security_group + update_body['security_group_rule'] = network_quotas.security_group_rule + update_body['floatingip'] = network_quotas.floatingip + update_body['network'] = network_quotas.network + update_body['port'] = network_quotas.port + update_body['router'] = network_quotas.router + update_body['subnet'] = network_quotas.subnet + + return neutron.update_quota(project_id, {'quota': update_body}) + + class NeutronException(Exception): """ Exception when calls to the Keystone client cannot be served properly