def get_hosts(service_instance, datacenter_name=None, host_names=None,
              cluster_name=None, get_all_hosts=False):
    '''
    Returns a list of vim.HostSystem objects representing ESXi hosts
    in a vcenter filtered by their names and/or datacenter, cluster membership.

    service_instance
        The Service Instance Object from which to obtain the hosts.

    datacenter_name
        The datacenter name. Default is None.

    host_names
        The host_names to be retrieved. Default is None.

    cluster_name
        The cluster name - used to restrict the hosts retrieved. Only used if
        the datacenter is set.  This argument is optional.

    get_all_hosts
        Specifies whether to retrieve all hosts in the container.
        Default value is False.
    '''
    properties = ['name']
    if cluster_name and not datacenter_name:
        raise salt.exceptions.ArgumentValueError(
            'Must specify the datacenter when specifying the cluster')
    if not host_names:
        host_names = []
    if not datacenter_name:
        # Assume the root folder is the starting point
        start_point = get_root_folder(service_instance)
    else:
        start_point = get_datacenter(service_instance, datacenter_name)
        if cluster_name:
            # Retrieval to test if cluster exists. Cluster existence only makes
            # sense if the datacenter has been specified
            properties.append('parent')

    # Search for the objects
    hosts = get_mors_with_properties(service_instance,
                                     vim.HostSystem,
                                     container_ref=start_point,
                                     property_list=properties)
    log.trace('Retrieved hosts: %s', [h['name'] for h in hosts])
    filtered_hosts = []
    for h in hosts:
        # Complex conditions checking if a host should be added to the
        # filtered list (either due to its name and/or cluster membership)

        if cluster_name:
            if not isinstance(h['parent'], vim.ClusterComputeResource):
                continue
            parent_name = get_managed_object_name(h['parent'])
            if parent_name != cluster_name:
                continue

        if get_all_hosts:
            filtered_hosts.append(h['object'])
            continue

        if h['name'] in host_names:
            filtered_hosts.append(h['object'])
    return filtered_hosts