]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
api: add virNodeDeviceDefineXML()
authorJonathon Jongsma <jjongsma@redhat.com>
Mon, 11 May 2020 16:40:26 +0000 (11:40 -0500)
committerJonathon Jongsma <jjongsma@redhat.com>
Wed, 7 Apr 2021 20:10:28 +0000 (15:10 -0500)
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@redhat.com>
Reviewed-by: Erik Skultety <eskultet@redhat.com>
include/libvirt/libvirt-nodedev.h
src/driver-nodedev.h
src/libvirt-nodedev.c
src/libvirt_public.syms
src/node_device/node_device_driver.c
src/node_device/node_device_driver.h
src/node_device/node_device_udev.c
src/remote/remote_driver.c
src/remote/remote_protocol.x
src/remote_protocol-structs
src/rpc/gendispatch.pl

index 77d814935e16a2f28328fb97f8aced5df5a9f4d5..33eb46b3cd34374eee400488aefdef35cd6438e3 100644 (file)
@@ -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:
  *
index d0fc7f19cf73318d93ea33aecadd1325945cbe1f..16d787f3fc5e2e8ed2ae5c9893fb9332039b7344 100644 (file)
@@ -74,6 +74,11 @@ typedef virNodeDevicePtr
 typedef int
 (*virDrvNodeDeviceDestroy)(virNodeDevicePtr dev);
 
+typedef virNodeDevicePtr
+(*virDrvNodeDeviceDefineXML)(virConnectPtr 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;
 };
index fb707b570fb18c8248e80ccd804d5d481b5e3cb8..88f092c35ead545d8d9562e336065c5914318b34 100644 (file)
@@ -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
+ */
+virNodeDevicePtr
+virNodeDeviceDefineXML(virConnectPtr 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)
+            goto error;
+        return dev;
+    }
+
+    virReportUnsupportedError();
+
+ error:
+    virDispatchError(conn);
+    return NULL;
+}
+
+
 /**
  * virConnectNodeDeviceEventRegisterAny:
  * @conn: pointer to the connection
index 51a3d7265a50e38a04f577429dcf6f66494ea8df..41f4aaf0fa92e0df67f478ce2471a0a058fd4c68 100644 (file)
@@ -889,4 +889,9 @@ LIBVIRT_7.2.0 {
         virDomainStartDirtyRateCalc;
 } LIBVIRT_7.1.0;
 
+LIBVIRT_7.3.0 {
+    global:
+        virNodeDeviceDefineXML;
+} LIBVIRT_7.2.0;
+
 # .... define new API here using predicted next version number ....
index de59c71b54eb78b6426858c22f514de64581faaf..64e84e4faf1870ef675028da22797469959ea81c 100644 (file)
@@ -776,6 +776,27 @@ 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);
+
+    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)
@@ -1116,6 +1137,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) {
+        if (errmsg)
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("Unable to define mediated device: %s"), errmsg);
+        return NULL;
+    }
+
+    def->caps->data.mdev.uuid = g_strdup(uuid);
+    mdevGenerateDeviceName(def);
+    device = nodeDeviceFindNewMediatedDevice(conn, uuid);
+
+    return device;
+}
+
+
 
 int
 nodeConnectNodeDeviceEventRegisterAny(virConnectPtr conn,
index 99967fb8102e9e98276a0836c5d27a1d7f11ebf7..15f8a2a2abb497119a15868bc9af2f38d40e0ee2 100644 (file)
@@ -102,6 +102,11 @@ nodeDeviceCreateXML(virConnectPtr conn,
 int
 nodeDeviceDestroy(virNodeDevicePtr dev);
 
+virNodeDevice*
+nodeDeviceDefineXML(virConnect *conn,
+                    const char *xmlDesc,
+                    unsigned int flags);
+
 int
 nodeConnectNodeDeviceEventRegisterAny(virConnectPtr conn,
                                       virNodeDevicePtr dev,
index 8a96681f07e1b96bcfcf1194fda405b320964bf0..20507c73aaabc3144d03f8223cc5b5099aac5902 100644 (file)
@@ -2325,6 +2325,7 @@ static virNodeDeviceDriver udevNodeDeviceDriver = {
     .nodeDeviceListCaps = nodeDeviceListCaps, /* 0.7.3 */
     .nodeDeviceCreateXML = nodeDeviceCreateXML, /* 0.7.3 */
     .nodeDeviceDestroy = nodeDeviceDestroy, /* 0.7.3 */
