'Creates a new server for a given user.'

@wsgi.response(202)
@extensions.expected_errors((400, 403, 409))
@validation.schema(schema_server_create_v20, '2.0', '2.0')
@validation.schema(schema_server_create, '2.1', '2.18')
@validation.schema(schema_server_create_v219, '2.19', '2.31')
@validation.schema(schema_server_create_v232, '2.32', '2.36')
@validation.schema(schema_server_create_v237, '2.37', '2.41')
@validation.schema(schema_server_create_v242, '2.42', '2.51')
@validation.schema(schema_server_create_v252, '2.52')
def create(self, req, body):

    context = req.environ['nova.context']
    server_dict = body['server']
    password = self._get_server_admin_password(server_dict)
    name = common.normalize_name(server_dict['name'])
    description = name
    if api_version_request.is_supported(req, min_version='2.19'):
        description = server_dict.get('description')
    create_kwargs = {}
    self._create_by_func_list(server_dict, create_kwargs, body)
    availability_zone = create_kwargs.pop('availability_zone', None)
    if api_version_request.is_supported(req, min_version='2.52'):
        create_kwargs['tags'] = server_dict.get('tags')
    helpers.translate_attributes(helpers.CREATE, server_dict, create_kwargs)
    target = {'project_id': context.project_id, 'user_id': context.user_id, 'availability_zone': availability_zone}
    context.can((server_policies.SERVERS % 'create'), target)
    parse_az = self.compute_api.parse_availability_zone
    try:
        (availability_zone, host, node) = parse_az(context, availability_zone)
    except exception.InvalidInput as err:
        raise exc.HTTPBadRequest(explanation=six.text_type(err))
    if (host or node):
        context.can((server_policies.SERVERS % 'create:forced_host'), {})
    min_compute_version = service_obj.get_minimum_version_all_cells(nova_context.get_admin_context(), ['nova-compute'])
    supports_device_tagging = (min_compute_version >= DEVICE_TAGGING_MIN_COMPUTE_VERSION)
    block_device_mapping = create_kwargs.get('block_device_mapping')
    if block_device_mapping:
        context.can((server_policies.SERVERS % 'create:attach_volume'), target)
        for bdm in block_device_mapping:
            if (bdm.get('tag', None) and (not supports_device_tagging)):
                msg = _('Block    device    tags    are    not    yet    supported.')
                raise exc.HTTPBadRequest(explanation=msg)
    image_uuid = self._image_from_req_data(server_dict, create_kwargs)
    return_reservation_id = create_kwargs.pop('return_reservation_id', False)
    requested_networks = server_dict.get('networks', None)
    if (requested_networks is not None):
        requested_networks = self._get_requested_networks(requested_networks, supports_device_tagging)
    if (requested_networks and len(requested_networks) and (not requested_networks.no_allocate)):
        context.can((server_policies.SERVERS % 'create:attach_network'), target)
    flavor_id = self._flavor_id_from_req_data(body)
    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=description, availability_zone=availability_zone, forced_host=host, forced_node=node, 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())
    except exception.ImageNotFound:
        msg = _('Can    not    find    requested    image')
        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.CPUThreadPolicyConfigurationInvalid, exception.ImageNotActive, exception.ImageBadRequest, exception.ImageNotAuthorized, exception.FixedIpNotFoundForAddress, exception.FlavorNotFound, 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.InvalidBDM, exception.InvalidBDMSnapshot, exception.InvalidBDMVolume, exception.InvalidBDMImage, exception.InvalidBDMBootSequence, exception.InvalidBDMLocalsLimit, exception.InvalidBDMVolumeNotBootable, exception.InvalidBDMEphemeralSize, exception.InvalidBDMFormat, exception.InvalidBDMSwapSize, exception.AutoDiskConfigDisabledByImage, exception.ImageCPUPinningForbidden, exception.ImageCPUThreadPolicyForbidden, exception.ImageNUMATopologyIncomplete, exception.ImageNUMATopologyForbidden, exception.ImageNUMATopologyAsymmetric, exception.ImageNUMATopologyCPUOutOfRange, exception.ImageNUMATopologyCPUDuplicates, exception.ImageNUMATopologyCPUsUnassigned, exception.ImageNUMATopologyMemoryOutOfRange, exception.InvalidNUMANodesNumber, exception.InstanceGroupNotFound, exception.MemoryPageSizeInvalid, exception.MemoryPageSizeForbidden, exception.PciRequestAliasNotDefined, exception.RealtimeConfigurationInvalid, exception.RealtimeMaskNotFoundOrInvalid, exception.SnapshotNotFound, exception.UnableToAutoAllocateNetwork) 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 return_reservation_id:
        return wsgi.ResponseObject({'reservation_id': resv_id})
    req.cache_db_instances(instances)
    server = self._view_builder.create(req, instances[0])
    if CONF.api.enable_instance_password:
        server['server']['adminPass'] = password
    robj = wsgi.ResponseObject(server)
    return self._add_location(robj)
