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 <jjongsma@xxxxxxxxxx> > --- > 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 <eskultet@xxxxxxxxxx>