2015-10-12 18:07:21 +03:00
/*
* virt - admin . c : a shell to exercise the libvirt admin API
*
* Copyright ( C ) 2015 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>
2020-02-24 00:45:34 +03:00
# include <stdio.h>
# include <unistd.h>
2015-10-12 18:07:21 +03:00
# include <getopt.h>
# include "internal.h"
2020-02-24 00:45:34 +03:00
# include "virt-admin.h"
2015-10-12 18:07:21 +03:00
# include "viralloc.h"
# include "virerror.h"
# include "virfile.h"
# include "virstring.h"
# include "virthread.h"
2016-04-13 01:29:52 +03:00
# include "virgettext.h"
2017-11-07 11:33:06 +03:00
# include "virt-admin-completer.h"
2018-09-21 17:17:24 +03:00
# include "vsh-table.h"
2019-04-01 13:14:26 +03:00
# include "virenum.h"
2015-10-12 18:07:21 +03:00
# define VIRT_ADMIN_PROMPT "virt-admin # "
static char * progname ;
static const vshCmdGrp cmdGroups [ ] ;
static const vshClientHooks hooks ;
2019-01-20 19:04:56 +03:00
VIR_ENUM_DECL ( virClientTransport ) ;
2016-04-16 10:13:21 +03:00
VIR_ENUM_IMPL ( virClientTransport ,
VIR_CLIENT_TRANS_LAST ,
N_ ( " unix " ) ,
N_ ( " tcp " ) ,
2019-01-20 19:30:15 +03:00
N_ ( " tls " ) ) ;
2016-04-16 10:13:21 +03:00
static const char *
vshAdmClientTransportToString ( int transport )
{
const char * str = virClientTransportTypeToString ( transport ) ;
return str ? _ ( str ) : _ ( " unknown " ) ;
}
2015-10-12 18:10:57 +03:00
/*
* vshAdmCatchDisconnect :
*
* We get here when the connection was closed . Unlike virsh , we do not save
2016-09-24 21:43:25 +03:00
* the fact that the event was raised , since there is virAdmConnectIsAlive to
2015-10-12 18:10:57 +03:00
* check if the communication channel has not been closed by remote party .
*/
static void
2019-10-14 15:44:29 +03:00
vshAdmCatchDisconnect ( virAdmConnectPtr conn G_GNUC_UNUSED ,
2015-10-12 18:10:57 +03:00
int reason ,
void * opaque )
{
vshControl * ctl = opaque ;
const char * str = " unknown reason " ;
if ( reason = = VIR_CONNECT_CLOSE_REASON_CLIENT )
return ;
switch ( ( virConnectCloseReason ) reason ) {
case VIR_CONNECT_CLOSE_REASON_ERROR :
2023-03-09 17:54:58 +03:00
str = N_ ( " Disconnected from %1$s due to I/O error " ) ;
2015-10-12 18:10:57 +03:00
break ;
case VIR_CONNECT_CLOSE_REASON_EOF :
2023-03-09 17:54:58 +03:00
str = N_ ( " Disconnected from %1$s due to end of file " ) ;
2015-10-12 18:10:57 +03:00
break ;
case VIR_CONNECT_CLOSE_REASON_KEEPALIVE :
2023-03-09 17:54:58 +03:00
str = N_ ( " Disconnected from %1$s due to keepalive timeout " ) ;
2015-10-12 18:10:57 +03:00
break ;
case VIR_CONNECT_CLOSE_REASON_CLIENT :
case VIR_CONNECT_CLOSE_REASON_LAST :
break ;
}
2023-12-14 19:13:08 +03:00
vshError ( ctl , _ ( str ) , NULLSTR ( ctl - > connname ) ) ;
2015-10-12 18:10:57 +03:00
}
2015-10-12 18:07:21 +03:00
static int
2015-12-10 15:46:45 +03:00
vshAdmConnect ( vshControl * ctl , unsigned int flags )
2015-10-12 18:07:21 +03:00
{
2021-03-11 10:16:13 +03:00
vshAdmControl * priv = ctl - > privData ;
2015-10-12 18:07:21 +03:00
2015-12-10 15:46:45 +03:00
priv - > conn = virAdmConnectOpen ( ctl - > connname , flags ) ;
2015-10-12 18:07:21 +03:00
2015-12-10 15:46:45 +03:00
if ( ! priv - > conn ) {
2024-02-01 12:40:41 +03:00
if ( ! ctl - > connname )
vshPrintExtra ( ctl , " %s " , _ ( " NOTE: Connecting to default daemon. Specify daemon using '-c' (e.g. virtqemud:///system) \n " ) ) ;
2015-10-12 18:07:21 +03:00
if ( priv - > wantReconnect )
vshError ( ctl , " %s " , _ ( " Failed to reconnect to the admin server " ) ) ;
else
vshError ( ctl , " %s " , _ ( " Failed to connect to the admin server " ) ) ;
return - 1 ;
} else {
2015-12-10 15:46:45 +03:00
if ( virAdmConnectRegisterCloseCallback ( priv - > conn , vshAdmCatchDisconnect ,
2024-03-19 14:02:51 +03:00
ctl , NULL ) < 0 )
2015-10-12 18:10:57 +03:00
vshError ( ctl , " %s " , _ ( " Unable to register disconnect callback " ) ) ;
2015-10-12 18:07:21 +03:00
if ( priv - > wantReconnect )
vshPrint ( ctl , " %s \n " , _ ( " Reconnected to the admin server " ) ) ;
2023-12-14 19:18:39 +03:00
if ( ! ctl - > connname )
ctl - > connname = virAdmConnectGetURI ( priv - > conn ) ;
2015-10-12 18:07:21 +03:00
}
return 0 ;
}
static int
vshAdmDisconnect ( vshControl * ctl )
{
int ret = 0 ;
2021-03-11 10:16:13 +03:00
vshAdmControl * priv = ctl - > privData ;
2015-10-12 18:07:21 +03:00
2015-12-10 15:46:45 +03:00
if ( ! priv - > conn )
2015-10-12 18:07:21 +03:00
return ret ;
2015-12-10 15:46:45 +03:00
virAdmConnectUnregisterCloseCallback ( priv - > conn , vshAdmCatchDisconnect ) ;
ret = virAdmConnectClose ( priv - > conn ) ;
2015-10-12 18:07:21 +03:00
if ( ret < 0 )
vshError ( ctl , " %s " , _ ( " Failed to disconnect from the admin server " ) ) ;
else if ( ret > 0 )
2023-08-24 18:04:34 +03:00
vshError ( ctl , " %s " , _ ( " One or more references were leaked after disconnect from the hypervisor " ) ) ;
2015-12-10 15:46:45 +03:00
priv - > conn = NULL ;
2015-10-12 18:07:21 +03:00
return ret ;
}
/*
* vshAdmReconnect :
*
* Reconnect to a daemon ' s admin server
*
*/
static void
vshAdmReconnect ( vshControl * ctl )
{
2021-03-11 10:16:13 +03:00
vshAdmControl * priv = ctl - > privData ;
2015-12-10 15:46:45 +03:00
if ( priv - > conn )
2015-10-12 18:07:21 +03:00
priv - > wantReconnect = true ;
vshAdmDisconnect ( ctl ) ;
2015-12-10 15:46:45 +03:00
vshAdmConnect ( ctl , 0 ) ;
2015-10-12 18:07:21 +03:00
priv - > wantReconnect = false ;
}
2015-10-12 17:07:52 +03:00
/*
* ' uri ' command
*/
2024-03-04 15:21:50 +03:00
static const vshCmdInfo info_uri = {
. help = N_ ( " print the admin server URI " ) ,
. desc = " " ,
2015-10-12 17:07:52 +03:00
} ;
static bool
2019-10-14 15:44:29 +03:00
cmdURI ( vshControl * ctl , const vshCmd * cmd G_GNUC_UNUSED )
2015-10-12 17:07:52 +03:00
{
2023-02-01 18:08:22 +03:00
g_autofree char * uri = NULL ;
2021-03-11 10:16:13 +03:00
vshAdmControl * priv = ctl - > privData ;
2015-10-12 17:07:52 +03:00
2015-12-10 15:46:45 +03:00
uri = virAdmConnectGetURI ( priv - > conn ) ;
2015-10-12 17:07:52 +03:00
if ( ! uri ) {
vshError ( ctl , " %s " , _ ( " failed to get URI " ) ) ;
return false ;
}
vshPrint ( ctl , " %s \n " , uri ) ;
return true ;
}
2015-10-05 18:17:51 +03:00
/*
* " version " command
*/
2024-03-04 15:21:50 +03:00
static const vshCmdInfo info_version = {
. help = N_ ( " show version " ) ,
. desc = N_ ( " Display the system and also the daemon version information. " ) ,
2015-10-05 18:17:51 +03:00
} ;
static bool
2019-10-14 15:44:29 +03:00
cmdVersion ( vshControl * ctl , const vshCmd * cmd G_GNUC_UNUSED )
2015-10-05 18:17:51 +03:00
{
unsigned long libVersion ;
unsigned long long includeVersion ;
unsigned long long daemonVersion ;
int ret ;
unsigned int major ;
unsigned int minor ;
unsigned int rel ;
2021-03-11 10:16:13 +03:00
vshAdmControl * priv = ctl - > privData ;
2015-10-05 18:17:51 +03:00
includeVersion = LIBVIR_VERSION_NUMBER ;
major = includeVersion / 1000000 ;
includeVersion % = 1000000 ;
minor = includeVersion / 1000 ;
rel = includeVersion % 1000 ;
2023-03-09 17:54:58 +03:00
vshPrint ( ctl , _ ( " Compiled against library: libvirt %1$d.%2$d.%3$d \n " ) ,
2015-10-05 18:17:51 +03:00
major , minor , rel ) ;
ret = virGetVersion ( & libVersion , NULL , NULL ) ;
if ( ret < 0 ) {
vshError ( ctl , " %s " , _ ( " failed to get the library version " ) ) ;
return false ;
}
major = libVersion / 1000000 ;
libVersion % = 1000000 ;
minor = libVersion / 1000 ;
rel = libVersion % 1000 ;
2023-03-09 17:54:58 +03:00
vshPrint ( ctl , _ ( " Using library: libvirt %1$d.%2$d.%3$d \n " ) ,
2015-10-05 18:17:51 +03:00
major , minor , rel ) ;
2015-12-10 15:46:45 +03:00
ret = virAdmConnectGetLibVersion ( priv - > conn , & daemonVersion ) ;
2015-10-05 18:17:51 +03:00
if ( ret < 0 ) {
vshError ( ctl , " %s " , _ ( " failed to get the daemon version " ) ) ;
} else {
major = daemonVersion / 1000000 ;
daemonVersion % = 1000000 ;
minor = daemonVersion / 1000 ;
rel = daemonVersion % 1000 ;
2023-03-09 17:54:58 +03:00
vshPrint ( ctl , _ ( " Running against daemon: %1$d.%2$d.%3$d \n " ) ,
2015-10-05 18:17:51 +03:00
major , minor , rel ) ;
}
return true ;
}
2015-10-12 17:07:52 +03:00
2015-10-12 18:07:21 +03:00
/* ---------------
* Command Connect
* - - - - - - - - - - - - - - -
*/
static const vshCmdOptDef opts_connect [ ] = {
{ . name = " name " ,
. type = VSH_OT_STRING ,
. flags = VSH_OFLAG_EMPTY_OK ,
. help = N_ ( " daemon's admin server connection URI " )
} ,
{ . name = NULL }
} ;
2024-03-04 15:21:50 +03:00
static const vshCmdInfo info_connect = {
. help = N_ ( " connect to daemon's admin server " ) ,
. desc = N_ ( " Connect to a daemon's administrating server. " ) ,
2015-10-12 18:07:21 +03:00
} ;
static bool
cmdConnect ( vshControl * ctl , const vshCmd * cmd )
{
const char * name = NULL ;
2021-03-11 10:16:13 +03:00
vshAdmControl * priv = ctl - > privData ;
2016-03-10 08:34:03 +03:00
bool connected = priv - > conn ;
2015-10-12 18:07:21 +03:00
if ( vshCommandOptStringReq ( ctl , cmd , " name " , & name ) < 0 )
return false ;
2016-04-21 15:06:10 +03:00
if ( name ) {
VIR_FREE ( ctl - > connname ) ;
2019-10-18 18:24:02 +03:00
ctl - > connname = g_strdup ( name ) ;
2016-04-21 15:06:10 +03:00
}
2015-10-12 18:07:21 +03:00
vshAdmReconnect ( ctl ) ;
2016-08-09 17:11:26 +03:00
if ( ! connected & & priv - > conn )
2016-03-10 08:34:03 +03:00
vshPrint ( ctl , " %s \n " , _ ( " Connected to the admin server " ) ) ;
2015-10-12 18:07:21 +03:00
2015-12-10 15:46:45 +03:00
return ! ! priv - > conn ;
2015-10-12 18:07:21 +03:00
}
2015-11-19 18:12:50 +03:00
2020-05-13 18:31:28 +03:00
/* -------------------
* Command server - list
* - - - - - - - - - - - - - - - - - - -
2015-11-19 18:12:50 +03:00
*/
2024-03-04 15:21:50 +03:00
static const vshCmdInfo info_srv_list = {
. help = N_ ( " list available servers on a daemon " ) ,
. desc = N_ ( " List all manageable servers on a daemon. " ) ,
2015-11-19 18:12:50 +03:00
} ;
static bool
2019-10-14 15:44:29 +03:00
cmdSrvList ( vshControl * ctl , const vshCmd * cmd G_GNUC_UNUSED )
2015-11-19 18:12:50 +03:00
{
int nsrvs = 0 ;
size_t i ;
bool ret = false ;
2023-02-01 18:08:22 +03:00
g_autofree char * uri = NULL ;
2015-11-19 18:12:50 +03:00
virAdmServerPtr * srvs = NULL ;
2021-03-11 10:16:13 +03:00
vshAdmControl * priv = ctl - > privData ;
2021-08-11 16:12:02 +03:00
g_autoptr ( vshTable ) table = NULL ;
2015-11-19 18:12:50 +03:00
/* Obtain a list of available servers on the daemon */
if ( ( nsrvs = virAdmConnectListServers ( priv - > conn , & srvs , 0 ) ) < 0 ) {
uri = virAdmConnectGetURI ( priv - > conn ) ;
2023-03-09 17:54:58 +03:00
vshError ( ctl , _ ( " failed to obtain list of available servers from %1$s " ) ,
2015-11-19 18:12:50 +03:00
NULLSTR ( uri ) ) ;
goto cleanup ;
}
2018-09-21 17:17:24 +03:00
table = vshTableNew ( _ ( " Id " ) , _ ( " Name " ) , NULL ) ;
if ( ! table )
goto cleanup ;
for ( i = 0 ; i < nsrvs ; i + + ) {
2019-10-15 16:16:31 +03:00
g_autofree char * idStr = NULL ;
2019-10-22 16:26:14 +03:00
idStr = g_strdup_printf ( " %zu " , i ) ;
2018-09-21 17:17:24 +03:00
if ( vshTableRowAppend ( table ,
idStr ,
virAdmServerGetName ( srvs [ i ] ) ,
NULL ) < 0 )
goto cleanup ;
}
vshTablePrintToStdout ( table , ctl ) ;
2015-11-19 18:12:50 +03:00
ret = true ;
cleanup :
if ( srvs ) {
for ( i = 0 ; i < nsrvs ; i + + )
virAdmServerFree ( srvs [ i ] ) ;
VIR_FREE ( srvs ) ;
}
return ret ;
}
2016-02-17 11:55:19 +03:00
2020-05-13 18:31:28 +03:00
/* ------------------------------
* Command server - threadpool - info
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2016-02-17 11:55:19 +03:00
*/
2024-03-04 15:21:50 +03:00
static const vshCmdInfo info_srv_threadpool_info = {
. help = N_ ( " get server workerpool parameters " ) ,
. desc = N_ ( " Retrieve threadpool attributes from a server. " ) ,
2016-02-17 11:55:19 +03:00
} ;
static const vshCmdOptDef opts_srv_threadpool_info [ ] = {
{ . name = " server " ,
2024-03-05 18:07:36 +03:00
. type = VSH_OT_STRING ,
2024-03-05 17:07:47 +03:00
. positional = true ,
. required = true ,
2017-11-07 11:33:06 +03:00
. completer = vshAdmServerCompleter ,
2016-02-17 11:55:19 +03:00
. help = N_ ( " Server to retrieve threadpool attributes from. " ) ,
} ,
{ . name = NULL }
} ;
static bool
cmdSrvThreadpoolInfo ( vshControl * ctl , const vshCmd * cmd )
{
bool ret = false ;
virTypedParameterPtr params = NULL ;
int nparams = 0 ;
size_t i ;
const char * srvname = NULL ;
virAdmServerPtr srv = NULL ;
2021-03-11 10:16:13 +03:00
vshAdmControl * priv = ctl - > privData ;
2016-02-17 11:55:19 +03:00
if ( vshCommandOptStringReq ( ctl , cmd , " server " , & srvname ) < 0 )
return false ;
if ( ! ( srv = virAdmConnectLookupServer ( priv - > conn , srvname , 0 ) ) )
goto cleanup ;
if ( virAdmServerGetThreadPoolParameters ( srv , & params ,
& nparams , 0 ) < 0 ) {
vshError ( ctl , " %s " ,
_ ( " Unable to get server workerpool parameters " ) ) ;
goto cleanup ;
}
for ( i = 0 ; i < nparams ; i + + )
2016-07-18 11:45:17 +03:00
vshPrint ( ctl , " %-15s: %u \n " , params [ i ] . field , params [ i ] . value . ui ) ;
2016-02-17 11:55:19 +03:00
ret = true ;
cleanup :
virTypedParamsFree ( params , nparams ) ;
if ( srv )
virAdmServerFree ( srv ) ;
return ret ;
}
2020-05-13 18:31:28 +03:00
/* -----------------------------
* Command server - threadpool - set
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2016-02-17 11:55:19 +03:00
*/
2024-03-04 15:21:50 +03:00
static const vshCmdInfo info_srv_threadpool_set = {
. help = N_ ( " set server workerpool parameters " ) ,
. desc = N_ ( " Tune threadpool attributes on a server. See OPTIONS for "
" currently supported attributes. " ) ,
2016-02-17 11:55:19 +03:00
} ;
static const vshCmdOptDef opts_srv_threadpool_set [ ] = {
{ . name = " server " ,
2024-03-05 18:07:36 +03:00
. type = VSH_OT_STRING ,
2024-03-05 17:07:47 +03:00
. positional = true ,
. required = true ,
2017-11-07 11:33:06 +03:00
. completer = vshAdmServerCompleter ,
2016-02-17 11:55:19 +03:00
. help = N_ ( " Server to alter threadpool attributes on. " ) ,
} ,
{ . name = " min-workers " ,
. type = VSH_OT_INT ,
. help = N_ ( " Change bottom limit to number of workers. " ) ,
} ,
{ . name = " max-workers " ,
. type = VSH_OT_INT ,
. help = N_ ( " Change upper limit to number of workers. " ) ,
} ,
{ . name = " priority-workers " ,
. type = VSH_OT_INT ,
. help = N_ ( " Change the current number of priority workers " ) ,
} ,
{ . name = NULL }
} ;
static bool
cmdSrvThreadpoolSet ( vshControl * ctl , const vshCmd * cmd )
{
bool ret = false ;
int rv = 0 ;
unsigned int val , min , max ;
int maxparams = 0 ;
int nparams = 0 ;
const char * srvname = NULL ;
virTypedParameterPtr params = NULL ;
virAdmServerPtr srv = NULL ;
2021-03-11 10:16:13 +03:00
vshAdmControl * priv = ctl - > privData ;
2016-02-17 11:55:19 +03:00
if ( vshCommandOptStringReq ( ctl , cmd , " server " , & srvname ) < 0 )
return false ;
2017-11-03 15:09:47 +03:00
# define PARSE_CMD_TYPED_PARAM(NAME, FIELD) \
if ( ( rv = vshCommandOptUInt ( ctl , cmd , NAME , & val ) ) < 0 ) { \
2023-03-09 17:54:58 +03:00
vshError ( ctl , _ ( " Unable to parse integer parameter '%1$s' " ) , NAME ) ; \
2017-11-03 15:09:47 +03:00
goto cleanup ; \
} else if ( rv > 0 ) { \
if ( virTypedParamsAddUInt ( & params , & nparams , & maxparams , \
FIELD , val ) < 0 ) \
goto save_error ; \
2016-02-17 11:55:19 +03:00
}
PARSE_CMD_TYPED_PARAM ( " max-workers " , VIR_THREADPOOL_WORKERS_MAX ) ;
PARSE_CMD_TYPED_PARAM ( " min-workers " , VIR_THREADPOOL_WORKERS_MIN ) ;
PARSE_CMD_TYPED_PARAM ( " priority-workers " , VIR_THREADPOOL_WORKERS_PRIORITY ) ;
# undef PARSE_CMD_TYPED_PARAM
if ( ! nparams ) {
vshError ( ctl , " %s " ,
2023-08-24 18:04:34 +03:00
_ ( " At least one of options --min-workers, --max-workers, --priority-workers is mandatory " ) ) ;
2016-02-17 11:55:19 +03:00
goto cleanup ;
}
if ( virTypedParamsGetUInt ( params , nparams ,
VIR_THREADPOOL_WORKERS_MAX , & max ) & &
virTypedParamsGetUInt ( params , nparams ,
VIR_THREADPOOL_WORKERS_MIN , & min ) & & min > max ) {
2023-08-24 18:04:34 +03:00
vshError ( ctl , " %s " , _ ( " --min-workers must be less than or equal to --max-workers " ) ) ;
2016-02-17 11:55:19 +03:00
goto cleanup ;
}
if ( ! ( srv = virAdmConnectLookupServer ( priv - > conn , srvname , 0 ) ) )
goto cleanup ;
if ( virAdmServerSetThreadPoolParameters ( srv , params ,
nparams , 0 ) < 0 )
goto error ;
ret = true ;
cleanup :
virTypedParamsFree ( params , nparams ) ;
if ( srv )
virAdmServerFree ( srv ) ;
return ret ;
save_error :
vshSaveLibvirtError ( ) ;
error :
vshError ( ctl , " %s " , _ ( " Unable to change server workerpool parameters " ) ) ;
goto cleanup ;
}
2020-05-13 18:31:28 +03:00
/* ---------------------------
* Command server - clients - list
* - - - - - - - - - - - - - - - - - - - - - - - - - - -
2016-04-16 10:13:21 +03:00
*/
2024-03-04 15:21:50 +03:00
static const vshCmdInfo info_srv_clients_list = {
. help = N_ ( " list clients connected to <server> " ) ,
. desc = N_ ( " List all manageable clients connected to <server>. " ) ,
2016-04-16 10:13:21 +03:00
} ;
static const vshCmdOptDef opts_srv_clients_list [ ] = {
{ . name = " server " ,
2024-03-05 18:07:36 +03:00
. type = VSH_OT_STRING ,
2024-03-05 17:07:47 +03:00
. positional = true ,
. required = true ,
2017-11-07 11:33:06 +03:00
. completer = vshAdmServerCompleter ,
2016-04-16 10:13:21 +03:00
. help = N_ ( " server which to list connected clients from " ) ,
} ,
{ . name = NULL }
} ;
static bool
cmdSrvClientsList ( vshControl * ctl , const vshCmd * cmd )
{
int nclts = 0 ;
size_t i ;
bool ret = false ;
const char * srvname = NULL ;
unsigned long long id ;
virClientTransport transport ;
virAdmServerPtr srv = NULL ;
virAdmClientPtr * clts = NULL ;
2021-03-11 10:16:13 +03:00
vshAdmControl * priv = ctl - > privData ;
2021-08-11 16:12:02 +03:00
g_autoptr ( vshTable ) table = NULL ;
2016-04-16 10:13:21 +03:00
if ( vshCommandOptStringReq ( ctl , cmd , " server " , & srvname ) < 0 )
return false ;
if ( ! ( srv = virAdmConnectLookupServer ( priv - > conn , srvname , 0 ) ) )
goto cleanup ;
/* Obtain a list of clients connected to server @srv */
if ( ( nclts = virAdmServerListClients ( srv , & clts , 0 ) ) < 0 ) {
2023-03-09 17:54:58 +03:00
vshError ( ctl , _ ( " failed to obtain list of connected clients from server '%1$s' " ) ,
virAdmServerGetName ( srv ) ) ;
2016-04-16 10:13:21 +03:00
goto cleanup ;
}
2018-12-04 20:08:14 +03:00
table = vshTableNew ( _ ( " Id " ) , _ ( " Transport " ) , _ ( " Connected since " ) , NULL ) ;
2018-09-21 17:17:24 +03:00
if ( ! table )
goto cleanup ;
2016-04-16 10:13:21 +03:00
for ( i = 0 ; i < nclts ; i + + ) {
2020-01-09 17:07:15 +03:00
g_autoptr ( GDateTime ) then = NULL ;
g_autofree gchar * thenstr = NULL ;
2019-10-15 16:16:31 +03:00
g_autofree char * idStr = NULL ;
2016-04-16 10:13:21 +03:00
virAdmClientPtr client = clts [ i ] ;
id = virAdmClientGetID ( client ) ;
2020-01-09 17:07:15 +03:00
then = g_date_time_new_from_unix_local ( virAdmClientGetTimestamp ( client ) ) ;
2016-04-16 10:13:21 +03:00
transport = virAdmClientGetTransport ( client ) ;
2020-01-09 17:07:15 +03:00
thenstr = g_date_time_format ( then , " %Y-%m-%d %H:%M:%S%z " ) ;
2019-10-22 16:26:14 +03:00
idStr = g_strdup_printf ( " %llu " , id ) ;
2018-09-21 17:17:24 +03:00
if ( vshTableRowAppend ( table , idStr ,
vshAdmClientTransportToString ( transport ) ,
2020-01-09 17:07:15 +03:00
thenstr , NULL ) < 0 )
2018-09-21 17:17:24 +03:00
goto cleanup ;
2016-04-16 10:13:21 +03:00
}
2018-09-21 17:17:24 +03:00
vshTablePrintToStdout ( table , ctl ) ;
2016-04-16 10:13:21 +03:00
ret = true ;
cleanup :
if ( clts ) {
for ( i = 0 ; i < nclts ; i + + )
virAdmClientFree ( clts [ i ] ) ;
VIR_FREE ( clts ) ;
}
virAdmServerFree ( srv ) ;
return ret ;
}
2016-04-22 14:12:01 +03:00
/* -------------------
* Command client - info
* - - - - - - - - - - - - - - - - - - -
*/
2024-03-04 15:21:50 +03:00
static const vshCmdInfo info_client_info = {
. help = N_ ( " retrieve client's identity info from server " ) ,
. desc = N_ ( " Retrieve identity details about <client> from <server> " ) ,
2016-04-22 14:12:01 +03:00
} ;
static const vshCmdOptDef opts_client_info [ ] = {
{ . name = " server " ,
2024-03-05 18:07:36 +03:00
. type = VSH_OT_STRING ,
2024-03-05 17:07:47 +03:00
. positional = true ,
. required = true ,
2017-11-07 11:33:06 +03:00
. completer = vshAdmServerCompleter ,
2016-04-22 14:12:01 +03:00
. help = N_ ( " server to which <client> is connected to " ) ,
} ,
{ . name = " client " ,
2024-03-05 18:07:36 +03:00
. type = VSH_OT_STRING ,
2024-03-05 17:07:47 +03:00
. positional = true ,
. required = true ,
2016-04-22 14:12:01 +03:00
. help = N_ ( " client which to retrieve identity information for " ) ,
} ,
{ . name = NULL }
} ;
static bool
cmdClientInfo ( vshControl * ctl , const vshCmd * cmd )
{
bool ret = false ;
size_t i ;
unsigned long long id ;
const char * srvname = NULL ;
2020-01-09 17:07:15 +03:00
g_autoptr ( GDateTime ) then = NULL ;
g_autofree gchar * thenstr = NULL ;
2016-04-22 14:12:01 +03:00
virAdmServerPtr srv = NULL ;
virAdmClientPtr clnt = NULL ;
virTypedParameterPtr params = NULL ;
int nparams = 0 ;
2021-03-11 10:16:13 +03:00
vshAdmControl * priv = ctl - > privData ;
2016-04-22 14:12:01 +03:00
if ( vshCommandOptULongLong ( ctl , cmd , " client " , & id ) < 0 )
return false ;
if ( vshCommandOptStringReq ( ctl , cmd , " server " , & srvname ) < 0 )
return false ;
if ( ! ( srv = virAdmConnectLookupServer ( priv - > conn , srvname , 0 ) ) | |
! ( clnt = virAdmServerLookupClient ( srv , id , 0 ) ) )
goto cleanup ;
/* Retrieve client identity info */
if ( virAdmClientGetInfo ( clnt , & params , & nparams , 0 ) < 0 ) {
2023-03-09 17:54:58 +03:00
vshError ( ctl , _ ( " failed to retrieve client identity information for client '%1$llu' connected to server '%2$s' " ) ,
2016-04-22 14:12:01 +03:00
id , virAdmServerGetName ( srv ) ) ;
goto cleanup ;
}
2020-01-09 17:07:15 +03:00
then = g_date_time_new_from_unix_local ( virAdmClientGetTimestamp ( clnt ) ) ;
thenstr = g_date_time_format ( then , " %Y-%m-%d %H:%M:%S%z " ) ;
2016-04-22 14:12:01 +03:00
/* this info is provided by the client object itself */
vshPrint ( ctl , " %-15s: %llu \n " , " id " , virAdmClientGetID ( clnt ) ) ;
2020-01-09 17:07:15 +03:00
vshPrint ( ctl , " %-15s: %s \n " , " connection_time " , thenstr ) ;
2016-04-22 14:12:01 +03:00
vshPrint ( ctl , " %-15s: %s \n " , " transport " ,
vshAdmClientTransportToString ( virAdmClientGetTransport ( clnt ) ) ) ;
for ( i = 0 ; i < nparams ; i + + ) {
2023-02-01 18:08:22 +03:00
g_autofree char * str = vshGetTypedParamValue ( ctl , & params [ i ] ) ;
2016-04-22 14:12:01 +03:00
vshPrint ( ctl , " %-15s: %s \n " , params [ i ] . field , str ) ;
}
ret = true ;
cleanup :
virTypedParamsFree ( params , nparams ) ;
virAdmServerFree ( srv ) ;
virAdmClientFree ( clnt ) ;
return ret ;
}
2016-04-28 11:38:32 +03:00
/* -------------------------
* Command client - disconnect
* - - - - - - - - - - - - - - - - - - - - - - - - -
*/
2024-03-04 15:21:50 +03:00
static const vshCmdInfo info_client_disconnect = {
. help = N_ ( " force disconnect a client from the given server " ) ,
. desc = N_ ( " Force close a specific client's connection to the given "
" server. " ) ,
2016-04-28 11:38:32 +03:00
} ;
static const vshCmdOptDef opts_client_disconnect [ ] = {
{ . name = " server " ,
2024-03-05 18:07:36 +03:00
. type = VSH_OT_STRING ,
2024-03-05 17:07:47 +03:00
. positional = true ,
. required = true ,
2017-11-07 11:33:06 +03:00
. completer = vshAdmServerCompleter ,
2016-04-28 11:38:32 +03:00
. help = N_ ( " server which the client is currently connected to " ) ,
} ,
{ . name = " client " ,
. type = VSH_OT_INT ,
2024-03-05 17:07:47 +03:00
. positional = true ,
. required = true ,
2016-04-28 11:38:32 +03:00
. help = N_ ( " client which to disconnect, specified by ID " ) ,
} ,
{ . name = NULL }
} ;
static bool
cmdClientDisconnect ( vshControl * ctl , const vshCmd * cmd )
{
bool ret = false ;
const char * srvname = NULL ;
unsigned long long id = 0 ;
virAdmServerPtr srv = NULL ;
virAdmClientPtr client = NULL ;
2021-03-11 10:16:13 +03:00
vshAdmControl * priv = ctl - > privData ;
2016-04-28 11:38:32 +03:00
if ( vshCommandOptStringReq ( ctl , cmd , " server " , & srvname ) < 0 )
return false ;
if ( vshCommandOptULongLongWrap ( ctl , cmd , " client " , & id ) < 0 )
return false ;
if ( ! ( srv = virAdmConnectLookupServer ( priv - > conn , srvname , 0 ) ) )
goto cleanup ;
if ( ! ( client = virAdmServerLookupClient ( srv , id , 0 ) ) )
goto cleanup ;
if ( virAdmClientClose ( client , 0 ) < 0 ) {
2023-03-09 17:54:58 +03:00
vshError ( ctl , _ ( " Failed to disconnect client '%1$llu' from server %2$s " ) ,
2016-04-28 11:38:32 +03:00
id , virAdmServerGetName ( srv ) ) ;
goto cleanup ;
}
2023-03-09 17:54:58 +03:00
vshPrint ( ctl , _ ( " Client '%1$llu' disconnected " ) , id ) ;
2016-04-28 11:38:32 +03:00
ret = true ;
cleanup :
virAdmClientFree ( client ) ;
virAdmServerFree ( srv ) ;
return ret ;
}
2020-05-13 18:31:28 +03:00
/* ---------------------------
* Command server - clients - info
* - - - - - - - - - - - - - - - - - - - - - - - - - - -
2016-04-09 19:49:44 +03:00
*/
2024-03-04 15:21:50 +03:00
static const vshCmdInfo info_srv_clients_info = {
. help = N_ ( " get server's client-related configuration limits " ) ,
. desc = N_ ( " Retrieve server's client-related configuration limits " ) ,
2016-04-09 19:49:44 +03:00
} ;
static const vshCmdOptDef opts_srv_clients_info [ ] = {
{ . name = " server " ,
2024-03-05 18:07:36 +03:00
. type = VSH_OT_STRING ,
2024-03-05 17:07:47 +03:00
. positional = true ,
. required = true ,
2017-11-07 11:33:06 +03:00
. completer = vshAdmServerCompleter ,
2016-04-09 19:49:44 +03:00
. help = N_ ( " Server to retrieve the client limits from. " ) ,
} ,
{ . name = NULL }
} ;
static bool
cmdSrvClientsInfo ( vshControl * ctl , const vshCmd * cmd )
{
bool ret = false ;
virTypedParameterPtr params = NULL ;
int nparams = 0 ;
size_t i ;
const char * srvname = NULL ;
virAdmServerPtr srv = NULL ;
2021-03-11 10:16:13 +03:00
vshAdmControl * priv = ctl - > privData ;
2016-04-09 19:49:44 +03:00
if ( vshCommandOptStringReq ( ctl , cmd , " server " , & srvname ) < 0 )
return false ;
if ( ! ( srv = virAdmConnectLookupServer ( priv - > conn , srvname , 0 ) ) )
goto cleanup ;
if ( virAdmServerGetClientLimits ( srv , & params , & nparams , 0 ) < 0 ) {
2023-08-24 18:04:34 +03:00
vshError ( ctl , " %s " , _ ( " Unable to retrieve client limits from server's configuration " ) ) ;
2016-04-09 19:49:44 +03:00
goto cleanup ;
}
for ( i = 0 ; i < nparams ; i + + )
2016-09-05 14:51:21 +03:00
vshPrint ( ctl , " %-20s: %u \n " , params [ i ] . field , params [ i ] . value . ui ) ;
2016-04-09 19:49:44 +03:00
ret = true ;
cleanup :
virTypedParamsFree ( params , nparams ) ;
virAdmServerFree ( srv ) ;
return ret ;
}
2020-05-13 18:31:28 +03:00
/* --------------------------
* Command server - clients - set
* - - - - - - - - - - - - - - - - - - - - - - - - - -
2016-04-09 19:49:44 +03:00
*/
2024-03-04 15:21:50 +03:00
static const vshCmdInfo info_srv_clients_set = {
. help = N_ ( " set server's client-related configuration limits " ) ,
. desc = N_ ( " Tune server's client-related configuration limits. "
" See OPTIONS for currently supported attributes. " ) ,
2016-04-09 19:49:44 +03:00
} ;
static const vshCmdOptDef opts_srv_clients_set [ ] = {
{ . name = " server " ,
2024-03-05 18:07:36 +03:00
. type = VSH_OT_STRING ,
2024-03-05 17:07:47 +03:00
. positional = true ,
. required = true ,
2017-11-07 11:33:06 +03:00
. completer = vshAdmServerCompleter ,
2016-04-09 19:49:44 +03:00
. help = N_ ( " Server to alter the client-related configuration limits on. " ) ,
} ,
{ . name = " max-clients " ,
. type = VSH_OT_INT ,
. help = N_ ( " Change the upper limit to overall number of clients "
" connected to the server. " ) ,
} ,
{ . name = " max-unauth-clients " ,
. type = VSH_OT_INT ,
. help = N_ ( " Change the upper limit to number of clients waiting for "
" authentication to be connected to the server " ) ,
} ,
{ . name = NULL }
} ;
static bool
cmdSrvClientsSet ( vshControl * ctl , const vshCmd * cmd )
{
bool ret = false ;
int rv = 0 ;
unsigned int val , max , unauth_max ;
int maxparams = 0 ;
int nparams = 0 ;
const char * srvname = NULL ;
virAdmServerPtr srv = NULL ;
virTypedParameterPtr params = NULL ;
2021-03-11 10:16:13 +03:00
vshAdmControl * priv = ctl - > privData ;
2016-04-09 19:49:44 +03:00
if ( vshCommandOptStringReq ( ctl , cmd , " server " , & srvname ) < 0 )
return false ;
2017-11-03 15:09:47 +03:00
# define PARSE_CMD_TYPED_PARAM(NAME, FIELD) \
if ( ( rv = vshCommandOptUInt ( ctl , cmd , NAME , & val ) ) < 0 ) { \
2023-03-09 17:54:58 +03:00
vshError ( ctl , _ ( " Unable to parse integer parameter '%1$s' " ) , NAME ) ; \
2017-11-03 15:09:47 +03:00
goto cleanup ; \
} else if ( rv > 0 ) { \
if ( virTypedParamsAddUInt ( & params , & nparams , & maxparams , \
FIELD , val ) < 0 ) \
goto save_error ; \
2016-04-09 19:49:44 +03:00
}
PARSE_CMD_TYPED_PARAM ( " max-clients " , VIR_SERVER_CLIENTS_MAX ) ;
PARSE_CMD_TYPED_PARAM ( " max-unauth-clients " , VIR_SERVER_CLIENTS_UNAUTH_MAX ) ;
# undef PARSE_CMD_TYPED_PARAM
if ( ! nparams ) {
2023-08-24 18:04:34 +03:00
vshError ( ctl , " %s " , _ ( " At least one of options --max-clients, --max-unauth-clients is mandatory " ) ) ;
2016-04-09 19:49:44 +03:00
goto cleanup ;
}
if ( virTypedParamsGetUInt ( params , nparams ,
VIR_SERVER_CLIENTS_MAX , & max ) & &
virTypedParamsGetUInt ( params , nparams ,
VIR_SERVER_CLIENTS_UNAUTH_MAX , & unauth_max ) & &
unauth_max > max ) {
2023-08-24 18:04:34 +03:00
vshError ( ctl , " %s " , _ ( " --max-unauth-clients must be less than or equal to --max-clients " ) ) ;
2016-04-09 19:49:44 +03:00
goto cleanup ;
}
if ( ! ( srv = virAdmConnectLookupServer ( priv - > conn , srvname , 0 ) ) )
goto cleanup ;
if ( virAdmServerSetClientLimits ( srv , params , nparams , 0 ) < 0 )
goto error ;
ret = true ;
cleanup :
virTypedParamsFree ( params , nparams ) ;
virAdmServerFree ( srv ) ;
return ret ;
save_error :
vshSaveLibvirtError ( ) ;
error :
2023-08-24 18:04:34 +03:00
vshError ( ctl , " %s " , _ ( " Unable to change server's client-related configuration limits " ) ) ;
2016-04-09 19:49:44 +03:00
goto cleanup ;
}
2020-05-13 18:31:28 +03:00
/* --------------------------
* Command server - update - tls
* - - - - - - - - - - - - - - - - - - - - - - - - - -
2020-03-07 14:31:03 +03:00
*/
2024-03-04 15:21:50 +03:00
static const vshCmdInfo info_srv_update_tls_file = {
. help = N_ ( " notify server to update TLS related files online. " ) ,
. desc = N_ ( " notify server to update the CA cert, "
2020-03-07 14:31:03 +03:00
" CA CRL, server cert / key without restarts. "
2024-03-04 15:21:50 +03:00
" See OPTIONS for currently supported attributes. " ) ,
2020-03-07 14:31:03 +03:00
} ;
static const vshCmdOptDef opts_srv_update_tls_file [ ] = {
{ . name = " server " ,
2024-03-05 18:07:36 +03:00
. type = VSH_OT_STRING ,
2024-03-05 17:07:47 +03:00
. positional = true ,
. required = true ,
2020-03-07 14:31:03 +03:00
. help = N_ ( " Available servers on a daemon. "
2020-05-12 12:49:10 +03:00
" Currently only supports 'libvirtd' or 'virtproxyd'. " )
2020-03-07 14:31:03 +03:00
} ,
{ . name = NULL }
} ;
static bool
cmdSrvUpdateTlsFiles ( vshControl * ctl , const vshCmd * cmd )
{
bool ret = false ;
const char * srvname = NULL ;
virAdmServerPtr srv = NULL ;
2021-03-11 10:16:13 +03:00
vshAdmControl * priv = ctl - > privData ;
2020-03-07 14:31:03 +03:00
if ( vshCommandOptStringReq ( ctl , cmd , " server " , & srvname ) < 0 )
return false ;
if ( ! ( srv = virAdmConnectLookupServer ( priv - > conn , srvname , 0 ) ) )
goto cleanup ;
if ( virAdmServerUpdateTlsFiles ( srv , 0 ) < 0 ) {
vshError ( ctl , " %s " , _ ( " Unable to update server's tls related files. " ) ) ;
goto cleanup ;
}
ret = true ;
vshPrint ( ctl , " update tls related files succeed \n " ) ;
cleanup :
virAdmServerFree ( srv ) ;
return ret ;
}
2016-03-09 17:12:55 +03:00
/* --------------------------
* Command daemon - log - filters
* - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
2024-03-04 15:21:50 +03:00
static const vshCmdInfo info_daemon_log_filters = {
. help = N_ ( " fetch or set the currently defined set of logging filters on "
" daemon " ) ,
. desc = N_ ( " Depending on whether run with or without options, the command "
2016-03-09 17:12:55 +03:00
" fetches or redefines the existing active set of filters on "
2024-03-04 15:21:50 +03:00
" daemon. " ) ,
2016-03-09 17:12:55 +03:00
} ;
static const vshCmdOptDef opts_daemon_log_filters [ ] = {
{ . name = " filters " ,
. type = VSH_OT_STRING ,
. help = N_ ( " redefine the existing set of logging filters " ) ,
. flags = VSH_OFLAG_EMPTY_OK
} ,
{ . name = NULL }
} ;
static bool
cmdDaemonLogFilters ( vshControl * ctl , const vshCmd * cmd )
{
2021-03-11 10:16:13 +03:00
vshAdmControl * priv = ctl - > privData ;
2016-03-09 17:12:55 +03:00
if ( vshCommandOptBool ( cmd , " filters " ) ) {
2020-08-03 00:35:16 +03:00
const char * filters = NULL ;
if ( ( vshCommandOptStringReq ( ctl , cmd , " filters " , & filters ) < 0 | |
2016-03-09 17:12:55 +03:00
virAdmConnectSetLoggingFilters ( priv - > conn , filters , 0 ) < 0 ) ) {
vshError ( ctl , _ ( " Unable to change daemon logging settings " ) ) ;
return false ;
}
} else {
2020-08-03 00:35:16 +03:00
g_autofree char * filters = NULL ;
2020-08-03 00:33:07 +03:00
if ( virAdmConnectGetLoggingFilters ( priv - > conn ,
& filters , 0 ) < 0 ) {
2016-03-09 17:12:55 +03:00
vshError ( ctl , _ ( " Unable to get daemon logging filters information " ) ) ;
return false ;
}
vshPrintExtra ( ctl , " %-15s " , _ ( " Logging filters: " ) ) ;
2019-02-12 19:25:06 +03:00
vshPrint ( ctl , " %s \n " , NULLSTR_EMPTY ( filters ) ) ;
2016-03-09 17:12:55 +03:00
}
return true ;
}
/* --------------------------
* Command daemon - log - outputs
* - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
2024-03-04 15:21:50 +03:00
static const vshCmdInfo info_daemon_log_outputs = {
. help = N_ ( " fetch or set the currently defined set of logging outputs on "
" daemon " ) ,
. desc = N_ ( " Depending on whether run with or without options, the command "
2016-03-09 17:12:55 +03:00
" fetches or redefines the existing active set of outputs on "
2024-03-04 15:21:50 +03:00
" daemon. " ) ,
2016-03-09 17:12:55 +03:00
} ;
2022-06-13 16:27:27 +03:00
static const vshCmdOptDef opts_daemon_timeout [ ] = {
{ . name = " timeout " ,
. type = VSH_OT_INT ,
2024-03-05 17:07:47 +03:00
. required = true ,
2022-06-13 16:27:27 +03:00
. help = N_ ( " number of seconds the daemon will run without any active connection " ) ,
2024-03-05 19:21:05 +03:00
. flags = VSH_OFLAG_REQ_OPT
2022-06-13 16:27:27 +03:00
} ,
{ . name = NULL }
} ;
static bool
cmdDaemonTimeout ( vshControl * ctl , const vshCmd * cmd )
{
vshAdmControl * priv = ctl - > privData ;
unsigned int timeout = 0 ;
if ( vshCommandOptUInt ( ctl , cmd , " timeout " , & timeout ) < 0 )
return false ;
if ( virAdmConnectSetDaemonTimeout ( priv - > conn , timeout , 0 ) < 0 )
return false ;
return true ;
}
/* --------------------------
* Command daemon - timeout
* - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
2024-03-04 15:21:50 +03:00
static const vshCmdInfo info_daemon_timeout = {
. help = N_ ( " set the auto shutdown timeout of the daemon " ) ,
. desc = N_ ( " set the auto shutdown timeout of the daemon " ) ,
2022-06-13 16:27:27 +03:00
} ;
2016-03-09 17:12:55 +03:00
static const vshCmdOptDef opts_daemon_log_outputs [ ] = {
{ . name = " outputs " ,
. type = VSH_OT_STRING ,
. help = N_ ( " redefine the existing set of logging outputs " ) ,
. flags = VSH_OFLAG_EMPTY_OK
} ,
{ . name = NULL }
} ;
static bool
cmdDaemonLogOutputs ( vshControl * ctl , const vshCmd * cmd )
{
2021-03-11 10:16:13 +03:00
vshAdmControl * priv = ctl - > privData ;
2016-03-09 17:12:55 +03:00
if ( vshCommandOptBool ( cmd , " outputs " ) ) {
2020-08-03 00:35:16 +03:00
const char * outputs = NULL ;
if ( ( vshCommandOptStringReq ( ctl , cmd , " outputs " , & outputs ) < 0 | |
2016-03-09 17:12:55 +03:00
virAdmConnectSetLoggingOutputs ( priv - > conn , outputs , 0 ) < 0 ) ) {
vshError ( ctl , _ ( " Unable to change daemon logging settings " ) ) ;
return false ;
}
} else {
2020-08-03 00:35:16 +03:00
g_autofree char * outputs = NULL ;
2020-08-03 00:33:07 +03:00
if ( virAdmConnectGetLoggingOutputs ( priv - > conn , & outputs , 0 ) < 0 ) {
2016-03-09 17:12:55 +03:00
vshError ( ctl , _ ( " Unable to get daemon logging outputs information " ) ) ;
return false ;
}
vshPrintExtra ( ctl , " %-15s " , _ ( " Logging outputs: " ) ) ;
2019-02-12 19:25:06 +03:00
vshPrint ( ctl , " %s \n " , NULLSTR_EMPTY ( outputs ) ) ;
2016-03-09 17:12:55 +03:00
}
return true ;
}
2015-10-12 18:07:21 +03:00
static void *
2015-12-10 15:46:45 +03:00
vshAdmConnectionHandler ( vshControl * ctl )
2015-10-12 18:07:21 +03:00
{
2021-03-11 10:16:13 +03:00
vshAdmControl * priv = ctl - > privData ;
2015-10-12 18:07:21 +03:00
2015-12-10 15:46:45 +03:00
if ( ! virAdmConnectIsAlive ( priv - > conn ) )
2015-10-12 18:07:21 +03:00
vshAdmReconnect ( ctl ) ;
2015-12-10 15:46:45 +03:00
if ( ! virAdmConnectIsAlive ( priv - > conn ) ) {
2015-10-12 18:07:21 +03:00
vshError ( ctl , " %s " , _ ( " no valid connection " ) ) ;
return NULL ;
}
2015-12-10 15:46:45 +03:00
return priv - > conn ;
2015-10-12 18:07:21 +03:00
}
/*
* Initialize connection .
*/
static bool
vshAdmInit ( vshControl * ctl )
{
2021-03-11 10:16:13 +03:00
vshAdmControl * priv = ctl - > privData ;
2015-10-12 18:07:21 +03:00
/* Since we have the commandline arguments parsed, we need to
* reload our initial settings to make debugging and readline
* work properly */
vshInitReload ( ctl ) ;
2015-12-10 15:46:45 +03:00
if ( priv - > conn )
2015-10-12 18:07:21 +03:00
return false ;
/* set up the library error handler */
virSetErrorFunc ( NULL , vshErrorHandler ) ;
if ( virEventRegisterDefaultImpl ( ) < 0 )
return false ;
if ( virThreadCreate ( & ctl - > eventLoop , true , vshEventLoop , ctl ) < 0 )
return false ;
ctl - > eventLoopStarted = true ;
2015-12-10 15:46:45 +03:00
if ( ctl - > connname ) {
2015-10-12 18:07:21 +03:00
vshAdmReconnect ( ctl ) ;
/* Connecting to a named connection must succeed, but we delay
* connecting to the default connection until we need it
* ( since the first command might be ' connect ' which allows a
* non - default connection , or might be ' help ' which needs no
* connection ) .
*/
2015-12-10 15:46:45 +03:00
if ( ! priv - > conn ) {
2015-10-12 18:07:21 +03:00
vshReportError ( ctl ) ;
return false ;
}
}
return true ;
}
static void
2019-10-14 15:44:29 +03:00
vshAdmDeinitTimer ( int timer G_GNUC_UNUSED , void * opaque G_GNUC_UNUSED )
2015-10-12 18:07:21 +03:00
{
/* nothing to be done here */
}
/*
* Deinitialize virt - admin
*/
static void
vshAdmDeinit ( vshControl * ctl )
{
2021-03-11 10:16:13 +03:00
vshAdmControl * priv = ctl - > privData ;
2015-10-12 18:07:21 +03:00
vshDeinit ( ctl ) ;
2015-12-10 15:46:45 +03:00
VIR_FREE ( ctl - > connname ) ;
2015-10-12 18:07:21 +03:00
2015-12-10 15:46:45 +03:00
if ( priv - > conn )
2015-10-12 18:07:21 +03:00
vshAdmDisconnect ( ctl ) ;
virResetLastError ( ) ;
if ( ctl - > eventLoopStarted ) {
2022-02-08 16:59:30 +03:00
int timer = - 1 ;
2015-10-12 18:07:21 +03:00
2022-02-08 16:59:30 +03:00
VIR_WITH_MUTEX_LOCK_GUARD ( & ctl - > lock ) {
ctl - > quit = true ;
/* HACK: Add a dummy timeout to break event loop */
timer = virEventAddTimeout ( 0 , vshAdmDeinitTimer , NULL , NULL ) ;
}
2015-10-12 18:07:21 +03:00
virThreadJoin ( & ctl - > eventLoop ) ;
if ( timer ! = - 1 )
virEventRemoveTimeout ( timer ) ;
ctl - > eventLoopStarted = false ;
}
virMutexDestroy ( & ctl - > lock ) ;
}
/*
* Print usage
*/
static void
vshAdmUsage ( void )
{
const vshCmdGrp * grp ;
const vshCmdDef * cmd ;
2023-08-28 14:07:34 +03:00
fprintf ( stdout , _ ( " \n "
" %1$s [options]... [<command_string>] \n "
" %2$s [options]... <command> [args...] \n "
" \n "
2015-10-12 18:07:21 +03:00
" options: \n "
" -c | --connect=URI daemon admin connection URI \n "
" -d | --debug=NUM debug level [0-4] \n "
" -h | --help this help \n "
" -l | --log=FILE output logging to file \n "
" -q | --quiet quiet mode \n "
" -v short version \n "
" -V long version \n "
" --version[=TYPE] version, TYPE is short or long (default short) \n "
" commands (non interactive mode): \n \n " ) , progname ,
progname ) ;
for ( grp = cmdGroups ; grp - > name ; grp + + ) {
2023-03-09 17:54:58 +03:00
fprintf ( stdout , _ ( " %1$s (help keyword '%2$s') \n " ) ,
2015-10-12 18:07:21 +03:00
grp - > name , grp - > keyword ) ;
for ( cmd = grp - > commands ; cmd - > name ; cmd + + ) {
2024-03-02 01:14:51 +03:00
if ( cmd - > alias | |
2021-09-16 16:57:28 +03:00
cmd - > flags & VSH_CMD_FLAG_HIDDEN )
2015-10-12 18:07:21 +03:00
continue ;
fprintf ( stdout ,
2024-03-04 15:21:50 +03:00
" %-30s %s \n " , cmd - > name , _ ( cmd - > info - > help ) ) ;
2015-10-12 18:07:21 +03:00
}
fprintf ( stdout , " \n " ) ;
}
fprintf ( stdout , " %s " ,
_ ( " \n (specify help <group> for details about the commands in the group) \n " ) ) ;
fprintf ( stdout , " %s " ,
_ ( " \n (specify help <command> for details about the command) \n \n " ) ) ;
return ;
}
/*
* Show version and options compiled in
*/
static void
2019-10-14 15:44:29 +03:00
vshAdmShowVersion ( vshControl * ctl G_GNUC_UNUSED )
2015-10-12 18:07:21 +03:00
{
/* FIXME - list a copyright blurb, as in GNU programs? */
2023-03-09 17:54:58 +03:00
vshPrint ( ctl , _ ( " Virt-admin command line tool of libvirt %1$s \n " ) , VERSION ) ;
vshPrint ( ctl , _ ( " See web site at %1$s \n \n " ) , " https://libvirt.org/ " ) ;
2015-10-12 18:07:21 +03:00
vshPrint ( ctl , " %s " , _ ( " Compiled with support for: " ) ) ;
# ifdef WITH_LIBVIRTD
vshPrint ( ctl , " Daemon " ) ;
# endif
vshPrint ( ctl , " Debug " ) ;
# if WITH_READLINE
vshPrint ( ctl , " Readline " ) ;
# endif
vshPrint ( ctl , " \n " ) ;
}
static bool
vshAdmParseArgv ( vshControl * ctl , int argc , char * * argv )
{
int arg , debug ;
size_t i ;
int longindex = - 1 ;
struct option opt [ ] = {
2022-11-22 04:50:01 +03:00
{ " connect " , required_argument , NULL , ' c ' } ,
{ " debug " , required_argument , NULL , ' d ' } ,
{ " help " , no_argument , NULL , ' h ' } ,
{ " log " , required_argument , NULL , ' l ' } ,
{ " quiet " , no_argument , NULL , ' q ' } ,
{ " version " , optional_argument , NULL , ' v ' } ,
{ NULL , 0 , NULL , 0 } ,
2015-10-12 18:07:21 +03:00
} ;
/* Standard (non-command) options. The leading + ensures that no
* argument reordering takes place , so that command options are
* not confused with top - level virt - admin options . */
while ( ( arg = getopt_long ( argc , argv , " +:c:d:hl:qvV " , opt , & longindex ) ) ! = - 1 ) {
switch ( arg ) {
case ' c ' :
2015-12-10 15:46:45 +03:00
VIR_FREE ( ctl - > connname ) ;
2019-10-18 18:24:02 +03:00
ctl - > connname = g_strdup ( optarg ) ;
2015-10-12 18:07:21 +03:00
break ;
case ' d ' :
if ( virStrToLong_i ( optarg , NULL , 10 , & debug ) < 0 ) {
2023-03-09 17:54:58 +03:00
vshError ( ctl , _ ( " option %1$s takes a numeric argument " ) ,
2015-10-12 18:07:21 +03:00
longindex = = - 1 ? " -d " : " --debug " ) ;
exit ( EXIT_FAILURE ) ;
}
if ( debug < VSH_ERR_DEBUG | | debug > VSH_ERR_ERROR )
2023-03-09 17:54:58 +03:00
vshError ( ctl , _ ( " ignoring debug level %1$d out of range [%2$d-%3$d] " ) ,
2015-10-12 18:07:21 +03:00
debug , VSH_ERR_DEBUG , VSH_ERR_ERROR ) ;
else
ctl - > debug = debug ;
break ;
case ' h ' :
vshAdmUsage ( ) ;
exit ( EXIT_SUCCESS ) ;
break ;
case ' l ' :
vshCloseLogFile ( ctl ) ;
2019-10-18 18:24:02 +03:00
ctl - > logfile = g_strdup ( optarg ) ;
2015-10-12 18:07:21 +03:00
vshOpenLogFile ( ctl ) ;
break ;
case ' q ' :
ctl - > quiet = true ;
break ;
case ' v ' :
if ( STRNEQ_NULLABLE ( optarg , " long " ) ) {
puts ( VERSION ) ;
exit ( EXIT_SUCCESS ) ;
}
2019-10-15 14:38:21 +03:00
G_GNUC_FALLTHROUGH ;
2015-10-12 18:07:21 +03:00
case ' V ' :
vshAdmShowVersion ( ctl ) ;
exit ( EXIT_SUCCESS ) ;
case ' : ' :
for ( i = 0 ; opt [ i ] . name ! = NULL ; i + + ) {
if ( opt [ i ] . val = = optopt )
break ;
}
if ( opt [ i ] . name )
2023-03-09 17:54:58 +03:00
vshError ( ctl , _ ( " option '-%1$c'/'--%2$s' requires an argument " ) ,
2015-10-12 18:07:21 +03:00
optopt , opt [ i ] . name ) ;
else
2023-03-09 17:54:58 +03:00
vshError ( ctl , _ ( " option '-%1$c' requires an argument " ) , optopt ) ;
2015-10-12 18:07:21 +03:00
exit ( EXIT_FAILURE ) ;
case ' ? ' :
if ( optopt )
2023-03-09 17:54:58 +03:00
vshError ( ctl , _ ( " unsupported option '-%1$c'. See --help. " ) , optopt ) ;
2015-10-12 18:07:21 +03:00
else
2023-03-09 17:54:58 +03:00
vshError ( ctl , _ ( " unsupported option '%1$s'. See --help. " ) , argv [ optind - 1 ] ) ;
2015-10-12 18:07:21 +03:00
exit ( EXIT_FAILURE ) ;
default :
vshError ( ctl , _ ( " unknown option " ) ) ;
exit ( EXIT_FAILURE ) ;
}
longindex = - 1 ;
}
if ( argc = = optind ) {
ctl - > imode = true ;
} else {
/* parse command */
ctl - > imode = false ;
if ( argc - optind = = 1 ) {
vshDebug ( ctl , VSH_ERR_INFO , " commands: \" %s \" \n " , argv [ optind ] ) ;
2021-01-26 11:51:27 +03:00
return vshCommandStringParse ( ctl , argv [ optind ] , NULL , 0 ) ;
2015-10-12 18:07:21 +03:00
} else {
return vshCommandArgvParse ( ctl , argc - optind , argv + optind ) ;
}
}
return true ;
}
static const vshCmdDef vshAdmCmds [ ] = {
VSH_CMD_CD ,
VSH_CMD_ECHO ,
VSH_CMD_EXIT ,
VSH_CMD_HELP ,
VSH_CMD_PWD ,
VSH_CMD_QUIT ,
2016-09-14 11:08:48 +03:00
VSH_CMD_SELF_TEST ,
2017-11-01 17:34:14 +03:00
VSH_CMD_COMPLETE ,
2015-10-12 17:07:52 +03:00
{ . name = " uri " ,
. handler = cmdURI ,
. opts = NULL ,
2024-03-04 15:21:50 +03:00
. info = & info_uri ,
2015-10-12 17:07:52 +03:00
. flags = 0
} ,
2015-10-05 18:17:51 +03:00
{ . name = " version " ,
. handler = cmdVersion ,
. opts = NULL ,
2024-03-04 15:21:50 +03:00
. info = & info_version ,
2015-10-05 18:17:51 +03:00
. flags = 0
} ,
2015-10-12 18:07:21 +03:00
{ . name = " connect " ,
. handler = cmdConnect ,
. opts = opts_connect ,
2024-03-04 15:21:50 +03:00
. info = & info_connect ,
2015-10-12 18:07:21 +03:00
. flags = VSH_CMD_FLAG_NOCONNECT
} ,
{ . name = NULL }
} ;
2015-11-19 18:12:50 +03:00
static const vshCmdDef monitoringCmds [ ] = {
{ . name = " srv-list " ,
2016-09-07 18:27:52 +03:00
. alias = " server-list "
} ,
{ . name = " server-list " ,
2015-11-19 18:12:50 +03:00
. handler = cmdSrvList ,
. opts = NULL ,
2024-03-04 15:21:50 +03:00
. info = & info_srv_list ,
2015-11-19 18:12:50 +03:00
. flags = 0
} ,
2016-02-17 11:55:19 +03:00
{ . name = " srv-threadpool-info " ,
2016-09-07 18:27:52 +03:00
. alias = " server-threadpool-info "
} ,
{ . name = " server-threadpool-info " ,
2016-02-17 11:55:19 +03:00
. handler = cmdSrvThreadpoolInfo ,
. opts = opts_srv_threadpool_info ,
2024-03-04 15:21:50 +03:00
. info = & info_srv_threadpool_info ,
2016-02-17 11:55:19 +03:00
. flags = 0
} ,
2016-04-16 10:13:21 +03:00
{ . name = " srv-clients-list " ,
2016-09-07 18:27:52 +03:00
. alias = " client-list "
} ,
{ . name = " client-list " ,
2016-04-16 10:13:21 +03:00
. handler = cmdSrvClientsList ,
. opts = opts_srv_clients_list ,
2024-03-04 15:21:50 +03:00
. info = & info_srv_clients_list ,
2016-04-16 10:13:21 +03:00
. flags = 0
} ,
2016-04-22 14:12:01 +03:00
{ . name = " client-info " ,
. handler = cmdClientInfo ,
. opts = opts_client_info ,
2024-03-04 15:21:50 +03:00
. info = & info_client_info ,
2016-04-22 14:12:01 +03:00
. flags = 0
} ,
2016-04-09 19:49:44 +03:00
{ . name = " srv-clients-info " ,
2016-09-07 18:27:52 +03:00
. alias = " server-clients-info "
} ,
{ . name = " server-clients-info " ,
2016-04-09 19:49:44 +03:00
. handler = cmdSrvClientsInfo ,
. opts = opts_srv_clients_info ,
2024-03-04 15:21:50 +03:00
. info = & info_srv_clients_info ,
2016-04-09 19:49:44 +03:00
. flags = 0
} ,
2016-02-17 11:55:19 +03:00
{ . name = NULL }
} ;
static const vshCmdDef managementCmds [ ] = {
{ . name = " srv-threadpool-set " ,
2016-09-07 18:27:52 +03:00
. alias = " server-threadpool-set "
} ,
{ . name = " server-threadpool-set " ,
2016-02-17 11:55:19 +03:00
. handler = cmdSrvThreadpoolSet ,
. opts = opts_srv_threadpool_set ,
2024-03-04 15:21:50 +03:00
. info = & info_srv_threadpool_set ,
2016-02-17 11:55:19 +03:00
. flags = 0
} ,
2016-04-28 11:38:32 +03:00
{ . name = " client-disconnect " ,
. handler = cmdClientDisconnect ,
. opts = opts_client_disconnect ,
2024-03-04 15:21:50 +03:00
. info = & info_client_disconnect ,
2016-04-28 11:38:32 +03:00
. flags = 0
} ,
2016-04-09 19:49:44 +03:00
{ . name = " srv-clients-set " ,
2016-09-07 18:27:52 +03:00
. alias = " server-clients-set "
} ,
{ . name = " server-clients-set " ,
2016-04-09 19:49:44 +03:00
. handler = cmdSrvClientsSet ,
. opts = opts_srv_clients_set ,
2024-03-04 15:21:50 +03:00
. info = & info_srv_clients_set ,
2016-04-09 19:49:44 +03:00
. flags = 0
} ,
2020-03-07 14:31:03 +03:00
{ . name = " srv-update-tls " ,
. alias = " server-update-tls "
} ,
{ . name = " server-update-tls " ,
. handler = cmdSrvUpdateTlsFiles ,
. opts = opts_srv_update_tls_file ,
2024-03-04 15:21:50 +03:00
. info = & info_srv_update_tls_file ,
2020-03-07 14:31:03 +03:00
. flags = 0
} ,
2016-03-09 17:12:55 +03:00
{ . name = " daemon-log-filters " ,
. handler = cmdDaemonLogFilters ,
. opts = opts_daemon_log_filters ,
2024-03-04 15:21:50 +03:00
. info = & info_daemon_log_filters ,
2016-03-09 17:12:55 +03:00
. flags = 0
} ,
{ . name = " daemon-log-outputs " ,
. handler = cmdDaemonLogOutputs ,
. opts = opts_daemon_log_outputs ,
2024-03-04 15:21:50 +03:00
. info = & info_daemon_log_outputs ,
2016-03-09 17:12:55 +03:00
. flags = 0
} ,
2022-06-13 16:27:27 +03:00
{ . name = " daemon-timeout " ,
. handler = cmdDaemonTimeout ,
. opts = opts_daemon_timeout ,
2024-03-04 15:21:50 +03:00
. info = & info_daemon_timeout ,
2022-06-13 16:27:27 +03:00
. flags = 0
} ,
2015-11-19 18:12:50 +03:00
{ . name = NULL }
} ;
2015-10-12 18:07:21 +03:00
static const vshCmdGrp cmdGroups [ ] = {
{ " Virt-admin itself " , " virt-admin " , vshAdmCmds } ,
2015-11-19 18:12:50 +03:00
{ " Monitoring commands " , " monitor " , monitoringCmds } ,
2016-02-17 11:55:19 +03:00
{ " Management commands " , " management " , managementCmds } ,
2015-10-12 18:07:21 +03:00
{ NULL , NULL , NULL }
} ;
static const vshClientHooks hooks = {
2015-12-10 15:46:45 +03:00
. connHandler = vshAdmConnectionHandler
2015-10-12 18:07:21 +03:00
} ;
int
main ( int argc , char * * argv )
{
2023-08-02 15:57:44 +03:00
vshControl _ctl = { 0 } ;
vshControl * ctl = & _ctl ;
vshAdmControl virtAdminCtl = { 0 } ;
2015-10-12 18:07:21 +03:00
bool ret = true ;
ctl - > name = " virt-admin " ; /* hardcoded name of the binary */
2016-07-28 13:54:16 +03:00
ctl - > env_prefix = " VIRT_ADMIN " ;
2015-10-12 18:07:21 +03:00
ctl - > log_fd = - 1 ; /* Initialize log file descriptor */
ctl - > debug = VSH_DEBUG_DEFAULT ;
ctl - > hooks = & hooks ;
ctl - > eventPipe [ 0 ] = - 1 ;
ctl - > eventPipe [ 1 ] = - 1 ;
ctl - > privData = & virtAdminCtl ;
if ( ! ( progname = strrchr ( argv [ 0 ] , ' / ' ) ) )
progname = argv [ 0 ] ;
else
progname + + ;
ctl - > progname = progname ;
2016-04-13 01:29:52 +03:00
if ( virGettextInitialize ( ) < 0 )
2015-10-12 18:07:21 +03:00
return EXIT_FAILURE ;
if ( isatty ( STDIN_FILENO ) ) {
ctl - > istty = true ;
# ifndef WIN32
if ( tcgetattr ( STDIN_FILENO , & ctl - > termattr ) < 0 )
ctl - > istty = false ;
# endif
}
if ( virMutexInit ( & ctl - > lock ) < 0 ) {
vshError ( ctl , " %s " , _ ( " Failed to initialize mutex " ) ) ;
return EXIT_FAILURE ;
}
2016-06-29 17:12:58 +03:00
if ( virAdmInitialize ( ) < 0 ) {
vshError ( ctl , " %s " , _ ( " Failed to initialize libvirt " ) ) ;
return EXIT_FAILURE ;
}
2019-08-29 13:52:08 +03:00
virFileActivateDirOverrideForProg ( argv [ 0 ] ) ;
2015-10-12 18:07:21 +03:00
2024-03-04 17:51:28 +03:00
if ( ! vshInit ( ctl , cmdGroups ) )
2015-10-12 18:07:21 +03:00
exit ( EXIT_FAILURE ) ;
if ( ! vshAdmParseArgv ( ctl , argc , argv ) | |
! vshAdmInit ( ctl ) ) {
vshAdmDeinit ( ctl ) ;
exit ( EXIT_FAILURE ) ;
}
if ( ! ctl - > imode ) {
ret = vshCommandRun ( ctl , ctl - > cmd ) ;
} else {
/* interactive mode */
if ( ! ctl - > quiet ) {
vshPrint ( ctl ,
2023-03-09 17:54:58 +03:00
_ ( " Welcome to %1$s, the administrating virtualization interactive terminal. \n \n " ) ,
2015-10-12 18:07:21 +03:00
progname ) ;
vshPrint ( ctl , " %s " ,
_ ( " Type: 'help' for help with commands \n "
" 'quit' to quit \n \n " ) ) ;
}
do {
ctl - > cmdstr = vshReadline ( ctl , VIRT_ADMIN_PROMPT ) ;
if ( ctl - > cmdstr = = NULL )
break ; /* EOF */
if ( * ctl - > cmdstr ) {
2020-09-03 11:02:52 +03:00
vshReadlineHistoryAdd ( ctl - > cmdstr ) ;
2021-01-26 11:51:27 +03:00
if ( vshCommandStringParse ( ctl , ctl - > cmdstr , NULL , 0 ) )
2015-10-12 18:07:21 +03:00
vshCommandRun ( ctl , ctl - > cmd ) ;
}
VIR_FREE ( ctl - > cmdstr ) ;
} while ( ctl - > imode ) ;
if ( ctl - > cmdstr = = NULL )
fputc ( ' \n ' , stdout ) ; /* line break after alone prompt */
}
vshAdmDeinit ( ctl ) ;
exit ( ret ? EXIT_SUCCESS : EXIT_FAILURE ) ;
}