static char *
esxStoragePoolGetXMLDesc(virStoragePoolPtr pool, unsigned int flags)
{
    char *xml = NULL;
    esxPrivate *priv = pool->conn->privateData;
    esxVI_HostInternetScsiHba *hostInternetScsiHba = NULL;
    esxVI_HostInternetScsiHbaStaticTarget *target;
    virStoragePoolDef def;

    virCheckFlags(0, NULL);

    memset(&def, 0, sizeof(def));

    if (esxVI_LookupHostInternetScsiHba(priv->primary, &hostInternetScsiHba))
        goto cleanup;

    for (target = hostInternetScsiHba->configuredStaticTarget;
         target; target = target->_next) {
        if (STREQ(target->iScsiName, pool->name))
            break;
    }

    if (!target) {
        /* pool not found */
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Could not find storage pool with name '%s'"),
                       pool->name);
        goto cleanup;
    }

    def.name = pool->name;

    memcpy(def.uuid, pool->uuid, VIR_UUID_BUFLEN);

    def.type = VIR_STORAGE_POOL_ISCSI;

    def.source.initiator.iqn = target->iScsiName;

    def.source.nhost = 1;

    if (VIR_ALLOC_N(def.source.hosts, def.source.nhost) < 0)
        goto cleanup;

    def.source.hosts[0].name = target->address;

    if (target->port)
        def.source.hosts[0].port = target->port->value;

    /* TODO: add CHAP authentication params */
    xml = virStoragePoolDefFormat(&def);

 cleanup:
    VIR_FREE(def.source.hosts);
    esxVI_HostInternetScsiHba_Free(&hostInternetScsiHba);

    return xml;
}
static int
esxConnectListStoragePools(virConnectPtr conn, char **const names,
                           const int maxnames)
{
    bool success = false;
    int count = 0;
    esxPrivate *priv = conn->storagePrivateData;
    esxVI_HostInternetScsiHba *hostInternetScsiHba = NULL;
    esxVI_HostInternetScsiHbaStaticTarget *target;
    size_t i;

    if (maxnames == 0) {
        return 0;
    }

    if (esxVI_LookupHostInternetScsiHba(priv->primary,
                                        &hostInternetScsiHba) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Unable to obtain iSCSI adapter"));
        goto cleanup;
    }

    /* FIXME: code looks for software iSCSI adapter only */
    if (!hostInternetScsiHba) {
        /* iSCSI adapter may not be enabled for this host */
        return 0;
    }

    /*
     * ESX has two kind of targets:
     * 1. staticIscsiTargets
     * 2. dynamicIscsiTargets
     * For each dynamic target if its reachable a static target is added.
     * return iSCSI names for all static targets to avoid duplicate names.
     */
    for (target = hostInternetScsiHba->configuredStaticTarget;
         target && count < maxnames; target = target->_next) {
        if (VIR_STRDUP(names[count], target->iScsiName) < 0)
            goto cleanup;

        ++count;
    }

    success = true;

 cleanup:
    if (! success) {
        for (i = 0; i < count; ++i) {
            VIR_FREE(names[i]);
        }
    }

    esxVI_HostInternetScsiHba_Free(&hostInternetScsiHba);

    return success ? count : -1;
}
static virStoragePoolPtr
esxStoragePoolLookupByUUID(virConnectPtr conn,
                           const unsigned char *uuid)
{
    virStoragePoolPtr pool = NULL;
    esxPrivate *priv = conn->storagePrivateData;
    esxVI_HostInternetScsiHba *hostInternetScsiHba = NULL;
    esxVI_HostInternetScsiHbaStaticTarget *target;
    /* MD5_DIGEST_SIZE = VIR_UUID_BUFLEN = 16 */
    unsigned char md5[MD5_DIGEST_SIZE];

    if (esxVI_LookupHostInternetScsiHba(priv->primary,
                                        &hostInternetScsiHba) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Unable to obtain iSCSI adapter"));
        goto cleanup;
    }

    /* FIXME: code just looks for software iSCSI adapter */
    if (!hostInternetScsiHba) {
        /* iSCSI adapter may not be enabled for this host */
        return NULL;
    }

    for (target = hostInternetScsiHba->configuredStaticTarget;
         target; target = target->_next) {
        md5_buffer(target->iScsiName, strlen(target->iScsiName), md5);

        if (memcmp(uuid, md5, VIR_UUID_STRING_BUFLEN) == 0) {
            break;
        }
    }

    if (!target) {
        /* pool not found, error handling done by the base driver */
        goto cleanup;
    }

    pool = virGetStoragePool(conn, target->iScsiName, md5,
                             &esxStorageBackendISCSI, NULL);

 cleanup:
    esxVI_HostInternetScsiHba_Free(&hostInternetScsiHba);

    return pool;
}
static int
esxConnectNumOfStoragePools(virConnectPtr conn)
{
    bool success = false;
    int count = 0;
    esxPrivate *priv = conn->storagePrivateData;
    esxVI_HostInternetScsiHba *hostInternetScsiHba = NULL;
    esxVI_HostInternetScsiHbaStaticTarget *target;

    if (esxVI_LookupHostInternetScsiHba(priv->primary,
                                        &hostInternetScsiHba) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Unable to obtain iSCSI adapter"));
        goto cleanup;
    }

    /* FIXME: code looks for software iSCSI adapter only */
    if (!hostInternetScsiHba) {
        /* iSCSI adapter may not be enabled for this host */
        return 0;
    }

    /*
     * ESX has two kind of targets:
     * 1. staticIscsiTargets
     * 2. dynamicIscsiTargets
     * For each dynamic target if its reachable a static target is added.
     * return iSCSI names for all static targets to avoid duplicate names.
     */
    for (target = hostInternetScsiHba->configuredStaticTarget;
         target; target = target->_next) {
        ++count;
    }

    success = true;

 cleanup:
    esxVI_HostInternetScsiHba_Free(&hostInternetScsiHba);

    return success ? count : -1;
}