2012-07-23 11:08:39 +04:00
/*
* virsh - nodedev . c : Commands in node device group
*
2016-01-09 16:36:29 +03:00
* Copyright ( C ) 2005 , 2007 - 2016 Red Hat , Inc .
2012-07-23 11:08:39 +04:00
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
* version 2.1 of the License , or ( at your option ) any later version .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public
2012-09-21 02:30:55 +04:00
* License along with this library . If not , see
2012-07-23 11:08:39 +04:00
* < http : //www.gnu.org/licenses/>.
*/
2012-08-21 02:23:10 +04:00
# include <config.h>
2022-04-02 13:31:47 +03:00
# include "virsh-completer-nodedev.h"
2012-08-21 02:23:10 +04:00
# include "virsh-nodedev.h"
2021-09-26 12:44:30 +03:00
# include "virsh-util.h"
2012-08-21 02:23:10 +04:00
# include "internal.h"
2012-12-12 22:06:53 +04:00
# include "viralloc.h"
2013-05-09 22:59:04 +04:00
# include "virfile.h"
2016-08-08 22:34:21 +03:00
# include "virtime.h"
2012-09-17 07:32:53 +04:00
# include "conf/node_device_conf.h"
2019-04-01 13:14:26 +03:00
# include "virenum.h"
2020-02-17 00:59:28 +03:00
# include "virutil.h"
2012-08-21 02:23:10 +04:00
2012-07-23 11:08:39 +04:00
/*
* " nodedev-create " command
*/
static const vshCmdInfo info_node_device_create [ ] = {
2013-02-07 19:25:10 +04:00
{ . name = " help " ,
. data = N_ ( " create a device defined "
" by an XML file on the node " )
} ,
{ . name = " desc " ,
. data = N_ ( " Create a device on the node. Note that this "
" command creates devices on the physical host "
" that can then be assigned to a virtual machine. " )
} ,
{ . name = NULL }
2012-07-23 11:08:39 +04:00
} ;
static const vshCmdOptDef opts_node_device_create [ ] = {
2016-01-09 16:36:29 +03:00
VIRSH_COMMON_OPT_FILE ( N_ ( " file containing an XML description "
" of the device " ) ) ,
2022-10-18 14:19:05 +03:00
{ . name = " validate " ,
. type = VSH_OT_BOOL ,
. help = N_ ( " validate the XML against the schema " )
} ,
2013-01-14 18:30:11 +04:00
{ . name = NULL }
2012-07-23 11:08:39 +04:00
} ;
static bool
cmdNodeDeviceCreate ( vshControl * ctl , const vshCmd * cmd )
{
2021-09-26 12:44:30 +03:00
g_autoptr ( virshNodeDevice ) dev = NULL ;
2012-07-23 11:08:39 +04:00
const char * from = NULL ;
2021-08-11 16:25:15 +03:00
g_autofree char * buffer = NULL ;
2021-03-11 10:16:13 +03:00
virshControl * priv = ctl - > privData ;
2022-10-18 14:19:05 +03:00
unsigned int flags = 0 ;
2012-07-23 11:08:39 +04:00
2013-01-21 20:29:14 +04:00
if ( vshCommandOptStringReq ( ctl , cmd , " file " , & from ) < 0 )
2012-07-23 11:08:39 +04:00
return false ;
virsh: use common namespacing
Convert the exported items in virsh.h to use a common 'vsh' prefix.
* tools/virsh.h (VIRSH_MAX_XML_FILE): Rename...
(VSH_MAX_XML_FILE): ...and parenthesize.
(DIFF_MSEC, CTRL_CLOSE_BRACKET): Delete.
(vshUsage, vshInit, vshDeinit, vshParseArgv): Remove prototype.
(editWriteToTempFile, editFile, editReadBackFile, prettyCapacity)
(virshReportError): Rename...
(vshEditWriteToTempFile, vshEditFile, vshEditReadBackFile)
(vshPrettyCapacity, vshReportError): ...into vsh namespace.
(jobWatchTimeoutFunc): Move to virsh-domain.c.
* tools/virsh.c (vshCommandRun): Inline former DIFF_MSEC.
(main): Inline former CTRL_CLOSE_BRACKET.
(vshUsage, vshInit, vshDeinit, vshParseArgv): Make static.
(prettyCapacity, virshReportError, editWriteToTempFile, editFile):
Fix naming, and adjust usage.
(vshAskReedit, vshCommandRun, vshEventLoop, vshInit): Adjust
usage.
* tools/virsh-domain.c (cmdAttachDevice, cmdCPUCompare)
(cmdCPUBaseline, cmdCreate, cmdDefine, cmdDetachDevice)
(cmdUpdateDevice, cmdDesc, cmdUndefine, cmdStart, cmdVcpucount)
(cmdAttachDevice, cmdDomjobinfo): Likewise.
* tools/virsh-edit.c (do): Likewise.
* tools/virsh-interface.c (cmdInterfaceDefine): Likewise.
* tools/virsh-network.c (cmdNetworkCreate, cmdNetworkDefine):
Likewise.
* tools/virsh-nodedev.c (cmdNodeDeviceCreate): Likewise.
* tools/virsh-nwfilter.c (cmdNWFilterDefine): Likewise.
* tools/virsh-pool.c (cmdPoolCreate, cmdPoolDefine)
(cmdPoolDiscoverSources, cmdPoolList): Likewise.
* tools/virsh-secret.c (cmdSecretDefine): Likewise.
* tools/virsh-snapshot.c (cmdSnapshotCreate, vshSnapshotCreate)
(vshLookupSnapshot, cmdSnapshotEdit, cmdSnapshotCurrent)
(vshGetSnapshotParent): Likewise.
* tools/virsh-volume.c (cmdVolCreate, cmdVolCreateFrom)
(cmdVolInfo, cmdVolList): Likewise.
2012-08-19 08:10:17 +04:00
if ( virFileReadAll ( from , VSH_MAX_XML_FILE , & buffer ) < 0 )
2012-07-23 11:08:39 +04:00
return false ;
2022-10-18 14:19:05 +03:00
if ( vshCommandOptBool ( cmd , " validate " ) )
flags | = VIR_NODE_DEVICE_CREATE_XML_VALIDATE ;
if ( ! ( dev = virNodeDeviceCreateXML ( priv - > conn , buffer , flags ) ) ) {
2023-03-09 17:54:58 +03:00
vshError ( ctl , _ ( " Failed to create node device from %1$s " ) , from ) ;
2021-09-24 02:49:08 +03:00
return false ;
2012-07-23 11:08:39 +04:00
}
2023-03-09 17:54:58 +03:00
vshPrintExtra ( ctl , _ ( " Node device %1$s created from %2$s \n " ) ,
2021-09-24 02:49:08 +03:00
virNodeDeviceGetName ( dev ) , from ) ;
return true ;
2012-07-23 11:08:39 +04:00
}
/*
* " nodedev-destroy " command
*/
static const vshCmdInfo info_node_device_destroy [ ] = {
2013-02-07 19:25:10 +04:00
{ . name = " help " ,
. data = N_ ( " destroy (stop) a device on the node " )
} ,
{ . name = " desc " ,
. data = N_ ( " Destroy a device on the node. Note that this "
" command destroys devices on the physical host " )
} ,
{ . name = NULL }
2012-07-23 11:08:39 +04:00
} ;
static const vshCmdOptDef opts_node_device_destroy [ ] = {
2013-01-14 18:30:11 +04:00
{ . name = " name " ,
2013-02-04 18:16:44 +04:00
. type = VSH_OT_ALIAS ,
. help = " device "
} ,
{ . name = " device " ,
2013-01-14 18:30:11 +04:00
. type = VSH_OT_DATA ,
. flags = VSH_OFLAG_REQ ,
2018-01-12 16:44:37 +03:00
. help = N_ ( " device name or wwn pair in 'wwnn,wwpn' format " ) ,
. completer = virshNodeDeviceNameCompleter ,
2013-01-14 18:30:11 +04:00
} ,
{ . name = NULL }
2012-07-23 11:08:39 +04:00
} ;
2020-08-18 00:21:48 +03:00
static virNodeDevice *
vshFindNodeDevice ( vshControl * ctl , const char * value )
2012-07-23 11:08:39 +04:00
{
virNodeDevicePtr dev = NULL ;
2021-08-11 16:45:02 +03:00
g_auto ( GStrv ) arr = NULL ;
2013-02-04 18:16:44 +04:00
int narr ;
2021-03-11 10:16:13 +03:00
virshControl * priv = ctl - > privData ;
2012-07-23 11:08:39 +04:00
2020-08-18 00:21:48 +03:00
if ( strchr ( value , ' , ' ) ) {
narr = vshStringToArray ( value , & arr ) ;
2013-02-04 18:16:44 +04:00
if ( narr ! = 2 ) {
2023-03-09 17:54:58 +03:00
vshError ( ctl , _ ( " Malformed device value '%1$s' " ) , value ) ;
2021-08-12 10:59:20 +03:00
return NULL ;
2013-02-04 18:16:44 +04:00
}
if ( ! virValidateWWN ( arr [ 0 ] ) | | ! virValidateWWN ( arr [ 1 ] ) )
2021-08-12 10:59:20 +03:00
return NULL ;
2013-02-04 18:16:44 +04:00
2015-06-15 19:53:58 +03:00
dev = virNodeDeviceLookupSCSIHostByWWN ( priv - > conn , arr [ 0 ] , arr [ 1 ] , 0 ) ;
2013-02-04 18:16:44 +04:00
} else {
2020-08-18 00:21:48 +03:00
dev = virNodeDeviceLookupByName ( priv - > conn , value ) ;
2013-02-04 18:16:44 +04:00
}
if ( ! dev ) {
2020-08-18 00:21:48 +03:00
vshError ( ctl , " %s '%s' " , _ ( " Could not find matching device " ) , value ) ;
2021-08-12 10:59:20 +03:00
return NULL ;
2013-02-04 18:16:44 +04:00
}
2012-07-23 11:08:39 +04:00
2020-08-18 00:21:48 +03:00
return dev ;
}
static bool
cmdNodeDeviceDestroy ( vshControl * ctl , const vshCmd * cmd )
{
2021-09-26 12:44:30 +03:00
g_autoptr ( virshNodeDevice ) dev = NULL ;
2020-08-18 00:21:48 +03:00
const char * device_value = NULL ;
if ( vshCommandOptStringReq ( ctl , cmd , " device " , & device_value ) < 0 )
return false ;
dev = vshFindNodeDevice ( ctl , device_value ) ;
if ( ! dev )
2021-11-04 17:26:07 +03:00
return false ;
2020-08-18 00:21:48 +03:00
2012-07-23 11:08:39 +04:00
if ( virNodeDeviceDestroy ( dev ) = = 0 ) {
2023-03-09 17:54:58 +03:00
vshPrintExtra ( ctl , _ ( " Destroyed node device '%1$s' \n " ) , device_value ) ;
2012-07-23 11:08:39 +04:00
} else {
2023-03-09 17:54:58 +03:00
vshError ( ctl , _ ( " Failed to destroy node device '%1$s' " ) , device_value ) ;
2021-11-04 17:26:07 +03:00
return false ;
2012-07-23 11:08:39 +04:00
}
2021-11-04 17:26:07 +03:00
return true ;
2012-07-23 11:08:39 +04:00
}
2015-06-15 19:53:58 +03:00
struct virshNodeList {
2012-07-23 11:08:39 +04:00
char * * names ;
char * * parents ;
} ;
static const char *
2015-06-15 19:53:58 +03:00
virshNodeListLookup ( int devid , bool parent , void * opaque )
2012-07-23 11:08:39 +04:00
{
2015-06-15 19:53:58 +03:00
struct virshNodeList * arrays = opaque ;
2012-07-23 11:08:39 +04:00
if ( parent )
return arrays - > parents [ devid ] ;
return arrays - > names [ devid ] ;
}
2012-09-17 07:32:53 +04:00
static int
2015-06-15 19:53:58 +03:00
virshNodeDeviceSorter ( const void * a , const void * b )
2012-09-17 07:32:53 +04:00
{
virNodeDevicePtr * na = ( virNodeDevicePtr * ) a ;
virNodeDevicePtr * nb = ( virNodeDevicePtr * ) b ;
if ( * na & & ! * nb )
return - 1 ;
if ( ! * na )
return * nb ! = NULL ;
return vshStrcasecmp ( virNodeDeviceGetName ( * na ) ,
virNodeDeviceGetName ( * nb ) ) ;
}
2015-06-15 19:53:58 +03:00
struct virshNodeDeviceList {
2012-09-17 07:32:53 +04:00
virNodeDevicePtr * devices ;
size_t ndevices ;
} ;
static void
2021-03-11 10:16:13 +03:00
virshNodeDeviceListFree ( struct virshNodeDeviceList * list )
2012-09-17 07:32:53 +04:00
{
Convert 'int i' to 'size_t i' in tools/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 18:09:33 +04:00
size_t i ;
2012-09-17 07:32:53 +04:00
2013-08-27 15:27:50 +04:00
if ( list & & list - > devices ) {
2012-09-17 07:32:53 +04:00
for ( i = 0 ; i < list - > ndevices ; i + + ) {
2021-09-26 12:44:30 +03:00
virshNodeDeviceFree ( list - > devices [ i ] ) ;
2012-09-17 07:32:53 +04:00
}
2021-02-03 22:32:55 +03:00
g_free ( list - > devices ) ;
2012-09-17 07:32:53 +04:00
}
2021-02-03 22:32:55 +03:00
g_free ( list ) ;
2012-09-17 07:32:53 +04:00
}
2021-03-11 10:16:13 +03:00
static struct virshNodeDeviceList *
2015-06-15 19:53:58 +03:00
virshNodeDeviceListCollect ( vshControl * ctl ,
2012-09-17 07:32:53 +04:00
char * * capnames ,
int ncapnames ,
unsigned int flags )
{
2021-03-11 10:16:13 +03:00
struct virshNodeDeviceList * list = g_new0 ( struct virshNodeDeviceList , 1 ) ;
Convert 'int i' to 'size_t i' in tools/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 18:09:33 +04:00
size_t i ;
2012-09-17 07:32:53 +04:00
int ret ;
virNodeDevicePtr device ;
bool success = false ;
size_t deleted = 0 ;
int ndevices = 0 ;
char * * names = NULL ;
2021-03-11 10:16:13 +03:00
virshControl * priv = ctl - > privData ;
2012-09-17 07:32:53 +04:00
/* try the list with flags support (0.10.2 and later) */
2015-06-15 19:53:58 +03:00
if ( ( ret = virConnectListAllNodeDevices ( priv - > conn ,
2012-09-17 07:32:53 +04:00
& list - > devices ,
flags ) ) > = 0 ) {
list - > ndevices = ret ;
goto finished ;
}
/* check if the command is actually supported */
if ( last_error & & last_error - > code = = VIR_ERR_NO_SUPPORT )
goto fallback ;
/* there was an error during the call */
vshError ( ctl , " %s " , _ ( " Failed to list node devices " ) ) ;
goto cleanup ;
2014-03-25 10:53:59 +04:00
fallback :
2012-09-17 07:32:53 +04:00
/* fall back to old method (0.10.1 and older) */
vshResetLibvirtError ( ) ;
2015-06-15 19:53:58 +03:00
ndevices = virNodeNumOfDevices ( priv - > conn , NULL , 0 ) ;
2012-09-17 07:32:53 +04:00
if ( ndevices < 0 ) {
vshError ( ctl , " %s " , _ ( " Failed to count node devices " ) ) ;
goto cleanup ;
}
if ( ndevices = = 0 )
return list ;
2020-10-05 19:50:09 +03:00
names = g_new0 ( char * , ndevices ) ;
2012-09-17 07:32:53 +04:00
2015-06-15 19:53:58 +03:00
ndevices = virNodeListDevices ( priv - > conn , NULL , names , ndevices , 0 ) ;
2012-09-17 07:32:53 +04:00
if ( ndevices < 0 ) {
vshError ( ctl , " %s " , _ ( " Failed to list node devices " ) ) ;
goto cleanup ;
}
2020-10-05 19:50:09 +03:00
list - > devices = g_new0 ( virNodeDevicePtr , ndevices ) ;
2012-09-17 07:32:53 +04:00
list - > ndevices = 0 ;
/* get the node devices */
2013-05-21 11:44:53 +04:00
for ( i = 0 ; i < ndevices ; i + + ) {
2015-06-15 19:53:58 +03:00
if ( ! ( device = virNodeDeviceLookupByName ( priv - > conn , names [ i ] ) ) )
2012-09-17 07:32:53 +04:00
continue ;
list - > devices [ list - > ndevices + + ] = device ;
}
/* truncate domains that weren't found */
deleted = ndevices - list - > ndevices ;
if ( ! capnames )
goto finished ;
/* filter the list if the list was acquired by fallback means */
for ( i = 0 ; i < list - > ndevices ; i + + ) {
2021-08-11 16:25:15 +03:00
g_autofree char * * caps = NULL ;
2012-09-17 07:32:53 +04:00
int ncaps = 0 ;
bool match = false ;
2020-08-03 18:27:58 +03:00
size_t j , k ;
2012-09-17 07:32:53 +04:00
device = list - > devices [ i ] ;
if ( ( ncaps = virNodeDeviceNumOfCaps ( device ) ) < 0 ) {
vshError ( ctl , " %s " , _ ( " Failed to get capability numbers "
" of the device " ) ) ;
goto cleanup ;
}
2020-10-05 19:50:09 +03:00
caps = g_new0 ( char * , ncaps ) ;
2012-09-17 07:32:53 +04:00
if ( ( ncaps = virNodeDeviceListCaps ( device , caps , ncaps ) ) < 0 ) {
vshError ( ctl , " %s " , _ ( " Failed to get capability names of the device " ) ) ;
goto cleanup ;
}
2013-10-15 16:44:06 +04:00
/* Check if the device's capability matches with provided
2012-09-17 07:32:53 +04:00
* capabilities .
*/
for ( j = 0 ; j < ncaps ; j + + ) {
for ( k = 0 ; k < ncapnames ; k + + ) {
if ( STREQ ( caps [ j ] , capnames [ k ] ) ) {
match = true ;
break ;
}
}
}
if ( ! match )
goto remove_entry ;
/* the device matched all filters, it may stay */
continue ;
2014-03-25 10:53:59 +04:00
remove_entry :
2012-09-17 07:32:53 +04:00
/* the device has to be removed as it failed one of the filters */
2021-09-26 12:44:30 +03:00
g_clear_pointer ( & list - > devices [ i ] , virshNodeDeviceFree ) ;
2012-09-17 07:32:53 +04:00
deleted + + ;
}
2014-03-25 10:53:59 +04:00
finished :
2012-09-17 07:32:53 +04:00
/* sort the list */
if ( list - > devices & & list - > ndevices )
qsort ( list - > devices , list - > ndevices ,
2015-06-15 19:53:58 +03:00
sizeof ( * list - > devices ) , virshNodeDeviceSorter ) ;
2012-09-17 07:32:53 +04:00
/* truncate the list if filter simulation deleted entries */
if ( deleted )
VIR_SHRINK_N ( list - > devices , list - > ndevices , deleted ) ;
success = true ;
2014-03-25 10:53:59 +04:00
cleanup :
2013-07-11 18:33:29 +04:00
for ( i = 0 ; ndevices ! = - 1 & & i < ndevices ; i + + )
2012-09-17 07:32:53 +04:00
VIR_FREE ( names [ i ] ) ;
VIR_FREE ( names ) ;
if ( ! success ) {
2022-01-28 20:42:45 +03:00
g_clear_pointer ( & list , virshNodeDeviceListFree ) ;
2012-09-17 07:32:53 +04:00
}
return list ;
}
2012-07-23 11:08:39 +04:00
/*
* " nodedev-list " command
*/
static const vshCmdInfo info_node_list_devices [ ] = {
2013-02-07 19:25:10 +04:00
{ . name = " help " ,
. data = N_ ( " enumerate devices on this host " )
} ,
{ . name = " desc " ,
. data = " "
} ,
{ . name = NULL }
2012-07-23 11:08:39 +04:00
} ;
static const vshCmdOptDef opts_node_list_devices [ ] = {
2013-01-14 18:30:11 +04:00
{ . name = " tree " ,
. type = VSH_OT_BOOL ,
. help = N_ ( " list devices in a tree " )
} ,
{ . name = " cap " ,
. type = VSH_OT_STRING ,
2019-07-14 12:47:34 +03:00
. completer = virshNodeDeviceCapabilityNameCompleter ,
2013-01-14 18:30:11 +04:00
. help = N_ ( " capability names, separated by comma " )
} ,
2020-07-10 22:47:01 +03:00
{ . name = " inactive " ,
. type = VSH_OT_BOOL ,
. help = N_ ( " list inactive devices " )
} ,
{ . name = " all " ,
. type = VSH_OT_BOOL ,
. help = N_ ( " list inactive & active devices " )
} ,
2013-01-14 18:30:11 +04:00
{ . name = NULL }
2012-07-23 11:08:39 +04:00
} ;
static bool
2019-10-14 15:44:29 +03:00
cmdNodeListDevices ( vshControl * ctl , const vshCmd * cmd G_GNUC_UNUSED )
2012-07-23 11:08:39 +04:00
{
2012-09-17 07:32:53 +04:00
const char * cap_str = NULL ;
Convert 'int i' to 'size_t i' in tools/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 18:09:33 +04:00
size_t i ;
2012-07-23 11:08:39 +04:00
bool tree = vshCommandOptBool ( cmd , " tree " ) ;
bool ret = true ;
2012-09-17 07:32:53 +04:00
unsigned int flags = 0 ;
2021-08-11 16:45:02 +03:00
g_auto ( GStrv ) caps = NULL ;
2012-09-17 07:32:53 +04:00
int ncaps = 0 ;
2021-03-11 10:16:13 +03:00
struct virshNodeDeviceList * list = NULL ;
2012-09-17 07:32:53 +04:00
int cap_type = - 1 ;
2020-07-10 22:47:01 +03:00
bool inactive = vshCommandOptBool ( cmd , " inactive " ) ;
bool all = vshCommandOptBool ( cmd , " all " ) ;
2012-07-23 11:08:39 +04:00
2015-12-03 15:47:56 +03:00
ignore_value ( vshCommandOptStringQuiet ( ctl , cmd , " cap " , & cap_str ) ) ;
2012-07-23 11:08:39 +04:00
2012-09-17 07:32:53 +04:00
if ( cap_str ) {
2013-08-15 20:20:05 +04:00
if ( ( ncaps = vshStringToArray ( cap_str , & caps ) ) < 0 )
return false ;
2012-07-23 11:08:39 +04:00
}
2020-07-10 22:47:01 +03:00
if ( all & & inactive ) {
vshError ( ctl , " %s " , _ ( " Option --all is incompatible with --inactive " ) ) ;
return false ;
}
2021-07-08 00:29:29 +03:00
if ( tree & & ( cap_str | | inactive ) ) {
vshError ( ctl , " %s " , _ ( " Option --tree is incompatible with --cap and --inactive " ) ) ;
2020-07-10 22:47:01 +03:00
return false ;
}
2012-09-17 07:32:53 +04:00
for ( i = 0 ; i < ncaps ; i + + ) {
if ( ( cap_type = virNodeDevCapTypeFromString ( caps [ i ] ) ) < 0 ) {
vshError ( ctl , " %s " , _ ( " Invalid capability type " ) ) ;
2013-08-27 15:47:57 +04:00
ret = false ;
goto cleanup ;
2012-09-17 07:32:53 +04:00
}
2017-02-17 18:09:15 +03:00
switch ( ( virNodeDevCapType ) cap_type ) {
2012-09-17 07:32:53 +04:00
case VIR_NODE_DEV_CAP_SYSTEM :
flags | = VIR_CONNECT_LIST_NODE_DEVICES_CAP_SYSTEM ;
break ;
case VIR_NODE_DEV_CAP_PCI_DEV :
flags | = VIR_CONNECT_LIST_NODE_DEVICES_CAP_PCI_DEV ;
break ;
case VIR_NODE_DEV_CAP_USB_DEV :
flags | = VIR_CONNECT_LIST_NODE_DEVICES_CAP_USB_DEV ;
break ;
case VIR_NODE_DEV_CAP_USB_INTERFACE :
flags | = VIR_CONNECT_LIST_NODE_DEVICES_CAP_USB_INTERFACE ;
break ;
case VIR_NODE_DEV_CAP_NET :
flags | = VIR_CONNECT_LIST_NODE_DEVICES_CAP_NET ;
break ;
case VIR_NODE_DEV_CAP_SCSI_HOST :
flags | = VIR_CONNECT_LIST_NODE_DEVICES_CAP_SCSI_HOST ;
break ;
case VIR_NODE_DEV_CAP_SCSI_TARGET :
flags | = VIR_CONNECT_LIST_NODE_DEVICES_CAP_SCSI_TARGET ;
break ;
case VIR_NODE_DEV_CAP_SCSI :
flags | = VIR_CONNECT_LIST_NODE_DEVICES_CAP_SCSI ;
break ;
case VIR_NODE_DEV_CAP_STORAGE :
flags | = VIR_CONNECT_LIST_NODE_DEVICES_CAP_STORAGE ;
break ;
2013-01-07 21:05:28 +04:00
case VIR_NODE_DEV_CAP_FC_HOST :
flags | = VIR_CONNECT_LIST_NODE_DEVICES_CAP_FC_HOST ;
break ;
case VIR_NODE_DEV_CAP_VPORTS :
flags | = VIR_CONNECT_LIST_NODE_DEVICES_CAP_VPORTS ;
break ;
2013-06-03 14:05:35 +04:00
case VIR_NODE_DEV_CAP_SCSI_GENERIC :
flags | = VIR_CONNECT_LIST_NODE_DEVICES_CAP_SCSI_GENERIC ;
break ;
2017-02-17 18:09:15 +03:00
case VIR_NODE_DEV_CAP_DRM :
flags | = VIR_CONNECT_LIST_NODE_DEVICES_CAP_DRM ;
break ;
2017-03-06 19:20:00 +03:00
case VIR_NODE_DEV_CAP_MDEV_TYPES :
flags | = VIR_CONNECT_LIST_NODE_DEVICES_CAP_MDEV_TYPES ;
break ;
case VIR_NODE_DEV_CAP_MDEV :
flags | = VIR_CONNECT_LIST_NODE_DEVICES_CAP_MDEV ;
break ;
2021-10-20 11:30:33 +03:00
case VIR_NODE_DEV_CAP_VPD :
flags | = VIR_CONNECT_LIST_NODE_DEVICES_CAP_VPD ;
break ;
2017-05-22 09:38:22 +03:00
case VIR_NODE_DEV_CAP_CCW_DEV :
2017-05-22 09:38:23 +03:00
flags | = VIR_CONNECT_LIST_NODE_DEVICES_CAP_CCW_DEV ;
break ;
2020-09-14 22:11:44 +03:00
case VIR_NODE_DEV_CAP_CSS_DEV :
2020-09-14 22:11:45 +03:00
flags | = VIR_CONNECT_LIST_NODE_DEVICES_CAP_CSS_DEV ;
break ;
2020-10-14 20:08:30 +03:00
case VIR_NODE_DEV_CAP_VDPA :
flags | = VIR_CONNECT_LIST_NODE_DEVICES_CAP_VDPA ;
break ;
2020-12-03 20:59:33 +03:00
case VIR_NODE_DEV_CAP_AP_CARD :
2020-12-03 20:59:37 +03:00
flags | = VIR_CONNECT_LIST_NODE_DEVICES_CAP_AP_CARD ;
break ;
2020-12-03 20:59:35 +03:00
case VIR_NODE_DEV_CAP_AP_QUEUE :
2020-12-03 20:59:37 +03:00
flags | = VIR_CONNECT_LIST_NODE_DEVICES_CAP_AP_QUEUE ;
break ;
2020-12-03 20:59:38 +03:00
case VIR_NODE_DEV_CAP_AP_MATRIX :
2020-12-03 20:59:40 +03:00
flags | = VIR_CONNECT_LIST_NODE_DEVICES_CAP_AP_MATRIX ;
break ;
2017-02-17 18:09:15 +03:00
case VIR_NODE_DEV_CAP_LAST :
2012-09-17 07:32:53 +04:00
break ;
}
2012-07-23 11:08:39 +04:00
}
2012-09-17 07:32:53 +04:00
2020-07-10 22:47:01 +03:00
if ( inactive | | all )
flags | = VIR_CONNECT_LIST_NODE_DEVICES_INACTIVE ;
if ( ! inactive )
flags | = VIR_CONNECT_LIST_NODE_DEVICES_ACTIVE ;
2015-06-15 19:53:58 +03:00
if ( ! ( list = virshNodeDeviceListCollect ( ctl , caps , ncaps , flags ) ) ) {
2012-09-17 07:32:53 +04:00
ret = false ;
goto cleanup ;
}
2012-07-23 11:08:39 +04:00
if ( tree ) {
2020-10-05 19:50:09 +03:00
char * * parents = g_new0 ( char * , list - > ndevices ) ;
char * * names = g_new0 ( char * , list - > ndevices ) ;
2015-06-15 19:53:58 +03:00
struct virshNodeList arrays = { names , parents } ;
2012-09-17 07:32:53 +04:00
for ( i = 0 ; i < list - > ndevices ; i + + )
2019-10-18 18:24:02 +03:00
names [ i ] = g_strdup ( virNodeDeviceGetName ( list - > devices [ i ] ) ) ;
2012-07-23 11:08:39 +04:00
2012-09-17 07:32:53 +04:00
for ( i = 0 ; i < list - > ndevices ; i + + ) {
virNodeDevicePtr dev = list - > devices [ i ] ;
if ( STRNEQ ( names [ i ] , " computer " ) ) {
2019-10-18 18:24:02 +03:00
parents [ i ] = g_strdup ( virNodeDeviceGetParent ( dev ) ) ;
2012-07-23 11:08:39 +04:00
} else {
parents [ i ] = NULL ;
}
}
2012-09-17 07:32:53 +04:00
2013-05-21 11:44:53 +04:00
for ( i = 0 ; i < list - > ndevices ; i + + ) {
2012-07-23 11:08:39 +04:00
if ( parents [ i ] = = NULL & &
2015-06-15 19:53:58 +03:00
vshTreePrint ( ctl , virshNodeListLookup , & arrays ,
2012-09-17 07:32:53 +04:00
list - > ndevices , i ) < 0 )
2012-07-23 11:08:39 +04:00
ret = false ;
}
2012-09-17 07:32:53 +04:00
2013-05-21 11:44:53 +04:00
for ( i = 0 ; i < list - > ndevices ; i + + )
2012-07-23 11:08:39 +04:00
VIR_FREE ( parents [ i ] ) ;
VIR_FREE ( parents ) ;
2012-09-17 07:32:53 +04:00
for ( i = 0 ; i < list - > ndevices ; i + + )
VIR_FREE ( names [ i ] ) ;
VIR_FREE ( names ) ;
2012-07-23 11:08:39 +04:00
} else {
2012-09-17 07:32:53 +04:00
for ( i = 0 ; i < list - > ndevices ; i + + )
vshPrint ( ctl , " %s \n " , virNodeDeviceGetName ( list - > devices [ i ] ) ) ;
}
2014-03-25 10:53:59 +04:00
cleanup :
2015-06-15 19:53:58 +03:00
virshNodeDeviceListFree ( list ) ;
2012-07-23 11:08:39 +04:00
return ret ;
}
/*
* " nodedev-dumpxml " command
*/
static const vshCmdInfo info_node_device_dumpxml [ ] = {
2013-02-07 19:25:10 +04:00
{ . name = " help " ,
. data = N_ ( " node device details in XML " )
} ,
{ . name = " desc " ,
. data = N_ ( " Output the node device details as an XML dump to stdout. " )
} ,
{ . name = NULL }
2012-07-23 11:08:39 +04:00
} ;
static const vshCmdOptDef opts_node_device_dumpxml [ ] = {
2013-01-14 18:30:11 +04:00
{ . name = " device " ,
. type = VSH_OT_DATA ,
. flags = VSH_OFLAG_REQ ,
2013-02-04 18:16:44 +04:00
. help = N_ ( " device name or wwn pair in 'wwnn,wwpn' format " ) ,
2018-01-12 16:44:37 +03:00
. completer = virshNodeDeviceNameCompleter ,
2013-01-14 18:30:11 +04:00
} ,
2022-06-16 18:29:54 +03:00
{ . name = " xpath " ,
. type = VSH_OT_STRING ,
virsh: Require --xpath for *dumpxml
Historically, the dumpxml command reject any unknown arguments,
for instance:
virsh dumpxml fedora xxx
However, after v8.5.0-rc1~31 the second argument ('xxx') is
treated as an XPath, but it's not that clearly visible.
Therefore, require the --xpath switch, like this:
virsh dumpxml fedora --xpath xxx
Yes, this breaks already released virsh, but I think we can argue
that the pool of users of this particular function is very small.
We also document the argument being mandatory:
dumpxml [--inactive] [--security-info] [--update-cpu] [--migratable]
[--xpath EXPRESSION] [--wrap] domain
The sooner we do this change, the better.
The same applies for other *dumpxml functions (net-dumpxml,
pool-dumpxml, vol-dumpxl to name a few).
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2103524
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
2022-07-08 13:45:42 +03:00
. flags = VSH_OFLAG_REQ_OPT ,
2022-06-16 18:29:54 +03:00
. completer = virshCompleteEmpty ,
. help = N_ ( " xpath expression to filter the XML document " )
} ,
{ . name = " wrap " ,
. type = VSH_OT_BOOL ,
. help = N_ ( " wrap xpath results in an common root element " ) ,
} ,
2013-01-14 18:30:11 +04:00
{ . name = NULL }
2012-07-23 11:08:39 +04:00
} ;
static bool
cmdNodeDeviceDumpXML ( vshControl * ctl , const vshCmd * cmd )
{
2021-09-26 12:44:30 +03:00
g_autoptr ( virshNodeDevice ) device = NULL ;
2021-08-11 16:25:15 +03:00
g_autofree char * xml = NULL ;
2013-02-04 18:16:44 +04:00
const char * device_value = NULL ;
2022-06-16 18:29:54 +03:00
bool wrap = vshCommandOptBool ( cmd , " wrap " ) ;
const char * xpath = NULL ;
2012-07-23 11:08:39 +04:00
2013-02-04 18:16:44 +04:00
if ( vshCommandOptStringReq ( ctl , cmd , " device " , & device_value ) < 0 )
return false ;
2013-01-21 20:41:14 +04:00
2022-06-16 18:29:54 +03:00
if ( vshCommandOptStringQuiet ( ctl , cmd , " xpath " , & xpath ) < 0 )
return false ;
2020-08-18 00:21:48 +03:00
device = vshFindNodeDevice ( ctl , device_value ) ;
2013-02-04 18:16:44 +04:00
2020-08-18 00:21:48 +03:00
if ( ! device )
2021-11-04 17:26:07 +03:00
return false ;
2012-07-23 11:08:39 +04:00
2013-01-21 20:41:14 +04:00
if ( ! ( xml = virNodeDeviceGetXMLDesc ( device , 0 ) ) )
2021-11-04 17:26:07 +03:00
return false ;
2012-07-23 11:08:39 +04:00
2022-06-16 18:29:54 +03:00
return virshDumpXML ( ctl , xml , " node-device " , xpath , wrap ) ;
2012-07-23 11:08:39 +04:00
}
/*
* " nodedev-detach " command
*/
static const vshCmdInfo info_node_device_detach [ ] = {
2013-02-07 19:25:10 +04:00
{ . name = " help " ,
. data = N_ ( " detach node device from its device driver " )
} ,
{ . name = " desc " ,
. data = N_ ( " Detach node device from its device driver before assigning to a domain. " )
} ,
{ . name = NULL }
2012-07-23 11:08:39 +04:00
} ;
static const vshCmdOptDef opts_node_device_detach [ ] = {
2013-01-14 18:30:11 +04:00
{ . name = " device " ,
. type = VSH_OT_DATA ,
. flags = VSH_OFLAG_REQ ,
2018-01-12 16:44:37 +03:00
. help = N_ ( " device key " ) ,
. completer = virshNodeDeviceNameCompleter ,
2013-01-14 18:30:11 +04:00
} ,
2013-04-24 22:22:36 +04:00
{ . name = " driver " ,
. type = VSH_OT_STRING ,
2022-04-02 13:31:47 +03:00
. completer = virshNodeDevicePCIBackendCompleter ,
2022-04-05 11:38:47 +03:00
. help = N_ ( " pci device assignment backend driver (e.g. 'vfio' or 'xen') " )
2013-04-24 22:22:36 +04:00
} ,
2013-01-14 18:30:11 +04:00
{ . name = NULL }
2012-07-23 11:08:39 +04:00
} ;
static bool
cmdNodeDeviceDetach ( vshControl * ctl , const vshCmd * cmd )
{
const char * name = NULL ;
2013-04-24 22:22:36 +04:00
const char * driverName = NULL ;
2021-09-26 12:44:30 +03:00
g_autoptr ( virshNodeDevice ) device = NULL ;
2012-07-23 11:08:39 +04:00
bool ret = true ;
2021-03-11 10:16:13 +03:00
virshControl * priv = ctl - > privData ;
2012-07-23 11:08:39 +04:00
2013-01-21 20:29:14 +04:00
if ( vshCommandOptStringReq ( ctl , cmd , " device " , & name ) < 0 )
2012-07-23 11:08:39 +04:00
return false ;
2013-01-21 20:41:14 +04:00
2015-12-03 15:47:56 +03:00
ignore_value ( vshCommandOptStringQuiet ( ctl , cmd , " driver " , & driverName ) ) ;
2013-04-24 22:22:36 +04:00
2015-06-15 19:53:58 +03:00
if ( ! ( device = virNodeDeviceLookupByName ( priv - > conn , name ) ) ) {
2023-03-09 17:54:58 +03:00
vshError ( ctl , _ ( " Could not find matching device '%1$s' " ) , name ) ;
2012-07-23 11:08:39 +04:00
return false ;
}
2013-04-24 22:22:36 +04:00
if ( driverName ) {
/* we must use the newer API that accepts a driverName */
if ( virNodeDeviceDetachFlags ( device , driverName , 0 ) < 0 )
ret = false ;
2012-07-23 11:08:39 +04:00
} else {
2013-04-24 22:22:36 +04:00
/* Yes, our (old) public API is misspelled. At least virsh
* can accept either spelling . */
if ( virNodeDeviceDettach ( device ) < 0 )
ret = false ;
2012-07-23 11:08:39 +04:00
}
2013-01-21 20:41:14 +04:00
2013-04-24 22:22:36 +04:00
if ( ret )
2023-03-09 17:54:58 +03:00
vshPrintExtra ( ctl , _ ( " Device %1$s detached \n " ) , name ) ;
2013-04-24 22:22:36 +04:00
else
2023-03-09 17:54:58 +03:00
vshError ( ctl , _ ( " Failed to detach device %1$s " ) , name ) ;
2013-04-24 22:22:36 +04:00
2012-07-23 11:08:39 +04:00
return ret ;
}
/*
* " nodedev-reattach " command
*/
static const vshCmdInfo info_node_device_reattach [ ] = {
2013-02-07 19:25:10 +04:00
{ . name = " help " ,
. data = N_ ( " reattach node device to its device driver " )
} ,
{ . name = " desc " ,
. data = N_ ( " Reattach node device to its device driver once released by the domain. " )
} ,
{ . name = NULL }
2012-07-23 11:08:39 +04:00
} ;
static const vshCmdOptDef opts_node_device_reattach [ ] = {
2013-01-14 18:30:11 +04:00
{ . name = " device " ,
. type = VSH_OT_DATA ,
. flags = VSH_OFLAG_REQ ,
2018-01-12 16:44:37 +03:00
. help = N_ ( " device key " ) ,
. completer = virshNodeDeviceNameCompleter ,
2013-01-14 18:30:11 +04:00
} ,
{ . name = NULL }
2012-07-23 11:08:39 +04:00
} ;
static bool
cmdNodeDeviceReAttach ( vshControl * ctl , const vshCmd * cmd )
{
const char * name = NULL ;
2021-09-26 12:44:30 +03:00
g_autoptr ( virshNodeDevice ) device = NULL ;
2012-07-23 11:08:39 +04:00
bool ret = true ;
2021-03-11 10:16:13 +03:00
virshControl * priv = ctl - > privData ;
2012-07-23 11:08:39 +04:00
2013-01-21 20:29:14 +04:00
if ( vshCommandOptStringReq ( ctl , cmd , " device " , & name ) < 0 )
2012-07-23 11:08:39 +04:00
return false ;
2013-01-21 20:41:14 +04:00
2015-06-15 19:53:58 +03:00
if ( ! ( device = virNodeDeviceLookupByName ( priv - > conn , name ) ) ) {
2023-03-09 17:54:58 +03:00
vshError ( ctl , _ ( " Could not find matching device '%1$s' " ) , name ) ;
2012-07-23 11:08:39 +04:00
return false ;
}
if ( virNodeDeviceReAttach ( device ) = = 0 ) {
2023-03-09 17:54:58 +03:00
vshPrintExtra ( ctl , _ ( " Device %1$s re-attached \n " ) , name ) ;
2012-07-23 11:08:39 +04:00
} else {
2023-03-09 17:54:58 +03:00
vshError ( ctl , _ ( " Failed to re-attach device %1$s " ) , name ) ;
2012-07-23 11:08:39 +04:00
ret = false ;
}
2013-01-21 20:41:14 +04:00
2012-07-23 11:08:39 +04:00
return ret ;
}
/*
* " nodedev-reset " command
*/
static const vshCmdInfo info_node_device_reset [ ] = {
2013-02-07 19:25:10 +04:00
{ . name = " help " ,
. data = N_ ( " reset node device " )
} ,
{ . name = " desc " ,
. data = N_ ( " Reset node device before or after assigning to a domain. " )
} ,
{ . name = NULL }
2012-07-23 11:08:39 +04:00
} ;
static const vshCmdOptDef opts_node_device_reset [ ] = {
2013-01-14 18:30:11 +04:00
{ . name = " device " ,
. type = VSH_OT_DATA ,
. flags = VSH_OFLAG_REQ ,
2018-01-12 16:44:37 +03:00
. help = N_ ( " device key " ) ,
. completer = virshNodeDeviceNameCompleter ,
2013-01-14 18:30:11 +04:00
} ,
{ . name = NULL }
2012-07-23 11:08:39 +04:00
} ;
static bool
cmdNodeDeviceReset ( vshControl * ctl , const vshCmd * cmd )
{
const char * name = NULL ;
2021-09-26 12:44:30 +03:00
g_autoptr ( virshNodeDevice ) device = NULL ;
2012-07-23 11:08:39 +04:00
bool ret = true ;
2021-03-11 10:16:13 +03:00
virshControl * priv = ctl - > privData ;
2012-07-23 11:08:39 +04:00
2013-01-21 20:29:14 +04:00
if ( vshCommandOptStringReq ( ctl , cmd , " device " , & name ) < 0 )
2012-07-23 11:08:39 +04:00
return false ;
2013-01-21 20:41:14 +04:00
2015-06-15 19:53:58 +03:00
if ( ! ( device = virNodeDeviceLookupByName ( priv - > conn , name ) ) ) {
2023-03-09 17:54:58 +03:00
vshError ( ctl , _ ( " Could not find matching device '%1$s' " ) , name ) ;
2012-07-23 11:08:39 +04:00
return false ;
}
if ( virNodeDeviceReset ( device ) = = 0 ) {
2023-03-09 17:54:58 +03:00
vshPrintExtra ( ctl , _ ( " Device %1$s reset \n " ) , name ) ;
2012-07-23 11:08:39 +04:00
} else {
2023-03-09 17:54:58 +03:00
vshError ( ctl , _ ( " Failed to reset device %1$s " ) , name ) ;
2012-07-23 11:08:39 +04:00
ret = false ;
}
2013-01-21 20:41:14 +04:00
2012-07-23 11:08:39 +04:00
return ret ;
}
2012-07-23 11:19:04 +04:00
2016-08-08 22:34:21 +03:00
/*
* " nodedev-event " command
*/
2019-01-20 19:04:56 +03:00
VIR_ENUM_DECL ( virshNodeDeviceEvent ) ;
2016-08-08 22:34:21 +03:00
VIR_ENUM_IMPL ( virshNodeDeviceEvent ,
VIR_NODE_DEVICE_EVENT_LAST ,
N_ ( " Created " ) ,
2020-07-09 18:56:51 +03:00
N_ ( " Deleted " ) ,
N_ ( " Defined " ) ,
N_ ( " Undefined " ) ) ;
2016-08-08 22:34:21 +03:00
static const char *
virshNodeDeviceEventToString ( int event )
{
const char * str = virshNodeDeviceEventTypeToString ( event ) ;
return str ? _ ( str ) : _ ( " unknown " ) ;
}
struct virshNodeDeviceEventData {
vshControl * ctl ;
bool loop ;
bool timestamp ;
int count ;
2019-07-14 12:47:34 +03:00
virshNodeDeviceEventCallback * cb ;
2016-08-08 22:34:21 +03:00
} ;
typedef struct virshNodeDeviceEventData virshNodeDeviceEventData ;
static void
2019-10-14 15:44:29 +03:00
vshEventLifecyclePrint ( virConnectPtr conn G_GNUC_UNUSED ,
2016-08-08 22:34:21 +03:00
virNodeDevicePtr dev ,
int event ,
2019-10-14 15:44:29 +03:00
int detail G_GNUC_UNUSED ,
2016-08-08 22:34:21 +03:00
void * opaque )
{
virshNodeDeviceEventData * data = opaque ;
if ( ! data - > loop & & data - > count )
return ;
if ( data - > timestamp ) {
char timestamp [ VIR_TIME_STRING_BUFLEN ] ;
if ( virTimeStringNowRaw ( timestamp ) < 0 )
timestamp [ 0 ] = ' \0 ' ;
2023-03-09 17:54:58 +03:00
vshPrint ( data - > ctl , _ ( " %1$s: event 'lifecycle' for node device %2$s: %3$s \n " ) ,
2016-08-08 22:34:21 +03:00
timestamp ,
virNodeDeviceGetName ( dev ) , virshNodeDeviceEventToString ( event ) ) ;
} else {
2023-03-09 17:54:58 +03:00
vshPrint ( data - > ctl , _ ( " event 'lifecycle' for node device %1$s: %2$s \n " ) ,
2016-08-08 22:34:21 +03:00
virNodeDeviceGetName ( dev ) , virshNodeDeviceEventToString ( event ) ) ;
}
data - > count + + ;
if ( ! data - > loop )
vshEventDone ( data - > ctl ) ;
}
2016-08-11 18:15:23 +03:00
static void
2019-10-14 15:44:29 +03:00
vshEventGenericPrint ( virConnectPtr conn G_GNUC_UNUSED ,
2016-08-11 18:15:23 +03:00
virNodeDevicePtr dev ,
void * opaque )
{
virshNodeDeviceEventData * data = opaque ;
if ( ! data - > loop & & data - > count )
return ;
if ( data - > timestamp ) {
char timestamp [ VIR_TIME_STRING_BUFLEN ] ;
if ( virTimeStringNowRaw ( timestamp ) < 0 )
timestamp [ 0 ] = ' \0 ' ;
2023-03-09 17:54:58 +03:00
vshPrint ( data - > ctl , _ ( " %1$s: event '%2$s' for node device %3$s \n " ) ,
2016-08-11 18:15:23 +03:00
timestamp ,
data - > cb - > name ,
virNodeDeviceGetName ( dev ) ) ;
} else {
2023-03-09 17:54:58 +03:00
vshPrint ( data - > ctl , _ ( " event '%1$s' for node device %2$s \n " ) ,
2016-08-11 18:15:23 +03:00
data - > cb - > name ,
virNodeDeviceGetName ( dev ) ) ;
}
data - > count + + ;
if ( ! data - > loop )
vshEventDone ( data - > ctl ) ;
}
2019-07-14 12:47:34 +03:00
virshNodeDeviceEventCallback virshNodeDeviceEventCallbacks [ ] = {
2016-08-11 18:15:23 +03:00
{ " lifecycle " ,
VIR_NODE_DEVICE_EVENT_CALLBACK ( vshEventLifecyclePrint ) , } ,
{ " update " , vshEventGenericPrint , }
} ;
2020-01-09 13:39:55 +03:00
G_STATIC_ASSERT ( VIR_NODE_DEVICE_EVENT_ID_LAST = = G_N_ELEMENTS ( virshNodeDeviceEventCallbacks ) ) ;
2016-08-11 18:15:23 +03:00
2016-08-08 22:34:21 +03:00
static const vshCmdInfo info_node_device_event [ ] = {
{ . name = " help " ,
. data = N_ ( " Node Device Events " )
} ,
{ . name = " desc " ,
. data = N_ ( " List event types, or wait for node device events to occur " )
} ,
{ . name = NULL }
} ;
static const vshCmdOptDef opts_node_device_event [ ] = {
{ . name = " device " ,
. type = VSH_OT_STRING ,
2018-01-12 16:44:37 +03:00
. help = N_ ( " filter by node device name " ) ,
. completer = virshNodeDeviceNameCompleter ,
2016-08-08 22:34:21 +03:00
} ,
{ . name = " event " ,
. type = VSH_OT_STRING ,
2019-07-14 12:47:34 +03:00
. completer = virshNodeDeviceEventNameCompleter ,
2016-08-08 22:34:21 +03:00
. help = N_ ( " which event type to wait for " )
} ,
{ . name = " loop " ,
. type = VSH_OT_BOOL ,
. help = N_ ( " loop until timeout or interrupt, rather than one-shot " )
} ,
{ . name = " timeout " ,
. type = VSH_OT_INT ,
. help = N_ ( " timeout seconds " )
} ,
{ . name = " list " ,
. type = VSH_OT_BOOL ,
. help = N_ ( " list valid event types " )
} ,
{ . name = " timestamp " ,
. type = VSH_OT_BOOL ,
. help = N_ ( " show timestamp for each printed event " )
} ,
{ . name = NULL }
} ;
static bool
cmdNodeDeviceEvent ( vshControl * ctl , const vshCmd * cmd )
{
2021-09-26 12:44:30 +03:00
g_autoptr ( virshNodeDevice ) dev = NULL ;
2016-08-08 22:34:21 +03:00
bool ret = false ;
int eventId = - 1 ;
int timeout = 0 ;
virshNodeDeviceEventData data ;
const char * eventName = NULL ;
const char * device_value = NULL ;
int event ;
2021-03-11 10:16:13 +03:00
virshControl * priv = ctl - > privData ;
2016-08-08 22:34:21 +03:00
if ( vshCommandOptBool ( cmd , " list " ) ) {
size_t i ;
for ( i = 0 ; i < VIR_NODE_DEVICE_EVENT_ID_LAST ; i + + )
2019-07-14 12:47:34 +03:00
vshPrint ( ctl , " %s \n " , virshNodeDeviceEventCallbacks [ i ] . name ) ;
2016-08-08 22:34:21 +03:00
return true ;
}
if ( vshCommandOptStringReq ( ctl , cmd , " event " , & eventName ) < 0 )
return false ;
if ( ! eventName ) {
2016-09-06 14:14:34 +03:00
vshError ( ctl , " %s " , _ ( " either --list or --event <type> is required " ) ) ;
2016-08-08 22:34:21 +03:00
return false ;
}
2016-08-11 18:15:23 +03:00
for ( event = 0 ; event < VIR_NODE_DEVICE_EVENT_ID_LAST ; event + + )
2019-07-14 12:47:34 +03:00
if ( STREQ ( eventName , virshNodeDeviceEventCallbacks [ event ] . name ) )
2016-08-11 18:15:23 +03:00
break ;
if ( event = = VIR_NODE_DEVICE_EVENT_ID_LAST ) {
2023-03-09 17:54:58 +03:00
vshError ( ctl , _ ( " unknown event type %1$s " ) , eventName ) ;
2016-08-08 22:34:21 +03:00
return false ;
}
data . ctl = ctl ;
data . loop = vshCommandOptBool ( cmd , " loop " ) ;
data . timestamp = vshCommandOptBool ( cmd , " timestamp " ) ;
data . count = 0 ;
2019-07-14 12:47:34 +03:00
data . cb = & virshNodeDeviceEventCallbacks [ event ] ;
2016-08-08 22:34:21 +03:00
if ( vshCommandOptTimeoutToMs ( ctl , cmd , & timeout ) < 0 )
return false ;
if ( vshCommandOptStringReq ( ctl , cmd , " device " , & device_value ) < 0 )
return false ;
if ( device_value ) {
if ( ! ( dev = virNodeDeviceLookupByName ( priv - > conn , device_value ) ) ) {
vshError ( ctl , " %s '%s' " ,
_ ( " Could not find matching device " ) , device_value ) ;
goto cleanup ;
}
}
if ( vshEventStart ( ctl , timeout ) < 0 )
goto cleanup ;
if ( ( eventId = virConnectNodeDeviceEventRegisterAny ( priv - > conn , dev , event ,
2016-08-11 18:15:23 +03:00
data . cb - > cb ,
2016-08-08 22:34:21 +03:00
& data , NULL ) ) < 0 )
goto cleanup ;
switch ( vshEventWait ( ctl ) ) {
case VSH_EVENT_INTERRUPT :
vshPrint ( ctl , " %s " , _ ( " event loop interrupted \n " ) ) ;
break ;
case VSH_EVENT_TIMEOUT :
vshPrint ( ctl , " %s " , _ ( " event loop timed out \n " ) ) ;
break ;
case VSH_EVENT_DONE :
break ;
default :
goto cleanup ;
}
2023-03-09 17:54:58 +03:00
vshPrint ( ctl , _ ( " events received: %1$d \n " ) , data . count ) ;
2016-08-08 22:34:21 +03:00
if ( data . count )
ret = true ;
cleanup :
vshEventCleanup ( ctl ) ;
if ( eventId > = 0 & &
virConnectNodeDeviceEventDeregisterAny ( priv - > conn , eventId ) < 0 )
ret = false ;
return ret ;
}
2020-07-14 00:56:48 +03:00
/*
* " nodedev-undefine " command
*/
static const vshCmdInfo info_node_device_undefine [ ] = {
{ . name = " help " ,
. data = N_ ( " Undefine an inactive node device " )
} ,
{ . name = " desc " ,
. data = N_ ( " Undefines the configuration for an inactive node device " )
} ,
{ . name = NULL }
} ;
static const vshCmdOptDef opts_node_device_undefine [ ] = {
{ . name = " device " ,
. type = VSH_OT_DATA ,
. flags = VSH_OFLAG_REQ ,
. help = N_ ( " device name or wwn pair in 'wwnn,wwpn' format " ) ,
. completer = virshNodeDeviceNameCompleter ,
} ,
{ . name = NULL }
} ;
static bool
cmdNodeDeviceUndefine ( vshControl * ctl , const vshCmd * cmd G_GNUC_UNUSED )
{
2021-09-26 12:44:30 +03:00
g_autoptr ( virshNodeDevice ) dev = NULL ;
2020-07-14 00:56:48 +03:00
const char * device_value = NULL ;
if ( vshCommandOptStringReq ( ctl , cmd , " device " , & device_value ) < 0 )
return false ;
dev = vshFindNodeDevice ( ctl , device_value ) ;
if ( ! dev )
2021-11-04 17:26:07 +03:00
return false ;
2020-07-14 00:56:48 +03:00
2021-11-08 18:09:48 +03:00
if ( virNodeDeviceUndefine ( dev , 0 ) < 0 ) {
2023-03-09 17:54:58 +03:00
vshError ( ctl , _ ( " Failed to undefine node device '%1$s' " ) , device_value ) ;
2021-11-04 17:26:07 +03:00
return false ;
2020-07-14 00:56:48 +03:00
}
2023-03-09 17:54:58 +03:00
vshPrintExtra ( ctl , _ ( " Undefined node device '%1$s' \n " ) , device_value ) ;
2021-11-04 17:26:07 +03:00
return true ;
2020-07-14 00:56:48 +03:00
}
2020-07-14 00:40:47 +03:00
/*
* " nodedev-define " command
*/
static const vshCmdInfo info_node_device_define [ ] = {
{ . name = " help " ,
. data = N_ ( " Define a device by an xml file on a node " )
} ,
{ . name = " desc " ,
. data = N_ ( " Defines a persistent device on the node that can be "
" assigned to a domain. The device must be started before "
" it can be assigned to a domain. " )
} ,
{ . name = NULL }
} ;
static const vshCmdOptDef opts_node_device_define [ ] = {
VIRSH_COMMON_OPT_FILE ( N_ ( " file containing an XML description "
" of the device " ) ) ,
2022-10-18 14:19:05 +03:00
{ . name = " validate " ,
. type = VSH_OT_BOOL ,
. help = N_ ( " validate the XML against the schema " )
} ,
2020-07-14 00:40:47 +03:00
{ . name = NULL }
} ;
static bool
cmdNodeDeviceDefine ( vshControl * ctl , const vshCmd * cmd G_GNUC_UNUSED )
{
2021-09-26 12:44:30 +03:00
g_autoptr ( virshNodeDevice ) dev = NULL ;
2020-07-14 00:40:47 +03:00
const char * from = NULL ;
2021-08-11 16:25:15 +03:00
g_autofree char * buffer = NULL ;
2020-07-14 00:40:47 +03:00
virshControl * priv = ctl - > privData ;
2022-10-18 14:19:05 +03:00
unsigned int flags = 0 ;
2020-07-14 00:40:47 +03:00
if ( vshCommandOptStringReq ( ctl , cmd , " file " , & from ) < 0 )
return false ;
if ( virFileReadAll ( from , VSH_MAX_XML_FILE , & buffer ) < 0 )
return false ;
2022-10-18 14:19:05 +03:00
if ( vshCommandOptBool ( cmd , " validate " ) )
flags | = VIR_NODE_DEVICE_DEFINE_XML_VALIDATE ;
if ( ! ( dev = virNodeDeviceDefineXML ( priv - > conn , buffer , flags ) ) ) {
2023-03-09 17:54:58 +03:00
vshError ( ctl , _ ( " Failed to define node device from '%1$s' " ) , from ) ;
2021-09-24 02:49:08 +03:00
return false ;
2020-07-14 00:40:47 +03:00
}
2023-03-09 17:54:58 +03:00
vshPrintExtra ( ctl , _ ( " Node device '%1$s' defined from '%2$s' \n " ) ,
2021-09-24 02:49:08 +03:00
virNodeDeviceGetName ( dev ) , from ) ;
return true ;
2020-07-14 00:40:47 +03:00
}
2020-07-10 00:05:41 +03:00
/*
* " nodedev-start " command
*/
static const vshCmdInfo info_node_device_start [ ] = {
{ . name = " help " ,
. data = N_ ( " Start an inactive node device " )
} ,
{ . name = " desc " ,
. data = N_ ( " Starts an inactive node device that was previously defined " )
} ,
{ . name = NULL }
} ;
static const vshCmdOptDef opts_node_device_start [ ] = {
{ . name = " device " ,
. type = VSH_OT_DATA ,
. flags = VSH_OFLAG_REQ ,
. help = N_ ( " device name " ) ,
. completer = virshNodeDeviceNameCompleter ,
} ,
{ . name = NULL }
} ;
static bool
cmdNodeDeviceStart ( vshControl * ctl , const vshCmd * cmd )
{
const char * name = NULL ;
2021-09-26 12:44:30 +03:00
g_autoptr ( virshNodeDevice ) device = NULL ;
2020-07-10 00:05:41 +03:00
bool ret = true ;
virshControl * priv = ctl - > privData ;
if ( vshCommandOptStringReq ( ctl , cmd , " device " , & name ) < 0 )
return false ;
if ( ! ( device = virNodeDeviceLookupByName ( priv - > conn , name ) ) ) {
2023-03-09 17:54:58 +03:00
vshError ( ctl , _ ( " Could not find matching device '%1$s' " ) , name ) ;
2020-07-10 00:05:41 +03:00
return false ;
}
2021-04-09 18:50:03 +03:00
if ( virNodeDeviceCreate ( device , 0 ) = = 0 ) {
2023-03-09 17:54:58 +03:00
vshPrintExtra ( ctl , _ ( " Device %1$s started \n " ) , name ) ;
2020-07-10 00:05:41 +03:00
} else {
2023-03-09 17:54:58 +03:00
vshError ( ctl , _ ( " Failed to start device %1$s " ) , name ) ;
2020-07-10 00:05:41 +03:00
ret = false ;
}
return ret ;
}
2021-05-28 00:20:13 +03:00
/*
* " nodedev-autostart " command
*/
static const vshCmdInfo info_node_device_autostart [ ] = {
{ . name = " help " ,
. data = N_ ( " autostart a defined node device " )
} ,
{ . name = " desc " ,
. data = N_ ( " Configure a node device to be automatically started at boot. " )
} ,
{ . name = NULL }
} ;
static const vshCmdOptDef opts_node_device_autostart [ ] = {
{ . name = " device " ,
. type = VSH_OT_DATA ,
. flags = VSH_OFLAG_REQ ,
. help = N_ ( " device name or wwn pair in 'wwnn,wwpn' format " ) ,
. completer = virshNodeDeviceNameCompleter ,
} ,
{ . name = " disable " ,
. type = VSH_OT_BOOL ,
. help = N_ ( " disable autostarting " )
} ,
{ . name = NULL }
} ;
static bool
cmdNodeDeviceAutostart ( vshControl * ctl , const vshCmd * cmd )
{
2021-09-26 12:44:30 +03:00
g_autoptr ( virshNodeDevice ) dev = NULL ;
2021-05-28 00:20:13 +03:00
const char * name = NULL ;
int autostart ;
if ( vshCommandOptStringReq ( ctl , cmd , " device " , & name ) < 0 )
return false ;
dev = vshFindNodeDevice ( ctl , name ) ;
2021-11-04 17:26:07 +03:00
if ( ! dev )
return false ;
2021-05-28 00:20:13 +03:00
autostart = ! vshCommandOptBool ( cmd , " disable " ) ;
if ( virNodeDeviceSetAutostart ( dev , autostart ) < 0 ) {
if ( autostart )
2023-03-09 17:54:58 +03:00
vshError ( ctl , _ ( " failed to mark device %1$s as autostarted " ) , name ) ;
2021-05-28 00:20:13 +03:00
else
2023-03-09 17:54:58 +03:00
vshError ( ctl , _ ( " failed to unmark device %1$s as autostarted " ) , name ) ;
2021-11-04 17:26:07 +03:00
return false ;
2021-05-28 00:20:13 +03:00
}
if ( autostart )
2023-03-09 17:54:58 +03:00
vshPrintExtra ( ctl , _ ( " Device %1$s marked as autostarted \n " ) , name ) ;
2021-05-28 00:20:13 +03:00
else
2023-03-09 17:54:58 +03:00
vshPrintExtra ( ctl , _ ( " Device %1$s unmarked as autostarted \n " ) , name ) ;
2021-05-28 00:20:13 +03:00
2021-11-04 17:26:07 +03:00
return true ;
2021-05-28 00:20:13 +03:00
}
2021-06-02 23:27:41 +03:00
/*
* " nodedev-info " command
*/
static const vshCmdInfo info_node_device_info [ ] = {
{ . name = " help " ,
. data = N_ ( " node device information " )
} ,
{ . name = " desc " ,
. data = N_ ( " Returns basic information about the node device " )
} ,
{ . name = NULL }
} ;
static const vshCmdOptDef opts_node_device_info [ ] = {
{ . name = " device " ,
. type = VSH_OT_DATA ,
. flags = VSH_OFLAG_REQ ,
. help = N_ ( " device name or wwn pair in 'wwnn,wwpn' format " ) ,
. completer = virshNodeDeviceNameCompleter ,
} ,
{ . name = NULL }
} ;
static bool
cmdNodeDeviceInfo ( vshControl * ctl , const vshCmd * cmd )
{
2021-09-26 12:44:30 +03:00
g_autoptr ( virshNodeDevice ) device = NULL ;
2021-06-02 23:27:41 +03:00
const char * device_value = NULL ;
int autostart ;
const char * parent = NULL ;
if ( vshCommandOptStringReq ( ctl , cmd , " device " , & device_value ) < 0 )
return false ;
device = vshFindNodeDevice ( ctl , device_value ) ;
if ( ! device )
2021-11-04 17:26:07 +03:00
return false ;
2021-06-02 23:27:41 +03:00
parent = virNodeDeviceGetParent ( device ) ;
vshPrint ( ctl , " %-15s %s \n " , _ ( " Name: " ) , virNodeDeviceGetName ( device ) ) ;
vshPrint ( ctl , " %-15s %s \n " , _ ( " Parent: " ) , parent ? parent : " " ) ;
vshPrint ( ctl , " %-15s %s \n " , _ ( " Active: " ) , virNodeDeviceIsActive ( device ) ?
_ ( " yes " ) : _ ( " no " ) ) ;
vshPrint ( ctl , " %-15s %s \n " , _ ( " Persistent: " ) ,
virNodeDeviceIsPersistent ( device ) ? _ ( " yes " ) : _ ( " no " ) ) ;
if ( virNodeDeviceGetAutostart ( device , & autostart ) < 0 )
vshPrint ( ctl , " %-15s %s \n " , _ ( " Autostart: " ) , _ ( " no autostart " ) ) ;
else
vshPrint ( ctl , " %-15s %s \n " , _ ( " Autostart: " ) , autostart ? _ ( " yes " ) : _ ( " no " ) ) ;
2021-11-04 17:26:07 +03:00
return true ;
2021-06-02 23:27:41 +03:00
}
2012-08-21 02:23:10 +04:00
const vshCmdDef nodedevCmds [ ] = {
2013-02-07 19:25:10 +04:00
{ . name = " nodedev-create " ,
. handler = cmdNodeDeviceCreate ,
. opts = opts_node_device_create ,
. info = info_node_device_create ,
. flags = 0
} ,
{ . name = " nodedev-destroy " ,
. handler = cmdNodeDeviceDestroy ,
. opts = opts_node_device_destroy ,
. info = info_node_device_destroy ,
. flags = 0
} ,
{ . name = " nodedev-detach " ,
. handler = cmdNodeDeviceDetach ,
. opts = opts_node_device_detach ,
. info = info_node_device_detach ,
. flags = 0
} ,
{ . name = " nodedev-dettach " ,
2016-09-07 18:30:48 +03:00
. flags = VSH_CMD_FLAG_ALIAS ,
. alias = " nodedev-detach "
2013-02-07 19:25:10 +04:00
} ,
{ . name = " nodedev-dumpxml " ,
. handler = cmdNodeDeviceDumpXML ,
. opts = opts_node_device_dumpxml ,
. info = info_node_device_dumpxml ,
. flags = 0
} ,
{ . name = " nodedev-list " ,
. handler = cmdNodeListDevices ,
. opts = opts_node_list_devices ,
. info = info_node_list_devices ,
. flags = 0
} ,
{ . name = " nodedev-reattach " ,
. handler = cmdNodeDeviceReAttach ,
. opts = opts_node_device_reattach ,
. info = info_node_device_reattach ,
. flags = 0
} ,
{ . name = " nodedev-reset " ,
. handler = cmdNodeDeviceReset ,
. opts = opts_node_device_reset ,
. info = info_node_device_reset ,
. flags = 0
} ,
2016-08-08 22:34:21 +03:00
{ . name = " nodedev-event " ,
. handler = cmdNodeDeviceEvent ,
. opts = opts_node_device_event ,
. info = info_node_device_event ,
. flags = 0
} ,
2020-07-14 00:40:47 +03:00
{ . name = " nodedev-define " ,
. handler = cmdNodeDeviceDefine ,
. opts = opts_node_device_define ,
. info = info_node_device_define ,
. flags = 0
} ,
2020-07-14 00:56:48 +03:00
{ . name = " nodedev-undefine " ,
. handler = cmdNodeDeviceUndefine ,
. opts = opts_node_device_undefine ,
. info = info_node_device_undefine ,
. flags = 0
} ,
2020-07-10 00:05:41 +03:00
{ . name = " nodedev-start " ,
. handler = cmdNodeDeviceStart ,
. opts = opts_node_device_start ,
. info = info_node_device_start ,
. flags = 0
} ,
2021-05-28 00:20:13 +03:00
{ . name = " nodedev-autostart " ,
. handler = cmdNodeDeviceAutostart ,
. opts = opts_node_device_autostart ,
. info = info_node_device_autostart ,
. flags = 0
} ,
2021-06-02 23:27:41 +03:00
{ . name = " nodedev-info " ,
. handler = cmdNodeDeviceInfo ,
. opts = opts_node_device_info ,
. info = info_node_device_info ,
. flags = 0
} ,
2013-02-07 19:25:10 +04:00
{ . name = NULL }
2012-07-23 11:19:04 +04:00
} ;