As usual we try to deal correctly with vz domains that were
created by other means and thus can have all range of SDK domain
parameters. If vz domain boot order can't be represented
in libvirt os boot section let's give warning and make os boot section
represent SDK to some extent.
1. Os boot section supports up to 4 boot devices. Here we just
cut SDK boot order up to this limit. Not too bad.
2. If there is a floppy in boot order let's just skip it.
Anyway we don't show it in the xml. Not too bad too.
3. SDK boot order with unsupported disks order. Say we have "hdb, hda" in
SDK. We can not present this thru os boot order. Well let's just
give warning but leave double <boot dev='hd'/> in xml. It's
kind of misleading but we warn you!
SDK boot order have an extra parameters 'inUse' and 'sequenceIndex'
which makes our task more complicated. In realitly however 'inUse'
is always on and 'sequenceIndex == boot position index + 1' which
simplifies out task back again! To be on a safe side let's explicitly
check for this conditions!
We have another exercise here. We want to check for unrepresentable
condition 3 (see above). The tricky part is that in contrast to
domains defined thru this driver 3-rd party defined domains can
have device ordering different from default. Thus we need
some id to check that N-th boot disk of os boot section is same as
N-th boot disk of SDK boot. This is what prlsdkBootOrderCheck
for. It uses disks sources paths as id for disks and iface names
for network devices.
Signed-off-by: Nikolay Shirokovskiy <nshirokovskiy(a)virtuozzo.com>
---
src/vz/vz_sdk.c | 238 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 238 insertions(+)
diff --git a/src/vz/vz_sdk.c b/src/vz/vz_sdk.c
index f059a8e..6cecb93 100644
--- a/src/vz/vz_sdk.c
+++ b/src/vz/vz_sdk.c
@@ -1273,6 +1273,240 @@ prlsdkNewDomainByHandle(vzConnPtr privconn, PRL_HANDLE sdkdom)
return dom;
}
+static PRL_HANDLE
+prlsdkGetDevByDevIndex(PRL_HANDLE sdkdom, PRL_DEVICE_TYPE type, PRL_UINT32 devIndex)
+{
+ PRL_RESULT pret;
+ PRL_UINT32 index, num;
+ PRL_HANDLE dev = PRL_INVALID_HANDLE;
+ size_t i;
+
+ pret = PrlVmCfg_GetDevsCountByType(sdkdom, type, &num);
+ prlsdkCheckRetGoto(pret, error);
+
+ for (i = 0; i < num; ++i) {
+ pret = PrlVmCfg_GetDevByType(sdkdom, type, i, &dev);
+ prlsdkCheckRetGoto(pret, error);
+
+ pret = PrlVmDev_GetIndex(dev, &index);
+ prlsdkCheckRetGoto(pret, error);
+
+ if (index == devIndex)
+ break;
+
+ PrlHandle_Free(dev);
+ dev = PRL_INVALID_HANDLE;
+ }
+
+ return dev;
+
+ error:
+ PrlHandle_Free(dev);
+ return PRL_INVALID_HANDLE;
+}
+
+static virDomainDiskDefPtr
+virFindDiskBootIndex(virDomainDefPtr def, virDomainDiskDevice type, int index)
+{
+ size_t i;
+ int c = 0;
+
+ for (i = 0; i < def->ndisks; ++i) {
+ if (def->disks[i]->device != type)
+ continue;
+ if (c == index)
+ return def->disks[i];
+ ++c;
+ }
+
+ return NULL;
+}
+
+static int
+prlsdkBootOrderCheck(PRL_HANDLE sdkdom, PRL_DEVICE_TYPE sdkType, int sdkIndex,
+ virDomainDefPtr def, int bootIndex)
+{
+ PRL_RESULT pret;
+ char *sdkName = NULL;
+ const char *bootName;
+ PRL_UINT32 buflen = 0;
+ PRL_HANDLE dev = PRL_INVALID_HANDLE;
+ virDomainDiskDefPtr disk;
+ virDomainDiskDevice device;
+ int ret = -1;
+
+ dev = prlsdkGetDevByDevIndex(sdkdom, sdkType, sdkIndex);
+ if (dev == PRL_INVALID_HANDLE) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("Can't find boot device of type: %d, device index:
%d"),
+ sdkType, sdkIndex);
+ return -1;
+ }
+
+ switch (sdkType) {
+ case PDE_OPTICAL_DISK:
+ case PDE_HARD_DISK:
+ pret = PrlVmDev_GetFriendlyName(dev, sdkName, &buflen);
+ prlsdkCheckRetGoto(pret, cleanup);
+
+ if (VIR_ALLOC_N(sdkName, buflen) < 0)
+ goto cleanup;
+
+ pret = PrlVmDev_GetFriendlyName(dev, sdkName, &buflen);
+ prlsdkCheckRetGoto(pret, cleanup);
+
+ switch (sdkType) {
+ case PDE_OPTICAL_DISK:
+ device = VIR_DOMAIN_DISK_DEVICE_CDROM;
+ break;
+ case PDE_HARD_DISK:
+ device = VIR_DOMAIN_DISK_DEVICE_DISK;
+ break;
+ default:
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("Unsupported disk type %d"), sdkType);
+ goto cleanup;
+ }
+
+ if (!(disk = virFindDiskBootIndex(def, device, bootIndex))) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("Can find boot device of type: %s, index: %d"),
+ virDomainDiskDeviceTypeToString(device), bootIndex);
+ goto cleanup;
+ }
+
+ bootName = disk->src->path;
+
+ break;
+ case PDE_GENERIC_NETWORK_ADAPTER:
+ pret = PrlVmDevNet_GetHostInterfaceName(dev, NULL, &buflen);
+ prlsdkCheckRetGoto(pret, cleanup);
+
+ if (VIR_ALLOC_N(sdkName, buflen) < 0)
+ goto cleanup;
+
+ pret = PrlVmDevNet_GetHostInterfaceName(dev, sdkName, &buflen);
+ prlsdkCheckRetGoto(pret, cleanup);
+
+ if (bootIndex >= def->nnets) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("Can find network boot device for index: %d"),
+ bootIndex);
+ goto cleanup;
+ }
+
+ bootName = def->nets[bootIndex]->ifname;
+
+ break;
+ default:
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("Unexpected device type %d"), sdkType);
+ goto cleanup;
+ }
+
+ if (STRNEQ(sdkName, bootName))
+ VIR_WARN("Unrepresentable boot order configuration");
+
+ ret = 0;
+
+ cleanup:
+
+ VIR_FREE(sdkName);
+ PrlHandle_Free(dev);
+ return ret;
+}
+
+static int
+prlsdkConvertBootOrder(PRL_HANDLE sdkdom, virDomainDefPtr def)
+{
+ int ret = -1;
+ PRL_RESULT pret;
+ PRL_UINT32 bootNum;
+ PRL_HANDLE bootDev = PRL_INVALID_HANDLE;
+ PRL_BOOL inUse;
+ PRL_DEVICE_TYPE sdkType;
+ virDomainBootOrder type;
+ PRL_UINT32 bootIndex, sdkIndex;
+ int bootUsage[VIR_DOMAIN_BOOT_LAST] = { 0 };
+ size_t i;
+
+ pret = PrlVmCfg_GetBootDevCount(sdkdom, &bootNum);
+ prlsdkCheckRetExit(pret, -1);
+
+ def->os.nBootDevs = 0;
+
+ if (bootNum > VIR_DOMAIN_MAX_BOOT_DEVS) {
+ bootNum = VIR_DOMAIN_MAX_BOOT_DEVS;
+ VIR_WARN("Too many boot devices");
+ }
+
+ for (i = 0; i < bootNum; ++i) {
+ pret = PrlVmCfg_GetBootDev(sdkdom, i, &bootDev);
+ prlsdkCheckRetGoto(pret, cleanup);
+
+ pret = PrlBootDev_IsInUse(bootDev, &inUse);
+ prlsdkCheckRetGoto(pret, cleanup);
+
+ if (!inUse) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Boot ordering with disabled items is not
supported"));
+ goto cleanup;
+ }
+
+ pret = PrlBootDev_GetSequenceIndex(bootDev, &bootIndex);
+ prlsdkCheckRetGoto(pret, cleanup);
+
+ /* bootIndex is started from 1 */
+ if (bootIndex != i + 1) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Unsupported boot order configuration"));
+ goto cleanup;
+ }
+
+ pret = PrlBootDev_GetType(bootDev, &sdkType);
+ prlsdkCheckRetGoto(pret, cleanup);
+
+ if (sdkType == PDE_FLOPPY_DISK) {
+ VIR_WARN("Skipping floppy from boot order.");
+ continue;
+ }
+
+ switch (sdkType) {
+ case PDE_OPTICAL_DISK:
+ type = VIR_DOMAIN_BOOT_CDROM;
+ break;
+ case PDE_HARD_DISK:
+ type = VIR_DOMAIN_BOOT_DISK;
+ break;
+ case PDE_GENERIC_NETWORK_ADAPTER:
+ type = VIR_DOMAIN_BOOT_NET;
+ break;
+ default:
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("Unexpected boot device type %i"), sdkType);
+ goto cleanup;
+ }
+
+ pret = PrlBootDev_GetIndex(bootDev, &sdkIndex);
+ prlsdkCheckRetGoto(pret, cleanup);
+
+ if (prlsdkBootOrderCheck(sdkdom, sdkType, sdkIndex, def, bootUsage[type]) <
0)
+ goto cleanup;
+
+ bootUsage[type]++;
+ def->os.bootDevs[def->os.nBootDevs++] = type;
+
+ PrlHandle_Free(bootDev);
+ bootDev = PRL_INVALID_HANDLE;
+ }
+
+ ret = 0;
+
+ cleanup:
+ PrlHandle_Free(bootDev);
+ return ret;
+}
+
int
prlsdkLoadDomain(vzConnPtr privconn, virDomainObjPtr dom)
{
@@ -1328,6 +1562,10 @@ prlsdkLoadDomain(vzConnPtr privconn, virDomainObjPtr dom)
if (prlsdkAddDomainHardware(privconn, sdkdom, def) < 0)
goto error;
+ /* depends on prlsdkAddDomainHardware */
+ if (prlsdkConvertBootOrder(sdkdom, def) < 0)
+ goto error;
+
if (prlsdkAddVNCInfo(sdkdom, def) < 0)
goto error;
--
1.8.3.1