[libvirt] [PATCH 0/3] vz: allow to create CT from template and boot VM from cdrom

Mikhail Feoktistov (3): vz: allow to create container based on template vz: allow to boot VM from cdrom vz: implementation of boot device order src/vz/vz_sdk.c | 174 ++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 125 insertions(+), 49 deletions(-) -- 1.8.3.1

We shouldn't delete disk from default config if we create container based on template, because we don't have the new disk from XML, only template name. And don't add template section from XML as new filesystem, we use PrlVmCfg_SetOsTemplate function to set template name. Do not set PRNVM_PRESERVE_DISK flag in PrlVm_RegEx() call, because this will cause an error during CT startup. --- diff from v2: fix syntax check diff from v1: Remove unusable variable (PRL_VM_DEV_EMULATION_TYPE emul) Add parameter useCtTemplateFs in prlsdkDoApplyConfig() function Allow only one fs with "template" type and only for CT creation Move this commit to patch series src/vz/vz_sdk.c | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/src/vz/vz_sdk.c b/src/vz/vz_sdk.c index 2b031c9..c5f8edd 100644 --- a/src/vz/vz_sdk.c +++ b/src/vz/vz_sdk.c @@ -2107,12 +2107,13 @@ prlsdkCheckUnsupportedParams(PRL_HANDLE sdkdom, virDomainDefPtr def) return 0; } -static int prlsdkClearDevices(PRL_HANDLE sdkdom) +static int prlsdkClearDevices(PRL_HANDLE sdkdom, bool skipdisk) { PRL_RESULT pret; PRL_UINT32 n, i; PRL_HANDLE devList; PRL_HANDLE dev; + PRL_DEVICE_TYPE devType; int ret = -1; pret = PrlVmCfg_SetVNCMode(sdkdom, PRD_DISABLED); @@ -2128,6 +2129,15 @@ static int prlsdkClearDevices(PRL_HANDLE sdkdom) pret = PrlHndlList_GetItem(devList, i, &dev); prlsdkCheckRetGoto(pret, cleanup); + if (skipdisk) { + pret = PrlVmDev_GetType(dev, &devType); + prlsdkCheckRetGoto(pret, cleanup); + + if (devType == PDE_HARD_DISK) { + PrlHandle_Free(dev); + continue; + } + } pret = PrlVmDev_Remove(dev); PrlHandle_Free(dev); } @@ -3470,7 +3480,8 @@ static int prlsdkDoApplyConfig(virConnectPtr conn, PRL_HANDLE sdkdom, virDomainDefPtr def, - virDomainDefPtr olddef) + virDomainDefPtr olddef, + bool useCtTemplateFs) { PRL_RESULT pret; size_t i; @@ -3526,7 +3537,7 @@ prlsdkDoApplyConfig(virConnectPtr conn, } prlsdkCheckRetGoto(pret, error); - if (prlsdkClearDevices(sdkdom) < 0) + if (prlsdkClearDevices(sdkdom, useCtTemplateFs) < 0) goto error; if (prlsdkRemoveBootDevices(sdkdom) < 0) @@ -3554,6 +3565,12 @@ prlsdkDoApplyConfig(virConnectPtr conn, } for (i = 0; i < def->nfss; i++) { + if (def->fss[i]->type == VIR_DOMAIN_FS_TYPE_TEMPLATE) { + if (useCtTemplateFs) + continue; + else + goto error; + } if (STREQ(def->fss[i]->dst, "/")) needBoot = false; if (prlsdkAddFS(sdkdom, def->fss[i]) < 0) @@ -3602,7 +3619,7 @@ prlsdkApplyConfig(virConnectPtr conn, if (PRL_FAILED(waitJob(job))) return -1; - ret = prlsdkDoApplyConfig(conn, sdkdom, new, dom->def); + ret = prlsdkDoApplyConfig(conn, sdkdom, new, dom->def, false); if (ret == 0) { job = PrlVm_CommitEx(sdkdom, PVCF_DETACH_HDD_BUNDLE); @@ -3642,7 +3659,7 @@ prlsdkCreateVm(virConnectPtr conn, virDomainDefPtr def) pret = PrlVmCfg_SetOfflineManagementEnabled(sdkdom, 0); prlsdkCheckRetGoto(pret, cleanup); - ret = prlsdkDoApplyConfig(conn, sdkdom, def, NULL); + ret = prlsdkDoApplyConfig(conn, sdkdom, def, NULL, false); if (ret) goto cleanup; @@ -3665,8 +3682,9 @@ prlsdkCreateCt(virConnectPtr conn, virDomainDefPtr def) PRL_HANDLE result = PRL_INVALID_HANDLE; PRL_RESULT pret; int ret = -1; - int useTemplate = 0; + bool useTemplate = false; size_t i; + PRL_UINT32 flags = 0; if (def->nfss > 1) { /* Check all filesystems */ @@ -3679,7 +3697,7 @@ prlsdkCreateCt(virConnectPtr conn, virDomainDefPtr def) } } else if (def->nfss == 1) { if (def->fss[0]->type == VIR_DOMAIN_FS_TYPE_TEMPLATE) { - useTemplate = 1; + useTemplate = true; } else if (def->fss[0]->type != VIR_DOMAIN_FS_TYPE_FILE) { virReportError(VIR_ERR_INVALID_ARG, "%s", _("Unsupported filesystem type.")); @@ -3704,12 +3722,15 @@ prlsdkCreateCt(virConnectPtr conn, virDomainDefPtr def) } - ret = prlsdkDoApplyConfig(conn, sdkdom, def, NULL); + ret = prlsdkDoApplyConfig(conn, sdkdom, def, NULL, useTemplate); if (ret) goto cleanup; - job = PrlVm_RegEx(sdkdom, "", - PACF_NON_INTERACTIVE_MODE | PRNVM_PRESERVE_DISK); + flags = PACF_NON_INTERACTIVE_MODE; + if (!useTemplate) + flags = flags | PRNVM_PRESERVE_DISK; + + job = PrlVm_RegEx(sdkdom, "", flags); if (PRL_FAILED(waitJob(job))) ret = -1; -- 1.8.3.1

