This interface allows you to undefine a persistently defined (but
inactive) mediated devices. It is implemented via 'mdevctl'
Signed-off-by: Jonathon Jongsma <jjongsma(a)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 | 73 +++++++++++++++++++
src/node_device/node_device_driver.h | 7 ++
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 +
.../nodedevmdevctldata/mdevctl-undefine.argv | 1 +
tests/nodedevmdevctltest.c | 8 ++
14 files changed, 158 insertions(+), 2 deletions(-)
create mode 100644 tests/nodedevmdevctldata/mdevctl-undefine.argv
diff --git a/include/libvirt/libvirt-nodedev.h b/include/libvirt/libvirt-nodedev.h
index 33eb46b3cd..623017f1fd 100644
--- a/include/libvirt/libvirt-nodedev.h
+++ b/include/libvirt/libvirt-nodedev.h
@@ -135,6 +135,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 64a0a7c473..c352462dda 100644
--- a/src/driver-nodedev.h
+++ b/src/driver-nodedev.h
@@ -79,6 +79,9 @@ typedef virNodeDevice*
const char *xmlDesc,
unsigned int flags);
+typedef int
+(*virDrvNodeDeviceUndefine)(virNodeDevice *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 cfc0c9de5b..1d397c6610 100644
--- a/src/libvirt-nodedev.c
+++ b/src/libvirt-nodedev.c
@@ -779,6 +779,42 @@ virNodeDeviceDefineXML(virConnect *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(virNodeDevice *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 3d8176351c..99b46587b9 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -888,6 +888,7 @@ LIBVIRT_7.2.0 {
global:
virDomainStartDirtyRateCalc;
virNodeDeviceDefineXML;
+ virNodeDeviceUndefine;
} 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 418faa9fb9..48b4b1f438 100644
--- a/src/node_device/node_device_driver.c
+++ b/src/node_device/node_device_driver.c
@@ -889,6 +889,18 @@ nodeDeviceGetMdevctlStopCommand(const char *uuid, char **errmsg)
}
+virCommand*
+nodeDeviceGetMdevctlUndefineCommand(const char *uuid, char **errmsg)
+{
+ virCommand *cmd = virCommandNewArgList(MDEVCTL,
+ "undefine",
+ "-u",
+ uuid,
+ NULL);
+ virCommandSetErrorBuffer(cmd, errmsg);
+ return cmd;
+}
+
static int
virMdevctlStop(virNodeDeviceDefPtr def, char **errmsg)
{
@@ -904,6 +916,22 @@ virMdevctlStop(virNodeDeviceDefPtr def, char **errmsg)
}
+static int
+virMdevctlUndefine(virNodeDeviceDef *def, char **errmsg)
+{
+ int status;
+ g_autoptr(virCommand) cmd = NULL;
+
+ cmd = nodeDeviceGetMdevctlUndefineCommand(def->caps->data.mdev.uuid,
+ errmsg);
+
+ if (virCommandRun(cmd, &status) < 0 || status != 0)
+ return -1;
+
+ return 0;
+}
+
+
virCommand*
nodeDeviceGetMdevctlListCommand(bool defined,
char **output)
@@ -1183,6 +1211,51 @@ nodeDeviceDefineXML(virConnect *conn,
}
+int
+nodeDeviceUndefine(virNodeDevice *device)
+{
+ int ret = -1;
+ virNodeDeviceObj *obj = NULL;
+ virNodeDeviceDef *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 (!virNodeDeviceObjIsPersistent(obj)) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ _("Node device '%s' is not defined"),
+ def->name);
+ goto cleanup;
+ }
+
+ if (nodeDeviceHasCapability(def, VIR_NODE_DEV_CAP_MDEV)) {
+ g_autofree char *errmsg = NULL;
+
+ if (virMdevctlUndefine(def, &errmsg) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Unable to undefine mediated device: %s"),
+ errmsg && errmsg[0] ? errmsg : "Unknown
Error");
+ 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 f626e9ac8a..92bb72ee5d 100644
--- a/src/node_device/node_device_driver.h
+++ b/src/node_device/node_device_driver.h
@@ -107,6 +107,9 @@ nodeDeviceDefineXML(virConnect *conn,
const char *xmlDesc,
unsigned int flags);
+int
+nodeDeviceUndefine(virNodeDevice *dev);
+
int
nodeConnectNodeDeviceEventRegisterAny(virConnectPtr conn,
virNodeDevicePtr dev,
@@ -132,6 +135,10 @@ virCommandPtr
nodeDeviceGetMdevctlStopCommand(const char *uuid,
char **errmsg);
+virCommand*
+nodeDeviceGetMdevctlUndefineCommand(const char *uuid,
+ char **errmsg);
+
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 9de658cab5..b870446c55 100644
--- a/src/node_device/node_device_udev.c
+++ b/src/node_device/node_device_udev.c
@@ -2322,6 +2322,7 @@ static virNodeDeviceDriver udevNodeDeviceDriver = {
.nodeDeviceCreateXML = nodeDeviceCreateXML, /* 0.7.3 */
.nodeDeviceDestroy = nodeDeviceDestroy, /* 0.7.3 */
.nodeDeviceDefineXML = nodeDeviceDefineXML, /* 7.2.0 */
+ .nodeDeviceUndefine = nodeDeviceUndefine, /* 7.2.0 */
};
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 15c592b5b5..d3e21ea797 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -8697,6 +8697,7 @@ static virNodeDeviceDriver node_device_driver = {
.nodeDeviceListCaps = remoteNodeDeviceListCaps, /* 0.5.0 */
.nodeDeviceCreateXML = remoteNodeDeviceCreateXML, /* 0.6.3 */
.nodeDeviceDefineXML = remoteNodeDeviceDefineXML, /* 7.2.0 */
+ .nodeDeviceUndefine = remoteNodeDeviceUndefine, /* 7.2.0 */
.nodeDeviceDestroy = remoteNodeDeviceDestroy /* 0.6.3 */
};
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
index a95ed65f12..10d4233d69 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -2154,6 +2154,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:
@@ -6760,5 +6764,13 @@ enum remote_procedure {
* @generate: both
* @acl: node_device:write
*/
- REMOTE_PROC_NODE_DEVICE_DEFINE_XML = 428
+ REMOTE_PROC_NODE_DEVICE_DEFINE_XML = 428,
+
+ /**
+ * @generate: both
+ * @priority: high
+ * @acl: node_device:delete
+ */
+ REMOTE_PROC_NODE_DEVICE_UNDEFINE = 429
+
};
diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs
index 3488659da1..792e858770 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;
};
@@ -3613,4 +3616,5 @@ enum remote_procedure {
REMOTE_PROC_DOMAIN_GET_MESSAGES = 426,
REMOTE_PROC_DOMAIN_START_DIRTY_RATE_CALC = 427,
REMOTE_PROC_NODE_DEVICE_DEFINE_XML = 428,
+ REMOTE_PROC_NODE_DEVICE_UNDEFINE = 429,
};
diff --git a/tests/nodedevmdevctldata/mdevctl-undefine.argv
b/tests/nodedevmdevctldata/mdevctl-undefine.argv
new file mode 100644
index 0000000000..54717455f7
--- /dev/null
+++ b/tests/nodedevmdevctldata/mdevctl-undefine.argv
@@ -0,0 +1 @@
+$MDEVCTL_BINARY$ undefine -u d76a6b78-45ed-4149-a325-005f9abc5281
diff --git a/tests/nodedevmdevctltest.c b/tests/nodedevmdevctltest.c
index 7cf9fa7c67..e471e2e6eb 100644
--- a/tests/nodedevmdevctltest.c
+++ b/tests/nodedevmdevctltest.c
@@ -185,6 +185,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;
}
@@ -422,6 +425,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)
@@ -444,6 +450,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.3