This public API is implemented for almost all other objects that have
a concept of persistent definition and activatability. Node devices
(mdevs) that can be defined and inactive, it will be useful to be
able to update defined and active node devices as well.
Signed-off-by: Boris Fiuczynski <fiuczy(a)linux.ibm.com>
---
include/libvirt/libvirt-nodedev.h | 18 +++++++++++++
src/access/viraccessperm.c | 1 +
src/access/viraccessperm.h | 6 +++++
src/conf/virnodedeviceobj.c | 42 +++++++++++++++++++++++++++++
src/conf/virnodedeviceobj.h | 3 +++
src/driver-nodedev.h | 6 +++++
src/libvirt-nodedev.c | 45 +++++++++++++++++++++++++++++++
src/libvirt_private.syms | 1 +
src/libvirt_public.syms | 5 ++++
src/remote/remote_driver.c | 1 +
src/remote/remote_protocol.x | 17 +++++++++++-
src/remote_protocol-structs | 6 +++++
12 files changed, 150 insertions(+), 1 deletion(-)
diff --git a/include/libvirt/libvirt-nodedev.h b/include/libvirt/libvirt-nodedev.h
index dff394ec86..c1d3769eaf 100644
--- a/include/libvirt/libvirt-nodedev.h
+++ b/include/libvirt/libvirt-nodedev.h
@@ -188,6 +188,24 @@ int virNodeDeviceIsPersistent(virNodeDevicePtr dev);
int virNodeDeviceIsActive(virNodeDevicePtr dev);
+/**
+ * virNodeDeviceUpdateXMLFlags:
+ *
+ * Flags to control options for virNodeDeviceUpdateXML()
+ *
+ * Since: 10.1.0
+ */
+typedef enum {
+ VIR_NODE_DEVICE_UPDATE_XML_AFFECT_CURRENT = 0, /* affect live if node device is
active,
+ config if it's not active
(Since: 10.1.0) */
+ VIR_NODE_DEVICE_UPDATE_XML_AFFECT_LIVE = 1 << 0, /* affect live state of
node device only (Since: 10.1.0) */
+ VIR_NODE_DEVICE_UPDATE_XML_AFFECT_CONFIG = 1 << 1, /* affect persistent config
only (Since: 10.1.0) */
+} virNodeDeviceUpdateXMLFlags;
+
+int virNodeDeviceUpdateXML(virNodeDevicePtr dev,
+ const char *xmlDesc,
+ unsigned int flags);
+
/**
* VIR_NODE_DEVICE_EVENT_CALLBACK:
*
diff --git a/src/access/viraccessperm.c b/src/access/viraccessperm.c
index d4a0c98b9b..702bee761d 100644
--- a/src/access/viraccessperm.c
+++ b/src/access/viraccessperm.c
@@ -71,6 +71,7 @@ VIR_ENUM_IMPL(virAccessPermNodeDevice,
"getattr", "read", "write",
"start", "stop",
"detach", "delete",
+ "save",
);
VIR_ENUM_IMPL(virAccessPermNWFilter,
diff --git a/src/access/viraccessperm.h b/src/access/viraccessperm.h
index 2f04459ed9..6cc2140c67 100644
--- a/src/access/viraccessperm.h
+++ b/src/access/viraccessperm.h
@@ -507,6 +507,12 @@ typedef enum {
*/
VIR_ACCESS_PERM_NODE_DEVICE_DELETE,
+ /**
+ * @desc: Save node device
+ * @message: Saving node device driver requires authorization
+ */
+ VIR_ACCESS_PERM_NODE_DEVICE_SAVE,
+
VIR_ACCESS_PERM_NODE_DEVICE_LAST
} virAccessPermNodeDevice;
diff --git a/src/conf/virnodedeviceobj.c b/src/conf/virnodedeviceobj.c
index 0b9ca8c864..f185f79322 100644
--- a/src/conf/virnodedeviceobj.c
+++ b/src/conf/virnodedeviceobj.c
@@ -1137,3 +1137,45 @@ virNodeDeviceObjListFind(virNodeDeviceObjList *devs,
virNodeDeviceObjListFindHelper,
&data);
}
+
+
+/**
+ * virNodeDeviceObjUpdateModificationImpact:
+ * @obj: Pointer to node device object
+ * @flags: flags to update the modification impact on
+ *
+ * Resolves virNodeDeviceObjUpdateModificationImpact flags in @flags so that
+ * they correctly apply to the actual state of @obj. @flags may be modified
+ * after call to this function.
+ *
+ * Returns 0 on success if @flags point to a valid combination for @obj or -1
+ * on error.
+ */
+int
+virNodeDeviceObjUpdateModificationImpact(virNodeDeviceObj *obj,
+ unsigned int *flags)
+{
+ bool isActive = virNodeDeviceObjIsActive(obj);
+
+ if ((*flags & (VIR_NODE_DEVICE_UPDATE_XML_AFFECT_LIVE |
VIR_NODE_DEVICE_UPDATE_XML_AFFECT_CONFIG)) ==
+ VIR_NODE_DEVICE_UPDATE_XML_AFFECT_CURRENT) {
+ if (isActive)
+ *flags |= VIR_NODE_DEVICE_UPDATE_XML_AFFECT_LIVE;
+ else
+ *flags |= VIR_NODE_DEVICE_UPDATE_XML_AFFECT_CONFIG;
+ }
+
+ if (!isActive && (*flags & VIR_NODE_DEVICE_UPDATE_XML_AFFECT_LIVE)) {
+ virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("mdev is not active"));
+ return -1;
+ }
+
+ if (!virNodeDeviceObjIsPersistent(obj) && (*flags &
VIR_NODE_DEVICE_UPDATE_XML_AFFECT_CONFIG)) {
+ virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("transient mdevs do not have any persistent
config"));
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/conf/virnodedeviceobj.h b/src/conf/virnodedeviceobj.h
index ba2e424998..43889b8dc8 100644
--- a/src/conf/virnodedeviceobj.h
+++ b/src/conf/virnodedeviceobj.h
@@ -159,3 +159,6 @@ virNodeDeviceObj *
virNodeDeviceObjListFind(virNodeDeviceObjList *devs,
virNodeDeviceObjListPredicate callback,
void *opaque);
+
+int virNodeDeviceObjUpdateModificationImpact(virNodeDeviceObj *obj,
+ unsigned int *flags);
diff --git a/src/driver-nodedev.h b/src/driver-nodedev.h
index 167a8166dd..1c6a731f4e 100644
--- a/src/driver-nodedev.h
+++ b/src/driver-nodedev.h
@@ -101,6 +101,11 @@ typedef int
typedef int
(*virDrvNodeDeviceIsActive)(virNodeDevicePtr dev);
+typedef int
+(*virDrvNodeDeviceUpdateXML)(virNodeDevicePtr dev,
+ const char *xmlDesc,
+ unsigned int flags);
+
typedef int
(*virDrvConnectNodeDeviceEventRegisterAny)(virConnectPtr conn,
virNodeDevicePtr dev,
@@ -146,4 +151,5 @@ struct _virNodeDeviceDriver {
virDrvNodeDeviceGetAutostart nodeDeviceGetAutostart;
virDrvNodeDeviceIsPersistent nodeDeviceIsPersistent;
virDrvNodeDeviceIsActive nodeDeviceIsActive;
+ virDrvNodeDeviceUpdateXML nodeDeviceUpdateXML;
};
diff --git a/src/libvirt-nodedev.c b/src/libvirt-nodedev.c
index 9cc5c6466b..e1f0c8af41 100644
--- a/src/libvirt-nodedev.c
+++ b/src/libvirt-nodedev.c
@@ -1174,3 +1174,48 @@ int virNodeDeviceIsActive(virNodeDevicePtr dev)
virDispatchError(dev->conn);
return -1;
}
+
+
+/**
+ * virNodeDeviceUpdateXML:
+ * @dev: pointer to the node device object
+ * @xmlDesc: string containing an XML description of the device to be defined
+ * @flags: bitwise OR of virNodeDeviceUpdateXMLFlags
+ *
+ * Update the definition of an existing node device, either its live
+ * running configuration, its persistent configuration, or both.
+ *
+ * Returns 0 in case of success, -1 in case of error
+ *
+ * Since: 10.1.0
+ */
+int
+virNodeDeviceUpdateXML(virNodeDevicePtr dev,
+ const char *xmlDesc,
+ unsigned int flags)
+{
+ VIR_DEBUG("nodeDevice=%p, xmlDesc=%s, flags=0x%x",
+ dev, NULLSTR(xmlDesc), flags);
+
+ virResetLastError();
+
+ virCheckNodeDeviceReturn(dev, -1);
+
+ virCheckReadOnlyGoto(dev->conn->flags, error);
+ virCheckNonNullArgGoto(xmlDesc, error);
+
+ if (dev->conn->nodeDeviceDriver &&
+ dev->conn->nodeDeviceDriver->nodeDeviceUpdateXML) {
+ int retval = dev->conn->nodeDeviceDriver->nodeDeviceUpdateXML(dev,
xmlDesc, flags);
+ if (retval < 0)
+ goto error;
+
+ return 0;
+ }
+
+ virReportUnsupportedError();
+
+ error:
+ virDispatchError(dev->conn);
+ return -1;
+}
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index fc26109029..eb52610c2d 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1373,6 +1373,7 @@ virNodeDeviceObjListRemoveLocked;
virNodeDeviceObjSetActive;
virNodeDeviceObjSetAutostart;
virNodeDeviceObjSetPersistent;
+virNodeDeviceObjUpdateModificationImpact;
# conf/virnwfilterbindingdef.h
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index bd1e916d2a..8b53eeb2ee 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -938,4 +938,9 @@ LIBVIRT_9.7.0 {
virNetworkSetMetadata;
} LIBVIRT_9.0.0;
+LIBVIRT_10.1.0 {
+ global:
+ virNodeDeviceUpdateXML;
+} LIBVIRT_9.7.0;
+
# .... define new API here using predicted next version number ....
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 392377deae..9639ea01b3 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -7983,6 +7983,7 @@ static virNodeDeviceDriver node_device_driver = {
.nodeDeviceSetAutostart = remoteNodeDeviceSetAutostart, /* 7.8.0 */
.nodeDeviceIsPersistent = remoteNodeDeviceIsPersistent, /* 7.8.0 */
.nodeDeviceIsActive = remoteNodeDeviceIsActive, /* 7.8.0 */
+ .nodeDeviceUpdateXML = remoteNodeDeviceUpdateXML, /* 10.1.0 */
};
static virNWFilterDriver nwfilter_driver = {
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
index e295b0acc3..e95f672daf 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -2237,6 +2237,12 @@ struct remote_node_device_is_active_ret {
int active;
};
+struct remote_node_device_update_xml_args {
+ remote_nonnull_string name;
+ remote_nonnull_string xml_desc;
+ unsigned int flags;
+};
+
/*
* Events Register/Deregister:
@@ -7021,5 +7027,14 @@ enum remote_procedure {
* @generate: both
* @acl: none
*/
- REMOTE_PROC_NETWORK_EVENT_CALLBACK_METADATA_CHANGE = 446
+ REMOTE_PROC_NETWORK_EVENT_CALLBACK_METADATA_CHANGE = 446,
+
+ /**
+ * @generate: both
+ * @priority: high
+ * @acl: node_device:write
+ * @acl:
node_device:save:!VIR_NODE_DEVICE_UPDATE_XML_AFFECT_CONFIG|VIR_NODE_DEVICE_UPDATE_XML_AFFECT_LIVE
+ * @acl: node_device:save:VIR_NODE_DEVICE_UPDATE_XML_AFFECT_CONFIG
+ */
+ REMOTE_PROC_NODE_DEVICE_UPDATE_XML = 447
};
diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs
index 924ca41825..9a1b881caf 100644
--- a/src/remote_protocol-structs
+++ b/src/remote_protocol-structs
@@ -1673,6 +1673,11 @@ struct remote_node_device_is_active_args {
struct remote_node_device_is_active_ret {
int active;
};
+struct remote_node_device_update_xml_args {
+ remote_nonnull_string name;
+ remote_nonnull_string xml_desc;
+ u_int flags;
+};
struct remote_connect_domain_event_register_ret {
int cb_registered;
};
@@ -3743,4 +3748,5 @@ enum remote_procedure {
REMOTE_PROC_NETWORK_SET_METADATA = 444,
REMOTE_PROC_NETWORK_GET_METADATA = 445,
REMOTE_PROC_NETWORK_EVENT_CALLBACK_METADATA_CHANGE = 446,
+ REMOTE_PROC_NODE_DEVICE_UPDATE_XML = 447,
};
--
2.42.0