示例#1
0
static virStorageVolPtr
esxStorageVolLookupByName(virStoragePoolPtr pool,
                          const char *name)
{
    virStorageVolPtr volume = NULL;
    esxPrivate *priv = pool->conn->privateData;
    char *datastorePath = NULL;
    char *key = NULL;

    if (virAsprintf(&datastorePath, "[%s] %s", pool->name, name) < 0)
        goto cleanup;

    if (esxVI_LookupStorageVolumeKeyByDatastorePath(priv->primary,
                                                    datastorePath, &key) < 0) {
        goto cleanup;
    }

    volume = virGetStorageVol(pool->conn, pool->name, name, key,
                              &esxStorageBackendVMFS, NULL);

 cleanup:
    VIR_FREE(datastorePath);
    VIR_FREE(key);

    return volume;
}
示例#2
0
static virStorageVolPtr
esxStorageVolLookupByPath(virConnectPtr conn, const char *path)
{
    virStorageVolPtr volume = NULL;
    esxPrivate *priv = conn->privateData;
    char *datastoreName = NULL;
    char *directoryAndFileName = NULL;
    char *key = NULL;

    if (esxUtil_ParseDatastorePath(path, &datastoreName, NULL,
                                   &directoryAndFileName) < 0) {
        goto cleanup;
    }

    if (esxVI_LookupStorageVolumeKeyByDatastorePath(priv->primary, path,
                                                    &key) < 0) {
        goto cleanup;
    }

    volume = virGetStorageVol(conn, datastoreName, directoryAndFileName, key,
                              &esxStorageBackendVMFS, NULL);

 cleanup:
    VIR_FREE(datastoreName);
    VIR_FREE(directoryAndFileName);
    VIR_FREE(key);

    return volume;
}
示例#3
0
virStorageVolPtr
parallelsStorageVolLookupByPathLocked(virConnectPtr conn, const char *path)
{
    parallelsConnPtr privconn = conn->privateData;
    size_t i;
    virStorageVolPtr ret = NULL;

    for (i = 0; i < privconn->pools.count; i++) {
        virStoragePoolObjLock(privconn->pools.objs[i]);
        if (virStoragePoolObjIsActive(privconn->pools.objs[i])) {
            virStorageVolDefPtr privvol =
                virStorageVolDefFindByPath(privconn->pools.objs[i], path);

            if (privvol) {
                ret = virGetStorageVol(conn,
                                       privconn->pools.objs[i]->def->name,
                                       privvol->name, privvol->key,
                                       NULL, NULL);
                virStoragePoolObjUnlock(privconn->pools.objs[i]);
                break;
            }
        }
        virStoragePoolObjUnlock(privconn->pools.objs[i]);
    }

    if (!ret)
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching path '%s'"), path);

    return ret;
}
static virStorageVolPtr
esxStorageVolLookupByKey(virConnectPtr conn, const char *key)
{
    virStorageVolPtr volume = NULL;
    esxPrivate *priv = conn->storagePrivateData;
    char *poolName = NULL;
    esxVI_ScsiLun *scsiLunList = NULL;
    esxVI_ScsiLun *scsiLun;
    /* MD5_DIGEST_SIZE = VIR_UUID_BUFLEN = 16 */
    unsigned char md5[MD5_DIGEST_SIZE];
    char uuid_string[VIR_UUID_STRING_BUFLEN] = "";

    /* key may be LUN device path */
    if (STRPREFIX(key, "/")) {
        return esxStorageVolLookupByPath(conn, key);
    }

    if (esxVI_LookupScsiLunList(priv->primary, &scsiLunList) < 0) {
        goto cleanup;
    }

    for (scsiLun = scsiLunList; scsiLun;
         scsiLun = scsiLun->_next) {
        memset(uuid_string, '\0', sizeof(uuid_string));
        memset(md5, '\0', sizeof(md5));

        md5_buffer(scsiLun->uuid, strlen(scsiLun->uuid), md5);
        virUUIDFormat(md5, uuid_string);

        if (STREQ(key, uuid_string)) {
            /* Found matching UUID */
            VIR_FREE(poolName);

            if (esxVI_LookupStoragePoolNameByScsiLunKey(priv->primary,
                                                        scsiLun->key,
                                                        &poolName) < 0) {
                goto cleanup;
            }

            volume = virGetStorageVol(conn, poolName, scsiLun->deviceName,
                                      uuid_string, &esxStorageBackendISCSI,
                                      NULL);
            break;
        }
    }

 cleanup:
    esxVI_ScsiLun_Free(&scsiLunList);
    VIR_FREE(poolName);

    return volume;
}
static virStorageVolPtr
esxStorageVolLookupByPath(virConnectPtr conn, const char *path)
{
    virStorageVolPtr volume = NULL;
    esxPrivate *priv = conn->storagePrivateData;
    esxVI_ScsiLun *scsiLunList = NULL;
    esxVI_ScsiLun *scsiLun;
    esxVI_HostScsiDisk *hostScsiDisk = NULL;
    char *poolName = NULL;
    /* MD5_DIGEST_SIZE = VIR_UUID_BUFLEN = 16 */
    unsigned char md5[MD5_DIGEST_SIZE];
    char uuid_string[VIR_UUID_STRING_BUFLEN] = "";

    if (esxVI_LookupScsiLunList(priv->primary, &scsiLunList) < 0) {
        goto cleanup;
    }

    for (scsiLun = scsiLunList; scsiLun; scsiLun = scsiLun->_next) {
        hostScsiDisk = esxVI_HostScsiDisk_DynamicCast(scsiLun);

        if (hostScsiDisk && STREQ(hostScsiDisk->devicePath, path)) {
            /* Found matching device */
            VIR_FREE(poolName);

            if (esxVI_LookupStoragePoolNameByScsiLunKey(priv->primary,
                                                        hostScsiDisk->key,
                                                        &poolName) < 0) {
                goto cleanup;
            }

            md5_buffer(scsiLun->uuid, strlen(scsiLun->uuid), md5);
            virUUIDFormat(md5, uuid_string);

            volume = virGetStorageVol(conn, poolName, path, uuid_string,
                                      &esxStorageBackendISCSI, NULL);
            break;
        }
    }

 cleanup:
    esxVI_ScsiLun_Free(&scsiLunList);
    VIR_FREE(poolName);

    return volume;
}
static virStorageVolPtr
esxStorageVolLookupByName(virStoragePoolPtr pool,
                          const char *name)
{
    virStorageVolPtr volume = NULL;
    esxPrivate *priv = pool->conn->storagePrivateData;
    esxVI_ScsiLun *scsiLunList = NULL;
    esxVI_ScsiLun *scsiLun;
    /* MD5_DIGEST_SIZE = VIR_UUID_BUFLEN = 16 */
    unsigned char md5[MD5_DIGEST_SIZE];
    char uuid_string[VIR_UUID_STRING_BUFLEN] = "";

    if (esxVI_LookupScsiLunList(priv->primary, &scsiLunList) < 0) {
        goto cleanup;
    }

    for (scsiLun = scsiLunList; scsiLun;
         scsiLun = scsiLun->_next) {
        if (STREQ(scsiLun->deviceName, name)) {
            /*
             * ScsiLun provides an UUID field that is unique accross
             * multiple servers. But this field length is ~55 characters
             * compute MD5 hash to transform it to an acceptable
             * libvirt format
             */
            md5_buffer(scsiLun->uuid, strlen(scsiLun->uuid), md5);
            virUUIDFormat(md5, uuid_string);

            /*
             * ScsiLun provides displayName and canonicalName but both are
             * optional and its observed that they can be NULL, using
             * deviceName to create volume.
             */
            volume = virGetStorageVol(pool->conn, pool->name, name, uuid_string,
                                      &esxStorageBackendISCSI, NULL);
            break;
        }
    }

 cleanup:
    esxVI_ScsiLun_Free(&scsiLunList);

    return volume;
}
示例#7
0
static virStorageVolPtr
parallelsStorageVolLookupByName(virStoragePoolPtr pool,
                                   const char *name)
{
    parallelsConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol;
    virStorageVolPtr ret = NULL;

    parallelsDriverLock(privconn);
    privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name);
    parallelsDriverUnlock(privconn);

    if (privpool == NULL) {
        parallelsPoolNotFoundError(pool->name);
        goto cleanup;
    }


    if (!virStoragePoolObjIsActive(privpool)) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
        goto cleanup;
    }

    privvol = virStorageVolDefFindByName(privpool, name);

    if (!privvol) {
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"), name);
        goto cleanup;
    }

    ret = virGetStorageVol(pool->conn, privpool->def->name,
                           privvol->name, privvol->key,
                           NULL, NULL);

 cleanup:
    if (privpool)
        virStoragePoolObjUnlock(privpool);
    return ret;
}
示例#8
0
static virStorageVolPtr
parallelsStorageVolCreateXML(virStoragePoolPtr pool,
                                const char *xmldesc, unsigned int flags)
{
    parallelsConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolPtr ret = NULL;
    virStorageVolDefPtr privvol = NULL;

    virCheckFlags(0, NULL);

    parallelsDriverLock(privconn);
    privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name);
    parallelsDriverUnlock(privconn);

    if (privpool == NULL) {
        parallelsPoolNotFoundError(pool->name);
        goto cleanup;
    }

    if (!virStoragePoolObjIsActive(privpool)) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
        goto cleanup;
    }

    privvol = parallelsStorageVolDefineXML(privpool, xmldesc, NULL, true);
    if (!privvol)
        goto cleanup;

    ret = virGetStorageVol(pool->conn, privpool->def->name,
                           privvol->name, privvol->key,
                           NULL, NULL);
 cleanup:
    if (privpool)
        virStoragePoolObjUnlock(privpool);
    return ret;
}
示例#9
0
static virStorageVolPtr
esxStorageVolCreateXML(virStoragePoolPtr pool,
                       const char *xmldesc,
                       unsigned int flags)
{
    virStorageVolPtr volume = NULL;
    esxPrivate *priv = pool->conn->privateData;
    virStoragePoolDef poolDef;
    virStorageVolDefPtr def = NULL;
    char *tmp;
    char *unescapedDatastorePath = NULL;
    char *unescapedDirectoryName = NULL;
    char *unescapedDirectoryAndFileName = NULL;
    char *directoryName = NULL;
    char *fileName = NULL;
    char *datastorePathWithoutFileName = NULL;
    char *datastorePath = NULL;
    esxVI_FileInfo *fileInfo = NULL;
    esxVI_FileBackedVirtualDiskSpec *virtualDiskSpec = NULL;
    esxVI_ManagedObjectReference *task = NULL;
    esxVI_TaskInfoState taskInfoState;
    char *taskInfoErrorMessage = NULL;
    char *uuid_string = NULL;
    char *key = NULL;

    virCheckFlags(0, NULL);

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

    if (esxLookupVMFSStoragePoolType(priv->primary, pool->name,
                                     &poolDef.type) < 0) {
        goto cleanup;
    }

    /* Parse config */
    def = virStorageVolDefParseString(&poolDef, xmldesc);

    if (!def)
        goto cleanup;

    if (def->type != VIR_STORAGE_VOL_FILE) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Creating non-file volumes is not supported"));
        goto cleanup;
    }

    /* Validate config */
    tmp = strrchr(def->name, '/');

    if (!tmp || *def->name == '/' || tmp[1] == '\0') {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Volume name '%s' doesn't have expected format "
                         "'<directory>/<file>'"), def->name);
        goto cleanup;
    }

    if (! virFileHasSuffix(def->name, ".vmdk")) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Volume name '%s' has unsupported suffix, "
                         "expecting '.vmdk'"), def->name);
        goto cleanup;
    }

    if (virAsprintf(&unescapedDatastorePath, "[%s] %s", pool->name,
                    def->name) < 0)
        goto cleanup;

    if (def->target.format == VIR_STORAGE_FILE_VMDK) {
        /* Parse and escape datastore path */
        if (esxUtil_ParseDatastorePath(unescapedDatastorePath, NULL,
                                       &unescapedDirectoryName,
                                       &unescapedDirectoryAndFileName) < 0) {
            goto cleanup;
        }

        directoryName = esxUtil_EscapeDatastoreItem(unescapedDirectoryName);

        if (!directoryName)
            goto cleanup;

        fileName = esxUtil_EscapeDatastoreItem(unescapedDirectoryAndFileName +
                                               strlen(unescapedDirectoryName) + 1);

        if (!fileName)
            goto cleanup;

        if (virAsprintf(&datastorePathWithoutFileName, "[%s] %s", pool->name,
                        directoryName) < 0)
            goto cleanup;

        if (virAsprintf(&datastorePath, "[%s] %s/%s", pool->name, directoryName,
                        fileName) < 0)
            goto cleanup;

        /* Create directory, if it doesn't exist yet */
        if (esxVI_LookupFileInfoByDatastorePath
              (priv->primary, datastorePathWithoutFileName, true, &fileInfo,
               esxVI_Occurrence_OptionalItem) < 0) {
            goto cleanup;
        }

        if (!fileInfo) {
            if (esxVI_MakeDirectory(priv->primary, datastorePathWithoutFileName,
                                    priv->primary->datacenter->_reference,
                                    esxVI_Boolean_True) < 0) {
                goto cleanup;
            }
        }

        /* Create VirtualDisk */
        if (esxVI_FileBackedVirtualDiskSpec_Alloc(&virtualDiskSpec) < 0 ||
            esxVI_Long_Alloc(&virtualDiskSpec->capacityKb) < 0) {
            goto cleanup;
        }

        /* From the vSphere API documentation about VirtualDiskType ... */
        if (def->target.allocation == def->target.capacity) {
            /*
             * "A preallocated disk has all space allocated at creation time
             *  and the space is zeroed on demand as the space is used."
             */
            virtualDiskSpec->diskType = (char *)"preallocated";
        } else if (def->target.allocation == 0) {
            /*
             * "Space required for thin-provisioned virtual disk is allocated
             *  and zeroed on demand as the space is used."
             */
            virtualDiskSpec->diskType = (char *)"thin";
        } else {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("Unsupported capacity-to-allocation relation"));
            goto cleanup;
        }

        /*
         * FIXME: The adapter type is a required parameter, but there is no
         * way to let the user specify it in the volume XML config. Therefore,
         * default to 'busLogic' here.
         */
        virtualDiskSpec->adapterType = (char *)"busLogic";

        virtualDiskSpec->capacityKb->value =
          VIR_DIV_UP(def->target.capacity, 1024); /* Scale from byte to kilobyte */

        if (esxVI_CreateVirtualDisk_Task
              (priv->primary, datastorePath,
               priv->primary->datacenter->_reference,
               esxVI_VirtualDiskSpec_DynamicCast(virtualDiskSpec), &task) < 0 ||
            esxVI_WaitForTaskCompletion(priv->primary, task, NULL,
                                        esxVI_Occurrence_None,
                                        priv->parsedUri->autoAnswer,
                                        &taskInfoState,
                                        &taskInfoErrorMessage) < 0) {
            goto cleanup;
        }

        if (taskInfoState != esxVI_TaskInfoState_Success) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Could not create volume: %s"),
                           taskInfoErrorMessage);
            goto cleanup;
        }

        if (priv->primary->hasQueryVirtualDiskUuid) {
            if (VIR_ALLOC_N(key, VIR_UUID_STRING_BUFLEN) < 0)
                goto cleanup;

            if (esxVI_QueryVirtualDiskUuid(priv->primary, datastorePath,
                                           priv->primary->datacenter->_reference,
                                           &uuid_string) < 0) {
                goto cleanup;
            }

            if (esxUtil_ReformatUuid(uuid_string, key) < 0)
                goto cleanup;
        } else {
            /* Fall back to the path as key */
            if (VIR_STRDUP(key, datastorePath) < 0)
                goto cleanup;
        }
    } else {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Creation of %s volumes is not supported"),
                       virStorageFileFormatTypeToString(def->target.format));
        goto cleanup;
    }

    volume = virGetStorageVol(pool->conn, pool->name, def->name, key,
                              &esxStorageBackendVMFS, NULL);

 cleanup:
    if (virtualDiskSpec) {
        virtualDiskSpec->diskType = NULL;
        virtualDiskSpec->adapterType = NULL;
    }

    virStorageVolDefFree(def);
    VIR_FREE(unescapedDatastorePath);
    VIR_FREE(unescapedDirectoryName);
    VIR_FREE(unescapedDirectoryAndFileName);
    VIR_FREE(directoryName);
    VIR_FREE(fileName);
    VIR_FREE(datastorePathWithoutFileName);
    VIR_FREE(datastorePath);
    esxVI_FileInfo_Free(&fileInfo);
    esxVI_FileBackedVirtualDiskSpec_Free(&virtualDiskSpec);
    esxVI_ManagedObjectReference_Free(&task);
    VIR_FREE(taskInfoErrorMessage);
    VIR_FREE(uuid_string);
    VIR_FREE(key);

    return volume;
}
示例#10
0
static virStorageVolPtr
esxStorageVolLookupByKey(virConnectPtr conn, const char *key)
{
    virStorageVolPtr volume = NULL;
    esxPrivate *priv = conn->privateData;
    esxVI_String *propertyNameList = NULL;
    esxVI_ObjectContent *datastoreList = NULL;
    esxVI_ObjectContent *datastore = NULL;
    char *datastoreName = NULL;
    esxVI_HostDatastoreBrowserSearchResults *searchResultsList = NULL;
    esxVI_HostDatastoreBrowserSearchResults *searchResults = NULL;
    char *directoryAndFileName = NULL;
    size_t length;
    char *datastorePath = NULL;
    char *volumeName = NULL;
    esxVI_FileInfo *fileInfo = NULL;
    char *uuid_string = NULL;
    char key_candidate[VIR_UUID_STRING_BUFLEN] = "";

    if (STRPREFIX(key, "[")) {
        /* Key is probably a datastore path */
        return esxStorageVolLookupByPath(conn, key);
    }

    if (!priv->primary->hasQueryVirtualDiskUuid) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("QueryVirtualDiskUuid not available, "
                         "cannot lookup storage volume by UUID"));
        return NULL;
    }

    /* Lookup all datastores */
    if (esxVI_String_AppendValueToList(&propertyNameList, "summary.name") < 0 ||
        esxVI_LookupDatastoreList(priv->primary, propertyNameList,
                                  &datastoreList) < 0) {
        goto cleanup;
    }

    for (datastore = datastoreList; datastore;
         datastore = datastore->_next) {
        datastoreName = NULL;

        if (esxVI_GetStringValue(datastore, "summary.name", &datastoreName,
                                 esxVI_Occurrence_RequiredItem) < 0) {
            goto cleanup;
        }

        /* Lookup datastore content */
        esxVI_HostDatastoreBrowserSearchResults_Free(&searchResultsList);

        if (esxVI_LookupDatastoreContentByDatastoreName
              (priv->primary, datastoreName, &searchResultsList) < 0) {
            goto cleanup;
        }

        /* Interpret search result */
        for (searchResults = searchResultsList; searchResults;
             searchResults = searchResults->_next) {
            VIR_FREE(directoryAndFileName);

            if (esxUtil_ParseDatastorePath(searchResults->folderPath, NULL,
                                           NULL, &directoryAndFileName) < 0) {
                goto cleanup;
            }

            /* Strip trailing separators */
            length = strlen(directoryAndFileName);

            while (length > 0 && directoryAndFileName[length - 1] == '/') {
                directoryAndFileName[length - 1] = '\0';
                --length;
            }

            /* Build datastore path and query the UUID */
            for (fileInfo = searchResults->file; fileInfo;
                 fileInfo = fileInfo->_next) {
                VIR_FREE(datastorePath);

                if (length < 1) {
                    if (VIR_STRDUP(volumeName, fileInfo->path) < 0)
                        goto cleanup;
                } else if (virAsprintf(&volumeName, "%s/%s",
                                       directoryAndFileName,
                                       fileInfo->path) < 0) {
                    goto cleanup;
                }

                if (virAsprintf(&datastorePath, "[%s] %s", datastoreName,
                                volumeName) < 0)
                    goto cleanup;

                if (!esxVI_VmDiskFileInfo_DynamicCast(fileInfo)) {
                    /* Only a VirtualDisk has a UUID */
                    continue;
                }

                VIR_FREE(uuid_string);

                if (esxVI_QueryVirtualDiskUuid
                      (priv->primary, datastorePath,
                       priv->primary->datacenter->_reference,
                       &uuid_string) < 0) {
                    goto cleanup;
                }

                if (esxUtil_ReformatUuid(uuid_string, key_candidate) < 0)
                    goto cleanup;

                if (STREQ(key, key_candidate)) {
                    /* Found matching UUID */
                    volume = virGetStorageVol(conn, datastoreName,
                                              volumeName, key,
                                              &esxStorageBackendVMFS, NULL);
                    goto cleanup;
                }
            }
        }
    }

 cleanup:
    esxVI_String_Free(&propertyNameList);
    esxVI_ObjectContent_Free(&datastoreList);
    esxVI_HostDatastoreBrowserSearchResults_Free(&searchResultsList);
    VIR_FREE(directoryAndFileName);
    VIR_FREE(datastorePath);
    VIR_FREE(volumeName);
    VIR_FREE(uuid_string);

    return volume;
}
示例#11
0
static virStorageVolPtr
esxStorageVolCreateXMLFrom(virStoragePoolPtr pool,
                           const char *xmldesc,
                           virStorageVolPtr sourceVolume,
                           unsigned int flags)
{
    virStorageVolPtr volume = NULL;
    esxPrivate *priv = pool->conn->privateData;
    virStoragePoolDef poolDef;
    char *sourceDatastorePath = NULL;
    virStorageVolDefPtr def = NULL;
    char *tmp;
    char *unescapedDatastorePath = NULL;
    char *unescapedDirectoryName = NULL;
    char *unescapedDirectoryAndFileName = NULL;
    char *directoryName = NULL;
    char *fileName = NULL;
    char *datastorePathWithoutFileName = NULL;
    char *datastorePath = NULL;
    esxVI_FileInfo *fileInfo = NULL;
    esxVI_ManagedObjectReference *task = NULL;
    esxVI_TaskInfoState taskInfoState;
    char *taskInfoErrorMessage = NULL;
    char *uuid_string = NULL;
    char *key = NULL;

    virCheckFlags(0, NULL);

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

    if (esxLookupVMFSStoragePoolType(priv->primary, pool->name,
                                     &poolDef.type) < 0) {
        goto cleanup;
    }

    if (virAsprintf(&sourceDatastorePath, "[%s] %s", sourceVolume->pool,
                    sourceVolume->name) < 0)
        goto cleanup;

    /* Parse config */
    def = virStorageVolDefParseString(&poolDef, xmldesc);

    if (!def)
        goto cleanup;

    if (def->type != VIR_STORAGE_VOL_FILE) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Creating non-file volumes is not supported"));
        goto cleanup;
    }

    /* Validate config */
    tmp = strrchr(def->name, '/');

    if (!tmp || *def->name == '/' || tmp[1] == '\0') {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Volume name '%s' doesn't have expected format "
                         "'<directory>/<file>'"), def->name);
        goto cleanup;
    }

    if (! virFileHasSuffix(def->name, ".vmdk")) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Volume name '%s' has unsupported suffix, "
                         "expecting '.vmdk'"), def->name);
        goto cleanup;
    }

    if (virAsprintf(&unescapedDatastorePath, "[%s] %s", pool->name,
                    def->name) < 0)
        goto cleanup;

    if (def->target.format == VIR_STORAGE_FILE_VMDK) {
        /* Parse and escape datastore path */
        if (esxUtil_ParseDatastorePath(unescapedDatastorePath, NULL,
                                       &unescapedDirectoryName,
                                       &unescapedDirectoryAndFileName) < 0) {
            goto cleanup;
        }

        directoryName = esxUtil_EscapeDatastoreItem(unescapedDirectoryName);

        if (!directoryName)
            goto cleanup;

        fileName = esxUtil_EscapeDatastoreItem(unescapedDirectoryAndFileName +
                                               strlen(unescapedDirectoryName) + 1);

        if (!fileName)
            goto cleanup;

        if (virAsprintf(&datastorePathWithoutFileName, "[%s] %s", pool->name,
                        directoryName) < 0)
            goto cleanup;

        if (virAsprintf(&datastorePath, "[%s] %s/%s", pool->name, directoryName,
                        fileName) < 0)
            goto cleanup;

        /* Create directory, if it doesn't exist yet */
        if (esxVI_LookupFileInfoByDatastorePath
              (priv->primary, datastorePathWithoutFileName, true, &fileInfo,
               esxVI_Occurrence_OptionalItem) < 0) {
            goto cleanup;
        }

        if (!fileInfo) {
            if (esxVI_MakeDirectory(priv->primary, datastorePathWithoutFileName,
                                    priv->primary->datacenter->_reference,
                                    esxVI_Boolean_True) < 0) {
                goto cleanup;
            }
        }

        /* Copy VirtualDisk */
        if (esxVI_CopyVirtualDisk_Task(priv->primary, sourceDatastorePath,
                                       priv->primary->datacenter->_reference,
                                       datastorePath,
                                       priv->primary->datacenter->_reference,
                                       NULL, esxVI_Boolean_False, &task) < 0 ||
            esxVI_WaitForTaskCompletion(priv->primary, task, NULL,
                                        esxVI_Occurrence_None,
                                        priv->parsedUri->autoAnswer,
                                        &taskInfoState,
                                        &taskInfoErrorMessage) < 0) {
            goto cleanup;
        }

        if (taskInfoState != esxVI_TaskInfoState_Success) {
            virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not copy volume: %s"),
                           taskInfoErrorMessage);
            goto cleanup;
        }

        if (priv->primary->hasQueryVirtualDiskUuid) {
            if (VIR_ALLOC_N(key, VIR_UUID_STRING_BUFLEN) < 0)
                goto cleanup;

            if (esxVI_QueryVirtualDiskUuid(priv->primary, datastorePath,
                                           priv->primary->datacenter->_reference,
                                           &uuid_string) < 0) {
                goto cleanup;
            }

            if (esxUtil_ReformatUuid(uuid_string, key) < 0)
                goto cleanup;
        } else {
            /* Fall back to the path as key */
            if (VIR_STRDUP(key, datastorePath) < 0)
                goto cleanup;
        }
    } else {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Creation of %s volumes is not supported"),
                       virStorageFileFormatTypeToString(def->target.format));
        goto cleanup;
    }

    volume = virGetStorageVol(pool->conn, pool->name, def->name, key,
                              &esxStorageBackendVMFS, NULL);

 cleanup:
    VIR_FREE(sourceDatastorePath);
    virStorageVolDefFree(def);
    VIR_FREE(unescapedDatastorePath);
    VIR_FREE(unescapedDirectoryName);
    VIR_FREE(unescapedDirectoryAndFileName);
    VIR_FREE(directoryName);
    VIR_FREE(fileName);
    VIR_FREE(datastorePathWithoutFileName);
    VIR_FREE(datastorePath);
    esxVI_FileInfo_Free(&fileInfo);
    esxVI_ManagedObjectReference_Free(&task);
    VIR_FREE(taskInfoErrorMessage);
    VIR_FREE(uuid_string);
    VIR_FREE(key);

    return volume;
}
示例#12
0
static virStorageVolPtr
vboxStorageVolCreateXML(virStoragePoolPtr pool,
                        const char *xml, unsigned int flags)
{
    vboxDriverPtr data = pool->conn->privateData;
    virStorageVolDefPtr def = NULL;
    PRUnichar *hddFormatUtf16 = NULL;
    PRUnichar *hddNameUtf16 = NULL;
    virStoragePoolDef poolDef;
    nsresult rc;
    vboxIID hddIID;
    unsigned char uuid[VIR_UUID_BUFLEN];
    char key[VIR_UUID_STRING_BUFLEN] = "";
    IMedium *hardDisk = NULL;
    IProgress *progress = NULL;
    PRUint64 logicalSize = 0;
    PRUint32 variant = HardDiskVariant_Standard;
    resultCodeUnion resultCode;
    virStorageVolPtr ret = NULL;

    if (!data->vboxObj)
        return ret;

    virCheckFlags(0, NULL);

    /* since there is currently one default pool now
     * and virStorageVolDefFormat() just checks it type
     * so just assign it for now, change the behaviour
     * when vbox supports pools.
     */
    memset(&poolDef, 0, sizeof(poolDef));
    poolDef.type = VIR_STORAGE_POOL_DIR;

    if ((def = virStorageVolDefParseString(&poolDef, xml, 0)) == NULL)
        goto cleanup;

    if (!def->name ||
        (def->type != VIR_STORAGE_VOL_FILE))
        goto cleanup;

    /* For now only the vmdk, vpc and vdi type harddisk
     * variants can be created.  For historical reason, we default to vdi */
    if (def->target.format == VIR_STORAGE_FILE_VMDK) {
        VBOX_UTF8_TO_UTF16("VMDK", &hddFormatUtf16);
    } else if (def->target.format == VIR_STORAGE_FILE_VPC) {
        VBOX_UTF8_TO_UTF16("VHD", &hddFormatUtf16);
    } else {
        VBOX_UTF8_TO_UTF16("VDI", &hddFormatUtf16);
    }

    /* If target.path isn't given, use default path ~/.VirtualBox/image_name */
    if (def->target.path == NULL &&
        virAsprintf(&def->target.path, "%s/.VirtualBox/%s", virGetUserDirectory(), def->name) < 0)
        goto cleanup;
    VBOX_UTF8_TO_UTF16(def->target.path, &hddNameUtf16);

    if (!hddFormatUtf16 || !hddNameUtf16)
        goto cleanup;

    rc = gVBoxAPI.UIVirtualBox.CreateHardDisk(data->vboxObj, hddFormatUtf16, hddNameUtf16, &hardDisk);
    if (NS_FAILED(rc)) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Could not create harddisk, rc=%08x"),
                       (unsigned)rc);
        goto cleanup;
    }

    logicalSize = VIR_DIV_UP(def->target.capacity, 1024 * 1024);

    if (def->target.capacity == def->target.allocation)
        variant = HardDiskVariant_Fixed;

    rc = gVBoxAPI.UIMedium.CreateBaseStorage(hardDisk, logicalSize, variant, &progress);
    if (NS_FAILED(rc) || !progress) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Could not create base storage, rc=%08x"),
                       (unsigned)rc);
        goto cleanup;
    }

    gVBoxAPI.UIProgress.WaitForCompletion(progress, -1);
    gVBoxAPI.UIProgress.GetResultCode(progress, &resultCode);
    if (RC_FAILED(resultCode)) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Could not create base storage, rc=%08x"),
                       (unsigned)resultCode.uResultCode);
        goto cleanup;
    }

    VBOX_IID_INITIALIZE(&hddIID);
    rc = gVBoxAPI.UIMedium.GetId(hardDisk, &hddIID);
    if (NS_FAILED(rc))
        goto cleanup;

    vboxIIDToUUID(&hddIID, uuid);
    virUUIDFormat(uuid, key);

    ret = virGetStorageVol(pool->conn, pool->name, def->name, key,
                           NULL, NULL);

 cleanup:
    vboxIIDUnalloc(&hddIID);
    VBOX_RELEASE(progress);
    VBOX_UTF16_FREE(hddFormatUtf16);
    VBOX_UTF16_FREE(hddNameUtf16);
    virStorageVolDefFree(def);
    return ret;
}
示例#13
0
static virStorageVolPtr
vboxStorageVolLookupByPath(virConnectPtr conn, const char *path)
{
    vboxDriverPtr data = conn->privateData;
    PRUnichar *hddPathUtf16 = NULL;
    IMedium *hardDisk = NULL;
    PRUnichar *hddNameUtf16 = NULL;
    char *hddNameUtf8 = NULL;
    unsigned char uuid[VIR_UUID_BUFLEN];
    char key[VIR_UUID_STRING_BUFLEN] = "";
    vboxIID hddIID;
    PRUint32 hddstate;
    nsresult rc;
    virStorageVolPtr ret = NULL;

    if (!data->vboxObj)
        return ret;

    VBOX_IID_INITIALIZE(&hddIID);

    if (!path)
        return ret;

    VBOX_UTF8_TO_UTF16(path, &hddPathUtf16);

    if (!hddPathUtf16)
        return ret;

    rc = gVBoxAPI.UIVirtualBox.FindHardDisk(data->vboxObj, hddPathUtf16,
                                            DeviceType_HardDisk, AccessMode_ReadWrite, &hardDisk);
    if (NS_FAILED(rc))
        goto cleanup;

    gVBoxAPI.UIMedium.GetState(hardDisk, &hddstate);
    if (hddstate == MediaState_Inaccessible)
        goto cleanup;

    gVBoxAPI.UIMedium.GetName(hardDisk, &hddNameUtf16);

    if (!hddNameUtf16)
        goto cleanup;

    VBOX_UTF16_TO_UTF8(hddNameUtf16, &hddNameUtf8);
    VBOX_UTF16_FREE(hddNameUtf16);

    if (!hddNameUtf8)
        goto cleanup;

    rc = gVBoxAPI.UIMedium.GetId(hardDisk, &hddIID);
    if (NS_FAILED(rc)) {
        VBOX_UTF8_FREE(hddNameUtf8);
        goto cleanup;
    }

    vboxIIDToUUID(&hddIID, uuid);
    virUUIDFormat(uuid, key);

    /* TODO: currently only one default pool and thus
     * the check below, change it when pools are supported
     */
    if (vboxConnectNumOfStoragePools(conn) == 1)
        ret = virGetStorageVol(conn, "default-pool", hddNameUtf8, key,
                               NULL, NULL);

    VIR_DEBUG("Storage Volume Pool: %s", "default-pool");
    VIR_DEBUG("Storage Volume Name: %s", hddNameUtf8);
    VIR_DEBUG("Storage Volume key : %s", key);

    vboxIIDUnalloc(&hddIID);
    VBOX_UTF8_FREE(hddNameUtf8);

 cleanup:
    VBOX_MEDIUM_RELEASE(hardDisk);
    VBOX_UTF16_FREE(hddPathUtf16);
    return ret;
}
示例#14
0
static virStorageVolPtr
vboxStorageVolLookupByKey(virConnectPtr conn, const char *key)
{
    vboxDriverPtr data = conn->privateData;
    vboxIID hddIID;
    unsigned char uuid[VIR_UUID_BUFLEN];
    IMedium *hardDisk = NULL;
    PRUnichar *hddNameUtf16 = NULL;
    char *hddNameUtf8 = NULL;
    PRUint32 hddstate;
    nsresult rc;
    virStorageVolPtr ret = NULL;

    if (!data->vboxObj)
        return ret;

    VBOX_IID_INITIALIZE(&hddIID);
    if (!key)
        return ret;

    if (virUUIDParse(key, uuid) < 0) {
        virReportError(VIR_ERR_INVALID_ARG,
                       _("Could not parse UUID from '%s'"), key);
        return NULL;
    }

    vboxIIDFromUUID(&hddIID, uuid);
    rc = gVBoxAPI.UIVirtualBox.GetHardDiskByIID(data->vboxObj, &hddIID, &hardDisk);
    if (NS_FAILED(rc))
        goto cleanup;

    gVBoxAPI.UIMedium.GetState(hardDisk, &hddstate);
    if (hddstate == MediaState_Inaccessible)
        goto cleanup;

    gVBoxAPI.UIMedium.GetName(hardDisk, &hddNameUtf16);
    if (!hddNameUtf16)
        goto cleanup;

    VBOX_UTF16_TO_UTF8(hddNameUtf16, &hddNameUtf8);
    if (!hddNameUtf8) {
        VBOX_UTF16_FREE(hddNameUtf16);
        goto cleanup;
    }

    if (vboxConnectNumOfStoragePools(conn) == 1) {
        ret = virGetStorageVol(conn, "default-pool", hddNameUtf8, key,
                               NULL, NULL);
        VIR_DEBUG("Storage Volume Pool: %s", "default-pool");
    } else {
        /* TODO: currently only one default pool and thus
         * nothing here, change it when pools are supported
         */
    }

    VIR_DEBUG("Storage Volume Name: %s", key);
    VIR_DEBUG("Storage Volume key : %s", hddNameUtf8);

    VBOX_UTF8_FREE(hddNameUtf8);
    VBOX_UTF16_FREE(hddNameUtf16);

 cleanup:
    VBOX_MEDIUM_RELEASE(hardDisk);
    vboxIIDUnalloc(&hddIID);
    return ret;
}
示例#15
0
static virStorageVolPtr
vboxStorageVolLookupByName(virStoragePoolPtr pool, const char *name)
{
    vboxDriverPtr data = pool->conn->privateData;
    vboxArray hardDisks = VBOX_ARRAY_INITIALIZER;
    nsresult rc;
    size_t i;
    virStorageVolPtr ret = NULL;

    if (!data->vboxObj)
        return ret;

    if (!name)
        return ret;

    rc = gVBoxAPI.UArray.vboxArrayGet(&hardDisks, data->vboxObj,
                                      gVBoxAPI.UArray.handleGetHardDisks(data->vboxObj));
    if (NS_FAILED(rc))
        return ret;

    for (i = 0; i < hardDisks.count; ++i) {
        IMedium *hardDisk = hardDisks.items[i];
        PRUint32 hddstate;
        char *nameUtf8 = NULL;
        PRUnichar *nameUtf16 = NULL;

        if (!hardDisk)
            continue;

        gVBoxAPI.UIMedium.GetState(hardDisk, &hddstate);
        if (hddstate == MediaState_Inaccessible)
            continue;

        gVBoxAPI.UIMedium.GetName(hardDisk, &nameUtf16);

        if (nameUtf16) {
            VBOX_UTF16_TO_UTF8(nameUtf16, &nameUtf8);
            VBOX_UTF16_FREE(nameUtf16);
        }

        if (nameUtf8 && STREQ(nameUtf8, name)) {
            vboxIID hddIID;
            unsigned char uuid[VIR_UUID_BUFLEN];
            char key[VIR_UUID_STRING_BUFLEN] = "";

            VBOX_IID_INITIALIZE(&hddIID);
            rc = gVBoxAPI.UIMedium.GetId(hardDisk, &hddIID);
            if (NS_SUCCEEDED(rc)) {
                vboxIIDToUUID(&hddIID, uuid);
                virUUIDFormat(uuid, key);

                ret = virGetStorageVol(pool->conn, pool->name, name, key,
                                       NULL, NULL);

                VIR_DEBUG("virStorageVolPtr: %p", ret);
                VIR_DEBUG("Storage Volume Name: %s", name);
                VIR_DEBUG("Storage Volume key : %s", key);
                VIR_DEBUG("Storage Volume Pool: %s", pool->name);
            }

            vboxIIDUnalloc(&hddIID);
            VBOX_UTF8_FREE(nameUtf8);
            break;
        }

        VBOX_UTF8_FREE(nameUtf8);
    }

    gVBoxAPI.UArray.vboxArrayRelease(&hardDisks);

    return ret;
}
示例#16
0
static virStorageVolPtr
parallelsStorageVolCreateXMLFrom(virStoragePoolPtr pool,
                                    const char *xmldesc,
                                    virStorageVolPtr clonevol,
                                    unsigned int flags)
{
    parallelsConnPtr privconn = pool->conn->privateData;
    virStoragePoolObjPtr privpool;
    virStorageVolDefPtr privvol = NULL, origvol = NULL;
    virStorageVolPtr ret = NULL;

    virCheckFlags(0, NULL);

    parallelsDriverLock(privconn);
    privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name);
    parallelsDriverUnlock(privconn);

    if (privpool == NULL) {
        parallelsPoolNotFoundError(pool->name);
        goto cleanup;
    }

    if (!virStoragePoolObjIsActive(privpool)) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->name);
        goto cleanup;
    }

    privvol = virStorageVolDefParseString(privpool->def, xmldesc);
    if (privvol == NULL)
        goto cleanup;

    if (virStorageVolDefFindByName(privpool, privvol->name)) {
        virReportError(VIR_ERR_OPERATION_FAILED,
                       "%s", _("storage vol already exists"));
        goto cleanup;
    }

    origvol = virStorageVolDefFindByName(privpool, clonevol->name);
    if (!origvol) {
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       clonevol->name);
        goto cleanup;
    }

    /* Make sure enough space */
    if ((privpool->def->allocation + privvol->target.allocation) >
        privpool->def->capacity) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Not enough free space in pool for volume '%s'"),
                       privvol->name);
        goto cleanup;
    }
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

    if (virAsprintf(&privvol->target.path, "%s/%s",
                    privpool->def->target.path, privvol->name) == -1)
        goto cleanup;

    if (VIR_STRDUP(privvol->key, privvol->target.path) < 0)
        goto cleanup;

    privpool->def->allocation += privvol->target.allocation;
    privpool->def->available = (privpool->def->capacity -
                                privpool->def->allocation);

    if (VIR_APPEND_ELEMENT_COPY(privpool->volumes.objs,
                                privpool->volumes.count, privvol) < 0)
        goto cleanup;

    ret = virGetStorageVol(pool->conn, privpool->def->name,
                           privvol->name, privvol->key,
                           NULL, NULL);
    privvol = NULL;

 cleanup:
    virStorageVolDefFree(privvol);
    if (privpool)
        virStoragePoolObjUnlock(privpool);
    return ret;
}