[PATCH 1/6] authz: support parsing authz devices

Han Han hhan at redhat.com
Thu Jan 14 10:14:40 UTC 2021


Since authz* objects are supported since qemu 4.0(around fb5c4ebc08) so the
in first patch the
qemu capability flag of authz objects to check if the target qemu support
this feature. And add tests for that
capability.

On Thu, Jan 14, 2021 at 4:39 PM Zihao Chang <changzihao1 at huawei.com> wrote:

> support parsing authz devices, which is like:
> <authzs type="sasl" mode="simple" index='1' identity='test'/>
>
> Signed-off-by: Zihao Chang <changzihao1 at huawei.com>
> ---
>  src/conf/domain_conf.c         | 103 +++++++++++++++++++++++++++++++++
>  src/conf/domain_conf.h         |  28 +++++++++
>  src/conf/domain_validate.c     |   1 +
>  src/conf/virconftypes.h        |   3 +
>  src/libvirt_private.syms       |   2 +
>  src/qemu/qemu_command.c        |   1 +
>  src/qemu/qemu_domain.c         |   1 +
>  src/qemu/qemu_domain_address.c |   2 +
>  src/qemu/qemu_driver.c         |   5 ++
>  src/qemu/qemu_hotplug.c        |   3 +
>  src/qemu/qemu_validate.c       |   1 +
>  11 files changed, 150 insertions(+)
>
> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
> index 349fc28c2a79..d547a93e16cd 100644
> --- a/src/conf/domain_conf.c
> +++ b/src/conf/domain_conf.c
> @@ -302,6 +302,7 @@ VIR_ENUM_IMPL(virDomainDevice,
>                "iommu",
>                "vsock",
>                "audio",
> +              "authz",
>
I disagree the authz* are set as domain device because the authz* are
objects in qemu:
-object authz-simple,id=id,identity=string

While for the devices in libvirt, they usually look like as the following
in qemu cmdline:
-device NAME,...

>  );
>
>  VIR_ENUM_IMPL(virDomainDiskDevice,
> @@ -1331,6 +1332,19 @@ VIR_ENUM_IMPL(virDomainLaunchSecurity,
>                "sev",
>  );
>
> +VIR_ENUM_IMPL(virDomainAuthzType,
> +                VIR_DOMAIN_AUTHZ_TYPE_LAST,
> +                "tls",
> +                "sasl",
> +);
> +VIR_ENUM_IMPL(virDomainAuthzMode,
> +                VIR_DOMAIN_AUTHZ_MODE_LAST,
> +                "simple",
> +                "list",
> +                "listfile",
> +                "pam",
> +);
> +
>  static virClassPtr virDomainObjClass;
>  static virClassPtr virDomainXMLOptionClass;
>  static void virDomainObjDispose(void *obj);
> @@ -2859,6 +2873,14 @@ void virDomainAudioDefFree(virDomainAudioDefPtr def)
>      VIR_FREE(def);
>  }
>
> +void virDomainAuthzDefFree(virDomainAuthzDefPtr def)
> +{
> +    if (!def)
> +        return;
> +    VIR_FREE(def->identity);
> +    VIR_FREE(def);
> +}
> +
>  virDomainSoundDefPtr
>  virDomainSoundDefRemove(virDomainDefPtr def, size_t idx)
>  {
> @@ -3200,6 +3222,9 @@ void virDomainDeviceDefFree(virDomainDeviceDefPtr
> def)
>      case VIR_DOMAIN_DEVICE_AUDIO:
>          virDomainAudioDefFree(def->data.audio);
>          break;
> +    case VIR_DOMAIN_DEVICE_AUTHZ:
> +        virDomainAuthzDefFree(def->data.authz);
> +        break;
>      case VIR_DOMAIN_DEVICE_LAST:
>      case VIR_DOMAIN_DEVICE_NONE:
>          break;
> @@ -4051,6 +4076,7 @@ virDomainDeviceGetInfo(virDomainDeviceDefPtr device)
>      case VIR_DOMAIN_DEVICE_GRAPHICS:
>      case VIR_DOMAIN_DEVICE_IOMMU:
>      case VIR_DOMAIN_DEVICE_AUDIO:
> +    case VIR_DOMAIN_DEVICE_AUTHZ:
>      case VIR_DOMAIN_DEVICE_LAST:
>      case VIR_DOMAIN_DEVICE_NONE:
>          break;
> @@ -4148,6 +4174,9 @@ virDomainDeviceSetData(virDomainDeviceDefPtr device,
>      case VIR_DOMAIN_DEVICE_AUDIO:
>          device->data.audio = devicedata;
>          break;
> +    case VIR_DOMAIN_DEVICE_AUTHZ:
> +        device->data.authz = devicedata;
> +        break;
>      case VIR_DOMAIN_DEVICE_NONE:
>      case VIR_DOMAIN_DEVICE_LAST:
>          break;
> @@ -4410,6 +4439,7 @@ virDomainDeviceInfoIterateFlags(virDomainDefPtr def,
>      case VIR_DOMAIN_DEVICE_IOMMU:
>      case VIR_DOMAIN_DEVICE_VSOCK:
>      case VIR_DOMAIN_DEVICE_AUDIO:
> +    case VIR_DOMAIN_DEVICE_AUTHZ:
>          break;
>      }
>  #endif
> @@ -5393,6 +5423,7 @@
> virDomainDeviceDefPostParseCommon(virDomainDeviceDefPtr dev,
>      case VIR_DOMAIN_DEVICE_MEMORY:
>      case VIR_DOMAIN_DEVICE_IOMMU:
>      case VIR_DOMAIN_DEVICE_AUDIO:
> +    case VIR_DOMAIN_DEVICE_AUTHZ:
>          ret = 0;
>          break;
>
> @@ -15669,6 +15700,44 @@ virDomainVsockDefParseXML(virDomainXMLOptionPtr
> xmlopt,
>      return g_steal_pointer(&vsock);
>  }
>
> +static virDomainAuthzDefPtr
> +virDomainAuthzDefParseXML(xmlNodePtr node)
> +{
> +    g_autofree char *mode = NULL;
> +    g_autofree char *identity = NULL;
> +    g_autofree char *tmp = NULL;
> +    virDomainAuthzDefPtr def;
> +
> +    def = g_new0(virDomainAuthzDef, 1);
> +
> +    if (!(mode = virXMLPropString(node, "mode")))
> +        def->mode = VIR_DOMAIN_AUTHZ_MODE_SIMPLE;
> +
> +    if ((def->mode = virDomainAuthzModeTypeFromString(mode)) < 0) {
> +        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
> +                       _("unknown authz mode: %s"), mode);
> +        goto error;
> +    }
> +
> +    if ((tmp = virXMLPropString(node, "index")) &&
> +        virStrToLong_ulp(tmp, NULL, 10, &def->index) < 0) {
> +        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
> +                       _("invalid authz index: %s"), tmp);
> +        goto error;
> +    }
> +
> +    if (!(def->identity = virXMLPropString(node, "identity"))) {
> +        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> +                       _("authz identity must be set"));
> +        goto error;
> +    }
> +
> +    return def;
> + error:
> +    virDomainAuthzDefFree(def);
> +    return NULL;
> +}
> +
>  virDomainDeviceDefPtr
>  virDomainDeviceDefParse(const char *xmlStr,
>                          const virDomainDef *def,
> @@ -15827,6 +15896,10 @@ virDomainDeviceDefParse(const char *xmlStr,
>                                                            flags)))
>              return NULL;
>          break;
> +    case VIR_DOMAIN_DEVICE_AUTHZ:
> +        if (!(dev->data.authz = virDomainAuthzDefParseXML(node)))
> +            return NULL;
> +        break;
>      case VIR_DOMAIN_DEVICE_NONE:
>      case VIR_DOMAIN_DEVICE_LAST:
>          break;
> @@ -20704,6 +20777,20 @@ virDomainDefParseXML(xmlDocPtr xml,
>      }
>      VIR_FREE(nodes);
>
> +    /* analysis of the authz devices */
> +    if ((n = virXPathNodeSet("./devices/authz", ctxt, &nodes)) < 0)
> +        goto error;
> +    if (n)
> +        def->authzs = g_new0(virDomainAuthzDefPtr, n);
> +
> +    for (i = 0; i < n; i++) {
> +        virDomainAuthzDefPtr authzs = virDomainAuthzDefParseXML(nodes[i]);
> +        if (!authzs)
> +            goto error;
> +        def->authzs[def->nauthzs++] = authzs;
> +    }
> +    VIR_FREE(nodes);
> +
>      /* analysis of the graphics devices */
>      if ((n = virXPathNodeSet("./devices/graphics", ctxt, &nodes)) < 0)
>          goto error;
> @@ -23371,6 +23458,7 @@ virDomainDefCheckABIStabilityFlags(virDomainDefPtr
> src,
>      case VIR_DOMAIN_DEVICE_IOMMU:
>      case VIR_DOMAIN_DEVICE_VSOCK:
>      case VIR_DOMAIN_DEVICE_AUDIO:
> +    case VIR_DOMAIN_DEVICE_AUTHZ:
>          break;
>      }
>  #endif
> @@ -26217,6 +26305,18 @@ virDomainAudioDefFormat(virBufferPtr buf,
>  }
>
>
> +static int
> +virDomainAuthzDefFormat(virBufferPtr buf,
> +                        virDomainAuthzDefPtr def)
> +{
> +    virBufferAsprintf(buf, "<authz mode='%s' index='%lu'
> identity='%s'/>\n",
> +                      virDomainAuthzModeTypeToString(def->mode),
> +                      def->index,
> +                      def->identity);
> +    return 0;
> +}
> +
> +
>  static int
>  virDomainMemballoonDefFormat(virBufferPtr buf,
>                               virDomainMemballoonDefPtr def,
> @@ -30045,6 +30145,9 @@ virDomainDeviceDefCopy(virDomainDeviceDefPtr src,
>      case VIR_DOMAIN_DEVICE_AUDIO:
>          rc = virDomainAudioDefFormat(&buf, src->data.audio);
>          break;
> +    case VIR_DOMAIN_DEVICE_AUTHZ:
> +        rc = virDomainAuthzDefFormat(&buf, src->data.authz);
> +        break;
>
>      case VIR_DOMAIN_DEVICE_NONE:
>      case VIR_DOMAIN_DEVICE_SMARTCARD:
> diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
> index ec43bbe18668..01e04250c28b 100644
> --- a/src/conf/domain_conf.h
> +++ b/src/conf/domain_conf.h
> @@ -86,6 +86,7 @@ typedef enum {
>      VIR_DOMAIN_DEVICE_IOMMU,
>      VIR_DOMAIN_DEVICE_VSOCK,
>      VIR_DOMAIN_DEVICE_AUDIO,
> +    VIR_DOMAIN_DEVICE_AUTHZ,
>
>      VIR_DOMAIN_DEVICE_LAST
>  } virDomainDeviceType;
> @@ -118,6 +119,7 @@ struct _virDomainDeviceDef {
>          virDomainIOMMUDefPtr iommu;
>          virDomainVsockDefPtr vsock;
>          virDomainAudioDefPtr audio;
> +        virDomainAuthzDefPtr authz;
>      } data;
>  };
>
> @@ -1461,6 +1463,26 @@ struct _virDomainAudioDef {
>      } backend;
>  };
>
> +typedef enum {
> +    VIR_DOMAIN_AUTHZ_TYPE_TLS,
> +    VIR_DOMAIN_AUTHZ_TYPE_SASL,
> +    VIR_DOMAIN_AUTHZ_TYPE_LAST
> +} virDomainAuthzType;
> +
> +typedef enum {
> +    VIR_DOMAIN_AUTHZ_MODE_SIMPLE,
> +    VIR_DOMAIN_AUTHZ_MODE_LIST,
> +    VIR_DOMAIN_AUTHZ_MODE_LISTFILE,
> +    VIR_DOMAIN_AUTHZ_MODE_PAM,
> +    VIR_DOMAIN_AUTHZ_MODE_LAST
> +} virDomainAuthzMode;
> +
> +struct _virDomainAuthzDef {
> +    int mode;
> +    unsigned long index;
> +    char *identity;
> +};
> +
>  typedef enum {
>      VIR_DOMAIN_WATCHDOG_MODEL_I6300ESB,
>      VIR_DOMAIN_WATCHDOG_MODEL_IB700,
> @@ -2627,6 +2649,9 @@ struct _virDomainDef {
>
>      virDomainClockDef clock;
>
> +    size_t nauthzs;
> +    virDomainAuthzDefPtr *authzs;
> +
>      size_t ngraphics;
>      virDomainGraphicsDefPtr *graphics;
>
> @@ -3108,6 +3133,7 @@ ssize_t virDomainSoundDefFind(const virDomainDef
> *def,
>  void virDomainSoundDefFree(virDomainSoundDefPtr def);
>  virDomainSoundDefPtr virDomainSoundDefRemove(virDomainDefPtr def, size_t
> idx);
>  void virDomainAudioDefFree(virDomainAudioDefPtr def);
> +void virDomainAuthzDefFree(virDomainAuthzDefPtr def);
>  void virDomainMemballoonDefFree(virDomainMemballoonDefPtr def);
>  void virDomainNVRAMDefFree(virDomainNVRAMDefPtr def);
>  void virDomainWatchdogDefFree(virDomainWatchdogDefPtr def);
> @@ -3674,6 +3700,8 @@ VIR_ENUM_DECL(virDomainChrSpicevmc);
>  VIR_ENUM_DECL(virDomainSoundCodec);
>  VIR_ENUM_DECL(virDomainSoundModel);
>  VIR_ENUM_DECL(virDomainAudioType);
> +VIR_ENUM_DECL(virDomainAuthzType);
> +VIR_ENUM_DECL(virDomainAuthzMode);
>  VIR_ENUM_DECL(virDomainKeyWrapCipherName);
>  VIR_ENUM_DECL(virDomainMemballoonModel);
>  VIR_ENUM_DECL(virDomainSmbiosMode);
> diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c
> index 988aff8dd7fe..3b5ddd241b46 100644
> --- a/src/conf/domain_validate.c
> +++ b/src/conf/domain_validate.c
> @@ -1542,6 +1542,7 @@ virDomainDeviceDefValidateInternal(const
> virDomainDeviceDef *dev,
>      case VIR_DOMAIN_DEVICE_TPM:
>      case VIR_DOMAIN_DEVICE_PANIC:
>      case VIR_DOMAIN_DEVICE_IOMMU:
> +    case VIR_DOMAIN_DEVICE_AUTHZ:
>      case VIR_DOMAIN_DEVICE_NONE:
>      case VIR_DOMAIN_DEVICE_LAST:
>          break;
> diff --git a/src/conf/virconftypes.h b/src/conf/virconftypes.h
> index 9042a2b34fb1..697bd60a04e2 100644
> --- a/src/conf/virconftypes.h
> +++ b/src/conf/virconftypes.h
> @@ -96,6 +96,9 @@ typedef virDomainABIStability *virDomainABIStabilityPtr;
>  typedef struct _virDomainActualNetDef virDomainActualNetDef;
>  typedef virDomainActualNetDef *virDomainActualNetDefPtr;
>
> +typedef struct _virDomainAuthzDef virDomainAuthzDef;
> +typedef virDomainAuthzDef *virDomainAuthzDefPtr;
> +
>  typedef struct _virDomainBackupDef virDomainBackupDef;
>  typedef virDomainBackupDef *virDomainBackupDefPtr;
>
> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> index c325040b60bf..e731c12458f7 100644
> --- a/src/libvirt_private.syms
> +++ b/src/libvirt_private.syms
> @@ -228,6 +228,8 @@ virDiskNameToIndex;
>  virDomainActualNetDefFree;
>  virDomainAudioTypeTypeFromString;
>  virDomainAudioTypeTypeToString;
> +virDomainAuthzModeTypeToString;
> +virDomainAuthzTypeTypeToString;
>  virDomainBlockedReasonTypeFromString;
>  virDomainBlockedReasonTypeToString;
>  virDomainBlockIoTuneInfoCopy;
> diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
> index 6f970a312896..d5f0bcb81877 100644
> --- a/src/qemu/qemu_command.c
> +++ b/src/qemu/qemu_command.c
> @@ -546,6 +546,7 @@ qemuBuildVirtioDevStr(virBufferPtr buf,
>          case VIR_DOMAIN_DEVICE_IOMMU:
>          case VIR_DOMAIN_DEVICE_AUDIO:
>          case VIR_DOMAIN_DEVICE_LAST:
> +        case VIR_DOMAIN_DEVICE_AUTHZ:
>          default:
>              return 0;
>      }
> diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
> index 0765dc72d2e2..f83407903e27 100644
> --- a/src/qemu/qemu_domain.c
> +++ b/src/qemu/qemu_domain.c
> @@ -5532,6 +5532,7 @@ qemuDomainDeviceDefPostParse(virDomainDeviceDefPtr
> dev,
>      case VIR_DOMAIN_DEVICE_RNG:
>      case VIR_DOMAIN_DEVICE_IOMMU:
>      case VIR_DOMAIN_DEVICE_AUDIO:
> +    case VIR_DOMAIN_DEVICE_AUTHZ:
>          ret = 0;
>          break;
>
> diff --git a/src/qemu/qemu_domain_address.c
> b/src/qemu/qemu_domain_address.c
> index f0ba318cc844..47aa574e67ca 100644
> --- a/src/qemu/qemu_domain_address.c
> +++ b/src/qemu/qemu_domain_address.c
> @@ -532,6 +532,7 @@ qemuDomainDeviceSupportZPCI(virDomainDeviceDefPtr
> device)
>      case VIR_DOMAIN_DEVICE_IOMMU:
>      case VIR_DOMAIN_DEVICE_VSOCK:
>      case VIR_DOMAIN_DEVICE_AUDIO:
> +    case VIR_DOMAIN_DEVICE_AUTHZ:
>          break;
>
>      case VIR_DOMAIN_DEVICE_NONE:
> @@ -1018,6 +1019,7 @@
> qemuDomainDeviceCalculatePCIConnectFlags(virDomainDeviceDefPtr dev,
>      case VIR_DOMAIN_DEVICE_GRAPHICS:
>      case VIR_DOMAIN_DEVICE_IOMMU:
>      case VIR_DOMAIN_DEVICE_AUDIO:
> +    case VIR_DOMAIN_DEVICE_AUTHZ:
>      case VIR_DOMAIN_DEVICE_LAST:
>      case VIR_DOMAIN_DEVICE_NONE:
>          return 0;
> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
> index 027617deefc7..17ef8451bf34 100644
> --- a/src/qemu/qemu_driver.c
> +++ b/src/qemu/qemu_driver.c
> @@ -7013,6 +7013,7 @@ qemuDomainAttachDeviceLive(virDomainObjPtr vm,
>      case VIR_DOMAIN_DEVICE_PANIC:
>      case VIR_DOMAIN_DEVICE_IOMMU:
>      case VIR_DOMAIN_DEVICE_AUDIO:
> +    case VIR_DOMAIN_DEVICE_AUTHZ:
>      case VIR_DOMAIN_DEVICE_LAST:
>          virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
>                         _("live attach of device '%s' is not supported"),
> @@ -7148,6 +7149,7 @@ qemuDomainUpdateDeviceLive(virDomainObjPtr vm,
>      case VIR_DOMAIN_DEVICE_IOMMU:
>      case VIR_DOMAIN_DEVICE_VSOCK:
>      case VIR_DOMAIN_DEVICE_AUDIO:
> +    case VIR_DOMAIN_DEVICE_AUTHZ:
>      case VIR_DOMAIN_DEVICE_LAST:
>          virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
>                         _("live update of device '%s' is not supported"),
> @@ -7365,6 +7367,7 @@ qemuDomainAttachDeviceConfig(virDomainDefPtr vmdef,
>      case VIR_DOMAIN_DEVICE_PANIC:
>      case VIR_DOMAIN_DEVICE_IOMMU:
>      case VIR_DOMAIN_DEVICE_AUDIO:
> +    case VIR_DOMAIN_DEVICE_AUTHZ:
>      case VIR_DOMAIN_DEVICE_LAST:
>           virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
>                          _("persistent attach of device '%s' is not
> supported"),
> @@ -7568,6 +7571,7 @@ qemuDomainDetachDeviceConfig(virDomainDefPtr vmdef,
>      case VIR_DOMAIN_DEVICE_PANIC:
>      case VIR_DOMAIN_DEVICE_IOMMU:
>      case VIR_DOMAIN_DEVICE_AUDIO:
> +    case VIR_DOMAIN_DEVICE_AUTHZ:
>      case VIR_DOMAIN_DEVICE_LAST:
>          virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
>                         _("persistent detach of device '%s' is not
> supported"),
> @@ -7676,6 +7680,7 @@ qemuDomainUpdateDeviceConfig(virDomainDefPtr vmdef,
>      case VIR_DOMAIN_DEVICE_IOMMU:
>      case VIR_DOMAIN_DEVICE_VSOCK:
>      case VIR_DOMAIN_DEVICE_AUDIO:
> +    case VIR_DOMAIN_DEVICE_AUTHZ:
>      case VIR_DOMAIN_DEVICE_LAST:
>          virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
>                         _("persistent update of device '%s' is not
> supported"),
> diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
> index f336a90c8eb5..49cc461970bc 100644
> --- a/src/qemu/qemu_hotplug.c
> +++ b/src/qemu/qemu_hotplug.c
> @@ -5048,6 +5048,7 @@ qemuDomainRemoveAuditDevice(virDomainObjPtr vm,
>      case VIR_DOMAIN_DEVICE_PANIC:
>      case VIR_DOMAIN_DEVICE_IOMMU:
>      case VIR_DOMAIN_DEVICE_AUDIO:
> +    case VIR_DOMAIN_DEVICE_AUTHZ:
>      case VIR_DOMAIN_DEVICE_LAST:
>          /* libvirt doesn't yet support detaching these devices */
>          break;
> @@ -5147,6 +5148,7 @@ qemuDomainRemoveDevice(virQEMUDriverPtr driver,
>      case VIR_DOMAIN_DEVICE_PANIC:
>      case VIR_DOMAIN_DEVICE_IOMMU:
>      case VIR_DOMAIN_DEVICE_AUDIO:
> +    case VIR_DOMAIN_DEVICE_AUTHZ:
>      case VIR_DOMAIN_DEVICE_LAST:
>          virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
>                         _("don't know how to remove a %s device"),
> @@ -5961,6 +5963,7 @@ qemuDomainDetachDeviceLive(virDomainObjPtr vm,
>      case VIR_DOMAIN_DEVICE_PANIC:
>      case VIR_DOMAIN_DEVICE_IOMMU:
>      case VIR_DOMAIN_DEVICE_AUDIO:
> +    case VIR_DOMAIN_DEVICE_AUTHZ:
>      case VIR_DOMAIN_DEVICE_LAST:
>          virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
>                         _("live detach of device '%s' is not supported"),
> diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c
> index eadf3af8b396..63a7c1789363 100644
> --- a/src/qemu/qemu_validate.c
> +++ b/src/qemu/qemu_validate.c
> @@ -4788,6 +4788,7 @@ qemuValidateDomainDeviceDef(const virDomainDeviceDef
> *dev,
>      case VIR_DOMAIN_DEVICE_LEASE:
>      case VIR_DOMAIN_DEVICE_PANIC:
>      case VIR_DOMAIN_DEVICE_AUDIO:
> +    case VIR_DOMAIN_DEVICE_AUTHZ:
>      case VIR_DOMAIN_DEVICE_NONE:
>      case VIR_DOMAIN_DEVICE_LAST:
>          break;
> --
> 2.28.0
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20210114/725712de/attachment-0001.htm>


More information about the libvir-list mailing list