On Tue, 2015-12-15 at 14:43 +0300, Mikhail Feoktistov wrote:
We shouldn't delete disk from default config if we create container based on template, because we don't have the new disk from XML, only template name. And don't add template section from XML as new filesystem, we use PrlVmCfg_SetOsTemplate function to set template name. Do not set PRNVM_PRESERVE_DISK flag in PrlVm_RegEx() call, because this will cause an error during CT startup.
ACK
--- diff from v2: fix syntax check
diff from v1: Remove unusable variable (PRL_VM_DEV_EMULATION_TYPE emul) Add parameter useCtTemplateFs in prlsdkDoApplyConfig() function Allow only one fs with "template" type and only for CT creation Move this commit to patch series
src/vz/vz_sdk.c | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-)
diff --git a/src/vz/vz_sdk.c b/src/vz/vz_sdk.c index 2b031c9..c5f8edd 100644 --- a/src/vz/vz_sdk.c +++ b/src/vz/vz_sdk.c @@ -2107,12 +2107,13 @@ prlsdkCheckUnsupportedParams(PRL_HANDLE sdkdom, virDomainDefPtr def) return 0; } -static int prlsdkClearDevices(PRL_HANDLE sdkdom) +static int prlsdkClearDevices(PRL_HANDLE sdkdom, bool skipdisk) { PRL_RESULT pret; PRL_UINT32 n, i; PRL_HANDLE devList; PRL_HANDLE dev; + PRL_DEVICE_TYPE devType; int ret = -1; pret = PrlVmCfg_SetVNCMode(sdkdom, PRD_DISABLED); @@ -2128,6 +2129,15 @@ static int prlsdkClearDevices(PRL_HANDLE sdkdom) pret = PrlHndlList_GetItem(devList, i, &dev); prlsdkCheckRetGoto(pret, cleanup); + if (skipdisk) { + pret = PrlVmDev_GetType(dev, &devType); + prlsdkCheckRetGoto(pret, cleanup); + + if (devType == PDE_HARD_DISK) { + PrlHandle_Free(dev); + continue; + } + } pret = PrlVmDev_Remove(dev); PrlHandle_Free(dev); } @@ -3470,7 +3480,8 @@ static int prlsdkDoApplyConfig(virConnectPtr conn, PRL_HANDLE sdkdom, virDomainDefPtr def, - virDomainDefPtr olddef) + virDomainDefPtr olddef, + bool useCtTemplateFs) { PRL_RESULT pret; size_t i; @@ -3526,7 +3537,7 @@ prlsdkDoApplyConfig(virConnectPtr conn, } prlsdkCheckRetGoto(pret, error); - if (prlsdkClearDevices(sdkdom) < 0) + if (prlsdkClearDevices(sdkdom, useCtTemplateFs) < 0) goto error; if (prlsdkRemoveBootDevices(sdkdom) < 0) @@ -3554,6 +3565,12 @@ prlsdkDoApplyConfig(virConnectPtr conn, } for (i = 0; i < def->nfss; i++) { + if (def->fss[i]->type == VIR_DOMAIN_FS_TYPE_TEMPLATE) { + if (useCtTemplateFs) + continue; + else + goto error; + } if (STREQ(def->fss[i]->dst, "/")) needBoot = false; if (prlsdkAddFS(sdkdom, def->fss[i]) < 0) @@ -3602,7 +3619,7 @@ prlsdkApplyConfig(virConnectPtr conn, if (PRL_FAILED(waitJob(job))) return -1; - ret = prlsdkDoApplyConfig(conn, sdkdom, new, dom->def); + ret = prlsdkDoApplyConfig(conn, sdkdom, new, dom->def, false); if (ret == 0) { job = PrlVm_CommitEx(sdkdom, PVCF_DETACH_HDD_BUNDLE); @@ -3642,7 +3659,7 @@ prlsdkCreateVm(virConnectPtr conn, virDomainDefPtr def) pret = PrlVmCfg_SetOfflineManagementEnabled(sdkdom, 0); prlsdkCheckRetGoto(pret, cleanup); - ret = prlsdkDoApplyConfig(conn, sdkdom, def, NULL); + ret = prlsdkDoApplyConfig(conn, sdkdom, def, NULL, false); if (ret) goto cleanup; @@ -3665,8 +3682,9 @@ prlsdkCreateCt(virConnectPtr conn, virDomainDefPtr def) PRL_HANDLE result = PRL_INVALID_HANDLE; PRL_RESULT pret; int ret = -1; - int useTemplate = 0; + bool useTemplate = false; size_t i; + PRL_UINT32 flags = 0; if (def->nfss > 1) { /* Check all filesystems */ @@ -3679,7 +3697,7 @@ prlsdkCreateCt(virConnectPtr conn, virDomainDefPtr def) } } else if (def->nfss == 1) { if (def->fss[0]->type == VIR_DOMAIN_FS_TYPE_TEMPLATE) { - useTemplate = 1; + useTemplate = true; } else if (def->fss[0]->type != VIR_DOMAIN_FS_TYPE_FILE) { virReportError(VIR_ERR_INVALID_ARG, "%s", _("Unsupported filesystem type.")); @@ -3704,12 +3722,15 @@ prlsdkCreateCt(virConnectPtr conn, virDomainDefPtr def) } - ret = prlsdkDoApplyConfig(conn, sdkdom, def, NULL); + ret = prlsdkDoApplyConfig(conn, s4dkdom, def, NULL, useTemplate); if (ret) goto cleanup; - job = PrlVm_RegEx(sdkdom, "", - PACF_NON_INTERACTIVE_MODE | PRNVM_PRESERVE_DISK); + flags = PACF_NON_INTERACTIVE_MODE; + if (!useTemplate) + flags = flags | PRNVM_PRESERVE_DISK; + + job = PrlVm_RegEx(sdkdom, "", flags); if (PRL_FAILED(waitJob(job))) ret = -1;

If user creates virtual machine via virt-manager and select "boot from ISO" then in libvirt we can see the following devices section <disk type="file" device="disk"> <source file="/var/lib/libvirt/images/generic.img"/> <target dev="hda" bus="ide"/> </disk> <disk type="file" device="cdrom"> <source file="/var/lib/libvirt/images/Fedora-Live-Xfce-x86_64-23-10.iso"/> <target dev="hdb" bus="ide"/> <readonly/> </disk> These devices don't have disk->format parameter, so we should allow to add disks with format = VIR_STORAGE_FILE_NONE. If user select boot from HDD and add new Cdrom device then we see <disk type="file" device="cdrom"> <target dev="hdb" bus="ide"/> <readonly/> </disk> Cdrom device doesn't have disk->source parameter, it means that user did select "attach to real device" or "use ISO". So we should not return error if we get device with empty source path. --- diff from v1: Add commit description Move this commit to patch series src/vz/vz_sdk.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/vz/vz_sdk.c b/src/vz/vz_sdk.c index c5f8edd..1fcfb2e 100644 --- a/src/vz/vz_sdk.c +++ b/src/vz/vz_sdk.c @@ -2026,8 +2026,9 @@ prlsdkCheckUnsupportedParams(PRL_HANDLE sdkdom, virDomainDefPtr def) } if (!IS_CT(def)) { - if (def->os.nBootDevs != 1 || - def->os.bootDevs[0] != VIR_DOMAIN_BOOT_DISK || + if (def->os.nBootDevs == 0 || + (def->os.bootDevs[0] != VIR_DOMAIN_BOOT_DISK && + def->os.bootDevs[0] != VIR_DOMAIN_BOOT_CDROM) || def->os.init != NULL || def->os.initargv != NULL) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", @@ -3192,11 +3193,12 @@ static int prlsdkAddDisk(PRL_HANDLE sdkdom, if (disk->src->type == VIR_STORAGE_TYPE_FILE) { if (disk->device == VIR_DOMAIN_DISK_DEVICE_DISK && - virDomainDiskGetFormat(disk) != VIR_STORAGE_FILE_PLOOP) { + (virDomainDiskGetFormat(disk) != VIR_STORAGE_FILE_PLOOP && + virDomainDiskGetFormat(disk) != VIR_STORAGE_FILE_NONE)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Invalid format of " - "disk %s, vz driver supports only " - "images in ploop format."), disk->src->path); + "disk %s, it should be either not set or " + "ploop format."), disk->src->path); goto cleanup; } @@ -3218,11 +3220,13 @@ static int prlsdkAddDisk(PRL_HANDLE sdkdom, pret = PrlVmDev_SetEmulatedType(sdkdisk, emutype); prlsdkCheckRetGoto(pret, cleanup); - pret = PrlVmDev_SetSysName(sdkdisk, disk->src->path); - prlsdkCheckRetGoto(pret, cleanup); + if (disk->src->path != NULL) { + pret = PrlVmDev_SetSysName(sdkdisk, disk->src->path); + prlsdkCheckRetGoto(pret, cleanup); - pret = PrlVmDev_SetFriendlyName(sdkdisk, disk->src->path); - prlsdkCheckRetGoto(pret, cleanup); + pret = PrlVmDev_SetFriendlyName(sdkdisk, disk->src->path); + prlsdkCheckRetGoto(pret, cleanup); + } drive = &disk->info.addr.drive; if (drive->controller > 0) { -- 1.8.3.1

On Tue, 2015-12-15 at 14:43 +0300, Mikhail Feoktistov wrote:
If user creates virtual machine via virt-manager and select "boot from ISO" then in libvirt we can see the following devices section
<disk type="file" device="disk"> <source file="/var/lib/libvirt/images/generic.img"/> <target dev="hda" bus="ide"/> </disk> <disk type="file" device="cdrom"> <source file="/var/lib/libvirt/images/Fedora-Live-Xfce-x86_64-23-10.iso"/> <target dev="hdb" bus="ide"/> <readonly/> </disk>
These devices don't have disk->format parameter, so we should allow to add disks with format = VIR_STORAGE_FILE_NONE.
If user select boot from HDD and add new Cdrom device then we see
<disk type="file" device="cdrom"> <target dev="hdb" bus="ide"/> <readonly/> </disk>
Cdrom device doesn't have disk->source parameter, it means that user did select "attach to real device" or "use ISO". So we should not return error if we get device with empty source path. --- diff from v1: Add commit description Move this commit to patch series
src/vz/vz_sdk.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-)
diff --git a/src/vz/vz_sdk.c b/src/vz/vz_sdk.c index c5f8edd..1fcfb2e 100644 --- a/src/vz/vz_sdk.c +++ b/src/vz/vz_sdk.c @@ -2026,8 +2026,9 @@ prlsdkCheckUnsupportedParams(PRL_HANDLE sdkdom, virDomainDefPtr def) } if (!IS_CT(def)) { - if (def->os.nBootDevs != 1 || - def->os.bootDevs[0] != VIR_DOMAIN_BOOT_DISK || + if (def->os.nBootDevs == 0 || + (def->os.bootDevs[0] != VIR_DOMAIN_BOOT_DISK && + def->os.bootDevs[0] != VIR_DOMAIN_BOOT_CDROM) || def->os.init != NULL || def->os.initargv != NULL) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", @@ -3192,11 +3193,12 @@ static int prlsdkAddDisk(PRL_HANDLE sdkdom, if (disk->src->type == VIR_STORAGE_TYPE_FILE) { if (disk->device == VIR_DOMAIN_DISK_DEVICE_DISK && - virDomainDiskGetFormat(disk) != VIR_STORAGE_FILE_PLOOP) { + (virDomainDiskGetFormat(disk) != VIR_STORAGE_FILE_PLOOP && + virDomainDiskGetFormat(disk) != VIR_STORAGE_FILE_NONE)) {
Virtual machines in vz7 use only qcow2, so we should accept VIR_STORAGE_FILE_PLOOP for containers and qcow2 for VMs.
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Invalid format of " - "disk %s, vz driver supports only " - "images in ploop format."), disk->src->path); + "disk %s, it should be either not set or " + "ploop format."), disk-
src->path); goto cleanup; } @@ -3218,11 +3220,13 @@ static int prlsdkAddDisk(PRL_HANDLE sdkdom, pret = PrlVmDev_SetEmulatedType(sdkdisk, emutype); prlsdkCheckRetGoto(pret, cleanup); - pret = PrlVmDev_SetSysName(sdkdisk, disk->src->path); - prlsdkCheckRetGoto(pret, cleanup); + if (disk->src->path != NULL) { + pret = PrlVmDev_SetSysName(sdkdisk, disk->src->path); + prlsdkCheckRetGoto(pret, cleanup); - pret = PrlVmDev_SetFriendlyName(sdkdisk, disk->src->path); - prlsdkCheckRetGoto(pret, cleanup); + pret = PrlVmDev_SetFriendlyName(sdkdisk, disk->src->path); + prlsdkCheckRetGoto(pret, cleanup); + } drive = &disk->info.addr.drive; if (drive->controller > 0) {

This patch implements functionality of boot device order based on boot element from os section in XML. Now we support boot from CDROM and HDD. If we have several devices of the same type (for example hdd0 and hdd1), than we mark the first one as bootable. --- diff from v1: Move this commit to patch series src/vz/vz_sdk.c | 111 +++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 81 insertions(+), 30 deletions(-) diff --git a/src/vz/vz_sdk.c b/src/vz/vz_sdk.c index 1fcfb2e..4cf9871 100644 --- a/src/vz/vz_sdk.c +++ b/src/vz/vz_sdk.c @@ -2212,6 +2212,78 @@ prlsdkAddDeviceToBootList(PRL_HANDLE sdkdom, return -1; } +static int +prlsdkSetBootDevices(PRL_HANDLE sdkdom, + virDomainDefPtr def) +{ + size_t i; + PRL_RESULT pret; + PRL_HANDLE devList = PRL_INVALID_HANDLE; + PRL_HANDLE dev = PRL_INVALID_HANDLE; + PRL_DEVICE_TYPE currentDevType, bootDevType; + PRL_UINT32 devIndex, devCount, j; + PRL_UINT32 bootSequence = 0; + bool rootMount = false; + + pret = PrlVmCfg_GetAllDevices(sdkdom, &devList); + prlsdkCheckRetGoto(pret, error); + + pret = PrlHndlList_GetItemsCount(devList, &devCount); + prlsdkCheckRetGoto(pret, error); + + for (i = 0; i < def->os.nBootDevs; i++) { + switch (def->os.bootDevs[i]) { + case VIR_DOMAIN_BOOT_CDROM: + bootDevType = PDE_OPTICAL_DISK; + break; + case VIR_DOMAIN_BOOT_DISK: + bootDevType = PDE_HARD_DISK; + break; + default: + continue; + } + + for (j = 0; j < devCount; j++) { + pret = PrlHndlList_GetItem(devList, j, &dev); + prlsdkCheckRetGoto(pret, error); + + pret = PrlVmDev_GetType(dev, ¤tDevType); + prlsdkCheckRetGoto(pret, error); + + if (currentDevType == bootDevType) { + pret = PrlVmDev_GetIndex(dev, &devIndex); + prlsdkCheckRetGoto(pret, error); + + if (prlsdkAddDeviceToBootList(sdkdom, devIndex, currentDevType, bootSequence) < 0) + goto error; + bootSequence++; + + if (IS_CT(def) && !rootMount) { + /* If we add physical device as a boot disk to container + we have to specify mount point for it */ + pret = PrlVmDevHd_SetMountPoint(dev, "/"); + prlsdkCheckRetGoto(pret, error); + rootMount = true; + } + } + PrlHandle_Free(dev); + dev = PRL_INVALID_HANDLE; + } + } + + PrlHandle_Free(devList); + return 0; + + error: + if (dev != PRL_INVALID_HANDLE) + PrlHandle_Free(dev); + + if (devList != PRL_INVALID_HANDLE) + PrlHandle_Free(devList); + + return -1; +} + static int prlsdkCheckGraphicsUnsupportedParams(virDomainDefPtr def) { virDomainGraphicsDefPtr gr; @@ -3159,9 +3231,7 @@ static int prlsdkDelDisk(PRL_HANDLE sdkdom, int idx) } static int prlsdkAddDisk(PRL_HANDLE sdkdom, - virDomainDiskDefPtr disk, - bool bootDisk, - bool isCt) + virDomainDiskDefPtr disk) { PRL_RESULT pret; PRL_HANDLE sdkdisk = PRL_INVALID_HANDLE; @@ -3170,7 +3240,6 @@ static int prlsdkAddDisk(PRL_HANDLE sdkdom, PRL_MASS_STORAGE_INTERFACE_TYPE sdkbus; int idx; virDomainDeviceDriveAddressPtr drive; - PRL_UINT32 devIndex; PRL_DEVICE_TYPE devType; char *dst = NULL; @@ -3319,21 +3388,6 @@ static int prlsdkAddDisk(PRL_HANDLE sdkdom, goto cleanup; } - if (bootDisk) { - pret = PrlVmDev_GetIndex(sdkdisk, &devIndex); - prlsdkCheckRetGoto(pret, cleanup); - - if (prlsdkAddDeviceToBootList(sdkdom, devIndex, devType, 0) < 0) - goto cleanup; - - /* If we add physical device as a boot disk to container - * we have to specify mount point for it */ - if (isCt) { - pret = PrlVmDevHd_SetMountPoint(sdkdisk, "/"); - prlsdkCheckRetGoto(pret, cleanup); - } - } - return 0; cleanup: PrlHandle_Free(sdkdisk); @@ -3352,7 +3406,7 @@ prlsdkAttachVolume(virDomainObjPtr dom, virDomainDiskDefPtr disk) if (PRL_FAILED(waitJob(job))) goto cleanup; - ret = prlsdkAddDisk(privdom->sdkdom, disk, false, IS_CT(dom->def)); + ret = prlsdkAddDisk(privdom->sdkdom, disk); if (ret == 0) { job = PrlVm_CommitEx(privdom->sdkdom, PVCF_DETACH_HDD_BUNDLE); if (PRL_FAILED(waitJob(job))) { @@ -3490,7 +3544,7 @@ prlsdkDoApplyConfig(virConnectPtr conn, PRL_RESULT pret; size_t i; char uuidstr[VIR_UUID_STRING_BUFLEN + 2]; - bool needBoot = true; + bool rootfsFound = false; char *mask = NULL; if (prlsdkCheckUnsupportedParams(sdkdom, def) < 0) @@ -3576,21 +3630,18 @@ prlsdkDoApplyConfig(virConnectPtr conn, goto error; } if (STREQ(def->fss[i]->dst, "/")) - needBoot = false; + rootfsFound = true; if (prlsdkAddFS(sdkdom, def->fss[i]) < 0) goto error; } for (i = 0; i < def->ndisks; i++) { - bool bootDisk = false; - - if (needBoot && - def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_DISK) { + if (prlsdkAddDisk(sdkdom, def->disks[i]) < 0) + goto error; + } - needBoot = false; - bootDisk = true; - } - if (prlsdkAddDisk(sdkdom, def->disks[i], bootDisk, IS_CT(def)) < 0) + if (!rootfsFound && !useCtTemplateFs) { + if (prlsdkSetBootDevices(sdkdom, def) < 0) goto error; } -- 1.8.3.1

On Tue, 2015-12-15 at 14:43 +0300, Mikhail Feoktistov wrote:
This patch implements functionality of boot device order based on boot element from os section in XML. Now we support boot from CDROM and HDD. If we have several devices of the same type (for example hdd0 and hdd1), than we mark the first one as bootable. --- diff from v1: Move this commit to patch series
src/vz/vz_sdk.c | 111 +++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 81 insertions(+), 30 deletions(-)
diff --git a/src/vz/vz_sdk.c b/src/vz/vz_sdk.c index 1fcfb2e..4cf9871 100644 --- a/src/vz/vz_sdk.c +++ b/src/vz/vz_sdk.c @@ -2212,6 +2212,78 @@ prlsdkAddDeviceToBootList(PRL_HANDLE sdkdom, return -1; } +static int +prlsdkSetBootDevices(PRL_HANDLE sdkdom, + virDomainDefPtr def) +{ + size_t i; + PRL_RESULT pret; + PRL_HANDLE devList = PRL_INVALID_HANDLE; + PRL_HANDLE dev = PRL_INVALID_HANDLE; + PRL_DEVICE_TYPE currentDevType, bootDevType; + PRL_UINT32 devIndex, devCount, j; + PRL_UINT32 bootSequence = 0; + bool rootMount = false; + + pret = PrlVmCfg_GetAllDevices(sdkdom, &devList); + prlsdkCheckRetGoto(pret, error); + + pret = PrlHndlList_GetItemsCount(devList, &devCount); + prlsdkCheckRetGoto(pret, error); + + for (i = 0; i < def->os.nBootDevs; i++) { + switch (def->os.bootDevs[i]) { + case VIR_DOMAIN_BOOT_CDROM: + bootDevType = PDE_OPTICAL_DISK; + break; + case VIR_DOMAIN_BOOT_DISK: + bootDevType = PDE_HARD_DISK; + break; + default: + continue; + } + + for (j = 0; j < devCount; j++) { + pret = PrlHndlList_GetItem(devList, j, &dev); + prlsdkCheckRetGoto(pret, error); + + pret = PrlVmDev_GetType(dev, ¤tDevType); + prlsdkCheckRetGoto(pret, error); + + if (currentDevType == bootDevType) { + pret = PrlVmDev_GetIndex(dev, &devIndex); + prlsdkCheckRetGoto(pret, error); + + if (prlsdkAddDeviceToBootList(sdkdom, devIndex, currentDevType, bootSequence) < 0) + goto error; + bootSequence++; +
Unfortunately it's not that simple. Here is paragraph from libvirt docs: The dev attribute takes one of the values "fd", "hd", "cdrom" or "network" and is used to specify the next boot device to consider. The boot element can be repeated multiple times to setup a priority list of boot devices to try in turn. Multiple devices of the same type are sorted according to their targets while preserving the order of buses. After defining the domain, its XML configuration returned by libvirt (through virDomainGetXMLDesc) lists devices in the sorted order. Once sorted, the first device is marked as bootable. Thus, e.g., a domain configured to boot from "hd" with vdb, hda, vda, and hdc disks assigned to it will boot from vda (the sorted list is vda, vdb, hda, hdc). Similar domain with hdc, vda, vdb, and hda disks will boot from hda (sorted disks are: hda, hdc, vda, vdb). It can be tricky to configure in the desired way, which is why per-device boot elements (see disks, network interfaces, and USB and PCI devices sections below) were introduced and they are the preferred way providing full control over booting order. The boot element and per-device boot elements are mutually exclusive. Since 0.1.3, per- device boot since 0.8.8 I think it'd simpler to fix virt-manager to use new per-device boot order feature.
+ if (IS_CT(def) && !rootMount) { + /* If we add physical device as a boot disk to container + we have to specify mount point for it */ + pret = PrlVmDevHd_SetMountPoint(dev, "/"); + prlsdkCheckRetGoto(pret, error); + rootMount = true; + } + } + PrlHandle_Free(dev); + dev = PRL_INVALID_HANDLE; + } + } + + PrlHandle_Free(devList); + return 0; + + error: + if (dev != PRL_INVALID_HANDLE) + PrlHandle_Free(dev); + + if (devList != PRL_INVALID_HANDLE) + PrlHandle_Free(devList); + + return -1; +} + static int prlsdkCheckGraphicsUnsupportedParams(virDomainDefPtr def) { virDomainGraphicsDefPtr gr; @@ -3159,9 +3231,7 @@ static int prlsdkDelDisk(PRL_HANDLE sdkdom, int idx) } static int prlsdkAddDisk(PRL_HANDLE sdkdom, - virDomainDiskDefPtr disk, - bool bootDisk, - bool isCt) + virDomainDiskDefPtr disk) { PRL_RESULT pret; PRL_HANDLE sdkdisk = PRL_INVALID_HANDLE; @@ -3170,7 +3240,6 @@ static int prlsdkAddDisk(PRL_HANDLE sdkdom, PRL_MASS_STORAGE_INTERFACE_TYPE sdkbus; int idx; virDomainDeviceDriveAddressPtr drive; - PRL_UINT32 devIndex; PRL_DEVICE_TYPE devType; char *dst = NULL; @@ -3319,21 +3388,6 @@ static int prlsdkAddDisk(PRL_HANDLE sdkdom, goto cleanup; } - if (bootDisk) { - pret = PrlVmDev_GetIndex(sdkdisk, &devIndex); - prlsdkCheckRetGoto(pret, cleanup); - - if (prlsdkAddDeviceToBootList(sdkdom, devIndex, devType, 0) < 0) - goto cleanup; - - /* If we add physical device as a boot disk to container - * we have to specify mount point for it */ - if (isCt) { - pret = PrlVmDevHd_SetMountPoint(sdkdisk, "/"); - prlsdkCheckRetGoto(pret, cleanup); - } - } - return 0; cleanup: PrlHandle_Free(sdkdisk); @@ -3352,7 +3406,7 @@ prlsdkAttachVolume(virDomainObjPtr dom, virDomainDiskDefPtr disk) if (PRL_FAILED(waitJob(job))) goto cleanup; - ret = prlsdkAddDisk(privdom->sdkdom, disk, false, IS_CT(dom->def)); + ret = prlsdkAddDisk(privdom->sdkdom, disk); if (ret == 0) { job = PrlVm_CommitEx(privdom->sdkdom, PVCF_DETACH_HDD_BUNDLE); if (PRL_FAILED(waitJob(job))) { @@ -3490,7 +3544,7 @@ prlsdkDoApplyConfig(virConnectPtr conn, PRL_RESULT pret; size_t i; char uuidstr[VIR_UUID_STRING_BUFLEN + 2]; - bool needBoot = true; + bool rootfsFound = false; char *mask = NULL; if (prlsdkCheckUnsupportedParams(sdkdom, def) < 0) @@ -3576,21 +3630,18 @@ prlsdkDoApplyConfig(virConnectPtr conn, goto error; } if (STREQ(def->fss[i]->dst, "/")) - needBoot = false; + rootfsFound = true; if (prlsdkAddFS(sdkdom, def->fss[i]) < 0) goto error; } for (i = 0; i < def->ndisks; i++) { - bool bootDisk = false; - - if (needBoot && - def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_DISK) { + if (prlsdkAddDisk(sdkdom, def->disks[i]) < 0) + goto error; + } - needBoot = false; - bootDisk = true; - } - if (prlsdkAddDisk(sdkdom, def->disks[i], bootDisk, IS_CT(def)) < 0) + if (!rootfsFound && !useCtTemplateFs) { + if (prlsdkSetBootDevices(sdkdom, def) < 0) goto error; }
participants (2)
-
Dmitry Guryanov
-
Mikhail Feoktistov