From 032c5bf988ddd6dc3bbd07692c3def1afb36a461 Mon Sep 17 00:00:00 2001 From: Nikolay Shirokovskiy Date: Tue, 22 Mar 2016 16:56:38 +0300 Subject: [PATCH] vz: support boot order in domain xml dump 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 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' is not less than 'boot position index' 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 Signed-off-by: Maxim Nestratov --- src/vz/vz_sdk.c | 239 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 239 insertions(+) diff --git a/src/vz/vz_sdk.c b/src/vz/vz_sdk.c index 0c2cfa0e63..c0065174a5 100644 --- a/src/vz/vz_sdk.c +++ b/src/vz/vz_sdk.c @@ -1273,6 +1273,241 @@ 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 prevBootIndex = 0, 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 <= prevBootIndex) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Unsupported boot order configuration")); + goto cleanup; + } + prevBootIndex = bootIndex; + + 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 +1563,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;