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(a)redhat.com>
---
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(a)redhat.com>