api: add virNodeDeviceUndefine()

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

Signed-off-by: Jonathon Jongsma <jjongsma@redhat.com>
Reviewed-by: Erik Skultety <eskultet@redhat.com>
This commit is contained in:
Jonathon Jongsma 2020-07-02 15:14:30 -05:00
parent f98c415f8a
commit bb311cede7
14 changed files with 158 additions and 2 deletions

View File

@ -135,6 +135,8 @@ virNodeDevicePtr virNodeDeviceDefineXML(virConnectPtr conn,
const char *xmlDesc,
unsigned int flags);
int virNodeDeviceUndefine(virNodeDevicePtr dev);
/**
* VIR_NODE_DEVICE_EVENT_CALLBACK:
*

View File

@ -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,

View File

@ -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;

View File

@ -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;
};

View File

@ -779,6 +779,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

View File

@ -892,6 +892,7 @@ LIBVIRT_7.2.0 {
LIBVIRT_7.3.0 {
global:
virNodeDeviceDefineXML;
virNodeDeviceUndefine;
} LIBVIRT_7.2.0;
# .... define new API here using predicted next version number ....

View File

@ -891,6 +891,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)
{
@ -906,6 +918,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,
@ -1188,6 +1216,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,

View File

@ -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,

View File

@ -2326,6 +2326,7 @@ static virNodeDeviceDriver udevNodeDeviceDriver = {
.nodeDeviceCreateXML = nodeDeviceCreateXML, /* 0.7.3 */
.nodeDeviceDestroy = nodeDeviceDestroy, /* 0.7.3 */
.nodeDeviceDefineXML = nodeDeviceDefineXML, /* 7.2.0 */
.nodeDeviceUndefine = nodeDeviceUndefine, /* 7.2.0 */
};

View File

@ -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 */
};

View File

@ -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
};

View File

@ -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,
};

View File

@ -0,0 +1 @@
$MDEVCTL_BINARY$ undefine -u d76a6b78-45ed-4149-a325-005f9abc5281

View File

@ -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;
}
@ -423,6 +426,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)
@ -445,6 +451,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);