def _get_requested_networks(self, requested_networks): """Create a list of requested networks from the networks attribute.""" networks = [] network_uuids = [] for network in requested_networks: request = objects.NetworkRequest() try: try: request.port_id = network.get('port', None) except ValueError: msg = _("Bad port format: port uuid is " "not in proper format " "(%s)") % network.get('port') raise exc.HTTPBadRequest(explanation=msg) if request.port_id: request.network_id = None if not utils.is_neutron(): # port parameter is only for neutron v2.0 msg = _("Unknown argument : port") raise exc.HTTPBadRequest(explanation=msg) else: request.network_id = network['uuid'] if (not request.port_id and not uuidutils.is_uuid_like(request.network_id)): br_uuid = request.network_id.split('-', 1)[-1] if not uuidutils.is_uuid_like(br_uuid): msg = _("Bad networks format: network uuid is " "not in proper format " "(%s)") % request.network_id raise exc.HTTPBadRequest(explanation=msg) # fixed IP address is optional # if the fixed IP address is not provided then # it will use one of the available IP address from the network try: request.address = network.get('fixed_ip', None) except ValueError: msg = (_("Invalid fixed IP address (%s)") % network.get('fixed_ip')) raise exc.HTTPBadRequest(explanation=msg) # duplicate networks are allowed only for neutron v2.0 if (not utils.is_neutron() and request.network_id and request.network_id in network_uuids): expl = (_("Duplicate networks" " (%s) are not allowed") % request.network_id) raise exc.HTTPBadRequest(explanation=expl) network_uuids.append(request.network_id) networks.append(request) except KeyError as key: expl = _('Bad network format: missing %s') % key raise exc.HTTPBadRequest(explanation=expl) except TypeError: expl = _('Bad networks format') raise exc.HTTPBadRequest(explanation=expl) return objects.NetworkRequestList(objects=networks)
def _get_requested_networks(self, requested_networks): """Create a list of requested networks from the networks attribute.""" networks = [] network_uuids = [] for network in requested_networks: request = objects.NetworkRequest() try: # fixed IP address is optional # if the fixed IP address is not provided then # it will use one of the available IP address from the network request.address = network.get("fixed_ip", None) request.port_id = network.get("port", None) if request.port_id: request.network_id = None if not utils.is_neutron(): # port parameter is only for neutron v2.0 msg = _("Unknown argument: port") raise exc.HTTPBadRequest(explanation=msg) if request.address is not None: msg = _( "Specified Fixed IP '%(addr)s' cannot be used " "with port '%(port)s': port already has " "a Fixed IP allocated." ) % {"addr": request.address, "port": request.port_id} raise exc.HTTPBadRequest(explanation=msg) else: request.network_id = network["uuid"] if not request.port_id and not uuidutils.is_uuid_like(request.network_id): br_uuid = request.network_id.split("-", 1)[-1] if not uuidutils.is_uuid_like(br_uuid): msg = ( _("Bad networks format: network uuid is " "not in proper format " "(%s)") % request.network_id ) raise exc.HTTPBadRequest(explanation=msg) # duplicate networks are allowed only for neutron v2.0 if not utils.is_neutron() and request.network_id and request.network_id in network_uuids: expl = _("Duplicate networks" " (%s) are not allowed") % request.network_id raise exc.HTTPBadRequest(explanation=expl) network_uuids.append(request.network_id) networks.append(request) except KeyError as key: expl = _("Bad network format: missing %s") % key raise exc.HTTPBadRequest(explanation=expl) except TypeError: expl = _("Bad networks format") raise exc.HTTPBadRequest(explanation=expl) return objects.NetworkRequestList(objects=networks)
def build_and_run_instance(self, ctxt, instance, host, image, request_spec, filter_properties, admin_password=None, injected_files=None, requested_networks=None, security_groups=None, block_device_mapping=None, node=None, limits=None): version = '3.33' if not self.client.can_send_version(version): version = '3.23' if requested_networks is not None: if utils.is_neutron(): requested_networks = [(network_id, address, port_id) for (network_id, address, port_id, _) in requested_networks.as_tuples()] else: requested_networks = [(network_id, address) for (network_id, address) in requested_networks.as_tuples()] cctxt = self.client.prepare(server=host, version=version) cctxt.cast(ctxt, 'build_and_run_instance', instance=instance, image=image, request_spec=request_spec, filter_properties=filter_properties, admin_password=admin_password, injected_files=injected_files, requested_networks=requested_networks, security_groups=security_groups, block_device_mapping=block_device_mapping, node=node, limits=limits)
def _validate_network_id(net_id, network_uuids): """Validates that a requested network id. This method performs two checks: 1. That the network id is in the proper uuid format. 2. That the network is not a duplicate when using nova-network. :param net_id: The network id to validate. :param network_uuids: A running list of requested network IDs that have passed validation already. :raises: webob.exc.HTTPBadRequest if validation fails """ if not uuidutils.is_uuid_like(net_id): # NOTE(mriedem): Neutron would allow a network id with a br- prefix # back in Folsom so continue to honor that. # TODO(mriedem): Need to figure out if this is still a valid case. br_uuid = net_id.split('-', 1)[-1] if not uuidutils.is_uuid_like(br_uuid): msg = _("Bad networks format: network uuid is " "not in proper format (%s)") % net_id raise exc.HTTPBadRequest(explanation=msg) # duplicate networks are allowed only for neutron v2.0 if net_id in network_uuids and not utils.is_neutron(): expl = _("Duplicate networks (%s) are not allowed") % net_id raise exc.HTTPBadRequest(explanation=expl)
def _start_container(self, instance, network_info): timeout = CONF.vif_plugging_timeout # check to see if neutron is ready before # doing anything else if (not self.client.container_running(instance.uuid) and utils.is_neutron() and timeout): events = self._get_neutron_events(network_info) else: events = {} try: with self.virtapi.wait_for_instance_event( instance, events, deadline=timeout, error_callback=self._neutron_failed_callback): self._start_network(instance, network_info) except exception.VirtualInterfaceCreateException: LOG.info(_LW('Failed')) try: (status, resp) = self.client.container_start(instance.uuid) if resp.get('status') != 'OK': raise exception.NovaException except Exception as e: LOG.debug(_('Failed to container instance: %s') % resp.get('metadata')) msg = _('Cannot container container: {0}') raise exception.NovaException(msg.format(e), instance_id=instance.name)
def validate_network_plugin(f, *args, **kwargs): """Decorator to validate the network plugin.""" if utils.is_neutron(): print(_("ERROR: Network commands are not supported when using the " "Neutron API. Use python-neutronclient instead.")) return(2) return f(*args, **kwargs)
def build_virtual_machine(self, instance, instance_name, image_info, dc_info, datastore, network_info, pg_vlan_instance_map): node_mo_id = vm_util.get_mo_id_from_instance(instance) res_pool_ref = vm_util.get_res_pool_ref(self._session, self._cluster, node_mo_id) vif_infos = vmwarevif.get_vif_info(self._session, self._cluster, utils.is_neutron(), image_info.vif_model, network_info, pg_vlan_instance_map) allocations = self._get_cpu_allocations(instance.instance_type_id) # Get the create vm config spec client_factory = self._session._get_vim().client.factory config_spec = vm_util.get_vm_create_spec(client_factory, instance, instance_name, datastore.name, vif_infos, image_info.os_type, allocations=allocations) # Create the VM vm_ref = vm_util.create_vm(self._session, instance, dc_info.vmFolder, config_spec, res_pool_ref) return vm_ref
def start_container(self, container_config, instance, network_info, need_vif_plugged): LOG.debug('Starting instance') if self.container_client.client('running', instance=instance.name, host=instance.host): return timeout = CONF.vif_plugging_timeout # check to see if neutron is ready before # doing anything else if (self.container_client.client('defined', instance=instance.name, host=instance.host) and need_vif_plugged and utils.is_neutron() and timeout): events = self._get_neutron_events(network_info) else: events = [] try: with self.virtapi.wait_for_instance_event( instance, events, deadline=timeout, error_callback=self._neutron_failed_callback): self.plug_vifs( container_config, instance, network_info, need_vif_plugged) except exception.VirtualInterfaceCreateException: LOG.info(_LW('Failed to connect networking to instance')) self.container_utils.container_start(instance.name, instance)
def _start_container(self, container_id, instance, network_info=None): self.docker.start(container_id) if not network_info: return timeout = CONF.vif_plugging_timeout if (utils.is_neutron() and timeout): events = self._get_neutron_events(network_info) else: events = [] try: with self.virtapi.wait_for_instance_event( instance, events, deadline=timeout, error_callback=self._neutron_failed_callback): self.plug_vifs(instance, network_info) self._attach_vifs(instance, network_info) except eventlet.timeout.Timeout: LOG.warning(('Timeout waiting for vif plugging callback for ' 'instance %(uuid)s'), {'uuid': instance['name']}) if CONF.vif_plugging_is_fatal: self.docker.kill(container_id) self.docker.remove_container(container_id, force=True) raise exception.InstanceDeployFailure( 'Timeout waiting for vif plugging', instance_id=instance['name']) except (Exception) as e: LOG.warning('Cannot setup network: %s', e, instance=instance, exc_info=True) msg = _('Cannot setup network: {0}') self.docker.kill(container_id) self.docker.remove_container(container_id, force=True) raise exception.InstanceDeployFailure(msg.format(e), instance_id=instance['name'])
def start_instance(self, container_config, instance, network_info, rescue=False, host=None): LOG.debug('Staring instance') name = instance.uuid if rescue: name = '%s-rescue' % instance.uuid timeout = CONF.vif_plugging_timeout # check to see if neutron is ready before # doing anything else if (not self.container_client.client('running', instance=name, host=host) and utils.is_neutron() and timeout): events = self._get_neutron_events(network_info) else: events = [] try: with self.virtapi.wait_for_instance_event( instance, events, deadline=timeout, error_callback=self._neutron_failed_callback): self.plug_vifs(container_config, instance, network_info) except exception.VirtualInterfaceCreateException: LOG.info(_LW('Failed to connect networking to instance')) (state, data) = self.container_client.client('start', instance=name, host=host) self.container_client.client('wait', oid=data.get('operation').split('/')[3], host=host)
def __init__(self, *args, **kwargs): super(MetadataManager, self).__init__(*args, **kwargs) if not utils.is_neutron(): # NOTE(mikal): we only add iptables rules if we're running # under nova-network. This code should go away when the # deprecation of nova-network is complete. self.network_driver = driver.load_network_driver() self.network_driver.metadata_accept()
def _get_neutron_events(self, network_info): # NOTE(danms): We need to collect any VIFs that are currently # down that we expect a down->up event for. Anything that is # already up will not undergo that transition, and for # anything that might be stale (cache-wise) assume it's # already up so we don't block on it. if utils.is_neutron() and CONF.vif_plugging_timeout: return [('network-vif-plugged', vif['id']) for vif in network_info if vif.get('active') is False] else: return []
def build_and_run_instance(self, ctxt, instance, host, image, request_spec, filter_properties, admin_password=None, injected_files=None, requested_networks=None, security_groups=None, block_device_mapping=None, node=None, limits=None): version = '4.0' if not self.client.can_send_version(version): version = '3.40' if not self.client.can_send_version(version): version = '3.36' if 'numa_topology' in limits and limits['numa_topology']: topology_limits = limits['numa_topology'] if node is not None: cnode = objects.ComputeNode.get_by_host_and_nodename( ctxt, host, node) else: cnode = ( objects.ComputeNode. get_first_node_by_host_for_old_compat( ctxt, host)) host_topology = objects.NUMATopology.obj_from_db_obj( cnode.numa_topology) limits['numa_topology'] = jsonutils.dumps( topology_limits.to_dict_legacy(host_topology)) if not self.client.can_send_version(version): version = '3.33' if 'instance_type' in filter_properties: flavor = filter_properties['instance_type'] flavor_p = objects_base.obj_to_primitive(flavor) filter_properties = dict(filter_properties, instance_type=flavor_p) if not self.client.can_send_version(version): version = '3.23' if requested_networks is not None: if utils.is_neutron(): requested_networks = [(network_id, address, port_id) for (network_id, address, port_id, _) in requested_networks.as_tuples()] else: requested_networks = [(network_id, address) for (network_id, address) in requested_networks.as_tuples()] cctxt = self.client.prepare(server=host, version=version) cctxt.cast(ctxt, 'build_and_run_instance', instance=instance, image=image, request_spec=request_spec, filter_properties=filter_properties, admin_password=admin_password, injected_files=injected_files, requested_networks=requested_networks, security_groups=security_groups, block_device_mapping=block_device_mapping, node=node, limits=limits)
def _determine_requested_networks(self, server_dict): requested_networks = None if (self.ext_mgr.is_loaded('os-networks') or utils.is_neutron()): requested_networks = server_dict.get('networks') if requested_networks is not None: if not isinstance(requested_networks, list): expl = _('Bad networks format') raise exc.HTTPBadRequest(explanation=expl) requested_networks = self._get_requested_networks( requested_networks) return requested_networks
def host_passes(self, host_state, filter_properties): if not utils.is_neutron(): return True pci_requests = filter_properties.get('pci_requests') if not pci_requests: LOG.info("pci_requests is empty in filter_properties, " "BandwidthFilter passed") return True if isinstance(host_state, dict): pci_stats = host_state.get('pci_stats', '{}') host = host_state['hypervisor_hostname'] else: pci_stats = host_state.pci_stats host = host_state.host try: netInfo = {} for phy_net, bandwidth in self._get_total_bandwidths( pci_stats).iteritems(): netInfo[phy_net] = {'type':'passthrough', 'total_bandwidth':bandwidth, 'used_bandwidth':'0'} if len(netInfo) == 0: LOG.info("pci_stats is empty in host_state, " "BandwidthFilter passed") return True self.host_net = hw_host_networklist.HostNetworkList( jsonutils.dumps(netInfo), host) bandwidth_req = self._get_bandwidth_req(filter_properties) for phy_net, bandwidth in bandwidth_req.iteritems(): if phy_net not in netInfo: LOG.error("the host do not have plane with name %s. " "host:%s" % (phy_net, host)) return False remain_bandwidth = self.host_net.get_remain_bandwidth(phy_net) if int(remain_bandwidth) < int(bandwidth): LOG.error("Need bandwidth %s, the host has %s, host:%s" % (bandwidth, remain_bandwidth, host)) return False except Exception: LOG.exception("BandwidthFilter failed") return False return True
def _get_requested_networks(self, requested_networks, supports_device_tagging=False): """Create a list of requested networks from the networks attribute.""" networks = [] network_uuids = [] for network in requested_networks: request = objects.NetworkRequest() try: # fixed IP address is optional # if the fixed IP address is not provided then # it will use one of the available IP address from the network request.address = network.get('fixed_ip', None) request.port_id = network.get('port', None) request.tag = network.get('tag', None) if request.tag and not supports_device_tagging: msg = _('Network interface tags are not yet supported.') raise exc.HTTPBadRequest(explanation=msg) if request.port_id: request.network_id = None if not utils.is_neutron(): # port parameter is only for neutron v2.0 msg = _("Unknown argument: port") raise exc.HTTPBadRequest(explanation=msg) if request.address is not None: msg = _("Specified Fixed IP '%(addr)s' cannot be used " "with port '%(port)s': the two cannot be " "specified together.") % { "addr": request.address, "port": request.port_id} raise exc.HTTPBadRequest(explanation=msg) else: request.network_id = network['uuid'] self._validate_network_id( request.network_id, network_uuids) network_uuids.append(request.network_id) networks.append(request) except KeyError as key: expl = _('Bad network format: missing %s') % key raise exc.HTTPBadRequest(explanation=expl) except TypeError: expl = _('Bad networks format') raise exc.HTTPBadRequest(explanation=expl) return objects.NetworkRequestList(objects=networks)
def _get_vif_events(self): """Returns the VIF events that need to be received for a VIF plug. In order for a VIF plug to be successful, certain events should be received from other components within the OpenStack ecosystem. If using neutron, certain events are needed. If Nova networking, then no events are required. This method returns the events needed for a given deploy. """ # See libvirt's driver.py -> _get_neutron_events method for # more information. if (utils.is_neutron() and CONF.vif_plugging_is_fatal and CONF.vif_plugging_timeout): return [('network-vif-plugged', network_info['id']) for network_info in self.network_infos if not network_info.get('active', True)] else: return []
def wait_vif_plug_events(self, instance, network_info): timeout = CONF.vif_plugging_timeout if utils.is_neutron(): events = self._get_neutron_events(network_info) else: events = [] try: with self._virtapi.wait_for_instance_event( instance, events, deadline=timeout, error_callback=self._neutron_failed_callback): yield except etimeout.Timeout: # We never heard from Neutron LOG.warning(_LW('Timeout waiting for vif plugging callback for ' 'instance.'), instance=instance) if CONF.vif_plugging_is_fatal: raise exception.VirtualInterfaceCreateException()
def _check_pci_network(self): if not utils.is_neutron(): LOG.warn(_("Not implement neutron. Can't check sriov.")) return # now, evs, sriov and netmap instance don't support # live migrate unsupported_port_type = [model.VNIC_TYPE_VHOSTUSER, model.VNIC_TYPE_DIRECT, "softdirect"] unsupported_port_trunktype = ["trunk"] search_opt = {'device_id': self.instance['uuid'], 'tenant_id': self.instance['project_id']} ports = self.network_api.list_ports(self.context, **search_opt)['ports'] for p in ports: if p['binding:vnic_type'] in unsupported_port_type: raise exception.MigrationPreCheckError( reason="Instance with pci network dose not support " "live migration") if p.get('trunkport:type', None) in unsupported_port_trunktype: raise exception.MigrationPreCheckError( reason="Instance with network dose not support invalid trunkport " "while living migration")
def spawn(self, context, instance, image_meta, injected_files, admin_password, network_info=None, block_device_info=None): """Create a new lxd container as a nova instance. Creating a new container requires a number of steps. First, the image is fetched from glance, if needed. Next, the network is connected. A profile is created in LXD, and then the container is created and started. See `nova.virt.driver.ComputeDriver.spawn` for more information. """ try: self.client.containers.get(instance.name) raise exception.InstanceExists(name=instance.name) except lxd_exceptions.LXDAPIException as e: if e.response.status_code != 404: raise # Re-raise the exception if it wasn't NotFound instance_dir = common.InstanceAttributes(instance).instance_dir if not os.path.exists(instance_dir): fileutils.ensure_tree(instance_dir) # Check to see if LXD already has a copy of the image. If not, # fetch it. try: self.client.images.get_by_alias(instance.image_ref) except lxd_exceptions.LXDAPIException as e: if e.response.status_code != 404: raise _sync_glance_image_to_lxd(self.client, context, instance.image_ref) # Plug in the network if network_info: timeout = CONF.vif_plugging_timeout if (utils.is_neutron() and timeout): events = [('network-vif-plugged', vif['id']) for vif in network_info if not vif.get('active', True)] else: events = [] try: with self.virtapi.wait_for_instance_event( instance, events, deadline=timeout, error_callback=_neutron_failed_callback): self.plug_vifs(instance, network_info) except eventlet.timeout.Timeout: LOG.warn( 'Timeout waiting for vif plugging callback for ' 'instance %(uuid)s', {'uuid': instance['name']}) if CONF.vif_plugging_is_fatal: self.destroy(context, instance, network_info, block_device_info) raise exception.InstanceDeployFailure( 'Timeout waiting for vif plugging', instance_id=instance['name']) # Create the profile try: profile = flavor.to_profile(self.client, instance, network_info, block_device_info) except lxd_exceptions.LXDAPIException as e: with excutils.save_and_reraise_exception(): self.cleanup(context, instance, network_info, block_device_info) # Create the container container_config = { 'name': instance.name, 'profiles': [profile.name], 'source': { 'type': 'image', 'alias': instance.image_ref, }, } try: container = self.client.containers.create(container_config, wait=True) except lxd_exceptions.LXDAPIException as e: with excutils.save_and_reraise_exception(): self.cleanup(context, instance, network_info, block_device_info) lxd_config = self.client.host_info storage.attach_ephemeral(self.client, block_device_info, lxd_config, instance) if configdrive.required_by(instance): configdrive_path = self._add_configdrive(context, instance, injected_files, admin_password, network_info) profile = self.client.profiles.get(instance.name) config_drive = { 'configdrive': { 'path': '/config-drive', 'source': configdrive_path, 'type': 'disk', 'readonly': 'True', } } profile.devices.update(config_drive) profile.save() try: self.firewall_driver.setup_basic_filtering(instance, network_info) self.firewall_driver.instance_filter(instance, network_info) container.start(wait=True) self.firewall_driver.apply_instance_filter(instance, network_info) except lxd_exceptions.LXDAPIException as e: with excutils.save_and_reraise_exception(): self.cleanup(context, instance, network_info, block_device_info)
def _get_neutron_event(network_info): if utils.is_neutron() and CONF.vif_plugging_timeout: return [('network-vif-plugged', vif['id']) for vif in network_info if vif.get('active') is False] else: return []
def test_nova_network(self): self.assertFalse(utils.is_neutron())
def to_tuple(self): address = str(self.address) if self.address is not None else None if utils.is_neutron(): return self.network_id, address, self.port_id, self.pci_request_id else: return self.network_id, address
def create(self, req, body): """Creates a new server for a given user.""" if not self.is_valid_body(body, 'server'): raise exc.HTTPUnprocessableEntity() context = req.environ['nova.context'] server_dict = body['server'] password = self._get_server_admin_password(server_dict) if 'name' not in server_dict: msg = _("Server name is not defined") raise exc.HTTPBadRequest(explanation=msg) name = server_dict['name'] self._validate_server_name(name) name = name.strip() image_uuid = self._image_from_req_data(body) personality = server_dict.get('personality') config_drive = None if self.ext_mgr.is_loaded('os-config-drive'): config_drive = server_dict.get('config_drive') injected_files = [] if personality: injected_files = self._get_injected_files(personality) sg_names = [] if self.ext_mgr.is_loaded('os-security-groups'): security_groups = server_dict.get('security_groups') if security_groups is not None: sg_names = [ sg['name'] for sg in security_groups if sg.get('name') ] if not sg_names: sg_names.append('default') sg_names = list(set(sg_names)) requested_networks = None if (self.ext_mgr.is_loaded('os-networks') or utils.is_neutron()): requested_networks = server_dict.get('networks') if requested_networks is not None: if not isinstance(requested_networks, list): expl = _('Bad networks format') raise exc.HTTPBadRequest(explanation=expl) requested_networks = self._get_requested_networks( requested_networks) (access_ip_v4, ) = server_dict.get('accessIPv4'), if access_ip_v4 is not None: self._validate_access_ipv4(access_ip_v4) (access_ip_v6, ) = server_dict.get('accessIPv6'), if access_ip_v6 is not None: self._validate_access_ipv6(access_ip_v6) try: flavor_id = self._flavor_id_from_req_data(body) except ValueError as error: msg = _("Invalid flavorRef provided.") raise exc.HTTPBadRequest(explanation=msg) # optional openstack extensions: key_name = None if self.ext_mgr.is_loaded('os-keypairs'): key_name = server_dict.get('key_name') user_data = None if self.ext_mgr.is_loaded('os-user-data'): user_data = server_dict.get('user_data') self._validate_user_data(user_data) availability_zone = None if self.ext_mgr.is_loaded('os-availability-zone'): availability_zone = server_dict.get('availability_zone') block_device_mapping = None block_device_mapping_v2 = None legacy_bdm = True if self.ext_mgr.is_loaded('os-volumes'): block_device_mapping = server_dict.get('block_device_mapping', []) if not isinstance(block_device_mapping, list): msg = _('block_device_mapping must be a list') raise exc.HTTPBadRequest(explanation=msg) for bdm in block_device_mapping: try: block_device.validate_device_name(bdm.get("device_name")) block_device.validate_and_default_volume_size(bdm) except exception.InvalidBDMFormat as e: raise exc.HTTPBadRequest(explanation=e.format_message()) if 'delete_on_termination' in bdm: bdm['delete_on_termination'] = strutils.bool_from_string( bdm['delete_on_termination']) if self.ext_mgr.is_loaded('os-block-device-mapping-v2-boot'): # Consider the new data format for block device mapping block_device_mapping_v2 = server_dict.get( 'block_device_mapping_v2', []) # NOTE (ndipanov): Disable usage of both legacy and new # block device format in the same request if block_device_mapping and block_device_mapping_v2: expl = _('Using different block_device_mapping syntaxes ' 'is not allowed in the same request.') raise exc.HTTPBadRequest(explanation=expl) if not isinstance(block_device_mapping_v2, list): msg = _('block_device_mapping_v2 must be a list') raise exc.HTTPBadRequest(explanation=msg) # Assume legacy format legacy_bdm = not bool(block_device_mapping_v2) try: block_device_mapping_v2 = [ block_device.BlockDeviceDict.from_api(bdm_dict) for bdm_dict in block_device_mapping_v2 ] except exception.InvalidBDMFormat as e: raise exc.HTTPBadRequest(explanation=e.format_message()) block_device_mapping = (block_device_mapping or block_device_mapping_v2) ret_resv_id = False # min_count and max_count are optional. If they exist, they may come # in as strings. Verify that they are valid integers and > 0. # Also, we want to default 'min_count' to 1, and default # 'max_count' to be 'min_count'. min_count = 1 max_count = 1 if self.ext_mgr.is_loaded('os-multiple-create'): ret_resv_id = server_dict.get('return_reservation_id', False) min_count = server_dict.get('min_count', 1) max_count = server_dict.get('max_count', min_count) try: min_count = utils.validate_integer(min_count, "min_count", min_value=1) max_count = utils.validate_integer(max_count, "max_count", min_value=1) except exception.InvalidInput as e: raise exc.HTTPBadRequest(explanation=e.format_message()) if min_count > max_count: msg = _('min_count must be <= max_count') raise exc.HTTPBadRequest(explanation=msg) auto_disk_config = False if self.ext_mgr.is_loaded('OS-DCF'): auto_disk_config = server_dict.get('auto_disk_config') scheduler_hints = {} if self.ext_mgr.is_loaded('OS-SCH-HNT'): scheduler_hints = server_dict.get('scheduler_hints', {}) check_server_group_quota = \ self.ext_mgr.is_loaded('os-server-group-quotas') try: _get_inst_type = flavors.get_flavor_by_flavor_id inst_type = _get_inst_type(flavor_id, ctxt=context, read_deleted="no") (instances, resv_id) = self.compute_api.create( context, inst_type, image_uuid, display_name=name, display_description=name, key_name=key_name, metadata=server_dict.get('metadata', {}), access_ip_v4=access_ip_v4, access_ip_v6=access_ip_v6, injected_files=injected_files, admin_password=password, min_count=min_count, max_count=max_count, requested_networks=requested_networks, security_group=sg_names, user_data=user_data, availability_zone=availability_zone, config_drive=config_drive, block_device_mapping=block_device_mapping, auto_disk_config=auto_disk_config, scheduler_hints=scheduler_hints, legacy_bdm=legacy_bdm, check_server_group_quota=check_server_group_quota) except (exception.QuotaError, exception.PortLimitExceeded) as error: raise exc.HTTPForbidden(explanation=error.format_message(), headers={'Retry-After': 0}) except exception.InvalidMetadataSize as error: raise exc.HTTPRequestEntityTooLarge( explanation=error.format_message()) except exception.ImageNotFound as error: msg = _("Can not find requested image") raise exc.HTTPBadRequest(explanation=msg) except exception.FlavorNotFound as error: msg = _("Invalid flavorRef provided.") raise exc.HTTPBadRequest(explanation=msg) except exception.KeypairNotFound as error: msg = _("Invalid key_name provided.") raise exc.HTTPBadRequest(explanation=msg) except exception.ConfigDriveInvalidValue: msg = _("Invalid config_drive provided.") raise exc.HTTPBadRequest(explanation=msg) except messaging.RemoteError as err: msg = "%(err_type)s: %(err_msg)s" % { 'err_type': err.exc_type, 'err_msg': err.value } raise exc.HTTPBadRequest(explanation=msg) except UnicodeDecodeError as error: msg = "UnicodeError: %s" % error raise exc.HTTPBadRequest(explanation=msg) except (exception.ImageNotActive, exception.FlavorDiskTooSmall, exception.FlavorMemoryTooSmall, exception.NetworkNotFound, exception.PortNotFound, exception.FixedIpAlreadyInUse, exception.SecurityGroupNotFound, exception.InstanceUserDataTooLarge, exception.InstanceUserDataMalformed) as error: raise exc.HTTPBadRequest(explanation=error.format_message()) except (exception.ImageNUMATopologyIncomplete, exception.ImageNUMATopologyForbidden, exception.ImageNUMATopologyAsymmetric, exception.ImageNUMATopologyCPUOutOfRange, exception.ImageNUMATopologyCPUDuplicates, exception.ImageNUMATopologyCPUsUnassigned, exception.ImageNUMATopologyMemoryOutOfRange) as error: raise exc.HTTPBadRequest(explanation=error.format_message()) except (exception.PortInUse, exception.InstanceExists, exception.NoUniqueMatch) as error: raise exc.HTTPConflict(explanation=error.format_message()) except exception.Invalid as error: raise exc.HTTPBadRequest(explanation=error.format_message()) # If the caller wanted a reservation_id, return it if ret_resv_id: return wsgi.ResponseObject({'reservation_id': resv_id}) req.cache_db_instances(instances) server = self._view_builder.create(req, instances[0]) if CONF.enable_instance_password: server['server']['adminPass'] = password robj = wsgi.ResponseObject(server) return self._add_location(robj)
def test_neutron(self): self.flags(network_api_class="nova.network.neutronv2.api.API") self.assertTrue(utils.is_neutron())
def _get_requested_networks(self, requested_networks): """Create a list of requested networks from the networks attribute.""" networks = [] network_uuids = [] for network in requested_networks: request = objects.NetworkRequest() try: # fixed IP address is optional # if the fixed IP address is not provided then # it will use one of the available IP address from the network try: request.address = network.get('fixed_ip', None) except ValueError: msg = (_("Invalid fixed IP address (%s)") % networks.get('fixed_ip')) raise exc.HTTPBadRequest(explanation=msg) try: request.port_id = network.get('port', None) except ValueError: msg = _("Bad port format: port uuid is " "not in proper format " "(%s)") % network.get('port') raise exc.HTTPBadRequest(explanation=msg) if request.port_id: request.network_id = None if not utils.is_neutron(): # port parameter is only for neutron v2.0 msg = _("Unknown argument: port") raise exc.HTTPBadRequest(explanation=msg) if request.address is not None: msg = _("Specified Fixed IP '%(addr)s' cannot be used " "with port '%(port)s': port already has " "a Fixed IP allocated.") % { "addr": request.address, "port": request.port_id } raise exc.HTTPBadRequest(explanation=msg) else: request.network_id = network['uuid'] if (not request.port_id and not uuidutils.is_uuid_like(request.network_id)): br_uuid = request.network_id.split('-', 1)[-1] if not uuidutils.is_uuid_like(br_uuid): msg = _("Bad networks format: network uuid is " "not in proper format " "(%s)") % request.network_id raise exc.HTTPBadRequest(explanation=msg) if (request.network_id and request.network_id in network_uuids): expl = (_("Duplicate networks" " (%s) are not allowed") % request.network_id) raise exc.HTTPBadRequest(explanation=expl) network_uuids.append(request.network_id) networks.append(request) except KeyError as key: expl = _('Bad network format: missing %s') % key raise exc.HTTPBadRequest(explanation=expl) except TypeError: expl = _('Bad networks format') raise exc.HTTPBadRequest(explanation=expl) return objects.NetworkRequestList(objects=networks)
def test_neutron(self): self.flags(use_neutron=True) self.assertTrue(utils.is_neutron())
def create(self, req, body): """Creates a new server for a given user.""" context = req.environ['nova.context'] server_dict = body['server'] password = self._get_server_admin_password(server_dict) name = server_dict['name'] # Arguments to be passed to instance create function create_kwargs = {} # Query extensions which want to manipulate the keyword # arguments. # NOTE(cyeoh): This is the hook that extensions use # to replace the extension specific code below. # When the extensions are ported this will also result # in some convenience function from this class being # moved to the extension if list(self.create_extension_manager): self.create_extension_manager.map(self._create_extension_point, server_dict, create_kwargs, body) image_uuid = self._image_from_req_data(server_dict, create_kwargs) # NOTE(cyeoh): Although an extension can set # return_reservation_id in order to request that a reservation # id be returned to the client instead of the newly created # instance information we do not want to pass this parameter # to the compute create call which always returns both. We use # this flag after the instance create call to determine what # to return to the client return_reservation_id = create_kwargs.pop('return_reservation_id', False) requested_networks = None # TODO(cyeoh): bp v3-api-core-as-extensions # Replace with an extension point when the os-networks # extension is ported. Currently reworked # to take into account is_neutron # if (self.ext_mgr.is_loaded('os-networks') # or utils.is_neutron()): # requested_networks = server_dict.get('networks') if utils.is_neutron(): requested_networks = server_dict.get('networks') if requested_networks is not None: requested_networks = self._get_requested_networks( requested_networks) try: flavor_id = self._flavor_id_from_req_data(body) except ValueError as error: msg = _("Invalid flavorRef provided.") raise exc.HTTPBadRequest(explanation=msg) try: inst_type = flavors.get_flavor_by_flavor_id( flavor_id, ctxt=context, read_deleted="no") (instances, resv_id) = self.compute_api.create(context, inst_type, image_uuid, display_name=name, display_description=name, metadata=server_dict.get('metadata', {}), admin_password=password, requested_networks=requested_networks, check_server_group_quota=True, **create_kwargs) except (exception.QuotaError, exception.PortLimitExceeded) as error: raise exc.HTTPForbidden( explanation=error.format_message(), headers={'Retry-After': 0}) except exception.ImageNotFound as error: msg = _("Can not find requested image") raise exc.HTTPBadRequest(explanation=msg) except exception.FlavorNotFound as error: msg = _("Invalid flavorRef provided.") raise exc.HTTPBadRequest(explanation=msg) except exception.KeypairNotFound as error: msg = _("Invalid key_name provided.") raise exc.HTTPBadRequest(explanation=msg) except exception.ConfigDriveInvalidValue: msg = _("Invalid config_drive provided.") raise exc.HTTPBadRequest(explanation=msg) except exception.ExternalNetworkAttachForbidden as error: raise exc.HTTPForbidden(explanation=error.format_message()) except messaging.RemoteError as err: msg = "%(err_type)s: %(err_msg)s" % {'err_type': err.exc_type, 'err_msg': err.value} raise exc.HTTPBadRequest(explanation=msg) except UnicodeDecodeError as error: msg = "UnicodeError: %s" % error raise exc.HTTPBadRequest(explanation=msg) except (exception.ImageNotActive, exception.FlavorDiskTooSmall, exception.FlavorMemoryTooSmall, exception.InvalidMetadata, exception.InvalidRequest, exception.InvalidVolume, exception.MultiplePortsNotApplicable, exception.InvalidFixedIpAndMaxCountRequest, exception.InstanceUserDataMalformed, exception.InstanceUserDataTooLarge, exception.PortNotFound, exception.FixedIpAlreadyInUse, exception.SecurityGroupNotFound, exception.PortRequiresFixedIP, exception.NetworkRequiresSubnet, exception.NetworkNotFound, exception.InvalidBDMVolumeNotBootable, exception.InvalidBDMSnapshot, exception.InvalidBDMVolume, exception.InvalidBDMImage, exception.InvalidBDMBootSequence, exception.InvalidBDMLocalsLimit, exception.InvalidBDMVolumeNotBootable, exception.AutoDiskConfigDisabledByImage) as error: raise exc.HTTPBadRequest(explanation=error.format_message()) except (exception.PortInUse, exception.InstanceExists, exception.NetworkAmbiguous, exception.NoUniqueMatch) as error: raise exc.HTTPConflict(explanation=error.format_message()) # If the caller wanted a reservation_id, return it if return_reservation_id: # NOTE(cyeoh): In v3 reservation_id was wrapped in # servers_reservation but this is reverted for V2 API # compatibility. In the long term with the tasks API we # will probably just drop the concept of reservation_id return wsgi.ResponseObject({'reservation_id': resv_id}) req.cache_db_instances(instances) server = self._view_builder.create(req, instances[0]) if CONF.enable_instance_password: server['server']['adminPass'] = password robj = wsgi.ResponseObject(server) return self._add_location(robj)
def create(self, req, body): """Creates a new server for a given user.""" context = req.environ['nova.context'] server_dict = body['server'] password = self._get_server_admin_password(server_dict) name = server_dict['name'] # Arguments to be passed to instance create function create_kwargs = {} # Query extensions which want to manipulate the keyword # arguments. # NOTE(cyeoh): This is the hook that extensions use # to replace the extension specific code below. # When the extensions are ported this will also result # in some convenience function from this class being # moved to the extension if list(self.create_extension_manager): self.create_extension_manager.map(self._create_extension_point, server_dict, create_kwargs, body) image_uuid = self._image_from_req_data(server_dict, create_kwargs) # NOTE(cyeoh): Although an extension can set # return_reservation_id in order to request that a reservation # id be returned to the client instead of the newly created # instance information we do not want to pass this parameter # to the compute create call which always returns both. We use # this flag after the instance create call to determine what # to return to the client return_reservation_id = create_kwargs.pop('return_reservation_id', False) requested_networks = None if ('os-networks' in self.extension_info.get_extensions() or utils.is_neutron()): requested_networks = server_dict.get('networks') if requested_networks is not None: requested_networks = self._get_requested_networks( requested_networks) try: flavor_id = self._flavor_id_from_req_data(body) except ValueError as error: msg = _("Invalid flavorRef provided.") raise exc.HTTPBadRequest(explanation=msg) try: inst_type = flavors.get_flavor_by_flavor_id( flavor_id, ctxt=context, read_deleted="no") (instances, resv_id) = self.compute_api.create(context, inst_type, image_uuid, display_name=name, display_description=name, metadata=server_dict.get('metadata', {}), admin_password=password, requested_networks=requested_networks, check_server_group_quota=True, **create_kwargs) except (exception.QuotaError, exception.PortLimitExceeded) as error: raise exc.HTTPForbidden( explanation=error.format_message(), headers={'Retry-After': 0}) except exception.ImageNotFound: msg = _("Can not find requested image") raise exc.HTTPBadRequest(explanation=msg) except exception.FlavorNotFound: msg = _("Invalid flavorRef provided.") raise exc.HTTPBadRequest(explanation=msg) except exception.KeypairNotFound: msg = _("Invalid key_name provided.") raise exc.HTTPBadRequest(explanation=msg) except exception.ConfigDriveInvalidValue: msg = _("Invalid config_drive provided.") raise exc.HTTPBadRequest(explanation=msg) except exception.ExternalNetworkAttachForbidden as error: raise exc.HTTPForbidden(explanation=error.format_message()) except messaging.RemoteError as err: msg = "%(err_type)s: %(err_msg)s" % {'err_type': err.exc_type, 'err_msg': err.value} raise exc.HTTPBadRequest(explanation=msg) except UnicodeDecodeError as error: msg = "UnicodeError: %s" % error raise exc.HTTPBadRequest(explanation=msg) except (exception.ImageNotActive, exception.FlavorDiskTooSmall, exception.FlavorMemoryTooSmall, exception.InvalidMetadata, exception.InvalidRequest, exception.InvalidVolume, exception.MultiplePortsNotApplicable, exception.InvalidFixedIpAndMaxCountRequest, exception.InstanceUserDataMalformed, exception.InstanceUserDataTooLarge, exception.PortNotFound, exception.FixedIpAlreadyInUse, exception.SecurityGroupNotFound, exception.PortRequiresFixedIP, exception.NetworkRequiresSubnet, exception.NetworkNotFound, exception.InvalidBDMVolumeNotBootable, exception.InvalidBDMSnapshot, exception.InvalidBDMVolume, exception.InvalidBDMImage, exception.InvalidBDMBootSequence, exception.InvalidBDMLocalsLimit, exception.InvalidBDMVolumeNotBootable, exception.AutoDiskConfigDisabledByImage, exception.ImageNUMATopologyIncomplete, exception.ImageNUMATopologyForbidden, exception.ImageNUMATopologyAsymmetric, exception.ImageNUMATopologyCPUOutOfRange, exception.ImageNUMATopologyCPUDuplicates, exception.ImageNUMATopologyCPUsUnassigned, exception.ImageNUMATopologyMemoryOutOfRange) as error: raise exc.HTTPBadRequest(explanation=error.format_message()) except (exception.PortInUse, exception.InstanceExists, exception.NetworkAmbiguous, exception.NoUniqueMatch) as error: raise exc.HTTPConflict(explanation=error.format_message()) # If the caller wanted a reservation_id, return it if return_reservation_id: # NOTE(cyeoh): In v3 reservation_id was wrapped in # servers_reservation but this is reverted for V2 API # compatibility. In the long term with the tasks API we # will probably just drop the concept of reservation_id return wsgi.ResponseObject({'reservation_id': resv_id}) req.cache_db_instances(instances) server = self._view_builder.create(req, instances[0]) if CONF.enable_instance_password: server['server']['adminPass'] = password robj = wsgi.ResponseObject(server) return self._add_location(robj)
def test_nova_network(self): self.flags(network_api_class='nova.network.api.API') self.assertFalse(utils.is_neutron())
def test_quantum(self): self.flags(network_api_class='nova.network.quantumv2.api.API') self.assertTrue(utils.is_neutron())
def create(self, req, body): """Creates a new server for a given user.""" context = req.environ['nova.context'] server_dict = body['server'] password = self._get_server_admin_password(server_dict) if 'name' not in server_dict: msg = _("Server name is not defined") raise exc.HTTPBadRequest(explanation=msg) name = server_dict['name'] self._validate_server_name(name) name = name.strip() # Arguments to be passed to instance create function create_kwargs = {} # Query extensions which want to manipulate the keyword # arguments. # NOTE(cyeoh): This is the hook that extensions use # to replace the extension specific code below. # When the extensions are ported this will also result # in some convenience function from this class being # moved to the extension if list(self.create_extension_manager): self.create_extension_manager.map(self._create_extension_point, server_dict, create_kwargs, body) image_uuid = self._image_from_req_data(server_dict, create_kwargs) # NOTE(cyeoh): Although an extension can set # return_reservation_id in order to request that a reservation # id be returned to the client instead of the newly created # instance information we do not want to pass this parameter # to the compute create call which always returns both. We use # this flag after the instance create call to determine what # to return to the client return_reservation_id = create_kwargs.pop('return_reservation_id', False) requested_networks = None # TODO(cyeoh): bp v3-api-core-as-extensions # Replace with an extension point when the os-networks # extension is ported. Currently reworked # to take into account is_neutron # if (self.ext_mgr.is_loaded('os-networks') # or utils.is_neutron()): # requested_networks = server_dict.get('networks') if utils.is_neutron(): requested_networks = server_dict.get('networks') if requested_networks is not None: requested_networks = self._get_requested_networks( requested_networks) try: flavor_id = self._flavor_id_from_req_data(body) except ValueError as error: msg = _("Invalid flavorRef provided.") raise exc.HTTPBadRequest(explanation=msg) try: inst_type = flavors.get_flavor_by_flavor_id(flavor_id, ctxt=context, read_deleted="no") (instances, resv_id) = self.compute_api.create( context, inst_type, image_uuid, display_name=name, display_description=name, metadata=server_dict.get('metadata', {}), admin_password=password, requested_networks=requested_networks, **create_kwargs) except (exception.QuotaError, exception.PortLimitExceeded) as error: raise exc.HTTPForbidden(explanation=error.format_message(), headers={'Retry-After': 0}) except exception.InvalidMetadataSize as error: raise exc.HTTPRequestEntityTooLarge( explanation=error.format_message()) except exception.ImageNotFound as error: msg = _("Can not find requested image") raise exc.HTTPBadRequest(explanation=msg) except exception.FlavorNotFound as error: msg = _("Invalid flavorRef provided.") raise exc.HTTPBadRequest(explanation=msg) except exception.KeypairNotFound as error: msg = _("Invalid key_name provided.") raise exc.HTTPBadRequest(explanation=msg) except exception.ConfigDriveInvalidValue: msg = _("Invalid config_drive provided.") raise exc.HTTPBadRequest(explanation=msg) except messaging.RemoteError as err: msg = "%(err_type)s: %(err_msg)s" % { 'err_type': err.exc_type, 'err_msg': err.value } raise exc.HTTPBadRequest(explanation=msg) except UnicodeDecodeError as error: msg = "UnicodeError: %s" % unicode(error) raise exc.HTTPBadRequest(explanation=msg) except (exception.ImageNotActive, exception.FlavorDiskTooSmall, exception.FlavorMemoryTooSmall, exception.InvalidMetadata, exception.InvalidRequest, exception.MultiplePortsNotApplicable, exception.InvalidFixedIpAndMaxCountRequest, exception.InstanceUserDataMalformed, exception.InstanceUserDataTooLarge, exception.PortNotFound, exception.FixedIpAlreadyInUse, exception.SecurityGroupNotFound, exception.PortRequiresFixedIP, exception.NetworkRequiresSubnet, exception.NetworkNotFound, exception.InvalidBDMVolumeNotBootable, exception.InvalidBDMSnapshot, exception.InvalidBDMVolume, exception.InvalidBDMImage, exception.InvalidBDMBootSequence, exception.InvalidBDMLocalsLimit, exception.InvalidBDMVolumeNotBootable) as error: raise exc.HTTPBadRequest(explanation=error.format_message()) except (exception.PortInUse, exception.NetworkAmbiguous, exception.NoUniqueMatch) as error: raise exc.HTTPConflict(explanation=error.format_message()) # If the caller wanted a reservation_id, return it if return_reservation_id: return wsgi.ResponseObject( {'servers_reservation': { 'reservation_id': resv_id }}) req.cache_db_instances(instances) server = self._view_builder.create(req, instances[0]) if CONF.enable_instance_password: server['server']['adminPass'] = password robj = wsgi.ResponseObject(server) return self._add_location(robj)
def _get_requested_networks(self, requested_networks): """Create a list of requested networks from the networks attribute.""" networks = [] for network in requested_networks: try: # fixed IP address is optional # if the fixed IP address is not provided then # it will use one of the available IP address from the network address = network.get('fixed_ip', None) if address is not None and not utils.is_valid_ipv4(address): msg = _("Invalid fixed IP address (%s)") % address raise exc.HTTPBadRequest(explanation=msg) port_id = network.get('port', None) if port_id: network_uuid = None if not utils.is_neutron(): # port parameter is only for neutron v2.0 msg = _("Unknown argument: port") raise exc.HTTPBadRequest(explanation=msg) if not uuidutils.is_uuid_like(port_id): msg = _("Bad port format: port uuid is " "not in proper format " "(%s)") % port_id raise exc.HTTPBadRequest(explanation=msg) if address is not None: msg = _("Specified Fixed IP '%(addr)s' cannot be used " "with port '%(port)s': port already has " "a Fixed IP allocated.") % { "addr": address, "port": port_id } raise exc.HTTPBadRequest(explanation=msg) else: network_uuid = network['uuid'] if not port_id and not uuidutils.is_uuid_like(network_uuid): br_uuid = network_uuid.split('-', 1)[-1] if not uuidutils.is_uuid_like(br_uuid): msg = _("Bad networks format: network uuid is " "not in proper format " "(%s)") % network_uuid raise exc.HTTPBadRequest(explanation=msg) # For neutronv2, requested_networks # should be tuple of (network_uuid, fixed_ip, port_id) if utils.is_neutron(): networks.append((network_uuid, address, port_id)) else: # check if the network id is already present in the list, # we don't want duplicate networks to be passed # at the boot time for id, ip in networks: if id == network_uuid: expl = (_("Duplicate networks" " (%s) are not allowed") % network_uuid) raise exc.HTTPBadRequest(explanation=expl) networks.append((network_uuid, address)) except KeyError as key: expl = _('Bad network format: missing %s') % key raise exc.HTTPBadRequest(explanation=expl) except TypeError: expl = _('Bad networks format') raise exc.HTTPBadRequest(explanation=expl) return networks
def _get_requested_networks(self, requested_networks): """Create a list of requested networks from the networks attribute.""" networks = [] for network in requested_networks: try: # fixed IP address is optional # if the fixed IP address is not provided then # it will use one of the available IP address from the network address = network.get('fixed_ip', None) if address is not None and not utils.is_valid_ipv4(address): msg = _("Invalid fixed IP address (%s)") % address raise exc.HTTPBadRequest(explanation=msg) port_id = network.get('port', None) if port_id: network_uuid = None if not utils.is_neutron(): # port parameter is only for neutron v2.0 msg = _("Unknown argument: port") raise exc.HTTPBadRequest(explanation=msg) if not uuidutils.is_uuid_like(port_id): msg = _("Bad port format: port uuid is " "not in proper format " "(%s)") % port_id raise exc.HTTPBadRequest(explanation=msg) if address is not None: msg = _("Specified Fixed IP '%(addr)s' cannot be used " "with port '%(port)s': port already has " "a Fixed IP allocated.") % {"addr": address, "port": port_id} raise exc.HTTPBadRequest(explanation=msg) else: network_uuid = network['uuid'] if not port_id and not uuidutils.is_uuid_like(network_uuid): br_uuid = network_uuid.split('-', 1)[-1] if not uuidutils.is_uuid_like(br_uuid): msg = _("Bad networks format: network uuid is " "not in proper format " "(%s)") % network_uuid raise exc.HTTPBadRequest(explanation=msg) # For neutronv2, requested_networks # should be tuple of (network_uuid, fixed_ip, port_id) if utils.is_neutron(): networks.append((network_uuid, address, port_id)) else: # check if the network id is already present in the list, # we don't want duplicate networks to be passed # at the boot time for id, ip in networks: if id == network_uuid: expl = (_("Duplicate networks" " (%s) are not allowed") % network_uuid) raise exc.HTTPBadRequest(explanation=expl) networks.append((network_uuid, address)) except KeyError as key: expl = _('Bad network format: missing %s') % key raise exc.HTTPBadRequest(explanation=expl) except TypeError: expl = _('Bad networks format') raise exc.HTTPBadRequest(explanation=expl) return networks
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'])
def create(self, req, body): """Creates a new server for a given user.""" if not self.is_valid_body(body, 'server'): raise exc.HTTPBadRequest(_("The request body is invalid")) context = req.environ['nova.context'] server_dict = body['server'] password = self._get_server_admin_password(server_dict) if 'name' not in server_dict: msg = _("Server name is not defined") raise exc.HTTPBadRequest(explanation=msg) name = server_dict['name'] self._validate_server_name(name) name = name.strip() # Arguments to be passed to instance create function create_kwargs = {} # Query extensions which want to manipulate the keyword # arguments. # NOTE(cyeoh): This is the hook that extensions use # to replace the extension specific code below. # When the extensions are ported this will also result # in some convenience function from this class being # moved to the extension if list(self.create_extension_manager): self.create_extension_manager.map(self._create_extension_point, server_dict, create_kwargs) image_uuid = self._image_from_req_data(server_dict, create_kwargs) # NOTE(cyeoh): Although an extension can set # return_reservation_id in order to request that a reservation # id be returned to the client instead of the newly created # instance information we do not want to pass this parameter # to the compute create call which always returns both. We use # this flag after the instance create call to determine what # to return to the client return_reservation_id = create_kwargs.pop('return_reservation_id', False) requested_networks = None # TODO(cyeoh): bp v3-api-core-as-extensions # Replace with an extension point when the os-networks # extension is ported. Currently reworked # to take into account is_neutron #if (self.ext_mgr.is_loaded('os-networks') # or utils.is_neutron()): # requested_networks = server_dict.get('networks') if utils.is_neutron(): requested_networks = server_dict.get('networks') if requested_networks is not None: requested_networks = self._get_requested_networks( requested_networks) try: flavor_id = self._flavor_id_from_req_data(body) except ValueError as error: msg = _("Invalid flavor_ref provided.") raise exc.HTTPBadRequest(explanation=msg) try: inst_type = flavors.get_flavor_by_flavor_id( flavor_id, ctxt=context, read_deleted="no") (instances, resv_id) = self.compute_api.create(context, inst_type, image_uuid, display_name=name, display_description=name, metadata=server_dict.get('metadata', {}), admin_password=password, requested_networks=requested_networks, **create_kwargs) except (exception.QuotaError, exception.PortLimitExceeded) as error: raise exc.HTTPRequestEntityTooLarge( explanation=error.format_message(), headers={'Retry-After': 0}) except exception.InvalidMetadataSize as error: raise exc.HTTPRequestEntityTooLarge( explanation=error.format_message()) except exception.ImageNotFound as error: msg = _("Can not find requested image") raise exc.HTTPBadRequest(explanation=msg) except exception.FlavorNotFound as error: msg = _("Invalid flavor_ref provided.") raise exc.HTTPBadRequest(explanation=msg) except exception.KeypairNotFound as error: msg = _("Invalid key_name provided.") raise exc.HTTPBadRequest(explanation=msg) except exception.ConfigDriveInvalidValue: msg = _("Invalid config_drive provided.") raise exc.HTTPBadRequest(explanation=msg) except messaging.RemoteError as err: msg = "%(err_type)s: %(err_msg)s" % {'err_type': err.exc_type, 'err_msg': err.value} raise exc.HTTPBadRequest(explanation=msg) except UnicodeDecodeError as error: msg = "UnicodeError: %s" % unicode(error) raise exc.HTTPBadRequest(explanation=msg) except (exception.ImageNotActive, exception.FlavorDiskTooSmall, exception.FlavorMemoryTooSmall, exception.InvalidMetadata, exception.InvalidRequest, exception.MultiplePortsNotApplicable, exception.InstanceUserDataMalformed, exception.PortNotFound, exception.SecurityGroupNotFound, exception.NetworkNotFound) as error: raise exc.HTTPBadRequest(explanation=error.format_message()) except (exception.PortInUse, exception.NoUniqueMatch) as error: raise exc.HTTPConflict(explanation=error.format_message()) # If the caller wanted a reservation_id, return it if return_reservation_id: return wsgi.ResponseObject( {'servers_reservation': {'reservation_id': resv_id}}) req.cache_db_instances(instances) server = self._view_builder.create(req, instances[0]) if CONF.enable_instance_password: server['server']['admin_password'] = password robj = wsgi.ResponseObject(server) return self._add_location(robj)
def create(self, req, body): """Creates a new server for a given user.""" context = req.environ["nova.context"] server_dict = body["server"] password = self._get_server_admin_password(server_dict) name = server_dict["name"] # Arguments to be passed to instance create function create_kwargs = {} # Query extensions which want to manipulate the keyword # arguments. # NOTE(cyeoh): This is the hook that extensions use # to replace the extension specific code below. # When the extensions are ported this will also result # in some convenience function from this class being # moved to the extension if list(self.create_extension_manager): self.create_extension_manager.map(self._create_extension_point, server_dict, create_kwargs, body) availability_zone = create_kwargs.get("availability_zone") target = {"project_id": context.project_id, "user_id": context.user_id, "availability_zone": availability_zone} authorize(context, target, "create") # TODO(Shao He, Feng) move this policy check to os-availabilty-zone # extension after refactor it. if availability_zone: _dummy, host, node = self.compute_api._handle_availability_zone(context, availability_zone) if host or node: authorize(context, {}, "create:forced_host") block_device_mapping = create_kwargs.get("block_device_mapping") # TODO(Shao He, Feng) move this policy check to os-block-device-mapping # extension after refactor it. if block_device_mapping: authorize(context, target, "create:attach_volume") image_uuid = self._image_from_req_data(server_dict, create_kwargs) # NOTE(cyeoh): Although an extension can set # return_reservation_id in order to request that a reservation # id be returned to the client instead of the newly created # instance information we do not want to pass this parameter # to the compute create call which always returns both. We use # this flag after the instance create call to determine what # to return to the client return_reservation_id = create_kwargs.pop("return_reservation_id", False) requested_networks = None if "os-networks" in self.extension_info.get_extensions() or utils.is_neutron(): requested_networks = server_dict.get("networks") if requested_networks is not None: requested_networks = self._get_requested_networks(requested_networks) if requested_networks and len(requested_networks): authorize(context, target, "create:attach_network") try: flavor_id = self._flavor_id_from_req_data(body) except ValueError: msg = _("Invalid flavorRef provided.") raise exc.HTTPBadRequest(explanation=msg) try: inst_type = flavors.get_flavor_by_flavor_id(flavor_id, ctxt=context, read_deleted="no") (instances, resv_id) = self.compute_api.create( context, inst_type, image_uuid, display_name=name, display_description=name, metadata=server_dict.get("metadata", {}), admin_password=password, requested_networks=requested_networks, check_server_group_quota=True, **create_kwargs ) except (exception.QuotaError, exception.PortLimitExceeded) as error: raise exc.HTTPForbidden(explanation=error.format_message(), headers={"Retry-After": 0}) except exception.ImageNotFound: msg = _("Can not find requested image") raise exc.HTTPBadRequest(explanation=msg) except exception.FlavorNotFound: msg = _("Invalid flavorRef provided.") raise exc.HTTPBadRequest(explanation=msg) except exception.KeypairNotFound: msg = _("Invalid key_name provided.") raise exc.HTTPBadRequest(explanation=msg) except exception.ConfigDriveInvalidValue: msg = _("Invalid config_drive provided.") raise exc.HTTPBadRequest(explanation=msg) except exception.ExternalNetworkAttachForbidden as error: raise exc.HTTPForbidden(explanation=error.format_message()) except messaging.RemoteError as err: msg = "%(err_type)s: %(err_msg)s" % {"err_type": err.exc_type, "err_msg": err.value} raise exc.HTTPBadRequest(explanation=msg) except UnicodeDecodeError as error: msg = "UnicodeError: %s" % error raise exc.HTTPBadRequest(explanation=msg) except ( exception.ImageNotActive, exception.FlavorDiskTooSmall, exception.FlavorMemoryTooSmall, exception.InvalidMetadata, exception.InvalidRequest, exception.InvalidVolume, exception.MultiplePortsNotApplicable, exception.InvalidFixedIpAndMaxCountRequest, exception.InstanceUserDataMalformed, exception.InstanceUserDataTooLarge, exception.PortNotFound, exception.FixedIpAlreadyInUse, exception.SecurityGroupNotFound, exception.PortRequiresFixedIP, exception.NetworkRequiresSubnet, exception.NetworkNotFound, exception.NetworkDuplicated, exception.InvalidBDMSnapshot, exception.InvalidBDMVolume, exception.InvalidBDMImage, exception.InvalidBDMBootSequence, exception.InvalidBDMLocalsLimit, exception.InvalidBDMVolumeNotBootable, exception.AutoDiskConfigDisabledByImage, exception.ImageNUMATopologyIncomplete, exception.ImageNUMATopologyForbidden, exception.ImageNUMATopologyAsymmetric, exception.ImageNUMATopologyCPUOutOfRange, exception.ImageNUMATopologyCPUDuplicates, exception.ImageNUMATopologyCPUsUnassigned, exception.ImageNUMATopologyMemoryOutOfRange, ) as error: raise exc.HTTPBadRequest(explanation=error.format_message()) except ( exception.PortInUse, exception.InstanceExists, exception.NetworkAmbiguous, exception.NoUniqueMatch, ) as error: raise exc.HTTPConflict(explanation=error.format_message()) # If the caller wanted a reservation_id, return it if return_reservation_id: # NOTE(cyeoh): In v3 reservation_id was wrapped in # servers_reservation but this is reverted for V2 API # compatibility. In the long term with the tasks API we # will probably just drop the concept of reservation_id return wsgi.ResponseObject({"reservation_id": resv_id}) req.cache_db_instances(instances) server = self._view_builder.create(req, instances[0]) if CONF.enable_instance_password: server["server"]["adminPass"] = password robj = wsgi.ResponseObject(server) return self._add_location(robj)