def test_list_ports_with_resource_request_admin_client(self): ctxt = context.get_admin_context() client = neutron_api.get_client(ctxt) ports = client.list_ports(ctxt)['ports'] port_id = self.neutron.port_with_resource_request['id'] ports = [port for port in ports if port_id == port['id']] self.assertIsNotNone(ports[0]['resource_request'])
def get(context, name=None, id=None, map_exception=False): neutron = neutronapi.get_client(context) try: if not id and name: # NOTE(flwang): The project id should be honoured so as to get # the correct security group id when user(with admin role but # non-admin project) try to query by name, so as to avoid # getting more than duplicated records with the same name. id = neutronv20.find_resourceid_by_name_or_id( neutron, 'security_group', name, context.project_id) group = neutron.show_security_group(id).get('security_group') return _convert_to_nova_security_group_format(group) 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: LOG.debug("Neutron security group %s not found", name) raise exception.SecurityGroupNotFound(six.text_type(e)) else: LOG.error("Neutron Error: %s", e) six.reraise(*exc_info) except TypeError as e: LOG.error("Neutron Error: %s", e) msg = _("Invalid security group name: %(name)s.") % {"name": name} raise exception.SecurityGroupNotFound(six.text_type(msg))
def add_to_instance(context, instance, security_group_name): """Add security group to the instance.""" neutron = neutronapi.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: 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}) raise exception.SecurityGroupNotFound(msg) else: raise e 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) raise exception.SecurityGroupNotFound(msg) for port in ports: if not _has_security_group_requirements(port): LOG.warning("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 n_exc.NeutronClientException as e: if e.status_code == 400: raise exception.SecurityGroupCannotBeApplied( six.text_type(e)) else: raise e except Exception: with excutils.save_and_reraise_exception(): LOG.exception("Neutron Error:")
def list(context, names=None, ids=None, project=None, search_opts=None): """Returns list of security group rules owned by tenant.""" neutron = neutronapi.get_client(context) params = {} search_opts = search_opts if search_opts else {} if names: params['name'] = names if ids: params['id'] = ids # NOTE(jeffrey4l): list all the security groups when following # conditions are met # * names and ids don't exist. # * it is admin context and all_tenants exist in search_opts. # * project is not specified. list_all_tenants = (context.is_admin and 'all_tenants' in search_opts and not any([names, ids])) # NOTE(jeffrey4l): The neutron doesn't have `all-tenants` concept. # All the security group will be returned if the project/tenant # id is not passed. if project and not list_all_tenants: params['tenant_id'] = project try: security_groups = neutron.list_security_groups( **params).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( _convert_to_nova_security_group_format(security_group)) return converted_rules
def add_rules(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 = neutronapi.get_client(context) body = _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) raise exception.SecurityGroupNotFound(six.text_type(e)) elif e.status_code == 409: LOG.exception("Neutron Error adding rules to security " "group %s", name) raise exception.SecurityGroupLimitExceeded(six.text_type(e)) elif e.status_code == 400: LOG.exception("Neutron Error: %s", e) raise exception.Invalid(six.text_type(e)) else: six.reraise(*exc_info) converted_rules = [] for rule in rules: converted_rules.append( _convert_to_nova_security_group_rule_format(rule)) return converted_rules
def remove_from_instance(context, instance, security_group_name): """Remove the security group associated with the instance.""" neutron = neutronapi.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: 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 }) raise exception.SecurityGroupNotFound(msg) else: raise e 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) raise exception.SecurityGroupNotFound(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( "Removing security group %(security_group_id)s from " "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 }) raise exception.SecurityGroupNotFound(msg)
def _get_instance_id_from_lb(self, provider_id, instance_address): # We use admin context, admin=True to lookup the # inter-Edge network port context = nova_context.get_admin_context() neutron = neutronapi.get_client(context, admin=True) # Tenant, instance ids are found in the following method: # X-Metadata-Provider contains id of the metadata provider, and since # overlapping networks cannot be connected to the same metadata # provider, the combo of tenant's instance IP and the metadata # provider has to be unique. # # The networks which are connected to the metadata provider are # retrieved in the 1st call to neutron.list_subnets() # In the 2nd call we read the ports which belong to any of the # networks retrieved above, and have the X-Forwarded-For IP address. # This combination has to be unique as explained above, and we can # read the instance_id, tenant_id from that port entry. # Retrieve networks which are connected to metadata provider md_subnets = neutron.list_subnets( context, advanced_service_providers=[provider_id], fields=['network_id']) md_networks = [subnet['network_id'] for subnet in md_subnets['subnets']] try: # Retrieve the instance data from the instance's port instance_data = neutron.list_ports( context, fixed_ips='ip_address=' + instance_address, network_id=md_networks, fields=['device_id', 'tenant_id'])['ports'][0] except Exception as e: LOG.error('Failed to get instance id for metadata ' 'request, provider %(provider)s ' 'networks %(networks)s ' 'requester %(requester)s. Error: %(error)s', {'provider': provider_id, 'networks': md_networks, 'requester': instance_address, 'error': e}) msg = _('An unknown error has occurred. ' 'Please try your request again.') raise webob.exc.HTTPBadRequest(explanation=msg) instance_id = instance_data['device_id'] tenant_id = instance_data['tenant_id'] # instance_data is unicode-encoded, while cache_utils doesn't like # that. Therefore we convert to str if isinstance(instance_id, six.text_type): instance_id = instance_id.encode('utf-8') return instance_id, tenant_id
def get(context, id): neutron = neutronapi.get_client(context) try: group = neutron.show_security_group(id).get('security_group') return _convert_to_nova_security_group_format(group) except n_exc.NeutronClientException as e: if e.status_code == 404: LOG.debug('Neutron security group %s not found', id) raise exception.SecurityGroupNotFound(six.text_type(e)) else: LOG.error("Neutron Error: %s", e) raise e
def get_rule(context, id): neutron = neutronapi.get_client(context) try: rule = neutron.show_security_group_rule(id).get('security_group_rule') except n_exc.NeutronClientException as e: if e.status_code == 404: LOG.debug("Neutron security group rule %s not found", id) raise exception.SecurityGroupNotFound(str(e)) else: LOG.error("Neutron Error: %s", e) raise e return _convert_to_nova_security_group_rule_format(rule)
def remove_rules(context, security_group, rule_ids): neutron = neutronapi.get_client(context) rule_ids = set(rule_ids) try: # The ec2 api allows one to delete multiple security group rules # at once. Since there is no bulk delete for neutron the best # thing we can do is delete the rules one by one and hope this # works.... :/ for rule_id in range(0, len(rule_ids)): neutron.delete_security_group_rule(rule_ids.pop()) except n_exc.NeutronClientException: with excutils.save_and_reraise_exception(): LOG.exception("Neutron Error unable to delete %s", rule_ids)
def get_rule(self, context, id): neutron = neutronapi.get_client(context) try: rule = neutron.show_security_group_rule(id).get( 'security_group_rule') except n_exc.NeutronClientException as e: exc_info = sys.exc_info() if e.status_code == 404: LOG.debug("Neutron security group rule %s not found", id) self.raise_not_found(six.text_type(e)) else: LOG.error("Neutron Error: %s", e) six.reraise(*exc_info) return self._convert_to_nova_security_group_rule_format(rule)
def destroy(context, security_group): """This function deletes a security group.""" neutron = neutronapi.get_client(context) try: neutron.delete_security_group(security_group['id']) except n_exc.NeutronClientException as e: if e.status_code == 404: raise exception.SecurityGroupNotFound(str(e)) elif e.status_code == 409: raise exception.Invalid(str(e)) else: LOG.error("Neutron Error: %s", e) raise e
def update_security_group(context, security_group, name, description): neutron = neutronapi.get_client(context) body = _make_neutron_security_group_dict(name, description) try: security_group = neutron.update_security_group( security_group['id'], body).get('security_group') except n_exc.NeutronClientException as e: LOG.exception("Neutron Error updating security group %s", name) if e.status_code == 401: # TODO(arosen) Cannot raise generic response from neutron here # as this error code could be related to bad input or over # quota raise exc.HTTPBadRequest() raise e return _convert_to_nova_security_group_format(security_group)
def destroy(self, context, security_group): """This function deletes a security group.""" neutron = neutronapi.get_client(context) try: neutron.delete_security_group(security_group['id']) except n_exc.NeutronClientException as e: exc_info = sys.exc_info() if e.status_code == 404: self.raise_not_found(six.text_type(e)) elif e.status_code == 409: self.raise_invalid_property(six.text_type(e)) else: LOG.error("Neutron Error: %s", e) six.reraise(*exc_info)
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. If detailed is False only the security group name is returned. """ neutron = neutronapi.get_client(context) ports = self._get_ports_from_server_list(servers, neutron) # If detailed is True, we want all fields from the security groups # including the potentially slow-to-join security_group_rules field. # But if detailed is False, only get the id and name fields since # that's all we'll use below. fields = None if detailed else ['id', 'name'] security_groups = self._get_secgroups_from_port_list(ports, neutron, fields=fields) 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 create_security_group(context, name, description): neutron = neutronapi.get_client(context) body = _make_neutron_security_group_dict(name, description) try: security_group = neutron.create_security_group( body).get('security_group') except n_exc.BadRequest as e: raise exception.Invalid(six.text_type(e)) except n_exc.NeutronClientException as e: LOG.exception("Neutron Error creating security group %s", name) if e.status_code == 401: # TODO(arosen) Cannot raise generic response from neutron here # as this error code could be related to bad input or over # quota raise exc.HTTPBadRequest() elif e.status_code == 409: raise exception.SecurityGroupLimitExceeded(six.text_type(e)) raise e return _convert_to_nova_security_group_format(security_group)
def validate_name(context: nova_context.RequestContext, name: str): """Validate a security group name and return the corresponding UUID. :param context: The nova request context. :param name: The name of the security group. :raises NoUniqueMatch: If there is no unique match for the provided name. :raises SecurityGroupNotFound: If there's no match for the provided name. :raises NeutronClientException: For all other exceptions. """ neutron = neutronapi.get_client(context) try: return neutronv20.find_resourceid_by_name_or_id( neutron, 'security_group', name, context.project_id) except n_exc.NeutronClientNoUniqueMatch as e: raise exception.NoUniqueMatch(str(e)) except n_exc.NeutronClientException as e: if e.status_code == 404: LOG.debug('Neutron security group %s not found', name) raise exception.SecurityGroupNotFound(str(e)) else: LOG.error('Neutron Error: %s', e) raise e