[libvirt PATCH v3 16/21] api: add virNodeDeviceUndefine()

Jonathon Jongsma jjongsma at redhat.com
Thu Dec 24 14:14:40 UTC 2020


This interface allows you to undefine a persistently defined (but
inactive) mediated devices. It is implemented via 'mdevctl'

Signed-off-by: Jonathon Jongsma <jjongsma at redhat.com>
---
 include/libvirt/libvirt-nodedev.h    |  2 +
 src/access/viraccessperm.c           |  2 +-
 src/access/viraccessperm.h           |  6 +++
 src/driver-nodedev.h                 |  4 ++
 src/libvirt-nodedev.c                | 36 +++++++++++++++
 src/libvirt_public.syms              |  1 +
 src/node_device/node_device_driver.c | 67 ++++++++++++++++++++++++++++
 src/node_device/node_device_driver.h |  6 +++
 src/node_device/node_device_udev.c   |  1 +
 src/remote/remote_driver.c           |  1 +
 src/remote/remote_protocol.x         | 14 +++++-
 src/remote_protocol-structs          |  4 ++
 tests/nodedevmdevctltest.c           |  8 ++++
 13 files changed, 150 insertions(+), 2 deletions(-)

diff --git a/include/libvirt/libvirt-nodedev.h b/include/libvirt/libvirt-nodedev.h
index 3e57e9522a..d9dac97147 100644
--- a/include/libvirt/libvirt-nodedev.h
+++ b/include/libvirt/libvirt-nodedev.h
@@ -136,6 +136,8 @@ virNodeDevicePtr virNodeDeviceDefineXML(virConnectPtr conn,
                                         const char *xmlDesc,
                                         unsigned int flags);
 
+int virNodeDeviceUndefine(virNodeDevicePtr dev);
+
 /**
  * VIR_NODE_DEVICE_EVENT_CALLBACK:
  *
diff --git a/src/access/viraccessperm.c b/src/access/viraccessperm.c
index 33db7752b6..d4a0c98b9b 100644
--- a/src/access/viraccessperm.c
+++ b/src/access/viraccessperm.c
@@ -70,7 +70,7 @@ VIR_ENUM_IMPL(virAccessPermNodeDevice,
               VIR_ACCESS_PERM_NODE_DEVICE_LAST,
               "getattr", "read", "write",
               "start", "stop",
-              "detach",
+              "detach", "delete",
 );
 
 VIR_ENUM_IMPL(virAccessPermNWFilter,
diff --git a/src/access/viraccessperm.h b/src/access/viraccessperm.h
index 42996b9741..051246a7b6 100644
--- a/src/access/viraccessperm.h
+++ b/src/access/viraccessperm.h
@@ -500,6 +500,12 @@ typedef enum {
      */
     VIR_ACCESS_PERM_NODE_DEVICE_DETACH,
 
+    /**
+     * @desc: Delete node device
+     * @message: Deleting node device driver requires authorization
+     */
+    VIR_ACCESS_PERM_NODE_DEVICE_DELETE,
+
     VIR_ACCESS_PERM_NODE_DEVICE_LAST
 } virAccessPermNodeDevice;
 
diff --git a/src/driver-nodedev.h b/src/driver-nodedev.h
index 16d787f3fc..e18029ab48 100644
--- a/src/driver-nodedev.h
+++ b/src/driver-nodedev.h
@@ -79,6 +79,9 @@ typedef virNodeDevicePtr
                              const char *xmlDesc,
                              unsigned int flags);
 
