2005-11-10 19:12:31 +03:00
/*
2010-06-09 13:00:30 +04:00
* virsh . c : a shell to exercise the libvirt API
2005-11-10 19:12:31 +03:00
*
2012-01-09 22:57:46 +04:00
* Copyright ( C ) 2005 , 2007 - 2012 Red Hat , Inc .
2005-11-10 19:12:31 +03:00
*
* 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-11-10 19:12:31 +03:00
*/
2008-01-29 21:15:54 +03:00
# include <config.h>
2007-12-04 21:27:52 +03:00
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>
2007-05-23 19:09:19 +04:00
# include <errno.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>
2010-05-11 19:32:19 +04:00
# include <sys/wait.h>
start using c-ctype functions
Up to now, we've been avoiding ctype functions like isspace, isdigit,
etc. because they are locale-dependent. Now that we have the c-ctype
functions, we can start using *them*, to make the code more readable
with changes like these:
- /* This may not work on EBCDIC. */
- if ((*p >= 'a' && *p <= 'z') ||
- (*p >= 'A' && *p <= 'Z') ||
- (*p >= '0' && *p <= '9'))
+ if (c_isalnum(*p))
- while ((*cur >= '0') && (*cur <= '9')) {
+ while (c_isdigit(*cur)) {
Also, some macros in conf.c used names that conflicted with
standard meaning of "BLANK" and "SPACE", so I've adjusted them
to be in line with the definition of e.g., isblank.
In addition, I've wrapped those statement macros with do {...} while (0),
so that we can't forget the ";" after a use. There was one like that
already (fixed below). The missing semicolon would mess up automatic
indenting.
* src/buf.c (virBufferURIEncodeString):
* src/conf.c (IS_EOL, SKIP_BLANKS_AND_EOL, SKIP_BLANKS)
(virConfParseLong, virConfParseValue, virConfParseName)
(virConfParseSeparator, virConfParseStatement, IS_BLANK, IS_CHAR)
(IS_DIGIT, IS_SPACE, SKIP_SPACES):
* src/nodeinfo.c:
* src/qemu_conf.c (qemudParseInterfaceXML):
* src/qemu_driver.c (qemudDomainBlockStats):
* src/sexpr.c:
* src/stats_linux.c:
* src/util.c (virParseNumber, virDiskNameToIndex):
* src/uuid.c (hextobin, virUUIDParse):
* src/virsh.c:
* src/xml.c (parseCpuNumber, virParseCpuSet):
2008-05-16 13:37:44 +04:00
# include "c-ctype.h"
2006-03-30 20:08:13 +04:00
# include <fcntl.h>
2006-09-29 20:23:27 +04:00
# include <locale.h>
2007-11-29 12:18:04 +03:00
# include <time.h>
2007-06-15 19:24:20 +04:00
# include <limits.h>
2007-06-05 16:06:08 +04:00
# include <assert.h>
2007-06-06 16:24:31 +04:00
# include <sys/stat.h>
2007-08-21 14:08:12 +04:00
# include <inttypes.h>
2010-03-05 12:59:52 +03:00
# include <signal.h>
2011-01-25 13:14:28 +03:00
# include <poll.h>
2011-07-16 01:49:37 +04:00
# include <strings.h>
2012-05-18 14:21:06 +04:00
# include <termios.h>
2005-12-08 13:23:34 +03:00
2007-01-26 14:54:29 +03:00
# include <libxml/parser.h>
# include <libxml/tree.h>
# include <libxml/xpath.h>
2010-02-17 16:52:07 +03:00
# include <libxml/xmlsave.h>
2007-01-26 14:54:29 +03:00
2007-12-04 21:27:52 +03:00
# ifdef HAVE_READLINE_READLINE_H
2010-03-09 21:22:22 +03:00
# include <readline / readline.h>
# include <readline / history.h>
2007-12-04 21:27:52 +03:00
# endif
2005-12-08 13:23:34 +03:00
Standardize use of header files, making internal.h primary.
* qemud/internal.h, qemud/qemud.h: Rename this file so it
doesn't conflict with src/internal.h.
* HACKING: Document how header files should be used.
* qemud/Makefile.am: Add src/ directory to includes.
* qemud/event.c, qemud/mdns.c, qemud/qemud.c, qemud/remote.c,
qemud/remote_protocol.c, qemud/remote_protocol.h,
qemud/remote_protocol.x, src/buf.c, src/libvirt.c,
src/nodeinfo.c, src/qemu_conf.c, src/qemu_driver.c,
src/stats_linux.c, src/storage_backend.c, src/storage_backend_fs.c,
src/storage_backend_iscsi.c, src/storage_backend_logical.c,
src/storage_conf.c, src/storage_driver.c, src/util.c,
src/util.h, src/virsh.c, src/virterror.c, src/xend_internal.c,
src/xml.c, tests/reconnect.c, tests/xmlrpctest.c,
tests/qparamtest.c: Standardize use of header files.
* docs/*, po/*: Rebuild docs.
2008-05-23 12:24:41 +04:00
# include "internal.h"
2010-01-03 17:45:10 +03:00
# include "virterror_internal.h"
2009-07-28 14:27:25 +04:00
# include "base64.h"
Use safewrite in place of write, in many cases.
Also add "make syntax-check" rules to ensure no new uses sneak in.
There are many uses of write like this:
if (write (fd, xml, towrite) != towrite)
return -1;
The problem is that the syscall can succeed, yet write less than
the requested number of bytes, so the caller should retry
rather than simply failing.
This patch changes most of them to use util.c's safewrite wrapper,
which encapsulates the process. Also, there were a few cases in
which the retry loop was open-coded, and I replaced those, too.
* Makefile.maint (sc_avoid_write): New rule, to avoid recurrence.
* .x-sc_avoid_write: New file. Record two legitimate exemptions.
* qemud/qemud.c (sig_handler, qemudClientWriteBuf): Use safewrite, not write.
* src/conf.c (__virConfWriteFile): Likewise.
* src/qemu_conf.c (qemudSaveConfig, qemudSaveNetworkConfig): Likewise.
* src/qemu_driver.c (qemudWaitForMonitor, qemudStartVMDaemon)
(qemudVMData, PROC_IP_FORWARD): Likewise.
* proxy/libvirt_proxy.c: Include "util.h".
(proxyWriteClientSocket): Use safewrite.
* src/test.c (testDomainSave, testDomainCoreDump): Likewise.
* src/proxy_internal.c (virProxyWriteClientSocket): Likewise.
* src/virsh.c: Include "util-lib.h".
(vshOutputLogFile): Use safewrite.
* src/console.c: Include "util-lib.h".
(vshRunConsole): Use safewrite.
2008-02-22 18:55:04 +03:00
# include "buf.h"
2007-01-26 14:54:29 +03:00
# include "console.h"
2008-01-21 18:27:14 +03:00
# include "util.h"
2010-01-03 19:13:27 +03:00
# include "memory.h"
2010-04-01 00:28:00 +04:00
# include "xml.h"
2010-04-13 22:08:59 +04:00
# include "libvirt/libvirt-qemu.h"
2011-07-19 22:32:58 +04:00
# include "virfile.h"
2011-02-24 20:58:04 +03:00
# include "event_poll.h"
2010-11-16 17:54:17 +03:00
# include "configmake.h"
2011-01-25 13:14:28 +03:00
# include "threads.h"
2011-01-29 00:22:39 +03:00
# include "command.h"
2011-07-21 11:49:10 +04:00
# include "virkeycode.h"
Split src/util/network.{c,h} into 5 pieces
The src/util/network.c file is a dumping ground for many different
APIs. Split it up into 5 pieces, along functional lines
- src/util/virnetdevbandwidth.c: virNetDevBandwidth type & helper APIs
- src/util/virnetdevvportprofile.c: virNetDevVPortProfile type & helper APIs
- src/util/virsocketaddr.c: virSocketAddr and APIs
- src/conf/netdev_bandwidth_conf.c: XML parsing / formatting
for virNetDevBandwidth
- src/conf/netdev_vport_profile_conf.c: XML parsing / formatting
for virNetDevVPortProfile
* src/util/network.c, src/util/network.h: Split into 5 pieces
* src/conf/netdev_bandwidth_conf.c, src/conf/netdev_bandwidth_conf.h,
src/conf/netdev_vport_profile_conf.c, src/conf/netdev_vport_profile_conf.h,
src/util/virnetdevbandwidth.c, src/util/virnetdevbandwidth.h,
src/util/virnetdevvportprofile.c, src/util/virnetdevvportprofile.h,
src/util/virsocketaddr.c, src/util/virsocketaddr.h: New pieces
* daemon/libvirtd.h, daemon/remote.c, src/conf/domain_conf.c,
src/conf/domain_conf.h, src/conf/network_conf.c,
src/conf/network_conf.h, src/conf/nwfilter_conf.h,
src/esx/esx_util.h, src/network/bridge_driver.c,
src/qemu/qemu_conf.c, src/rpc/virnetsocket.c,
src/rpc/virnetsocket.h, src/util/dnsmasq.h, src/util/interface.h,
src/util/iptables.h, src/util/macvtap.c, src/util/macvtap.h,
src/util/virnetdev.h, src/util/virnetdevtap.c,
tools/virsh.c: Update include files
2011-11-02 19:40:08 +04:00
# include "virnetdevbandwidth.h"
2011-06-06 14:20:11 +04:00
# include "util/bitmap.h"
2011-12-20 12:35:03 +04:00
# include "conf/domain_conf.h"
2012-01-03 02:03:19 +04:00
# include "virtypedparam.h"
2012-06-19 17:18:16 +04:00
# include "conf/virdomainlist.h"
2005-12-08 13:23:34 +03:00
static char * progname ;
2008-01-21 18:27:14 +03:00
# define VIRSH_MAX_XML_FILE 10*1024*1024
2005-12-08 13:23:34 +03:00
# define VSH_PROMPT_RW "virsh # "
# define VSH_PROMPT_RO "virsh > "
2011-08-19 01:37:14 +04:00
# define VIR_FROM_THIS VIR_FROM_NONE
2005-12-08 13:23:34 +03:00
# 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 )
2011-11-22 20:08:05 +04:00
/* Default escape char Ctrl-] as per telnet */
# define CTRL_CLOSE_BRACKET "^]"
2007-06-06 16:24:31 +04:00
/**
* The log configuration
*/
# define MSG_BUFFER 4096
# define SIGN_NAME "virsh"
# define DIR_MODE (S_IWUSR | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) /* 0755 */
# define FILE_MODE (S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH) /* 0644 */
# define LOCK_MODE (S_IWUSR | S_IRUSR) /* 0600 */
# define LVL_DEBUG "DEBUG"
# define LVL_INFO "INFO"
# define LVL_NOTICE "NOTICE"
# define LVL_WARNING "WARNING"
# define LVL_ERROR "ERROR"
/**
* vshErrorLevel :
*
2010-05-11 18:02:28 +04:00
* Indicates the level of a log message
2007-06-06 16:24:31 +04:00
*/
typedef enum {
VSH_ERR_DEBUG = 0 ,
VSH_ERR_INFO ,
VSH_ERR_NOTICE ,
VSH_ERR_WARNING ,
VSH_ERR_ERROR
} vshErrorLevel ;
2011-07-14 15:58:02 +04:00
# define VSH_DEBUG_DEFAULT VSH_ERR_ERROR
2005-12-08 13:23:34 +03:00
/*
* virsh command line grammar :
*
* command_line = < command > \ n | < command > ; < command > ; . . .
*
2010-10-13 02:23:18 +04:00
* command = < keyword > < option > [ - - ] < data >
2005-12-08 13:23:34 +03:00
*
* option = < bool_option > | < int_option > | < string_option >
* data = < string >
*
* bool_option = - - optionname
2010-10-13 02:23:18 +04:00
* int_option = - - optionname < number > | - - optionname = < number >
* string_option = - - optionname < string > | - - optionname = < string >
2007-02-07 16:50:18 +03:00
*
2010-10-13 02:23:18 +04:00
* keyword = [ a - zA - Z ] [ a - zA - Z - ] *
2006-01-25 12:46:22 +03:00
* number = [ 0 - 9 ] +
2010-10-13 02:23:18 +04:00
* string = ( ' [ ^ ' ] * ' | " ([^ \\ " ] | \ \ . ) * " |([^ \t \n \\ ' " ] | \ \ . ) ) +
2005-12-08 13:23:34 +03:00
*
*/
/*
2007-02-07 16:50:18 +03:00
* vshCmdOptType - command option type
2006-03-15 15:13:25 +03:00
*/
2005-12-08 13:23:34 +03:00
typedef enum {
2010-10-19 20:27:02 +04:00
VSH_OT_BOOL , /* optional boolean option */
VSH_OT_STRING , /* optional string option */
VSH_OT_INT , /* optional or mandatory int option */
2010-10-15 17:38:49 +04:00
VSH_OT_DATA , /* string data (as non-option) */
2012-03-02 22:01:15 +04:00
VSH_OT_ARGV , /* remaining arguments */
VSH_OT_ALIAS , /* alternate spelling for a later argument */
2005-12-08 13:23:34 +03:00
} vshCmdOptType ;
2010-11-30 09:37:04 +03:00
/*
* Command group types
*/
# define VSH_CMD_GRP_DOM_MANAGEMENT "Domain Management"
# define VSH_CMD_GRP_DOM_MONITORING "Domain Monitoring"
# define VSH_CMD_GRP_STORAGE_POOL "Storage Pool"
# define VSH_CMD_GRP_STORAGE_VOL "Storage Volume"
# define VSH_CMD_GRP_NETWORK "Networking"
# define VSH_CMD_GRP_NODEDEV "Node Device"
# define VSH_CMD_GRP_IFACE "Interface"
# define VSH_CMD_GRP_NWFILTER "Network Filter"
# define VSH_CMD_GRP_SECRET "Secret"
# define VSH_CMD_GRP_SNAPSHOT "Snapshot"
# define VSH_CMD_GRP_HOST_AND_HV "Host and Hypervisor"
# define VSH_CMD_GRP_VIRSH "Virsh itself"
2005-12-08 13:23:34 +03:00
/*
* Command Option Flags
*/
2011-03-14 19:44:37 +03:00
enum {
VSH_OFLAG_NONE = 0 , /* without flags */
VSH_OFLAG_REQ = ( 1 < < 0 ) , /* option required */
VSH_OFLAG_EMPTY_OK = ( 1 < < 1 ) , /* empty string option allowed */
2011-06-07 13:11:10 +04:00
VSH_OFLAG_REQ_OPT = ( 1 < < 2 ) , /* --optionname required */
2011-03-14 19:44:37 +03:00
} ;
2005-12-08 13:23:34 +03:00
/* dummy */
typedef struct __vshControl vshControl ;
typedef struct __vshCmd vshCmd ;
/*
2011-07-15 21:23:17 +04:00
* vshCmdInfo - - name / value pair for information about command
*
* Commands should have at least the following names :
* " name " - command name
* " desc " - description of command , or empty string
2005-12-08 13:23:34 +03:00
*/
2006-03-15 15:13:25 +03:00
typedef struct {
2011-07-15 21:23:17 +04:00
const char * name ; /* name of information, or NULL for list end */
const char * data ; /* non-NULL information */
2005-12-08 13:23:34 +03:00
} vshCmdInfo ;
/*
* vshCmdOptDef - command option definition
*/
2006-03-15 15:13:25 +03:00
typedef struct {
2011-07-15 21:23:17 +04:00
const char * name ; /* the name of option, or NULL for list end */
2006-03-15 15:13:25 +03:00
vshCmdOptType type ; /* option type */
virsh: prefer unsigned flags
virsh had some leftover 'int flags', and even an 'int flag'
declaration, compared to our preferred style of 'unsigned int flags'.
* tools/virsh.c (cmdUndefine, cmdSave, cmdSaveImageDumpxml)
(cmdSaveImageEdit, cmdManagedSave, cmdRestore, cmdDump)
(cmdVcpuPin, cmdSetvcpus, cmdSetmem, cmdSetmaxmem, cmdDumpXML)
(cmdDomXMLFromNative, cmdDomXMLToNative, doMigrate)
(cmdInterfaceEdit, cmdInterfaceDumpXML, cmdEdit): Match coding
style for flags.
(struct vshComdOptDef): Rename field member.
(vshCmddefOptParse, vshCmddefHelp): Adjust clients.
2011-09-01 07:11:23 +04:00
unsigned int flags ; /* flags */
2012-03-02 22:01:15 +04:00
const char * help ; /* non-NULL help string; or for VSH_OT_ALIAS
* the name of a later public option */
2005-12-08 13:23:34 +03:00
} vshCmdOptDef ;
/*
* vshCmdOpt - command options
2011-07-15 21:23:17 +04:00
*
* After parsing a command , all arguments to the command have been
* collected into a list of these objects .
2005-12-08 13:23:34 +03:00
*/
typedef struct vshCmdOpt {
2011-07-15 21:23:17 +04:00
const vshCmdOptDef * def ; /* non-NULL pointer to option definition */
char * data ; /* allocated data, or NULL for bool option */
2006-03-15 15:13:25 +03:00
struct vshCmdOpt * next ;
2005-12-08 13:23:34 +03:00
} vshCmdOpt ;
virsh: optimize creation of default connection
Ramon de Carvalho Valle reported a problem with:
virsh connect qemu:///system
as a non-root user. The real root problem appears to be a regression
in libvirtd being auto-started on the default qemu:///session URI;
however, the symptom points to an independent flaw in virsh - we
shouldn't be wasting efforts on making a connection if we aren't going
to be using that connection. Fixing virsh avoids Ramon's issue, while
I work in the meantime to fix the real libvirtd regression.
This patch looks big, but that's because 'gcc -Wmissing-field-initializers'
gets triggered by './autobuild.sh --enable-compile-warnings=error', so I
had to add 0 initialization to everyone (rather than my preference of
just adding the non-zero flags to virshCmds and to cmdConnect).
Meanwhile, if you use 'virsh -c URI', the connection must succeed; this
patch _only_ optimizes the default connection to be deferred to a later
point where we know if a particular command to be run needs a connection.
* tools/virsh.c (VSH_CMD_FLAG_NOCONNECT): New flag.
(vshCmdDef): Add new flags field.
(vshCommandRun): Honor new flag.
(domManagementCmds, domMonitoringCmds, storagePoolCmds)
(storageVolCmds, networkCmds, nodedevCmds, ifaceCmds)
(nwfilterCmds, secretCmds, virshCmds, snapshotCmds)
(hostAndHypervisorCmds): Populate new field.
(vshReconnect): Don't warn on initial connection.
2011-03-14 23:30:24 +03:00
/*
* Command Usage Flags
*/
enum {
VSH_CMD_FLAG_NOCONNECT = ( 1 < < 0 ) , /* no prior connection needed */
2012-03-02 23:01:06 +04:00
VSH_CMD_FLAG_ALIAS = ( 1 < < 1 ) , /* command is an alias */
virsh: optimize creation of default connection
Ramon de Carvalho Valle reported a problem with:
virsh connect qemu:///system
as a non-root user. The real root problem appears to be a regression
in libvirtd being auto-started on the default qemu:///session URI;
however, the symptom points to an independent flaw in virsh - we
shouldn't be wasting efforts on making a connection if we aren't going
to be using that connection. Fixing virsh avoids Ramon's issue, while
I work in the meantime to fix the real libvirtd regression.
This patch looks big, but that's because 'gcc -Wmissing-field-initializers'
gets triggered by './autobuild.sh --enable-compile-warnings=error', so I
had to add 0 initialization to everyone (rather than my preference of
just adding the non-zero flags to virshCmds and to cmdConnect).
Meanwhile, if you use 'virsh -c URI', the connection must succeed; this
patch _only_ optimizes the default connection to be deferred to a later
point where we know if a particular command to be run needs a connection.
* tools/virsh.c (VSH_CMD_FLAG_NOCONNECT): New flag.
(vshCmdDef): Add new flags field.
(vshCommandRun): Honor new flag.
(domManagementCmds, domMonitoringCmds, storagePoolCmds)
(storageVolCmds, networkCmds, nodedevCmds, ifaceCmds)
(nwfilterCmds, secretCmds, virshCmds, snapshotCmds)
(hostAndHypervisorCmds): Populate new field.
(vshReconnect): Don't warn on initial connection.
2011-03-14 23:30:24 +03:00
} ;
2005-12-08 13:23:34 +03:00
/*
* vshCmdDef - command definition
*/
2006-03-15 15:13:25 +03:00
typedef struct {
2011-07-15 21:23:17 +04:00
const char * name ; /* name of command, or NULL for list end */
2011-04-19 02:37:42 +04:00
bool ( * handler ) ( vshControl * , const vshCmd * ) ; /* command handler */
2008-08-01 16:19:56 +04:00
const vshCmdOptDef * opts ; /* definition of command options */
const vshCmdInfo * info ; /* details about command */
2011-07-07 21:53:04 +04:00
unsigned int flags ; /* bitwise OR of VSH_CMD_FLAG */
2005-12-08 13:23:34 +03:00
} vshCmdDef ;
/*
* vshCmd - parsed command
*/
typedef struct __vshCmd {
2008-08-01 16:19:56 +04:00
const vshCmdDef * def ; /* command definition */
2006-03-15 15:13:25 +03:00
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 */
2007-06-20 21:22:09 +04:00
virConnectPtr conn ; /* connection to hypervisor (MAY BE NULL) */
2006-03-15 15:13:25 +03:00
vshCmd * cmd ; /* the current command */
char * cmdstr ; /* string with command */
2011-04-19 02:37:42 +04:00
bool imode ; /* interactive mode? */
bool quiet ; /* quiet mode */
2006-03-15 15:13:25 +03:00
int debug ; /* print debug messages? */
2011-04-19 02:37:42 +04:00
bool timing ; /* print timing info? */
bool readonly ; /* connect readonly (first time only, not
2007-03-08 16:48:22 +03:00
* during explicit connect command )
*/
2007-06-06 16:24:31 +04:00
char * logfile ; /* log file name */
int log_fd ; /* log file descriptor */
2010-01-03 17:45:10 +03:00
char * historydir ; /* readline history directory name */
char * historyfile ; /* readline history file name */
2011-04-29 12:20:49 +04:00
bool useGetInfo ; /* must use virDomainGetInfo, since
virDomainGetState is not supported */
2011-09-30 01:18:50 +04:00
bool useSnapshotOld ; /* cannot use virDomainSnapshotGetParent or
virDomainSnapshotNumChildren */
2011-10-11 17:05:52 +04:00
virThread eventLoop ;
2011-11-30 23:42:20 +04:00
virMutex lock ;
2011-10-11 17:05:52 +04:00
bool eventLoopStarted ;
bool quit ;
2011-11-22 20:08:05 +04:00
const char * escapeChar ; /* String representation of
console escape character */
2005-12-08 13:23:34 +03:00
} __vshControl ;
2005-11-10 19:12:31 +03:00
2010-11-30 09:37:04 +03:00
typedef struct vshCmdGrp {
2011-07-15 21:23:17 +04:00
const char * name ; /* name of group, or NULL for list end */
2010-11-30 09:37:04 +03:00
const char * keyword ; /* help keyword */
const vshCmdDef * commands ;
} vshCmdGrp ;
2005-12-02 17:16:21 +03:00
2010-11-30 09:37:04 +03:00
static const vshCmdGrp cmdGroups [ ] ;
2005-12-08 13:23:34 +03:00
2009-09-29 15:42:42 +04:00
static void vshError ( vshControl * ctl , const char * format , . . . )
ATTRIBUTE_FMT_PRINTF ( 2 , 3 ) ;
2011-04-19 02:37:42 +04:00
static bool vshInit ( vshControl * ctl ) ;
static bool vshDeinit ( vshControl * ctl ) ;
2008-12-08 16:14:48 +03:00
static void vshUsage ( void ) ;
2007-06-06 16:24:31 +04:00
static void vshOpenLogFile ( vshControl * ctl ) ;
2010-07-16 19:38:10 +04:00
static void vshOutputLogFile ( vshControl * ctl , int log_level , const char * format , va_list ap )
ATTRIBUTE_FMT_PRINTF ( 3 , 0 ) ;
2007-06-06 16:24:31 +04:00
static void vshCloseLogFile ( vshControl * ctl ) ;
2005-12-08 13:23:34 +03:00
2011-04-19 02:37:42 +04:00
static bool vshParseArgv ( vshControl * ctl , int argc , char * * argv ) ;
2005-12-08 13:23:34 +03:00
2008-08-01 17:51:18 +04:00
static const char * vshCmddefGetInfo ( const vshCmdDef * cmd , const char * info ) ;
2008-08-01 16:19:56 +04:00
static const vshCmdDef * vshCmddefSearch ( const char * cmdname ) ;
2011-04-19 02:37:42 +04:00
static bool vshCmddefHelp ( vshControl * ctl , const char * name ) ;
2010-11-30 09:37:04 +03:00
static const vshCmdGrp * vshCmdGrpSearch ( const char * grpname ) ;
2011-04-19 02:37:42 +04:00
static bool vshCmdGrpHelp ( vshControl * ctl , const char * name ) ;
2005-12-08 13:23:34 +03:00
2011-07-15 21:23:17 +04:00
static int vshCommandOpt ( const vshCmd * cmd , const char * name , vshCmdOpt * * opt )
ATTRIBUTE_NONNULL ( 1 ) ATTRIBUTE_NONNULL ( 2 ) ATTRIBUTE_NONNULL ( 3 )
ATTRIBUTE_RETURN_CHECK ;
2011-03-08 19:29:31 +03:00
static int vshCommandOptInt ( const vshCmd * cmd , const char * name , int * value )
ATTRIBUTE_NONNULL ( 3 ) ATTRIBUTE_RETURN_CHECK ;
2011-05-12 20:29:12 +04:00
static int vshCommandOptUInt ( const vshCmd * cmd , const char * name ,
unsigned int * value )
ATTRIBUTE_NONNULL ( 3 ) ATTRIBUTE_RETURN_CHECK ;
2011-03-08 19:29:31 +03:00
static int vshCommandOptUL ( const vshCmd * cmd , const char * name ,
unsigned long * value )
ATTRIBUTE_NONNULL ( 3 ) ATTRIBUTE_RETURN_CHECK ;
static int vshCommandOptString ( const vshCmd * cmd , const char * name ,
const char * * value )
ATTRIBUTE_NONNULL ( 3 ) ATTRIBUTE_RETURN_CHECK ;
static int vshCommandOptLongLong ( const vshCmd * cmd , const char * name ,
long long * value )
ATTRIBUTE_NONNULL ( 3 ) ATTRIBUTE_RETURN_CHECK ;
2009-07-14 17:24:53 +04:00
static int vshCommandOptULongLong ( const vshCmd * cmd , const char * name ,
unsigned long long * value )
ATTRIBUTE_NONNULL ( 3 ) ATTRIBUTE_RETURN_CHECK ;
2012-03-08 05:10:30 +04:00
static int vshCommandOptScaledInt ( const vshCmd * cmd , const char * name ,
unsigned long long * value , int scale ,
unsigned long long max )
ATTRIBUTE_NONNULL ( 3 ) ATTRIBUTE_RETURN_CHECK ;
2011-04-19 02:37:42 +04:00
static bool vshCommandOptBool ( const vshCmd * cmd , const char * name ) ;
2011-06-14 21:26:20 +04:00
static const vshCmdOpt * vshCommandOptArgv ( const vshCmd * cmd ,
const vshCmdOpt * opt ) ;
2012-02-01 17:03:51 +04:00
static char * vshGetDomainDescription ( vshControl * ctl , virDomainPtr dom ,
bool title , unsigned int flags )
ATTRIBUTE_NONNULL ( 1 ) ATTRIBUTE_NONNULL ( 2 ) ATTRIBUTE_RETURN_CHECK ;
2006-05-29 19:39:31 +04:00
2007-02-14 18:44:58 +03:00
# define VSH_BYID (1 << 1)
# define VSH_BYUUID (1 << 2)
# define VSH_BYNAME (1 << 3)
2009-07-16 23:44:10 +04:00
# define VSH_BYMAC (1 << 4)
2006-05-29 19:39:31 +04:00
2008-08-01 17:51:18 +04:00
static virDomainPtr vshCommandOptDomainBy ( vshControl * ctl , const vshCmd * cmd ,
2011-03-08 19:29:30 +03:00
const char * * name , int flag ) ;
2006-05-29 19:39:31 +04:00
/* default is lookup by Id, Name and UUID */
remove redundant optname arguments
This is the second part of the change mentioned here:
http://thread.gmane.org/gmane.comp.emulators.libvirt/10331
It removes the essentially redundant "optname" parameter
from each of the vshCommandOptNetworkBy and vshCommandOptDomainBy
functions as well as the correspond macros (without "By" suffix).
Now, instead of always passing the optname, "domain", to
vshCommandOptDomainBy, that function requires that its command
argument refer to an opts array containing a "domain" option.
This normalization makes one more help-related change:
it renames the net-start "name" argument to the more
sensible and consistent "network".
* src/virsh.c (VSH_BYNAME, vshCommandOptDomain)
(cmd_has_option): New function, used in vshCommandOptDomainBy
and vshCommandOptNetworkBy.
(vshCommandOptDomainBy, vshCommandOptNetworkBy): Remove the optname
parameter, it's always "domain" ("network"). Update all callers.
Call cmd_has_option.
(vshCommandOptNetwork, cmdAutostart, cmdConsole, cmdDomstate)
(cmdDomblkstat, cmdDomIfstat, cmdSuspend, cmdUndefine, cmdStart)
(cmdSave, cmdSchedinfo, cmdDump, cmdResume, cmdShutdown)
(cmdReboot, cmdDestroy, cmdDominfo, cmdVcpuinfo, cmdVcpupin)
(cmdSetvcpus, cmdSetmem, cmdSetmaxmem, cmdDumpXML, cmdDomname)
(cmdDomid, cmdDomuuid, cmdMigrate, cmdNetworkAutostart)
(cmdNetworkDestroy, cmdNetworkDumpXML, cmdNetworkName)
(opts_network_start, cmdNetworkStart, cmdNetworkUndefine)
(cmdNetworkUuid, cmdVNCDisplay, cmdTTYConsole, cmdAttachDevice)
(cmdDetachDevice, cmdAttachInterface, cmdDetachInterface)
(cmdAttachDisk, cmdDetachDisk, cmdEdit)
* src/Makefile.am (virsh-pool-edit.c): This code is generated
from cmdEdit, and cmdEdit uses the vshCommandOptDomain macro which
now, with the changes above, has only 3 (was 4) arguments, yet the
macro use is mapped to vshCommandOptPool, which still requires 4
arguments. So this change adjusts the sed code to reinsert the
just-removed argument -- we're not changing pool-related code right
now, because it's not as straight-forward.
2008-12-15 13:26:54 +03:00
# define vshCommandOptDomain(_ctl, _cmd, _name) \
vshCommandOptDomainBy ( _ctl , _cmd , _name , VSH_BYID | VSH_BYUUID | VSH_BYNAME )
2007-02-14 18:44:58 +03:00
2008-08-01 17:51:18 +04:00
static virNetworkPtr vshCommandOptNetworkBy ( vshControl * ctl , const vshCmd * cmd ,
2011-03-08 19:29:30 +03:00
const char * * name , int flag ) ;
2007-02-14 19:53:55 +03:00
/* default is lookup by Name and UUID */
remove redundant optname arguments
This is the second part of the change mentioned here:
http://thread.gmane.org/gmane.comp.emulators.libvirt/10331
It removes the essentially redundant "optname" parameter
from each of the vshCommandOptNetworkBy and vshCommandOptDomainBy
functions as well as the correspond macros (without "By" suffix).
Now, instead of always passing the optname, "domain", to
vshCommandOptDomainBy, that function requires that its command
argument refer to an opts array containing a "domain" option.
This normalization makes one more help-related change:
it renames the net-start "name" argument to the more
sensible and consistent "network".
* src/virsh.c (VSH_BYNAME, vshCommandOptDomain)
(cmd_has_option): New function, used in vshCommandOptDomainBy
and vshCommandOptNetworkBy.
(vshCommandOptDomainBy, vshCommandOptNetworkBy): Remove the optname
parameter, it's always "domain" ("network"). Update all callers.
Call cmd_has_option.
(vshCommandOptNetwork, cmdAutostart, cmdConsole, cmdDomstate)
(cmdDomblkstat, cmdDomIfstat, cmdSuspend, cmdUndefine, cmdStart)
(cmdSave, cmdSchedinfo, cmdDump, cmdResume, cmdShutdown)
(cmdReboot, cmdDestroy, cmdDominfo, cmdVcpuinfo, cmdVcpupin)
(cmdSetvcpus, cmdSetmem, cmdSetmaxmem, cmdDumpXML, cmdDomname)
(cmdDomid, cmdDomuuid, cmdMigrate, cmdNetworkAutostart)
(cmdNetworkDestroy, cmdNetworkDumpXML, cmdNetworkName)
(opts_network_start, cmdNetworkStart, cmdNetworkUndefine)
(cmdNetworkUuid, cmdVNCDisplay, cmdTTYConsole, cmdAttachDevice)
(cmdDetachDevice, cmdAttachInterface, cmdDetachInterface)
(cmdAttachDisk, cmdDetachDisk, cmdEdit)
* src/Makefile.am (virsh-pool-edit.c): This code is generated
from cmdEdit, and cmdEdit uses the vshCommandOptDomain macro which
now, with the changes above, has only 3 (was 4) arguments, yet the
macro use is mapped to vshCommandOptPool, which still requires 4
arguments. So this change adjusts the sed code to reinsert the
just-removed argument -- we're not changing pool-related code right
now, because it's not as straight-forward.
2008-12-15 13:26:54 +03:00
# define vshCommandOptNetwork(_ctl, _cmd, _name) \
vshCommandOptNetworkBy ( _ctl , _cmd , _name , \
2007-02-14 19:53:55 +03:00
VSH_BYUUID | VSH_BYNAME )
2010-03-25 20:46:06 +03:00
static virNWFilterPtr vshCommandOptNWFilterBy ( vshControl * ctl , const vshCmd * cmd ,
2011-03-08 19:29:30 +03:00
const char * * name , int flag ) ;
2010-03-25 20:46:06 +03:00
/* default is lookup by Name and UUID */
# define vshCommandOptNWFilter(_ctl, _cmd, _name) \
vshCommandOptNWFilterBy ( _ctl , _cmd , _name , \
VSH_BYUUID | VSH_BYNAME )
2009-07-16 23:44:10 +04:00
static virInterfacePtr vshCommandOptInterfaceBy ( vshControl * ctl , const vshCmd * cmd ,
virsh: add iface-bridge and iface-unbridge commands
One of the top questions by libvirt users is how to create a host
bridge device so that guests can be directly on the physical
network. There are several example documents that explain how to do
this manually, but following them often results in confusion and
failure. virt-manager does a good job of creating a bridge based on an
existing network device, but not everyone wants to use virt-manager.
This patch adds a new command, iface-bridge that makes it just about
as simple as possible to create a new bridge device based on an
existing ethernet/vlan/bond device (including associating IP
configuration with the bridge rather than the now-attached device),
and start that new bridge up ready for action, eg:
virsh iface-bridge eth0 br0
For symmetry's sake, it also adds a command to remove a device from a
bridge, restoring the IP config to the now-unattached device:
virsh iface-unbridge br0
(I had a short debate about whether to do "iface-unbridge eth0"
instead, but that would involve searching through all bridge devices
for the one that contained eth0, which seems like a bit too much
trouble).
NOTE: These two commands require that the netcf library be available
on the host. Hopefully this will provide some extra incentive for
people using suse, debian, ubuntu, and other similar systems to polish
up (and push downstream) the ports to those distros recently pushed to
the upstream netcf repo by Dan Berrange. Anyone interested in helping
with that effort in any way should join the netcf-devel mailing list
(subscription info at
https://fedorahosted.org/mailman/listinfo/netcf-devel)
During creation of the bridge, it's possible to specify whether or not
the STP protocol should be started up on the bridge and, if so, how
many seconds the bridge should squelch traffic from newly added
devices while learning new topology (defaults are stp='on' and
delay='0', which seems to usually work best for bridges used in the
context of libvirt guests).
There is also an option to not immediately start the bridge (and a
similar option to not immediately start the un-attached device after
destroying the bridge. Default is to start the new device, because in
the case of iface-unbridge not starting is strongly discouraged as it
will leave the system with no network connectivity on that interface
(because it's necessary to destroy/undefine the bridge device before
the unattached device can be defined), and it seemed better to make
the option for iface-bridge behave consistently.
NOTE TO THOSE TRYING THESE COMMANDS FOR THE FIRST TIME: to guard
against any "unexpected" change to configuration, it is advisable to
issue an "virsh iface-begin" command before starting any interface
config changes, and "virsh iface-commit" only after you've verified
that everything is working as you expect. If something goes wrong,
you can always run "virsh iface-rollback" or reboot the system (which
should automatically do iface-rollback).
Aside from adding the code for these two functions, and the two
entries into the command table, the only other change to virsh.c was
to add the option name to vshCommandOptInterfaceBy(), because the
iface-unbridge command names its interface option as "bridge".
virsh.pod has also been updated with short descriptions of these two
new commands.
2011-11-07 20:15:58 +04:00
const char * optname ,
2011-03-08 19:29:30 +03:00
const char * * name , int flag ) ;
2009-07-16 23:44:10 +04:00
/* default is lookup by Name and MAC */
# define vshCommandOptInterface(_ctl, _cmd, _name) \
virsh: add iface-bridge and iface-unbridge commands
One of the top questions by libvirt users is how to create a host
bridge device so that guests can be directly on the physical
network. There are several example documents that explain how to do
this manually, but following them often results in confusion and
failure. virt-manager does a good job of creating a bridge based on an
existing network device, but not everyone wants to use virt-manager.
This patch adds a new command, iface-bridge that makes it just about
as simple as possible to create a new bridge device based on an
existing ethernet/vlan/bond device (including associating IP
configuration with the bridge rather than the now-attached device),
and start that new bridge up ready for action, eg:
virsh iface-bridge eth0 br0
For symmetry's sake, it also adds a command to remove a device from a
bridge, restoring the IP config to the now-unattached device:
virsh iface-unbridge br0
(I had a short debate about whether to do "iface-unbridge eth0"
instead, but that would involve searching through all bridge devices
for the one that contained eth0, which seems like a bit too much
trouble).
NOTE: These two commands require that the netcf library be available
on the host. Hopefully this will provide some extra incentive for
people using suse, debian, ubuntu, and other similar systems to polish
up (and push downstream) the ports to those distros recently pushed to
the upstream netcf repo by Dan Berrange. Anyone interested in helping
with that effort in any way should join the netcf-devel mailing list
(subscription info at
https://fedorahosted.org/mailman/listinfo/netcf-devel)
During creation of the bridge, it's possible to specify whether or not
the STP protocol should be started up on the bridge and, if so, how
many seconds the bridge should squelch traffic from newly added
devices while learning new topology (defaults are stp='on' and
delay='0', which seems to usually work best for bridges used in the
context of libvirt guests).
There is also an option to not immediately start the bridge (and a
similar option to not immediately start the un-attached device after
destroying the bridge. Default is to start the new device, because in
the case of iface-unbridge not starting is strongly discouraged as it
will leave the system with no network connectivity on that interface
(because it's necessary to destroy/undefine the bridge device before
the unattached device can be defined), and it seemed better to make
the option for iface-bridge behave consistently.
NOTE TO THOSE TRYING THESE COMMANDS FOR THE FIRST TIME: to guard
against any "unexpected" change to configuration, it is advisable to
issue an "virsh iface-begin" command before starting any interface
config changes, and "virsh iface-commit" only after you've verified
that everything is working as you expect. If something goes wrong,
you can always run "virsh iface-rollback" or reboot the system (which
should automatically do iface-rollback).
Aside from adding the code for these two functions, and the two
entries into the command table, the only other change to virsh.c was
to add the option name to vshCommandOptInterfaceBy(), because the
iface-unbridge command names its interface option as "bridge".
virsh.pod has also been updated with short descriptions of these two
new commands.
2011-11-07 20:15:58 +04:00
vshCommandOptInterfaceBy ( _ctl , _cmd , NULL , _name , \
VSH_BYMAC | VSH_BYNAME )
2009-07-16 23:44:10 +04:00
2009-07-28 14:27:25 +04:00
static virSecretPtr vshCommandOptSecret ( vshControl * ctl , const vshCmd * cmd ,
2011-03-08 19:29:30 +03:00
const char * * name ) ;
2009-07-28 14:27:25 +04:00
2008-08-01 17:51:18 +04:00
static void vshPrintExtra ( vshControl * ctl , const char * format , . . . )
Fix misc Win32 compile warnings
GCC >= 4.4 assumes the 'printf' attribute refers to the native
runtime libraries format specifiers. Thanks to gnulib, libvirt
has GNU format specifiers everywhere. This means we need to
use 'gnu_printf' with GCC >= 4.4 to get correct compiler
checking of printf format specifiers.
* HACKING: Document new rules for ATTRIBUTE_FMT_PRINTF
* autobuild.sh, mingw32-libvirt.spec.in: Disable OpenNebula
driver on mingw32 builds
* qemud/dispatch.h, qemud/qemu.h, src/buf.h src/internal.h,
src/logging.h, src/security.h, src/sexpr.h, src/util.h,
src/virterror_internal.h, src/xend_internal.c: Change
over to ATTRIBUTE_FMT_PRINTF.
* src/virsh.c: Disable 'cd' and 'pwd' commands on Win32
since they don't compile
* src/threads-win32.c: Add missing return value check
2009-07-23 19:07:32 +04:00
ATTRIBUTE_FMT_PRINTF ( 2 , 3 ) ;
2008-08-01 17:51:18 +04:00
static void vshDebug ( vshControl * ctl , int level , const char * format , . . . )
Fix misc Win32 compile warnings
GCC >= 4.4 assumes the 'printf' attribute refers to the native
runtime libraries format specifiers. Thanks to gnulib, libvirt
has GNU format specifiers everywhere. This means we need to
use 'gnu_printf' with GCC >= 4.4 to get correct compiler
checking of printf format specifiers.
* HACKING: Document new rules for ATTRIBUTE_FMT_PRINTF
* autobuild.sh, mingw32-libvirt.spec.in: Disable OpenNebula
driver on mingw32 builds
* qemud/dispatch.h, qemud/qemu.h, src/buf.h src/internal.h,
src/logging.h, src/security.h, src/sexpr.h, src/util.h,
src/virterror_internal.h, src/xend_internal.c: Change
over to ATTRIBUTE_FMT_PRINTF.
* src/virsh.c: Disable 'cd' and 'pwd' commands on Win32
since they don't compile
* src/threads-win32.c: Add missing return value check
2009-07-23 19:07:32 +04:00
ATTRIBUTE_FMT_PRINTF ( 3 , 4 ) ;
2006-05-29 19:39:31 +04:00
/* XXX: add batch support */
2011-02-12 03:17:12 +03:00
# define vshPrint(_ctl, ...) vshPrintExtra(NULL, __VA_ARGS__)
2005-12-08 13:23:34 +03:00
2011-04-29 12:20:49 +04:00
static int vshDomainState ( vshControl * ctl , virDomainPtr dom , int * reason ) ;
2005-12-08 17:22:52 +03:00
static const char * vshDomainStateToString ( int state ) ;
2011-04-29 12:20:49 +04:00
static const char * vshDomainStateReasonToString ( int state , int reason ) ;
2011-05-31 20:21:58 +04:00
static const char * vshDomainControlStateToString ( int state ) ;
2006-08-07 18:35:20 +04:00
static const char * vshDomainVcpuStateToString ( int state ) ;
2011-04-19 02:37:42 +04:00
static bool vshConnectionUsability ( vshControl * ctl , virConnectPtr conn ) ;
2011-09-19 16:23:12 +04:00
static virTypedParameterPtr vshFindTypedParamByName ( const char * name ,
virTypedParameterPtr list ,
int count ) ;
2011-12-20 03:06:08 +04:00
static char * vshGetTypedParamValue ( vshControl * ctl , virTypedParameterPtr item )
ATTRIBUTE_NONNULL ( 1 ) ATTRIBUTE_NONNULL ( 2 ) ;
2005-12-08 13:23:34 +03:00
2012-04-15 02:35:22 +04:00
static char * editWriteToTempFile ( vshControl * ctl , const char * doc ) ;
static int editFile ( vshControl * ctl , const char * filename ) ;
static char * editReadBackFile ( vshControl * ctl , const char * filename ) ;
2009-07-16 23:44:10 +04:00
2011-12-20 17:04:28 +04:00
/* Typedefs, function prototypes for job progress reporting.
* There are used by some long lingering commands like
* migrate , dump , save , managedsave .
*/
typedef struct __vshCtrlData {
vshControl * ctl ;
const vshCmd * cmd ;
int writefd ;
} vshCtrlData ;
typedef void ( * jobWatchTimeoutFunc ) ( vshControl * ctl , virDomainPtr dom ,
void * opaque ) ;
static bool
vshWatchJob ( vshControl * ctl ,
virDomainPtr dom ,
bool verbose ,
int pipe_fd ,
int timeout ,
jobWatchTimeoutFunc timeout_func ,
void * opaque ,
const char * label ) ;
2008-08-01 17:51:18 +04:00
static void * _vshMalloc ( vshControl * ctl , size_t sz , const char * filename , int line ) ;
2006-04-06 14:33:06 +04:00
# define vshMalloc(_ctl, _sz) _vshMalloc(_ctl, _sz, __FILE__, __LINE__)
2008-08-01 17:51:18 +04:00
static void * _vshCalloc ( vshControl * ctl , size_t nmemb , size_t sz , const char * filename , int line ) ;
2006-04-06 14:33:06 +04:00
# define vshCalloc(_ctl, _nmemb, _sz) _vshCalloc(_ctl, _nmemb, _sz, __FILE__, __LINE__)
2008-08-01 17:51:18 +04:00
static char * _vshStrdup ( vshControl * ctl , const char * s , const char * filename , int line ) ;
2006-04-06 14:33:06 +04:00
# define vshStrdup(_ctl, _s) _vshStrdup(_ctl, _s, __FILE__, __LINE__)
2011-12-29 11:33:21 +04:00
static int parseRateStr ( const char * rateStr , virNetDevBandwidthRatePtr rate ) ;
2010-10-12 21:24:00 +04:00
static void *
_vshMalloc ( vshControl * ctl , size_t size , const char * filename , int line )
{
2012-02-03 02:47:04 +04:00
char * x ;
2010-10-12 21:24:00 +04:00
2012-02-03 02:47:04 +04:00
if ( VIR_ALLOC_N ( x , size ) = = 0 )
2010-10-12 21:24:00 +04:00
return x ;
vshError ( ctl , _ ( " %s: %d: failed to allocate %d bytes " ) ,
filename , line , ( int ) size ) ;
exit ( EXIT_FAILURE ) ;
}
static void *
_vshCalloc ( vshControl * ctl , size_t nmemb , size_t size , const char * filename , int line )
{
2012-02-03 02:47:04 +04:00
char * x ;
2010-10-12 21:24:00 +04:00
2012-02-03 02:47:04 +04:00
if ( ! xalloc_oversized ( nmemb , size ) & &
VIR_ALLOC_N ( x , nmemb * size ) = = 0 )
2010-10-12 21:24:00 +04:00
return x ;
vshError ( ctl , _ ( " %s: %d: failed to allocate %d bytes " ) ,
filename , line , ( int ) ( size * nmemb ) ) ;
exit ( EXIT_FAILURE ) ;
}
static char *
_vshStrdup ( vshControl * ctl , const char * s , const char * filename , int line )
{
char * x ;
if ( s = = NULL )
2012-03-22 15:33:35 +04:00
return NULL ;
2010-10-12 21:24:00 +04:00
if ( ( x = strdup ( s ) ) )
return x ;
vshError ( ctl , _ ( " %s: %d: failed to allocate %lu bytes " ) ,
filename , line , ( unsigned long ) strlen ( s ) ) ;
exit ( EXIT_FAILURE ) ;
}
/* Poison the raw allocating identifiers in favor of our vsh variants. */
# undef malloc
# undef calloc
# undef realloc
# undef strdup
# define malloc use_vshMalloc_instead_of_malloc
# define calloc use_vshCalloc_instead_of_calloc
# define realloc use_vshRealloc_instead_of_realloc
# define strdup use_vshStrdup_instead_of_strdup
2007-02-14 18:44:58 +03:00
2012-06-19 17:13:47 +04:00
static int
vshNameSorter ( const void * a , const void * b )
{
const char * * sa = ( const char * * ) a ;
const char * * sb = ( const char * * ) b ;
2007-02-14 18:44:58 +03:00
2012-06-19 17:13:47 +04:00
/* User visible sort, so we want locale-specific case comparison. */
return strcasecmp ( * sa , * sb ) ;
2007-02-14 18:44:58 +03:00
}
2010-02-03 19:45:05 +03:00
static double
prettyCapacity ( unsigned long long val ,
const char * * unit ) {
if ( val < 1024 ) {
* unit = " " ;
return ( double ) val ;
} else if ( val < ( 1024.0 l * 1024.0 l ) ) {
2012-05-01 00:27:56 +04:00
* unit = " KiB " ;
2010-02-03 19:45:05 +03:00
return ( ( ( double ) val / 1024.0 l ) ) ;
} else if ( val < ( 1024.0 l * 1024.0 l * 1024.0 l ) ) {
2012-05-01 00:27:56 +04:00
* unit = " MiB " ;
2012-03-22 15:33:35 +04:00
return ( double ) val / ( 1024.0 l * 1024.0 l ) ;
2010-02-03 19:45:05 +03:00
} else if ( val < ( 1024.0 l * 1024.0 l * 1024.0 l * 1024.0 l ) ) {
2012-05-01 00:27:56 +04:00
* unit = " GiB " ;
2012-03-22 15:33:35 +04:00
return ( double ) val / ( 1024.0 l * 1024.0 l * 1024.0 l ) ;
2010-02-03 19:45:05 +03:00
} else {
2012-05-01 00:27:56 +04:00
* unit = " TiB " ;
2012-03-22 15:33:35 +04:00
return ( double ) val / ( 1024.0 l * 1024.0 l * 1024.0 l * 1024.0 l ) ;
2010-02-03 19:45:05 +03:00
}
}
2009-02-09 17:24:06 +03:00
static virErrorPtr last_error ;
/*
* Quieten libvirt until we ' re done with the command .
*/
static void
virshErrorHandler ( void * unused ATTRIBUTE_UNUSED , virErrorPtr error )
{
virFreeError ( last_error ) ;
last_error = virSaveLastError ( ) ;
if ( getenv ( " VIRSH_DEBUG " ) ! = NULL )
virDefaultErrorFunc ( error ) ;
}
/*
* Report an error when a command finishes . This is better than before
* ( when correct operation would report errors ) , but it has some
* problems : we lose the smarter formatting of virDefaultErrorFunc ( ) ,
* and it can become harder to debug problems , if errors get reported
* twice during one command . This case shouldn ' t really happen anyway ,
* and it ' s IMHO a bug that libvirt does that sometimes .
*/
static void
virshReportError ( vshControl * ctl )
{
2010-02-24 19:13:00 +03:00
if ( last_error = = NULL ) {
/* Calling directly into libvirt util functions won't trigger the
* error callback ( which sets last_error ) , so check it ourselves .
*
* If the returned error has CODE_OK , this most likely means that
* no error was ever raised , so just ignore */
last_error = virSaveLastError ( ) ;
if ( ! last_error | | last_error - > code = = VIR_ERR_OK )
2010-06-18 18:14:04 +04:00
goto out ;
2010-02-24 19:13:00 +03:00
}
2009-02-09 17:24:06 +03:00
if ( last_error - > code = = VIR_ERR_OK ) {
2009-09-29 15:42:42 +04:00
vshError ( ctl , " %s " , _ ( " unknown error " ) ) ;
2009-02-09 17:24:06 +03:00
goto out ;
}
2009-09-29 15:42:42 +04:00
vshError ( ctl , " %s " , last_error - > message ) ;
2009-02-09 17:24:06 +03:00
out :
virFreeError ( last_error ) ;
last_error = NULL ;
}
2011-01-25 13:14:28 +03:00
static volatile sig_atomic_t intCaught = 0 ;
static void vshCatchInt ( int sig ATTRIBUTE_UNUSED ,
siginfo_t * siginfo ATTRIBUTE_UNUSED ,
void * context ATTRIBUTE_UNUSED )
{
intCaught = 1 ;
}
2010-03-05 12:59:52 +03:00
/*
* Detection of disconnections and automatic reconnection support
*/
static int disconnected = 0 ; /* we may have been disconnected */
2010-12-24 05:26:15 +03:00
/* Gnulib doesn't guarantee SA_SIGINFO support. */
# ifndef SA_SIGINFO
# define SA_SIGINFO 0
# endif
2010-03-05 12:59:52 +03:00
/*
* vshCatchDisconnect :
*
* We get here when a SIGPIPE is being raised , we can ' t do much in the
* handler , just save the fact it was raised
*/
2010-12-24 05:26:15 +03:00
static void vshCatchDisconnect ( int sig , siginfo_t * siginfo ,
void * context ATTRIBUTE_UNUSED ) {
2012-04-15 02:35:22 +04:00
if ( sig = = SIGPIPE | |
2010-12-24 05:26:15 +03:00
( SA_SIGINFO & & siginfo - > si_signo = = SIGPIPE ) )
2010-03-05 12:59:52 +03:00
disconnected + + ;
}
/*
* vshSetupSignals :
*
* Catch SIGPIPE signals which may arise when disconnection
* from libvirtd occurs
*/
2010-03-12 13:39:24 +03:00
static void
2010-03-05 12:59:52 +03:00
vshSetupSignals ( void ) {
struct sigaction sig_action ;
sig_action . sa_sigaction = vshCatchDisconnect ;
sig_action . sa_flags = SA_SIGINFO ;
sigemptyset ( & sig_action . sa_mask ) ;
sigaction ( SIGPIPE , & sig_action , NULL ) ;
}
/*
* vshReconnect :
*
2010-03-12 13:39:24 +03:00
* Reconnect after a disconnect from libvirtd
2010-03-05 12:59:52 +03:00
*
*/
2010-03-12 13:39:24 +03:00
static void
virsh: optimize creation of default connection
Ramon de Carvalho Valle reported a problem with:
virsh connect qemu:///system
as a non-root user. The real root problem appears to be a regression
in libvirtd being auto-started on the default qemu:///session URI;
however, the symptom points to an independent flaw in virsh - we
shouldn't be wasting efforts on making a connection if we aren't going
to be using that connection. Fixing virsh avoids Ramon's issue, while
I work in the meantime to fix the real libvirtd regression.
This patch looks big, but that's because 'gcc -Wmissing-field-initializers'
gets triggered by './autobuild.sh --enable-compile-warnings=error', so I
had to add 0 initialization to everyone (rather than my preference of
just adding the non-zero flags to virshCmds and to cmdConnect).
Meanwhile, if you use 'virsh -c URI', the connection must succeed; this
patch _only_ optimizes the default connection to be deferred to a later
point where we know if a particular command to be run needs a connection.
* tools/virsh.c (VSH_CMD_FLAG_NOCONNECT): New flag.
(vshCmdDef): Add new flags field.
(vshCommandRun): Honor new flag.
(domManagementCmds, domMonitoringCmds, storagePoolCmds)
(storageVolCmds, networkCmds, nodedevCmds, ifaceCmds)
(nwfilterCmds, secretCmds, virshCmds, snapshotCmds)
(hostAndHypervisorCmds): Populate new field.
(vshReconnect): Don't warn on initial connection.
2011-03-14 23:30:24 +03:00
vshReconnect ( vshControl * ctl )
{
bool connected = false ;
if ( ctl - > conn ! = NULL ) {
connected = true ;
2010-03-05 12:59:52 +03:00
virConnectClose ( ctl - > conn ) ;
virsh: optimize creation of default connection
Ramon de Carvalho Valle reported a problem with:
virsh connect qemu:///system
as a non-root user. The real root problem appears to be a regression
in libvirtd being auto-started on the default qemu:///session URI;
however, the symptom points to an independent flaw in virsh - we
shouldn't be wasting efforts on making a connection if we aren't going
to be using that connection. Fixing virsh avoids Ramon's issue, while
I work in the meantime to fix the real libvirtd regression.
This patch looks big, but that's because 'gcc -Wmissing-field-initializers'
gets triggered by './autobuild.sh --enable-compile-warnings=error', so I
had to add 0 initialization to everyone (rather than my preference of
just adding the non-zero flags to virshCmds and to cmdConnect).
Meanwhile, if you use 'virsh -c URI', the connection must succeed; this
patch _only_ optimizes the default connection to be deferred to a later
point where we know if a particular command to be run needs a connection.
* tools/virsh.c (VSH_CMD_FLAG_NOCONNECT): New flag.
(vshCmdDef): Add new flags field.
(vshCommandRun): Honor new flag.
(domManagementCmds, domMonitoringCmds, storagePoolCmds)
(storageVolCmds, networkCmds, nodedevCmds, ifaceCmds)
(nwfilterCmds, secretCmds, virshCmds, snapshotCmds)
(hostAndHypervisorCmds): Populate new field.
(vshReconnect): Don't warn on initial connection.
2011-03-14 23:30:24 +03:00
}
2010-03-05 12:59:52 +03:00
ctl - > conn = virConnectOpenAuth ( ctl - > name ,
virConnectAuthPtrDefault ,
ctl - > readonly ? VIR_CONNECT_RO : 0 ) ;
if ( ! ctl - > conn )
vshError ( ctl , " %s " , _ ( " Failed to reconnect to the hypervisor " ) ) ;
virsh: optimize creation of default connection
Ramon de Carvalho Valle reported a problem with:
virsh connect qemu:///system
as a non-root user. The real root problem appears to be a regression
in libvirtd being auto-started on the default qemu:///session URI;
however, the symptom points to an independent flaw in virsh - we
shouldn't be wasting efforts on making a connection if we aren't going
to be using that connection. Fixing virsh avoids Ramon's issue, while
I work in the meantime to fix the real libvirtd regression.
This patch looks big, but that's because 'gcc -Wmissing-field-initializers'
gets triggered by './autobuild.sh --enable-compile-warnings=error', so I
had to add 0 initialization to everyone (rather than my preference of
just adding the non-zero flags to virshCmds and to cmdConnect).
Meanwhile, if you use 'virsh -c URI', the connection must succeed; this
patch _only_ optimizes the default connection to be deferred to a later
point where we know if a particular command to be run needs a connection.
* tools/virsh.c (VSH_CMD_FLAG_NOCONNECT): New flag.
(vshCmdDef): Add new flags field.
(vshCommandRun): Honor new flag.
(domManagementCmds, domMonitoringCmds, storagePoolCmds)
(storageVolCmds, networkCmds, nodedevCmds, ifaceCmds)
(nwfilterCmds, secretCmds, virshCmds, snapshotCmds)
(hostAndHypervisorCmds): Populate new field.
(vshReconnect): Don't warn on initial connection.
2011-03-14 23:30:24 +03:00
else if ( connected )
2010-03-05 12:59:52 +03:00
vshError ( ctl , " %s " , _ ( " Reconnected to the hypervisor " ) ) ;
disconnected = 0 ;
2011-04-29 12:20:49 +04:00
ctl - > useGetInfo = false ;
2011-09-30 01:18:50 +04:00
ctl - > useSnapshotOld = false ;
2010-03-05 12:59:52 +03:00
}
2007-02-14 18:44:58 +03:00
2012-06-21 17:46:03 +04:00
# ifndef WIN32
2012-06-13 13:11:27 +04:00
static void
vshPrintRaw ( vshControl * ctl , . . . )
{
va_list ap ;
char * key ;
va_start ( ap , ctl ) ;
while ( ( key = va_arg ( ap , char * ) ) ! = NULL ) {
vshPrint ( ctl , " %s \r \n " , key ) ;
}
va_end ( ap ) ;
}
2012-05-18 14:21:06 +04:00
/**
* vshAskReedit :
* @ msg : Question to ask user
*
* Ask user if he wants to return to previously
* edited file .
*
* Returns ' y ' if he wants to
* ' f ' if he forcibly wants to
* ' n ' if he doesn ' t want to
* - 1 on error
* 0 otherwise
*/
static int
vshAskReedit ( vshControl * ctl , const char * msg )
{
int c = - 1 ;
struct termios ttyattr ;
if ( ! isatty ( STDIN_FILENO ) )
return - 1 ;
virshReportError ( ctl ) ;
if ( vshMakeStdinRaw ( & ttyattr , false ) < 0 )
return - 1 ;
while ( true ) {
/* TRANSLATORS: For now, we aren't using LC_MESSAGES, and the user
* choices really are limited to just ' y ' , ' n ' , ' f ' and ' ? ' */
vshPrint ( ctl , " \r %s %s " , msg , _ ( " Try again? [y,n,f,?]: " ) ) ;
c = c_tolower ( getchar ( ) ) ;
if ( c = = ' ? ' ) {
2012-06-13 13:11:27 +04:00
vshPrintRaw ( ctl ,
" " ,
_ ( " y - yes, start editor again " ) ,
_ ( " n - no, throw away my changes " ) ,
_ ( " f - force, try to redefine again " ) ,
_ ( " ? - print this help " ) ,
NULL ) ;
2012-05-18 14:21:06 +04:00
continue ;
} else if ( c = = ' y ' | | c = = ' n ' | | c = = ' f ' ) {
break ;
}
}
tcsetattr ( STDIN_FILENO , TCSAFLUSH , & ttyattr ) ;
vshPrint ( ctl , " \r \n " ) ;
return c ;
2012-06-21 17:46:03 +04:00
}
# else /* WIN32 */
static int
vshAskReedit ( vshControl * ctl , const char * msg ATTRIBUTE_UNUSED )
{
2012-05-18 14:21:06 +04:00
vshDebug ( ctl , VSH_ERR_WARNING , " %s " , _ ( " This function is not "
" supported on WIN32 platform " ) ) ;
return 0 ;
}
2012-06-21 17:46:03 +04:00
# endif /* WIN32 */
2012-05-18 14:21:06 +04:00
2012-07-25 19:37:18 +04:00
static int vshStreamSink ( virStreamPtr st ATTRIBUTE_UNUSED ,
const char * bytes , size_t nbytes , void * opaque )
{
int * fd = opaque ;
return safewrite ( * fd , bytes , nbytes ) ;
}
2005-12-08 13:23:34 +03:00
/* ---------------
* Commands
* - - - - - - - - - - - - - - -
*/
/*
2007-02-07 16:50:18 +03:00
* " help " command
2005-12-08 13:23:34 +03:00
*/
2008-08-01 16:19:56 +04:00
static const vshCmdInfo info_help [ ] = {
2010-03-09 20:05:02 +03:00
{ " help " , N_ ( " print help " ) } ,
2010-12-01 15:24:58 +03:00
{ " desc " , N_ ( " Prints global help, command specific help, or help for a \n "
" group of related commands " ) } ,
2006-09-21 19:24:37 +04:00
2006-03-15 15:13:25 +03:00
{ NULL , NULL }
2005-12-08 13:23:34 +03:00
} ;
2008-08-01 16:19:56 +04:00
static const vshCmdOptDef opts_help [ ] = {
2010-12-03 10:34:23 +03:00
{ " command " , VSH_OT_DATA , 0 , N_ ( " Prints global help, command specific help, or help for a group of related commands " ) } ,
2006-03-15 15:13:25 +03:00
{ NULL , 0 , 0 , NULL }
2005-12-08 13:23:34 +03:00
} ;
2011-04-19 02:37:42 +04:00
static bool
2008-08-01 17:51:18 +04:00
cmdHelp ( vshControl * ctl , const vshCmd * cmd )
2010-11-30 09:37:04 +03:00
{
2011-03-08 19:29:31 +03:00
const char * name = NULL ;
2010-12-01 15:24:58 +03:00
2011-03-08 19:29:31 +03:00
if ( vshCommandOptString ( cmd , " command " , & name ) < = 0 ) {
2010-11-30 09:37:04 +03:00
const vshCmdGrp * grp ;
2008-08-01 16:19:56 +04:00
const vshCmdDef * def ;
2006-03-15 15:13:25 +03:00
2010-11-30 09:37:04 +03:00
vshPrint ( ctl , " %s " , _ ( " Grouped commands: \n \n " ) ) ;
for ( grp = cmdGroups ; grp - > name ; grp + + ) {
vshPrint ( ctl , _ ( " %s (help keyword '%s'): \n " ) , grp - > name ,
grp - > keyword ) ;
2012-03-02 23:01:06 +04:00
for ( def = grp - > commands ; def - > name ; def + + ) {
if ( def - > flags & VSH_CMD_FLAG_ALIAS )
continue ;
2010-11-30 09:37:04 +03:00
vshPrint ( ctl , " %-30s %s \n " , def - > name ,
_ ( vshCmddefGetInfo ( def , " help " ) ) ) ;
2012-03-02 23:01:06 +04:00
}
2010-11-30 09:37:04 +03:00
vshPrint ( ctl , " \n " ) ;
}
2011-04-19 02:37:42 +04:00
return true ;
2010-12-01 15:24:58 +03:00
}
2010-11-30 09:37:04 +03:00
2011-02-15 02:06:31 +03:00
if ( vshCmddefSearch ( name ) ) {
2010-11-30 09:37:04 +03:00
return vshCmddefHelp ( ctl , name ) ;
2011-02-15 02:06:31 +03:00
} else if ( vshCmdGrpSearch ( name ) ) {
2010-11-30 09:37:04 +03:00
return vshCmdGrpHelp ( ctl , name ) ;
} else {
vshError ( ctl , _ ( " command or command group '%s' doesn't exist " ) , name ) ;
2011-04-19 02:37:42 +04:00
return false ;
2005-12-08 13:23:34 +03:00
}
}
/*
2007-02-07 16:50:18 +03:00
* " connect " command
2005-12-08 13:23:34 +03:00
*/
2008-08-01 16:19:56 +04:00
static const vshCmdInfo info_connect [ ] = {
2010-03-09 20:05:02 +03:00
{ " help " , N_ ( " (re)connect to hypervisor " ) } ,
2006-03-15 15:13:25 +03:00
{ " desc " ,
2010-03-09 20:05:02 +03:00
N_ ( " Connect to local hypervisor. This is built-in command after shell start up. " ) } ,
2006-03-15 15:13:25 +03:00
{ NULL , NULL }
2005-12-08 13:23:34 +03:00
} ;
2008-08-01 16:19:56 +04:00
static const vshCmdOptDef opts_connect [ ] = {
2011-03-14 19:44:37 +03:00
{ " name " , VSH_OT_DATA , VSH_OFLAG_EMPTY_OK ,
N_ ( " hypervisor connection URI " ) } ,
2010-03-09 20:05:02 +03:00
{ " readonly " , VSH_OT_BOOL , 0 , N_ ( " read-only connection " ) } ,
2006-03-15 15:13:25 +03:00
{ NULL , 0 , 0 , NULL }
2005-12-08 13:23:34 +03:00
} ;
2011-04-19 02:37:42 +04:00
static bool
2008-08-01 17:51:18 +04:00
cmdConnect ( vshControl * ctl , const vshCmd * cmd )
2006-03-15 15:13:25 +03:00
{
2011-04-19 02:37:42 +04:00
bool ro = vshCommandOptBool ( cmd , " readonly " ) ;
2011-03-08 19:29:31 +03:00
const char * name = NULL ;
2007-02-07 16:50:18 +03:00
2005-12-08 13:23:34 +03:00
if ( ctl - > conn ) {
2010-11-11 18:15:46 +03:00
int ret ;
if ( ( ret = virConnectClose ( ctl - > conn ) ) ! = 0 ) {
vshError ( ctl , _ ( " Failed to disconnect from the hypervisor, %d leaked reference(s) " ) , ret ) ;
2011-04-19 02:37:42 +04:00
return false ;
2005-12-08 13:23:34 +03:00
}
ctl - > conn = NULL ;
}
2007-02-07 16:50:18 +03:00
2010-01-03 19:13:27 +03:00
VIR_FREE ( ctl - > name ) ;
2011-03-14 15:34:57 +03:00
if ( vshCommandOptString ( cmd , " name " , & name ) < 0 ) {
vshError ( ctl , " %s " , _ ( " Please specify valid connection URI " ) ) ;
2011-04-19 02:37:42 +04:00
return false ;
2011-03-14 15:34:57 +03:00
}
2010-06-17 22:58:55 +04:00
ctl - > name = vshStrdup ( ctl , name ) ;
2006-05-29 19:39:31 +04:00
2011-04-29 12:20:49 +04:00
ctl - > useGetInfo = false ;
2011-09-30 01:18:50 +04:00
ctl - > useSnapshotOld = false ;
2011-04-19 02:37:42 +04:00
ctl - > readonly = ro ;
2005-12-08 13:23:34 +03:00
2009-03-23 19:36:32 +03:00
ctl - > conn = virConnectOpenAuth ( ctl - > name , virConnectAuthPtrDefault ,
ctl - > readonly ? VIR_CONNECT_RO : 0 ) ;
2005-12-08 13:23:34 +03:00
if ( ! ctl - > conn )
2009-09-29 15:42:42 +04:00
vshError ( ctl , " %s " , _ ( " Failed to connect to the hypervisor " ) ) ;
2006-03-15 15:13:25 +03:00
2011-04-19 02:37:42 +04:00
return ! ! ctl - > conn ;
2005-12-08 13:23:34 +03:00
}
2007-01-26 14:54:29 +03:00
/*
2012-07-25 19:37:18 +04:00
* " freecell " command
2007-01-26 14:54:29 +03:00
*/
2012-07-25 19:37:18 +04:00
static const vshCmdInfo info_freecell [ ] = {
{ " help " , N_ ( " NUMA free memory " ) } ,
{ " desc " , N_ ( " display available free memory for the NUMA cell. " ) } ,
2007-01-26 14:54:29 +03:00
{ NULL , NULL }
} ;
2012-07-25 19:37:18 +04:00
static const vshCmdOptDef opts_freecell [ ] = {
{ " cellno " , VSH_OT_INT , 0 , N_ ( " NUMA cell number " ) } ,
{ " all " , VSH_OT_BOOL , 0 , N_ ( " show free memory for all NUMA cells " ) } ,
2007-01-26 14:54:29 +03:00
{ NULL , 0 , 0 , NULL }
} ;
2011-04-19 02:37:42 +04:00
static bool
2012-07-25 19:37:18 +04:00
cmdFreecell ( vshControl * ctl , const vshCmd * cmd )
2007-01-26 14:54:29 +03:00
{
2012-07-25 19:37:18 +04:00
bool func_ret = false ;
int ret ;
int cell = - 1 , cell_given ;
unsigned long long memory ;
xmlNodePtr * nodes = NULL ;
unsigned long nodes_cnt ;
unsigned long * nodes_id = NULL ;
unsigned long long * nodes_free = NULL ;
int all_given ;
int i ;
char * cap_xml = NULL ;
xmlDocPtr xml = NULL ;
xmlXPathContextPtr ctxt = NULL ;
2007-01-26 14:54:29 +03:00
2009-11-12 17:14:23 +03:00
2012-07-25 19:37:18 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
return false ;
if ( ( cell_given = vshCommandOptInt ( cmd , " cellno " , & cell ) ) < 0 ) {
vshError ( ctl , " %s " , _ ( " cell number has to be a number " ) ) ;
2009-11-12 17:14:23 +03:00
goto cleanup ;
}
2012-07-25 19:37:18 +04:00
all_given = vshCommandOptBool ( cmd , " all " ) ;
2009-11-12 17:14:23 +03:00
2012-07-25 19:37:18 +04:00
if ( all_given & & cell_given ) {
vshError ( ctl , " %s " , _ ( " --cellno and --all are mutually exclusive. "
" Please choose only one. " ) ) ;
2012-02-15 17:12:11 +04:00
goto cleanup ;
}
2012-07-25 19:37:18 +04:00
if ( all_given ) {
cap_xml = virConnectGetCapabilities ( ctl - > conn ) ;
if ( ! cap_xml ) {
vshError ( ctl , " %s " , _ ( " unable to get node capabilities " ) ) ;
goto cleanup ;
}
2007-01-26 14:54:29 +03:00
2012-07-25 19:37:18 +04:00
xml = virXMLParseStringCtxt ( cap_xml , _ ( " (capabilities) " ) , & ctxt ) ;
if ( ! xml ) {
vshError ( ctl , " %s " , _ ( " unable to get node capabilities " ) ) ;
goto cleanup ;
}
nodes_cnt = virXPathNodeSet ( " /capabilities/host/topology/cells/cell " ,
ctxt , & nodes ) ;
2009-04-03 18:03:38 +04:00
2012-07-25 19:37:18 +04:00
if ( nodes_cnt = = - 1 ) {
vshError ( ctl , " %s " , _ ( " could not get information about "
" NUMA topology " ) ) ;
goto cleanup ;
}
nodes_free = vshCalloc ( ctl , nodes_cnt , sizeof ( * nodes_free ) ) ;
nodes_id = vshCalloc ( ctl , nodes_cnt , sizeof ( * nodes_id ) ) ;
for ( i = 0 ; i < nodes_cnt ; i + + ) {
unsigned long id ;
char * val = virXMLPropString ( nodes [ i ] , " id " ) ;
if ( virStrToLong_ul ( val , NULL , 10 , & id ) ) {
vshError ( ctl , " %s " , _ ( " conversion from string failed " ) ) ;
VIR_FREE ( val ) ;
goto cleanup ;
}
VIR_FREE ( val ) ;
nodes_id [ i ] = id ;
ret = virNodeGetCellsFreeMemory ( ctl - > conn , & ( nodes_free [ i ] ) , id , 1 ) ;
if ( ret ! = 1 ) {
vshError ( ctl , _ ( " failed to get free memory for NUMA node "
" number: %lu " ) , id ) ;
goto cleanup ;
}
}
memory = 0 ;
for ( cell = 0 ; cell < nodes_cnt ; cell + + ) {
vshPrint ( ctl , " %5lu: %10llu KiB \n " , nodes_id [ cell ] ,
( nodes_free [ cell ] / 1024 ) ) ;
memory + = nodes_free [ cell ] ;
}
vshPrintExtra ( ctl , " -------------------- \n " ) ;
vshPrintExtra ( ctl , " %5s: %10llu KiB \n " , _ ( " Total " ) , memory / 1024 ) ;
} else {
if ( ! cell_given ) {
memory = virNodeGetFreeMemory ( ctl - > conn ) ;
if ( memory = = 0 )
goto cleanup ;
} else {
ret = virNodeGetCellsFreeMemory ( ctl - > conn , & memory , cell , 1 ) ;
if ( ret ! = 1 )
goto cleanup ;
}
if ( cell = = - 1 )
vshPrint ( ctl , " %s: %llu KiB \n " , _ ( " Total " ) , ( memory / 1024 ) ) ;
else
vshPrint ( ctl , " %d: %llu KiB \n " , cell , ( memory / 1024 ) ) ;
}
func_ret = true ;
cleanup :
xmlXPathFreeContext ( ctxt ) ;
xmlFreeDoc ( xml ) ;
VIR_FREE ( nodes ) ;
VIR_FREE ( nodes_free ) ;
VIR_FREE ( nodes_id ) ;
VIR_FREE ( cap_xml ) ;
return func_ret ;
2007-01-26 14:54:29 +03:00
}
2012-07-25 19:37:18 +04:00
/*
* " nodeinfo " command
*/
static const vshCmdInfo info_nodeinfo [ ] = {
{ " help " , N_ ( " node information " ) } ,
{ " desc " , N_ ( " Returns basic information about the node. " ) } ,
{ NULL , NULL }
} ;
2011-04-19 02:37:42 +04:00
static bool
2012-07-25 19:37:18 +04:00
cmdNodeinfo ( vshControl * ctl , const vshCmd * cmd ATTRIBUTE_UNUSED )
2009-04-03 18:03:38 +04:00
{
2012-07-25 19:37:18 +04:00
virNodeInfo info ;
2009-04-03 18:03:38 +04:00
2010-06-17 18:47:06 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
2011-04-19 02:37:42 +04:00
return false ;
2009-04-03 18:03:38 +04:00
2012-07-25 19:37:18 +04:00
if ( virNodeGetInfo ( ctl - > conn , & info ) < 0 ) {
vshError ( ctl , " %s " , _ ( " failed to get node information " ) ) ;
2011-04-19 02:37:42 +04:00
return false ;
2011-03-14 15:34:57 +03:00
}
2012-07-25 19:37:18 +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 KiB \n " , _ ( " Memory size: " ) , info . memory ) ;
2010-07-27 13:40:30 +04:00
2012-07-25 19:37:18 +04:00
return true ;
2009-04-03 18:03:38 +04:00
}
2012-02-01 17:03:51 +04:00
/*
2012-07-25 19:37:18 +04:00
* " nodecpustats " command
2012-02-01 17:03:51 +04:00
*/
2012-07-25 19:37:18 +04:00
static const vshCmdInfo info_nodecpustats [ ] = {
{ " help " , N_ ( " Prints cpu stats of the node. " ) } ,
{ " desc " , N_ ( " Returns cpu stats of the node, in nanoseconds. " ) } ,
2012-02-01 17:03:51 +04:00
{ NULL , NULL }
} ;
2012-07-25 19:37:18 +04:00
static const vshCmdOptDef opts_node_cpustats [ ] = {
{ " cpu " , VSH_OT_INT , 0 , N_ ( " prints specified cpu statistics only. " ) } ,
{ " percent " , VSH_OT_BOOL , 0 , N_ ( " prints by percentage during 1 second. " ) } ,
2012-02-01 17:03:51 +04:00
{ NULL , 0 , 0 , NULL }
} ;
static bool
2012-07-25 19:37:18 +04:00
cmdNodeCpuStats ( vshControl * ctl , const vshCmd * cmd )
2012-02-01 17:03:51 +04:00
{
2012-07-25 19:37:18 +04:00
int i , j ;
bool flag_utilization = false ;
bool flag_percent = vshCommandOptBool ( cmd , " percent " ) ;
int cpuNum = VIR_NODE_CPU_STATS_ALL_CPUS ;
virNodeCPUStatsPtr params ;
int nparams = 0 ;
2012-02-01 17:03:51 +04:00
bool ret = false ;
2012-07-25 19:37:18 +04:00
struct cpu_stats {
unsigned long long user ;
unsigned long long sys ;
unsigned long long idle ;
unsigned long long iowait ;
unsigned long long util ;
} cpu_stats [ 2 ] ;
double user_time , sys_time , idle_time , iowait_time , total_time ;
double usage ;
2012-02-08 14:31:10 +04:00
2012-02-01 17:03:51 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
return false ;
2012-07-25 19:37:18 +04:00
if ( vshCommandOptInt ( cmd , " cpu " , & cpuNum ) < 0 ) {
vshError ( ctl , " %s " , _ ( " Invalid value of cpuNum " ) ) ;
2012-02-01 17:03:51 +04:00
return false ;
}
2012-07-25 19:37:18 +04:00
if ( virNodeGetCPUStats ( ctl - > conn , cpuNum , NULL , & nparams , 0 ) ! = 0 ) {
vshError ( ctl , " %s " ,
_ ( " Unable to get number of cpu stats " ) ) ;
return false ;
}
if ( nparams = = 0 ) {
/* nothing to output */
return true ;
2012-02-01 17:03:51 +04:00
}
2012-07-25 19:37:18 +04:00
memset ( cpu_stats , 0 , sizeof ( cpu_stats ) ) ;
params = vshCalloc ( ctl , nparams , sizeof ( * params ) ) ;
2012-02-01 17:03:51 +04:00
2012-07-25 19:37:18 +04:00
for ( i = 0 ; i < 2 ; i + + ) {
if ( i > 0 )
sleep ( 1 ) ;
2012-02-01 17:03:51 +04:00
2012-07-25 19:37:18 +04:00
if ( virNodeGetCPUStats ( ctl - > conn , cpuNum , params , & nparams , 0 ) ! = 0 ) {
vshError ( ctl , " %s " , _ ( " Unable to get node cpu stats " ) ) ;
goto cleanup ;
}
2012-02-01 17:03:51 +04:00
2012-07-25 19:37:18 +04:00
for ( j = 0 ; j < nparams ; j + + ) {
unsigned long long value = params [ j ] . value ;
2012-02-01 17:03:51 +04:00
2012-07-25 19:37:18 +04:00
if ( STREQ ( params [ j ] . field , VIR_NODE_CPU_STATS_KERNEL ) ) {
cpu_stats [ i ] . sys = value ;
} else if ( STREQ ( params [ j ] . field , VIR_NODE_CPU_STATS_USER ) ) {
cpu_stats [ i ] . user = value ;
} else if ( STREQ ( params [ j ] . field , VIR_NODE_CPU_STATS_IDLE ) ) {
cpu_stats [ i ] . idle = value ;
} else if ( STREQ ( params [ j ] . field , VIR_NODE_CPU_STATS_IOWAIT ) ) {
cpu_stats [ i ] . iowait = value ;
} else if ( STREQ ( params [ j ] . field , VIR_NODE_CPU_STATS_UTILIZATION ) ) {
cpu_stats [ i ] . util = value ;
flag_utilization = true ;
2012-02-01 17:03:51 +04:00
}
}
2012-07-25 19:37:18 +04:00
if ( flag_utilization | | ! flag_percent )
break ;
}
if ( ! flag_percent ) {
if ( ! flag_utilization ) {
vshPrint ( ctl , " %-15s %20llu \n " , _ ( " user: " ) , cpu_stats [ 0 ] . user ) ;
vshPrint ( ctl , " %-15s %20llu \n " , _ ( " system: " ) , cpu_stats [ 0 ] . sys ) ;
vshPrint ( ctl , " %-15s %20llu \n " , _ ( " idle: " ) , cpu_stats [ 0 ] . idle ) ;
vshPrint ( ctl , " %-15s %20llu \n " , _ ( " iowait: " ) , cpu_stats [ 0 ] . iowait ) ;
2012-02-01 17:03:51 +04:00
}
} else {
2012-07-25 19:37:18 +04:00
if ( flag_utilization ) {
usage = cpu_stats [ 0 ] . util ;
2012-02-01 17:03:51 +04:00
2012-07-25 19:37:18 +04:00
vshPrint ( ctl , " %-15s %5.1lf%% \n " , _ ( " usage: " ) , usage ) ;
vshPrint ( ctl , " %-15s %5.1lf%% \n " , _ ( " idle: " ) , 100 - usage ) ;
} else {
user_time = cpu_stats [ 1 ] . user - cpu_stats [ 0 ] . user ;
sys_time = cpu_stats [ 1 ] . sys - cpu_stats [ 0 ] . sys ;
idle_time = cpu_stats [ 1 ] . idle - cpu_stats [ 0 ] . idle ;
iowait_time = cpu_stats [ 1 ] . iowait - cpu_stats [ 0 ] . iowait ;
total_time = user_time + sys_time + idle_time + iowait_time ;
usage = ( user_time + sys_time ) / total_time * 100 ;
vshPrint ( ctl , " %-15s %5.1lf%% \n " ,
_ ( " usage: " ) , usage ) ;
vshPrint ( ctl , " %-15s %5.1lf%% \n " ,
_ ( " user: " ) , user_time / total_time * 100 ) ;
vshPrint ( ctl , " %-15s %5.1lf%% \n " ,
_ ( " system: " ) , sys_time / total_time * 100 ) ;
vshPrint ( ctl , " %-15s %5.1lf%% \n " ,
_ ( " idle: " ) , idle_time / total_time * 100 ) ;
vshPrint ( ctl , " %-15s %5.1lf%% \n " ,
_ ( " iowait: " ) , iowait_time / total_time * 100 ) ;
}
2012-02-01 17:03:51 +04:00
}
ret = true ;
2012-07-25 19:37:18 +04:00
cleanup :
VIR_FREE ( params ) ;
2012-02-01 17:03:51 +04:00
return ret ;
2005-12-08 13:23:34 +03:00
}
2012-07-25 19:37:18 +04:00
/*
* " nodememstats " command
2005-12-08 13:23:34 +03:00
*/
2012-07-25 19:37:18 +04:00
static const vshCmdInfo info_nodememstats [ ] = {
{ " help " , N_ ( " Prints memory stats of the node. " ) } ,
{ " desc " , N_ ( " Returns memory stats of the node, in kilobytes. " ) } ,
{ NULL , NULL }
2005-12-08 13:23:34 +03:00
} ;
2012-07-25 19:37:18 +04:00
static const vshCmdOptDef opts_node_memstats [ ] = {
{ " cell " , VSH_OT_INT , 0 , N_ ( " prints specified cell statistics only. " ) } ,
2006-03-15 15:13:25 +03:00
{ NULL , 0 , 0 , NULL }
2005-12-08 13:23:34 +03:00
} ;
2011-04-19 02:37:42 +04:00
static bool
2012-07-25 19:37:18 +04:00
cmdNodeMemStats ( vshControl * ctl , const vshCmd * cmd )
2006-03-15 15:13:25 +03:00
{
2012-07-25 19:37:18 +04:00
int nparams = 0 ;
unsigned int i = 0 ;
int cellNum = VIR_NODE_MEMORY_STATS_ALL_CELLS ;
virNodeMemoryStatsPtr params = NULL ;
2012-07-24 12:24:50 +04:00
bool ret = false ;
2006-03-15 15:13:25 +03:00
2010-06-17 18:47:06 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
2011-04-19 02:37:42 +04:00
return false ;
2005-12-05 21:14:37 +03:00
2012-07-25 19:37:18 +04:00
if ( vshCommandOptInt ( cmd , " cell " , & cellNum ) < 0 ) {
vshError ( ctl , " %s " , _ ( " Invalid value of cellNum " ) ) ;
2011-04-19 02:37:42 +04:00
return false ;
2011-05-31 20:21:58 +04:00
}
2012-07-25 19:37:18 +04:00
/* get the number of memory parameters */
if ( virNodeGetMemoryStats ( ctl - > conn , cellNum , NULL , & nparams , 0 ) ! = 0 ) {
vshError ( ctl , " %s " ,
_ ( " Unable to get number of memory stats " ) ) ;
2012-07-24 12:24:50 +04:00
goto cleanup ;
2011-05-31 20:21:58 +04:00
}
2012-07-25 19:37:18 +04:00
if ( nparams = = 0 ) {
/* nothing to output */
ret = true ;
2011-09-06 12:31:59 +04:00
goto cleanup ;
}
2012-07-25 19:37:18 +04:00
/* now go get all the memory parameters */
params = vshCalloc ( ctl , nparams , sizeof ( * params ) ) ;
if ( virNodeGetMemoryStats ( ctl - > conn , cellNum , params , & nparams , 0 ) ! = 0 ) {
vshError ( ctl , " %s " , _ ( " Unable to get memory stats " ) ) ;
2011-09-06 12:31:59 +04:00
goto cleanup ;
}
2012-07-25 19:37:18 +04:00
for ( i = 0 ; i < nparams ; i + + )
vshPrint ( ctl , " %-7s: %20llu KiB \n " , params [ i ] . field , params [ i ] . value ) ;
2012-01-20 10:30:47 +04:00
2012-07-25 19:37:18 +04:00
ret = true ;
2011-09-06 12:31:59 +04:00
2012-07-25 19:37:18 +04:00
cleanup :
VIR_FREE ( params ) ;
return ret ;
}
2011-09-06 12:31:59 +04:00
2012-07-25 19:37:18 +04:00
/*
* " nodesuspend " command
*/
static const vshCmdInfo info_nodesuspend [ ] = {
{ " help " , N_ ( " suspend the host node for a given time duration " ) } ,
{ " desc " , N_ ( " Suspend the host node for a given time duration "
" and attempt to resume thereafter. " ) } ,
{ NULL , NULL }
} ;
2011-09-06 12:31:59 +04:00
2012-07-25 19:37:18 +04:00
static const vshCmdOptDef opts_node_suspend [ ] = {
{ " target " , VSH_OT_DATA , VSH_OFLAG_REQ , N_ ( " mem(Suspend-to-RAM), "
" disk(Suspend-to-Disk), hybrid(Hybrid-Suspend) " ) } ,
{ " duration " , VSH_OT_INT , VSH_OFLAG_REQ , N_ ( " Suspend duration in seconds " ) } ,
{ " flags " , VSH_OT_INT , VSH_OFLAG_NONE , N_ ( " Suspend flags, 0 for default " ) } ,
{ NULL , 0 , 0 , NULL }
} ;
2011-09-06 12:31:59 +04:00
2012-07-25 19:37:18 +04:00
static bool
cmdNodeSuspend ( vshControl * ctl , const vshCmd * cmd )
{
const char * target = NULL ;
unsigned int suspendTarget ;
long long duration ;
unsigned int flags = 0 ;
2011-09-06 12:31:59 +04:00
2012-07-25 19:37:18 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
return false ;
2011-09-06 12:31:59 +04:00
2012-07-25 19:37:18 +04:00
if ( vshCommandOptString ( cmd , " target " , & target ) < 0 ) {
vshError ( ctl , _ ( " Invalid target argument " ) ) ;
return false ;
2011-09-06 12:31:59 +04:00
}
2012-07-25 19:37:18 +04:00
if ( vshCommandOptLongLong ( cmd , " duration " , & duration ) < 0 ) {
vshError ( ctl , _ ( " Invalid duration argument " ) ) ;
return false ;
}
2011-09-06 12:31:59 +04:00
2012-07-25 19:37:18 +04:00
if ( vshCommandOptUInt ( cmd , " flags " , & flags ) < 0 ) {
vshError ( ctl , _ ( " Invalid flags argument " ) ) ;
return false ;
2011-09-06 12:31:59 +04:00
}
2012-07-25 19:37:18 +04:00
if ( STREQ ( target , " mem " ) )
suspendTarget = VIR_NODE_SUSPEND_TARGET_MEM ;
else if ( STREQ ( target , " disk " ) )
suspendTarget = VIR_NODE_SUSPEND_TARGET_DISK ;
else if ( STREQ ( target , " hybrid " ) )
suspendTarget = VIR_NODE_SUSPEND_TARGET_HYBRID ;
else {
vshError ( ctl , " %s " , _ ( " Invalid target " ) ) ;
return false ;
2012-07-24 12:24:50 +04:00
}
2012-07-25 19:37:18 +04:00
if ( duration < = 0 ) {
vshError ( ctl , " %s " , _ ( " Invalid duration " ) ) ;
return false ;
2012-07-24 12:24:50 +04:00
}
2012-07-25 19:37:18 +04:00
if ( virNodeSuspendForDuration ( ctl - > conn , suspendTarget , duration ,
flags ) < 0 ) {
vshError ( ctl , " %s " , _ ( " The host was not suspended " ) ) ;
return false ;
2012-07-24 12:24:50 +04:00
}
2012-07-25 19:37:18 +04:00
return true ;
}
2011-09-06 12:31:59 +04:00
2012-07-24 12:24:50 +04:00
2012-07-25 19:37:18 +04:00
/*
* " capabilities " command
*/
static const vshCmdInfo info_capabilities [ ] = {
{ " help " , N_ ( " capabilities " ) } ,
{ " desc " , N_ ( " Returns capabilities of hypervisor/driver. " ) } ,
{ NULL , NULL }
} ;
2011-09-06 12:31:59 +04:00
2012-07-25 19:37:18 +04:00
static bool
cmdCapabilities ( vshControl * ctl , const vshCmd * cmd ATTRIBUTE_UNUSED )
{
char * caps ;
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
return false ;
if ( ( caps = virConnectGetCapabilities ( ctl - > conn ) ) = = NULL ) {
vshError ( ctl , " %s " , _ ( " failed to get capabilities " ) ) ;
return false ;
}
vshPrint ( ctl , " %s \n " , caps ) ;
VIR_FREE ( caps ) ;
return true ;
2011-09-06 12:31:59 +04:00
}
2012-07-25 19:37:18 +04:00
/*
* " net-autostart " command
2011-12-29 11:33:21 +04:00
*/
2012-07-25 19:37:18 +04:00
static const vshCmdInfo info_network_autostart [ ] = {
{ " help " , N_ ( " autostart a network " ) } ,
{ " desc " ,
N_ ( " Configure a network to be automatically started at boot. " ) } ,
{ NULL , NULL }
2011-12-29 11:33:21 +04:00
} ;
2012-07-25 19:37:18 +04:00
static const vshCmdOptDef opts_network_autostart [ ] = {
{ " network " , VSH_OT_DATA , VSH_OFLAG_REQ , N_ ( " network name or uuid " ) } ,
{ " disable " , VSH_OT_BOOL , 0 , N_ ( " disable autostarting " ) } ,
2011-12-29 11:33:21 +04:00
{ NULL , 0 , 0 , NULL }
} ;
static bool
2012-07-25 19:37:18 +04:00
cmdNetworkAutostart ( vshControl * ctl , const vshCmd * cmd )
2011-12-29 11:33:21 +04:00
{
2012-07-25 19:37:18 +04:00
virNetworkPtr network ;
const char * name ;
int autostart ;
2011-12-29 11:33:21 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
return false ;
2012-07-25 19:37:18 +04:00
if ( ! ( network = vshCommandOptNetwork ( ctl , cmd , & name ) ) )
2011-12-29 11:33:21 +04:00
return false ;
2012-07-25 19:37:18 +04:00
autostart = ! vshCommandOptBool ( cmd , " disable " ) ;
2012-01-11 16:45:31 +04:00
2012-07-25 19:37:18 +04:00
if ( virNetworkSetAutostart ( network , autostart ) < 0 ) {
if ( autostart )
vshError ( ctl , _ ( " failed to mark network %s as autostarted " ) , name ) ;
else
vshError ( ctl , _ ( " failed to unmark network %s as autostarted " ) , name ) ;
virNetworkFree ( network ) ;
return false ;
2012-01-11 16:45:31 +04:00
}
2012-07-25 19:37:18 +04:00
if ( autostart )
vshPrint ( ctl , _ ( " Network %s marked as autostarted \n " ) , name ) ;
else
vshPrint ( ctl , _ ( " Network %s unmarked as autostarted \n " ) , name ) ;
2012-01-11 16:45:31 +04:00
2012-07-25 19:37:18 +04:00
virNetworkFree ( network ) ;
return true ;
2012-01-11 16:45:31 +04:00
}
2005-12-09 02:01:48 +03:00
/*
2012-07-25 19:37:18 +04:00
* " net-create " command
2005-12-09 02:01:48 +03:00
*/
2012-07-25 19:37:18 +04:00
static const vshCmdInfo info_network_create [ ] = {
{ " help " , N_ ( " create a network from an XML file " ) } ,
{ " desc " , N_ ( " Create a network. " ) } ,
2006-03-15 15:13:25 +03:00
{ NULL , NULL }
2005-12-09 02:01:48 +03:00
} ;
2012-07-25 19:37:18 +04:00
static const vshCmdOptDef opts_network_create [ ] = {
{ " file " , VSH_OT_DATA , VSH_OFLAG_REQ , N_ ( " file containing an XML network description " ) } ,
2006-03-15 15:13:25 +03:00
{ NULL , 0 , 0 , NULL }
2005-12-09 02:01:48 +03:00
} ;
2011-04-19 02:37:42 +04:00
static bool
2012-07-25 19:37:18 +04:00
cmdNetworkCreate ( vshControl * ctl , const vshCmd * cmd )
2006-03-15 15:13:25 +03:00
{
2012-07-25 19:37:18 +04:00
virNetworkPtr network ;
const char * from = NULL ;
2011-04-19 02:37:42 +04:00
bool ret = true ;
2012-07-25 19:37:18 +04:00
char * buffer ;
2006-03-15 15:13:25 +03:00
2010-06-17 18:47:06 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
2011-04-19 02:37:42 +04:00
return false ;
2005-12-09 02:01:48 +03:00
2012-07-25 19:37:18 +04:00
if ( vshCommandOptString ( cmd , " file " , & from ) < = 0 )
return false ;
if ( virFileReadAll ( from , VIRSH_MAX_XML_FILE , & buffer ) < 0 )
2011-04-19 02:37:42 +04:00
return false ;
2006-03-15 15:13:25 +03:00
2012-07-25 19:37:18 +04:00
network = virNetworkCreateXML ( ctl - > conn , buffer ) ;
VIR_FREE ( buffer ) ;
if ( network ! = NULL ) {
vshPrint ( ctl , _ ( " Network %s created from %s \n " ) ,
virNetworkGetName ( network ) , from ) ;
virNetworkFree ( network ) ;
2005-12-09 02:01:48 +03:00
} else {
2012-07-25 19:37:18 +04:00
vshError ( ctl , _ ( " Failed to create network from %s " ) , from ) ;
2011-04-19 02:37:42 +04:00
ret = false ;
2005-12-09 02:01:48 +03:00
}
return ret ;
}
2012-07-25 19:37:18 +04:00
2012-01-26 23:20:49 +04:00
/*
2012-07-25 19:37:18 +04:00
* " net-define " command
2012-01-26 23:20:49 +04:00
*/
2012-07-25 19:37:18 +04:00
static const vshCmdInfo info_network_define [ ] = {
{ " help " , N_ ( " define (but don't start) a network from an XML file " ) } ,
{ " desc " , N_ ( " Define a network. " ) } ,
2012-01-26 23:20:49 +04:00
{ NULL , NULL }
} ;
2012-07-25 19:37:18 +04:00
static const vshCmdOptDef opts_network_define [ ] = {
{ " file " , VSH_OT_DATA , VSH_OFLAG_REQ , N_ ( " file containing an XML network description " ) } ,
2012-01-26 23:20:49 +04:00
{ NULL , 0 , 0 , NULL }
} ;
static bool
2012-07-25 19:37:18 +04:00
cmdNetworkDefine ( vshControl * ctl , const vshCmd * cmd )
2012-01-26 23:20:49 +04:00
{
2012-07-25 19:37:18 +04:00
virNetworkPtr network ;
const char * from = NULL ;
bool ret = true ;
char * buffer ;
2012-01-26 23:20:49 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
return false ;
2012-07-25 19:37:18 +04:00
if ( vshCommandOptString ( cmd , " file " , & from ) < = 0 )
2012-01-26 23:20:49 +04:00
return false ;
2012-07-25 19:37:18 +04:00
if ( virFileReadAll ( from , VIRSH_MAX_XML_FILE , & buffer ) < 0 )
return false ;
2012-01-26 23:20:49 +04:00
2012-07-25 19:37:18 +04:00
network = virNetworkDefineXML ( ctl - > conn , buffer ) ;
VIR_FREE ( buffer ) ;
2012-01-26 23:20:49 +04:00
2012-07-25 19:37:18 +04:00
if ( network ! = NULL ) {
vshPrint ( ctl , _ ( " Network %s defined from %s \n " ) ,
virNetworkGetName ( network ) , from ) ;
virNetworkFree ( network ) ;
} else {
vshError ( ctl , _ ( " Failed to define network from %s " ) , from ) ;
ret = false ;
2012-01-26 23:20:49 +04:00
}
return ret ;
}
2012-07-25 19:37:18 +04:00
2012-02-10 16:07:24 +04:00
/*
2012-07-25 19:37:18 +04:00
* " net-destroy " command
2012-02-10 16:07:24 +04:00
*/
2012-07-25 19:37:18 +04:00
static const vshCmdInfo info_network_destroy [ ] = {
{ " help " , N_ ( " destroy (stop) a network " ) } ,
{ " desc " , N_ ( " Forcefully stop a given network. " ) } ,
2012-02-10 16:07:24 +04:00
{ NULL , NULL }
} ;
2012-07-25 19:37:18 +04:00
static const vshCmdOptDef opts_network_destroy [ ] = {
{ " network " , VSH_OT_DATA , VSH_OFLAG_REQ , N_ ( " network name or uuid " ) } ,
2012-02-10 16:07:24 +04:00
{ NULL , 0 , 0 , NULL }
} ;
static bool
2012-07-25 19:37:18 +04:00
cmdNetworkDestroy ( vshControl * ctl , const vshCmd * cmd )
2012-02-10 16:07:24 +04:00
{
2012-07-25 19:37:18 +04:00
virNetworkPtr network ;
bool ret = true ;
2012-02-10 16:07:24 +04:00
const char * name ;
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
return false ;
2012-07-25 19:37:18 +04:00
if ( ! ( network = vshCommandOptNetwork ( ctl , cmd , & name ) ) )
2012-02-10 16:07:24 +04:00
return false ;
2012-07-25 19:37:18 +04:00
if ( virNetworkDestroy ( network ) = = 0 ) {
vshPrint ( ctl , _ ( " Network %s destroyed \n " ) , name ) ;
} else {
vshError ( ctl , _ ( " Failed to destroy network %s " ) , name ) ;
ret = false ;
2012-02-10 16:07:24 +04:00
}
2012-07-25 19:37:18 +04:00
virNetworkFree ( network ) ;
2012-02-10 16:07:24 +04:00
return ret ;
}
2012-07-25 19:37:18 +04:00
2006-03-30 20:08:13 +04:00
/*
2012-07-25 19:37:18 +04:00
* " net-dumpxml " command
2006-03-30 20:08:13 +04:00
*/
2012-07-25 19:37:18 +04:00
static const vshCmdInfo info_network_dumpxml [ ] = {
{ " help " , N_ ( " network information in XML " ) } ,
{ " desc " , N_ ( " Output the network information as an XML dump to stdout. " ) } ,
2006-03-30 20:08:13 +04:00
{ NULL , NULL }
} ;
2012-07-25 19:37:18 +04:00
static const vshCmdOptDef opts_network_dumpxml [ ] = {
{ " network " , VSH_OT_DATA , VSH_OFLAG_REQ , N_ ( " network name or uuid " ) } ,
{ " inactive " , VSH_OT_BOOL , VSH_OFLAG_NONE , N_ ( " network information of an inactive domain " ) } ,
2006-03-30 20:08:13 +04:00
{ NULL , 0 , 0 , NULL }
} ;
2011-04-19 02:37:42 +04:00
static bool
2012-07-25 19:37:18 +04:00
cmdNetworkDumpXML ( vshControl * ctl , const vshCmd * cmd )
2006-03-30 20:08:13 +04:00
{
2012-07-25 19:37:18 +04:00
virNetworkPtr network ;
2011-04-19 02:37:42 +04:00
bool ret = true ;
2012-07-25 19:37:18 +04:00
char * dump ;
unsigned int flags = 0 ;
int inactive ;
2006-03-30 20:08:13 +04:00
2010-06-17 18:47:06 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
2011-04-19 02:37:42 +04:00
return false ;
2006-03-30 20:08:13 +04:00
2012-07-25 19:37:18 +04:00
if ( ! ( network = vshCommandOptNetwork ( ctl , cmd , NULL ) ) )
2011-04-19 02:37:42 +04:00
return false ;
2007-05-23 19:09:19 +04:00
2012-07-25 19:37:18 +04:00
inactive = vshCommandOptBool ( cmd , " inactive " ) ;
if ( inactive )
flags | = VIR_NETWORK_XML_INACTIVE ;
2010-06-08 23:43:01 +04:00
2012-07-25 19:37:18 +04:00
dump = virNetworkGetXMLDesc ( network , flags ) ;
2007-05-23 19:09:19 +04:00
2012-07-25 19:37:18 +04:00
if ( dump ! = NULL ) {
vshPrint ( ctl , " %s " , dump ) ;
VIR_FREE ( dump ) ;
2006-03-30 20:08:13 +04:00
} else {
2011-04-19 02:37:42 +04:00
ret = false ;
2006-03-30 20:08:13 +04:00
}
2012-07-25 19:37:18 +04:00
virNetworkFree ( network ) ;
2006-03-30 20:08:13 +04:00
return ret ;
}
2006-08-30 18:32:32 +04:00
/*
2012-07-25 19:37:18 +04:00
* " net-info " command
2006-08-30 18:32:32 +04:00
*/
2012-07-25 19:37:18 +04:00
static const vshCmdInfo info_network_info [ ] = {
{ " help " , N_ ( " network information " ) } ,
{ " desc " , N_ ( " Returns basic information about the network " ) } ,
2006-08-30 18:32:32 +04:00
{ NULL , NULL }
} ;
2012-07-25 19:37:18 +04:00
static const vshCmdOptDef opts_network_info [ ] = {
{ " network " , VSH_OT_DATA , VSH_OFLAG_REQ , N_ ( " network name or uuid " ) } ,
2006-08-30 18:32:32 +04:00
{ NULL , 0 , 0 , NULL }
} ;
2011-04-19 02:37:42 +04:00
static bool
2012-07-25 19:37:18 +04:00
cmdNetworkInfo ( vshControl * ctl , const vshCmd * cmd )
2006-08-30 18:32:32 +04:00
{
2012-07-25 19:37:18 +04:00
virNetworkPtr network ;
char uuid [ VIR_UUID_STRING_BUFLEN ] ;
int autostart ;
int persistent = - 1 ;
int active = - 1 ;
char * bridge = NULL ;
2006-08-30 18:32:32 +04:00
2010-06-17 18:47:06 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
2011-04-19 02:37:42 +04:00
return false ;
2006-08-30 18:32:32 +04:00
2012-07-25 19:37:18 +04:00
if ( ! ( network = vshCommandOptNetwork ( ctl , cmd , NULL ) ) )
2011-04-19 02:37:42 +04:00
return false ;
2006-08-30 18:32:32 +04:00
2012-07-25 19:37:18 +04:00
vshPrint ( ctl , " %-15s %s \n " , _ ( " Name " ) , virNetworkGetName ( network ) ) ;
2007-05-23 19:09:19 +04:00
2012-07-25 19:37:18 +04:00
if ( virNetworkGetUUIDString ( network , uuid ) = = 0 )
vshPrint ( ctl , " %-15s %s \n " , _ ( " UUID " ) , uuid ) ;
2007-05-23 19:09:19 +04:00
2012-07-25 19:37:18 +04:00
active = virNetworkIsActive ( network ) ;
if ( active > = 0 )
vshPrint ( ctl , " %-15s %s \n " , _ ( " Active: " ) , active ? _ ( " yes " ) : _ ( " no " ) ) ;
2006-08-30 18:32:32 +04:00
2012-07-25 19:37:18 +04:00
persistent = virNetworkIsPersistent ( network ) ;
if ( persistent < 0 )
vshPrint ( ctl , " %-15s %s \n " , _ ( " Persistent: " ) , _ ( " unknown " ) ) ;
else
vshPrint ( ctl , " %-15s %s \n " , _ ( " Persistent: " ) , persistent ? _ ( " yes " ) : _ ( " no " ) ) ;
if ( virNetworkGetAutostart ( network , & autostart ) < 0 )
vshPrint ( ctl , " %-15s %s \n " , _ ( " Autostart: " ) , _ ( " no autostart " ) ) ;
else
vshPrint ( ctl , " %-15s %s \n " , _ ( " Autostart: " ) , autostart ? _ ( " yes " ) : _ ( " no " ) ) ;
bridge = virNetworkGetBridgeName ( network ) ;
if ( bridge )
vshPrint ( ctl , " %-15s %s \n " , _ ( " Bridge: " ) , bridge ) ;
VIR_FREE ( bridge ) ;
virNetworkFree ( network ) ;
return true ;
}
/*
* " iface-edit " command
*/
static const vshCmdInfo info_interface_edit [ ] = {
{ " help " , N_ ( " edit XML configuration for a physical host interface " ) } ,
{ " desc " , N_ ( " Edit the XML configuration for a physical host interface. " ) } ,
2006-08-30 18:32:32 +04:00
{ NULL , NULL }
} ;
2012-07-25 19:37:18 +04:00
static const vshCmdOptDef opts_interface_edit [ ] = {
{ " interface " , VSH_OT_DATA , VSH_OFLAG_REQ , N_ ( " interface name or MAC address " ) } ,
2006-08-30 18:32:32 +04:00
{ NULL , 0 , 0 , NULL }
} ;
2011-04-19 02:37:42 +04:00
static bool
2012-07-25 19:37:18 +04:00
cmdInterfaceEdit ( vshControl * ctl , const vshCmd * cmd )
2006-08-30 18:32:32 +04:00
{
2011-08-12 06:24:19 +04:00
bool ret = false ;
2012-07-25 19:37:18 +04:00
virInterfacePtr iface = NULL ;
virInterfacePtr iface_edited = NULL ;
unsigned int flags = VIR_INTERFACE_XML_INACTIVE ;
2006-08-30 18:32:32 +04:00
2010-06-17 18:47:06 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
2011-08-12 06:24:19 +04:00
goto cleanup ;
2012-07-25 19:37:18 +04:00
iface = vshCommandOptInterface ( ctl , cmd , NULL ) ;
if ( iface = = NULL )
2011-09-08 16:48:47 +04:00
goto cleanup ;
2012-07-25 19:37:18 +04:00
# define EDIT_GET_XML virInterfaceGetXMLDesc(iface, flags)
# define EDIT_NOT_CHANGED \
vshPrint ( ctl , _ ( " Interface %s XML configuration not changed. \n " ) , \
virInterfaceGetName ( iface ) ) ; \
ret = true ; goto edit_cleanup ;
# define EDIT_DEFINE \
( iface_edited = virInterfaceDefineXML ( ctl - > conn , doc_edited , 0 ) )
# define EDIT_FREE \
if ( iface_edited ) \
virInterfaceFree ( iface_edited ) ;
# include "virsh-edit.c"
2011-09-08 16:48:47 +04:00
2012-07-25 19:37:18 +04:00
vshPrint ( ctl , _ ( " Interface %s XML configuration edited. \n " ) ,
virInterfaceGetName ( iface_edited ) ) ;
2011-09-08 16:48:47 +04:00
2012-07-25 19:37:18 +04:00
ret = true ;
2006-08-30 18:32:32 +04:00
2011-08-12 06:24:19 +04:00
cleanup :
2012-07-25 19:37:18 +04:00
if ( iface )
virInterfaceFree ( iface ) ;
if ( iface_edited )
virInterfaceFree ( iface_edited ) ;
2006-08-30 18:32:32 +04:00
return ret ;
}
/*
2012-07-25 19:37:18 +04:00
* " net-list " command
2006-08-30 18:32:32 +04:00
*/
2012-07-25 19:37:18 +04:00
static const vshCmdInfo info_network_list [ ] = {
{ " help " , N_ ( " list networks " ) } ,
{ " desc " , N_ ( " Returns list of networks. " ) } ,
2006-08-30 18:32:32 +04:00
{ NULL , NULL }
} ;
2012-07-25 19:37:18 +04:00
static const vshCmdOptDef opts_network_list [ ] = {
{ " inactive " , VSH_OT_BOOL , 0 , N_ ( " list inactive networks " ) } ,
{ " all " , VSH_OT_BOOL , 0 , N_ ( " list inactive & active networks " ) } ,
2006-08-30 18:32:32 +04:00
{ NULL , 0 , 0 , NULL }
} ;
2011-04-19 02:37:42 +04:00
static bool
2012-07-25 19:37:18 +04:00
cmdNetworkList ( vshControl * ctl , const vshCmd * cmd ATTRIBUTE_UNUSED )
2006-08-30 18:32:32 +04:00
{
2012-07-25 19:37:18 +04:00
bool inactive = vshCommandOptBool ( cmd , " inactive " ) ;
bool all = vshCommandOptBool ( cmd , " all " ) ;
bool active = ! inactive | | all ;
int maxactive = 0 , maxinactive = 0 , i ;
char * * activeNames = NULL , * * inactiveNames = NULL ;
inactive | = all ;
2006-08-30 18:32:32 +04:00
2010-06-17 18:47:06 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
2011-04-19 02:37:42 +04:00
return false ;
2006-08-30 18:32:32 +04:00
2012-07-25 19:37:18 +04:00
if ( active ) {
maxactive = virConnectNumOfNetworks ( ctl - > conn ) ;
if ( maxactive < 0 ) {
vshError ( ctl , " %s " , _ ( " Failed to list active networks " ) ) ;
return false ;
}
if ( maxactive ) {
activeNames = vshMalloc ( ctl , sizeof ( char * ) * maxactive ) ;
2006-08-30 18:32:32 +04:00
2012-07-25 19:37:18 +04:00
if ( ( maxactive = virConnectListNetworks ( ctl - > conn , activeNames ,
maxactive ) ) < 0 ) {
vshError ( ctl , " %s " , _ ( " Failed to list active networks " ) ) ;
VIR_FREE ( activeNames ) ;
return false ;
}
2006-08-30 18:32:32 +04:00
2012-07-25 19:37:18 +04:00
qsort ( & activeNames [ 0 ] , maxactive , sizeof ( char * ) , vshNameSorter ) ;
2011-08-30 19:51:25 +04:00
}
2012-07-25 19:37:18 +04:00
}
if ( inactive ) {
maxinactive = virConnectNumOfDefinedNetworks ( ctl - > conn ) ;
if ( maxinactive < 0 ) {
vshError ( ctl , " %s " , _ ( " Failed to list inactive networks " ) ) ;
VIR_FREE ( activeNames ) ;
return false ;
}
if ( maxinactive ) {
inactiveNames = vshMalloc ( ctl , sizeof ( char * ) * maxinactive ) ;
if ( ( maxinactive =
virConnectListDefinedNetworks ( ctl - > conn , inactiveNames ,
maxinactive ) ) < 0 ) {
vshError ( ctl , " %s " , _ ( " Failed to list inactive networks " ) ) ;
VIR_FREE ( activeNames ) ;
VIR_FREE ( inactiveNames ) ;
return false ;
2011-08-30 19:51:25 +04:00
}
2012-07-25 19:37:18 +04:00
qsort ( & inactiveNames [ 0 ] , maxinactive , sizeof ( char * ) , vshNameSorter ) ;
2011-08-30 19:51:25 +04:00
}
}
2012-07-25 19:37:18 +04:00
vshPrintExtra ( ctl , " %-20s %-10s %s \n " , _ ( " Name " ) , _ ( " State " ) ,
_ ( " Autostart " ) ) ;
vshPrintExtra ( ctl , " ----------------------------------------- \n " ) ;
2011-08-30 19:51:25 +04:00
2012-07-25 19:37:18 +04:00
for ( i = 0 ; i < maxactive ; i + + ) {
virNetworkPtr network =
virNetworkLookupByName ( ctl - > conn , activeNames [ i ] ) ;
const char * autostartStr ;
int autostart = 0 ;
2011-08-30 19:51:25 +04:00
2012-07-25 19:37:18 +04:00
/* this kind of work with networks is not atomic operation */
if ( ! network ) {
VIR_FREE ( activeNames [ i ] ) ;
continue ;
}
2011-08-30 19:51:25 +04:00
2012-07-25 19:37:18 +04:00
if ( virNetworkGetAutostart ( network , & autostart ) < 0 )
autostartStr = _ ( " no autostart " ) ;
else
autostartStr = autostart ? _ ( " yes " ) : _ ( " no " ) ;
2011-08-30 19:51:25 +04:00
2012-07-25 19:37:18 +04:00
vshPrint ( ctl , " %-20s %-10s %-10s \n " ,
virNetworkGetName ( network ) ,
_ ( " active " ) ,
autostartStr ) ;
virNetworkFree ( network ) ;
VIR_FREE ( activeNames [ i ] ) ;
}
for ( i = 0 ; i < maxinactive ; i + + ) {
virNetworkPtr network = virNetworkLookupByName ( ctl - > conn , inactiveNames [ i ] ) ;
const char * autostartStr ;
int autostart = 0 ;
/* this kind of work with networks is not atomic operation */
if ( ! network ) {
VIR_FREE ( inactiveNames [ i ] ) ;
continue ;
}
if ( virNetworkGetAutostart ( network , & autostart ) < 0 )
autostartStr = _ ( " no autostart " ) ;
else
autostartStr = autostart ? _ ( " yes " ) : _ ( " no " ) ;
vshPrint ( ctl , " %-20s %-10s %-10s \n " ,
inactiveNames [ i ] ,
_ ( " inactive " ) ,
autostartStr ) ;
virNetworkFree ( network ) ;
VIR_FREE ( inactiveNames [ i ] ) ;
}
VIR_FREE ( activeNames ) ;
VIR_FREE ( inactiveNames ) ;
return true ;
2006-08-30 18:32:32 +04:00
}
2012-07-25 19:37:18 +04:00
2006-01-20 13:00:08 +03:00
/*
2012-07-25 19:37:18 +04:00
* " net-name " command
2006-01-20 13:00:08 +03:00
*/
2012-07-25 19:37:18 +04:00
static const vshCmdInfo info_network_name [ ] = {
{ " help " , N_ ( " convert a network UUID to network name " ) } ,
{ " desc " , " " } ,
2006-03-15 15:13:25 +03:00
{ NULL , NULL }
2006-01-20 13:00:08 +03:00
} ;
2012-07-25 19:37:18 +04:00
static const vshCmdOptDef opts_network_name [ ] = {
{ " network " , VSH_OT_DATA , VSH_OFLAG_REQ , N_ ( " network uuid " ) } ,
2006-03-15 15:13:25 +03:00
{ NULL , 0 , 0 , NULL }
2006-01-20 13:00:08 +03:00
} ;
2011-12-20 18:35:15 +04:00
static bool
2012-07-25 19:37:18 +04:00
cmdNetworkName ( vshControl * ctl , const vshCmd * cmd )
2011-12-20 18:35:15 +04:00
{
2012-07-25 19:37:18 +04:00
virNetworkPtr network ;
2011-12-20 18:35:15 +04:00
2012-07-25 19:37:18 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
return false ;
if ( ! ( network = vshCommandOptNetworkBy ( ctl , cmd , NULL ,
VSH_BYUUID ) ) )
2011-12-20 18:35:15 +04:00
return false ;
2012-07-25 19:37:18 +04:00
vshPrint ( ctl , " %s \n " , virNetworkGetName ( network ) ) ;
virNetworkFree ( network ) ;
return true ;
2006-01-20 13:00:08 +03:00
}
2012-07-25 19:37:18 +04:00
2011-07-20 20:23:57 +04:00
/*
2012-07-25 19:37:18 +04:00
* " net-start " command
2011-07-20 20:23:57 +04:00
*/
2012-07-25 19:37:18 +04:00
static const vshCmdInfo info_network_start [ ] = {
{ " help " , N_ ( " start a (previously defined) inactive network " ) } ,
{ " desc " , N_ ( " Start a network. " ) } ,
2011-07-20 20:23:57 +04:00
{ NULL , NULL }
} ;
2012-07-25 19:37:18 +04:00
static const vshCmdOptDef opts_network_start [ ] = {
{ " network " , VSH_OT_DATA , VSH_OFLAG_REQ , N_ ( " network name or uuid " ) } ,
2011-07-20 20:23:57 +04:00
{ NULL , 0 , 0 , NULL }
} ;
static bool
2012-07-25 19:37:18 +04:00
cmdNetworkStart ( vshControl * ctl , const vshCmd * cmd )
2011-07-20 20:23:57 +04:00
{
2012-07-25 19:37:18 +04:00
virNetworkPtr network ;
bool ret = true ;
const char * name = NULL ;
2011-07-20 20:23:57 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
return false ;
2012-07-25 19:37:18 +04:00
if ( ! ( network = vshCommandOptNetwork ( ctl , cmd , & name ) ) )
return false ;
2011-07-20 20:23:57 +04:00
2012-07-25 19:37:18 +04:00
if ( virNetworkCreate ( network ) = = 0 ) {
vshPrint ( ctl , _ ( " Network %s started \n " ) , name ) ;
} else {
vshError ( ctl , _ ( " Failed to start network %s " ) , name ) ;
ret = false ;
}
virNetworkFree ( network ) ;
2011-07-20 20:23:57 +04:00
return ret ;
}
2012-07-25 19:37:18 +04:00
2011-07-20 20:23:57 +04:00
/*
2012-07-25 19:37:18 +04:00
* " net-undefine " command
2011-07-20 20:23:57 +04:00
*/
2012-07-25 19:37:18 +04:00
static const vshCmdInfo info_network_undefine [ ] = {
{ " help " , N_ ( " undefine an inactive network " ) } ,
{ " desc " , N_ ( " Undefine the configuration for an inactive network. " ) } ,
2011-07-20 20:23:57 +04:00
{ NULL , NULL }
} ;
2012-07-25 19:37:18 +04:00
static const vshCmdOptDef opts_network_undefine [ ] = {
{ " network " , VSH_OT_DATA , VSH_OFLAG_REQ , N_ ( " network name or uuid " ) } ,
2011-07-20 20:23:57 +04:00
{ NULL , 0 , 0 , NULL }
} ;
static bool
2012-07-25 19:37:18 +04:00
cmdNetworkUndefine ( vshControl * ctl , const vshCmd * cmd )
2011-07-20 20:23:57 +04:00
{
2012-07-25 19:37:18 +04:00
virNetworkPtr network ;
bool ret = true ;
const char * name ;
2011-07-20 20:23:57 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
return false ;
2012-07-25 19:37:18 +04:00
if ( ! ( network = vshCommandOptNetwork ( ctl , cmd , & name ) ) )
2011-07-20 20:23:57 +04:00
return false ;
2012-07-25 19:37:18 +04:00
if ( virNetworkUndefine ( network ) = = 0 ) {
vshPrint ( ctl , _ ( " Network %s has been undefined \n " ) , name ) ;
} else {
vshError ( ctl , _ ( " Failed to undefine network %s " ) , name ) ;
ret = false ;
2011-07-20 20:23:57 +04:00
}
2012-07-25 19:37:18 +04:00
virNetworkFree ( network ) ;
2011-07-20 20:23:57 +04:00
return ret ;
}
2012-07-25 19:37:18 +04:00
2011-07-20 20:23:57 +04:00
/*
2012-07-25 19:37:18 +04:00
* " net-uuid " command
2011-07-20 20:23:57 +04:00
*/
2012-07-25 19:37:18 +04:00
static const vshCmdInfo info_network_uuid [ ] = {
{ " help " , N_ ( " convert a network name to network UUID " ) } ,
{ " desc " , " " } ,
2011-07-20 20:23:57 +04:00
{ NULL , NULL }
} ;
2012-07-25 19:37:18 +04:00
static const vshCmdOptDef opts_network_uuid [ ] = {
{ " network " , VSH_OT_DATA , VSH_OFLAG_REQ , N_ ( " network name " ) } ,
2011-07-20 20:23:57 +04:00
{ NULL , 0 , 0 , NULL }
} ;
static bool
2012-07-25 19:37:18 +04:00
cmdNetworkUuid ( vshControl * ctl , const vshCmd * cmd )
2011-07-20 20:23:57 +04:00
{
2012-07-25 19:37:18 +04:00
virNetworkPtr network ;
char uuid [ VIR_UUID_STRING_BUFLEN ] ;
2011-07-20 20:23:57 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
return false ;
2012-07-25 19:37:18 +04:00
if ( ! ( network = vshCommandOptNetworkBy ( ctl , cmd , NULL ,
VSH_BYNAME ) ) )
2011-07-20 20:23:57 +04:00
return false ;
2012-07-25 19:37:18 +04:00
if ( virNetworkGetUUIDString ( network , uuid ) ! = - 1 )
vshPrint ( ctl , " %s \n " , uuid ) ;
else
vshError ( ctl , " %s " , _ ( " failed to get network UUID " ) ) ;
2011-07-20 20:23:57 +04:00
2012-07-25 19:37:18 +04:00
virNetworkFree ( network ) ;
return true ;
2011-07-20 20:23:57 +04:00
}
2012-07-25 19:37:18 +04:00
/**************************************************************************/
2010-04-01 20:05:38 +04:00
/*
2012-07-25 19:37:18 +04:00
* " iface-list " command
2010-04-01 20:05:38 +04:00
*/
2012-07-25 19:37:18 +04:00
static const vshCmdInfo info_interface_list [ ] = {
{ " help " , N_ ( " list physical host interfaces " ) } ,
{ " desc " , N_ ( " Returns list of physical host interfaces. " ) } ,
2010-04-01 20:05:38 +04:00
{ NULL , NULL }
} ;
2012-07-25 19:37:18 +04:00
static const vshCmdOptDef opts_interface_list [ ] = {
{ " inactive " , VSH_OT_BOOL , 0 , N_ ( " list inactive interfaces " ) } ,
{ " all " , VSH_OT_BOOL , 0 , N_ ( " list inactive & active interfaces " ) } ,
2010-04-01 20:05:38 +04:00
{ NULL , 0 , 0 , NULL }
} ;
2012-07-25 19:37:18 +04:00
static bool
cmdInterfaceList ( vshControl * ctl , const vshCmd * cmd ATTRIBUTE_UNUSED )
2010-04-01 20:05:38 +04:00
{
2012-07-25 19:37:18 +04:00
bool inactive = vshCommandOptBool ( cmd , " inactive " ) ;
bool all = vshCommandOptBool ( cmd , " all " ) ;
bool active = ! inactive | | all ;
int maxactive = 0 , maxinactive = 0 , i ;
char * * activeNames = NULL , * * inactiveNames = NULL ;
inactive | = all ;
2010-04-01 20:05:38 +04:00
2010-06-17 18:47:06 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
2012-07-25 19:37:18 +04:00
return false ;
2010-04-01 20:05:38 +04:00
2012-07-25 19:37:18 +04:00
if ( active ) {
maxactive = virConnectNumOfInterfaces ( ctl - > conn ) ;
if ( maxactive < 0 ) {
vshError ( ctl , " %s " , _ ( " Failed to list active interfaces " ) ) ;
return false ;
}
if ( maxactive ) {
activeNames = vshMalloc ( ctl , sizeof ( char * ) * maxactive ) ;
2011-07-09 07:09:16 +04:00
2012-07-25 19:37:18 +04:00
if ( ( maxactive = virConnectListInterfaces ( ctl - > conn , activeNames ,
maxactive ) ) < 0 ) {
vshError ( ctl , " %s " , _ ( " Failed to list active interfaces " ) ) ;
VIR_FREE ( activeNames ) ;
return false ;
}
2010-04-01 20:05:38 +04:00
2012-07-25 19:37:18 +04:00
qsort ( & activeNames [ 0 ] , maxactive , sizeof ( char * ) , vshNameSorter ) ;
}
2010-04-01 20:05:38 +04:00
}
2012-07-25 19:37:18 +04:00
if ( inactive ) {
maxinactive = virConnectNumOfDefinedInterfaces ( ctl - > conn ) ;
if ( maxinactive < 0 ) {
vshError ( ctl , " %s " , _ ( " Failed to list inactive interfaces " ) ) ;
VIR_FREE ( activeNames ) ;
return false ;
}
if ( maxinactive ) {
inactiveNames = vshMalloc ( ctl , sizeof ( char * ) * maxinactive ) ;
2010-04-01 20:05:38 +04:00
2012-07-25 19:37:18 +04:00
if ( ( maxinactive =
virConnectListDefinedInterfaces ( ctl - > conn , inactiveNames ,
maxinactive ) ) < 0 ) {
vshError ( ctl , " %s " , _ ( " Failed to list inactive interfaces " ) ) ;
VIR_FREE ( activeNames ) ;
VIR_FREE ( inactiveNames ) ;
return false ;
}
2011-12-20 18:50:52 +04:00
2012-07-25 19:37:18 +04:00
qsort ( & inactiveNames [ 0 ] , maxinactive , sizeof ( char * ) , vshNameSorter ) ;
}
}
vshPrintExtra ( ctl , " %-20s %-10s %s \n " , _ ( " Name " ) , _ ( " State " ) ,
_ ( " MAC Address " ) ) ;
vshPrintExtra ( ctl , " -------------------------------------------- \n " ) ;
2011-12-20 18:50:52 +04:00
2012-07-25 19:37:18 +04:00
for ( i = 0 ; i < maxactive ; i + + ) {
virInterfacePtr iface =
virInterfaceLookupByName ( ctl - > conn , activeNames [ i ] ) ;
2011-12-20 18:50:52 +04:00
2012-07-25 19:37:18 +04:00
/* this kind of work with interfaces is not atomic */
if ( ! iface ) {
VIR_FREE ( activeNames [ i ] ) ;
continue ;
}
2011-12-20 18:50:52 +04:00
2012-07-25 19:37:18 +04:00
vshPrint ( ctl , " %-20s %-10s %s \n " ,
virInterfaceGetName ( iface ) ,
_ ( " active " ) ,
virInterfaceGetMACString ( iface ) ) ;
virInterfaceFree ( iface ) ;
VIR_FREE ( activeNames [ i ] ) ;
}
for ( i = 0 ; i < maxinactive ; i + + ) {
virInterfacePtr iface =
virInterfaceLookupByName ( ctl - > conn , inactiveNames [ i ] ) ;
2011-12-20 18:50:52 +04:00
2012-07-25 19:37:18 +04:00
/* this kind of work with interfaces is not atomic */
if ( ! iface ) {
VIR_FREE ( inactiveNames [ i ] ) ;
continue ;
}
2011-12-20 18:50:52 +04:00
2012-07-25 19:37:18 +04:00
vshPrint ( ctl , " %-20s %-10s %s \n " ,
virInterfaceGetName ( iface ) ,
_ ( " inactive " ) ,
virInterfaceGetMACString ( iface ) ) ;
virInterfaceFree ( iface ) ;
VIR_FREE ( inactiveNames [ i ] ) ;
}
VIR_FREE ( activeNames ) ;
VIR_FREE ( inactiveNames ) ;
return true ;
2011-07-09 07:09:16 +04:00
2010-04-01 20:05:38 +04:00
}
2010-06-22 17:50:17 +04:00
/*
2012-07-25 19:37:18 +04:00
* " iface-name " command
2010-06-22 17:50:17 +04:00
*/
2012-07-25 19:37:18 +04:00
static const vshCmdInfo info_interface_name [ ] = {
{ " help " , N_ ( " convert an interface MAC address to interface name " ) } ,
{ " desc " , " " } ,
2010-06-22 17:50:17 +04:00
{ NULL , NULL }
} ;
2012-07-25 19:37:18 +04:00
static const vshCmdOptDef opts_interface_name [ ] = {
{ " interface " , VSH_OT_DATA , VSH_OFLAG_REQ , N_ ( " interface mac " ) } ,
2010-06-22 17:50:17 +04:00
{ NULL , 0 , 0 , NULL }
} ;
2011-04-19 02:37:42 +04:00
static bool
2012-07-25 19:37:18 +04:00
cmdInterfaceName ( vshControl * ctl , const vshCmd * cmd )
2010-06-22 17:50:17 +04:00
{
2012-07-25 19:37:18 +04:00
virInterfacePtr iface ;
2010-06-22 17:50:17 +04:00
2010-06-17 18:47:06 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
2011-04-19 02:37:42 +04:00
return false ;
2012-07-25 19:37:18 +04:00
if ( ! ( iface = vshCommandOptInterfaceBy ( ctl , cmd , NULL , NULL ,
VSH_BYMAC ) ) )
2011-04-19 02:37:42 +04:00
return false ;
2010-06-22 17:50:17 +04:00
2012-07-25 19:37:18 +04:00
vshPrint ( ctl , " %s \n " , virInterfaceGetName ( iface ) ) ;
virInterfaceFree ( iface ) ;
return true ;
2010-06-22 17:50:17 +04:00
}
2007-06-05 16:06:08 +04:00
/*
2012-07-25 19:37:18 +04:00
* " iface-mac " command
2007-06-05 16:06:08 +04:00
*/
2012-07-25 19:37:18 +04:00
static const vshCmdInfo info_interface_mac [ ] = {
{ " help " , N_ ( " convert an interface name to interface MAC address " ) } ,
{ " desc " , " " } ,
2007-06-05 16:06:08 +04:00
{ NULL , NULL }
} ;
2012-07-25 19:37:18 +04:00
static const vshCmdOptDef opts_interface_mac [ ] = {
{ " interface " , VSH_OT_DATA , VSH_OFLAG_REQ , N_ ( " interface name " ) } ,
2007-06-05 16:06:08 +04:00
{ NULL , 0 , 0 , NULL }
} ;
2012-07-25 19:37:18 +04:00
static bool
cmdInterfaceMAC ( vshControl * ctl , const vshCmd * cmd )
2007-06-05 16:06:08 +04:00
{
2012-07-25 19:37:18 +04:00
virInterfacePtr iface ;
2009-07-09 17:11:21 +04:00
2012-07-25 19:37:18 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
return false ;
if ( ! ( iface = vshCommandOptInterfaceBy ( ctl , cmd , NULL , NULL ,
VSH_BYNAME ) ) )
return false ;
2007-06-05 16:06:08 +04:00
2012-07-25 19:37:18 +04:00
vshPrint ( ctl , " %s \n " , virInterfaceGetMACString ( iface ) ) ;
virInterfaceFree ( iface ) ;
return true ;
2009-07-09 17:11:21 +04:00
}
2007-06-05 16:06:08 +04:00
2012-07-25 19:37:18 +04:00
/*
* " iface-dumpxml " command
*/
static const vshCmdInfo info_interface_dumpxml [ ] = {
{ " help " , N_ ( " interface information in XML " ) } ,
{ " desc " , N_ ( " Output the physical host interface information as an XML dump to stdout. " ) } ,
{ NULL , NULL }
} ;
static const vshCmdOptDef opts_interface_dumpxml [ ] = {
{ " interface " , VSH_OT_DATA , VSH_OFLAG_REQ , N_ ( " interface name or MAC address " ) } ,
{ " inactive " , VSH_OT_BOOL , 0 , N_ ( " show inactive defined XML " ) } ,
{ NULL , 0 , 0 , NULL }
} ;
2008-10-08 20:28:48 +04:00
2011-04-19 02:37:42 +04:00
static bool
2012-07-25 19:37:18 +04:00
cmdInterfaceDumpXML ( vshControl * ctl , const vshCmd * cmd )
2009-07-09 17:11:21 +04:00
{
2012-07-25 19:37:18 +04:00
virInterfacePtr iface ;
bool ret = true ;
char * dump ;
2011-05-17 10:20:03 +04:00
unsigned int flags = 0 ;
2012-07-25 19:37:18 +04:00
bool inactive = vshCommandOptBool ( cmd , " inactive " ) ;
2011-05-17 10:20:03 +04:00
2012-07-25 19:37:18 +04:00
if ( inactive )
flags | = VIR_INTERFACE_XML_INACTIVE ;
2007-06-05 16:06:08 +04:00
2010-06-17 18:47:06 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
2011-04-19 02:37:42 +04:00
return false ;
2007-06-05 16:06:08 +04:00
2012-07-25 19:37:18 +04:00
if ( ! ( iface = vshCommandOptInterface ( ctl , cmd , NULL ) ) )
2011-04-19 02:37:42 +04:00
return false ;
2007-06-05 16:06:08 +04:00
2012-07-25 19:37:18 +04:00
dump = virInterfaceGetXMLDesc ( iface , flags ) ;
if ( dump ! = NULL ) {
vshPrint ( ctl , " %s " , dump ) ;
VIR_FREE ( dump ) ;
2007-06-05 16:06:08 +04:00
} else {
2012-07-25 19:37:18 +04:00
ret = false ;
2007-06-05 16:06:08 +04:00
}
2009-07-09 17:11:21 +04:00
2012-07-25 19:37:18 +04:00
virInterfaceFree ( iface ) ;
return ret ;
2007-06-05 16:06:08 +04:00
}
2006-01-20 13:00:08 +03:00
/*
2012-07-25 19:37:18 +04:00
* " iface-define " command
2006-01-20 13:00:08 +03:00
*/
2012-07-25 19:37:18 +04:00
static const vshCmdInfo info_interface_define [ ] = {
{ " help " , N_ ( " define (but don't start) a physical host interface from an XML file " ) } ,
{ " desc " , N_ ( " Define a physical host interface. " ) } ,
2006-03-15 15:13:25 +03:00
{ NULL , NULL }
2006-01-20 13:00:08 +03:00
} ;
2012-07-25 19:37:18 +04:00
static const vshCmdOptDef opts_interface_define [ ] = {
{ " file " , VSH_OT_DATA , VSH_OFLAG_REQ , N_ ( " file containing an XML interface description " ) } ,
2006-03-15 15:13:25 +03:00
{ NULL , 0 , 0 , NULL }
2006-01-20 13:00:08 +03:00
} ;
2011-04-19 02:37:42 +04:00
static bool
2012-07-25 19:37:18 +04:00
cmdInterfaceDefine ( vshControl * ctl , const vshCmd * cmd )
2006-03-15 15:13:25 +03:00
{
2012-07-25 19:37:18 +04:00
virInterfacePtr iface ;
2011-03-08 19:29:31 +03:00
const char * from = NULL ;
2012-07-25 19:37:18 +04:00
bool ret = true ;
char * buffer ;
2006-03-15 15:13:25 +03:00
2010-06-17 18:47:06 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
2011-04-19 02:37:42 +04:00
return false ;
2006-01-20 13:00:08 +03:00
2011-03-08 19:29:31 +03:00
if ( vshCommandOptString ( cmd , " file " , & from ) < = 0 )
2011-04-19 02:37:42 +04:00
return false ;
2006-03-15 15:13:25 +03:00
2012-07-25 19:37:18 +04:00
if ( virFileReadAll ( from , VIRSH_MAX_XML_FILE , & buffer ) < 0 )
2011-07-20 00:24:29 +04:00
return false ;
2012-07-25 19:37:18 +04:00
iface = virInterfaceDefineXML ( ctl - > conn , buffer , 0 ) ;
VIR_FREE ( buffer ) ;
2011-07-20 00:24:29 +04:00
2012-07-25 19:37:18 +04:00
if ( iface ! = NULL ) {
vshPrint ( ctl , _ ( " Interface %s defined from %s \n " ) ,
virInterfaceGetName ( iface ) , from ) ;
virInterfaceFree ( iface ) ;
} else {
vshError ( ctl , _ ( " Failed to define interface from %s " ) , from ) ;
ret = false ;
2006-01-20 13:00:08 +03:00
}
2012-07-25 19:37:18 +04:00
return ret ;
}
2006-01-20 13:00:08 +03:00
2006-11-22 20:48:29 +03:00
/*
2012-07-25 19:37:18 +04:00
* " iface-undefine " command
2006-11-22 20:48:29 +03:00
*/
2012-07-25 19:37:18 +04:00
static const vshCmdInfo info_interface_undefine [ ] = {
{ " help " , N_ ( " undefine a physical host interface (remove it from configuration) " ) } ,
{ " desc " , N_ ( " undefine an interface. " ) } ,
2006-11-22 20:48:29 +03:00
{ NULL , NULL }
} ;
2012-07-25 19:37:18 +04:00
static const vshCmdOptDef opts_interface_undefine [ ] = {
{ " interface " , VSH_OT_DATA , VSH_OFLAG_REQ , N_ ( " interface name or MAC address " ) } ,
2006-11-22 20:48:29 +03:00
{ NULL , 0 , 0 , NULL }
} ;
2011-12-20 17:56:33 +04:00
static bool
2012-07-25 19:37:18 +04:00
cmdInterfaceUndefine ( vshControl * ctl , const vshCmd * cmd )
2011-12-20 17:56:33 +04:00
{
2012-07-25 19:37:18 +04:00
virInterfacePtr iface ;
bool ret = true ;
const char * name ;
2011-12-20 17:56:33 +04:00
2012-07-25 19:37:18 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
2011-12-20 17:56:33 +04:00
return false ;
2012-07-25 19:37:18 +04:00
if ( ! ( iface = vshCommandOptInterface ( ctl , cmd , & name ) ) )
2011-12-20 17:56:33 +04:00
return false ;
2012-07-25 19:37:18 +04:00
if ( virInterfaceUndefine ( iface ) = = 0 ) {
vshPrint ( ctl , _ ( " Interface %s undefined \n " ) , name ) ;
} else {
vshError ( ctl , _ ( " Failed to undefine interface %s " ) , name ) ;
ret = false ;
}
2011-07-09 07:09:16 +04:00
2012-07-25 19:37:18 +04:00
virInterfaceFree ( iface ) ;
2006-11-22 20:48:29 +03:00
return ret ;
}
2012-07-25 19:37:18 +04:00
/*
* " iface-start " command
*/
static const vshCmdInfo info_interface_start [ ] = {
{ " help " , N_ ( " start a physical host interface (enable it / \" if-up \" ) " ) } ,
{ " desc " , N_ ( " start a physical host interface. " ) } ,
2011-05-12 20:29:12 +04:00
{ NULL , NULL }
} ;
2012-07-25 19:37:18 +04:00
static const vshCmdOptDef opts_interface_start [ ] = {
{ " interface " , VSH_OT_DATA , VSH_OFLAG_REQ , N_ ( " interface name or MAC address " ) } ,
2011-05-12 20:29:12 +04:00
{ NULL , 0 , 0 , NULL }
} ;
static bool
2012-07-25 19:37:18 +04:00
cmdInterfaceStart ( vshControl * ctl , const vshCmd * cmd )
2011-05-12 20:29:12 +04:00
{
2012-07-25 19:37:18 +04:00
virInterfacePtr iface ;
bool ret = true ;
const char * name ;
2011-05-12 20:29:12 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
return false ;
2012-07-25 19:37:18 +04:00
if ( ! ( iface = vshCommandOptInterface ( ctl , cmd , & name ) ) )
2011-05-12 20:29:12 +04:00
return false ;
2012-07-25 19:37:18 +04:00
if ( virInterfaceCreate ( iface , 0 ) = = 0 ) {
vshPrint ( ctl , _ ( " Interface %s started \n " ) , name ) ;
2011-10-01 05:05:13 +04:00
} else {
2012-07-25 19:37:18 +04:00
vshError ( ctl , _ ( " Failed to start interface %s " ) , name ) ;
ret = false ;
2011-05-12 20:29:12 +04:00
}
2012-07-25 19:37:18 +04:00
virInterfaceFree ( iface ) ;
2011-05-12 20:29:12 +04:00
return ret ;
}
2005-12-09 02:01:48 +03:00
/*
2012-07-25 19:37:18 +04:00
* " iface-destroy " command
2005-12-09 02:01:48 +03:00
*/
2012-07-25 19:37:18 +04:00
static const vshCmdInfo info_interface_destroy [ ] = {
{ " help " , N_ ( " destroy a physical host interface (disable it / \" if-down \" ) " ) } ,
{ " desc " , N_ ( " forcefully stop a physical host interface. " ) } ,
2006-03-15 15:13:25 +03:00
{ NULL , NULL }
2005-12-09 02:01:48 +03:00
} ;
2012-07-25 19:37:18 +04:00
static const vshCmdOptDef opts_interface_destroy [ ] = {
{ " interface " , VSH_OT_DATA , VSH_OFLAG_REQ , N_ ( " interface name or MAC address " ) } ,
2006-03-15 15:13:25 +03:00
{ NULL , 0 , 0 , NULL }
2005-12-09 02:01:48 +03:00
} ;
2011-04-19 02:37:42 +04:00
static bool
2012-07-25 19:37:18 +04:00
cmdInterfaceDestroy ( vshControl * ctl , const vshCmd * cmd )
2006-03-15 15:13:25 +03:00
{
2012-07-25 19:37:18 +04:00
virInterfacePtr iface ;
2011-04-19 02:37:42 +04:00
bool ret = true ;
2011-03-08 19:29:30 +03:00
const char * name ;
2006-03-15 15:13:25 +03:00
2010-06-17 18:47:06 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
2011-04-19 02:37:42 +04:00
return false ;
2005-12-09 02:01:48 +03:00
2012-07-25 19:37:18 +04:00
if ( ! ( iface = vshCommandOptInterface ( ctl , cmd , & name ) ) )
2011-04-19 02:37:42 +04:00
return false ;
2006-03-15 15:13:25 +03:00
2012-07-25 19:37:18 +04:00
if ( virInterfaceDestroy ( iface , 0 ) = = 0 ) {
vshPrint ( ctl , _ ( " Interface %s destroyed \n " ) , name ) ;
2005-12-09 02:01:48 +03:00
} else {
2012-07-25 19:37:18 +04:00
vshError ( ctl , _ ( " Failed to destroy interface %s " ) , name ) ;
2011-04-19 02:37:42 +04:00
ret = false ;
2005-12-09 02:01:48 +03:00
}
2006-03-15 15:13:25 +03:00
2012-07-25 19:37:18 +04:00
virInterfaceFree ( iface ) ;
2005-12-09 02:01:48 +03:00
return ret ;
}
2005-12-16 15:16:41 +03:00
/*
2012-07-25 19:37:18 +04:00
* " iface-begin " command
2005-12-16 15:16:41 +03:00
*/
2012-07-25 19:37:18 +04:00
static const vshCmdInfo info_interface_begin [ ] = {
{ " help " , N_ ( " create a snapshot of current interfaces settings, "
" which can be later committed (iface-commit) or "
" restored (iface-rollback) " ) } ,
{ " desc " , N_ ( " Create a restore point for interfaces settings " ) } ,
2006-03-15 15:13:25 +03:00
{ NULL , NULL }
2005-12-16 15:16:41 +03:00
} ;
2012-07-25 19:37:18 +04:00
static const vshCmdOptDef opts_interface_begin [ ] = {
2006-03-15 15:13:25 +03:00
{ NULL , 0 , 0 , NULL }
2005-12-16 15:16:41 +03:00
} ;
2011-04-19 02:37:42 +04:00
static bool
2012-07-25 19:37:18 +04:00
cmdInterfaceBegin ( vshControl * ctl , const vshCmd * cmd ATTRIBUTE_UNUSED )
2006-03-15 15:13:25 +03:00
{
2010-06-17 18:47:06 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
2011-04-19 02:37:42 +04:00
return false ;
2005-12-16 15:16:41 +03:00
2012-07-25 19:37:18 +04:00
if ( virInterfaceChangeBegin ( ctl - > conn , 0 ) < 0 ) {
vshError ( ctl , " %s " , _ ( " Failed to begin network config change transaction " ) ) ;
2011-04-19 02:37:42 +04:00
return false ;
2005-12-16 15:16:41 +03:00
}
2006-03-15 15:13:25 +03:00
2012-07-25 19:37:18 +04:00
vshPrint ( ctl , " %s " , _ ( " Network config change transaction started \n " ) ) ;
return true ;
2005-12-16 15:16:41 +03:00
}
2006-04-03 17:46:43 +04:00
/*
2012-07-25 19:37:18 +04:00
* " iface-commit " command
2006-04-03 17:46:43 +04:00
*/
2012-07-25 19:37:18 +04:00
static const vshCmdInfo info_interface_commit [ ] = {
{ " help " , N_ ( " commit changes made since iface-begin and free restore point " ) } ,
{ " desc " , N_ ( " commit changes and free restore point " ) } ,
2006-04-03 17:46:43 +04:00
{ NULL , NULL }
} ;
2012-07-25 19:37:18 +04:00
static const vshCmdOptDef opts_interface_commit [ ] = {
2006-04-03 17:46:43 +04:00
{ NULL , 0 , 0 , NULL }
} ;
2011-04-19 02:37:42 +04:00
static bool
2012-07-25 19:37:18 +04:00
cmdInterfaceCommit ( vshControl * ctl , const vshCmd * cmd ATTRIBUTE_UNUSED )
2006-04-03 17:46:43 +04:00
{
2010-06-17 18:47:06 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
2011-04-19 02:37:42 +04:00
return false ;
2006-04-03 17:46:43 +04:00
2012-07-25 19:37:18 +04:00
if ( virInterfaceChangeCommit ( ctl - > conn , 0 ) < 0 ) {
vshError ( ctl , " %s " , _ ( " Failed to commit network config change transaction " ) ) ;
2011-04-19 02:37:42 +04:00
return false ;
2006-04-03 17:46:43 +04:00
}
2012-07-25 19:37:18 +04:00
vshPrint ( ctl , " %s " , _ ( " Network config change transaction committed \n " ) ) ;
return true ;
2006-04-03 17:46:43 +04:00
}
2011-09-29 12:57:12 +04:00
/*
2012-07-25 19:37:18 +04:00
* " iface-rollback " command
2011-09-29 12:57:12 +04:00
*/
2012-07-25 19:37:18 +04:00
static const vshCmdInfo info_interface_rollback [ ] = {
{ " help " , N_ ( " rollback to previous saved configuration created via iface-begin " ) } ,
{ " desc " , N_ ( " rollback to previous restore point " ) } ,
2011-09-29 12:57:12 +04:00
{ NULL , NULL }
} ;
2012-07-25 19:37:18 +04:00
static const vshCmdOptDef opts_interface_rollback [ ] = {
2011-09-29 12:57:12 +04:00
{ NULL , 0 , 0 , NULL }
} ;
static bool
2012-07-25 19:37:18 +04:00
cmdInterfaceRollback ( vshControl * ctl , const vshCmd * cmd ATTRIBUTE_UNUSED )
2011-09-29 12:57:12 +04:00
{
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
return false ;
2012-07-25 19:37:18 +04:00
if ( virInterfaceChangeRollback ( ctl - > conn , 0 ) < 0 ) {
vshError ( ctl , " %s " , _ ( " Failed to rollback network config change transaction " ) ) ;
2011-09-29 12:57:12 +04:00
return false ;
}
2012-07-25 19:37:18 +04:00
vshPrint ( ctl , " %s " , _ ( " Network config change transaction rolled back \n " ) ) ;
return true ;
2011-09-29 12:57:12 +04:00
}
2005-12-09 02:01:48 +03:00
/*
2012-07-25 19:37:18 +04:00
* " iface-bridge " command
2005-12-09 02:01:48 +03:00
*/
2012-07-25 19:37:18 +04:00
static const vshCmdInfo info_interface_bridge [ ] = {
{ " help " , N_ ( " create a bridge device and attach an existing network device to it " ) } ,
{ " desc " , N_ ( " bridge an existing network device " ) } ,
{ NULL , NULL }
2005-12-09 02:01:48 +03:00
} ;
2012-07-25 19:37:18 +04:00
static const vshCmdOptDef opts_interface_bridge [ ] = {
{ " interface " , VSH_OT_DATA , VSH_OFLAG_REQ , N_ ( " existing interface name " ) } ,
{ " bridge " , VSH_OT_DATA , VSH_OFLAG_REQ , N_ ( " new bridge device name " ) } ,
{ " no-stp " , VSH_OT_BOOL , 0 , N_ ( " do not enable STP for this bridge " ) } ,
{ " delay " , VSH_OT_INT , 0 ,
N_ ( " number of seconds to squelch traffic on newly connected ports " ) } ,
{ " no-start " , VSH_OT_BOOL , 0 , N_ ( " don't start the bridge immediately " ) } ,
2006-03-15 15:13:25 +03:00
{ NULL , 0 , 0 , NULL }
2005-12-09 02:01:48 +03:00
} ;
2011-04-19 02:37:42 +04:00
static bool
2012-07-25 19:37:18 +04:00
cmdInterfaceBridge ( vshControl * ctl , const vshCmd * cmd )
2006-03-15 15:13:25 +03:00
{
2012-07-25 19:37:18 +04:00
bool ret = false ;
virInterfacePtr if_handle = NULL , br_handle = NULL ;
const char * if_name , * br_name ;
char * if_type = NULL , * if2_name = NULL , * delay_str = NULL ;
bool stp = false , nostart = false ;
unsigned int delay = 0 ;
char * if_xml = NULL ;
xmlChar * br_xml = NULL ;
int br_xml_size ;
xmlDocPtr xml_doc = NULL ;
xmlXPathContextPtr ctxt = NULL ;
xmlNodePtr top_node , br_node , if_node , cur ;
2006-03-15 15:13:25 +03:00
2010-06-17 18:47:06 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
2012-07-25 19:37:18 +04:00
goto cleanup ;
2005-12-09 02:01:48 +03:00
2012-07-25 19:37:18 +04:00
/* Get a handle to the original device */
if ( ! ( if_handle = vshCommandOptInterfaceBy ( ctl , cmd , " interface " ,
& if_name , VSH_BYNAME ) ) ) {
goto cleanup ;
}
2006-03-15 15:13:25 +03:00
2012-07-25 19:37:18 +04:00
/* Name for new bridge device */
if ( vshCommandOptString ( cmd , " bridge " , & br_name ) < = 0 ) {
vshError ( ctl , " %s " , _ ( " Missing bridge device name in command " ) ) ;
goto cleanup ;
}
2012-02-03 23:14:36 +04:00
2012-07-25 19:37:18 +04:00
/* make sure "new" device doesn't already exist */
if ( ( br_handle = virInterfaceLookupByName ( ctl - > conn , br_name ) ) ) {
vshError ( ctl , _ ( " Network device %s already exists " ) , br_name ) ;
goto cleanup ;
}
2012-02-03 23:14:36 +04:00
2012-07-25 19:37:18 +04:00
/* use "no-stp" because we want "stp" to default true */
stp = ! vshCommandOptBool ( cmd , " no-stp " ) ;
if ( vshCommandOptUInt ( cmd , " delay " , & delay ) < 0 ) {
vshError ( ctl , " %s " , _ ( " Unable to parse delay parameter " ) ) ;
goto cleanup ;
2005-12-09 02:01:48 +03:00
}
2006-03-15 15:13:25 +03:00
2012-07-25 19:37:18 +04:00
nostart = vshCommandOptBool ( cmd , " no-start " ) ;
2005-12-08 13:23:34 +03:00
2012-07-25 19:37:18 +04:00
/* Get the original interface into an xmlDoc */
if ( ! ( if_xml = virInterfaceGetXMLDesc ( if_handle , VIR_INTERFACE_XML_INACTIVE ) ) )
goto cleanup ;
if ( ! ( xml_doc = virXMLParseStringCtxt ( if_xml ,
_ ( " (interface definition) " ) , & ctxt ) ) ) {
vshError ( ctl , _ ( " Failed to parse configuration of %s " ) , if_name ) ;
goto cleanup ;
}
top_node = ctxt - > node ;
2010-02-03 19:45:05 +03:00
2012-07-25 19:37:18 +04:00
/* Verify that the original device isn't already a bridge. */
if ( ! ( if_type = virXMLPropString ( top_node , " type " ) ) ) {
vshError ( ctl , _ ( " Existing device %s has no type " ) , if_name ) ;
goto cleanup ;
}
2010-02-03 19:45:05 +03:00
2012-07-25 19:37:18 +04:00
if ( STREQ ( if_type , " bridge " ) ) {
vshError ( ctl , _ ( " Existing device %s is already a bridge " ) , if_name ) ;
goto cleanup ;
}
2010-02-03 19:45:05 +03:00
2012-07-25 19:37:18 +04:00
/* verify the name in the XML matches the device name */
if ( ! ( if2_name = virXMLPropString ( top_node , " name " ) ) | |
STRNEQ ( if2_name , if_name ) ) {
vshError ( ctl , _ ( " Interface name from config %s doesn't match given supplied name %s " ) ,
if2_name , if_name ) ;
goto cleanup ;
}
2010-02-03 19:45:05 +03:00
2012-07-25 19:37:18 +04:00
/* Create a <bridge> node under <interface>. */
if ( ! ( br_node = xmlNewChild ( top_node , NULL , BAD_CAST " bridge " , NULL ) ) ) {
vshError ( ctl , " %s " , _ ( " Failed to create bridge node in xml document " ) ) ;
goto cleanup ;
}
2010-02-03 19:45:05 +03:00
2012-07-25 19:37:18 +04:00
/* Set stp and delay attributes in <bridge> according to the
* commandline options .
*/
if ( ! xmlSetProp ( br_node , BAD_CAST " stp " , BAD_CAST ( stp ? " on " : " off " ) ) ) {
vshError ( ctl , " %s " , _ ( " Failed to set stp attribute in xml document " ) ) ;
goto cleanup ;
}
2010-02-03 19:45:05 +03:00
2012-07-25 19:37:18 +04:00
if ( ( delay | | stp ) & &
( ( virAsprintf ( & delay_str , " %d " , delay ) < 0 ) | |
! xmlSetProp ( br_node , BAD_CAST " delay " , BAD_CAST delay_str ) ) ) {
vshError ( ctl , _ ( " Failed to set bridge delay %d in xml document " ) , delay ) ;
goto cleanup ;
}
2010-02-03 19:45:05 +03:00
2012-07-25 19:37:18 +04:00
/* Change the type of the outer/master interface to "bridge" and the
* name to the provided bridge name .
*/
if ( ! xmlSetProp ( top_node , BAD_CAST " type " , BAD_CAST " bridge " ) ) {
vshError ( ctl , " %s " , _ ( " Failed to set bridge interface type to 'bridge' in xml document " ) ) ;
goto cleanup ;
}
2010-02-03 19:45:05 +03:00
2012-07-25 19:37:18 +04:00
if ( ! xmlSetProp ( top_node , BAD_CAST " name " , BAD_CAST br_name ) ) {
vshError ( ctl , _ ( " Failed to set master bridge interface name to '%s' in xml document " ) ,
br_name ) ;
goto cleanup ;
}
2010-02-03 19:45:05 +03:00
2012-07-25 19:37:18 +04:00
/* Create an <interface> node under <bridge> that uses the
* original interface ' s type and name .
*/
if ( ! ( if_node = xmlNewChild ( br_node , NULL , BAD_CAST " interface " , NULL ) ) ) {
vshError ( ctl , " %s " , _ ( " Failed to create interface node under bridge node in xml document " ) ) ;
goto cleanup ;
}
2010-02-03 19:45:05 +03:00
2012-07-25 19:37:18 +04:00
/* set the type of the inner/slave interface to the original
* if_type , and the name to the original if_name .
*/
if ( ! xmlSetProp ( if_node , BAD_CAST " type " , BAD_CAST if_type ) ) {
vshError ( ctl , _ ( " Failed to set new slave interface type to '%s' in xml document " ) ,
if_name ) ;
goto cleanup ;
}
if ( ! xmlSetProp ( if_node , BAD_CAST " name " , BAD_CAST if_name ) ) {
vshError ( ctl , _ ( " Failed to set new slave interface name to '%s' in xml document " ) ,
br_name ) ;
goto cleanup ;
}
/* Cycle through all the nodes under the original <interface>,
* moving all < mac > , < bond > and < vlan > nodes down into the new
* lower level < interface > .
*/
cur = top_node - > children ;
while ( cur ) {
xmlNodePtr old = cur ;
cur = cur - > next ;
if ( ( old - > type = = XML_ELEMENT_NODE ) & &
( xmlStrEqual ( old - > name , BAD_CAST " mac " ) | | /* ethernet stuff to move down */
xmlStrEqual ( old - > name , BAD_CAST " bond " ) | | /* bond stuff to move down */
xmlStrEqual ( old - > name , BAD_CAST " vlan " ) ) ) { /* vlan stuff to move down */
xmlUnlinkNode ( old ) ;
if ( ! xmlAddChild ( if_node , old ) ) {
vshError ( ctl , _ ( " Failed to move '%s' element in xml document " ) , old - > name ) ;
xmlFreeNode ( old ) ;
goto cleanup ;
}
2010-02-03 19:45:05 +03:00
}
}
2012-07-25 19:37:18 +04:00
/* The document should now be fully converted; write it out to a string. */
xmlDocDumpMemory ( xml_doc , & br_xml , & br_xml_size ) ;
2010-02-03 22:11:27 +03:00
2012-07-25 19:37:18 +04:00
if ( ! br_xml | | br_xml_size < = 0 ) {
vshError ( ctl , _ ( " Failed to format new xml document for bridge %s " ) , br_name ) ;
goto cleanup ;
}
2010-02-03 22:11:27 +03:00
2012-07-25 19:37:18 +04:00
/* br_xml is the new interface to define. It will automatically undefine the
* independent original interface .
*/
if ( ! ( br_handle = virInterfaceDefineXML ( ctl - > conn , ( char * ) br_xml , 0 ) ) ) {
vshError ( ctl , _ ( " Failed to define new bridge interface %s " ) ,
br_name ) ;
goto cleanup ;
}
2010-02-03 22:11:27 +03:00
2012-07-25 19:37:18 +04:00
vshPrint ( ctl , _ ( " Created bridge %s with attached device %s \n " ) ,
br_name , if_name ) ;
2010-02-03 22:11:27 +03:00
2012-07-25 19:37:18 +04:00
/* start it up unless requested not to */
if ( ! nostart ) {
if ( virInterfaceCreate ( br_handle , 0 ) < 0 ) {
vshError ( ctl , _ ( " Failed to start bridge interface %s " ) , br_name ) ;
goto cleanup ;
}
vshPrint ( ctl , _ ( " Bridge interface %s started \n " ) , br_name ) ;
}
2010-02-03 22:11:27 +03:00
2012-07-25 19:37:18 +04:00
ret = true ;
cleanup :
if ( if_handle )
virInterfaceFree ( if_handle ) ;
if ( br_handle )
virInterfaceFree ( br_handle ) ;
VIR_FREE ( if_xml ) ;
VIR_FREE ( br_xml ) ;
VIR_FREE ( if_type ) ;
VIR_FREE ( if2_name ) ;
VIR_FREE ( delay_str ) ;
xmlXPathFreeContext ( ctxt ) ;
xmlFreeDoc ( xml_doc ) ;
2010-02-03 22:11:27 +03:00
return ret ;
}
2007-09-28 18:28:12 +04:00
/*
2012-07-25 19:37:18 +04:00
* " iface-unbridge " command
2007-09-28 18:28:12 +04:00
*/
2012-07-25 19:37:18 +04:00
static const vshCmdInfo info_interface_unbridge [ ] = {
{ " help " , N_ ( " undefine a bridge device after detaching its slave device " ) } ,
{ " desc " , N_ ( " unbridge a network device " ) } ,
2007-09-28 18:28:12 +04:00
{ NULL , NULL }
} ;
2012-07-25 19:37:18 +04:00
static const vshCmdOptDef opts_interface_unbridge [ ] = {
{ " bridge " , VSH_OT_DATA , VSH_OFLAG_REQ , N_ ( " current bridge device name " ) } ,
{ " no-start " , VSH_OT_BOOL , 0 ,
N_ ( " don't start the un-slaved interface immediately (not recommended) " ) } ,
2007-09-28 18:28:12 +04:00
{ NULL , 0 , 0 , NULL }
} ;
2011-04-19 02:37:42 +04:00
static bool
2012-07-25 19:37:18 +04:00
cmdInterfaceUnbridge ( vshControl * ctl , const vshCmd * cmd )
2007-09-28 18:28:12 +04:00
{
2012-07-25 19:37:18 +04:00
bool ret = false ;
virInterfacePtr if_handle = NULL , br_handle = NULL ;
const char * br_name ;
char * if_type = NULL , * if_name = NULL ;
bool nostart = false ;
char * br_xml = NULL ;
xmlChar * if_xml = NULL ;
int if_xml_size ;
xmlDocPtr xml_doc = NULL ;
2011-02-18 14:42:21 +03:00
xmlXPathContextPtr ctxt = NULL ;
2012-07-25 19:37:18 +04:00
xmlNodePtr top_node , br_node , if_node , cur ;
2007-09-28 18:28:12 +04:00
2010-06-17 18:47:06 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
2012-07-25 19:37:18 +04:00
goto cleanup ;
2007-09-28 18:28:12 +04:00
2012-07-25 19:37:18 +04:00
/* Get a handle to the original device */
if ( ! ( br_handle = vshCommandOptInterfaceBy ( ctl , cmd , " bridge " ,
& br_name , VSH_BYNAME ) ) ) {
2011-03-08 19:29:31 +03:00
goto cleanup ;
}
2011-01-28 21:21:57 +03:00
2012-07-25 19:37:18 +04:00
nostart = vshCommandOptBool ( cmd , " no-start " ) ;
/* Get the bridge xml into an xmlDoc */
if ( ! ( br_xml = virInterfaceGetXMLDesc ( br_handle , VIR_INTERFACE_XML_INACTIVE ) ) )
goto cleanup ;
if ( ! ( xml_doc = virXMLParseStringCtxt ( br_xml ,
_ ( " (bridge interface definition) " ) ,
& ctxt ) ) ) {
vshError ( ctl , _ ( " Failed to parse configuration of %s " ) , br_name ) ;
2011-01-28 21:21:57 +03:00
goto cleanup ;
}
2012-07-25 19:37:18 +04:00
top_node = ctxt - > node ;
2011-01-28 21:21:57 +03:00
2012-07-25 19:37:18 +04:00
/* Verify that the device really is a bridge. */
if ( ! ( if_type = virXMLPropString ( top_node , " type " ) ) ) {
vshError ( ctl , _ ( " Existing device %s has no type " ) , br_name ) ;
goto cleanup ;
}
2011-01-28 21:21:57 +03:00
2012-07-25 19:37:18 +04:00
if ( STRNEQ ( if_type , " bridge " ) ) {
vshError ( ctl , _ ( " Device %s is not a bridge " ) , br_name ) ;
goto cleanup ;
}
VIR_FREE ( if_type ) ;
2011-02-18 14:42:21 +03:00
2012-07-25 19:37:18 +04:00
/* verify the name in the XML matches the device name */
if ( ! ( if_name = virXMLPropString ( top_node , " name " ) ) | |
STRNEQ ( if_name , br_name ) ) {
vshError ( ctl , _ ( " Interface name from config %s doesn't match given supplied name %s " ) ,
if_name , br_name ) ;
goto cleanup ;
}
VIR_FREE ( if_name ) ;
2011-01-28 21:21:57 +03:00
2012-07-25 19:37:18 +04:00
/* Find the <bridge> node under <interface>. */
if ( ! ( br_node = virXPathNode ( " ./bridge " , ctxt ) ) ) {
vshError ( ctl , " %s " , _ ( " No bridge node in xml document " ) ) ;
goto cleanup ;
}
2011-02-18 14:42:21 +03:00
2012-07-25 19:37:18 +04:00
if ( ( if_node = virXPathNode ( " ./bridge/interface[2] " , ctxt ) ) ) {
vshError ( ctl , " %s " , _ ( " Multiple interfaces attached to bridge " ) ) ;
goto cleanup ;
}
if ( ! ( if_node = virXPathNode ( " ./bridge/interface " , ctxt ) ) ) {
vshError ( ctl , " %s " , _ ( " No interface attached to bridge " ) ) ;
goto cleanup ;
}
/* Change the type and name of the outer/master interface to
* the type / name of the attached slave interface .
*/
if ( ! ( if_name = virXMLPropString ( if_node , " name " ) ) ) {
vshError ( ctl , _ ( " Device attached to bridge %s has no name " ) , br_name ) ;
goto cleanup ;
}
if ( ! ( if_type = virXMLPropString ( if_node , " type " ) ) ) {
vshError ( ctl , _ ( " Attached device %s has no type " ) , if_name ) ;
goto cleanup ;
}
if ( ! xmlSetProp ( top_node , BAD_CAST " type " , BAD_CAST if_type ) ) {
vshError ( ctl , _ ( " Failed to set interface type to '%s' in xml document " ) ,
if_type ) ;
goto cleanup ;
}
if ( ! xmlSetProp ( top_node , BAD_CAST " name " , BAD_CAST if_name ) ) {
vshError ( ctl , _ ( " Failed to set interface name to '%s' in xml document " ) ,
if_name ) ;
goto cleanup ;
}
/* Cycle through all the nodes under the attached <interface>,
* moving all < mac > , < bond > and < vlan > nodes up into the toplevel
* < interface > .
*/
cur = if_node - > children ;
while ( cur ) {
xmlNodePtr old = cur ;
cur = cur - > next ;
if ( ( old - > type = = XML_ELEMENT_NODE ) & &
( xmlStrEqual ( old - > name , BAD_CAST " mac " ) | | /* ethernet stuff to move down */
xmlStrEqual ( old - > name , BAD_CAST " bond " ) | | /* bond stuff to move down */
xmlStrEqual ( old - > name , BAD_CAST " vlan " ) ) ) { /* vlan stuff to move down */
xmlUnlinkNode ( old ) ;
if ( ! xmlAddChild ( top_node , old ) ) {
vshError ( ctl , _ ( " Failed to move '%s' element in xml document " ) , old - > name ) ;
xmlFreeNode ( old ) ;
2011-02-18 14:42:21 +03:00
goto cleanup ;
}
}
2012-07-25 19:37:18 +04:00
}
2011-02-18 14:42:21 +03:00
2012-07-25 19:37:18 +04:00
/* The document should now be fully converted; write it out to a string. */
xmlDocDumpMemory ( xml_doc , & if_xml , & if_xml_size ) ;
2011-01-28 21:21:57 +03:00
2012-07-25 19:37:18 +04:00
if ( ! if_xml | | if_xml_size < = 0 ) {
vshError ( ctl , _ ( " Failed to format new xml document for un-enslaved interface %s " ) ,
if_name ) ;
goto cleanup ;
}
2011-01-28 21:21:57 +03:00
2012-07-25 19:37:18 +04:00
/* Destroy and Undefine the bridge device, since we otherwise
* can ' t safely define the unattached device .
*/
if ( virInterfaceDestroy ( br_handle , 0 ) < 0 ) {
vshError ( ctl , _ ( " Failed to destroy bridge interface %s " ) , br_name ) ;
goto cleanup ;
}
if ( virInterfaceUndefine ( br_handle ) < 0 ) {
vshError ( ctl , _ ( " Failed to undefine bridge interface %s " ) , br_name ) ;
goto cleanup ;
2007-09-28 18:28:12 +04:00
}
2012-07-25 19:37:18 +04:00
/* if_xml is the new interface to define.
*/
if ( ! ( if_handle = virInterfaceDefineXML ( ctl - > conn , ( char * ) if_xml , 0 ) ) ) {
vshError ( ctl , _ ( " Failed to define new interface %s " ) , if_name ) ;
goto cleanup ;
}
2007-09-28 18:28:12 +04:00
2012-07-25 19:37:18 +04:00
vshPrint ( ctl , _ ( " Device %s un-attached from bridge %s \n " ) ,
if_name , br_name ) ;
/* unless requested otherwise, undefine the bridge device */
if ( ! nostart ) {
if ( virInterfaceCreate ( if_handle , 0 ) < 0 ) {
vshError ( ctl , _ ( " Failed to start interface %s " ) , if_name ) ;
goto cleanup ;
}
vshPrint ( ctl , _ ( " Interface %s started \n " ) , if_name ) ;
}
ret = true ;
cleanup :
if ( if_handle )
virInterfaceFree ( if_handle ) ;
if ( br_handle )
virInterfaceFree ( br_handle ) ;
VIR_FREE ( if_xml ) ;
VIR_FREE ( br_xml ) ;
VIR_FREE ( if_type ) ;
VIR_FREE ( if_name ) ;
2011-02-18 14:42:21 +03:00
xmlXPathFreeContext ( ctxt ) ;
2012-07-25 19:37:18 +04:00
xmlFreeDoc ( xml_doc ) ;
return ret ;
2007-09-28 18:28:12 +04:00
}
2010-09-30 01:20:23 +04:00
/*
2012-07-25 19:37:18 +04:00
* " nwfilter-define " command
2010-09-30 01:20:23 +04:00
*/
2012-07-25 19:37:18 +04:00
static const vshCmdInfo info_nwfilter_define [ ] = {
{ " help " , N_ ( " define or update a network filter from an XML file " ) } ,
{ " desc " , N_ ( " Define a new network filter or update an existing one. " ) } ,
2010-09-30 01:20:23 +04:00
{ NULL , NULL }
} ;
2012-07-25 19:37:18 +04:00
static const vshCmdOptDef opts_nwfilter_define [ ] = {
{ " file " , VSH_OT_DATA , VSH_OFLAG_REQ , N_ ( " file containing an XML network filter description " ) } ,
2010-09-30 01:20:23 +04:00
{ NULL , 0 , 0 , NULL }
} ;
2011-04-19 02:37:42 +04:00
static bool
2012-07-25 19:37:18 +04:00
cmdNWFilterDefine ( vshControl * ctl , const vshCmd * cmd )
2010-09-30 01:20:23 +04:00
{
2012-07-25 19:37:18 +04:00
virNWFilterPtr nwfilter ;
const char * from = NULL ;
bool ret = true ;
char * buffer ;
2010-09-30 01:20:23 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
2011-04-19 02:37:42 +04:00
return false ;
2010-09-30 01:20:23 +04:00
2012-07-25 19:37:18 +04:00
if ( vshCommandOptString ( cmd , " file " , & from ) < = 0 )
2011-04-19 02:37:42 +04:00
return false ;
2010-09-30 01:20:23 +04:00
2012-07-25 19:37:18 +04:00
if ( virFileReadAll ( from , VIRSH_MAX_XML_FILE , & buffer ) < 0 )
return false ;
2010-09-30 01:20:23 +04:00
2012-07-25 19:37:18 +04:00
nwfilter = virNWFilterDefineXML ( ctl - > conn , buffer ) ;
VIR_FREE ( buffer ) ;
2010-09-30 01:20:23 +04:00
2012-07-25 19:37:18 +04:00
if ( nwfilter ! = NULL ) {
vshPrint ( ctl , _ ( " Network filter %s defined from %s \n " ) ,
virNWFilterGetName ( nwfilter ) , from ) ;
virNWFilterFree ( nwfilter ) ;
} else {
vshError ( ctl , _ ( " Failed to define network filter from %s " ) , from ) ;
ret = false ;
}
return ret ;
}
/*
* " nwfilter-undefine " command
*/
static const vshCmdInfo info_nwfilter_undefine [ ] = {
{ " help " , N_ ( " undefine a network filter " ) } ,
{ " desc " , N_ ( " Undefine a given network filter. " ) } ,
{ NULL , NULL }
} ;
static const vshCmdOptDef opts_nwfilter_undefine [ ] = {
{ " nwfilter " , VSH_OT_DATA , VSH_OFLAG_REQ , N_ ( " network filter name or uuid " ) } ,
2010-09-30 01:20:23 +04:00
{ NULL , 0 , 0 , NULL }
} ;
2011-04-19 02:37:42 +04:00
static bool
2012-07-25 19:37:18 +04:00
cmdNWFilterUndefine ( vshControl * ctl , const vshCmd * cmd )
2010-09-30 01:20:23 +04:00
{
2012-07-25 19:37:18 +04:00
virNWFilterPtr nwfilter ;
2011-04-19 02:37:42 +04:00
bool ret = true ;
2012-07-25 19:37:18 +04:00
const char * name ;
2010-09-30 01:20:23 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
2011-04-19 02:37:42 +04:00
return false ;
2010-09-30 01:20:23 +04:00
2012-07-25 19:37:18 +04:00
if ( ! ( nwfilter = vshCommandOptNWFilter ( ctl , cmd , & name ) ) )
2011-04-19 02:37:42 +04:00
return false ;
2010-09-30 01:20:23 +04:00
2012-07-25 19:37:18 +04:00
if ( virNWFilterUndefine ( nwfilter ) = = 0 ) {
vshPrint ( ctl , _ ( " Network filter %s undefined \n " ) , name ) ;
} else {
vshError ( ctl , _ ( " Failed to undefine network filter %s " ) , name ) ;
ret = false ;
2010-09-30 01:20:23 +04:00
}
2012-07-25 19:37:18 +04:00
virNWFilterFree ( nwfilter ) ;
2010-09-30 01:20:23 +04:00
return ret ;
}
2012-07-25 19:37:18 +04:00
2006-08-07 18:35:20 +04:00
/*
2012-07-25 19:37:18 +04:00
* " nwfilter-dumpxml " command
2006-08-07 18:35:20 +04:00
*/
2012-07-25 19:37:18 +04:00
static const vshCmdInfo info_nwfilter_dumpxml [ ] = {
{ " help " , N_ ( " network filter information in XML " ) } ,
{ " desc " , N_ ( " Output the network filter information as an XML dump to stdout. " ) } ,
2006-08-07 18:35:20 +04:00
{ NULL , NULL }
} ;
2012-07-24 12:49:27 +04:00
static const vshCmdOptDef opts_nwfilter_dumpxml [ ] = {
{ " nwfilter " , VSH_OT_DATA , VSH_OFLAG_REQ , N_ ( " network filter name or uuid " ) } ,
2008-02-20 18:27:08 +03:00
{ NULL , 0 , 0 , NULL }
} ;
2011-04-19 02:37:42 +04:00
static bool
2012-07-24 12:49:27 +04:00
cmdNWFilterDumpXML ( vshControl * ctl , const vshCmd * cmd )
2008-02-20 18:27:08 +03:00
{
2012-07-24 12:49:27 +04:00
virNWFilterPtr nwfilter ;
bool ret = true ;
char * dump ;
2008-02-20 18:27:08 +03:00
2010-06-17 18:47:06 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
2011-04-19 02:37:42 +04:00
return false ;
2008-02-20 18:27:08 +03:00
2012-07-24 12:49:27 +04:00
if ( ! ( nwfilter = vshCommandOptNWFilter ( ctl , cmd , NULL ) ) )
2012-07-24 12:44:49 +04:00
return false ;
2008-02-20 18:27:08 +03:00
2012-07-24 12:49:27 +04:00
dump = virNWFilterGetXMLDesc ( nwfilter , 0 ) ;
if ( dump ! = NULL ) {
vshPrint ( ctl , " %s " , dump ) ;
VIR_FREE ( dump ) ;
} else {
ret = false ;
2012-06-25 01:36:00 +04:00
}
2008-02-20 18:27:08 +03:00
2012-07-24 12:49:27 +04:00
virNWFilterFree ( nwfilter ) ;
return ret ;
2012-07-24 12:44:49 +04:00
}
2008-02-20 18:27:08 +03:00
2012-07-24 12:44:49 +04:00
/*
2012-07-24 12:49:27 +04:00
* " nwfilter-list " command
2012-07-24 12:44:49 +04:00
*/
2012-07-24 12:49:27 +04:00
static const vshCmdInfo info_nwfilter_list [ ] = {
{ " help " , N_ ( " list network filters " ) } ,
{ " desc " , N_ ( " Returns list of network filters. " ) } ,
2012-07-24 12:44:49 +04:00
{ NULL , NULL }
} ;
2008-02-20 18:27:08 +03:00
2012-07-24 12:49:27 +04:00
static const vshCmdOptDef opts_nwfilter_list [ ] = {
2012-07-24 12:44:49 +04:00
{ NULL , 0 , 0 , NULL }
} ;
2012-06-25 01:36:00 +04:00
2012-07-24 12:44:49 +04:00
static bool
2012-07-24 12:49:27 +04:00
cmdNWFilterList ( vshControl * ctl , const vshCmd * cmd ATTRIBUTE_UNUSED )
2012-07-24 12:44:49 +04:00
{
2012-07-24 12:49:27 +04:00
int numfilters , i ;
char * * names ;
2012-07-24 12:44:49 +04:00
char uuid [ VIR_UUID_STRING_BUFLEN ] ;
2008-02-20 18:27:08 +03:00
2012-07-24 12:44:49 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
return false ;
2008-02-20 18:27:08 +03:00
2012-07-24 12:49:27 +04:00
numfilters = virConnectNumOfNWFilters ( ctl - > conn ) ;
if ( numfilters < 0 ) {
vshError ( ctl , " %s " , _ ( " Failed to list network filters " ) ) ;
2012-07-24 12:44:49 +04:00
return false ;
2012-07-24 12:49:27 +04:00
}
2008-02-20 18:27:08 +03:00
2012-07-24 12:49:27 +04:00
names = vshMalloc ( ctl , sizeof ( char * ) * numfilters ) ;
2008-02-20 18:27:08 +03:00
2012-07-24 12:49:27 +04:00
if ( ( numfilters = virConnectListNWFilters ( ctl - > conn , names ,
numfilters ) ) < 0 ) {
vshError ( ctl , " %s " , _ ( " Failed to list network filters " ) ) ;
VIR_FREE ( names ) ;
return false ;
}
2008-02-20 18:27:08 +03:00
2012-07-24 12:49:27 +04:00
qsort ( & names [ 0 ] , numfilters , sizeof ( char * ) , vshNameSorter ) ;
2008-02-20 18:27:08 +03:00
2012-07-24 12:49:27 +04:00
vshPrintExtra ( ctl , " %-36s %-20s \n " , _ ( " UUID " ) , _ ( " Name " ) ) ;
vshPrintExtra ( ctl ,
" ---------------------------------------------------------------- \n " ) ;
2008-02-20 18:27:08 +03:00
2012-07-24 12:49:27 +04:00
for ( i = 0 ; i < numfilters ; i + + ) {
virNWFilterPtr nwfilter =
virNWFilterLookupByName ( ctl - > conn , names [ i ] ) ;
2012-07-25 19:37:18 +04:00
2012-07-24 12:49:27 +04:00
/* this kind of work with networks is not atomic operation */
if ( ! nwfilter ) {
VIR_FREE ( names [ i ] ) ;
continue ;
2012-07-24 12:44:49 +04:00
}
2012-07-24 12:49:27 +04:00
virNWFilterGetUUIDString ( nwfilter , uuid ) ;
vshPrint ( ctl , " %-36s %-20s \n " ,
uuid ,
virNWFilterGetName ( nwfilter ) ) ;
virNWFilterFree ( nwfilter ) ;
VIR_FREE ( names [ i ] ) ;
2008-02-20 18:27:08 +03:00
}
2012-07-24 12:49:27 +04:00
VIR_FREE ( names ) ;
return true ;
2008-02-20 18:27:08 +03:00
}
2012-07-25 19:37:18 +04:00
2012-07-10 14:45:30 +04:00
/*
2012-07-24 12:49:27 +04:00
* " nwfilter-edit " command
2012-07-10 14:45:30 +04:00
*/
2012-07-24 12:49:27 +04:00
static const vshCmdInfo info_nwfilter_edit [ ] = {
{ " help " , N_ ( " edit XML configuration for a network filter " ) } ,
{ " desc " , N_ ( " Edit the XML configuration for a network filter. " ) } ,
2012-07-10 14:45:30 +04:00
{ NULL , NULL }
} ;
2012-07-24 12:49:27 +04:00
static const vshCmdOptDef opts_nwfilter_edit [ ] = {
{ " nwfilter " , VSH_OT_DATA , VSH_OFLAG_REQ , N_ ( " network filter name or uuid " ) } ,
2012-07-10 14:45:30 +04:00
{ NULL , 0 , 0 , NULL }
} ;
static bool
2012-07-24 12:49:27 +04:00
cmdNWFilterEdit ( vshControl * ctl , const vshCmd * cmd )
2012-07-10 14:45:30 +04:00
{
2012-07-24 12:49:27 +04:00
bool ret = false ;
virNWFilterPtr nwfilter = NULL ;
virNWFilterPtr nwfilter_edited = NULL ;
2012-07-10 14:45:30 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
2012-07-24 12:49:27 +04:00
goto cleanup ;
2007-05-23 19:09:19 +04:00
2012-07-24 12:49:27 +04:00
nwfilter = vshCommandOptNWFilter ( ctl , cmd , NULL ) ;
if ( nwfilter = = NULL )
goto cleanup ;
2007-05-23 19:09:19 +04:00
2012-07-24 12:49:27 +04:00
# define EDIT_GET_XML virNWFilterGetXMLDesc(nwfilter, 0)
# define EDIT_NOT_CHANGED \
vshPrint ( ctl , _ ( " Network filter %s XML " \
" configuration not changed. \n " ) , \
virNWFilterGetName ( nwfilter ) ) ; \
ret = true ; goto edit_cleanup ;
# define EDIT_DEFINE \
( nwfilter_edited = virNWFilterDefineXML ( ctl - > conn , doc_edited ) )
# define EDIT_FREE \
if ( nwfilter_edited ) \
virNWFilterFree ( nwfilter ) ;
# include "virsh-edit.c"
2007-05-23 19:09:19 +04:00
2012-07-24 12:49:27 +04:00
vshPrint ( ctl , _ ( " Network filter %s XML configuration edited. \n " ) ,
virNWFilterGetName ( nwfilter_edited ) ) ;
2007-05-23 19:09:19 +04:00
2012-07-24 12:49:27 +04:00
ret = true ;
2007-05-23 19:09:19 +04:00
2012-07-24 12:49:27 +04:00
cleanup :
if ( nwfilter )
virNWFilterFree ( nwfilter ) ;
if ( nwfilter_edited )
virNWFilterFree ( nwfilter_edited ) ;
2007-05-23 19:09:19 +04:00
2012-07-24 12:44:49 +04:00
return ret ;
2007-05-23 19:09:19 +04:00
}
2012-07-25 19:37:18 +04:00
/*
2012-07-24 12:49:27 +04:00
* " nodedev-create " command
2012-07-25 19:37:18 +04:00
*/
2012-07-24 12:49:27 +04:00
static const vshCmdInfo info_node_device_create [ ] = {
{ " help " , N_ ( " create a device defined "
" by an XML file on the node " ) } ,
{ " desc " , N_ ( " Create a device on the node. Note that this "
" command creates devices on the physical host "
" that can then be assigned to a virtual machine. " ) } ,
2012-07-25 19:37:18 +04:00
{ NULL , NULL }
} ;
2011-06-06 14:20:11 +04:00
2012-07-24 12:49:27 +04:00
static const vshCmdOptDef opts_node_device_create [ ] = {
{ " file " , VSH_OT_DATA , VSH_OFLAG_REQ ,
N_ ( " file containing an XML description of the device " ) } ,
2012-07-25 19:37:18 +04:00
{ NULL , 0 , 0 , NULL }
} ;
2011-06-06 14:20:11 +04:00
2012-07-25 19:37:18 +04:00
static bool
2012-07-24 12:49:27 +04:00
cmdNodeDeviceCreate ( vshControl * ctl , const vshCmd * cmd )
2012-07-25 19:37:18 +04:00
{
2012-07-24 12:49:27 +04:00
virNodeDevicePtr dev = NULL ;
const char * from = NULL ;
2012-07-24 12:44:49 +04:00
bool ret = true ;
2012-07-24 12:49:27 +04:00
char * buffer ;
2011-06-06 14:20:11 +04:00
2012-07-25 19:37:18 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
2011-06-06 14:20:11 +04:00
return false ;
2012-07-24 12:49:27 +04:00
if ( vshCommandOptString ( cmd , " file " , & from ) < = 0 )
return false ;
if ( virFileReadAll ( from , VIRSH_MAX_XML_FILE , & buffer ) < 0 )
2011-06-06 14:20:11 +04:00
return false ;
2012-07-24 12:49:27 +04:00
dev = virNodeDeviceCreateXML ( ctl - > conn , buffer , 0 ) ;
VIR_FREE ( buffer ) ;
if ( dev ! = NULL ) {
vshPrint ( ctl , _ ( " Node device %s created from %s \n " ) ,
virNodeDeviceGetName ( dev ) , from ) ;
virNodeDeviceFree ( dev ) ;
2012-07-24 12:44:49 +04:00
} else {
2012-07-24 12:49:27 +04:00
vshError ( ctl , _ ( " Failed to create node device from %s " ) , from ) ;
2012-07-24 12:44:49 +04:00
ret = false ;
}
2011-06-06 14:20:11 +04:00
2012-07-24 12:44:49 +04:00
return ret ;
}
2011-06-06 14:20:11 +04:00
2007-05-23 19:09:19 +04:00
/*
2012-07-24 12:49:27 +04:00
* " nodedev-destroy " command
2007-05-23 19:09:19 +04:00
*/
2012-07-24 12:49:27 +04:00
static const vshCmdInfo info_node_device_destroy [ ] = {
{ " help " , N_ ( " destroy (stop) a device on the node " ) } ,
{ " desc " , N_ ( " Destroy a device on the node. Note that this "
" command destroys devices on the physical host " ) } ,
2007-05-23 19:09:19 +04:00
{ NULL , NULL }
} ;
2012-07-24 12:49:27 +04:00
static const vshCmdOptDef opts_node_device_destroy [ ] = {
{ " name " , VSH_OT_DATA , VSH_OFLAG_REQ ,
N_ ( " name of the device to be destroyed " ) } ,
2007-05-23 19:09:19 +04:00
{ NULL , 0 , 0 , NULL }
} ;
2011-04-19 02:37:42 +04:00
static bool
2012-07-24 12:49:27 +04:00
cmdNodeDeviceDestroy ( vshControl * ctl , const vshCmd * cmd )
2007-05-23 19:09:19 +04:00
{
2012-07-24 12:49:27 +04:00
virNodeDevicePtr dev = NULL ;
bool ret = true ;
const char * name = NULL ;
2007-05-23 19:09:19 +04:00
2012-07-24 12:49:27 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) ) {
2011-04-19 02:37:42 +04:00
return false ;
2012-07-24 12:49:27 +04:00
}
2007-05-23 19:09:19 +04:00
2012-07-24 12:49:27 +04:00
if ( vshCommandOptString ( cmd , " name " , & name ) < = 0 )
2011-04-19 02:37:42 +04:00
return false ;
2011-06-06 14:20:11 +04:00
2012-07-24 12:49:27 +04:00
dev = virNodeDeviceLookupByName ( ctl - > conn , name ) ;
2007-05-23 19:09:19 +04:00
2012-07-24 12:49:27 +04:00
if ( virNodeDeviceDestroy ( dev ) = = 0 ) {
vshPrint ( ctl , _ ( " Destroyed node device '%s' \n " ) , name ) ;
} else {
vshError ( ctl , _ ( " Failed to destroy node device '%s' " ) , name ) ;
ret = false ;
}
virNodeDeviceFree ( dev ) ;
return ret ;
2007-05-23 19:09:19 +04:00
}
2010-03-22 21:45:09 +03:00
/*
2012-07-25 19:37:18 +04:00
* " secret-define " command
2010-03-22 21:45:09 +03:00
*/
2012-07-25 19:37:18 +04:00
static const vshCmdInfo info_secret_define [ ] = {
{ " help " , N_ ( " define or modify a secret from an XML file " ) } ,
{ " desc " , N_ ( " Define or modify a secret. " ) } ,
2010-03-22 21:45:09 +03:00
{ NULL , NULL }
} ;
2012-07-25 19:37:18 +04:00
static const vshCmdOptDef opts_secret_define [ ] = {
{ " file " , VSH_OT_DATA , VSH_OFLAG_REQ , N_ ( " file containing secret attributes in XML " ) } ,
2010-03-22 21:45:09 +03:00
{ NULL , 0 , 0 , NULL }
} ;
2011-04-19 02:37:42 +04:00
static bool
2012-07-25 19:37:18 +04:00
cmdSecretDefine ( vshControl * ctl , const vshCmd * cmd )
2010-03-22 21:45:09 +03:00
{
2011-03-08 19:29:31 +03:00
const char * from = NULL ;
2010-03-22 21:45:09 +03:00
char * buffer ;
2012-07-25 19:37:18 +04:00
virSecretPtr res ;
char uuid [ VIR_UUID_STRING_BUFLEN ] ;
2010-03-22 21:45:09 +03:00
2010-06-17 18:47:06 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
2011-04-19 02:37:42 +04:00
return false ;
2010-03-22 21:45:09 +03:00
2012-07-25 19:37:18 +04:00
if ( vshCommandOptString ( cmd , " file " , & from ) < = 0 )
2011-04-19 02:37:42 +04:00
return false ;
2010-03-22 21:45:09 +03:00
2012-07-25 19:37:18 +04:00
if ( virFileReadAll ( from , VIRSH_MAX_XML_FILE , & buffer ) < 0 )
2011-04-19 02:37:42 +04:00
return false ;
2010-12-22 19:01:53 +03:00
2012-07-25 19:37:18 +04:00
res = virSecretDefineXML ( ctl - > conn , buffer , 0 ) ;
2010-03-22 21:45:09 +03:00
VIR_FREE ( buffer ) ;
2012-07-25 19:37:18 +04:00
if ( res = = NULL ) {
vshError ( ctl , _ ( " Failed to set attributes from %s " ) , from ) ;
return false ;
}
if ( virSecretGetUUIDString ( res , & ( uuid [ 0 ] ) ) < 0 ) {
vshError ( ctl , " %s " , _ ( " Failed to get UUID of created secret " ) ) ;
virSecretFree ( res ) ;
2011-04-19 02:37:42 +04:00
return false ;
2010-03-22 21:45:09 +03:00
}
2012-07-25 19:37:18 +04:00
vshPrint ( ctl , _ ( " Secret %s created \n " ) , uuid ) ;
virSecretFree ( res ) ;
2011-04-19 02:37:42 +04:00
return true ;
2010-03-22 21:45:09 +03:00
}
2007-06-19 13:12:55 +04:00
/*
2012-07-25 19:37:18 +04:00
* " secret-dumpxml " command
2007-06-19 13:12:55 +04:00
*/
2012-07-25 19:37:18 +04:00
static const vshCmdInfo info_secret_dumpxml [ ] = {
{ " help " , N_ ( " secret attributes in XML " ) } ,
{ " desc " , N_ ( " Output attributes of a secret as an XML dump to stdout. " ) } ,
2007-06-19 13:12:55 +04:00
{ NULL , NULL }
} ;
2012-07-25 19:37:18 +04:00
static const vshCmdOptDef opts_secret_dumpxml [ ] = {
{ " secret " , VSH_OT_DATA , VSH_OFLAG_REQ , N_ ( " secret UUID " ) } ,
2007-06-19 13:12:55 +04:00
{ NULL , 0 , 0 , NULL }
} ;
2011-04-19 02:37:42 +04:00
static bool
2012-07-25 19:37:18 +04:00
cmdSecretDumpXML ( vshControl * ctl , const vshCmd * cmd )
2007-06-19 13:12:55 +04:00
{
2012-07-25 19:37:18 +04:00
virSecretPtr secret ;
bool ret = false ;
2010-09-10 15:38:40 +04:00
char * xml ;
2007-06-19 13:12:55 +04:00
2010-06-17 18:47:06 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
2012-07-25 19:37:18 +04:00
return false ;
2011-10-18 11:32:30 +04:00
2012-07-25 19:37:18 +04:00
secret = vshCommandOptSecret ( ctl , cmd , NULL ) ;
if ( secret = = NULL )
return false ;
2007-06-19 13:12:55 +04:00
2012-07-25 19:37:18 +04:00
xml = virSecretGetXMLDesc ( secret , 0 ) ;
if ( xml = = NULL )
fix virsh's regression
This patch does the following things:
1. The return value of cmdSchedInfoUpdate() can be -1, 0 and 1. So the
type of return value should be int not bool.(This function is not a
entry of a virsh command, but the name of this function likes cmdXXX)
2. The type of cmdSchedinfo()'s, cmdFreecell()'s, cmdPoolList()'s and
cmdVolList()'s return value is bool not int, so change the type of
variable ret_val, func_ret and functionReturn.
3. Add a variable functionReturn for cmdMigrate(), cmdAttachInterface(),
cmdDetachInterface(), cmdAttachDisk() and cmdDetachDisk() to save the
return value.
4. Change the type of variable ret in the function cmdAttachDevice(),
cmdDetachDevice(), cmdUpdateDevice(), cmdAttachInterface(),
cmdDetachInterface(), cmdAttachDisk() and cmdDetachDisk() to int, as
we use it to save the return value of virXXX() and the type of virXXX()'s
return value is int not bool.
5. Do some cleanup when virBuff.error is 1.
The bug 1-4 were introduced by commit b56fa5bb.
2011-04-26 07:03:04 +04:00
goto cleanup ;
2012-07-25 19:37:18 +04:00
vshPrint ( ctl , " %s " , xml ) ;
2010-09-10 15:38:40 +04:00
VIR_FREE ( xml ) ;
2012-07-25 19:37:18 +04:00
ret = true ;
2010-09-10 15:38:40 +04:00
2012-07-25 19:37:18 +04:00
cleanup :
virSecretFree ( secret ) ;
return ret ;
2007-06-19 13:12:55 +04:00
}
/*
2012-07-25 19:37:18 +04:00
* " secret-set-value " command
2007-06-19 13:12:55 +04:00
*/
2012-07-25 19:37:18 +04:00
static const vshCmdInfo info_secret_set_value [ ] = {
{ " help " , N_ ( " set a secret value " ) } ,
{ " desc " , N_ ( " Set a secret value. " ) } ,
2007-06-19 13:12:55 +04:00
{ NULL , NULL }
} ;
2012-07-25 19:37:18 +04:00
static const vshCmdOptDef opts_secret_set_value [ ] = {
{ " secret " , VSH_OT_DATA , VSH_OFLAG_REQ , N_ ( " secret UUID " ) } ,
{ " base64 " , VSH_OT_DATA , VSH_OFLAG_REQ , N_ ( " base64-encoded secret value " ) } ,
2007-06-19 13:12:55 +04:00
{ NULL , 0 , 0 , NULL }
} ;
2011-04-19 02:37:42 +04:00
static bool
2012-07-25 19:37:18 +04:00
cmdSecretSetValue ( vshControl * ctl , const vshCmd * cmd )
2007-06-19 13:12:55 +04:00
{
2012-07-25 19:37:18 +04:00
virSecretPtr secret ;
size_t value_size ;
const char * base64 = NULL ;
char * value ;
int res ;
bool ret = false ;
2007-06-19 13:12:55 +04:00
2010-06-17 18:47:06 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
2012-07-25 19:37:18 +04:00
return false ;
2007-06-19 13:12:55 +04:00
2012-07-25 19:37:18 +04:00
secret = vshCommandOptSecret ( ctl , cmd , NULL ) ;
if ( secret = = NULL )
return false ;
2007-06-19 13:12:55 +04:00
2012-07-25 19:37:18 +04:00
if ( vshCommandOptString ( cmd , " base64 " , & base64 ) < = 0 )
2007-06-19 13:12:55 +04:00
goto cleanup ;
2012-07-25 19:37:18 +04:00
if ( ! base64_decode_alloc ( base64 , strlen ( base64 ) , & value , & value_size ) ) {
vshError ( ctl , " %s " , _ ( " Invalid base64 data " ) ) ;
2011-01-25 20:31:00 +03:00
goto cleanup ;
}
2012-07-25 19:37:18 +04:00
if ( value = = NULL ) {
2009-09-29 15:42:42 +04:00
vshError ( ctl , " %s " , _ ( " Failed to allocate memory " ) ) ;
2012-07-25 19:37:18 +04:00
return false ;
2007-06-19 13:12:55 +04:00
}
2012-07-25 19:37:18 +04:00
res = virSecretSetValue ( secret , ( unsigned char * ) value , value_size , 0 ) ;
memset ( value , 0 , value_size ) ;
VIR_FREE ( value ) ;
2010-01-14 04:54:58 +03:00
2012-07-25 19:37:18 +04:00
if ( res ! = 0 ) {
vshError ( ctl , " %s " , _ ( " Failed to set secret value " ) ) ;
goto cleanup ;
2008-09-03 16:38:28 +04:00
}
2012-07-25 19:37:18 +04:00
vshPrint ( ctl , " %s " , _ ( " Secret value set \n " ) ) ;
ret = true ;
2007-06-19 13:12:55 +04:00
2012-07-25 19:37:18 +04:00
cleanup :
virSecretFree ( secret ) ;
return ret ;
2007-06-19 13:12:55 +04:00
}
/*
2012-07-25 19:37:18 +04:00
* " secret-get-value " command
2007-06-19 13:12:55 +04:00
*/
2012-07-25 19:37:18 +04:00
static const vshCmdInfo info_secret_get_value [ ] = {
{ " help " , N_ ( " Output a secret value " ) } ,
{ " desc " , N_ ( " Output a secret value to stdout. " ) } ,
2007-06-19 13:12:55 +04:00
{ NULL , NULL }
} ;
2012-07-25 19:37:18 +04:00
static const vshCmdOptDef opts_secret_get_value [ ] = {
{ " secret " , VSH_OT_DATA , VSH_OFLAG_REQ , N_ ( " secret UUID " ) } ,
2007-06-19 13:12:55 +04:00
{ NULL , 0 , 0 , NULL }
} ;
2012-07-25 19:37:18 +04:00
static bool
cmdSecretGetValue ( vshControl * ctl , const vshCmd * cmd )
2011-07-15 11:06:53 +04:00
{
2012-07-25 19:37:18 +04:00
virSecretPtr secret ;
char * base64 ;
unsigned char * value ;
size_t value_size ;
bool ret = false ;
2011-07-15 11:06:53 +04:00
2012-07-25 19:37:18 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
return false ;
2011-07-15 11:06:53 +04:00
2012-07-25 19:37:18 +04:00
secret = vshCommandOptSecret ( ctl , cmd , NULL ) ;
if ( secret = = NULL )
return false ;
2011-07-15 11:06:53 +04:00
2012-07-25 19:37:18 +04:00
value = virSecretGetValue ( secret , & value_size , 0 ) ;
if ( value = = NULL )
goto cleanup ;
2011-07-15 11:06:53 +04:00
2012-07-25 19:37:18 +04:00
base64_encode_alloc ( ( char * ) value , value_size , & base64 ) ;
memset ( value , 0 , value_size ) ;
VIR_FREE ( value ) ;
2011-07-15 11:06:53 +04:00
2012-07-25 19:37:18 +04:00
if ( base64 = = NULL ) {
vshError ( ctl , " %s " , _ ( " Failed to allocate memory " ) ) ;
goto cleanup ;
}
vshPrint ( ctl , " %s " , base64 ) ;
memset ( base64 , 0 , strlen ( base64 ) ) ;
VIR_FREE ( base64 ) ;
ret = true ;
2011-07-15 11:06:53 +04:00
2012-07-25 19:37:18 +04:00
cleanup :
virSecretFree ( secret ) ;
return ret ;
2011-07-15 11:06:53 +04:00
}
2012-07-25 19:37:18 +04:00
/*
* " secret-undefine " command
2011-07-15 11:06:53 +04:00
*/
2012-07-25 19:37:18 +04:00
static const vshCmdInfo info_secret_undefine [ ] = {
{ " help " , N_ ( " undefine a secret " ) } ,
{ " desc " , N_ ( " Undefine a secret. " ) } ,
{ NULL , NULL }
} ;
static const vshCmdOptDef opts_secret_undefine [ ] = {
{ " secret " , VSH_OT_DATA , VSH_OFLAG_REQ , N_ ( " secret UUID " ) } ,
{ NULL , 0 , 0 , NULL }
} ;
2011-07-15 11:06:53 +04:00
2012-07-25 19:37:18 +04:00
static bool
cmdSecretUndefine ( vshControl * ctl , const vshCmd * cmd )
2011-07-15 11:06:53 +04:00
{
2012-07-25 19:37:18 +04:00
virSecretPtr secret ;
bool ret = false ;
const char * uuid ;
2011-07-15 11:06:53 +04:00
2012-07-25 19:37:18 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
return false ;
2011-07-15 11:06:53 +04:00
2012-07-25 19:37:18 +04:00
secret = vshCommandOptSecret ( ctl , cmd , & uuid ) ;
if ( secret = = NULL )
return false ;
2011-07-15 11:06:53 +04:00
2012-07-25 19:37:18 +04:00
if ( virSecretUndefine ( secret ) < 0 ) {
vshError ( ctl , _ ( " Failed to delete secret %s " ) , uuid ) ;
goto cleanup ;
2011-07-15 11:06:53 +04:00
}
2012-07-25 19:37:18 +04:00
vshPrint ( ctl , _ ( " Secret %s deleted \n " ) , uuid ) ;
ret = true ;
2011-07-15 11:06:53 +04:00
2012-07-25 19:37:18 +04:00
cleanup :
virSecretFree ( secret ) ;
return ret ;
2011-07-15 11:06:53 +04:00
}
2012-07-25 19:37:18 +04:00
/*
* " secret-list " command
*/
static const vshCmdInfo info_secret_list [ ] = {
{ " help " , N_ ( " list secrets " ) } ,
{ " desc " , N_ ( " Returns a list of secrets " ) } ,
{ NULL , NULL }
} ;
2011-04-19 02:37:42 +04:00
static bool
2012-07-25 19:37:18 +04:00
cmdSecretList ( vshControl * ctl , const vshCmd * cmd ATTRIBUTE_UNUSED )
2007-06-19 13:12:55 +04:00
{
2012-07-25 19:37:18 +04:00
int maxuuids = 0 , i ;
char * * uuids = NULL ;
2007-06-19 13:12:55 +04:00
2010-06-17 18:47:06 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
2012-07-25 19:37:18 +04:00
return false ;
2007-06-19 13:12:55 +04:00
2012-07-25 19:37:18 +04:00
maxuuids = virConnectNumOfSecrets ( ctl - > conn ) ;
if ( maxuuids < 0 ) {
vshError ( ctl , " %s " , _ ( " Failed to list secrets " ) ) ;
return false ;
2011-03-08 19:29:31 +03:00
}
2012-07-25 19:37:18 +04:00
uuids = vshMalloc ( ctl , sizeof ( * uuids ) * maxuuids ) ;
2007-06-19 13:12:55 +04:00
2012-07-25 19:37:18 +04:00
maxuuids = virConnectListSecrets ( ctl - > conn , uuids , maxuuids ) ;
if ( maxuuids < 0 ) {
vshError ( ctl , " %s " , _ ( " Failed to list secrets " ) ) ;
VIR_FREE ( uuids ) ;
return false ;
2007-06-19 13:12:55 +04:00
}
2012-07-25 19:37:18 +04:00
qsort ( uuids , maxuuids , sizeof ( char * ) , vshNameSorter ) ;
2007-06-19 13:12:55 +04:00
2012-07-25 19:37:18 +04:00
vshPrintExtra ( ctl , " %-36s %s \n " , _ ( " UUID " ) , _ ( " Usage " ) ) ;
vshPrintExtra ( ctl , " ----------------------------------------------------------- \n " ) ;
2010-09-10 15:38:40 +04:00
2012-07-25 19:37:18 +04:00
for ( i = 0 ; i < maxuuids ; i + + ) {
virSecretPtr sec = virSecretLookupByUUIDString ( ctl - > conn , uuids [ i ] ) ;
const char * usageType = NULL ;
2010-12-02 04:19:30 +03:00
2012-07-25 19:37:18 +04:00
if ( ! sec ) {
VIR_FREE ( uuids [ i ] ) ;
continue ;
}
2010-12-02 04:19:30 +03:00
2012-07-25 19:37:18 +04:00
switch ( virSecretGetUsageType ( sec ) ) {
case VIR_SECRET_USAGE_TYPE_VOLUME :
usageType = _ ( " Volume " ) ;
break ;
}
if ( usageType ) {
vshPrint ( ctl , " %-36s %s %s \n " ,
uuids [ i ] , usageType ,
virSecretGetUsageID ( sec ) ) ;
} else {
vshPrint ( ctl , " %-36s %s \n " ,
uuids [ i ] , _ ( " Unused " ) ) ;
}
virSecretFree ( sec ) ;
VIR_FREE ( uuids [ i ] ) ;
2012-06-13 18:55:51 +04:00
}
2012-07-25 19:37:18 +04:00
VIR_FREE ( uuids ) ;
return true ;
}
2010-09-10 15:38:40 +04:00
2012-07-25 19:37:18 +04:00
/*
* " version " command
*/
static const vshCmdInfo info_version [ ] = {
{ " help " , N_ ( " show version " ) } ,
{ " desc " , N_ ( " Display the system version information. " ) } ,
{ NULL , NULL }
} ;
2011-07-15 11:06:53 +04:00
2012-07-25 19:37:18 +04:00
static const vshCmdOptDef opts_version [ ] = {
{ " daemon " , VSH_OT_BOOL , VSH_OFLAG_NONE , N_ ( " report daemon version too " ) } ,
{ NULL , 0 , 0 , NULL }
} ;
2011-07-15 11:06:53 +04:00
2012-07-25 19:37:18 +04:00
static bool
cmdVersion ( vshControl * ctl , const vshCmd * cmd ATTRIBUTE_UNUSED )
{
unsigned long hvVersion ;
const char * hvType ;
unsigned long libVersion ;
unsigned long includeVersion ;
unsigned long apiVersion ;
unsigned long daemonVersion ;
int ret ;
unsigned int major ;
unsigned int minor ;
unsigned int rel ;
2011-07-15 11:06:53 +04:00
2012-07-25 19:37:18 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
return false ;
hvType = virConnectGetType ( ctl - > conn ) ;
if ( hvType = = NULL ) {
vshError ( ctl , " %s " , _ ( " failed to get hypervisor type " ) ) ;
return false ;
2011-07-15 11:06:53 +04:00
}
2012-07-25 19:37:18 +04:00
includeVersion = LIBVIR_VERSION_NUMBER ;
major = includeVersion / 1000000 ;
includeVersion % = 1000000 ;
minor = includeVersion / 1000 ;
rel = includeVersion % 1000 ;
vshPrint ( ctl , _ ( " Compiled against library: libvir %d.%d.%d \n " ) ,
major , minor , rel ) ;
2007-06-19 13:12:55 +04:00
2012-07-25 19:37:18 +04:00
ret = virGetVersion ( & libVersion , hvType , & apiVersion ) ;
if ( ret < 0 ) {
vshError ( ctl , " %s " , _ ( " failed to get the library version " ) ) ;
2011-04-19 02:37:42 +04:00
return false ;
2007-06-19 13:12:55 +04:00
}
2012-07-25 19:37:18 +04:00
major = libVersion / 1000000 ;
libVersion % = 1000000 ;
minor = libVersion / 1000 ;
rel = libVersion % 1000 ;
vshPrint ( ctl , _ ( " Using library: libvir %d.%d.%d \n " ) ,
major , minor , rel ) ;
2007-06-19 13:12:55 +04:00
2012-07-25 19:37:18 +04:00
major = apiVersion / 1000000 ;
apiVersion % = 1000000 ;
minor = apiVersion / 1000 ;
rel = apiVersion % 1000 ;
vshPrint ( ctl , _ ( " Using API: %s %d.%d.%d \n " ) , hvType ,
major , minor , rel ) ;
2007-06-19 13:12:55 +04:00
2012-07-25 19:37:18 +04:00
ret = virConnectGetVersion ( ctl - > conn , & hvVersion ) ;
if ( ret < 0 ) {
vshError ( ctl , " %s " , _ ( " failed to get the hypervisor version " ) ) ;
return false ;
2010-01-14 04:54:58 +03:00
}
2012-07-25 19:37:18 +04:00
if ( hvVersion = = 0 ) {
vshPrint ( ctl ,
_ ( " Cannot extract running %s hypervisor version \n " ) , hvType ) ;
} else {
major = hvVersion / 1000000 ;
hvVersion % = 1000000 ;
minor = hvVersion / 1000 ;
rel = hvVersion % 1000 ;
2007-06-19 13:12:55 +04:00
2012-07-25 19:37:18 +04:00
vshPrint ( ctl , _ ( " Running hypervisor: %s %d.%d.%d \n " ) ,
hvType , major , minor , rel ) ;
}
2010-09-10 15:38:40 +04:00
2012-07-25 19:37:18 +04:00
if ( vshCommandOptBool ( cmd , " daemon " ) ) {
ret = virConnectGetLibVersion ( ctl - > conn , & daemonVersion ) ;
if ( ret < 0 ) {
vshError ( ctl , " %s " , _ ( " failed to get the daemon version " ) ) ;
} else {
major = daemonVersion / 1000000 ;
daemonVersion % = 1000000 ;
minor = daemonVersion / 1000 ;
rel = daemonVersion % 1000 ;
vshPrint ( ctl , _ ( " Running against daemon: %d.%d.%d \n " ) ,
major , minor , rel ) ;
}
2010-01-14 04:54:58 +03:00
}
2007-06-19 13:12:55 +04:00
2012-07-25 19:37:18 +04:00
return true ;
2007-06-19 13:12:55 +04:00
}
2012-07-25 19:37:18 +04:00
/* Tree listing helpers. */
/* Given an index, return either the name of that device (non-NULL) or
* of its parent ( NULL if a root ) . */
typedef const char * ( * vshTreeLookup ) ( int devid , bool parent , void * opaque ) ;
static int
vshTreePrintInternal ( vshControl * ctl ,
vshTreeLookup lookup ,
void * opaque ,
int num_devices ,
int devid ,
int lastdev ,
bool root ,
virBufferPtr indent )
2012-02-28 10:38:03 +04:00
{
2012-07-25 19:37:18 +04:00
int i ;
int nextlastdev = - 1 ;
int ret = - 1 ;
const char * dev = ( lookup ) ( devid , false , opaque ) ;
2012-02-28 10:38:03 +04:00
2012-07-25 19:37:18 +04:00
if ( virBufferError ( indent ) )
2012-02-28 10:38:03 +04:00
goto cleanup ;
2012-07-25 19:37:18 +04:00
/* Print this device, with indent if not at root */
vshPrint ( ctl , " %s%s%s \n " , virBufferCurrentContent ( indent ) ,
root ? " " : " +- " , dev ) ;
/* Update indent to show '|' or ' ' for child devices */
if ( ! root ) {
virBufferAddChar ( indent , devid = = lastdev ? ' ' : ' | ' ) ;
virBufferAddChar ( indent , ' ' ) ;
if ( virBufferError ( indent ) )
goto cleanup ;
2012-02-28 10:38:03 +04:00
}
2012-07-25 19:37:18 +04:00
/* Determine the index of the last child device */
for ( i = 0 ; i < num_devices ; i + + ) {
const char * parent = ( lookup ) ( i , true , opaque ) ;
2012-02-28 10:38:03 +04:00
2012-07-25 19:37:18 +04:00
if ( parent & & STREQ ( parent , dev ) )
nextlastdev = i ;
}
2012-02-28 10:38:03 +04:00
2012-07-25 19:37:18 +04:00
/* If there is a child device, then print another blank line */
if ( nextlastdev ! = - 1 )
vshPrint ( ctl , " %s | \n " , virBufferCurrentContent ( indent ) ) ;
2012-02-28 10:38:03 +04:00
2012-07-25 19:37:18 +04:00
/* Finally print all children */
virBufferAddLit ( indent , " " ) ;
for ( i = 0 ; i < num_devices ; i + + ) {
const char * parent = ( lookup ) ( i , true , opaque ) ;
2012-02-28 10:38:03 +04:00
2012-07-25 19:37:18 +04:00
if ( parent & & STREQ ( parent , dev ) & &
vshTreePrintInternal ( ctl , lookup , opaque ,
num_devices , i , nextlastdev ,
false , indent ) < 0 )
goto cleanup ;
2012-02-28 10:38:03 +04:00
}
2012-07-25 19:37:18 +04:00
virBufferTrim ( indent , " " , - 1 ) ;
2012-02-28 10:38:03 +04:00
2012-07-25 19:37:18 +04:00
/* If there was no child device, and we're the last in
* a list of devices , then print another blank line */
if ( nextlastdev = = - 1 & & devid = = lastdev )
vshPrint ( ctl , " %s \n " , virBufferCurrentContent ( indent ) ) ;
2012-02-28 10:38:03 +04:00
2012-07-25 19:37:18 +04:00
if ( ! root )
virBufferTrim ( indent , NULL , 2 ) ;
ret = 0 ;
2012-02-28 10:38:03 +04:00
cleanup :
return ret ;
}
2012-07-25 19:37:18 +04:00
static int
vshTreePrint ( vshControl * ctl , vshTreeLookup lookup , void * opaque ,
int num_devices , int devid )
2012-02-28 10:38:03 +04:00
{
2012-07-25 19:37:18 +04:00
int ret ;
virBuffer indent = VIR_BUFFER_INITIALIZER ;
2012-02-28 10:38:03 +04:00
2012-07-25 19:37:18 +04:00
ret = vshTreePrintInternal ( ctl , lookup , opaque , num_devices ,
devid , devid , true , & indent ) ;
if ( ret < 0 )
vshError ( ctl , " %s " , _ ( " Failed to complete tree listing " ) ) ;
virBufferFreeAndReset ( & indent ) ;
2012-02-28 10:38:03 +04:00
return ret ;
2012-07-25 19:37:18 +04:00
}
2012-02-28 10:38:03 +04:00
2012-07-25 19:37:18 +04:00
struct vshNodeList {
char * * names ;
char * * parents ;
} ;
static const char *
vshNodeListLookup ( int devid , bool parent , void * opaque )
{
struct vshNodeList * arrays = opaque ;
if ( parent )
return arrays - > parents [ devid ] ;
return arrays - > names [ devid ] ;
2012-02-28 10:38:03 +04:00
}
2007-06-19 13:12:55 +04:00
/*
2012-07-25 19:37:18 +04:00
* " nodedev-list " command
2007-06-19 13:12:55 +04:00
*/
2012-07-25 19:37:18 +04:00
static const vshCmdInfo info_node_list_devices [ ] = {
{ " help " , N_ ( " enumerate devices on this host " ) } ,
{ " desc " , " " } ,
2007-06-19 13:12:55 +04:00
{ NULL , NULL }
} ;
2012-07-25 19:37:18 +04:00
static const vshCmdOptDef opts_node_list_devices [ ] = {
{ " tree " , VSH_OT_BOOL , 0 , N_ ( " list devices in a tree " ) } ,
{ " cap " , VSH_OT_STRING , VSH_OFLAG_NONE , N_ ( " capability name " ) } ,
2007-06-19 13:12:55 +04:00
{ NULL , 0 , 0 , NULL }
} ;
2011-04-19 02:37:42 +04:00
static bool
2012-07-25 19:37:18 +04:00
cmdNodeListDevices ( vshControl * ctl , const vshCmd * cmd ATTRIBUTE_UNUSED )
2007-06-19 13:12:55 +04:00
{
2012-07-25 19:37:18 +04:00
const char * cap = NULL ;
char * * devices ;
int num_devices , i ;
bool tree = vshCommandOptBool ( cmd , " tree " ) ;
bool ret = true ;
2007-06-19 13:12:55 +04:00
2010-06-17 18:47:06 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
2012-07-25 19:37:18 +04:00
return false ;
2007-06-19 13:12:55 +04:00
2012-07-25 19:37:18 +04:00
if ( vshCommandOptString ( cmd , " cap " , & cap ) < = 0 )
cap = NULL ;
2007-06-19 13:12:55 +04:00
2012-07-25 19:37:18 +04:00
num_devices = virNodeNumOfDevices ( ctl - > conn , cap , 0 ) ;
if ( num_devices < 0 ) {
vshError ( ctl , " %s " , _ ( " Failed to count node devices " ) ) ;
return false ;
} else if ( num_devices = = 0 ) {
return true ;
}
2007-06-19 13:12:55 +04:00
2012-07-25 19:37:18 +04:00
devices = vshMalloc ( ctl , sizeof ( char * ) * num_devices ) ;
num_devices =
virNodeListDevices ( ctl - > conn , cap , devices , num_devices , 0 ) ;
if ( num_devices < 0 ) {
vshError ( ctl , " %s " , _ ( " Failed to list node devices " ) ) ;
VIR_FREE ( devices ) ;
return false ;
2010-01-14 04:54:58 +03:00
}
2012-07-25 19:37:18 +04:00
qsort ( & devices [ 0 ] , num_devices , sizeof ( char * ) , vshNameSorter ) ;
if ( tree ) {
char * * parents = vshMalloc ( ctl , sizeof ( char * ) * num_devices ) ;
struct vshNodeList arrays = { devices , parents } ;
2010-01-14 04:54:58 +03:00
2012-07-25 19:37:18 +04:00
for ( i = 0 ; i < num_devices ; i + + ) {
virNodeDevicePtr dev = virNodeDeviceLookupByName ( ctl - > conn , devices [ i ] ) ;
if ( dev & & STRNEQ ( devices [ i ] , " computer " ) ) {
const char * parent = virNodeDeviceGetParent ( dev ) ;
parents [ i ] = parent ? vshStrdup ( ctl , parent ) : NULL ;
} else {
parents [ i ] = NULL ;
}
virNodeDeviceFree ( dev ) ;
}
for ( i = 0 ; i < num_devices ; i + + ) {
if ( parents [ i ] = = NULL & &
vshTreePrint ( ctl , vshNodeListLookup , & arrays , num_devices ,
i ) < 0 )
ret = false ;
}
for ( i = 0 ; i < num_devices ; i + + ) {
VIR_FREE ( devices [ i ] ) ;
VIR_FREE ( parents [ i ] ) ;
}
VIR_FREE ( parents ) ;
2010-01-14 04:54:58 +03:00
} else {
2012-07-25 19:37:18 +04:00
for ( i = 0 ; i < num_devices ; i + + ) {
vshPrint ( ctl , " %s \n " , devices [ i ] ) ;
VIR_FREE ( devices [ i ] ) ;
}
2008-09-03 16:38:28 +04:00
}
2012-07-25 19:37:18 +04:00
VIR_FREE ( devices ) ;
return ret ;
2007-06-19 13:12:55 +04:00
}
2012-02-28 11:36:38 +04:00
/*
2012-07-25 19:37:18 +04:00
* " nodedev-dumpxml " command
2012-02-28 11:36:38 +04:00
*/
2012-07-25 19:37:18 +04:00
static const vshCmdInfo info_node_device_dumpxml [ ] = {
{ " help " , N_ ( " node device details in XML " ) } ,
{ " desc " , N_ ( " Output the node device details as an XML dump to stdout. " ) } ,
2012-02-28 11:36:38 +04:00
{ NULL , NULL }
} ;
2012-07-25 19:37:18 +04:00
static const vshCmdOptDef opts_node_device_dumpxml [ ] = {
{ " device " , VSH_OT_DATA , VSH_OFLAG_REQ , N_ ( " device key " ) } ,
2012-02-28 11:36:38 +04:00
{ NULL , 0 , 0 , NULL }
} ;
static bool
2012-07-25 19:37:18 +04:00
cmdNodeDeviceDumpXML ( vshControl * ctl , const vshCmd * cmd )
2012-02-28 11:36:38 +04:00
{
2012-07-25 19:37:18 +04:00
const char * name = NULL ;
virNodeDevicePtr device ;
char * xml ;
2012-02-28 11:36:38 +04:00
2012-07-25 19:37:18 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
return false ;
if ( vshCommandOptString ( cmd , " device " , & name ) < = 0 )
return false ;
if ( ! ( device = virNodeDeviceLookupByName ( ctl - > conn , name ) ) ) {
vshError ( ctl , " %s '%s' " , _ ( " Could not find matching device " ) , name ) ;
return false ;
2012-02-28 11:36:38 +04:00
}
2012-07-25 19:37:18 +04:00
xml = virNodeDeviceGetXMLDesc ( device , 0 ) ;
if ( ! xml ) {
virNodeDeviceFree ( device ) ;
return false ;
2012-02-28 11:36:38 +04:00
}
2012-07-25 19:37:18 +04:00
vshPrint ( ctl , " %s \n " , xml ) ;
VIR_FREE ( xml ) ;
virNodeDeviceFree ( device ) ;
return true ;
}
2012-02-28 11:36:38 +04:00
2012-07-25 19:37:18 +04:00
/*
* " nodedev-detach " command
*/
static const vshCmdInfo info_node_device_detach [ ] = {
{ " help " , N_ ( " detach node device from its device driver " ) } ,
{ " desc " , N_ ( " Detach node device from its device driver before assigning to a domain. " ) } ,
{ NULL , NULL }
} ;
2012-02-28 11:36:38 +04:00
2012-07-25 19:37:18 +04:00
static const vshCmdOptDef opts_node_device_detach [ ] = {
{ " device " , VSH_OT_DATA , VSH_OFLAG_REQ , N_ ( " device key " ) } ,
{ NULL , 0 , 0 , NULL }
} ;
2012-02-28 11:36:38 +04:00
2012-07-25 19:37:18 +04:00
static bool
cmdNodeDeviceDetach ( vshControl * ctl , const vshCmd * cmd )
{
const char * name = NULL ;
virNodeDevicePtr device ;
bool ret = true ;
2012-02-28 11:36:38 +04:00
2012-07-25 19:37:18 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
return false ;
if ( vshCommandOptString ( cmd , " device " , & name ) < = 0 )
return false ;
if ( ! ( device = virNodeDeviceLookupByName ( ctl - > conn , name ) ) ) {
vshError ( ctl , " %s '%s' " , _ ( " Could not find matching device " ) , name ) ;
return false ;
2012-02-28 11:36:38 +04:00
}
2012-07-25 19:37:18 +04:00
/* Yes, our public API is misspelled. At least virsh can accept
* either spelling . */
if ( virNodeDeviceDettach ( device ) = = 0 ) {
vshPrint ( ctl , _ ( " Device %s detached \n " ) , name ) ;
} else {
vshError ( ctl , _ ( " Failed to detach device %s " ) , name ) ;
ret = false ;
}
virNodeDeviceFree ( device ) ;
2012-02-28 11:36:38 +04:00
return ret ;
}
2009-12-18 18:28:15 +03:00
/*
2012-07-25 19:37:18 +04:00
* " nodedev-reattach " command
2009-12-18 18:28:15 +03:00
*/
2012-07-25 19:37:18 +04:00
static const vshCmdInfo info_node_device_reattach [ ] = {
{ " help " , N_ ( " reattach node device to its device driver " ) } ,
{ " desc " , N_ ( " Reattach node device to its device driver once released by the domain. " ) } ,
2009-12-18 18:28:15 +03:00
{ NULL , NULL }
} ;
2012-07-25 19:37:18 +04:00
static const vshCmdOptDef opts_node_device_reattach [ ] = {
{ " device " , VSH_OT_DATA , VSH_OFLAG_REQ , N_ ( " device key " ) } ,
2009-12-18 18:28:15 +03:00
{ NULL , 0 , 0 , NULL }
} ;
2011-04-19 02:37:42 +04:00
static bool
2012-07-25 19:37:18 +04:00
cmdNodeDeviceReAttach ( vshControl * ctl , const vshCmd * cmd )
2009-12-18 18:28:15 +03:00
{
2012-07-25 19:37:18 +04:00
const char * name = NULL ;
virNodeDevicePtr device ;
bool ret = true ;
2009-12-18 18:28:15 +03:00
2010-06-17 18:47:06 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
2011-04-19 02:37:42 +04:00
return false ;
2012-07-25 19:37:18 +04:00
if ( vshCommandOptString ( cmd , " device " , & name ) < = 0 )
2011-04-19 02:37:42 +04:00
return false ;
2012-07-25 19:37:18 +04:00
if ( ! ( device = virNodeDeviceLookupByName ( ctl - > conn , name ) ) ) {
vshError ( ctl , " %s '%s' " , _ ( " Could not find matching device " ) , name ) ;
2011-04-19 02:37:42 +04:00
return false ;
2011-09-15 11:18:04 +04:00
}
2009-12-18 18:28:15 +03:00
2012-07-25 19:37:18 +04:00
if ( virNodeDeviceReAttach ( device ) = = 0 ) {
vshPrint ( ctl , _ ( " Device %s re-attached \n " ) , name ) ;
2011-09-15 11:18:04 +04:00
} else {
2012-07-25 19:37:18 +04:00
vshError ( ctl , _ ( " Failed to re-attach device %s " ) , name ) ;
ret = false ;
2011-09-15 11:18:04 +04:00
}
2012-07-25 19:37:18 +04:00
virNodeDeviceFree ( device ) ;
return ret ;
}
2011-09-15 11:18:04 +04:00
2012-07-25 19:37:18 +04:00
/*
* " nodedev-reset " command
*/
static const vshCmdInfo info_node_device_reset [ ] = {
{ " help " , N_ ( " reset node device " ) } ,
{ " desc " , N_ ( " Reset node device before or after assigning to a domain. " ) } ,
{ NULL , NULL }
} ;
2009-12-18 18:28:15 +03:00
2012-07-25 19:37:18 +04:00
static const vshCmdOptDef opts_node_device_reset [ ] = {
{ " device " , VSH_OT_DATA , VSH_OFLAG_REQ , N_ ( " device key " ) } ,
{ NULL , 0 , 0 , NULL }
} ;
2009-12-18 18:28:15 +03:00
2012-07-25 19:37:18 +04:00
static bool
cmdNodeDeviceReset ( vshControl * ctl , const vshCmd * cmd )
{
const char * name = NULL ;
virNodeDevicePtr device ;
bool ret = true ;
2009-12-18 18:28:15 +03:00
2012-07-25 19:37:18 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
return false ;
if ( vshCommandOptString ( cmd , " device " , & name ) < = 0 )
return false ;
if ( ! ( device = virNodeDeviceLookupByName ( ctl - > conn , name ) ) ) {
vshError ( ctl , " %s '%s' " , _ ( " Could not find matching device " ) , name ) ;
return false ;
2009-12-18 18:28:15 +03:00
}
2012-07-25 19:37:18 +04:00
if ( virNodeDeviceReset ( device ) = = 0 ) {
vshPrint ( ctl , _ ( " Device %s reset \n " ) , name ) ;
} else {
vshError ( ctl , _ ( " Failed to reset device %s " ) , name ) ;
ret = false ;
}
virNodeDeviceFree ( device ) ;
2009-12-18 18:28:15 +03:00
return ret ;
}
2010-02-17 16:52:07 +03:00
/*
2012-07-25 19:37:18 +04:00
* " hostname " command
2010-02-17 16:52:07 +03:00
*/
2012-07-25 19:37:18 +04:00
static const vshCmdInfo info_hostname [ ] = {
{ " help " , N_ ( " print the hypervisor hostname " ) } ,
{ " desc " , " " } ,
2010-02-17 16:52:07 +03:00
{ NULL , NULL }
} ;
2011-04-19 02:37:42 +04:00
static bool
2012-07-25 19:37:18 +04:00
cmdHostname ( vshControl * ctl , const vshCmd * cmd ATTRIBUTE_UNUSED )
2010-02-17 16:52:07 +03:00
{
2012-07-25 19:37:18 +04:00
char * hostname ;
2010-02-17 16:52:07 +03:00
2010-06-17 18:47:06 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
2011-04-19 02:37:42 +04:00
return false ;
2010-02-17 16:52:07 +03:00
2012-07-25 19:37:18 +04:00
hostname = virConnectGetHostname ( ctl - > conn ) ;
if ( hostname = = NULL ) {
vshError ( ctl , " %s " , _ ( " failed to get hostname " ) ) ;
2011-04-19 02:37:42 +04:00
return false ;
2012-07-25 19:37:18 +04:00
}
2010-02-17 16:52:07 +03:00
2012-07-25 19:37:18 +04:00
vshPrint ( ctl , " %s \n " , hostname ) ;
VIR_FREE ( hostname ) ;
2010-02-17 16:52:07 +03:00
2012-07-25 19:37:18 +04:00
return true ;
}
2011-09-15 15:51:01 +04:00
2012-07-25 19:37:18 +04:00
/*
* " uri " command
*/
static const vshCmdInfo info_uri [ ] = {
{ " help " , N_ ( " print the hypervisor canonical URI " ) } ,
{ " desc " , " " } ,
{ NULL , NULL }
} ;
2011-09-15 15:51:01 +04:00
2012-07-25 19:37:18 +04:00
static bool
cmdURI ( vshControl * ctl , const vshCmd * cmd ATTRIBUTE_UNUSED )
{
char * uri ;
2011-09-15 15:51:01 +04:00
2012-07-25 19:37:18 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
return false ;
2011-09-15 15:51:01 +04:00
2012-07-25 19:37:18 +04:00
uri = virConnectGetURI ( ctl - > conn ) ;
if ( uri = = NULL ) {
vshError ( ctl , " %s " , _ ( " failed to get URI " ) ) ;
return false ;
2010-02-17 16:52:07 +03:00
}
2012-07-25 19:37:18 +04:00
vshPrint ( ctl , " %s \n " , uri ) ;
VIR_FREE ( uri ) ;
2010-02-17 16:52:07 +03:00
2012-07-25 19:37:18 +04:00
return true ;
}
2010-02-17 16:52:07 +03:00
2012-07-25 19:37:18 +04:00
/*
* " sysinfo " command
*/
static const vshCmdInfo info_sysinfo [ ] = {
{ " help " , N_ ( " print the hypervisor sysinfo " ) } ,
{ " desc " ,
N_ ( " output an XML string for the hypervisor sysinfo, if available " ) } ,
{ NULL , NULL }
} ;
2010-02-17 16:52:07 +03:00
2012-07-25 19:37:18 +04:00
static bool
cmdSysinfo ( vshControl * ctl , const vshCmd * cmd ATTRIBUTE_UNUSED )
{
char * sysinfo ;
2010-02-17 16:52:07 +03:00
2012-07-25 19:37:18 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
return false ;
2010-02-17 16:52:07 +03:00
2012-07-25 19:37:18 +04:00
sysinfo = virConnectGetSysinfo ( ctl - > conn , 0 ) ;
if ( sysinfo = = NULL ) {
vshError ( ctl , " %s " , _ ( " failed to get sysinfo " ) ) ;
return false ;
2010-02-17 16:52:07 +03:00
}
2012-07-25 19:37:18 +04:00
vshPrint ( ctl , " %s " , sysinfo ) ;
VIR_FREE ( sysinfo ) ;
2010-02-17 16:52:07 +03:00
2012-07-25 19:37:18 +04:00
return true ;
2010-02-17 16:52:07 +03:00
}
2008-08-01 18:30:41 +04:00
/* Common code for the edit / net-edit / pool-edit functions which follow. */
static char *
2012-07-11 10:17:28 +04:00
editWriteToTempFile ( vshControl * ctl , const char * doc )
2008-08-01 18:30:41 +04:00
{
char * ret ;
const char * tmpdir ;
int fd ;
tmpdir = getenv ( " TMPDIR " ) ;
if ( ! tmpdir ) tmpdir = " /tmp " ;
2012-05-25 17:14:07 +04:00
if ( virAsprintf ( & ret , " %s/virshXXXXXX.xml " , tmpdir ) < 0 ) {
vshError ( ctl , " %s " , _ ( " out of memory " ) ) ;
return NULL ;
}
2010-11-09 12:27:09 +03:00
fd = mkstemps ( ret , 4 ) ;
2008-08-01 18:30:41 +04:00
if ( fd = = - 1 ) {
2010-11-09 12:27:09 +03:00
vshError ( ctl , _ ( " mkstemps: failed to create temporary file: %s " ) ,
2009-09-29 15:42:42 +04:00
strerror ( errno ) ) ;
2010-01-03 19:13:27 +03:00
VIR_FREE ( ret ) ;
2008-08-01 18:30:41 +04:00
return NULL ;
}
2012-07-11 10:17:28 +04:00
if ( safewrite ( fd , doc , strlen ( doc ) ) = = - 1 ) {
2009-09-29 15:42:42 +04:00
vshError ( ctl , _ ( " write: %s: failed to write to temporary file: %s " ) ,
ret , strerror ( errno ) ) ;
2010-11-17 18:19:13 +03:00
VIR_FORCE_CLOSE ( fd ) ;
2012-07-11 10:17:28 +04:00
unlink ( ret ) ;
2010-01-03 19:13:27 +03:00
VIR_FREE ( ret ) ;
2008-08-01 18:30:41 +04:00
return NULL ;
}
2010-11-17 18:19:13 +03:00
if ( VIR_CLOSE ( fd ) < 0 ) {
2009-09-29 15:42:42 +04:00
vshError ( ctl , _ ( " close: %s: failed to write or close temporary file: %s " ) ,
ret , strerror ( errno ) ) ;
2012-07-11 10:17:28 +04:00
unlink ( ret ) ;
2010-01-03 19:13:27 +03:00
VIR_FREE ( ret ) ;
2008-08-01 18:30:41 +04:00
return NULL ;
}
/* Temporary filename: caller frees. */
return ret ;
}
/* Characters permitted in $EDITOR environment variable and temp filename. */
# define ACCEPTED_CHARS \
" abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-/_.:@ "
static int
2012-07-11 10:17:28 +04:00
editFile ( vshControl * ctl , const char * filename )
2008-08-01 18:30:41 +04:00
{
const char * editor ;
2011-01-29 00:22:39 +03:00
virCommandPtr cmd ;
int ret = - 1 ;
int outfd = STDOUT_FILENO ;
int errfd = STDERR_FILENO ;
2008-08-01 18:30:41 +04:00
2012-07-11 10:17:28 +04:00
editor = getenv ( " VISUAL " ) ;
2011-01-29 00:22:39 +03:00
if ( ! editor )
2012-07-11 10:17:28 +04:00
editor = getenv ( " EDITOR " ) ;
2011-01-29 00:22:39 +03:00
if ( ! editor )
editor = " vi " ; /* could be cruel & default to ed(1) here */
2008-08-01 18:30:41 +04:00
2010-03-12 19:33:22 +03:00
/* Check that filename doesn't contain shell meta-characters, and
* if it does , refuse to run . Follow the Unix conventions for
* EDITOR : the user can intentionally specify command options , so
* we don ' t protect any shell metacharacters there . Lots more
* than virsh will misbehave if EDITOR has bogus contents ( which
2011-01-29 00:22:39 +03:00
* is why sudo scrubs it by default ) . Conversely , if the editor
* is safe , we can run it directly rather than wasting a shell .
2008-08-01 18:30:41 +04:00
*/
2012-07-11 10:17:28 +04:00
if ( strspn ( editor , ACCEPTED_CHARS ) ! = strlen ( editor ) ) {
if ( strspn ( filename , ACCEPTED_CHARS ) ! = strlen ( filename ) ) {
2011-01-29 00:22:39 +03:00
vshError ( ctl ,
_ ( " %s: temporary filename contains shell meta or other "
" unacceptable characters (is $TMPDIR wrong?) " ) ,
filename ) ;
return - 1 ;
}
cmd = virCommandNewArgList ( " sh " , " -c " , NULL ) ;
virCommandAddArgFormat ( cmd , " %s %s " , editor , filename ) ;
} else {
cmd = virCommandNewArgList ( editor , filename , NULL ) ;
2008-08-01 18:30:41 +04:00
}
2011-01-29 00:22:39 +03:00
virCommandSetInputFD ( cmd , STDIN_FILENO ) ;
virCommandSetOutputFD ( cmd , & outfd ) ;
virCommandSetErrorFD ( cmd , & errfd ) ;
if ( virCommandRunAsync ( cmd , NULL ) < 0 | |
virCommandWait ( cmd , NULL ) < 0 ) {
virshReportError ( ctl ) ;
goto cleanup ;
2008-08-01 18:30:41 +04:00
}
2011-01-29 00:22:39 +03:00
ret = 0 ;
2008-08-01 18:30:41 +04:00
2011-01-29 00:22:39 +03:00
cleanup :
virCommandFree ( cmd ) ;
return ret ;
2008-08-01 18:30:41 +04:00
}
static char *
2012-07-11 10:17:28 +04:00
editReadBackFile ( vshControl * ctl , const char * filename )
2008-08-01 18:30:41 +04:00
{
char * ret ;
2012-04-15 02:35:22 +04:00
if ( virFileReadAll ( filename , VIRSH_MAX_XML_FILE , & ret ) = = - 1 ) {
2009-09-29 15:42:42 +04:00
vshError ( ctl ,
2008-08-01 18:30:41 +04:00
_ ( " %s: failed to read temporary file: %s " ) ,
2009-09-29 15:42:42 +04:00
filename , strerror ( errno ) ) ;
2008-08-01 18:30:41 +04:00
return NULL ;
}
return ret ;
}
Fix misc Win32 compile warnings
GCC >= 4.4 assumes the 'printf' attribute refers to the native
runtime libraries format specifiers. Thanks to gnulib, libvirt
has GNU format specifiers everywhere. This means we need to
use 'gnu_printf' with GCC >= 4.4 to get correct compiler
checking of printf format specifiers.
* HACKING: Document new rules for ATTRIBUTE_FMT_PRINTF
* autobuild.sh, mingw32-libvirt.spec.in: Disable OpenNebula
driver on mingw32 builds
* qemud/dispatch.h, qemud/qemu.h, src/buf.h src/internal.h,
src/logging.h, src/security.h, src/sexpr.h, src/util.h,
src/virterror_internal.h, src/xend_internal.c: Change
over to ATTRIBUTE_FMT_PRINTF.
* src/virsh.c: Disable 'cd' and 'pwd' commands on Win32
since they don't compile
* src/threads-win32.c: Add missing return value check
2009-07-23 19:07:32 +04:00
2009-07-16 18:40:08 +04:00
/*
* " cd " command
*/
static const vshCmdInfo info_cd [ ] = {
2010-03-09 20:05:02 +03:00
{ " help " , N_ ( " change the current directory " ) } ,
{ " desc " , N_ ( " Change the current directory. " ) } ,
2009-07-16 18:40:08 +04:00
{ NULL , NULL }
} ;
static const vshCmdOptDef opts_cd [ ] = {
2010-03-09 20:05:02 +03:00
{ " dir " , VSH_OT_DATA , 0 , N_ ( " directory to switch to (default: home or else root) " ) } ,
2009-07-16 18:40:08 +04:00
{ NULL , 0 , 0 , NULL }
} ;
2011-04-19 02:37:42 +04:00
static bool
virsh: optimize creation of default connection
Ramon de Carvalho Valle reported a problem with:
virsh connect qemu:///system
as a non-root user. The real root problem appears to be a regression
in libvirtd being auto-started on the default qemu:///session URI;
however, the symptom points to an independent flaw in virsh - we
shouldn't be wasting efforts on making a connection if we aren't going
to be using that connection. Fixing virsh avoids Ramon's issue, while
I work in the meantime to fix the real libvirtd regression.
This patch looks big, but that's because 'gcc -Wmissing-field-initializers'
gets triggered by './autobuild.sh --enable-compile-warnings=error', so I
had to add 0 initialization to everyone (rather than my preference of
just adding the non-zero flags to virshCmds and to cmdConnect).
Meanwhile, if you use 'virsh -c URI', the connection must succeed; this
patch _only_ optimizes the default connection to be deferred to a later
point where we know if a particular command to be run needs a connection.
* tools/virsh.c (VSH_CMD_FLAG_NOCONNECT): New flag.
(vshCmdDef): Add new flags field.
(vshCommandRun): Honor new flag.
(domManagementCmds, domMonitoringCmds, storagePoolCmds)
(storageVolCmds, networkCmds, nodedevCmds, ifaceCmds)
(nwfilterCmds, secretCmds, virshCmds, snapshotCmds)
(hostAndHypervisorCmds): Populate new field.
(vshReconnect): Don't warn on initial connection.
2011-03-14 23:30:24 +03:00
cmdCd ( vshControl * ctl , const vshCmd * cmd )
2009-07-16 18:40:08 +04:00
{
2011-03-08 19:29:31 +03:00
const char * dir = NULL ;
2011-03-08 19:29:30 +03:00
char * dir_malloced = NULL ;
2011-04-19 02:37:42 +04:00
bool ret = true ;
2009-07-16 18:40:08 +04:00
if ( ! ctl - > imode ) {
2009-09-29 15:42:42 +04:00
vshError ( ctl , " %s " , _ ( " cd: command valid only in interactive mode " ) ) ;
2011-04-19 02:37:42 +04:00
return false ;
2009-07-16 18:40:08 +04:00
}
2011-03-08 19:29:31 +03:00
if ( vshCommandOptString ( cmd , " dir " , & dir ) < = 0 ) {
2012-05-24 16:29:42 +04:00
dir = dir_malloced = virGetUserDirectory ( ) ;
2009-07-16 18:40:08 +04:00
}
if ( ! dir )
dir = " / " ;
2011-03-04 19:52:12 +03:00
if ( chdir ( dir ) = = - 1 ) {
2009-09-29 15:42:42 +04:00
vshError ( ctl , _ ( " cd: %s: %s " ) , strerror ( errno ) , dir ) ;
2011-04-19 02:37:42 +04:00
ret = false ;
2009-07-16 18:40:08 +04:00
}
2011-03-08 19:29:30 +03:00
VIR_FREE ( dir_malloced ) ;
2011-03-04 19:52:12 +03:00
return ret ;
2009-07-16 18:40:08 +04:00
}
/*
* " pwd " command
*/
static const vshCmdInfo info_pwd [ ] = {
2010-03-09 20:05:02 +03:00
{ " help " , N_ ( " print the current directory " ) } ,
{ " desc " , N_ ( " Print the current directory. " ) } ,
2009-07-16 18:40:08 +04:00
{ NULL , NULL }
} ;
2011-04-19 02:37:42 +04:00
static bool
2009-07-16 18:40:08 +04:00
cmdPwd ( vshControl * ctl , const vshCmd * cmd ATTRIBUTE_UNUSED )
{
char * cwd ;
2011-04-29 21:14:23 +04:00
bool ret = true ;
2009-07-16 18:40:08 +04:00
2011-04-29 21:14:23 +04:00
cwd = getcwd ( NULL , 0 ) ;
if ( ! cwd ) {
2009-09-29 15:42:42 +04:00
vshError ( ctl , _ ( " pwd: cannot get current directory: %s " ) ,
strerror ( errno ) ) ;
2011-04-29 21:14:23 +04:00
ret = false ;
} else {
2012-07-11 10:17:28 +04:00
vshPrint ( ctl , _ ( " %s \n " ) , cwd ) ;
2011-04-29 21:14:23 +04:00
VIR_FREE ( cwd ) ;
}
2009-07-16 18:40:08 +04:00
2011-04-29 21:14:23 +04:00
return ret ;
2009-07-16 18:40:08 +04:00
}
2010-10-15 17:39:34 +04:00
/*
* " echo " command
*/
static const vshCmdInfo info_echo [ ] = {
{ " help " , N_ ( " echo arguments " ) } ,
{ " desc " , N_ ( " Echo back arguments, possibly with quoting. " ) } ,
{ NULL , NULL }
} ;
static const vshCmdOptDef opts_echo [ ] = {
{ " shell " , VSH_OT_BOOL , 0 , N_ ( " escape for shell use " ) } ,
{ " xml " , VSH_OT_BOOL , 0 , N_ ( " escape for XML use " ) } ,
2012-03-02 22:01:15 +04:00
{ " str " , VSH_OT_ALIAS , 0 , " string " } ,
2011-06-07 13:11:08 +04:00
{ " string " , VSH_OT_ARGV , 0 , N_ ( " arguments to echo " ) } ,
2010-10-15 17:39:34 +04:00
{ NULL , 0 , 0 , NULL }
} ;
/* Exists mainly for debugging virsh, but also handy for adding back
* quotes for later evaluation .
*/
2011-04-19 02:37:42 +04:00
static bool
2012-07-11 10:17:28 +04:00
cmdEcho ( vshControl * ctl , const vshCmd * cmd )
2010-10-15 17:39:34 +04:00
{
bool shell = false ;
bool xml = false ;
int count = 0 ;
2011-06-14 21:26:20 +04:00
const vshCmdOpt * opt = NULL ;
2010-10-15 17:39:34 +04:00
char * arg ;
virBuffer buf = VIR_BUFFER_INITIALIZER ;
if ( vshCommandOptBool ( cmd , " shell " ) )
shell = true ;
if ( vshCommandOptBool ( cmd , " xml " ) )
xml = true ;
2011-06-14 21:26:20 +04:00
while ( ( opt = vshCommandOptArgv ( cmd , opt ) ) ) {
2011-10-14 00:49:15 +04:00
char * str ;
virBuffer xmlbuf = VIR_BUFFER_INITIALIZER ;
2010-10-15 17:39:34 +04:00
2011-06-14 21:26:20 +04:00
arg = opt - > data ;
2011-10-14 00:49:15 +04:00
2010-10-15 17:39:34 +04:00
if ( count )
virBufferAddChar ( & buf , ' ' ) ;
2011-10-14 00:49:15 +04:00
2010-10-15 17:39:34 +04:00
if ( xml ) {
2011-10-14 00:49:15 +04:00
virBufferEscapeString ( & xmlbuf , " %s " , arg ) ;
if ( virBufferError ( & buf ) ) {
vshPrint ( ctl , " %s " , _ ( " Failed to allocate XML buffer " ) ) ;
return false ;
2010-10-15 17:39:34 +04:00
}
2011-10-14 00:49:15 +04:00
str = virBufferContentAndReset ( & xmlbuf ) ;
} else {
str = vshStrdup ( ctl , arg ) ;
2010-10-15 17:39:34 +04:00
}
2011-10-14 00:49:15 +04:00
if ( shell )
virBufferEscapeShell ( & buf , str ) ;
else
virBufferAdd ( & buf , str , - 1 ) ;
2010-10-15 17:39:34 +04:00
count + + ;
2011-10-14 00:49:15 +04:00
VIR_FREE ( str ) ;
2010-10-15 17:39:34 +04:00
}
if ( virBufferError ( & buf ) ) {
vshPrint ( ctl , " %s " , _ ( " Failed to allocate XML buffer " ) ) ;
2011-04-19 02:37:42 +04:00
return false ;
2010-10-15 17:39:34 +04:00
}
arg = virBufferContentAndReset ( & buf ) ;
if ( arg )
vshPrint ( ctl , " %s " , arg ) ;
VIR_FREE ( arg ) ;
2011-04-19 02:37:42 +04:00
return true ;
2010-10-15 17:39:34 +04:00
}
2008-08-01 18:30:41 +04:00
/*
* " net-edit " command
*/
static const vshCmdInfo info_network_edit [ ] = {
2010-03-09 20:05:02 +03:00
{ " help " , N_ ( " edit XML configuration for a network " ) } ,
{ " desc " , N_ ( " Edit the XML configuration for a network. " ) } ,
2008-08-01 18:30:41 +04:00
{ NULL , NULL }
} ;
static const vshCmdOptDef opts_network_edit [ ] = {
2010-11-08 17:32:04 +03:00
{ " network " , VSH_OT_DATA , VSH_OFLAG_REQ , N_ ( " network name or uuid " ) } ,
2008-08-01 18:30:41 +04:00
{ NULL , 0 , 0 , NULL }
} ;
2012-06-04 22:45:16 +04:00
static char * vshNetworkGetXMLDesc ( virNetworkPtr network )
{
unsigned int flags = VIR_NETWORK_XML_INACTIVE ;
char * doc = virNetworkGetXMLDesc ( network , flags ) ;
if ( ! doc & & last_error - > code = = VIR_ERR_INVALID_ARG ) {
/* The server side libvirt doesn't support
* VIR_NETWORK_XML_INACTIVE , so retry without it .
*/
virFreeError ( last_error ) ;
last_error = NULL ;
flags & = ~ VIR_NETWORK_XML_INACTIVE ;
doc = virNetworkGetXMLDesc ( network , flags ) ;
}
return doc ;
}
2012-05-17 19:08:53 +04:00
static bool
cmdNetworkEdit ( vshControl * ctl , const vshCmd * cmd )
{
bool ret = false ;
virNetworkPtr network = NULL ;
virNetworkPtr network_edited = NULL ;
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
goto cleanup ;
network = vshCommandOptNetwork ( ctl , cmd , NULL ) ;
if ( network = = NULL )
goto cleanup ;
2012-06-04 22:45:16 +04:00
# define EDIT_GET_XML vshNetworkGetXMLDesc(network)
2012-06-04 07:37:50 +04:00
# define EDIT_NOT_CHANGED \
vshPrint ( ctl , _ ( " Network %s XML configuration not changed. \n " ) , \
2012-07-11 10:17:28 +04:00
virNetworkGetName ( network ) ) ; \
2012-06-04 07:37:50 +04:00
ret = true ; goto edit_cleanup ;
# define EDIT_DEFINE \
( network_edited = virNetworkDefineXML ( ctl - > conn , doc_edited ) )
# define EDIT_FREE \
if ( network_edited ) \
virNetworkFree ( network_edited ) ;
# include "virsh-edit.c"
2012-05-17 19:08:53 +04:00
vshPrint ( ctl , _ ( " Network %s XML configuration edited. \n " ) ,
2012-06-14 16:18:31 +04:00
virNetworkGetName ( network_edited ) ) ;
2012-05-17 19:08:53 +04:00
ret = true ;
cleanup :
if ( network )
virNetworkFree ( network ) ;
if ( network_edited )
virNetworkFree ( network_edited ) ;
return ret ;
}
2008-08-01 18:30:41 +04:00
2005-12-08 13:23:34 +03:00
/*
* " quit " command
*/
2008-08-01 16:19:56 +04:00
static const vshCmdInfo info_quit [ ] = {
2010-03-09 20:05:02 +03:00
{ " help " , N_ ( " quit this interactive terminal " ) } ,
2009-01-05 16:27:43 +03:00
{ " desc " , " " } ,
2006-03-15 15:13:25 +03:00
{ NULL , NULL }
2005-12-08 13:23:34 +03:00
} ;
2011-04-19 02:37:42 +04:00
static bool
2008-08-01 17:51:18 +04:00
cmdQuit ( vshControl * ctl , const vshCmd * cmd ATTRIBUTE_UNUSED )
2006-03-15 15:13:25 +03:00
{
2011-04-19 02:37:42 +04:00
ctl - > imode = false ;
return true ;
2005-12-08 13:23:34 +03:00
}
2011-08-19 00:07:43 +04:00
/* Helper for snapshot-create and snapshot-create-as */
static bool
vshSnapshotCreate ( vshControl * ctl , virDomainPtr dom , const char * buffer ,
unsigned int flags , const char * from )
{
bool ret = false ;
virDomainSnapshotPtr snapshot ;
2011-08-18 18:37:26 +04:00
bool halt = false ;
2011-08-19 00:07:43 +04:00
char * doc = NULL ;
xmlDocPtr xml = NULL ;
xmlXPathContextPtr ctxt = NULL ;
2011-09-08 16:16:57 +04:00
const char * name = NULL ;
2011-08-19 00:07:43 +04:00
snapshot = virDomainSnapshotCreateXML ( dom , buffer , flags ) ;
2011-08-18 18:37:26 +04:00
/* Emulate --halt on older servers. */
if ( ! snapshot & & last_error - > code = = VIR_ERR_INVALID_ARG & &
( flags & VIR_DOMAIN_SNAPSHOT_CREATE_HALT ) ) {
int persistent ;
virFreeError ( last_error ) ;
last_error = NULL ;
persistent = virDomainIsPersistent ( dom ) ;
if ( persistent < 0 ) {
virshReportError ( ctl ) ;
goto cleanup ;
}
if ( ! persistent ) {
vshError ( ctl , " %s " ,
_ ( " cannot halt after snapshot of transient domain " ) ) ;
goto cleanup ;
}
if ( virDomainIsActive ( dom ) = = 1 )
halt = true ;
flags & = ~ VIR_DOMAIN_SNAPSHOT_CREATE_HALT ;
snapshot = virDomainSnapshotCreateXML ( dom , buffer , flags ) ;
}
2011-08-19 00:07:43 +04:00
if ( snapshot = = NULL )
goto cleanup ;
2011-08-18 18:37:26 +04:00
if ( halt & & virDomainDestroy ( dom ) < 0 ) {
virshReportError ( ctl ) ;
goto cleanup ;
}
2011-09-08 16:16:57 +04:00
name = virDomainSnapshotGetName ( snapshot ) ;
2011-08-19 00:07:43 +04:00
if ( ! name ) {
2011-09-08 16:16:57 +04:00
vshError ( ctl , " %s " , _ ( " Could not get snapshot name " ) ) ;
2011-08-19 00:07:43 +04:00
goto cleanup ;
}
if ( from )
vshPrint ( ctl , _ ( " Domain snapshot %s created from '%s' " ) , name , from ) ;
else
vshPrint ( ctl , _ ( " Domain snapshot %s created " ) , name ) ;
ret = true ;
cleanup :
xmlXPathFreeContext ( ctxt ) ;
xmlFreeDoc ( xml ) ;
if ( snapshot )
virDomainSnapshotFree ( snapshot ) ;
VIR_FREE ( doc ) ;
return ret ;
}
2010-04-01 00:28:00 +04:00
/*
* " snapshot-create " command
*/
static const vshCmdInfo info_snapshot_create [ ] = {
2011-06-16 00:24:53 +04:00
{ " help " , N_ ( " Create a snapshot from XML " ) } ,
{ " desc " , N_ ( " Create a snapshot (disk and RAM) from XML " ) } ,
2010-04-01 00:28:00 +04:00
{ NULL , NULL }
} ;
static const vshCmdOptDef opts_snapshot_create [ ] = {
{ " domain " , VSH_OT_DATA , VSH_OFLAG_REQ , N_ ( " domain name, id or uuid " ) } ,
{ " xmlfile " , VSH_OT_DATA , 0 , N_ ( " domain snapshot XML " ) } ,
snapshot: improve virsh snapshot-create, add snapshot-edit
Wire up the new snapshot creation flags in virsh. For convenience,
teach 'snapshot-current' how to make an existing snapshot become
current (can be used after upgrading to newer libvirt to recover
from the fact that the older libvirt lost track of the current
snapshot after a restart). The snapshot-create-as command is
intentionally not taught --redefine or --current, as this would
imply adding a lot of other options for everything else that can
appear in the <domainsnapshot> xml, but which is normally read-only.
Besides, redefining will usually be done on files created by
snapshot-dumpxml, rather than something built up by hand on the
command line. And now that we can redefine, we can edit.
* tools/virsh.c (cmdSnapshotCreate): Add --redefine, --current,
and --no-metadata.
(cmdSnapshotCreateAs): Add --no-metadata.
(cmdSnapshotCurrent): Add snapshotname to alter current snapshot.
(cmdSnapshotEdit): New command.
* tools/virsh.pod (snapshot-create, snapshot-create-as)
(snapshot-current, snapshot-edit): Document these.
2011-09-02 00:21:28 +04:00
{ " redefine " , VSH_OT_BOOL , 0 , N_ ( " redefine metadata for existing snapshot " ) } ,
{ " current " , VSH_OT_BOOL , 0 , N_ ( " with redefine, set current snapshot " ) } ,
{ " no-metadata " , VSH_OT_BOOL , 0 , N_ ( " take snapshot but create no metadata " ) } ,
2011-08-18 18:37:26 +04:00
{ " halt " , VSH_OT_BOOL , 0 , N_ ( " halt domain after snapshot is created " ) } ,
2011-08-23 03:12:56 +04:00
{ " disk-only " , VSH_OT_BOOL , 0 , N_ ( " capture disk state but not vm state " ) } ,
2012-01-09 22:57:46 +04:00
{ " reuse-external " , VSH_OT_BOOL , 0 , N_ ( " reuse any existing external files " ) } ,
2012-01-24 18:47:09 +04:00
{ " quiesce " , VSH_OT_BOOL , 0 , N_ ( " quiesce guest's file systems " ) } ,
snapshot: add atomic create flag
Right now, it is appallingly easy to cause qemu disk snapshots
to alter a domain then fail; for example, by requesting a two-disk
snapshot where the second disk name resides on read-only storage.
In this failure scenario, libvirt reports failure, but modifies
the live domain XML in-place to record that the first disk snapshot
was taken; and places a difficult burden on the management app
to grab the XML and reparse it to see which disks, if any, were
altered by the partial snapshot.
This patch adds a new flag where implementations can request that
the hypervisor make snapshots atomically; either no changes to
XML occur, or all disks were altered as a group. If you request
the flag, you either get outright failure up front, or you take
advantage of hypervisor abilities to make an atomic snapshot. Of
course, drivers should prefer the atomic means even without the
flag explicitly requested.
There's no way to make snapshots 100% bulletproof - even if the
hypervisor does it perfectly atomic, we could run out of memory
during the followup tasks of updating our in-memory XML, and report
a failure. However, these sorts of catastrophic failures are rare
and unlikely, and it is still nicer to know that either all
snapshots happened or none of them, as that is an easier state to
recover from.
* include/libvirt/libvirt.h.in
(VIR_DOMAIN_SNAPSHOT_CREATE_ATOMIC): New flag.
* src/libvirt.c (virDomainSnapshotCreateXML): Document it.
* tools/virsh.c (cmdSnapshotCreate, cmdSnapshotCreateAs): Expose it.
* tools/virsh.pod (snapshot-create, snapshot-create-as): Document
it.
2012-03-17 01:23:00 +04:00
{ " atomic " , VSH_OT_BOOL , 0 , N_ ( " require atomic operation " ) } ,
2010-04-01 00:28:00 +04:00
{ NULL , 0 , 0 , NULL }
} ;
2011-04-19 02:37:42 +04:00
static bool
2010-04-01 00:28:00 +04:00
cmdSnapshotCreate ( vshControl * ctl , const vshCmd * cmd )
{
virDomainPtr dom = NULL ;
2011-04-19 02:37:42 +04:00
bool ret = false ;
2011-03-08 19:29:31 +03:00
const char * from = NULL ;
2010-04-01 00:28:00 +04:00
char * buffer = NULL ;
snapshot: improve virsh snapshot-create, add snapshot-edit
Wire up the new snapshot creation flags in virsh. For convenience,
teach 'snapshot-current' how to make an existing snapshot become
current (can be used after upgrading to newer libvirt to recover
from the fact that the older libvirt lost track of the current
snapshot after a restart). The snapshot-create-as command is
intentionally not taught --redefine or --current, as this would
imply adding a lot of other options for everything else that can
appear in the <domainsnapshot> xml, but which is normally read-only.
Besides, redefining will usually be done on files created by
snapshot-dumpxml, rather than something built up by hand on the
command line. And now that we can redefine, we can edit.
* tools/virsh.c (cmdSnapshotCreate): Add --redefine, --current,
and --no-metadata.
(cmdSnapshotCreateAs): Add --no-metadata.
(cmdSnapshotCurrent): Add snapshotname to alter current snapshot.
(cmdSnapshotEdit): New command.
* tools/virsh.pod (snapshot-create, snapshot-create-as)
(snapshot-current, snapshot-edit): Document these.
2011-09-02 00:21:28 +04:00
unsigned int flags = 0 ;
if ( vshCommandOptBool ( cmd , " redefine " ) )
flags | = VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE ;
if ( vshCommandOptBool ( cmd , " current " ) )
flags | = VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT ;
if ( vshCommandOptBool ( cmd , " no-metadata " ) )
flags | = VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA ;
2011-08-18 18:37:26 +04:00
if ( vshCommandOptBool ( cmd , " halt " ) )
flags | = VIR_DOMAIN_SNAPSHOT_CREATE_HALT ;
2011-08-23 03:12:56 +04:00
if ( vshCommandOptBool ( cmd , " disk-only " ) )
flags | = VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY ;
2012-01-09 22:57:46 +04:00
if ( vshCommandOptBool ( cmd , " reuse-external " ) )
flags | = VIR_DOMAIN_SNAPSHOT_CREATE_REUSE_EXT ;
2012-01-24 18:47:09 +04:00
if ( vshCommandOptBool ( cmd , " quiesce " ) )
flags | = VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE ;
snapshot: add atomic create flag
Right now, it is appallingly easy to cause qemu disk snapshots
to alter a domain then fail; for example, by requesting a two-disk
snapshot where the second disk name resides on read-only storage.
In this failure scenario, libvirt reports failure, but modifies
the live domain XML in-place to record that the first disk snapshot
was taken; and places a difficult burden on the management app
to grab the XML and reparse it to see which disks, if any, were
altered by the partial snapshot.
This patch adds a new flag where implementations can request that
the hypervisor make snapshots atomically; either no changes to
XML occur, or all disks were altered as a group. If you request
the flag, you either get outright failure up front, or you take
advantage of hypervisor abilities to make an atomic snapshot. Of
course, drivers should prefer the atomic means even without the
flag explicitly requested.
There's no way to make snapshots 100% bulletproof - even if the
hypervisor does it perfectly atomic, we could run out of memory
during the followup tasks of updating our in-memory XML, and report
a failure. However, these sorts of catastrophic failures are rare
and unlikely, and it is still nicer to know that either all
snapshots happened or none of them, as that is an easier state to
recover from.
* include/libvirt/libvirt.h.in
(VIR_DOMAIN_SNAPSHOT_CREATE_ATOMIC): New flag.
* src/libvirt.c (virDomainSnapshotCreateXML): Document it.
* tools/virsh.c (cmdSnapshotCreate, cmdSnapshotCreateAs): Expose it.
* tools/virsh.pod (snapshot-create, snapshot-create-as): Document
it.
2012-03-17 01:23:00 +04:00
if ( vshCommandOptBool ( cmd , " atomic " ) )
flags | = VIR_DOMAIN_SNAPSHOT_CREATE_ATOMIC ;
2010-04-01 00:28:00 +04:00
2010-06-17 18:47:06 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
2010-04-01 00:28:00 +04:00
goto cleanup ;
dom = vshCommandOptDomain ( ctl , cmd , NULL ) ;
if ( dom = = NULL )
goto cleanup ;
2011-03-08 19:29:31 +03:00
if ( vshCommandOptString ( cmd , " xmlfile " , & from ) < = 0 )
2010-10-12 21:24:00 +04:00
buffer = vshStrdup ( ctl , " <domainsnapshot/> " ) ;
2010-04-01 00:28:00 +04:00
else {
if ( virFileReadAll ( from , VIRSH_MAX_XML_FILE , & buffer ) < 0 ) {
/* we have to report the error here because during cleanup
* we ' ll run through virDomainFree ( ) , which loses the
* last error
*/
virshReportError ( ctl ) ;
goto cleanup ;
}
}
if ( buffer = = NULL ) {
vshError ( ctl , " %s " , _ ( " Out of memory " ) ) ;
goto cleanup ;
}
snapshot: improve virsh snapshot-create, add snapshot-edit
Wire up the new snapshot creation flags in virsh. For convenience,
teach 'snapshot-current' how to make an existing snapshot become
current (can be used after upgrading to newer libvirt to recover
from the fact that the older libvirt lost track of the current
snapshot after a restart). The snapshot-create-as command is
intentionally not taught --redefine or --current, as this would
imply adding a lot of other options for everything else that can
appear in the <domainsnapshot> xml, but which is normally read-only.
Besides, redefining will usually be done on files created by
snapshot-dumpxml, rather than something built up by hand on the
command line. And now that we can redefine, we can edit.
* tools/virsh.c (cmdSnapshotCreate): Add --redefine, --current,
and --no-metadata.
(cmdSnapshotCreateAs): Add --no-metadata.
(cmdSnapshotCurrent): Add snapshotname to alter current snapshot.
(cmdSnapshotEdit): New command.
* tools/virsh.pod (snapshot-create, snapshot-create-as)
(snapshot-current, snapshot-edit): Document these.
2011-09-02 00:21:28 +04:00
ret = vshSnapshotCreate ( ctl , dom , buffer , flags , from ) ;
2010-04-01 00:28:00 +04:00
cleanup :
VIR_FREE ( buffer ) ;
if ( dom )
virDomainFree ( dom ) ;
return ret ;
}
2011-06-16 02:19:13 +04:00
/*
* " snapshot-create-as " command
*/
2011-08-23 03:12:56 +04:00
static int
vshParseSnapshotDiskspec ( vshControl * ctl , virBufferPtr buf , const char * str )
{
int ret = - 1 ;
char * name = NULL ;
char * snapshot = NULL ;
char * driver = NULL ;
char * file = NULL ;
char * spec = vshStrdup ( ctl , str ) ;
char * tmp = spec ;
size_t len = strlen ( str ) ;
if ( * str = = ' , ' )
goto cleanup ;
name = tmp ;
while ( ( tmp = strchr ( tmp , ' , ' ) ) ) {
if ( tmp [ 1 ] = = ' , ' ) {
/* Recognize ,, as an escape for a literal comma */
2012-05-07 23:22:09 +04:00
memmove ( & tmp [ 1 ] , & tmp [ 2 ] , len - ( tmp - spec ) - 2 + 1 ) ;
2011-08-23 03:12:56 +04:00
len - - ;
tmp + + ;
continue ;
}
/* Terminate previous string, look for next recognized one */
* tmp + + = ' \0 ' ;
if ( ! snapshot & & STRPREFIX ( tmp , " snapshot= " ) )
snapshot = tmp + strlen ( " snapshot= " ) ;
else if ( ! driver & & STRPREFIX ( tmp , " driver= " ) )
driver = tmp + strlen ( " driver= " ) ;
else if ( ! file & & STRPREFIX ( tmp , " file= " ) )
file = tmp + strlen ( " file= " ) ;
else
goto cleanup ;
}
virBufferEscapeString ( buf , " <disk name='%s' " , name ) ;
if ( snapshot )
virBufferAsprintf ( buf , " snapshot='%s' " , snapshot ) ;
if ( driver | | file ) {
virBufferAddLit ( buf , " > \n " ) ;
if ( driver )
virBufferAsprintf ( buf , " <driver type='%s'/> \n " , driver ) ;
if ( file )
virBufferEscapeString ( buf , " <source file='%s'/> \n " , file ) ;
virBufferAddLit ( buf , " </disk> \n " ) ;
} else {
virBufferAddLit ( buf , " /> \n " ) ;
}
ret = 0 ;
cleanup :
if ( ret < 0 )
vshError ( ctl , _ ( " unable to parse diskspec: %s " ) , str ) ;
VIR_FREE ( spec ) ;
return ret ;
}
2011-06-16 02:19:13 +04:00
static const vshCmdInfo info_snapshot_create_as [ ] = {
{ " help " , N_ ( " Create a snapshot from a set of args " ) } ,
{ " desc " , N_ ( " Create a snapshot (disk and RAM) from arguments " ) } ,
{ NULL , NULL }
} ;
static const vshCmdOptDef opts_snapshot_create_as [ ] = {
{ " domain " , VSH_OT_DATA , VSH_OFLAG_REQ , N_ ( " domain name, id or uuid " ) } ,
{ " name " , VSH_OT_DATA , 0 , N_ ( " name of snapshot " ) } ,
{ " description " , VSH_OT_DATA , 0 , N_ ( " description of snapshot " ) } ,
2011-06-16 02:24:40 +04:00
{ " print-xml " , VSH_OT_BOOL , 0 , N_ ( " print XML document rather than create " ) } ,
snapshot: improve virsh snapshot-create, add snapshot-edit
Wire up the new snapshot creation flags in virsh. For convenience,
teach 'snapshot-current' how to make an existing snapshot become
current (can be used after upgrading to newer libvirt to recover
from the fact that the older libvirt lost track of the current
snapshot after a restart). The snapshot-create-as command is
intentionally not taught --redefine or --current, as this would
imply adding a lot of other options for everything else that can
appear in the <domainsnapshot> xml, but which is normally read-only.
Besides, redefining will usually be done on files created by
snapshot-dumpxml, rather than something built up by hand on the
command line. And now that we can redefine, we can edit.
* tools/virsh.c (cmdSnapshotCreate): Add --redefine, --current,
and --no-metadata.
(cmdSnapshotCreateAs): Add --no-metadata.
(cmdSnapshotCurrent): Add snapshotname to alter current snapshot.
(cmdSnapshotEdit): New command.
* tools/virsh.pod (snapshot-create, snapshot-create-as)
(snapshot-current, snapshot-edit): Document these.
2011-09-02 00:21:28 +04:00
{ " no-metadata " , VSH_OT_BOOL , 0 , N_ ( " take snapshot but create no metadata " ) } ,
2011-08-18 18:37:26 +04:00
{ " halt " , VSH_OT_BOOL , 0 , N_ ( " halt domain after snapshot is created " ) } ,
2011-08-23 03:12:56 +04:00
{ " disk-only " , VSH_OT_BOOL , 0 , N_ ( " capture disk state but not vm state " ) } ,
2012-01-09 22:57:46 +04:00
{ " reuse-external " , VSH_OT_BOOL , 0 , N_ ( " reuse any existing external files " ) } ,
2012-01-24 18:47:09 +04:00
{ " quiesce " , VSH_OT_BOOL , 0 , N_ ( " quiesce guest's file systems " ) } ,
snapshot: add atomic create flag
Right now, it is appallingly easy to cause qemu disk snapshots
to alter a domain then fail; for example, by requesting a two-disk
snapshot where the second disk name resides on read-only storage.
In this failure scenario, libvirt reports failure, but modifies
the live domain XML in-place to record that the first disk snapshot
was taken; and places a difficult burden on the management app
to grab the XML and reparse it to see which disks, if any, were
altered by the partial snapshot.
This patch adds a new flag where implementations can request that
the hypervisor make snapshots atomically; either no changes to
XML occur, or all disks were altered as a group. If you request
the flag, you either get outright failure up front, or you take
advantage of hypervisor abilities to make an atomic snapshot. Of
course, drivers should prefer the atomic means even without the
flag explicitly requested.
There's no way to make snapshots 100% bulletproof - even if the
hypervisor does it perfectly atomic, we could run out of memory
during the followup tasks of updating our in-memory XML, and report
a failure. However, these sorts of catastrophic failures are rare
and unlikely, and it is still nicer to know that either all
snapshots happened or none of them, as that is an easier state to
recover from.
* include/libvirt/libvirt.h.in
(VIR_DOMAIN_SNAPSHOT_CREATE_ATOMIC): New flag.
* src/libvirt.c (virDomainSnapshotCreateXML): Document it.
* tools/virsh.c (cmdSnapshotCreate, cmdSnapshotCreateAs): Expose it.
* tools/virsh.pod (snapshot-create, snapshot-create-as): Document
it.
2012-03-17 01:23:00 +04:00
{ " atomic " , VSH_OT_BOOL , 0 , N_ ( " require atomic operation " ) } ,
2011-08-23 03:12:56 +04:00
{ " diskspec " , VSH_OT_ARGV , 0 ,
N_ ( " disk attributes: disk[,snapshot=type][,driver=type][,file=name] " ) } ,
2011-06-16 02:19:13 +04:00
{ NULL , 0 , 0 , NULL }
} ;
static bool
cmdSnapshotCreateAs ( vshControl * ctl , const vshCmd * cmd )
{
virDomainPtr dom = NULL ;
bool ret = false ;
char * buffer = NULL ;
const char * name = NULL ;
const char * desc = NULL ;
virBuffer buf = VIR_BUFFER_INITIALIZER ;
snapshot: improve virsh snapshot-create, add snapshot-edit
Wire up the new snapshot creation flags in virsh. For convenience,
teach 'snapshot-current' how to make an existing snapshot become
current (can be used after upgrading to newer libvirt to recover
from the fact that the older libvirt lost track of the current
snapshot after a restart). The snapshot-create-as command is
intentionally not taught --redefine or --current, as this would
imply adding a lot of other options for everything else that can
appear in the <domainsnapshot> xml, but which is normally read-only.
Besides, redefining will usually be done on files created by
snapshot-dumpxml, rather than something built up by hand on the
command line. And now that we can redefine, we can edit.
* tools/virsh.c (cmdSnapshotCreate): Add --redefine, --current,
and --no-metadata.
(cmdSnapshotCreateAs): Add --no-metadata.
(cmdSnapshotCurrent): Add snapshotname to alter current snapshot.
(cmdSnapshotEdit): New command.
* tools/virsh.pod (snapshot-create, snapshot-create-as)
(snapshot-current, snapshot-edit): Document these.
2011-09-02 00:21:28 +04:00
unsigned int flags = 0 ;
2011-08-23 03:12:56 +04:00
const vshCmdOpt * opt = NULL ;
snapshot: improve virsh snapshot-create, add snapshot-edit
Wire up the new snapshot creation flags in virsh. For convenience,
teach 'snapshot-current' how to make an existing snapshot become
current (can be used after upgrading to newer libvirt to recover
from the fact that the older libvirt lost track of the current
snapshot after a restart). The snapshot-create-as command is
intentionally not taught --redefine or --current, as this would
imply adding a lot of other options for everything else that can
appear in the <domainsnapshot> xml, but which is normally read-only.
Besides, redefining will usually be done on files created by
snapshot-dumpxml, rather than something built up by hand on the
command line. And now that we can redefine, we can edit.
* tools/virsh.c (cmdSnapshotCreate): Add --redefine, --current,
and --no-metadata.
(cmdSnapshotCreateAs): Add --no-metadata.
(cmdSnapshotCurrent): Add snapshotname to alter current snapshot.
(cmdSnapshotEdit): New command.
* tools/virsh.pod (snapshot-create, snapshot-create-as)
(snapshot-current, snapshot-edit): Document these.
2011-09-02 00:21:28 +04:00
if ( vshCommandOptBool ( cmd , " no-metadata " ) )
flags | = VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA ;
2011-08-18 18:37:26 +04:00
if ( vshCommandOptBool ( cmd , " halt " ) )
flags | = VIR_DOMAIN_SNAPSHOT_CREATE_HALT ;
2011-08-23 03:12:56 +04:00
if ( vshCommandOptBool ( cmd , " disk-only " ) )
flags | = VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY ;
2012-01-09 22:57:46 +04:00
if ( vshCommandOptBool ( cmd , " reuse-external " ) )
flags | = VIR_DOMAIN_SNAPSHOT_CREATE_REUSE_EXT ;
2012-01-24 18:47:09 +04:00
if ( vshCommandOptBool ( cmd , " quiesce " ) )
flags | = VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE ;
snapshot: add atomic create flag
Right now, it is appallingly easy to cause qemu disk snapshots
to alter a domain then fail; for example, by requesting a two-disk
snapshot where the second disk name resides on read-only storage.
In this failure scenario, libvirt reports failure, but modifies
the live domain XML in-place to record that the first disk snapshot
was taken; and places a difficult burden on the management app
to grab the XML and reparse it to see which disks, if any, were
altered by the partial snapshot.
This patch adds a new flag where implementations can request that
the hypervisor make snapshots atomically; either no changes to
XML occur, or all disks were altered as a group. If you request
the flag, you either get outright failure up front, or you take
advantage of hypervisor abilities to make an atomic snapshot. Of
course, drivers should prefer the atomic means even without the
flag explicitly requested.
There's no way to make snapshots 100% bulletproof - even if the
hypervisor does it perfectly atomic, we could run out of memory
during the followup tasks of updating our in-memory XML, and report
a failure. However, these sorts of catastrophic failures are rare
and unlikely, and it is still nicer to know that either all
snapshots happened or none of them, as that is an easier state to
recover from.
* include/libvirt/libvirt.h.in
(VIR_DOMAIN_SNAPSHOT_CREATE_ATOMIC): New flag.
* src/libvirt.c (virDomainSnapshotCreateXML): Document it.
* tools/virsh.c (cmdSnapshotCreate, cmdSnapshotCreateAs): Expose it.
* tools/virsh.pod (snapshot-create, snapshot-create-as): Document
it.
2012-03-17 01:23:00 +04:00
if ( vshCommandOptBool ( cmd , " atomic " ) )
flags | = VIR_DOMAIN_SNAPSHOT_CREATE_ATOMIC ;
2011-06-16 02:19:13 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
goto cleanup ;
dom = vshCommandOptDomain ( ctl , cmd , NULL ) ;
if ( dom = = NULL )
goto cleanup ;
if ( vshCommandOptString ( cmd , " name " , & name ) < 0 | |
vshCommandOptString ( cmd , " description " , & desc ) < 0 ) {
vshError ( ctl , _ ( " argument must not be empty " ) ) ;
goto cleanup ;
}
virBufferAddLit ( & buf , " <domainsnapshot> \n " ) ;
if ( name )
2011-08-11 03:00:26 +04:00
virBufferEscapeString ( & buf , " <name>%s</name> \n " , name ) ;
2011-06-16 02:19:13 +04:00
if ( desc )
2011-08-11 03:00:26 +04:00
virBufferEscapeString ( & buf , " <description>%s</description> \n " , desc ) ;
2011-08-23 03:12:56 +04:00
if ( vshCommandOptBool ( cmd , " diskspec " ) ) {
virBufferAddLit ( & buf , " <disks> \n " ) ;
while ( ( opt = vshCommandOptArgv ( cmd , opt ) ) ) {
if ( vshParseSnapshotDiskspec ( ctl , & buf , opt - > data ) < 0 ) {
virBufferFreeAndReset ( & buf ) ;
goto cleanup ;
}
}
virBufferAddLit ( & buf , " </disks> \n " ) ;
}
2011-06-16 02:19:13 +04:00
virBufferAddLit ( & buf , " </domainsnapshot> \n " ) ;
buffer = virBufferContentAndReset ( & buf ) ;
if ( buffer = = NULL ) {
vshError ( ctl , " %s " , _ ( " Out of memory " ) ) ;
goto cleanup ;
}
2011-06-16 02:24:40 +04:00
if ( vshCommandOptBool ( cmd , " print-xml " ) ) {
vshPrint ( ctl , " %s \n " , buffer ) ;
ret = true ;
goto cleanup ;
}
snapshot: improve virsh snapshot-create, add snapshot-edit
Wire up the new snapshot creation flags in virsh. For convenience,
teach 'snapshot-current' how to make an existing snapshot become
current (can be used after upgrading to newer libvirt to recover
from the fact that the older libvirt lost track of the current
snapshot after a restart). The snapshot-create-as command is
intentionally not taught --redefine or --current, as this would
imply adding a lot of other options for everything else that can
appear in the <domainsnapshot> xml, but which is normally read-only.
Besides, redefining will usually be done on files created by
snapshot-dumpxml, rather than something built up by hand on the
command line. And now that we can redefine, we can edit.
* tools/virsh.c (cmdSnapshotCreate): Add --redefine, --current,
and --no-metadata.
(cmdSnapshotCreateAs): Add --no-metadata.
(cmdSnapshotCurrent): Add snapshotname to alter current snapshot.
(cmdSnapshotEdit): New command.
* tools/virsh.pod (snapshot-create, snapshot-create-as)
(snapshot-current, snapshot-edit): Document these.
2011-09-02 00:21:28 +04:00
ret = vshSnapshotCreate ( ctl , dom , buffer , flags , NULL ) ;
2011-06-16 02:19:13 +04:00
cleanup :
VIR_FREE ( buffer ) ;
if ( dom )
virDomainFree ( dom ) ;
return ret ;
}
snapshot: virsh shorthand for operating on current snap
Rather than having to do:
$ virsh snapshot-revert dom $(virsh snapshot-current dom --name)
I thought it would be nice to do:
$ virsh snapshot-revert dom --current
I didn't add 'virsh snapshot-dumpxml --current' since we already have
'virsh snapshot-current' for the same task. snapshot-list accepted
a name but did not require it, and that remains the case, with
--current serving in place of that name. For all other commands,
name used to be required, and can now be replaced by --current;
I intentionally made it so that omitting both --current and a name
is an error (having the absence of a name imply --current seems
just a bit too magic, so --current must be explicit). I also had
to keep snapshot-edit backwards-compatible, as the only command
that already had a --current argument alongside a name, which still
works to both edit a named snapshot and make it current.
* tools/virsh.c (vshLookupSnapshot): New helper function.
(cmdSnapshotEdit, cmdSnapshotList, cmdSnapshotParent)
(cmdSnapshotDelete, cmdDomainSnapshotRevert): Use it, adding an
option where needed.
* tools/virsh.pod (snapshot-delete, snapshot-edit)
(snapshot-list, snapshot-parent, snapshot-revert): Document
use of --current.
(snapshot-dumpxml): Mention alternative.
2011-10-07 01:01:18 +04:00
/* Helper for resolving {--current | --ARG name} into a snapshot
* belonging to DOM . If EXCLUSIVE , fail if both - - current and arg are
* present . On success , populate * SNAP and * NAME , before returning 0.
* On failure , return - 1 after issuing an error message . */
static int
vshLookupSnapshot ( vshControl * ctl , const vshCmd * cmd ,
const char * arg , bool exclusive , virDomainPtr dom ,
virDomainSnapshotPtr * snap , const char * * name )
{
bool current = vshCommandOptBool ( cmd , " current " ) ;
const char * snapname = NULL ;
if ( vshCommandOptString ( cmd , arg , & snapname ) < 0 ) {
vshError ( ctl , _ ( " invalid argument for --%s " ) , arg ) ;
return - 1 ;
}
if ( exclusive & & current & & snapname ) {
vshError ( ctl , _ ( " --%s and --current are mutually exclusive " ) , arg ) ;
return - 1 ;
}
if ( snapname ) {
* snap = virDomainSnapshotLookupByName ( dom , snapname , 0 ) ;
} else if ( current ) {
* snap = virDomainSnapshotCurrent ( dom , 0 ) ;
} else {
vshError ( ctl , _ ( " --%s or --current is required " ) , arg ) ;
return - 1 ;
}
if ( ! * snap ) {
virshReportError ( ctl ) ;
return - 1 ;
}
* name = virDomainSnapshotGetName ( * snap ) ;
return 0 ;
}
snapshot: improve virsh snapshot-create, add snapshot-edit
Wire up the new snapshot creation flags in virsh. For convenience,
teach 'snapshot-current' how to make an existing snapshot become
current (can be used after upgrading to newer libvirt to recover
from the fact that the older libvirt lost track of the current
snapshot after a restart). The snapshot-create-as command is
intentionally not taught --redefine or --current, as this would
imply adding a lot of other options for everything else that can
appear in the <domainsnapshot> xml, but which is normally read-only.
Besides, redefining will usually be done on files created by
snapshot-dumpxml, rather than something built up by hand on the
command line. And now that we can redefine, we can edit.
* tools/virsh.c (cmdSnapshotCreate): Add --redefine, --current,
and --no-metadata.
(cmdSnapshotCreateAs): Add --no-metadata.
(cmdSnapshotCurrent): Add snapshotname to alter current snapshot.
(cmdSnapshotEdit): New command.
* tools/virsh.pod (snapshot-create, snapshot-create-as)
(snapshot-current, snapshot-edit): Document these.
2011-09-02 00:21:28 +04:00
/*
* " snapshot-edit " command
*/
static const vshCmdInfo info_snapshot_edit [ ] = {
{ " help " , N_ ( " edit XML for a snapshot " ) } ,
{ " desc " , N_ ( " Edit the domain snapshot XML for a named snapshot " ) } ,
{ NULL , NULL }
} ;
static const vshCmdOptDef opts_snapshot_edit [ ] = {
{ " domain " , VSH_OT_DATA , VSH_OFLAG_REQ , N_ ( " domain name, id or uuid " ) } ,
snapshot: virsh shorthand for operating on current snap
Rather than having to do:
$ virsh snapshot-revert dom $(virsh snapshot-current dom --name)
I thought it would be nice to do:
$ virsh snapshot-revert dom --current
I didn't add 'virsh snapshot-dumpxml --current' since we already have
'virsh snapshot-current' for the same task. snapshot-list accepted
a name but did not require it, and that remains the case, with
--current serving in place of that name. For all other commands,
name used to be required, and can now be replaced by --current;
I intentionally made it so that omitting both --current and a name
is an error (having the absence of a name imply --current seems
just a bit too magic, so --current must be explicit). I also had
to keep snapshot-edit backwards-compatible, as the only command
that already had a --current argument alongside a name, which still
works to both edit a named snapshot and make it current.
* tools/virsh.c (vshLookupSnapshot): New helper function.
(cmdSnapshotEdit, cmdSnapshotList, cmdSnapshotParent)
(cmdSnapshotDelete, cmdDomainSnapshotRevert): Use it, adding an
option where needed.
* tools/virsh.pod (snapshot-delete, snapshot-edit)
(snapshot-list, snapshot-parent, snapshot-revert): Document
use of --current.
(snapshot-dumpxml): Mention alternative.
2011-10-07 01:01:18 +04:00
{ " snapshotname " , VSH_OT_DATA , 0 , N_ ( " snapshot name " ) } ,
snapshot: improve virsh snapshot-create, add snapshot-edit
Wire up the new snapshot creation flags in virsh. For convenience,
teach 'snapshot-current' how to make an existing snapshot become
current (can be used after upgrading to newer libvirt to recover
from the fact that the older libvirt lost track of the current
snapshot after a restart). The snapshot-create-as command is
intentionally not taught --redefine or --current, as this would
imply adding a lot of other options for everything else that can
appear in the <domainsnapshot> xml, but which is normally read-only.
Besides, redefining will usually be done on files created by
snapshot-dumpxml, rather than something built up by hand on the
command line. And now that we can redefine, we can edit.
* tools/virsh.c (cmdSnapshotCreate): Add --redefine, --current,
and --no-metadata.
(cmdSnapshotCreateAs): Add --no-metadata.
(cmdSnapshotCurrent): Add snapshotname to alter current snapshot.
(cmdSnapshotEdit): New command.
* tools/virsh.pod (snapshot-create, snapshot-create-as)
(snapshot-current, snapshot-edit): Document these.
2011-09-02 00:21:28 +04:00
{ " current " , VSH_OT_BOOL , 0 , N_ ( " also set edited snapshot as current " ) } ,
snapshot: avoid accidental renames with snapshot-edit
I was a bit surprised that 'virsh snapshot-edit dom name' silently
allowed me to clone things, while still telling me the old name,
especially since other commands like 'virsh edit dom' reject rename
attempts (*). This fixes things to be more explicit (**).
(*) Technically, 'virsh edit dom' relies on virDomainDefineXML
behavior, which rejects attempts to mix a new name with existing
uuid or new uuid with existing name, but you can create a new
domain by changing both uuid and name. On the other hand, while
snapshot-edit --clone is a true clone, creating a new domain
would also have to decide whether to clone snapshot metadata,
managed save, and any other secondary data related to the domain.
Domain renames are not trivial either.
(**) Renaming or creating a clone is still a risky proposition -
for offline snapshots and system checkpoints, if the new name
does not match an actual name recorded in the qcow2 internal
snapshots, then you cannot revert to the new checkpoint. But it
is assumed that anyone using the new virsh flags knows what they
are doing, and can deal with the fallout caused by a rename/clone;
that is, we can't completely prevent a user from shooting
themselves in the foot, so much as we are making the default
action less risky.
* tools/virsh.c (cmdSnapshotEdit): Add --rename, --clone.
* tools/virsh.pod (snapshot-edit): Document them.
2011-10-08 02:20:58 +04:00
{ " rename " , VSH_OT_BOOL , 0 , N_ ( " allow renaming an existing snapshot " ) } ,
{ " clone " , VSH_OT_BOOL , 0 , N_ ( " allow cloning to new name " ) } ,
snapshot: improve virsh snapshot-create, add snapshot-edit
Wire up the new snapshot creation flags in virsh. For convenience,
teach 'snapshot-current' how to make an existing snapshot become
current (can be used after upgrading to newer libvirt to recover
from the fact that the older libvirt lost track of the current
snapshot after a restart). The snapshot-create-as command is
intentionally not taught --redefine or --current, as this would
imply adding a lot of other options for everything else that can
appear in the <domainsnapshot> xml, but which is normally read-only.
Besides, redefining will usually be done on files created by
snapshot-dumpxml, rather than something built up by hand on the
command line. And now that we can redefine, we can edit.
* tools/virsh.c (cmdSnapshotCreate): Add --redefine, --current,
and --no-metadata.
(cmdSnapshotCreateAs): Add --no-metadata.
(cmdSnapshotCurrent): Add snapshotname to alter current snapshot.
(cmdSnapshotEdit): New command.
* tools/virsh.pod (snapshot-create, snapshot-create-as)
(snapshot-current, snapshot-edit): Document these.
2011-09-02 00:21:28 +04:00
{ NULL , 0 , 0 , NULL }
} ;
static bool
cmdSnapshotEdit ( vshControl * ctl , const vshCmd * cmd )
{
virDomainPtr dom = NULL ;
virDomainSnapshotPtr snapshot = NULL ;
snapshot: avoid accidental renames with snapshot-edit
I was a bit surprised that 'virsh snapshot-edit dom name' silently
allowed me to clone things, while still telling me the old name,
especially since other commands like 'virsh edit dom' reject rename
attempts (*). This fixes things to be more explicit (**).
(*) Technically, 'virsh edit dom' relies on virDomainDefineXML
behavior, which rejects attempts to mix a new name with existing
uuid or new uuid with existing name, but you can create a new
domain by changing both uuid and name. On the other hand, while
snapshot-edit --clone is a true clone, creating a new domain
would also have to decide whether to clone snapshot metadata,
managed save, and any other secondary data related to the domain.
Domain renames are not trivial either.
(**) Renaming or creating a clone is still a risky proposition -
for offline snapshots and system checkpoints, if the new name
does not match an actual name recorded in the qcow2 internal
snapshots, then you cannot revert to the new checkpoint. But it
is assumed that anyone using the new virsh flags knows what they
are doing, and can deal with the fallout caused by a rename/clone;
that is, we can't completely prevent a user from shooting
themselves in the foot, so much as we are making the default
action less risky.
* tools/virsh.c (cmdSnapshotEdit): Add --rename, --clone.
* tools/virsh.pod (snapshot-edit): Document them.
2011-10-08 02:20:58 +04:00
virDomainSnapshotPtr edited = NULL ;
snapshot: improve virsh snapshot-create, add snapshot-edit
Wire up the new snapshot creation flags in virsh. For convenience,
teach 'snapshot-current' how to make an existing snapshot become
current (can be used after upgrading to newer libvirt to recover
from the fact that the older libvirt lost track of the current
snapshot after a restart). The snapshot-create-as command is
intentionally not taught --redefine or --current, as this would
imply adding a lot of other options for everything else that can
appear in the <domainsnapshot> xml, but which is normally read-only.
Besides, redefining will usually be done on files created by
snapshot-dumpxml, rather than something built up by hand on the
command line. And now that we can redefine, we can edit.
* tools/virsh.c (cmdSnapshotCreate): Add --redefine, --current,
and --no-metadata.
(cmdSnapshotCreateAs): Add --no-metadata.
(cmdSnapshotCurrent): Add snapshotname to alter current snapshot.
(cmdSnapshotEdit): New command.
* tools/virsh.pod (snapshot-create, snapshot-create-as)
(snapshot-current, snapshot-edit): Document these.
2011-09-02 00:21:28 +04:00
const char * name ;
snapshot: avoid accidental renames with snapshot-edit
I was a bit surprised that 'virsh snapshot-edit dom name' silently
allowed me to clone things, while still telling me the old name,
especially since other commands like 'virsh edit dom' reject rename
attempts (*). This fixes things to be more explicit (**).
(*) Technically, 'virsh edit dom' relies on virDomainDefineXML
behavior, which rejects attempts to mix a new name with existing
uuid or new uuid with existing name, but you can create a new
domain by changing both uuid and name. On the other hand, while
snapshot-edit --clone is a true clone, creating a new domain
would also have to decide whether to clone snapshot metadata,
managed save, and any other secondary data related to the domain.
Domain renames are not trivial either.
(**) Renaming or creating a clone is still a risky proposition -
for offline snapshots and system checkpoints, if the new name
does not match an actual name recorded in the qcow2 internal
snapshots, then you cannot revert to the new checkpoint. But it
is assumed that anyone using the new virsh flags knows what they
are doing, and can deal with the fallout caused by a rename/clone;
that is, we can't completely prevent a user from shooting
themselves in the foot, so much as we are making the default
action less risky.
* tools/virsh.c (cmdSnapshotEdit): Add --rename, --clone.
* tools/virsh.pod (snapshot-edit): Document them.
2011-10-08 02:20:58 +04:00
const char * edited_name ;
snapshot: improve virsh snapshot-create, add snapshot-edit
Wire up the new snapshot creation flags in virsh. For convenience,
teach 'snapshot-current' how to make an existing snapshot become
current (can be used after upgrading to newer libvirt to recover
from the fact that the older libvirt lost track of the current
snapshot after a restart). The snapshot-create-as command is
intentionally not taught --redefine or --current, as this would
imply adding a lot of other options for everything else that can
appear in the <domainsnapshot> xml, but which is normally read-only.
Besides, redefining will usually be done on files created by
snapshot-dumpxml, rather than something built up by hand on the
command line. And now that we can redefine, we can edit.
* tools/virsh.c (cmdSnapshotCreate): Add --redefine, --current,
and --no-metadata.
(cmdSnapshotCreateAs): Add --no-metadata.
(cmdSnapshotCurrent): Add snapshotname to alter current snapshot.
(cmdSnapshotEdit): New command.
* tools/virsh.pod (snapshot-create, snapshot-create-as)
(snapshot-current, snapshot-edit): Document these.
2011-09-02 00:21:28 +04:00
bool ret = false ;
unsigned int getxml_flags = VIR_DOMAIN_XML_SECURE ;
unsigned int define_flags = VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE ;
snapshot: avoid accidental renames with snapshot-edit
I was a bit surprised that 'virsh snapshot-edit dom name' silently
allowed me to clone things, while still telling me the old name,
especially since other commands like 'virsh edit dom' reject rename
attempts (*). This fixes things to be more explicit (**).
(*) Technically, 'virsh edit dom' relies on virDomainDefineXML
behavior, which rejects attempts to mix a new name with existing
uuid or new uuid with existing name, but you can create a new
domain by changing both uuid and name. On the other hand, while
snapshot-edit --clone is a true clone, creating a new domain
would also have to decide whether to clone snapshot metadata,
managed save, and any other secondary data related to the domain.
Domain renames are not trivial either.
(**) Renaming or creating a clone is still a risky proposition -
for offline snapshots and system checkpoints, if the new name
does not match an actual name recorded in the qcow2 internal
snapshots, then you cannot revert to the new checkpoint. But it
is assumed that anyone using the new virsh flags knows what they
are doing, and can deal with the fallout caused by a rename/clone;
that is, we can't completely prevent a user from shooting
themselves in the foot, so much as we are making the default
action less risky.
* tools/virsh.c (cmdSnapshotEdit): Add --rename, --clone.
* tools/virsh.pod (snapshot-edit): Document them.
2011-10-08 02:20:58 +04:00
bool rename_okay = vshCommandOptBool ( cmd , " rename " ) ;
bool clone_okay = vshCommandOptBool ( cmd , " clone " ) ;
if ( rename_okay & & clone_okay ) {
vshError ( ctl , " %s " ,
_ ( " --rename and --clone are mutually exclusive " ) ) ;
return false ;
}
snapshot: improve virsh snapshot-create, add snapshot-edit
Wire up the new snapshot creation flags in virsh. For convenience,
teach 'snapshot-current' how to make an existing snapshot become
current (can be used after upgrading to newer libvirt to recover
from the fact that the older libvirt lost track of the current
snapshot after a restart). The snapshot-create-as command is
intentionally not taught --redefine or --current, as this would
imply adding a lot of other options for everything else that can
appear in the <domainsnapshot> xml, but which is normally read-only.
Besides, redefining will usually be done on files created by
snapshot-dumpxml, rather than something built up by hand on the
command line. And now that we can redefine, we can edit.
* tools/virsh.c (cmdSnapshotCreate): Add --redefine, --current,
and --no-metadata.
(cmdSnapshotCreateAs): Add --no-metadata.
(cmdSnapshotCurrent): Add snapshotname to alter current snapshot.
(cmdSnapshotEdit): New command.
* tools/virsh.pod (snapshot-create, snapshot-create-as)
(snapshot-current, snapshot-edit): Document these.
2011-09-02 00:21:28 +04:00
snapshot: virsh shorthand for operating on current snap
Rather than having to do:
$ virsh snapshot-revert dom $(virsh snapshot-current dom --name)
I thought it would be nice to do:
$ virsh snapshot-revert dom --current
I didn't add 'virsh snapshot-dumpxml --current' since we already have
'virsh snapshot-current' for the same task. snapshot-list accepted
a name but did not require it, and that remains the case, with
--current serving in place of that name. For all other commands,
name used to be required, and can now be replaced by --current;
I intentionally made it so that omitting both --current and a name
is an error (having the absence of a name imply --current seems
just a bit too magic, so --current must be explicit). I also had
to keep snapshot-edit backwards-compatible, as the only command
that already had a --current argument alongside a name, which still
works to both edit a named snapshot and make it current.
* tools/virsh.c (vshLookupSnapshot): New helper function.
(cmdSnapshotEdit, cmdSnapshotList, cmdSnapshotParent)
(cmdSnapshotDelete, cmdDomainSnapshotRevert): Use it, adding an
option where needed.
* tools/virsh.pod (snapshot-delete, snapshot-edit)
(snapshot-list, snapshot-parent, snapshot-revert): Document
use of --current.
(snapshot-dumpxml): Mention alternative.
2011-10-07 01:01:18 +04:00
if ( vshCommandOptBool ( cmd , " current " ) & &
vshCommandOptBool ( cmd , " snapshotname " ) )
snapshot: improve virsh snapshot-create, add snapshot-edit
Wire up the new snapshot creation flags in virsh. For convenience,
teach 'snapshot-current' how to make an existing snapshot become
current (can be used after upgrading to newer libvirt to recover
from the fact that the older libvirt lost track of the current
snapshot after a restart). The snapshot-create-as command is
intentionally not taught --redefine or --current, as this would
imply adding a lot of other options for everything else that can
appear in the <domainsnapshot> xml, but which is normally read-only.
Besides, redefining will usually be done on files created by
snapshot-dumpxml, rather than something built up by hand on the
command line. And now that we can redefine, we can edit.
* tools/virsh.c (cmdSnapshotCreate): Add --redefine, --current,
and --no-metadata.
(cmdSnapshotCreateAs): Add --no-metadata.
(cmdSnapshotCurrent): Add snapshotname to alter current snapshot.
(cmdSnapshotEdit): New command.
* tools/virsh.pod (snapshot-create, snapshot-create-as)
(snapshot-current, snapshot-edit): Document these.
2011-09-02 00:21:28 +04:00
define_flags | = VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT ;
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
return false ;
dom = vshCommandOptDomain ( ctl , cmd , NULL ) ;
if ( dom = = NULL )
goto cleanup ;
snapshot: virsh shorthand for operating on current snap
Rather than having to do:
$ virsh snapshot-revert dom $(virsh snapshot-current dom --name)
I thought it would be nice to do:
$ virsh snapshot-revert dom --current
I didn't add 'virsh snapshot-dumpxml --current' since we already have
'virsh snapshot-current' for the same task. snapshot-list accepted
a name but did not require it, and that remains the case, with
--current serving in place of that name. For all other commands,
name used to be required, and can now be replaced by --current;
I intentionally made it so that omitting both --current and a name
is an error (having the absence of a name imply --current seems
just a bit too magic, so --current must be explicit). I also had
to keep snapshot-edit backwards-compatible, as the only command
that already had a --current argument alongside a name, which still
works to both edit a named snapshot and make it current.
* tools/virsh.c (vshLookupSnapshot): New helper function.
(cmdSnapshotEdit, cmdSnapshotList, cmdSnapshotParent)
(cmdSnapshotDelete, cmdDomainSnapshotRevert): Use it, adding an
option where needed.
* tools/virsh.pod (snapshot-delete, snapshot-edit)
(snapshot-list, snapshot-parent, snapshot-revert): Document
use of --current.
(snapshot-dumpxml): Mention alternative.
2011-10-07 01:01:18 +04:00
if ( vshLookupSnapshot ( ctl , cmd , " snapshotname " , false , dom ,
& snapshot , & name ) < 0 )
snapshot: improve virsh snapshot-create, add snapshot-edit
Wire up the new snapshot creation flags in virsh. For convenience,
teach 'snapshot-current' how to make an existing snapshot become
current (can be used after upgrading to newer libvirt to recover
from the fact that the older libvirt lost track of the current
snapshot after a restart). The snapshot-create-as command is
intentionally not taught --redefine or --current, as this would
imply adding a lot of other options for everything else that can
appear in the <domainsnapshot> xml, but which is normally read-only.
Besides, redefining will usually be done on files created by
snapshot-dumpxml, rather than something built up by hand on the
command line. And now that we can redefine, we can edit.
* tools/virsh.c (cmdSnapshotCreate): Add --redefine, --current,
and --no-metadata.
(cmdSnapshotCreateAs): Add --no-metadata.
(cmdSnapshotCurrent): Add snapshotname to alter current snapshot.
(cmdSnapshotEdit): New command.
* tools/virsh.pod (snapshot-create, snapshot-create-as)
(snapshot-current, snapshot-edit): Document these.
2011-09-02 00:21:28 +04:00
goto cleanup ;
2012-06-04 07:37:50 +04:00
# define EDIT_GET_XML \
virDomainSnapshotGetXMLDesc ( snapshot , getxml_flags )
# define EDIT_NOT_CHANGED \
/* Depending on flags, we re-edit even if XML is unchanged. */ \
if ( ! ( define_flags & VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT ) ) { \
vshPrint ( ctl , \
_ ( " Snapshot %s XML configuration not changed. \n " ) , \
name ) ; \
ret = true ; \
goto cleanup ; \
}
# define EDIT_DEFINE \
( strstr ( doc , " <state>disk-snapshot</state> " ) ? \
define_flags | = VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY : 0 ) , \
edited = virDomainSnapshotCreateXML ( dom , doc_edited , define_flags )
# define EDIT_FREE \
if ( edited ) \
virDomainSnapshotFree ( edited ) ;
# include "virsh-edit.c"
snapshot: improve virsh snapshot-create, add snapshot-edit
Wire up the new snapshot creation flags in virsh. For convenience,
teach 'snapshot-current' how to make an existing snapshot become
current (can be used after upgrading to newer libvirt to recover
from the fact that the older libvirt lost track of the current
snapshot after a restart). The snapshot-create-as command is
intentionally not taught --redefine or --current, as this would
imply adding a lot of other options for everything else that can
appear in the <domainsnapshot> xml, but which is normally read-only.
Besides, redefining will usually be done on files created by
snapshot-dumpxml, rather than something built up by hand on the
command line. And now that we can redefine, we can edit.
* tools/virsh.c (cmdSnapshotCreate): Add --redefine, --current,
and --no-metadata.
(cmdSnapshotCreateAs): Add --no-metadata.
(cmdSnapshotCurrent): Add snapshotname to alter current snapshot.
(cmdSnapshotEdit): New command.
* tools/virsh.pod (snapshot-create, snapshot-create-as)
(snapshot-current, snapshot-edit): Document these.
2011-09-02 00:21:28 +04:00
snapshot: avoid accidental renames with snapshot-edit
I was a bit surprised that 'virsh snapshot-edit dom name' silently
allowed me to clone things, while still telling me the old name,
especially since other commands like 'virsh edit dom' reject rename
attempts (*). This fixes things to be more explicit (**).
(*) Technically, 'virsh edit dom' relies on virDomainDefineXML
behavior, which rejects attempts to mix a new name with existing
uuid or new uuid with existing name, but you can create a new
domain by changing both uuid and name. On the other hand, while
snapshot-edit --clone is a true clone, creating a new domain
would also have to decide whether to clone snapshot metadata,
managed save, and any other secondary data related to the domain.
Domain renames are not trivial either.
(**) Renaming or creating a clone is still a risky proposition -
for offline snapshots and system checkpoints, if the new name
does not match an actual name recorded in the qcow2 internal
snapshots, then you cannot revert to the new checkpoint. But it
is assumed that anyone using the new virsh flags knows what they
are doing, and can deal with the fallout caused by a rename/clone;
that is, we can't completely prevent a user from shooting
themselves in the foot, so much as we are making the default
action less risky.
* tools/virsh.c (cmdSnapshotEdit): Add --rename, --clone.
* tools/virsh.pod (snapshot-edit): Document them.
2011-10-08 02:20:58 +04:00
edited_name = virDomainSnapshotGetName ( edited ) ;
if ( STREQ ( name , edited_name ) ) {
vshPrint ( ctl , _ ( " Snapshot %s edited. \n " ) , name ) ;
} else if ( clone_okay ) {
vshPrint ( ctl , _ ( " Snapshot %s cloned to %s. \n " ) , name ,
edited_name ) ;
} else {
unsigned int delete_flags ;
delete_flags = VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY ;
if ( virDomainSnapshotDelete ( rename_okay ? snapshot : edited ,
delete_flags ) < 0 ) {
virshReportError ( ctl ) ;
vshError ( ctl , _ ( " Failed to clean up %s " ) ,
rename_okay ? name : edited_name ) ;
goto cleanup ;
}
if ( ! rename_okay ) {
vshError ( ctl , _ ( " Must use --rename or --clone to change %s to %s " ) ,
name , edited_name ) ;
goto cleanup ;
}
}
snapshot: improve virsh snapshot-create, add snapshot-edit
Wire up the new snapshot creation flags in virsh. For convenience,
teach 'snapshot-current' how to make an existing snapshot become
current (can be used after upgrading to newer libvirt to recover
from the fact that the older libvirt lost track of the current
snapshot after a restart). The snapshot-create-as command is
intentionally not taught --redefine or --current, as this would
imply adding a lot of other options for everything else that can
appear in the <domainsnapshot> xml, but which is normally read-only.
Besides, redefining will usually be done on files created by
snapshot-dumpxml, rather than something built up by hand on the
command line. And now that we can redefine, we can edit.
* tools/virsh.c (cmdSnapshotCreate): Add --redefine, --current,
and --no-metadata.
(cmdSnapshotCreateAs): Add --no-metadata.
(cmdSnapshotCurrent): Add snapshotname to alter current snapshot.
(cmdSnapshotEdit): New command.
* tools/virsh.pod (snapshot-create, snapshot-create-as)
(snapshot-current, snapshot-edit): Document these.
2011-09-02 00:21:28 +04:00
ret = true ;
cleanup :
snapshot: avoid accidental renames with snapshot-edit
I was a bit surprised that 'virsh snapshot-edit dom name' silently
allowed me to clone things, while still telling me the old name,
especially since other commands like 'virsh edit dom' reject rename
attempts (*). This fixes things to be more explicit (**).
(*) Technically, 'virsh edit dom' relies on virDomainDefineXML
behavior, which rejects attempts to mix a new name with existing
uuid or new uuid with existing name, but you can create a new
domain by changing both uuid and name. On the other hand, while
snapshot-edit --clone is a true clone, creating a new domain
would also have to decide whether to clone snapshot metadata,
managed save, and any other secondary data related to the domain.
Domain renames are not trivial either.
(**) Renaming or creating a clone is still a risky proposition -
for offline snapshots and system checkpoints, if the new name
does not match an actual name recorded in the qcow2 internal
snapshots, then you cannot revert to the new checkpoint. But it
is assumed that anyone using the new virsh flags knows what they
are doing, and can deal with the fallout caused by a rename/clone;
that is, we can't completely prevent a user from shooting
themselves in the foot, so much as we are making the default
action less risky.
* tools/virsh.c (cmdSnapshotEdit): Add --rename, --clone.
* tools/virsh.pod (snapshot-edit): Document them.
2011-10-08 02:20:58 +04:00
if ( edited )
virDomainSnapshotFree ( edited ) ;
2012-05-17 19:08:53 +04:00
else
vshError ( ctl , _ ( " Failed to update %s " ) , name ) ;
if ( snapshot )
virDomainSnapshotFree ( snapshot ) ;
snapshot: improve virsh snapshot-create, add snapshot-edit
Wire up the new snapshot creation flags in virsh. For convenience,
teach 'snapshot-current' how to make an existing snapshot become
current (can be used after upgrading to newer libvirt to recover
from the fact that the older libvirt lost track of the current
snapshot after a restart). The snapshot-create-as command is
intentionally not taught --redefine or --current, as this would
imply adding a lot of other options for everything else that can
appear in the <domainsnapshot> xml, but which is normally read-only.
Besides, redefining will usually be done on files created by
snapshot-dumpxml, rather than something built up by hand on the
command line. And now that we can redefine, we can edit.
* tools/virsh.c (cmdSnapshotCreate): Add --redefine, --current,
and --no-metadata.
(cmdSnapshotCreateAs): Add --no-metadata.
(cmdSnapshotCurrent): Add snapshotname to alter current snapshot.
(cmdSnapshotEdit): New command.
* tools/virsh.pod (snapshot-create, snapshot-create-as)
(snapshot-current, snapshot-edit): Document these.
2011-09-02 00:21:28 +04:00
if ( dom )
virDomainFree ( dom ) ;
return ret ;
}
2010-04-01 00:28:00 +04:00
/*
* " snapshot-current " command
*/
static const vshCmdInfo info_snapshot_current [ ] = {
snapshot: improve virsh snapshot-create, add snapshot-edit
Wire up the new snapshot creation flags in virsh. For convenience,
teach 'snapshot-current' how to make an existing snapshot become
current (can be used after upgrading to newer libvirt to recover
from the fact that the older libvirt lost track of the current
snapshot after a restart). The snapshot-create-as command is
intentionally not taught --redefine or --current, as this would
imply adding a lot of other options for everything else that can
appear in the <domainsnapshot> xml, but which is normally read-only.
Besides, redefining will usually be done on files created by
snapshot-dumpxml, rather than something built up by hand on the
command line. And now that we can redefine, we can edit.
* tools/virsh.c (cmdSnapshotCreate): Add --redefine, --current,
and --no-metadata.
(cmdSnapshotCreateAs): Add --no-metadata.
(cmdSnapshotCurrent): Add snapshotname to alter current snapshot.
(cmdSnapshotEdit): New command.
* tools/virsh.pod (snapshot-create, snapshot-create-as)
(snapshot-current, snapshot-edit): Document these.
2011-09-02 00:21:28 +04:00
{ " help " , N_ ( " Get or set the current snapshot " ) } ,
{ " desc " , N_ ( " Get or set the current snapshot " ) } ,
2010-04-01 00:28:00 +04:00
{ NULL , NULL }
} ;
static const vshCmdOptDef opts_snapshot_current [ ] = {
{ " domain " , VSH_OT_DATA , VSH_OFLAG_REQ , N_ ( " domain name, id or uuid " ) } ,
2011-08-10 07:10:25 +04:00
{ " name " , VSH_OT_BOOL , 0 , N_ ( " list the name, rather than the full xml " ) } ,
2011-08-16 23:34:22 +04:00
{ " security-info " , VSH_OT_BOOL , 0 ,
N_ ( " include security sensitive information in XML dump " ) } ,
snapshot: improve virsh snapshot-create, add snapshot-edit
Wire up the new snapshot creation flags in virsh. For convenience,
teach 'snapshot-current' how to make an existing snapshot become
current (can be used after upgrading to newer libvirt to recover
from the fact that the older libvirt lost track of the current
snapshot after a restart). The snapshot-create-as command is
intentionally not taught --redefine or --current, as this would
imply adding a lot of other options for everything else that can
appear in the <domainsnapshot> xml, but which is normally read-only.
Besides, redefining will usually be done on files created by
snapshot-dumpxml, rather than something built up by hand on the
command line. And now that we can redefine, we can edit.
* tools/virsh.c (cmdSnapshotCreate): Add --redefine, --current,
and --no-metadata.
(cmdSnapshotCreateAs): Add --no-metadata.
(cmdSnapshotCurrent): Add snapshotname to alter current snapshot.
(cmdSnapshotEdit): New command.
* tools/virsh.pod (snapshot-create, snapshot-create-as)
(snapshot-current, snapshot-edit): Document these.
2011-09-02 00:21:28 +04:00
{ " snapshotname " , VSH_OT_DATA , 0 ,
N_ ( " name of existing snapshot to make current " ) } ,
2010-04-01 00:28:00 +04:00
{ NULL , 0 , 0 , NULL }
} ;
2011-04-19 02:37:42 +04:00
static bool
2010-04-01 00:28:00 +04:00
cmdSnapshotCurrent ( vshControl * ctl , const vshCmd * cmd )
{
virDomainPtr dom = NULL ;
2011-04-19 02:37:42 +04:00
bool ret = false ;
2010-04-01 00:28:00 +04:00
int current ;
virDomainSnapshotPtr snapshot = NULL ;
2011-08-10 07:10:25 +04:00
char * xml = NULL ;
snapshot: improve virsh snapshot-create, add snapshot-edit
Wire up the new snapshot creation flags in virsh. For convenience,
teach 'snapshot-current' how to make an existing snapshot become
current (can be used after upgrading to newer libvirt to recover
from the fact that the older libvirt lost track of the current
snapshot after a restart). The snapshot-create-as command is
intentionally not taught --redefine or --current, as this would
imply adding a lot of other options for everything else that can
appear in the <domainsnapshot> xml, but which is normally read-only.
Besides, redefining will usually be done on files created by
snapshot-dumpxml, rather than something built up by hand on the
command line. And now that we can redefine, we can edit.
* tools/virsh.c (cmdSnapshotCreate): Add --redefine, --current,
and --no-metadata.
(cmdSnapshotCreateAs): Add --no-metadata.
(cmdSnapshotCurrent): Add snapshotname to alter current snapshot.
(cmdSnapshotEdit): New command.
* tools/virsh.pod (snapshot-create, snapshot-create-as)
(snapshot-current, snapshot-edit): Document these.
2011-09-02 00:21:28 +04:00
const char * snapshotname = NULL ;
2011-08-16 23:34:22 +04:00
unsigned int flags = 0 ;
2011-09-30 19:45:43 +04:00
const char * domname ;
2011-08-16 23:34:22 +04:00
if ( vshCommandOptBool ( cmd , " security-info " ) )
flags | = VIR_DOMAIN_XML_SECURE ;
2010-04-01 00:28:00 +04:00
2010-06-17 18:47:06 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
2010-04-01 00:28:00 +04:00
goto cleanup ;
2011-09-30 19:45:43 +04:00
dom = vshCommandOptDomain ( ctl , cmd , & domname ) ;
2010-04-01 00:28:00 +04:00
if ( dom = = NULL )
goto cleanup ;
snapshot: improve virsh snapshot-create, add snapshot-edit
Wire up the new snapshot creation flags in virsh. For convenience,
teach 'snapshot-current' how to make an existing snapshot become
current (can be used after upgrading to newer libvirt to recover
from the fact that the older libvirt lost track of the current
snapshot after a restart). The snapshot-create-as command is
intentionally not taught --redefine or --current, as this would
imply adding a lot of other options for everything else that can
appear in the <domainsnapshot> xml, but which is normally read-only.
Besides, redefining will usually be done on files created by
snapshot-dumpxml, rather than something built up by hand on the
command line. And now that we can redefine, we can edit.
* tools/virsh.c (cmdSnapshotCreate): Add --redefine, --current,
and --no-metadata.
(cmdSnapshotCreateAs): Add --no-metadata.
(cmdSnapshotCurrent): Add snapshotname to alter current snapshot.
(cmdSnapshotEdit): New command.
* tools/virsh.pod (snapshot-create, snapshot-create-as)
(snapshot-current, snapshot-edit): Document these.
2011-09-02 00:21:28 +04:00
if ( vshCommandOptString ( cmd , " snapshotname " , & snapshotname ) < 0 ) {
vshError ( ctl , _ ( " invalid snapshotname argument '%s' " ) , snapshotname ) ;
goto cleanup ;
}
if ( snapshotname ) {
virDomainSnapshotPtr snapshot2 = NULL ;
flags = ( VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE |
VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT ) ;
if ( vshCommandOptBool ( cmd , " name " ) ) {
vshError ( ctl , " %s " ,
_ ( " --name and snapshotname are mutually exclusive " ) ) ;
goto cleanup ;
}
snapshot = virDomainSnapshotLookupByName ( dom , snapshotname , 0 ) ;
if ( snapshot = = NULL )
goto cleanup ;
xml = virDomainSnapshotGetXMLDesc ( snapshot , VIR_DOMAIN_XML_SECURE ) ;
if ( ! xml )
goto cleanup ;
2011-10-07 02:58:28 +04:00
/* strstr is safe here, since xml came from libvirt API and not user */
if ( strstr ( xml , " <state>disk-snapshot</state> " ) )
flags | = VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY ;
snapshot: improve virsh snapshot-create, add snapshot-edit
Wire up the new snapshot creation flags in virsh. For convenience,
teach 'snapshot-current' how to make an existing snapshot become
current (can be used after upgrading to newer libvirt to recover
from the fact that the older libvirt lost track of the current
snapshot after a restart). The snapshot-create-as command is
intentionally not taught --redefine or --current, as this would
imply adding a lot of other options for everything else that can
appear in the <domainsnapshot> xml, but which is normally read-only.
Besides, redefining will usually be done on files created by
snapshot-dumpxml, rather than something built up by hand on the
command line. And now that we can redefine, we can edit.
* tools/virsh.c (cmdSnapshotCreate): Add --redefine, --current,
and --no-metadata.
(cmdSnapshotCreateAs): Add --no-metadata.
(cmdSnapshotCurrent): Add snapshotname to alter current snapshot.
(cmdSnapshotEdit): New command.
* tools/virsh.pod (snapshot-create, snapshot-create-as)
(snapshot-current, snapshot-edit): Document these.
2011-09-02 00:21:28 +04:00
snapshot2 = virDomainSnapshotCreateXML ( dom , xml , flags ) ;
if ( snapshot2 = = NULL )
goto cleanup ;
virDomainSnapshotFree ( snapshot2 ) ;
vshPrint ( ctl , _ ( " Snapshot %s set as current " ) , snapshotname ) ;
ret = true ;
goto cleanup ;
}
2010-04-01 00:28:00 +04:00
current = virDomainHasCurrentSnapshot ( dom , 0 ) ;
2011-09-30 19:45:43 +04:00
if ( current < 0 ) {
goto cleanup ;
} else if ( ! current ) {
vshError ( ctl , _ ( " domain '%s' has no current snapshot " ) , domname ) ;
2010-04-01 00:28:00 +04:00
goto cleanup ;
2011-09-30 19:45:43 +04:00
} else {
2011-09-08 16:16:57 +04:00
const char * name = NULL ;
2010-04-01 00:28:00 +04:00
if ( ! ( snapshot = virDomainSnapshotCurrent ( dom , 0 ) ) )
goto cleanup ;
2011-08-10 07:10:25 +04:00
if ( vshCommandOptBool ( cmd , " name " ) ) {
2011-09-08 16:16:57 +04:00
name = virDomainSnapshotGetName ( snapshot ) ;
2011-08-10 07:10:25 +04:00
if ( ! name )
goto cleanup ;
2011-09-08 16:16:57 +04:00
} else {
xml = virDomainSnapshotGetXMLDesc ( snapshot , flags ) ;
if ( ! xml )
goto cleanup ;
2011-08-10 07:10:25 +04:00
}
vshPrint ( ctl , " %s " , name ? name : xml ) ;
2010-04-01 00:28:00 +04:00
}
2011-04-19 02:37:42 +04:00
ret = true ;
2010-04-01 00:28:00 +04:00
cleanup :
2011-09-30 19:45:43 +04:00
if ( ! ret )
virshReportError ( ctl ) ;
2011-08-10 07:10:25 +04:00
VIR_FREE ( xml ) ;
2010-04-01 00:28:00 +04:00
if ( snapshot )
virDomainSnapshotFree ( snapshot ) ;
if ( dom )
virDomainFree ( dom ) ;
return ret ;
}
2011-08-11 03:31:04 +04:00
/* Helper function to get the name of a snapshot's parent. Caller
2011-09-30 19:45:43 +04:00
* must free the result . Returns 0 on success ( including when it was
* proven no parent exists ) , and - 1 on failure with error reported
* ( such as no snapshot support or domain deleted in meantime ) . */
static int
vshGetSnapshotParent ( vshControl * ctl , virDomainSnapshotPtr snapshot ,
char * * parent_name )
2011-08-11 03:31:04 +04:00
{
virDomainSnapshotPtr parent = NULL ;
char * xml = NULL ;
xmlDocPtr xmldoc = NULL ;
xmlXPathContextPtr ctxt = NULL ;
2011-09-30 19:45:43 +04:00
int ret = - 1 ;
* parent_name = NULL ;
2011-08-11 03:31:04 +04:00
/* Try new API, since it is faster. */
2011-09-30 01:18:50 +04:00
if ( ! ctl - > useSnapshotOld ) {
2011-08-11 03:31:04 +04:00
parent = virDomainSnapshotGetParent ( snapshot , 0 ) ;
if ( parent ) {
/* API works, and virDomainSnapshotGetName will succeed */
2011-09-30 19:45:43 +04:00
* parent_name = vshStrdup ( ctl , virDomainSnapshotGetName ( parent ) ) ;
ret = 0 ;
2011-08-11 03:31:04 +04:00
goto cleanup ;
}
if ( last_error - > code = = VIR_ERR_NO_DOMAIN_SNAPSHOT ) {
/* API works, and we found a root with no parent */
2011-09-30 19:45:43 +04:00
ret = 0 ;
2011-08-11 03:31:04 +04:00
goto cleanup ;
}
/* API didn't work, fall back to XML scraping. */
2011-09-30 01:18:50 +04:00
ctl - > useSnapshotOld = true ;
2011-08-11 03:31:04 +04:00
}
xml = virDomainSnapshotGetXMLDesc ( snapshot , 0 ) ;
if ( ! xml )
goto cleanup ;
xmldoc = virXMLParseStringCtxt ( xml , _ ( " (domain_snapshot) " ) , & ctxt ) ;
if ( ! xmldoc )
goto cleanup ;
2011-09-30 19:45:43 +04:00
* parent_name = virXPathString ( " string(/domainsnapshot/parent/name) " , ctxt ) ;
ret = 0 ;
2011-08-11 03:31:04 +04:00
cleanup :
2011-09-30 19:45:43 +04:00
if ( ret < 0 ) {
virshReportError ( ctl ) ;
vshError ( ctl , " %s " , _ ( " unable to determine if snapshot has parent " ) ) ;
} else {
virFreeError ( last_error ) ;
last_error = NULL ;
}
2011-08-11 03:31:04 +04:00
if ( parent )
virDomainSnapshotFree ( parent ) ;
xmlXPathFreeContext ( ctxt ) ;
xmlFreeDoc ( xmldoc ) ;
VIR_FREE ( xml ) ;
2011-09-30 19:45:43 +04:00
return ret ;
2011-08-11 03:31:04 +04:00
}
2012-05-25 01:53:24 +04:00
/*
* " snapshot-info " command
*/
static const vshCmdInfo info_snapshot_info [ ] = {
{ " help " , N_ ( " snapshot information " ) } ,
{ " desc " , N_ ( " Returns basic information about a snapshot. " ) } ,
{ NULL , NULL }
} ;
static const vshCmdOptDef opts_snapshot_info [ ] = {
{ " domain " , VSH_OT_DATA , VSH_OFLAG_REQ , N_ ( " domain name, id or uuid " ) } ,
{ " snapshotname " , VSH_OT_DATA , 0 , N_ ( " snapshot name " ) } ,
{ " current " , VSH_OT_BOOL , 0 , N_ ( " info on current snapshot " ) } ,
{ NULL , 0 , 0 , NULL }
} ;
static bool
cmdSnapshotInfo ( vshControl * ctl , const vshCmd * cmd )
{
virDomainPtr dom ;
virDomainSnapshotPtr snapshot = NULL ;
const char * name ;
char * doc = NULL ;
char * tmp ;
char * parent = NULL ;
bool ret = false ;
int count ;
unsigned int flags ;
int current ;
int metadata ;
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
return false ;
dom = vshCommandOptDomain ( ctl , cmd , NULL ) ;
if ( dom = = NULL )
return false ;
if ( vshLookupSnapshot ( ctl , cmd , " snapshotname " , true , dom ,
& snapshot , & name ) < 0 )
goto cleanup ;
vshPrint ( ctl , " %-15s %s \n " , _ ( " Name: " ) , name ) ;
vshPrint ( ctl , " %-15s %s \n " , _ ( " Domain: " ) , virDomainGetName ( dom ) ) ;
/* Determine if snapshot is current; this is useful enough that we
* attempt a fallback . */
current = virDomainSnapshotIsCurrent ( snapshot , 0 ) ;
if ( current < 0 ) {
virDomainSnapshotPtr other = virDomainSnapshotCurrent ( dom , 0 ) ;
virResetLastError ( ) ;
current = 0 ;
if ( other ) {
if ( STREQ ( name , virDomainSnapshotGetName ( other ) ) )
current = 1 ;
virDomainSnapshotFree ( other ) ;
}
}
vshPrint ( ctl , " %-15s %s \n " , _ ( " Current: " ) ,
current > 0 ? _ ( " yes " ) : _ ( " no " ) ) ;
/* Get the XML configuration of the snapshot to determine the
* state of the machine at the time of the snapshot . */
doc = virDomainSnapshotGetXMLDesc ( snapshot , 0 ) ;
if ( ! doc )
goto cleanup ;
tmp = strstr ( doc , " <state> " ) ;
if ( ! tmp ) {
vshError ( ctl , " %s " ,
_ ( " unexpected problem reading snapshot xml " ) ) ;
goto cleanup ;
}
tmp + = strlen ( " <state> " ) ;
vshPrint ( ctl , " %-15s %.*s \n " , _ ( " State: " ) ,
( int ) ( strchr ( tmp , ' < ' ) - tmp ) , tmp ) ;
if ( vshGetSnapshotParent ( ctl , snapshot , & parent ) < 0 )
goto cleanup ;
vshPrint ( ctl , " %-15s %s \n " , _ ( " Parent: " ) , parent ? parent : " - " ) ;
/* Children, Descendants. After this point, the fallback to
* compute children is too expensive , so we gracefully quit if the
* APIs don ' t exist . */
if ( ctl - > useSnapshotOld ) {
ret = true ;
goto cleanup ;
}
flags = 0 ;
count = virDomainSnapshotNumChildren ( snapshot , flags ) ;
if ( count < 0 )
goto cleanup ;
vshPrint ( ctl , " %-15s %d \n " , _ ( " Children: " ) , count ) ;
flags = VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS ;
count = virDomainSnapshotNumChildren ( snapshot , flags ) ;
if ( count < 0 )
goto cleanup ;
vshPrint ( ctl , " %-15s %d \n " , _ ( " Descendants: " ) , count ) ;
/* Metadata; the fallback here relies on the fact that metadata
* used to have an all - or - nothing effect on snapshot count . */
metadata = virDomainSnapshotHasMetadata ( snapshot , 0 ) ;
if ( metadata < 0 ) {
metadata = virDomainSnapshotNum ( dom ,
VIR_DOMAIN_SNAPSHOT_LIST_METADATA ) ;
virResetLastError ( ) ;
}
if ( metadata > = 0 )
vshPrint ( ctl , " %-15s %s \n " , _ ( " Metadata: " ) ,
metadata ? _ ( " yes " ) : _ ( " no " ) ) ;
ret = true ;
cleanup :
VIR_FREE ( doc ) ;
VIR_FREE ( parent ) ;
if ( snapshot )
virDomainSnapshotFree ( snapshot ) ;
virDomainFree ( dom ) ;
return ret ;
}
2012-06-15 04:50:03 +04:00
/* Helpers for collecting a list of snapshots. */
struct vshSnap {
virDomainSnapshotPtr snap ;
char * parent ;
} ;
struct vshSnapshotList {
struct vshSnap * snaps ;
int nsnaps ;
} ;
typedef struct vshSnapshotList * vshSnapshotListPtr ;
static void
vshSnapshotListFree ( vshSnapshotListPtr snaplist )
{
int i ;
if ( ! snaplist )
return ;
if ( snaplist - > snaps ) {
for ( i = 0 ; i < snaplist - > nsnaps ; i + + ) {
if ( snaplist - > snaps [ i ] . snap )
virDomainSnapshotFree ( snaplist - > snaps [ i ] . snap ) ;
VIR_FREE ( snaplist - > snaps [ i ] . parent ) ;
}
VIR_FREE ( snaplist - > snaps ) ;
}
VIR_FREE ( snaplist ) ;
}
static int
vshSnapSorter ( const void * a , const void * b )
{
const struct vshSnap * sa = a ;
const struct vshSnap * sb = b ;
if ( sa - > snap & & ! sb - > snap )
return - 1 ;
if ( ! sa - > snap )
return sb - > snap ! = NULL ;
/* User visible sort, so we want locale-specific case comparison. */
return strcasecmp ( virDomainSnapshotGetName ( sa - > snap ) ,
virDomainSnapshotGetName ( sb - > snap ) ) ;
}
/* Compute a list of snapshots from DOM. If FROM is provided, the
* list is limited to descendants of the given snapshot . If FLAGS is
* given , the list is filtered . If TREE is specified , then all but
* FROM or the roots will also have parent information . */
2012-06-09 08:25:39 +04:00
static vshSnapshotListPtr
2012-06-15 04:50:03 +04:00
vshSnapshotListCollect ( vshControl * ctl , virDomainPtr dom ,
virDomainSnapshotPtr from ,
unsigned int flags , bool tree )
{
int i ;
char * * names = NULL ;
int count = - 1 ;
bool descendants = false ;
bool roots = false ;
2012-06-09 02:00:43 +04:00
virDomainSnapshotPtr * snaps ;
2012-06-15 04:50:03 +04:00
vshSnapshotListPtr snaplist = vshMalloc ( ctl , sizeof ( * snaplist ) ) ;
vshSnapshotListPtr ret = NULL ;
const char * fromname = NULL ;
int start_index = - 1 ;
int deleted = 0 ;
2012-06-09 02:00:43 +04:00
/* Try the interface available in 0.9.13 and newer. */
if ( ! ctl - > useSnapshotOld ) {
if ( from )
count = virDomainSnapshotListAllChildren ( from , & snaps , flags ) ;
else
count = virDomainListAllSnapshots ( dom , & snaps , flags ) ;
}
if ( count > = 0 ) {
/* When mixing --from and --tree, we also want a copy of from
* in the list , but with no parent for that one entry . */
2012-07-04 14:15:19 +04:00
snaplist - > snaps = vshCalloc ( ctl , count + ( tree & & from ) ,
sizeof ( * snaplist - > snaps ) ) ;
2012-06-09 02:00:43 +04:00
snaplist - > nsnaps = count ;
for ( i = 0 ; i < count ; i + + )
snaplist - > snaps [ i ] . snap = snaps [ i ] ;
VIR_FREE ( snaps ) ;
if ( tree ) {
for ( i = 0 ; i < count ; i + + ) {
if ( vshGetSnapshotParent ( ctl , snaplist - > snaps [ i ] . snap ,
& snaplist - > snaps [ i ] . parent ) < 0 )
goto cleanup ;
}
if ( from ) {
snaps [ snaplist - > nsnaps + + ] = from ;
virDomainSnapshotRef ( from ) ;
}
}
goto success ;
}
2012-06-15 04:50:03 +04:00
2012-06-09 02:31:24 +04:00
/* Assume that if we got this far, then the --no-leaves and
* - - no - metadata flags were not supported . Disable groups that
* have no impact . */
/* XXX should we emulate --no-leaves? */
if ( flags & VIR_DOMAIN_SNAPSHOT_LIST_NO_LEAVES & &
flags & VIR_DOMAIN_SNAPSHOT_LIST_LEAVES )
flags & = ~ ( VIR_DOMAIN_SNAPSHOT_LIST_NO_LEAVES |
VIR_DOMAIN_SNAPSHOT_LIST_LEAVES ) ;
if ( flags & VIR_DOMAIN_SNAPSHOT_LIST_NO_METADATA & &
flags & VIR_DOMAIN_SNAPSHOT_LIST_METADATA )
flags & = ~ ( VIR_DOMAIN_SNAPSHOT_LIST_NO_METADATA |
VIR_DOMAIN_SNAPSHOT_LIST_METADATA ) ;
if ( flags & VIR_DOMAIN_SNAPSHOT_LIST_NO_METADATA ) {
/* We can emulate --no-metadata if --metadata was supported,
* since it was an all - or - none attribute on old servers . */
count = virDomainSnapshotNum ( dom ,
VIR_DOMAIN_SNAPSHOT_LIST_METADATA ) ;
if ( count < 0 )
goto cleanup ;
if ( count > 0 )
return snaplist ;
flags & = ~ VIR_DOMAIN_SNAPSHOT_LIST_NO_METADATA ;
}
2012-06-15 04:50:03 +04:00
/* This uses the interfaces available in 0.8.0-0.9.6
* ( virDomainSnapshotListNames , global list only ) and in
* 0.9 .7 - 0.9 .12 ( addition of virDomainSnapshotListChildrenNames
* for child listing , and new flags ) , as follows , with [ * ] by the
* combinations that need parent info ( either for filtering
* purposes or for the resulting tree listing ) :
* old new
* list global as - is global as - is
* list - - roots * global + filter global + flags
* list - - from * global + filter child as - is
* list - - from - - descendants * global + filter child + flags
* list - - tree * global as - is * global as - is
* list - - tree - - from * global + filter * child + flags
*
* Additionally , when - - tree and - - from are both used , from is
* added to the final list as the only element without a parent .
* Otherwise , - - from does not appear in the final list .
*/
if ( from ) {
fromname = virDomainSnapshotGetName ( from ) ;
if ( ! fromname ) {
vshError ( ctl , " %s " , _ ( " Could not get snapshot name " ) ) ;
goto cleanup ;
}
descendants = ( flags & VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS ) | | tree ;
if ( tree )
flags | = VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS ;
/* Determine if we can use the new child listing API. */
if ( ctl - > useSnapshotOld | |
( ( count = virDomainSnapshotNumChildren ( from , flags ) ) < 0 & &
last_error - > code = = VIR_ERR_NO_SUPPORT ) ) {
/* We can emulate --from. */
/* XXX can we also emulate --leaves? */
virFreeError ( last_error ) ;
last_error = NULL ;
ctl - > useSnapshotOld = true ;
flags & = ~ VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS ;
goto global ;
}
if ( tree & & count > = 0 )
count + + ;
} else {
global :
/* Global listing (including fallback when --from failed with
* child listing ) . */
count = virDomainSnapshotNum ( dom , flags ) ;
/* Fall back to simulation if --roots was unsupported. */
/* XXX can we also emulate --leaves? */
if ( ! from & & count < 0 & & last_error - > code = = VIR_ERR_INVALID_ARG & &
( flags & VIR_DOMAIN_SNAPSHOT_LIST_ROOTS ) ) {
virFreeError ( last_error ) ;
last_error = NULL ;
roots = true ;
flags & = ~ VIR_DOMAIN_SNAPSHOT_LIST_ROOTS ;
count = virDomainSnapshotNum ( dom , flags ) ;
}
}
if ( count < 0 ) {
if ( ! last_error )
vshError ( ctl , _ ( " failed to collect snapshot list " ) ) ;
goto cleanup ;
}
if ( ! count )
goto success ;
names = vshCalloc ( ctl , sizeof ( * names ) , count ) ;
/* Now that we have a count, collect the list. */
if ( from & & ! ctl - > useSnapshotOld ) {
if ( tree ) {
if ( count )
count = virDomainSnapshotListChildrenNames ( from , names + 1 ,
count - 1 , flags ) ;
if ( count > = 0 ) {
count + + ;
names [ 0 ] = vshStrdup ( ctl , fromname ) ;
}
} else {
count = virDomainSnapshotListChildrenNames ( from , names ,
count , flags ) ;
}
} else {
count = virDomainSnapshotListNames ( dom , names , count , flags ) ;
}
if ( count < 0 )
goto cleanup ;
snaplist - > snaps = vshCalloc ( ctl , sizeof ( * snaplist - > snaps ) , count ) ;
snaplist - > nsnaps = count ;
for ( i = 0 ; i < count ; i + + ) {
snaplist - > snaps [ i ] . snap = virDomainSnapshotLookupByName ( dom ,
names [ i ] , 0 ) ;
if ( ! snaplist - > snaps [ i ] . snap )
goto cleanup ;
}
/* Collect parents when needed. With the new API, --tree and
* - - from together put from as the first element without a parent ;
* with the old API we still need to do a post - process filtering
* based on all parent information . */
if ( tree | | ( from & & ctl - > useSnapshotOld ) | | roots ) {
for ( i = ( from & & ! ctl - > useSnapshotOld ) ; i < count ; i + + ) {
if ( from & & ctl - > useSnapshotOld & & STREQ ( names [ i ] , fromname ) ) {
start_index = i ;
if ( tree )
continue ;
}
if ( vshGetSnapshotParent ( ctl , snaplist - > snaps [ i ] . snap ,
& snaplist - > snaps [ i ] . parent ) < 0 )
goto cleanup ;
if ( ( from & & ( ( tree & & ! snaplist - > snaps [ i ] . parent ) | |
( ! descendants & &
STRNEQ_NULLABLE ( fromname ,
snaplist - > snaps [ i ] . parent ) ) ) ) | |
( roots & & snaplist - > snaps [ i ] . parent ) ) {
virDomainSnapshotFree ( snaplist - > snaps [ i ] . snap ) ;
snaplist - > snaps [ i ] . snap = NULL ;
VIR_FREE ( snaplist - > snaps [ i ] . parent ) ;
deleted + + ;
}
}
}
if ( tree )
goto success ;
if ( ctl - > useSnapshotOld & & descendants ) {
bool changed = false ;
bool remaining = false ;
/* Make multiple passes over the list - first pass finds
* direct children and NULLs out all roots and from , remaining
* passes NULL out any undecided entry whose parent is not
* still in list . We mark known descendants by clearing
* snaps [ i ] . parents . Sorry , this is O ( n ^ 3 ) - hope your
* hierarchy isn ' t huge . XXX Is it worth making O ( n ^ 2 log n )
* by using qsort and bsearch ? */
if ( start_index < 0 ) {
vshError ( ctl , _ ( " snapshot %s disappeared from list " ) , fromname ) ;
goto cleanup ;
}
for ( i = 0 ; i < count ; i + + ) {
if ( i = = start_index | | ! snaplist - > snaps [ i ] . parent ) {
VIR_FREE ( names [ i ] ) ;
virDomainSnapshotFree ( snaplist - > snaps [ i ] . snap ) ;
snaplist - > snaps [ i ] . snap = NULL ;
VIR_FREE ( snaplist - > snaps [ i ] . parent ) ;
deleted + + ;
} else if ( STREQ ( snaplist - > snaps [ i ] . parent , fromname ) ) {
VIR_FREE ( snaplist - > snaps [ i ] . parent ) ;
changed = true ;
} else {
remaining = true ;
}
}
if ( ! changed ) {
ret = vshMalloc ( ctl , sizeof ( * snaplist ) ) ;
goto cleanup ;
}
while ( changed & & remaining ) {
changed = remaining = false ;
for ( i = 0 ; i < count ; i + + ) {
bool found_parent = false ;
int j ;
if ( ! names [ i ] | | ! snaplist - > snaps [ i ] . parent )
continue ;
for ( j = 0 ; j < count ; j + + ) {
if ( ! names [ j ] | | i = = j )
continue ;
if ( STREQ ( snaplist - > snaps [ i ] . parent , names [ j ] ) ) {
found_parent = true ;
if ( ! snaplist - > snaps [ j ] . parent )
VIR_FREE ( snaplist - > snaps [ i ] . parent ) ;
else
remaining = true ;
break ;
}
}
if ( ! found_parent ) {
changed = true ;
VIR_FREE ( names [ i ] ) ;
virDomainSnapshotFree ( snaplist - > snaps [ i ] . snap ) ;
snaplist - > snaps [ i ] . snap = NULL ;
VIR_FREE ( snaplist - > snaps [ i ] . parent ) ;
deleted + + ;
}
}
}
}
success :
qsort ( snaplist - > snaps , snaplist - > nsnaps , sizeof ( * snaplist - > snaps ) ,
vshSnapSorter ) ;
snaplist - > nsnaps - = deleted ;
ret = snaplist ;
snaplist = NULL ;
cleanup :
vshSnapshotListFree ( snaplist ) ;
if ( names )
for ( i = 0 ; i < count ; i + + )
VIR_FREE ( names [ i ] ) ;
VIR_FREE ( names ) ;
return ret ;
}
2012-06-09 08:25:39 +04:00
static const char *
vshSnapshotListLookup ( int id , bool parent , void * opaque )
{
vshSnapshotListPtr snaplist = opaque ;
if ( parent )
return snaplist - > snaps [ id ] . parent ;
return virDomainSnapshotGetName ( snaplist - > snaps [ id ] . snap ) ;
}
2010-04-01 00:28:00 +04:00
/*
* " snapshot-list " command
*/
static const vshCmdInfo info_snapshot_list [ ] = {
{ " help " , N_ ( " List snapshots for a domain " ) } ,
{ " desc " , N_ ( " Snapshot List " ) } ,
{ NULL , NULL }
} ;
static const vshCmdOptDef opts_snapshot_list [ ] = {
{ " domain " , VSH_OT_DATA , VSH_OFLAG_REQ , N_ ( " domain name, id or uuid " ) } ,
2011-08-16 23:34:22 +04:00
{ " parent " , VSH_OT_BOOL , 0 , N_ ( " add a column showing parent snapshot " ) } ,
2011-08-16 23:34:22 +04:00
{ " roots " , VSH_OT_BOOL , 0 , N_ ( " list only snapshots without parents " ) } ,
2011-10-01 03:36:00 +04:00
{ " leaves " , VSH_OT_BOOL , 0 , N_ ( " list only snapshots without children " ) } ,
2012-06-09 02:31:24 +04:00
{ " no-leaves " , VSH_OT_BOOL , 0 ,
N_ ( " list only snapshots that are not leaves (with children) " ) } ,
2011-08-16 23:34:22 +04:00
{ " metadata " , VSH_OT_BOOL , 0 ,
N_ ( " list only snapshots that have metadata that would prevent undefine " ) } ,
2012-06-09 02:31:24 +04:00
{ " no-metadata " , VSH_OT_BOOL , 0 ,
N_ ( " list only snapshots that have no metadata managed by libvirt " ) } ,
2011-09-25 03:42:50 +04:00
{ " tree " , VSH_OT_BOOL , 0 , N_ ( " list snapshots in a tree " ) } ,
2011-09-29 21:51:23 +04:00
{ " from " , VSH_OT_DATA , 0 , N_ ( " limit list to children of given snapshot " ) } ,
snapshot: virsh shorthand for operating on current snap
Rather than having to do:
$ virsh snapshot-revert dom $(virsh snapshot-current dom --name)
I thought it would be nice to do:
$ virsh snapshot-revert dom --current
I didn't add 'virsh snapshot-dumpxml --current' since we already have
'virsh snapshot-current' for the same task. snapshot-list accepted
a name but did not require it, and that remains the case, with
--current serving in place of that name. For all other commands,
name used to be required, and can now be replaced by --current;
I intentionally made it so that omitting both --current and a name
is an error (having the absence of a name imply --current seems
just a bit too magic, so --current must be explicit). I also had
to keep snapshot-edit backwards-compatible, as the only command
that already had a --current argument alongside a name, which still
works to both edit a named snapshot and make it current.
* tools/virsh.c (vshLookupSnapshot): New helper function.
(cmdSnapshotEdit, cmdSnapshotList, cmdSnapshotParent)
(cmdSnapshotDelete, cmdDomainSnapshotRevert): Use it, adding an
option where needed.
* tools/virsh.pod (snapshot-delete, snapshot-edit)
(snapshot-list, snapshot-parent, snapshot-revert): Document
use of --current.
(snapshot-dumpxml): Mention alternative.
2011-10-07 01:01:18 +04:00
{ " current " , VSH_OT_BOOL , 0 ,
N_ ( " limit list to children of current snapshot " ) } ,
2011-09-29 21:51:23 +04:00
{ " descendants " , VSH_OT_BOOL , 0 , N_ ( " with --from, list all descendants " ) } ,
2010-04-01 00:28:00 +04:00
{ NULL , 0 , 0 , NULL }
} ;
2011-04-19 02:37:42 +04:00
static bool
2010-04-01 00:28:00 +04:00
cmdSnapshotList ( vshControl * ctl , const vshCmd * cmd )
{
virDomainPtr dom = NULL ;
2011-04-19 02:37:42 +04:00
bool ret = false ;
2011-08-16 23:34:22 +04:00
unsigned int flags = 0 ;
2012-06-09 08:25:39 +04:00
bool show_parent = false ;
2010-04-01 00:28:00 +04:00
int i ;
xmlDocPtr xml = NULL ;
xmlXPathContextPtr ctxt = NULL ;
char * doc = NULL ;
virDomainSnapshotPtr snapshot = NULL ;
char * state = NULL ;
2011-08-16 23:34:22 +04:00
char * parent = NULL ;
2011-05-13 10:31:03 +04:00
long long creation_longlong ;
time_t creation_time_t ;
2010-04-01 00:28:00 +04:00
char timestr [ 100 ] ;
struct tm time_info ;
2011-09-25 03:42:50 +04:00
bool tree = vshCommandOptBool ( cmd , " tree " ) ;
2011-10-01 03:36:00 +04:00
bool leaves = vshCommandOptBool ( cmd , " leaves " ) ;
2012-06-09 02:31:24 +04:00
bool no_leaves = vshCommandOptBool ( cmd , " no-leaves " ) ;
2011-09-29 21:51:23 +04:00
const char * from = NULL ;
virDomainSnapshotPtr start = NULL ;
2012-06-09 08:25:39 +04:00
vshSnapshotListPtr snaplist = NULL ;
2011-09-29 21:51:23 +04:00
snapshot: virsh shorthand for operating on current snap
Rather than having to do:
$ virsh snapshot-revert dom $(virsh snapshot-current dom --name)
I thought it would be nice to do:
$ virsh snapshot-revert dom --current
I didn't add 'virsh snapshot-dumpxml --current' since we already have
'virsh snapshot-current' for the same task. snapshot-list accepted
a name but did not require it, and that remains the case, with
--current serving in place of that name. For all other commands,
name used to be required, and can now be replaced by --current;
I intentionally made it so that omitting both --current and a name
is an error (having the absence of a name imply --current seems
just a bit too magic, so --current must be explicit). I also had
to keep snapshot-edit backwards-compatible, as the only command
that already had a --current argument alongside a name, which still
works to both edit a named snapshot and make it current.
* tools/virsh.c (vshLookupSnapshot): New helper function.
(cmdSnapshotEdit, cmdSnapshotList, cmdSnapshotParent)
(cmdSnapshotDelete, cmdDomainSnapshotRevert): Use it, adding an
option where needed.
* tools/virsh.pod (snapshot-delete, snapshot-edit)
(snapshot-list, snapshot-parent, snapshot-revert): Document
use of --current.
(snapshot-dumpxml): Mention alternative.
2011-10-07 01:01:18 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
goto cleanup ;
dom = vshCommandOptDomain ( ctl , cmd , NULL ) ;
if ( dom = = NULL )
goto cleanup ;
if ( ( vshCommandOptBool ( cmd , " from " ) | |
vshCommandOptBool ( cmd , " current " ) ) & &
vshLookupSnapshot ( ctl , cmd , " from " , true , dom , & start , & from ) < 0 )
2011-09-29 21:51:23 +04:00
goto cleanup ;
2010-04-01 00:28:00 +04:00
2011-08-16 23:34:22 +04:00
if ( vshCommandOptBool ( cmd , " parent " ) ) {
2011-08-16 23:34:22 +04:00
if ( vshCommandOptBool ( cmd , " roots " ) ) {
vshError ( ctl , " %s " ,
2011-10-07 17:53:27 +04:00
_ ( " --parent and --roots are mutually exclusive " ) ) ;
2012-03-28 12:15:49 +04:00
goto cleanup ;
2011-08-16 23:34:22 +04:00
}
2011-09-25 03:42:50 +04:00
if ( tree ) {
vshError ( ctl , " %s " ,
2011-10-07 17:53:27 +04:00
_ ( " --parent and --tree are mutually exclusive " ) ) ;
2012-03-28 12:15:49 +04:00
goto cleanup ;
2011-09-25 03:42:50 +04:00
}
2012-06-09 08:25:39 +04:00
show_parent = true ;
2011-08-16 23:34:22 +04:00
} else if ( vshCommandOptBool ( cmd , " roots " ) ) {
2011-09-25 03:42:50 +04:00
if ( tree ) {
vshError ( ctl , " %s " ,
2011-10-07 17:53:27 +04:00
_ ( " --roots and --tree are mutually exclusive " ) ) ;
2012-03-28 12:15:49 +04:00
goto cleanup ;
2011-09-25 03:42:50 +04:00
}
2011-09-29 21:51:23 +04:00
if ( from ) {
vshError ( ctl , " %s " ,
_ ( " --roots and --from are mutually exclusive " ) ) ;
2012-03-28 12:15:49 +04:00
goto cleanup ;
2011-09-29 21:51:23 +04:00
}
2011-08-16 23:34:22 +04:00
flags | = VIR_DOMAIN_SNAPSHOT_LIST_ROOTS ;
}
2011-10-01 03:36:00 +04:00
if ( leaves ) {
if ( tree ) {
vshError ( ctl , " %s " ,
_ ( " --leaves and --tree are mutually exclusive " ) ) ;
2012-03-28 12:15:49 +04:00
goto cleanup ;
2011-10-01 03:36:00 +04:00
}
flags | = VIR_DOMAIN_SNAPSHOT_LIST_LEAVES ;
}
2012-06-09 02:31:24 +04:00
if ( no_leaves ) {
if ( tree ) {
vshError ( ctl , " %s " ,
_ ( " --no-leaves and --tree are mutually exclusive " ) ) ;
goto cleanup ;
}
flags | = VIR_DOMAIN_SNAPSHOT_LIST_NO_LEAVES ;
}
2011-08-16 23:34:22 +04:00
if ( vshCommandOptBool ( cmd , " metadata " ) ) {
flags | = VIR_DOMAIN_SNAPSHOT_LIST_METADATA ;
2011-08-16 23:34:22 +04:00
}
2012-06-09 02:31:24 +04:00
if ( vshCommandOptBool ( cmd , " no-metadata " ) ) {
flags | = VIR_DOMAIN_SNAPSHOT_LIST_NO_METADATA ;
}
2011-08-16 23:34:22 +04:00
2012-06-09 08:25:39 +04:00
if ( vshCommandOptBool ( cmd , " descendants " ) ) {
if ( ! from ) {
vshError ( ctl , " %s " ,
_ ( " --descendants requires either --from or --current " ) ) ;
goto cleanup ;
2011-09-29 21:51:23 +04:00
}
2012-06-09 08:25:39 +04:00
flags | = VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS ;
2011-08-16 23:34:22 +04:00
}
2012-06-09 08:25:39 +04:00
if ( ( snaplist = vshSnapshotListCollect ( ctl , dom , start , flags ,
tree ) ) = = NULL )
2010-04-01 00:28:00 +04:00
goto cleanup ;
2011-09-25 03:42:50 +04:00
if ( ! tree ) {
2012-06-09 08:25:39 +04:00
if ( show_parent )
2011-09-25 03:42:50 +04:00
vshPrintExtra ( ctl , " %-20s %-25s %-15s %s " ,
_ ( " Name " ) , _ ( " Creation Time " ) , _ ( " State " ) ,
_ ( " Parent " ) ) ;
else
vshPrintExtra ( ctl , " %-20s %-25s %s " ,
_ ( " Name " ) , _ ( " Creation Time " ) , _ ( " State " ) ) ;
2012-04-15 02:35:22 +04:00
vshPrintExtra ( ctl , " \n "
" ------------------------------------------------------------ \n " ) ;
2011-09-25 03:42:50 +04:00
}
2010-04-01 00:28:00 +04:00
2012-06-09 08:25:39 +04:00
if ( ! snaplist - > nsnaps ) {
2011-09-25 03:42:50 +04:00
ret = true ;
goto cleanup ;
}
2010-04-01 00:28:00 +04:00
2011-09-30 01:57:52 +04:00
if ( tree ) {
2012-06-09 08:25:39 +04:00
for ( i = 0 ; i < snaplist - > nsnaps ; i + + ) {
if ( ! snaplist - > snaps [ i ] . parent & &
vshTreePrint ( ctl , vshSnapshotListLookup , snaplist ,
snaplist - > nsnaps , i ) < 0 )
2012-06-09 00:26:06 +04:00
goto cleanup ;
2011-09-25 03:42:50 +04:00
}
ret = true ;
goto cleanup ;
2012-06-09 01:59:21 +04:00
}
2012-06-09 08:25:39 +04:00
for ( i = 0 ; i < snaplist - > nsnaps ; i + + ) {
const char * name ;
2010-04-01 00:28:00 +04:00
2012-06-09 01:59:21 +04:00
/* free up memory from previous iterations of the loop */
VIR_FREE ( parent ) ;
VIR_FREE ( state ) ;
xmlXPathFreeContext ( ctxt ) ;
xmlFreeDoc ( xml ) ;
VIR_FREE ( doc ) ;
2010-04-01 00:28:00 +04:00
2012-06-09 08:25:39 +04:00
snapshot = snaplist - > snaps [ i ] . snap ;
name = virDomainSnapshotGetName ( snapshot ) ;
assert ( name ) ;
2010-04-01 00:28:00 +04:00
2012-06-09 01:59:21 +04:00
doc = virDomainSnapshotGetXMLDesc ( snapshot , 0 ) ;
if ( ! doc )
continue ;
2010-04-01 00:28:00 +04:00
2012-06-09 01:59:21 +04:00
xml = virXMLParseStringCtxt ( doc , _ ( " (domain_snapshot) " ) , & ctxt ) ;
if ( ! xml )
continue ;
2011-08-16 23:34:22 +04:00
2012-06-09 08:25:39 +04:00
if ( show_parent )
2012-06-09 01:59:21 +04:00
parent = virXPathString ( " string(/domainsnapshot/parent/name) " ,
ctxt ) ;
2010-04-01 00:28:00 +04:00
2012-06-09 01:59:21 +04:00
state = virXPathString ( " string(/domainsnapshot/state) " , ctxt ) ;
if ( state = = NULL )
continue ;
if ( virXPathLongLong ( " string(/domainsnapshot/creationTime) " , ctxt ,
& creation_longlong ) < 0 )
continue ;
creation_time_t = creation_longlong ;
if ( creation_time_t ! = creation_longlong ) {
vshError ( ctl , " %s " , _ ( " time_t overflow " ) ) ;
continue ;
2010-04-01 00:28:00 +04:00
}
2012-06-09 01:59:21 +04:00
localtime_r ( & creation_time_t , & time_info ) ;
strftime ( timestr , sizeof ( timestr ) , " %Y-%m-%d %H:%M:%S %z " ,
& time_info ) ;
if ( parent )
vshPrint ( ctl , " %-20s %-25s %-15s %s \n " ,
2012-06-09 08:25:39 +04:00
name , timestr , state , parent ) ;
2012-06-09 01:59:21 +04:00
else
2012-06-09 08:25:39 +04:00
vshPrint ( ctl , " %-20s %-25s %s \n " , name , timestr , state ) ;
2010-04-01 00:28:00 +04:00
}
2011-04-19 02:37:42 +04:00
ret = true ;
2010-04-01 00:28:00 +04:00
cleanup :
/* this frees up memory from the last iteration of the loop */
2012-06-09 08:25:39 +04:00
vshSnapshotListFree ( snaplist ) ;
2011-08-16 23:34:22 +04:00
VIR_FREE ( parent ) ;
2010-04-01 00:28:00 +04:00
VIR_FREE ( state ) ;
2011-09-29 21:51:23 +04:00
if ( start )
virDomainSnapshotFree ( start ) ;
2010-04-01 00:28:00 +04:00
xmlXPathFreeContext ( ctxt ) ;
2011-08-19 00:54:43 +04:00
xmlFreeDoc ( xml ) ;
2010-04-01 00:28:00 +04:00
VIR_FREE ( doc ) ;
if ( dom )
virDomainFree ( dom ) ;
return ret ;
}
/*
* " snapshot-dumpxml " command
*/
static const vshCmdInfo info_snapshot_dumpxml [ ] = {
{ " help " , N_ ( " Dump XML for a domain snapshot " ) } ,
{ " desc " , N_ ( " Snapshot Dump XML " ) } ,
{ NULL , NULL }
} ;
static const vshCmdOptDef opts_snapshot_dumpxml [ ] = {
{ " domain " , VSH_OT_DATA , VSH_OFLAG_REQ , N_ ( " domain name, id or uuid " ) } ,
{ " snapshotname " , VSH_OT_DATA , VSH_OFLAG_REQ , N_ ( " snapshot name " ) } ,
2011-08-16 23:34:22 +04:00
{ " security-info " , VSH_OT_BOOL , 0 ,
N_ ( " include security sensitive information in XML dump " ) } ,
2010-04-01 00:28:00 +04:00
{ NULL , 0 , 0 , NULL }
} ;
2011-04-19 02:37:42 +04:00
static bool
2010-04-01 00:28:00 +04:00
cmdSnapshotDumpXML ( vshControl * ctl , const vshCmd * cmd )
{
virDomainPtr dom = NULL ;
2011-04-19 02:37:42 +04:00
bool ret = false ;
2011-03-08 19:29:31 +03:00
const char * name = NULL ;
2010-04-01 00:28:00 +04:00
virDomainSnapshotPtr snapshot = NULL ;
char * xml = NULL ;
2011-08-16 23:34:22 +04:00
unsigned int flags = 0 ;
if ( vshCommandOptBool ( cmd , " security-info " ) )
flags | = VIR_DOMAIN_XML_SECURE ;
2010-04-01 00:28:00 +04:00
2010-06-17 18:47:06 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
2010-04-01 00:28:00 +04:00
goto cleanup ;
dom = vshCommandOptDomain ( ctl , cmd , NULL ) ;
if ( dom = = NULL )
goto cleanup ;
2011-03-08 19:29:31 +03:00
if ( vshCommandOptString ( cmd , " snapshotname " , & name ) < = 0 )
2010-04-01 00:28:00 +04:00
goto cleanup ;
snapshot = virDomainSnapshotLookupByName ( dom , name , 0 ) ;
if ( snapshot = = NULL )
goto cleanup ;
2011-08-16 23:34:22 +04:00
xml = virDomainSnapshotGetXMLDesc ( snapshot , flags ) ;
2010-04-01 00:28:00 +04:00
if ( ! xml )
goto cleanup ;
2010-06-16 09:25:05 +04:00
vshPrint ( ctl , " %s " , xml ) ;
2010-04-01 00:28:00 +04:00
2011-04-19 02:37:42 +04:00
ret = true ;
2010-04-01 00:28:00 +04:00
cleanup :
VIR_FREE ( xml ) ;
if ( snapshot )
virDomainSnapshotFree ( snapshot ) ;
if ( dom )
virDomainFree ( dom ) ;
return ret ;
}
2011-08-11 03:18:55 +04:00
/*
* " snapshot-parent " command
*/
static const vshCmdInfo info_snapshot_parent [ ] = {
2011-08-17 02:54:14 +04:00
{ " help " , N_ ( " Get the name of the parent of a snapshot " ) } ,
2011-08-11 03:18:55 +04:00
{ " desc " , N_ ( " Extract the snapshot's parent, if any " ) } ,
{ NULL , NULL }
} ;
static const vshCmdOptDef opts_snapshot_parent [ ] = {
{ " domain " , VSH_OT_DATA , VSH_OFLAG_REQ , N_ ( " domain name, id or uuid " ) } ,
snapshot: virsh shorthand for operating on current snap
Rather than having to do:
$ virsh snapshot-revert dom $(virsh snapshot-current dom --name)
I thought it would be nice to do:
$ virsh snapshot-revert dom --current
I didn't add 'virsh snapshot-dumpxml --current' since we already have
'virsh snapshot-current' for the same task. snapshot-list accepted
a name but did not require it, and that remains the case, with
--current serving in place of that name. For all other commands,
name used to be required, and can now be replaced by --current;
I intentionally made it so that omitting both --current and a name
is an error (having the absence of a name imply --current seems
just a bit too magic, so --current must be explicit). I also had
to keep snapshot-edit backwards-compatible, as the only command
that already had a --current argument alongside a name, which still
works to both edit a named snapshot and make it current.
* tools/virsh.c (vshLookupSnapshot): New helper function.
(cmdSnapshotEdit, cmdSnapshotList, cmdSnapshotParent)
(cmdSnapshotDelete, cmdDomainSnapshotRevert): Use it, adding an
option where needed.
* tools/virsh.pod (snapshot-delete, snapshot-edit)
(snapshot-list, snapshot-parent, snapshot-revert): Document
use of --current.
(snapshot-dumpxml): Mention alternative.
2011-10-07 01:01:18 +04:00
{ " snapshotname " , VSH_OT_DATA , 0 , N_ ( " find parent of snapshot name " ) } ,
{ " current " , VSH_OT_BOOL , 0 , N_ ( " find parent of current snapshot " ) } ,
2011-08-11 03:18:55 +04:00
{ NULL , 0 , 0 , NULL }
} ;
static bool
cmdSnapshotParent ( vshControl * ctl , const vshCmd * cmd )
{
virDomainPtr dom = NULL ;
bool ret = false ;
const char * name = NULL ;
virDomainSnapshotPtr snapshot = NULL ;
char * parent = NULL ;
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
goto cleanup ;
dom = vshCommandOptDomain ( ctl , cmd , NULL ) ;
if ( dom = = NULL )
goto cleanup ;
snapshot: virsh shorthand for operating on current snap
Rather than having to do:
$ virsh snapshot-revert dom $(virsh snapshot-current dom --name)
I thought it would be nice to do:
$ virsh snapshot-revert dom --current
I didn't add 'virsh snapshot-dumpxml --current' since we already have
'virsh snapshot-current' for the same task. snapshot-list accepted
a name but did not require it, and that remains the case, with
--current serving in place of that name. For all other commands,
name used to be required, and can now be replaced by --current;
I intentionally made it so that omitting both --current and a name
is an error (having the absence of a name imply --current seems
just a bit too magic, so --current must be explicit). I also had
to keep snapshot-edit backwards-compatible, as the only command
that already had a --current argument alongside a name, which still
works to both edit a named snapshot and make it current.
* tools/virsh.c (vshLookupSnapshot): New helper function.
(cmdSnapshotEdit, cmdSnapshotList, cmdSnapshotParent)
(cmdSnapshotDelete, cmdDomainSnapshotRevert): Use it, adding an
option where needed.
* tools/virsh.pod (snapshot-delete, snapshot-edit)
(snapshot-list, snapshot-parent, snapshot-revert): Document
use of --current.
(snapshot-dumpxml): Mention alternative.
2011-10-07 01:01:18 +04:00
if ( vshLookupSnapshot ( ctl , cmd , " snapshotname " , true , dom ,
& snapshot , & name ) < 0 )
2011-08-11 03:18:55 +04:00
goto cleanup ;
2011-09-30 19:45:43 +04:00
if ( vshGetSnapshotParent ( ctl , snapshot , & parent ) < 0 )
2011-08-11 03:18:55 +04:00
goto cleanup ;
2011-09-30 19:45:43 +04:00
if ( ! parent ) {
vshError ( ctl , _ ( " snapshot '%s' has no parent " ) , name ) ;
goto cleanup ;
}
2011-08-11 03:18:55 +04:00
vshPrint ( ctl , " %s " , parent ) ;
ret = true ;
cleanup :
VIR_FREE ( parent ) ;
if ( snapshot )
virDomainSnapshotFree ( snapshot ) ;
if ( dom )
virDomainFree ( dom ) ;
return ret ;
}
2010-04-01 00:28:00 +04:00
/*
2010-04-12 17:36:13 +04:00
* " snapshot-revert " command
2010-04-01 00:28:00 +04:00
*/
2010-04-12 17:36:13 +04:00
static const vshCmdInfo info_snapshot_revert [ ] = {
2010-04-01 00:28:00 +04:00
{ " help " , N_ ( " Revert a domain to a snapshot " ) } ,
{ " desc " , N_ ( " Revert domain to snapshot " ) } ,
{ NULL , NULL }
} ;
2010-04-12 17:36:13 +04:00
static const vshCmdOptDef opts_snapshot_revert [ ] = {
2010-04-01 00:28:00 +04:00
{ " domain " , VSH_OT_DATA , VSH_OFLAG_REQ , N_ ( " domain name, id or uuid " ) } ,
snapshot: virsh shorthand for operating on current snap
Rather than having to do:
$ virsh snapshot-revert dom $(virsh snapshot-current dom --name)
I thought it would be nice to do:
$ virsh snapshot-revert dom --current
I didn't add 'virsh snapshot-dumpxml --current' since we already have
'virsh snapshot-current' for the same task. snapshot-list accepted
a name but did not require it, and that remains the case, with
--current serving in place of that name. For all other commands,
name used to be required, and can now be replaced by --current;
I intentionally made it so that omitting both --current and a name
is an error (having the absence of a name imply --current seems
just a bit too magic, so --current must be explicit). I also had
to keep snapshot-edit backwards-compatible, as the only command
that already had a --current argument alongside a name, which still
works to both edit a named snapshot and make it current.
* tools/virsh.c (vshLookupSnapshot): New helper function.
(cmdSnapshotEdit, cmdSnapshotList, cmdSnapshotParent)
(cmdSnapshotDelete, cmdDomainSnapshotRevert): Use it, adding an
option where needed.
* tools/virsh.pod (snapshot-delete, snapshot-edit)
(snapshot-list, snapshot-parent, snapshot-revert): Document
use of --current.
(snapshot-dumpxml): Mention alternative.
2011-10-07 01:01:18 +04:00
{ " snapshotname " , VSH_OT_DATA , 0 , N_ ( " snapshot name " ) } ,
{ " current " , VSH_OT_BOOL , 0 , N_ ( " revert to current snapshot " ) } ,
2011-08-27 18:16:04 +04:00
{ " running " , VSH_OT_BOOL , 0 , N_ ( " after reverting, change state to running " ) } ,
{ " paused " , VSH_OT_BOOL , 0 , N_ ( " after reverting, change state to paused " ) } ,
2011-09-30 03:52:06 +04:00
{ " force " , VSH_OT_BOOL , 0 , N_ ( " try harder on risky reverts " ) } ,
2010-04-01 00:28:00 +04:00
{ NULL , 0 , 0 , NULL }
} ;
2011-04-19 02:37:42 +04:00
static bool
2010-04-12 17:36:13 +04:00
cmdDomainSnapshotRevert ( vshControl * ctl , const vshCmd * cmd )
2010-04-01 00:28:00 +04:00
{
virDomainPtr dom = NULL ;
2011-04-19 02:37:42 +04:00
bool ret = false ;
2011-03-08 19:29:31 +03:00
const char * name = NULL ;
2010-04-01 00:28:00 +04:00
virDomainSnapshotPtr snapshot = NULL ;
2011-08-27 18:16:04 +04:00
unsigned int flags = 0 ;
2011-09-30 03:52:06 +04:00
bool force = false ;
int result ;
2011-08-27 18:16:04 +04:00
if ( vshCommandOptBool ( cmd , " running " ) )
flags | = VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING ;
if ( vshCommandOptBool ( cmd , " paused " ) )
flags | = VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED ;
2011-09-30 03:52:06 +04:00
/* We want virsh snapshot-revert --force to work even when talking
* to older servers that did the unsafe revert by default but
* reject the flag , so we probe without the flag , and only use it
* when the error says it will make a difference . */
if ( vshCommandOptBool ( cmd , " force " ) )
force = true ;
2010-04-01 00:28:00 +04:00
2010-06-17 18:47:06 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
2010-04-01 00:28:00 +04:00
goto cleanup ;
dom = vshCommandOptDomain ( ctl , cmd , NULL ) ;
if ( dom = = NULL )
goto cleanup ;
snapshot: virsh shorthand for operating on current snap
Rather than having to do:
$ virsh snapshot-revert dom $(virsh snapshot-current dom --name)
I thought it would be nice to do:
$ virsh snapshot-revert dom --current
I didn't add 'virsh snapshot-dumpxml --current' since we already have
'virsh snapshot-current' for the same task. snapshot-list accepted
a name but did not require it, and that remains the case, with
--current serving in place of that name. For all other commands,
name used to be required, and can now be replaced by --current;
I intentionally made it so that omitting both --current and a name
is an error (having the absence of a name imply --current seems
just a bit too magic, so --current must be explicit). I also had
to keep snapshot-edit backwards-compatible, as the only command
that already had a --current argument alongside a name, which still
works to both edit a named snapshot and make it current.
* tools/virsh.c (vshLookupSnapshot): New helper function.
(cmdSnapshotEdit, cmdSnapshotList, cmdSnapshotParent)
(cmdSnapshotDelete, cmdDomainSnapshotRevert): Use it, adding an
option where needed.
* tools/virsh.pod (snapshot-delete, snapshot-edit)
(snapshot-list, snapshot-parent, snapshot-revert): Document
use of --current.
(snapshot-dumpxml): Mention alternative.
2011-10-07 01:01:18 +04:00
if ( vshLookupSnapshot ( ctl , cmd , " snapshotname " , true , dom ,
& snapshot , & name ) < 0 )
2010-04-01 00:28:00 +04:00
goto cleanup ;
2011-09-30 03:52:06 +04:00
result = virDomainRevertToSnapshot ( snapshot , flags ) ;
if ( result < 0 & & force & &
last_error - > code = = VIR_ERR_SNAPSHOT_REVERT_RISKY ) {
flags | = VIR_DOMAIN_SNAPSHOT_REVERT_FORCE ;
virFreeError ( last_error ) ;
last_error = NULL ;
result = virDomainRevertToSnapshot ( snapshot , flags ) ;
}
if ( result < 0 )
2010-04-01 00:28:00 +04:00
goto cleanup ;
2011-04-19 02:37:42 +04:00
ret = true ;
2010-04-01 00:28:00 +04:00
cleanup :
if ( snapshot )
virDomainSnapshotFree ( snapshot ) ;
if ( dom )
virDomainFree ( dom ) ;
return ret ;
}
/*
* " snapshot-delete " command
*/
static const vshCmdInfo info_snapshot_delete [ ] = {
{ " help " , N_ ( " Delete a domain snapshot " ) } ,
{ " desc " , N_ ( " Snapshot Delete " ) } ,
{ NULL , NULL }
} ;
static const vshCmdOptDef opts_snapshot_delete [ ] = {
{ " domain " , VSH_OT_DATA , VSH_OFLAG_REQ , N_ ( " domain name, id or uuid " ) } ,
snapshot: virsh shorthand for operating on current snap
Rather than having to do:
$ virsh snapshot-revert dom $(virsh snapshot-current dom --name)
I thought it would be nice to do:
$ virsh snapshot-revert dom --current
I didn't add 'virsh snapshot-dumpxml --current' since we already have
'virsh snapshot-current' for the same task. snapshot-list accepted
a name but did not require it, and that remains the case, with
--current serving in place of that name. For all other commands,
name used to be required, and can now be replaced by --current;
I intentionally made it so that omitting both --current and a name
is an error (having the absence of a name imply --current seems
just a bit too magic, so --current must be explicit). I also had
to keep snapshot-edit backwards-compatible, as the only command
that already had a --current argument alongside a name, which still
works to both edit a named snapshot and make it current.
* tools/virsh.c (vshLookupSnapshot): New helper function.
(cmdSnapshotEdit, cmdSnapshotList, cmdSnapshotParent)
(cmdSnapshotDelete, cmdDomainSnapshotRevert): Use it, adding an
option where needed.
* tools/virsh.pod (snapshot-delete, snapshot-edit)
(snapshot-list, snapshot-parent, snapshot-revert): Document
use of --current.
(snapshot-dumpxml): Mention alternative.
2011-10-07 01:01:18 +04:00
{ " snapshotname " , VSH_OT_DATA , 0 , N_ ( " snapshot name " ) } ,
{ " current " , VSH_OT_BOOL , 0 , N_ ( " delete current snapshot " ) } ,
2010-04-01 00:28:00 +04:00
{ " children " , VSH_OT_BOOL , 0 , N_ ( " delete snapshot and all children " ) } ,
2011-08-17 02:48:04 +04:00
{ " children-only " , VSH_OT_BOOL , 0 , N_ ( " delete children but not snapshot " ) } ,
{ " metadata " , VSH_OT_BOOL , 0 ,
N_ ( " delete only libvirt metadata, leaving snapshot contents behind " ) } ,
2010-04-01 00:28:00 +04:00
{ NULL , 0 , 0 , NULL }
} ;
2011-04-19 02:37:42 +04:00
static bool
2010-04-01 00:28:00 +04:00
cmdSnapshotDelete ( vshControl * ctl , const vshCmd * cmd )
{
virDomainPtr dom = NULL ;
2011-04-19 02:37:42 +04:00
bool ret = false ;
2011-03-08 19:29:31 +03:00
const char * name = NULL ;
2010-04-01 00:28:00 +04:00
virDomainSnapshotPtr snapshot = NULL ;
unsigned int flags = 0 ;
2010-06-17 18:47:06 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
2010-04-01 00:28:00 +04:00
goto cleanup ;
dom = vshCommandOptDomain ( ctl , cmd , NULL ) ;
if ( dom = = NULL )
goto cleanup ;
snapshot: virsh shorthand for operating on current snap
Rather than having to do:
$ virsh snapshot-revert dom $(virsh snapshot-current dom --name)
I thought it would be nice to do:
$ virsh snapshot-revert dom --current
I didn't add 'virsh snapshot-dumpxml --current' since we already have
'virsh snapshot-current' for the same task. snapshot-list accepted
a name but did not require it, and that remains the case, with
--current serving in place of that name. For all other commands,
name used to be required, and can now be replaced by --current;
I intentionally made it so that omitting both --current and a name
is an error (having the absence of a name imply --current seems
just a bit too magic, so --current must be explicit). I also had
to keep snapshot-edit backwards-compatible, as the only command
that already had a --current argument alongside a name, which still
works to both edit a named snapshot and make it current.
* tools/virsh.c (vshLookupSnapshot): New helper function.
(cmdSnapshotEdit, cmdSnapshotList, cmdSnapshotParent)
(cmdSnapshotDelete, cmdDomainSnapshotRevert): Use it, adding an
option where needed.
* tools/virsh.pod (snapshot-delete, snapshot-edit)
(snapshot-list, snapshot-parent, snapshot-revert): Document
use of --current.
(snapshot-dumpxml): Mention alternative.
2011-10-07 01:01:18 +04:00
if ( vshLookupSnapshot ( ctl , cmd , " snapshotname " , true , dom ,
& snapshot , & name ) < 0 )
2010-04-01 00:28:00 +04:00
goto cleanup ;
if ( vshCommandOptBool ( cmd , " children " ) )
flags | = VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN ;
2011-08-17 02:48:04 +04:00
if ( vshCommandOptBool ( cmd , " children-only " ) )
flags | = VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY ;
if ( vshCommandOptBool ( cmd , " metadata " ) )
flags | = VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY ;
2010-04-01 00:28:00 +04:00
2011-08-17 02:48:04 +04:00
/* XXX If we wanted, we could emulate DELETE_CHILDREN_ONLY even on
* older servers that reject the flag , by manually computing the
* list of descendants . But that ' s a lot of code to maintain . */
2011-07-13 12:36:32 +04:00
if ( virDomainSnapshotDelete ( snapshot , flags ) = = 0 ) {
2011-08-17 02:48:04 +04:00
if ( flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY )
vshPrint ( ctl , _ ( " Domain snapshot %s children deleted \n " ) , name ) ;
else
vshPrint ( ctl , _ ( " Domain snapshot %s deleted \n " ) , name ) ;
2011-07-13 12:36:32 +04:00
} else {
vshError ( ctl , _ ( " Failed to delete snapshot %s " ) , name ) ;
2010-04-01 00:28:00 +04:00
goto cleanup ;
2011-07-13 12:36:32 +04:00
}
2010-04-01 00:28:00 +04:00
2011-04-19 02:37:42 +04:00
ret = true ;
2010-04-01 00:28:00 +04:00
cleanup :
if ( snapshot )
virDomainSnapshotFree ( snapshot ) ;
if ( dom )
virDomainFree ( dom ) ;
return ret ;
}
2010-04-13 22:08:59 +04:00
/*
* " qemu-monitor-command " command
*/
static const vshCmdInfo info_qemu_monitor_command [ ] = {
2011-05-05 20:32:07 +04:00
{ " help " , N_ ( " QEMU Monitor Command " ) } ,
{ " desc " , N_ ( " QEMU Monitor Command " ) } ,
2010-04-13 22:08:59 +04:00
{ NULL , NULL }
} ;
static const vshCmdOptDef opts_qemu_monitor_command [ ] = {
{ " domain " , VSH_OT_DATA , VSH_OFLAG_REQ , N_ ( " domain name, id or uuid " ) } ,
2011-02-02 18:37:10 +03:00
{ " hmp " , VSH_OT_BOOL , 0 , N_ ( " command is in human monitor protocol " ) } ,
2011-08-06 03:48:13 +04:00
{ " cmd " , VSH_OT_ARGV , VSH_OFLAG_REQ , N_ ( " command " ) } ,
2010-04-13 22:08:59 +04:00
{ NULL , 0 , 0 , NULL }
} ;
2011-04-19 02:37:42 +04:00
static bool
2010-04-13 22:08:59 +04:00
cmdQemuMonitorCommand ( vshControl * ctl , const vshCmd * cmd )
{
virDomainPtr dom = NULL ;
2011-04-19 02:37:42 +04:00
bool ret = false ;
2011-08-06 03:48:13 +04:00
char * monitor_cmd = NULL ;
2010-04-13 22:08:59 +04:00
char * result = NULL ;
2011-02-02 18:37:10 +03:00
unsigned int flags = 0 ;
2011-08-06 03:48:13 +04:00
const vshCmdOpt * opt = NULL ;
virBuffer buf = VIR_BUFFER_INITIALIZER ;
bool pad = false ;
2010-04-13 22:08:59 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
goto cleanup ;
dom = vshCommandOptDomain ( ctl , cmd , NULL ) ;
if ( dom = = NULL )
goto cleanup ;
2011-08-06 03:48:13 +04:00
while ( ( opt = vshCommandOptArgv ( cmd , opt ) ) ) {
if ( pad )
virBufferAddChar ( & buf , ' ' ) ;
pad = true ;
virBufferAdd ( & buf , opt - > data , - 1 ) ;
}
if ( virBufferError ( & buf ) ) {
vshPrint ( ctl , " %s " , _ ( " Failed to collect command " ) ) ;
2010-04-13 22:08:59 +04:00
goto cleanup ;
}
2011-08-06 03:48:13 +04:00
monitor_cmd = virBufferContentAndReset ( & buf ) ;
2010-04-13 22:08:59 +04:00
2011-02-02 18:37:10 +03:00
if ( vshCommandOptBool ( cmd , " hmp " ) )
flags | = VIR_DOMAIN_QEMU_MONITOR_COMMAND_HMP ;
if ( virDomainQemuMonitorCommand ( dom , monitor_cmd , & result , flags ) < 0 )
2010-04-13 22:08:59 +04:00
goto cleanup ;
printf ( " %s \n " , result ) ;
2011-04-19 02:37:42 +04:00
ret = true ;
2010-04-13 22:08:59 +04:00
cleanup :
VIR_FREE ( result ) ;
2011-08-06 03:48:13 +04:00
VIR_FREE ( monitor_cmd ) ;
2010-04-13 22:08:59 +04:00
if ( dom )
virDomainFree ( dom ) ;
return ret ;
}
2011-05-05 20:32:07 +04:00
/*
* " qemu-attach " command
*/
static const vshCmdInfo info_qemu_attach [ ] = {
{ " help " , N_ ( " QEMU Attach " ) } ,
{ " desc " , N_ ( " QEMU Attach " ) } ,
{ NULL , NULL }
} ;
static const vshCmdOptDef opts_qemu_attach [ ] = {
{ " pid " , VSH_OT_DATA , VSH_OFLAG_REQ , N_ ( " pid " ) } ,
{ NULL , 0 , 0 , NULL }
} ;
static bool
cmdQemuAttach ( vshControl * ctl , const vshCmd * cmd )
{
virDomainPtr dom = NULL ;
bool ret = false ;
unsigned int flags = 0 ;
build: use correct type for pid and similar types
No thanks to 64-bit windows, with 64-bit pid_t, we have to avoid
constructs like 'int pid'. Our API in libvirt-qemu cannot be
changed without breaking ABI; but then again, libvirt-qemu can
only be used on systems that support UNIX sockets, which rules
out Windows (even if qemu could be compiled there) - so for all
points on the call chain that interact with this API decision,
we require a different variable name to make it clear that we
audited the use for safety.
Adding a syntax-check rule only solves half the battle; anywhere
that uses printf on a pid_t still needs to be converted, but that
will be a separate patch.
* cfg.mk (sc_correct_id_types): New syntax check.
* src/libvirt-qemu.c (virDomainQemuAttach): Document why we didn't
use pid_t for pid, and validate for overflow.
* include/libvirt/libvirt-qemu.h (virDomainQemuAttach): Tweak name
for syntax check.
* src/vmware/vmware_conf.c (vmwareExtractPid): Likewise.
* src/driver.h (virDrvDomainQemuAttach): Likewise.
* tools/virsh.c (cmdQemuAttach): Likewise.
* src/remote/qemu_protocol.x (qemu_domain_attach_args): Likewise.
* src/qemu_protocol-structs (qemu_domain_attach_args): Likewise.
* src/util/cgroup.c (virCgroupPidCode, virCgroupKillInternal):
Likewise.
* src/qemu/qemu_command.c(qemuParseProcFileStrings): Likewise.
(qemuParseCommandLinePid): Use pid_t for pid.
* daemon/libvirtd.c (daemonForkIntoBackground): Likewise.
* src/conf/domain_conf.h (_virDomainObj): Likewise.
* src/probes.d (rpc_socket_new): Likewise.
* src/qemu/qemu_command.h (qemuParseCommandLinePid): Likewise.
* src/qemu/qemu_driver.c (qemudGetProcessInfo, qemuDomainAttach):
Likewise.
* src/qemu/qemu_process.c (qemuProcessAttach): Likewise.
* src/qemu/qemu_process.h (qemuProcessAttach): Likewise.
* src/uml/uml_driver.c (umlGetProcessInfo): Likewise.
* src/util/virnetdev.h (virNetDevSetNamespace): Likewise.
* src/util/virnetdev.c (virNetDevSetNamespace): Likewise.
* tests/testutils.c (virtTestCaptureProgramOutput): Likewise.
* src/conf/storage_conf.h (_virStoragePerms): Use mode_t, uid_t,
and gid_t rather than int.
* src/security/security_dac.c (virSecurityDACSetOwnership): Likewise.
* src/conf/storage_conf.c (virStorageDefParsePerms): Avoid
compiler warning.
2012-02-11 03:08:11 +04:00
unsigned int pid_value ; /* API uses unsigned int, not pid_t */
2011-05-05 20:32:07 +04:00
if ( ! vshConnectionUsability ( ctl , ctl - > conn ) )
goto cleanup ;
build: use correct type for pid and similar types
No thanks to 64-bit windows, with 64-bit pid_t, we have to avoid
constructs like 'int pid'. Our API in libvirt-qemu cannot be
changed without breaking ABI; but then again, libvirt-qemu can
only be used on systems that support UNIX sockets, which rules
out Windows (even if qemu could be compiled there) - so for all
points on the call chain that interact with this API decision,
we require a different variable name to make it clear that we
audited the use for safety.
Adding a syntax-check rule only solves half the battle; anywhere
that uses printf on a pid_t still needs to be converted, but that
will be a separate patch.
* cfg.mk (sc_correct_id_types): New syntax check.
* src/libvirt-qemu.c (virDomainQemuAttach): Document why we didn't
use pid_t for pid, and validate for overflow.
* include/libvirt/libvirt-qemu.h (virDomainQemuAttach): Tweak name
for syntax check.
* src/vmware/vmware_conf.c (vmwareExtractPid): Likewise.
* src/driver.h (virDrvDomainQemuAttach): Likewise.
* tools/virsh.c (cmdQemuAttach): Likewise.
* src/remote/qemu_protocol.x (qemu_domain_attach_args): Likewise.
* src/qemu_protocol-structs (qemu_domain_attach_args): Likewise.
* src/util/cgroup.c (virCgroupPidCode, virCgroupKillInternal):
Likewise.
* src/qemu/qemu_command.c(qemuParseProcFileStrings): Likewise.
(qemuParseCommandLinePid): Use pid_t for pid.
* daemon/libvirtd.c (daemonForkIntoBackground): Likewise.
* src/conf/domain_conf.h (_virDomainObj): Likewise.
* src/probes.d (rpc_socket_new): Likewise.
* src/qemu/qemu_command.h (qemuParseCommandLinePid): Likewise.
* src/qemu/qemu_driver.c (qemudGetProcessInfo, qemuDomainAttach):
Likewise.
* src/qemu/qemu_process.c (qemuProcessAttach): Likewise.
* src/qemu/qemu_process.h (qemuProcessAttach): Likewise.
* src/uml/uml_driver.c (umlGetProcessInfo): Likewise.
* src/util/virnetdev.h (virNetDevSetNamespace): Likewise.
* src/util/virnetdev.c (virNetDevSetNamespace): Likewise.
* tests/testutils.c (virtTestCaptureProgramOutput): Likewise.
* src/conf/storage_conf.h (_virStoragePerms): Use mode_t, uid_t,
and gid_t rather than int.
* src/security/security_dac.c (virSecurityDACSetOwnership): Likewise.
* src/conf/storage_conf.c (virStorageDefParsePerms): Avoid
compiler warning.
2012-02-11 03:08:11 +04:00
if ( vshCommandOptUInt ( cmd , " pid " , & pid_value ) < = 0 ) {
2011-05-05 20:32:07 +04:00
vshError ( ctl , " %s " , _ ( " missing pid value " ) ) ;
goto cleanup ;
}
build: use correct type for pid and similar types
No thanks to 64-bit windows, with 64-bit pid_t, we have to avoid
constructs like 'int pid'. Our API in libvirt-qemu cannot be
changed without breaking ABI; but then again, libvirt-qemu can
only be used on systems that support UNIX sockets, which rules
out Windows (even if qemu could be compiled there) - so for all
points on the call chain that interact with this API decision,
we require a different variable name to make it clear that we
audited the use for safety.
Adding a syntax-check rule only solves half the battle; anywhere
that uses printf on a pid_t still needs to be converted, but that
will be a separate patch.
* cfg.mk (sc_correct_id_types): New syntax check.
* src/libvirt-qemu.c (virDomainQemuAttach): Document why we didn't
use pid_t for pid, and validate for overflow.
* include/libvirt/libvirt-qemu.h (virDomainQemuAttach): Tweak name
for syntax check.
* src/vmware/vmware_conf.c (vmwareExtractPid): Likewise.
* src/driver.h (virDrvDomainQemuAttach): Likewise.
* tools/virsh.c (cmdQemuAttach): Likewise.
* src/remote/qemu_protocol.x (qemu_domain_attach_args): Likewise.
* src/qemu_protocol-structs (qemu_domain_attach_args): Likewise.
* src/util/cgroup.c (virCgroupPidCode, virCgroupKillInternal):
Likewise.
* src/qemu/qemu_command.c(qemuParseProcFileStrings): Likewise.
(qemuParseCommandLinePid): Use pid_t for pid.
* daemon/libvirtd.c (daemonForkIntoBackground): Likewise.
* src/conf/domain_conf.h (_virDomainObj): Likewise.
* src/probes.d (rpc_socket_new): Likewise.
* src/qemu/qemu_command.h (qemuParseCommandLinePid): Likewise.
* src/qemu/qemu_driver.c (qemudGetProcessInfo, qemuDomainAttach):
Likewise.
* src/qemu/qemu_process.c (qemuProcessAttach): Likewise.
* src/qemu/qemu_process.h (qemuProcessAttach): Likewise.
* src/uml/uml_driver.c (umlGetProcessInfo): Likewise.
* src/util/virnetdev.h (virNetDevSetNamespace): Likewise.
* src/util/virnetdev.c (virNetDevSetNamespace): Likewise.
* tests/testutils.c (virtTestCaptureProgramOutput): Likewise.
* src/conf/storage_conf.h (_virStoragePerms): Use mode_t, uid_t,
and gid_t rather than int.
* src/security/security_dac.c (virSecurityDACSetOwnership): Likewise.
* src/conf/storage_conf.c (virStorageDefParsePerms): Avoid
compiler warning.
2012-02-11 03:08:11 +04:00
if ( ! ( dom = virDomainQemuAttach ( ctl - > conn , pid_value , flags ) ) )
2011-05-05 20:32:07 +04:00
goto cleanup ;
if ( dom ! = NULL ) {
vshPrint ( ctl , _ ( " Domain %s attached to pid %u \n " ) ,
build: use correct type for pid and similar types
No thanks to 64-bit windows, with 64-bit pid_t, we have to avoid
constructs like 'int pid'. Our API in libvirt-qemu cannot be
changed without breaking ABI; but then again, libvirt-qemu can
only be used on systems that support UNIX sockets, which rules
out Windows (even if qemu could be compiled there) - so for all
points on the call chain that interact with this API decision,
we require a different variable name to make it clear that we
audited the use for safety.
Adding a syntax-check rule only solves half the battle; anywhere
that uses printf on a pid_t still needs to be converted, but that
will be a separate patch.
* cfg.mk (sc_correct_id_types): New syntax check.
* src/libvirt-qemu.c (virDomainQemuAttach): Document why we didn't
use pid_t for pid, and validate for overflow.
* include/libvirt/libvirt-qemu.h (virDomainQemuAttach): Tweak name
for syntax check.
* src/vmware/vmware_conf.c (vmwareExtractPid): Likewise.
* src/driver.h (virDrvDomainQemuAttach): Likewise.
* tools/virsh.c (cmdQemuAttach): Likewise.
* src/remote/qemu_protocol.x (qemu_domain_attach_args): Likewise.
* src/qemu_protocol-structs (qemu_domain_attach_args): Likewise.
* src/util/cgroup.c (virCgroupPidCode, virCgroupKillInternal):
Likewise.
* src/qemu/qemu_command.c(qemuParseProcFileStrings): Likewise.
(qemuParseCommandLinePid): Use pid_t for pid.
* daemon/libvirtd.c (daemonForkIntoBackground): Likewise.
* src/conf/domain_conf.h (_virDomainObj): Likewise.
* src/probes.d (rpc_socket_new): Likewise.
* src/qemu/qemu_command.h (qemuParseCommandLinePid): Likewise.
* src/qemu/qemu_driver.c (qemudGetProcessInfo, qemuDomainAttach):
Likewise.
* src/qemu/qemu_process.c (qemuProcessAttach): Likewise.
* src/qemu/qemu_process.h (qemuProcessAttach): Likewise.
* src/uml/uml_driver.c (umlGetProcessInfo): Likewise.
* src/util/virnetdev.h (virNetDevSetNamespace): Likewise.
* src/util/virnetdev.c (virNetDevSetNamespace): Likewise.
* tests/testutils.c (virtTestCaptureProgramOutput): Likewise.
* src/conf/storage_conf.h (_virStoragePerms): Use mode_t, uid_t,
and gid_t rather than int.
* src/security/security_dac.c (virSecurityDACSetOwnership): Likewise.
* src/conf/storage_conf.c (virStorageDefParsePerms): Avoid
compiler warning.
2012-02-11 03:08:11 +04:00
virDomainGetName ( dom ) , pid_value ) ;
2011-05-05 20:32:07 +04:00
virDomainFree ( dom ) ;
ret = true ;
} else {
build: use correct type for pid and similar types
No thanks to 64-bit windows, with 64-bit pid_t, we have to avoid
constructs like 'int pid'. Our API in libvirt-qemu cannot be
changed without breaking ABI; but then again, libvirt-qemu can
only be used on systems that support UNIX sockets, which rules
out Windows (even if qemu could be compiled there) - so for all
points on the call chain that interact with this API decision,
we require a different variable name to make it clear that we
audited the use for safety.
Adding a syntax-check rule only solves half the battle; anywhere
that uses printf on a pid_t still needs to be converted, but that
will be a separate patch.
* cfg.mk (sc_correct_id_types): New syntax check.
* src/libvirt-qemu.c (virDomainQemuAttach): Document why we didn't
use pid_t for pid, and validate for overflow.
* include/libvirt/libvirt-qemu.h (virDomainQemuAttach): Tweak name
for syntax check.
* src/vmware/vmware_conf.c (vmwareExtractPid): Likewise.
* src/driver.h (virDrvDomainQemuAttach): Likewise.
* tools/virsh.c (cmdQemuAttach): Likewise.
* src/remote/qemu_protocol.x (qemu_domain_attach_args): Likewise.
* src/qemu_protocol-structs (qemu_domain_attach_args): Likewise.
* src/util/cgroup.c (virCgroupPidCode, virCgroupKillInternal):
Likewise.
* src/qemu/qemu_command.c(qemuParseProcFileStrings): Likewise.
(qemuParseCommandLinePid): Use pid_t for pid.
* daemon/libvirtd.c (daemonForkIntoBackground): Likewise.
* src/conf/domain_conf.h (_virDomainObj): Likewise.
* src/probes.d (rpc_socket_new): Likewise.
* src/qemu/qemu_command.h (qemuParseCommandLinePid): Likewise.
* src/qemu/qemu_driver.c (qemudGetProcessInfo, qemuDomainAttach):
Likewise.
* src/qemu/qemu_process.c (qemuProcessAttach): Likewise.
* src/qemu/qemu_process.h (qemuProcessAttach): Likewise.
* src/uml/uml_driver.c (umlGetProcessInfo): Likewise.
* src/util/virnetdev.h (virNetDevSetNamespace): Likewise.
* src/util/virnetdev.c (virNetDevSetNamespace): Likewise.
* tests/testutils.c (virtTestCaptureProgramOutput): Likewise.
* src/conf/storage_conf.h (_virStoragePerms): Use mode_t, uid_t,
and gid_t rather than int.
* src/security/security_dac.c (virSecurityDACSetOwnership): Likewise.
* src/conf/storage_conf.c (virStorageDefParsePerms): Avoid
compiler warning.
2012-02-11 03:08:11 +04:00
vshError ( ctl , _ ( " Failed to attach to pid %u " ) , pid_value ) ;
2011-05-05 20:32:07 +04:00
}
cleanup :
return ret ;
}
2012-07-23 07:57:53 +04:00
/* ---------------
* Utils for work with command definition
* - - - - - - - - - - - - - - -
*/
static const char *
vshCmddefGetInfo ( const vshCmdDef * cmd , const char * name )
{
const vshCmdInfo * info ;
2010-11-30 09:37:04 +03:00
2012-07-23 07:57:53 +04:00
for ( info = cmd - > info ; info & & info - > name ; info + + ) {
if ( STREQ ( info - > name , name ) )
return info - > data ;
}
return NULL ;
}
2010-11-30 09:37:04 +03:00
2012-07-23 07:57:53 +04:00
/* Validate that the options associated with cmd can be parsed. */
static int
vshCmddefOptParse ( const vshCmdDef * cmd , uint32_t * opts_need_arg ,
uint32_t * opts_required )
{
int i ;
bool optional = false ;
2008-02-20 18:27:08 +03:00
2012-07-23 07:57:53 +04:00
* opts_need_arg = 0 ;
* opts_required = 0 ;
2009-07-16 23:44:10 +04:00
2012-07-23 07:57:53 +04:00
if ( ! cmd - > opts )
return 0 ;
2010-11-30 09:37:04 +03:00
2012-07-23 07:57:53 +04:00
for ( i = 0 ; cmd - > opts [ i ] . name ; i + + ) {
const vshCmdOptDef * opt = & cmd - > opts [ i ] ;
2011-04-13 00:42:59 +04:00
if ( i > 31 )
return - 1 ; /* too many options */
if ( opt - > type = = VSH_OT_BOOL ) {
virsh: prefer unsigned flags
virsh had some leftover 'int flags', and even an 'int flag'
declaration, compared to our preferred style of 'unsigned int flags'.
* tools/virsh.c (cmdUndefine, cmdSave, cmdSaveImageDumpxml)
(cmdSaveImageEdit, cmdManagedSave, cmdRestore, cmdDump)
(cmdVcpuPin, cmdSetvcpus, cmdSetmem, cmdSetmaxmem, cmdDumpXML)
(cmdDomXMLFromNative, cmdDomXMLToNative, doMigrate)
(cmdInterfaceEdit, cmdInterfaceDumpXML, cmdEdit): Match coding
style for flags.
(struct vshComdOptDef): Rename field member.
(vshCmddefOptParse, vshCmddefHelp): Adjust clients.
2011-09-01 07:11:23 +04:00
if ( opt - > flags & VSH_OFLAG_REQ )
2011-04-13 00:42:59 +04:00
return - 1 ; /* bool options can't be mandatory */
continue ;
}
2012-03-02 22:01:15 +04:00
if ( opt - > type = = VSH_OT_ALIAS ) {
int j ;
if ( opt - > flags | | ! opt - > help )
return - 1 ; /* alias options are tracked by the original name */
for ( j = i + 1 ; cmd - > opts [ j ] . name ; j + + ) {
if ( STREQ ( opt - > help , cmd - > opts [ j ] . name ) )
break ;
}
if ( ! cmd - > opts [ j ] . name )
return - 1 ; /* alias option must map to a later option name */
continue ;
}
virsh: prefer unsigned flags
virsh had some leftover 'int flags', and even an 'int flag'
declaration, compared to our preferred style of 'unsigned int flags'.
* tools/virsh.c (cmdUndefine, cmdSave, cmdSaveImageDumpxml)
(cmdSaveImageEdit, cmdManagedSave, cmdRestore, cmdDump)
(cmdVcpuPin, cmdSetvcpus, cmdSetmem, cmdSetmaxmem, cmdDumpXML)
(cmdDomXMLFromNative, cmdDomXMLToNative, doMigrate)
(cmdInterfaceEdit, cmdInterfaceDumpXML, cmdEdit): Match coding
style for flags.
(struct vshComdOptDef): Rename field member.
(vshCmddefOptParse, vshCmddefHelp): Adjust clients.
2011-09-01 07:11:23 +04:00
if ( opt - > flags & VSH_OFLAG_REQ_OPT ) {
if ( opt - > flags & VSH_OFLAG_REQ )
2011-06-07 13:11:10 +04:00
* opts_required | = 1 < < i ;
continue ;
}
2011-04-13 00:42:59 +04:00
* opts_need_arg | = 1 < < i ;
virsh: prefer unsigned flags
virsh had some leftover 'int flags', and even an 'int flag'
declaration, compared to our preferred style of 'unsigned int flags'.
* tools/virsh.c (cmdUndefine, cmdSave, cmdSaveImageDumpxml)
(cmdSaveImageEdit, cmdManagedSave, cmdRestore, cmdDump)
(cmdVcpuPin, cmdSetvcpus, cmdSetmem, cmdSetmaxmem, cmdDumpXML)
(cmdDomXMLFromNative, cmdDomXMLToNative, doMigrate)
(cmdInterfaceEdit, cmdInterfaceDumpXML, cmdEdit): Match coding
style for flags.
(struct vshComdOptDef): Rename field member.
(vshCmddefOptParse, vshCmddefHelp): Adjust clients.
2011-09-01 07:11:23 +04:00
if ( opt - > flags & VSH_OFLAG_REQ ) {
2011-04-13 00:42:59 +04:00
if ( optional )
return - 1 ; /* mandatory options must be listed first */
* opts_required | = 1 < < i ;
} else {
optional = true ;
}
2011-09-21 18:54:47 +04:00
if ( opt - > type = = VSH_OT_ARGV & & cmd - > opts [ i + 1 ] . name )
return - 1 ; /* argv option must be listed last */
2011-04-13 00:42:59 +04:00
}
return 0 ;
}
2008-08-01 16:19:56 +04:00
static const vshCmdOptDef *
2011-04-13 00:42:59 +04:00
vshCmddefGetOption ( vshControl * ctl , const vshCmdDef * cmd , const char * name ,
2011-09-21 18:54:47 +04:00
uint32_t * opts_seen , int * opt_index )
2006-03-15 15:13:25 +03:00
{
2011-04-13 00:42:59 +04:00
int i ;
for ( i = 0 ; cmd - > opts & & cmd - > opts [ i ] . name ; i + + ) {
const vshCmdOptDef * opt = & cmd - > opts [ i ] ;
2006-03-15 15:13:25 +03:00
2011-04-13 00:42:59 +04:00
if ( STREQ ( opt - > name , name ) ) {
2012-03-02 22:01:15 +04:00
if ( opt - > type = = VSH_OT_ALIAS ) {
name = opt - > help ;
continue ;
}
2011-09-21 18:54:47 +04:00
if ( ( * opts_seen & ( 1 < < i ) ) & & opt - > type ! = VSH_OT_ARGV ) {
2011-04-13 00:42:59 +04:00
vshError ( ctl , _ ( " option --%s already seen " ) , name ) ;
return NULL ;
}
2011-09-21 18:54:47 +04:00
* opts_seen | = 1 < < i ;
* opt_index = i ;
2005-12-08 13:23:34 +03:00
return opt ;
2011-04-13 00:42:59 +04:00
}
}
vshError ( ctl , _ ( " command '%s' doesn't support option --%s " ) ,
cmd - > name , name ) ;
2005-12-08 13:23:34 +03:00
return NULL ;
}
2008-08-01 16:19:56 +04:00
static const vshCmdOptDef *
2011-04-13 00:42:59 +04:00
vshCmddefGetData ( const vshCmdDef * cmd , uint32_t * opts_need_arg ,
uint32_t * opts_seen )
2006-03-15 15:13:25 +03:00
{
2011-04-13 00:42:59 +04:00
int i ;
2008-08-01 16:19:56 +04:00
const vshCmdOptDef * opt ;
2005-12-08 13:23:34 +03:00
2011-04-13 00:42:59 +04:00
if ( ! * opts_need_arg )
return NULL ;
/* Grab least-significant set bit */
2011-07-16 01:49:37 +04:00
i = ffs ( * opts_need_arg ) - 1 ;
2011-04-13 00:42:59 +04:00
opt = & cmd - > opts [ i ] ;
2011-09-21 18:54:47 +04:00
if ( opt - > type ! = VSH_OT_ARGV )
2011-04-13 00:42:59 +04:00
* opts_need_arg & = ~ ( 1 < < i ) ;
2011-09-21 18:54:47 +04:00
* opts_seen | = 1 < < i ;
2011-04-13 00:42:59 +04:00
return opt ;
2005-12-08 13:23:34 +03:00
}
2006-01-25 12:46:22 +03:00
/*
* Checks for required options
*/
2006-03-15 15:13:25 +03:00
static int
2011-04-13 00:42:59 +04:00
vshCommandCheckOpts ( vshControl * ctl , const vshCmd * cmd , uint32_t opts_required ,
uint32_t opts_seen )
2006-01-25 12:46:22 +03:00
{
2008-08-01 16:19:56 +04:00
const vshCmdDef * def = cmd - > def ;
2011-04-13 00:42:59 +04:00
int i ;
opts_required & = ~ opts_seen ;
if ( ! opts_required )
return 0 ;
for ( i = 0 ; def - > opts [ i ] . name ; i + + ) {
if ( opts_required & ( 1 < < i ) ) {
const vshCmdOptDef * opt = & def - > opts [ i ] ;
2006-03-15 15:13:25 +03:00
2011-04-13 00:42:59 +04:00
vshError ( ctl ,
2011-06-07 13:11:08 +04:00
opt - > type = = VSH_OT_DATA | | opt - > type = = VSH_OT_ARGV ?
2011-04-13 00:42:59 +04:00
_ ( " command '%s' requires <%s> option " ) :
_ ( " command '%s' requires --%s option " ) ,
def - > name , opt - > name ) ;
2006-01-25 12:46:22 +03:00
}
}
2011-04-13 00:42:59 +04:00
return - 1 ;
2006-01-25 12:46:22 +03:00
}
2008-08-01 16:19:56 +04:00
static const vshCmdDef *
2006-03-15 15:13:25 +03:00
vshCmddefSearch ( const char * cmdname )
{
2010-11-30 09:37:04 +03:00
const vshCmdGrp * g ;
2008-08-01 16:19:56 +04:00
const vshCmdDef * c ;
2006-03-15 15:13:25 +03:00
2010-11-30 09:37:04 +03:00
for ( g = cmdGroups ; g - > name ; g + + ) {
for ( c = g - > commands ; c - > name ; c + + ) {
2011-04-08 09:08:52 +04:00
if ( STREQ ( c - > name , cmdname ) )
2010-11-30 09:37:04 +03:00
return c ;
}
}
2005-12-08 13:23:34 +03:00
return NULL ;
}
2010-11-30 09:37:04 +03:00
static const vshCmdGrp *
vshCmdGrpSearch ( const char * grpname )
{
const vshCmdGrp * g ;
for ( g = cmdGroups ; g - > name ; g + + ) {
2011-04-08 09:08:52 +04:00
if ( STREQ ( g - > name , grpname ) | | STREQ ( g - > keyword , grpname ) )
2010-11-30 09:37:04 +03:00
return g ;
}
return NULL ;
}
2011-04-19 02:37:42 +04:00
static bool
2010-11-30 09:37:04 +03:00
vshCmdGrpHelp ( vshControl * ctl , const char * grpname )
{
const vshCmdGrp * grp = vshCmdGrpSearch ( grpname ) ;
const vshCmdDef * cmd = NULL ;
if ( ! grp ) {
vshError ( ctl , _ ( " command group '%s' doesn't exist " ) , grpname ) ;
2011-04-19 02:37:42 +04:00
return false ;
2010-11-30 09:37:04 +03:00
} else {
vshPrint ( ctl , _ ( " %s (help keyword '%s'): \n " ) , grp - > name ,
grp - > keyword ) ;
for ( cmd = grp - > commands ; cmd - > name ; cmd + + ) {
vshPrint ( ctl , " %-30s %s \n " , cmd - > name ,
_ ( vshCmddefGetInfo ( cmd , " help " ) ) ) ;
}
}
2011-04-19 02:37:42 +04:00
return true ;
2010-11-30 09:37:04 +03:00
}
2011-04-19 02:37:42 +04:00
static bool
2008-12-08 16:14:48 +03:00
vshCmddefHelp ( vshControl * ctl , const char * cmdname )
2006-03-15 15:13:25 +03:00
{
2008-08-01 16:19:56 +04:00
const vshCmdDef * def = vshCmddefSearch ( cmdname ) ;
2006-03-15 15:13:25 +03:00
2005-12-08 13:23:34 +03:00
if ( ! def ) {
2009-09-29 15:42:42 +04:00
vshError ( ctl , _ ( " command '%s' doesn't exist " ) , cmdname ) ;
2011-04-19 02:37:42 +04:00
return false ;
2006-03-15 15:13:25 +03:00
} else {
2011-06-21 00:25:08 +04:00
/* Don't translate desc if it is "". */
const char * desc = vshCmddefGetInfo ( def , " desc " ) ;
2010-03-09 20:05:01 +03:00
const char * help = _ ( vshCmddefGetInfo ( def , " help " ) ) ;
2008-12-08 16:14:48 +03:00
char buf [ 256 ] ;
2011-04-13 00:42:59 +04:00
uint32_t opts_need_arg ;
uint32_t opts_required ;
2011-09-15 01:20:08 +04:00
bool shortopt = false ; /* true if 'arg' works instead of '--opt arg' */
2011-04-13 00:42:59 +04:00
if ( vshCmddefOptParse ( def , & opts_need_arg , & opts_required ) ) {
vshError ( ctl , _ ( " internal error: bad options in command: '%s' " ) ,
def - > name ) ;
2011-04-19 02:37:42 +04:00
return false ;
2011-04-13 00:42:59 +04:00
}
2005-12-08 13:23:34 +03:00
2006-09-21 19:24:37 +04:00
fputs ( _ ( " NAME \n " ) , stdout ) ;
2006-03-15 15:13:25 +03:00
fprintf ( stdout , " %s - %s \n " , def - > name , help ) ;
2008-12-08 16:14:48 +03:00
fputs ( _ ( " \n SYNOPSIS \n " ) , stdout ) ;
fprintf ( stdout , " %s " , def - > name ) ;
if ( def - > opts ) {
const vshCmdOptDef * opt ;
for ( opt = def - > opts ; opt - > name ; opt + + ) {
2011-05-13 10:27:59 +04:00
const char * fmt = " %s " ;
2010-10-15 17:38:49 +04:00
switch ( opt - > type ) {
case VSH_OT_BOOL :
2008-12-08 16:14:48 +03:00
fmt = " [--%s] " ;
2010-10-15 17:38:49 +04:00
break ;
case VSH_OT_INT :
2010-03-09 20:05:01 +03:00
/* xgettext:c-format */
virsh: prefer unsigned flags
virsh had some leftover 'int flags', and even an 'int flag'
declaration, compared to our preferred style of 'unsigned int flags'.
* tools/virsh.c (cmdUndefine, cmdSave, cmdSaveImageDumpxml)
(cmdSaveImageEdit, cmdManagedSave, cmdRestore, cmdDump)
(cmdVcpuPin, cmdSetvcpus, cmdSetmem, cmdSetmaxmem, cmdDumpXML)
(cmdDomXMLFromNative, cmdDomXMLToNative, doMigrate)
(cmdInterfaceEdit, cmdInterfaceDumpXML, cmdEdit): Match coding
style for flags.
(struct vshComdOptDef): Rename field member.
(vshCmddefOptParse, vshCmddefHelp): Adjust clients.
2011-09-01 07:11:23 +04:00
fmt = ( ( opt - > flags & VSH_OFLAG_REQ ) ? " <%s> "
2010-10-19 20:27:02 +04:00
: _ ( " [--%s <number>] " ) ) ;
2011-09-15 01:20:08 +04:00
if ( ! ( opt - > flags & VSH_OFLAG_REQ_OPT ) )
shortopt = true ;
2010-10-15 17:38:49 +04:00
break ;
case VSH_OT_STRING :
2010-03-09 20:05:01 +03:00
/* xgettext:c-format */
fmt = _ ( " [--%s <string>] " ) ;
2011-09-15 01:20:08 +04:00
if ( ! ( opt - > flags & VSH_OFLAG_REQ_OPT ) )
shortopt = true ;
2010-10-15 17:38:49 +04:00
break ;
case VSH_OT_DATA :
virsh: prefer unsigned flags
virsh had some leftover 'int flags', and even an 'int flag'
declaration, compared to our preferred style of 'unsigned int flags'.
* tools/virsh.c (cmdUndefine, cmdSave, cmdSaveImageDumpxml)
(cmdSaveImageEdit, cmdManagedSave, cmdRestore, cmdDump)
(cmdVcpuPin, cmdSetvcpus, cmdSetmem, cmdSetmaxmem, cmdDumpXML)
(cmdDomXMLFromNative, cmdDomXMLToNative, doMigrate)
(cmdInterfaceEdit, cmdInterfaceDumpXML, cmdEdit): Match coding
style for flags.
(struct vshComdOptDef): Rename field member.
(vshCmddefOptParse, vshCmddefHelp): Adjust clients.
2011-09-01 07:11:23 +04:00
fmt = ( ( opt - > flags & VSH_OFLAG_REQ ) ? " <%s> " : " [<%s>] " ) ;
2011-09-15 01:20:08 +04:00
if ( ! ( opt - > flags & VSH_OFLAG_REQ_OPT ) )
shortopt = true ;
2010-10-15 17:38:49 +04:00
break ;
case VSH_OT_ARGV :
/* xgettext:c-format */
2011-09-15 01:20:08 +04:00
if ( shortopt ) {
fmt = ( opt - > flags & VSH_OFLAG_REQ )
? _ ( " {[--%s] <string>}... " )
: _ ( " [[--%s] <string>]... " ) ;
} else {
fmt = ( opt - > flags & VSH_OFLAG_REQ ) ? _ ( " <%s>... " )
: _ ( " [<%s>]... " ) ;
}
2010-10-15 17:38:49 +04:00
break ;
2012-03-02 22:01:15 +04:00
case VSH_OT_ALIAS :
/* aliases are intentionally undocumented */
continue ;
2010-10-15 17:38:49 +04:00
default :
2008-12-08 16:14:48 +03:00
assert ( 0 ) ;
2010-10-15 17:38:49 +04:00
}
2008-12-08 16:14:48 +03:00
fputc ( ' ' , stdout ) ;
2010-03-09 20:05:01 +03:00
fprintf ( stdout , fmt , opt - > name ) ;
2008-12-08 16:14:48 +03:00
}
2005-12-08 13:23:34 +03:00
}
2008-12-08 16:14:48 +03:00
fputc ( ' \n ' , stdout ) ;
if ( desc [ 0 ] ) {
2009-01-05 16:27:43 +03:00
/* Print the description only if it's not empty. */
2006-09-21 19:24:37 +04:00
fputs ( _ ( " \n DESCRIPTION \n " ) , stdout ) ;
2011-06-21 00:25:08 +04:00
fprintf ( stdout , " %s \n " , _ ( desc ) ) ;
2005-12-08 13:23:34 +03:00
}
2008-12-08 16:14:48 +03:00
2005-12-08 13:23:34 +03:00
if ( def - > opts ) {
2008-12-08 16:14:48 +03:00
const vshCmdOptDef * opt ;
2006-09-21 19:24:37 +04:00
fputs ( _ ( " \n OPTIONS \n " ) , stdout ) ;
2006-03-15 15:13:25 +03:00
for ( opt = def - > opts ; opt - > name ; opt + + ) {
2010-10-15 17:38:49 +04:00
switch ( opt - > type ) {
case VSH_OT_BOOL :
2005-12-08 13:23:34 +03:00
snprintf ( buf , sizeof ( buf ) , " --%s " , opt - > name ) ;
2010-10-15 17:38:49 +04:00
break ;
case VSH_OT_INT :
2010-10-19 20:27:02 +04:00
snprintf ( buf , sizeof ( buf ) ,
virsh: prefer unsigned flags
virsh had some leftover 'int flags', and even an 'int flag'
declaration, compared to our preferred style of 'unsigned int flags'.
* tools/virsh.c (cmdUndefine, cmdSave, cmdSaveImageDumpxml)
(cmdSaveImageEdit, cmdManagedSave, cmdRestore, cmdDump)
(cmdVcpuPin, cmdSetvcpus, cmdSetmem, cmdSetmaxmem, cmdDumpXML)
(cmdDomXMLFromNative, cmdDomXMLToNative, doMigrate)
(cmdInterfaceEdit, cmdInterfaceDumpXML, cmdEdit): Match coding
style for flags.
(struct vshComdOptDef): Rename field member.
(vshCmddefOptParse, vshCmddefHelp): Adjust clients.
2011-09-01 07:11:23 +04:00
( opt - > flags & VSH_OFLAG_REQ ) ? _ ( " [--%s] <number> " )
2010-10-19 20:27:02 +04:00
: _ ( " --%s <number> " ) , opt - > name ) ;
2010-10-15 17:38:49 +04:00
break ;
case VSH_OT_STRING :
2010-10-19 20:27:02 +04:00
/* OT_STRING should never be VSH_OFLAG_REQ */
2006-09-21 19:24:37 +04:00
snprintf ( buf , sizeof ( buf ) , _ ( " --%s <string> " ) , opt - > name ) ;
2010-10-15 17:38:49 +04:00
break ;
case VSH_OT_DATA :
2010-06-30 02:14:57 +04:00
snprintf ( buf , sizeof ( buf ) , _ ( " [--%s] <string> " ) ,
opt - > name ) ;
2010-10-15 17:38:49 +04:00
break ;
case VSH_OT_ARGV :
2011-09-15 01:20:08 +04:00
snprintf ( buf , sizeof ( buf ) ,
shortopt ? _ ( " [--%s] <string> " ) : _ ( " <%s> " ) ,
opt - > name ) ;
2011-06-07 13:11:08 +04:00
break ;
2012-03-02 22:01:15 +04:00
case VSH_OT_ALIAS :
continue ;
2010-10-15 17:38:49 +04:00
default :
assert ( 0 ) ;
}
2006-03-15 15:13:25 +03:00
2010-03-09 20:05:01 +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 ) ;
}
2011-04-19 02:37:42 +04:00
return true ;
2005-12-08 13:23:34 +03:00
}
/* ---------------
* 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 ;
2010-01-03 19:13:27 +03:00
VIR_FREE ( tmp - > data ) ;
VIR_FREE ( tmp ) ;
2005-12-08 13:23:34 +03:00
}
}
static void
2008-08-01 17:51:18 +04:00
vshCommandFree ( vshCmd * cmd )
2006-03-15 15:13:25 +03:00
{
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 ) ;
2010-01-03 19:13:27 +03:00
VIR_FREE ( tmp ) ;
2005-12-08 13:23:34 +03:00
}
}
2011-07-15 21:23:17 +04:00
/**
* vshCommandOpt :
* @ cmd : parsed command line to search
* @ name : option name to search for
* @ opt : result of the search
*
* Look up an option passed to CMD by NAME . Returns 1 with * OPT set
* to the option if found , 0 with * OPT set to NULL if the name is
* valid and the option is not required , - 1 with * OPT set to NULL if
* the option is required but not present , and - 2 if NAME is not valid
* ( - 2 indicates a programming error ) . No error messages are issued .
2005-12-08 13:23:34 +03:00
*/
2011-07-15 21:23:17 +04:00
static int
vshCommandOpt ( const vshCmd * cmd , const char * name , vshCmdOpt * * opt )
2006-03-15 15:13:25 +03:00
{
2011-07-15 21:23:17 +04:00
vshCmdOpt * candidate = cmd - > opts ;
const vshCmdOptDef * valid = cmd - > def - > opts ;
2006-03-15 15:13:25 +03:00
2011-07-15 21:23:17 +04:00
/* See if option is present on command line. */
while ( candidate ) {
if ( STREQ ( candidate - > def - > name , name ) ) {
* opt = candidate ;
return 1 ;
}
candidate = candidate - > next ;
2005-12-08 13:23:34 +03:00
}
2011-07-15 21:23:17 +04:00
/* Option not present, see if command requires it. */
* opt = NULL ;
while ( valid ) {
if ( ! valid - > name )
break ;
if ( STREQ ( name , valid - > name ) )
virsh: prefer unsigned flags
virsh had some leftover 'int flags', and even an 'int flag'
declaration, compared to our preferred style of 'unsigned int flags'.
* tools/virsh.c (cmdUndefine, cmdSave, cmdSaveImageDumpxml)
(cmdSaveImageEdit, cmdManagedSave, cmdRestore, cmdDump)
(cmdVcpuPin, cmdSetvcpus, cmdSetmem, cmdSetmaxmem, cmdDumpXML)
(cmdDomXMLFromNative, cmdDomXMLToNative, doMigrate)
(cmdInterfaceEdit, cmdInterfaceDumpXML, cmdEdit): Match coding
style for flags.
(struct vshComdOptDef): Rename field member.
(vshCmddefOptParse, vshCmddefHelp): Adjust clients.
2011-09-01 07:11:23 +04:00
return ( valid - > flags & VSH_OFLAG_REQ ) = = 0 ? 0 : - 1 ;
2011-07-15 21:23:17 +04:00
valid + + ;
}
/* If we got here, the name is unknown. */
return - 2 ;
2005-12-08 13:23:34 +03:00
}
2011-07-15 21:23:17 +04:00
/**
* vshCommandOptInt :
2011-03-08 19:29:31 +03:00
* @ cmd command reference
* @ name option name
* @ value result
*
* Convert option to int
* Return value :
* > 0 if option found and valid ( @ value updated )
2011-07-15 21:23:17 +04:00
* 0 if option not found and not required ( @ value untouched )
2011-03-08 19:29:31 +03:00
* < 0 in all other cases ( @ value untouched )
2005-12-08 13:23:34 +03:00
*/
static int
2011-03-08 19:29:31 +03:00
vshCommandOptInt ( const vshCmd * cmd , const char * name , int * value )
2006-03-15 15:13:25 +03:00
{
2011-07-15 21:23:17 +04:00
vshCmdOpt * arg ;
int ret ;
2006-03-15 15:13:25 +03:00
2011-07-15 21:23:17 +04:00
ret = vshCommandOpt ( cmd , name , & arg ) ;
if ( ret < = 0 )
return ret ;
if ( ! arg - > data ) {
/* only possible on bool, but if name is bool, this is a
* programming bug */
return - 2 ;
2007-08-16 17:21:36 +04:00
}
2011-07-15 21:23:17 +04:00
2012-04-19 03:26:17 +04:00
if ( virStrToLong_i ( arg - > data , NULL , 10 , value ) < 0 )
return - 1 ;
return 1 ;
2005-12-08 13:23:34 +03:00
}
2011-05-12 20:29:12 +04:00
2011-07-15 21:23:17 +04:00
/**
* vshCommandOptUInt :
* @ cmd command reference
* @ name option name
* @ value result
*
2011-05-12 20:29:12 +04:00
* Convert option to unsigned int
* See vshCommandOptInt ( )
*/
static int
vshCommandOptUInt ( const vshCmd * cmd , const char * name , unsigned int * value )
{
2011-07-15 21:23:17 +04:00
vshCmdOpt * arg ;
int ret ;
2011-05-12 20:29:12 +04:00
2011-07-15 21:23:17 +04:00
ret = vshCommandOpt ( cmd , name , & arg ) ;
if ( ret < = 0 )
return ret ;
if ( ! arg - > data ) {
/* only possible on bool, but if name is bool, this is a
* programming bug */
return - 2 ;
2011-05-12 20:29:12 +04:00
}
2011-07-15 21:23:17 +04:00
2012-04-19 03:26:17 +04:00
if ( virStrToLong_ui ( arg - > data , NULL , 10 , value ) < 0 )
return - 1 ;
return 1 ;
2011-05-12 20:29:12 +04:00
}
2011-03-08 19:29:31 +03:00
/*
2011-07-15 21:23:17 +04:00
* vshCommandOptUL :
* @ cmd command reference
* @ name option name
* @ value result
*
2011-03-08 19:29:31 +03:00
* Convert option to unsigned long
* See vshCommandOptInt ( )
*/
static int
vshCommandOptUL ( const vshCmd * cmd , const char * name , unsigned long * value )
2010-06-17 23:36:36 +04:00
{
2011-07-15 21:23:17 +04:00
vshCmdOpt * arg ;
int ret ;
2010-06-17 23:36:36 +04:00
2011-07-15 21:23:17 +04:00
ret = vshCommandOpt ( cmd , name , & arg ) ;
if ( ret < = 0 )
return ret ;
if ( ! arg - > data ) {
/* only possible on bool, but if name is bool, this is a
* programming bug */
return - 2 ;
2010-06-17 23:36:36 +04:00
}
2011-07-15 21:23:17 +04:00
2012-04-19 03:26:17 +04:00
if ( virStrToLong_ul ( arg - > data , NULL , 10 , value ) < 0 )
return - 1 ;
return 1 ;
2010-06-17 23:36:36 +04:00
}
2011-07-15 21:23:17 +04:00
/**
* vshCommandOptString :
* @ cmd command reference
* @ name option name
* @ value result
*
2005-12-08 13:23:34 +03:00
* Returns option as STRING
2011-07-15 21:23:17 +04:00
* Return value :
* > 0 if option found and valid ( @ value updated )
* 0 if option not found and not required ( @ value untouched )
* < 0 in all other cases ( @ value untouched )
2005-12-08 13:23:34 +03:00
*/
2011-03-08 19:29:31 +03:00
static int
vshCommandOptString ( const vshCmd * cmd , const char * name , const char * * value )
2006-03-15 15:13:25 +03:00
{
2011-07-15 21:23:17 +04:00
vshCmdOpt * arg ;
int ret ;
ret = vshCommandOpt ( cmd , name , & arg ) ;
if ( ret < = 0 )
return ret ;
if ( ! arg - > data ) {
/* only possible on bool, but if name is bool, this is a
* programming bug */
return - 2 ;
2011-03-08 19:29:31 +03:00
}
2006-03-15 15:13:25 +03:00
virsh: prefer unsigned flags
virsh had some leftover 'int flags', and even an 'int flag'
declaration, compared to our preferred style of 'unsigned int flags'.
* tools/virsh.c (cmdUndefine, cmdSave, cmdSaveImageDumpxml)
(cmdSaveImageEdit, cmdManagedSave, cmdRestore, cmdDump)
(cmdVcpuPin, cmdSetvcpus, cmdSetmem, cmdSetmaxmem, cmdDumpXML)
(cmdDomXMLFromNative, cmdDomXMLToNative, doMigrate)
(cmdInterfaceEdit, cmdInterfaceDumpXML, cmdEdit): Match coding
style for flags.
(struct vshComdOptDef): Rename field member.
(vshCmddefOptParse, vshCmddefHelp): Adjust clients.
2011-09-01 07:11:23 +04:00
if ( ! * arg - > data & & ! ( arg - > def - > flags & VSH_OFLAG_EMPTY_OK ) ) {
2011-07-15 21:23:17 +04:00
return - 1 ;
}
* value = arg - > data ;
return 1 ;
2005-12-08 13:23:34 +03:00
}
2011-07-15 21:23:17 +04:00
/**
* vshCommandOptLongLong :
* @ cmd command reference
* @ name option name
* @ value result
*
2010-03-17 19:18:36 +03:00
* Returns option as long long
2011-03-08 19:29:31 +03:00
* See vshCommandOptInt ( )
2010-03-17 19:18:36 +03:00
*/
2011-03-08 19:29:31 +03:00
static int
vshCommandOptLongLong ( const vshCmd * cmd , const char * name ,
long long * value )
2010-03-17 19:18:36 +03:00
{
2011-07-15 21:23:17 +04:00
vshCmdOpt * arg ;
int ret ;
2010-03-17 19:18:36 +03:00
2011-07-15 21:23:17 +04:00
ret = vshCommandOpt ( cmd , name , & arg ) ;
if ( ret < = 0 )
return ret ;
if ( ! arg - > data ) {
/* only possible on bool, but if name is bool, this is a
* programming bug */
return - 2 ;
2011-03-08 19:29:31 +03:00
}
2011-07-15 21:23:17 +04:00
2012-04-19 03:26:17 +04:00
if ( virStrToLong_ll ( arg - > data , NULL , 10 , value ) < 0 )
return - 1 ;
return 1 ;
2010-03-17 19:18:36 +03:00
}
2011-07-15 21:23:17 +04:00
/**
* vshCommandOptULongLong :
* @ cmd command reference
* @ name option name
* @ value result
*
* Returns option as long long
* See vshCommandOptInt ( )
*/
2009-07-14 17:24:53 +04:00
static int
vshCommandOptULongLong ( const vshCmd * cmd , const char * name ,
unsigned long long * value )
{
2011-07-15 21:23:17 +04:00
vshCmdOpt * arg ;
int ret ;
2009-07-14 17:24:53 +04:00
2011-07-15 21:23:17 +04:00
ret = vshCommandOpt ( cmd , name , & arg ) ;
if ( ret < = 0 )
return ret ;
if ( ! arg - > data ) {
/* only possible on bool, but if name is bool, this is a
* programming bug */
return - 2 ;
2009-07-14 17:24:53 +04:00
}
2011-07-15 21:23:17 +04:00
2012-04-19 03:26:17 +04:00
if ( virStrToLong_ull ( arg - > data , NULL , 10 , value ) < 0 )
return - 1 ;
return 1 ;
2009-07-14 17:24:53 +04:00
}
2012-03-08 05:10:30 +04:00
/**
* vshCommandOptScaledInt :
* @ cmd command reference
* @ name option name
* @ value result
* @ scale default of 1 or 1024 , if no suffix is present
* @ max maximum value permitted
*
* Returns option as long long , scaled according to suffix
* See vshCommandOptInt ( )
*/
static int
vshCommandOptScaledInt ( const vshCmd * cmd , const char * name ,
unsigned long long * value , int scale ,
unsigned long long max )
{
const char * str ;
int ret ;
char * end ;
ret = vshCommandOptString ( cmd , name , & str ) ;
if ( ret < = 0 )
return ret ;
if ( virStrToLong_ull ( str , & end , 10 , value ) < 0 | |
virScaleInteger ( value , end , scale , max ) < 0 )
return - 1 ;
return 1 ;
}
2011-07-15 21:23:17 +04:00
/**
* vshCommandOptBool :
* @ cmd command reference
* @ name option name
*
* Returns true / false if the option exists . Note that this does NOT
* validate whether the option is actually boolean , or even whether
* name is legal ; so that this can be used to probe whether a data
* option is present without actually using that data .
2005-12-08 13:23:34 +03:00
*/
2011-04-19 02:37:42 +04:00
static bool
2008-08-01 17:51:18 +04:00
vshCommandOptBool ( const vshCmd * cmd , const char * name )
2006-03-15 15:13:25 +03:00
{
2011-07-15 21:23:17 +04:00
vshCmdOpt * dummy ;
return vshCommandOpt ( cmd , name , & dummy ) = = 1 ;
2005-12-08 13:23:34 +03:00
}
2011-07-15 21:23:17 +04:00
/**
* vshCommandOptArgv :
* @ cmd command reference
* @ opt starting point for the search
*
2011-06-14 21:26:20 +04:00
* Returns the next argv argument after OPT ( or the first one if OPT
* is NULL ) , or NULL if no more are present .
2010-10-15 17:38:49 +04:00
*
2011-06-14 21:26:20 +04:00
* Requires that a VSH_OT_ARGV option be last in the
2010-10-15 17:38:49 +04:00
* list of supported options in CMD - > def - > opts .
*/
2011-06-14 21:26:20 +04:00
static const vshCmdOpt *
vshCommandOptArgv ( const vshCmd * cmd , const vshCmdOpt * opt )
2010-10-15 17:38:49 +04:00
{
2011-06-14 21:26:20 +04:00
opt = opt ? opt - > next : cmd - > opts ;
2010-10-15 17:38:49 +04:00
while ( opt ) {
2011-07-15 21:23:17 +04:00
if ( opt - > def - > type = = VSH_OT_ARGV ) {
2011-06-14 21:26:20 +04:00
return opt ;
2010-10-15 17:38:49 +04:00
}
opt = opt - > next ;
}
return NULL ;
}
remove redundant optname arguments
This is the second part of the change mentioned here:
http://thread.gmane.org/gmane.comp.emulators.libvirt/10331
It removes the essentially redundant "optname" parameter
from each of the vshCommandOptNetworkBy and vshCommandOptDomainBy
functions as well as the correspond macros (without "By" suffix).
Now, instead of always passing the optname, "domain", to
vshCommandOptDomainBy, that function requires that its command
argument refer to an opts array containing a "domain" option.
This normalization makes one more help-related change:
it renames the net-start "name" argument to the more
sensible and consistent "network".
* src/virsh.c (VSH_BYNAME, vshCommandOptDomain)
(cmd_has_option): New function, used in vshCommandOptDomainBy
and vshCommandOptNetworkBy.
(vshCommandOptDomainBy, vshCommandOptNetworkBy): Remove the optname
parameter, it's always "domain" ("network"). Update all callers.
Call cmd_has_option.
(vshCommandOptNetwork, cmdAutostart, cmdConsole, cmdDomstate)
(cmdDomblkstat, cmdDomIfstat, cmdSuspend, cmdUndefine, cmdStart)
(cmdSave, cmdSchedinfo, cmdDump, cmdResume, cmdShutdown)
(cmdReboot, cmdDestroy, cmdDominfo, cmdVcpuinfo, cmdVcpupin)
(cmdSetvcpus, cmdSetmem, cmdSetmaxmem, cmdDumpXML, cmdDomname)
(cmdDomid, cmdDomuuid, cmdMigrate, cmdNetworkAutostart)
(cmdNetworkDestroy, cmdNetworkDumpXML, cmdNetworkName)
(opts_network_start, cmdNetworkStart, cmdNetworkUndefine)
(cmdNetworkUuid, cmdVNCDisplay, cmdTTYConsole, cmdAttachDevice)
(cmdDetachDevice, cmdAttachInterface, cmdDetachInterface)
(cmdAttachDisk, cmdDetachDisk, cmdEdit)
* src/Makefile.am (virsh-pool-edit.c): This code is generated
from cmdEdit, and cmdEdit uses the vshCommandOptDomain macro which
now, with the changes above, has only 3 (was 4) arguments, yet the
macro use is mapped to vshCommandOptPool, which still requires 4
arguments. So this change adjusts the sed code to reinsert the
just-removed argument -- we're not changing pool-related code right
now, because it's not as straight-forward.
2008-12-15 13:26:54 +03:00
/* Determine whether CMD->opts includes an option with name OPTNAME.
If not , give a diagnostic and return false .
If so , return true . */
static bool
2012-07-11 10:17:28 +04:00
cmd_has_option ( vshControl * ctl , const vshCmd * cmd , const char * optname )
remove redundant optname arguments
This is the second part of the change mentioned here:
http://thread.gmane.org/gmane.comp.emulators.libvirt/10331
It removes the essentially redundant "optname" parameter
from each of the vshCommandOptNetworkBy and vshCommandOptDomainBy
functions as well as the correspond macros (without "By" suffix).
Now, instead of always passing the optname, "domain", to
vshCommandOptDomainBy, that function requires that its command
argument refer to an opts array containing a "domain" option.
This normalization makes one more help-related change:
it renames the net-start "name" argument to the more
sensible and consistent "network".
* src/virsh.c (VSH_BYNAME, vshCommandOptDomain)
(cmd_has_option): New function, used in vshCommandOptDomainBy
and vshCommandOptNetworkBy.
(vshCommandOptDomainBy, vshCommandOptNetworkBy): Remove the optname
parameter, it's always "domain" ("network"). Update all callers.
Call cmd_has_option.
(vshCommandOptNetwork, cmdAutostart, cmdConsole, cmdDomstate)
(cmdDomblkstat, cmdDomIfstat, cmdSuspend, cmdUndefine, cmdStart)
(cmdSave, cmdSchedinfo, cmdDump, cmdResume, cmdShutdown)
(cmdReboot, cmdDestroy, cmdDominfo, cmdVcpuinfo, cmdVcpupin)
(cmdSetvcpus, cmdSetmem, cmdSetmaxmem, cmdDumpXML, cmdDomname)
(cmdDomid, cmdDomuuid, cmdMigrate, cmdNetworkAutostart)
(cmdNetworkDestroy, cmdNetworkDumpXML, cmdNetworkName)
(opts_network_start, cmdNetworkStart, cmdNetworkUndefine)
(cmdNetworkUuid, cmdVNCDisplay, cmdTTYConsole, cmdAttachDevice)
(cmdDetachDevice, cmdAttachInterface, cmdDetachInterface)
(cmdAttachDisk, cmdDetachDisk, cmdEdit)
* src/Makefile.am (virsh-pool-edit.c): This code is generated
from cmdEdit, and cmdEdit uses the vshCommandOptDomain macro which
now, with the changes above, has only 3 (was 4) arguments, yet the
macro use is mapped to vshCommandOptPool, which still requires 4
arguments. So this change adjusts the sed code to reinsert the
just-removed argument -- we're not changing pool-related code right
now, because it's not as straight-forward.
2008-12-15 13:26:54 +03:00
{
/* Iterate through cmd->opts, to ensure that there is an entry
with name OPTNAME and type VSH_OT_DATA . */
bool found = false ;
const vshCmdOpt * opt ;
for ( opt = cmd - > opts ; opt ; opt = opt - > next ) {
2012-07-11 10:17:28 +04:00
if ( STREQ ( opt - > def - > name , optname ) & & opt - > def - > type = = VSH_OT_DATA ) {
remove redundant optname arguments
This is the second part of the change mentioned here:
http://thread.gmane.org/gmane.comp.emulators.libvirt/10331
It removes the essentially redundant "optname" parameter
from each of the vshCommandOptNetworkBy and vshCommandOptDomainBy
functions as well as the correspond macros (without "By" suffix).
Now, instead of always passing the optname, "domain", to
vshCommandOptDomainBy, that function requires that its command
argument refer to an opts array containing a "domain" option.
This normalization makes one more help-related change:
it renames the net-start "name" argument to the more
sensible and consistent "network".
* src/virsh.c (VSH_BYNAME, vshCommandOptDomain)
(cmd_has_option): New function, used in vshCommandOptDomainBy
and vshCommandOptNetworkBy.
(vshCommandOptDomainBy, vshCommandOptNetworkBy): Remove the optname
parameter, it's always "domain" ("network"). Update all callers.
Call cmd_has_option.
(vshCommandOptNetwork, cmdAutostart, cmdConsole, cmdDomstate)
(cmdDomblkstat, cmdDomIfstat, cmdSuspend, cmdUndefine, cmdStart)
(cmdSave, cmdSchedinfo, cmdDump, cmdResume, cmdShutdown)
(cmdReboot, cmdDestroy, cmdDominfo, cmdVcpuinfo, cmdVcpupin)
(cmdSetvcpus, cmdSetmem, cmdSetmaxmem, cmdDumpXML, cmdDomname)
(cmdDomid, cmdDomuuid, cmdMigrate, cmdNetworkAutostart)
(cmdNetworkDestroy, cmdNetworkDumpXML, cmdNetworkName)
(opts_network_start, cmdNetworkStart, cmdNetworkUndefine)
(cmdNetworkUuid, cmdVNCDisplay, cmdTTYConsole, cmdAttachDevice)
(cmdDetachDevice, cmdAttachInterface, cmdDetachInterface)
(cmdAttachDisk, cmdDetachDisk, cmdEdit)
* src/Makefile.am (virsh-pool-edit.c): This code is generated
from cmdEdit, and cmdEdit uses the vshCommandOptDomain macro which
now, with the changes above, has only 3 (was 4) arguments, yet the
macro use is mapped to vshCommandOptPool, which still requires 4
arguments. So this change adjusts the sed code to reinsert the
just-removed argument -- we're not changing pool-related code right
now, because it's not as straight-forward.
2008-12-15 13:26:54 +03:00
found = true ;
break ;
}
}
if ( ! found )
2009-09-29 15:42:42 +04:00
vshError ( ctl , _ ( " internal error: virsh %s: no %s VSH_OT_DATA option " ) ,
remove redundant optname arguments
This is the second part of the change mentioned here:
http://thread.gmane.org/gmane.comp.emulators.libvirt/10331
It removes the essentially redundant "optname" parameter
from each of the vshCommandOptNetworkBy and vshCommandOptDomainBy
functions as well as the correspond macros (without "By" suffix).
Now, instead of always passing the optname, "domain", to
vshCommandOptDomainBy, that function requires that its command
argument refer to an opts array containing a "domain" option.
This normalization makes one more help-related change:
it renames the net-start "name" argument to the more
sensible and consistent "network".
* src/virsh.c (VSH_BYNAME, vshCommandOptDomain)
(cmd_has_option): New function, used in vshCommandOptDomainBy
and vshCommandOptNetworkBy.
(vshCommandOptDomainBy, vshCommandOptNetworkBy): Remove the optname
parameter, it's always "domain" ("network"). Update all callers.
Call cmd_has_option.
(vshCommandOptNetwork, cmdAutostart, cmdConsole, cmdDomstate)
(cmdDomblkstat, cmdDomIfstat, cmdSuspend, cmdUndefine, cmdStart)
(cmdSave, cmdSchedinfo, cmdDump, cmdResume, cmdShutdown)
(cmdReboot, cmdDestroy, cmdDominfo, cmdVcpuinfo, cmdVcpupin)
(cmdSetvcpus, cmdSetmem, cmdSetmaxmem, cmdDumpXML, cmdDomname)
(cmdDomid, cmdDomuuid, cmdMigrate, cmdNetworkAutostart)
(cmdNetworkDestroy, cmdNetworkDumpXML, cmdNetworkName)
(opts_network_start, cmdNetworkStart, cmdNetworkUndefine)
(cmdNetworkUuid, cmdVNCDisplay, cmdTTYConsole, cmdAttachDevice)
(cmdDetachDevice, cmdAttachInterface, cmdDetachInterface)
(cmdAttachDisk, cmdDetachDisk, cmdEdit)
* src/Makefile.am (virsh-pool-edit.c): This code is generated
from cmdEdit, and cmdEdit uses the vshCommandOptDomain macro which
now, with the changes above, has only 3 (was 4) arguments, yet the
macro use is mapped to vshCommandOptPool, which still requires 4
arguments. So this change adjusts the sed code to reinsert the
just-removed argument -- we're not changing pool-related code right
now, because it's not as straight-forward.
2008-12-15 13:26:54 +03:00
cmd - > def - > name , optname ) ;
return found ;
}
2006-01-25 12:46:22 +03:00
2005-12-15 20:00:43 +03:00
static virDomainPtr
remove redundant optname arguments
This is the second part of the change mentioned here:
http://thread.gmane.org/gmane.comp.emulators.libvirt/10331
It removes the essentially redundant "optname" parameter
from each of the vshCommandOptNetworkBy and vshCommandOptDomainBy
functions as well as the correspond macros (without "By" suffix).
Now, instead of always passing the optname, "domain", to
vshCommandOptDomainBy, that function requires that its command
argument refer to an opts array containing a "domain" option.
This normalization makes one more help-related change:
it renames the net-start "name" argument to the more
sensible and consistent "network".
* src/virsh.c (VSH_BYNAME, vshCommandOptDomain)
(cmd_has_option): New function, used in vshCommandOptDomainBy
and vshCommandOptNetworkBy.
(vshCommandOptDomainBy, vshCommandOptNetworkBy): Remove the optname
parameter, it's always "domain" ("network"). Update all callers.
Call cmd_has_option.
(vshCommandOptNetwork, cmdAutostart, cmdConsole, cmdDomstate)
(cmdDomblkstat, cmdDomIfstat, cmdSuspend, cmdUndefine, cmdStart)
(cmdSave, cmdSchedinfo, cmdDump, cmdResume, cmdShutdown)
(cmdReboot, cmdDestroy, cmdDominfo, cmdVcpuinfo, cmdVcpupin)
(cmdSetvcpus, cmdSetmem, cmdSetmaxmem, cmdDumpXML, cmdDomname)
(cmdDomid, cmdDomuuid, cmdMigrate, cmdNetworkAutostart)
(cmdNetworkDestroy, cmdNetworkDumpXML, cmdNetworkName)
(opts_network_start, cmdNetworkStart, cmdNetworkUndefine)
(cmdNetworkUuid, cmdVNCDisplay, cmdTTYConsole, cmdAttachDevice)
(cmdDetachDevice, cmdAttachInterface, cmdDetachInterface)
(cmdAttachDisk, cmdDetachDisk, cmdEdit)
* src/Makefile.am (virsh-pool-edit.c): This code is generated
from cmdEdit, and cmdEdit uses the vshCommandOptDomain macro which
now, with the changes above, has only 3 (was 4) arguments, yet the
macro use is mapped to vshCommandOptPool, which still requires 4
arguments. So this change adjusts the sed code to reinsert the
just-removed argument -- we're not changing pool-related code right
now, because it's not as straight-forward.
2008-12-15 13:26:54 +03:00
vshCommandOptDomainBy ( vshControl * ctl , const vshCmd * cmd ,
2011-03-08 19:29:30 +03:00
const char * * name , int flag )
2006-03-15 15:13:25 +03:00
{
2005-12-15 20:00:43 +03:00
virDomainPtr dom = NULL ;
2011-03-08 19:29:31 +03:00
const char * n = NULL ;
2005-12-15 20:00:43 +03:00
int id ;
remove redundant optname arguments
This is the second part of the change mentioned here:
http://thread.gmane.org/gmane.comp.emulators.libvirt/10331
It removes the essentially redundant "optname" parameter
from each of the vshCommandOptNetworkBy and vshCommandOptDomainBy
functions as well as the correspond macros (without "By" suffix).
Now, instead of always passing the optname, "domain", to
vshCommandOptDomainBy, that function requires that its command
argument refer to an opts array containing a "domain" option.
This normalization makes one more help-related change:
it renames the net-start "name" argument to the more
sensible and consistent "network".
* src/virsh.c (VSH_BYNAME, vshCommandOptDomain)
(cmd_has_option): New function, used in vshCommandOptDomainBy
and vshCommandOptNetworkBy.
(vshCommandOptDomainBy, vshCommandOptNetworkBy): Remove the optname
parameter, it's always "domain" ("network"). Update all callers.
Call cmd_has_option.
(vshCommandOptNetwork, cmdAutostart, cmdConsole, cmdDomstate)
(cmdDomblkstat, cmdDomIfstat, cmdSuspend, cmdUndefine, cmdStart)
(cmdSave, cmdSchedinfo, cmdDump, cmdResume, cmdShutdown)
(cmdReboot, cmdDestroy, cmdDominfo, cmdVcpuinfo, cmdVcpupin)
(cmdSetvcpus, cmdSetmem, cmdSetmaxmem, cmdDumpXML, cmdDomname)
(cmdDomid, cmdDomuuid, cmdMigrate, cmdNetworkAutostart)
(cmdNetworkDestroy, cmdNetworkDumpXML, cmdNetworkName)
(opts_network_start, cmdNetworkStart, cmdNetworkUndefine)
(cmdNetworkUuid, cmdVNCDisplay, cmdTTYConsole, cmdAttachDevice)
(cmdDetachDevice, cmdAttachInterface, cmdDetachInterface)
(cmdAttachDisk, cmdDetachDisk, cmdEdit)
* src/Makefile.am (virsh-pool-edit.c): This code is generated
from cmdEdit, and cmdEdit uses the vshCommandOptDomain macro which
now, with the changes above, has only 3 (was 4) arguments, yet the
macro use is mapped to vshCommandOptPool, which still requires 4
arguments. So this change adjusts the sed code to reinsert the
just-removed argument -- we're not changing pool-related code right
now, because it's not as straight-forward.
2008-12-15 13:26:54 +03:00
const char * optname = " domain " ;
2012-07-11 10:17:28 +04:00
if ( ! cmd_has_option ( ctl , cmd , optname ) )
remove redundant optname arguments
This is the second part of the change mentioned here:
http://thread.gmane.org/gmane.comp.emulators.libvirt/10331
It removes the essentially redundant "optname" parameter
from each of the vshCommandOptNetworkBy and vshCommandOptDomainBy
functions as well as the correspond macros (without "By" suffix).
Now, instead of always passing the optname, "domain", to
vshCommandOptDomainBy, that function requires that its command
argument refer to an opts array containing a "domain" option.
This normalization makes one more help-related change:
it renames the net-start "name" argument to the more
sensible and consistent "network".
* src/virsh.c (VSH_BYNAME, vshCommandOptDomain)
(cmd_has_option): New function, used in vshCommandOptDomainBy
and vshCommandOptNetworkBy.
(vshCommandOptDomainBy, vshCommandOptNetworkBy): Remove the optname
parameter, it's always "domain" ("network"). Update all callers.
Call cmd_has_option.
(vshCommandOptNetwork, cmdAutostart, cmdConsole, cmdDomstate)
(cmdDomblkstat, cmdDomIfstat, cmdSuspend, cmdUndefine, cmdStart)
(cmdSave, cmdSchedinfo, cmdDump, cmdResume, cmdShutdown)
(cmdReboot, cmdDestroy, cmdDominfo, cmdVcpuinfo, cmdVcpupin)
(cmdSetvcpus, cmdSetmem, cmdSetmaxmem, cmdDumpXML, cmdDomname)
(cmdDomid, cmdDomuuid, cmdMigrate, cmdNetworkAutostart)
(cmdNetworkDestroy, cmdNetworkDumpXML, cmdNetworkName)
(opts_network_start, cmdNetworkStart, cmdNetworkUndefine)
(cmdNetworkUuid, cmdVNCDisplay, cmdTTYConsole, cmdAttachDevice)
(cmdDetachDevice, cmdAttachInterface, cmdDetachInterface)
(cmdAttachDisk, cmdDetachDisk, cmdEdit)
* src/Makefile.am (virsh-pool-edit.c): This code is generated
from cmdEdit, and cmdEdit uses the vshCommandOptDomain macro which
now, with the changes above, has only 3 (was 4) arguments, yet the
macro use is mapped to vshCommandOptPool, which still requires 4
arguments. So this change adjusts the sed code to reinsert the
just-removed argument -- we're not changing pool-related code right
now, because it's not as straight-forward.
2008-12-15 13:26:54 +03:00
return NULL ;
2006-03-15 15:13:25 +03:00
2011-03-08 19:29:31 +03:00
if ( vshCommandOptString ( cmd , optname , & n ) < = 0 )
2006-03-15 15:13:25 +03:00
return NULL ;
2011-06-30 12:22:20 +04:00
vshDebug ( ctl , VSH_ERR_INFO , " %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 */
2007-02-14 18:44:58 +03:00
if ( flag & VSH_BYID ) {
2008-02-08 12:15:16 +03:00
if ( virStrToLong_i ( n , NULL , 10 , & id ) = = 0 & & id > = 0 ) {
2011-06-30 12:22:20 +04:00
vshDebug ( ctl , VSH_ERR_DEBUG ,
" %s: <%s> seems like domain ID \n " ,
2006-05-29 19:39:31 +04:00
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 */
2007-02-14 18:44:58 +03:00
if ( dom = = NULL & & ( flag & VSH_BYUUID ) & & strlen ( n ) = = VIR_UUID_STRING_BUFLEN - 1 ) {
2011-06-30 12:22:20 +04:00
vshDebug ( ctl , VSH_ERR_DEBUG , " %s: <%s> trying as domain UUID \n " ,
2007-02-07 16:50:18 +03:00
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 */
2007-02-14 18:44:58 +03:00
if ( dom = = NULL & & ( flag & VSH_BYNAME ) ) {
2011-06-30 12:22:20 +04:00
vshDebug ( ctl , VSH_ERR_DEBUG , " %s: <%s> trying 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 )
2009-09-29 15:42:42 +04:00
vshError ( ctl , _ ( " failed to get domain '%s' " ) , n ) ;
2006-03-15 15:13:25 +03:00
2005-12-15 20:00:43 +03:00
return dom ;
}
2007-02-14 19:53:55 +03:00
static virNetworkPtr
remove redundant optname arguments
This is the second part of the change mentioned here:
http://thread.gmane.org/gmane.comp.emulators.libvirt/10331
It removes the essentially redundant "optname" parameter
from each of the vshCommandOptNetworkBy and vshCommandOptDomainBy
functions as well as the correspond macros (without "By" suffix).
Now, instead of always passing the optname, "domain", to
vshCommandOptDomainBy, that function requires that its command
argument refer to an opts array containing a "domain" option.
This normalization makes one more help-related change:
it renames the net-start "name" argument to the more
sensible and consistent "network".
* src/virsh.c (VSH_BYNAME, vshCommandOptDomain)
(cmd_has_option): New function, used in vshCommandOptDomainBy
and vshCommandOptNetworkBy.
(vshCommandOptDomainBy, vshCommandOptNetworkBy): Remove the optname
parameter, it's always "domain" ("network"). Update all callers.
Call cmd_has_option.
(vshCommandOptNetwork, cmdAutostart, cmdConsole, cmdDomstate)
(cmdDomblkstat, cmdDomIfstat, cmdSuspend, cmdUndefine, cmdStart)
(cmdSave, cmdSchedinfo, cmdDump, cmdResume, cmdShutdown)
(cmdReboot, cmdDestroy, cmdDominfo, cmdVcpuinfo, cmdVcpupin)
(cmdSetvcpus, cmdSetmem, cmdSetmaxmem, cmdDumpXML, cmdDomname)
(cmdDomid, cmdDomuuid, cmdMigrate, cmdNetworkAutostart)
(cmdNetworkDestroy, cmdNetworkDumpXML, cmdNetworkName)
(opts_network_start, cmdNetworkStart, cmdNetworkUndefine)
(cmdNetworkUuid, cmdVNCDisplay, cmdTTYConsole, cmdAttachDevice)
(cmdDetachDevice, cmdAttachInterface, cmdDetachInterface)
(cmdAttachDisk, cmdDetachDisk, cmdEdit)
* src/Makefile.am (virsh-pool-edit.c): This code is generated
from cmdEdit, and cmdEdit uses the vshCommandOptDomain macro which
now, with the changes above, has only 3 (was 4) arguments, yet the
macro use is mapped to vshCommandOptPool, which still requires 4
arguments. So this change adjusts the sed code to reinsert the
just-removed argument -- we're not changing pool-related code right
now, because it's not as straight-forward.
2008-12-15 13:26:54 +03:00
vshCommandOptNetworkBy ( vshControl * ctl , const vshCmd * cmd ,
2011-03-08 19:29:30 +03:00
const char * * name , int flag )
2007-02-14 19:53:55 +03:00
{
virNetworkPtr network = NULL ;
2011-03-08 19:29:31 +03:00
const char * n = NULL ;
remove redundant optname arguments
This is the second part of the change mentioned here:
http://thread.gmane.org/gmane.comp.emulators.libvirt/10331
It removes the essentially redundant "optname" parameter
from each of the vshCommandOptNetworkBy and vshCommandOptDomainBy
functions as well as the correspond macros (without "By" suffix).
Now, instead of always passing the optname, "domain", to
vshCommandOptDomainBy, that function requires that its command
argument refer to an opts array containing a "domain" option.
This normalization makes one more help-related change:
it renames the net-start "name" argument to the more
sensible and consistent "network".
* src/virsh.c (VSH_BYNAME, vshCommandOptDomain)
(cmd_has_option): New function, used in vshCommandOptDomainBy
and vshCommandOptNetworkBy.
(vshCommandOptDomainBy, vshCommandOptNetworkBy): Remove the optname
parameter, it's always "domain" ("network"). Update all callers.
Call cmd_has_option.
(vshCommandOptNetwork, cmdAutostart, cmdConsole, cmdDomstate)
(cmdDomblkstat, cmdDomIfstat, cmdSuspend, cmdUndefine, cmdStart)
(cmdSave, cmdSchedinfo, cmdDump, cmdResume, cmdShutdown)
(cmdReboot, cmdDestroy, cmdDominfo, cmdVcpuinfo, cmdVcpupin)
(cmdSetvcpus, cmdSetmem, cmdSetmaxmem, cmdDumpXML, cmdDomname)
(cmdDomid, cmdDomuuid, cmdMigrate, cmdNetworkAutostart)
(cmdNetworkDestroy, cmdNetworkDumpXML, cmdNetworkName)
(opts_network_start, cmdNetworkStart, cmdNetworkUndefine)
(cmdNetworkUuid, cmdVNCDisplay, cmdTTYConsole, cmdAttachDevice)
(cmdDetachDevice, cmdAttachInterface, cmdDetachInterface)
(cmdAttachDisk, cmdDetachDisk, cmdEdit)
* src/Makefile.am (virsh-pool-edit.c): This code is generated
from cmdEdit, and cmdEdit uses the vshCommandOptDomain macro which
now, with the changes above, has only 3 (was 4) arguments, yet the
macro use is mapped to vshCommandOptPool, which still requires 4
arguments. So this change adjusts the sed code to reinsert the
just-removed argument -- we're not changing pool-related code right
now, because it's not as straight-forward.
2008-12-15 13:26:54 +03:00
const char * optname = " network " ;
2012-07-11 10:17:28 +04:00
if ( ! cmd_has_option ( ctl , cmd , optname ) )
remove redundant optname arguments
This is the second part of the change mentioned here:
http://thread.gmane.org/gmane.comp.emulators.libvirt/10331
It removes the essentially redundant "optname" parameter
from each of the vshCommandOptNetworkBy and vshCommandOptDomainBy
functions as well as the correspond macros (without "By" suffix).
Now, instead of always passing the optname, "domain", to
vshCommandOptDomainBy, that function requires that its command
argument refer to an opts array containing a "domain" option.
This normalization makes one more help-related change:
it renames the net-start "name" argument to the more
sensible and consistent "network".
* src/virsh.c (VSH_BYNAME, vshCommandOptDomain)
(cmd_has_option): New function, used in vshCommandOptDomainBy
and vshCommandOptNetworkBy.
(vshCommandOptDomainBy, vshCommandOptNetworkBy): Remove the optname
parameter, it's always "domain" ("network"). Update all callers.
Call cmd_has_option.
(vshCommandOptNetwork, cmdAutostart, cmdConsole, cmdDomstate)
(cmdDomblkstat, cmdDomIfstat, cmdSuspend, cmdUndefine, cmdStart)
(cmdSave, cmdSchedinfo, cmdDump, cmdResume, cmdShutdown)
(cmdReboot, cmdDestroy, cmdDominfo, cmdVcpuinfo, cmdVcpupin)
(cmdSetvcpus, cmdSetmem, cmdSetmaxmem, cmdDumpXML, cmdDomname)
(cmdDomid, cmdDomuuid, cmdMigrate, cmdNetworkAutostart)
(cmdNetworkDestroy, cmdNetworkDumpXML, cmdNetworkName)
(opts_network_start, cmdNetworkStart, cmdNetworkUndefine)
(cmdNetworkUuid, cmdVNCDisplay, cmdTTYConsole, cmdAttachDevice)
(cmdDetachDevice, cmdAttachInterface, cmdDetachInterface)
(cmdAttachDisk, cmdDetachDisk, cmdEdit)
* src/Makefile.am (virsh-pool-edit.c): This code is generated
from cmdEdit, and cmdEdit uses the vshCommandOptDomain macro which
now, with the changes above, has only 3 (was 4) arguments, yet the
macro use is mapped to vshCommandOptPool, which still requires 4
arguments. So this change adjusts the sed code to reinsert the
just-removed argument -- we're not changing pool-related code right
now, because it's not as straight-forward.
2008-12-15 13:26:54 +03:00
return NULL ;
2007-02-14 19:53:55 +03:00
2011-03-08 19:29:31 +03:00
if ( vshCommandOptString ( cmd , optname , & n ) < = 0 )
2007-02-14 19:53:55 +03:00
return NULL ;
2011-06-30 12:22:20 +04:00
vshDebug ( ctl , VSH_ERR_INFO , " %s: found option <%s>: %s \n " ,
2007-02-14 19:53:55 +03:00
cmd - > def - > name , optname , n ) ;
if ( name )
* name = n ;
/* try it by UUID */
2012-04-15 02:35:22 +04:00
if ( ( flag & VSH_BYUUID ) & & strlen ( n ) = = VIR_UUID_STRING_BUFLEN - 1 ) {
2011-06-30 12:22:20 +04:00
vshDebug ( ctl , VSH_ERR_DEBUG , " %s: <%s> trying as network UUID \n " ,
2008-04-10 20:54:54 +04:00
cmd - > def - > name , optname ) ;
2007-02-14 19:53:55 +03:00
network = virNetworkLookupByUUIDString ( ctl - > conn , n ) ;
}
/* try it by NAME */
if ( network = = NULL & & ( flag & VSH_BYNAME ) ) {
2011-06-30 12:22:20 +04:00
vshDebug ( ctl , VSH_ERR_DEBUG , " %s: <%s> trying as network NAME \n " ,
2007-02-14 19:53:55 +03:00
cmd - > def - > name , optname ) ;
network = virNetworkLookupByName ( ctl - > conn , n ) ;
}
if ( ! network )
2009-09-29 15:42:42 +04:00
vshError ( ctl , _ ( " failed to get network '%s' " ) , n ) ;
2007-02-14 19:53:55 +03:00
return network ;
}
2010-03-25 20:46:06 +03:00
static virNWFilterPtr
vshCommandOptNWFilterBy ( vshControl * ctl , const vshCmd * cmd ,
2011-03-08 19:29:30 +03:00
const char * * name , int flag )
2010-03-25 20:46:06 +03:00
{
virNWFilterPtr nwfilter = NULL ;
2011-03-08 19:29:31 +03:00
const char * n = NULL ;
2010-03-25 20:46:06 +03:00
const char * optname = " nwfilter " ;
2012-07-11 10:17:28 +04:00
if ( ! cmd_has_option ( ctl , cmd , optname ) )
2010-03-25 20:46:06 +03:00
return NULL ;
2011-03-08 19:29:31 +03:00
if ( vshCommandOptString ( cmd , optname , & n ) < = 0 )
2010-03-25 20:46:06 +03:00
return NULL ;
2011-06-30 12:22:20 +04:00
vshDebug ( ctl , VSH_ERR_INFO , " %s: found option <%s>: %s \n " ,
2010-03-25 20:46:06 +03:00
cmd - > def - > name , optname , n ) ;
if ( name )
* name = n ;
/* try it by UUID */
2012-04-15 02:35:22 +04:00
if ( ( flag & VSH_BYUUID ) & & strlen ( n ) = = VIR_UUID_STRING_BUFLEN - 1 ) {
2011-06-30 12:22:20 +04:00
vshDebug ( ctl , VSH_ERR_DEBUG , " %s: <%s> trying as nwfilter UUID \n " ,
2010-03-25 20:46:06 +03:00
cmd - > def - > name , optname ) ;
nwfilter = virNWFilterLookupByUUIDString ( ctl - > conn , n ) ;
}
/* try it by NAME */
if ( nwfilter = = NULL & & ( flag & VSH_BYNAME ) ) {
2011-06-30 12:22:20 +04:00
vshDebug ( ctl , VSH_ERR_DEBUG , " %s: <%s> trying as nwfilter NAME \n " ,
2010-03-25 20:46:06 +03:00
cmd - > def - > name , optname ) ;
nwfilter = virNWFilterLookupByName ( ctl - > conn , n ) ;
}
if ( ! nwfilter )
vshError ( ctl , _ ( " failed to get nwfilter '%s' " ) , n ) ;
return nwfilter ;
}
2009-07-16 23:44:10 +04:00
static virInterfacePtr
vshCommandOptInterfaceBy ( vshControl * ctl , const vshCmd * cmd ,
virsh: add iface-bridge and iface-unbridge commands
One of the top questions by libvirt users is how to create a host
bridge device so that guests can be directly on the physical
network. There are several example documents that explain how to do
this manually, but following them often results in confusion and
failure. virt-manager does a good job of creating a bridge based on an
existing network device, but not everyone wants to use virt-manager.
This patch adds a new command, iface-bridge that makes it just about
as simple as possible to create a new bridge device based on an
existing ethernet/vlan/bond device (including associating IP
configuration with the bridge rather than the now-attached device),
and start that new bridge up ready for action, eg:
virsh iface-bridge eth0 br0
For symmetry's sake, it also adds a command to remove a device from a
bridge, restoring the IP config to the now-unattached device:
virsh iface-unbridge br0
(I had a short debate about whether to do "iface-unbridge eth0"
instead, but that would involve searching through all bridge devices
for the one that contained eth0, which seems like a bit too much
trouble).
NOTE: These two commands require that the netcf library be available
on the host. Hopefully this will provide some extra incentive for
people using suse, debian, ubuntu, and other similar systems to polish
up (and push downstream) the ports to those distros recently pushed to
the upstream netcf repo by Dan Berrange. Anyone interested in helping
with that effort in any way should join the netcf-devel mailing list
(subscription info at
https://fedorahosted.org/mailman/listinfo/netcf-devel)
During creation of the bridge, it's possible to specify whether or not
the STP protocol should be started up on the bridge and, if so, how
many seconds the bridge should squelch traffic from newly added
devices while learning new topology (defaults are stp='on' and
delay='0', which seems to usually work best for bridges used in the
context of libvirt guests).
There is also an option to not immediately start the bridge (and a
similar option to not immediately start the un-attached device after
destroying the bridge. Default is to start the new device, because in
the case of iface-unbridge not starting is strongly discouraged as it
will leave the system with no network connectivity on that interface
(because it's necessary to destroy/undefine the bridge device before
the unattached device can be defined), and it seemed better to make
the option for iface-bridge behave consistently.
NOTE TO THOSE TRYING THESE COMMANDS FOR THE FIRST TIME: to guard
against any "unexpected" change to configuration, it is advisable to
issue an "virsh iface-begin" command before starting any interface
config changes, and "virsh iface-commit" only after you've verified
that everything is working as you expect. If something goes wrong,
you can always run "virsh iface-rollback" or reboot the system (which
should automatically do iface-rollback).
Aside from adding the code for these two functions, and the two
entries into the command table, the only other change to virsh.c was
to add the option name to vshCommandOptInterfaceBy(), because the
iface-unbridge command names its interface option as "bridge".
virsh.pod has also been updated with short descriptions of these two
new commands.
2011-11-07 20:15:58 +04:00
const char * optname ,
2011-03-08 19:29:30 +03:00
const char * * name , int flag )
2009-07-16 23:44:10 +04:00
{
virInterfacePtr iface = NULL ;
2011-03-08 19:29:31 +03:00
const char * n = NULL ;
virsh: add iface-bridge and iface-unbridge commands
One of the top questions by libvirt users is how to create a host
bridge device so that guests can be directly on the physical
network. There are several example documents that explain how to do
this manually, but following them often results in confusion and
failure. virt-manager does a good job of creating a bridge based on an
existing network device, but not everyone wants to use virt-manager.
This patch adds a new command, iface-bridge that makes it just about
as simple as possible to create a new bridge device based on an
existing ethernet/vlan/bond device (including associating IP
configuration with the bridge rather than the now-attached device),
and start that new bridge up ready for action, eg:
virsh iface-bridge eth0 br0
For symmetry's sake, it also adds a command to remove a device from a
bridge, restoring the IP config to the now-unattached device:
virsh iface-unbridge br0
(I had a short debate about whether to do "iface-unbridge eth0"
instead, but that would involve searching through all bridge devices
for the one that contained eth0, which seems like a bit too much
trouble).
NOTE: These two commands require that the netcf library be available
on the host. Hopefully this will provide some extra incentive for
people using suse, debian, ubuntu, and other similar systems to polish
up (and push downstream) the ports to those distros recently pushed to
the upstream netcf repo by Dan Berrange. Anyone interested in helping
with that effort in any way should join the netcf-devel mailing list
(subscription info at
https://fedorahosted.org/mailman/listinfo/netcf-devel)
During creation of the bridge, it's possible to specify whether or not
the STP protocol should be started up on the bridge and, if so, how
many seconds the bridge should squelch traffic from newly added
devices while learning new topology (defaults are stp='on' and
delay='0', which seems to usually work best for bridges used in the
context of libvirt guests).
There is also an option to not immediately start the bridge (and a
similar option to not immediately start the un-attached device after
destroying the bridge. Default is to start the new device, because in
the case of iface-unbridge not starting is strongly discouraged as it
will leave the system with no network connectivity on that interface
(because it's necessary to destroy/undefine the bridge device before
the unattached device can be defined), and it seemed better to make
the option for iface-bridge behave consistently.
NOTE TO THOSE TRYING THESE COMMANDS FOR THE FIRST TIME: to guard
against any "unexpected" change to configuration, it is advisable to
issue an "virsh iface-begin" command before starting any interface
config changes, and "virsh iface-commit" only after you've verified
that everything is working as you expect. If something goes wrong,
you can always run "virsh iface-rollback" or reboot the system (which
should automatically do iface-rollback).
Aside from adding the code for these two functions, and the two
entries into the command table, the only other change to virsh.c was
to add the option name to vshCommandOptInterfaceBy(), because the
iface-unbridge command names its interface option as "bridge".
virsh.pod has also been updated with short descriptions of these two
new commands.
2011-11-07 20:15:58 +04:00
if ( ! optname )
optname = " interface " ;
2012-07-11 10:17:28 +04:00
if ( ! cmd_has_option ( ctl , cmd , optname ) )
2009-07-16 23:44:10 +04:00
return NULL ;
2011-03-08 19:29:31 +03:00
if ( vshCommandOptString ( cmd , optname , & n ) < = 0 )
2009-07-16 23:44:10 +04:00
return NULL ;
2011-06-30 12:22:20 +04:00
vshDebug ( ctl , VSH_ERR_INFO , " %s: found option <%s>: %s \n " ,
2009-07-16 23:44:10 +04:00
cmd - > def - > name , optname , n ) ;
if ( name )
* name = n ;
/* try it by NAME */
2012-04-15 02:35:22 +04:00
if ( flag & VSH_BYNAME ) {
2011-06-30 12:22:20 +04:00
vshDebug ( ctl , VSH_ERR_DEBUG , " %s: <%s> trying as interface NAME \n " ,
2009-07-16 23:44:10 +04:00
cmd - > def - > name , optname ) ;
iface = virInterfaceLookupByName ( ctl - > conn , n ) ;
}
/* try it by MAC */
2012-04-15 02:35:22 +04:00
if ( iface = = NULL & & ( flag & VSH_BYMAC ) ) {
2011-06-30 12:22:20 +04:00
vshDebug ( ctl , VSH_ERR_DEBUG , " %s: <%s> trying as interface MAC \n " ,
2009-07-16 23:44:10 +04:00
cmd - > def - > name , optname ) ;
iface = virInterfaceLookupByMACString ( ctl - > conn , n ) ;
}
if ( ! iface )
2009-09-29 15:42:42 +04:00
vshError ( ctl , _ ( " failed to get interface '%s' " ) , n ) ;
2009-07-16 23:44:10 +04:00
return iface ;
}
2009-07-28 14:27:25 +04:00
static virSecretPtr
2011-03-08 19:29:30 +03:00
vshCommandOptSecret ( vshControl * ctl , const vshCmd * cmd , const char * * name )
2009-07-28 14:27:25 +04:00
{
virSecretPtr secret = NULL ;
2011-03-08 19:29:31 +03:00
const char * n = NULL ;
2009-07-28 14:27:25 +04:00
const char * optname = " secret " ;
2012-07-11 10:17:28 +04:00
if ( ! cmd_has_option ( ctl , cmd , optname ) )
2009-07-28 14:27:25 +04:00
return NULL ;
2011-03-08 19:29:31 +03:00
if ( vshCommandOptString ( cmd , optname , & n ) < = 0 )
2009-07-28 14:27:25 +04:00
return NULL ;
2011-06-30 12:22:20 +04:00
vshDebug ( ctl , VSH_ERR_DEBUG ,
" %s: found option <%s>: %s \n " , cmd - > def - > name , optname , n ) ;
2009-07-28 14:27:25 +04:00
if ( name ! = NULL )
* name = n ;
secret = virSecretLookupByUUIDString ( ctl - > conn , n ) ;
if ( secret = = NULL )
2009-09-29 15:42:42 +04:00
vshError ( ctl , _ ( " failed to get secret '%s' " ) , n ) ;
2009-07-28 14:27:25 +04:00
return secret ;
}
2005-12-08 13:23:34 +03:00
/*
* Executes command ( s ) and returns return code from last command
*/
2011-04-19 02:37:42 +04:00
static bool
2008-08-01 17:51:18 +04:00
vshCommandRun ( vshControl * ctl , const vshCmd * cmd )
2006-03-15 15:13:25 +03:00
{
2011-04-19 02:37:42 +04:00
bool ret = true ;
2006-03-15 15:13:25 +03:00
while ( cmd ) {
2005-12-08 13:23:34 +03:00
struct timeval before , after ;
2010-04-14 11:04:28 +04:00
bool enable_timing = ctl - > timing ;
2006-03-15 15:13:25 +03:00
virsh: optimize creation of default connection
Ramon de Carvalho Valle reported a problem with:
virsh connect qemu:///system
as a non-root user. The real root problem appears to be a regression
in libvirtd being auto-started on the default qemu:///session URI;
however, the symptom points to an independent flaw in virsh - we
shouldn't be wasting efforts on making a connection if we aren't going
to be using that connection. Fixing virsh avoids Ramon's issue, while
I work in the meantime to fix the real libvirtd regression.
This patch looks big, but that's because 'gcc -Wmissing-field-initializers'
gets triggered by './autobuild.sh --enable-compile-warnings=error', so I
had to add 0 initialization to everyone (rather than my preference of
just adding the non-zero flags to virshCmds and to cmdConnect).
Meanwhile, if you use 'virsh -c URI', the connection must succeed; this
patch _only_ optimizes the default connection to be deferred to a later
point where we know if a particular command to be run needs a connection.
* tools/virsh.c (VSH_CMD_FLAG_NOCONNECT): New flag.
(vshCmdDef): Add new flags field.
(vshCommandRun): Honor new flag.
(domManagementCmds, domMonitoringCmds, storagePoolCmds)
(storageVolCmds, networkCmds, nodedevCmds, ifaceCmds)
(nwfilterCmds, secretCmds, virshCmds, snapshotCmds)
(hostAndHypervisorCmds): Populate new field.
(vshReconnect): Don't warn on initial connection.
2011-03-14 23:30:24 +03:00
if ( ( ctl - > conn = = NULL | | disconnected ) & &
! ( cmd - > def - > flags & VSH_CMD_FLAG_NOCONNECT ) )
2010-03-05 12:59:52 +03:00
vshReconnect ( ctl ) ;
2010-04-14 11:04:28 +04:00
if ( enable_timing )
2005-12-08 13:23:34 +03:00
GETTIMEOFDAY ( & before ) ;
2006-03-15 15:13:25 +03:00
2005-12-08 13:23:34 +03:00
ret = cmd - > def - > handler ( ctl , cmd ) ;
2010-04-14 11:04:28 +04:00
if ( enable_timing )
2005-12-08 13:23:34 +03:00
GETTIMEOFDAY ( & after ) ;
2006-03-15 15:13:25 +03:00
2012-01-02 20:07:31 +04:00
/* try to automatically catch disconnections */
if ( ! ret & &
( ( last_error ! = NULL ) & &
( ( ( last_error - > code = = VIR_ERR_SYSTEM_ERROR ) & &
( last_error - > domain = = VIR_FROM_REMOTE ) ) | |
( last_error - > code = = VIR_ERR_RPC ) | |
( last_error - > code = = VIR_ERR_NO_CONNECT ) | |
( last_error - > code = = VIR_ERR_INVALID_CONN ) ) ) )
disconnected + + ;
2011-05-06 00:27:51 +04:00
if ( ! ret )
2009-02-09 17:24:06 +03:00
virshReportError ( ctl ) ;
2012-01-02 20:07:31 +04:00
if ( ! ret & & disconnected ! = 0 )
2010-03-05 12:59:52 +03:00
vshReconnect ( ctl ) ;
2008-05-14 23:51:24 +04:00
if ( STREQ ( cmd - > def - > name , " quit " ) ) /* hack ... */
2005-12-08 13:23:34 +03:00
return ret ;
2010-04-14 11:04:28 +04:00
if ( enable_timing )
2006-09-21 19:24:37 +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 ;
}
/* ---------------
2010-10-13 02:01:02 +04:00
* Command parsing
2005-12-08 13:23:34 +03:00
* - - - - - - - - - - - - - - -
*/
2010-10-12 11:13:50 +04:00
typedef enum {
VSH_TK_ERROR , /* Failed to parse a token */
VSH_TK_ARG , /* Arbitrary argument, might be option or empty */
VSH_TK_SUBCMD_END , /* Separation between commands */
VSH_TK_END /* No more commands */
} vshCommandToken ;
typedef struct __vshCommandParser {
2012-07-11 10:17:28 +04:00
vshCommandToken ( * getNextArg ) ( vshControl * , struct __vshCommandParser * ,
2010-10-12 11:13:50 +04:00
char * * ) ;
2010-10-12 11:14:01 +04:00
/* vshCommandStringGetArg() */
2010-10-12 11:13:50 +04:00
char * pos ;
2010-10-12 11:14:01 +04:00
/* vshCommandArgvGetArg() */
char * * arg_pos ;
char * * arg_end ;
2010-10-12 11:13:50 +04:00
} vshCommandParser ;
2011-04-19 02:37:42 +04:00
static bool
2010-10-12 11:13:50 +04:00
vshCommandParse ( vshControl * ctl , vshCommandParser * parser )
2006-03-15 15:13:25 +03:00
{
2005-12-08 13:23:34 +03:00
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
2010-10-12 11:13:50 +04:00
while ( 1 ) {
2005-12-08 13:23:34 +03:00
vshCmdOpt * last = NULL ;
2008-08-01 16:19:56 +04:00
const vshCmdDef * cmd = NULL ;
2010-10-12 11:13:50 +04:00
vshCommandToken tk ;
2010-10-12 11:14:22 +04:00
bool data_only = false ;
2011-04-13 00:42:59 +04:00
uint32_t opts_need_arg = 0 ;
uint32_t opts_required = 0 ;
uint32_t opts_seen = 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
2010-10-12 11:13:50 +04:00
while ( 1 ) {
2008-08-01 16:19:56 +04:00
const vshCmdOptDef * opt = NULL ;
2006-03-15 15:13:25 +03:00
2005-12-08 13:23:34 +03:00
tkdata = NULL ;
2010-10-12 11:13:50 +04:00
tk = parser - > getNextArg ( ctl , parser , & tkdata ) ;
2006-03-15 15:13:25 +03:00
if ( tk = = VSH_TK_ERROR )
2005-12-08 13:23:34 +03:00
goto syntaxError ;
2010-12-22 10:12:34 +03:00
if ( tk ! = VSH_TK_ARG ) {
VIR_FREE ( tkdata ) ;
2010-10-12 11:13:50 +04:00
break ;
2010-12-22 10:12:34 +03:00
}
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 */
if ( ! ( cmd = vshCmddefSearch ( tkdata ) ) ) {
2009-09-29 15:42:42 +04:00
vshError ( ctl , _ ( " unknown command: '%s' " ) , tkdata ) ;
2006-03-15 15:13:25 +03:00
goto syntaxError ; /* ... or ignore this command only? */
2005-12-08 13:23:34 +03:00
}
2011-04-13 00:42:59 +04:00
if ( vshCmddefOptParse ( cmd , & opts_need_arg ,
& opts_required ) < 0 ) {
vshError ( ctl ,
_ ( " internal error: bad options in command: '%s' " ) ,
tkdata ) ;
goto syntaxError ;
}
2010-01-03 19:13:27 +03:00
VIR_FREE ( tkdata ) ;
2010-10-12 11:14:22 +04:00
} else if ( data_only ) {
goto get_data ;
} else if ( tkdata [ 0 ] = = ' - ' & & tkdata [ 1 ] = = ' - ' & &
c_isalnum ( tkdata [ 2 ] ) ) {
2010-10-12 11:13:39 +04:00
char * optstr = strchr ( tkdata + 2 , ' = ' ) ;
2011-09-21 18:54:47 +04:00
int opt_index ;
2010-10-12 11:13:39 +04:00
if ( optstr ) {
* optstr = ' \0 ' ; /* convert the '=' to '\0' */
optstr = vshStrdup ( ctl , optstr + 1 ) ;
}
2011-04-13 00:42:59 +04:00
if ( ! ( opt = vshCmddefGetOption ( ctl , cmd , tkdata + 2 ,
2011-09-21 18:54:47 +04:00
& opts_seen , & opt_index ) ) ) {
2010-10-12 11:13:39 +04:00
VIR_FREE ( optstr ) ;
2005-12-08 13:23:34 +03:00
goto syntaxError ;
}
2010-10-12 11:13:39 +04:00
VIR_FREE ( tkdata ) ;
2005-12-08 13:23:34 +03:00
if ( opt - > type ! = VSH_OT_BOOL ) {
/* option data */
2010-10-12 11:13:39 +04:00
if ( optstr )
tkdata = optstr ;
else
2010-10-12 11:13:50 +04:00
tk = parser - > getNextArg ( ctl , parser , & tkdata ) ;
2006-03-15 15:13:25 +03:00
if ( tk = = VSH_TK_ERROR )
2005-12-08 13:23:34 +03:00
goto syntaxError ;
2010-10-12 11:13:50 +04:00
if ( tk ! = VSH_TK_ARG ) {
2009-09-29 15:42:42 +04:00
vshError ( ctl ,
2006-09-21 19:24:37 +04:00
_ ( " expected syntax: --%s <%s> " ) ,
2006-03-15 15:13:25 +03:00
opt - > name ,
opt - > type = =
2006-09-21 19:24:37 +04:00
VSH_OT_INT ? _ ( " number " ) : _ ( " string " ) ) ;
2005-12-08 13:23:34 +03:00
goto syntaxError ;
}
2011-09-21 18:54:47 +04:00
if ( opt - > type ! = VSH_OT_ARGV )
opts_need_arg & = ~ ( 1 < < opt_index ) ;
2010-10-12 11:13:39 +04:00
} else {
tkdata = NULL ;
if ( optstr ) {
vshError ( ctl , _ ( " invalid '=' after option --%s " ) ,
opt - > name ) ;
VIR_FREE ( optstr ) ;
goto syntaxError ;
}
2005-12-08 13:23:34 +03:00
}
2010-10-12 11:14:22 +04:00
} else if ( tkdata [ 0 ] = = ' - ' & & tkdata [ 1 ] = = ' - ' & &
tkdata [ 2 ] = = ' \0 ' ) {
data_only = true ;
continue ;
2010-10-12 11:13:50 +04:00
} else {
2010-10-12 11:14:22 +04:00
get_data :
2011-04-13 00:42:59 +04:00
if ( ! ( opt = vshCmddefGetData ( cmd , & opts_need_arg ,
& opts_seen ) ) ) {
2009-09-29 15:42:42 +04:00
vshError ( ctl , _ ( " 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
2011-06-30 12:22:20 +04:00
vshDebug ( ctl , VSH_ERR_INFO , " %s: %s(%s): %s \n " ,
2006-03-15 15:13:25 +03:00
cmd - > name ,
opt - > name ,
2010-10-12 11:13:39 +04:00
opt - > type ! = VSH_OT_BOOL ? _ ( " optdata " ) : _ ( " bool " ) ,
opt - > type ! = VSH_OT_BOOL ? arg - > data : _ ( " (none) " ) ) ;
2005-12-08 13:23:34 +03:00
}
}
2006-03-15 15:13:25 +03:00
2008-04-04 11:58:29 +04:00
/* command parsed -- allocate new struct for the command */
2005-12-08 13:23:34 +03:00
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 ;
2011-04-13 00:42:59 +04:00
if ( vshCommandCheckOpts ( ctl , c , opts_required , opts_seen ) < 0 ) {
2010-01-03 19:13:27 +03:00
VIR_FREE ( c ) ;
2006-01-25 12:46:22 +03:00
goto syntaxError ;
2007-05-29 17:55:19 +04:00
}
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 ;
}
2010-10-12 11:13:50 +04:00
if ( tk = = VSH_TK_END )
break ;
2005-12-08 13:23:34 +03:00
}
2006-03-15 15:13:25 +03:00
2011-04-19 02:37:42 +04:00
return true ;
2005-12-08 13:23:34 +03:00
2007-02-07 16:50:18 +03:00
syntaxError :
2010-03-12 14:00:46 +03:00
if ( ctl - > cmd ) {
2005-12-08 13:23:34 +03:00
vshCommandFree ( ctl - > cmd ) ;
2010-03-12 14:00:46 +03:00
ctl - > cmd = NULL ;
}
2005-12-08 13:23:34 +03:00
if ( first )
vshCommandOptFree ( first ) ;
2010-01-03 19:13:27 +03:00
VIR_FREE ( tkdata ) ;
2011-04-19 02:37:42 +04:00
return false ;
2005-12-08 13:23:34 +03:00
}
2010-10-13 02:01:02 +04:00
/* --------------------
* Command argv parsing
* - - - - - - - - - - - - - - - - - - - -
*/
static vshCommandToken ATTRIBUTE_NONNULL ( 2 ) ATTRIBUTE_NONNULL ( 3 )
vshCommandArgvGetArg ( vshControl * ctl , vshCommandParser * parser , char * * res )
{
if ( parser - > arg_pos = = parser - > arg_end ) {
* res = NULL ;
return VSH_TK_END ;
}
* res = vshStrdup ( ctl , * parser - > arg_pos ) ;
parser - > arg_pos + + ;
return VSH_TK_ARG ;
}
2011-04-19 02:37:42 +04:00
static bool
vshCommandArgvParse ( vshControl * ctl , int nargs , char * * argv )
2010-10-13 02:01:02 +04:00
{
vshCommandParser parser ;
if ( nargs < = 0 )
2011-04-19 02:37:42 +04:00
return false ;
2010-10-13 02:01:02 +04:00
parser . arg_pos = argv ;
parser . arg_end = argv + nargs ;
parser . getNextArg = vshCommandArgvGetArg ;
return vshCommandParse ( ctl , & parser ) ;
}
/* ----------------------
* Command string parsing
* - - - - - - - - - - - - - - - - - - - - - -
*/
static vshCommandToken ATTRIBUTE_NONNULL ( 2 ) ATTRIBUTE_NONNULL ( 3 )
vshCommandStringGetArg ( vshControl * ctl , vshCommandParser * parser , char * * res )
{
bool single_quote = false ;
bool double_quote = false ;
int sz = 0 ;
char * p = parser - > pos ;
char * q = vshStrdup ( ctl , p ) ;
* res = q ;
while ( * p & & ( * p = = ' ' | | * p = = ' \t ' ) )
p + + ;
if ( * p = = ' \0 ' )
return VSH_TK_END ;
if ( * p = = ' ; ' ) {
parser - > pos = + + p ; /* = \0 or begin of next command */
return VSH_TK_SUBCMD_END ;
}
while ( * p ) {
/* end of token is blank space or ';' */
if ( ! double_quote & & ! single_quote & &
( * p = = ' ' | | * p = = ' \t ' | | * p = = ' ; ' ) )
break ;
if ( ! double_quote & & * p = = ' \' ' ) { /* single quote */
single_quote = ! single_quote ;
p + + ;
continue ;
} else if ( ! single_quote & & * p = = ' \\ ' ) { /* escape */
/*
* The same as the bash , a \ in " " is an escaper ,
* but a \ in ' ' is not an escaper .
*/
p + + ;
if ( * p = = ' \0 ' ) {
vshError ( ctl , " %s " , _ ( " dangling \\ " ) ) ;
return VSH_TK_ERROR ;
}
} else if ( ! single_quote & & * p = = ' " ' ) { /* double quote */
double_quote = ! double_quote ;
p + + ;
continue ;
}
* q + + = * p + + ;
sz + + ;
}
if ( double_quote ) {
vshError ( ctl , " %s " , _ ( " missing \" " ) ) ;
return VSH_TK_ERROR ;
}
* q = ' \0 ' ;
parser - > pos = p ;
return VSH_TK_ARG ;
}
2011-04-19 02:37:42 +04:00
static bool
vshCommandStringParse ( vshControl * ctl , char * cmdstr )
2010-10-13 02:01:02 +04:00
{
vshCommandParser parser ;
if ( cmdstr = = NULL | | * cmdstr = = ' \0 ' )
2011-04-19 02:37:42 +04:00
return false ;
2010-10-13 02:01:02 +04:00
parser . pos = cmdstr ;
parser . getNextArg = vshCommandStringGetArg ;
return vshCommandParse ( ctl , & parser ) ;
}
2005-12-08 13:23:34 +03:00
/* ---------------
2007-02-07 16:50:18 +03:00
* Misc utils
2005-12-08 13:23:34 +03:00
* - - - - - - - - - - - - - - -
*/
2011-04-29 12:20:49 +04:00
static int
vshDomainState ( vshControl * ctl , virDomainPtr dom , int * reason )
{
virDomainInfo info ;
if ( reason )
* reason = - 1 ;
if ( ! ctl - > useGetInfo ) {
int state ;
if ( virDomainGetState ( dom , & state , reason , 0 ) < 0 ) {
virErrorPtr err = virGetLastError ( ) ;
if ( err & & err - > code = = VIR_ERR_NO_SUPPORT )
ctl - > useGetInfo = true ;
else
return - 1 ;
} else {
return state ;
}
}
/* fall back to virDomainGetInfo if virDomainGetState is not supported */
if ( virDomainGetInfo ( dom , & info ) < 0 )
return - 1 ;
else
return info . state ;
}
2011-12-20 03:06:08 +04:00
/* Return a non-NULL string representation of a typed parameter; exit
* if we are out of memory . */
2011-09-19 16:23:12 +04:00
static char *
vshGetTypedParamValue ( vshControl * ctl , virTypedParameterPtr item )
{
int ret = 0 ;
char * str = NULL ;
switch ( item - > type ) {
case VIR_TYPED_PARAM_INT :
ret = virAsprintf ( & str , " %d " , item - > value . i ) ;
break ;
case VIR_TYPED_PARAM_UINT :
ret = virAsprintf ( & str , " %u " , item - > value . ui ) ;
break ;
case VIR_TYPED_PARAM_LLONG :
ret = virAsprintf ( & str , " %lld " , item - > value . l ) ;
break ;
case VIR_TYPED_PARAM_ULLONG :
ret = virAsprintf ( & str , " %llu " , item - > value . ul ) ;
break ;
case VIR_TYPED_PARAM_DOUBLE :
ret = virAsprintf ( & str , " %f " , item - > value . d ) ;
break ;
case VIR_TYPED_PARAM_BOOLEAN :
ret = virAsprintf ( & str , " %s " , item - > value . b ? _ ( " yes " ) : _ ( " no " ) ) ;
break ;
2011-12-20 03:06:08 +04:00
case VIR_TYPED_PARAM_STRING :
str = vshStrdup ( ctl , item - > value . s ) ;
break ;
2011-09-19 16:23:12 +04:00
default :
2011-12-20 03:06:08 +04:00
vshError ( ctl , _ ( " unimplemented parameter type %d " ) , item - > type ) ;
2011-09-19 16:23:12 +04:00
}
2011-12-20 03:06:08 +04:00
if ( ret < 0 ) {
2011-09-19 16:23:12 +04:00
vshError ( ctl , " %s " , _ ( " Out of memory " ) ) ;
2011-12-20 03:06:08 +04:00
exit ( EXIT_FAILURE ) ;
}
2011-09-19 16:23:12 +04:00
return str ;
}
static virTypedParameterPtr
vshFindTypedParamByName ( const char * name , virTypedParameterPtr list , int count )
{
int i = count ;
virTypedParameterPtr found = list ;
if ( ! list | | ! name )
return NULL ;
while ( i - - > 0 ) {
if ( STREQ ( name , found - > field ) )
return found ;
found + + ; /* go to next struct in array */
}
/* not found */
return NULL ;
}
2011-04-19 02:37:42 +04:00
static bool
2010-06-17 18:47:06 +04:00
vshConnectionUsability ( vshControl * ctl , virConnectPtr conn )
2006-03-15 15:13:25 +03:00
{
2007-02-07 16:50:18 +03:00
/* TODO: use something like virConnectionState() to
* check usability of the connection
2005-12-08 13:23:34 +03:00
*/
if ( ! conn ) {
2010-06-17 18:47:06 +04:00
vshError ( ctl , " %s " , _ ( " no valid connection " ) ) ;
2011-04-19 02:37:42 +04:00
return false ;
2005-12-08 13:23:34 +03:00
}
2011-04-19 02:37:42 +04:00
return true ;
2005-12-08 13:23:34 +03:00
}
2006-05-22 18:38:33 +04:00
static void
2008-08-01 17:51:18 +04:00
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 ;
2011-04-29 01:09:08 +04:00
char * str ;
2006-05-22 18:38:33 +04:00
2011-06-30 12:22:32 +04:00
/* Aligning log levels to that of libvirt.
* Traces with levels > = user - specified - level
* gets logged into file
*/
if ( level < ctl - > debug )
return ;
2007-06-06 16:24:31 +04:00
va_start ( ap , format ) ;
2011-06-30 12:22:32 +04:00
vshOutputLogFile ( ctl , level , format , ap ) ;
2007-06-06 16:24:31 +04:00
va_end ( ap ) ;
2006-05-22 18:38:33 +04:00
va_start ( ap , format ) ;
2011-04-29 01:09:08 +04:00
if ( virVasprintf ( & str , format , ap ) < 0 ) {
/* Skip debug messages on low memory */
va_end ( ap ) ;
return ;
}
2006-05-22 18:38:33 +04:00
va_end ( ap ) ;
2011-04-29 01:09:08 +04:00
fputs ( str , stdout ) ;
VIR_FREE ( str ) ;
2005-12-08 13:23:34 +03:00
}
static void
2008-08-01 17:51:18 +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 ;
2011-02-12 03:17:12 +03:00
char * str ;
2006-03-15 15:13:25 +03:00
2011-05-06 00:27:51 +04:00
if ( ctl & & ctl - > quiet )
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 ) ;
2011-02-12 03:17:12 +03:00
if ( virVasprintf ( & str , format , ap ) < 0 ) {
vshError ( ctl , " %s " , _ ( " Out of memory " ) ) ;
va_end ( ap ) ;
return ;
}
2005-12-08 13:23:34 +03:00
va_end ( ap ) ;
2011-04-29 01:09:08 +04:00
fputs ( str , stdout ) ;
2011-02-12 03:17:12 +03:00
VIR_FREE ( str ) ;
2005-12-08 13:23:34 +03:00
}
2006-05-22 18:38:33 +04:00
2005-12-08 13:23:34 +03:00
static void
2009-09-29 15:42:42 +04:00
vshError ( vshControl * ctl , const char * format , . . . )
2006-03-15 15:13:25 +03:00
{
2005-12-08 13:23:34 +03:00
va_list ap ;
2011-02-12 03:17:12 +03:00
char * str ;
2006-03-15 15:13:25 +03:00
2010-03-05 12:59:52 +03:00
if ( ctl ! = NULL ) {
va_start ( ap , format ) ;
vshOutputLogFile ( ctl , VSH_ERR_ERROR , format , ap ) ;
va_end ( ap ) ;
}
2007-06-06 16:24:31 +04:00
2011-08-19 19:20:35 +04:00
/* Most output is to stdout, but if someone ran virsh 2>&1, then
* printing to stderr will not interleave correctly with stdout
* unless we flush between every transition between streams . */
fflush ( stdout ) ;
2009-09-29 15:42:42 +04:00
fputs ( _ ( " error: " ) , stderr ) ;
2006-03-15 15:13:25 +03:00
2005-12-08 13:23:34 +03:00
va_start ( ap , format ) ;
2011-02-12 03:17:12 +03:00
/* We can't recursively call vshError on an OOM situation, so ignore
failure here . */
ignore_value ( virVasprintf ( & str , format , ap ) ) ;
2005-12-08 13:23:34 +03:00
va_end ( ap ) ;
2011-02-12 03:17:12 +03:00
fprintf ( stderr , " %s \n " , NULLSTR ( str ) ) ;
2011-08-19 19:20:35 +04:00
fflush ( stderr ) ;
2011-02-12 03:17:12 +03:00
VIR_FREE ( str ) ;
2005-12-08 13:23:34 +03:00
}
2011-04-29 12:20:49 +04:00
2011-10-11 17:05:52 +04:00
static void
vshEventLoop ( void * opaque )
{
vshControl * ctl = opaque ;
2011-11-30 23:42:20 +04:00
while ( 1 ) {
bool quit ;
virMutexLock ( & ctl - > lock ) ;
quit = ctl - > quit ;
virMutexUnlock ( & ctl - > lock ) ;
if ( quit )
break ;
if ( virEventRunDefaultImpl ( ) < 0 )
2011-10-11 17:05:52 +04:00
virshReportError ( ctl ) ;
}
}
2005-12-08 13:23:34 +03:00
/*
2007-06-20 21:22:09 +04:00
* Initialize connection .
2005-12-08 13:23:34 +03:00
*/
2011-04-19 02:37:42 +04:00
static bool
2008-08-01 17:51:18 +04:00
vshInit ( vshControl * ctl )
2006-03-15 15:13:25 +03:00
{
2011-05-09 11:08:06 +04:00
char * debugEnv ;
2005-12-08 13:23:34 +03:00
if ( ctl - > conn )
2011-04-19 02:37:42 +04:00
return false ;
2005-12-08 13:23:34 +03:00
2011-07-14 15:58:02 +04:00
if ( ctl - > debug = = VSH_DEBUG_DEFAULT ) {
2011-05-09 11:08:06 +04:00
/* log level not set from commandline, check env variable */
debugEnv = getenv ( " VIRSH_DEBUG " ) ;
if ( debugEnv ) {
2011-07-14 15:58:02 +04:00
int debug ;
if ( virStrToLong_i ( debugEnv , NULL , 10 , & debug ) < 0 | |
debug < VSH_ERR_DEBUG | | debug > VSH_ERR_ERROR ) {
2011-05-09 11:08:06 +04:00
vshError ( ctl , " %s " ,
_ ( " VIRSH_DEBUG not set with a valid numeric value " ) ) ;
2011-07-14 15:58:02 +04:00
} else {
ctl - > debug = debug ;
2011-05-09 11:08:06 +04:00
}
}
}
if ( ctl - > logfile = = NULL ) {
/* log file not set from cmdline */
debugEnv = getenv ( " VIRSH_LOG_FILE " ) ;
if ( debugEnv & & * debugEnv ) {
ctl - > logfile = vshStrdup ( ctl , debugEnv ) ;
}
}
2007-06-06 16:24:31 +04:00
vshOpenLogFile ( ctl ) ;
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
2010-03-05 12:59:52 +03:00
/* set up the signals handlers to catch disconnections */
vshSetupSignals ( ) ;
2011-03-02 19:59:54 +03:00
if ( virEventRegisterDefaultImpl ( ) < 0 )
2011-04-19 02:37:42 +04:00
return false ;
2010-07-27 13:40:30 +04:00
2011-10-11 17:05:52 +04:00
if ( virThreadCreate ( & ctl - > eventLoop , true , vshEventLoop , ctl ) < 0 )
return false ;
ctl - > eventLoopStarted = true ;
virsh: optimize creation of default connection
Ramon de Carvalho Valle reported a problem with:
virsh connect qemu:///system
as a non-root user. The real root problem appears to be a regression
in libvirtd being auto-started on the default qemu:///session URI;
however, the symptom points to an independent flaw in virsh - we
shouldn't be wasting efforts on making a connection if we aren't going
to be using that connection. Fixing virsh avoids Ramon's issue, while
I work in the meantime to fix the real libvirtd regression.
This patch looks big, but that's because 'gcc -Wmissing-field-initializers'
gets triggered by './autobuild.sh --enable-compile-warnings=error', so I
had to add 0 initialization to everyone (rather than my preference of
just adding the non-zero flags to virshCmds and to cmdConnect).
Meanwhile, if you use 'virsh -c URI', the connection must succeed; this
patch _only_ optimizes the default connection to be deferred to a later
point where we know if a particular command to be run needs a connection.
* tools/virsh.c (VSH_CMD_FLAG_NOCONNECT): New flag.
(vshCmdDef): Add new flags field.
(vshCommandRun): Honor new flag.
(domManagementCmds, domMonitoringCmds, storagePoolCmds)
(storageVolCmds, networkCmds, nodedevCmds, ifaceCmds)
(nwfilterCmds, secretCmds, virshCmds, snapshotCmds)
(hostAndHypervisorCmds): Populate new field.
(vshReconnect): Don't warn on initial connection.
2011-03-14 23:30:24 +03:00
if ( ctl - > name ) {
ctl - > conn = virConnectOpenAuth ( ctl - > name ,
virConnectAuthPtrDefault ,
ctl - > readonly ? VIR_CONNECT_RO : 0 ) ;
2006-03-15 15:13:25 +03:00
virsh: optimize creation of default connection
Ramon de Carvalho Valle reported a problem with:
virsh connect qemu:///system
as a non-root user. The real root problem appears to be a regression
in libvirtd being auto-started on the default qemu:///session URI;
however, the symptom points to an independent flaw in virsh - we
shouldn't be wasting efforts on making a connection if we aren't going
to be using that connection. Fixing virsh avoids Ramon's issue, while
I work in the meantime to fix the real libvirtd regression.
This patch looks big, but that's because 'gcc -Wmissing-field-initializers'
gets triggered by './autobuild.sh --enable-compile-warnings=error', so I
had to add 0 initialization to everyone (rather than my preference of
just adding the non-zero flags to virshCmds and to cmdConnect).
Meanwhile, if you use 'virsh -c URI', the connection must succeed; this
patch _only_ optimizes the default connection to be deferred to a later
point where we know if a particular command to be run needs a connection.
* tools/virsh.c (VSH_CMD_FLAG_NOCONNECT): New flag.
(vshCmdDef): Add new flags field.
(vshCommandRun): Honor new flag.
(domManagementCmds, domMonitoringCmds, storagePoolCmds)
(storageVolCmds, networkCmds, nodedevCmds, ifaceCmds)
(nwfilterCmds, secretCmds, virshCmds, snapshotCmds)
(hostAndHypervisorCmds): Populate new field.
(vshReconnect): Don't warn on initial connection.
2011-03-14 23:30:24 +03:00
/* 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 ) .
*/
if ( ! ctl - > conn ) {
virshReportError ( ctl ) ;
vshError ( ctl , " %s " , _ ( " failed to connect to the hypervisor " ) ) ;
return false ;
}
2007-12-05 19:24:22 +03:00
}
2005-12-08 13:23:34 +03:00
2011-04-19 02:37:42 +04:00
return true ;
2005-12-08 13:23:34 +03:00
}
2007-12-07 17:56:37 +03:00
# define LOGFILE_FLAGS (O_WRONLY | O_APPEND | O_CREAT | O_SYNC)
2007-06-06 16:24:31 +04:00
/**
* vshOpenLogFile :
*
* Open log file .
*/
static void
vshOpenLogFile ( vshControl * ctl )
{
struct stat st ;
if ( ctl - > logfile = = NULL )
return ;
/* check log file */
if ( stat ( ctl - > logfile , & st ) = = - 1 ) {
switch ( errno ) {
case ENOENT :
break ;
default :
2009-09-29 15:42:42 +04:00
vshError ( ctl , " %s " ,
2008-01-16 20:13:23 +03:00
_ ( " failed to get the log file information " ) ) ;
2009-09-29 15:42:42 +04:00
exit ( EXIT_FAILURE ) ;
2007-06-06 16:24:31 +04:00
}
} else {
if ( ! S_ISREG ( st . st_mode ) ) {
2009-09-29 15:42:42 +04:00
vshError ( ctl , " %s " , _ ( " the log path is not a file " ) ) ;
exit ( EXIT_FAILURE ) ;
2007-06-06 16:24:31 +04:00
}
}
/* log file open */
2007-12-07 17:56:37 +03:00
if ( ( ctl - > log_fd = open ( ctl - > logfile , LOGFILE_FLAGS , FILE_MODE ) ) < 0 ) {
2009-09-29 15:42:42 +04:00
vshError ( ctl , " %s " ,
2008-01-16 20:13:23 +03:00
_ ( " failed to open the log file. check the log file path " ) ) ;
2009-09-29 15:42:42 +04:00
exit ( EXIT_FAILURE ) ;
2007-06-06 16:24:31 +04:00
}
}
/**
* vshOutputLogFile :
*
* Outputting an error to log file .
*/
static void
2011-04-30 14:56:14 +04:00
vshOutputLogFile ( vshControl * ctl , int log_level , const char * msg_format ,
va_list ap )
2007-06-06 16:24:31 +04:00
{
2011-04-30 21:05:43 +04:00
virBuffer buf = VIR_BUFFER_INITIALIZER ;
char * str ;
size_t len ;
2007-06-06 16:24:31 +04:00
const char * lvl = " " ;
struct timeval stTimeval ;
struct tm * stTm ;
if ( ctl - > log_fd = = - 1 )
return ;
/**
* create log format
*
* [ YYYY . MM . DD HH : MM : SS SIGNATURE PID ] LOG_LEVEL message
*/
gettimeofday ( & stTimeval , NULL ) ;
stTm = localtime ( & stTimeval . tv_sec ) ;
2011-05-09 11:08:06 +04:00
virBufferAsprintf ( & buf , " [%d.%02d.%02d %02d:%02d:%02d %s %d] " ,
2011-04-30 21:05:43 +04:00
( 1900 + stTm - > tm_year ) ,
( 1 + stTm - > tm_mon ) ,
stTm - > tm_mday ,
stTm - > tm_hour ,
stTm - > tm_min ,
stTm - > tm_sec ,
2011-05-09 11:08:06 +04:00
SIGN_NAME ,
( int ) getpid ( ) ) ;
2007-06-06 16:24:31 +04:00
switch ( log_level ) {
case VSH_ERR_DEBUG :
lvl = LVL_DEBUG ;
break ;
case VSH_ERR_INFO :
lvl = LVL_INFO ;
break ;
case VSH_ERR_NOTICE :
lvl = LVL_INFO ;
break ;
case VSH_ERR_WARNING :
lvl = LVL_WARNING ;
break ;
case VSH_ERR_ERROR :
lvl = LVL_ERROR ;
break ;
default :
lvl = LVL_DEBUG ;
break ;
}
2011-04-30 21:05:43 +04:00
virBufferAsprintf ( & buf , " %s " , lvl ) ;
virBufferVasprintf ( & buf , msg_format , ap ) ;
virBufferAddChar ( & buf , ' \n ' ) ;
2007-06-06 16:24:31 +04:00
2011-04-30 21:05:43 +04:00
if ( virBufferError ( & buf ) )
goto error ;
2007-06-06 16:24:31 +04:00
2011-04-30 21:05:43 +04:00
str = virBufferContentAndReset ( & buf ) ;
len = strlen ( str ) ;
if ( len > 1 & & str [ len - 2 ] = = ' \n ' ) {
str [ len - 1 ] = ' \0 ' ;
len - - ;
2007-06-06 16:24:31 +04:00
}
2011-04-03 13:21:23 +04:00
2011-04-30 21:05:43 +04:00
/* write log */
if ( safewrite ( ctl - > log_fd , str , len ) < 0 )
goto error ;
return ;
error :
vshCloseLogFile ( ctl ) ;
vshError ( ctl , " %s " , _ ( " failed to write the log file " ) ) ;
virBufferFreeAndReset ( & buf ) ;
VIR_FREE ( str ) ;
2007-06-06 16:24:31 +04:00
}
/**
* vshCloseLogFile :
*
* Close log file .
*/
static void
vshCloseLogFile ( vshControl * ctl )
{
/* log file close */
2010-11-09 23:48:48 +03:00
if ( VIR_CLOSE ( ctl - > log_fd ) < 0 ) {
vshError ( ctl , _ ( " %s: failed to write log file: %s " ) ,
ctl - > logfile ? ctl - > logfile : " ? " , strerror ( errno ) ) ;
2007-06-06 16:24:31 +04:00
}
if ( ctl - > logfile ) {
2010-01-03 19:13:27 +03:00
VIR_FREE ( ctl - > logfile ) ;
2007-06-06 16:24:31 +04:00
ctl - > logfile = NULL ;
}
}
2007-12-06 13:24:52 +03:00
# ifdef USE_READLINE
2007-12-04 21:27:52 +03:00
2005-12-08 13:23:34 +03:00
/* -----------------
* Readline stuff
* - - - - - - - - - - - - - - - - -
*/
2007-02-07 16:50:18 +03:00
/*
2005-12-08 13:23:34 +03:00
* Generator function for command completion . STATE lets us
* know whether to start from scratch ; without any state
2007-02-07 16:50:18 +03:00
* ( i . e . STATE = = 0 ) , then we start at the top of the list .
2005-12-08 13:23:34 +03:00
*/
static char *
2006-03-15 15:13:25 +03:00
vshReadlineCommandGenerator ( const char * text , int state )
{
2010-11-30 09:37:04 +03:00
static int grp_list_index , cmd_list_index , len ;
2005-12-08 17:22:52 +03:00
const char * name ;
2010-11-30 09:37:04 +03:00
const vshCmdGrp * grp ;
const vshCmdDef * cmds ;
2005-12-08 13:23:34 +03:00
if ( ! state ) {
2010-11-30 09:37:04 +03:00
grp_list_index = 0 ;
cmd_list_index = 0 ;
2006-03-15 15:13:25 +03:00
len = strlen ( text ) ;
2005-12-08 13:23:34 +03:00
}
2010-11-30 09:37:04 +03:00
grp = cmdGroups ;
2005-12-08 13:23:34 +03:00
/* Return the next name which partially matches from the
2007-02-07 16:50:18 +03:00
* command list .
2005-12-08 13:23:34 +03:00
*/
2010-11-30 09:37:04 +03:00
while ( grp [ grp_list_index ] . name ) {
cmds = grp [ grp_list_index ] . commands ;
if ( cmds [ cmd_list_index ] . name ) {
while ( ( name = cmds [ cmd_list_index ] . name ) ) {
cmd_list_index + + ;
if ( STREQLEN ( name , text , len ) )
return vshStrdup ( NULL , name ) ;
}
} else {
cmd_list_index = 0 ;
grp_list_index + + ;
}
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 ;
2008-08-01 16:19:56 +04:00
static const 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 ) ;
2010-01-03 19:13:27 +03:00
VIR_FREE ( cmdname ) ;
2005-12-08 13:23:34 +03:00
}
if ( ! cmd )
return NULL ;
2006-03-15 15:13:25 +03:00
2007-02-27 18:35:50 +03:00
if ( ! cmd - > opts )
return NULL ;
2005-12-08 17:22:52 +03:00
while ( ( name = cmd - > opts [ list_index ] . name ) ) {
2008-08-01 16:19:56 +04:00
const vshCmdOptDef * opt = & cmd - > opts [ list_index ] ;
2005-12-08 13:23:34 +03:00
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
2011-06-07 13:11:08 +04:00
if ( opt - > type = = VSH_OT_DATA | | opt - > type = = VSH_OT_ARGV )
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 ) {
2008-05-14 23:51:24 +04:00
if ( STRNEQLEN ( 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 ) ;
2007-03-23 19:15:07 +03:00
snprintf ( res , strlen ( name ) + 3 , " --%s " , name ) ;
2005-12-08 13:23:34 +03:00
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 ;
}
2010-01-03 17:45:10 +03:00
static int
vshReadlineInit ( vshControl * ctl )
2006-03-15 15:13:25 +03:00
{
2010-01-03 17:45:10 +03:00
char * userdir = NULL ;
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 ;
2009-02-09 13:24:27 +03:00
/* Limit the total size of the history buffer */
stifle_history ( 500 ) ;
2010-01-03 17:45:10 +03:00
2012-05-03 20:36:27 +04:00
/* Prepare to read/write history from/to the $XDG_CACHE_HOME/virsh/history file */
2012-05-24 16:29:42 +04:00
userdir = virGetUserCacheDirectory ( ) ;
2010-01-03 17:45:10 +03:00
2011-05-15 09:31:42 +04:00
if ( userdir = = NULL ) {
vshError ( ctl , " %s " , _ ( " Could not determine home directory " ) ) ;
2010-01-03 17:45:10 +03:00
return - 1 ;
2011-05-15 09:31:42 +04:00
}
2010-01-03 17:45:10 +03:00
2012-05-03 20:36:27 +04:00
if ( virAsprintf ( & ctl - > historydir , " %s/virsh " , userdir ) < 0 ) {
2010-01-03 17:45:10 +03:00
vshError ( ctl , " %s " , _ ( " Out of memory " ) ) ;
2010-01-03 19:13:27 +03:00
VIR_FREE ( userdir ) ;
2010-01-03 17:45:10 +03:00
return - 1 ;
}
if ( virAsprintf ( & ctl - > historyfile , " %s/history " , ctl - > historydir ) < 0 ) {
vshError ( ctl , " %s " , _ ( " Out of memory " ) ) ;
2010-01-03 19:13:27 +03:00
VIR_FREE ( userdir ) ;
2010-01-03 17:45:10 +03:00
return - 1 ;
}
2010-01-03 19:13:27 +03:00
VIR_FREE ( userdir ) ;
2010-01-03 17:45:10 +03:00
read_history ( ctl - > historyfile ) ;
return 0 ;
}
static void
2012-07-11 10:17:28 +04:00
vshReadlineDeinit ( vshControl * ctl )
2010-01-03 17:45:10 +03:00
{
if ( ctl - > historyfile ! = NULL ) {
2012-07-10 15:24:04 +04:00
if ( virFileMakePathWithMode ( ctl - > historydir , 0755 ) < 0 & &
errno ! = EEXIST ) {
2010-01-03 17:45:10 +03:00
char ebuf [ 1024 ] ;
vshError ( ctl , _ ( " Failed to create '%s': %s " ) ,
2012-03-29 13:52:04 +04:00
ctl - > historydir , virStrerror ( errno , ebuf , sizeof ( ebuf ) ) ) ;
2012-04-15 02:35:22 +04:00
} else {
2010-01-03 17:45:10 +03:00
write_history ( ctl - > historyfile ) ;
2012-04-15 02:35:22 +04:00
}
2010-01-03 17:45:10 +03:00
}
2010-01-03 19:13:27 +03:00
VIR_FREE ( ctl - > historydir ) ;
VIR_FREE ( ctl - > historyfile ) ;
2005-12-08 13:23:34 +03:00
}
2007-12-04 21:27:52 +03:00
static char *
2012-07-11 10:17:28 +04:00
vshReadline ( vshControl * ctl ATTRIBUTE_UNUSED , const char * prompt )
2007-12-04 21:27:52 +03:00
{
2012-07-11 10:17:28 +04:00
return readline ( prompt ) ;
2007-12-04 21:27:52 +03:00
}
2007-12-06 13:24:52 +03:00
# else /* !USE_READLINE */
2007-12-04 21:27:52 +03:00
2010-01-03 17:45:10 +03:00
static int
2012-07-11 10:17:28 +04:00
vshReadlineInit ( vshControl * ctl ATTRIBUTE_UNUSED )
2010-01-03 17:45:10 +03:00
{
/* empty */
return 0 ;
}
2007-12-04 21:27:52 +03:00
static void
2012-07-11 10:17:28 +04:00
vshReadlineDeinit ( vshControl * ctl ATTRIBUTE_UNUSED )
2007-12-04 21:27:52 +03:00
{
/* empty */
}
static char *
2012-07-11 10:17:28 +04:00
vshReadline ( vshControl * ctl , const char * prompt )
2007-12-04 21:27:52 +03:00
{
char line [ 1024 ] ;
char * r ;
int len ;
2012-07-11 10:17:28 +04:00
fputs ( prompt , stdout ) ;
r = fgets ( line , sizeof ( line ) , stdin ) ;
2007-12-04 21:27:52 +03:00
if ( r = = NULL ) return NULL ; /* EOF */
/* Chomp trailing \n */
2012-07-11 10:17:28 +04:00
len = strlen ( r ) ;
2007-12-04 21:27:52 +03:00
if ( len > 0 & & r [ len - 1 ] = = ' \n ' )
r [ len - 1 ] = ' \0 ' ;
2012-07-11 10:17:28 +04:00
return vshStrdup ( ctl , r ) ;
2007-12-04 21:27:52 +03:00
}
2007-12-06 13:24:52 +03:00
# endif /* !USE_READLINE */
2007-12-04 21:27:52 +03:00
2011-11-30 23:42:20 +04:00
static void
vshDeinitTimer ( int timer ATTRIBUTE_UNUSED , void * opaque ATTRIBUTE_UNUSED )
{
/* nothing to be done here */
}
2005-12-08 13:23:34 +03:00
/*
2008-02-04 17:58:47 +03:00
* Deinitialize virsh
2005-12-08 13:23:34 +03:00
*/
2011-04-19 02:37:42 +04:00
static bool
2008-08-01 17:51:18 +04:00
vshDeinit ( vshControl * ctl )
2006-03-15 15:13:25 +03:00
{
2010-01-03 17:45:10 +03:00
vshReadlineDeinit ( ctl ) ;
2007-06-06 16:24:31 +04:00
vshCloseLogFile ( ctl ) ;
2010-01-03 19:13:27 +03:00
VIR_FREE ( ctl - > name ) ;
2005-12-08 13:23:34 +03:00
if ( ctl - > conn ) {
2010-11-11 18:15:46 +03:00
int ret ;
if ( ( ret = virConnectClose ( ctl - > conn ) ) ! = 0 ) {
vshError ( ctl , _ ( " Failed to disconnect from the hypervisor, %d leaked reference(s) " ) , ret ) ;
2005-12-08 13:23:34 +03:00
}
}
2007-12-01 18:45:25 +03:00
virResetLastError ( ) ;
2011-10-11 17:05:52 +04:00
if ( ctl - > eventLoopStarted ) {
2011-11-30 23:42:20 +04:00
int timer ;
virMutexLock ( & ctl - > lock ) ;
ctl - > quit = true ;
2011-10-11 17:05:52 +04:00
/* HACK: Add a dummy timeout to break event loop */
2011-11-30 23:42:20 +04:00
timer = virEventAddTimeout ( 0 , vshDeinitTimer , NULL , NULL ) ;
virMutexUnlock ( & ctl - > lock ) ;
virThreadJoin ( & ctl - > eventLoop ) ;
2011-10-11 17:05:52 +04:00
if ( timer ! = - 1 )
virEventRemoveTimeout ( timer ) ;
ctl - > eventLoopStarted = false ;
}
2011-11-30 23:42:20 +04:00
virMutexDestroy ( & ctl - > lock ) ;
2011-04-19 02:37:42 +04:00
return true ;
2005-12-08 13:23:34 +03:00
}
2006-03-15 15:13:25 +03:00
2005-12-08 13:23:34 +03:00
/*
* Print usage
*/
static void
2008-12-08 16:14:48 +03:00
vshUsage ( void )
2006-03-15 15:13:25 +03:00
{
2010-11-30 09:37:04 +03:00
const vshCmdGrp * grp ;
2008-08-01 16:19:56 +04:00
const vshCmdDef * cmd ;
2010-11-30 09:37:04 +03:00
2010-10-12 11:14:01 +04:00
fprintf ( stdout , _ ( " \n %s [options]... [<command_string>] "
" \n %s [options]... <command> [args...] \n \n "
2008-12-08 16:14:48 +03:00
" options: \n "
2011-11-22 20:08:05 +04:00
" -c | --connect=URI hypervisor connection URI \n "
2008-12-08 16:14:48 +03:00
" -r | --readonly connect readonly \n "
2011-11-22 20:08:05 +04:00
" -d | --debug=NUM debug level [0-4] \n "
2008-12-08 16:14:48 +03:00
" -h | --help this help \n "
" -q | --quiet quiet mode \n "
" -t | --timing print timing information \n "
2011-11-22 20:08:05 +04:00
" -l | --log=FILE output logging to file \n "
" -v short version \n "
" -V long version \n "
" --version[=TYPE] version, TYPE is short or long (default short) \n "
" -e | --escape <char> set escape sequence for console \n \n "
2010-11-30 09:37:04 +03:00
" commands (non interactive mode): \n \n " ) , progname , progname ) ;
2008-12-08 16:14:48 +03:00
2010-11-30 09:37:04 +03:00
for ( grp = cmdGroups ; grp - > name ; grp + + ) {
2012-03-16 23:23:00 +04:00
fprintf ( stdout , _ ( " %s (help keyword '%s') \n " ) ,
grp - > name , grp - > keyword ) ;
for ( cmd = grp - > commands ; cmd - > name ; cmd + + ) {
if ( cmd - > flags & VSH_CMD_FLAG_ALIAS )
continue ;
2010-11-30 09:37:04 +03:00
fprintf ( stdout ,
2012-03-16 23:23:00 +04:00
" %-30s %s \n " , cmd - > name ,
_ ( vshCmddefGetInfo ( cmd , " help " ) ) ) ;
}
2010-11-30 09:37:04 +03:00
fprintf ( stdout , " \n " ) ;
}
fprintf ( stdout , " %s " ,
_ ( " \n (specify help <group> for details about the commands in the group) \n " ) ) ;
2008-12-08 16:14:48 +03:00
fprintf ( stdout , " %s " ,
_ ( " \n (specify help <command> for details about the command) \n \n " ) ) ;
return ;
2005-12-08 13:23:34 +03:00
}
2010-11-08 17:03:32 +03:00
/*
* Show version and options compiled in
*/
static void
vshShowVersion ( vshControl * ctl ATTRIBUTE_UNUSED )
{
/* FIXME - list a copyright blurb, as in GNU programs? */
vshPrint ( ctl , _ ( " Virsh command line tool of libvirt %s \n " ) , VERSION ) ;
vshPrint ( ctl , _ ( " See web site at %s \n \n " ) , " http://libvirt.org/ " ) ;
2010-11-10 01:37:05 +03:00
vshPrint ( ctl , " %s " , _ ( " Compiled with support for: \n " ) ) ;
vshPrint ( ctl , " %s " , _ ( " Hypervisors: " ) ) ;
2010-11-08 17:03:32 +03:00
# ifdef WITH_QEMU
vshPrint ( ctl , " QEmu/KVM " ) ;
# endif
2012-06-26 22:31:31 +04:00
# ifdef WITH_LXC
vshPrint ( ctl , " LXC " ) ;
# endif
2010-11-08 17:03:32 +03:00
# ifdef WITH_UML
vshPrint ( ctl , " UML " ) ;
# endif
2012-06-26 22:31:31 +04:00
# ifdef WITH_XEN
vshPrint ( ctl , " Xen " ) ;
# endif
# ifdef WITH_LIBXL
vshPrint ( ctl , " LibXL " ) ;
# endif
2010-11-08 17:03:32 +03:00
# ifdef WITH_OPENVZ
vshPrint ( ctl , " OpenVZ " ) ;
# endif
2012-06-26 22:31:31 +04:00
# ifdef WITH_VMWARE
vshPrint ( ctl , " VMWare " ) ;
2010-11-08 17:03:32 +03:00
# endif
2012-06-26 22:31:31 +04:00
# ifdef WITH_PHYP
vshPrint ( ctl , " PHYP " ) ;
2010-11-08 17:03:32 +03:00
# endif
2012-06-26 22:31:31 +04:00
# ifdef WITH_VBOX
vshPrint ( ctl , " VirtualBox " ) ;
2010-11-08 17:03:32 +03:00
# endif
# ifdef WITH_ESX
vshPrint ( ctl , " ESX " ) ;
# endif
2012-06-26 22:31:31 +04:00
# ifdef WITH_HYPERV
vshPrint ( ctl , " Hyper-V " ) ;
2010-11-08 17:03:32 +03:00
# endif
2012-06-26 22:31:31 +04:00
# ifdef WITH_XENAPI
vshPrint ( ctl , " XenAPI " ) ;
2010-11-08 17:03:32 +03:00
# endif
# ifdef WITH_TEST
vshPrint ( ctl , " Test " ) ;
# endif
vshPrint ( ctl , " \n " ) ;
2010-11-10 01:37:05 +03:00
vshPrint ( ctl , " %s " , _ ( " Networking: " ) ) ;
2010-11-08 17:03:32 +03:00
# ifdef WITH_REMOTE
vshPrint ( ctl , " Remote " ) ;
# endif
# ifdef WITH_LIBVIRTD
vshPrint ( ctl , " Daemon " ) ;
# endif
# ifdef WITH_NETWORK
vshPrint ( ctl , " Network " ) ;
# endif
# ifdef WITH_BRIDGE
vshPrint ( ctl , " Bridging " ) ;
# endif
# ifdef WITH_NETCF
2012-06-26 22:31:31 +04:00
vshPrint ( ctl , " Interface " ) ;
2010-11-08 17:03:32 +03:00
# endif
# ifdef WITH_NWFILTER
vshPrint ( ctl , " Nwfilter " ) ;
# endif
# ifdef WITH_VIRTUALPORT
vshPrint ( ctl , " VirtualPort " ) ;
# endif
vshPrint ( ctl , " \n " ) ;
2010-11-10 01:37:05 +03:00
vshPrint ( ctl , " %s " , _ ( " Storage: " ) ) ;
2010-11-08 17:03:32 +03:00
# ifdef WITH_STORAGE_DIR
vshPrint ( ctl , " Dir " ) ;
# endif
# ifdef WITH_STORAGE_DISK
vshPrint ( ctl , " Disk " ) ;
# endif
# ifdef WITH_STORAGE_FS
vshPrint ( ctl , " Filesystem " ) ;
# endif
# ifdef WITH_STORAGE_SCSI
vshPrint ( ctl , " SCSI " ) ;
# endif
# ifdef WITH_STORAGE_MPATH
vshPrint ( ctl , " Multipath " ) ;
# endif
# ifdef WITH_STORAGE_ISCSI
vshPrint ( ctl , " iSCSI " ) ;
# endif
# ifdef WITH_STORAGE_LVM
vshPrint ( ctl , " LVM " ) ;
2012-05-14 13:06:42 +04:00
# endif
# ifdef WITH_STORAGE_RBD
vshPrint ( ctl , " RBD " ) ;
2012-07-18 23:06:58 +04:00
# endif
# ifdef WITH_STORAGE_SHEEPDOG
vshPrint ( ctl , " Sheepdog " ) ;
2010-11-08 17:03:32 +03:00
# endif
vshPrint ( ctl , " \n " ) ;
2012-07-23 07:57:53 +04:00
vshPrint ( ctl , " %s " , _ ( " Miscellaneous: " ) ) ;
# ifdef WITH_NODE_DEVICES
vshPrint ( ctl , " Nodedev " ) ;
# endif
# ifdef WITH_SECDRIVER_APPARMOR
vshPrint ( ctl , " AppArmor " ) ;
# endif
# ifdef WITH_SECDRIVER_SELINUX
vshPrint ( ctl , " SELinux " ) ;
# endif
# ifdef WITH_SECRETS
vshPrint ( ctl , " Secrets " ) ;
# endif
# ifdef ENABLE_DEBUG
vshPrint ( ctl , " Debug " ) ;
# endif
# ifdef WITH_DTRACE_PROBES
vshPrint ( ctl , " DTrace " ) ;
# endif
# ifdef USE_READLINE
vshPrint ( ctl , " Readline " ) ;
# endif
# ifdef WITH_DRIVER_MODULES
vshPrint ( ctl , " Modular " ) ;
# endif
vshPrint ( ctl , " \n " ) ;
}
static bool
vshAllowedEscapeChar ( char c )
{
/* Allowed escape characters:
* a - z A - Z @ [ \ ] ^ _
*/
return ( ' a ' < = c & & c < = ' z ' ) | |
( ' @ ' < = c & & c < = ' _ ' ) ;
}
/*
* argv [ ] : virsh [ options ] [ command ]
*
*/
static bool
vshParseArgv ( vshControl * ctl , int argc , char * * argv )
{
int arg , len ;
struct option opt [ ] = {
{ " debug " , required_argument , NULL , ' d ' } ,
{ " help " , no_argument , NULL , ' h ' } ,
{ " quiet " , no_argument , NULL , ' q ' } ,
{ " timing " , no_argument , NULL , ' t ' } ,
{ " version " , optional_argument , NULL , ' v ' } ,
{ " connect " , required_argument , NULL , ' c ' } ,
{ " readonly " , no_argument , NULL , ' r ' } ,
{ " log " , required_argument , NULL , ' l ' } ,
{ " escape " , required_argument , NULL , ' e ' } ,
{ NULL , 0 , NULL , 0 }
} ;
/* Standard (non-command) options. The leading + ensures that no
* argument reordering takes place , so that command options are
* not confused with top - level virsh options . */
while ( ( arg = getopt_long ( argc , argv , " +d:hqtc:vVrl:e: " , opt , NULL ) ) ! = - 1 ) {
switch ( arg ) {
case ' d ' :
if ( virStrToLong_i ( optarg , NULL , 10 , & ctl - > debug ) < 0 ) {
vshError ( ctl , " %s " , _ ( " option -d takes a numeric argument " ) ) ;
exit ( EXIT_FAILURE ) ;
}
break ;
case ' h ' :
vshUsage ( ) ;
exit ( EXIT_SUCCESS ) ;
break ;
case ' q ' :
ctl - > quiet = true ;
break ;
case ' t ' :
ctl - > timing = true ;
break ;
case ' c ' :
ctl - > name = vshStrdup ( ctl , optarg ) ;
break ;
case ' v ' :
if ( STRNEQ_NULLABLE ( optarg , " long " ) ) {
puts ( VERSION ) ;
exit ( EXIT_SUCCESS ) ;
}
/* fall through */
case ' V ' :
vshShowVersion ( ctl ) ;
exit ( EXIT_SUCCESS ) ;
case ' r ' :
ctl - > readonly = true ;
break ;
case ' l ' :
ctl - > logfile = vshStrdup ( ctl , optarg ) ;
break ;
case ' e ' :
len = strlen ( optarg ) ;
if ( ( len = = 2 & & * optarg = = ' ^ ' & &
vshAllowedEscapeChar ( optarg [ 1 ] ) ) | |
( len = = 1 & & * optarg ! = ' ^ ' ) ) {
ctl - > escapeChar = optarg ;
} else {
vshError ( ctl , _ ( " Invalid string '%s' for escape sequence " ) ,
optarg ) ;
exit ( EXIT_FAILURE ) ;
}
break ;
default :
vshError ( ctl , _ ( " unsupported option '-%c'. See --help. " ) , arg ) ;
exit ( EXIT_FAILURE ) ;
}
}
if ( argc > optind ) {
/* parse command */
ctl - > imode = false ;
if ( argc - optind = = 1 ) {
vshDebug ( ctl , VSH_ERR_INFO , " commands: \" %s \" \n " , argv [ optind ] ) ;
return vshCommandStringParse ( ctl , argv [ optind ] ) ;
} else {
return vshCommandArgvParse ( ctl , argc - optind , argv + optind ) ;
}
}
return true ;
}
2012-07-25 19:37:18 +04:00
# include "virsh-domain.c"
2012-07-23 07:57:53 +04:00
static const vshCmdDef domManagementCmds [ ] = {
{ " attach-device " , cmdAttachDevice , opts_attach_device ,
info_attach_device , 0 } ,
{ " attach-disk " , cmdAttachDisk , opts_attach_disk ,
info_attach_disk , 0 } ,
{ " attach-interface " , cmdAttachInterface , opts_attach_interface ,
info_attach_interface , 0 } ,
{ " autostart " , cmdAutostart , opts_autostart , info_autostart , 0 } ,
{ " blkdeviotune " , cmdBlkdeviotune , opts_blkdeviotune , info_blkdeviotune , 0 } ,
{ " blkiotune " , cmdBlkiotune , opts_blkiotune , info_blkiotune , 0 } ,
{ " blockcopy " , cmdBlockCopy , opts_block_copy , info_block_copy , 0 } ,
{ " blockjob " , cmdBlockJob , opts_block_job , info_block_job , 0 } ,
{ " blockpull " , cmdBlockPull , opts_block_pull , info_block_pull , 0 } ,
{ " blockresize " , cmdBlockResize , opts_block_resize , info_block_resize , 0 } ,
{ " change-media " , cmdChangeMedia , opts_change_media , info_change_media , 0 } ,
# ifndef WIN32
{ " console " , cmdConsole , opts_console , info_console , 0 } ,
# endif
{ " cpu-baseline " , cmdCPUBaseline , opts_cpu_baseline , info_cpu_baseline , 0 } ,
{ " cpu-compare " , cmdCPUCompare , opts_cpu_compare , info_cpu_compare , 0 } ,
{ " cpu-stats " , cmdCPUStats , opts_cpu_stats , info_cpu_stats , 0 } ,
{ " create " , cmdCreate , opts_create , info_create , 0 } ,
{ " define " , cmdDefine , opts_define , info_define , 0 } ,
{ " desc " , cmdDesc , opts_desc , info_desc , 0 } ,
{ " destroy " , cmdDestroy , opts_destroy , info_destroy , 0 } ,
{ " detach-device " , cmdDetachDevice , opts_detach_device ,
info_detach_device , 0 } ,
{ " detach-disk " , cmdDetachDisk , opts_detach_disk , info_detach_disk , 0 } ,
{ " detach-interface " , cmdDetachInterface , opts_detach_interface ,
info_detach_interface , 0 } ,
{ " domdisplay " , cmdDomDisplay , opts_domdisplay , info_domdisplay , 0 } ,
{ " domhostname " , cmdDomHostname , opts_domhostname , info_domhostname , 0 } ,
{ " domid " , cmdDomid , opts_domid , info_domid , 0 } ,
{ " domif-setlink " , cmdDomIfSetLink , opts_domif_setlink , info_domif_setlink , 0 } ,
{ " domiftune " , cmdDomIftune , opts_domiftune , info_domiftune , 0 } ,
{ " domjobabort " , cmdDomjobabort , opts_domjobabort , info_domjobabort , 0 } ,
{ " domjobinfo " , cmdDomjobinfo , opts_domjobinfo , info_domjobinfo , 0 } ,
{ " domname " , cmdDomname , opts_domname , info_domname , 0 } ,
{ " dompmsuspend " , cmdDomPMSuspend ,
opts_dom_pm_suspend , info_dom_pm_suspend , 0 } ,
{ " dompmwakeup " , cmdDomPMWakeup ,
opts_dom_pm_wakeup , info_dom_pm_wakeup , 0 } ,
{ " domuuid " , cmdDomuuid , opts_domuuid , info_domuuid , 0 } ,
{ " domxml-from-native " , cmdDomXMLFromNative , opts_domxmlfromnative ,
info_domxmlfromnative , 0 } ,
{ " domxml-to-native " , cmdDomXMLToNative , opts_domxmltonative ,
info_domxmltonative , 0 } ,
{ " dump " , cmdDump , opts_dump , info_dump , 0 } ,
{ " dumpxml " , cmdDumpXML , opts_dumpxml , info_dumpxml , 0 } ,
{ " edit " , cmdEdit , opts_edit , info_edit , 0 } ,
{ " inject-nmi " , cmdInjectNMI , opts_inject_nmi , info_inject_nmi , 0 } ,
{ " send-key " , cmdSendKey , opts_send_key , info_send_key , 0 } ,
{ " managedsave " , cmdManagedSave , opts_managedsave , info_managedsave , 0 } ,
{ " managedsave-remove " , cmdManagedSaveRemove , opts_managedsaveremove ,
info_managedsaveremove , 0 } ,
{ " maxvcpus " , cmdMaxvcpus , opts_maxvcpus , info_maxvcpus , 0 } ,
{ " memtune " , cmdMemtune , opts_memtune , info_memtune , 0 } ,
{ " migrate " , cmdMigrate , opts_migrate , info_migrate , 0 } ,
{ " migrate-setmaxdowntime " , cmdMigrateSetMaxDowntime ,
opts_migrate_setmaxdowntime , info_migrate_setmaxdowntime , 0 } ,
{ " migrate-setspeed " , cmdMigrateSetMaxSpeed ,
opts_migrate_setspeed , info_migrate_setspeed , 0 } ,
{ " migrate-getspeed " , cmdMigrateGetMaxSpeed ,
opts_migrate_getspeed , info_migrate_getspeed , 0 } ,
{ " numatune " , cmdNumatune , opts_numatune , info_numatune , 0 } ,
{ " reboot " , cmdReboot , opts_reboot , info_reboot , 0 } ,
{ " reset " , cmdReset , opts_reset , info_reset , 0 } ,
{ " restore " , cmdRestore , opts_restore , info_restore , 0 } ,
{ " resume " , cmdResume , opts_resume , info_resume , 0 } ,
{ " save " , cmdSave , opts_save , info_save , 0 } ,
{ " save-image-define " , cmdSaveImageDefine , opts_save_image_define ,
info_save_image_define , 0 } ,
{ " save-image-dumpxml " , cmdSaveImageDumpxml , opts_save_image_dumpxml ,
info_save_image_dumpxml , 0 } ,
{ " save-image-edit " , cmdSaveImageEdit , opts_save_image_edit ,
info_save_image_edit , 0 } ,
{ " schedinfo " , cmdSchedinfo , opts_schedinfo , info_schedinfo , 0 } ,
{ " screenshot " , cmdScreenshot , opts_screenshot , info_screenshot , 0 } ,
{ " setmaxmem " , cmdSetmaxmem , opts_setmaxmem , info_setmaxmem , 0 } ,
{ " setmem " , cmdSetmem , opts_setmem , info_setmem , 0 } ,
{ " setvcpus " , cmdSetvcpus , opts_setvcpus , info_setvcpus , 0 } ,
{ " shutdown " , cmdShutdown , opts_shutdown , info_shutdown , 0 } ,
{ " start " , cmdStart , opts_start , info_start , 0 } ,
{ " suspend " , cmdSuspend , opts_suspend , info_suspend , 0 } ,
{ " ttyconsole " , cmdTTYConsole , opts_ttyconsole , info_ttyconsole , 0 } ,
{ " undefine " , cmdUndefine , opts_undefine , info_undefine , 0 } ,
{ " update-device " , cmdUpdateDevice , opts_update_device ,
info_update_device , 0 } ,
{ " vcpucount " , cmdVcpucount , opts_vcpucount , info_vcpucount , 0 } ,
{ " vcpuinfo " , cmdVcpuinfo , opts_vcpuinfo , info_vcpuinfo , 0 } ,
{ " vcpupin " , cmdVcpuPin , opts_vcpupin , info_vcpupin , 0 } ,
{ " vncdisplay " , cmdVNCDisplay , opts_vncdisplay , info_vncdisplay , 0 } ,
{ NULL , NULL , NULL , NULL , 0 }
} ;
2012-07-24 12:24:50 +04:00
# include "virsh-domain-monitor.c"
2012-07-23 07:57:53 +04:00
static const vshCmdDef domMonitoringCmds [ ] = {
{ " domblkerror " , cmdDomBlkError , opts_domblkerror , info_domblkerror , 0 } ,
{ " domblkinfo " , cmdDomblkinfo , opts_domblkinfo , info_domblkinfo , 0 } ,
{ " domblklist " , cmdDomblklist , opts_domblklist , info_domblklist , 0 } ,
{ " domblkstat " , cmdDomblkstat , opts_domblkstat , info_domblkstat , 0 } ,
{ " domcontrol " , cmdDomControl , opts_domcontrol , info_domcontrol , 0 } ,
{ " domif-getlink " , cmdDomIfGetLink , opts_domif_getlink , info_domif_getlink , 0 } ,
{ " domiflist " , cmdDomiflist , opts_domiflist , info_domiflist , 0 } ,
{ " domifstat " , cmdDomIfstat , opts_domifstat , info_domifstat , 0 } ,
{ " dominfo " , cmdDominfo , opts_dominfo , info_dominfo , 0 } ,
{ " dommemstat " , cmdDomMemStat , opts_dommemstat , info_dommemstat , 0 } ,
{ " domstate " , cmdDomstate , opts_domstate , info_domstate , 0 } ,
{ " list " , cmdList , opts_list , info_list , 0 } ,
{ NULL , NULL , NULL , NULL , 0 }
} ;
2012-07-24 12:49:27 +04:00
# include "virsh-pool.c"
2012-07-23 07:57:53 +04:00
static const vshCmdDef storagePoolCmds [ ] = {
{ " find-storage-pool-sources-as " , cmdPoolDiscoverSourcesAs ,
opts_find_storage_pool_sources_as , info_find_storage_pool_sources_as , 0 } ,
{ " find-storage-pool-sources " , cmdPoolDiscoverSources ,
opts_find_storage_pool_sources , info_find_storage_pool_sources , 0 } ,
{ " pool-autostart " , cmdPoolAutostart , opts_pool_autostart ,
info_pool_autostart , 0 } ,
{ " pool-build " , cmdPoolBuild , opts_pool_build , info_pool_build , 0 } ,
{ " pool-create-as " , cmdPoolCreateAs , opts_pool_X_as , info_pool_create_as , 0 } ,
{ " pool-create " , cmdPoolCreate , opts_pool_create , info_pool_create , 0 } ,
{ " pool-define-as " , cmdPoolDefineAs , opts_pool_X_as , info_pool_define_as , 0 } ,
{ " pool-define " , cmdPoolDefine , opts_pool_define , info_pool_define , 0 } ,
{ " pool-delete " , cmdPoolDelete , opts_pool_delete , info_pool_delete , 0 } ,
{ " pool-destroy " , cmdPoolDestroy , opts_pool_destroy , info_pool_destroy , 0 } ,
{ " pool-dumpxml " , cmdPoolDumpXML , opts_pool_dumpxml , info_pool_dumpxml , 0 } ,
{ " pool-edit " , cmdPoolEdit , opts_pool_edit , info_pool_edit , 0 } ,
{ " pool-info " , cmdPoolInfo , opts_pool_info , info_pool_info , 0 } ,
{ " pool-list " , cmdPoolList , opts_pool_list , info_pool_list , 0 } ,
{ " pool-name " , cmdPoolName , opts_pool_name , info_pool_name , 0 } ,
{ " pool-refresh " , cmdPoolRefresh , opts_pool_refresh , info_pool_refresh , 0 } ,
{ " pool-start " , cmdPoolStart , opts_pool_start , info_pool_start , 0 } ,
{ " pool-undefine " , cmdPoolUndefine , opts_pool_undefine ,
info_pool_undefine , 0 } ,
{ " pool-uuid " , cmdPoolUuid , opts_pool_uuid , info_pool_uuid , 0 } ,
{ NULL , NULL , NULL , NULL , 0 }
} ;
2012-07-24 12:44:49 +04:00
# include "virsh-volume.c"
2012-07-23 07:57:53 +04:00
static const vshCmdDef storageVolCmds [ ] = {
{ " vol-clone " , cmdVolClone , opts_vol_clone , info_vol_clone , 0 } ,
{ " vol-create-as " , cmdVolCreateAs , opts_vol_create_as ,
info_vol_create_as , 0 } ,
{ " vol-create " , cmdVolCreate , opts_vol_create , info_vol_create , 0 } ,
{ " vol-create-from " , cmdVolCreateFrom , opts_vol_create_from ,
info_vol_create_from , 0 } ,
{ " vol-delete " , cmdVolDelete , opts_vol_delete , info_vol_delete , 0 } ,
{ " vol-download " , cmdVolDownload , opts_vol_download , info_vol_download , 0 } ,
{ " vol-dumpxml " , cmdVolDumpXML , opts_vol_dumpxml , info_vol_dumpxml , 0 } ,
{ " vol-info " , cmdVolInfo , opts_vol_info , info_vol_info , 0 } ,
{ " vol-key " , cmdVolKey , opts_vol_key , info_vol_key , 0 } ,
{ " vol-list " , cmdVolList , opts_vol_list , info_vol_list , 0 } ,
{ " vol-name " , cmdVolName , opts_vol_name , info_vol_name , 0 } ,
{ " vol-path " , cmdVolPath , opts_vol_path , info_vol_path , 0 } ,
{ " vol-pool " , cmdVolPool , opts_vol_pool , info_vol_pool , 0 } ,
{ " vol-resize " , cmdVolResize , opts_vol_resize , info_vol_resize , 0 } ,
{ " vol-upload " , cmdVolUpload , opts_vol_upload , info_vol_upload , 0 } ,
{ " vol-wipe " , cmdVolWipe , opts_vol_wipe , info_vol_wipe , 0 } ,
{ NULL , NULL , NULL , NULL , 0 }
} ;
static const vshCmdDef networkCmds [ ] = {
{ " net-autostart " , cmdNetworkAutostart , opts_network_autostart ,
info_network_autostart , 0 } ,
{ " net-create " , cmdNetworkCreate , opts_network_create ,
info_network_create , 0 } ,
{ " net-define " , cmdNetworkDefine , opts_network_define ,
info_network_define , 0 } ,
{ " net-destroy " , cmdNetworkDestroy , opts_network_destroy ,
info_network_destroy , 0 } ,
{ " net-dumpxml " , cmdNetworkDumpXML , opts_network_dumpxml ,
info_network_dumpxml , 0 } ,
{ " net-edit " , cmdNetworkEdit , opts_network_edit , info_network_edit , 0 } ,
{ " net-info " , cmdNetworkInfo , opts_network_info , info_network_info , 0 } ,
{ " net-list " , cmdNetworkList , opts_network_list , info_network_list , 0 } ,
{ " net-name " , cmdNetworkName , opts_network_name , info_network_name , 0 } ,
{ " net-start " , cmdNetworkStart , opts_network_start , info_network_start , 0 } ,
{ " net-undefine " , cmdNetworkUndefine , opts_network_undefine ,
info_network_undefine , 0 } ,
{ " net-uuid " , cmdNetworkUuid , opts_network_uuid , info_network_uuid , 0 } ,
{ NULL , NULL , NULL , NULL , 0 }
} ;
static const vshCmdDef nodedevCmds [ ] = {
{ " nodedev-create " , cmdNodeDeviceCreate , opts_node_device_create ,
info_node_device_create , 0 } ,
{ " nodedev-destroy " , cmdNodeDeviceDestroy , opts_node_device_destroy ,
info_node_device_destroy , 0 } ,
{ " nodedev-detach " , cmdNodeDeviceDetach , opts_node_device_detach ,
info_node_device_detach , 0 } ,
{ " nodedev-dettach " , cmdNodeDeviceDetach , opts_node_device_detach ,
info_node_device_detach , VSH_CMD_FLAG_ALIAS } ,
{ " nodedev-dumpxml " , cmdNodeDeviceDumpXML , opts_node_device_dumpxml ,
info_node_device_dumpxml , 0 } ,
{ " nodedev-list " , cmdNodeListDevices , opts_node_list_devices ,
info_node_list_devices , 0 } ,
{ " nodedev-reattach " , cmdNodeDeviceReAttach , opts_node_device_reattach ,
info_node_device_reattach , 0 } ,
{ " nodedev-reset " , cmdNodeDeviceReset , opts_node_device_reset ,
info_node_device_reset , 0 } ,
{ NULL , NULL , NULL , NULL , 0 }
} ;
static const vshCmdDef ifaceCmds [ ] = {
{ " iface-begin " , cmdInterfaceBegin , opts_interface_begin ,
info_interface_begin , 0 } ,
{ " iface-bridge " , cmdInterfaceBridge , opts_interface_bridge ,
info_interface_bridge , 0 } ,
{ " iface-commit " , cmdInterfaceCommit , opts_interface_commit ,
info_interface_commit , 0 } ,
{ " iface-define " , cmdInterfaceDefine , opts_interface_define ,
info_interface_define , 0 } ,
{ " iface-destroy " , cmdInterfaceDestroy , opts_interface_destroy ,
info_interface_destroy , 0 } ,
{ " iface-dumpxml " , cmdInterfaceDumpXML , opts_interface_dumpxml ,
info_interface_dumpxml , 0 } ,
{ " iface-edit " , cmdInterfaceEdit , opts_interface_edit ,
info_interface_edit , 0 } ,
{ " iface-list " , cmdInterfaceList , opts_interface_list ,
info_interface_list , 0 } ,
{ " iface-mac " , cmdInterfaceMAC , opts_interface_mac ,
info_interface_mac , 0 } ,
{ " iface-name " , cmdInterfaceName , opts_interface_name ,
info_interface_name , 0 } ,
{ " iface-rollback " , cmdInterfaceRollback , opts_interface_rollback ,
info_interface_rollback , 0 } ,
{ " iface-start " , cmdInterfaceStart , opts_interface_start ,
info_interface_start , 0 } ,
{ " iface-unbridge " , cmdInterfaceUnbridge , opts_interface_unbridge ,
info_interface_unbridge , 0 } ,
{ " iface-undefine " , cmdInterfaceUndefine , opts_interface_undefine ,
info_interface_undefine , 0 } ,
{ NULL , NULL , NULL , NULL , 0 }
} ;
2010-11-08 17:03:32 +03:00
2012-07-23 07:57:53 +04:00
static const vshCmdDef nwfilterCmds [ ] = {
{ " nwfilter-define " , cmdNWFilterDefine , opts_nwfilter_define ,
info_nwfilter_define , 0 } ,
{ " nwfilter-dumpxml " , cmdNWFilterDumpXML , opts_nwfilter_dumpxml ,
info_nwfilter_dumpxml , 0 } ,
{ " nwfilter-edit " , cmdNWFilterEdit , opts_nwfilter_edit ,
info_nwfilter_edit , 0 } ,
{ " nwfilter-list " , cmdNWFilterList , opts_nwfilter_list ,
info_nwfilter_list , 0 } ,
{ " nwfilter-undefine " , cmdNWFilterUndefine , opts_nwfilter_undefine ,
info_nwfilter_undefine , 0 } ,
{ NULL , NULL , NULL , NULL , 0 }
} ;
2012-04-03 16:59:06 +04:00
2012-07-23 07:57:53 +04:00
static const vshCmdDef secretCmds [ ] = {
{ " secret-define " , cmdSecretDefine , opts_secret_define ,
info_secret_define , 0 } ,
{ " secret-dumpxml " , cmdSecretDumpXML , opts_secret_dumpxml ,
info_secret_dumpxml , 0 } ,
{ " secret-get-value " , cmdSecretGetValue , opts_secret_get_value ,
info_secret_get_value , 0 } ,
{ " secret-list " , cmdSecretList , NULL , info_secret_list , 0 } ,
{ " secret-set-value " , cmdSecretSetValue , opts_secret_set_value ,
info_secret_set_value , 0 } ,
{ " secret-undefine " , cmdSecretUndefine , opts_secret_undefine ,
info_secret_undefine , 0 } ,
{ NULL , NULL , NULL , NULL , 0 }
} ;
2006-03-15 15:13:25 +03:00
2012-07-23 07:57:53 +04:00
static const vshCmdDef virshCmds [ ] = {
{ " cd " , cmdCd , opts_cd , info_cd , VSH_CMD_FLAG_NOCONNECT } ,
{ " echo " , cmdEcho , opts_echo , info_echo , VSH_CMD_FLAG_NOCONNECT } ,
{ " exit " , cmdQuit , NULL , info_quit , VSH_CMD_FLAG_NOCONNECT } ,
{ " help " , cmdHelp , opts_help , info_help , VSH_CMD_FLAG_NOCONNECT } ,
{ " pwd " , cmdPwd , NULL , info_pwd , VSH_CMD_FLAG_NOCONNECT } ,
{ " quit " , cmdQuit , NULL , info_quit , VSH_CMD_FLAG_NOCONNECT } ,
{ NULL , NULL , NULL , NULL , 0 }
} ;
2011-11-22 20:08:05 +04:00
2012-07-23 07:57:53 +04:00
static const vshCmdDef snapshotCmds [ ] = {
{ " snapshot-create " , cmdSnapshotCreate , opts_snapshot_create ,
info_snapshot_create , 0 } ,
{ " snapshot-create-as " , cmdSnapshotCreateAs , opts_snapshot_create_as ,
info_snapshot_create_as , 0 } ,
{ " snapshot-current " , cmdSnapshotCurrent , opts_snapshot_current ,
info_snapshot_current , 0 } ,
{ " snapshot-delete " , cmdSnapshotDelete , opts_snapshot_delete ,
info_snapshot_delete , 0 } ,
{ " snapshot-dumpxml " , cmdSnapshotDumpXML , opts_snapshot_dumpxml ,
info_snapshot_dumpxml , 0 } ,
{ " snapshot-edit " , cmdSnapshotEdit , opts_snapshot_edit ,
info_snapshot_edit , 0 } ,
{ " snapshot-info " , cmdSnapshotInfo , opts_snapshot_info ,
info_snapshot_info , 0 } ,
{ " snapshot-list " , cmdSnapshotList , opts_snapshot_list ,
info_snapshot_list , 0 } ,
{ " snapshot-parent " , cmdSnapshotParent , opts_snapshot_parent ,
info_snapshot_parent , 0 } ,
{ " snapshot-revert " , cmdDomainSnapshotRevert , opts_snapshot_revert ,
info_snapshot_revert , 0 } ,
{ NULL , NULL , NULL , NULL , 0 }
} ;
2005-12-08 13:23:34 +03:00
2012-07-23 07:57:53 +04:00
static const vshCmdDef hostAndHypervisorCmds [ ] = {
{ " capabilities " , cmdCapabilities , NULL , info_capabilities , 0 } ,
{ " connect " , cmdConnect , opts_connect , info_connect ,
VSH_CMD_FLAG_NOCONNECT } ,
{ " freecell " , cmdFreecell , opts_freecell , info_freecell , 0 } ,
{ " hostname " , cmdHostname , NULL , info_hostname , 0 } ,
{ " nodecpustats " , cmdNodeCpuStats , opts_node_cpustats , info_nodecpustats , 0 } ,
{ " nodeinfo " , cmdNodeinfo , NULL , info_nodeinfo , 0 } ,
{ " nodememstats " , cmdNodeMemStats , opts_node_memstats , info_nodememstats , 0 } ,
{ " nodesuspend " , cmdNodeSuspend , opts_node_suspend , info_nodesuspend , 0 } ,
{ " qemu-attach " , cmdQemuAttach , opts_qemu_attach , info_qemu_attach , 0 } ,
{ " qemu-monitor-command " , cmdQemuMonitorCommand , opts_qemu_monitor_command ,
info_qemu_monitor_command , 0 } ,
{ " sysinfo " , cmdSysinfo , NULL , info_sysinfo , 0 } ,
{ " uri " , cmdURI , NULL , info_uri , 0 } ,
{ " version " , cmdVersion , opts_version , info_version , 0 } ,
{ NULL , NULL , NULL , NULL , 0 }
} ;
static const vshCmdGrp cmdGroups [ ] = {
{ VSH_CMD_GRP_DOM_MANAGEMENT , " domain " , domManagementCmds } ,
{ VSH_CMD_GRP_DOM_MONITORING , " monitor " , domMonitoringCmds } ,
{ VSH_CMD_GRP_HOST_AND_HV , " host " , hostAndHypervisorCmds } ,
{ VSH_CMD_GRP_IFACE , " interface " , ifaceCmds } ,
{ VSH_CMD_GRP_NWFILTER , " filter " , nwfilterCmds } ,
{ VSH_CMD_GRP_NETWORK , " network " , networkCmds } ,
{ VSH_CMD_GRP_NODEDEV , " nodedev " , nodedevCmds } ,
{ VSH_CMD_GRP_SECRET , " secret " , secretCmds } ,
{ VSH_CMD_GRP_SNAPSHOT , " snapshot " , snapshotCmds } ,
{ VSH_CMD_GRP_STORAGE_POOL , " pool " , storagePoolCmds } ,
{ VSH_CMD_GRP_STORAGE_VOL , " volume " , storageVolCmds } ,
{ VSH_CMD_GRP_VIRSH , " virsh " , virshCmds } ,
{ NULL , NULL , NULL }
} ;
2005-12-08 13:23:34 +03:00
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 ;
2011-04-19 02:37:42 +04:00
bool ret = true ;
2005-12-08 13:23:34 +03:00
2011-05-09 15:57:09 +04:00
memset ( ctl , 0 , sizeof ( vshControl ) ) ;
ctl - > imode = true ; /* default is interactive mode */
ctl - > log_fd = - 1 ; /* Initialize log file descriptor */
2011-07-14 15:58:02 +04:00
ctl - > debug = VSH_DEBUG_DEFAULT ;
2011-11-22 20:08:05 +04:00
ctl - > escapeChar = CTRL_CLOSE_BRACKET ;
2011-05-09 15:57:09 +04:00
2006-09-21 19:24:37 +04:00
if ( ! setlocale ( LC_ALL , " " ) ) {
perror ( " setlocale " ) ;
2009-01-29 14:49:33 +03:00
/* failure to setup locale is not fatal */
2006-09-21 19:24:37 +04:00
}
2010-11-16 17:54:17 +03:00
if ( ! bindtextdomain ( PACKAGE , LOCALEDIR ) ) {
2006-09-21 19:24:37 +04:00
perror ( " bindtextdomain " ) ;
2010-11-16 22:01:37 +03:00
return EXIT_FAILURE ;
2006-09-21 19:24:37 +04:00
}
2010-11-16 17:54:17 +03:00
if ( ! textdomain ( PACKAGE ) ) {
2006-09-21 19:24:37 +04:00
perror ( " textdomain " ) ;
2010-11-16 22:01:37 +03:00
return EXIT_FAILURE ;
2006-09-21 19:24:37 +04:00
}
2011-11-30 23:42:20 +04:00
if ( virMutexInit ( & ctl - > lock ) < 0 ) {
vshError ( ctl , " %s " , _ ( " Failed to initialize mutex " ) ) ;
return EXIT_FAILURE ;
}
2011-05-09 15:57:09 +04:00
if ( virInitialize ( ) < 0 ) {
vshError ( ctl , " %s " , _ ( " Failed to initialize libvirt " ) ) ;
return EXIT_FAILURE ;
}
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
2006-08-26 02:40:33 +04:00
if ( ( defaultConn = getenv ( " VIRSH_DEFAULT_CONNECT_URI " ) ) ) {
2010-10-12 21:24:00 +04:00
ctl - > name = vshStrdup ( ctl , defaultConn ) ;
2006-08-26 02:40:33 +04:00
}
2007-12-01 18:45:25 +03:00
if ( ! vshParseArgv ( ctl , argc , argv ) ) {
vshDeinit ( ctl ) ;
2005-12-08 13:23:34 +03:00
exit ( EXIT_FAILURE ) ;
2007-12-01 18:45:25 +03:00
}
2006-03-15 15:13:25 +03:00
2007-12-01 18:45:25 +03:00
if ( ! vshInit ( ctl ) ) {
vshDeinit ( ctl ) ;
2005-12-08 13:23:34 +03:00
exit ( EXIT_FAILURE ) ;
2007-12-01 18:45:25 +03:00
}
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-09-21 19:24:37 +04:00
_ ( " Welcome to %s, the virtualization interactive terminal. \n \n " ) ,
2006-03-15 15:13:25 +03:00
progname ) ;
2008-01-16 20:13:23 +03:00
vshPrint ( ctl , " %s " ,
2006-09-21 19:24:37 +04:00
_ ( " Type: 'help' for help with commands \n "
2007-02-07 16:50:18 +03:00
" 'quit' to quit \n \n " ) ) ;
2005-12-08 13:23:34 +03:00
}
2010-01-03 17:45:10 +03:00
if ( vshReadlineInit ( ctl ) < 0 ) {
vshDeinit ( ctl ) ;
exit ( EXIT_FAILURE ) ;
}
2005-12-08 13:23:34 +03:00
do {
2007-12-06 19:36:21 +03:00
const char * prompt = ctl - > readonly ? VSH_PROMPT_RO : VSH_PROMPT_RW ;
2006-03-15 15:13:25 +03:00
ctl - > cmdstr =
2007-12-06 19:36:21 +03:00
vshReadline ( ctl , prompt ) ;
2006-03-15 15:13:25 +03:00
if ( ctl - > cmdstr = = NULL )
break ; /* EOF */
2005-12-08 13:23:34 +03:00
if ( * ctl - > cmdstr ) {
2007-12-06 13:24:52 +03:00
# if USE_READLINE
2005-12-08 13:23:34 +03:00
add_history ( ctl - > cmdstr ) ;
2007-12-04 21:27:52 +03:00
# endif
2010-10-12 11:13:50 +04:00
if ( vshCommandStringParse ( ctl , ctl - > cmdstr ) )
2005-12-08 13:23:34 +03:00
vshCommandRun ( ctl , ctl - > cmd ) ;
}
2010-01-03 19:13:27 +03:00
VIR_FREE ( ctl - > cmdstr ) ;
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
}