int virNodeDeviceDestroy (virNodeDevicePtr dev);
+virNodeDevicePtr virNodeDeviceDefineXML(virConnectPtr conn,
+ const char *xmlDesc,
+ unsigned int flags);
+
/**
* VIR_NODE_DEVICE_EVENT_CALLBACK:
*
typedef int
(*virDrvNodeDeviceDestroy)(virNodeDevicePtr dev);
+typedef virNodeDevicePtr
+(*virDrvNodeDeviceDefineXML)(virConnectPtr conn,
+ const char *xmlDesc,
+ unsigned int flags);
+
typedef int
(*virDrvConnectNodeDeviceEventRegisterAny)(virConnectPtr conn,
virNodeDevicePtr dev,
virDrvNodeDeviceListCaps nodeDeviceListCaps;
virDrvNodeDeviceCreateXML nodeDeviceCreateXML;
virDrvNodeDeviceDestroy nodeDeviceDestroy;
+ virDrvNodeDeviceDefineXML nodeDeviceDefineXML;
};
}
+/**
+ * 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
virDomainStartDirtyRateCalc;
} LIBVIRT_7.1.0;
+LIBVIRT_7.3.0 {
+ global:
+ virNodeDeviceDefineXML;
+} LIBVIRT_7.2.0;
+
# .... define new API here using predicted next version number ....
}
+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)
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,
int
nodeDeviceDestroy(virNodeDevicePtr dev);
+virNodeDevice*
+nodeDeviceDefineXML(virConnect *conn,
+ const char *xmlDesc,
+ unsigned int flags);
+
int
nodeConnectNodeDeviceEventRegisterAny(virConnectPtr conn,
virNodeDevicePtr dev,
.nodeDeviceListCaps = nodeDeviceListCaps, /* 0.7.3 */
.nodeDeviceCreateXML = nodeDeviceCreateXML, /* 0.7.3 */
.nodeDeviceDestroy = nodeDeviceDestroy, /* 0.7.3 */
+ .nodeDeviceDefineXML = nodeDeviceDefineXML, /* 7.2.0 */
};
.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 */
};
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:
* @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
};
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;
};
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,
};
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");