[libvirt] [PATCH 3/3] vz: support boot order in domain xml dump

Maxim Nestratov mnestratov at virtuozzo.com
Thu Apr 7 09:54:22 UTC 2016


22.03.2016 16:56, Nikolay Shirokovskiy пишет:
> 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 at 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;
> +        }
> +

This check doesn't work because boot indexes are not necessarily 
continuous. The only condition we should check here is that they should 
be growing.

I added the following chunk to your code and if you don't mind I can 
squash it to your patch and push.

@@ -1432,7 +1432,7 @@ prlsdkConvertBootOrder(PRL_HANDLE sdkdom, 
virDomainDefPtr def)
      PRL_BOOL inUse;
      PRL_DEVICE_TYPE sdkType;
      virDomainBootOrder type;
-    PRL_UINT32 bootIndex, sdkIndex;
+    PRL_UINT32 prevBootIndex = 0, bootIndex, sdkIndex;
      int bootUsage[VIR_DOMAIN_BOOT_LAST] = { 0 };
      size_t i;

@@ -1463,11 +1463,12 @@ prlsdkConvertBootOrder(PRL_HANDLE sdkdom, 
virDomainDefPtr def)
          prlsdkCheckRetGoto(pret, cleanup);

          /* bootIndex is started from 1 */
-        if (bootIndex != i + 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);

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




More information about the libvir-list mailing list