api: add virNodeDeviceUpdate()

A public API method which allows to update or modify objects is
implemented for almost all other objects that have a concept of
persistent definition and activatability. Currently node devices of type
mdev can be persistent and active. This new method allows to update
defined and active node devices as well.

Signed-off-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
Reviewed-by: Jonathon Jongsma <jjongsma@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
Boris Fiuczynski 2024-02-22 14:02:06 +01:00 committed by Michal Privoznik
parent e4abc0789c
commit 69f9e7dbc2
12 changed files with 150 additions and 1 deletions

View File

@ -188,6 +188,24 @@ int virNodeDeviceIsPersistent(virNodeDevicePtr dev);
int virNodeDeviceIsActive(virNodeDevicePtr dev);
/**
* virNodeDeviceUpdateFlags:
*
* Flags to control options for virNodeDeviceUpdate()
*
* Since: 10.1.0
*/
typedef enum {
VIR_NODE_DEVICE_UPDATE_AFFECT_CURRENT = 0, /* affect live if node device is active,
config if it's not active (Since: 10.1.0) */
VIR_NODE_DEVICE_UPDATE_AFFECT_LIVE = 1 << 0, /* affect live state of node device only (Since: 10.1.0) */
VIR_NODE_DEVICE_UPDATE_AFFECT_CONFIG = 1 << 1, /* affect persistent config only (Since: 10.1.0) */
} virNodeDeviceUpdateFlags;
int virNodeDeviceUpdate(virNodeDevicePtr dev,
const char *xmlDesc,
unsigned int flags);
/**
* VIR_NODE_DEVICE_EVENT_CALLBACK:
*

View File

@ -71,6 +71,7 @@ VIR_ENUM_IMPL(virAccessPermNodeDevice,
"getattr", "read", "write",
"start", "stop",
"detach", "delete",
"save",
);
VIR_ENUM_IMPL(virAccessPermNWFilter,

View File

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

View File

@ -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 virNodeDeviceUpdateFlags 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_AFFECT_LIVE | VIR_NODE_DEVICE_UPDATE_AFFECT_CONFIG)) ==
VIR_NODE_DEVICE_UPDATE_AFFECT_CURRENT) {
if (isActive)
*flags |= VIR_NODE_DEVICE_UPDATE_AFFECT_LIVE;
else
*flags |= VIR_NODE_DEVICE_UPDATE_AFFECT_CONFIG;
}
if (!isActive && (*flags & VIR_NODE_DEVICE_UPDATE_AFFECT_LIVE)) {
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
_("node device is not active"));
return -1;
}
if (!virNodeDeviceObjIsPersistent(obj) && (*flags & VIR_NODE_DEVICE_UPDATE_AFFECT_CONFIG)) {
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
_("transient node devices do not have any persistent config"));
return -1;
}
return 0;
}

View File

@ -159,3 +159,6 @@ virNodeDeviceObj *
virNodeDeviceObjListFind(virNodeDeviceObjList *devs,
virNodeDeviceObjListPredicate callback,
void *opaque);
int virNodeDeviceObjUpdateModificationImpact(virNodeDeviceObj *obj,
unsigned int *flags);

View File

@ -101,6 +101,11 @@ typedef int
typedef int
(*virDrvNodeDeviceIsActive)(virNodeDevicePtr dev);
typedef int
(*virDrvNodeDeviceUpdate)(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;
virDrvNodeDeviceUpdate nodeDeviceUpdate;
};

View File

@ -1174,3 +1174,48 @@ int virNodeDeviceIsActive(virNodeDevicePtr dev)
virDispatchError(dev->conn);
return -1;
}
/**
* virNodeDeviceUpdate:
* @dev: pointer to the node device object
* @xmlDesc: string containing an XML description of the device to be defined
* @flags: bitwise OR of virNodeDeviceUpdateFlags
*
* 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
virNodeDeviceUpdate(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->nodeDeviceUpdate) {
int retval = dev->conn->nodeDeviceDriver->nodeDeviceUpdate(dev, xmlDesc, flags);
if (retval < 0)
goto error;
return 0;
}
virReportUnsupportedError();
error:
virDispatchError(dev->conn);
return -1;
}

View File

@ -1373,6 +1373,7 @@ virNodeDeviceObjListRemoveLocked;
virNodeDeviceObjSetActive;
virNodeDeviceObjSetAutostart;
virNodeDeviceObjSetPersistent;
virNodeDeviceObjUpdateModificationImpact;
# conf/virnwfilterbindingdef.h

View File

@ -938,4 +938,9 @@ LIBVIRT_9.7.0 {
virNetworkSetMetadata;
} LIBVIRT_9.0.0;
LIBVIRT_10.1.0 {
global:
virNodeDeviceUpdate;
} LIBVIRT_9.7.0;
# .... define new API here using predicted next version number ....

View File

@ -7983,6 +7983,7 @@ static virNodeDeviceDriver node_device_driver = {
.nodeDeviceSetAutostart = remoteNodeDeviceSetAutostart, /* 7.8.0 */
.nodeDeviceIsPersistent = remoteNodeDeviceIsPersistent, /* 7.8.0 */
.nodeDeviceIsActive = remoteNodeDeviceIsActive, /* 7.8.0 */
.nodeDeviceUpdate = remoteNodeDeviceUpdate, /* 10.1.0 */
};
static virNWFilterDriver nwfilter_driver = {

View File

@ -2237,6 +2237,12 @@ struct remote_node_device_is_active_ret {
int active;
};
struct remote_node_device_update_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_AFFECT_CONFIG|VIR_NODE_DEVICE_UPDATE_AFFECT_LIVE
* @acl: node_device:save:VIR_NODE_DEVICE_UPDATE_AFFECT_CONFIG
*/
REMOTE_PROC_NODE_DEVICE_UPDATE = 447
};

View File

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