+typedef int
+(*virDrvNodeDeviceUndefine)(virNodeDevicePtr dev);
+
 typedef int
 (*virDrvConnectNodeDeviceEventRegisterAny)(virConnectPtr conn,
                                            virNodeDevicePtr dev,
@@ -119,4 +122,5 @@ struct _virNodeDeviceDriver {
     virDrvNodeDeviceCreateXML nodeDeviceCreateXML;
     virDrvNodeDeviceDestroy nodeDeviceDestroy;
     virDrvNodeDeviceDefineXML nodeDeviceDefineXML;
+    virDrvNodeDeviceUndefine nodeDeviceUndefine;
 };
diff --git a/src/libvirt-nodedev.c b/src/libvirt-nodedev.c
index 15eb70218a..618778517b 100644
--- a/src/libvirt-nodedev.c
+++ b/src/libvirt-nodedev.c
@@ -807,6 +807,42 @@ virNodeDeviceDefineXML(virConnectPtr conn,
 }
 
 
+/**
+ * virNodeDeviceUndefine:
+ * @dev: a device object
+ *
+ * Undefine the device object. The virtual device  is removed from the host
+ * operating system.  This function may require privileged access.
+ *
+ * Returns 0 in case of success and -1 in case of failure.
+ */
+int
+virNodeDeviceUndefine(virNodeDevicePtr dev)
+{
+    VIR_DEBUG("dev=%p", dev);
+
+    virResetLastError();
+
+    virCheckNodeDeviceReturn(dev, -1);
+    virCheckReadOnlyGoto(dev->conn->flags, error);
+
+    if (dev->conn->nodeDeviceDriver &&
+        dev->conn->nodeDeviceDriver->nodeDeviceUndefine) {
+        int retval = dev->conn->nodeDeviceDriver->nodeDeviceUndefine(dev);
+        if (retval < 0)
+            goto error;
+
+        return 0;
+    }
+
+    virReportUnsupportedError();
+
+ error:
+    virDispatchError(dev->conn);
+    return -1;
+}
+
+
 /**
  * virConnectNodeDeviceEventRegisterAny:
  * @conn: pointer to the connection
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index 8fae4352ff..16022a74bf 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -878,6 +878,7 @@ LIBVIRT_6.10.0 {
         virDomainAuthorizedSSHKeysGet;
         virDomainAuthorizedSSHKeysSet;
         virNodeDeviceDefineXML;
+        virNodeDeviceUndefine;
 } LIBVIRT_6.0.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 4fbe8743b4..e38aef0656 100644
--- a/src/node_device/node_device_driver.c
+++ b/src/node_device/node_device_driver.c
@@ -878,6 +878,17 @@ nodeDeviceGetMdevctlStopCommand(const char *uuid)
 
 }
 
+virCommandPtr
+nodeDeviceGetMdevctlUndefineCommand(const char *uuid)
+{
+    return virCommandNewArgList(MDEVCTL,
+                                "undefine",
+                                "-u",
+                                uuid,
+                                NULL);
+
+}
+
 static int
 virMdevctlStop(virNodeDeviceDefPtr def)
 {
@@ -893,6 +904,21 @@ virMdevctlStop(virNodeDeviceDefPtr def)
 }
 
 
+static int
+virMdevctlUndefine(virNodeDeviceDefPtr def)
+{
+    int status;
+    g_autoptr(virCommand) cmd = NULL;
+
+    cmd = nodeDeviceGetMdevctlUndefineCommand(def->caps->data.mdev.uuid);
+
+    if (virCommandRun(cmd, &status) < 0 || status != 0)
+        return -1;
+
+    return 0;
+}
+
+
 virCommandPtr
 nodeDeviceGetMdevctlListCommand(bool defined,
                                 char **output)
@@ -1157,6 +1183,47 @@ nodeDeviceDefineXML(virConnectPtr conn,
 }
 
 
+int
+nodeDeviceUndefine(virNodeDevicePtr device)
+{
+    int ret = -1;
+    virNodeDeviceObjPtr obj = NULL;
+    virNodeDeviceDefPtr def;
+
+    if (nodeDeviceWaitInit() < 0)
+        return -1;
+
+    if (!(obj = nodeDeviceObjFindByName(device->name)))
+        return -1;
+    def = virNodeDeviceObjGetDef(obj);
+
+    if (virNodeDeviceUndefineEnsureACL(device->conn, def) < 0)
+        goto cleanup;
+
+    if (virNodeDeviceObjIsActive(obj)) {
+        virReportError(VIR_ERR_OPERATION_INVALID,
+                       _("node device '%s' is still active"),
+                       def->name);
+        goto cleanup;
+    }
+
+    if (nodeDeviceHasCapability(def, VIR_NODE_DEV_CAP_MDEV)) {
+        if (virMdevctlUndefine(def) < 0) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("Unable to undefine mediated device"));
+            goto cleanup;
+        }
+        ret = 0;
+    } else {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("Unsupported device type"));
+    }
+
+ cleanup:
+    virNodeDeviceObjEndAPI(&obj);
+    return ret;
+}
+
 
 int
 nodeConnectNodeDeviceEventRegisterAny(virConnectPtr conn,
diff --git a/src/node_device/node_device_driver.h b/src/node_device/node_device_driver.h
index e58bb0f124..e06d62cee6 100644
--- a/src/node_device/node_device_driver.h
+++ b/src/node_device/node_device_driver.h
@@ -107,6 +107,9 @@ nodeDeviceDefineXML(virConnectPtr conn,
                     const char *xmlDesc,
                     unsigned int flags);
 
+int
+nodeDeviceUndefine(virNodeDevicePtr dev);
+
 int
 nodeConnectNodeDeviceEventRegisterAny(virConnectPtr conn,
                                       virNodeDevicePtr dev,
@@ -129,6 +132,9 @@ nodeDeviceGetMdevctlDefineCommand(virNodeDeviceDefPtr def,
 virCommandPtr
 nodeDeviceGetMdevctlStopCommand(const char *uuid);
 
+virCommandPtr
+nodeDeviceGetMdevctlUndefineCommand(const char *uuid);
+
 virCommandPtr
 nodeDeviceGetMdevctlListCommand(bool defined, char **output);
 
diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c
index 2532c3189e..d7521a9c18 100644
--- a/src/node_device/node_device_udev.c
+++ b/src/node_device/node_device_udev.c
@@ -2339,6 +2339,7 @@ static virNodeDeviceDriver udevNodeDeviceDriver = {
     .nodeDeviceCreateXML = nodeDeviceCreateXML, /* 0.7.3 */
     .nodeDeviceDestroy = nodeDeviceDestroy, /* 0.7.3 */
     .nodeDeviceDefineXML = nodeDeviceDefineXML, /* 6.5.0 */
+    .nodeDeviceUndefine = nodeDeviceUndefine, /* 6.5.0 */
 };
 
 
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index f826b6f73e..de569b74e5 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -8666,6 +8666,7 @@ static virNodeDeviceDriver node_device_driver = {
     .nodeDeviceListCaps = remoteNodeDeviceListCaps, /* 0.5.0 */
     .nodeDeviceCreateXML = remoteNodeDeviceCreateXML, /* 0.6.3 */
     .nodeDeviceDefineXML = remoteNodeDeviceDefineXML, /* 6.5.0 */
+    .nodeDeviceUndefine = remoteNodeDeviceUndefine, /* 6.5.0 */
     .nodeDeviceDestroy = remoteNodeDeviceDestroy /* 0.6.3 */
 };
 
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
index d2250502b4..7fee7539f0 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -2151,6 +2151,10 @@ struct remote_node_device_define_xml_ret {
     remote_nonnull_node_device dev;
 };
 
