mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-08-27 21:50:11 +03:00
Allow creating volumes with a backing store but no capacity
The tool creating the image can get the capacity from the backing storage. Just refresh the volume afterwards. https://bugzilla.redhat.com/show_bug.cgi?id=958510
This commit is contained in:
@ -487,6 +487,12 @@ virStorageBackendCreateRaw(virConnectPtr conn ATTRIBUTE_UNUSED,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (vol->target.backingStore) {
|
||||||
|
virReportError(VIR_ERR_NO_SUPPORT, "%s",
|
||||||
|
_("backing storage not supported for raw volumes"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
if (flags & VIR_STORAGE_VOL_CREATE_REFLINK)
|
if (flags & VIR_STORAGE_VOL_CREATE_REFLINK)
|
||||||
reflink_copy = true;
|
reflink_copy = true;
|
||||||
|
|
||||||
@ -1055,7 +1061,7 @@ virStorageBackendCreateQemuImgCmd(virConnectPtr conn,
|
|||||||
if (convert)
|
if (convert)
|
||||||
virCommandAddArg(cmd, inputPath);
|
virCommandAddArg(cmd, inputPath);
|
||||||
virCommandAddArg(cmd, vol->target.path);
|
virCommandAddArg(cmd, vol->target.path);
|
||||||
if (!convert)
|
if (!convert && size_arg)
|
||||||
virCommandAddArgFormat(cmd, "%lluK", size_arg);
|
virCommandAddArgFormat(cmd, "%lluK", size_arg);
|
||||||
|
|
||||||
return cmd;
|
return cmd;
|
||||||
|
@ -1037,6 +1037,13 @@ static int createFileDir(virConnectPtr conn ATTRIBUTE_UNUSED,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (vol->target.backingStore) {
|
||||||
|
virReportError(VIR_ERR_NO_SUPPORT, "%s",
|
||||||
|
_("backing storage not supported for directories volumes"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if ((err = virDirCreate(vol->target.path, vol->target.perms->mode,
|
if ((err = virDirCreate(vol->target.path, vol->target.perms->mode,
|
||||||
vol->target.perms->uid,
|
vol->target.perms->uid,
|
||||||
vol->target.perms->gid,
|
vol->target.perms->gid,
|
||||||
|
@ -509,6 +509,12 @@ virStorageBackendRBDBuildVol(virConnectPtr conn,
|
|||||||
|
|
||||||
virCheckFlags(0, -1);
|
virCheckFlags(0, -1);
|
||||||
|
|
||||||
|
if (!vol->target.capacity) {
|
||||||
|
virReportError(VIR_ERR_NO_SUPPORT, "%s",
|
||||||
|
_("volume capacity required for this storage pool"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
if (virStorageBackendRBDOpenRADOSConn(&ptr, conn, &pool->def->source) < 0)
|
if (virStorageBackendRBDOpenRADOSConn(&ptr, conn, &pool->def->source) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
|
@ -266,6 +266,12 @@ virStorageBackendSheepdogBuildVol(virConnectPtr conn,
|
|||||||
|
|
||||||
virCheckFlags(0, -1);
|
virCheckFlags(0, -1);
|
||||||
|
|
||||||
|
if (!vol->target.capacity) {
|
||||||
|
virReportError(VIR_ERR_NO_SUPPORT, "%s",
|
||||||
|
_("volume capacity required for this pool"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
virCommandPtr cmd = virCommandNewArgList(COLLIE, "vdi", "create", vol->name, NULL);
|
virCommandPtr cmd = virCommandNewArgList(COLLIE, "vdi", "create", vol->name, NULL);
|
||||||
virCommandAddArgFormat(cmd, "%llu", vol->target.capacity);
|
virCommandAddArgFormat(cmd, "%llu", vol->target.capacity);
|
||||||
virStorageBackendSheepdogAddHostArg(cmd, pool);
|
virStorageBackendSheepdogAddHostArg(cmd, pool);
|
||||||
|
@ -1649,10 +1649,18 @@ storageVolCreateXML(virStoragePoolPtr obj,
|
|||||||
if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
|
if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
voldef = virStorageVolDefParseString(pool->def, xmldesc, 0);
|
voldef = virStorageVolDefParseString(pool->def, xmldesc,
|
||||||
|
VIR_VOL_XML_PARSE_OPT_CAPACITY);
|
||||||
if (voldef == NULL)
|
if (voldef == NULL)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
|
if (!voldef->target.capacity && !backend->buildVol) {
|
||||||
|
virReportError(VIR_ERR_NO_SUPPORT,
|
||||||
|
"%s", _("volume capacity required for this "
|
||||||
|
"storage pool"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
if (virStorageVolCreateXMLEnsureACL(obj->conn, pool->def, voldef) < 0)
|
if (virStorageVolCreateXMLEnsureACL(obj->conn, pool->def, voldef) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
@ -1725,6 +1733,10 @@ storageVolCreateXML(virStoragePoolPtr obj,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (backend->refreshVol &&
|
||||||
|
backend->refreshVol(obj->conn, pool, voldef) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
/* Update pool metadata */
|
/* Update pool metadata */
|
||||||
pool->def->allocation += buildvoldef->target.allocation;
|
pool->def->allocation += buildvoldef->target.allocation;
|
||||||
pool->def->available -= buildvoldef->target.allocation;
|
pool->def->available -= buildvoldef->target.allocation;
|
||||||
|
5
tests/storagevolxml2argvdata/qcow2-nocapacity.argv
Normal file
5
tests/storagevolxml2argvdata/qcow2-nocapacity.argv
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
qemu-img create \
|
||||||
|
-f qcow2 \
|
||||||
|
-b /dev/null \
|
||||||
|
-o backing_fmt=raw,encryption=on \
|
||||||
|
/var/lib/libvirt/images/OtherDemo.img
|
@ -40,7 +40,8 @@ testCompareXMLToArgvFiles(bool shouldFail,
|
|||||||
const char *inputvolxml,
|
const char *inputvolxml,
|
||||||
const char *cmdline,
|
const char *cmdline,
|
||||||
unsigned int flags,
|
unsigned int flags,
|
||||||
int imgformat)
|
int imgformat,
|
||||||
|
unsigned long parse_flags)
|
||||||
{
|
{
|
||||||
char *volXmlData = NULL;
|
char *volXmlData = NULL;
|
||||||
char *poolXmlData = NULL;
|
char *poolXmlData = NULL;
|
||||||
@ -49,7 +50,6 @@ testCompareXMLToArgvFiles(bool shouldFail,
|
|||||||
char *expectedCmdline = NULL;
|
char *expectedCmdline = NULL;
|
||||||
char *actualCmdline = NULL;
|
char *actualCmdline = NULL;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
unsigned long parse_flags = 0;
|
|
||||||
|
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
@ -149,6 +149,7 @@ struct testInfo {
|
|||||||
const char *cmdline;
|
const char *cmdline;
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
int imgformat;
|
int imgformat;
|
||||||
|
unsigned long parseflags;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -183,7 +184,7 @@ testCompareXMLToArgvHelper(const void *data)
|
|||||||
result = testCompareXMLToArgvFiles(info->shouldFail, poolxml, volxml,
|
result = testCompareXMLToArgvFiles(info->shouldFail, poolxml, volxml,
|
||||||
inputpoolxml, inputvolxml,
|
inputpoolxml, inputvolxml,
|
||||||
cmdline, info->flags,
|
cmdline, info->flags,
|
||||||
info->imgformat);
|
info->imgformat, info->parseflags);
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
VIR_FREE(poolxml);
|
VIR_FREE(poolxml);
|
||||||
@ -210,11 +211,11 @@ mymain(void)
|
|||||||
int ret = 0;
|
int ret = 0;
|
||||||
unsigned int flags = VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA;
|
unsigned int flags = VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA;
|
||||||
|
|
||||||
#define DO_TEST_FULL(shouldFail, pool, vol, inputpool, inputvol, cmdline, \
|
#define DO_TEST_FULL(shouldFail, parseflags, pool, vol, inputpool, inputvol, \
|
||||||
flags, imgformat) \
|
cmdline, flags, imgformat) \
|
||||||
do { \
|
do { \
|
||||||
struct testInfo info = { shouldFail, pool, vol, inputpool, inputvol, \
|
struct testInfo info = { shouldFail, pool, vol, inputpool, inputvol, \
|
||||||
cmdline, flags, imgformat }; \
|
cmdline, flags, imgformat, parseflags }; \
|
||||||
if (virtTestRun("Storage Vol XML-2-argv " cmdline, \
|
if (virtTestRun("Storage Vol XML-2-argv " cmdline, \
|
||||||
testCompareXMLToArgvHelper, &info) < 0) \
|
testCompareXMLToArgvHelper, &info) < 0) \
|
||||||
ret = -1; \
|
ret = -1; \
|
||||||
@ -222,10 +223,10 @@ mymain(void)
|
|||||||
while (0);
|
while (0);
|
||||||
|
|
||||||
#define DO_TEST(pool, ...) \
|
#define DO_TEST(pool, ...) \
|
||||||
DO_TEST_FULL(false, pool, __VA_ARGS__)
|
DO_TEST_FULL(false, 0, pool, __VA_ARGS__)
|
||||||
|
|
||||||
#define DO_TEST_FAIL(pool, ...) \
|
#define DO_TEST_FAIL(pool, ...) \
|
||||||
DO_TEST_FULL(true, pool, __VA_ARGS__)
|
DO_TEST_FULL(true, 0, pool, __VA_ARGS__)
|
||||||
|
|
||||||
DO_TEST("pool-dir", "vol-qcow2",
|
DO_TEST("pool-dir", "vol-qcow2",
|
||||||
NULL, NULL,
|
NULL, NULL,
|
||||||
@ -312,6 +313,9 @@ mymain(void)
|
|||||||
DO_TEST("pool-dir", "vol-qcow2-nocapacity",
|
DO_TEST("pool-dir", "vol-qcow2-nocapacity",
|
||||||
"pool-dir", "vol-file",
|
"pool-dir", "vol-file",
|
||||||
"qcow2-nocapacity-convert-prealloc", flags, FMT_OPTIONS);
|
"qcow2-nocapacity-convert-prealloc", flags, FMT_OPTIONS);
|
||||||
|
DO_TEST_FULL(false, VIR_VOL_XML_PARSE_OPT_CAPACITY,
|
||||||
|
"pool-dir", "vol-qcow2-nocapacity-backing", NULL, NULL,
|
||||||
|
"qcow2-nocapacity", 0, FMT_OPTIONS);
|
||||||
|
|
||||||
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
|
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
23
tests/storagevolxml2xmlin/vol-qcow2-nocapacity-backing.xml
Normal file
23
tests/storagevolxml2xmlin/vol-qcow2-nocapacity-backing.xml
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<volume>
|
||||||
|
<name>OtherDemo.img</name>
|
||||||
|
<key>/var/lib/libvirt/images/OtherDemo.img</key>
|
||||||
|
<source>
|
||||||
|
</source>
|
||||||
|
<target>
|
||||||
|
<path>/var/lib/libvirt/images/OtherDemo.img</path>
|
||||||
|
<format type='qcow2'/>
|
||||||
|
<permissions>
|
||||||
|
<mode>0644</mode>
|
||||||
|
<owner>0</owner>
|
||||||
|
<group>0</group>
|
||||||
|
<label>unconfined_u:object_r:virt_image_t:s0</label>
|
||||||
|
</permissions>
|
||||||
|
<encryption format='qcow'>
|
||||||
|
<secret type='passphrase' uuid='e78d4b51-a2af-485f-b0f5-afca709a80f4'/>
|
||||||
|
</encryption>
|
||||||
|
</target>
|
||||||
|
<backingStore>
|
||||||
|
<path>/dev/null</path>
|
||||||
|
<format type='raw'/>
|
||||||
|
</backingStore>
|
||||||
|
</volume>
|
Reference in New Issue
Block a user