def deallocate_ports_for_instance(self, context, instance, network_info, requested_networks): if network_info is None: # not allocated networks return neutron = neutronv2.get_client(context) port_req_body = {'port': {'device_id': ''}} # Requires admin creds to set port bindings if self._has_port_binding_extension(context): port_req_body['port']['binding:host_id'] = None port_client = neutronv2.get_client(context, admin=True) else: port_client = neutron if requested_networks: for req in requested_networks: if req.port_id: port_client.update_port(req.port_id, port_req_body) elif req.network_id: port_ids = [] port_id = dict(network_info[0]).get('id') port_ids.append(port_id) self._delete_ports(neutron, instance, port_ids) self.get_instance_nw_info(context, instance, use_slave=True)
def remove_fixed_ip_from_instance(self, context, instance, address): """Remove a fixed ip from the instance.""" zone = 'compute:%s' % instance['availability_zone'] search_opts = {'device_id': instance['uuid'], 'device_owner': zone, 'fixed_ips': 'ip_address=%s' % address} data = neutronv2.get_client(context).list_ports(**search_opts) ports = data['ports'] for p in ports: fixed_ips = p['fixed_ips'] new_fixed_ips = [] for fixed_ip in fixed_ips: if fixed_ip['ip_address'] != address: new_fixed_ips.append(fixed_ip) port_req_body = {'port': {'fixed_ips': new_fixed_ips}} try: neutronv2.get_client(context).update_port(p['id'], port_req_body) except Exception as ex: msg = _("Unable to update port %(portid)s with" " failure: %(exception)s") LOG.debug(msg, {'portid': p['id'], 'exception': ex}) return raise exception.FixedIpNotFoundForSpecificInstance( instance_uuid=instance['uuid'], ip=address)
def deallocate_ports_for_instance(self, context, instance, network_info, requested_networks): if network_info is None: # not allocated networks return neutron = neutronv2.get_client(context) port_req_body = {"port": {"device_id": ""}} # Requires admin creds to set port bindings if self._has_port_binding_extension(context): port_req_body["port"]["binding:host_id"] = None port_client = neutronv2.get_client(context, admin=True) else: port_client = neutron if requested_networks: for req in requested_networks: if req.port_id: port_client.update_port(req.port_id, port_req_body) elif req.network_id: port_ids = [] port_id = dict(network_info[0]).get("id") port_ids.append(port_id) self._delete_ports(neutron, instance, port_ids) self.get_instance_nw_info(context, instance, use_slave=True)
def setUp(self): super(TestNeutronDriver, self).setUp() self.mox.StubOutWithMock(neutronv2, "get_client") self.moxed_client = self.mox.CreateMock(client.Client) neutronv2.get_client(mox.IgnoreArg()).MultipleTimes().AndReturn(self.moxed_client) self.context = context.RequestContext("userid", "my_tenantid") setattr(self.context, "auth_token", "bff4a5a6b9eb4ea2a6efec6eefb77936")
def add_fixed_ip_to_instance(self, context, instance, network_id): """Add a fixed ip to the instance from specified network.""" search_opts = {'network_id': network_id} data = neutronv2.get_client(context).list_subnets(**search_opts) ipam_subnets = data.get('subnets', []) if not ipam_subnets: raise exception.NetworkNotFoundForInstance( instance_id=instance['uuid']) zone = 'compute:%s' % instance['availability_zone'] search_opts = {'device_id': instance['uuid'], 'device_owner': zone, 'network_id': network_id} data = neutronv2.get_client(context).list_ports(**search_opts) ports = data['ports'] for p in ports: for subnet in ipam_subnets: fixed_ips = p['fixed_ips'] fixed_ips.append({'subnet_id': subnet['id']}) port_req_body = {'port': {'fixed_ips': fixed_ips}} try: neutronv2.get_client(context).update_port(p['id'], port_req_body) return except Exception as ex: msg = _("Unable to update port %(portid)s on subnet " "%(subnet_id)s with failure: %(exception)s") LOG.debug(msg, {'portid': p['id'], 'subnet_id': subnet['id'], 'exception': ex}) raise exception.NetworkNotFoundForInstance( instance_id=instance['uuid'])
def deallocate_for_instance(self, context, instance, **kwargs): """Deallocate all network resources related to the instance. This version differs from super class because it will not delete network owned ports. """ LOG.debug(_('deallocate_for_instance() for %s'), instance['display_name']) requested_networks = kwargs.get('requested_networks') or {} ports_to_skip = [port_id for nets, fips, port_id in requested_networks] search_opts = {'device_id': instance['uuid']} data = neutronv2.get_client(context).list_ports(**search_opts) ports = data.get('ports', []) for port in ports: if port['id'] in ports_to_skip: continue try: # NOTE(rods): The following 'if' statement is the only # difference with the parent method if port['device_owner'].startswith('network:'): body = dict(device_id='') neutronv2.get_client(context).update_port( port['id'], dict(port=body)) else: neutronv2.get_client(context).delete_port(port['id']) except Exception: LOG.exception( _("Failed to delete neutron port %(portid)s") % {'portid': port['id']})
def deallocate_for_instance(self, context, instance, **kwargs): """Deallocate all network resources related to the instance. This version differs from super class because it will not delete network owned ports. """ LOG.debug(_('deallocate_for_instance() for %s'), instance['display_name']) requested_networks = kwargs.get('requested_networks') or {} ports_to_skip = [port_id for nets, fips, port_id in requested_networks] search_opts = {'device_id': instance['uuid']} data = neutronv2.get_client(context).list_ports(**search_opts) ports = data.get('ports', []) for port in ports: if port['id'] in ports_to_skip: continue try: # NOTE(rods): The following 'if' statement is the only # difference with the parent method if port['device_owner'].startswith('network:'): body = dict(device_id='') neutronv2.get_client(context).update_port( port['id'], dict(port=body)) else: neutronv2.get_client(context).delete_port(port['id']) except Exception: LOG.exception(_("Failed to delete neutron port %(portid)s") % {'portid': port['id']})
def remove_fixed_ip_from_instance(self, context, instance, address, conductor_api=None): """Remove a fixed ip from the instance.""" zone = 'compute:%s' % instance['availability_zone'] search_opts = {'device_id': instance['uuid'], 'device_owner': zone, 'fixed_ips': 'ip_address=%s' % address} data = neutronv2.get_client(context).list_ports(**search_opts) ports = data['ports'] for p in ports: fixed_ips = p['fixed_ips'] new_fixed_ips = [] for fixed_ip in fixed_ips: if fixed_ip['ip_address'] != address: new_fixed_ips.append(fixed_ip) port_req_body = {'port': {'fixed_ips': new_fixed_ips}} try: neutronv2.get_client(context).update_port(p['id'], port_req_body) except Exception as ex: msg = _("Unable to update port %(portid)s with" " failure: %(exception)s") LOG.debug(msg, {'portid': p['id'], 'exception': ex}) return raise exception.FixedIpNotFoundForSpecificInstance( instance_uuid=instance['uuid'], ip=address)
def add_fixed_ip_to_instance(self, context, instance, network_id, conductor_api=None): """Add a fixed ip to the instance from specified network.""" search_opts = {"network_id": network_id} data = neutronv2.get_client(context).list_subnets(**search_opts) ipam_subnets = data.get("subnets", []) if not ipam_subnets: raise exception.NetworkNotFoundForInstance(instance_id=instance["uuid"]) zone = "compute:%s" % instance["availability_zone"] search_opts = {"device_id": instance["uuid"], "device_owner": zone, "network_id": network_id} data = neutronv2.get_client(context).list_ports(**search_opts) ports = data["ports"] for p in ports: for subnet in ipam_subnets: fixed_ips = p["fixed_ips"] fixed_ips.append({"subnet_id": subnet["id"]}) port_req_body = {"port": {"fixed_ips": fixed_ips}} try: neutronv2.get_client(context).update_port(p["id"], port_req_body) return except Exception as ex: msg = _("Unable to update port %(portid)s on subnet " "%(subnet_id)s with failure: %(exception)s") LOG.debug(msg, {"portid": p["id"], "subnet_id": subnet["id"], "exception": ex}) raise exception.NetworkNotFoundForInstance(instance_id=instance["uuid"])
def add_fixed_ip_to_instance(self, context, instance, network_id, conductor_api=None): """Add a fixed ip to the instance from specified network.""" search_opts = {'network_id': network_id} data = neutronv2.get_client(context).list_subnets(**search_opts) ipam_subnets = data.get('subnets', []) if not ipam_subnets: raise exception.NetworkNotFoundForInstance( instance_id=instance['uuid']) zone = 'compute:%s' % instance['availability_zone'] search_opts = {'device_id': instance['uuid'], 'device_owner': zone, 'network_id': network_id} data = neutronv2.get_client(context).list_ports(**search_opts) ports = data['ports'] for p in ports: for subnet in ipam_subnets: fixed_ips = p['fixed_ips'] fixed_ips.append({'subnet_id': subnet['id']}) port_req_body = {'port': {'fixed_ips': fixed_ips}} try: neutronv2.get_client(context).update_port(p['id'], port_req_body) return except Exception as ex: msg = _("Unable to update port %(portid)s on subnet " "%(subnet_id)s with failure: %(exception)s") LOG.debug(msg, {'portid': p['id'], 'subnet_id': subnet['id'], 'exception': ex}) raise exception.NetworkNotFoundForInstance( instance_id=instance['uuid'])
def _remove_network_from_routers(self, context, network): ports = neutron.get_client(context).list_ports( network_id=network["id"]) for port in ports["ports"]: if port["device_owner"] != "network:router_interface": continue neutron.get_client(context).remove_interface_router( port["device_id"], {"port_id": port["id"]})
def setUp(self): super(TestNeutronDriver, self).setUp() self.mox.StubOutWithMock(neutronv2, 'get_client') self.moxed_client = self.mox.CreateMock(client.Client) neutronv2.get_client(mox.IgnoreArg()).MultipleTimes().AndReturn( self.moxed_client) self.context = context.RequestContext('userid', 'my_tenantid') setattr(self.context, 'auth_token', 'bff4a5a6b9eb4ea2a6efec6eefb77936')
def _neutron_unused_port_cleanup(context): """ This task periodically runs to check if there are any 'stale' neutron ports that need cleanup or not and eventually cleans it up. 'stale' ports are those which are not in use by any of the instance and hence should be freed up for deploys if they exit :param context: The context object. """ LOG.debug('pvc_nova.compute.manager.PowerVCComputeManager ' '_neutron_unused_port_cleanup: Cleaning up unused neutron ' 'ports...') #Get all the running instances from the DB which aren't deleted. ports_ids_to_delete = [] try: # Expensive! db_instances = nova_db.instance_get_all(context) # Get all the neutron ports. Expensive! network_data = neutronv2.get_client(context).list_ports() ports = network_data.get('ports', []) # We run through the list of ports and see if they have a device_id # If the device_id exists, we see if they are in use with an # instance or not, if No, then we delete them. for port in ports: found_server = False for instance in db_instances: if port.get('device_id', None) is not None and\ port['device_id'] == instance['uuid']: found_server = True break # Only delete ports that are owned by Compute. Do NOT # delete ports owned by say SCE. dev_owner = port.get('device_owner', None) owned_by_compute = False if dev_owner is not None and dev_owner == 'compute:None': owned_by_compute = True if not found_server and owned_by_compute: ports_ids_to_delete.append(port['id']) LOG.info(_('Deleting neutron port with id %(id)s and data ' '%(data)s') % {'id': port['id'], 'data': str(port)}) except Exception as exc: LOG.exception(exc) # Now iterate the legit candidates for deletion and delete them. for port_id in ports_ids_to_delete: try: neutronv2.get_client(context).delete_port(port_id) LOG.warning(_('Cleaning up the unused neutron port with id ' '%(port)s') % {'port': port_id}) except Exception as exc: LOG.exception(exc) LOG.debug('Exiting neutron port clean up')
def deallocate_port_for_instance(self, context, instance, port_id, conductor_api=None): """Remove a specified port from the instance. Return network information for the instance """ try: neutronv2.get_client(context).delete_port(port_id) except Exception as ex: LOG.exception(_("Failed to delete neutron port %s") % port_id) return self._get_instance_nw_info(context, instance)
def deallocate_port_for_instance(self, context, instance, port_id): """Remove a specified port from the instance. Return network information for the instance """ try: neutronv2.get_client(context).delete_port(port_id) except Exception as ex: LOG.exception(_("Failed to delete neutron port %s") % port_id) return self._get_instance_nw_info(context, instance)
def deallocate_for_instance(self, context, instance, **kwargs): """Deallocate all network resources related to the instance.""" LOG.debug(_('deallocate_for_instance() for %s'), instance['display_name']) search_opts = {'device_id': instance['uuid']} data = neutronv2.get_client(context).list_ports(**search_opts) ports = data.get('ports', []) for port in ports: try: neutronv2.get_client(context).delete_port(port['id']) except Exception: LOG.exception(_("Failed to delete neutron port %(portid)s") % {'portid': port['id']})
def _get_subnets_from_port(self, context, port): """Return the subnets for a given port.""" fixed_ips = port['fixed_ips'] # No fixed_ips for the port means there is no subnet associated # with the network the port is created on. # Since list_subnets(id=[]) returns all subnets visible for the # current tenant, returned subnets may contain subnets which is not # related to the port. To avoid this, the method returns here. if not fixed_ips: return [] search_opts = {'id': [ip['subnet_id'] for ip in fixed_ips]} data = neutronv2.get_client(context).list_subnets(**search_opts) ipam_subnets = data.get('subnets', []) subnets = [] for subnet in ipam_subnets: subnet_dict = { 'cidr': subnet['cidr'], 'gateway': network_model.IP(address=subnet['gateway_ip'], type='gateway'), } # attempt to populate DHCP server field search_opts = { 'network_id': subnet['network_id'], 'device_owner': 'network:dhcp' } data = neutronv2.get_client(context).list_ports(**search_opts) dhcp_ports = data.get('ports', []) for p in dhcp_ports: for ip_pair in p['fixed_ips']: if ip_pair['subnet_id'] == subnet['id']: subnet_dict['dhcp_server'] = ip_pair['ip_address'] break subnet_object = network_model.Subnet(**subnet_dict) for dns in subnet.get('dns_nameservers', []): subnet_object.add_dns(network_model.IP(address=dns, type='dns')) for route in subnet.get('host_routes', []): subnet_object.add_route( network_model.Route(cidr=route['destination'], gateway=network_model.IP( address=route['nexthop'], type='gateway'))) subnets.append(subnet_object) return subnets
def deallocate_for_instance(self, context, instance, **kwargs): """Deallocate all network resources related to the instance.""" LOG.debug(_('deallocate_for_instance() for %s'), instance['display_name']) search_opts = {'device_id': instance['uuid']} data = neutronv2.get_client(context).list_ports(**search_opts) ports = data.get('ports', []) for port in ports: try: neutronv2.get_client(context).delete_port(port['id']) except Exception: LOG.exception( _("Failed to delete neutron port %(portid)s") % {'portid': port['id']})
def _add_subnet_to_external_router(self, context, subnet_id): routers = neutron.get_client(context).list_routers() routers = routers["routers"] router = next((r for r in routers if (r["status"] == "ACTIVE" and r["tenant_id"] == context.project_id and r["external_gateway_info"])), None) if router is None: return try: neutron.get_client(context).add_interface_router( router["id"], {"subnet_id": subnet_id}) except Exception: LOG.exception("Failed to add subnet (%s) to router (%s)", subnet_id, router["id"])
def _get_subnets_from_port(self, context, port): """Return the subnets for a given port.""" fixed_ips = port['fixed_ips'] # No fixed_ips for the port means there is no subnet associated # with the network the port is created on. # Since list_subnets(id=[]) returns all subnets visible for the # current tenant, returned subnets may contain subnets which is not # related to the port. To avoid this, the method returns here. if not fixed_ips: return [] search_opts = {'id': [ip['subnet_id'] for ip in fixed_ips]} data = neutronv2.get_client(context).list_subnets(**search_opts) ipam_subnets = data.get('subnets', []) subnets = [] for subnet in ipam_subnets: subnet_dict = {'cidr': subnet['cidr'], 'gateway': network_model.IP( address=subnet['gateway_ip'], type='gateway'), } # attempt to populate DHCP server field search_opts = {'network_id': subnet['network_id'], 'device_owner': 'network:dhcp'} data = neutronv2.get_client(context).list_ports(**search_opts) dhcp_ports = data.get('ports', []) for p in dhcp_ports: for ip_pair in p['fixed_ips']: if ip_pair['subnet_id'] == subnet['id']: subnet_dict['dhcp_server'] = ip_pair['ip_address'] break subnet_object = network_model.Subnet(**subnet_dict) for dns in subnet.get('dns_nameservers', []): subnet_object.add_dns( network_model.IP(address=dns, type='dns')) for route in subnet.get('host_routes', []): subnet_object.add_route( network_model.Route(cidr=route['destination'], gateway=network_model.IP( address=route['nexthop'], type='gateway'))) subnets.append(subnet_object) return subnets
def get_all(self, context): """Get all networks for client.""" client = neutronv2.get_client(context) networks = client.list_networks().get("networks") for network in networks: network["label"] = network["name"] return networks
def get_floating_ip_by_address(self, context, address): """Return a floating ip given an address.""" client = neutronv2.get_client(context) fip = self._get_floating_ip_by_address(client, address) pool_dict = self._setup_net_dict(client, fip["floating_network_id"]) port_dict = self._setup_port_dict(client, fip["port_id"]) return self._format_floating_ip_model(fip, pool_dict, port_dict)
def get_floating_ip(self, context, id): """Return floating ip object given the floating ip id.""" client = neutronv2.get_client(context) fip = client.show_floatingip(id)["floatingip"] pool_dict = self._setup_net_dict(client, fip["floating_network_id"]) port_dict = self._setup_port_dict(client, fip["port_id"]) return self._format_floating_ip_model(fip, pool_dict, port_dict)
def _get_available_networks(self, context, project_id, net_ids=None): """Return a network list available for the tenant. The list contains networks owned by the tenant and public networks. If net_ids specified, it searches networks with requested IDs only. """ neutron = neutronv2.get_client(context) if context.is_admin: # To allow admin to connect port from one tenant to instance in # another tenant, this function should return networks without # filtering over tenant_id. search_opts = {} if net_ids: search_opts["id"] = net_ids nets = neutron.list_networks(**search_opts).get("networks", []) else: # If user has specified to attach instance only to specific # networks, add them to **search_opts # (1) Retrieve non-public network list owned by the tenant. search_opts = {"tenant_id": project_id, "shared": False} if net_ids: search_opts["id"] = net_ids nets = neutron.list_networks(**search_opts).get("networks", []) # (2) Retrieve public network list. search_opts = {"shared": True} if net_ids: search_opts["id"] = net_ids nets += neutron.list_networks(**search_opts).get("networks", []) _ensure_requested_network_ordering(lambda x: x["id"], nets, net_ids) return nets
def add_item(self, context, name, body, zone_id=None): ip_range = body['IPv4Range'] gateway = body.get('gatewayIPv4') if gateway is None: network_cidr = netaddr.IPNetwork(ip_range) gateway_ip = netaddr.IPAddress(network_cidr.first + 1) gateway = str(gateway_ip) quantum_api = neutron.get_client(context) network = None try: network = self.get_item(context, name) except exception.NotFound: pass if network is not None: raise exception.Duplicate network_body = {} network_body["network"] = {"name": name} network = quantum_api.create_network(network_body) network = network["network"] if ip_range: subnet_body = {} subnet_body["subnet"] = { # NOTE(Alex) "name": name + ".default_subnet", # Won't give it a name for now "network_id": network["id"], "ip_version": "4", "cidr": ip_range, "gateway_ip": gateway} result_data = quantum_api.create_subnet(subnet_body) subnet_id = result_data["subnet"]["id"] self._add_subnet_to_external_router(context, subnet_id) return network
def deallocate(self, context, instance_id): """Deallocate all network resources related to the instance.""" search_opts = {'device_id': instance_id} neutron = neutronv2.get_client(context, admin=True) data = neutron.list_ports(**search_opts) ports = [port['id'] for port in data.get('ports', [])] self._delete_ports(neutron, instance_id, ports, raise_if_fail=True)
def create_pci_requests_for_sriov_ports(self, context, pci_requests, requested_networks): """Check requested networks for any SR-IOV port request. Create a PCI request object for each SR-IOV port, and add it to the pci_requests object that contains a list of PCI request object. """ if not requested_networks: return neutron = neutronv2.get_client(context, admin=True) for request_net in requested_networks: phynet_name = None vnic_type = network_model.VNIC_TYPE_NORMAL # TODO if the base code changes, should check here vnic_type_list = [network_model.VNIC_TYPE_VHOSTUSER, network_model.VNIC_TYPE_NORMAL] if request_net.port_id: vnic_type, phynet_name = self._get_port_vnic_info(context, neutron, request_net.port_id) pci_request_id = None if vnic_type not in vnic_type_list: request = objects.InstancePCIRequest( count=1, spec=[{pci_request.PCI_NET_TAG: phynet_name}], request_id=str(uuid.uuid4()) ) pci_requests.requests.append(request) pci_request_id = request.request_id request_net.pci_request_id = pci_request_id
def get_floating_ip(self, context, id): """Return floating ip object given the floating ip id.""" client = neutronv2.get_client(context) fip = client.show_floatingip(id)['floatingip'] pool_dict = self._setup_net_dict(client, fip['floating_network_id']) port_dict = self._setup_port_dict(client, fip['port_id']) return self._format_floating_ip_model(fip, pool_dict, port_dict)
def get_floating_ips_by_project(self, context): client = neutronv2.get_client(context) project_id = context.project_id fips = client.list_floatingips(tenant_id=project_id)["floatingips"] pool_dict = self._setup_pools_dict(client) port_dict = self._setup_ports_dict(client, project_id) return [self._format_floating_ip_model(fip, pool_dict, port_dict) for fip in fips]
def get_instances_security_groups_bindings(self, context, servers, detailed=False): """Returns a dict(instance_id, [security_groups]) to allow obtaining all of the instances and their security groups in one shot. """ neutron = neutronv2.get_client(context) ports = self._get_ports_from_server_list(servers, neutron) security_groups = self._get_secgroups_from_port_list(ports, neutron) instances_security_group_bindings = {} for port in ports: for port_sg_id in port.get("security_groups", []): # Note: have to check we found port_sg as its possible # the port has an SG that this user doesn't have access to port_sg = security_groups.get(port_sg_id) if port_sg: if detailed: sg_entry = self._convert_to_nova_security_group_format(port_sg) instances_security_group_bindings.setdefault(port["device_id"], []).append(sg_entry) else: # name is optional in neutron so if not specified # return id name = port_sg.get("name") if not name: name = port_sg.get("id") sg_entry = {"name": name} instances_security_group_bindings.setdefault(port["device_id"], []).append(sg_entry) return instances_security_group_bindings
def validate_networks(self, context, requested_networks): """Validate that the tenant can use the requested networks.""" LOG.debug(_('validate_networks() for %s'), requested_networks) if not requested_networks: return net_ids = [] for (net_id, _i, port_id) in requested_networks: if port_id: port = (neutronv2.get_client(context) .show_port(port_id) .get('port')) if not port: raise exception.PortNotFound(port_id=port_id) if port.get('device_id', None): raise exception.PortInUse(port_id=port_id) net_id = port['network_id'] if net_id in net_ids: raise exception.NetworkDuplicated(network_id=net_id) net_ids.append(net_id) nets = self._get_available_networks(context, context.project_id, net_ids) if len(nets) != len(net_ids): requsted_netid_set = set(net_ids) returned_netid_set = set([net['id'] for net in nets]) lostid_set = requsted_netid_set - returned_netid_set id_str = '' for _id in lostid_set: id_str = id_str and id_str + ', ' + _id or _id raise exception.NetworkNotFound(network_id=id_str)
def validate_networks(self, context, requested_networks): """Validate that the tenant can use the requested networks.""" LOG.debug(_('validate_networks() for %s'), requested_networks) if not requested_networks: return net_ids = [] for (net_id, _i, port_id) in requested_networks: if port_id: port = (neutronv2.get_client(context).show_port(port_id).get( 'port')) if not port: raise exception.PortNotFound(port_id=port_id) if port.get('device_id', None): raise exception.PortInUse(port_id=port_id) net_id = port['network_id'] if net_id in net_ids: raise exception.NetworkDuplicated(network_id=net_id) net_ids.append(net_id) nets = self._get_available_networks(context, context.project_id, net_ids) if len(nets) != len(net_ids): requsted_netid_set = set(net_ids) returned_netid_set = set([net['id'] for net in nets]) lostid_set = requsted_netid_set - returned_netid_set id_str = '' for _id in lostid_set: id_str = id_str and id_str + ', ' + _id or _id raise exception.NetworkNotFound(network_id=id_str)
def remove_from_instance(self, context, instance, security_group_name): """Remove the security group associated with the instance.""" neutron = neutronv2.get_client(context) try: security_group_id = neutronv20.find_resourceid_by_name_or_id( neutron, 'security_group', security_group_name, context.project_id) except n_exc.NeutronClientException as e: exc_info = sys.exc_info() if e.status_code == 404: msg = (_("Security group %(name)s is not found for " "project %(project)s") % {'name': security_group_name, 'project': context.project_id}) self.raise_not_found(msg) else: LOG.exception(_("Neutron Error:")) raise exc_info[0], exc_info[1], exc_info[2] params = {'device_id': instance['uuid']} try: ports = neutron.list_ports(**params).get('ports') except n_exc.NeutronClientException: with excutils.save_and_reraise_exception(): LOG.exception(_("Neutron Error:")) if not ports: msg = (_("instance_id %s could not be found as device id on" " any ports") % instance['uuid']) self.raise_not_found(msg) found_security_group = False for port in ports: try: port.get('security_groups', []).remove(security_group_id) except ValueError: # When removing a security group from an instance the security # group should be on both ports since it was added this way if # done through the nova api. In case it is not a 404 is only # raised if the security group is not found on any of the # ports on the instance. continue updated_port = {'security_groups': port['security_groups']} try: LOG.info(_("Adding security group %(security_group_id)s to " "port %(port_id)s"), {'security_group_id': security_group_id, 'port_id': port['id']}) neutron.update_port(port['id'], {'port': updated_port}) found_security_group = True except Exception: with excutils.save_and_reraise_exception(): LOG.exception(_("Neutron Error:")) if not found_security_group: msg = (_("Security group %(security_group_name)s not associated " "with the instance %(instance)s") % {'security_group_name': security_group_name, 'instance': instance['uuid']}) self.raise_not_found(msg)
def _get_available_networks(self, context, project_id, net_ids=None): """Return a network list available for the tenant. The list contains networks owned by the tenant and public networks. If net_ids specified, it searches networks with requested IDs only. """ neutron = neutronv2.get_client(context) # If user has specified to attach instance only to specific # networks, add them to **search_opts # (1) Retrieve non-public network list owned by the tenant. search_opts = {"tenant_id": project_id, 'shared': False} if net_ids: search_opts['id'] = net_ids nets = neutron.list_networks(**search_opts).get('networks', []) # (2) Retrieve public network list. search_opts = {'shared': True} if net_ids: search_opts['id'] = net_ids nets += neutron.list_networks(**search_opts).get('networks', []) _ensure_requested_network_ordering( lambda x: x['id'], nets, net_ids) return nets
def add_rules(self, context, id, name, vals): """Add security group rule(s) to security group. Note: the Nova security group API doesn't support adding multiple security group rules at once but the EC2 one does. Therefore, this function is written to support both. Multiple rules are installed to a security group in neutron using bulk support. """ neutron = neutronv2.get_client(context) body = self._make_neutron_security_group_rules_list(vals) try: rules = neutron.create_security_group_rule( body).get('security_group_rules') except n_exc.NeutronClientException as e: exc_info = sys.exc_info() if e.status_code == 404: LOG.exception(_("Neutron Error getting security group %s"), name) self.raise_not_found(unicode(e)) elif e.status_code == 409: LOG.exception(_("Neutron Error adding rules to security " "group %s"), name) self.raise_over_quota(unicode(e)) else: LOG.exception(_("Neutron Error:")) raise exc_info[0], exc_info[1], exc_info[2] converted_rules = [] for rule in rules: converted_rules.append( self._convert_to_nova_security_group_rule_format(rule)) return converted_rules
def add_to_instance(self, context, instance, security_group_name): """Add security group to the instance.""" neutron = neutronv2.get_client(context) try: security_group_id = neutronv20.find_resourceid_by_name_or_id( neutron, 'security_group', security_group_name, context.project_id) except n_exc.NeutronClientNoUniqueMatch as e: raise exception.NoUniqueMatch(six.text_type(e)) except n_exc.NeutronClientException as e: exc_info = sys.exc_info() if e.status_code == 404: msg = (_("Security group %(name)s is not found for " "project %(project)s") % { 'name': security_group_name, 'project': context.project_id }) self.raise_not_found(msg) else: LOG.exception(_("Neutron Error:")) raise exc_info[0], exc_info[1], exc_info[2] params = {'device_id': instance['uuid']} try: ports = neutron.list_ports(**params).get('ports') except n_exc.NeutronClientException: with excutils.save_and_reraise_exception(): LOG.exception(_("Neutron Error:")) if not ports: msg = (_("instance_id %s could not be found as device id on" " any ports") % instance['uuid']) self.raise_not_found(msg) for port in ports: if not self._has_security_group_requirements(port): LOG.warn( _("Cannot add security group %(name)s to %(instance)s" " since the port %(port_id)s does not meet security" " requirements"), { 'name': security_group_name, 'instance': instance['uuid'], 'port_id': port['id'] }) raise exception.SecurityGroupCannotBeApplied() if 'security_groups' not in port: port['security_groups'] = [] port['security_groups'].append(security_group_id) updated_port = {'security_groups': port['security_groups']} try: LOG.info( _("Adding security group %(security_group_id)s to " "port %(port_id)s"), { 'security_group_id': security_group_id, 'port_id': port['id'] }) neutron.update_port(port['id'], {'port': updated_port}) except Exception: with excutils.save_and_reraise_exception(): LOG.exception(_("Neutron Error:"))
def get_floating_ip_by_address(self, context, address): """Return a floating ip given an address.""" client = neutronv2.get_client(context) fip = self._get_floating_ip_by_address(client, address) pool_dict = self._setup_net_dict(client, fip['floating_network_id']) port_dict = self._setup_port_dict(client, fip['port_id']) return self._format_floating_ip_model(fip, pool_dict, port_dict)
def list(self, context, names=None, ids=None, project=None, search_opts=None): """Returns list of security group rules owned by tenant.""" neutron = neutronv2.get_client(context) search_opts = {} if names: search_opts['name'] = names if ids: search_opts['id'] = ids if project: search_opts['tenant_id'] = project try: security_groups = neutron.list_security_groups( **search_opts).get('security_groups') except n_exc.NeutronClientException: with excutils.save_and_reraise_exception(): LOG.exception(_("Neutron Error getting security groups")) converted_rules = [] for security_group in security_groups: converted_rules.append( self._convert_to_nova_security_group_format(security_group)) return converted_rules
def _get_available_networks(self, context, project_id, net_ids=None): """Return a network list available for the tenant. The list contains networks owned by the tenant and public networks. If net_ids specified, it searches networks with requested IDs only. """ neutron = neutronv2.get_client(context) if context.is_admin: # To allow admin to connect port from one tenant to instance in # another tenant, this function should return networks without # filtering over tenant_id. search_opts = {} if net_ids: search_opts['id'] = net_ids nets = neutron.list_networks(**search_opts).get('networks', []) else: # If user has specified to attach instance only to specific # networks, add them to **search_opts # (1) Retrieve non-public network list owned by the tenant. search_opts = {"tenant_id": project_id, 'shared': False} if net_ids: search_opts['id'] = net_ids nets = neutron.list_networks(**search_opts).get('networks', []) # (2) Retrieve public network list. search_opts = {'shared': True} if net_ids: search_opts['id'] = net_ids nets += neutron.list_networks(**search_opts).get('networks', []) _ensure_requested_network_ordering(lambda x: x['id'], nets, net_ids) return nets
def get_instances_security_groups_bindings(self, context): """Returns a dict(instance_id, [security_groups]) to allow obtaining all of the instances and their security groups in one shot. """ neutron = neutronv2.get_client(context) ports = neutron.list_ports().get('ports') security_groups = neutron.list_security_groups().get('security_groups') security_group_lookup = {} instances_security_group_bindings = {} for security_group in security_groups: security_group_lookup[security_group['id']] = security_group for port in ports: for port_security_group in port.get('security_groups', []): try: sg = security_group_lookup[port_security_group] # name is optional in neutron so if not specified return id if sg.get('name'): sg_entry = {'name': sg['name']} else: sg_entry = {'name': sg['id']} instances_security_group_bindings.setdefault( port['device_id'], []).append(sg_entry) except KeyError: # This should only happen due to a race condition # if the security group on a port was deleted after the # ports were returned. We pass since this security # group is no longer on the port. pass return instances_security_group_bindings
def deallocate_for_instance(self, context, instance, **kwargs): """Deallocate all network resources related to the instance.""" LOG.debug(_("deallocate_for_instance() for %s"), instance["display_name"]) search_opts = {"device_id": instance["uuid"]} data = neutronv2.get_client(context).list_ports(**search_opts) ports = [port["id"] for port in data.get("ports", [])] requested_networks = kwargs.get("requested_networks") or {} ports_to_skip = [port_id for nets, fips, port_id in requested_networks] ports = set(ports) - set(ports_to_skip) for port in ports: try: neutronv2.get_client(context).delete_port(port) except Exception: LOG.exception(_("Failed to delete neutron port %(portid)s") % {"portid": port})
def associate_floating_ip(self, context, instance, floating_address, fixed_address, affect_auto_assigned=False): """Associate a floating ip with a fixed ip.""" # Note(amotoki): 'affect_auto_assigned' is not respected # since it is not used anywhere in nova code and I could # find why this parameter exists. client = neutronv2.get_client(context) port_id = self._get_port_id_by_fixed_address(client, instance, fixed_address) fip = self._get_floating_ip_by_address(client, floating_address) param = {'port_id': port_id, 'fixed_ip_address': fixed_address} client.update_floatingip(fip['id'], {'floatingip': param}) if fip['port_id']: port = client.show_port(fip['port_id'])['port'] orig_instance_uuid = port['device_id'] msg_dict = dict(address=floating_address, instance_id=orig_instance_uuid) LOG.info(_('re-assign floating IP %(address)s from ' 'instance %(instance_id)s') % msg_dict) orig_instance = self.db.instance_get_by_uuid(context, orig_instance_uuid) # purge cached nw info for the original instance update_instance_info_cache(self, context, orig_instance)
def _get_available_networks(self, context, project_id, net_ids=None): """Return a network list available for the tenant. The list contains networks owned by the tenant and public networks. If net_ids specified, it searches networks with requested IDs only. """ neutron = neutronv2.get_client(context) if net_ids: # If user has specified to attach instance only to specific # networks then only add these to **search_opts. This search will # also include 'shared' networks. search_opts = {'id': net_ids} nets = neutron.list_networks(**search_opts).get('networks', []) else: # (1) Retrieve non-public network list owned by the tenant. search_opts = {'tenant_id': project_id, 'shared': False} nets = neutron.list_networks(**search_opts).get('networks', []) # (2) Retrieve public network list. search_opts = {'shared': True} nets += neutron.list_networks(**search_opts).get('networks', []) _ensure_requested_network_ordering( lambda x: x['id'], nets, net_ids) return nets
def add_rules(self, context, id, name, vals): """Add security group rule(s) to security group. Note: the Nova security group API doesn't support adding muliple security group rules at once but the EC2 one does. Therefore, this function is writen to support both. Multiple rules are installed to a security group in neutron using bulk support. """ neutron = neutronv2.get_client(context) body = self._make_neutron_security_group_rules_list(vals) try: rules = neutron.create_security_group_rule( body).get('security_group_rules') except n_exc.NeutronClientException as e: exc_info = sys.exc_info() if e.status_code == 409: LOG.exception(_("Neutron Error getting security group %s"), name) self.raise_not_found(e.message) else: LOG.exception(_("Neutron Error:")) raise exc_info[0], exc_info[1], exc_info[2] converted_rules = [] for rule in rules: converted_rules.append( self._convert_to_nova_security_group_rule_format(rule)) return converted_rules
def get_all(self, context): """Get all networks for client.""" client = neutronv2.get_client(context) networks = client.list_networks().get('networks') for network in networks: network['label'] = network['name'] return networks
def remove_from_instance(self, context, instance, security_group_name): """Remove the security group associated with the instance.""" neutron = neutronv2.get_client(context) try: security_group_id = neutronv20.find_resourceid_by_name_or_id( neutron, 'security_group', security_group_name) except n_exc.NeutronClientException as e: exc_info = sys.exc_info() if e.status_code == 404: msg = ("Security group %s is not found for project %s" % (security_group_name, context.project_id)) self.raise_not_found(msg) else: LOG.exception(_("Neutron Error:")) raise exc_info[0], exc_info[1], exc_info[2] params = {'device_id': instance['uuid']} try: ports = neutron.list_ports(**params).get('ports') except n_exc.NeutronClientException: with excutils.save_and_reraise_exception(): LOG.exception(_("Neutron Error:")) if not ports: msg = ("instance_id %s could not be found as device id on" " any ports" % instance['uuid']) self.raise_not_found(msg) found_security_group = False for port in ports: try: port.get('security_groups', []).remove(security_group_id) except ValueError: # When removing a security group from an instance the security # group should be on both ports since it was added this way if # done through the nova api. In case it is not a 404 is only # raised if the security group is not found on any of the # ports on the instance. continue updated_port = {'security_groups': port['security_groups']} try: LOG.info( _("Adding security group %(security_group_id)s to " "port %(port_id)s"), { 'security_group_id': security_group_id, 'port_id': port['id'] }) neutron.update_port(port['id'], {'port': updated_port}) found_security_group = True except Exception: with excutils.save_and_reraise_exception(): LOG.exception(_("Neutron Error:")) if not found_security_group: msg = (_("Security group %(security_group_name)s not assocaited " "with the instance %(instance)s"), { 'security_group_name': security_group_name, 'instance': instance['uuid'] }) self.raise_not_found(msg)
def get_instance_id_by_floating_address(self, context, address): """Return the instance id a floating ip's fixed ip is allocated to.""" client = neutronv2.get_client(context) fip = self._get_floating_ip_by_address(client, address) if not fip['port_id']: return None port = client.show_port(fip['port_id'])['port'] return port['device_id']
def get_floating_ips_by_project(self, context): client = neutronv2.get_client(context) project_id = context.project_id fips = client.list_floatingips(tenant_id=project_id)['floatingips'] pool_dict = self._setup_pools_dict(client) port_dict = self._setup_ports_dict(client, project_id) return [self._format_floating_ip_model(fip, pool_dict, port_dict) for fip in fips]
def migrate_instance_finish(self, context, instance, migration, rt=None): """Finish migrating the network of an instance.""" if not self._has_port_binding_extension(context, refresh_cache=True): return neutron = neutronv2.get_client(context, admin=True) search_opts = { 'device_id': instance['uuid'], 'tenant_id': instance['project_id'] } data = neutron.list_ports(**search_opts) ports = data['ports'] vif_profiles = {} allocated_pci_devs = [] if rt: network_info = instance['info_cache'].get('network_info') task_state = instance['task_state'] if isinstance( instance, dict) else instance.task_state if task_state == task_states.RESIZE_REVERTING: inst_pcis = rt.pci_tracker.allocations[instance['uuid']] else: inst_pcis = rt.pci_tracker.claims[instance['uuid']] for claimed_dev, port in itertools.product(inst_pcis, ports): pool = rt.pci_tracker.pci_stats._create_pool_keys_from_dev( claimed_dev) if not pool or 'physical_network' not in pool: LOG.warning( _("Cannot get pool for dev: %s or device " "haven't physical_network"), claimed_dev) continue if (pool['physical_network'] == port['binding:profile'].get('physical_network') and claimed_dev.address not in allocated_pci_devs and port['id'] not in vif_profiles): port['binding:profile']['pci_slot'] = claimed_dev.address allocated_pci_devs.append(claimed_dev.address) port['binding:profile']['pci_vendor_info'] = ':'.join( (pool['vendor_id'], pool['product_id'])) vif_profiles[port['id']] = port['binding:profile'] for vif in network_info: if vif['id'] in vif_profiles: vif['profile'] = vif_profiles[vif['id']] for p in ports: port_req_body = { 'port': { 'binding:host_id': migration['dest_compute'] } } if vif_profiles and p['id'] in vif_profiles: port_req_body['port'].update( {'binding:profile': vif_profiles[p['id']]}) try: neutron.update_port(p['id'], port_req_body) except Exception: with excutils.save_and_reraise_exception(): msg = _LE("Unable to update host of port %s") LOG.exception(msg, p['id'])
def deallocate_for_instance(self, context, instance, **kwargs): """Deallocate all network resources related to the instance.""" LOG.debug(_('deallocate_for_instance() for %s'), instance['display_name']) search_opts = {'device_id': instance['uuid']} data = neutronv2.get_client(context).list_ports(**search_opts) ports = [port['id'] for port in data.get('ports', [])] requested_networks = kwargs.get('requested_networks') or {} ports_to_skip = [port_id for nets, fips, port_id in requested_networks] ports = set(ports) - set(ports_to_skip) for port in ports: try: neutronv2.get_client(context).delete_port(port) except Exception: LOG.exception(_("Failed to delete neutron port %(portid)s") % {'portid': port})
def allocate(self, context, instance_id, tenant_id, zone, **kwargs): neutron = neutronv2.get_client(context, admin=True) dhcp_opts = kwargs.get('dhcp_options', None) net_ids = [kwargs.get('network_id')] nets = self._get_available_networks(context, tenant_id, net_ids) if not nets: LOG.warn(_LW("No network configured!")) return network_model.NetworkInfo([]) security_groups = kwargs.get('security_groups', []) security_group_ids = [] if len(security_groups): search_opts = {'tenant_id': tenant_id} user_security_groups = neutron.list_security_groups( **search_opts).get('security_groups') for security_group in security_groups: name_match = None uuid_match = None for user_security_group in user_security_groups: if user_security_group['name'] == security_group: if name_match: raise exception.NoUniqueMatch( _("Multiple security groups found matching" " '%s'. Use an ID to be more specific.") % security_group) name_match = user_security_group['id'] if user_security_group['id'] == security_group: uuid_match = user_security_group['id'] # If a user names the security group the same as # another's security groups uuid, the name takes priority. if not name_match and not uuid_match: raise exception.SecurityGroupNotFound( security_group_id=security_group) elif name_match: security_group_ids.append(name_match) elif uuid_match: security_group_ids.append(uuid_match) for net in nets: if net['id'] == kwargs.get('network_id'): network = net break if (security_groups and not ( network['subnets'] and network.get('port_security_enabled', True))): raise exception.SecurityGroupCannotBeApplied() port_req_body = {'port': {'device_id': instance_id, 'device_owner': zone, 'binding:host_id': 'qjnode2.test.ibm.com'}} created_port = self._create_port( neutron, tenant_id, network['id'], port_req_body, None, security_group_ids, dhcp_opts) nw_info = self._build_network_info_model(context, instance_id, tenant_id, networks=[net], port_ids=[created_port]) return network_model.NetworkInfo([vif for vif in nw_info])
def _get_instance_uuids_by_ip(self, context, address): """Retrieve instance uuids associated with the given ip address. :returns: A list of dicts containing the uuids keyed by 'instance_uuid' e.g. [{'instance_uuid': uuid}, ...] """ search_opts = {"fixed_ips": 'ip_address=%s' % address} data = neutronv2.get_client(context).list_ports(**search_opts) ports = data.get('ports', []) return [{'instance_uuid': port['device_id']} for port in ports if port['device_id']]
def get_floating_ip(self, context, id): """Return floating ip object given the floating ip id.""" client = neutronv2.get_client(context) try: fip = client.show_floatingip(id)['floatingip'] except neutronv2.exceptions.NeutronClientException as e: if e.status_code == 404: raise exception.FloatingIpNotFound(id=id) pool_dict = self._setup_net_dict(client, fip['floating_network_id']) port_dict = self._setup_port_dict(client, fip['port_id']) return self._format_floating_ip_model(fip, pool_dict, port_dict)
def disassociate_floating_ip(self, context, instance, address, affect_auto_assigned=False): """Disassociate a floating ip from the instance.""" # Note(amotoki): 'affect_auto_assigned' is not respected # since it is not used anywhere in nova code and I could # find why this parameter exists. client = neutronv2.get_client(context) fip = self._get_floating_ip_by_address(client, address) client.update_floatingip(fip['id'], {'floatingip': {'port_id': None}})
def _refresh_neutron_extensions_cache(self): """Refresh the neutron extensions cache when necessary.""" if (not self.last_neutron_extension_sync or ((time.time() - self.last_neutron_extension_sync) >= CONF.neutron_extension_sync_interval)): neutron = neutronv2.get_client(context.get_admin_context()) extensions_list = neutron.list_extensions()['extensions'] self.last_neutron_extension_sync = time.time() self.extensions.clear() self.extensions = dict((ext['name'], ext) for ext in extensions_list)