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>
# include "virsh-nodedev.h"
# 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"
2015-04-01 18:09:04 +03:00
# include "virstring.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 " ) ) ,
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 )
{
virNodeDevicePtr dev = NULL ;
const char * from = NULL ;
bool ret = true ;
char * buffer ;
2015-06-15 19:53:58 +03:00
virshControlPtr priv = ctl - > privData ;
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 ;
2015-06-15 19:53:58 +03:00
dev = virNodeDeviceCreateXML ( priv - > conn , buffer , 0 ) ;
2012-07-23 11:08:39 +04:00
VIR_FREE ( buffer ) ;
if ( dev ! = NULL ) {
2016-08-24 17:14:23 +03:00
vshPrintExtra ( ctl , _ ( " Node device %s created from %s \n " ) ,
virNodeDeviceGetName ( dev ) , from ) ;
2012-07-23 11:08:39 +04:00
virNodeDeviceFree ( dev ) ;
} else {
vshError ( ctl , _ ( " Failed to create node device from %s " ) , from ) ;
ret = false ;
}
return ret ;
}
/*
* " 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
} ;
static bool
cmdNodeDeviceDestroy ( vshControl * ctl , const vshCmd * cmd )
{
virNodeDevicePtr dev = NULL ;
2013-02-04 18:16:44 +04:00
bool ret = false ;
const char * device_value = NULL ;
char * * arr = NULL ;
int narr ;
2015-06-15 19:53:58 +03:00
virshControlPtr priv = ctl - > privData ;
2012-07-23 11:08:39 +04:00
2013-02-04 18:16:44 +04:00
if ( vshCommandOptStringReq ( ctl , cmd , " device " , & device_value ) < 0 )
2012-07-23 11:08:39 +04:00
return false ;
2013-02-04 18:16:44 +04:00
if ( strchr ( device_value , ' , ' ) ) {
narr = vshStringToArray ( device_value , & arr ) ;
if ( narr ! = 2 ) {
vshError ( ctl , _ ( " Malformed device value '%s' " ) , device_value ) ;
goto cleanup ;
}
if ( ! virValidateWWN ( arr [ 0 ] ) | | ! virValidateWWN ( arr [ 1 ] ) )
goto cleanup ;
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 {
2015-06-15 19:53:58 +03:00
dev = virNodeDeviceLookupByName ( priv - > conn , device_value ) ;
2013-02-04 18:16:44 +04:00
}
if ( ! dev ) {
vshError ( ctl , " %s '%s' " , _ ( " Could not find matching device " ) , device_value ) ;
goto cleanup ;
}
2012-07-23 11:08:39 +04:00
if ( virNodeDeviceDestroy ( dev ) = = 0 ) {
2016-08-24 17:14:23 +03:00
vshPrintExtra ( ctl , _ ( " Destroyed node device '%s' \n " ) , device_value ) ;
2012-07-23 11:08:39 +04:00
} else {
2013-02-04 18:16:44 +04:00
vshError ( ctl , _ ( " Failed to destroy node device '%s' " ) , device_value ) ;
goto cleanup ;
2012-07-23 11:08:39 +04:00
}
2013-02-04 18:16:44 +04:00
ret = true ;
2014-03-25 10:53:59 +04:00
cleanup :
2020-08-02 20:36:03 +03:00
g_strfreev ( arr ) ;
2014-06-02 18:48:22 +04:00
if ( dev )
virNodeDeviceFree ( dev ) ;
2012-07-23 11:08:39 +04:00
return ret ;
}
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 ;
} ;
2015-06-15 19:53:58 +03:00
typedef struct virshNodeDeviceList * virshNodeDeviceListPtr ;
2012-09-17 07:32:53 +04:00
static void
2015-06-15 19:53:58 +03:00
virshNodeDeviceListFree ( virshNodeDeviceListPtr 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 + + ) {
if ( list - > devices [ i ] )
virNodeDeviceFree ( list - > devices [ i ] ) ;
}
VIR_FREE ( list - > devices ) ;
}
VIR_FREE ( list ) ;
}
2015-06-15 19:53:58 +03:00
static virshNodeDeviceListPtr
virshNodeDeviceListCollect ( vshControl * ctl ,
2012-09-17 07:32:53 +04:00
char * * capnames ,
int ncapnames ,
unsigned int flags )
{
2020-10-05 19:50:09 +03:00
virshNodeDeviceListPtr 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 ;
2015-06-15 19:53:58 +03:00
virshControlPtr 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 + + ) {
char * * caps = NULL ;
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 " ) ) ;
VIR_FREE ( caps ) ;
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 ;
}
}
}
VIR_FREE ( caps ) ;
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 */
virNodeDeviceFree ( list - > devices [ i ] ) ;
list - > devices [ i ] = NULL ;
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 ) {
2015-06-15 19:53:58 +03:00
virshNodeDeviceListFree ( list ) ;
2012-09-17 07:32:53 +04:00
list = NULL ;
}
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 " )
} ,
{ . 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 ;
char * * caps = NULL ;
int ncaps = 0 ;
2015-06-15 19:53:58 +03:00
virshNodeDeviceListPtr list = NULL ;
2012-09-17 07:32:53 +04:00
int cap_type = - 1 ;
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 ) {
if ( tree ) {
vshError ( ctl , " %s " , _ ( " Options --tree and --cap are incompatible " ) ) ;
return false ;
}
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
}
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 ;
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 ;
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
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 :
2020-08-02 20:36:03 +03:00
g_strfreev ( caps ) ;
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
} ,
{ . name = NULL }
2012-07-23 11:08:39 +04:00
} ;
static bool
cmdNodeDeviceDumpXML ( vshControl * ctl , const vshCmd * cmd )
{
2013-01-21 20:41:14 +04:00
virNodeDevicePtr device = NULL ;
char * xml = NULL ;
2013-02-04 18:16:44 +04:00
const char * device_value = NULL ;
char * * arr = NULL ;
int narr ;
2013-01-21 20:41:14 +04:00
bool ret = false ;
2015-06-15 19:53:58 +03:00
virshControlPtr priv = ctl - > privData ;
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
2013-02-04 18:16:44 +04:00
if ( strchr ( device_value , ' , ' ) ) {
narr = vshStringToArray ( device_value , & arr ) ;
if ( narr ! = 2 ) {
vshError ( ctl , _ ( " Malformed device value '%s' " ) , device_value ) ;
goto cleanup ;
}
if ( ! virValidateWWN ( arr [ 0 ] ) | | ! virValidateWWN ( arr [ 1 ] ) )
goto cleanup ;
2015-06-15 19:53:58 +03:00
device = virNodeDeviceLookupSCSIHostByWWN ( priv - > conn , arr [ 0 ] , arr [ 1 ] , 0 ) ;
2013-02-04 18:16:44 +04:00
} else {
2015-06-15 19:53:58 +03:00
device = virNodeDeviceLookupByName ( priv - > conn , device_value ) ;
2013-02-04 18:16:44 +04:00
}
if ( ! device ) {
vshError ( ctl , " %s '%s' " , _ ( " Could not find matching device " ) , device_value ) ;
goto cleanup ;
2012-07-23 11:08:39 +04:00
}
2013-01-21 20:41:14 +04:00
if ( ! ( xml = virNodeDeviceGetXMLDesc ( device , 0 ) ) )
goto cleanup ;
2012-07-23 11:08:39 +04:00
vshPrint ( ctl , " %s \n " , xml ) ;
2013-01-21 20:41:14 +04:00
2013-02-04 18:16:44 +04:00
ret = true ;
2014-03-25 10:53:59 +04:00
cleanup :
2020-08-02 20:36:03 +03:00
g_strfreev ( arr ) ;
2012-07-23 11:08:39 +04:00
VIR_FREE ( xml ) ;
2014-06-02 18:48:22 +04:00
if ( device )
virNodeDeviceFree ( device ) ;
2013-01-21 20:41:14 +04:00
return ret ;
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 ,
2013-06-27 15:21:07 +04:00
. help = N_ ( " pci device assignment backend driver (e.g. 'vfio' or 'kvm') " )
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 ;
2012-07-23 11:08:39 +04:00
virNodeDevicePtr device ;
bool ret = true ;
2015-06-15 19:53:58 +03:00
virshControlPtr 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 ) ) ) {
2013-01-21 20:41:14 +04:00
vshError ( ctl , _ ( " Could not find matching device '%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 )
2016-08-24 17:14:23 +03:00
vshPrintExtra ( ctl , _ ( " Device %s detached \n " ) , name ) ;
2013-04-24 22:22:36 +04:00
else
vshError ( ctl , _ ( " Failed to detach device %s " ) , name ) ;
2012-07-23 11:08:39 +04:00
virNodeDeviceFree ( device ) ;
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 ;
virNodeDevicePtr device ;
bool ret = true ;
2015-06-15 19:53:58 +03:00
virshControlPtr 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 ) ) ) {
2013-01-21 20:41:14 +04:00
vshError ( ctl , _ ( " Could not find matching device '%s' " ) , name ) ;
2012-07-23 11:08:39 +04:00
return false ;
}
if ( virNodeDeviceReAttach ( device ) = = 0 ) {
2016-08-24 17:14:23 +03:00
vshPrintExtra ( ctl , _ ( " Device %s re-attached \n " ) , name ) ;
2012-07-23 11:08:39 +04:00
} else {
vshError ( ctl , _ ( " Failed to re-attach device %s " ) , name ) ;
ret = false ;
}
2013-01-21 20:41:14 +04:00
2012-07-23 11:08:39 +04:00
virNodeDeviceFree ( device ) ;
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 ;
virNodeDevicePtr device ;
bool ret = true ;
2015-06-15 19:53:58 +03:00
virshControlPtr 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 ) ) ) {
2013-01-21 20:41:14 +04:00
vshError ( ctl , _ ( " Could not find matching device '%s' " ) , name ) ;
2012-07-23 11:08:39 +04:00
return false ;
}
if ( virNodeDeviceReset ( device ) = = 0 ) {
2016-08-24 17:14:23 +03:00
vshPrintExtra ( ctl , _ ( " Device %s reset \n " ) , name ) ;
2012-07-23 11:08:39 +04:00
} else {
vshError ( ctl , _ ( " Failed to reset device %s " ) , name ) ;
ret = false ;
}
2013-01-21 20:41:14 +04:00
2012-07-23 11:08:39 +04:00
virNodeDeviceFree ( device ) ;
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 " ) ,
2019-01-20 19:30:15 +03:00
N_ ( " Deleted " ) ) ;
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 ' ;
vshPrint ( data - > ctl , _ ( " %s: event 'lifecycle' for node device %s: %s \n " ) ,
timestamp ,
virNodeDeviceGetName ( dev ) , virshNodeDeviceEventToString ( event ) ) ;
} else {
vshPrint ( data - > ctl , _ ( " event 'lifecycle' for node device %s: %s \n " ) ,
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 ' ;
2016-12-01 23:50:08 +03:00
vshPrint ( data - > ctl , _ ( " %s: event '%s' for node device %s \n " ) ,
2016-08-11 18:15:23 +03:00
timestamp ,
data - > cb - > name ,
virNodeDeviceGetName ( dev ) ) ;
} else {
vshPrint ( data - > ctl , _ ( " event '%s' for node device %s \n " ) ,
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 )
{
virNodeDevicePtr dev = NULL ;
bool ret = false ;
int eventId = - 1 ;
int timeout = 0 ;
virshNodeDeviceEventData data ;
const char * eventName = NULL ;
const char * device_value = NULL ;
int event ;
virshControlPtr priv = ctl - > privData ;
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 ) {
2016-08-08 22:34:21 +03:00
vshError ( ctl , _ ( " unknown event type %s " ) , eventName ) ;
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 ;
}
vshPrint ( ctl , _ ( " events received: %d \n " ) , data . count ) ;
if ( data . count )
ret = true ;
cleanup :
vshEventCleanup ( ctl ) ;
if ( eventId > = 0 & &
virConnectNodeDeviceEventDeregisterAny ( priv - > conn , eventId ) < 0 )
ret = false ;
if ( dev )
virNodeDeviceFree ( dev ) ;
return ret ;
}
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
} ,
2013-02-07 19:25:10 +04:00
{ . name = NULL }
2012-07-23 11:19:04 +04:00
} ;