[libvirt] [PATCH 0/5] parallels: manage container's filesystems

This patch series adds ability to manage container's filesystems: you can add or remove fs from existing container or create new one, based on existing disk image. Dmitry Guryanov (5): add ploop fs driver type parallels: dump info about container filesystems parallels: commit with PVCF_DETACH_HDD_BUNDLE flag parallels: allow to add filesystems to container parallels: create container from existing image src/conf/domain_conf.c | 3 +- src/conf/domain_conf.h | 1 + src/parallels/parallels_sdk.c | 209 ++++++++++++++++++++++++++++++++++++++---- src/qemu/qemu_command.c | 1 + 4 files changed, 196 insertions(+), 18 deletions(-) -- 2.1.0

Ploop is a pseudo device which makes possible to access to an image in a file via block device, like loop devices, but with additional features: snapshots, write tracker and without double-caching. It used in PCS for containers and in OpenVZ. You can manage ploop devices and images with ploop utility (http://git.openvz.org/?p=ploop). Signed-off-by: Dmitry Guryanov <dguryanov@parallels.com> --- src/conf/domain_conf.c | 3 ++- src/conf/domain_conf.h | 1 + src/qemu/qemu_command.c | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index aafc05e..b502b50 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -374,7 +374,8 @@ VIR_ENUM_IMPL(virDomainFSDriver, VIR_DOMAIN_FS_DRIVER_TYPE_LAST, "path", "handle", "loop", - "nbd") + "nbd", + "ploop") VIR_ENUM_IMPL(virDomainFSAccessMode, VIR_DOMAIN_FS_ACCESSMODE_LAST, "passthrough", diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 57297cd..44f00a0 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -791,6 +791,7 @@ typedef enum { VIR_DOMAIN_FS_DRIVER_TYPE_HANDLE, VIR_DOMAIN_FS_DRIVER_TYPE_LOOP, VIR_DOMAIN_FS_DRIVER_TYPE_NBD, + VIR_DOMAIN_FS_DRIVER_TYPE_PLOOP, VIR_DOMAIN_FS_DRIVER_TYPE_LAST } virDomainFSDriverType; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index d5679de..077962f 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -151,6 +151,7 @@ VIR_ENUM_IMPL(qemuDomainFSDriver, VIR_DOMAIN_FS_DRIVER_TYPE_LAST, "local", "handle", NULL, + NULL, NULL); VIR_ENUM_DECL(qemuNumaPolicy) -- 2.1.0

On 26.12.2014 15:43, Dmitry Guryanov wrote:
Ploop is a pseudo device which makes possible to access to an image in a file via block device, like loop devices, but with additional features: snapshots, write tracker and without double-caching.
It used in PCS for containers and in OpenVZ. You can manage ploop devices and images with ploop utility (http://git.openvz.org/?p=ploop).
Signed-off-by: Dmitry Guryanov <dguryanov@parallels.com> --- src/conf/domain_conf.c | 3 ++- src/conf/domain_conf.h | 1 + src/qemu/qemu_command.c | 1 + 3 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index aafc05e..b502b50 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -374,7 +374,8 @@ VIR_ENUM_IMPL(virDomainFSDriver, VIR_DOMAIN_FS_DRIVER_TYPE_LAST, "path", "handle", "loop", - "nbd") + "nbd", + "ploop")
VIR_ENUM_IMPL(virDomainFSAccessMode, VIR_DOMAIN_FS_ACCESSMODE_LAST, "passthrough", diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 57297cd..44f00a0 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -791,6 +791,7 @@ typedef enum { VIR_DOMAIN_FS_DRIVER_TYPE_HANDLE, VIR_DOMAIN_FS_DRIVER_TYPE_LOOP, VIR_DOMAIN_FS_DRIVER_TYPE_NBD, + VIR_DOMAIN_FS_DRIVER_TYPE_PLOOP,
VIR_DOMAIN_FS_DRIVER_TYPE_LAST } virDomainFSDriverType; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index d5679de..077962f 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -151,6 +151,7 @@ VIR_ENUM_IMPL(qemuDomainFSDriver, VIR_DOMAIN_FS_DRIVER_TYPE_LAST, "local", "handle", NULL, + NULL, NULL);
VIR_ENUM_DECL(qemuNumaPolicy)
This extends domain XML space. That always must go hand in hand with RNG schema adjustment and some documentation. Introduction of a test case is strongly recommended too. I can't ACK a patch without it, sorry. Michal

On 01/12/2015 06:39 PM, Michal Privoznik wrote:
On 26.12.2014 15:43, Dmitry Guryanov wrote:
Ploop is a pseudo device which makes possible to access to an image in a file via block device, like loop devices, but with additional features: snapshots, write tracker and without double-caching.
It used in PCS for containers and in OpenVZ. You can manage ploop devices and images with ploop utility (http://git.openvz.org/?p=ploop).
Signed-off-by: Dmitry Guryanov <dguryanov@parallels.com> --- src/conf/domain_conf.c | 3 ++- src/conf/domain_conf.h | 1 + src/qemu/qemu_command.c | 1 + 3 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index aafc05e..b502b50 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -374,7 +374,8 @@ VIR_ENUM_IMPL(virDomainFSDriver, VIR_DOMAIN_FS_DRIVER_TYPE_LAST, "path", "handle", "loop", - "nbd") + "nbd", + "ploop")
VIR_ENUM_IMPL(virDomainFSAccessMode, VIR_DOMAIN_FS_ACCESSMODE_LAST, "passthrough", diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 57297cd..44f00a0 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -791,6 +791,7 @@ typedef enum { VIR_DOMAIN_FS_DRIVER_TYPE_HANDLE, VIR_DOMAIN_FS_DRIVER_TYPE_LOOP, VIR_DOMAIN_FS_DRIVER_TYPE_NBD, + VIR_DOMAIN_FS_DRIVER_TYPE_PLOOP,
VIR_DOMAIN_FS_DRIVER_TYPE_LAST } virDomainFSDriverType; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index d5679de..077962f 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -151,6 +151,7 @@ VIR_ENUM_IMPL(qemuDomainFSDriver, VIR_DOMAIN_FS_DRIVER_TYPE_LAST, "local", "handle", NULL, + NULL, NULL);
VIR_ENUM_DECL(qemuNumaPolicy)
This extends domain XML space. That always must go hand in hand with RNG schema adjustment and some documentation. Introduction of a test case is strongly recommended too. I can't ACK a patch without it, sorry.
OK, I'll extend RNG schema and add documentation. Could you, please, point to some tests, which I can use as a sample?
Michal
-- Dmitry Guryanov

On 13.01.2015 09:43, Dmitry Guryanov wrote:
On 01/12/2015 06:39 PM, Michal Privoznik wrote:
On 26.12.2014 15:43, Dmitry Guryanov wrote:
Ploop is a pseudo device which makes possible to access to an image in a file via block device, like loop devices, but with additional features: snapshots, write tracker and without double-caching.
It used in PCS for containers and in OpenVZ. You can manage ploop devices and images with ploop utility (http://git.openvz.org/?p=ploop).
Signed-off-by: Dmitry Guryanov <dguryanov@parallels.com> --- src/conf/domain_conf.c | 3 ++- src/conf/domain_conf.h | 1 + src/qemu/qemu_command.c | 1 + 3 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index aafc05e..b502b50 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -374,7 +374,8 @@ VIR_ENUM_IMPL(virDomainFSDriver, VIR_DOMAIN_FS_DRIVER_TYPE_LAST, "path", "handle", "loop", - "nbd") + "nbd", + "ploop")
VIR_ENUM_IMPL(virDomainFSAccessMode, VIR_DOMAIN_FS_ACCESSMODE_LAST, "passthrough", diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 57297cd..44f00a0 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -791,6 +791,7 @@ typedef enum { VIR_DOMAIN_FS_DRIVER_TYPE_HANDLE, VIR_DOMAIN_FS_DRIVER_TYPE_LOOP, VIR_DOMAIN_FS_DRIVER_TYPE_NBD, + VIR_DOMAIN_FS_DRIVER_TYPE_PLOOP,
VIR_DOMAIN_FS_DRIVER_TYPE_LAST } virDomainFSDriverType; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index d5679de..077962f 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -151,6 +151,7 @@ VIR_ENUM_IMPL(qemuDomainFSDriver, VIR_DOMAIN_FS_DRIVER_TYPE_LAST, "local", "handle", NULL, + NULL, NULL);
VIR_ENUM_DECL(qemuNumaPolicy)
This extends domain XML space. That always must go hand in hand with RNG schema adjustment and some documentation. Introduction of a test case is strongly recommended too. I can't ACK a patch without it, sorry.
OK, I'll extend RNG schema and add documentation. Could you, please, point to some tests, which I can use as a sample?
In this case, creating yet another domain XML is okay. Something like: tests/domainschemadata/domain-parallels-* Michal

Obtain information about container's filesystems and store it in virDomainDef structure. Signed-off-by: Dmitry Guryanov <dguryanov@parallels.com> --- src/parallels/parallels_sdk.c | 63 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 60 insertions(+), 3 deletions(-) diff --git a/src/parallels/parallels_sdk.c b/src/parallels/parallels_sdk.c index 0b5430d..5f494f2 100644 --- a/src/parallels/parallels_sdk.c +++ b/src/parallels/parallels_sdk.c @@ -535,6 +535,55 @@ prlsdkGetDiskInfo(PRL_HANDLE prldisk, } static int +prlsdkGetFSInfo(PRL_HANDLE prldisk, + virDomainFSDefPtr fs) +{ + char *buf = NULL; + PRL_UINT32 buflen = 0; + PRL_RESULT pret; + int ret = -1; + + fs->type = VIR_DOMAIN_FS_TYPE_FILE; + fs->fsdriver = VIR_DOMAIN_FS_DRIVER_TYPE_PLOOP; + fs->accessmode = VIR_DOMAIN_FS_ACCESSMODE_PASSTHROUGH; + fs->wrpolicy = VIR_DOMAIN_FS_WRPOLICY_DEFAULT; + fs->format = VIR_STORAGE_FILE_PLOOP; + + fs->readonly = false; + fs->symlinksResolved = false; + + pret = PrlVmDev_GetImagePath(prldisk, NULL, &buflen); + prlsdkCheckRetGoto(pret, cleanup); + + if (VIR_ALLOC_N(buf, buflen) < 0) + goto cleanup; + + pret = PrlVmDev_GetImagePath(prldisk, buf, &buflen); + prlsdkCheckRetGoto(pret, cleanup); + + fs->src = buf; + buf = NULL; + + pret = PrlVmDevHd_GetMountPoint(prldisk, NULL, &buflen); + prlsdkCheckRetGoto(pret, cleanup); + + if (VIR_ALLOC_N(buf, buflen) < 0) + goto cleanup; + + pret = PrlVmDevHd_GetMountPoint(prldisk, buf, &buflen); + prlsdkCheckRetGoto(pret, cleanup); + + fs->dst = buf; + buf = NULL; + + ret = 0; + + cleanup: + VIR_FREE(buf); + return ret; +} + +static int prlsdkAddDomainHardDisksInfo(PRL_HANDLE sdkdom, virDomainDefPtr def) { PRL_RESULT pret; @@ -542,6 +591,7 @@ prlsdkAddDomainHardDisksInfo(PRL_HANDLE sdkdom, virDomainDefPtr def) PRL_UINT32 i; PRL_HANDLE hdd = PRL_INVALID_HANDLE; virDomainDiskDefPtr disk = NULL; + virDomainFSDefPtr fs; pret = PrlVmCfg_GetHardDisksCount(sdkdom, &hddCount); prlsdkCheckRetGoto(pret, error); @@ -551,9 +601,15 @@ prlsdkAddDomainHardDisksInfo(PRL_HANDLE sdkdom, virDomainDefPtr def) prlsdkCheckRetGoto(pret, error); if (IS_CT(def)) { - /* TODO: convert info about disks in container - * to virDomainFSDef structs */ - VIR_WARN("Skipping disk information for container"); + + if (VIR_ALLOC(fs) < 0) + goto error; + + if (prlsdkGetFSInfo(hdd, fs) < 0) + goto error; + + if (virDomainFSInsert(def, fs) < 0) + goto error; PrlHandle_Free(hdd); hdd = PRL_INVALID_HANDLE; @@ -577,6 +633,7 @@ prlsdkAddDomainHardDisksInfo(PRL_HANDLE sdkdom, virDomainDefPtr def) error: PrlHandle_Free(hdd); virDomainDiskDefFree(disk); + virDomainFSDefFree(fs); return -1; } -- 2.1.0

On 26.12.2014 15:43, Dmitry Guryanov wrote:
Obtain information about container's filesystems and store it in virDomainDef structure.
Signed-off-by: Dmitry Guryanov <dguryanov@parallels.com> --- src/parallels/parallels_sdk.c | 63 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 60 insertions(+), 3 deletions(-)
diff --git a/src/parallels/parallels_sdk.c b/src/parallels/parallels_sdk.c index 0b5430d..5f494f2 100644 --- a/src/parallels/parallels_sdk.c +++ b/src/parallels/parallels_sdk.c @@ -535,6 +535,55 @@ prlsdkGetDiskInfo(PRL_HANDLE prldisk, }
static int +prlsdkGetFSInfo(PRL_HANDLE prldisk, + virDomainFSDefPtr fs) +{ + char *buf = NULL; + PRL_UINT32 buflen = 0; + PRL_RESULT pret; + int ret = -1; + + fs->type = VIR_DOMAIN_FS_TYPE_FILE; + fs->fsdriver = VIR_DOMAIN_FS_DRIVER_TYPE_PLOOP; + fs->accessmode = VIR_DOMAIN_FS_ACCESSMODE_PASSTHROUGH; + fs->wrpolicy = VIR_DOMAIN_FS_WRPOLICY_DEFAULT; + fs->format = VIR_STORAGE_FILE_PLOOP; + + fs->readonly = false; + fs->symlinksResolved = false; + + pret = PrlVmDev_GetImagePath(prldisk, NULL, &buflen); + prlsdkCheckRetGoto(pret, cleanup); + + if (VIR_ALLOC_N(buf, buflen) < 0) + goto cleanup; + + pret = PrlVmDev_GetImagePath(prldisk, buf, &buflen); + prlsdkCheckRetGoto(pret, cleanup); + + fs->src = buf; + buf = NULL; + + pret = PrlVmDevHd_GetMountPoint(prldisk, NULL, &buflen); + prlsdkCheckRetGoto(pret, cleanup); + + if (VIR_ALLOC_N(buf, buflen) < 0) + goto cleanup; + + pret = PrlVmDevHd_GetMountPoint(prldisk, buf, &buflen); + prlsdkCheckRetGoto(pret, cleanup); + + fs->dst = buf; + buf = NULL; + + ret = 0; + + cleanup: + VIR_FREE(buf); + return ret; +} + +static int prlsdkAddDomainHardDisksInfo(PRL_HANDLE sdkdom, virDomainDefPtr def) { PRL_RESULT pret; @@ -542,6 +591,7 @@ prlsdkAddDomainHardDisksInfo(PRL_HANDLE sdkdom, virDomainDefPtr def) PRL_UINT32 i; PRL_HANDLE hdd = PRL_INVALID_HANDLE; virDomainDiskDefPtr disk = NULL; + virDomainFSDefPtr fs;
This needs to be initialized to NULL, otherwise you may end up freeing a random memory if the control jumps to 'error' label.
pret = PrlVmCfg_GetHardDisksCount(sdkdom, &hddCount); prlsdkCheckRetGoto(pret, error); @@ -551,9 +601,15 @@ prlsdkAddDomainHardDisksInfo(PRL_HANDLE sdkdom, virDomainDefPtr def) prlsdkCheckRetGoto(pret, error);
if (IS_CT(def)) { - /* TODO: convert info about disks in container - * to virDomainFSDef structs */ - VIR_WARN("Skipping disk information for container"); + + if (VIR_ALLOC(fs) < 0) + goto error; + + if (prlsdkGetFSInfo(hdd, fs) < 0) + goto error; + + if (virDomainFSInsert(def, fs) < 0) + goto error;
What are you missing here is fs = NULL; after the insert. Otherwise in next iteration - if we fail - we jump to 'error' and free @fs which, however, is already part of domain @def. Same applies for @disk. Previously it wasn't problem as there was only @disk which would get overwritten as the first thing in new loop.
PrlHandle_Free(hdd); hdd = PRL_INVALID_HANDLE; @@ -577,6 +633,7 @@ prlsdkAddDomainHardDisksInfo(PRL_HANDLE sdkdom, virDomainDefPtr def) error: PrlHandle_Free(hdd); virDomainDiskDefFree(disk); + virDomainFSDefFree(fs); return -1; }
Michal

PCS removes disk image from filesystem, if you remove it from config. There is a special flag PVCF_DETACH_HDD_BUNDLE which allow to remove disk only from VM/CT config. If you call virDomainDefine and remove some disk from config it should be preserved, so call PrlVm_CommitEx always with flag PVCF_DETACH_HDD_BUNDLE. Signed-off-by: Dmitry Guryanov <dguryanov@parallels.com> --- src/parallels/parallels_sdk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/parallels/parallels_sdk.c b/src/parallels/parallels_sdk.c index 5f494f2..39c1c70 100644 --- a/src/parallels/parallels_sdk.c +++ b/src/parallels/parallels_sdk.c @@ -2728,7 +2728,7 @@ prlsdkApplyConfig(virConnectPtr conn, ret = prlsdkDoApplyConfig(sdkdom, new); if (ret == 0) { - job = PrlVm_Commit(sdkdom); + job = PrlVm_CommitEx(sdkdom, PVCF_DETACH_HDD_BUNDLE); if (PRL_FAILED(waitJob(job, privconn->jobTimeout))) ret = -1; } -- 2.1.0

Handle information about filesystems in domain config and add corresponding devices to container via parallels sdk. Signed-off-by: Dmitry Guryanov <dguryanov@parallels.com> --- src/parallels/parallels_sdk.c | 109 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 107 insertions(+), 2 deletions(-) diff --git a/src/parallels/parallels_sdk.c b/src/parallels/parallels_sdk.c index 39c1c70..7b4e1bb 100644 --- a/src/parallels/parallels_sdk.c +++ b/src/parallels/parallels_sdk.c @@ -1921,8 +1921,14 @@ prlsdkCheckUnsupportedParams(PRL_HANDLE sdkdom, virDomainDefPtr def) return -1; } - if (def->nfss != 0 || - def->nsounds != 0 || def->nhostdevs != 0 || + if (!IS_CT(def) && def->nfss !=0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Filesystems in VMs are not supported " + "by parallels driver")); + return -1; + } + + if (def->nsounds != 0 || def->nhostdevs != 0 || def->nredirdevs != 0 || def->nsmartcards != 0 || def->nparallels || def->nchannels != 0 || def->nleases != 0 || def->nhubs != 0) { @@ -2341,6 +2347,60 @@ static int prlsdkCheckDiskUnsupportedParams(virDomainDiskDefPtr disk) return 0; } +static int prlsdkCheckFSUnsupportedParams(virDomainFSDefPtr fs) +{ + if (fs->type != VIR_DOMAIN_FS_TYPE_FILE) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Only file based filesystems are " + "supported by parallels driver.")); + return -1; + } + + if (fs->fsdriver != VIR_DOMAIN_FS_DRIVER_TYPE_PLOOP) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Only ploop fs driver is " + "supported by parallels driver.")); + return -1; + } + + if (fs->accessmode != VIR_DOMAIN_FS_ACCESSMODE_PASSTHROUGH) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Changing fs access mode is not " + "supported by parallels driver.")); + return -1; + } + + if (fs->wrpolicy != VIR_DOMAIN_FS_WRPOLICY_DEFAULT) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Changing fs write policy is not " + "supported by parallels driver.")); + return -1; + } + + if (fs->format != VIR_STORAGE_FILE_PLOOP) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Only ploop disk images are " + "supported by parallels driver.")); + return -1; + } + + if (fs->readonly) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Setting readonly for filesystems is " + "not supported by parallels driver.")); + return -1; + } + + if (fs->space_hard_limit || fs->space_soft_limit) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Setting fs quotas is not " + "supported by parallels driver.")); + return -1; + } + + return 0; +} + static int prlsdkApplyGraphicsParams(PRL_HANDLE sdkdom, virDomainDefPtr def) { virDomainGraphicsDefPtr gr; @@ -2644,6 +2704,46 @@ static int prlsdkAddDisk(PRL_HANDLE sdkdom, virDomainDiskDefPtr disk) } static int +prlsdkAddFS(PRL_HANDLE sdkdom, virDomainFSDefPtr fs) +{ + PRL_RESULT pret; + PRL_HANDLE sdkdisk = PRL_INVALID_HANDLE; + int ret = -1; + + if (prlsdkCheckFSUnsupportedParams(fs) < 0) + return -1; + + pret = PrlVmCfg_CreateVmDev(sdkdom, PDE_HARD_DISK, &sdkdisk); + prlsdkCheckRetGoto(pret, cleanup); + + pret = PrlVmDev_SetEnabled(sdkdisk, 1); + prlsdkCheckRetGoto(pret, cleanup); + + pret = PrlVmDev_SetConnected(sdkdisk, 1); + prlsdkCheckRetGoto(pret, cleanup); + + pret = PrlVmDev_SetEmulatedType(sdkdisk, PDT_USE_IMAGE_FILE); + prlsdkCheckRetGoto(pret, cleanup); + + pret = PrlVmDev_SetSysName(sdkdisk, fs->src); + prlsdkCheckRetGoto(pret, cleanup); + + pret = PrlVmDev_SetImagePath(sdkdisk, fs->src); + prlsdkCheckRetGoto(pret, cleanup); + + pret = PrlVmDev_SetFriendlyName(sdkdisk, fs->src); + prlsdkCheckRetGoto(pret, cleanup); + + pret = PrlVmDevHd_SetMountPoint(sdkdisk, fs->dst); + prlsdkCheckRetGoto(pret, cleanup); + + ret = 0; + + cleanup: + PrlHandle_Free(sdkdisk); + return ret; +} +static int prlsdkDoApplyConfig(PRL_HANDLE sdkdom, virDomainDefPtr def) { @@ -2701,6 +2801,11 @@ prlsdkDoApplyConfig(PRL_HANDLE sdkdom, goto error; } + for (i = 0; i < def->nfss; i++) { + if (prlsdkAddFS(sdkdom, def->fss[i]) < 0) + goto error; + } + return 0; error: -- 2.1.0

On 26.12.2014 15:43, Dmitry Guryanov wrote:
Handle information about filesystems in domain config and add corresponding devices to container via parallels sdk.
Signed-off-by: Dmitry Guryanov <dguryanov@parallels.com> --- src/parallels/parallels_sdk.c | 109 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 107 insertions(+), 2 deletions(-)
diff --git a/src/parallels/parallels_sdk.c b/src/parallels/parallels_sdk.c index 39c1c70..7b4e1bb 100644 --- a/src/parallels/parallels_sdk.c +++ b/src/parallels/parallels_sdk.c @@ -1921,8 +1921,14 @@ prlsdkCheckUnsupportedParams(PRL_HANDLE sdkdom, virDomainDefPtr def) return -1; }
- if (def->nfss != 0 || - def->nsounds != 0 || def->nhostdevs != 0 || + if (!IS_CT(def) && def->nfss !=0) {
s/ !=/ != /
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Filesystems in VMs are not supported " + "by parallels driver")); + return -1; + } + + if (def->nsounds != 0 || def->nhostdevs != 0 || def->nredirdevs != 0 || def->nsmartcards != 0 || def->nparallels || def->nchannels != 0 || def->nleases != 0 || def->nhubs != 0) { @@ -2341,6 +2347,60 @@ static int prlsdkCheckDiskUnsupportedParams(virDomainDiskDefPtr disk) return 0; }
+static int prlsdkCheckFSUnsupportedParams(virDomainFSDefPtr fs) +{ + if (fs->type != VIR_DOMAIN_FS_TYPE_FILE) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Only file based filesystems are " + "supported by parallels driver.")); + return -1; + } + + if (fs->fsdriver != VIR_DOMAIN_FS_DRIVER_TYPE_PLOOP) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Only ploop fs driver is " + "supported by parallels driver.")); + return -1; + } + + if (fs->accessmode != VIR_DOMAIN_FS_ACCESSMODE_PASSTHROUGH) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Changing fs access mode is not " + "supported by parallels driver.")); + return -1; + } + + if (fs->wrpolicy != VIR_DOMAIN_FS_WRPOLICY_DEFAULT) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Changing fs write policy is not " + "supported by parallels driver.")); + return -1; + } + + if (fs->format != VIR_STORAGE_FILE_PLOOP) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Only ploop disk images are " + "supported by parallels driver.")); + return -1; + } + + if (fs->readonly) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Setting readonly for filesystems is " + "not supported by parallels driver.")); + return -1; + } + + if (fs->space_hard_limit || fs->space_soft_limit) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Setting fs quotas is not " + "supported by parallels driver.")); + return -1; + } + + return 0; +} + static int prlsdkApplyGraphicsParams(PRL_HANDLE sdkdom, virDomainDefPtr def) { virDomainGraphicsDefPtr gr; @@ -2644,6 +2704,46 @@ static int prlsdkAddDisk(PRL_HANDLE sdkdom, virDomainDiskDefPtr disk) }
static int +prlsdkAddFS(PRL_HANDLE sdkdom, virDomainFSDefPtr fs) +{ + PRL_RESULT pret; + PRL_HANDLE sdkdisk = PRL_INVALID_HANDLE; + int ret = -1; + + if (prlsdkCheckFSUnsupportedParams(fs) < 0) + return -1; + + pret = PrlVmCfg_CreateVmDev(sdkdom, PDE_HARD_DISK, &sdkdisk); + prlsdkCheckRetGoto(pret, cleanup); + + pret = PrlVmDev_SetEnabled(sdkdisk, 1); + prlsdkCheckRetGoto(pret, cleanup); + + pret = PrlVmDev_SetConnected(sdkdisk, 1); + prlsdkCheckRetGoto(pret, cleanup); + + pret = PrlVmDev_SetEmulatedType(sdkdisk, PDT_USE_IMAGE_FILE); + prlsdkCheckRetGoto(pret, cleanup); + + pret = PrlVmDev_SetSysName(sdkdisk, fs->src); + prlsdkCheckRetGoto(pret, cleanup); + + pret = PrlVmDev_SetImagePath(sdkdisk, fs->src); + prlsdkCheckRetGoto(pret, cleanup); + + pret = PrlVmDev_SetFriendlyName(sdkdisk, fs->src); + prlsdkCheckRetGoto(pret, cleanup); + + pret = PrlVmDevHd_SetMountPoint(sdkdisk, fs->dst); + prlsdkCheckRetGoto(pret, cleanup); + + ret = 0; + + cleanup: + PrlHandle_Free(sdkdisk); + return ret; +} +static int prlsdkDoApplyConfig(PRL_HANDLE sdkdom, virDomainDefPtr def) { @@ -2701,6 +2801,11 @@ prlsdkDoApplyConfig(PRL_HANDLE sdkdom, goto error; }
+ for (i = 0; i < def->nfss; i++) { + if (prlsdkAddFS(sdkdom, def->fss[i]) < 0) + goto error; + } + return 0;
error:
Michal

It's possible to create a container with existing disk image as root filesystem. You need to remove existing disks from PCS VM config and then add a new one, pointing to your image. And then call PrlVm_RegEx with PRNVM_PRESERVE_DISK flag. With this patch you can create a container with the following new domain XML config: <filesystem type='file' accessmode='passthrough'> <driver type='ploop' format='ploop'/> <source file='/path-to-image'/> <target dir='/'/> </filesystem> Signed-off-by: Dmitry Guryanov <dguryanov@parallels.com> --- src/parallels/parallels_sdk.c | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/src/parallels/parallels_sdk.c b/src/parallels/parallels_sdk.c index 7b4e1bb..9406746 100644 --- a/src/parallels/parallels_sdk.c +++ b/src/parallels/parallels_sdk.c @@ -2890,14 +2890,26 @@ prlsdkCreateCt(virConnectPtr conn, virDomainDefPtr def) PRL_HANDLE result = PRL_INVALID_HANDLE; PRL_RESULT pret; int ret = -1; - - if (def->nfss && (def->nfss > 1 || - def->fss[0]->type != VIR_DOMAIN_FS_TYPE_TEMPLATE)) { - - virReportError(VIR_ERR_INVALID_ARG, "%s", - _("There must be no more than 1 template FS for " - "container creation")); - return -1; + int useTemplate = 0; + unsigned int i; + + if (def->nfss > 1) { + /* Check all filesystems */ + for (i = 0; i < def->nfss; i++) { + if (def->fss[i]->type != VIR_DOMAIN_FS_TYPE_FILE) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("Unsupported filesystem type.")); + return -1; + } + } + } else if (def->nfss == 1) { + if (def->fss[0]->type == VIR_DOMAIN_FS_TYPE_TEMPLATE) { + useTemplate = 1; + } else if (def->fss[0]->type != VIR_DOMAIN_FS_TYPE_FILE) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("Unsupported filesystem type.")); + return -1; + } } confParam.nVmType = PVT_CT; @@ -2911,22 +2923,23 @@ prlsdkCreateCt(virConnectPtr conn, virDomainDefPtr def) pret = PrlResult_GetParamByIndex(result, 0, &sdkdom); prlsdkCheckRetGoto(pret, cleanup); - if (def->nfss == 1) { + if (useTemplate) { pret = PrlVmCfg_SetOsTemplate(sdkdom, def->fss[0]->src); prlsdkCheckRetGoto(pret, cleanup); + } ret = prlsdkDoApplyConfig(sdkdom, def); if (ret) goto cleanup; - job = PrlVm_RegEx(sdkdom, "", PACF_NON_INTERACTIVE_MODE); + job = PrlVm_RegEx(sdkdom, "", PACF_NON_INTERACTIVE_MODE|PRNVM_PRESERVE_DISK); if (PRL_FAILED(waitJob(job, privconn->jobTimeout))) ret = -1; cleanup: PrlHandle_Free(sdkdom); - return -1; + return ret; } int -- 2.1.0

On 26.12.2014 15:43, Dmitry Guryanov wrote:
It's possible to create a container with existing disk image as root filesystem. You need to remove existing disks from PCS VM config and then add a new one, pointing to your image. And then call PrlVm_RegEx with PRNVM_PRESERVE_DISK flag.
With this patch you can create a container with the following new domain XML config:
<filesystem type='file' accessmode='passthrough'> <driver type='ploop' format='ploop'/> <source file='/path-to-image'/> <target dir='/'/> </filesystem>
Signed-off-by: Dmitry Guryanov <dguryanov@parallels.com> --- src/parallels/parallels_sdk.c | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-)
diff --git a/src/parallels/parallels_sdk.c b/src/parallels/parallels_sdk.c index 7b4e1bb..9406746 100644 --- a/src/parallels/parallels_sdk.c +++ b/src/parallels/parallels_sdk.c @@ -2890,14 +2890,26 @@ prlsdkCreateCt(virConnectPtr conn, virDomainDefPtr def) PRL_HANDLE result = PRL_INVALID_HANDLE; PRL_RESULT pret; int ret = -1; - - if (def->nfss && (def->nfss > 1 || - def->fss[0]->type != VIR_DOMAIN_FS_TYPE_TEMPLATE)) { - - virReportError(VIR_ERR_INVALID_ARG, "%s", - _("There must be no more than 1 template FS for " - "container creation")); - return -1; + int useTemplate = 0; + unsigned int i; + + if (def->nfss > 1) { + /* Check all filesystems */ + for (i = 0; i < def->nfss; i++) {
def->nfss is type of size_t which may not fit into unsigned int. Therefore, @i needs to be size_t type too.
+ if (def->fss[i]->type != VIR_DOMAIN_FS_TYPE_FILE) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("Unsupported filesystem type.")); + return -1; + } + } + } else if (def->nfss == 1) { + if (def->fss[0]->type == VIR_DOMAIN_FS_TYPE_TEMPLATE) { + useTemplate = 1; + } else if (def->fss[0]->type != VIR_DOMAIN_FS_TYPE_FILE) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("Unsupported filesystem type.")); + return -1; + } }
confParam.nVmType = PVT_CT; @@ -2911,22 +2923,23 @@ prlsdkCreateCt(virConnectPtr conn, virDomainDefPtr def) pret = PrlResult_GetParamByIndex(result, 0, &sdkdom); prlsdkCheckRetGoto(pret, cleanup);
- if (def->nfss == 1) { + if (useTemplate) { pret = PrlVmCfg_SetOsTemplate(sdkdom, def->fss[0]->src); prlsdkCheckRetGoto(pret, cleanup); + }
ret = prlsdkDoApplyConfig(sdkdom, def); if (ret) goto cleanup;
- job = PrlVm_RegEx(sdkdom, "", PACF_NON_INTERACTIVE_MODE); + job = PrlVm_RegEx(sdkdom, "", PACF_NON_INTERACTIVE_MODE|PRNVM_PRESERVE_DISK); if (PRL_FAILED(waitJob(job, privconn->jobTimeout))) ret = -1;
cleanup: PrlHandle_Free(sdkdom); - return -1; + return ret; }
int
Michal
participants (2)
-
Dmitry Guryanov
-
Michal Privoznik