static int test_vdi_list_parser(collie_test test, char *poolxml, char *volxml) { int ret = -1; char *poolXmlData = NULL; char *volXmlData = NULL; char *output = NULL; virStoragePoolDefPtr pool = NULL; virStorageVolDefPtr vol = NULL; if (virtTestLoadFile(poolxml, &poolXmlData) < 0) goto cleanup; if (virtTestLoadFile(volxml, &volXmlData) < 0) goto cleanup; if (!(pool = virStoragePoolDefParseString(poolXmlData))) goto cleanup; if (!(vol = virStorageVolDefParseString(pool, volXmlData))) goto cleanup; output = strdup(test.output); if (!output) goto cleanup; if (virStorageBackendSheepdogParseVdiList(vol, output) != test.expected_return) goto cleanup; if (test.expected_return) { ret = 0; goto cleanup; } if (vol->capacity == test.expected_capacity && vol->allocation == test.expected_allocation) ret = 0; cleanup: VIR_FREE(output); VIR_FREE(poolXmlData); VIR_FREE(volXmlData); virStoragePoolDefFree(pool); virStorageVolDefFree(vol); return ret; }
static int testCompareXMLToXMLFiles(const char *poolxml, const char *inxml, const char *outxml) { char *poolXmlData = NULL; char *inXmlData = NULL; char *outXmlData = NULL; char *actual = NULL; int ret = -1; virStoragePoolDefPtr pool = NULL; virStorageVolDefPtr dev = NULL; if (virtTestLoadFile(poolxml, &poolXmlData) < 0) goto fail; if (virtTestLoadFile(inxml, &inXmlData) < 0) goto fail; if (virtTestLoadFile(outxml, &outXmlData) < 0) goto fail; if (!(pool = virStoragePoolDefParseString(poolXmlData))) goto fail; if (!(dev = virStorageVolDefParseString(pool, inXmlData))) goto fail; if (!(actual = virStorageVolDefFormat(pool, dev))) goto fail; if (STRNEQ(outXmlData, actual)) { virtTestDifference(stderr, outXmlData, actual); goto fail; } ret = 0; fail: VIR_FREE(poolXmlData); VIR_FREE(inXmlData); VIR_FREE(outXmlData); VIR_FREE(actual); virStoragePoolDefFree(pool); virStorageVolDefFree(dev); return ret; }
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; }
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; }
static int testCompareXMLToArgvFiles(bool shouldFail, const char *poolxml, const char *volxml, const char *inputpoolxml, const char *inputvolxml, const char *cmdline, unsigned int flags, int imgformat) { char *volXmlData = NULL; char *poolXmlData = NULL; char *inputpoolXmlData = NULL; char *inputvolXmlData = NULL; char *expectedCmdline = NULL; char *actualCmdline = NULL; int ret = -1; int len; virCommandPtr cmd = NULL; virConnectPtr conn; virStorageVolDefPtr vol = NULL, inputvol = NULL; virStoragePoolDefPtr pool = NULL; virStoragePoolDefPtr inputpool = NULL; virStoragePoolObj poolobj = {.def = NULL }; if (!(conn = virGetConnect())) goto cleanup; if (virtTestLoadFile(poolxml, &poolXmlData) < 0) goto cleanup; if (virtTestLoadFile(volxml, &volXmlData) < 0) goto cleanup; if (inputvolxml && virtTestLoadFile(inputvolxml, &inputvolXmlData) < 0) goto cleanup; if (!(pool = virStoragePoolDefParseString(poolXmlData))) goto cleanup; poolobj.def = pool; if (inputpoolxml) { if (virtTestLoadFile(inputpoolxml, &inputpoolXmlData) < 0) goto cleanup; if (!(inputpool = virStoragePoolDefParseString(inputpoolXmlData))) goto cleanup; } if (!(vol = virStorageVolDefParseString(pool, volXmlData))) goto cleanup; if (inputvolxml && !(inputvol = virStorageVolDefParseString(inputpool, inputvolXmlData))) goto cleanup; testSetVolumeType(vol, pool); testSetVolumeType(inputvol, inputpool); cmd = virStorageBackendCreateQemuImgCmd(conn, &poolobj, vol, inputvol, flags, create_tool, imgformat); if (!cmd) { if (shouldFail) { virResetLastError(); ret = 0; } goto cleanup; } if (!(actualCmdline = virCommandToString(cmd))) goto cleanup; len = virtTestLoadFile(cmdline, &expectedCmdline); if (len < 0) goto cleanup; if (len && expectedCmdline[len-1] == '\n') expectedCmdline[len-1] = '\0'; if (STRNEQ_NULLABLE(expectedCmdline, actualCmdline)) { virtTestDifference(stderr, expectedCmdline, actualCmdline); goto cleanup; } ret = 0; cleanup: virStoragePoolDefFree(pool); virStoragePoolDefFree(inputpool); virStorageVolDefFree(vol); virStorageVolDefFree(inputvol); virCommandFree(cmd); VIR_FREE(actualCmdline); VIR_FREE(expectedCmdline); VIR_FREE(inputpoolXmlData); VIR_FREE(poolXmlData); VIR_FREE(volXmlData); VIR_FREE(inputvolXmlData); virObjectUnref(conn); return ret; }
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; }
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; }
static virStorageVolDefPtr parallelsStorageVolDefineXML(virStoragePoolObjPtr pool, const char *xmldesc, const char *xmlfile, bool is_new) { virStorageVolDefPtr privvol = NULL; virStorageVolDefPtr ret = NULL; char *xml_path = NULL; if (xmlfile) privvol = virStorageVolDefParseFile(pool->def, xmlfile); else privvol = virStorageVolDefParseString(pool->def, xmldesc); if (privvol == NULL) goto cleanup; if (virStorageVolDefFindByName(pool, privvol->name)) { virReportError(VIR_ERR_OPERATION_FAILED, "%s", _("storage vol already exists")); goto cleanup; } if (is_new) { /* Make sure enough space */ if ((pool->def->allocation + privvol->target.allocation) > pool->def->capacity) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Not enough free space in pool for volume '%s'"), privvol->name); goto cleanup; } } if (virAsprintf(&privvol->target.path, "%s/%s", pool->def->target.path, privvol->name) < 0) goto cleanup; if (VIR_STRDUP(privvol->key, privvol->target.path) < 0) goto cleanup; if (is_new) { xml_path = parallelsAddFileExt(privvol->target.path, ".xml"); if (!xml_path) goto cleanup; if (virXMLSaveFile(xml_path, NULL, "volume-create", xmldesc)) { virReportError(VIR_ERR_OPERATION_FAILED, "%s", _("Can't create file with volume description")); goto cleanup; } pool->def->allocation += privvol->target.allocation; pool->def->available = (pool->def->capacity - pool->def->allocation); } if (VIR_APPEND_ELEMENT_COPY(pool->volumes.objs, pool->volumes.count, privvol) < 0) goto cleanup; ret = privvol; privvol = NULL; cleanup: virStorageVolDefFree(privvol); VIR_FREE(xml_path); return ret; }