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;