2019-07-13 19:00:35 +03:00
/*
* virsh - completer - domain . c : virsh completer callbacks related to domains
*
* Copyright ( C ) 2019 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-domain.h"
# include "viralloc.h"
# include "virmacaddr.h"
# include "virsh-domain.h"
2019-12-05 18:00:22 +03:00
# include "virsh-domain-monitor.h"
2019-07-13 19:00:35 +03:00
# include "virsh-util.h"
# include "virsh.h"
# include "virstring.h"
# include "virxml.h"
2020-09-11 10:13:06 +03:00
# include "virperf.h"
2020-11-10 12:50:52 +03:00
# include "virbitmap.h"
2021-02-16 23:15:43 +03:00
# include "virkeycode.h"
2021-02-18 21:11:22 +03:00
# include "virkeynametable_linux.h"
# include "virkeynametable_osx.h"
# include "virkeynametable_win32.h"
2019-07-13 19:00:35 +03:00
char * *
virshDomainNameCompleter ( vshControl * ctl ,
2019-10-14 15:44:29 +03:00
const vshCmd * cmd G_GNUC_UNUSED ,
2019-07-13 19:00:35 +03:00
unsigned int flags )
{
2021-03-11 10:16:13 +03:00
virshControl * priv = ctl - > privData ;
2019-07-13 19:00:35 +03:00
virDomainPtr * domains = NULL ;
int ndomains = 0 ;
size_t i = 0 ;
char * * ret = NULL ;
2020-12-01 11:21:32 +03:00
g_auto ( GStrv ) tmp = NULL ;
2019-07-13 19:00:35 +03:00
virCheckFlags ( VIR_CONNECT_LIST_DOMAINS_ACTIVE |
VIR_CONNECT_LIST_DOMAINS_INACTIVE |
VIR_CONNECT_LIST_DOMAINS_OTHER |
VIR_CONNECT_LIST_DOMAINS_PAUSED |
VIR_CONNECT_LIST_DOMAINS_PERSISTENT |
VIR_CONNECT_LIST_DOMAINS_RUNNING |
2020-09-11 10:13:02 +03:00
VIR_CONNECT_LIST_DOMAINS_SHUTOFF |
VIR_CONNECT_LIST_DOMAINS_MANAGEDSAVE |
VIR_CONNECT_LIST_DOMAINS_HAS_SNAPSHOT |
VIR_CONNECT_LIST_DOMAINS_HAS_CHECKPOINT ,
2019-07-13 19:00:35 +03:00
NULL ) ;
if ( ! priv - > conn | | virConnectIsAlive ( priv - > conn ) < = 0 )
return NULL ;
if ( ( ndomains = virConnectListAllDomains ( priv - > conn , & domains , flags ) ) < 0 )
return NULL ;
2020-09-14 17:24:44 +03:00
tmp = g_new0 ( char * , ndomains + 1 ) ;
2019-07-13 19:00:35 +03:00
for ( i = 0 ; i < ndomains ; i + + ) {
const char * name = virDomainGetName ( domains [ i ] ) ;
2019-10-20 14:49:46 +03:00
tmp [ i ] = g_strdup ( name ) ;
2019-07-13 19:00:35 +03:00
}
2019-10-16 14:43:36 +03:00
ret = g_steal_pointer ( & tmp ) ;
2019-07-13 19:00:35 +03:00
for ( i = 0 ; i < ndomains ; i + + )
virshDomainFree ( domains [ i ] ) ;
2020-09-14 17:10:15 +03:00
g_free ( domains ) ;
2019-07-13 19:00:35 +03:00
return ret ;
}
2020-09-11 10:13:09 +03:00
char * *
virshDomainUUIDCompleter ( vshControl * ctl ,
const vshCmd * cmd G_GNUC_UNUSED ,
unsigned int flags )
{
2021-03-11 10:16:13 +03:00
virshControl * priv = ctl - > privData ;
2020-09-11 10:13:09 +03:00
virDomainPtr * domains = NULL ;
int ndomains = 0 ;
size_t i = 0 ;
char * * ret = NULL ;
2020-12-01 11:21:32 +03:00
g_auto ( GStrv ) tmp = NULL ;
2020-09-11 10:13:09 +03:00
virCheckFlags ( VIR_CONNECT_LIST_DOMAINS_ACTIVE |
VIR_CONNECT_LIST_DOMAINS_INACTIVE |
VIR_CONNECT_LIST_DOMAINS_OTHER |
VIR_CONNECT_LIST_DOMAINS_PAUSED |
VIR_CONNECT_LIST_DOMAINS_PERSISTENT |
VIR_CONNECT_LIST_DOMAINS_RUNNING |
VIR_CONNECT_LIST_DOMAINS_SHUTOFF |
VIR_CONNECT_LIST_DOMAINS_MANAGEDSAVE |
VIR_CONNECT_LIST_DOMAINS_HAS_SNAPSHOT |
VIR_CONNECT_LIST_DOMAINS_HAS_CHECKPOINT ,
NULL ) ;
if ( ! priv - > conn | | virConnectIsAlive ( priv - > conn ) < = 0 )
return NULL ;
if ( ( ndomains = virConnectListAllDomains ( priv - > conn , & domains , flags ) ) < 0 )
return NULL ;
2020-09-14 17:24:44 +03:00
tmp = g_new0 ( char * , ndomains + 1 ) ;
2020-09-11 10:13:09 +03:00
for ( i = 0 ; i < ndomains ; i + + ) {
char uuid [ VIR_UUID_STRING_BUFLEN ] ;
if ( virDomainGetUUIDString ( domains [ i ] , uuid ) < 0 )
goto cleanup ;
tmp [ i ] = g_strdup ( uuid ) ;
}
ret = g_steal_pointer ( & tmp ) ;
cleanup :
for ( i = 0 ; i < ndomains ; i + + )
virshDomainFree ( domains [ i ] ) ;
2020-09-14 17:10:15 +03:00
g_free ( domains ) ;
2020-09-11 10:13:09 +03:00
return ret ;
}
2019-07-13 19:00:35 +03:00
char * *
virshDomainInterfaceCompleter ( vshControl * ctl ,
const vshCmd * cmd ,
unsigned int flags )
{
2021-03-11 10:16:13 +03:00
virshControl * priv = ctl - > privData ;
2019-10-15 15:47:50 +03:00
g_autoptr ( xmlDoc ) xmldoc = NULL ;
g_autoptr ( xmlXPathContext ) ctxt = NULL ;
2019-07-13 19:00:35 +03:00
int ninterfaces ;
2019-10-15 16:16:31 +03:00
g_autofree xmlNodePtr * interfaces = NULL ;
2019-07-13 19:00:35 +03:00
size_t i ;
unsigned int domainXMLFlags = 0 ;
2020-12-01 11:21:32 +03:00
g_auto ( GStrv ) tmp = NULL ;
2019-07-13 19:00:35 +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 )
return NULL ;
ninterfaces = virXPathNodeSet ( " ./devices/interface " , ctxt , & interfaces ) ;
if ( ninterfaces < 0 )
return NULL ;
2020-09-14 17:24:44 +03:00
tmp = g_new0 ( char * , ninterfaces + 1 ) ;
2019-07-13 19:00:35 +03:00
for ( i = 0 ; i < ninterfaces ; i + + ) {
ctxt - > node = interfaces [ i ] ;
if ( ! ( flags & VIRSH_DOMAIN_INTERFACE_COMPLETER_MAC ) & &
( tmp [ i ] = virXPathString ( " string(./target/@dev) " , ctxt ) ) )
continue ;
/* In case we are dealing with inactive domain XML there's no
* < target dev = ' ' / > . Offer MAC addresses then . */
if ( ! ( tmp [ i ] = virXPathString ( " string(./mac/@address) " , ctxt ) ) )
return NULL ;
}
2019-10-17 11:10:10 +03:00
return g_steal_pointer ( & tmp ) ;
2019-07-13 19:00:35 +03:00
}
char * *
virshDomainDiskTargetCompleter ( vshControl * ctl ,
const vshCmd * cmd ,
unsigned int flags )
{
2021-03-11 10:16:13 +03:00
virshControl * priv = ctl - > privData ;
2019-10-15 15:47:50 +03:00
g_autoptr ( xmlDoc ) xmldoc = NULL ;
g_autoptr ( xmlXPathContext ) ctxt = NULL ;
2019-10-15 16:16:31 +03:00
g_autofree xmlNodePtr * disks = NULL ;
2019-07-13 19:00:35 +03:00
int ndisks ;
size_t i ;
2020-12-01 11:21:32 +03:00
g_auto ( GStrv ) tmp = NULL ;
2019-07-13 19:00:35 +03:00
virCheckFlags ( 0 , NULL ) ;
if ( ! priv - > conn | | virConnectIsAlive ( priv - > conn ) < = 0 )
return NULL ;
if ( virshDomainGetXML ( ctl , cmd , 0 , & xmldoc , & ctxt ) < 0 )
return NULL ;
ndisks = virXPathNodeSet ( " ./devices/disk " , ctxt , & disks ) ;
if ( ndisks < 0 )
return NULL ;
2020-09-14 17:24:44 +03:00
tmp = g_new0 ( char * , ndisks + 1 ) ;
2019-07-13 19:00:35 +03:00
for ( i = 0 ; i < ndisks ; i + + ) {
ctxt - > node = disks [ i ] ;
if ( ! ( tmp [ i ] = virXPathString ( " string(./target/@dev) " , ctxt ) ) )
return NULL ;
}
2019-10-17 11:10:10 +03:00
return g_steal_pointer ( & tmp ) ;
2019-07-13 19:00:35 +03:00
}
char * *
2019-10-14 15:44:29 +03:00
virshDomainEventNameCompleter ( vshControl * ctl G_GNUC_UNUSED ,
const vshCmd * cmd G_GNUC_UNUSED ,
2019-07-13 19:00:35 +03:00
unsigned int flags )
{
size_t i = 0 ;
2020-12-01 11:21:32 +03:00
g_auto ( GStrv ) tmp = NULL ;
2019-07-13 19:00:35 +03:00
virCheckFlags ( 0 , NULL ) ;
2020-09-14 17:24:44 +03:00
tmp = g_new0 ( char * , VIR_DOMAIN_EVENT_ID_LAST + 1 ) ;
2019-07-13 19:00:35 +03:00
2019-10-20 14:49:46 +03:00
for ( i = 0 ; i < VIR_DOMAIN_EVENT_ID_LAST ; i + + )
tmp [ i ] = g_strdup ( virshDomainEventCallbacks [ i ] . name ) ;
2019-07-13 19:00:35 +03:00
2019-10-17 11:10:10 +03:00
return g_steal_pointer ( & tmp ) ;
2019-07-13 19:00:35 +03:00
}
char * *
virshDomainInterfaceStateCompleter ( vshControl * ctl ,
const vshCmd * cmd ,
unsigned int flags )
{
2021-03-11 10:16:13 +03:00
virshControl * priv = ctl - > privData ;
2019-07-13 19:00:35 +03:00
const char * iface = NULL ;
2019-10-15 15:47:50 +03:00
g_autoptr ( xmlDoc ) xml = NULL ;
g_autoptr ( xmlXPathContext ) ctxt = NULL ;
2019-07-13 19:00:35 +03:00
virMacAddr macaddr ;
char macstr [ VIR_MAC_STRING_BUFLEN ] = " " ;
int ninterfaces ;
2019-10-15 16:16:31 +03:00
g_autofree xmlNodePtr * interfaces = NULL ;
g_autofree char * xpath = NULL ;
g_autofree char * state = NULL ;
2020-12-01 11:21:32 +03:00
g_auto ( GStrv ) tmp = NULL ;
2019-07-13 19:00:35 +03:00
virCheckFlags ( 0 , NULL ) ;
if ( ! priv - > conn | | virConnectIsAlive ( priv - > conn ) < = 0 )
return NULL ;
if ( virshDomainGetXML ( ctl , cmd , flags , & xml , & ctxt ) < 0 )
return NULL ;
if ( vshCommandOptStringReq ( ctl , cmd , " interface " , & iface ) < 0 )
return NULL ;
/* normalize the mac addr */
if ( virMacAddrParse ( iface , & macaddr ) = = 0 )
virMacAddrFormat ( & macaddr , macstr ) ;
2019-10-22 16:26:14 +03:00
xpath = g_strdup_printf ( " /domain/devices/interface[(mac/@address = '%s') or "
" (target/@dev = '%s')] " , macstr ,
iface ) ;
2019-07-13 19:00:35 +03:00
if ( ( ninterfaces = virXPathNodeSet ( xpath , ctxt , & interfaces ) ) < 0 )
return NULL ;
if ( ninterfaces ! = 1 )
return NULL ;
ctxt - > node = interfaces [ 0 ] ;
2020-09-14 17:24:44 +03:00
tmp = g_new0 ( char * , 2 ) ;
2019-07-13 19:00:35 +03:00
if ( ( state = virXPathString ( " string(./link/@state) " , ctxt ) ) & &
STREQ ( state , " down " ) ) {
2019-10-20 14:49:46 +03:00
tmp [ 0 ] = g_strdup ( " up " ) ;
2019-07-13 19:00:35 +03:00
} else {
2019-10-20 14:49:46 +03:00
tmp [ 0 ] = g_strdup ( " down " ) ;
2019-07-13 19:00:35 +03:00
}
2019-10-17 11:10:10 +03:00
return g_steal_pointer ( & tmp ) ;
2019-07-13 19:00:35 +03:00
}
char * *
virshDomainDeviceAliasCompleter ( vshControl * ctl ,
const vshCmd * cmd ,
unsigned int flags )
{
2021-03-11 10:16:13 +03:00
virshControl * priv = ctl - > privData ;
2019-10-15 15:47:50 +03:00
g_autoptr ( xmlDoc ) xmldoc = NULL ;
g_autoptr ( xmlXPathContext ) ctxt = NULL ;
2019-07-13 19:00:35 +03:00
int naliases ;
2019-10-15 16:16:31 +03:00
g_autofree xmlNodePtr * aliases = NULL ;
2019-07-13 19:00:35 +03:00
size_t i ;
unsigned int domainXMLFlags = 0 ;
2020-12-01 11:21:32 +03:00
g_auto ( GStrv ) tmp = NULL ;
2019-07-13 19:00:35 +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 )
return NULL ;
2021-01-22 11:29:54 +03:00
naliases = virXPathNodeSet ( " /domain/devices//alias[@name] " , ctxt , & aliases ) ;
2019-07-13 19:00:35 +03:00
if ( naliases < 0 )
return NULL ;
2020-09-14 17:24:44 +03:00
tmp = g_new0 ( char * , naliases + 1 ) ;
2019-07-13 19:00:35 +03:00
for ( i = 0 ; i < naliases ; i + + ) {
2021-01-22 11:29:54 +03:00
if ( ! ( tmp [ i ] = virXMLPropString ( aliases [ i ] , " name " ) ) )
2019-07-13 19:00:35 +03:00
return NULL ;
}
2019-10-17 11:10:10 +03:00
return g_steal_pointer ( & tmp ) ;
2019-07-13 19:00:35 +03:00
}
char * *
virshDomainShutdownModeCompleter ( vshControl * ctl ,
const vshCmd * cmd ,
unsigned int flags )
{
const char * modes [ ] = { " acpi " , " agent " , " initctl " , " signal " , " paravirt " , NULL } ;
const char * mode = NULL ;
virCheckFlags ( 0 , NULL ) ;
if ( vshCommandOptStringQuiet ( ctl , cmd , " mode " , & mode ) < 0 )
return NULL ;
return virshCommaStringListComplete ( mode , modes ) ;
}
2020-01-02 18:07:06 +03:00
char * *
2019-12-05 18:00:22 +03:00
virshDomainInterfaceAddrSourceCompleter ( vshControl * ctl G_GNUC_UNUSED ,
const vshCmd * cmd G_GNUC_UNUSED ,
2020-01-02 18:07:06 +03:00
unsigned int flags )
{
2019-12-05 18:00:22 +03:00
char * * ret = NULL ;
size_t i ;
2020-01-02 18:07:06 +03:00
virCheckFlags ( 0 , NULL ) ;
2020-10-07 21:54:13 +03:00
ret = g_new0 ( char * , VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LAST + 1 ) ;
2020-01-02 18:07:06 +03:00
2019-12-05 18:00:22 +03:00
for ( i = 0 ; i < VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LAST ; i + + )
ret [ i ] = g_strdup ( virshDomainInterfaceAddressesSourceTypeToString ( i ) ) ;
return ret ;
2020-01-02 18:07:06 +03:00
}
2019-12-27 23:36:25 +03:00
char * *
virshDomainHostnameSourceCompleter ( vshControl * ctl G_GNUC_UNUSED ,
const vshCmd * cmd G_GNUC_UNUSED ,
unsigned int flags )
{
char * * ret = NULL ;
size_t i ;
virCheckFlags ( 0 , NULL ) ;
2020-10-07 21:54:13 +03:00
ret = g_new0 ( char * , VIRSH_DOMAIN_HOSTNAME_SOURCE_LAST + 1 ) ;
2019-12-27 23:36:25 +03:00
for ( i = 0 ; i < VIRSH_DOMAIN_HOSTNAME_SOURCE_LAST ; i + + )
ret [ i ] = g_strdup ( virshDomainHostnameSourceTypeToString ( i ) ) ;
return ret ;
}
2020-09-11 10:13:06 +03:00
char * *
virshDomainPerfEnableCompleter ( vshControl * ctl ,
const vshCmd * cmd ,
unsigned int flags )
{
size_t i = 0 ;
2020-12-01 11:21:32 +03:00
g_auto ( GStrv ) events = NULL ;
2020-09-11 10:13:06 +03:00
const char * event = NULL ;
virCheckFlags ( 0 , NULL ) ;
2020-09-14 17:24:44 +03:00
events = g_new0 ( char * , VIR_PERF_EVENT_LAST + 1 ) ;
2020-09-11 10:13:06 +03:00
for ( i = 0 ; i < VIR_PERF_EVENT_LAST ; i + + )
events [ i ] = g_strdup ( virPerfEventTypeToString ( i ) ) ;
if ( vshCommandOptStringQuiet ( ctl , cmd , " enable " , & event ) < 0 )
return NULL ;
return virshCommaStringListComplete ( event , ( const char * * ) events ) ;
}
char * *
virshDomainPerfDisableCompleter ( vshControl * ctl ,
const vshCmd * cmd ,
unsigned int flags )
{
size_t i = 0 ;
2020-12-01 11:21:32 +03:00
g_auto ( GStrv ) events = NULL ;
2020-09-11 10:13:06 +03:00
const char * event = NULL ;
virCheckFlags ( 0 , NULL ) ;
2020-09-14 17:24:44 +03:00
events = g_new0 ( char * , VIR_PERF_EVENT_LAST + 1 ) ;
2020-09-11 10:13:06 +03:00
for ( i = 0 ; i < VIR_PERF_EVENT_LAST ; i + + )
events [ i ] = g_strdup ( virPerfEventTypeToString ( i ) ) ;
if ( vshCommandOptStringQuiet ( ctl , cmd , " disable " , & event ) < 0 )
return NULL ;
return virshCommaStringListComplete ( event , ( const char * * ) events ) ;
}
2020-09-11 10:13:10 +03:00
char * *
virshDomainIOThreadIdCompleter ( vshControl * ctl ,
const vshCmd * cmd ,
unsigned int flags )
{
virDomainPtr dom = NULL ;
size_t niothreads = 0 ;
g_autofree virDomainIOThreadInfoPtr * info = NULL ;
size_t i ;
int rc ;
char * * ret = NULL ;
2020-12-01 11:21:32 +03:00
g_auto ( GStrv ) tmp = NULL ;
2020-09-11 10:13:10 +03:00
virCheckFlags ( 0 , NULL ) ;
if ( ! ( dom = virshCommandOptDomain ( ctl , cmd , NULL ) ) )
return NULL ;
if ( ( rc = virDomainGetIOThreadInfo ( dom , & info , flags ) ) < 0 )
goto cleanup ;
niothreads = rc ;
2020-09-14 17:24:44 +03:00
tmp = g_new0 ( char * , niothreads + 1 ) ;
2020-09-11 10:13:10 +03:00
for ( i = 0 ; i < niothreads ; i + + )
tmp [ i ] = g_strdup_printf ( " %u " , info [ i ] - > iothread_id ) ;
ret = g_steal_pointer ( & tmp ) ;
cleanup :
virshDomainFree ( dom ) ;
return ret ;
}
2020-09-11 10:13:12 +03:00
char * *
virshDomainVcpuCompleter ( vshControl * ctl ,
const vshCmd * cmd ,
unsigned int flags )
{
virDomainPtr dom = NULL ;
xmlDocPtr xml = NULL ;
xmlXPathContextPtr ctxt = NULL ;
int nvcpus = 0 ;
unsigned int id ;
char * * ret = NULL ;
2020-12-01 11:21:32 +03:00
g_auto ( GStrv ) tmp = NULL ;
2020-09-11 10:13:12 +03:00
virCheckFlags ( 0 , NULL ) ;
if ( ! ( dom = virshCommandOptDomain ( ctl , cmd , NULL ) ) )
return NULL ;
if ( virshDomainGetXMLFromDom ( ctl , dom , VIR_DOMAIN_XML_INACTIVE ,
& xml , & ctxt ) < 0 )
goto cleanup ;
/* Query the max rather than the current vcpu count */
if ( virXPathInt ( " string(/domain/vcpu) " , ctxt , & nvcpus ) < 0 )
goto cleanup ;
2020-09-14 17:24:44 +03:00
tmp = g_new0 ( char * , nvcpus + 1 ) ;
2020-09-11 10:13:12 +03:00
for ( id = 0 ; id < nvcpus ; id + + )
tmp [ id ] = g_strdup_printf ( " %u " , id ) ;
ret = g_steal_pointer ( & tmp ) ;
cleanup :
xmlXPathFreeContext ( ctxt ) ;
xmlFreeDoc ( xml ) ;
virshDomainFree ( dom ) ;
return ret ;
}
2020-09-11 10:13:13 +03:00
char * *
virshDomainVcpulistCompleter ( vshControl * ctl ,
const vshCmd * cmd ,
unsigned int flags )
{
virDomainPtr dom = NULL ;
xmlDocPtr xml = NULL ;
xmlXPathContextPtr ctxt = NULL ;
int nvcpus = 0 ;
unsigned int id ;
2020-12-01 11:21:32 +03:00
g_auto ( GStrv ) vcpulist = NULL ;
2020-09-11 10:13:13 +03:00
const char * vcpuid = NULL ;
char * * ret = NULL ;
virCheckFlags ( 0 , NULL ) ;
if ( ! ( dom = virshCommandOptDomain ( ctl , cmd , NULL ) ) )
return NULL ;
if ( vshCommandOptStringQuiet ( ctl , cmd , " vcpulist " , & vcpuid ) < 0 )
goto cleanup ;
if ( virshDomainGetXMLFromDom ( ctl , dom , VIR_DOMAIN_XML_INACTIVE ,
& xml , & ctxt ) < 0 )
goto cleanup ;
/* Query the max rather than the current vcpu count */
if ( virXPathInt ( " string(/domain/vcpu) " , ctxt , & nvcpus ) < 0 )
goto cleanup ;
2020-09-14 17:24:44 +03:00
vcpulist = g_new0 ( char * , nvcpus + 1 ) ;
2020-09-11 10:13:13 +03:00
for ( id = 0 ; id < nvcpus ; id + + )
vcpulist [ id ] = g_strdup_printf ( " %u " , id ) ;
ret = virshCommaStringListComplete ( vcpuid , ( const char * * ) vcpulist ) ;
cleanup :
xmlXPathFreeContext ( ctxt ) ;
xmlFreeDoc ( xml ) ;
virshDomainFree ( dom ) ;
return ret ;
}
2020-09-11 10:13:14 +03:00
char * *
virshDomainCpulistCompleter ( vshControl * ctl ,
const vshCmd * cmd ,
unsigned int flags )
{
2021-03-11 10:16:13 +03:00
virshControl * priv = ctl - > privData ;
2020-09-11 10:13:14 +03:00
size_t i ;
int cpunum ;
g_autofree unsigned char * cpumap = NULL ;
unsigned int online ;
2020-12-01 11:21:32 +03:00
g_auto ( GStrv ) cpulist = NULL ;
2020-09-11 10:13:14 +03:00
const char * cpuid = NULL ;
virCheckFlags ( 0 , NULL ) ;
if ( vshCommandOptStringQuiet ( ctl , cmd , " cpulist " , & cpuid ) < 0 )
return NULL ;
if ( ( cpunum = virNodeGetCPUMap ( priv - > conn , & cpumap , & online , 0 ) ) < 0 )
return NULL ;
2020-09-14 17:24:44 +03:00
cpulist = g_new0 ( char * , cpunum + 1 ) ;
2020-09-11 10:13:14 +03:00
for ( i = 0 ; i < cpunum ; i + + )
cpulist [ i ] = g_strdup_printf ( " %zu " , i ) ;
return virshCommaStringListComplete ( cpuid , ( const char * * ) cpulist ) ;
}
2020-11-10 12:50:52 +03:00
char * *
virshDomainVcpulistViaAgentCompleter ( vshControl * ctl ,
const vshCmd * cmd ,
unsigned int flags )
{
virDomainPtr dom ;
bool enable = vshCommandOptBool ( cmd , " enable " ) ;
bool disable = vshCommandOptBool ( cmd , " disable " ) ;
virTypedParameterPtr params = NULL ;
unsigned int nparams = 0 ;
size_t i ;
int nvcpus ;
2020-12-01 11:21:32 +03:00
g_auto ( GStrv ) cpulist = NULL ;
2020-11-10 12:50:52 +03:00
const char * vcpuid = NULL ;
char * * ret = NULL ;
virCheckFlags ( 0 , NULL ) ;
if ( ! ( dom = virshCommandOptDomain ( ctl , cmd , NULL ) ) )
return NULL ;
if ( vshCommandOptStringQuiet ( ctl , cmd , " cpulist " , & vcpuid ) < 0 )
goto cleanup ;
/* retrieve vcpu count from the guest instead of the hypervisor */
if ( ( nvcpus = virDomainGetVcpusFlags ( dom ,
VIR_DOMAIN_VCPU_GUEST |
VIR_DOMAIN_VCPU_MAXIMUM ) ) < 0 )
goto cleanup ;
if ( ! enable & & ! disable ) {
cpulist = g_new0 ( char * , nvcpus + 1 ) ;
for ( i = 0 ; i < nvcpus ; i + + )
cpulist [ i ] = g_strdup_printf ( " %zu " , i ) ;
} else {
g_autofree char * onlineVcpuStr = NULL ;
2021-04-22 13:38:19 +03:00
g_autofree char * offlinableVcpuStr = NULL ;
g_autofree unsigned char * onlineVcpumap = NULL ;
g_autofree unsigned char * offlinableVcpumap = NULL ;
g_autoptr ( virBitmap ) onlineVcpus = NULL ;
g_autoptr ( virBitmap ) offlinableVcpus = NULL ;
size_t j = 0 ;
int lastcpu ;
2020-11-10 12:50:52 +03:00
int dummy ;
if ( virDomainGetGuestVcpus ( dom , & params , & nparams , 0 ) < 0 )
goto cleanup ;
onlineVcpuStr = vshGetTypedParamValue ( ctl , & params [ 1 ] ) ;
2021-04-22 13:38:19 +03:00
if ( ! ( onlineVcpus = virBitmapParseUnlimited ( onlineVcpuStr ) ) )
2020-11-10 12:50:52 +03:00
goto cleanup ;
2021-04-22 13:38:19 +03:00
if ( virBitmapToData ( onlineVcpus , & onlineVcpumap , & dummy ) < 0 )
2020-11-10 12:50:52 +03:00
goto cleanup ;
if ( enable ) {
2021-04-22 13:38:19 +03:00
offlinableVcpuStr = vshGetTypedParamValue ( ctl , & params [ 2 ] ) ;
if ( ! ( offlinableVcpus = virBitmapParseUnlimited ( offlinableVcpuStr ) ) )
goto cleanup ;
if ( virBitmapToData ( offlinableVcpus , & offlinableVcpumap , & dummy ) < 0 )
goto cleanup ;
lastcpu = virBitmapLastSetBit ( offlinableVcpus ) ;
cpulist = g_new0 ( char * , nvcpus - virBitmapCountBits ( onlineVcpus ) + 1 ) ;
for ( i = 0 ; i < nvcpus - virBitmapCountBits ( onlineVcpus ) ; i + + ) {
while ( j < = lastcpu ) {
if ( VIR_CPU_USED ( onlineVcpumap , j ) ! = 0 | |
VIR_CPU_USED ( offlinableVcpumap , j ) = = 0 ) {
j + = 1 ;
continue ;
} else {
break ;
}
}
cpulist [ i ] = g_strdup_printf ( " %zu " , j + + ) ;
2020-11-10 12:50:52 +03:00
}
} else if ( disable ) {
2021-04-22 13:38:19 +03:00
lastcpu = virBitmapLastSetBit ( onlineVcpus ) ;
cpulist = g_new0 ( char * , virBitmapCountBits ( onlineVcpus ) + 1 ) ;
for ( i = 0 ; i < virBitmapCountBits ( onlineVcpus ) ; i + + ) {
while ( j < = lastcpu ) {
if ( VIR_CPU_USED ( onlineVcpumap , j ) = = 0 ) {
j + = 1 ;
continue ;
} else {
break ;
}
}
cpulist [ i ] = g_strdup_printf ( " %zu " , j + + ) ;
2020-11-10 12:50:52 +03:00
}
}
}
ret = virshCommaStringListComplete ( vcpuid , ( const char * * ) cpulist ) ;
cleanup :
virTypedParamsFree ( params , nparams ) ;
virshDomainFree ( dom ) ;
return ret ;
}
2020-11-10 12:50:54 +03:00
char * *
virshDomainConsoleCompleter ( vshControl * ctl ,
const vshCmd * cmd ,
unsigned int flags )
{
2021-03-11 10:16:13 +03:00
virshControl * priv = ctl - > privData ;
2020-11-10 12:50:54 +03:00
g_autoptr ( xmlDoc ) xmldoc = NULL ;
g_autoptr ( xmlXPathContext ) ctxt = NULL ;
int nserials ;
int nparallels ;
g_autofree xmlNodePtr * serials = NULL ;
g_autofree xmlNodePtr * parallels = NULL ;
size_t i ;
size_t offset = 0 ;
2020-12-01 11:21:32 +03:00
g_auto ( GStrv ) tmp = NULL ;
2020-11-10 12:50:54 +03:00
virCheckFlags ( 0 , NULL ) ;
if ( ! priv - > conn | | virConnectIsAlive ( priv - > conn ) < = 0 )
return NULL ;
if ( virshDomainGetXML ( ctl , cmd , 0 , & xmldoc , & ctxt ) < 0 )
return NULL ;
nserials = virXPathNodeSet ( " ./devices/serial " , ctxt , & serials ) ;
if ( nserials < 0 )
return NULL ;
nparallels = virXPathNodeSet ( " ./devices/parallel " , ctxt , & parallels ) ;
if ( nparallels < 0 )
return NULL ;
tmp = g_new0 ( char * , nserials + nparallels + 1 ) ;
for ( i = 0 ; i < nserials + nparallels ; i + + ) {
g_autofree char * type = NULL ;
if ( i < nserials )
ctxt - > node = serials [ i ] ;
else
ctxt - > node = parallels [ i - nserials ] ;
type = virXPathString ( " string(./@type) " , ctxt ) ;
if ( STRNEQ ( type , " pty " ) )
continue ;
tmp [ offset + + ] = virXPathString ( " string(./alias/@name) " , ctxt ) ;
}
return g_steal_pointer ( & tmp ) ;
}
2020-11-10 12:51:02 +03:00
char * *
virshDomainSignalCompleter ( vshControl * ctl G_GNUC_UNUSED ,
const vshCmd * cmd G_GNUC_UNUSED ,
unsigned int flags )
{
2020-12-01 11:21:32 +03:00
g_auto ( GStrv ) tmp = NULL ;
2020-11-10 12:51:02 +03:00
size_t i = 0 ;
virCheckFlags ( 0 , NULL ) ;
tmp = g_new0 ( char * , VIR_DOMAIN_PROCESS_SIGNAL_LAST + 1 ) ;
for ( i = 0 ; i < VIR_DOMAIN_PROCESS_SIGNAL_LAST ; i + + ) {
const char * name = virDomainProcessSignalTypeToString ( i ) ;
tmp [ i ] = g_strdup ( name ) ;
}
return g_steal_pointer ( & tmp ) ;
}
2020-11-10 12:51:03 +03:00
char * *
virshDomainLifecycleCompleter ( vshControl * ctl G_GNUC_UNUSED ,
const vshCmd * cmd G_GNUC_UNUSED ,
unsigned int flags )
{
2020-12-01 11:21:32 +03:00
g_auto ( GStrv ) tmp = NULL ;
2020-11-10 12:51:03 +03:00
size_t i = 0 ;
virCheckFlags ( 0 , NULL ) ;
tmp = g_new0 ( char * , VIR_DOMAIN_LIFECYCLE_LAST + 1 ) ;
for ( i = 0 ; i < VIR_DOMAIN_LIFECYCLE_LAST ; i + + ) {
const char * name = virDomainLifecycleTypeToString ( i ) ;
tmp [ i ] = g_strdup ( name ) ;
}
return g_steal_pointer ( & tmp ) ;
}
2020-11-10 12:51:04 +03:00
char * *
virshDomainLifecycleActionCompleter ( vshControl * ctl G_GNUC_UNUSED ,
const vshCmd * cmd G_GNUC_UNUSED ,
unsigned int flags )
{
2020-12-01 11:21:32 +03:00
g_auto ( GStrv ) tmp = NULL ;
2020-11-10 12:51:04 +03:00
size_t i = 0 ;
virCheckFlags ( 0 , NULL ) ;
tmp = g_new0 ( char * , VIR_DOMAIN_LIFECYCLE_ACTION_LAST + 1 ) ;
for ( i = 0 ; i < VIR_DOMAIN_LIFECYCLE_ACTION_LAST ; i + + ) {
const char * action = virDomainLifecycleActionTypeToString ( i ) ;
tmp [ i ] = g_strdup ( action ) ;
}
return g_steal_pointer ( & tmp ) ;
}
2021-02-16 23:15:43 +03:00
char * *
virshCodesetNameCompleter ( vshControl * ctl G_GNUC_UNUSED ,
const vshCmd * cmd G_GNUC_UNUSED ,
unsigned int flags )
{
g_auto ( GStrv ) tmp = NULL ;
size_t i = 0 ;
virCheckFlags ( 0 , NULL ) ;
tmp = g_new0 ( char * , VIR_KEYCODE_SET_LAST + 1 ) ;
for ( i = 0 ; i < VIR_KEYCODE_SET_LAST ; i + + ) {
const char * name = virKeycodeSetTypeToString ( i ) ;
tmp [ i ] = g_strdup ( name ) ;
}
return g_steal_pointer ( & tmp ) ;
}
2021-02-18 21:11:22 +03:00
char * *
virshKeycodeNameCompleter ( vshControl * ctl ,
const vshCmd * cmd ,
unsigned int flags )
{
g_auto ( GStrv ) tmp = NULL ;
size_t i = 0 ;
size_t j = 0 ;
const char * codeset_option ;
int codeset ;
const char * * names = NULL ;
size_t len ;
virCheckFlags ( 0 , NULL ) ;
if ( vshCommandOptStringQuiet ( ctl , cmd , " codeset " , & codeset_option ) < = 0 )
codeset_option = " linux " ;
if ( STREQ ( codeset_option , " rfb " ) )
codeset_option = " qnum " ;
codeset = virKeycodeSetTypeFromString ( codeset_option ) ;
if ( codeset < 0 )
return NULL ;
switch ( ( virKeycodeSet ) codeset ) {
case VIR_KEYCODE_SET_LINUX :
names = virKeyNameTable_linux ;
len = virKeyNameTable_linux_len ;
break ;
case VIR_KEYCODE_SET_OSX :
names = virKeyNameTable_osx ;
len = virKeyNameTable_osx_len ;
break ;
case VIR_KEYCODE_SET_WIN32 :
names = virKeyNameTable_win32 ;
len = virKeyNameTable_win32_len ;
break ;
case VIR_KEYCODE_SET_XT :
case VIR_KEYCODE_SET_ATSET1 :
case VIR_KEYCODE_SET_ATSET2 :
case VIR_KEYCODE_SET_ATSET3 :
case VIR_KEYCODE_SET_XT_KBD :
case VIR_KEYCODE_SET_USB :
case VIR_KEYCODE_SET_QNUM :
case VIR_KEYCODE_SET_LAST :
break ;
}
if ( ! names )
return NULL ;
tmp = g_new0 ( char * , len + 1 ) ;
for ( i = 0 ; i < len ; i + + ) {
if ( ! names [ i ] )
continue ;
tmp [ j ] = g_strdup ( names [ i ] ) ;
j + + ;
}
tmp = g_renew ( char * , tmp , j + 1 ) ;
return g_steal_pointer ( & tmp ) ;
}
2021-04-22 13:38:18 +03:00
char * *
virshDomainFSMountpointsCompleter ( vshControl * ctl ,
const vshCmd * cmd ,
unsigned int flags )
{
g_auto ( GStrv ) tmp = NULL ;
virDomainPtr dom = NULL ;
int rc = - 1 ;
size_t i ;
virDomainFSInfoPtr * info = NULL ;
size_t ninfos = 0 ;
char * * ret = NULL ;
virCheckFlags ( 0 , NULL ) ;
if ( ! ( dom = virshCommandOptDomain ( ctl , cmd , NULL ) ) )
return NULL ;
rc = virDomainGetFSInfo ( dom , & info , 0 ) ;
if ( rc < = 0 ) {
goto cleanup ;
}
ninfos = rc ;
tmp = g_new0 ( char * , ninfos + 1 ) ;
for ( i = 0 ; i < ninfos ; i + + ) {
tmp [ i ] = g_strdup ( info [ i ] - > mountpoint ) ;
}
ret = g_steal_pointer ( & tmp ) ;
cleanup :
if ( info ) {
for ( i = 0 ; i < ninfos ; i + + )
virDomainFSInfoFree ( info [ i ] ) ;
VIR_FREE ( info ) ;
}
virshDomainFree ( dom ) ;
return ret ;
}
2021-06-07 06:14:18 +03:00
char * *
virshDomainCoreDumpFormatCompleter ( vshControl * ctl G_GNUC_UNUSED ,
const vshCmd * cmd G_GNUC_UNUSED ,
unsigned int flags )
{
char * * ret = NULL ;
size_t i ;
virCheckFlags ( 0 , NULL ) ;
ret = g_new0 ( char * , VIR_DOMAIN_CORE_DUMP_FORMAT_LAST + 1 ) ;
for ( i = 0 ; i < VIR_DOMAIN_CORE_DUMP_FORMAT_LAST ; i + + )
ret [ i ] = g_strdup ( virDomainCoreDumpFormatTypeToString ( i ) ) ;
return ret ;
}
2021-06-15 03:38:21 +03:00
char * *
virshDomainMigrateCompMethodsCompleter ( vshControl * ctl ,
const vshCmd * cmd ,
unsigned int flags )
{
const char * methods [ ] = { " xbzrle " , " mt " , NULL } ;
const char * method = NULL ;
virCheckFlags ( 0 , NULL ) ;
if ( vshCommandOptStringQuiet ( ctl , cmd , " comp-methods " , & method ) < 0 )
return NULL ;
return virshCommaStringListComplete ( method , methods ) ;
}