+    .nodeDeviceDefineXML = nodeDeviceDefineXML, /* 7.2.0 */
 };
 
 
index 62ada08344139e4f49210da8b6699553e46587f4..15c592b5b5405f0cfbb55127c0fb8f4d0d5fd740 100644 (file)
@@ -8696,6 +8696,7 @@ static virNodeDeviceDriver node_device_driver = {
     .nodeDeviceNumOfCaps = remoteNodeDeviceNumOfCaps, /* 0.5.0 */
     .nodeDeviceListCaps = remoteNodeDeviceListCaps, /* 0.5.0 */
     .nodeDeviceCreateXML = remoteNodeDeviceCreateXML, /* 0.6.3 */
+    .nodeDeviceDefineXML = remoteNodeDeviceDefineXML, /* 7.2.0 */
     .nodeDeviceDestroy = remoteNodeDeviceDestroy /* 0.6.3 */
 };
 
index 743c21b3165a871393866629d3f1acb71fc7d6ab..f47b5e6998ac63e7e2fbbd50ecbc20432cb8670f 100644 (file)
@@ -2145,6 +2145,15 @@ struct remote_node_device_destroy_args {
     remote_nonnull_string name;
 };
 
+struct remote_node_device_define_xml_args {
+    remote_nonnull_string xml_desc;
+    unsigned int flags;
+};
+
+struct remote_node_device_define_xml_ret {
+    remote_nonnull_node_device dev;
+};
+
 
 /*
  * Events Register/Deregister:
@@ -6745,5 +6754,11 @@ enum remote_procedure {
      * @generate: both
      * @acl: domain:write
      */
-    REMOTE_PROC_DOMAIN_START_DIRTY_RATE_CALC = 427
+    REMOTE_PROC_DOMAIN_START_DIRTY_RATE_CALC = 427,
+
+    /**
+     * @generate: both
+     * @acl: node_device:write
+     */
+    REMOTE_PROC_NODE_DEVICE_DEFINE_XML = 428
 };
index d13dc81a82ca44449b0cdfad11fdf6d487af77fa..3488659da1c492fdfa457860f733696bf0165c5d 100644 (file)
@@ -1600,6 +1600,13 @@ struct remote_node_device_create_xml_ret {
 struct remote_node_device_destroy_args {
         remote_nonnull_string      name;
 };
+struct remote_node_device_define_xml_args {
+        remote_nonnull_string      xml_desc;
+        u_int                      flags;
+};
+struct remote_node_device_define_xml_ret {
+        remote_nonnull_node_device dev;
+};
 struct remote_connect_domain_event_register_ret {
         int                        cb_registered;
 };
@@ -3605,4 +3612,5 @@ enum remote_procedure {
         REMOTE_PROC_DOMAIN_AUTHORIZED_SSH_KEYS_SET = 425,
         REMOTE_PROC_DOMAIN_GET_MESSAGES = 426,
         REMOTE_PROC_DOMAIN_START_DIRTY_RATE_CALC = 427,
+        REMOTE_PROC_NODE_DEVICE_DEFINE_XML = 428,
 };
index 9dcd8c3e89832cd4d23b224dcce223dd7c6957f4..9f5bf0e3165986f32bc3dd635c8155f0fc3237e8 100755 (executable)
@@ -567,6 +567,7 @@ elsif ($mode eq "server") {
             if ($argtype =~ m/^remote_node_device_/ and
                 !($argtype =~ m/^remote_node_device_lookup_by_name_/) and
                 !($argtype =~ m/^remote_node_device_create_xml_/) and
+                !($argtype =~ m/^remote_node_device_define_xml_/) and
                 !($argtype =~ m/^remote_node_device_lookup_scsi_host_by_wwn_/)) {
                 $has_node_device = 1;
                 push(@vars_list, "virNodeDevicePtr dev = NULL");