static int
storageBackendCreateQemuImgSetInput(virStorageVolDefPtr inputvol,
+ virStorageVolEncryptConvertStep convertStep,
struct _virStorageBackendQemuImgInfo *info)
{
- if (!(info->inputPath = inputvol->target.path)) {
- virReportError(VIR_ERR_INVALID_ARG, "%s",
- _("missing input volume target path"));
- return -1;
+ if (convertStep != VIR_STORAGE_VOL_ENCRYPT_CREATE) {
+ if (!(info->inputPath = inputvol->target.path)) {
+ virReportError(VIR_ERR_INVALID_ARG, "%s",
+ _("missing input volume target path"));
+ return -1;
+ }
}
info->inputFormat = inputvol->target.format;
virStorageBackendCreateQemuImgSetInfo(virStoragePoolObjPtr pool,
virStorageVolDefPtr vol,
virStorageVolDefPtr inputvol,
+ virStorageVolEncryptConvertStep convertStep,
struct _virStorageBackendQemuImgInfo *info)
{
/* Treat output block devices as 'raw' format */
return -1;
}
if (info->format == VIR_STORAGE_FILE_RAW && vol->target.encryption) {
- if (inputvol) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("cannot use inputvol with encrypted raw volume"));
- return -1;
- }
if (vol->target.encryption->format == VIR_STORAGE_ENCRYPTION_FORMAT_LUKS) {
info->type = "luks";
} else {
}
if (inputvol &&
- storageBackendCreateQemuImgSetInput(inputvol, info) < 0)
+ storageBackendCreateQemuImgSetInput(inputvol, convertStep, info) < 0)
return -1;
if (virStorageSourceHasBacking(&vol->target) &&
virStorageVolDefPtr inputvol,
unsigned int flags,
const char *create_tool,
- const char *secretPath)
+ const char *secretPath,
+ virStorageVolEncryptConvertStep convertStep)
{
virCommandPtr cmd = NULL;
struct _virStorageBackendQemuImgInfo info = {
goto error;
}
- if (virStorageBackendCreateQemuImgSetInfo(pool, vol, inputvol, &info) < 0)
+ if (virStorageBackendCreateQemuImgSetInfo(pool, vol, inputvol,
+ convertStep, &info) < 0)
goto error;
cmd = virCommandNew(create_tool);
- /* ignore the backing volume when we're converting a volume */
- if (info.inputPath)
+ /* ignore the backing volume when we're converting a volume
+ * including when we're doing a two step convert during create */
+ if (info.inputPath || convertStep == VIR_STORAGE_VOL_ENCRYPT_CREATE)
info.backingPath = NULL;
- if (info.inputPath)
+ /* Converting to use encryption is a two step process - step 1 is to
+ * create the image and step 2 is to convert it using special arguments */
+ if (info.inputPath && convertStep == VIR_STORAGE_VOL_ENCRYPT_NONE)
virCommandAddArgList(cmd, "convert", "-f", info.inputFormatStr,
"-O", info.type, NULL);
+ else if (info.inputPath && convertStep == VIR_STORAGE_VOL_ENCRYPT_CONVERT)
+ virCommandAddArgList(cmd, "convert", "--image-opts", "-n",
+ "--target-image-opts", NULL);
else
virCommandAddArgList(cmd, "create", "-f", info.type, NULL);
encinfo = &enc->encinfo;
}
- if (storageBackendCreateQemuImgSetOptions(cmd, encinfo, info) < 0)
- goto error;
- VIR_FREE(info.secretAlias);
+ if (convertStep != VIR_STORAGE_VOL_ENCRYPT_CONVERT) {
+ if (storageBackendCreateQemuImgSetOptions(cmd, encinfo, info) < 0)
+ goto error;
+ if (info.inputPath)
+ virCommandAddArg(cmd, info.inputPath);
+ virCommandAddArg(cmd, info.path);
+ if (!info.inputPath && (info.size_arg || !info.backingPath))
+ virCommandAddArgFormat(cmd, "%lluK", info.size_arg);
+ } else {
+ /* source */
+ virCommandAddArgFormat(cmd, "driver=raw,file.filename=%s",
+ info.inputPath);
- if (info.inputPath)
- virCommandAddArg(cmd, info.inputPath);
- virCommandAddArg(cmd, info.path);
- if (!info.inputPath && (info.size_arg || !info.backingPath))
- virCommandAddArgFormat(cmd, "%lluK", info.size_arg);
+ /* dest */
+ virCommandAddArgFormat(cmd, "driver=%s,file.filename=%s,key-secret=%s",
+ info.type, info.path, info.secretAlias);
+ }
+ VIR_FREE(info.secretAlias);
return cmd;
virStorageVolDefPtr inputvol,
unsigned int flags,
const char *create_tool,
- const char *secretPath)
+ const char *secretPath,
+ virStorageVolEncryptConvertStep convertStep)
{
int ret;
virCommandPtr cmd;
cmd = virStorageBackendCreateQemuImgCmdFromVol(pool, vol, inputvol,
flags, create_tool,
- secretPath);
+ secretPath, convertStep);
if (!cmd)
return -1;
int ret = -1;
char *create_tool;
char *secretPath = NULL;
+ virStorageVolEncryptConvertStep convertStep = VIR_STORAGE_VOL_ENCRYPT_NONE;
virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, -1);
!(secretPath = storageBackendCreateQemuImgSecretPath(pool, vol)))
goto cleanup;
- ret = storageBackendDoCreateQemuImg(pool, vol, inputvol, flags,
- create_tool, secretPath);
+ /* Using an input file for encryption requires a multi-step process
+ * to create an image of the same size as the inputvol and then to
+ * convert the inputvol afterwards. */
+ if (secretPath && inputvol)
+ convertStep = VIR_STORAGE_VOL_ENCRYPT_CREATE;
+
+ do {
+ ret = storageBackendDoCreateQemuImg(pool, vol, inputvol, flags,
+ create_tool, secretPath,
+ convertStep);
+
+ /* Failure to convert, attempt to delete what we created */
+ if (ret < 0 && convertStep == VIR_STORAGE_VOL_ENCRYPT_CONVERT)
+ ignore_value(virFileRemove(vol->target.path,
+ vol->target.perms->uid,
+ vol->target.perms->gid));
+
+ if (ret < 0 || convertStep == VIR_STORAGE_VOL_ENCRYPT_NONE)
+ goto cleanup;
+
+ if (convertStep == VIR_STORAGE_VOL_ENCRYPT_CREATE)
+ convertStep = VIR_STORAGE_VOL_ENCRYPT_CONVERT;
+ else if (convertStep == VIR_STORAGE_VOL_ENCRYPT_CONVERT)
+ convertStep = VIR_STORAGE_VOL_ENCRYPT_DONE;
+ } while (convertStep != VIR_STORAGE_VOL_ENCRYPT_DONE);
+
cleanup:
if (secretPath) {
unlink(secretPath);
virStorageBackendBuildVolFrom create_func;
if (inputvol) {
- if (vol->target.encryption) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- "%s", _("storage pool does not support "
- "building encrypted volumes from "
- "other volumes"));
- return -1;
- }
if (!(create_func =
virStorageBackendGetBuildVolFromFunction(vol, inputvol)))
return -1;
unsigned long parse_flags)
{
char *actualCmdline = NULL;
+ virStorageVolEncryptConvertStep convertStep = VIR_STORAGE_VOL_ENCRYPT_NONE;
int ret = -1;
virCommandPtr cmd = NULL;
testSetVolumeType(vol, def);
testSetVolumeType(inputvol, inputpool);
- cmd = virStorageBackendCreateQemuImgCmdFromVol(obj, vol,
- inputvol, flags,
- create_tool,
- "/path/to/secretFile");
- if (!cmd) {
- if (shouldFail) {
- virResetLastError();
- ret = 0;
+ /* Using an input file for encryption requires a multi-step process
+ * to create an image of the same size as the inputvol and then to
+ * convert the inputvol afterwards. Since we only care about the
+ * command line we have to copy code from storageBackendCreateQemuImg
+ * and adjust it for the test needs. */
+ if (inputvol && vol->target.encryption)
+ convertStep = VIR_STORAGE_VOL_ENCRYPT_CREATE;
+
+ do {
+ cmd = virStorageBackendCreateQemuImgCmdFromVol(obj, vol,
+ inputvol, flags,
+ create_tool,
+ "/path/to/secretFile",
+ convertStep);
+ if (!cmd) {
+ if (shouldFail) {
+ virResetLastError();
+ ret = 0;
+ }
+ goto cleanup;
}
- goto cleanup;
- }
- if (!(actualCmdline = virCommandToString(cmd)))
- goto cleanup;
+ if (convertStep != VIR_STORAGE_VOL_ENCRYPT_CONVERT) {
+ if (!(actualCmdline = virCommandToString(cmd)))
+ goto cleanup;
+ } else {
+ char *createCmdline = actualCmdline;
+ char *cvtCmdline;
+ int rc;
+
+ if (!(cvtCmdline = virCommandToString(cmd)))
+ goto cleanup;
+
+ rc = virAsprintf(&actualCmdline, "%s\n%s",
+ createCmdline, cvtCmdline);
+
+ VIR_FREE(createCmdline);
+ VIR_FREE(cvtCmdline);
+ if (rc < 0)
+ goto cleanup;
+ }
+
+ if (convertStep == VIR_STORAGE_VOL_ENCRYPT_NONE)
+ convertStep = VIR_STORAGE_VOL_ENCRYPT_DONE;
+ else if (convertStep == VIR_STORAGE_VOL_ENCRYPT_CREATE)
+ convertStep = VIR_STORAGE_VOL_ENCRYPT_CONVERT;
+ else if (convertStep == VIR_STORAGE_VOL_ENCRYPT_CONVERT)
+ convertStep = VIR_STORAGE_VOL_ENCRYPT_DONE;
+
+ } while (convertStep != VIR_STORAGE_VOL_ENCRYPT_DONE);
if (virTestCompareToFile(actualCmdline, cmdline) < 0)
goto cleanup;
NULL, NULL,
"luks-cipher", 0);
+ DO_TEST("pool-dir", "vol-luks-convert",
+ "pool-dir", "vol-file",
+ "luks-convert", 0);
+
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}