api: add virNodeDeviceDefineXML()

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>
This commit is contained in:
Jonathon Jongsma 2020-05-11 11:40:26 -05:00
parent a48a2abe60
commit 7e386cde1f
11 changed files with 161 additions and 1 deletions

View 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:
*

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

View 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

View 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 ....

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

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

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

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

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

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

View File

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