+struct remote_node_device_undefine_args {
+    remote_nonnull_string name;
+};
+
 
 /*
  * Events Register/Deregister:
@@ -6729,5 +6733,13 @@ enum remote_procedure {
      * @generate: both
      * @acl: node_device:write
      */
-    REMOTE_PROC_NODE_DEVICE_DEFINE_XML = 426
+    REMOTE_PROC_NODE_DEVICE_DEFINE_XML = 426,
+
+    /**
+     * @generate: both
+     * @priority: high
+     * @acl: node_device:delete
+     */
+    REMOTE_PROC_NODE_DEVICE_UNDEFINE = 427
+
 };
diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs
index 565c1673f1..6d136bdb66 100644
--- a/src/remote_protocol-structs
+++ b/src/remote_protocol-structs
@@ -1607,6 +1607,9 @@ struct remote_node_device_define_xml_args {
 struct remote_node_device_define_xml_ret {
         remote_nonnull_node_device dev;
 };
+struct remote_node_device_undefine_args {
+        remote_nonnull_string      name;
+};
 struct remote_connect_domain_event_register_ret {
         int                        cb_registered;
 };
@@ -3596,4 +3599,5 @@ enum remote_procedure {
         REMOTE_PROC_DOMAIN_AUTHORIZED_SSH_KEYS_GET = 424,
         REMOTE_PROC_DOMAIN_AUTHORIZED_SSH_KEYS_SET = 425,
         REMOTE_PROC_NODE_DEVICE_DEFINE_XML = 426,
+        REMOTE_PROC_NODE_DEVICE_UNDEFINE = 427,
 };
diff --git a/tests/nodedevmdevctltest.c b/tests/nodedevmdevctltest.c
index 56265cfaea..753cfd273e 100644
--- a/tests/nodedevmdevctltest.c
+++ b/tests/nodedevmdevctltest.c
@@ -183,6 +183,9 @@ testMdevctlUuidCommandHelper(const void *data)
     if (info->command == MDEVCTL_CMD_STOP) {
         cmd = "stop";
         func = nodeDeviceGetMdevctlStopCommand;
+    } else if (info->command == MDEVCTL_CMD_UNDEFINE) {
+        cmd = "undefine";
+        func = nodeDeviceGetMdevctlUndefineCommand;
     } else {
         return -1;
     }
@@ -420,6 +423,9 @@ mymain(void)
 #define DO_TEST_STOP(uuid) \
     DO_TEST_UUID_COMMAND_FULL("mdevctl stop " uuid, uuid, MDEVCTL_CMD_STOP)
 
+#define DO_TEST_UNDEFINE(uuid) \
+    DO_TEST_UUID_COMMAND_FULL("mdevctl undefine " uuid, uuid, MDEVCTL_CMD_UNDEFINE)
+
 #define DO_TEST_LIST_DEFINED() \
     DO_TEST_FULL("mdevctl list --defined", testMdevctlListDefined, NULL)
 
@@ -442,6 +448,8 @@ mymain(void)
     DO_TEST_DEFINE("mdev_fedc4916_1ca8_49ac_b176_871d16c13076");
     DO_TEST_DEFINE("mdev_d2441d39_495e_4243_ad9f_beb3f14c23d9");
 
+    DO_TEST_UNDEFINE("d76a6b78-45ed-4149-a325-005f9abc5281");
+
  done:
     nodedevTestDriverFree(driver);
 
-- 
2.26.2




More information about the libvir-list mailing list