2017-10-31 11:24:21 +03:00
/*
* virsh - completer . c : virsh completer callbacks
*
* Copyright ( C ) 2017 Red Hat , Inc .
*
* 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
* License along with this library . If not , see
* < http : //www.gnu.org/licenses/>.
*/
# include <config.h>
# include "virsh-completer.h"
2018-05-23 09:32:42 +03:00
# include "virsh-domain.h"
2017-10-31 11:24:21 +03:00
# include "virsh.h"
2018-01-12 16:15:11 +03:00
# include "virsh-pool.h"
2018-05-23 09:32:46 +03:00
# include "virsh-nodedev.h"
2017-10-31 11:24:21 +03:00
# include "virsh-util.h"
2018-05-23 09:32:40 +03:00
# include "virsh-secret.h"
2019-03-05 06:17:39 +03:00
# include "virsh-network.h"
2017-10-31 11:24:21 +03:00
# include "internal.h"
2018-05-21 14:53:44 +03:00
# include "virutil.h"
2017-10-31 11:24:21 +03:00
# include "viralloc.h"
2018-07-12 17:07:59 +03:00
# include "virmacaddr.h"
2017-10-31 11:24:21 +03:00
# include "virstring.h"
2017-11-06 17:48:01 +03:00
# include "virxml.h"
2019-06-14 15:27:13 +03:00
# include "conf/node_device_conf.h"
2017-10-31 11:24:21 +03:00
2019-01-22 14:23:07 +03:00
/**
* A completer callback is a function that accepts three arguments :
*
* @ ctl : virsh control structure
* @ cmd : parsed input
* @ flags : optional flags to alter completer ' s behaviour
*
* The @ ctl contains connection to the daemon ( should the
* completer need it ) . Any completer that requires a connection
* must check whether connection is still alive .
*
* The @ cmd contains parsed user input which might be missing
* some arguments ( if user is still typing the command ) , but may
* already contain important data . For instance if the completer
* needs domain XML it may inspect @ cmd to find - - domain . Using
* existing wrappers is advised . If @ cmd does not contain all
* necessary bits , completer might return sensible defaults ( i . e .
* generic values not tailored to specific use case ) or return
* NULL ( i . e . no strings are offered to the user for completion ) .
*
* The @ flags contains a . completer_flags value defined for each
* use or 0 if no . completer_flags were specified . If a completer
2019-03-28 19:42:23 +03:00
* is generic enough @ flags can be used to alter its behaviour .
2019-01-22 14:23:07 +03:00
* For instance , a completer to fetch names of domains can use
* @ flags to return names of only domains in a particular state
* that the command accepts .
*
* Under no circumstances should a completer output anything .
* Neither to stdout nor to stderr . This would harm the user
* experience .
*/
2019-06-18 13:16:17 +03:00
/**
* virshCommaStringListComplete :
* @ input : user input so far
* @ options : ALL options available for argument
*
* Some arguments to our commands accept the following form :
*
* virsh command - - arg str1 , str2 , str3
*
* This does not play nicely with our completer funtions , because
* they have to return strings prepended with user ' s input . For
* instance :
*
* str1 , str2 , str3 , strA
* str1 , str2 , str3 , strB
* str1 , str2 , str3 , strC
*
* This helper function takes care of that . In this specific case
* it would be called as follows :
*
* virshCommaStringListComplete ( " str1,str2,str3 " ,
* { " strA " , " strB " , " strC " , NULL } ) ;
*
* Returns : string list of completions on success ,
* NULL otherwise .
*/
static char * *
virshCommaStringListComplete ( const char * input ,
const char * * options )
{
const size_t optionsLen = virStringListLength ( options ) ;
VIR_AUTOFREE ( char * ) inputCopy = NULL ;
VIR_AUTOSTRINGLIST inputList = NULL ;
VIR_AUTOSTRINGLIST ret = NULL ;
size_t nret = 0 ;
size_t i ;
if ( STREQ_NULLABLE ( input , " " ) )
input = NULL ;
if ( input ) {
char * comma = NULL ;
if ( VIR_STRDUP ( inputCopy , input ) < 0 )
return NULL ;
if ( ( comma = strrchr ( inputCopy , ' , ' ) ) )
* comma = ' \0 ' ;
else
VIR_FREE ( inputCopy ) ;
}
if ( inputCopy & & ! ( inputList = virStringSplit ( inputCopy , " , " , 0 ) ) )
return NULL ;
if ( VIR_ALLOC_N ( ret , optionsLen + 1 ) < 0 )
return NULL ;
for ( i = 0 ; i < optionsLen ; i + + ) {
if ( virStringListHasString ( ( const char * * ) inputList , options [ i ] ) )
continue ;
if ( ( inputCopy & & virAsprintf ( & ret [ nret ] , " %s,%s " , inputCopy , options [ i ] ) < 0 ) | |
( ! inputCopy & & VIR_STRDUP ( ret [ nret ] , options [ i ] ) < 0 ) )
return NULL ;
nret + + ;
}
VIR_RETURN_PTR ( ret ) ;
}
2017-10-31 11:24:21 +03:00
char * *
virshDomainNameCompleter ( vshControl * ctl ,
const vshCmd * cmd ATTRIBUTE_UNUSED ,
unsigned int flags )
{
virshControlPtr priv = ctl - > privData ;
virDomainPtr * domains = NULL ;
int ndomains = 0 ;
size_t i = 0 ;
char * * ret = NULL ;
2019-03-29 16:36:57 +03:00
VIR_AUTOSTRINGLIST tmp = NULL ;
2017-10-31 11:24:21 +03:00
virCheckFlags ( VIR_CONNECT_LIST_DOMAINS_ACTIVE |
VIR_CONNECT_LIST_DOMAINS_INACTIVE |
2018-01-25 16:47:56 +03:00
VIR_CONNECT_LIST_DOMAINS_OTHER |
VIR_CONNECT_LIST_DOMAINS_PAUSED |
2017-10-31 11:24:21 +03:00
VIR_CONNECT_LIST_DOMAINS_PERSISTENT |
VIR_CONNECT_LIST_DOMAINS_RUNNING |
2018-01-25 16:47:56 +03:00
VIR_CONNECT_LIST_DOMAINS_SHUTOFF ,
2017-10-31 11:24:21 +03:00
NULL ) ;
if ( ! priv - > conn | | virConnectIsAlive ( priv - > conn ) < = 0 )
return NULL ;
if ( ( ndomains = virConnectListAllDomains ( priv - > conn , & domains , flags ) ) < 0 )
return NULL ;
2019-03-28 20:03:30 +03:00
if ( VIR_ALLOC_N ( tmp , ndomains + 1 ) < 0 )
2019-03-29 18:46:54 +03:00
goto cleanup ;
2017-10-31 11:24:21 +03:00
for ( i = 0 ; i < ndomains ; i + + ) {
const char * name = virDomainGetName ( domains [ i ] ) ;
2019-03-28 20:03:30 +03:00
if ( VIR_STRDUP ( tmp [ i ] , name ) < 0 )
2019-03-29 18:46:54 +03:00
goto cleanup ;
2017-10-31 11:24:21 +03:00
}
2019-03-28 20:03:30 +03:00
VIR_STEAL_PTR ( ret , tmp ) ;
2019-03-28 20:26:44 +03:00
cleanup :
2019-03-28 20:32:36 +03:00
for ( i = 0 ; i < ndomains ; i + + )
virshDomainFree ( domains [ i ] ) ;
VIR_FREE ( domains ) ;
2017-10-31 11:24:21 +03:00
return ret ;
}
2017-11-06 17:48:01 +03:00
char * *
virshDomainInterfaceCompleter ( vshControl * ctl ,
const vshCmd * cmd ,
unsigned int flags )
{
virshControlPtr priv = ctl - > privData ;
2019-03-29 20:18:57 +03:00
VIR_AUTOPTR ( xmlDoc ) xmldoc = NULL ;
VIR_AUTOPTR ( xmlXPathContext ) ctxt = NULL ;
2017-11-06 17:48:01 +03:00
int ninterfaces ;
2019-03-29 17:04:43 +03:00
VIR_AUTOFREE ( xmlNodePtr * ) interfaces = NULL ;
2017-11-06 17:48:01 +03:00
size_t i ;
unsigned int domainXMLFlags = 0 ;
char * * ret = NULL ;
2019-03-29 16:36:57 +03:00
VIR_AUTOSTRINGLIST tmp = NULL ;
2017-11-06 17:48:01 +03:00
virCheckFlags ( VIRSH_DOMAIN_INTERFACE_COMPLETER_MAC , NULL ) ;
if ( ! priv - > conn | | virConnectIsAlive ( priv - > conn ) < = 0 )
return NULL ;
if ( vshCommandOptBool ( cmd , " config " ) )
domainXMLFlags = VIR_DOMAIN_XML_INACTIVE ;
if ( virshDomainGetXML ( ctl , cmd , domainXMLFlags , & xmldoc , & ctxt ) < 0 )
2019-03-29 18:46:54 +03:00
return NULL ;
2017-11-06 17:48:01 +03:00
ninterfaces = virXPathNodeSet ( " ./devices/interface " , ctxt , & interfaces ) ;
if ( ninterfaces < 0 )
2019-03-29 18:46:54 +03:00
return NULL ;
2017-11-06 17:48:01 +03:00
2018-05-21 12:00:01 +03:00
if ( VIR_ALLOC_N ( tmp , ninterfaces + 1 ) < 0 )
2019-03-29 18:46:54 +03:00
return NULL ;
2017-11-06 17:48:01 +03:00
for ( i = 0 ; i < ninterfaces ; i + + ) {
ctxt - > node = interfaces [ i ] ;
if ( ! ( flags & VIRSH_DOMAIN_INTERFACE_COMPLETER_MAC ) & &
2018-05-21 12:00:01 +03:00
( tmp [ i ] = virXPathString ( " string(./target/@dev) " , ctxt ) ) )
2017-11-06 17:48:01 +03:00
continue ;
/* In case we are dealing with inactive domain XML there's no
* < target dev = ' ' / > . Offer MAC addresses then . */
2018-05-21 12:00:01 +03:00
if ( ! ( tmp [ i ] = virXPathString ( " string(./mac/@address) " , ctxt ) ) )
2019-03-29 18:46:54 +03:00
return NULL ;
2017-11-06 17:48:01 +03:00
}
2018-05-21 12:00:01 +03:00
VIR_STEAL_PTR ( ret , tmp ) ;
2017-11-06 17:48:01 +03:00
return ret ;
}
2018-01-12 16:01:33 +03:00
2018-05-15 14:18:23 +03:00
char * *
virshDomainDiskTargetCompleter ( vshControl * ctl ,
const vshCmd * cmd ,
unsigned int flags )
{
virshControlPtr priv = ctl - > privData ;
2019-03-29 20:18:57 +03:00
VIR_AUTOPTR ( xmlDoc ) xmldoc = NULL ;
VIR_AUTOPTR ( xmlXPathContext ) ctxt = NULL ;
2019-03-29 17:04:43 +03:00
VIR_AUTOFREE ( xmlNodePtr * ) disks = NULL ;
2018-05-15 14:18:23 +03:00
int ndisks ;
size_t i ;
2019-03-29 16:36:57 +03:00
VIR_AUTOSTRINGLIST tmp = NULL ;
2018-05-15 14:18:23 +03:00
char * * ret = NULL ;
virCheckFlags ( 0 , NULL ) ;
if ( ! priv - > conn | | virConnectIsAlive ( priv - > conn ) < = 0 )
return NULL ;
if ( virshDomainGetXML ( ctl , cmd , 0 , & xmldoc , & ctxt ) < 0 )
2019-03-29 18:46:54 +03:00
return NULL ;
2018-05-15 14:18:23 +03:00
ndisks = virXPathNodeSet ( " ./devices/disk " , ctxt , & disks ) ;
if ( ndisks < 0 )
2019-03-29 18:46:54 +03:00
return NULL ;
2018-05-15 14:18:23 +03:00
2018-05-21 12:00:01 +03:00
if ( VIR_ALLOC_N ( tmp , ndisks + 1 ) < 0 )
2019-03-29 18:46:54 +03:00
return NULL ;
2018-05-15 14:18:23 +03:00
for ( i = 0 ; i < ndisks ; i + + ) {
ctxt - > node = disks [ i ] ;
2018-05-21 12:00:01 +03:00
if ( ! ( tmp [ i ] = virXPathString ( " string(./target/@dev) " , ctxt ) ) )
2019-03-29 18:46:54 +03:00
return NULL ;
2018-05-15 14:18:23 +03:00
}
2018-05-21 12:00:01 +03:00
VIR_STEAL_PTR ( ret , tmp ) ;
2018-05-15 14:18:23 +03:00
return ret ;
}
2018-01-12 16:01:33 +03:00
char * *
virshStoragePoolNameCompleter ( vshControl * ctl ,
const vshCmd * cmd ATTRIBUTE_UNUSED ,
unsigned int flags )
{
virshControlPtr priv = ctl - > privData ;
virStoragePoolPtr * pools = NULL ;
int npools = 0 ;
size_t i = 0 ;
char * * ret = NULL ;
2019-03-29 16:36:57 +03:00
VIR_AUTOSTRINGLIST tmp = NULL ;
2018-01-12 16:01:33 +03:00
virCheckFlags ( VIR_CONNECT_LIST_STORAGE_POOLS_INACTIVE |
VIR_CONNECT_LIST_STORAGE_POOLS_ACTIVE |
VIR_CONNECT_LIST_STORAGE_POOLS_PERSISTENT ,
NULL ) ;
if ( ! priv - > conn | | virConnectIsAlive ( priv - > conn ) < = 0 )
return NULL ;
if ( ( npools = virConnectListAllStoragePools ( priv - > conn , & pools , flags ) ) < 0 )
return NULL ;
2019-03-28 20:03:30 +03:00
if ( VIR_ALLOC_N ( tmp , npools + 1 ) < 0 )
2019-03-29 18:46:54 +03:00
goto cleanup ;
2018-01-12 16:01:33 +03:00
for ( i = 0 ; i < npools ; i + + ) {
const char * name = virStoragePoolGetName ( pools [ i ] ) ;
2019-03-28 20:03:30 +03:00
if ( VIR_STRDUP ( tmp [ i ] , name ) < 0 )
2019-03-29 18:46:54 +03:00
goto cleanup ;
2018-01-12 16:01:33 +03:00
}
2019-03-28 20:03:30 +03:00
VIR_STEAL_PTR ( ret , tmp ) ;
2019-03-28 20:26:44 +03:00
cleanup :
2019-03-28 20:32:36 +03:00
for ( i = 0 ; i < npools ; i + + )
virStoragePoolFree ( pools [ i ] ) ;
VIR_FREE ( pools ) ;
2018-01-12 16:01:33 +03:00
return ret ;
}
2018-01-12 16:15:11 +03:00
char * *
virshStorageVolNameCompleter ( vshControl * ctl ,
const vshCmd * cmd ,
unsigned int flags )
{
virshControlPtr priv = ctl - > privData ;
virStoragePoolPtr pool = NULL ;
virStorageVolPtr * vols = NULL ;
2019-03-28 05:15:43 +03:00
int rc ;
2018-01-12 16:15:11 +03:00
int nvols = 0 ;
size_t i = 0 ;
char * * ret = NULL ;
2019-03-29 16:36:57 +03:00
VIR_AUTOSTRINGLIST tmp = NULL ;
2018-01-12 16:15:11 +03:00
virCheckFlags ( 0 , NULL ) ;
if ( ! priv - > conn | | virConnectIsAlive ( priv - > conn ) < = 0 )
return NULL ;
if ( ! ( pool = virshCommandOptPool ( ctl , cmd , " pool " , NULL ) ) )
2019-02-11 17:21:35 +03:00
return NULL ;
2018-01-12 16:15:11 +03:00
2019-03-28 05:15:43 +03:00
if ( ( rc = virStoragePoolListAllVolumes ( pool , & vols , flags ) ) < 0 )
2019-03-29 18:46:54 +03:00
goto cleanup ;
2019-03-28 05:15:43 +03:00
nvols = rc ;
2018-01-12 16:15:11 +03:00
2019-03-28 20:03:30 +03:00
if ( VIR_ALLOC_N ( tmp , nvols + 1 ) < 0 )
2019-03-29 18:46:54 +03:00
goto cleanup ;
2018-01-12 16:15:11 +03:00
for ( i = 0 ; i < nvols ; i + + ) {
const char * name = virStorageVolGetName ( vols [ i ] ) ;
2019-03-28 20:03:30 +03:00
if ( VIR_STRDUP ( tmp [ i ] , name ) < 0 )
2019-03-29 18:46:54 +03:00
goto cleanup ;
2018-01-12 16:15:11 +03:00
}
2019-03-28 20:03:30 +03:00
VIR_STEAL_PTR ( ret , tmp ) ;
2019-03-28 20:26:44 +03:00
cleanup :
2019-03-28 20:32:36 +03:00
virStoragePoolFree ( pool ) ;
for ( i = 0 ; i < nvols ; i + + )
virStorageVolFree ( vols [ i ] ) ;
VIR_FREE ( vols ) ;
2018-01-12 16:15:11 +03:00
return ret ;
}
2018-01-12 16:26:35 +03:00
char * *
virshInterfaceNameCompleter ( vshControl * ctl ,
const vshCmd * cmd ATTRIBUTE_UNUSED ,
unsigned int flags )
{
virshControlPtr priv = ctl - > privData ;
virInterfacePtr * ifaces = NULL ;
int nifaces = 0 ;
size_t i = 0 ;
char * * ret = NULL ;
2019-03-29 16:36:57 +03:00
VIR_AUTOSTRINGLIST tmp = NULL ;
2018-01-12 16:26:35 +03:00
virCheckFlags ( VIR_CONNECT_LIST_INTERFACES_ACTIVE |
VIR_CONNECT_LIST_INTERFACES_INACTIVE ,
NULL ) ;
if ( ! priv - > conn | | virConnectIsAlive ( priv - > conn ) < = 0 )
return NULL ;
if ( ( nifaces = virConnectListAllInterfaces ( priv - > conn , & ifaces , flags ) ) < 0 )
return NULL ;
2019-03-28 20:03:30 +03:00
if ( VIR_ALLOC_N ( tmp , nifaces + 1 ) < 0 )
2019-03-29 18:46:54 +03:00
goto cleanup ;
2018-01-12 16:26:35 +03:00
for ( i = 0 ; i < nifaces ; i + + ) {
const char * name = virInterfaceGetName ( ifaces [ i ] ) ;
2019-03-28 20:03:30 +03:00
if ( VIR_STRDUP ( tmp [ i ] , name ) < 0 )
2019-03-29 18:46:54 +03:00
goto cleanup ;
2018-01-12 16:26:35 +03:00
}
2019-03-28 20:03:30 +03:00
VIR_STEAL_PTR ( ret , tmp ) ;
2019-03-28 20:26:44 +03:00
cleanup :
2019-03-28 20:32:36 +03:00
for ( i = 0 ; i < nifaces ; i + + )
virInterfaceFree ( ifaces [ i ] ) ;
VIR_FREE ( ifaces ) ;
2018-01-12 16:26:35 +03:00
return ret ;
}
2018-01-12 16:35:40 +03:00
char * *
virshNetworkNameCompleter ( vshControl * ctl ,
const vshCmd * cmd ATTRIBUTE_UNUSED ,
unsigned int flags )
{
virshControlPtr priv = ctl - > privData ;
virNetworkPtr * nets = NULL ;
int nnets = 0 ;
size_t i = 0 ;
char * * ret = NULL ;
2019-03-29 16:36:57 +03:00
VIR_AUTOSTRINGLIST tmp = NULL ;
2018-01-12 16:35:40 +03:00
virCheckFlags ( VIR_CONNECT_LIST_NETWORKS_INACTIVE |
VIR_CONNECT_LIST_NETWORKS_ACTIVE |
VIR_CONNECT_LIST_NETWORKS_PERSISTENT ,
NULL ) ;
if ( ! priv - > conn | | virConnectIsAlive ( priv - > conn ) < = 0 )
return NULL ;
if ( ( nnets = virConnectListAllNetworks ( priv - > conn , & nets , flags ) ) < 0 )
return NULL ;
2019-03-28 20:03:30 +03:00
if ( VIR_ALLOC_N ( tmp , nnets + 1 ) < 0 )
2019-03-29 18:46:54 +03:00
goto cleanup ;
2018-01-12 16:35:40 +03:00
for ( i = 0 ; i < nnets ; i + + ) {
const char * name = virNetworkGetName ( nets [ i ] ) ;
2019-03-28 20:03:30 +03:00
if ( VIR_STRDUP ( tmp [ i ] , name ) < 0 )
2019-03-29 18:46:54 +03:00
goto cleanup ;
2018-01-12 16:35:40 +03:00
}
2019-03-28 20:03:30 +03:00
VIR_STEAL_PTR ( ret , tmp ) ;
2019-03-28 20:26:44 +03:00
cleanup :
2019-03-28 20:32:36 +03:00
for ( i = 0 ; i < nnets ; i + + )
virNetworkFree ( nets [ i ] ) ;
VIR_FREE ( nets ) ;
2018-01-12 16:35:40 +03:00
return ret ;
}
2018-01-12 16:44:37 +03:00
2019-03-05 06:17:39 +03:00
char * *
virshNetworkEventNameCompleter ( vshControl * ctl ATTRIBUTE_UNUSED ,
const vshCmd * cmd ATTRIBUTE_UNUSED ,
unsigned int flags )
{
size_t i = 0 ;
char * * ret = NULL ;
2019-03-29 16:36:57 +03:00
VIR_AUTOSTRINGLIST tmp = NULL ;
2019-03-05 06:17:39 +03:00
virCheckFlags ( 0 , NULL ) ;
2019-03-28 20:03:30 +03:00
if ( VIR_ALLOC_N ( tmp , VIR_NETWORK_EVENT_ID_LAST + 1 ) < 0 )
2019-03-29 18:46:54 +03:00
goto cleanup ;
2019-03-05 06:17:39 +03:00
for ( i = 0 ; i < VIR_NETWORK_EVENT_ID_LAST ; i + + ) {
2019-03-28 20:03:30 +03:00
if ( VIR_STRDUP ( tmp [ i ] , virshNetworkEventCallbacks [ i ] . name ) < 0 )
2019-03-29 18:46:54 +03:00
goto cleanup ;
2019-03-05 06:17:39 +03:00
}
2019-03-28 20:03:30 +03:00
VIR_STEAL_PTR ( ret , tmp ) ;
2019-03-28 20:26:44 +03:00
cleanup :
2019-03-05 06:17:39 +03:00
return ret ;
}
2018-01-12 16:44:37 +03:00
2018-12-12 19:58:31 +03:00
char * *
virshNetworkPortUUIDCompleter ( vshControl * ctl ,
const vshCmd * cmd ATTRIBUTE_UNUSED ,
unsigned int flags )
{
virshControlPtr priv = ctl - > privData ;
virNetworkPtr net = NULL ;
virNetworkPortPtr * ports = NULL ;
int nports = 0 ;
size_t i = 0 ;
char * * ret = NULL ;
virCheckFlags ( 0 , NULL ) ;
if ( ! priv - > conn | | virConnectIsAlive ( priv - > conn ) < = 0 )
return NULL ;
if ( ! ( net = virshCommandOptNetwork ( ctl , cmd , NULL ) ) )
return false ;
if ( ( nports = virNetworkListAllPorts ( net , & ports , flags ) ) < 0 )
return NULL ;
if ( VIR_ALLOC_N ( ret , nports + 1 ) < 0 )
goto error ;
for ( i = 0 ; i < nports ; i + + ) {
char uuid [ VIR_UUID_STRING_BUFLEN ] ;
if ( virNetworkPortGetUUIDString ( ports [ i ] , uuid ) < 0 | |
VIR_STRDUP ( ret [ i ] , uuid ) < 0 )
goto error ;
virNetworkPortFree ( ports [ i ] ) ;
}
VIR_FREE ( ports ) ;
return ret ;
error :
for ( ; i < nports ; i + + )
virNetworkPortFree ( ports [ i ] ) ;
VIR_FREE ( ports ) ;
for ( i = 0 ; i < nports ; i + + )
VIR_FREE ( ret [ i ] ) ;
VIR_FREE ( ret ) ;
return NULL ;
}
2018-01-12 16:44:37 +03:00
char * *
virshNodeDeviceNameCompleter ( vshControl * ctl ,
const vshCmd * cmd ATTRIBUTE_UNUSED ,
unsigned int flags )
{
virshControlPtr priv = ctl - > privData ;
virNodeDevicePtr * devs = NULL ;
int ndevs = 0 ;
size_t i = 0 ;
char * * ret = NULL ;
2019-03-29 16:36:57 +03:00
VIR_AUTOSTRINGLIST tmp = NULL ;
2018-01-12 16:44:37 +03:00
virCheckFlags ( 0 , NULL ) ;
if ( ! priv - > conn | | virConnectIsAlive ( priv - > conn ) < = 0 )
return NULL ;
if ( ( ndevs = virConnectListAllNodeDevices ( priv - > conn , & devs , flags ) ) < 0 )
return NULL ;
2019-03-28 20:03:30 +03:00
if ( VIR_ALLOC_N ( tmp , ndevs + 1 ) < 0 )
2019-03-29 18:46:54 +03:00
goto cleanup ;
2018-01-12 16:44:37 +03:00
for ( i = 0 ; i < ndevs ; i + + ) {
const char * name = virNodeDeviceGetName ( devs [ i ] ) ;
2019-03-28 20:03:30 +03:00
if ( VIR_STRDUP ( tmp [ i ] , name ) < 0 )
2019-03-29 18:46:54 +03:00
goto cleanup ;
2018-01-12 16:44:37 +03:00
}
2019-03-28 20:03:30 +03:00
VIR_STEAL_PTR ( ret , tmp ) ;
2019-03-28 20:26:44 +03:00
cleanup :
2019-03-28 20:32:36 +03:00
for ( i = 0 ; i < ndevs ; i + + )
virNodeDeviceFree ( devs [ i ] ) ;
VIR_FREE ( devs ) ;
2018-01-12 16:44:37 +03:00
return ret ;
}
2018-01-12 16:51:34 +03:00
char * *
virshNWFilterNameCompleter ( vshControl * ctl ,
const vshCmd * cmd ATTRIBUTE_UNUSED ,
unsigned int flags )
{
virshControlPtr priv = ctl - > privData ;
virNWFilterPtr * nwfilters = NULL ;
int nnwfilters = 0 ;
size_t i = 0 ;
char * * ret = NULL ;
2019-03-29 16:36:57 +03:00
VIR_AUTOSTRINGLIST tmp = NULL ;
2018-01-12 16:51:34 +03:00
virCheckFlags ( 0 , NULL ) ;
if ( ! priv - > conn | | virConnectIsAlive ( priv - > conn ) < = 0 )
return NULL ;
if ( ( nnwfilters = virConnectListAllNWFilters ( priv - > conn , & nwfilters , flags ) ) < 0 )
return NULL ;
2019-03-28 20:03:30 +03:00
if ( VIR_ALLOC_N ( tmp , nnwfilters + 1 ) < 0 )
2019-03-29 18:46:54 +03:00
goto cleanup ;
2018-01-12 16:51:34 +03:00
for ( i = 0 ; i < nnwfilters ; i + + ) {
const char * name = virNWFilterGetName ( nwfilters [ i ] ) ;
2019-03-28 20:03:30 +03:00
if ( VIR_STRDUP ( tmp [ i ] , name ) < 0 )
2019-03-29 18:46:54 +03:00
goto cleanup ;
2018-01-12 16:51:34 +03:00
}
2019-03-28 20:03:30 +03:00
VIR_STEAL_PTR ( ret , tmp ) ;
2019-03-28 20:26:44 +03:00
cleanup :
2019-03-28 20:32:36 +03:00
for ( i = 0 ; i < nnwfilters ; i + + )
virNWFilterFree ( nwfilters [ i ] ) ;
VIR_FREE ( nwfilters ) ;
2018-01-12 16:51:34 +03:00
return ret ;
}
2018-01-12 17:00:40 +03:00
2018-05-09 19:44:35 +03:00
char * *
virshNWFilterBindingNameCompleter ( vshControl * ctl ,
const vshCmd * cmd ATTRIBUTE_UNUSED ,
unsigned int flags )
{
virshControlPtr priv = ctl - > privData ;
virNWFilterBindingPtr * bindings = NULL ;
int nbindings = 0 ;
size_t i = 0 ;
char * * ret = NULL ;
2019-03-29 16:36:57 +03:00
VIR_AUTOSTRINGLIST tmp = NULL ;
2018-05-09 19:44:35 +03:00
virCheckFlags ( 0 , NULL ) ;
if ( ! priv - > conn | | virConnectIsAlive ( priv - > conn ) < = 0 )
return NULL ;
if ( ( nbindings = virConnectListAllNWFilterBindings ( priv - > conn , & bindings , flags ) ) < 0 )
return NULL ;
2019-03-28 20:03:30 +03:00
if ( VIR_ALLOC_N ( tmp , nbindings + 1 ) < 0 )
2019-03-29 18:46:54 +03:00
goto cleanup ;
2018-05-09 19:44:35 +03:00
for ( i = 0 ; i < nbindings ; i + + ) {
const char * name = virNWFilterBindingGetPortDev ( bindings [ i ] ) ;
2019-03-28 20:03:30 +03:00
if ( VIR_STRDUP ( tmp [ i ] , name ) < 0 )
2019-03-29 18:46:54 +03:00
goto cleanup ;
2018-05-09 19:44:35 +03:00
}
2019-03-28 20:03:30 +03:00
VIR_STEAL_PTR ( ret , tmp ) ;
2019-03-28 20:26:44 +03:00
cleanup :
2019-03-28 20:32:36 +03:00
for ( i = 0 ; i < nbindings ; i + + )
virNWFilterBindingFree ( bindings [ i ] ) ;
VIR_FREE ( bindings ) ;
2018-05-09 19:44:35 +03:00
return ret ;
}
2018-01-12 17:00:40 +03:00
char * *
virshSecretUUIDCompleter ( vshControl * ctl ,
const vshCmd * cmd ATTRIBUTE_UNUSED ,
unsigned int flags )
{
virshControlPtr priv = ctl - > privData ;
virSecretPtr * secrets = NULL ;
int nsecrets = 0 ;
size_t i = 0 ;
char * * ret = NULL ;
2019-03-29 16:36:57 +03:00
VIR_AUTOSTRINGLIST tmp = NULL ;
2018-01-12 17:00:40 +03:00
virCheckFlags ( 0 , NULL ) ;
if ( ! priv - > conn | | virConnectIsAlive ( priv - > conn ) < = 0 )
return NULL ;
if ( ( nsecrets = virConnectListAllSecrets ( priv - > conn , & secrets , flags ) ) < 0 )
return NULL ;
2019-03-28 20:03:30 +03:00
if ( VIR_ALLOC_N ( tmp , nsecrets + 1 ) < 0 )
2019-03-29 18:46:54 +03:00
goto cleanup ;
2018-01-12 17:00:40 +03:00
for ( i = 0 ; i < nsecrets ; i + + ) {
char uuid [ VIR_UUID_STRING_BUFLEN ] ;
if ( virSecretGetUUIDString ( secrets [ i ] , uuid ) < 0 | |
2019-03-28 20:03:30 +03:00
VIR_STRDUP ( tmp [ i ] , uuid ) < 0 )
2019-03-29 18:46:54 +03:00
goto cleanup ;
2018-01-12 17:00:40 +03:00
}
2019-03-28 20:03:30 +03:00
VIR_STEAL_PTR ( ret , tmp ) ;
2019-03-28 20:26:44 +03:00
cleanup :
2019-03-28 20:32:36 +03:00
for ( i = 0 ; i < nsecrets ; i + + )
virSecretFree ( secrets [ i ] ) ;
VIR_FREE ( secrets ) ;
2018-01-12 17:00:40 +03:00
return ret ;
}
2018-01-12 17:28:30 +03:00
2019-03-14 00:04:51 +03:00
char * *
virshCheckpointNameCompleter ( vshControl * ctl ,
const vshCmd * cmd ,
unsigned int flags )
{
virshControlPtr priv = ctl - > privData ;
virDomainPtr dom = NULL ;
virDomainCheckpointPtr * checkpoints = NULL ;
int ncheckpoints = 0 ;
size_t i = 0 ;
char * * ret = NULL ;
virCheckFlags ( 0 , NULL ) ;
if ( ! priv - > conn | | virConnectIsAlive ( priv - > conn ) < = 0 )
return NULL ;
if ( ! ( dom = virshCommandOptDomain ( ctl , cmd , NULL ) ) )
return NULL ;
if ( ( ncheckpoints = virDomainListAllCheckpoints ( dom , & checkpoints ,
flags ) ) < 0 )
goto error ;
if ( VIR_ALLOC_N ( ret , ncheckpoints + 1 ) < 0 )
goto error ;
for ( i = 0 ; i < ncheckpoints ; i + + ) {
const char * name = virDomainCheckpointGetName ( checkpoints [ i ] ) ;
if ( VIR_STRDUP ( ret [ i ] , name ) < 0 )
goto error ;
virshDomainCheckpointFree ( checkpoints [ i ] ) ;
}
VIR_FREE ( checkpoints ) ;
virshDomainFree ( dom ) ;
return ret ;
error :
for ( ; i < ncheckpoints ; i + + )
virshDomainCheckpointFree ( checkpoints [ i ] ) ;
VIR_FREE ( checkpoints ) ;
for ( i = 0 ; i < ncheckpoints ; i + + )
VIR_FREE ( ret [ i ] ) ;
VIR_FREE ( ret ) ;
virshDomainFree ( dom ) ;
return NULL ;
}
2018-01-12 17:28:30 +03:00
char * *
virshSnapshotNameCompleter ( vshControl * ctl ,
const vshCmd * cmd ,
unsigned int flags )
{
virshControlPtr priv = ctl - > privData ;
virDomainPtr dom = NULL ;
virDomainSnapshotPtr * snapshots = NULL ;
2019-03-28 05:15:43 +03:00
int rc ;
2018-01-12 17:28:30 +03:00
int nsnapshots = 0 ;
size_t i = 0 ;
char * * ret = NULL ;
2019-03-29 16:36:57 +03:00
VIR_AUTOSTRINGLIST tmp = NULL ;
2018-01-12 17:28:30 +03:00
virCheckFlags ( 0 , NULL ) ;
if ( ! priv - > conn | | virConnectIsAlive ( priv - > conn ) < = 0 )
return NULL ;
if ( ! ( dom = virshCommandOptDomain ( ctl , cmd , NULL ) ) )
return NULL ;
2019-03-28 05:15:43 +03:00
if ( ( rc = virDomainListAllSnapshots ( dom , & snapshots , flags ) ) < 0 )
2019-03-29 18:46:54 +03:00
goto cleanup ;
2019-03-28 05:15:43 +03:00
nsnapshots = rc ;
2018-01-12 17:28:30 +03:00
2019-03-28 20:03:30 +03:00
if ( VIR_ALLOC_N ( tmp , nsnapshots + 1 ) < 0 )
2019-03-29 18:46:54 +03:00
goto cleanup ;
2018-01-12 17:28:30 +03:00
for ( i = 0 ; i < nsnapshots ; i + + ) {
const char * name = virDomainSnapshotGetName ( snapshots [ i ] ) ;
2019-03-28 20:03:30 +03:00
if ( VIR_STRDUP ( tmp [ i ] , name ) < 0 )
2019-03-29 18:46:54 +03:00
goto cleanup ;
2018-01-12 17:28:30 +03:00
}
2019-03-28 20:03:30 +03:00
VIR_STEAL_PTR ( ret , tmp ) ;
2019-03-28 20:26:44 +03:00
cleanup :
2019-03-28 20:32:36 +03:00
virshDomainFree ( dom ) ;
for ( i = 0 ; i < nsnapshots ; i + + )
virshDomainSnapshotFree ( snapshots [ i ] ) ;
VIR_FREE ( snapshots ) ;
2018-01-12 17:28:30 +03:00
return ret ;
}
2018-05-21 14:53:44 +03:00
2019-03-29 20:31:01 +03:00
static char *
virshPagesizeNodeToString ( xmlNodePtr node )
{
VIR_AUTOFREE ( char * ) pagesize = NULL ;
VIR_AUTOFREE ( char * ) unit = NULL ;
unsigned long long byteval = 0 ;
const char * suffix = NULL ;
double size = 0 ;
char * ret ;
pagesize = virXMLPropString ( node , " size " ) ;
unit = virXMLPropString ( node , " unit " ) ;
if ( virStrToLong_ull ( pagesize , NULL , 10 , & byteval ) < 0 )
return NULL ;
if ( virScaleInteger ( & byteval , unit , 1024 , UINT_MAX ) < 0 )
return NULL ;
size = vshPrettyCapacity ( byteval , & suffix ) ;
if ( virAsprintf ( & ret , " %.0f%s " , size , suffix ) < 0 )
return NULL ;
return ret ;
}
2018-05-21 14:53:44 +03:00
char * *
virshAllocpagesPagesizeCompleter ( vshControl * ctl ,
2018-05-24 12:04:33 +03:00
const vshCmd * cmd ATTRIBUTE_UNUSED ,
unsigned int flags )
2018-05-21 14:53:44 +03:00
{
2019-03-29 20:18:57 +03:00
VIR_AUTOPTR ( xmlXPathContext ) ctxt = NULL ;
2018-05-21 14:53:44 +03:00
virshControlPtr priv = ctl - > privData ;
unsigned int npages = 0 ;
2019-03-29 17:04:43 +03:00
VIR_AUTOFREE ( xmlNodePtr * ) pages = NULL ;
2019-03-29 20:18:57 +03:00
VIR_AUTOPTR ( xmlDoc ) doc = NULL ;
2018-05-21 14:53:44 +03:00
size_t i = 0 ;
2018-05-22 12:54:44 +03:00
const char * cellnum = NULL ;
bool cellno = vshCommandOptBool ( cmd , " cellno " ) ;
2019-03-29 17:22:46 +03:00
VIR_AUTOFREE ( char * ) path = NULL ;
VIR_AUTOFREE ( char * ) cap_xml = NULL ;
2018-05-21 14:53:44 +03:00
char * * ret = NULL ;
2019-03-29 16:36:57 +03:00
VIR_AUTOSTRINGLIST tmp = NULL ;
2018-05-21 14:53:44 +03:00
virCheckFlags ( 0 , NULL ) ;
if ( ! priv - > conn | | virConnectIsAlive ( priv - > conn ) < = 0 )
2019-03-29 18:46:54 +03:00
return NULL ;
2018-05-21 14:53:44 +03:00
if ( ! ( cap_xml = virConnectGetCapabilities ( priv - > conn ) ) )
2019-03-29 18:46:54 +03:00
return NULL ;
2018-05-21 14:53:44 +03:00
2018-05-23 15:40:41 +03:00
if ( ! ( doc = virXMLParseStringCtxt ( cap_xml , _ ( " capabilities " ) , & ctxt ) ) )
2019-03-29 18:46:54 +03:00
return NULL ;
2018-05-21 14:53:44 +03:00
2018-05-22 12:54:44 +03:00
if ( cellno & & vshCommandOptStringQuiet ( ctl , cmd , " cellno " , & cellnum ) > 0 ) {
if ( virAsprintf ( & path ,
" /capabilities/host/topology/cells/cell[@id= \" %s \" ]/pages " ,
cellnum ) < 0 )
2019-03-29 18:46:54 +03:00
return NULL ;
2018-05-22 12:54:44 +03:00
} else {
if ( virAsprintf ( & path , " /capabilities/host/cpu/pages " ) < 0 )
2019-03-29 18:46:54 +03:00
return NULL ;
2018-05-22 12:54:44 +03:00
}
npages = virXPathNodeSet ( path , ctxt , & pages ) ;
2018-05-21 14:53:44 +03:00
if ( npages < = 0 )
2019-03-29 18:46:54 +03:00
return NULL ;
2018-05-21 14:53:44 +03:00
2019-03-28 20:03:30 +03:00
if ( VIR_ALLOC_N ( tmp , npages + 1 ) < 0 )
2019-03-29 18:46:54 +03:00
return NULL ;
2018-05-21 14:53:44 +03:00
for ( i = 0 ; i < npages ; i + + ) {
2019-03-29 20:31:01 +03:00
if ( ! ( tmp [ i ] = virshPagesizeNodeToString ( pages [ i ] ) ) )
2019-03-29 18:46:54 +03:00
return NULL ;
2018-05-21 14:53:44 +03:00
}
2019-03-28 20:03:30 +03:00
VIR_STEAL_PTR ( ret , tmp ) ;
2018-05-21 14:53:44 +03:00
return ret ;
}
2018-05-23 09:32:40 +03:00
char * *
virshSecretEventNameCompleter ( vshControl * ctl ATTRIBUTE_UNUSED ,
const vshCmd * cmd ATTRIBUTE_UNUSED ,
unsigned int flags )
{
size_t i ;
char * * ret = NULL ;
2019-03-29 16:36:57 +03:00
VIR_AUTOSTRINGLIST tmp = NULL ;
2018-05-23 09:32:40 +03:00
virCheckFlags ( 0 , NULL ) ;
2019-03-28 20:03:30 +03:00
if ( VIR_ALLOC_N ( tmp , VIR_SECRET_EVENT_ID_LAST + 1 ) < 0 )
2019-03-29 18:46:54 +03:00
return NULL ;
2018-05-23 09:32:40 +03:00
for ( i = 0 ; i < VIR_SECRET_EVENT_ID_LAST ; i + + ) {
2019-03-28 20:03:30 +03:00
if ( VIR_STRDUP ( tmp [ i ] , virshSecretEventCallbacks [ i ] . name ) < 0 )
2019-03-29 18:46:54 +03:00
return NULL ;
2018-05-23 09:32:40 +03:00
}
2019-03-28 20:03:30 +03:00
VIR_STEAL_PTR ( ret , tmp ) ;
2018-05-23 09:32:40 +03:00
return ret ;
}
2018-05-23 09:32:42 +03:00
char * *
virshDomainEventNameCompleter ( vshControl * ctl ATTRIBUTE_UNUSED ,
const vshCmd * cmd ATTRIBUTE_UNUSED ,
unsigned int flags )
{
size_t i = 0 ;
char * * ret = NULL ;
2019-03-29 16:36:57 +03:00
VIR_AUTOSTRINGLIST tmp = NULL ;
2018-05-23 09:32:42 +03:00
virCheckFlags ( 0 , NULL ) ;
2019-03-28 20:03:30 +03:00
if ( VIR_ALLOC_N ( tmp , VIR_DOMAIN_EVENT_ID_LAST + 1 ) < 0 )
2019-03-29 18:46:54 +03:00
return NULL ;
2018-05-23 09:32:42 +03:00
for ( i = 0 ; i < VIR_DOMAIN_EVENT_ID_LAST ; i + + ) {
2019-03-28 20:03:30 +03:00
if ( VIR_STRDUP ( tmp [ i ] , virshDomainEventCallbacks [ i ] . name ) < 0 )
2019-03-29 18:46:54 +03:00
return NULL ;
2018-05-23 09:32:42 +03:00
}
2019-03-28 20:03:30 +03:00
VIR_STEAL_PTR ( ret , tmp ) ;
2018-05-23 09:32:42 +03:00
return ret ;
}
2018-05-24 16:16:26 +03:00
char * *
virshPoolEventNameCompleter ( vshControl * ctl ATTRIBUTE_UNUSED ,
const vshCmd * cmd ATTRIBUTE_UNUSED ,
unsigned int flags )
{
size_t i = 0 ;
char * * ret = NULL ;
2019-03-29 16:36:57 +03:00
VIR_AUTOSTRINGLIST tmp = NULL ;
2018-05-24 16:16:26 +03:00
virCheckFlags ( 0 , NULL ) ;
2019-03-28 20:03:30 +03:00
if ( VIR_ALLOC_N ( tmp , VIR_STORAGE_POOL_EVENT_ID_LAST + 1 ) < 0 )
2019-03-29 18:46:54 +03:00
return NULL ;
2018-05-24 16:16:26 +03:00
for ( i = 0 ; i < VIR_STORAGE_POOL_EVENT_ID_LAST ; i + + ) {
2019-03-28 20:03:30 +03:00
if ( VIR_STRDUP ( tmp [ i ] , virshPoolEventCallbacks [ i ] . name ) < 0 )
2019-03-29 18:46:54 +03:00
return NULL ;
2018-05-24 16:16:26 +03:00
}
2019-03-28 20:03:30 +03:00
VIR_STEAL_PTR ( ret , tmp ) ;
2018-05-24 16:16:26 +03:00
return ret ;
}
2018-05-23 09:32:46 +03:00
2018-07-12 17:07:59 +03:00
char * *
virshDomainInterfaceStateCompleter ( vshControl * ctl ,
const vshCmd * cmd ,
unsigned int flags )
{
virshControlPtr priv = ctl - > privData ;
const char * iface = NULL ;
char * * ret = NULL ;
2019-03-29 20:18:57 +03:00
VIR_AUTOPTR ( xmlDoc ) xml = NULL ;
VIR_AUTOPTR ( xmlXPathContext ) ctxt = NULL ;
2018-07-12 17:07:59 +03:00
virMacAddr macaddr ;
char macstr [ VIR_MAC_STRING_BUFLEN ] = " " ;
int ninterfaces ;
2019-03-29 17:04:43 +03:00
VIR_AUTOFREE ( xmlNodePtr * ) interfaces = NULL ;
2019-03-29 17:22:46 +03:00
VIR_AUTOFREE ( char * ) xpath = NULL ;
VIR_AUTOFREE ( char * ) state = NULL ;
2019-03-29 16:36:57 +03:00
VIR_AUTOSTRINGLIST tmp = NULL ;
2018-07-12 17:07:59 +03:00
virCheckFlags ( 0 , NULL ) ;
if ( ! priv - > conn | | virConnectIsAlive ( priv - > conn ) < = 0 )
return NULL ;
if ( virshDomainGetXML ( ctl , cmd , flags , & xml , & ctxt ) < 0 )
2019-03-29 18:46:54 +03:00
return NULL ;
2018-07-12 17:07:59 +03:00
if ( vshCommandOptStringReq ( ctl , cmd , " interface " , & iface ) < 0 )
2019-03-29 18:46:54 +03:00
return NULL ;
2018-07-12 17:07:59 +03:00
/* normalize the mac addr */
if ( virMacAddrParse ( iface , & macaddr ) = = 0 )
virMacAddrFormat ( & macaddr , macstr ) ;
if ( virAsprintf ( & xpath , " /domain/devices/interface[(mac/@address = '%s') or "
" (target/@dev = '%s')] " ,
macstr , iface ) < 0 )
2019-03-29 18:46:54 +03:00
return NULL ;
2018-07-12 17:07:59 +03:00
if ( ( ninterfaces = virXPathNodeSet ( xpath , ctxt , & interfaces ) ) < 0 )
2019-03-29 18:46:54 +03:00
return NULL ;
2018-07-12 17:07:59 +03:00
if ( ninterfaces ! = 1 )
2019-03-29 18:46:54 +03:00
return NULL ;
2018-07-12 17:07:59 +03:00
ctxt - > node = interfaces [ 0 ] ;
2019-03-28 20:03:30 +03:00
if ( VIR_ALLOC_N ( tmp , 2 ) < 0 )
2019-03-29 18:46:54 +03:00
return NULL ;
2018-07-12 17:07:59 +03:00
if ( ( state = virXPathString ( " string(./link/@state) " , ctxt ) ) & &
STREQ ( state , " down " ) ) {
2019-03-28 20:03:30 +03:00
if ( VIR_STRDUP ( tmp [ 0 ] , " up " ) < 0 )
2019-03-29 18:46:54 +03:00
return NULL ;
2018-07-12 17:07:59 +03:00
} else {
2019-03-28 20:03:30 +03:00
if ( VIR_STRDUP ( tmp [ 0 ] , " down " ) < 0 )
2019-03-29 18:46:54 +03:00
return NULL ;
2018-07-12 17:07:59 +03:00
}
2019-03-28 20:03:30 +03:00
VIR_STEAL_PTR ( ret , tmp ) ;
2018-07-12 17:07:59 +03:00
return ret ;
}
2018-05-23 09:32:46 +03:00
char * *
2019-07-14 12:47:34 +03:00
virshNodeDeviceEventNameCompleter ( vshControl * ctl ATTRIBUTE_UNUSED ,
const vshCmd * cmd ATTRIBUTE_UNUSED ,
unsigned int flags )
2018-05-23 09:32:46 +03:00
{
size_t i = 0 ;
char * * ret = NULL ;
2019-03-29 16:36:57 +03:00
VIR_AUTOSTRINGLIST tmp = NULL ;
2018-05-23 09:32:46 +03:00
virCheckFlags ( 0 , NULL ) ;
2019-03-28 20:03:30 +03:00
if ( VIR_ALLOC_N ( tmp , VIR_NODE_DEVICE_EVENT_ID_LAST + 1 ) < 0 )
2019-03-29 18:46:54 +03:00
return NULL ;
2018-05-23 09:32:46 +03:00
for ( i = 0 ; i < VIR_NODE_DEVICE_EVENT_ID_LAST ; i + + ) {
2019-07-14 12:47:34 +03:00
if ( VIR_STRDUP ( tmp [ i ] , virshNodeDeviceEventCallbacks [ i ] . name ) < 0 )
2019-03-29 18:46:54 +03:00
return NULL ;
2018-05-23 09:32:46 +03:00
}
2019-03-28 20:03:30 +03:00
VIR_STEAL_PTR ( ret , tmp ) ;
2018-05-23 09:32:46 +03:00
return ret ;
}
2018-05-25 10:12:37 +03:00
2019-06-14 15:27:13 +03:00
char * *
2019-07-14 12:47:34 +03:00
virshNodeDeviceCapabilityNameCompleter ( vshControl * ctl ,
const vshCmd * cmd ,
unsigned int flags )
2019-06-14 15:27:13 +03:00
{
VIR_AUTOSTRINGLIST tmp = NULL ;
const char * cap_str = NULL ;
size_t i = 0 ;
virCheckFlags ( 0 , NULL ) ;
if ( vshCommandOptStringQuiet ( ctl , cmd , " cap " , & cap_str ) < 0 )
return NULL ;
if ( VIR_ALLOC_N ( tmp , VIR_NODE_DEV_CAP_LAST + 1 ) < 0 )
return NULL ;
for ( i = 0 ; i < VIR_NODE_DEV_CAP_LAST ; i + + ) {
if ( VIR_STRDUP ( tmp [ i ] , virNodeDevCapTypeToString ( i ) ) < 0 )
return NULL ;
}
return virshCommaStringListComplete ( cap_str , ( const char * * ) tmp ) ;
}
2018-05-25 10:12:37 +03:00
char * *
virshCellnoCompleter ( vshControl * ctl ,
const vshCmd * cmd ATTRIBUTE_UNUSED ,
unsigned int flags )
{
2019-03-29 20:18:57 +03:00
VIR_AUTOPTR ( xmlXPathContext ) ctxt = NULL ;
2018-05-25 10:12:37 +03:00
virshControlPtr priv = ctl - > privData ;
unsigned int ncells = 0 ;
2019-03-29 17:04:43 +03:00
VIR_AUTOFREE ( xmlNodePtr * ) cells = NULL ;
2019-03-29 20:18:57 +03:00
VIR_AUTOPTR ( xmlDoc ) doc = NULL ;
2018-05-25 10:12:37 +03:00
size_t i = 0 ;
2019-03-29 17:22:46 +03:00
VIR_AUTOFREE ( char * ) cap_xml = NULL ;
2018-05-25 10:12:37 +03:00
char * * ret = NULL ;
2019-03-29 16:36:57 +03:00
VIR_AUTOSTRINGLIST tmp = NULL ;
2018-05-25 10:12:37 +03:00
virCheckFlags ( 0 , NULL ) ;
if ( ! priv - > conn | | virConnectIsAlive ( priv - > conn ) < = 0 )
2019-03-29 18:46:54 +03:00
return NULL ;
2018-05-25 10:12:37 +03:00
if ( ! ( cap_xml = virConnectGetCapabilities ( priv - > conn ) ) )
2019-03-29 18:46:54 +03:00
return NULL ;
2018-05-25 10:12:37 +03:00
if ( ! ( doc = virXMLParseStringCtxt ( cap_xml , _ ( " capabilities " ) , & ctxt ) ) )
2019-03-29 18:46:54 +03:00
return NULL ;
2018-05-25 10:12:37 +03:00
ncells = virXPathNodeSet ( " /capabilities/host/topology/cells/cell " , ctxt , & cells ) ;
if ( ncells < = 0 )
2019-03-29 18:46:54 +03:00
return NULL ;
2018-05-25 10:12:37 +03:00
2019-03-28 20:03:30 +03:00
if ( VIR_ALLOC_N ( tmp , ncells + 1 ) )
2019-03-29 18:46:54 +03:00
return NULL ;
2018-05-25 10:12:37 +03:00
for ( i = 0 ; i < ncells ; i + + ) {
2019-03-28 20:03:30 +03:00
if ( ! ( tmp [ i ] = virXMLPropString ( cells [ i ] , " id " ) ) )
2019-03-29 18:46:54 +03:00
return NULL ;
2018-05-25 10:12:37 +03:00
}
2019-03-28 20:03:30 +03:00
VIR_STEAL_PTR ( ret , tmp ) ;
2018-05-25 10:12:37 +03:00
return ret ;
}
2018-06-26 13:41:34 +03:00
char * *
virshDomainDeviceAliasCompleter ( vshControl * ctl ,
const vshCmd * cmd ,
unsigned int flags )
{
virshControlPtr priv = ctl - > privData ;
2019-03-29 20:18:57 +03:00
VIR_AUTOPTR ( xmlDoc ) xmldoc = NULL ;
VIR_AUTOPTR ( xmlXPathContext ) ctxt = NULL ;
2018-06-26 13:41:34 +03:00
int naliases ;
2019-03-29 17:04:43 +03:00
VIR_AUTOFREE ( xmlNodePtr * ) aliases = NULL ;
2018-06-26 13:41:34 +03:00
size_t i ;
unsigned int domainXMLFlags = 0 ;
char * * ret = NULL ;
2019-03-29 16:36:57 +03:00
VIR_AUTOSTRINGLIST tmp = NULL ;
2018-06-26 13:41:34 +03:00
virCheckFlags ( 0 , NULL ) ;
if ( ! priv - > conn | | virConnectIsAlive ( priv - > conn ) < = 0 )
return NULL ;
if ( vshCommandOptBool ( cmd , " config " ) )
domainXMLFlags = VIR_DOMAIN_XML_INACTIVE ;
if ( virshDomainGetXML ( ctl , cmd , domainXMLFlags , & xmldoc , & ctxt ) < 0 )
2019-03-29 18:46:54 +03:00
return NULL ;
2018-06-26 13:41:34 +03:00
naliases = virXPathNodeSet ( " ./devices//alias/@name " , ctxt , & aliases ) ;
if ( naliases < 0 )
2019-03-29 18:46:54 +03:00
return NULL ;
2018-06-26 13:41:34 +03:00
if ( VIR_ALLOC_N ( tmp , naliases + 1 ) < 0 )
2019-03-29 18:46:54 +03:00
return NULL ;
2018-06-26 13:41:34 +03:00
for ( i = 0 ; i < naliases ; i + + ) {
if ( ! ( tmp [ i ] = virXMLNodeContentString ( aliases [ i ] ) ) )
2019-03-29 18:46:54 +03:00
return NULL ;
2018-06-26 13:41:34 +03:00
}
VIR_STEAL_PTR ( ret , tmp ) ;
return ret ;
}
2018-12-30 07:28:04 +03:00
char * *
virshDomainShutdownModeCompleter ( vshControl * ctl ,
const vshCmd * cmd ,
unsigned int flags )
{
2019-06-18 13:16:17 +03:00
const char * modes [ ] = { " acpi " , " agent " , " initctl " , " signal " , " paravirt " , NULL } ;
const char * mode = NULL ;
2018-12-30 07:28:04 +03:00
virCheckFlags ( 0 , NULL ) ;
2019-06-18 13:16:17 +03:00
if ( vshCommandOptStringQuiet ( ctl , cmd , " mode " , & mode ) < 0 )
2018-12-30 07:28:04 +03:00
return NULL ;
2019-06-18 13:16:17 +03:00
return virshCommaStringListComplete ( mode , modes ) ;
2018-12-30 07:28:04 +03:00
}