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 not port_id: net_ids.append(net_id) continue port = quantumv2.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: nets = self._get_available_networks(context, context.project_id) if len(nets) > 1: # Attaching to more than one network by default doesn't # make sense, as the order will be arbitrary and the guest OS # won't know which to configure msg = _("Multiple possible networks found, use a Network " "ID to be more specific.") raise exception.NetworkAmbiguous(msg) return net_ids = [] for (net_id, _i, port_id) in requested_networks: if port_id: try: port = (neutronv2.get_client(context) .show_port(port_id) .get('port')) except neutronv2.exceptions.NeutronClientException as e: if e.status_code == 404: port = None 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) # Now check to see if all requested networks exist 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, num_instances): """Validate that the tenant can use the requested networks. Return the number of instances than can be successfully allocated with the requested network configuration. """ LOG.debug(_('validate_networks() for %s'), requested_networks) neutron = neutronv2.get_client(context) ports_needed_per_instance = 0 if not requested_networks: nets = self._get_available_networks(context, context.project_id, neutron=neutron) if len(nets) > 1: # Attaching to more than one network by default doesn't # make sense, as the order will be arbitrary and the guest OS # won't know which to configure msg = _("Multiple possible networks found, use a Network " "ID to be more specific.") raise exception.NetworkAmbiguous(msg) else: ports_needed_per_instance = 1 else: net_ids = [] for (net_id, _i, port_id) in requested_networks: if port_id: try: port = neutron.show_port(port_id).get('port') except neutronv2.exceptions.NeutronClientException as e: if e.status_code == 404: port = None else: with excutils.save_and_reraise_exception(): LOG.exception(_("Failed to access port %s"), port_id) if not port: raise exception.PortNotFound(port_id=port_id) if port.get('device_id', None): raise exception.PortInUse(port_id=port_id) if not port.get('fixed_ips'): raise exception.PortRequiresFixedIP(port_id=port_id) net_id = port['network_id'] else: ports_needed_per_instance += 1 if net_id in net_ids: raise exception.NetworkDuplicated(network_id=net_id) net_ids.append(net_id) # Now check to see if all requested networks exist nets = self._get_available_networks(context, context.project_id, net_ids, neutron=neutron) for net in nets: if not net.get('subnets'): raise exception.NetworkRequiresSubnet( network_uuid=net['id']) 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) # Note(PhilD): Ideally Nova would create all required ports as part of # network validation, but port creation requires some details # from the hypervisor. So we just check the quota and return # how many of the requested number of instances can be created ports = [] quotas = neutron.show_quota(tenant_id=context.project_id)['quota'] if quotas.get('port', -1) == -1: # Unlimited Port Quota return num_instances else: free_ports = quotas.get('port') - len(ports) ports_needed = ports_needed_per_instance * num_instances if free_ports >= ports_needed: return num_instances else: return free_ports // ports_needed_per_instance
def create(self, req, server_id, body): """Attach an interface to an instance.""" context = req.environ['nova.context'] authorize(context) network_id = None port_id = None req_ip = None if body: attachment = body['interfaceAttachment'] network_id = attachment.get('net_id', None) port_id = attachment.get('port_id', None) try: req_ip = attachment['fixed_ips'][0]['ip_address'] except Exception: pass if network_id and port_id: msg = _("Must not input both network_id and port_id") raise exc.HTTPBadRequest(explanation=msg) if req_ip and not network_id: msg = _("Must input network_id when request IP address") raise exc.HTTPBadRequest(explanation=msg) #if the port has attached in this instance, raise port_info = {} if utils.is_neutron(): if port_id: try: port_info = self.network_api.show_port(context, port_id) except exception.NotFound as e: raise exc.HTTPNotFound(explanation=e.format_message()) if port_info['port']['device_id']: raise exception.PortInUse(port_id=port_id) #check network is duplicated or not when allow_duplicate_networks is false if utils.is_neutron(): if not cfg.CONF.neutron.allow_duplicate_networks: search_opts = {'device_id': server_id} try: data = self.network_api.list_ports(context, **search_opts) except exception.NotFound as e: raise exc.HTTPNotFound(explanation=e.format_message()) except NotImplementedError: msg = _("Network driver does not support this function.") raise webob.exc.HTTPNotImplemented(explanation=msg) ports = data.get('ports', []) instance_networks = [] for port in ports: instance_networks.append(port.get('network_id')) if port_id: network_id = port_info['port'].get('network_id') if network_id in instance_networks: raise exception.NetworkDuplicated(network_id=network_id) try: instance = common.get_instance(self.compute_api, context, server_id, want_objects=True) LOG.audit(_("Attach interface"), instance=instance) vif = self.compute_api.attach_interface(context, instance, network_id, port_id, req_ip) except (exception.PortNotFound, exception.FixedIpAlreadyInUse, exception.PortInUse, exception.NetworkDuplicated, exception.NetworkAmbiguous, exception.NetworkNotFound, exception.PortNotUsable) as e: raise exc.HTTPBadRequest(explanation=e.format_message()) except exception.InstanceIsLocked as e: raise exc.HTTPConflict(explanation=e.format_message()) except NotImplementedError: msg = _("Network driver does not support this function.") raise webob.exc.HTTPNotImplemented(explanation=msg) except exception.InterfaceAttachFailed as e: LOG.exception(e) msg = _("Failed to attach interface") raise webob.exc.HTTPInternalServerError(explanation=msg) except exception.InstanceInvalidState as state_error: common.raise_http_conflict_for_instance_invalid_state(state_error, 'attach_interface') return self.show(req, server_id, vif['id'])