On Fri, Mar 26, 2021 at 11:48:12AM -0500, Jonathon Jongsma wrote:
> With mediated devices, we can now define persistent node devices that
> can be started and stopped. In order to take advantage of this, we need
> an API to define new node devices.
>
> Signed-off-by: Jonathon Jongsma <[email protected]>
> ---
> include/libvirt/libvirt-nodedev.h | 4 ++
> src/driver-nodedev.h | 6 +++
> src/libvirt-nodedev.c | 42 ++++++++++++++++
> src/libvirt_public.syms | 1 +
> src/node_device/node_device_driver.c | 71 ++++++++++++++++++++++++++++
> src/node_device/node_device_driver.h | 5 ++
> src/node_device/node_device_udev.c | 1 +
> src/remote/remote_driver.c | 1 +
> src/remote/remote_protocol.x | 17 ++++++-
> src/remote_protocol-structs | 8 ++++
> src/rpc/gendispatch.pl | 1 +
> 11 files changed, 156 insertions(+), 1 deletion(-)
>
> diff --git a/include/libvirt/libvirt-nodedev.h
> b/include/libvirt/libvirt-nodedev.h
> index 77d814935e..33eb46b3cd 100644
> --- a/include/libvirt/libvirt-nodedev.h
> +++ b/include/libvirt/libvirt-nodedev.h
> @@ -131,6 +131,10 @@ virNodeDevicePtr virNodeDeviceCreateXML
> (virConnectPtr conn,
>
> int virNodeDeviceDestroy (virNodeDevicePtr dev);
>
> +virNodeDevicePtr virNodeDeviceDefineXML(virConnectPtr conn,
> + const char *xmlDesc,
> + unsigned int flags);
> +
> /**
> * VIR_NODE_DEVICE_EVENT_CALLBACK:
> *
> diff --git a/src/driver-nodedev.h b/src/driver-nodedev.h
> index d0fc7f19cf..64a0a7c473 100644
> --- a/src/driver-nodedev.h
> +++ b/src/driver-nodedev.h
> @@ -74,6 +74,11 @@ typedef virNodeDevicePtr
> typedef int
> (*virDrvNodeDeviceDestroy)(virNodeDevicePtr dev);
>
> +typedef virNodeDevice*
> +(*virDrvNodeDeviceDefineXML)(virConnect *conn,
> + const char *xmlDesc,
> + unsigned int flags);
> +
> typedef int
> (*virDrvConnectNodeDeviceEventRegisterAny)(virConnectPtr conn,
> virNodeDevicePtr dev,
> @@ -113,4 +118,5 @@ struct _virNodeDeviceDriver {
> virDrvNodeDeviceListCaps nodeDeviceListCaps;
> virDrvNodeDeviceCreateXML nodeDeviceCreateXML;
> virDrvNodeDeviceDestroy nodeDeviceDestroy;
> + virDrvNodeDeviceDefineXML nodeDeviceDefineXML;
> };
> diff --git a/src/libvirt-nodedev.c b/src/libvirt-nodedev.c
> index fb707b570f..cfc0c9de5b 100644
> --- a/src/libvirt-nodedev.c
> +++ b/src/libvirt-nodedev.c
> @@ -737,6 +737,48 @@ virNodeDeviceDestroy(virNodeDevicePtr dev)
> }
>
>
> +/**
> + * virNodeDeviceDefineXML:
> + * @conn: pointer to the hypervisor connection
> + * @xmlDesc: string containing an XML description of the device to be defined
> + * @flags: extra flags; not used yet, so callers should always pass 0
> + *
> + * Define a new device on the VM host machine, for example, a mediated device
> + *
> + * virNodeDeviceFree should be used to free the resources after the
> + * node device object is no longer needed.
> + *
> + * Returns a node device object if successful, NULL in case of failure
> + */
> +virNodeDevice*
> +virNodeDeviceDefineXML(virConnect *conn,
> + const char *xmlDesc,
> + unsigned int flags)
> +{
> + VIR_DEBUG("conn=%p, xmlDesc=%s, flags=0x%x", conn, NULLSTR(xmlDesc),
> flags);
> +
> + virResetLastError();
> +
> + virCheckConnectReturn(conn, NULL);
> + virCheckReadOnlyGoto(conn->flags, error);
> + virCheckNonNullArgGoto(xmlDesc, error);
> +
> + if (conn->nodeDeviceDriver &&
> + conn->nodeDeviceDriver->nodeDeviceDefineXML) {
> + virNodeDevice *dev =
> conn->nodeDeviceDriver->nodeDeviceDefineXML(conn, xmlDesc, flags);
> + if (dev == NULL)
if (!dev)
goto error;
> + goto error;
> + return dev;
> + }
> +
> + virReportUnsupportedError();
> +
> + error:
> + virDispatchError(conn);
> + return NULL;
> +}
> +
> +
> /**
> * virConnectNodeDeviceEventRegisterAny:
> * @conn: pointer to the connection
> diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
> index 51a3d7265a..3d8176351c 100644
> --- a/src/libvirt_public.syms
> +++ b/src/libvirt_public.syms
> @@ -887,6 +887,7 @@ LIBVIRT_7.1.0 {
> LIBVIRT_7.2.0 {
> global:
> virDomainStartDirtyRateCalc;
> + virNodeDeviceDefineXML;
Obvious note: this will have to be bumped 1 last time :).
> } LIBVIRT_7.1.0;
>
> # .... define new API here using predicted next version number ....
> diff --git a/src/node_device/node_device_driver.c
> b/src/node_device/node_device_driver.c
> index abd45a6eab..418faa9fb9 100644
> --- a/src/node_device/node_device_driver.c
> +++ b/src/node_device/node_device_driver.c
> @@ -776,6 +776,26 @@ virMdevctlStart(virNodeDeviceDefPtr def, char **uuid,
> char **errmsg)
> }
>
>
> +static int
> +virMdevctlDefine(virNodeDeviceDefPtr def, char **uuid, char **errmsg)
> +{
> + int status;
> + g_autoptr(virCommand) cmd = nodeDeviceGetMdevctlDefineCommand(def, uuid,
> errmsg);
newline here^
> + if (!cmd)
> + return -1;
> +
> + /* an auto-generated uuid is returned via stdout if no uuid is specified
> in
> + * the mdevctl args */
> + if (virCommandRun(cmd, &status) < 0 || status != 0)
> + return -1;
> +
> + /* remove newline */
> + *uuid = g_strstrip(*uuid);
> +
> + return 0;
> +}
> +
> +
> static virNodeDevicePtr
> nodeDeviceCreateXMLMdev(virConnectPtr conn,
> virNodeDeviceDefPtr def)
> @@ -1112,6 +1132,57 @@ nodeDeviceDestroy(virNodeDevicePtr device)
> return ret;
> }
>
> +virNodeDevice*
> +nodeDeviceDefineXML(virConnect *conn,
> + const char *xmlDesc,
> + unsigned int flags)
> +{
> + g_autoptr(virNodeDeviceDef) def = NULL;
> + virNodeDevice *device = NULL;
> + const char *virt_type = NULL;
> + g_autofree char *uuid = NULL;
> + g_autofree char *errmsg = NULL;
> +
> + virCheckFlags(0, NULL);
> +
> + if (nodeDeviceWaitInit() < 0)
> + return NULL;
> +
> + virt_type = virConnectGetType(conn);
> +
> + if (!(def = virNodeDeviceDefParseString(xmlDesc, CREATE_DEVICE,
> virt_type)))
> + return NULL;
> +
> + if (virNodeDeviceDefineXMLEnsureACL(conn, def) < 0)
> + return NULL;
> +
> + if (!nodeDeviceHasCapability(def, VIR_NODE_DEV_CAP_MDEV)) {
> + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> + _("Unsupported device type"));
> + return NULL;
> + }
> +
> + if (!def->parent) {
> + virReportError(VIR_ERR_XML_ERROR, "%s",
> + _("cannot define a mediated device without a
> parent"));
> + return NULL;
> + }
> +
> + if (virMdevctlDefine(def, &uuid, &errmsg) < 0) {
> + virReportError(VIR_ERR_INTERNAL_ERROR,
> + _("Unable to define mediated device: %s"),
> + errmsg && errmsg[0] ? errmsg : "Unknown Error");
My comment from 1/30 would apply ^here too.
Reviewed-by: Erik Skultety <[email protected]>