@classmethod
def from_components(cls, context, instance_uuid, image, flavor,
    numa_topology, pci_requests, filter_properties, instance_group,
    availability_zone, security_groups=None, project_id=None, user_id=None,
    port_resource_requests=None):
    """Returns a new RequestSpec object hydrated by various components.

        This helper is useful in creating the RequestSpec from the various
        objects that are assembled early in the boot process.  This method
        creates a complete RequestSpec object with all properties set or
        intentionally left blank.

        :param context: a context object
        :param instance_uuid: the uuid of the instance to schedule
        :param image: a dict of properties for an image or volume
        :param flavor: a flavor NovaObject
        :param numa_topology: InstanceNUMATopology or None
        :param pci_requests: InstancePCIRequests
        :param filter_properties: a dict of properties for scheduling
        :param instance_group: None or an instance group NovaObject
        :param availability_zone: an availability_zone string
        :param security_groups: A SecurityGroupList object. If None, don't
                                set security_groups on the resulting object.
        :param project_id: The project_id for the requestspec (should match
                           the instance project_id).
        :param user_id: The user_id for the requestspec (should match
                           the instance user_id).
        :param port_resource_requests: a list of RequestGroup objects
                                       representing the resource needs of the
                                       neutron ports
        """
    spec_obj = cls(context)
    spec_obj.num_instances = 1
    spec_obj.instance_uuid = instance_uuid
    spec_obj.instance_group = instance_group
    if spec_obj.instance_group is None and filter_properties:
        spec_obj._populate_group_info(filter_properties)
    spec_obj.project_id = project_id or context.project_id
    spec_obj.user_id = user_id or context.user_id
    spec_obj._image_meta_from_image(image)
    spec_obj._from_flavor(flavor)
    spec_obj._from_instance_pci_requests(pci_requests)
    spec_obj._from_instance_numa_topology(numa_topology)
    spec_obj.ignore_hosts = filter_properties.get('ignore_hosts')
    spec_obj.force_hosts = filter_properties.get('force_hosts')
    spec_obj.force_nodes = filter_properties.get('force_nodes')
    spec_obj._from_retry(filter_properties.get('retry', {}))
    spec_obj._from_limits(filter_properties.get('limits', {}))
    spec_obj._from_hints(filter_properties.get('scheduler_hints', {}))
    spec_obj.availability_zone = availability_zone
    if security_groups is not None:
        spec_obj.security_groups = security_groups
    spec_obj.requested_destination = filter_properties.get(
        'requested_destination')
    spec_obj.requested_resources = []
    if port_resource_requests:
        spec_obj.requested_resources.extend(port_resource_requests)
    spec_obj.obj_set_defaults()
    return spec_obj
