2005-11-10 19:12:31 +03:00
/*
2005-12-05 14:16:07 +03:00
* virsh . c : a Xen shell used to exercise the libvir API
2005-11-10 19:12:31 +03:00
*
* Copyright ( C ) 2005 Red Hat , Inc .
*
* See COPYING . LIB for the License of this software
*
* Daniel Veillard < veillard @ redhat . com >
2005-12-08 17:22:52 +03:00
* Karel Zak < kzak @ redhat . com >
2006-05-29 19:39:31 +04:00
* Daniel P . Berrange < berrange @ redhat . com >
*
2005-12-08 17:22:52 +03:00
*
* $ Id $
2005-11-10 19:12:31 +03:00
*/
2006-03-15 15:13:25 +03:00
# define _GNU_SOURCE /* isblank() */
2005-12-08 13:23:34 +03:00
2006-06-26 19:02:18 +04:00
# include "libvirt/libvirt.h"
# include "libvirt/virterror.h"
2005-11-10 19:12:31 +03:00
# include <stdio.h>
2005-12-08 13:23:34 +03:00
# include <stdlib.h>
# include <string.h>
# include <stdarg.h>
2005-12-01 19:35:42 +03:00
# include <unistd.h>
2005-12-08 13:23:34 +03:00
# include <getopt.h>
2005-12-01 19:35:42 +03:00
# include <sys/types.h>
2005-12-08 17:22:52 +03:00
# include <sys/time.h>
2005-12-08 13:23:34 +03:00
# include <ctype.h>
2006-03-30 20:08:13 +04:00
# include <fcntl.h>
2005-12-08 13:23:34 +03:00
# include <readline/readline.h>
# include <readline/history.h>
# include "config.h"
2005-12-08 18:08:46 +03:00
# include "internal.h"
2005-12-08 13:23:34 +03:00
static char * progname ;
# ifndef TRUE
# define TRUE 1
# define FALSE 0
# endif
# define VSH_PROMPT_RW "virsh # "
# define VSH_PROMPT_RO "virsh > "
# define GETTIMEOFDAY(T) gettimeofday(T, NULL)
# define DIFF_MSEC(T, U) \
( ( ( ( int ) ( ( T ) - > tv_sec - ( U ) - > tv_sec ) ) * 1000000.0 + \
( ( int ) ( ( T ) - > tv_usec - ( U ) - > tv_usec ) ) ) / 1000.0 )
2006-02-28 00:34:28 +03:00
/*
* The error handler for virtsh
*/
static void
2006-03-15 15:13:25 +03:00
virshErrorHandler ( void * unused , virErrorPtr error )
{
2006-02-28 00:34:28 +03:00
if ( ( unused ! = NULL ) | | ( error = = NULL ) )
return ;
/* Suppress the VIR_ERR_NO_XEN error which fails as non-root */
if ( ( error - > code = = VIR_ERR_NO_XEN ) | | ( error - > code = = VIR_ERR_OK ) )
return ;
virDefaultErrorFunc ( error ) ;
}
2005-12-08 13:23:34 +03:00
/*
* virsh command line grammar :
*
* command_line = < command > \ n | < command > ; < command > ; . . .
*
* command = < keyword > < option > < data >
*
* option = < bool_option > | < int_option > | < string_option >
* data = < string >
*
* bool_option = - - optionname
* int_option = - - optionname < number >
* string_option = - - optionname < string >
*
2006-01-25 12:46:22 +03:00
* keyword = [ a - zA - Z ]
* number = [ 0 - 9 ] +
* string = [ ^ [ : blank : ] ] | " [[:alnum:]] " $
2005-12-08 13:23:34 +03:00
*
*/
/*
* vshCmdOptType - command option type
2006-03-15 15:13:25 +03:00
*/
2005-12-08 13:23:34 +03:00
typedef enum {
2006-03-15 15:13:25 +03:00
VSH_OT_NONE = 0 , /* none */
VSH_OT_BOOL , /* boolean option */
VSH_OT_STRING , /* string option */
VSH_OT_INT , /* int option */
VSH_OT_DATA /* string data (as non-option) */
2005-12-08 13:23:34 +03:00
} vshCmdOptType ;
/*
* Command Option Flags
*/
2006-03-15 15:13:25 +03:00
# define VSH_OFLAG_NONE 0 /* without flags */
# define VSH_OFLAG_REQ (1 << 1) /* option required */
2005-12-08 13:23:34 +03:00
/* dummy */
typedef struct __vshControl vshControl ;
typedef struct __vshCmd vshCmd ;
/*
* vshCmdInfo - - information about command
*/
2006-03-15 15:13:25 +03:00
typedef struct {
const char * name ; /* name of information */
const char * data ; /* information */
2005-12-08 13:23:34 +03:00
} vshCmdInfo ;
/*
* vshCmdOptDef - command option definition
*/
2006-03-15 15:13:25 +03:00
typedef struct {
const char * name ; /* the name of option */
vshCmdOptType type ; /* option type */
int flag ; /* flags */
const char * help ; /* help string */
2005-12-08 13:23:34 +03:00
} vshCmdOptDef ;
/*
* vshCmdOpt - command options
*/
typedef struct vshCmdOpt {
2006-03-15 15:13:25 +03:00
vshCmdOptDef * def ; /* pointer to relevant option */
char * data ; /* allocated data */
struct vshCmdOpt * next ;
2005-12-08 13:23:34 +03:00
} vshCmdOpt ;
/*
* vshCmdDef - command definition
*/
2006-03-15 15:13:25 +03:00
typedef struct {
const char * name ;
int ( * handler ) ( vshControl * , vshCmd * ) ; /* command handler */
vshCmdOptDef * opts ; /* definition of command options */
vshCmdInfo * info ; /* details about command */
2005-12-08 13:23:34 +03:00
} vshCmdDef ;
/*
* vshCmd - parsed command
*/
typedef struct __vshCmd {
2006-03-15 15:13:25 +03:00
vshCmdDef * def ; /* command definition */
vshCmdOpt * opts ; /* list of command arguments */
struct __vshCmd * next ; /* next command */
2005-12-08 13:23:34 +03:00
} __vshCmd ;
/*
* vshControl
*/
typedef struct __vshControl {
2006-05-29 19:39:31 +04:00
char * name ; /* connection name */
2006-03-15 15:13:25 +03:00
virConnectPtr conn ; /* connection to hypervisor */
vshCmd * cmd ; /* the current command */
char * cmdstr ; /* string with command */
uid_t uid ; /* process owner */
int imode ; /* interactive mode? */
int quiet ; /* quiet mode */
int debug ; /* print debug messages? */
int timing ; /* print timing info? */
2005-12-08 13:23:34 +03:00
} __vshControl ;
2005-11-10 19:12:31 +03:00
2005-12-02 17:16:21 +03:00
2005-12-08 13:23:34 +03:00
static vshCmdDef commands [ ] ;
2006-03-15 15:13:25 +03:00
static void vshError ( vshControl * ctl , int doexit , const char * format ,
. . . ) ;
static int vshInit ( vshControl * ctl ) ;
static int vshDeinit ( vshControl * ctl ) ;
static void vshUsage ( vshControl * ctl , const char * cmdname ) ;
2005-12-08 13:23:34 +03:00
2006-03-15 15:13:25 +03:00
static int vshParseArgv ( vshControl * ctl , int argc , char * * argv ) ;
2005-12-08 13:23:34 +03:00
2006-03-15 15:13:25 +03:00
static const char * vshCmddefGetInfo ( vshCmdDef * cmd , const char * info ) ;
2005-12-08 17:22:52 +03:00
static vshCmdDef * vshCmddefSearch ( const char * cmdname ) ;
2006-03-15 15:13:25 +03:00
static int vshCmddefHelp ( vshControl * ctl , const char * name , int withprog ) ;
2005-12-08 13:23:34 +03:00
2006-03-15 15:13:25 +03:00
static vshCmdOpt * vshCommandOpt ( vshCmd * cmd , const char * name ) ;
static int vshCommandOptInt ( vshCmd * cmd , const char * name , int * found ) ;
static char * vshCommandOptString ( vshCmd * cmd , const char * name ,
int * found ) ;
static int vshCommandOptBool ( vshCmd * cmd , const char * name ) ;
2006-05-29 19:39:31 +04:00
# define VSH_DOMBYID (1 << 1)
# define VSH_DOMBYUUID (1 << 2)
# define VSH_DOMBYNAME (1 << 3)
static virDomainPtr vshCommandOptDomainBy ( vshControl * ctl , vshCmd * cmd ,
const char * optname , char * * name , int flag ) ;
/* default is lookup by Id, Name and UUID */
# define vshCommandOptDomain(_ctl, _cmd, _optname, _name) \
vshCommandOptDomainBy ( _ctl , _cmd , _optname , _name , \
VSH_DOMBYID | VSH_DOMBYUUID | VSH_DOMBYNAME )
2005-12-15 20:00:43 +03:00
2006-05-22 18:38:33 +04:00
static void vshPrintExtra ( vshControl * ctl , const char * format , . . . ) ;
static void vshDebug ( vshControl * ctl , int level , const char * format , . . . ) ;
2006-05-29 19:39:31 +04:00
/* XXX: add batch support */
2006-05-22 18:38:33 +04:00
# define vshPrint(_ctl, ...) fprintf(stdout, __VA_ARGS__)
2005-12-08 13:23:34 +03:00
2005-12-08 17:22:52 +03:00
static const char * vshDomainStateToString ( int state ) ;
2006-08-07 18:35:20 +04:00
static const char * vshDomainVcpuStateToString ( int state ) ;
2006-03-15 15:13:25 +03:00
static int vshConnectionUsability ( vshControl * ctl , virConnectPtr conn ,
int showerror ) ;
2005-12-08 13:23:34 +03:00
2006-04-06 14:33:06 +04:00
static void * _vshMalloc ( vshControl * ctl , size_t sz , const char * filename , int line ) ;
# define vshMalloc(_ctl, _sz) _vshMalloc(_ctl, _sz, __FILE__, __LINE__)
static void * _vshCalloc ( vshControl * ctl , size_t nmemb , size_t sz , const char * filename , int line ) ;
# define vshCalloc(_ctl, _nmemb, _sz) _vshCalloc(_ctl, _nmemb, _sz, __FILE__, __LINE__)
static char * _vshStrdup ( vshControl * ctl , const char * s , const char * filename , int line ) ;
# define vshStrdup(_ctl, _s) _vshStrdup(_ctl, _s, __FILE__, __LINE__)
2005-12-08 13:23:34 +03:00
/* ---------------
* Commands
* - - - - - - - - - - - - - - -
*/
/*
* " help " command
*/
static vshCmdInfo info_help [ ] = {
2006-03-15 15:13:25 +03:00
{ " syntax " , " help [<command>] " } ,
{ " help " , " print help " } ,
{ " desc " , " Prints global help or command specific help. " } ,
2006-07-20 02:24:37 +04:00
{ " version " , " Prints version information. " } ,
2006-03-15 15:13:25 +03:00
{ NULL , NULL }
2005-12-08 13:23:34 +03:00
} ;
static vshCmdOptDef opts_help [ ] = {
2006-03-15 15:13:25 +03:00
{ " command " , VSH_OT_DATA , 0 , " name of command " } ,
{ NULL , 0 , 0 , NULL }
2005-12-08 13:23:34 +03:00
} ;
static int
2006-03-15 15:13:25 +03:00
cmdHelp ( vshControl * ctl , vshCmd * cmd )
{
2005-12-08 17:22:52 +03:00
const char * cmdname = vshCommandOptString ( cmd , " command " , NULL ) ;
2005-12-08 13:23:34 +03:00
if ( ! cmdname ) {
vshCmdDef * def ;
2006-03-15 15:13:25 +03:00
2006-05-22 18:38:33 +04:00
vshPrint ( ctl , " Commands: \n \n " ) ;
2006-03-15 15:13:25 +03:00
for ( def = commands ; def - > name ; def + + )
2006-05-22 18:38:33 +04:00
vshPrint ( ctl , " %-15s %s \n " , def - > name ,
2006-03-15 15:13:25 +03:00
vshCmddefGetInfo ( def , " help " ) ) ;
2005-12-08 13:23:34 +03:00
return TRUE ;
}
return vshCmddefHelp ( ctl , cmdname , FALSE ) ;
}
/*
* " connect " command
*/
static vshCmdInfo info_connect [ ] = {
2006-05-29 19:39:31 +04:00
{ " syntax " , " connect [name] [--readonly] " } ,
2006-03-15 15:13:25 +03:00
{ " help " , " (re)connect to hypervisor " } ,
{ " desc " ,
" Connect to local hypervisor. This is build-in command after shell start up. " } ,
{ NULL , NULL }
2005-12-08 13:23:34 +03:00
} ;
static vshCmdOptDef opts_connect [ ] = {
2006-05-29 19:39:31 +04:00
{ " name " , VSH_OT_DATA , 0 , " optional argument currently unused (or used for tests only) " } ,
2006-03-15 15:13:25 +03:00
{ " readonly " , VSH_OT_BOOL , 0 , " read-only connection " } ,
{ NULL , 0 , 0 , NULL }
2005-12-08 13:23:34 +03:00
} ;
static int
2006-03-15 15:13:25 +03:00
cmdConnect ( vshControl * ctl , vshCmd * cmd )
{
2005-12-08 13:23:34 +03:00
int ro = vshCommandOptBool ( cmd , " readonly " ) ;
2006-05-29 19:39:31 +04:00
2005-12-08 13:23:34 +03:00
if ( ctl - > conn ) {
2006-03-15 15:13:25 +03:00
if ( virConnectClose ( ctl - > conn ) ! = 0 ) {
vshError ( ctl , FALSE ,
" failed to disconnect from the hypervisor " ) ;
2005-12-08 13:23:34 +03:00
return FALSE ;
}
ctl - > conn = NULL ;
}
2006-05-29 19:39:31 +04:00
if ( ctl - > name )
free ( ctl - > name ) ;
ctl - > name = vshCommandOptString ( cmd , " name " , NULL ) ;
2005-12-08 13:23:34 +03:00
if ( ! ro )
2006-05-29 19:39:31 +04:00
ctl - > conn = virConnectOpen ( ctl - > name ) ;
2005-12-08 13:23:34 +03:00
else
2006-05-29 19:39:31 +04:00
ctl - > conn = virConnectOpenReadOnly ( ctl - > name ) ;
2005-12-08 13:23:34 +03:00
if ( ! ctl - > conn )
vshError ( ctl , FALSE , " failed to connect to the hypervisor " ) ;
2006-03-15 15:13:25 +03:00
2005-12-08 13:23:34 +03:00
return ctl - > conn ? TRUE : FALSE ;
}
/*
* " list " command
*/
static vshCmdInfo info_list [ ] = {
2006-03-15 15:13:25 +03:00
{ " syntax " , " list " } ,
{ " help " , " list domains " } ,
{ " desc " , " Returns list of domains. " } ,
{ NULL , NULL }
2005-12-08 13:23:34 +03:00
} ;
2006-08-30 18:32:32 +04:00
static vshCmdOptDef opts_list [ ] = {
{ " inactive " , VSH_OT_BOOL , 0 , " list inactive domains " } ,
{ " all " , VSH_OT_BOOL , 0 , " list inactive & active domains " } ,
{ NULL , 0 , 0 , NULL }
} ;
2005-12-08 13:23:34 +03:00
2006-09-03 21:34:04 +04:00
static int domidsorter ( const void * a , const void * b ) {
const int * ia = ( const int * ) a ;
const int * ib = ( const int * ) b ;
if ( * ia > * ib )
return 1 ;
else if ( * ia < * ib )
return - 1 ;
return 0 ;
}
static int domnamesorter ( const void * a , const void * b ) {
const char * * sa = ( const char * * ) a ;
const char * * sb = ( const char * * ) b ;
2005-12-08 13:23:34 +03:00
2006-09-03 21:34:04 +04:00
return strcasecmp ( * sa , * sb ) ;
}
2005-12-08 13:23:34 +03:00
static int
2006-03-15 15:13:25 +03:00
cmdList ( vshControl * ctl , vshCmd * cmd ATTRIBUTE_UNUSED )
{
2006-08-30 18:32:32 +04:00
int inactive = vshCommandOptBool ( cmd , " inactive " ) ;
int all = vshCommandOptBool ( cmd , " all " ) ;
int active = ! inactive | | all ? 1 : 0 ;
int * ids = NULL , maxid = 0 , i ;
const char * * names = NULL ;
int maxname = 0 ;
inactive | = all ;
2005-12-08 13:23:34 +03:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn , TRUE ) )
return FALSE ;
2006-08-30 18:32:32 +04:00
if ( active ) {
maxid = virConnectNumOfDomains ( ctl - > conn ) ;
if ( maxid < 0 ) {
2005-12-08 13:23:34 +03:00
vshError ( ctl , FALSE , " failed to list active domains. " ) ;
return FALSE ;
2006-08-30 18:32:32 +04:00
}
if ( maxid ) {
2006-08-26 02:40:33 +04:00
ids = vshMalloc ( ctl , sizeof ( int ) * maxid ) ;
2006-08-30 18:32:32 +04:00
2006-09-03 21:34:04 +04:00
if ( ( maxid = virConnectListDomains ( ctl - > conn , & ids [ 0 ] , maxid ) ) < 0 ) {
2006-08-30 18:32:32 +04:00
vshError ( ctl , FALSE , " failed to list active domains. " ) ;
free ( ids ) ;
return FALSE ;
2006-08-26 02:40:33 +04:00
}
2006-09-03 21:34:04 +04:00
qsort ( & ids [ 0 ] , maxid , sizeof ( int ) , domidsorter ) ;
2006-08-30 18:32:32 +04:00
}
}
if ( inactive ) {
maxname = virConnectNumOfDefinedDomains ( ctl - > conn ) ;
if ( maxname < 0 ) {
vshError ( ctl , FALSE , " failed to list inactive domains. " ) ;
if ( ids )
free ( ids ) ;
return FALSE ;
}
if ( maxname ) {
2006-09-03 21:34:04 +04:00
names = vshMalloc ( ctl , sizeof ( char * ) * maxname ) ;
2006-08-30 18:32:32 +04:00
2006-09-03 21:34:04 +04:00
if ( ( maxname = virConnectListDefinedDomains ( ctl - > conn , names , maxname ) ) < 0 ) {
2006-08-30 18:32:32 +04:00
vshError ( ctl , FALSE , " failed to list inactive domains. " ) ;
if ( ids )
free ( ids ) ;
free ( names ) ;
return FALSE ;
}
2006-09-03 21:34:04 +04:00
qsort ( & names [ 0 ] , maxname , sizeof ( char * ) , domnamesorter ) ;
2006-08-30 18:32:32 +04:00
}
2006-08-21 21:58:09 +04:00
}
2006-05-22 18:38:33 +04:00
vshPrintExtra ( ctl , " %3s %-20s %s \n " , " Id " , " Name " , " State " ) ;
vshPrintExtra ( ctl , " ---------------------------------- \n " ) ;
2006-03-15 15:13:25 +03:00
for ( i = 0 ; i < maxid ; i + + ) {
2005-12-08 13:23:34 +03:00
int ret ;
virDomainInfo info ;
virDomainPtr dom = virDomainLookupByID ( ctl - > conn , ids [ i ] ) ;
2006-03-15 15:13:25 +03:00
/* this kind of work with domains is not atomic operation */
2005-12-08 13:23:34 +03:00
if ( ! dom )
continue ;
ret = virDomainGetInfo ( dom , & info ) ;
2006-03-15 15:13:25 +03:00
2006-05-22 18:38:33 +04:00
vshPrint ( ctl , " %3d %-20s %s \n " ,
2006-03-15 15:13:25 +03:00
virDomainGetID ( dom ) ,
virDomainGetName ( dom ) ,
ret <
0 ? " no state " : vshDomainStateToString ( info . state ) ) ;
2005-12-09 02:01:48 +03:00
virDomainFree ( dom ) ;
2005-12-08 13:23:34 +03:00
}
2006-08-30 18:32:32 +04:00
for ( i = 0 ; i < maxname ; i + + ) {
int ret ;
2006-09-03 21:34:04 +04:00
unsigned int id ;
2006-08-30 18:32:32 +04:00
virDomainInfo info ;
virDomainPtr dom = virDomainLookupByName ( ctl - > conn , names [ i ] ) ;
/* this kind of work with domains is not atomic operation */
if ( ! dom )
continue ;
ret = virDomainGetInfo ( dom , & info ) ;
2006-09-03 21:34:04 +04:00
id = virDomainGetID ( dom ) ;
if ( id = = ( ( unsigned int ) - 1 ) ) {
vshPrint ( ctl , " %3s %-20s %s \n " ,
" - " ,
names [ i ] ,
ret <
0 ? " no state " : vshDomainStateToString ( info . state ) ) ;
} else {
vshPrint ( ctl , " %3d %-20s %s \n " ,
id ,
names [ i ] ,
ret <
0 ? " no state " : vshDomainStateToString ( info . state ) ) ;
}
2006-08-30 18:32:32 +04:00
virDomainFree ( dom ) ;
}
2006-08-26 02:40:33 +04:00
if ( ids )
free ( ids ) ;
2006-08-30 18:32:32 +04:00
if ( names )
free ( names ) ;
2005-12-08 13:23:34 +03:00
return TRUE ;
}
/*
2006-04-05 01:52:31 +04:00
* " domstate " command
2005-12-08 13:23:34 +03:00
*/
2006-04-05 01:52:31 +04:00
static vshCmdInfo info_domstate [ ] = {
{ " syntax " , " domstate <domain> " } ,
2006-03-15 15:13:25 +03:00
{ " help " , " domain state " } ,
{ " desc " , " Returns state about a running domain. " } ,
{ NULL , NULL }
2005-12-08 13:23:34 +03:00
} ;
2006-04-05 01:52:31 +04:00
static vshCmdOptDef opts_domstate [ ] = {
2006-05-29 19:39:31 +04:00
{ " domain " , VSH_OT_DATA , VSH_OFLAG_REQ , " domain name, id or uuid " } ,
2006-03-15 15:13:25 +03:00
{ NULL , 0 , 0 , NULL }
2005-12-08 13:23:34 +03:00
} ;
static int
2006-04-05 01:52:31 +04:00
cmdDomstate ( vshControl * ctl , vshCmd * cmd )
2006-03-15 15:13:25 +03:00
{
2005-12-05 21:14:37 +03:00
virDomainInfo info ;
2005-12-08 13:23:34 +03:00
virDomainPtr dom ;
2005-12-15 20:00:43 +03:00
int ret = TRUE ;
2006-03-15 15:13:25 +03:00
2005-12-08 13:23:34 +03:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn , TRUE ) )
return FALSE ;
2005-12-05 21:14:37 +03:00
2005-12-15 20:00:43 +03:00
if ( ! ( dom = vshCommandOptDomain ( ctl , cmd , " domain " , NULL ) ) )
2005-12-08 13:23:34 +03:00
return FALSE ;
2006-03-15 15:13:25 +03:00
if ( virDomainGetInfo ( dom , & info ) = = 0 )
2006-05-22 18:38:33 +04:00
vshPrint ( ctl , " %s \n " ,
2006-03-15 15:13:25 +03:00
vshDomainStateToString ( info . state ) ) ;
2005-12-08 13:23:34 +03:00
else
ret = FALSE ;
2006-03-15 15:13:25 +03:00
2005-12-09 02:01:48 +03:00
virDomainFree ( dom ) ;
return ret ;
}
/*
* " suspend " command
*/
static vshCmdInfo info_suspend [ ] = {
2006-03-15 15:13:25 +03:00
{ " syntax " , " suspend <domain> " } ,
{ " help " , " suspend a domain " } ,
{ " desc " , " Suspend a running domain. " } ,
{ NULL , NULL }
2005-12-09 02:01:48 +03:00
} ;
static vshCmdOptDef opts_suspend [ ] = {
2006-05-29 19:39:31 +04:00
{ " domain " , VSH_OT_DATA , VSH_OFLAG_REQ , " domain name, id or uuid " } ,
2006-03-15 15:13:25 +03:00
{ NULL , 0 , 0 , NULL }
2005-12-09 02:01:48 +03:00
} ;
static int
2006-03-15 15:13:25 +03:00
cmdSuspend ( vshControl * ctl , vshCmd * cmd )
{
2005-12-09 02:01:48 +03:00
virDomainPtr dom ;
2005-12-15 20:00:43 +03:00
char * name ;
int ret = TRUE ;
2006-03-15 15:13:25 +03:00
2005-12-09 02:01:48 +03:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn , TRUE ) )
return FALSE ;
2005-12-15 20:00:43 +03:00
if ( ! ( dom = vshCommandOptDomain ( ctl , cmd , " domain " , & name ) ) )
2005-12-09 02:01:48 +03:00
return FALSE ;
2006-03-15 15:13:25 +03:00
if ( virDomainSuspend ( dom ) = = 0 ) {
2006-05-22 18:38:33 +04:00
vshPrint ( ctl , " Domain %s suspended \n " , name ) ;
2005-12-09 02:01:48 +03:00
} else {
vshError ( ctl , FALSE , " Failed to suspend domain \n " ) ;
ret = FALSE ;
}
2006-03-15 15:13:25 +03:00
2005-12-09 02:01:48 +03:00
virDomainFree ( dom ) ;
return ret ;
}
2006-03-30 20:08:13 +04:00
/*
* " create " command
*/
static vshCmdInfo info_create [ ] = {
{ " syntax " , " create a domain from an XML <file> " } ,
{ " help " , " create a domain from an XML file " } ,
{ " desc " , " Create a domain. " } ,
{ NULL , NULL }
} ;
static vshCmdOptDef opts_create [ ] = {
{ " file " , VSH_OT_DATA , VSH_OFLAG_REQ , " file conatining an XML domain description " } ,
{ NULL , 0 , 0 , NULL }
} ;
static int
cmdCreate ( vshControl * ctl , vshCmd * cmd )
{
virDomainPtr dom ;
char * from ;
int found ;
int ret = TRUE ;
char buffer [ 4096 ] ;
int fd , l ;
if ( ! vshConnectionUsability ( ctl , ctl - > conn , TRUE ) )
return FALSE ;
from = vshCommandOptString ( cmd , " file " , & found ) ;
if ( ! found )
return FALSE ;
fd = open ( from , O_RDONLY ) ;
if ( fd < 0 ) {
vshError ( ctl , FALSE , " Failed to read description file %s \n " , from ) ;
return ( FALSE ) ;
}
l = read ( fd , & buffer [ 0 ] , sizeof ( buffer ) ) ;
if ( ( l < = 0 ) | | ( l > = ( int ) sizeof ( buffer ) ) ) {
vshError ( ctl , FALSE , " Failed to read description file %s \n " , from ) ;
close ( fd ) ;
return ( FALSE ) ;
}
buffer [ l ] = 0 ;
dom = virDomainCreateLinux ( ctl - > conn , & buffer [ 0 ] , 0 ) ;
if ( dom ! = NULL ) {
2006-05-22 18:38:33 +04:00
vshPrint ( ctl , " Domain %s created from %s \n " ,
2006-03-30 20:08:13 +04:00
virDomainGetName ( dom ) , from ) ;
} else {
vshError ( ctl , FALSE , " Failed to create domain \n " ) ;
ret = FALSE ;
}
return ret ;
}
2006-08-30 18:32:32 +04:00
/*
* " define " command
*/
static vshCmdInfo info_define [ ] = {
{ " syntax " , " define a domain from an XML <file> " } ,
{ " help " , " define (but don't start) a domain from an XML file " } ,
{ " desc " , " Define a domain. " } ,
{ NULL , NULL }
} ;
static vshCmdOptDef opts_define [ ] = {
{ " file " , VSH_OT_DATA , VSH_OFLAG_REQ , " file conatining an XML domain description " } ,
{ NULL , 0 , 0 , NULL }
} ;
static int
cmdDefine ( vshControl * ctl , vshCmd * cmd )
{
virDomainPtr dom ;
char * from ;
int found ;
int ret = TRUE ;
char buffer [ 4096 ] ;
int fd , l ;
if ( ! vshConnectionUsability ( ctl , ctl - > conn , TRUE ) )
return FALSE ;
from = vshCommandOptString ( cmd , " file " , & found ) ;
if ( ! found )
return FALSE ;
fd = open ( from , O_RDONLY ) ;
if ( fd < 0 ) {
vshError ( ctl , FALSE , " Failed to read description file %s \n " , from ) ;
return ( FALSE ) ;
}
l = read ( fd , & buffer [ 0 ] , sizeof ( buffer ) ) ;
if ( ( l < = 0 ) | | ( l > = ( int ) sizeof ( buffer ) ) ) {
vshError ( ctl , FALSE , " Failed to read description file %s \n " , from ) ;
close ( fd ) ;
return ( FALSE ) ;
}
buffer [ l ] = 0 ;
dom = virDomainDefineXML ( ctl - > conn , & buffer [ 0 ] ) ;
if ( dom ! = NULL ) {
vshPrint ( ctl , " Domain %s defined from %s \n " ,
virDomainGetName ( dom ) , from ) ;
} else {
vshError ( ctl , FALSE , " Failed to define domain \n " ) ;
ret = FALSE ;
}
return ret ;
}
/*
* " undefine " command
*/
static vshCmdInfo info_undefine [ ] = {
{ " syntax " , " undefine <domain> " } ,
{ " help " , " Undefine an inactive domain " } ,
{ " desc " , " Undefine the configuration for an inactive domain " } ,
{ NULL , NULL }
} ;
static vshCmdOptDef opts_undefine [ ] = {
{ " domain " , VSH_OT_DATA , VSH_OFLAG_REQ , " domain name, or uuid " } ,
{ NULL , 0 , 0 , NULL }
} ;
static int
cmdUndefine ( vshControl * ctl , vshCmd * cmd )
{
virDomainPtr dom ;
int ret = TRUE ;
char * name ;
if ( ! vshConnectionUsability ( ctl , ctl - > conn , TRUE ) )
return FALSE ;
if ( ! ( dom = vshCommandOptDomain ( ctl , cmd , " domain " , & name ) ) )
return FALSE ;
if ( virDomainUndefine ( dom ) = = 0 ) {
vshPrint ( ctl , " Domain %s has been undefined \n " , name ) ;
} else {
vshError ( ctl , FALSE , " Failed to undefine domain \n " ) ;
ret = FALSE ;
}
return ret ;
}
/*
* " start " command
*/
static vshCmdInfo info_start [ ] = {
{ " syntax " , " start a domain " } ,
{ " help " , " start a (previously defined) inactive domain " } ,
{ " desc " , " Start a domain. " } ,
{ NULL , NULL }
} ;
static vshCmdOptDef opts_start [ ] = {
{ " name " , VSH_OT_DATA , VSH_OFLAG_REQ , " name of the inactive domain " } ,
{ NULL , 0 , 0 , NULL }
} ;
static int
cmdStart ( vshControl * ctl , vshCmd * cmd )
{
virDomainPtr dom ;
char * name ;
int found ;
int ret = TRUE ;
if ( ! vshConnectionUsability ( ctl , ctl - > conn , TRUE ) )
return FALSE ;
name = vshCommandOptString ( cmd , " name " , & found ) ;
if ( ! found )
return FALSE ;
dom = virDomainLookupByName ( ctl - > conn , name ) ;
if ( ! dom )
return FALSE ;
if ( virDomainGetID ( dom ) ! = ( unsigned int ) - 1 ) {
vshError ( ctl , FALSE , " Domain is already active \n " ) ;
return FALSE ;
}
if ( virDomainCreate ( dom ) = = 0 ) {
vshPrint ( ctl , " Domain %s started \n " ,
name ) ;
} else {
vshError ( ctl , FALSE , " Failed to start domain \n " ) ;
ret = FALSE ;
}
return ret ;
}
2006-01-20 13:00:08 +03:00
/*
* " save " command
*/
static vshCmdInfo info_save [ ] = {
2006-03-15 15:13:25 +03:00
{ " syntax " , " save <domain> <file> " } ,
{ " help " , " save a domain state to a file " } ,
{ " desc " , " Save a running domain. " } ,
{ NULL , NULL }
2006-01-20 13:00:08 +03:00
} ;
static vshCmdOptDef opts_save [ ] = {
2006-05-29 19:39:31 +04:00
{ " domain " , VSH_OT_DATA , VSH_OFLAG_REQ , " domain name, id or uuid " } ,
2006-03-15 15:13:25 +03:00
{ " file " , VSH_OT_DATA , VSH_OFLAG_REQ , " where to save the data " } ,
{ NULL , 0 , 0 , NULL }
2006-01-20 13:00:08 +03:00
} ;
static int
2006-03-15 15:13:25 +03:00
cmdSave ( vshControl * ctl , vshCmd * cmd )
{
2006-01-20 13:00:08 +03:00
virDomainPtr dom ;
char * name ;
char * to ;
int ret = TRUE ;
2006-03-15 15:13:25 +03:00
2006-01-20 13:00:08 +03:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn , TRUE ) )
return FALSE ;
2006-01-25 12:46:22 +03:00
if ( ! ( to = vshCommandOptString ( cmd , " file " , NULL ) ) )
2006-01-20 13:00:08 +03:00
return FALSE ;
2006-03-15 15:13:25 +03:00
2006-01-20 13:00:08 +03:00
if ( ! ( dom = vshCommandOptDomain ( ctl , cmd , " domain " , & name ) ) )
return FALSE ;
2006-03-15 15:13:25 +03:00
if ( virDomainSave ( dom , to ) = = 0 ) {
2006-05-22 18:38:33 +04:00
vshPrint ( ctl , " Domain %s saved \n " , name ) ;
2006-01-20 13:00:08 +03:00
} else {
vshError ( ctl , FALSE , " Failed to save domain \n " ) ;
ret = FALSE ;
}
2006-03-15 15:13:25 +03:00
2006-01-20 13:00:08 +03:00
virDomainFree ( dom ) ;
return ret ;
}
/*
* " restore " command
*/
static vshCmdInfo info_restore [ ] = {
2006-03-15 15:13:25 +03:00
{ " syntax " , " restore a domain from <file> " } ,
{ " help " , " restore a domain from a saved state in a file " } ,
{ " desc " , " Restore a domain. " } ,
{ NULL , NULL }
2006-01-20 13:00:08 +03:00
} ;
static vshCmdOptDef opts_restore [ ] = {
2006-03-15 15:13:25 +03:00
{ " file " , VSH_OT_DATA , VSH_OFLAG_REQ , " the state to restore " } ,
{ NULL , 0 , 0 , NULL }
2006-01-20 13:00:08 +03:00
} ;
static int
2006-03-15 15:13:25 +03:00
cmdRestore ( vshControl * ctl , vshCmd * cmd )
{
2006-01-20 13:00:08 +03:00
char * from ;
int found ;
int ret = TRUE ;
2006-03-15 15:13:25 +03:00
2006-01-20 13:00:08 +03:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn , TRUE ) )
return FALSE ;
from = vshCommandOptString ( cmd , " file " , & found ) ;
if ( ! found )
return FALSE ;
2006-03-15 15:13:25 +03:00
if ( virDomainRestore ( ctl - > conn , from ) = = 0 ) {
2006-05-22 18:38:33 +04:00
vshPrint ( ctl , " Domain restored from %s \n " , from ) ;
2006-01-20 13:00:08 +03:00
} else {
vshError ( ctl , FALSE , " Failed to restore domain \n " ) ;
ret = FALSE ;
}
return ret ;
}
2005-12-09 02:01:48 +03:00
/*
* " resume " command
*/
static vshCmdInfo info_resume [ ] = {
2006-03-15 15:13:25 +03:00
{ " syntax " , " resume <domain> " } ,
{ " help " , " resume a domain " } ,
{ " desc " , " Resume a previously suspended domain. " } ,
{ NULL , NULL }
2005-12-09 02:01:48 +03:00
} ;
static vshCmdOptDef opts_resume [ ] = {
2006-05-29 19:39:31 +04:00
{ " domain " , VSH_OT_DATA , VSH_OFLAG_REQ , " domain name, id or uuid " } ,
2006-03-15 15:13:25 +03:00
{ NULL , 0 , 0 , NULL }
2005-12-09 02:01:48 +03:00
} ;
static int
2006-03-15 15:13:25 +03:00
cmdResume ( vshControl * ctl , vshCmd * cmd )
{
2005-12-09 02:01:48 +03:00
virDomainPtr dom ;
2005-12-15 20:00:43 +03:00
int ret = TRUE ;
char * name ;
2006-03-15 15:13:25 +03:00
2005-12-09 02:01:48 +03:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn , TRUE ) )
return FALSE ;
2005-12-15 20:00:43 +03:00
if ( ! ( dom = vshCommandOptDomain ( ctl , cmd , " domain " , & name ) ) )
2005-12-09 02:01:48 +03:00
return FALSE ;
2006-03-15 15:13:25 +03:00
if ( virDomainResume ( dom ) = = 0 ) {
2006-05-22 18:38:33 +04:00
vshPrint ( ctl , " Domain %s resumed \n " , name ) ;
2005-12-09 02:01:48 +03:00
} else {
vshError ( ctl , FALSE , " Failed to resume domain \n " ) ;
ret = FALSE ;
}
2006-03-15 15:13:25 +03:00
2005-12-09 02:01:48 +03:00
virDomainFree ( dom ) ;
return ret ;
}
2005-12-16 15:16:41 +03:00
/*
* " shutdown " command
*/
static vshCmdInfo info_shutdown [ ] = {
2006-03-15 15:13:25 +03:00
{ " syntax " , " shutdown <domain> " } ,
{ " help " , " gracefully shutdown a domain " } ,
{ " desc " , " Run shutdown in the targetted domain " } ,
{ NULL , NULL }
2005-12-16 15:16:41 +03:00
} ;
static vshCmdOptDef opts_shutdown [ ] = {
2006-05-29 19:39:31 +04:00
{ " domain " , VSH_OT_DATA , VSH_OFLAG_REQ , " domain name, id or uuid " } ,
2006-03-15 15:13:25 +03:00
{ NULL , 0 , 0 , NULL }
2005-12-16 15:16:41 +03:00
} ;
static int
2006-03-15 15:13:25 +03:00
cmdShutdown ( vshControl * ctl , vshCmd * cmd )
{
2005-12-16 15:16:41 +03:00
virDomainPtr dom ;
int ret = TRUE ;
char * name ;
2006-03-15 15:13:25 +03:00
2005-12-16 15:16:41 +03:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn , TRUE ) )
return FALSE ;
if ( ! ( dom = vshCommandOptDomain ( ctl , cmd , " domain " , & name ) ) )
return FALSE ;
2006-03-15 15:13:25 +03:00
if ( virDomainShutdown ( dom ) = = 0 ) {
2006-05-22 18:38:33 +04:00
vshPrint ( ctl , " Domain %s is being shutdown \n " , name ) ;
2005-12-16 15:16:41 +03:00
} else {
vshError ( ctl , FALSE , " Failed to shutdown domain \n " ) ;
ret = FALSE ;
}
2006-03-15 15:13:25 +03:00
2005-12-16 15:16:41 +03:00
virDomainFree ( dom ) ;
return ret ;
}
2006-04-03 17:46:43 +04:00
/*
* " reboot " command
*/
static vshCmdInfo info_reboot [ ] = {
{ " syntax " , " reboot <domain> " } ,
{ " help " , " reboot a domain " } ,
{ " desc " , " Run a reboot command in the targetted domain " } ,
{ NULL , NULL }
} ;
static vshCmdOptDef opts_reboot [ ] = {
2006-05-29 19:39:31 +04:00
{ " domain " , VSH_OT_DATA , VSH_OFLAG_REQ , " domain name, id or uuid " } ,
2006-04-03 17:46:43 +04:00
{ NULL , 0 , 0 , NULL }
} ;
static int
cmdReboot ( vshControl * ctl , vshCmd * cmd )
{
virDomainPtr dom ;
int ret = TRUE ;
char * name ;
if ( ! vshConnectionUsability ( ctl , ctl - > conn , TRUE ) )
return FALSE ;
if ( ! ( dom = vshCommandOptDomain ( ctl , cmd , " domain " , & name ) ) )
return FALSE ;
if ( virDomainReboot ( dom , 0 ) = = 0 ) {
2006-05-22 18:38:33 +04:00
vshPrint ( ctl , " Domain %s is being rebooted \n " , name ) ;
2006-04-03 17:46:43 +04:00
} else {
vshError ( ctl , FALSE , " Failed to reboot domain \n " ) ;
ret = FALSE ;
}
virDomainFree ( dom ) ;
return ret ;
}
2005-12-09 02:01:48 +03:00
/*
* " destroy " command
*/
static vshCmdInfo info_destroy [ ] = {
2006-03-15 15:13:25 +03:00
{ " syntax " , " destroy <domain> " } ,
{ " help " , " destroy a domain " } ,
{ " desc " , " Destroy a given domain. " } ,
{ NULL , NULL }
2005-12-09 02:01:48 +03:00
} ;
static vshCmdOptDef opts_destroy [ ] = {
2006-05-29 19:39:31 +04:00
{ " domain " , VSH_OT_DATA , VSH_OFLAG_REQ , " domain name, id or uuid " } ,
2006-03-15 15:13:25 +03:00
{ NULL , 0 , 0 , NULL }
2005-12-09 02:01:48 +03:00
} ;
static int
2006-03-15 15:13:25 +03:00
cmdDestroy ( vshControl * ctl , vshCmd * cmd )
{
2005-12-09 02:01:48 +03:00
virDomainPtr dom ;
2005-12-15 20:00:43 +03:00
int ret = TRUE ;
char * name ;
2006-03-15 15:13:25 +03:00
2005-12-09 02:01:48 +03:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn , TRUE ) )
return FALSE ;
2005-12-15 20:00:43 +03:00
if ( ! ( dom = vshCommandOptDomain ( ctl , cmd , " domain " , & name ) ) )
2005-12-09 02:01:48 +03:00
return FALSE ;
2006-03-15 15:13:25 +03:00
if ( virDomainDestroy ( dom ) = = 0 ) {
2006-05-22 18:38:33 +04:00
vshPrint ( ctl , " Domain %s destroyed \n " , name ) ;
2005-12-09 02:01:48 +03:00
} else {
vshError ( ctl , FALSE , " Failed to destroy domain \n " ) ;
ret = FALSE ;
virDomainFree ( dom ) ;
}
2006-03-15 15:13:25 +03:00
2005-12-08 13:23:34 +03:00
return ret ;
}
/*
2006-04-04 18:37:32 +04:00
* " dominfo " command
2005-12-08 13:23:34 +03:00
*/
2006-04-04 18:37:32 +04:00
static vshCmdInfo info_dominfo [ ] = {
{ " syntax " , " dominfo <domain> " } ,
2006-03-15 15:13:25 +03:00
{ " help " , " domain information " } ,
{ " desc " , " Returns basic information about the domain. " } ,
{ NULL , NULL }
2005-12-08 13:23:34 +03:00
} ;
2006-04-04 18:37:32 +04:00
static vshCmdOptDef opts_dominfo [ ] = {
2006-05-29 19:39:31 +04:00
{ " domain " , VSH_OT_DATA , VSH_OFLAG_REQ , " domain name, id or uuid " } ,
2006-03-15 15:13:25 +03:00
{ NULL , 0 , 0 , NULL }
2005-12-08 13:23:34 +03:00
} ;
static int
2006-04-04 18:37:32 +04:00
cmdDominfo ( vshControl * ctl , vshCmd * cmd )
2006-03-15 15:13:25 +03:00
{
2005-12-08 13:23:34 +03:00
virDomainInfo info ;
virDomainPtr dom ;
2005-12-15 20:00:43 +03:00
int ret = TRUE ;
2006-09-03 21:34:04 +04:00
unsigned int id ;
2006-05-22 18:38:33 +04:00
char * str , uuid [ 37 ] ;
2006-03-15 15:13:25 +03:00
2005-12-08 13:23:34 +03:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn , TRUE ) )
return FALSE ;
2005-12-15 20:00:43 +03:00
if ( ! ( dom = vshCommandOptDomain ( ctl , cmd , " domain " , NULL ) ) )
2005-12-08 13:23:34 +03:00
return FALSE ;
2006-03-15 15:13:25 +03:00
2006-09-03 21:34:04 +04:00
id = virDomainGetID ( dom ) ;
if ( id = = ( ( unsigned int ) - 1 ) )
vshPrint ( ctl , " %-15s %s \n " , " Id: " , " - " ) ;
else
vshPrint ( ctl , " %-15s %d \n " , " Id: " , id ) ;
2006-05-22 18:38:33 +04:00
vshPrint ( ctl , " %-15s %s \n " , " Name: " , virDomainGetName ( dom ) ) ;
if ( virDomainGetUUIDString ( dom , & uuid [ 0 ] ) = = 0 )
vshPrint ( ctl , " %-15s %s \n " , " UUID: " , uuid ) ;
2006-03-15 15:13:25 +03:00
if ( ( str = virDomainGetOSType ( dom ) ) ) {
2006-05-22 18:38:33 +04:00
vshPrint ( ctl , " %-15s %s \n " , " OS Type: " , str ) ;
2006-03-15 15:13:25 +03:00
free ( str ) ;
}
if ( virDomainGetInfo ( dom , & info ) = = 0 ) {
2006-05-22 18:38:33 +04:00
vshPrint ( ctl , " %-15s %s \n " , " State: " ,
2006-03-15 15:13:25 +03:00
vshDomainStateToString ( info . state ) ) ;
2006-05-22 18:38:33 +04:00
vshPrint ( ctl , " %-15s %d \n " , " CPU(s): " , info . nrVirtCpu ) ;
2006-03-15 15:13:25 +03:00
if ( info . cpuTime ! = 0 ) {
2006-06-13 23:08:40 +04:00
double cpuUsed = info . cpuTime ;
2006-03-15 15:13:25 +03:00
2006-06-13 23:08:40 +04:00
cpuUsed / = 1000000000.0 ;
2006-03-15 15:13:25 +03:00
2006-06-13 23:08:40 +04:00
vshPrint ( ctl , " %-15s %.1lfs \n " , " CPU time: " , cpuUsed ) ;
2005-12-08 13:23:34 +03:00
}
2006-03-15 15:13:25 +03:00
2006-05-22 18:38:33 +04:00
vshPrint ( ctl , " %-15s %lu kB \n " , " Max memory: " ,
2006-03-15 15:13:25 +03:00
info . maxMem ) ;
2006-05-22 18:38:33 +04:00
vshPrint ( ctl , " %-15s %lu kB \n " , " Used memory: " ,
2006-03-15 15:13:25 +03:00
info . memory ) ;
2005-12-08 13:23:34 +03:00
} else {
ret = FALSE ;
}
2006-03-15 15:13:25 +03:00
2005-12-09 02:01:48 +03:00
virDomainFree ( dom ) ;
2005-12-08 13:23:34 +03:00
return ret ;
}
2006-08-07 18:35:20 +04:00
/*
* " vcpuinfo " command
*/
static vshCmdInfo info_vcpuinfo [ ] = {
{ " syntax " , " vcpuinfo <domain> " } ,
{ " help " , " domain vcpu information " } ,
{ " desc " , " Returns basic information about the domain virtual CPUs. " } ,
{ NULL , NULL }
} ;
static vshCmdOptDef opts_vcpuinfo [ ] = {
{ " domain " , VSH_OT_DATA , VSH_OFLAG_REQ , " domain name, id or uuid " } ,
{ NULL , 0 , 0 , NULL }
} ;
static int
cmdVcpuinfo ( vshControl * ctl , vshCmd * cmd )
{
virDomainInfo info ;
virDomainPtr dom ;
virNodeInfo nodeinfo ;
virVcpuInfoPtr cpuinfo ;
unsigned char * cpumap ;
int ncpus ;
size_t cpumaplen ;
int ret = TRUE ;
if ( ! vshConnectionUsability ( ctl , ctl - > conn , TRUE ) )
return FALSE ;
if ( ! ( dom = vshCommandOptDomain ( ctl , cmd , " domain " , NULL ) ) )
return FALSE ;
if ( virNodeGetInfo ( ctl - > conn , & nodeinfo ) ! = 0 ) {
virDomainFree ( dom ) ;
return FALSE ;
}
if ( virDomainGetInfo ( dom , & info ) ! = 0 ) {
virDomainFree ( dom ) ;
return FALSE ;
}
cpuinfo = malloc ( sizeof ( virVcpuInfo ) * info . nrVirtCpu ) ;
cpumaplen = VIR_CPU_MAPLEN ( VIR_NODEINFO_MAXCPUS ( nodeinfo ) ) ;
cpumap = malloc ( info . nrVirtCpu * cpumaplen ) ;
if ( ( ncpus = virDomainGetVcpus ( dom ,
cpuinfo , info . nrVirtCpu ,
cpumap , cpumaplen ) ) > = 0 ) {
int n ;
for ( n = 0 ; n < ncpus ; n + + ) {
unsigned int m ;
vshPrint ( ctl , " %-15s %d \n " , " VCPU: " , n ) ;
vshPrint ( ctl , " %-15s %d \n " , " CPU: " , cpuinfo [ n ] . cpu ) ;
vshPrint ( ctl , " %-15s %s \n " , " State: " ,
vshDomainVcpuStateToString ( cpuinfo [ n ] . state ) ) ;
if ( cpuinfo [ n ] . cpuTime ! = 0 ) {
double cpuUsed = cpuinfo [ n ] . cpuTime ;
cpuUsed / = 1000000000.0 ;
vshPrint ( ctl , " %-15s %.1lfs \n " , " CPU time: " , cpuUsed ) ;
}
vshPrint ( ctl , " %-15s " , " CPU Affinity: " ) ;
for ( m = 0 ; m < VIR_NODEINFO_MAXCPUS ( nodeinfo ) ; m + + ) {
vshPrint ( ctl , " %c " , VIR_CPU_USABLE ( cpumap , cpumaplen , n , m ) ? ' y ' : ' - ' ) ;
}
vshPrint ( ctl , " \n " ) ;
if ( n < ( ncpus - 1 ) ) {
vshPrint ( ctl , " \n " ) ;
}
}
} else {
ret = FALSE ;
}
free ( cpumap ) ;
free ( cpuinfo ) ;
virDomainFree ( dom ) ;
return ret ;
}
/*
* " vcpupin " command
*/
static vshCmdInfo info_vcpupin [ ] = {
{ " syntax " , " vcpupin <domain> " } ,
{ " help " , " control domain vcpu affinity " } ,
{ " desc " , " Pin domain VCPUs to host physical CPUs " } ,
{ NULL , NULL }
} ;
static vshCmdOptDef opts_vcpupin [ ] = {
{ " domain " , VSH_OT_DATA , VSH_OFLAG_REQ , " domain name, id or uuid " } ,
{ " vcpu " , VSH_OT_DATA , VSH_OFLAG_REQ , " vcpu number " } ,
{ " cpulist " , VSH_OT_DATA , VSH_OFLAG_REQ , " host cpu number(s) (comma separated) " } ,
{ NULL , 0 , 0 , NULL }
} ;
static int
cmdVcpupin ( vshControl * ctl , vshCmd * cmd )
{
virDomainInfo info ;
virDomainPtr dom ;
virNodeInfo nodeinfo ;
int vcpu ;
char * cpulist ;
int ret = TRUE ;
int vcpufound = 0 ;
unsigned char * cpumap ;
int cpumaplen ;
if ( ! vshConnectionUsability ( ctl , ctl - > conn , TRUE ) )
return FALSE ;
if ( ! ( dom = vshCommandOptDomain ( ctl , cmd , " domain " , NULL ) ) )
return FALSE ;
vcpu = vshCommandOptInt ( cmd , " vcpu " , & vcpufound ) ;
if ( ! vcpufound ) {
virDomainFree ( dom ) ;
return FALSE ;
}
if ( ! ( cpulist = vshCommandOptString ( cmd , " cpulist " , NULL ) ) ) {
virDomainFree ( dom ) ;
return FALSE ;
}
if ( virNodeGetInfo ( ctl - > conn , & nodeinfo ) ! = 0 ) {
virDomainFree ( dom ) ;
return FALSE ;
}
if ( virDomainGetInfo ( dom , & info ) ! = 0 ) {
virDomainFree ( dom ) ;
return FALSE ;
}
if ( vcpu > = info . nrVirtCpu ) {
virDomainFree ( dom ) ;
return FALSE ;
}
cpumaplen = VIR_CPU_MAPLEN ( VIR_NODEINFO_MAXCPUS ( nodeinfo ) ) ;
cpumap = malloc ( cpumaplen ) ;
memset ( cpumap , 0 , cpumaplen ) ;
do {
unsigned int cpu = atoi ( cpulist ) ;
if ( cpu < VIR_NODEINFO_MAXCPUS ( nodeinfo ) ) {
VIR_USE_CPU ( cpumap , cpu ) ;
}
cpulist = index ( cpulist , ' , ' ) ;
if ( cpulist )
cpulist + + ;
} while ( cpulist ) ;
if ( virDomainPinVcpu ( dom , vcpu , cpumap , cpumaplen ) ! = 0 ) {
ret = FALSE ;
}
free ( cpumap ) ;
virDomainFree ( dom ) ;
return ret ;
}
2006-08-16 21:30:33 +04:00
/*
* " setvcpus " command
*/
static vshCmdInfo info_setvcpus [ ] = {
{ " syntax " , " setvcpus <domain> <count> " } ,
{ " help " , " change number of virtual CPUs " } ,
{ " desc " , " Change the number of virtual CPUs active in the guest domain " } ,
{ NULL , NULL }
} ;
static vshCmdOptDef opts_setvcpus [ ] = {
{ " domain " , VSH_OT_DATA , VSH_OFLAG_REQ , " domain name, id or uuid " } ,
{ " count " , VSH_OT_DATA , VSH_OFLAG_REQ , " number of virtual CPUs " } ,
{ NULL , 0 , 0 , NULL }
} ;
static int
cmdSetvcpus ( vshControl * ctl , vshCmd * cmd )
{
virDomainPtr dom ;
int count ;
int ret = TRUE ;
if ( ! vshConnectionUsability ( ctl , ctl - > conn , TRUE ) )
return FALSE ;
if ( ! ( dom = vshCommandOptDomain ( ctl , cmd , " domain " , NULL ) ) )
return FALSE ;
count = vshCommandOptInt ( cmd , " count " , & count ) ;
if ( ! count ) {
virDomainFree ( dom ) ;
return FALSE ;
}
if ( virDomainSetVcpus ( dom , count ) ! = 0 ) {
ret = FALSE ;
}
virDomainFree ( dom ) ;
return ret ;
}
/*
* " setmemory " command
*/
static vshCmdInfo info_setmem [ ] = {
{ " syntax " , " setmem <domain> <bytes> " } ,
{ " help " , " change memory allocation " } ,
{ " desc " , " Change the current memory allocation in the guest domain " } ,
{ NULL , NULL }
} ;
static vshCmdOptDef opts_setmem [ ] = {
{ " domain " , VSH_OT_DATA , VSH_OFLAG_REQ , " domain name, id or uuid " } ,
{ " bytes " , VSH_OT_DATA , VSH_OFLAG_REQ , " number of bytes of memory " } ,
{ NULL , 0 , 0 , NULL }
} ;
static int
cmdSetmem ( vshControl * ctl , vshCmd * cmd )
{
virDomainPtr dom ;
int bytes ;
int ret = TRUE ;
if ( ! vshConnectionUsability ( ctl , ctl - > conn , TRUE ) )
return FALSE ;
if ( ! ( dom = vshCommandOptDomain ( ctl , cmd , " domain " , NULL ) ) )
return FALSE ;
bytes = vshCommandOptInt ( cmd , " bytes " , & bytes ) ;
if ( ! bytes ) {
virDomainFree ( dom ) ;
return FALSE ;
}
if ( virDomainSetMemory ( dom , bytes ) ! = 0 ) {
ret = FALSE ;
}
virDomainFree ( dom ) ;
return ret ;
}
/*
* " setmaxmem " command
*/
static vshCmdInfo info_setmaxmem [ ] = {
{ " syntax " , " setmaxmem <domain> <bytes> " } ,
{ " help " , " change maximum memory limit " } ,
{ " desc " , " Change the maximum memory allocation limit in the guest domain " } ,
{ NULL , NULL }
} ;
static vshCmdOptDef opts_setmaxmem [ ] = {
{ " domain " , VSH_OT_DATA , VSH_OFLAG_REQ , " domain name, id or uuid " } ,
{ " bytes " , VSH_OT_DATA , VSH_OFLAG_REQ , " maxmimum memory limit in bytes " } ,
{ NULL , 0 , 0 , NULL }
} ;
static int
cmdSetmaxmem ( vshControl * ctl , vshCmd * cmd )
{
virDomainPtr dom ;
int bytes ;
int ret = TRUE ;
if ( ! vshConnectionUsability ( ctl , ctl - > conn , TRUE ) )
return FALSE ;
if ( ! ( dom = vshCommandOptDomain ( ctl , cmd , " domain " , NULL ) ) )
return FALSE ;
bytes = vshCommandOptInt ( cmd , " bytes " , & bytes ) ;
if ( ! bytes ) {
virDomainFree ( dom ) ;
return FALSE ;
}
if ( virDomainSetMaxMemory ( dom , bytes ) ! = 0 ) {
ret = FALSE ;
}
virDomainFree ( dom ) ;
return ret ;
}
2006-04-04 18:37:32 +04:00
/*
* " nodeinfo " command
*/
static vshCmdInfo info_nodeinfo [ ] = {
{ " syntax " , " nodeinfo " } ,
{ " help " , " node information " } ,
{ " desc " , " Returns basic information about the node. " } ,
{ NULL , NULL }
} ;
static int
cmdNodeinfo ( vshControl * ctl , vshCmd * cmd ATTRIBUTE_UNUSED )
{
virNodeInfo info ;
if ( ! vshConnectionUsability ( ctl , ctl - > conn , TRUE ) )
return FALSE ;
if ( virNodeGetInfo ( ctl - > conn , & info ) < 0 ) {
vshError ( ctl , FALSE , " failed to get node information " ) ;
return FALSE ;
}
2006-05-22 18:38:33 +04:00
vshPrint ( ctl , " %-20s %s \n " , " CPU model: " , info . model ) ;
vshPrint ( ctl , " %-20s %d \n " , " CPU(s): " , info . cpus ) ;
vshPrint ( ctl , " %-20s %d MHz \n " , " CPU frequency: " , info . mhz ) ;
vshPrint ( ctl , " %-20s %d \n " , " CPU socket(s): " , info . sockets ) ;
vshPrint ( ctl , " %-20s %d \n " , " Core(s) per socket: " , info . cores ) ;
vshPrint ( ctl , " %-20s %d \n " , " Thread(s) per core: " , info . threads ) ;
vshPrint ( ctl , " %-20s %d \n " , " NUMA cell(s): " , info . nodes ) ;
vshPrint ( ctl , " %-20s %lu kB \n " , " Memory size: " , info . memory ) ;
2006-04-04 18:37:32 +04:00
return TRUE ;
}
2005-12-13 19:22:05 +03:00
/*
* " dumpxml " command
*/
static vshCmdInfo info_dumpxml [ ] = {
2006-03-15 15:13:25 +03:00
{ " syntax " , " dumpxml <name> " } ,
{ " help " , " domain information in XML " } ,
2006-07-20 02:24:37 +04:00
{ " desc " , " Ouput the domain information as an XML dump to stdout " } ,
2006-03-15 15:13:25 +03:00
{ NULL , NULL }
2005-12-13 19:22:05 +03:00
} ;
static vshCmdOptDef opts_dumpxml [ ] = {
2006-05-29 19:39:31 +04:00
{ " domain " , VSH_OT_DATA , VSH_OFLAG_REQ , " domain name, id, uuid " } ,
2006-03-15 15:13:25 +03:00
{ NULL , 0 , 0 , NULL }
2005-12-13 19:22:05 +03:00
} ;
static int
2006-03-15 15:13:25 +03:00
cmdDumpXML ( vshControl * ctl , vshCmd * cmd )
{
2005-12-13 19:22:05 +03:00
virDomainPtr dom ;
2005-12-15 20:00:43 +03:00
int ret = TRUE ;
2005-12-13 19:22:05 +03:00
char * dump ;
2006-03-15 15:13:25 +03:00
2005-12-13 19:22:05 +03:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn , TRUE ) )
return FALSE ;
2005-12-15 20:00:43 +03:00
if ( ! ( dom = vshCommandOptDomain ( ctl , cmd , " domain " , NULL ) ) )
2005-12-13 19:22:05 +03:00
return FALSE ;
2006-03-15 15:13:25 +03:00
2005-12-13 19:22:05 +03:00
dump = virDomainGetXMLDesc ( dom , 0 ) ;
if ( dump ! = NULL ) {
printf ( " %s " , dump ) ;
free ( dump ) ;
} else {
ret = FALSE ;
}
2006-03-15 15:13:25 +03:00
2005-12-13 19:22:05 +03:00
virDomainFree ( dom ) ;
return ret ;
}
2005-12-08 13:23:34 +03:00
/*
2006-04-05 01:52:31 +04:00
* " domname " command
2005-12-08 13:23:34 +03:00
*/
2006-04-05 01:52:31 +04:00
static vshCmdInfo info_domname [ ] = {
2006-05-29 19:39:31 +04:00
{ " syntax " , " domname <domain> " } ,
{ " help " , " convert a domain Id or UUID to domain name " } ,
2006-03-15 15:13:25 +03:00
{ NULL , NULL }
2005-12-08 13:23:34 +03:00
} ;
2006-04-05 01:52:31 +04:00
static vshCmdOptDef opts_domname [ ] = {
2006-05-29 19:39:31 +04:00
{ " domain " , VSH_OT_DATA , VSH_OFLAG_REQ , " domain id or uuid " } ,
2006-03-15 15:13:25 +03:00
{ NULL , 0 , 0 , NULL }
2005-12-08 13:23:34 +03:00
} ;
static int
2006-04-05 01:52:31 +04:00
cmdDomname ( vshControl * ctl , vshCmd * cmd )
2006-03-15 15:13:25 +03:00
{
2005-12-08 13:23:34 +03:00
virDomainPtr dom ;
if ( ! vshConnectionUsability ( ctl , ctl - > conn , TRUE ) )
return FALSE ;
2006-05-29 19:39:31 +04:00
if ( ! ( dom = vshCommandOptDomainBy ( ctl , cmd , " domain " , NULL ,
VSH_DOMBYID | VSH_DOMBYUUID ) ) )
2005-12-08 13:23:34 +03:00
return FALSE ;
2006-03-15 15:13:25 +03:00
2006-05-29 19:39:31 +04:00
vshPrint ( ctl , " %s \n " , virDomainGetName ( dom ) ) ;
virDomainFree ( dom ) ;
2005-12-08 13:23:34 +03:00
return TRUE ;
}
/*
2006-04-05 01:52:31 +04:00
* " domid " command
2005-12-08 13:23:34 +03:00
*/
2006-04-05 01:52:31 +04:00
static vshCmdInfo info_domid [ ] = {
2006-05-29 19:39:31 +04:00
{ " syntax " , " domid <domain> " } ,
{ " help " , " convert a domain name or UUID to domain Id " } ,
2006-03-15 15:13:25 +03:00
{ NULL , NULL }
2005-12-08 13:23:34 +03:00
} ;
2006-04-05 01:52:31 +04:00
static vshCmdOptDef opts_domid [ ] = {
2006-05-29 19:39:31 +04:00
{ " domain " , VSH_OT_DATA , VSH_OFLAG_REQ , " domain name or uuid " } ,
2006-03-15 15:13:25 +03:00
{ NULL , 0 , 0 , NULL }
2005-12-08 13:23:34 +03:00
} ;
static int
2006-04-05 01:52:31 +04:00
cmdDomid ( vshControl * ctl , vshCmd * cmd )
2006-03-15 15:13:25 +03:00
{
2005-12-05 14:16:07 +03:00
virDomainPtr dom ;
2006-09-03 21:34:04 +04:00
unsigned int id ;
2005-12-08 13:23:34 +03:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn , TRUE ) )
return FALSE ;
2006-05-29 19:39:31 +04:00
if ( ! ( dom = vshCommandOptDomainBy ( ctl , cmd , " domain " , NULL ,
VSH_DOMBYNAME | VSH_DOMBYUUID ) ) )
2005-12-08 13:23:34 +03:00
return FALSE ;
2006-05-29 19:39:31 +04:00
2006-09-03 21:34:04 +04:00
id = virDomainGetID ( dom ) ;
if ( id = = ( ( unsigned int ) - 1 ) )
vshPrint ( ctl , " %s \n " , " - " ) ;
else
vshPrint ( ctl , " %d \n " , id ) ;
2006-05-29 19:39:31 +04:00
virDomainFree ( dom ) ;
return TRUE ;
}
2006-03-15 15:13:25 +03:00
2006-05-29 19:39:31 +04:00
/*
* " domuuid " command
*/
static vshCmdInfo info_domuuid [ ] = {
{ " syntax " , " domuuid <domain> " } ,
{ " help " , " convert a domain name or id to domain UUID " } ,
{ NULL , NULL }
} ;
static vshCmdOptDef opts_domuuid [ ] = {
{ " domain " , VSH_OT_DATA , VSH_OFLAG_REQ , " domain id or name " } ,
{ NULL , 0 , 0 , NULL }
} ;
static int
cmdDomuuid ( vshControl * ctl , vshCmd * cmd )
{
virDomainPtr dom ;
char uuid [ 37 ] ;
if ( ! vshConnectionUsability ( ctl , ctl - > conn , TRUE ) )
2005-12-08 13:23:34 +03:00
return FALSE ;
2006-05-29 19:39:31 +04:00
if ( ! ( dom = vshCommandOptDomainBy ( ctl , cmd , " domain " , NULL ,
VSH_DOMBYNAME | VSH_DOMBYID ) ) )
return FALSE ;
if ( virDomainGetUUIDString ( dom , uuid ) ! = - 1 )
vshPrint ( ctl , " %s \n " , uuid ) ;
else
vshError ( ctl , FALSE , " failed to get domain UUID " ) ;
2005-12-08 13:23:34 +03:00
return TRUE ;
}
2006-05-29 19:39:31 +04:00
2005-12-08 16:26:52 +03:00
/*
* " version " command
*/
static vshCmdInfo info_version [ ] = {
2006-03-15 15:13:25 +03:00
{ " syntax " , " version " } ,
{ " help " , " show versions " } ,
2006-07-20 02:24:37 +04:00
{ " desc " , " Display the version information available " } ,
2006-03-15 15:13:25 +03:00
{ NULL , NULL }
2005-12-08 16:26:52 +03:00
} ;
static int
2006-03-15 15:13:25 +03:00
cmdVersion ( vshControl * ctl , vshCmd * cmd ATTRIBUTE_UNUSED )
{
2005-12-08 16:26:52 +03:00
unsigned long hvVersion ;
const char * hvType ;
2005-12-08 18:08:46 +03:00
unsigned long libVersion ;
unsigned long includeVersion ;
unsigned long apiVersion ;
int ret ;
unsigned int major ;
unsigned int minor ;
unsigned int rel ;
2005-12-08 16:26:52 +03:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn , TRUE ) )
return FALSE ;
2006-03-15 15:13:25 +03:00
2005-12-08 16:26:52 +03:00
hvType = virConnectGetType ( ctl - > conn ) ;
if ( hvType = = NULL ) {
2005-12-08 17:22:52 +03:00
vshError ( ctl , FALSE , " failed to get hypervisor type \n " ) ;
2005-12-08 16:26:52 +03:00
return FALSE ;
}
2005-12-08 18:08:46 +03:00
includeVersion = LIBVIR_VERSION_NUMBER ;
major = includeVersion / 1000000 ;
includeVersion % = 1000000 ;
minor = includeVersion / 1000 ;
rel = includeVersion % 1000 ;
2006-05-22 18:38:33 +04:00
vshPrint ( ctl , " Compiled against library: libvir %d.%d.%d \n " ,
2005-12-08 18:08:46 +03:00
major , minor , rel ) ;
ret = virGetVersion ( & libVersion , hvType , & apiVersion ) ;
if ( ret < 0 ) {
vshError ( ctl , FALSE , " failed to get the library version " ) ;
return FALSE ;
}
major = libVersion / 1000000 ;
libVersion % = 1000000 ;
minor = libVersion / 1000 ;
rel = libVersion % 1000 ;
2006-05-22 18:38:33 +04:00
vshPrint ( ctl , " Using library: libvir %d.%d.%d \n " ,
2005-12-08 18:08:46 +03:00
major , minor , rel ) ;
2006-03-15 15:13:25 +03:00
2005-12-08 18:08:46 +03:00
major = apiVersion / 1000000 ;
apiVersion % = 1000000 ;
minor = apiVersion / 1000 ;
rel = apiVersion % 1000 ;
2006-05-22 18:38:33 +04:00
vshPrint ( ctl , " Using API: %s %d.%d.%d \n " , hvType ,
2005-12-08 18:08:46 +03:00
major , minor , rel ) ;
2006-03-15 15:13:25 +03:00
ret = virConnectGetVersion ( ctl - > conn , & hvVersion ) ;
2005-12-08 18:08:46 +03:00
if ( ret < 0 ) {
vshError ( ctl , FALSE , " failed to get the hypervisor version " ) ;
2005-12-08 16:26:52 +03:00
return FALSE ;
}
if ( hvVersion = = 0 ) {
2006-05-22 18:38:33 +04:00
vshPrint ( ctl ,
2006-03-15 15:13:25 +03:00
" cannot extract running %s hypervisor version \n " , hvType ) ;
2005-12-08 16:26:52 +03:00
} else {
2005-12-08 18:08:46 +03:00
major = hvVersion / 1000000 ;
2005-12-08 16:26:52 +03:00
hvVersion % = 1000000 ;
2005-12-08 18:08:46 +03:00
minor = hvVersion / 1000 ;
rel = hvVersion % 1000 ;
2005-12-08 16:26:52 +03:00
2006-05-22 18:38:33 +04:00
vshPrint ( ctl , " Running hypervisor: %s %d.%d.%d \n " ,
2006-03-15 15:13:25 +03:00
hvType , major , minor , rel ) ;
2005-12-08 16:26:52 +03:00
}
return TRUE ;
}
2005-12-08 13:23:34 +03:00
/*
* " quit " command
*/
static vshCmdInfo info_quit [ ] = {
2006-03-15 15:13:25 +03:00
{ " syntax " , " quit " } ,
{ " help " , " quit this interactive terminal " } ,
{ NULL , NULL }
2005-12-08 13:23:34 +03:00
} ;
static int
2006-03-15 15:13:25 +03:00
cmdQuit ( vshControl * ctl , vshCmd * cmd ATTRIBUTE_UNUSED )
{
2005-12-08 13:23:34 +03:00
ctl - > imode = FALSE ;
return TRUE ;
}
/*
* Commands
*/
static vshCmdDef commands [ ] = {
2006-03-15 15:13:25 +03:00
{ " connect " , cmdConnect , opts_connect , info_connect } ,
2006-03-30 20:08:13 +04:00
{ " create " , cmdCreate , opts_create , info_create } ,
2006-08-30 18:32:32 +04:00
{ " start " , cmdStart , opts_start , info_start } ,
2006-04-05 01:52:31 +04:00
{ " destroy " , cmdDestroy , opts_destroy , info_destroy } ,
2006-08-30 18:32:32 +04:00
{ " define " , cmdDefine , opts_define , info_define } ,
2006-04-05 01:52:31 +04:00
{ " domid " , cmdDomid , opts_domid , info_domid } ,
2006-05-29 19:39:31 +04:00
{ " domuuid " , cmdDomuuid , opts_domuuid , info_domuuid } ,
2006-04-04 18:37:32 +04:00
{ " dominfo " , cmdDominfo , opts_dominfo , info_dominfo } ,
2006-04-05 01:52:31 +04:00
{ " domname " , cmdDomname , opts_domname , info_domname } ,
{ " domstate " , cmdDomstate , opts_domstate , info_domstate } ,
2006-03-15 15:13:25 +03:00
{ " dumpxml " , cmdDumpXML , opts_dumpxml , info_dumpxml } ,
2006-04-05 01:52:31 +04:00
{ " help " , cmdHelp , opts_help , info_help } ,
2006-08-30 18:32:32 +04:00
{ " list " , cmdList , opts_list , info_list } ,
2006-04-05 01:52:31 +04:00
{ " nodeinfo " , cmdNodeinfo , NULL , info_nodeinfo } ,
{ " quit " , cmdQuit , NULL , info_quit } ,
{ " reboot " , cmdReboot , opts_reboot , info_reboot } ,
{ " restore " , cmdRestore , opts_restore , info_restore } ,
2006-03-15 15:13:25 +03:00
{ " resume " , cmdResume , opts_resume , info_resume } ,
{ " save " , cmdSave , opts_save , info_save } ,
{ " shutdown " , cmdShutdown , opts_shutdown , info_shutdown } ,
2006-08-16 21:30:33 +04:00
{ " setmem " , cmdSetmem , opts_setmem , info_setmem } ,
{ " setmaxmem " , cmdSetmaxmem , opts_setmaxmem , info_setmaxmem } ,
{ " setvcpus " , cmdSetvcpus , opts_setvcpus , info_setvcpus } ,
2006-04-05 01:52:31 +04:00
{ " suspend " , cmdSuspend , opts_suspend , info_suspend } ,
2006-08-30 18:32:32 +04:00
{ " undefine " , cmdUndefine , opts_undefine , info_undefine } ,
2006-08-07 18:35:20 +04:00
{ " vcpuinfo " , cmdVcpuinfo , opts_vcpuinfo , info_vcpuinfo } ,
{ " vcpupin " , cmdVcpupin , opts_vcpupin , info_vcpupin } ,
2006-03-15 15:13:25 +03:00
{ " version " , cmdVersion , NULL , info_version } ,
{ NULL , NULL , NULL , NULL }
2005-12-08 13:23:34 +03:00
} ;
/* ---------------
* Utils for work with command definition
* - - - - - - - - - - - - - - -
*/
2005-12-08 17:22:52 +03:00
static const char *
2006-03-15 15:13:25 +03:00
vshCmddefGetInfo ( vshCmdDef * cmd , const char * name )
{
2005-12-08 13:23:34 +03:00
vshCmdInfo * info ;
2006-03-15 15:13:25 +03:00
2005-12-08 13:23:34 +03:00
for ( info = cmd - > info ; info & & info - > name ; info + + ) {
2006-03-15 15:13:25 +03:00
if ( strcmp ( info - > name , name ) = = 0 )
2005-12-08 13:23:34 +03:00
return info - > data ;
}
return NULL ;
}
static vshCmdOptDef *
2006-03-15 15:13:25 +03:00
vshCmddefGetOption ( vshCmdDef * cmd , const char * name )
{
2005-12-08 13:23:34 +03:00
vshCmdOptDef * opt ;
2006-03-15 15:13:25 +03:00
2005-12-08 13:23:34 +03:00
for ( opt = cmd - > opts ; opt & & opt - > name ; opt + + )
2006-03-15 15:13:25 +03:00
if ( strcmp ( opt - > name , name ) = = 0 )
2005-12-08 13:23:34 +03:00
return opt ;
return NULL ;
}
static vshCmdOptDef *
2006-03-15 15:13:25 +03:00
vshCmddefGetData ( vshCmdDef * cmd , int data_ct )
{
2005-12-08 13:23:34 +03:00
vshCmdOptDef * opt ;
2006-01-25 12:46:22 +03:00
for ( opt = cmd - > opts ; opt & & opt - > name ; opt + + ) {
2006-03-15 15:13:25 +03:00
if ( opt - > type = = VSH_OT_DATA ) {
if ( data_ct = = 0 )
2006-01-25 12:46:22 +03:00
return opt ;
else
data_ct - - ;
}
}
2005-12-08 13:23:34 +03:00
return NULL ;
}
2006-01-25 12:46:22 +03:00
/*
* Checks for required options
*/
2006-03-15 15:13:25 +03:00
static int
vshCommandCheckOpts ( vshControl * ctl , vshCmd * cmd )
2006-01-25 12:46:22 +03:00
{
vshCmdDef * def = cmd - > def ;
vshCmdOptDef * d ;
2006-03-15 15:13:25 +03:00
int err = 0 ;
2006-01-25 12:46:22 +03:00
for ( d = def - > opts ; d & & d - > name ; d + + ) {
if ( d - > flag & VSH_OFLAG_REQ ) {
vshCmdOpt * o = cmd - > opts ;
2006-03-15 15:13:25 +03:00
int ok = 0 ;
while ( o & & ok = = 0 ) {
2006-01-25 12:46:22 +03:00
if ( o - > def = = d )
2006-03-15 15:13:25 +03:00
ok = 1 ;
2006-01-25 12:46:22 +03:00
o = o - > next ;
}
if ( ! ok ) {
2006-03-15 15:13:25 +03:00
vshError ( ctl , FALSE ,
d - > type = = VSH_OT_DATA ?
" command '%s' requires <%s> option " :
" command '%s' requires --%s option " ,
def - > name , d - > name ) ;
2006-01-25 12:46:22 +03:00
err = 1 ;
}
2006-03-15 15:13:25 +03:00
2006-01-25 12:46:22 +03:00
}
}
return ! err ;
}
2005-12-08 13:23:34 +03:00
static vshCmdDef *
2006-03-15 15:13:25 +03:00
vshCmddefSearch ( const char * cmdname )
{
2005-12-08 13:23:34 +03:00
vshCmdDef * c ;
2006-03-15 15:13:25 +03:00
2005-12-08 13:23:34 +03:00
for ( c = commands ; c - > name ; c + + )
2006-03-15 15:13:25 +03:00
if ( strcmp ( c - > name , cmdname ) = = 0 )
2005-12-08 13:23:34 +03:00
return c ;
return NULL ;
}
static int
2006-03-15 15:13:25 +03:00
vshCmddefHelp ( vshControl * ctl , const char * cmdname , int withprog )
{
2005-12-08 13:23:34 +03:00
vshCmdDef * def = vshCmddefSearch ( cmdname ) ;
2006-03-15 15:13:25 +03:00
2005-12-08 13:23:34 +03:00
if ( ! def ) {
2006-03-15 15:13:25 +03:00
vshError ( ctl , FALSE , " command '%s' doesn't exist " , cmdname ) ;
return FALSE ;
} else {
2005-12-08 13:23:34 +03:00
vshCmdOptDef * opt ;
2005-12-08 17:22:52 +03:00
const char * desc = vshCmddefGetInfo ( def , " desc " ) ;
const char * help = vshCmddefGetInfo ( def , " help " ) ;
const char * syntax = vshCmddefGetInfo ( def , " syntax " ) ;
2005-12-08 13:23:34 +03:00
fputs ( " NAME \n " , stdout ) ;
2006-03-15 15:13:25 +03:00
fprintf ( stdout , " %s - %s \n " , def - > name , help ) ;
2005-12-08 13:23:34 +03:00
if ( syntax ) {
fputs ( " \n SYNOPSIS \n " , stdout ) ;
if ( ! withprog )
fprintf ( stdout , " %s \n " , syntax ) ;
else
fprintf ( stdout , " %s %s \n " , progname , syntax ) ;
}
if ( desc ) {
fputs ( " \n DESCRIPTION \n " , stdout ) ;
fprintf ( stdout , " %s \n " , desc ) ;
}
if ( def - > opts ) {
fputs ( " \n OPTIONS \n " , stdout ) ;
2006-03-15 15:13:25 +03:00
for ( opt = def - > opts ; opt - > name ; opt + + ) {
2005-12-08 13:23:34 +03:00
char buf [ 256 ] ;
2006-03-15 15:13:25 +03:00
if ( opt - > type = = VSH_OT_BOOL )
2005-12-08 13:23:34 +03:00
snprintf ( buf , sizeof ( buf ) , " --%s " , opt - > name ) ;
2006-03-15 15:13:25 +03:00
else if ( opt - > type = = VSH_OT_INT )
2005-12-08 13:23:34 +03:00
snprintf ( buf , sizeof ( buf ) , " --%s <number> " , opt - > name ) ;
2006-03-15 15:13:25 +03:00
else if ( opt - > type = = VSH_OT_STRING )
2005-12-08 13:23:34 +03:00
snprintf ( buf , sizeof ( buf ) , " --%s <string> " , opt - > name ) ;
2006-03-15 15:13:25 +03:00
else if ( opt - > type = = VSH_OT_DATA )
2005-12-08 13:23:34 +03:00
snprintf ( buf , sizeof ( buf ) , " <%s> " , opt - > name ) ;
2006-03-15 15:13:25 +03:00
2005-12-08 13:23:34 +03:00
fprintf ( stdout , " %-15s %s \n " , buf , opt - > help ) ;
2006-03-15 15:13:25 +03:00
}
2005-12-08 13:23:34 +03:00
}
fputc ( ' \n ' , stdout ) ;
}
return TRUE ;
}
/* ---------------
* Utils for work with runtime commands data
* - - - - - - - - - - - - - - -
*/
2006-03-15 15:13:25 +03:00
static void
vshCommandOptFree ( vshCmdOpt * arg )
{
2005-12-08 13:23:34 +03:00
vshCmdOpt * a = arg ;
2006-03-15 15:13:25 +03:00
while ( a ) {
2005-12-08 13:23:34 +03:00
vshCmdOpt * tmp = a ;
2006-03-15 15:13:25 +03:00
2005-12-08 13:23:34 +03:00
a = a - > next ;
if ( tmp - > data )
free ( tmp - > data ) ;
free ( tmp ) ;
}
}
static void
2006-03-15 15:13:25 +03:00
vshCommandFree ( vshCmd * cmd )
{
2005-12-08 13:23:34 +03:00
vshCmd * c = cmd ;
2006-03-15 15:13:25 +03:00
while ( c ) {
2005-12-08 13:23:34 +03:00
vshCmd * tmp = c ;
2006-03-15 15:13:25 +03:00
2005-12-08 13:23:34 +03:00
c = c - > next ;
if ( tmp - > opts )
vshCommandOptFree ( tmp - > opts ) ;
free ( tmp ) ;
}
}
/*
* Returns option by name
*/
static vshCmdOpt *
2006-03-15 15:13:25 +03:00
vshCommandOpt ( vshCmd * cmd , const char * name )
{
2005-12-08 13:23:34 +03:00
vshCmdOpt * opt = cmd - > opts ;
2006-03-15 15:13:25 +03:00
while ( opt ) {
if ( opt - > def & & strcmp ( opt - > def - > name , name ) = = 0 )
2005-12-08 13:23:34 +03:00
return opt ;
opt = opt - > next ;
}
return NULL ;
}
/*
* Returns option as INT
*/
static int
2006-03-15 15:13:25 +03:00
vshCommandOptInt ( vshCmd * cmd , const char * name , int * found )
{
2005-12-08 13:23:34 +03:00
vshCmdOpt * arg = vshCommandOpt ( cmd , name ) ;
int res = 0 ;
2006-03-15 15:13:25 +03:00
2005-12-08 13:23:34 +03:00
if ( arg )
res = atoi ( arg - > data ) ;
if ( found )
* found = arg ? TRUE : FALSE ;
return res ;
}
/*
* Returns option as STRING
*/
static char *
2006-03-15 15:13:25 +03:00
vshCommandOptString ( vshCmd * cmd , const char * name , int * found )
{
2005-12-08 13:23:34 +03:00
vshCmdOpt * arg = vshCommandOpt ( cmd , name ) ;
2006-03-15 15:13:25 +03:00
2005-12-08 13:23:34 +03:00
if ( found )
* found = arg ? TRUE : FALSE ;
2006-01-25 12:46:22 +03:00
return arg & & arg - > data & & * arg - > data ? arg - > data : NULL ;
2005-12-08 13:23:34 +03:00
}
/*
* Returns TRUE / FALSE if the option exists
*/
static int
2006-03-15 15:13:25 +03:00
vshCommandOptBool ( vshCmd * cmd , const char * name )
{
2005-12-08 13:23:34 +03:00
return vshCommandOpt ( cmd , name ) ? TRUE : FALSE ;
}
2006-01-25 12:46:22 +03:00
2005-12-15 20:00:43 +03:00
static virDomainPtr
2006-05-29 19:39:31 +04:00
vshCommandOptDomainBy ( vshControl * ctl , vshCmd * cmd , const char * optname ,
char * * name , int flag )
2006-03-15 15:13:25 +03:00
{
2005-12-15 20:00:43 +03:00
virDomainPtr dom = NULL ;
char * n , * end = NULL ;
int id ;
2006-03-15 15:13:25 +03:00
2005-12-15 20:00:43 +03:00
if ( ! ( n = vshCommandOptString ( cmd , optname , NULL ) ) ) {
vshError ( ctl , FALSE , " undefined domain name or id " ) ;
2006-03-15 15:13:25 +03:00
return NULL ;
2005-12-15 20:00:43 +03:00
}
2006-03-15 15:13:25 +03:00
2006-05-22 18:38:33 +04:00
vshDebug ( ctl , 5 , " %s: found option <%s>: %s \n " ,
2006-03-15 15:13:25 +03:00
cmd - > def - > name , optname , n ) ;
2005-12-15 20:00:43 +03:00
if ( name )
* name = n ;
2006-03-15 15:13:25 +03:00
2005-12-15 20:00:43 +03:00
/* try it by ID */
2006-05-29 19:39:31 +04:00
if ( flag & VSH_DOMBYID ) {
id = ( int ) strtol ( n , & end , 10 ) ;
if ( id > = 0 & & end & & * end = = ' \0 ' ) {
vshDebug ( ctl , 5 , " %s: <%s> seems like domain ID \n " ,
cmd - > def - > name , optname ) ;
dom = virDomainLookupByID ( ctl - > conn , id ) ;
}
2006-01-25 12:46:22 +03:00
}
2006-05-22 18:38:33 +04:00
/* try it by UUID */
2006-05-29 19:39:31 +04:00
if ( dom = = NULL & & ( flag & VSH_DOMBYUUID ) & & strlen ( n ) = = 36 ) {
2006-05-22 18:38:33 +04:00
vshDebug ( ctl , 5 , " %s: <%s> tring as domain UUID \n " ,
cmd - > def - > name , optname ) ;
2006-05-29 19:39:31 +04:00
dom = virDomainLookupByUUIDString ( ctl - > conn , n ) ;
2006-05-22 18:38:33 +04:00
}
2005-12-15 20:00:43 +03:00
/* try it by NAME */
2006-05-29 19:39:31 +04:00
if ( dom = = NULL & & ( flag & VSH_DOMBYNAME ) ) {
2006-05-22 18:38:33 +04:00
vshDebug ( ctl , 5 , " %s: <%s> tring as domain NAME \n " ,
2006-03-15 15:13:25 +03:00
cmd - > def - > name , optname ) ;
2005-12-15 20:00:43 +03:00
dom = virDomainLookupByName ( ctl - > conn , n ) ;
2006-01-25 12:46:22 +03:00
}
2006-05-22 18:38:33 +04:00
2006-03-15 15:13:25 +03:00
if ( ! dom )
2005-12-15 20:00:43 +03:00
vshError ( ctl , FALSE , " failed to get domain '%s' " , n ) ;
2006-03-15 15:13:25 +03:00
2005-12-15 20:00:43 +03:00
return dom ;
}
2005-12-08 13:23:34 +03:00
/*
* Executes command ( s ) and returns return code from last command
*/
static int
2006-03-15 15:13:25 +03:00
vshCommandRun ( vshControl * ctl , vshCmd * cmd )
{
2005-12-08 13:23:34 +03:00
int ret = TRUE ;
2006-03-15 15:13:25 +03:00
while ( cmd ) {
2005-12-08 13:23:34 +03:00
struct timeval before , after ;
2006-03-15 15:13:25 +03:00
2005-12-08 13:23:34 +03:00
if ( ctl - > timing )
GETTIMEOFDAY ( & before ) ;
2006-03-15 15:13:25 +03:00
2005-12-08 13:23:34 +03:00
ret = cmd - > def - > handler ( ctl , cmd ) ;
if ( ctl - > timing )
GETTIMEOFDAY ( & after ) ;
2006-03-15 15:13:25 +03:00
if ( strcmp ( cmd - > def - > name , " quit " ) = = 0 ) /* hack ... */
2005-12-08 13:23:34 +03:00
return ret ;
if ( ctl - > timing )
2006-05-22 18:38:33 +04:00
vshPrint ( ctl , " \n (Time: %.3f ms) \n \n " ,
2006-03-15 15:13:25 +03:00
DIFF_MSEC ( & after , & before ) ) ;
else
2006-05-22 18:38:33 +04:00
vshPrintExtra ( ctl , " \n " ) ;
2005-12-08 13:23:34 +03:00
cmd = cmd - > next ;
}
return ret ;
}
/* ---------------
* Command string parsing
* - - - - - - - - - - - - - - -
*/
# define VSH_TK_ERROR -1
# define VSH_TK_NONE 0
# define VSH_TK_OPTION 1
# define VSH_TK_DATA 2
# define VSH_TK_END 3
2006-03-15 15:13:25 +03:00
static int
vshCommandGetToken ( vshControl * ctl , char * str , char * * end , char * * res )
{
2005-12-08 13:23:34 +03:00
int tk = VSH_TK_NONE ;
int quote = FALSE ;
int sz = 0 ;
char * p = str ;
char * tkstr = NULL ;
2006-03-15 15:13:25 +03:00
2005-12-08 13:23:34 +03:00
* end = NULL ;
2006-03-15 15:13:25 +03:00
while ( p & & * p & & isblank ( ( unsigned char ) * p ) )
2005-12-08 13:23:34 +03:00
p + + ;
2006-03-15 15:13:25 +03:00
if ( p = = NULL | | * p = = ' \0 ' )
2005-12-08 13:23:34 +03:00
return VSH_TK_END ;
2006-03-15 15:13:25 +03:00
if ( * p = = ' ; ' ) {
* end = + + p ; /* = \0 or begi of next command */
2005-12-08 13:23:34 +03:00
return VSH_TK_END ;
}
2006-03-15 15:13:25 +03:00
while ( * p ) {
2005-12-08 13:23:34 +03:00
/* end of token is blank space or ';' */
2006-03-15 15:13:25 +03:00
if ( ( quote = = FALSE & & isblank ( ( unsigned char ) * p ) ) | | * p = = ' ; ' )
2005-12-08 13:23:34 +03:00
break ;
2006-03-15 15:13:25 +03:00
2006-01-25 12:46:22 +03:00
/* end of option name could be '=' */
2006-03-15 15:13:25 +03:00
if ( tk = = VSH_TK_OPTION & & * p = = ' = ' ) {
p + + ; /* skip '=' */
2006-01-25 12:46:22 +03:00
break ;
}
2006-03-15 15:13:25 +03:00
if ( tk = = VSH_TK_NONE ) {
if ( * p = = ' - ' & & * ( p + 1 ) = = ' - ' & & * ( p + 2 )
& & isalnum ( ( unsigned char ) * ( p + 2 ) ) ) {
2005-12-08 13:23:34 +03:00
tk = VSH_TK_OPTION ;
2006-03-15 15:13:25 +03:00
p + = 2 ;
2005-12-08 13:23:34 +03:00
} else {
tk = VSH_TK_DATA ;
2006-03-15 15:13:25 +03:00
if ( * p = = ' " ' ) {
quote = TRUE ;
2005-12-08 13:23:34 +03:00
p + + ;
} else {
quote = FALSE ;
}
}
2006-03-15 15:13:25 +03:00
tkstr = p ; /* begin of token */
} else if ( quote & & * p = = ' " ' ) {
2005-12-08 13:23:34 +03:00
quote = FALSE ;
p + + ;
2006-03-15 15:13:25 +03:00
break ; /* end of "..." token */
2005-12-08 13:23:34 +03:00
}
p + + ;
sz + + ;
}
if ( quote ) {
vshError ( ctl , FALSE , " missing \" " ) ;
return VSH_TK_ERROR ;
}
2006-03-15 15:13:25 +03:00
if ( tkstr = = NULL | | * tkstr = = ' \0 ' | | p = = NULL )
2005-12-08 13:23:34 +03:00
return VSH_TK_END ;
2006-03-15 15:13:25 +03:00
if ( sz = = 0 )
2005-12-08 13:23:34 +03:00
return VSH_TK_END ;
2006-03-15 15:13:25 +03:00
2006-04-06 14:33:06 +04:00
* res = vshMalloc ( ctl , sz + 1 ) ;
2005-12-08 13:23:34 +03:00
memcpy ( * res , tkstr , sz ) ;
2006-03-15 15:13:25 +03:00
* ( * res + sz ) = ' \0 ' ;
2005-12-08 13:23:34 +03:00
* end = p ;
return tk ;
}
static int
2006-03-15 15:13:25 +03:00
vshCommandParse ( vshControl * ctl , char * cmdstr )
{
2005-12-08 13:23:34 +03:00
char * str ;
char * tkdata = NULL ;
vshCmd * clast = NULL ;
vshCmdOpt * first = NULL ;
2006-03-15 15:13:25 +03:00
2005-12-08 13:23:34 +03:00
if ( ctl - > cmd ) {
vshCommandFree ( ctl - > cmd ) ;
ctl - > cmd = NULL ;
}
2006-03-15 15:13:25 +03:00
if ( cmdstr = = NULL | | * cmdstr = = ' \0 ' )
2005-12-08 13:23:34 +03:00
return FALSE ;
2006-03-15 15:13:25 +03:00
2005-12-08 13:23:34 +03:00
str = cmdstr ;
2006-03-15 15:13:25 +03:00
while ( str & & * str ) {
2005-12-08 13:23:34 +03:00
vshCmdOpt * last = NULL ;
vshCmdDef * cmd = NULL ;
int tk = VSH_TK_NONE ;
2006-01-25 12:46:22 +03:00
int data_ct = 0 ;
2006-03-15 15:13:25 +03:00
2005-12-08 13:23:34 +03:00
first = NULL ;
2006-03-15 15:13:25 +03:00
while ( tk ! = VSH_TK_END ) {
2005-12-08 13:23:34 +03:00
char * end = NULL ;
vshCmdOptDef * opt = NULL ;
2006-03-15 15:13:25 +03:00
2005-12-08 13:23:34 +03:00
tkdata = NULL ;
2006-03-15 15:13:25 +03:00
2005-12-08 13:23:34 +03:00
/* get token */
tk = vshCommandGetToken ( ctl , str , & end , & tkdata ) ;
2006-03-15 15:13:25 +03:00
2005-12-08 13:23:34 +03:00
str = end ;
2006-03-15 15:13:25 +03:00
if ( tk = = VSH_TK_END )
2005-12-08 13:23:34 +03:00
break ;
2006-03-15 15:13:25 +03:00
if ( tk = = VSH_TK_ERROR )
2005-12-08 13:23:34 +03:00
goto syntaxError ;
2006-03-15 15:13:25 +03:00
if ( cmd = = NULL ) {
2005-12-08 13:23:34 +03:00
/* first token must be command name */
2006-03-15 15:13:25 +03:00
if ( tk ! = VSH_TK_DATA ) {
vshError ( ctl , FALSE ,
" unexpected token (command name): '%s' " ,
tkdata ) ;
2005-12-08 13:23:34 +03:00
goto syntaxError ;
}
if ( ! ( cmd = vshCmddefSearch ( tkdata ) ) ) {
2006-03-15 15:13:25 +03:00
vshError ( ctl , FALSE , " unknown command: '%s' " , tkdata ) ;
goto syntaxError ; /* ... or ignore this command only? */
2005-12-08 13:23:34 +03:00
}
free ( tkdata ) ;
2006-03-15 15:13:25 +03:00
} else if ( tk = = VSH_TK_OPTION ) {
2005-12-08 13:23:34 +03:00
if ( ! ( opt = vshCmddefGetOption ( cmd , tkdata ) ) ) {
vshError ( ctl , FALSE ,
2006-03-15 15:13:25 +03:00
" command '%s' doesn't support option --%s " ,
cmd - > name , tkdata ) ;
2005-12-08 13:23:34 +03:00
goto syntaxError ;
}
2006-03-15 15:13:25 +03:00
free ( tkdata ) ; /* option name */
2005-12-08 13:23:34 +03:00
tkdata = NULL ;
if ( opt - > type ! = VSH_OT_BOOL ) {
/* option data */
tk = vshCommandGetToken ( ctl , str , & end , & tkdata ) ;
2006-03-15 15:13:25 +03:00
str = end ;
if ( tk = = VSH_TK_ERROR )
2005-12-08 13:23:34 +03:00
goto syntaxError ;
2006-03-15 15:13:25 +03:00
if ( tk ! = VSH_TK_DATA ) {
2005-12-08 13:23:34 +03:00
vshError ( ctl , FALSE ,
2006-03-15 15:13:25 +03:00
" expected syntax: --%s <%s> " ,
opt - > name ,
opt - > type = =
VSH_OT_INT ? " number " : " string " ) ;
2005-12-08 13:23:34 +03:00
goto syntaxError ;
}
}
2006-03-15 15:13:25 +03:00
} else if ( tk = = VSH_TK_DATA ) {
2006-01-25 12:46:22 +03:00
if ( ! ( opt = vshCmddefGetData ( cmd , data_ct + + ) ) ) {
2006-03-15 15:13:25 +03:00
vshError ( ctl , FALSE , " unexpected data '%s' " , tkdata ) ;
2005-12-08 13:23:34 +03:00
goto syntaxError ;
}
}
if ( opt ) {
/* save option */
2006-04-06 14:33:06 +04:00
vshCmdOpt * arg = vshMalloc ( ctl , sizeof ( vshCmdOpt ) ) ;
2006-03-15 15:13:25 +03:00
2005-12-08 13:23:34 +03:00
arg - > def = opt ;
arg - > data = tkdata ;
arg - > next = NULL ;
tkdata = NULL ;
2006-03-15 15:13:25 +03:00
2005-12-08 13:23:34 +03:00
if ( ! first )
first = arg ;
if ( last )
last - > next = arg ;
last = arg ;
2006-03-15 15:13:25 +03:00
2006-05-22 18:38:33 +04:00
vshDebug ( ctl , 4 , " %s: %s(%s): %s \n " ,
2006-03-15 15:13:25 +03:00
cmd - > name ,
opt - > name ,
tk = = VSH_TK_OPTION ? " OPTION " : " DATA " ,
arg - > data ) ;
2005-12-08 13:23:34 +03:00
}
if ( ! str )
break ;
}
2006-03-15 15:13:25 +03:00
2005-12-08 13:23:34 +03:00
/* commad parsed -- allocate new struct for the command */
if ( cmd ) {
2006-04-06 14:33:06 +04:00
vshCmd * c = vshMalloc ( ctl , sizeof ( vshCmd ) ) ;
2006-03-30 16:14:40 +04:00
2005-12-08 13:23:34 +03:00
c - > opts = first ;
c - > def = cmd ;
c - > next = NULL ;
2006-01-25 12:46:22 +03:00
if ( ! vshCommandCheckOpts ( ctl , c ) )
goto syntaxError ;
2006-03-15 15:13:25 +03:00
2005-12-08 13:23:34 +03:00
if ( ! ctl - > cmd )
ctl - > cmd = c ;
if ( clast )
clast - > next = c ;
clast = c ;
}
}
2006-03-15 15:13:25 +03:00
2005-12-08 13:23:34 +03:00
return TRUE ;
2006-03-15 15:13:25 +03:00
syntaxError :
2005-12-08 13:23:34 +03:00
if ( ctl - > cmd )
vshCommandFree ( ctl - > cmd ) ;
if ( first )
vshCommandOptFree ( first ) ;
if ( tkdata )
free ( tkdata ) ;
2006-03-15 15:13:25 +03:00
return FALSE ;
2005-12-08 13:23:34 +03:00
}
/* ---------------
* Misc utils
* - - - - - - - - - - - - - - -
*/
2005-12-08 17:22:52 +03:00
static const char *
2006-03-15 15:13:25 +03:00
vshDomainStateToString ( int state )
{
2005-12-08 13:23:34 +03:00
switch ( state ) {
case VIR_DOMAIN_RUNNING :
2006-03-15 15:13:25 +03:00
return " running " ;
2005-12-08 13:23:34 +03:00
case VIR_DOMAIN_BLOCKED :
return " blocked " ;
case VIR_DOMAIN_PAUSED :
return " paused " ;
case VIR_DOMAIN_SHUTDOWN :
return " in shutdown " ;
case VIR_DOMAIN_SHUTOFF :
return " shut off " ;
2006-05-22 18:38:33 +04:00
case VIR_DOMAIN_CRASHED :
return " crashed " ;
2005-12-08 13:23:34 +03:00
default :
2006-03-15 15:13:25 +03:00
return " no state " ; /* = dom0 state */
2005-12-08 13:23:34 +03:00
}
return NULL ;
}
2006-08-07 18:35:20 +04:00
static const char *
vshDomainVcpuStateToString ( int state )
{
switch ( state ) {
case VIR_VCPU_OFFLINE :
return " offline " ;
case VIR_VCPU_BLOCKED :
return " blocked " ;
case VIR_VCPU_RUNNING :
return " running " ;
default :
return " no state " ;
}
return NULL ;
}
2005-12-08 13:23:34 +03:00
static int
2006-03-15 15:13:25 +03:00
vshConnectionUsability ( vshControl * ctl , virConnectPtr conn , int showerror )
{
2005-12-08 13:23:34 +03:00
/* TODO: use something like virConnectionState() to
* check usability of the connection
*/
if ( ! conn ) {
if ( showerror )
vshError ( ctl , FALSE , " no valid connection. " ) ;
return FALSE ;
}
return TRUE ;
}
2006-05-22 18:38:33 +04:00
static void
vshDebug ( vshControl * ctl , int level , const char * format , . . . )
2006-03-15 15:13:25 +03:00
{
2006-05-22 18:38:33 +04:00
va_list ap ;
if ( level > ctl - > debug )
return ;
va_start ( ap , format ) ;
vfprintf ( stdout , format , ap ) ;
va_end ( ap ) ;
2005-12-08 13:23:34 +03:00
}
static void
2006-05-22 18:38:33 +04:00
vshPrintExtra ( vshControl * ctl , const char * format , . . . )
2006-03-15 15:13:25 +03:00
{
2005-12-08 13:23:34 +03:00
va_list ap ;
2006-03-15 15:13:25 +03:00
2006-05-22 18:38:33 +04:00
if ( ctl - > quiet = = TRUE )
2005-12-08 13:23:34 +03:00
return ;
2006-03-15 15:13:25 +03:00
2005-12-08 13:23:34 +03:00
va_start ( ap , format ) ;
2006-04-06 14:33:06 +04:00
vfprintf ( stdout , format , ap ) ;
2005-12-08 13:23:34 +03:00
va_end ( ap ) ;
}
2006-05-22 18:38:33 +04:00
2005-12-08 13:23:34 +03:00
static void
2006-03-15 15:13:25 +03:00
vshError ( vshControl * ctl , int doexit , const char * format , . . . )
{
2005-12-08 13:23:34 +03:00
va_list ap ;
2006-03-15 15:13:25 +03:00
2005-12-08 13:23:34 +03:00
if ( doexit )
fprintf ( stderr , " %s: error: " , progname ) ;
else
fputs ( " error: " , stderr ) ;
2006-03-15 15:13:25 +03:00
2005-12-08 13:23:34 +03:00
va_start ( ap , format ) ;
vfprintf ( stderr , format , ap ) ;
va_end ( ap ) ;
fputc ( ' \n ' , stderr ) ;
2006-03-15 15:13:25 +03:00
2005-12-08 13:23:34 +03:00
if ( doexit ) {
2006-04-06 14:33:06 +04:00
if ( ctl )
vshDeinit ( ctl ) ;
2005-12-08 13:23:34 +03:00
exit ( EXIT_FAILURE ) ;
}
}
2006-04-06 14:33:06 +04:00
static void *
_vshMalloc ( vshControl * ctl , size_t size , const char * filename , int line )
{
void * x ;
if ( ( x = malloc ( size ) ) )
return x ;
vshError ( ctl , TRUE , " %s: %d: failed to allocate %d bytes \n " ,
filename , line , ( int ) size ) ;
return NULL ;
}
static void *
_vshCalloc ( vshControl * ctl , size_t nmemb , size_t size , const char * filename , int line )
{
void * x ;
if ( ( x = calloc ( nmemb , size ) ) )
return x ;
vshError ( ctl , TRUE , " %s: %d: failed to allocate %d bytes \n " ,
filename , line , ( int ) ( size * nmemb ) ) ;
return NULL ;
}
static char *
_vshStrdup ( vshControl * ctl , const char * s , const char * filename , int line )
{
char * x ;
if ( ( x = strdup ( s ) ) )
return x ;
vshError ( ctl , TRUE , " %s: %d: failed to allocate %d bytes \n " ,
filename , line , strlen ( s ) ) ;
return NULL ;
}
2005-12-08 13:23:34 +03:00
/*
* Initialize vistsh
*/
static int
2006-03-15 15:13:25 +03:00
vshInit ( vshControl * ctl )
{
2005-12-08 13:23:34 +03:00
if ( ctl - > conn )
return FALSE ;
ctl - > uid = getuid ( ) ;
2006-03-15 15:13:25 +03:00
2006-02-28 00:34:28 +03:00
/* set up the library error handler */
virSetErrorFunc ( NULL , virshErrorHandler ) ;
2006-03-15 15:13:25 +03:00
2006-08-16 21:30:33 +04:00
/* basic connection to hypervisor, for Xen connections unless
we ' re root open a read only connections . Allow ' test ' HV
to be RW all the time though */
if ( ctl - > uid = = 0 | | ( ctl - > name & & ! strncmp ( ctl - > name , " test " , 4 ) ) )
2006-05-29 19:39:31 +04:00
ctl - > conn = virConnectOpen ( ctl - > name ) ;
2005-12-08 13:23:34 +03:00
else
2006-05-29 19:39:31 +04:00
ctl - > conn = virConnectOpenReadOnly ( ctl - > name ) ;
2006-03-15 15:13:25 +03:00
2005-12-08 13:23:34 +03:00
if ( ! ctl - > conn )
vshError ( ctl , TRUE , " failed to connect to the hypervisor " ) ;
return TRUE ;
}
/* -----------------
* Readline stuff
* - - - - - - - - - - - - - - - - -
*/
/*
* Generator function for command completion . STATE lets us
* know whether to start from scratch ; without any state
* ( i . e . STATE = = 0 ) , then we start at the top of the list .
*/
static char *
2006-03-15 15:13:25 +03:00
vshReadlineCommandGenerator ( const char * text , int state )
{
2005-12-08 13:23:34 +03:00
static int list_index , len ;
2005-12-08 17:22:52 +03:00
const char * name ;
2005-12-08 13:23:34 +03:00
/* If this is a new word to complete, initialize now. This
* includes saving the length of TEXT for efficiency , and
* initializing the index variable to 0.
*/
if ( ! state ) {
list_index = 0 ;
2006-03-15 15:13:25 +03:00
len = strlen ( text ) ;
2005-12-08 13:23:34 +03:00
}
/* Return the next name which partially matches from the
* command list .
*/
2005-12-08 17:22:52 +03:00
while ( ( name = commands [ list_index ] . name ) ) {
2005-12-08 13:23:34 +03:00
list_index + + ;
2006-03-15 15:13:25 +03:00
if ( strncmp ( name , text , len ) = = 0 )
2006-04-06 14:33:06 +04:00
return vshStrdup ( NULL , name ) ;
2005-12-08 13:23:34 +03:00
}
/* If no names matched, then return NULL. */
return NULL ;
}
static char *
2006-03-15 15:13:25 +03:00
vshReadlineOptionsGenerator ( const char * text , int state )
{
2005-12-08 13:23:34 +03:00
static int list_index , len ;
static vshCmdDef * cmd = NULL ;
2005-12-08 17:22:52 +03:00
const char * name ;
2005-12-08 13:23:34 +03:00
if ( ! state ) {
/* determine command name */
char * p ;
char * cmdname ;
if ( ! ( p = strchr ( rl_line_buffer , ' ' ) ) )
return NULL ;
2006-04-06 14:33:06 +04:00
cmdname = vshCalloc ( NULL , ( p - rl_line_buffer ) + 1 , 1 ) ;
2006-03-15 15:13:25 +03:00
memcpy ( cmdname , rl_line_buffer , p - rl_line_buffer ) ;
2005-12-08 13:23:34 +03:00
cmd = vshCmddefSearch ( cmdname ) ;
list_index = 0 ;
2006-03-15 15:13:25 +03:00
len = strlen ( text ) ;
2005-12-08 13:23:34 +03:00
free ( cmdname ) ;
}
if ( ! cmd )
return NULL ;
2006-03-15 15:13:25 +03:00
2005-12-08 17:22:52 +03:00
while ( ( name = cmd - > opts [ list_index ] . name ) ) {
2005-12-08 13:23:34 +03:00
vshCmdOptDef * opt = & cmd - > opts [ list_index ] ;
char * res ;
2006-03-15 15:13:25 +03:00
2005-12-08 13:23:34 +03:00
list_index + + ;
2006-03-15 15:13:25 +03:00
2005-12-08 17:22:52 +03:00
if ( opt - > type = = VSH_OT_DATA )
2005-12-08 13:23:34 +03:00
/* ignore non --option */
continue ;
2006-03-15 15:13:25 +03:00
2005-12-08 13:23:34 +03:00
if ( len > 2 ) {
2006-03-15 15:13:25 +03:00
if ( strncmp ( name , text + 2 , len - 2 ) )
2005-12-08 13:23:34 +03:00
continue ;
}
2006-04-06 14:33:06 +04:00
res = vshMalloc ( NULL , strlen ( name ) + 3 ) ;
2005-12-08 13:23:34 +03:00
sprintf ( res , " --%s " , name ) ;
return res ;
}
/* If no names matched, then return NULL. */
return NULL ;
}
static char * *
2006-03-15 15:13:25 +03:00
vshReadlineCompletion ( const char * text , int start ,
int end ATTRIBUTE_UNUSED )
{
2005-12-08 13:23:34 +03:00
char * * matches = ( char * * ) NULL ;
2006-03-15 15:13:25 +03:00
if ( start = = 0 )
2005-12-08 13:23:34 +03:00
/* command name generator */
2006-03-15 15:13:25 +03:00
matches = rl_completion_matches ( text , vshReadlineCommandGenerator ) ;
2005-12-08 13:23:34 +03:00
else
/* commands options */
2006-03-15 15:13:25 +03:00
matches = rl_completion_matches ( text , vshReadlineOptionsGenerator ) ;
2005-12-08 13:23:34 +03:00
return matches ;
}
static void
2006-03-15 15:13:25 +03:00
vshReadlineInit ( void )
{
2005-12-08 13:23:34 +03:00
/* Allow conditional parsing of the ~/.inputrc file. */
rl_readline_name = " virsh " ;
/* Tell the completer that we want a crack first. */
rl_attempted_completion_function = vshReadlineCompletion ;
}
/*
* Deinitliaze virsh
*/
static int
2006-03-15 15:13:25 +03:00
vshDeinit ( vshControl * ctl )
{
2005-12-08 13:23:34 +03:00
if ( ctl - > conn ) {
2006-03-15 15:13:25 +03:00
if ( virConnectClose ( ctl - > conn ) ! = 0 ) {
ctl - > conn = NULL ; /* prevent recursive call from vshError() */
vshError ( ctl , TRUE ,
" failed to disconnect from the hypervisor " ) ;
2005-12-08 13:23:34 +03:00
}
}
return TRUE ;
}
2006-03-15 15:13:25 +03:00
2005-12-08 13:23:34 +03:00
/*
* Print usage
*/
static void
2006-03-15 15:13:25 +03:00
vshUsage ( vshControl * ctl , const char * cmdname )
{
2005-12-08 13:23:34 +03:00
vshCmdDef * cmd ;
2006-03-15 15:13:25 +03:00
2005-12-08 13:23:34 +03:00
/* global help */
if ( ! cmdname ) {
fprintf ( stdout , " \n %s [options] [commands] \n \n "
" options: \n "
2006-05-29 19:39:31 +04:00
" -c | --connect <name> optional argument currently unused (or used for tests only) \n "
2005-12-08 13:23:34 +03:00
" -d | --debug <num> debug level [0-5] \n "
" -h | --help this help \n "
" -q | --quiet quiet mode \n "
" -t | --timing print timing information \n "
" -v | --version program version \n \n "
" commands (non interactive mode): \n " , progname ) ;
2006-03-15 15:13:25 +03:00
for ( cmd = commands ; cmd - > name ; cmd + + )
fprintf ( stdout ,
" %-15s %s \n " , cmd - > name , vshCmddefGetInfo ( cmd ,
" help " ) ) ;
fprintf ( stdout ,
" \n (specify --help <command> for details about the command) \n \n " ) ;
2005-12-08 13:23:34 +03:00
return ;
}
if ( ! vshCmddefHelp ( ctl , cmdname , TRUE ) )
exit ( EXIT_FAILURE ) ;
}
/*
* argv [ ] : virsh [ options ] [ command ]
*
*/
static int
2006-03-15 15:13:25 +03:00
vshParseArgv ( vshControl * ctl , int argc , char * * argv )
{
2005-12-08 13:23:34 +03:00
char * last = NULL ;
int i , end = 0 , help = 0 ;
2006-03-15 15:13:25 +03:00
int arg , idx = 0 ;
2005-12-08 13:23:34 +03:00
struct option opt [ ] = {
2006-03-15 15:13:25 +03:00
{ " debug " , 1 , 0 , ' d ' } ,
{ " help " , 0 , 0 , ' h ' } ,
{ " quiet " , 0 , 0 , ' q ' } ,
{ " timing " , 0 , 0 , ' t ' } ,
{ " version " , 0 , 0 , ' v ' } ,
2006-05-29 19:39:31 +04:00
{ " connect " , 1 , 0 , ' c ' } ,
2005-12-08 13:23:34 +03:00
{ 0 , 0 , 0 , 0 }
2006-03-15 15:13:25 +03:00
} ;
2005-12-08 13:23:34 +03:00
if ( argc < 2 )
2005-12-08 17:22:52 +03:00
return TRUE ;
2006-03-15 15:13:25 +03:00
2006-01-25 12:46:22 +03:00
/* look for begin of the command, for example:
2005-12-08 13:23:34 +03:00
* . / virsh - - debug 5 - q command - - cmdoption
* < - - - ^ - - - >
* getopt ( ) stuff | command suff
*/
2006-03-15 15:13:25 +03:00
for ( i = 1 ; i < argc ; i + + ) {
2005-12-08 13:23:34 +03:00
if ( * argv [ i ] ! = ' - ' ) {
int valid = FALSE ;
2006-03-15 15:13:25 +03:00
2005-12-08 13:23:34 +03:00
/* non "--option" argv, is it command? */
if ( last ) {
struct option * o ;
int sz = strlen ( last ) ;
2006-03-15 15:13:25 +03:00
for ( o = opt ; o - > name ; o + + ) {
if ( sz = = 2 & & * ( last + 1 ) = = o - > val )
2005-12-08 13:23:34 +03:00
/* valid virsh short option */
valid = TRUE ;
2006-03-15 15:13:25 +03:00
else if ( sz > 2 & & strcmp ( o - > name , last + 2 ) = = 0 )
2005-12-08 13:23:34 +03:00
/* valid virsh long option */
valid = TRUE ;
}
}
if ( ! valid ) {
end = i ;
break ;
}
}
last = argv [ i ] ;
}
end = end ? : argc ;
2006-03-15 15:13:25 +03:00
2005-12-08 13:23:34 +03:00
/* standard (non-command) options */
2006-03-15 15:13:25 +03:00
while ( ( arg = getopt_long ( end , argv , " d:hqtv " , opt , & idx ) ) ! = - 1 ) {
switch ( arg ) {
2005-12-08 13:23:34 +03:00
case ' d ' :
ctl - > debug = atoi ( optarg ) ;
break ;
case ' h ' :
help = 1 ;
break ;
case ' q ' :
ctl - > quiet = TRUE ;
break ;
case ' t ' :
ctl - > timing = TRUE ;
break ;
2006-05-29 19:39:31 +04:00
case ' c ' :
ctl - > name = vshStrdup ( ctl , optarg ) ;
break ;
2005-12-08 13:23:34 +03:00
case ' v ' :
fprintf ( stdout , " %s \n " , VERSION ) ;
exit ( EXIT_SUCCESS ) ;
default :
2006-03-15 15:13:25 +03:00
vshError ( ctl , TRUE ,
" unsupported option '-%c'. See --help. " , arg ) ;
2005-12-08 13:23:34 +03:00
break ;
}
}
if ( help ) {
/* global or command specific help */
vshUsage ( ctl , argc > end ? argv [ end ] : NULL ) ;
exit ( EXIT_SUCCESS ) ;
2006-03-15 15:13:25 +03:00
}
2005-12-08 13:23:34 +03:00
if ( argc > end ) {
/* parse command */
char * cmdstr ;
2006-03-15 15:13:25 +03:00
int sz = 0 , ret ;
2005-12-08 13:23:34 +03:00
ctl - > imode = FALSE ;
2006-03-15 15:13:25 +03:00
for ( i = end ; i < argc ; i + + )
sz + = strlen ( argv [ i ] ) + 1 ; /* +1 is for blank space between items */
2006-04-06 14:33:06 +04:00
cmdstr = vshCalloc ( ctl , sz + 1 , 1 ) ;
2006-03-15 15:13:25 +03:00
for ( i = end ; i < argc ; i + + ) {
2005-12-08 13:23:34 +03:00
strncat ( cmdstr , argv [ i ] , sz ) ;
sz - = strlen ( argv [ i ] ) ;
strncat ( cmdstr , " " , sz - - ) ;
}
2006-05-22 18:38:33 +04:00
vshDebug ( ctl , 2 , " command: \" %s \" \n " , cmdstr ) ;
2005-12-08 13:23:34 +03:00
ret = vshCommandParse ( ctl , cmdstr ) ;
2006-03-15 15:13:25 +03:00
2005-12-08 13:23:34 +03:00
free ( cmdstr ) ;
return ret ;
}
return TRUE ;
}
2006-03-15 15:13:25 +03:00
int
main ( int argc , char * * argv )
{
vshControl _ctl , * ctl = & _ctl ;
2006-08-26 02:40:33 +04:00
char * defaultConn ;
2005-12-08 13:23:34 +03:00
int ret = TRUE ;
2006-03-15 15:13:25 +03:00
if ( ! ( progname = strrchr ( argv [ 0 ] , ' / ' ) ) )
2005-12-08 13:23:34 +03:00
progname = argv [ 0 ] ;
else
progname + + ;
2006-03-15 15:13:25 +03:00
2005-12-08 13:23:34 +03:00
memset ( ctl , 0 , sizeof ( vshControl ) ) ;
2006-03-15 15:13:25 +03:00
ctl - > imode = TRUE ; /* default is interactive mode */
2005-12-08 13:23:34 +03:00
2006-08-26 02:40:33 +04:00
if ( ( defaultConn = getenv ( " VIRSH_DEFAULT_CONNECT_URI " ) ) ) {
ctl - > name = strdup ( defaultConn ) ;
}
2005-12-08 13:23:34 +03:00
if ( ! vshParseArgv ( ctl , argc , argv ) )
exit ( EXIT_FAILURE ) ;
2006-03-15 15:13:25 +03:00
2005-12-08 13:23:34 +03:00
if ( ! vshInit ( ctl ) )
exit ( EXIT_FAILURE ) ;
2006-03-15 15:13:25 +03:00
2005-12-08 13:23:34 +03:00
if ( ! ctl - > imode ) {
2006-03-15 15:13:25 +03:00
ret = vshCommandRun ( ctl , ctl - > cmd ) ;
2005-12-01 19:35:42 +03:00
} else {
2005-12-08 13:23:34 +03:00
/* interactive mode */
if ( ! ctl - > quiet ) {
2006-05-22 18:38:33 +04:00
vshPrint ( ctl ,
2006-03-15 15:13:25 +03:00
" Welcome to %s, the virtualization interactive terminal. \n \n " ,
progname ) ;
2006-05-22 18:38:33 +04:00
vshPrint ( ctl ,
2006-03-15 15:13:25 +03:00
" Type: 'help' for help with commands \n "
" 'quit' to quit \n \n " ) ;
2005-12-08 13:23:34 +03:00
}
2005-12-08 17:22:52 +03:00
vshReadlineInit ( ) ;
2005-12-08 13:23:34 +03:00
do {
2006-03-15 15:13:25 +03:00
ctl - > cmdstr =
readline ( ctl - > uid = = 0 ? VSH_PROMPT_RW : VSH_PROMPT_RO ) ;
if ( ctl - > cmdstr = = NULL )
break ; /* EOF */
2005-12-08 13:23:34 +03:00
if ( * ctl - > cmdstr ) {
add_history ( ctl - > cmdstr ) ;
if ( vshCommandParse ( ctl , ctl - > cmdstr ) )
vshCommandRun ( ctl , ctl - > cmd ) ;
}
free ( ctl - > cmdstr ) ;
ctl - > cmdstr = NULL ;
2006-03-15 15:13:25 +03:00
} while ( ctl - > imode ) ;
2005-12-08 13:23:34 +03:00
2006-03-15 15:13:25 +03:00
if ( ctl - > cmdstr = = NULL )
fputc ( ' \n ' , stdout ) ; /* line break after alone prompt */
2005-12-08 13:23:34 +03:00
}
2006-03-15 15:13:25 +03:00
2005-12-08 13:23:34 +03:00
vshDeinit ( ctl ) ;
exit ( ret ? EXIT_SUCCESS : EXIT_FAILURE ) ;
2005-11-10 19:12:31 +03:00
}
2005-12-08 13:23:34 +03:00
/*
* vim : set tabstop = 4 :
* vim : set shiftwidth = 4 :
* vim : set expandtab :
*/