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;
}