libvirt/tools/virsh.c

10473 lines
280 KiB
C
Raw Normal View History

/*
* virsh.c: a Xen shell used to exercise the libvirt API
*
* Copyright (C) 2005, 2007-2010 Red Hat, Inc.
*
* See COPYING.LIB for the License of this software
*
* Daniel Veillard <veillard@redhat.com>
2005-12-08 14:22:52 +00:00
* Karel Zak <kzak@redhat.com>
2006-05-29 15:39:31 +00:00
* Daniel P. Berrange <berrange@redhat.com>
*/
#include <config.h>
#include <stdio.h>
2005-12-08 10:23:34 +00:00
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
#include <errno.h>
2005-12-08 10:23:34 +00:00
#include <getopt.h>
#include <sys/types.h>
2005-12-08 14:22:52 +00:00
#include <sys/time.h>
#include "c-ctype.h"
#include <fcntl.h>
#include <locale.h>
#include <time.h>
#include <limits.h>
#include <assert.h>
#include <errno.h>
#include <sys/stat.h>
#include <inttypes.h>
#include <signal.h>
2005-12-08 10:23:34 +00:00
#include <libxml/parser.h>
#include <libxml/tree.h>
#include <libxml/xpath.h>
#include <libxml/xmlsave.h>
#ifdef HAVE_READLINE_READLINE_H
# include <readline/readline.h>
# include <readline/history.h>
#endif
2005-12-08 10:23:34 +00:00
#include "internal.h"
#include "virterror_internal.h"
#include "base64.h"
#include "buf.h"
#include "console.h"
2008-01-21 15:27:14 +00:00
#include "util.h"
#include "memory.h"
#include "xml.h"
2005-12-08 10:23:34 +00:00
static char *progname;
#ifndef TRUE
# define TRUE 1
# define FALSE 0
2005-12-08 10:23:34 +00:00
#endif
2008-01-21 15:27:14 +00:00
#define VIRSH_MAX_XML_FILE 10*1024*1024
2005-12-08 10:23:34 +00:00
#define VSH_PROMPT_RW "virsh # "
#define VSH_PROMPT_RO "virsh > "
#define GETTIMEOFDAY(T) gettimeofday(T, NULL)
#define DIFF_MSEC(T, U) \
((((int) ((T)->tv_sec - (U)->tv_sec)) * 1000000.0 + \
((int) ((T)->tv_usec - (U)->tv_usec))) / 1000.0)
/**
* 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"
2008-08-12 08:25:48 +00:00
#ifndef WEXITSTATUS
# define WEXITSTATUS(x) ((x) & 0xff)
#endif
/**
* vshErrorLevel:
*
* Indicates the level of an log message
*/
typedef enum {
VSH_ERR_DEBUG = 0,
VSH_ERR_INFO,
VSH_ERR_NOTICE,
VSH_ERR_WARNING,
VSH_ERR_ERROR
} vshErrorLevel;
2005-12-08 10:23:34 +00:00
/*
* virsh command line grammar:
*
* command_line = <command>\n | <command>; <command>; ...
*
* command = <keyword> <option> <data>
*
* option = <bool_option> | <int_option> | <string_option>
* data = <string>
*
* bool_option = --optionname
* int_option = --optionname <number>
* string_option = --optionname <string>
*
2006-01-25 09:46:22 +00:00
* keyword = [a-zA-Z]
* number = [0-9]+
* string = [^[:blank:]] | "[[:alnum:]]"$
2005-12-08 10:23:34 +00:00
*
*/
/*
* vshCmdOptType - command option type
*/
2005-12-08 10:23:34 +00:00
typedef enum {
VSH_OT_NONE = 0, /* none */
VSH_OT_BOOL, /* boolean option */
VSH_OT_STRING, /* string option */
VSH_OT_INT, /* int option */
VSH_OT_DATA /* string data (as non-option) */
2005-12-08 10:23:34 +00:00
} vshCmdOptType;
/*
* Command Option Flags
*/
#define VSH_OFLAG_NONE 0 /* without flags */
#define VSH_OFLAG_REQ (1 << 1) /* option required */
2005-12-08 10:23:34 +00:00
/* dummy */
typedef struct __vshControl vshControl;
typedef struct __vshCmd vshCmd;
/*
* vshCmdInfo -- information about command
*/
typedef struct {
const char *name; /* name of information */
const char *data; /* information */
2005-12-08 10:23:34 +00:00
} vshCmdInfo;
/*
* vshCmdOptDef - command option definition
*/
typedef struct {
const char *name; /* the name of option */
vshCmdOptType type; /* option type */
int flag; /* flags */
const char *help; /* help string */
2005-12-08 10:23:34 +00:00
} vshCmdOptDef;
/*
* vshCmdOpt - command options
*/
typedef struct vshCmdOpt {
const vshCmdOptDef *def; /* pointer to relevant option */
char *data; /* allocated data */
struct vshCmdOpt *next;
2005-12-08 10:23:34 +00:00
} vshCmdOpt;
/*
* vshCmdDef - command definition
*/
typedef struct {
const char *name;
2008-08-01 13:51:18 +00:00
int (*handler) (vshControl *, const vshCmd *); /* command handler */
const vshCmdOptDef *opts; /* definition of command options */
const vshCmdInfo *info; /* details about command */
2005-12-08 10:23:34 +00:00
} vshCmdDef;
/*
* vshCmd - parsed command
*/
typedef struct __vshCmd {
const vshCmdDef *def; /* command definition */
vshCmdOpt *opts; /* list of command arguments */
struct __vshCmd *next; /* next command */
2005-12-08 10:23:34 +00:00
} __vshCmd;
/*
* vshControl
*/
typedef struct __vshControl {
2006-05-29 15:39:31 +00:00
char *name; /* connection name */
virConnectPtr conn; /* connection to hypervisor (MAY BE NULL) */
vshCmd *cmd; /* the current command */
char *cmdstr; /* string with command */
int imode; /* interactive mode? */
int quiet; /* quiet mode */
int debug; /* print debug messages? */
int timing; /* print timing info? */
2007-03-08 13:48:22 +00:00
int readonly; /* connect readonly (first time only, not
* during explicit connect command)
*/
char *logfile; /* log file name */
int log_fd; /* log file descriptor */
char *historydir; /* readline history directory name */
char *historyfile; /* readline history file name */
2005-12-08 10:23:34 +00:00
} __vshControl;
static const vshCmdDef commands[];
2005-12-08 10:23:34 +00:00
static void vshError(vshControl *ctl, const char *format, ...)
ATTRIBUTE_FMT_PRINTF(2, 3);
2008-08-01 13:51:18 +00:00
static int vshInit(vshControl *ctl);
static int vshDeinit(vshControl *ctl);
static void vshUsage(void);
static void vshOpenLogFile(vshControl *ctl);
static void vshOutputLogFile(vshControl *ctl, int log_level, const char *format, va_list ap);
static void vshCloseLogFile(vshControl *ctl);
2005-12-08 10:23:34 +00:00
2008-08-01 13:51:18 +00:00
static int vshParseArgv(vshControl *ctl, int argc, char **argv);
2005-12-08 10:23:34 +00:00
2008-08-01 13:51:18 +00:00
static const char *vshCmddefGetInfo(const vshCmdDef *cmd, const char *info);
static const vshCmdDef *vshCmddefSearch(const char *cmdname);
static int vshCmddefHelp(vshControl *ctl, const char *name);
2005-12-08 10:23:34 +00:00
2008-08-01 13:51:18 +00:00
static vshCmdOpt *vshCommandOpt(const vshCmd *cmd, const char *name);
static int vshCommandOptInt(const vshCmd *cmd, const char *name, int *found);
static char *vshCommandOptString(const vshCmd *cmd, const char *name,
int *found);
static long long vshCommandOptLongLong(const vshCmd *cmd, const char *name,
int *found);
#if 0
2008-08-01 13:51:18 +00:00
static int vshCommandOptStringList(const vshCmd *cmd, const char *name, char ***data);
#endif
2008-08-01 13:51:18 +00:00
static int vshCommandOptBool(const vshCmd *cmd, const char *name);
2006-05-29 15:39:31 +00:00
#define VSH_BYID (1 << 1)
#define VSH_BYUUID (1 << 2)
#define VSH_BYNAME (1 << 3)
#define VSH_BYMAC (1 << 4)
2006-05-29 15:39:31 +00:00
2008-08-01 13:51:18 +00:00
static virDomainPtr vshCommandOptDomainBy(vshControl *ctl, const vshCmd *cmd,
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 10:26:54 +00:00
char **name, int flag);
2006-05-29 15:39:31 +00: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 10:26:54 +00:00
#define vshCommandOptDomain(_ctl, _cmd, _name) \
vshCommandOptDomainBy(_ctl, _cmd, _name, VSH_BYID|VSH_BYUUID|VSH_BYNAME)
2008-08-01 13:51:18 +00:00
static virNetworkPtr vshCommandOptNetworkBy(vshControl *ctl, const vshCmd *cmd,
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 10:26:54 +00:00
char **name, int flag);
/* 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 10:26:54 +00:00
#define vshCommandOptNetwork(_ctl, _cmd, _name) \
vshCommandOptNetworkBy(_ctl, _cmd, _name, \
VSH_BYUUID|VSH_BYNAME)
static virNWFilterPtr vshCommandOptNWFilterBy(vshControl *ctl, const vshCmd *cmd,
char **name, int flag);
/* default is lookup by Name and UUID */
#define vshCommandOptNWFilter(_ctl, _cmd, _name) \
vshCommandOptNWFilterBy(_ctl, _cmd, _name, \
VSH_BYUUID|VSH_BYNAME)
static virInterfacePtr vshCommandOptInterfaceBy(vshControl *ctl, const vshCmd *cmd,
char **name, int flag);
/* default is lookup by Name and MAC */
#define vshCommandOptInterface(_ctl, _cmd, _name) \
vshCommandOptInterfaceBy(_ctl, _cmd, _name, \
VSH_BYMAC|VSH_BYNAME)
2008-08-01 13:51:18 +00:00
static virStoragePoolPtr vshCommandOptPoolBy(vshControl *ctl, const vshCmd *cmd,
const char *optname, char **name, int flag);
/* default is lookup by Name and UUID */
#define vshCommandOptPool(_ctl, _cmd, _optname, _name) \
vshCommandOptPoolBy(_ctl, _cmd, _optname, _name, \
VSH_BYUUID|VSH_BYNAME)
2008-08-01 13:51:18 +00:00
static virStorageVolPtr vshCommandOptVolBy(vshControl *ctl, const vshCmd *cmd,
const char *optname,
const char *pooloptname,
char **name, int flag);
/* default is lookup by Name and UUID */
#define vshCommandOptVol(_ctl, _cmd,_optname, _pooloptname, _name) \
vshCommandOptVolBy(_ctl, _cmd, _optname, _pooloptname, _name, \
VSH_BYUUID|VSH_BYNAME)
static virSecretPtr vshCommandOptSecret(vshControl *ctl, const vshCmd *cmd,
char **name);
2008-08-01 13:51:18 +00:00
static void vshPrintExtra(vshControl *ctl, const char *format, ...)
ATTRIBUTE_FMT_PRINTF(2, 3);
2008-08-01 13:51:18 +00:00
static void vshDebug(vshControl *ctl, int level, const char *format, ...)
ATTRIBUTE_FMT_PRINTF(3, 4);
2006-05-29 15:39:31 +00:00
/* XXX: add batch support */
2006-05-22 14:38:33 +00:00
#define vshPrint(_ctl, ...) fprintf(stdout, __VA_ARGS__)
2005-12-08 10:23:34 +00:00
2005-12-08 14:22:52 +00:00
static const char *vshDomainStateToString(int state);
static const char *vshDomainVcpuStateToString(int state);
2008-08-01 13:51:18 +00:00
static int vshConnectionUsability(vshControl *ctl, virConnectPtr conn,
int showerror);
2005-12-08 10:23:34 +00: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);
2008-08-01 13:51:18 +00:00
static void *_vshMalloc(vshControl *ctl, size_t sz, const char *filename, int line);
#define vshMalloc(_ctl, _sz) _vshMalloc(_ctl, _sz, __FILE__, __LINE__)
2008-08-01 13:51:18 +00:00
static void *_vshCalloc(vshControl *ctl, size_t nmemb, size_t sz, const char *filename, int line);
#define vshCalloc(_ctl, _nmemb, _sz) _vshCalloc(_ctl, _nmemb, _sz, __FILE__, __LINE__)
2008-08-01 13:51:18 +00:00
static void *_vshRealloc(vshControl *ctl, void *ptr, size_t sz, const char *filename, int line);
#define vshRealloc(_ctl, _ptr, _sz) _vshRealloc(_ctl, _ptr, _sz, __FILE__, __LINE__)
2008-08-01 13:51:18 +00:00
static char *_vshStrdup(vshControl *ctl, const char *s, const char *filename, int line);
#define vshStrdup(_ctl, _s) _vshStrdup(_ctl, _s, __FILE__, __LINE__)
static int idsorter(const void *a, const void *b) {
const int *ia = (const int *)a;
const int *ib = (const int *)b;
if (*ia > *ib)
return 1;
else if (*ia < *ib)
return -1;
return 0;
}
static int namesorter(const void *a, const void *b) {
const char **sa = (const char**)a;
const char **sb = (const char**)b;
return strcasecmp(*sa, *sb);
}
static double
prettyCapacity(unsigned long long val,
const char **unit) {
if (val < 1024) {
*unit = "";
return (double)val;
} else if (val < (1024.0l * 1024.0l)) {
*unit = "KB";
return (((double)val / 1024.0l));
} else if (val < (1024.0l * 1024.0l * 1024.0l)) {
*unit = "MB";
return ((double)val / (1024.0l * 1024.0l));
} else if (val < (1024.0l * 1024.0l * 1024.0l * 1024.0l)) {
*unit = "GB";
return ((double)val / (1024.0l * 1024.0l * 1024.0l));
} else {
*unit = "TB";
return ((double)val / (1024.0l * 1024.0l * 1024.0l * 1024.0l));
}
}
2009-02-09 14:24:06 +00: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)
{
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)
return;
}
2009-02-09 14:24:06 +00:00
if (last_error->code == VIR_ERR_OK) {
vshError(ctl, "%s", _("unknown error"));
2009-02-09 14:24:06 +00:00
goto out;
}
vshError(ctl, "%s", last_error->message);
2009-02-09 14:24:06 +00:00
out:
virFreeError(last_error);
last_error = NULL;
}
/*
* Detection of disconnections and automatic reconnection support
*/
static int disconnected = 0; /* we may have been disconnected */
#ifdef SIGPIPE
/*
* 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
*/
static void vshCatchDisconnect(int sig, siginfo_t * siginfo,
void* context ATTRIBUTE_UNUSED) {
if ((sig == SIGPIPE) || (siginfo->si_signo == SIGPIPE))
disconnected++;
}
/*
* vshSetupSignals:
*
* Catch SIGPIPE signals which may arise when disconnection
* from libvirtd occurs
*/
static void
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);
}
#else
static void
vshSetupSignals(void) {}
#endif
/*
* vshReconnect:
*
* Reconnect after a disconnect from libvirtd
*
*/
static void
vshReconnect(vshControl *ctl) {
if (ctl->conn != NULL)
virConnectClose(ctl->conn);
ctl->conn = virConnectOpenAuth(ctl->name,
virConnectAuthPtrDefault,
ctl->readonly ? VIR_CONNECT_RO : 0);
if (!ctl->conn)
vshError(ctl, "%s", _("Failed to reconnect to the hypervisor"));
else
vshError(ctl, "%s", _("Reconnected to the hypervisor"));
disconnected = 0;
}
2005-12-08 10:23:34 +00:00
/* ---------------
* Commands
* ---------------
*/
/*
* "help" command
2005-12-08 10:23:34 +00:00
*/
static const vshCmdInfo info_help[] = {
{"help", N_("print help")},
{"desc", N_("Prints global help or command specific help.")},
{NULL, NULL}
2005-12-08 10:23:34 +00:00
};
static const vshCmdOptDef opts_help[] = {
{"command", VSH_OT_DATA, 0, N_("name of command")},
{NULL, 0, 0, NULL}
2005-12-08 10:23:34 +00:00
};
static int
2008-08-01 13:51:18 +00:00
cmdHelp(vshControl *ctl, const vshCmd *cmd)
{
2005-12-08 14:22:52 +00:00
const char *cmdname = vshCommandOptString(cmd, "command", NULL);
2005-12-08 10:23:34 +00:00
if (!cmdname) {
const vshCmdDef *def;
vshPrint(ctl, "%s", _("Commands:\n\n"));
for (def = commands; def->name; def++)
2006-05-22 14:38:33 +00:00
vshPrint(ctl, " %-15s %s\n", def->name,
_(vshCmddefGetInfo(def, "help")));
2005-12-08 10:23:34 +00:00
return TRUE;
}
return vshCmddefHelp(ctl, cmdname);
2005-12-08 10:23:34 +00:00
}
/*
* "autostart" command
*/
static const vshCmdInfo info_autostart[] = {
{"help", N_("autostart a domain")},
{"desc",
N_("Configure a domain to be automatically started at boot.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_autostart[] = {
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
{"disable", VSH_OT_BOOL, 0, N_("disable autostarting")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdAutostart(vshControl *ctl, const vshCmd *cmd)
{
virDomainPtr dom;
char *name;
int autostart;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
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 10:26:54 +00:00
if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
return FALSE;
autostart = !vshCommandOptBool(cmd, "disable");
if (virDomainSetAutostart(dom, autostart) < 0) {
if (autostart)
vshError(ctl, _("Failed to mark domain %s as autostarted"), name);
else
vshError(ctl, _("Failed to unmark domain %s as autostarted"), name);
virDomainFree(dom);
return FALSE;
}
if (autostart)
vshPrint(ctl, _("Domain %s marked as autostarted\n"), name);
else
vshPrint(ctl, _("Domain %s unmarked as autostarted\n"), name);
virDomainFree(dom);
return TRUE;
}
2005-12-08 10:23:34 +00:00
/*
* "connect" command
2005-12-08 10:23:34 +00:00
*/
static const vshCmdInfo info_connect[] = {
{"help", N_("(re)connect to hypervisor")},
{"desc",
N_("Connect to local hypervisor. This is built-in command after shell start up.")},
{NULL, NULL}
2005-12-08 10:23:34 +00:00
};
static const vshCmdOptDef opts_connect[] = {
{"name", VSH_OT_DATA, 0, N_("hypervisor connection URI")},
{"readonly", VSH_OT_BOOL, 0, N_("read-only connection")},
{NULL, 0, 0, NULL}
2005-12-08 10:23:34 +00:00
};
static int
2008-08-01 13:51:18 +00:00
cmdConnect(vshControl *ctl, const vshCmd *cmd)
{
2005-12-08 10:23:34 +00:00
int ro = vshCommandOptBool(cmd, "readonly");
2005-12-08 10:23:34 +00:00
if (ctl->conn) {
if (virConnectClose(ctl->conn) != 0) {
vshError(ctl, "%s", _("Failed to disconnect from the hypervisor"));
2005-12-08 10:23:34 +00:00
return FALSE;
}
ctl->conn = NULL;
}
VIR_FREE(ctl->name);
2007-01-22 20:43:02 +00:00
ctl->name = vshStrdup(ctl, vshCommandOptString(cmd, "name", NULL));
2006-05-29 15:39:31 +00:00
2007-03-08 13:48:22 +00:00
if (!ro) {
ctl->readonly = 0;
} else {
ctl->readonly = 1;
}
2005-12-08 10:23:34 +00:00
ctl->conn = virConnectOpenAuth(ctl->name, virConnectAuthPtrDefault,
ctl->readonly ? VIR_CONNECT_RO : 0);
2005-12-08 10:23:34 +00:00
if (!ctl->conn)
vshError(ctl, "%s", _("Failed to connect to the hypervisor"));
2005-12-08 10:23:34 +00:00
return ctl->conn ? TRUE : FALSE;
}
#ifndef WIN32
/*
* "console" command
*/
static const vshCmdInfo info_console[] = {
{"help", N_("connect to the guest console")},
{"desc",
N_("Connect the virtual serial console for the guest")},
{NULL, NULL}
};
static const vshCmdOptDef opts_console[] = {
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
{NULL, 0, 0, NULL}
};
static int
cmdRunConsole(vshControl *ctl, virDomainPtr dom)
{
xmlDocPtr xml = NULL;
xmlXPathObjectPtr obj = NULL;
xmlXPathContextPtr ctxt = NULL;
int ret = FALSE;
char *doc;
char *thatHost = NULL;
char *thisHost = NULL;
virDomainInfo dominfo;
if (!(thisHost = virGetHostname(ctl->conn))) {
vshError(ctl, "%s", _("Failed to get local hostname"));
goto cleanup;
}
if (!(thatHost = virConnectGetHostname(ctl->conn))) {
vshError(ctl, "%s", _("Failed to get connection hostname"));
goto cleanup;
}
if (STRNEQ(thisHost, thatHost)) {
vshError(ctl, "%s", _("Cannot connect to a remote console device"));
goto cleanup;
}
if (virDomainGetInfo(dom, &dominfo) < 0) {
vshError(ctl, "%s", _("Unable to get domain status"));
goto cleanup;
}
if (dominfo.state == VIR_DOMAIN_SHUTOFF) {
vshError(ctl, "%s", _("The domain is not running"));
goto cleanup;
}
doc = virDomainGetXMLDesc(dom, 0);
if (!doc)
goto cleanup;
xml = xmlReadDoc((const xmlChar *) doc, "domain.xml", NULL,
XML_PARSE_NOENT | XML_PARSE_NONET |
XML_PARSE_NOWARNING);
VIR_FREE(doc);
if (!xml)
goto cleanup;
ctxt = xmlXPathNewContext(xml);
if (!ctxt)
goto cleanup;
obj = xmlXPathEval(BAD_CAST "string(/domain/devices/console/@tty)", ctxt);
if ((obj != NULL) && ((obj->type == XPATH_STRING) &&
(obj->stringval != NULL) && (obj->stringval[0] != 0))) {
vshPrintExtra(ctl, _("Connected to domain %s\n"), virDomainGetName(dom));
vshPrintExtra(ctl, "%s", _("Escape character is ^]\n"));
2007-01-28 19:47:36 +00:00
if (vshRunConsole((const char *)obj->stringval) == 0)
ret = TRUE;
} else {
vshPrintExtra(ctl, "%s", _("No console available for domain\n"));
}
xmlXPathFreeObject(obj);
cleanup:
xmlXPathFreeContext(ctxt);
if (xml)
xmlFreeDoc(xml);
VIR_FREE(thisHost);
VIR_FREE(thatHost);
return ret;
}
static int
cmdConsole(vshControl *ctl, const vshCmd *cmd)
{
virDomainPtr dom;
int ret;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
return FALSE;
ret = cmdRunConsole(ctl, dom);
virDomainFree(dom);
return ret;
}
#endif /* WIN32 */
2005-12-08 10:23:34 +00:00
/*
* "list" command
*/
static const vshCmdInfo info_list[] = {
{"help", N_("list domains")},
{"desc", N_("Returns list of domains.")},
{NULL, NULL}
2005-12-08 10:23:34 +00:00
};
static const vshCmdOptDef opts_list[] = {
{"inactive", VSH_OT_BOOL, 0, N_("list inactive domains")},
{"all", VSH_OT_BOOL, 0, N_("list inactive & active domains")},
{NULL, 0, 0, NULL}
};
2005-12-08 10:23:34 +00:00
static int
2008-08-01 13:51:18 +00:00
cmdList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
{
int inactive = vshCommandOptBool(cmd, "inactive");
int all = vshCommandOptBool(cmd, "all");
int active = !inactive || all ? 1 : 0;
int *ids = NULL, maxid = 0, i;
2007-03-06 21:55:44 +00:00
char **names = NULL;
int maxname = 0;
inactive |= all;
2005-12-08 10:23:34 +00:00
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
if (active) {
maxid = virConnectNumOfDomains(ctl->conn);
if (maxid < 0) {
vshError(ctl, "%s", _("Failed to list active domains"));
return FALSE;
}
if (maxid) {
ids = vshMalloc(ctl, sizeof(int) * maxid);
if ((maxid = virConnectListDomains(ctl->conn, &ids[0], maxid)) < 0) {
vshError(ctl, "%s", _("Failed to list active domains"));
VIR_FREE(ids);
return FALSE;
}
qsort(&ids[0], maxid, sizeof(int), idsorter);
}
}
if (inactive) {
maxname = virConnectNumOfDefinedDomains(ctl->conn);
if (maxname < 0) {
vshError(ctl, "%s", _("Failed to list inactive domains"));
VIR_FREE(ids);
return FALSE;
}
if (maxname) {
names = vshMalloc(ctl, sizeof(char *) * maxname);
if ((maxname = virConnectListDefinedDomains(ctl->conn, names, maxname)) < 0) {
vshError(ctl, "%s", _("Failed to list inactive domains"));
VIR_FREE(ids);
VIR_FREE(names);
return FALSE;
}
qsort(&names[0], maxname, sizeof(char*), namesorter);
}
}
vshPrintExtra(ctl, "%3s %-20s %s\n", _("Id"), _("Name"), _("State"));
2006-05-22 14:38:33 +00:00
vshPrintExtra(ctl, "----------------------------------\n");
for (i = 0; i < maxid; i++) {
2005-12-08 10:23:34 +00:00
virDomainInfo info;
virDomainPtr dom = virDomainLookupByID(ctl->conn, ids[i]);
const char *state;
/* this kind of work with domains is not atomic operation */
2005-12-08 10:23:34 +00:00
if (!dom)
continue;
if (virDomainGetInfo(dom, &info) < 0)
state = _("no state");
else
state = _(vshDomainStateToString(info.state));
2006-05-22 14:38:33 +00:00
vshPrint(ctl, "%3d %-20s %s\n",
virDomainGetID(dom),
virDomainGetName(dom),
state);
virDomainFree(dom);
2005-12-08 10:23:34 +00:00
}
for (i = 0; i < maxname; i++) {
virDomainInfo info;
virDomainPtr dom = virDomainLookupByName(ctl->conn, names[i]);
const char *state;
/* this kind of work with domains is not atomic operation */
if (!dom) {
VIR_FREE(names[i]);
continue;
}
if (virDomainGetInfo(dom, &info) < 0)
state = _("no state");
else
state = _(vshDomainStateToString(info.state));
vshPrint(ctl, "%3s %-20s %s\n", "-", names[i], state);
virDomainFree(dom);
VIR_FREE(names[i]);
}
VIR_FREE(ids);
VIR_FREE(names);
2005-12-08 10:23:34 +00:00
return TRUE;
}
/*
2006-04-04 21:52:31 +00:00
* "domstate" command
2005-12-08 10:23:34 +00:00
*/
static const vshCmdInfo info_domstate[] = {
{"help", N_("domain state")},
{"desc", N_("Returns state about a domain.")},
{NULL, NULL}
2005-12-08 10:23:34 +00:00
};
static const vshCmdOptDef opts_domstate[] = {
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
{NULL, 0, 0, NULL}
2005-12-08 10:23:34 +00:00
};
static int
2008-08-01 13:51:18 +00:00
cmdDomstate(vshControl *ctl, const vshCmd *cmd)
{
virDomainInfo info;
2005-12-08 10:23:34 +00:00
virDomainPtr dom;
2005-12-15 17:00:43 +00:00
int ret = TRUE;
2005-12-08 10:23:34 +00:00
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
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 10:26:54 +00:00
if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
2005-12-08 10:23:34 +00:00
return FALSE;
if (virDomainGetInfo(dom, &info) == 0)
2006-05-22 14:38:33 +00:00
vshPrint(ctl, "%s\n",
_(vshDomainStateToString(info.state)));
2005-12-08 10:23:34 +00:00
else
ret = FALSE;
virDomainFree(dom);
return ret;
}
/* "domblkstat" command
*/
static const vshCmdInfo info_domblkstat[] = {
{"help", N_("get device block stats for a domain")},
{"desc", N_("Get device block stats for a running domain.")},
{NULL,NULL}
};
static const vshCmdOptDef opts_domblkstat[] = {
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
{"device", VSH_OT_DATA, VSH_OFLAG_REQ, N_("block device")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdDomblkstat (vshControl *ctl, const vshCmd *cmd)
{
virDomainPtr dom;
char *name, *device;
struct _virDomainBlockStats stats;
if (!vshConnectionUsability (ctl, ctl->conn, TRUE))
return FALSE;
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 10:26:54 +00:00
if (!(dom = vshCommandOptDomain (ctl, cmd, &name)))
return FALSE;
if (!(device = vshCommandOptString (cmd, "device", NULL))) {
virDomainFree(dom);
return FALSE;
}
if (virDomainBlockStats (dom, device, &stats, sizeof stats) == -1) {
vshError(ctl, _("Failed to get block stats %s %s"), name, device);
virDomainFree(dom);
return FALSE;
}
if (stats.rd_req >= 0)
vshPrint (ctl, "%s rd_req %lld\n", device, stats.rd_req);
if (stats.rd_bytes >= 0)
vshPrint (ctl, "%s rd_bytes %lld\n", device, stats.rd_bytes);
if (stats.wr_req >= 0)
vshPrint (ctl, "%s wr_req %lld\n", device, stats.wr_req);
if (stats.wr_bytes >= 0)
vshPrint (ctl, "%s wr_bytes %lld\n", device, stats.wr_bytes);
if (stats.errs >= 0)
vshPrint (ctl, "%s errs %lld\n", device, stats.errs);
virDomainFree(dom);
return TRUE;
}
/* "domifstat" command
*/
static const vshCmdInfo info_domifstat[] = {
{"help", N_("get network interface stats for a domain")},
{"desc", N_("Get network interface stats for a running domain.")},
{NULL,NULL}
};
static const vshCmdOptDef opts_domifstat[] = {
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
{"interface", VSH_OT_DATA, VSH_OFLAG_REQ, N_("interface device")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdDomIfstat (vshControl *ctl, const vshCmd *cmd)
{
virDomainPtr dom;
char *name, *device;
struct _virDomainInterfaceStats stats;
if (!vshConnectionUsability (ctl, ctl->conn, TRUE))
return FALSE;
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 10:26:54 +00:00
if (!(dom = vshCommandOptDomain (ctl, cmd, &name)))
return FALSE;
if (!(device = vshCommandOptString (cmd, "interface", NULL))) {
virDomainFree(dom);
return FALSE;
}
if (virDomainInterfaceStats (dom, device, &stats, sizeof stats) == -1) {
vshError(ctl, _("Failed to get interface stats %s %s"), name, device);
virDomainFree(dom);
return FALSE;
}
if (stats.rx_bytes >= 0)
vshPrint (ctl, "%s rx_bytes %lld\n", device, stats.rx_bytes);
if (stats.rx_packets >= 0)
vshPrint (ctl, "%s rx_packets %lld\n", device, stats.rx_packets);
if (stats.rx_errs >= 0)
vshPrint (ctl, "%s rx_errs %lld\n", device, stats.rx_errs);
if (stats.rx_drop >= 0)
vshPrint (ctl, "%s rx_drop %lld\n", device, stats.rx_drop);
if (stats.tx_bytes >= 0)
vshPrint (ctl, "%s tx_bytes %lld\n", device, stats.tx_bytes);
if (stats.tx_packets >= 0)
vshPrint (ctl, "%s tx_packets %lld\n", device, stats.tx_packets);
if (stats.tx_errs >= 0)
vshPrint (ctl, "%s tx_errs %lld\n", device, stats.tx_errs);
if (stats.tx_drop >= 0)
vshPrint (ctl, "%s tx_drop %lld\n", device, stats.tx_drop);
virDomainFree(dom);
return TRUE;
}
/*
* "dommemstats" command
*/
static const vshCmdInfo info_dommemstat[] = {
{"help", N_("get memory statistics for a domain")},
{"desc", N_("Get memory statistics for a runnng domain.")},
{NULL,NULL}
};
static const vshCmdOptDef opts_dommemstat[] = {
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
{NULL, 0, 0, NULL}
};
static int
cmdDomMemStat(vshControl *ctl, const vshCmd *cmd)
{
virDomainPtr dom;
char *name;
struct _virDomainMemoryStat stats[VIR_DOMAIN_MEMORY_STAT_NR];
unsigned int nr_stats, i;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
return FALSE;
nr_stats = virDomainMemoryStats (dom, stats, VIR_DOMAIN_MEMORY_STAT_NR, 0);
if (nr_stats == -1) {
vshError(ctl, _("Failed to get memory statistics for domain %s"), name);
virDomainFree(dom);
return FALSE;
}
for (i = 0; i < nr_stats; i++) {
if (stats[i].tag == VIR_DOMAIN_MEMORY_STAT_SWAP_IN)
vshPrint (ctl, "swap_in %llu\n", stats[i].val);
if (stats[i].tag == VIR_DOMAIN_MEMORY_STAT_SWAP_OUT)
vshPrint (ctl, "swap_out %llu\n", stats[i].val);
if (stats[i].tag == VIR_DOMAIN_MEMORY_STAT_MAJOR_FAULT)
vshPrint (ctl, "major_fault %llu\n", stats[i].val);
if (stats[i].tag == VIR_DOMAIN_MEMORY_STAT_MINOR_FAULT)
vshPrint (ctl, "minor_fault %llu\n", stats[i].val);
if (stats[i].tag == VIR_DOMAIN_MEMORY_STAT_UNUSED)
vshPrint (ctl, "unused %llu\n", stats[i].val);
if (stats[i].tag == VIR_DOMAIN_MEMORY_STAT_AVAILABLE)
vshPrint (ctl, "available %llu\n", stats[i].val);
}
virDomainFree(dom);
return TRUE;
}
/*
* "suspend" command
*/
static const vshCmdInfo info_suspend[] = {
{"help", N_("suspend a domain")},
{"desc", N_("Suspend a running domain.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_suspend[] = {
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdSuspend(vshControl *ctl, const vshCmd *cmd)
{
virDomainPtr dom;
2005-12-15 17:00:43 +00:00
char *name;
int ret = TRUE;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
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 10:26:54 +00:00
if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
return FALSE;
if (virDomainSuspend(dom) == 0) {
vshPrint(ctl, _("Domain %s suspended\n"), name);
} else {
vshError(ctl, _("Failed to suspend domain %s"), name);
ret = FALSE;
}
virDomainFree(dom);
return ret;
}
/*
* "create" command
*/
static const vshCmdInfo info_create[] = {
{"help", N_("create a domain from an XML file")},
{"desc", N_("Create a domain.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_create[] = {
{"file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("file containing an XML domain description")},
#ifndef WIN32
{"console", VSH_OT_BOOL, 0, N_("attach to console after creation")},
#endif
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdCreate(vshControl *ctl, const vshCmd *cmd)
{
virDomainPtr dom;
char *from;
int found;
int ret = TRUE;
char *buffer;
#ifndef WIN32
int console = vshCommandOptBool(cmd, "console");
#endif
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
from = vshCommandOptString(cmd, "file", &found);
if (!found)
return FALSE;
2008-01-21 15:27:14 +00:00
if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0)
return FALSE;
dom = virDomainCreateXML(ctl->conn, buffer, 0);
VIR_FREE(buffer);
if (dom != NULL) {
vshPrint(ctl, _("Domain %s created from %s\n"),
virDomainGetName(dom), from);
#ifndef WIN32
if (console)
cmdRunConsole(ctl, dom);
#endif
virDomainFree(dom);
} else {
vshError(ctl, _("Failed to create domain from %s"), from);
ret = FALSE;
}
return ret;
}
/*
* "define" command
*/
static const vshCmdInfo info_define[] = {
{"help", N_("define (but don't start) a domain from an XML file")},
{"desc", N_("Define a domain.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_define[] = {
{"file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("file containing an XML domain description")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdDefine(vshControl *ctl, const vshCmd *cmd)
{
virDomainPtr dom;
char *from;
int found;
int ret = TRUE;
char *buffer;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
from = vshCommandOptString(cmd, "file", &found);
if (!found)
return FALSE;
2008-01-21 15:27:14 +00:00
if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0)
return FALSE;
dom = virDomainDefineXML(ctl->conn, buffer);
VIR_FREE(buffer);
if (dom != NULL) {
vshPrint(ctl, _("Domain %s defined from %s\n"),
virDomainGetName(dom), from);
virDomainFree(dom);
} else {
vshError(ctl, _("Failed to define domain from %s"), from);
ret = FALSE;
}
return ret;
}
/*
* "undefine" command
*/
static const vshCmdInfo info_undefine[] = {
{"help", N_("undefine an inactive domain")},
{"desc", N_("Undefine the configuration for an inactive domain.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_undefine[] = {
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name or uuid")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdUndefine(vshControl *ctl, const vshCmd *cmd)
{
virDomainPtr dom;
int ret = TRUE;
char *name;
int found;
int id;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
name = vshCommandOptString(cmd, "domain", &found);
if (!found)
return FALSE;
if (name && virStrToLong_i(name, NULL, 10, &id) == 0
&& id >= 0 && (dom = virDomainLookupByID(ctl->conn, id))) {
vshError(ctl,
_("a running domain like %s cannot be undefined;\n"
"to undefine, first shutdown then undefine"
" using its name or UUID"),
name);
virDomainFree(dom);
return FALSE;
}
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 10:26:54 +00:00
if (!(dom = vshCommandOptDomainBy(ctl, cmd, &name,
VSH_BYNAME|VSH_BYUUID)))
return FALSE;
if (virDomainUndefine(dom) == 0) {
vshPrint(ctl, _("Domain %s has been undefined\n"), name);
} else {
vshError(ctl, _("Failed to undefine domain %s"), name);
ret = FALSE;
}
virDomainFree(dom);
return ret;
}
/*
* "start" command
*/
static const vshCmdInfo info_start[] = {
{"help", N_("start a (previously defined) inactive domain")},
{"desc", N_("Start a domain.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_start[] = {
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("name of the inactive domain")},
#ifndef WIN32
{"console", VSH_OT_BOOL, 0, N_("attach to console after creation")},
#endif
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdStart(vshControl *ctl, const vshCmd *cmd)
{
virDomainPtr dom;
int ret = TRUE;
#ifndef WIN32
int console = vshCommandOptBool(cmd, "console");
#endif
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
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 10:26:54 +00:00
if (!(dom = vshCommandOptDomainBy(ctl, cmd, NULL, VSH_BYNAME)))
return FALSE;
if (virDomainGetID(dom) != (unsigned int)-1) {
vshError(ctl, "%s", _("Domain is already active"));
virDomainFree(dom);
return FALSE;
}
if (virDomainCreate(dom) == 0) {
vshPrint(ctl, _("Domain %s started\n"),
virDomainGetName(dom));
#ifndef WIN32
if (console)
cmdRunConsole(ctl, dom);
#endif
} else {
vshError(ctl, _("Failed to start domain %s"), virDomainGetName(dom));
ret = FALSE;
}
virDomainFree(dom);
return ret;
}
/*
* "save" command
*/
static const vshCmdInfo info_save[] = {
{"help", N_("save a domain state to a file")},
{"desc", N_("Save a running domain.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_save[] = {
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
{"file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("where to save the data")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdSave(vshControl *ctl, const vshCmd *cmd)
{
virDomainPtr dom;
char *name;
char *to;
int ret = TRUE;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
2006-01-25 09:46:22 +00:00
if (!(to = vshCommandOptString(cmd, "file", NULL)))
return FALSE;
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 10:26:54 +00:00
if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
return FALSE;
if (virDomainSave(dom, to) == 0) {
vshPrint(ctl, _("Domain %s saved to %s\n"), name, to);
} else {
vshError(ctl, _("Failed to save domain %s to %s"), name, to);
ret = FALSE;
}
virDomainFree(dom);
return ret;
}
/*
* "managedsave" command
*/
static const vshCmdInfo info_managedsave[] = {
{"help", N_("managed save of a domain state")},
{"desc", N_("Save and stop a running domain, so libvirt can restart it from the same state")},
{NULL, NULL}
};
static const vshCmdOptDef opts_managedsave[] = {
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
{NULL, 0, 0, NULL}
};
static int
cmdManagedSave(vshControl *ctl, const vshCmd *cmd)
{
virDomainPtr dom;
char *name;
int ret = TRUE;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
return FALSE;
if (virDomainManagedSave(dom, 0) == 0) {
vshPrint(ctl, _("Domain %s state saved by libvirt\n"), name);
} else {
vshError(ctl, _("Failed to save domain %s state"), name);
ret = FALSE;
}
virDomainFree(dom);
return ret;
}
/*
* "schedinfo" command
*/
static const vshCmdInfo info_schedinfo[] = {
{"help", N_("show/set scheduler parameters")},
{"desc", N_("Show/Set scheduler parameters.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_schedinfo[] = {
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
{"set", VSH_OT_STRING, VSH_OFLAG_NONE, N_("parameter=value")},
{"weight", VSH_OT_INT, VSH_OFLAG_NONE, N_("weight for XEN_CREDIT")},
{"cap", VSH_OT_INT, VSH_OFLAG_NONE, N_("cap for XEN_CREDIT")},
{NULL, 0, 0, NULL}
};
static int
cmdSchedInfoUpdate(vshControl *ctl, const vshCmd *cmd,
virSchedParameterPtr param)
{
int found;
char *data;
/* Legacy 'weight' parameter */
if (STREQ(param->field, "weight") &&
param->type == VIR_DOMAIN_SCHED_FIELD_UINT &&
vshCommandOptBool(cmd, "weight")) {
int val;
val = vshCommandOptInt(cmd, "weight", &found);
if (!found) {
vshError(ctl, "%s", _("Invalid value of weight"));
return -1;
} else {
param->value.ui = val;
}
return 1;
}
/* Legacy 'cap' parameter */
if (STREQ(param->field, "cap") &&
param->type == VIR_DOMAIN_SCHED_FIELD_UINT &&
vshCommandOptBool(cmd, "cap")) {
int val;
val = vshCommandOptInt(cmd, "cap", &found);
if (!found) {
vshError(ctl, "%s", _("Invalid value of cap"));
return -1;
} else {
param->value.ui = val;
}
return 1;
}
if ((data = vshCommandOptString(cmd, "set", NULL))) {
char *val = strchr(data, '=');
int match = 0;
if (!val) {
vshError(ctl, "%s", _("Invalid syntax for --set, expecting name=value"));
return -1;
}
*val = '\0';
match = STREQ(data, param->field);
*val = '=';
val++;
if (!match)
return 0;
switch (param->type) {
case VIR_DOMAIN_SCHED_FIELD_INT:
if (virStrToLong_i(val, NULL, 10, &param->value.i) < 0) {
vshError(ctl, "%s",
_("Invalid value for parameter, expecting an int"));
return -1;
}
break;
case VIR_DOMAIN_SCHED_FIELD_UINT:
if (virStrToLong_ui(val, NULL, 10, &param->value.ui) < 0) {
vshError(ctl, "%s",
_("Invalid value for parameter, expecting an unsigned int"));
return -1;
}
break;
case VIR_DOMAIN_SCHED_FIELD_LLONG:
if (virStrToLong_ll(val, NULL, 10, &param->value.l) < 0) {
vshError(ctl, "%s",
_("Invalid value for parameter, expecting an long long"));
return -1;
}
break;
case VIR_DOMAIN_SCHED_FIELD_ULLONG:
if (virStrToLong_ull(val, NULL, 10, &param->value.ul) < 0) {
vshError(ctl, "%s",
_("Invalid value for parameter, expecting an unsigned long long"));
return -1;
}
break;
case VIR_DOMAIN_SCHED_FIELD_DOUBLE:
if (virStrToDouble(val, NULL, &param->value.d) < 0) {
vshError(ctl, "%s", _("Invalid value for parameter, expecting a double"));
return -1;
}
break;
case VIR_DOMAIN_SCHED_FIELD_BOOLEAN:
param->value.b = STREQ(val, "0") ? 0 : 1;
}
return 1;
}
return 0;
}
static int
cmdSchedinfo(vshControl *ctl, const vshCmd *cmd)
{
char *schedulertype;
virDomainPtr dom;
virSchedParameterPtr params = NULL;
int nparams = 0;
int update = 0;
int i, ret;
int ret_val = FALSE;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
return FALSE;
/* Print SchedulerType */
schedulertype = virDomainGetSchedulerType(dom, &nparams);
if (schedulertype!= NULL){
vshPrint(ctl, "%-15s: %s\n", _("Scheduler"),
schedulertype);
VIR_FREE(schedulertype);
} else {
vshPrint(ctl, "%-15s: %s\n", _("Scheduler"), _("Unknown"));
goto cleanup;
}
if (nparams) {
params = vshMalloc(ctl, sizeof(virSchedParameter)* nparams);
if (params == NULL)
goto cleanup;
memset(params, 0, sizeof(virSchedParameter)* nparams);
ret = virDomainGetSchedulerParameters(dom, params, &nparams);
if (ret == -1)
goto cleanup;
/* See if any params are being set */
for (i = 0; i < nparams; i++){
ret = cmdSchedInfoUpdate(ctl, cmd, &(params[i]));
if (ret == -1)
goto cleanup;
if (ret == 1)
update = 1;
}
/* Update parameters & refresh data */
if (update) {
ret = virDomainSetSchedulerParameters(dom, params, nparams);
if (ret == -1)
goto cleanup;
ret = virDomainGetSchedulerParameters(dom, params, &nparams);
if (ret == -1)
goto cleanup;
}
ret_val = TRUE;
for (i = 0; i < nparams; i++){
switch (params[i].type) {
case VIR_DOMAIN_SCHED_FIELD_INT:
printf("%-15s: %d\n", params[i].field, params[i].value.i);
break;
case VIR_DOMAIN_SCHED_FIELD_UINT:
printf("%-15s: %u\n", params[i].field, params[i].value.ui);
break;
case VIR_DOMAIN_SCHED_FIELD_LLONG:
printf("%-15s: %lld\n", params[i].field, params[i].value.l);
break;
case VIR_DOMAIN_SCHED_FIELD_ULLONG:
printf("%-15s: %llu\n", params[i].field, params[i].value.ul);
break;
case VIR_DOMAIN_SCHED_FIELD_DOUBLE:
printf("%-15s: %f\n", params[i].field, params[i].value.d);
break;
case VIR_DOMAIN_SCHED_FIELD_BOOLEAN:
printf("%-15s: %d\n", params[i].field, params[i].value.b);
break;
default:
printf("not implemented scheduler parameter type\n");
}
}
}
cleanup:
VIR_FREE(params);
virDomainFree(dom);
return ret_val;
}
/*
* "restore" command
*/
static const vshCmdInfo info_restore[] = {
{"help", N_("restore a domain from a saved state in a file")},
{"desc", N_("Restore a domain.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_restore[] = {
{"file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("the state to restore")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdRestore(vshControl *ctl, const vshCmd *cmd)
{
char *from;
int found;
int ret = TRUE;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
from = vshCommandOptString(cmd, "file", &found);
if (!found)
return FALSE;
if (virDomainRestore(ctl->conn, from) == 0) {
vshPrint(ctl, _("Domain restored from %s\n"), from);
} else {
vshError(ctl, _("Failed to restore domain from %s"), from);
ret = FALSE;
}
return ret;
}
/*
* "dump" command
*/
static const vshCmdInfo info_dump[] = {
{"help", N_("dump the core of a domain to a file for analysis")},
{"desc", N_("Core dump a domain.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_dump[] = {
{"live", VSH_OT_BOOL, 0, N_("perform a live core dump if supported")},
{"crash", VSH_OT_BOOL, 0, N_("crash the domain after core dump")},
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
{"file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("where to dump the core")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdDump(vshControl *ctl, const vshCmd *cmd)
{
virDomainPtr dom;
char *name;
char *to;
int ret = TRUE;
int flags = 0;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
if (!(to = vshCommandOptString(cmd, "file", NULL)))
return FALSE;
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 10:26:54 +00:00
if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
return FALSE;
if (vshCommandOptBool (cmd, "live"))
flags |= VIR_DUMP_LIVE;
if (vshCommandOptBool (cmd, "crash"))
flags |= VIR_DUMP_CRASH;
if (virDomainCoreDump(dom, to, flags) == 0) {
vshPrint(ctl, _("Domain %s dumped to %s\n"), name, to);
} else {
vshError(ctl, _("Failed to core dump domain %s to %s"), name, to);
ret = FALSE;
}
virDomainFree(dom);
return ret;
}
/*
* "resume" command
*/
static const vshCmdInfo info_resume[] = {
{"help", N_("resume a domain")},
{"desc", N_("Resume a previously suspended domain.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_resume[] = {
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdResume(vshControl *ctl, const vshCmd *cmd)
{
virDomainPtr dom;
2005-12-15 17:00:43 +00:00
int ret = TRUE;
char *name;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
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 10:26:54 +00:00
if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
return FALSE;
if (virDomainResume(dom) == 0) {
vshPrint(ctl, _("Domain %s resumed\n"), name);
} else {
vshError(ctl, _("Failed to resume domain %s"), name);
ret = FALSE;
}
virDomainFree(dom);
return ret;
}
/*
* "shutdown" command
*/
static const vshCmdInfo info_shutdown[] = {
{"help", N_("gracefully shutdown a domain")},
{"desc", N_("Run shutdown in the target domain.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_shutdown[] = {
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdShutdown(vshControl *ctl, const vshCmd *cmd)
{
virDomainPtr dom;
int ret = TRUE;
char *name;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
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 10:26:54 +00:00
if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
return FALSE;
if (virDomainShutdown(dom) == 0) {
vshPrint(ctl, _("Domain %s is being shutdown\n"), name);
} else {
vshError(ctl, _("Failed to shutdown domain %s"), name);
ret = FALSE;
}
virDomainFree(dom);
return ret;
}
/*
* "reboot" command
*/
static const vshCmdInfo info_reboot[] = {
{"help", N_("reboot a domain")},
{"desc", N_("Run a reboot command in the target domain.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_reboot[] = {
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdReboot(vshControl *ctl, const vshCmd *cmd)
{
virDomainPtr dom;
int ret = TRUE;
char *name;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
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 10:26:54 +00:00
if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
return FALSE;
if (virDomainReboot(dom, 0) == 0) {
vshPrint(ctl, _("Domain %s is being rebooted\n"), name);
} else {
vshError(ctl, _("Failed to reboot domain %s"), name);
ret = FALSE;
}
virDomainFree(dom);
return ret;
}
/*
* "destroy" command
*/
static const vshCmdInfo info_destroy[] = {
{"help", N_("destroy a domain")},
{"desc", N_("Destroy a given domain.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_destroy[] = {
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdDestroy(vshControl *ctl, const vshCmd *cmd)
{
virDomainPtr dom;
2005-12-15 17:00:43 +00:00
int ret = TRUE;
char *name;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
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 10:26:54 +00:00
if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
return FALSE;
if (virDomainDestroy(dom) == 0) {
vshPrint(ctl, _("Domain %s destroyed\n"), name);
} else {
vshError(ctl, _("Failed to destroy domain %s"), name);
ret = FALSE;
}
virDomainFree(dom);
2005-12-08 10:23:34 +00:00
return ret;
}
/*
* "dominfo" command
2005-12-08 10:23:34 +00:00
*/
static const vshCmdInfo info_dominfo[] = {
{"help", N_("domain information")},
{"desc", N_("Returns basic information about the domain.")},
{NULL, NULL}
2005-12-08 10:23:34 +00:00
};
static const vshCmdOptDef opts_dominfo[] = {
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
{NULL, 0, 0, NULL}
2005-12-08 10:23:34 +00:00
};
static int
2008-08-01 13:51:18 +00:00
cmdDominfo(vshControl *ctl, const vshCmd *cmd)
{
2005-12-08 10:23:34 +00:00
virDomainInfo info;
virDomainPtr dom;
virSecurityModel secmodel;
virSecurityLabel seclabel;
int ret = TRUE, autostart;
unsigned int id;
char *str, uuid[VIR_UUID_STRING_BUFLEN];
2005-12-08 10:23:34 +00:00
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
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 10:26:54 +00:00
if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
2005-12-08 10:23:34 +00:00
return FALSE;
id = virDomainGetID(dom);
if (id == ((unsigned int)-1))
vshPrint(ctl, "%-15s %s\n", _("Id:"), "-");
else
vshPrint(ctl, "%-15s %d\n", _("Id:"), id);
vshPrint(ctl, "%-15s %s\n", _("Name:"), virDomainGetName(dom));
2006-05-22 14:38:33 +00:00
if (virDomainGetUUIDString(dom, &uuid[0])==0)
vshPrint(ctl, "%-15s %s\n", _("UUID:"), uuid);
if ((str = virDomainGetOSType(dom))) {
vshPrint(ctl, "%-15s %s\n", _("OS Type:"), str);
VIR_FREE(str);
}
if (virDomainGetInfo(dom, &info) == 0) {
vshPrint(ctl, "%-15s %s\n", _("State:"),
_(vshDomainStateToString(info.state)));
vshPrint(ctl, "%-15s %d\n", _("CPU(s):"), info.nrVirtCpu);
if (info.cpuTime != 0) {
double cpuUsed = info.cpuTime;
cpuUsed /= 1000000000.0;
vshPrint(ctl, "%-15s %.1lfs\n", _("CPU time:"), cpuUsed);
2005-12-08 10:23:34 +00:00
}
if (info.maxMem != UINT_MAX)
vshPrint(ctl, "%-15s %lu kB\n", _("Max memory:"),
info.maxMem);
else
vshPrint(ctl, "%-15s %s\n", _("Max memory:"),
_("no limit"));
vshPrint(ctl, "%-15s %lu kB\n", _("Used memory:"),
info.memory);
2005-12-08 10:23:34 +00:00
} else {
ret = FALSE;
}
if (!virDomainGetAutostart(dom, &autostart)) {
vshPrint(ctl, "%-15s %s\n", _("Autostart:"),
autostart ? _("enable") : _("disable") );
}
/* Security model and label information */
memset(&secmodel, 0, sizeof secmodel);
if (virNodeGetSecurityModel(ctl->conn, &secmodel) == -1) {
if (last_error->code != VIR_ERR_NO_SUPPORT) {
virDomainFree(dom);
return FALSE;
}
} else {
/* Only print something if a security model is active */
if (secmodel.model[0] != '\0') {
vshPrint(ctl, "%-15s %s\n", _("Security model:"), secmodel.model);
vshPrint(ctl, "%-15s %s\n", _("Security DOI:"), secmodel.doi);
/* Security labels are only valid for active domains */
memset(&seclabel, 0, sizeof seclabel);
if (virDomainGetSecurityLabel(dom, &seclabel) == -1) {
virDomainFree(dom);
return FALSE;
} else {
if (seclabel.label[0] != '\0')
vshPrint(ctl, "%-15s %s (%s)\n", _("Security label:"),
seclabel.label, seclabel.enforcing ? "enforcing" : "permissive");
}
}
}
virDomainFree(dom);
2005-12-08 10:23:34 +00:00
return ret;
}
/*
* "domjobinfo" command
*/
static const vshCmdInfo info_domjobinfo[] = {
{"help", N_("domain job information")},
{"desc", N_("Returns information about jobs running on a domain.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_domjobinfo[] = {
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
{NULL, 0, 0, NULL}
};
static int
cmdDomjobinfo(vshControl *ctl, const vshCmd *cmd)
{
virDomainJobInfo info;
virDomainPtr dom;
int ret = TRUE;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
return FALSE;
if (virDomainGetJobInfo(dom, &info) == 0) {
const char *unit;
double val;
vshPrint(ctl, "%-17s ", _("Job type:"));
switch (info.type) {
case VIR_DOMAIN_JOB_BOUNDED:
vshPrint(ctl, "%-12s\n", _("Bounded"));
break;
case VIR_DOMAIN_JOB_UNBOUNDED:
vshPrint(ctl, "%-12s\n", _("Unbounded"));
break;
case VIR_DOMAIN_JOB_NONE:
default:
vshPrint(ctl, "%-12s\n", _("None"));
goto cleanup;
}
vshPrint(ctl, "%-17s %-12llu ms\n", _("Time elapsed:"), info.timeElapsed);
if (info.type == VIR_DOMAIN_JOB_BOUNDED)
vshPrint(ctl, "%-17s %-12llu ms\n", _("Time remaining:"), info.timeRemaining);
if (info.dataTotal || info.dataRemaining || info.dataProcessed) {
val = prettyCapacity(info.dataProcessed, &unit);
vshPrint(ctl, "%-17s %-.3lf %s\n", _("Data processed:"), val, unit);
val = prettyCapacity(info.dataRemaining, &unit);
vshPrint(ctl, "%-17s %-.3lf %s\n", _("Data remaining:"), val, unit);
val = prettyCapacity(info.dataTotal, &unit);
vshPrint(ctl, "%-17s %-.3lf %s\n", _("Data total:"), val, unit);
}
if (info.memTotal || info.memRemaining || info.memProcessed) {
val = prettyCapacity(info.memProcessed, &unit);
vshPrint(ctl, "%-17s %-.3lf %s\n", _("Memory processed:"), val, unit);
val = prettyCapacity(info.memRemaining, &unit);
vshPrint(ctl, "%-17s %-.3lf %s\n", _("Memory remaining:"), val, unit);
val = prettyCapacity(info.memTotal, &unit);
vshPrint(ctl, "%-17s %-.3lf %s\n", _("Memory total:"), val, unit);
}
if (info.fileTotal || info.fileRemaining || info.fileProcessed) {
val = prettyCapacity(info.fileProcessed, &unit);
vshPrint(ctl, "%-17s %-.3lf %s\n", _("File processed:"), val, unit);
val = prettyCapacity(info.fileRemaining, &unit);
vshPrint(ctl, "%-17s %-.3lf %s\n", _("File remaining:"), val, unit);
val = prettyCapacity(info.fileTotal, &unit);
vshPrint(ctl, "%-17s %-.3lf %s\n", _("File total:"), val, unit);
}
} else {
ret = FALSE;
}
cleanup:
virDomainFree(dom);
return ret;
}
/*
* "domjobabort" command
*/
static const vshCmdInfo info_domjobabort[] = {
{"help", N_("abort active domain job")},
{"desc", N_("Aborts the currently running domain job")},
{NULL, NULL}
};
static const vshCmdOptDef opts_domjobabort[] = {
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
{NULL, 0, 0, NULL}
};
static int
cmdDomjobabort(vshControl *ctl, const vshCmd *cmd)
{
virDomainPtr dom;
int ret = TRUE;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
return FALSE;
if (virDomainAbortJob(dom) < 0)
ret = FALSE;
virDomainFree(dom);
return ret;
}
/*
* "freecell" command
*/
static const vshCmdInfo info_freecell[] = {
{"help", N_("NUMA free memory")},
{"desc", N_("display available free memory for the NUMA cell.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_freecell[] = {
{"cellno", VSH_OT_DATA, 0, N_("NUMA cell number")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdFreecell(vshControl *ctl, const vshCmd *cmd)
{
int ret;
int cell, cell_given;
unsigned long long memory;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
cell = vshCommandOptInt(cmd, "cellno", &cell_given);
if (!cell_given) {
memory = virNodeGetFreeMemory(ctl->conn);
2009-04-03 12:45:05 +00:00
if (memory == 0)
return FALSE;
} else {
ret = virNodeGetCellsFreeMemory(ctl->conn, &memory, cell, 1);
if (ret != 1)
return FALSE;
}
if (cell == -1)
2009-04-03 12:45:05 +00:00
vshPrint(ctl, "%s: %llu kB\n", _("Total"), (memory/1024));
else
2009-04-03 12:45:05 +00:00
vshPrint(ctl, "%d: %llu kB\n", cell, (memory/1024));
return TRUE;
}
/*
* "vcpuinfo" command
*/
static const vshCmdInfo info_vcpuinfo[] = {
{"help", N_("domain vcpu information")},
{"desc", N_("Returns basic information about the domain virtual CPUs.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_vcpuinfo[] = {
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdVcpuinfo(vshControl *ctl, const vshCmd *cmd)
{
virDomainInfo info;
virDomainPtr dom;
virNodeInfo nodeinfo;
virVcpuInfoPtr cpuinfo;
unsigned char *cpumap;
int ncpus;
size_t cpumaplen;
int ret = TRUE;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
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 10:26:54 +00:00
if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
return FALSE;
if (virNodeGetInfo(ctl->conn, &nodeinfo) != 0) {
virDomainFree(dom);
return FALSE;
}
if (virDomainGetInfo(dom, &info) != 0) {
virDomainFree(dom);
return FALSE;
}
cpuinfo = vshMalloc(ctl, sizeof(virVcpuInfo)*info.nrVirtCpu);
cpumaplen = VIR_CPU_MAPLEN(VIR_NODEINFO_MAXCPUS(nodeinfo));
cpumap = vshMalloc(ctl, info.nrVirtCpu * cpumaplen);
if ((ncpus = virDomainGetVcpus(dom,
cpuinfo, info.nrVirtCpu,
cpumap, cpumaplen)) >= 0) {
int n;
for (n = 0 ; n < ncpus ; n++) {
unsigned int m;
vshPrint(ctl, "%-15s %d\n", _("VCPU:"), n);
vshPrint(ctl, "%-15s %d\n", _("CPU:"), cpuinfo[n].cpu);
vshPrint(ctl, "%-15s %s\n", _("State:"),
_(vshDomainVcpuStateToString(cpuinfo[n].state)));
if (cpuinfo[n].cpuTime != 0) {
double cpuUsed = cpuinfo[n].cpuTime;
cpuUsed /= 1000000000.0;
vshPrint(ctl, "%-15s %.1lfs\n", _("CPU time:"), cpuUsed);
}
vshPrint(ctl, "%-15s ", _("CPU Affinity:"));
for (m = 0 ; m < VIR_NODEINFO_MAXCPUS(nodeinfo) ; m++) {
vshPrint(ctl, "%c", VIR_CPU_USABLE(cpumap, cpumaplen, n, m) ? 'y' : '-');
}
vshPrint(ctl, "\n");
if (n < (ncpus - 1)) {
vshPrint(ctl, "\n");
}
}
} else {
if (info.state == VIR_DOMAIN_SHUTOFF) {
vshError(ctl, "%s",
_("Domain shut off, virtual CPUs not present."));
}
ret = FALSE;
}
VIR_FREE(cpumap);
VIR_FREE(cpuinfo);
virDomainFree(dom);
return ret;
}
/*
* "vcpupin" command
*/
static const vshCmdInfo info_vcpupin[] = {
{"help", N_("control domain vcpu affinity")},
{"desc", N_("Pin domain VCPUs to host physical CPUs.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_vcpupin[] = {
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
{"vcpu", VSH_OT_DATA, VSH_OFLAG_REQ, N_("vcpu number")},
{"cpulist", VSH_OT_DATA, VSH_OFLAG_REQ, N_("host cpu number(s) (comma separated)")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdVcpupin(vshControl *ctl, const vshCmd *cmd)
{
virDomainInfo info;
virDomainPtr dom;
virNodeInfo nodeinfo;
int vcpu;
char *cpulist;
int ret = TRUE;
int vcpufound = 0;
unsigned char *cpumap;
int cpumaplen;
int i;
enum { expect_num, expect_num_or_comma } state;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
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 10:26:54 +00:00
if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
return FALSE;
vcpu = vshCommandOptInt(cmd, "vcpu", &vcpufound);
if (!vcpufound) {
vshError(ctl, "%s", _("vcpupin: Invalid or missing vCPU number."));
virDomainFree(dom);
return FALSE;
}
if (!(cpulist = vshCommandOptString(cmd, "cpulist", NULL))) {
vshError(ctl, "%s", _("vcpupin: Missing cpulist"));
virDomainFree(dom);
return FALSE;
}
if (virNodeGetInfo(ctl->conn, &nodeinfo) != 0) {
virDomainFree(dom);
return FALSE;
}
if (virDomainGetInfo(dom, &info) != 0) {
vshError(ctl, "%s", _("vcpupin: failed to get domain informations."));
virDomainFree(dom);
return FALSE;
}
if (vcpu >= info.nrVirtCpu) {
vshError(ctl, "%s", _("vcpupin: Invalid vCPU number."));
virDomainFree(dom);
return FALSE;
}
/* Check that the cpulist parameter is a comma-separated list of
* numbers and give an intelligent error message if not.
*/
if (cpulist[0] == '\0') {
vshError(ctl, "%s", _("cpulist: Invalid format. Empty string."));
virDomainFree (dom);
return FALSE;
}
state = expect_num;
for (i = 0; cpulist[i]; i++) {
switch (state) {
case expect_num:
if (!c_isdigit (cpulist[i])) {
vshError(ctl, _("cpulist: %s: Invalid format. Expecting "
"digit at position %d (near '%c')."),
cpulist, i, cpulist[i]);
virDomainFree (dom);
return FALSE;
}
state = expect_num_or_comma;
break;
case expect_num_or_comma:
if (cpulist[i] == ',')
state = expect_num;
else if (!c_isdigit (cpulist[i])) {
vshError(ctl, _("cpulist: %s: Invalid format. Expecting "
"digit or comma at position %d (near '%c')."),
cpulist, i, cpulist[i]);
virDomainFree (dom);
return FALSE;
}
}
}
if (state == expect_num) {
vshError(ctl, _("cpulist: %s: Invalid format. Trailing comma "
"at position %d."),
cpulist, i);
virDomainFree (dom);
return FALSE;
}
cpumaplen = VIR_CPU_MAPLEN(VIR_NODEINFO_MAXCPUS(nodeinfo));
cpumap = vshCalloc(ctl, 1, cpumaplen);
do {
unsigned int cpu = atoi(cpulist);
if (cpu < VIR_NODEINFO_MAXCPUS(nodeinfo)) {
VIR_USE_CPU(cpumap, cpu);
} else {
vshError(ctl, _("Physical CPU %d doesn't exist."), cpu);
VIR_FREE(cpumap);
virDomainFree(dom);
return FALSE;
}
cpulist = strchr(cpulist, ',');
if (cpulist)
cpulist++;
} while (cpulist);
if (virDomainPinVcpu(dom, vcpu, cpumap, cpumaplen) != 0) {
ret = FALSE;
}
VIR_FREE(cpumap);
virDomainFree(dom);
return ret;
}
/*
* "setvcpus" command
*/
static const vshCmdInfo info_setvcpus[] = {
{"help", N_("change number of virtual CPUs")},
{"desc", N_("Change the number of virtual CPUs in the guest domain.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_setvcpus[] = {
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
{"count", VSH_OT_DATA, VSH_OFLAG_REQ, N_("number of virtual CPUs")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdSetvcpus(vshControl *ctl, const vshCmd *cmd)
{
virDomainPtr dom;
int count;
int maxcpu;
int ret = TRUE;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
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 10:26:54 +00:00
if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
return FALSE;
count = vshCommandOptInt(cmd, "count", &count);
if (count <= 0) {
vshError(ctl, "%s", _("Invalid number of virtual CPUs."));
virDomainFree(dom);
return FALSE;
}
maxcpu = virDomainGetMaxVcpus(dom);
if (maxcpu <= 0) {
virDomainFree(dom);
return FALSE;
}
if (count > maxcpu) {
vshError(ctl, "%s", _("Too many virtual CPUs."));
virDomainFree(dom);
return FALSE;
}
if (virDomainSetVcpus(dom, count) != 0) {
ret = FALSE;
}
virDomainFree(dom);
return ret;
}
/*
* "setmemory" command
*/
static const vshCmdInfo info_setmem[] = {
{"help", N_("change memory allocation")},
{"desc", N_("Change the current memory allocation in the guest domain.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_setmem[] = {
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
{"kilobytes", VSH_OT_DATA, VSH_OFLAG_REQ, N_("number of kilobytes of memory")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdSetmem(vshControl *ctl, const vshCmd *cmd)
{
virDomainPtr dom;
virDomainInfo info;
int kilobytes;
int ret = TRUE;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
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 10:26:54 +00:00
if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
return FALSE;
kilobytes = vshCommandOptInt(cmd, "kilobytes", &kilobytes);
if (kilobytes <= 0) {
virDomainFree(dom);
vshError(ctl, _("Invalid value of %d for memory size"), kilobytes);
return FALSE;
}
if (virDomainGetInfo(dom, &info) != 0) {
virDomainFree(dom);
vshError(ctl, "%s", _("Unable to verify MaxMemorySize"));
return FALSE;
}
if (kilobytes > info.maxMem) {
virDomainFree(dom);
vshError(ctl, _("Requested memory size %d kb is larger than maximum of %lu kb"),
kilobytes, info.maxMem);
return FALSE;
}
if (virDomainSetMemory(dom, kilobytes) != 0) {
ret = FALSE;
}
virDomainFree(dom);
return ret;
}
/*
* "setmaxmem" command
*/
static const vshCmdInfo info_setmaxmem[] = {
{"help", N_("change maximum memory limit")},
{"desc", N_("Change the maximum memory allocation limit in the guest domain.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_setmaxmem[] = {
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
{"kilobytes", VSH_OT_DATA, VSH_OFLAG_REQ, N_("maximum memory limit in kilobytes")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdSetmaxmem(vshControl *ctl, const vshCmd *cmd)
{
virDomainPtr dom;
virDomainInfo info;
int kilobytes;
int ret = TRUE;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
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 10:26:54 +00:00
if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
return FALSE;
kilobytes = vshCommandOptInt(cmd, "kilobytes", &kilobytes);
if (kilobytes <= 0) {
virDomainFree(dom);
vshError(ctl, _("Invalid value of %d for memory size"), kilobytes);
return FALSE;
}
if (virDomainGetInfo(dom, &info) != 0) {
virDomainFree(dom);
vshError(ctl, "%s", _("Unable to verify current MemorySize"));
return FALSE;
}
if (kilobytes < info.memory) {
if (virDomainSetMemory(dom, kilobytes) != 0) {
virDomainFree(dom);
vshError(ctl, "%s", _("Unable to shrink current MemorySize"));
return FALSE;
}
}
if (virDomainSetMaxMemory(dom, kilobytes) != 0) {
vshError(ctl, "%s", _("Unable to change MaxMemorySize"));
ret = FALSE;
}
virDomainFree(dom);
return ret;
}
/*
* "nodeinfo" command
*/
static const vshCmdInfo info_nodeinfo[] = {
{"help", N_("node information")},
{"desc", N_("Returns basic information about the node.")},
{NULL, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdNodeinfo(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
{
virNodeInfo info;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
if (virNodeGetInfo(ctl->conn, &info) < 0) {
vshError(ctl, "%s", _("failed to get node information"));
return FALSE;
}
vshPrint(ctl, "%-20s %s\n", _("CPU model:"), info.model);
vshPrint(ctl, "%-20s %d\n", _("CPU(s):"), info.cpus);
vshPrint(ctl, "%-20s %d MHz\n", _("CPU frequency:"), info.mhz);
vshPrint(ctl, "%-20s %d\n", _("CPU socket(s):"), info.sockets);
vshPrint(ctl, "%-20s %d\n", _("Core(s) per socket:"), info.cores);
vshPrint(ctl, "%-20s %d\n", _("Thread(s) per core:"), info.threads);
vshPrint(ctl, "%-20s %d\n", _("NUMA cell(s):"), info.nodes);
vshPrint(ctl, "%-20s %lu kB\n", _("Memory size:"), info.memory);
return TRUE;
}
/*
* "capabilities" command
*/
static const vshCmdInfo info_capabilities[] = {
{"help", N_("capabilities")},
{"desc", N_("Returns capabilities of hypervisor/driver.")},
{NULL, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdCapabilities (vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
{
char *caps;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
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;
}
/*
* "dumpxml" command
*/
static const vshCmdInfo info_dumpxml[] = {
{"help", N_("domain information in XML")},
{"desc", N_("Output the domain information as an XML dump to stdout.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_dumpxml[] = {
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
{"inactive", VSH_OT_BOOL, 0, N_("show inactive defined XML")},
{"security-info", VSH_OT_BOOL, 0, N_("include security sensitive information in XML dump")},
{"update-cpu", VSH_OT_BOOL, 0, N_("update guest CPU according to host CPU")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdDumpXML(vshControl *ctl, const vshCmd *cmd)
{
virDomainPtr dom;
2005-12-15 17:00:43 +00:00
int ret = TRUE;
char *dump;
int flags = 0;
int inactive = vshCommandOptBool(cmd, "inactive");
int secure = vshCommandOptBool(cmd, "security-info");
int update = vshCommandOptBool(cmd, "update-cpu");
if (inactive)
flags |= VIR_DOMAIN_XML_INACTIVE;
if (secure)
flags |= VIR_DOMAIN_XML_SECURE;
if (update)
flags |= VIR_DOMAIN_XML_UPDATE_CPU;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
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 10:26:54 +00:00
if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
return FALSE;
dump = virDomainGetXMLDesc(dom, flags);
if (dump != NULL) {
printf("%s", dump);
VIR_FREE(dump);
} else {
ret = FALSE;
}
virDomainFree(dom);
return ret;
}
2009-05-21 13:46:35 +00:00
/*
* "domxml-from-native" command
*/
static const vshCmdInfo info_domxmlfromnative[] = {
{"help", N_("Convert native config to domain XML")},
{"desc", N_("Convert native guest configuration format to domain XML format.")},
2009-05-21 13:46:35 +00:00
{NULL, NULL}
};
static const vshCmdOptDef opts_domxmlfromnative[] = {
{"format", VSH_OT_DATA, VSH_OFLAG_REQ, N_("source config data format")},
{"config", VSH_OT_DATA, VSH_OFLAG_REQ, N_("config data file to import from")},
2009-05-21 13:46:35 +00:00
{NULL, 0, 0, NULL}
};
static int
cmdDomXMLFromNative(vshControl *ctl, const vshCmd *cmd)
{
int ret = TRUE;
char *format;
char *configFile;
char *configData;
char *xmlData;
int flags = 0;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
format = vshCommandOptString(cmd, "format", NULL);
configFile = vshCommandOptString(cmd, "config", NULL);
if (virFileReadAll(configFile, 1024*1024, &configData) < 0)
2009-05-21 13:46:35 +00:00
return FALSE;
xmlData = virConnectDomainXMLFromNative(ctl->conn, format, configData, flags);
if (xmlData != NULL) {
printf("%s", xmlData);
VIR_FREE(xmlData);
2009-05-21 13:46:35 +00:00
} else {
ret = FALSE;
}
return ret;
}
/*
* "domxml-to-native" command
*/
static const vshCmdInfo info_domxmltonative[] = {
{"help", N_("Convert domain XML to native config")},
{"desc", N_("Convert domain XML config to a native guest configuration format.")},
2009-05-21 13:46:35 +00:00
{NULL, NULL}
};
static const vshCmdOptDef opts_domxmltonative[] = {
{"format", VSH_OT_DATA, VSH_OFLAG_REQ, N_("target config data type format")},
{"xml", VSH_OT_DATA, VSH_OFLAG_REQ, N_("xml data file to export from")},
2009-05-21 13:46:35 +00:00
{NULL, 0, 0, NULL}
};
static int
cmdDomXMLToNative(vshControl *ctl, const vshCmd *cmd)
{
int ret = TRUE;
char *format;
char *xmlFile;
char *configData;
char *xmlData;
int flags = 0;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
format = vshCommandOptString(cmd, "format", NULL);
xmlFile = vshCommandOptString(cmd, "xml", NULL);
if (virFileReadAll(xmlFile, 1024*1024, &xmlData) < 0)
2009-05-21 13:46:35 +00:00
return FALSE;
configData = virConnectDomainXMLToNative(ctl->conn, format, xmlData, flags);
if (configData != NULL) {
printf("%s", configData);
VIR_FREE(configData);
2009-05-21 13:46:35 +00:00
} else {
ret = FALSE;
}
return ret;
}
2005-12-08 10:23:34 +00:00
/*
2006-04-04 21:52:31 +00:00
* "domname" command
2005-12-08 10:23:34 +00:00
*/
static const vshCmdInfo info_domname[] = {
{"help", N_("convert a domain id or UUID to domain name")},
{"desc", ""},
{NULL, NULL}
2005-12-08 10:23:34 +00:00
};
static const vshCmdOptDef opts_domname[] = {
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain id or uuid")},
{NULL, 0, 0, NULL}
2005-12-08 10:23:34 +00:00
};
static int
2008-08-01 13:51:18 +00:00
cmdDomname(vshControl *ctl, const vshCmd *cmd)
{
2005-12-08 10:23:34 +00:00
virDomainPtr dom;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
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 10:26:54 +00:00
if (!(dom = vshCommandOptDomainBy(ctl, cmd, NULL,
VSH_BYID|VSH_BYUUID)))
2005-12-08 10:23:34 +00:00
return FALSE;
2006-05-29 15:39:31 +00:00
vshPrint(ctl, "%s\n", virDomainGetName(dom));
virDomainFree(dom);
2005-12-08 10:23:34 +00:00
return TRUE;
}
/*
2006-04-04 21:52:31 +00:00
* "domid" command
2005-12-08 10:23:34 +00:00
*/
static const vshCmdInfo info_domid[] = {
{"help", N_("convert a domain name or UUID to domain id")},
{"desc", ""},
{NULL, NULL}
2005-12-08 10:23:34 +00:00
};
static const vshCmdOptDef opts_domid[] = {
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name or uuid")},
{NULL, 0, 0, NULL}
2005-12-08 10:23:34 +00:00
};
static int
2008-08-01 13:51:18 +00:00
cmdDomid(vshControl *ctl, const vshCmd *cmd)
{
virDomainPtr dom;
unsigned int id;
2005-12-08 10:23:34 +00:00
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
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 10:26:54 +00:00
if (!(dom = vshCommandOptDomainBy(ctl, cmd, NULL,
VSH_BYNAME|VSH_BYUUID)))
2005-12-08 10:23:34 +00:00
return FALSE;
id = virDomainGetID(dom);
if (id == ((unsigned int)-1))
vshPrint(ctl, "%s\n", "-");
else
vshPrint(ctl, "%d\n", id);
2006-05-29 15:39:31 +00:00
virDomainFree(dom);
return TRUE;
}
2006-05-29 15:39:31 +00:00
/*
* "domuuid" command
*/
static const vshCmdInfo info_domuuid[] = {
{"help", N_("convert a domain name or id to domain UUID")},
{"desc", ""},
2006-05-29 15:39:31 +00:00
{NULL, NULL}
};
static const vshCmdOptDef opts_domuuid[] = {
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain id or name")},
2006-05-29 15:39:31 +00:00
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdDomuuid(vshControl *ctl, const vshCmd *cmd)
2006-05-29 15:39:31 +00:00
{
virDomainPtr dom;
char uuid[VIR_UUID_STRING_BUFLEN];
2006-05-29 15:39:31 +00:00
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
2005-12-08 10:23:34 +00:00
return FALSE;
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 10:26:54 +00:00
if (!(dom = vshCommandOptDomainBy(ctl, cmd, NULL,
VSH_BYNAME|VSH_BYID)))
2006-05-29 15:39:31 +00:00
return FALSE;
2006-05-29 15:39:31 +00:00
if (virDomainGetUUIDString(dom, uuid) != -1)
vshPrint(ctl, "%s\n", uuid);
else
vshError(ctl, "%s", _("failed to get domain UUID"));
virDomainFree(dom);
2005-12-08 10:23:34 +00:00
return TRUE;
}
/*
* "migrate" command
*/
static const vshCmdInfo info_migrate[] = {
{"help", N_("migrate domain to another host")},
{"desc", N_("Migrate domain to another host. Add --live for live migration.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_migrate[] = {
{"live", VSH_OT_BOOL, 0, N_("live migration")},
{"p2p", VSH_OT_BOOL, 0, N_("peer-2-peer migration")},
{"direct", VSH_OT_BOOL, 0, N_("direct migration")},
{"tunnelled", VSH_OT_BOOL, 0, N_("tunnelled migration")},
{"persistent", VSH_OT_BOOL, 0, N_("persist VM on destination")},
{"undefinesource", VSH_OT_BOOL, 0, N_("undefine VM on source")},
{"suspend", VSH_OT_BOOL, 0, N_("do not restart the domain on the destination host")},
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
{"desturi", VSH_OT_DATA, VSH_OFLAG_REQ, N_("connection URI of the destination host")},
{"migrateuri", VSH_OT_DATA, 0, N_("migration URI, usually can be omitted")},
{"dname", VSH_OT_DATA, 0, N_("rename to new name during migration (if supported)")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdMigrate (vshControl *ctl, const vshCmd *cmd)
{
virDomainPtr dom = NULL;
const char *desturi;
const char *migrateuri;
const char *dname;
int flags = 0, found, ret = FALSE;
if (!vshConnectionUsability (ctl, ctl->conn, TRUE))
return FALSE;
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 10:26:54 +00:00
if (!(dom = vshCommandOptDomain (ctl, cmd, NULL)))
return FALSE;
desturi = vshCommandOptString (cmd, "desturi", &found);
if (!found) {
vshError(ctl, "%s", _("migrate: Missing desturi"));
goto done;
}
migrateuri = vshCommandOptString (cmd, "migrateuri", NULL);
dname = vshCommandOptString (cmd, "dname", NULL);
if (vshCommandOptBool (cmd, "live"))
flags |= VIR_MIGRATE_LIVE;
Support a new peer-to-peer migration mode & public API Introduces several new public API options for migration - VIR_MIGRATE_PEER2PEER: With this flag the client only invokes the virDomainMigratePerform method, expecting the source host driver to do whatever is required to complete the entire migration process. - VIR_MIGRATE_TUNNELLED: With this flag the actual data for migration will be tunnelled over the libvirtd RPC channel. This requires that VIR_MIGRATE_PEER2PEER is also set. - virDomainMigrateToURI: This is variant of the existing virDomainMigrate method which does not require any virConnectPtr for the destination host. Given suitable driver support, this allows for all the same modes as virDomainMigrate() The URI for VIR_MIGRATE_PEER2PEER must be a valid libvirt URI. For non-p2p migration a hypervisor specific migration URI is used. virDomainMigrateToURI without a PEER2PEER flag is only support for Xen currently, and it involves XenD talking directly to XenD, no libvirtd involved at all. * include/libvirt/libvirt.h.in: Add VIR_MIGRATE_PEER2PEER flag for migration * src/libvirt_internal.h: Add feature flags for peer to peer migration (VIR_FEATURE_MIGRATE_P2P) and direct migration (VIR_MIGRATE_PEER2PEER mode) * src/libvirt.c: Implement support for VIR_MIGRATE_PEER2PEER and virDomainMigrateToURI APIs. * src/xen/xen_driver.c: Advertise support for DIRECT migration * src/xen/xend_internal.c: Add TODO item for p2p migration * src/libvirt_public.syms: Export virDomainMigrateToURI method * src/qemu/qemu_driver.c: Add support for PEER2PEER and migration, and adapt TUNNELLED migration. * tools/virsh.c: Add --p2p and --direct args and use the new virDomainMigrateToURI method where possible.
2009-09-17 17:10:04 +00:00
if (vshCommandOptBool (cmd, "p2p"))
flags |= VIR_MIGRATE_PEER2PEER;
if (vshCommandOptBool (cmd, "tunnelled"))
flags |= VIR_MIGRATE_TUNNELLED;
if (vshCommandOptBool (cmd, "persistent"))
flags |= VIR_MIGRATE_PERSIST_DEST;
if (vshCommandOptBool (cmd, "undefinesource"))
flags |= VIR_MIGRATE_UNDEFINE_SOURCE;
if (vshCommandOptBool (cmd, "suspend"))
flags |= VIR_MIGRATE_PAUSED;
Support a new peer-to-peer migration mode & public API Introduces several new public API options for migration - VIR_MIGRATE_PEER2PEER: With this flag the client only invokes the virDomainMigratePerform method, expecting the source host driver to do whatever is required to complete the entire migration process. - VIR_MIGRATE_TUNNELLED: With this flag the actual data for migration will be tunnelled over the libvirtd RPC channel. This requires that VIR_MIGRATE_PEER2PEER is also set. - virDomainMigrateToURI: This is variant of the existing virDomainMigrate method which does not require any virConnectPtr for the destination host. Given suitable driver support, this allows for all the same modes as virDomainMigrate() The URI for VIR_MIGRATE_PEER2PEER must be a valid libvirt URI. For non-p2p migration a hypervisor specific migration URI is used. virDomainMigrateToURI without a PEER2PEER flag is only support for Xen currently, and it involves XenD talking directly to XenD, no libvirtd involved at all. * include/libvirt/libvirt.h.in: Add VIR_MIGRATE_PEER2PEER flag for migration * src/libvirt_internal.h: Add feature flags for peer to peer migration (VIR_FEATURE_MIGRATE_P2P) and direct migration (VIR_MIGRATE_PEER2PEER mode) * src/libvirt.c: Implement support for VIR_MIGRATE_PEER2PEER and virDomainMigrateToURI APIs. * src/xen/xen_driver.c: Advertise support for DIRECT migration * src/xen/xend_internal.c: Add TODO item for p2p migration * src/libvirt_public.syms: Export virDomainMigrateToURI method * src/qemu/qemu_driver.c: Add support for PEER2PEER and migration, and adapt TUNNELLED migration. * tools/virsh.c: Add --p2p and --direct args and use the new virDomainMigrateToURI method where possible.
2009-09-17 17:10:04 +00:00
if ((flags & VIR_MIGRATE_PEER2PEER) ||
vshCommandOptBool (cmd, "direct")) {
/* For peer2peer migration or direct migration we only expect one URI
* a libvirt URI, or a hypervisor specific URI. */
Support a new peer-to-peer migration mode & public API Introduces several new public API options for migration - VIR_MIGRATE_PEER2PEER: With this flag the client only invokes the virDomainMigratePerform method, expecting the source host driver to do whatever is required to complete the entire migration process. - VIR_MIGRATE_TUNNELLED: With this flag the actual data for migration will be tunnelled over the libvirtd RPC channel. This requires that VIR_MIGRATE_PEER2PEER is also set. - virDomainMigrateToURI: This is variant of the existing virDomainMigrate method which does not require any virConnectPtr for the destination host. Given suitable driver support, this allows for all the same modes as virDomainMigrate() The URI for VIR_MIGRATE_PEER2PEER must be a valid libvirt URI. For non-p2p migration a hypervisor specific migration URI is used. virDomainMigrateToURI without a PEER2PEER flag is only support for Xen currently, and it involves XenD talking directly to XenD, no libvirtd involved at all. * include/libvirt/libvirt.h.in: Add VIR_MIGRATE_PEER2PEER flag for migration * src/libvirt_internal.h: Add feature flags for peer to peer migration (VIR_FEATURE_MIGRATE_P2P) and direct migration (VIR_MIGRATE_PEER2PEER mode) * src/libvirt.c: Implement support for VIR_MIGRATE_PEER2PEER and virDomainMigrateToURI APIs. * src/xen/xen_driver.c: Advertise support for DIRECT migration * src/xen/xend_internal.c: Add TODO item for p2p migration * src/libvirt_public.syms: Export virDomainMigrateToURI method * src/qemu/qemu_driver.c: Add support for PEER2PEER and migration, and adapt TUNNELLED migration. * tools/virsh.c: Add --p2p and --direct args and use the new virDomainMigrateToURI method where possible.
2009-09-17 17:10:04 +00:00
if (migrateuri != NULL) {
vshError(ctl, "%s", _("migrate: Unexpected migrateuri for peer2peer/direct migration"));
Support a new peer-to-peer migration mode & public API Introduces several new public API options for migration - VIR_MIGRATE_PEER2PEER: With this flag the client only invokes the virDomainMigratePerform method, expecting the source host driver to do whatever is required to complete the entire migration process. - VIR_MIGRATE_TUNNELLED: With this flag the actual data for migration will be tunnelled over the libvirtd RPC channel. This requires that VIR_MIGRATE_PEER2PEER is also set. - virDomainMigrateToURI: This is variant of the existing virDomainMigrate method which does not require any virConnectPtr for the destination host. Given suitable driver support, this allows for all the same modes as virDomainMigrate() The URI for VIR_MIGRATE_PEER2PEER must be a valid libvirt URI. For non-p2p migration a hypervisor specific migration URI is used. virDomainMigrateToURI without a PEER2PEER flag is only support for Xen currently, and it involves XenD talking directly to XenD, no libvirtd involved at all. * include/libvirt/libvirt.h.in: Add VIR_MIGRATE_PEER2PEER flag for migration * src/libvirt_internal.h: Add feature flags for peer to peer migration (VIR_FEATURE_MIGRATE_P2P) and direct migration (VIR_MIGRATE_PEER2PEER mode) * src/libvirt.c: Implement support for VIR_MIGRATE_PEER2PEER and virDomainMigrateToURI APIs. * src/xen/xen_driver.c: Advertise support for DIRECT migration * src/xen/xend_internal.c: Add TODO item for p2p migration * src/libvirt_public.syms: Export virDomainMigrateToURI method * src/qemu/qemu_driver.c: Add support for PEER2PEER and migration, and adapt TUNNELLED migration. * tools/virsh.c: Add --p2p and --direct args and use the new virDomainMigrateToURI method where possible.
2009-09-17 17:10:04 +00:00
goto done;
}
Support a new peer-to-peer migration mode & public API Introduces several new public API options for migration - VIR_MIGRATE_PEER2PEER: With this flag the client only invokes the virDomainMigratePerform method, expecting the source host driver to do whatever is required to complete the entire migration process. - VIR_MIGRATE_TUNNELLED: With this flag the actual data for migration will be tunnelled over the libvirtd RPC channel. This requires that VIR_MIGRATE_PEER2PEER is also set. - virDomainMigrateToURI: This is variant of the existing virDomainMigrate method which does not require any virConnectPtr for the destination host. Given suitable driver support, this allows for all the same modes as virDomainMigrate() The URI for VIR_MIGRATE_PEER2PEER must be a valid libvirt URI. For non-p2p migration a hypervisor specific migration URI is used. virDomainMigrateToURI without a PEER2PEER flag is only support for Xen currently, and it involves XenD talking directly to XenD, no libvirtd involved at all. * include/libvirt/libvirt.h.in: Add VIR_MIGRATE_PEER2PEER flag for migration * src/libvirt_internal.h: Add feature flags for peer to peer migration (VIR_FEATURE_MIGRATE_P2P) and direct migration (VIR_MIGRATE_PEER2PEER mode) * src/libvirt.c: Implement support for VIR_MIGRATE_PEER2PEER and virDomainMigrateToURI APIs. * src/xen/xen_driver.c: Advertise support for DIRECT migration * src/xen/xend_internal.c: Add TODO item for p2p migration * src/libvirt_public.syms: Export virDomainMigrateToURI method * src/qemu/qemu_driver.c: Add support for PEER2PEER and migration, and adapt TUNNELLED migration. * tools/virsh.c: Add --p2p and --direct args and use the new virDomainMigrateToURI method where possible.
2009-09-17 17:10:04 +00:00
if (virDomainMigrateToURI (dom, desturi, flags, dname, 0) == 0)
ret = TRUE;
} else {
/* For traditional live migration, connect to the destination host directly. */
virConnectPtr dconn = NULL;
virDomainPtr ddom = NULL;
dconn = virConnectOpenAuth (desturi, virConnectAuthPtrDefault, 0);
if (!dconn) goto done;
ddom = virDomainMigrate (dom, dconn, flags, dname, migrateuri, 0);
if (ddom) {
virDomainFree(ddom);
ret = TRUE;
}
virConnectClose (dconn);
}
done:
if (dom) virDomainFree (dom);
return ret;
}
/*
* "migrate-setmaxdowntime" command
*/
static const vshCmdInfo info_migrate_setmaxdowntime[] = {
{"help", N_("set maximum tolerable downtime")},
{"desc", N_("Set maximum tolerable downtime of a domain which is being live-migrated to another host.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_migrate_setmaxdowntime[] = {
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
{"downtime", VSH_OT_DATA, VSH_OFLAG_REQ, N_("maximum tolerable downtime (in milliseconds) for migration")},
{NULL, 0, 0, NULL}
};
static int
cmdMigrateSetMaxDowntime(vshControl *ctl, const vshCmd *cmd)
{
virDomainPtr dom = NULL;
long long downtime;
int found;
int ret = FALSE;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
return FALSE;
downtime = vshCommandOptLongLong(cmd, "downtime", &found);
if (!found || downtime < 1) {
vshError(ctl, "%s", _("migrate: Invalid downtime"));
goto done;
}
if (virDomainMigrateSetMaxDowntime(dom, downtime, 0))
goto done;
ret = TRUE;
done:
virDomainFree(dom);
return ret;
}
/*
* "net-autostart" command
*/
static const vshCmdInfo info_network_autostart[] = {
{"help", N_("autostart a network")},
{"desc",
N_("Configure a network to be automatically started at boot.")},
{NULL, NULL}
};
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")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdNetworkAutostart(vshControl *ctl, const vshCmd *cmd)
{
virNetworkPtr network;
char *name;
int autostart;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
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 10:26:54 +00:00
if (!(network = vshCommandOptNetwork(ctl, cmd, &name)))
return FALSE;
autostart = !vshCommandOptBool(cmd, "disable");
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;
}
if (autostart)
vshPrint(ctl, _("Network %s marked as autostarted\n"), name);
else
vshPrint(ctl, _("Network %s unmarked as autostarted\n"), name);
virNetworkFree(network);
return TRUE;
}
2006-05-29 15:39:31 +00:00
/*
* "net-create" command
*/
static const vshCmdInfo info_network_create[] = {
{"help", N_("create a network from an XML file")},
{"desc", N_("Create a network.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_network_create[] = {
{"file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("file containing an XML network description")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdNetworkCreate(vshControl *ctl, const vshCmd *cmd)
{
virNetworkPtr network;
char *from;
int found;
int ret = TRUE;
char *buffer;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
from = vshCommandOptString(cmd, "file", &found);
if (!found)
return FALSE;
2008-01-21 15:27:14 +00:00
if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0)
return FALSE;
network = virNetworkCreateXML(ctl->conn, buffer);
VIR_FREE(buffer);
if (network != NULL) {
vshPrint(ctl, _("Network %s created from %s\n"),
virNetworkGetName(network), from);
virNetworkFree(network);
} else {
vshError(ctl, _("Failed to create network from %s"), from);
ret = FALSE;
}
return ret;
}
/*
* "net-define" command
*/
static const vshCmdInfo info_network_define[] = {
{"help", N_("define (but don't start) a network from an XML file")},
{"desc", N_("Define a network.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_network_define[] = {
{"file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("file containing an XML network description")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdNetworkDefine(vshControl *ctl, const vshCmd *cmd)
{
virNetworkPtr network;
char *from;
int found;
int ret = TRUE;
char *buffer;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
from = vshCommandOptString(cmd, "file", &found);
if (!found)
return FALSE;
2008-01-21 15:27:14 +00:00
if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0)
return FALSE;
network = virNetworkDefineXML(ctl->conn, buffer);
VIR_FREE(buffer);
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;
}
return ret;
}
/*
* "net-destroy" command
*/
static const vshCmdInfo info_network_destroy[] = {
{"help", N_("destroy a network")},
{"desc", N_("Destroy a given network.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_network_destroy[] = {
{"network", VSH_OT_DATA, VSH_OFLAG_REQ, N_("network name, id or uuid")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdNetworkDestroy(vshControl *ctl, const vshCmd *cmd)
{
virNetworkPtr network;
int ret = TRUE;
char *name;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
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 10:26:54 +00:00
if (!(network = vshCommandOptNetwork(ctl, cmd, &name)))
return FALSE;
if (virNetworkDestroy(network) == 0) {
vshPrint(ctl, _("Network %s destroyed\n"), name);
} else {
vshError(ctl, _("Failed to destroy network %s"), name);
ret = FALSE;
}
virNetworkFree(network);
return ret;
}
/*
* "net-dumpxml" command
*/
static const vshCmdInfo info_network_dumpxml[] = {
{"help", N_("network information in XML")},
{"desc", N_("Output the network information as an XML dump to stdout.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_network_dumpxml[] = {
{"network", VSH_OT_DATA, VSH_OFLAG_REQ, N_("network name, id or uuid")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdNetworkDumpXML(vshControl *ctl, const vshCmd *cmd)
{
virNetworkPtr network;
int ret = TRUE;
char *dump;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
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 10:26:54 +00:00
if (!(network = vshCommandOptNetwork(ctl, cmd, NULL)))
return FALSE;
dump = virNetworkGetXMLDesc(network, 0);
if (dump != NULL) {
printf("%s", dump);
VIR_FREE(dump);
} else {
ret = FALSE;
}
virNetworkFree(network);
return ret;
}
/*
* "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.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_interface_edit[] = {
{"interface", VSH_OT_DATA, VSH_OFLAG_REQ, N_("interface name or MAC address")},
{NULL, 0, 0, NULL}
};
static int
cmdInterfaceEdit (vshControl *ctl, const vshCmd *cmd)
{
int ret = FALSE;
virInterfacePtr iface = NULL;
char *tmp = NULL;
char *doc = NULL;
char *doc_edited = NULL;
char *doc_reread = NULL;
int flags = VIR_INTERFACE_XML_INACTIVE;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
goto cleanup;
iface = vshCommandOptInterface (ctl, cmd, NULL);
if (iface == NULL)
goto cleanup;
/* Get the XML configuration of the interface. */
doc = virInterfaceGetXMLDesc (iface, flags);
if (!doc)
goto cleanup;
/* Create and open the temporary file. */
tmp = editWriteToTempFile (ctl, doc);
if (!tmp) goto cleanup;
/* Start the editor. */
if (editFile (ctl, tmp) == -1) goto cleanup;
/* Read back the edited file. */
doc_edited = editReadBackFile (ctl, tmp);
if (!doc_edited) goto cleanup;
unlink (tmp);
tmp = NULL;
/* Compare original XML with edited. Has it changed at all? */
if (STREQ (doc, doc_edited)) {
vshPrint (ctl, _("Interface %s XML configuration not changed.\n"),
virInterfaceGetName (iface));
ret = TRUE;
goto cleanup;
}
/* Now re-read the interface XML. Did someone else change it while
* it was being edited? This also catches problems such as us
* losing a connection or the interface going away.
*/
doc_reread = virInterfaceGetXMLDesc (iface, flags);
if (!doc_reread)
goto cleanup;
if (STRNEQ (doc, doc_reread)) {
vshError(ctl, "%s",
_("ERROR: the XML configuration was changed by another user"));
goto cleanup;
}
/* Everything checks out, so redefine the interface. */
virInterfaceFree (iface);
iface = virInterfaceDefineXML (ctl->conn, doc_edited, 0);
if (!iface)
goto cleanup;
vshPrint (ctl, _("Interface %s XML configuration edited.\n"),
virInterfaceGetName(iface));
ret = TRUE;
cleanup:
if (iface)
virInterfaceFree (iface);
VIR_FREE(doc);
VIR_FREE(doc_edited);
VIR_FREE(doc_reread);
if (tmp) {
unlink (tmp);
VIR_FREE(tmp);
}
return ret;
}
/*
* "net-list" command
*/
static const vshCmdInfo info_network_list[] = {
{"help", N_("list networks")},
{"desc", N_("Returns list of networks.")},
{NULL, NULL}
};
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")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdNetworkList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
{
int inactive = vshCommandOptBool(cmd, "inactive");
int all = vshCommandOptBool(cmd, "all");
int active = !inactive || all ? 1 : 0;
int maxactive = 0, maxinactive = 0, i;
2007-03-06 21:55:44 +00:00
char **activeNames = NULL, **inactiveNames = NULL;
inactive |= all;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
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);
if ((maxactive = virConnectListNetworks(ctl->conn, activeNames,
maxactive)) < 0) {
vshError(ctl, "%s", _("Failed to list active networks"));
VIR_FREE(activeNames);
return FALSE;
}
qsort(&activeNames[0], maxactive, sizeof(char *), namesorter);
}
}
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;
}
qsort(&inactiveNames[0], maxinactive, sizeof(char*), namesorter);
}
}
vshPrintExtra(ctl, "%-20s %-10s %s\n", _("Name"), _("State"),
_("Autostart"));
vshPrintExtra(ctl, "-----------------------------------------\n");
for (i = 0; i < maxactive; i++) {
virNetworkPtr network =
virNetworkLookupByName(ctl->conn, activeNames[i]);
const char *autostartStr;
int autostart = 0;
/* this kind of work with networks is not atomic operation */
if (!network) {
VIR_FREE(activeNames[i]);
continue;
}
if (virNetworkGetAutostart(network, &autostart) < 0)
autostartStr = _("no autostart");
else
autostartStr = autostart ? "yes" : "no";
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;
}
/*
* "net-name" command
*/
static const vshCmdInfo info_network_name[] = {
{"help", N_("convert a network UUID to network name")},
{"desc", ""},
{NULL, NULL}
};
static const vshCmdOptDef opts_network_name[] = {
{"network", VSH_OT_DATA, VSH_OFLAG_REQ, N_("network uuid")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdNetworkName(vshControl *ctl, const vshCmd *cmd)
{
virNetworkPtr network;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
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 10:26:54 +00:00
if (!(network = vshCommandOptNetworkBy(ctl, cmd, NULL,
VSH_BYUUID)))
return FALSE;
vshPrint(ctl, "%s\n", virNetworkGetName(network));
virNetworkFree(network);
return TRUE;
}
/*
* "net-start" command
*/
static const vshCmdInfo info_network_start[] = {
{"help", N_("start a (previously defined) inactive network")},
{"desc", N_("Start a network.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_network_start[] = {
{"network", VSH_OT_DATA, VSH_OFLAG_REQ, N_("name of the inactive network")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdNetworkStart(vshControl *ctl, const vshCmd *cmd)
{
virNetworkPtr network;
int ret = TRUE;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
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 10:26:54 +00:00
if (!(network = vshCommandOptNetworkBy(ctl, cmd, NULL, VSH_BYNAME)))
return FALSE;
if (virNetworkCreate(network) == 0) {
vshPrint(ctl, _("Network %s started\n"),
virNetworkGetName(network));
} else {
vshError(ctl, _("Failed to start network %s"),
virNetworkGetName(network));
ret = FALSE;
}
virNetworkFree(network);
return ret;
}
/*
* "net-undefine" command
*/
static const vshCmdInfo info_network_undefine[] = {
{"help", N_("undefine an inactive network")},
{"desc", N_("Undefine the configuration for an inactive network.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_network_undefine[] = {
{"network", VSH_OT_DATA, VSH_OFLAG_REQ, N_("network name or uuid")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdNetworkUndefine(vshControl *ctl, const vshCmd *cmd)
{
virNetworkPtr network;
int ret = TRUE;
char *name;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
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 10:26:54 +00:00
if (!(network = vshCommandOptNetwork(ctl, cmd, &name)))
return FALSE;
if (virNetworkUndefine(network) == 0) {
vshPrint(ctl, _("Network %s has been undefined\n"), name);
} else {
vshError(ctl, _("Failed to undefine network %s"), name);
ret = FALSE;
}
virNetworkFree(network);
return ret;
}
/*
* "net-uuid" command
*/
static const vshCmdInfo info_network_uuid[] = {
{"help", N_("convert a network name to network UUID")},
{"desc", ""},
{NULL, NULL}
};
static const vshCmdOptDef opts_network_uuid[] = {
{"network", VSH_OT_DATA, VSH_OFLAG_REQ, N_("network name")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdNetworkUuid(vshControl *ctl, const vshCmd *cmd)
{
virNetworkPtr network;
char uuid[VIR_UUID_STRING_BUFLEN];
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
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 10:26:54 +00:00
if (!(network = vshCommandOptNetworkBy(ctl, cmd, NULL,
VSH_BYNAME)))
return FALSE;
if (virNetworkGetUUIDString(network, uuid) != -1)
vshPrint(ctl, "%s\n", uuid);
else
vshError(ctl, "%s", _("failed to get network UUID"));
virNetworkFree(network);
return TRUE;
}
/**************************************************************************/
/*
* "iface-list" command
*/
static const vshCmdInfo info_interface_list[] = {
{"help", N_("list physical host interfaces")},
{"desc", N_("Returns list of physical host interfaces.")},
{NULL, NULL}
};
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")},
{NULL, 0, 0, NULL}
};
static int
cmdInterfaceList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
{
int inactive = vshCommandOptBool(cmd, "inactive");
int all = vshCommandOptBool(cmd, "all");
int active = !inactive || all ? 1 : 0;
int maxactive = 0, maxinactive = 0, i;
char **activeNames = NULL, **inactiveNames = NULL;
inactive |= all;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
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);
if ((maxactive = virConnectListInterfaces(ctl->conn, activeNames,
maxactive)) < 0) {
vshError(ctl, "%s", _("Failed to list active interfaces"));
VIR_FREE(activeNames);
return FALSE;
}
qsort(&activeNames[0], maxactive, sizeof(char *), namesorter);
}
}
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);
if ((maxinactive =
virConnectListDefinedInterfaces(ctl->conn, inactiveNames,
maxinactive)) < 0) {
vshError(ctl, "%s", _("Failed to list inactive interfaces"));
VIR_FREE(activeNames);
VIR_FREE(inactiveNames);
return FALSE;
}
qsort(&inactiveNames[0], maxinactive, sizeof(char*), namesorter);
}
}
vshPrintExtra(ctl, "%-20s %-10s %s\n", _("Name"), _("State"),
_("MAC Address"));
vshPrintExtra(ctl, "--------------------------------------------\n");
for (i = 0; i < maxactive; i++) {
virInterfacePtr iface =
virInterfaceLookupByName(ctl->conn, activeNames[i]);
/* this kind of work with interfaces is not atomic */
if (!iface) {
VIR_FREE(activeNames[i]);
continue;
}
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]);
/* this kind of work with interfaces is not atomic */
if (!iface) {
VIR_FREE(inactiveNames[i]);
continue;
}
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;
}
/*
* "iface-name" command
*/
static const vshCmdInfo info_interface_name[] = {
{"help", N_("convert an interface MAC address to interface name")},
{"desc", ""},
{NULL, NULL}
};
static const vshCmdOptDef opts_interface_name[] = {
{"interface", VSH_OT_DATA, VSH_OFLAG_REQ, N_("interface mac")},
{NULL, 0, 0, NULL}
};
static int
cmdInterfaceName(vshControl *ctl, const vshCmd *cmd)
{
virInterfacePtr iface;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
if (!(iface = vshCommandOptInterfaceBy(ctl, cmd, NULL,
VSH_BYMAC)))
return FALSE;
vshPrint(ctl, "%s\n", virInterfaceGetName(iface));
virInterfaceFree(iface);
return TRUE;
}
/*
* "iface-mac" command
*/
static const vshCmdInfo info_interface_mac[] = {
{"help", N_("convert an interface name to interface MAC address")},
{"desc", ""},
{NULL, NULL}
};
static const vshCmdOptDef opts_interface_mac[] = {
{"interface", VSH_OT_DATA, VSH_OFLAG_REQ, N_("interface name")},
{NULL, 0, 0, NULL}
};
static int
cmdInterfaceMAC(vshControl *ctl, const vshCmd *cmd)
{
virInterfacePtr iface;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
if (!(iface = vshCommandOptInterfaceBy(ctl, cmd, NULL,
VSH_BYNAME)))
return FALSE;
vshPrint(ctl, "%s\n", virInterfaceGetMACString(iface));
virInterfaceFree(iface);
return TRUE;
}
/*
* "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}
};
static int
cmdInterfaceDumpXML(vshControl *ctl, const vshCmd *cmd)
{
virInterfacePtr iface;
int ret = TRUE;
char *dump;
int flags = 0;
int inactive = vshCommandOptBool(cmd, "inactive");
if (inactive)
flags |= VIR_INTERFACE_XML_INACTIVE;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
if (!(iface = vshCommandOptInterface(ctl, cmd, NULL)))
return FALSE;
dump = virInterfaceGetXMLDesc(iface, flags);
if (dump != NULL) {
printf("%s", dump);
VIR_FREE(dump);
} else {
ret = FALSE;
}
virInterfaceFree(iface);
return ret;
}
/*
* "iface-define" command
*/
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.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_interface_define[] = {
{"file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("file containing an XML interface description")},
{NULL, 0, 0, NULL}
};
static int
cmdInterfaceDefine(vshControl *ctl, const vshCmd *cmd)
{
virInterfacePtr iface;
char *from;
int found;
int ret = TRUE;
char *buffer;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
from = vshCommandOptString(cmd, "file", &found);
if (!found)
return FALSE;
if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0)
return FALSE;
iface = virInterfaceDefineXML(ctl->conn, buffer, 0);
VIR_FREE(buffer);
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;
}
return ret;
}
/*
* "iface-undefine" command
*/
static const vshCmdInfo info_interface_undefine[] = {
{"help", N_("undefine a physical host interface (remove it from configuration)")},
{"desc", N_("undefine an interface.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_interface_undefine[] = {
{"interface", VSH_OT_DATA, VSH_OFLAG_REQ, N_("interface name or MAC address")},
{NULL, 0, 0, NULL}
};
static int
cmdInterfaceUndefine(vshControl *ctl, const vshCmd *cmd)
{
virInterfacePtr iface;
int ret = TRUE;
char *name;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
if (!(iface = vshCommandOptInterface(ctl, cmd, &name)))
return FALSE;
if (virInterfaceUndefine(iface) == 0) {
vshPrint(ctl, _("Interface %s undefined\n"), name);
} else {
vshError(ctl, _("Failed to undefine interface %s"), name);
ret = FALSE;
}
virInterfaceFree(iface);
return ret;
}
/*
* "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.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_interface_start[] = {
{"interface", VSH_OT_DATA, VSH_OFLAG_REQ, N_("interface name or MAC address")},
{NULL, 0, 0, NULL}
};
static int
cmdInterfaceStart(vshControl *ctl, const vshCmd *cmd)
{
virInterfacePtr iface;
int ret = TRUE;
char *name;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
if (!(iface = vshCommandOptInterface(ctl, cmd, &name)))
return FALSE;
if (virInterfaceCreate(iface, 0) == 0) {
vshPrint(ctl, _("Interface %s started\n"), name);
} else {
vshError(ctl, _("Failed to start interface %s"), name);
ret = FALSE;
}
virInterfaceFree(iface);
return ret;
}
/*
* "iface-destroy" command
*/
static const vshCmdInfo info_interface_destroy[] = {
{"help", N_("destroy a physical host interface (disable it / \"if-down\")")},
{"desc", N_("destroy a physical host interface.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_interface_destroy[] = {
{"interface", VSH_OT_DATA, VSH_OFLAG_REQ, N_("interface name or MAC address")},
{NULL, 0, 0, NULL}
};
static int
cmdInterfaceDestroy(vshControl *ctl, const vshCmd *cmd)
{
virInterfacePtr iface;
int ret = TRUE;
char *name;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
if (!(iface = vshCommandOptInterface(ctl, cmd, &name)))
return FALSE;
if (virInterfaceDestroy(iface, 0) == 0) {
vshPrint(ctl, _("Interface %s destroyed\n"), name);
} else {
vshError(ctl, _("Failed to destroy interface %s"), name);
ret = FALSE;
}
virInterfaceFree(iface);
return ret;
}
/*
* "nwfilter-define" command
*/
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.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_nwfilter_define[] = {
{"file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("file containing an XML network filter description")},
{NULL, 0, 0, NULL}
};
static int
cmdNWFilterDefine(vshControl *ctl, const vshCmd *cmd)
{
virNWFilterPtr nwfilter;
char *from;
int found;
int ret = TRUE;
char *buffer;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
from = vshCommandOptString(cmd, "file", &found);
if (!found)
return FALSE;
if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0)
return FALSE;
nwfilter = virNWFilterDefineXML(ctl->conn, buffer);
VIR_FREE(buffer);
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")},
{NULL, 0, 0, NULL}
};
static int
cmdNWFilterUndefine(vshControl *ctl, const vshCmd *cmd)
{
virNWFilterPtr nwfilter;
int ret = TRUE;
char *name;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
if (!(nwfilter = vshCommandOptNWFilter(ctl, cmd, &name)))
return FALSE;
if (virNWFilterUndefine(nwfilter) == 0) {
vshPrint(ctl, _("Network filter %s undefined\n"), name);
} else {
vshError(ctl, _("Failed to undefine network filter %s"), name);
ret = FALSE;
}
virNWFilterFree(nwfilter);
return ret;
}
/*
* "nwfilter-dumpxml" command
*/
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.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_nwfilter_dumpxml[] = {
{"nwfilter", VSH_OT_DATA, VSH_OFLAG_REQ, N_("network filter name or uuid")},
{NULL, 0, 0, NULL}
};
static int
cmdNWFilterDumpXML(vshControl *ctl, const vshCmd *cmd)
{
virNWFilterPtr nwfilter;
int ret = TRUE;
char *dump;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
if (!(nwfilter = vshCommandOptNWFilter(ctl, cmd, NULL)))
return FALSE;
dump = virNWFilterGetXMLDesc(nwfilter, 0);
if (dump != NULL) {
printf("%s", dump);
VIR_FREE(dump);
} else {
ret = FALSE;
}
virNWFilterFree(nwfilter);
return ret;
}
/*
* "nwfilter-list" command
*/
static const vshCmdInfo info_nwfilter_list[] = {
{"help", N_("list network filters")},
{"desc", N_("Returns list of network filters.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_nwfilter_list[] = {
{NULL, 0, 0, NULL}
};
static int
cmdNWFilterList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
{
int numfilters, i;
char **names;
char uuid[VIR_UUID_STRING_BUFLEN];
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
numfilters = virConnectNumOfNWFilters(ctl->conn);
if (numfilters < 0) {
vshError(ctl, "%s", _("Failed to list network filters"));
return FALSE;
}
names = vshMalloc(ctl, sizeof(char *) * numfilters);
if ((numfilters = virConnectListNWFilters(ctl->conn, names,
numfilters)) < 0) {
vshError(ctl, "%s", _("Failed to list network filters"));
VIR_FREE(names);
return FALSE;
}
qsort(&names[0], numfilters, sizeof(char *), namesorter);
vshPrintExtra(ctl, "%-36s %-20s \n", _("UUID"), _("Name"));
vshPrintExtra(ctl,
"----------------------------------------------------------------\n");
for (i = 0; i < numfilters; i++) {
virNWFilterPtr nwfilter =
virNWFilterLookupByName(ctl->conn, names[i]);
/* this kind of work with networks is not atomic operation */
if (!nwfilter) {
VIR_FREE(names[i]);
continue;
}
virNWFilterGetUUIDString(nwfilter, uuid);
vshPrint(ctl, "%-36s %-20s\n",
uuid,
virNWFilterGetName(nwfilter));
virNWFilterFree(nwfilter);
VIR_FREE(names[i]);
}
VIR_FREE(names);
return TRUE;
}
/*
* "nwfilter-edit" command
*/
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.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_nwfilter_edit[] = {
{"nwfilter", VSH_OT_DATA, VSH_OFLAG_REQ, N_("network filter name or uuid")},
{NULL, 0, 0, NULL}
};
static int
cmdNWFilterEdit (vshControl *ctl, const vshCmd *cmd)
{
int ret = FALSE;
virNWFilterPtr nwfilter = NULL;
char *tmp = NULL;
char *doc = NULL;
char *doc_edited = NULL;
char *doc_reread = NULL;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
goto cleanup;
nwfilter = vshCommandOptNWFilter (ctl, cmd, NULL);
if (nwfilter == NULL)
goto cleanup;
/* Get the XML configuration of the interface. */
doc = virNWFilterGetXMLDesc (nwfilter, 0);
if (!doc)
goto cleanup;
/* Create and open the temporary file. */
tmp = editWriteToTempFile (ctl, doc);
if (!tmp) goto cleanup;
/* Start the editor. */
if (editFile (ctl, tmp) == -1) goto cleanup;
/* Read back the edited file. */
doc_edited = editReadBackFile (ctl, tmp);
if (!doc_edited) goto cleanup;
unlink (tmp);
tmp = NULL;
/* Compare original XML with edited. Has it changed at all? */
if (STREQ (doc, doc_edited)) {
vshPrint (ctl, _("Network filter %s XML configuration not changed.\n"),
virNWFilterGetName (nwfilter));
ret = TRUE;
goto cleanup;
}
/* Now re-read the network filter XML. Did someone else change it while
* it was being edited? This also catches problems such as us
* losing a connection or the interface going away.
*/
doc_reread = virNWFilterGetXMLDesc (nwfilter, 0);
if (!doc_reread)
goto cleanup;
if (STRNEQ (doc, doc_reread)) {
vshError(ctl, "%s",
_("ERROR: the XML configuration was changed by another user"));
goto cleanup;
}
/* Everything checks out, so redefine the interface. */
virNWFilterFree (nwfilter);
nwfilter = virNWFilterDefineXML (ctl->conn, doc_edited);
if (!nwfilter)
goto cleanup;
vshPrint (ctl, _("Network filter %s XML configuration edited.\n"),
virNWFilterGetName(nwfilter));
ret = TRUE;
cleanup:
if (nwfilter)
virNWFilterFree (nwfilter);
VIR_FREE(doc);
VIR_FREE(doc_edited);
VIR_FREE(doc_reread);
if (tmp) {
unlink (tmp);
VIR_FREE(tmp);
}
return ret;
}
/**************************************************************************/
/*
* "pool-autostart" command
*/
static const vshCmdInfo info_pool_autostart[] = {
{"help", N_("autostart a pool")},
{"desc",
N_("Configure a pool to be automatically started at boot.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_pool_autostart[] = {
{"pool", VSH_OT_DATA, VSH_OFLAG_REQ, N_("pool name or uuid")},
{"disable", VSH_OT_BOOL, 0, N_("disable autostarting")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdPoolAutostart(vshControl *ctl, const vshCmd *cmd)
{
virStoragePoolPtr pool;
char *name;
int autostart;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
if (!(pool = vshCommandOptPool(ctl, cmd, "pool", &name)))
return FALSE;
autostart = !vshCommandOptBool(cmd, "disable");
if (virStoragePoolSetAutostart(pool, autostart) < 0) {
if (autostart)
vshError(ctl, _("failed to mark pool %s as autostarted"), name);
else
vshError(ctl, _("failed to unmark pool %s as autostarted"), name);
virStoragePoolFree(pool);
return FALSE;
}
if (autostart)
vshPrint(ctl, _("Pool %s marked as autostarted\n"), name);
else
vshPrint(ctl, _("Pool %s unmarked as autostarted\n"), name);
virStoragePoolFree(pool);
return TRUE;
}
/*
* "pool-create" command
*/
static const vshCmdInfo info_pool_create[] = {
{"help", N_("create a pool from an XML file")},
{"desc", N_("Create a pool.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_pool_create[] = {
{"file", VSH_OT_DATA, VSH_OFLAG_REQ,
N_("file containing an XML pool description")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdPoolCreate(vshControl *ctl, const vshCmd *cmd)
{
virStoragePoolPtr pool;
char *from;
int found;
int ret = TRUE;
char *buffer;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
from = vshCommandOptString(cmd, "file", &found);
if (!found)
return FALSE;
if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0)
return FALSE;
pool = virStoragePoolCreateXML(ctl->conn, buffer, 0);
VIR_FREE(buffer);
if (pool != NULL) {
vshPrint(ctl, _("Pool %s created from %s\n"),
virStoragePoolGetName(pool), from);
virStoragePoolFree(pool);
} else {
vshError(ctl, _("Failed to create pool from %s"), from);
ret = FALSE;
}
return ret;
}
2008-12-22 16:23:36 +00:00
/*
* "nodedev-create" command
*/
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.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_node_device_create[] = {
{"file", VSH_OT_DATA, VSH_OFLAG_REQ,
N_("file containing an XML description of the device")},
{NULL, 0, 0, NULL}
};
static int
cmdNodeDeviceCreate(vshControl *ctl, const vshCmd *cmd)
{
virNodeDevicePtr dev = NULL;
char *from;
int found = 0;
int ret = TRUE;
char *buffer;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
from = vshCommandOptString(cmd, "file", &found);
if (!found) {
return FALSE;
}
if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0)
return FALSE;
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);
} else {
vshError(ctl, _("Failed to create node device from %s"), from);
ret = FALSE;
}
return ret;
}
/*
* "nodedev-destroy" command
*/
static const vshCmdInfo info_node_device_destroy[] = {
{"help", N_("destroy a device on the node")},
{"desc", N_("Destroy a device on the node. Note that this "
"command destroys devices on the physical host ")},
{NULL, NULL}
};
static const vshCmdOptDef opts_node_device_destroy[] = {
{"name", VSH_OT_DATA, VSH_OFLAG_REQ,
N_("name of the device to be destroyed")},
{NULL, 0, 0, NULL}
};
static int
cmdNodeDeviceDestroy(vshControl *ctl, const vshCmd *cmd)
{
virNodeDevicePtr dev = NULL;
int ret = TRUE;
int found = 0;
char *name;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE)) {
return FALSE;
}
name = vshCommandOptString(cmd, "name", &found);
if (!found) {
return FALSE;
}
dev = virNodeDeviceLookupByName(ctl->conn, name);
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;
}
/*
2008-12-22 16:23:36 +00:00
* XML Building helper for pool-define-as and pool-create-as
*/
2008-12-22 16:23:36 +00:00
static const vshCmdOptDef opts_pool_X_as[] = {
{"name", VSH_OT_DATA, VSH_OFLAG_REQ, N_("name of the pool")},
{"print-xml", VSH_OT_BOOL, 0, N_("print XML document, but don't define/create")},
{"type", VSH_OT_DATA, VSH_OFLAG_REQ, N_("type of the pool")},
{"source-host", VSH_OT_DATA, 0, N_("source-host for underlying storage")},
{"source-path", VSH_OT_DATA, 0, N_("source path for underlying storage")},
{"source-dev", VSH_OT_DATA, 0, N_("source device for underlying storage")},
{"source-name", VSH_OT_DATA, 0, N_("source name for underlying storage")},
{"target", VSH_OT_DATA, 0, N_("target for underlying storage")},
{NULL, 0, 0, NULL}
};
2008-12-22 16:23:36 +00:00
static int buildPoolXML(const vshCmd *cmd, char **retname, char **xml) {
int found;
2008-12-22 16:23:36 +00:00
char *name, *type, *srcHost, *srcPath, *srcDev, *srcName, *target;
virBuffer buf = VIR_BUFFER_INITIALIZER;
name = vshCommandOptString(cmd, "name", &found);
if (!found)
goto cleanup;
type = vshCommandOptString(cmd, "type", &found);
if (!found)
goto cleanup;
srcHost = vshCommandOptString(cmd, "source-host", &found);
srcPath = vshCommandOptString(cmd, "source-path", &found);
srcDev = vshCommandOptString(cmd, "source-dev", &found);
2008-12-22 16:23:36 +00:00
srcName = vshCommandOptString(cmd, "source-name", &found);
target = vshCommandOptString(cmd, "target", &found);
virBufferVSprintf(&buf, "<pool type='%s'>\n", type);
virBufferVSprintf(&buf, " <name>%s</name>\n", name);
if (srcHost || srcPath || srcDev) {
virBufferAddLit(&buf, " <source>\n");
2008-12-22 16:23:36 +00:00
if (srcHost)
virBufferVSprintf(&buf, " <host name='%s'/>\n", srcHost);
if (srcPath)
virBufferVSprintf(&buf, " <dir path='%s'/>\n", srcPath);
if (srcDev)
virBufferVSprintf(&buf, " <device path='%s'/>\n", srcDev);
2008-12-22 16:23:36 +00:00
if (srcName)
virBufferVSprintf(&buf, " <name>%s</name>\n", srcName);
virBufferAddLit(&buf, " </source>\n");
}
if (target) {
virBufferAddLit(&buf, " <target>\n");
virBufferVSprintf(&buf, " <path>%s</path>\n", target);
virBufferAddLit(&buf, " </target>\n");
}
virBufferAddLit(&buf, "</pool>\n");
if (virBufferError(&buf)) {
vshPrint(ctl, "%s", _("Failed to allocate XML buffer"));
return FALSE;
}
2008-12-22 16:23:36 +00:00
*xml = virBufferContentAndReset(&buf);
*retname = name;
return TRUE;
cleanup:
virBufferFreeAndReset(&buf);
2008-12-22 16:23:36 +00:00
return FALSE;
}
/*
* "pool-create-as" command
*/
static const vshCmdInfo info_pool_create_as[] = {
{"help", N_("create a pool from a set of args")},
{"desc", N_("Create a pool.")},
2008-12-22 16:23:36 +00:00
{NULL, NULL}
};
static int
cmdPoolCreateAs(vshControl *ctl, const vshCmd *cmd)
{
virStoragePoolPtr pool;
char *xml, *name;
int printXML = vshCommandOptBool(cmd, "print-xml");
2008-12-22 16:23:36 +00:00
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
if (!buildPoolXML(cmd, &name, &xml))
return FALSE;
if (printXML) {
printf("%s", xml);
VIR_FREE(xml);
} else {
pool = virStoragePoolCreateXML(ctl->conn, xml, 0);
VIR_FREE(xml);
if (pool != NULL) {
vshPrint(ctl, _("Pool %s created\n"), name);
virStoragePoolFree(pool);
} else {
vshError(ctl, _("Failed to create pool %s"), name);
return FALSE;
}
}
return TRUE;
}
/*
* "pool-define" command
*/
static const vshCmdInfo info_pool_define[] = {
{"help", N_("define (but don't start) a pool from an XML file")},
{"desc", N_("Define a pool.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_pool_define[] = {
{"file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("file containing an XML pool description")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdPoolDefine(vshControl *ctl, const vshCmd *cmd)
{
virStoragePoolPtr pool;
char *from;
int found;
int ret = TRUE;
char *buffer;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
from = vshCommandOptString(cmd, "file", &found);
if (!found)
return FALSE;
if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0)
return FALSE;
pool = virStoragePoolDefineXML(ctl->conn, buffer, 0);
VIR_FREE(buffer);
if (pool != NULL) {
vshPrint(ctl, _("Pool %s defined from %s\n"),
virStoragePoolGetName(pool), from);
virStoragePoolFree(pool);
} else {
vshError(ctl, _("Failed to define pool from %s"), from);
ret = FALSE;
}
return ret;
}
/*
* "pool-define-as" command
*/
static const vshCmdInfo info_pool_define_as[] = {
{"help", N_("define a pool from a set of args")},
{"desc", N_("Define a pool.")},
{NULL, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdPoolDefineAs(vshControl *ctl, const vshCmd *cmd)
{
virStoragePoolPtr pool;
2008-12-22 16:23:36 +00:00
char *xml, *name;
int printXML = vshCommandOptBool(cmd, "print-xml");
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
2008-12-22 16:23:36 +00:00
if (!buildPoolXML(cmd, &name, &xml))
return FALSE;
if (printXML) {
printf("%s", xml);
VIR_FREE(xml);
} else {
pool = virStoragePoolDefineXML(ctl->conn, xml, 0);
VIR_FREE(xml);
if (pool != NULL) {
vshPrint(ctl, _("Pool %s defined\n"), name);
virStoragePoolFree(pool);
} else {
vshError(ctl, _("Failed to define pool %s"), name);
return FALSE;
}
}
return TRUE;
}
/*
* "pool-build" command
*/
static const vshCmdInfo info_pool_build[] = {
{"help", N_("build a pool")},
{"desc", N_("Build a given pool.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_pool_build[] = {
{"pool", VSH_OT_DATA, VSH_OFLAG_REQ, N_("pool name or uuid")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdPoolBuild(vshControl *ctl, const vshCmd *cmd)
{
virStoragePoolPtr pool;
int ret = TRUE;
char *name;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
if (!(pool = vshCommandOptPool(ctl, cmd, "pool", &name)))
return FALSE;
if (virStoragePoolBuild(pool, 0) == 0) {
vshPrint(ctl, _("Pool %s built\n"), name);
} else {
vshError(ctl, _("Failed to build pool %s"), name);
ret = FALSE;
}
virStoragePoolFree(pool);
return ret;
}
/*
* "pool-destroy" command
*/
static const vshCmdInfo info_pool_destroy[] = {
{"help", N_("destroy a pool")},
{"desc", N_("Destroy a given pool.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_pool_destroy[] = {
{"pool", VSH_OT_DATA, VSH_OFLAG_REQ, N_("pool name or uuid")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdPoolDestroy(vshControl *ctl, const vshCmd *cmd)
{
virStoragePoolPtr pool;
int ret = TRUE;
char *name;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
if (!(pool = vshCommandOptPool(ctl, cmd, "pool", &name)))
return FALSE;
if (virStoragePoolDestroy(pool) == 0) {
vshPrint(ctl, _("Pool %s destroyed\n"), name);
} else {
vshError(ctl, _("Failed to destroy pool %s"), name);
ret = FALSE;
}
virStoragePoolFree(pool);
return ret;
}
/*
* "pool-delete" command
*/
static const vshCmdInfo info_pool_delete[] = {
{"help", N_("delete a pool")},
{"desc", N_("Delete a given pool.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_pool_delete[] = {
{"pool", VSH_OT_DATA, VSH_OFLAG_REQ, N_("pool name or uuid")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdPoolDelete(vshControl *ctl, const vshCmd *cmd)
{
virStoragePoolPtr pool;
int ret = TRUE;
char *name;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
if (!(pool = vshCommandOptPool(ctl, cmd, "pool", &name)))
return FALSE;
if (virStoragePoolDelete(pool, 0) == 0) {
vshPrint(ctl, _("Pool %s deleted\n"), name);
} else {
vshError(ctl, _("Failed to delete pool %s"), name);
ret = FALSE;
}
virStoragePoolFree(pool);
return ret;
}
/*
* "pool-refresh" command
*/
static const vshCmdInfo info_pool_refresh[] = {
{"help", N_("refresh a pool")},
{"desc", N_("Refresh a given pool.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_pool_refresh[] = {
{"pool", VSH_OT_DATA, VSH_OFLAG_REQ, N_("pool name or uuid")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdPoolRefresh(vshControl *ctl, const vshCmd *cmd)
{
virStoragePoolPtr pool;
int ret = TRUE;
char *name;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
if (!(pool = vshCommandOptPool(ctl, cmd, "pool", &name)))
return FALSE;
if (virStoragePoolRefresh(pool, 0) == 0) {
vshPrint(ctl, _("Pool %s refreshed\n"), name);
} else {
vshError(ctl, _("Failed to refresh pool %s"), name);
ret = FALSE;
}
virStoragePoolFree(pool);
return ret;
}
/*
* "pool-dumpxml" command
*/
static const vshCmdInfo info_pool_dumpxml[] = {
{"help", N_("pool information in XML")},
{"desc", N_("Output the pool information as an XML dump to stdout.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_pool_dumpxml[] = {
{"pool", VSH_OT_DATA, VSH_OFLAG_REQ, N_("pool name or uuid")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdPoolDumpXML(vshControl *ctl, const vshCmd *cmd)
{
virStoragePoolPtr pool;
int ret = TRUE;
char *dump;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
if (!(pool = vshCommandOptPool(ctl, cmd, "pool", NULL)))
return FALSE;
dump = virStoragePoolGetXMLDesc(pool, 0);
if (dump != NULL) {
printf("%s", dump);
VIR_FREE(dump);
} else {
ret = FALSE;
}
virStoragePoolFree(pool);
return ret;
}
/*
* "pool-list" command
*/
static const vshCmdInfo info_pool_list[] = {
{"help", N_("list pools")},
{"desc", N_("Returns list of pools.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_pool_list[] = {
{"inactive", VSH_OT_BOOL, 0, N_("list inactive pools")},
{"all", VSH_OT_BOOL, 0, N_("list inactive & active pools")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdPoolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
{
int inactive = vshCommandOptBool(cmd, "inactive");
int all = vshCommandOptBool(cmd, "all");
int active = !inactive || all ? 1 : 0;
int maxactive = 0, maxinactive = 0, i;
char **activeNames = NULL, **inactiveNames = NULL;
inactive |= all;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
if (active) {
maxactive = virConnectNumOfStoragePools(ctl->conn);
if (maxactive < 0) {
vshError(ctl, "%s", _("Failed to list active pools"));
return FALSE;
}
if (maxactive) {
activeNames = vshMalloc(ctl, sizeof(char *) * maxactive);
if ((maxactive = virConnectListStoragePools(ctl->conn, activeNames,
maxactive)) < 0) {
vshError(ctl, "%s", _("Failed to list active pools"));
VIR_FREE(activeNames);
return FALSE;
}
qsort(&activeNames[0], maxactive, sizeof(char *), namesorter);
}
}
if (inactive) {
maxinactive = virConnectNumOfDefinedStoragePools(ctl->conn);
if (maxinactive < 0) {
vshError(ctl, "%s", _("Failed to list inactive pools"));
VIR_FREE(activeNames);
return FALSE;
}
if (maxinactive) {
inactiveNames = vshMalloc(ctl, sizeof(char *) * maxinactive);
if ((maxinactive = virConnectListDefinedStoragePools(ctl->conn, inactiveNames, maxinactive)) < 0) {
vshError(ctl, "%s", _("Failed to list inactive pools"));
VIR_FREE(activeNames);
VIR_FREE(inactiveNames);
return FALSE;
}
qsort(&inactiveNames[0], maxinactive, sizeof(char*), namesorter);
}
}
vshPrintExtra(ctl, "%-20s %-10s %-10s\n", _("Name"), _("State"), _("Autostart"));
vshPrintExtra(ctl, "-----------------------------------------\n");
for (i = 0; i < maxactive; i++) {
virStoragePoolPtr pool = virStoragePoolLookupByName(ctl->conn, activeNames[i]);
const char *autostartStr;
int autostart = 0;
/* this kind of work with pools is not atomic operation */
if (!pool) {
VIR_FREE(activeNames[i]);
continue;
}
if (virStoragePoolGetAutostart(pool, &autostart) < 0)
autostartStr = _("no autostart");
else
autostartStr = autostart ? "yes" : "no";
vshPrint(ctl, "%-20s %-10s %-10s\n",
virStoragePoolGetName(pool),
_("active"),
autostartStr);
virStoragePoolFree(pool);
VIR_FREE(activeNames[i]);
}
for (i = 0; i < maxinactive; i++) {
virStoragePoolPtr pool = virStoragePoolLookupByName(ctl->conn, inactiveNames[i]);
const char *autostartStr;
int autostart = 0;
/* this kind of work with pools is not atomic operation */
if (!pool) {
VIR_FREE(inactiveNames[i]);
continue;
}
if (virStoragePoolGetAutostart(pool, &autostart) < 0)
autostartStr = _("no autostart");
else
autostartStr = autostart ? "yes" : "no";
vshPrint(ctl, "%-20s %-10s %-10s\n",
inactiveNames[i],
_("inactive"),
autostartStr);
virStoragePoolFree(pool);
VIR_FREE(inactiveNames[i]);
}
VIR_FREE(activeNames);
VIR_FREE(inactiveNames);
return TRUE;
}
/*
* "find-storage-pool-sources-as" command
*/
static const vshCmdInfo info_find_storage_pool_sources_as[] = {
{"help", N_("find potential storage pool sources")},
{"desc", N_("Returns XML <sources> document.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_find_storage_pool_sources_as[] = {
{"type", VSH_OT_DATA, VSH_OFLAG_REQ,
N_("type of storage pool sources to find")},
{"host", VSH_OT_DATA, VSH_OFLAG_NONE, N_("optional host to query")},
{"port", VSH_OT_DATA, VSH_OFLAG_NONE, N_("optional port to query")},
{NULL, 0, 0, NULL}
};
static int
cmdPoolDiscoverSourcesAs(vshControl * ctl, const vshCmd * cmd ATTRIBUTE_UNUSED)
{
char *type, *host;
char *srcSpec = NULL;
char *srcList;
int found;
type = vshCommandOptString(cmd, "type", &found);
if (!found)
return FALSE;
host = vshCommandOptString(cmd, "host", &found);
if (!found)
host = NULL;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
if (host) {
size_t hostlen = strlen(host);
char *port = vshCommandOptString(cmd, "port", &found);
int ret;
if (!found) {
port = strrchr(host, ':');
if (port) {
if (*(++port))
hostlen = port - host - 1;
else
port = NULL;
}
}
ret = port ?
2008-12-23 13:03:29 +00:00
virAsprintf(&srcSpec,
"<source><host name='%.*s' port='%s'/></source>",
(int)hostlen, host, port) :
virAsprintf(&srcSpec,
"<source><host name='%.*s'/></source>",
(int)hostlen, host);
if (ret < 0) {
switch (errno) {
case ENOMEM:
vshError(ctl, "%s", _("Out of memory"));
break;
default:
vshError(ctl, _("virAsprintf failed (errno %d)"), errno);
}
return FALSE;
}
}
srcList = virConnectFindStoragePoolSources(ctl->conn, type, srcSpec, 0);
VIR_FREE(srcSpec);
if (srcList == NULL) {
vshError(ctl, _("Failed to find any %s pool sources"), type);
return FALSE;
}
vshPrint(ctl, "%s", srcList);
VIR_FREE(srcList);
return TRUE;
}
/*
* "find-storage-pool-sources" command
*/
static const vshCmdInfo info_find_storage_pool_sources[] = {
{"help", N_("discover potential storage pool sources")},
{"desc", N_("Returns XML <sources> document.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_find_storage_pool_sources[] = {
{"type", VSH_OT_DATA, VSH_OFLAG_REQ,
N_("type of storage pool sources to discover")},
{"srcSpec", VSH_OT_DATA, VSH_OFLAG_NONE,
N_("optional file of source xml to query for pools")},
{NULL, 0, 0, NULL}
};
static int
cmdPoolDiscoverSources(vshControl * ctl, const vshCmd * cmd ATTRIBUTE_UNUSED)
{
char *type, *srcSpecFile, *srcList;
char *srcSpec = NULL;
int found;
type = vshCommandOptString(cmd, "type", &found);
if (!found)
return FALSE;
srcSpecFile = vshCommandOptString(cmd, "srcSpec", &found);
if (!found)
srcSpecFile = NULL;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
if (srcSpecFile && virFileReadAll(srcSpecFile, VIRSH_MAX_XML_FILE, &srcSpec) < 0)
return FALSE;
srcList = virConnectFindStoragePoolSources(ctl->conn, type, srcSpec, 0);
VIR_FREE(srcSpec);
if (srcList == NULL) {
vshError(ctl, _("Failed to find any %s pool sources"), type);
return FALSE;
}
vshPrint(ctl, "%s", srcList);
VIR_FREE(srcList);
return TRUE;
}
/*
* "pool-info" command
*/
static const vshCmdInfo info_pool_info[] = {
{"help", N_("storage pool information")},
{"desc", N_("Returns basic information about the storage pool.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_pool_info[] = {
{"pool", VSH_OT_DATA, VSH_OFLAG_REQ, N_("pool name or uuid")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdPoolInfo(vshControl *ctl, const vshCmd *cmd)
{
virStoragePoolInfo info;
virStoragePoolPtr pool;
int ret = TRUE;
char uuid[VIR_UUID_STRING_BUFLEN];
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
if (!(pool = vshCommandOptPool(ctl, cmd, "pool", NULL)))
return FALSE;
vshPrint(ctl, "%-15s %s\n", _("Name:"), virStoragePoolGetName(pool));
if (virStoragePoolGetUUIDString(pool, &uuid[0])==0)
vshPrint(ctl, "%-15s %s\n", _("UUID:"), uuid);
if (virStoragePoolGetInfo(pool, &info) == 0) {
double val;
const char *unit;
switch (info.state) {
case VIR_STORAGE_POOL_INACTIVE:
vshPrint(ctl, "%-15s %s\n", _("State:"),
_("inactive"));
break;
case VIR_STORAGE_POOL_BUILDING:
vshPrint(ctl, "%-15s %s\n", _("State:"),
_("building"));
break;
case VIR_STORAGE_POOL_RUNNING:
vshPrint(ctl, "%-15s %s\n", _("State:"),
_("running"));
break;
case VIR_STORAGE_POOL_DEGRADED:
vshPrint(ctl, "%-15s %s\n", _("State:"),
_("degraded"));
break;
}
if (info.state == VIR_STORAGE_POOL_RUNNING ||
info.state == VIR_STORAGE_POOL_DEGRADED) {
val = prettyCapacity(info.capacity, &unit);
vshPrint(ctl, "%-15s %2.2lf %s\n", _("Capacity:"), val, unit);
val = prettyCapacity(info.allocation, &unit);
vshPrint(ctl, "%-15s %2.2lf %s\n", _("Allocation:"), val, unit);
val = prettyCapacity(info.available, &unit);
vshPrint(ctl, "%-15s %2.2lf %s\n", _("Available:"), val, unit);
}
} else {
ret = FALSE;
}
virStoragePoolFree(pool);
return ret;
}
/*
* "pool-name" command
*/
static const vshCmdInfo info_pool_name[] = {
{"help", N_("convert a pool UUID to pool name")},
{"desc", ""},
{NULL, NULL}
};
static const vshCmdOptDef opts_pool_name[] = {
{"pool", VSH_OT_DATA, VSH_OFLAG_REQ, N_("pool uuid")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdPoolName(vshControl *ctl, const vshCmd *cmd)
{
virStoragePoolPtr pool;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
if (!(pool = vshCommandOptPoolBy(ctl, cmd, "pool", NULL,
VSH_BYUUID)))
return FALSE;
vshPrint(ctl, "%s\n", virStoragePoolGetName(pool));
virStoragePoolFree(pool);
return TRUE;
}
/*
* "pool-start" command
*/
static const vshCmdInfo info_pool_start[] = {
{"help", N_("start a (previously defined) inactive pool")},
{"desc", N_("Start a pool.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_pool_start[] = {
{"pool", VSH_OT_DATA, VSH_OFLAG_REQ, N_("name of the inactive pool")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdPoolStart(vshControl *ctl, const vshCmd *cmd)
{
virStoragePoolPtr pool;
int ret = TRUE;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
if (!(pool = vshCommandOptPoolBy(ctl, cmd, "pool", NULL, VSH_BYNAME)))
return FALSE;
if (virStoragePoolCreate(pool, 0) == 0) {
vshPrint(ctl, _("Pool %s started\n"),
virStoragePoolGetName(pool));
} else {
vshError(ctl, _("Failed to start pool %s"), virStoragePoolGetName(pool));
ret = FALSE;
}
virStoragePoolFree(pool);
return ret;
}
/*
* "vol-create-as" command
*/
static const vshCmdInfo info_vol_create_as[] = {
{"help", N_("create a volume from a set of args")},
{"desc", N_("Create a vol.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_vol_create_as[] = {
{"pool", VSH_OT_DATA, VSH_OFLAG_REQ, N_("pool name")},
{"name", VSH_OT_DATA, VSH_OFLAG_REQ, N_("name of the volume")},
{"capacity", VSH_OT_DATA, VSH_OFLAG_REQ, N_("size of the vol with optional k,M,G,T suffix")},
{"allocation", VSH_OT_STRING, 0, N_("initial allocation size with optional k,M,G,T suffix")},
{"format", VSH_OT_STRING, 0, N_("file format type raw,bochs,qcow,qcow2,vmdk")},
{NULL, 0, 0, NULL}
};
static int cmdVolSize(const char *data, unsigned long long *val)
{
char *end;
if (virStrToLong_ull(data, &end, 10, val) < 0)
return -1;
if (end && *end) {
/* Deliberate fallthrough cases here :-) */
switch (*end) {
case 'T':
*val *= 1024;
case 'G':
*val *= 1024;
case 'M':
*val *= 1024;
case 'k':
*val *= 1024;
break;
default:
return -1;
}
end++;
if (*end)
return -1;
}
return 0;
}
static int
2008-08-01 13:51:18 +00:00
cmdVolCreateAs(vshControl *ctl, const vshCmd *cmd)
{
virStoragePoolPtr pool;
virStorageVolPtr vol;
int found;
char *xml;
char *name, *capacityStr, *allocationStr, *format;
unsigned long long capacity, allocation = 0;
virBuffer buf = VIR_BUFFER_INITIALIZER;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
if (!(pool = vshCommandOptPoolBy(ctl, cmd, "pool", NULL,
VSH_BYNAME)))
return FALSE;
name = vshCommandOptString(cmd, "name", &found);
if (!found)
goto cleanup;
capacityStr = vshCommandOptString(cmd, "capacity", &found);
if (!found)
goto cleanup;
if (cmdVolSize(capacityStr, &capacity) < 0)
vshError(ctl, _("Malformed size %s"), capacityStr);
allocationStr = vshCommandOptString(cmd, "allocation", &found);
if (allocationStr &&
cmdVolSize(allocationStr, &allocation) < 0)
vshError(ctl, _("Malformed size %s"), allocationStr);
format = vshCommandOptString(cmd, "format", &found);
virBufferAddLit(&buf, "<volume>\n");
virBufferVSprintf(&buf, " <name>%s</name>\n", name);
virBufferVSprintf(&buf, " <capacity>%llu</capacity>\n", capacity);
if (allocationStr)
virBufferVSprintf(&buf, " <allocation>%llu</allocation>\n", allocation);
if (format) {
virBufferAddLit(&buf, " <target>\n");
virBufferVSprintf(&buf, " <format type='%s'/>\n",format);
virBufferAddLit(&buf, " </target>\n");
}
virBufferAddLit(&buf, "</volume>\n");
if (virBufferError(&buf)) {
vshPrint(ctl, "%s", _("Failed to allocate XML buffer"));
return FALSE;
}
xml = virBufferContentAndReset(&buf);
vol = virStorageVolCreateXML(pool, xml, 0);
VIR_FREE(xml);
virStoragePoolFree(pool);
if (vol != NULL) {
vshPrint(ctl, _("Vol %s created\n"), name);
virStorageVolFree(vol);
return TRUE;
} else {
vshError(ctl, _("Failed to create vol %s"), name);
return FALSE;
}
cleanup:
virBufferFreeAndReset(&buf);
virStoragePoolFree(pool);
return FALSE;
}
/*
* "pool-undefine" command
*/
static const vshCmdInfo info_pool_undefine[] = {
{"help", N_("undefine an inactive pool")},
{"desc", N_("Undefine the configuration for an inactive pool.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_pool_undefine[] = {
{"pool", VSH_OT_DATA, VSH_OFLAG_REQ, N_("pool name or uuid")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdPoolUndefine(vshControl *ctl, const vshCmd *cmd)
{
virStoragePoolPtr pool;
int ret = TRUE;
char *name;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
if (!(pool = vshCommandOptPool(ctl, cmd, "pool", &name)))
return FALSE;
if (virStoragePoolUndefine(pool) == 0) {
vshPrint(ctl, _("Pool %s has been undefined\n"), name);
} else {
vshError(ctl, _("Failed to undefine pool %s"), name);
ret = FALSE;
}
virStoragePoolFree(pool);
return ret;
}
/*
* "pool-uuid" command
*/
static const vshCmdInfo info_pool_uuid[] = {
{"help", N_("convert a pool name to pool UUID")},
{"desc", ""},
{NULL, NULL}
};
static const vshCmdOptDef opts_pool_uuid[] = {
{"pool", VSH_OT_DATA, VSH_OFLAG_REQ, N_("pool name")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdPoolUuid(vshControl *ctl, const vshCmd *cmd)
{
virStoragePoolPtr pool;
char uuid[VIR_UUID_STRING_BUFLEN];
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
if (!(pool = vshCommandOptPoolBy(ctl, cmd, "pool", NULL,
VSH_BYNAME)))
return FALSE;
if (virStoragePoolGetUUIDString(pool, uuid) != -1)
vshPrint(ctl, "%s\n", uuid);
else
vshError(ctl, "%s", _("failed to get pool UUID"));
virStoragePoolFree(pool);
return TRUE;
}
/*
* "vol-create" command
*/
static const vshCmdInfo info_vol_create[] = {
{"help", N_("create a vol from an XML file")},
{"desc", N_("Create a vol.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_vol_create[] = {
{"pool", VSH_OT_DATA, VSH_OFLAG_REQ, N_("pool name")},
{"file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("file containing an XML vol description")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdVolCreate(vshControl *ctl, const vshCmd *cmd)
{
virStoragePoolPtr pool;
virStorageVolPtr vol;
char *from;
int found;
int ret = TRUE;
char *buffer;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
if (!(pool = vshCommandOptPoolBy(ctl, cmd, "pool", NULL,
VSH_BYNAME)))
return FALSE;
from = vshCommandOptString(cmd, "file", &found);
if (!found) {
virStoragePoolFree(pool);
return FALSE;
}
if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) {
virshReportError(ctl);
virStoragePoolFree(pool);
return FALSE;
}
vol = virStorageVolCreateXML(pool, buffer, 0);
VIR_FREE(buffer);
virStoragePoolFree(pool);
if (vol != NULL) {
vshPrint(ctl, _("Vol %s created from %s\n"),
virStorageVolGetName(vol), from);
virStorageVolFree(vol);
} else {
vshError(ctl, _("Failed to create vol from %s"), from);
ret = FALSE;
}
return ret;
}
/*
* "vol-create-from" command
*/
static const vshCmdInfo info_vol_create_from[] = {
{"help", N_("create a vol, using another volume as input")},
{"desc", N_("Create a vol from an existing volume.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_vol_create_from[] = {
{"pool", VSH_OT_DATA, VSH_OFLAG_REQ, N_("pool name")},
{"file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("file containing an XML vol description")},
{"inputpool", VSH_OT_STRING, 0, N_("pool name or uuid of the input volume's pool")},
{"vol", VSH_OT_DATA, VSH_OFLAG_REQ, N_("input vol name or key")},
{NULL, 0, 0, NULL}
};
static int
cmdVolCreateFrom(vshControl *ctl, const vshCmd *cmd)
{
virStoragePoolPtr pool = NULL;
virStorageVolPtr newvol = NULL, inputvol = NULL;
char *from;
int found;
int ret = FALSE;
char *buffer = NULL;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
goto cleanup;
if (!(pool = vshCommandOptPoolBy(ctl, cmd, "pool", NULL, VSH_BYNAME)))
goto cleanup;
from = vshCommandOptString(cmd, "file", &found);
if (!found) {
goto cleanup;
}
if (!(inputvol = vshCommandOptVol(ctl, cmd, "vol", "inputpool", NULL)))
goto cleanup;
if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) {
virshReportError(ctl);
goto cleanup;
}
newvol = virStorageVolCreateXMLFrom(pool, buffer, inputvol, 0);
if (newvol != NULL) {
vshPrint(ctl, _("Vol %s created from input vol %s\n"),
virStorageVolGetName(newvol), virStorageVolGetName(inputvol));
} else {
vshError(ctl, _("Failed to create vol from %s"), from);
goto cleanup;
}
ret = TRUE;
cleanup:
VIR_FREE(buffer);
if (pool)
virStoragePoolFree(pool);
if (inputvol)
virStorageVolFree(inputvol);
if (newvol)
virStorageVolFree(newvol);
return ret;
}
static xmlChar *
makeCloneXML(char *origxml, char *newname) {
xmlDocPtr doc = NULL;
xmlXPathContextPtr ctxt = NULL;
xmlXPathObjectPtr obj = NULL;
xmlChar *newxml = NULL;
int size;
doc = xmlReadDoc((const xmlChar *) origxml, "domain.xml", NULL,
XML_PARSE_NOENT | XML_PARSE_NONET | XML_PARSE_NOWARNING);
if (!doc)
goto cleanup;
ctxt = xmlXPathNewContext(doc);
if (!ctxt)
goto cleanup;
obj = xmlXPathEval(BAD_CAST "/volume/name", ctxt);
if ((obj == NULL) || (obj->nodesetval == NULL) ||
(obj->nodesetval->nodeTab == NULL))
goto cleanup;
xmlNodeSetContent(obj->nodesetval->nodeTab[0], (const xmlChar *)newname);
xmlDocDumpMemory(doc, &newxml, &size);
cleanup:
xmlXPathFreeObject(obj);
xmlXPathFreeContext(ctxt);
xmlFreeDoc(doc);
return newxml;
}
/*
* "vol-clone" command
*/
static const vshCmdInfo info_vol_clone[] = {
{"help", N_("clone a volume.")},
{"desc", N_("Clone an existing volume.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_vol_clone[] = {
{"pool", VSH_OT_STRING, 0, N_("pool name or uuid")},
{"vol", VSH_OT_DATA, VSH_OFLAG_REQ, N_("orig vol name or key")},
{"newname", VSH_OT_DATA, VSH_OFLAG_REQ, N_("clone name")},
{NULL, 0, 0, NULL}
};
static int
cmdVolClone(vshControl *ctl, const vshCmd *cmd)
{
virStoragePoolPtr origpool = NULL;
virStorageVolPtr origvol = NULL, newvol = NULL;
char *name, *origxml = NULL;
xmlChar *newxml = NULL;
int found;
int ret = FALSE;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
goto cleanup;
if (!(origvol = vshCommandOptVol(ctl, cmd, "vol", "pool", NULL)))
goto cleanup;
origpool = virStoragePoolLookupByVolume(origvol);
if (!origpool) {
vshError(ctl, "%s", _("failed to get parent pool"));
goto cleanup;
}
name = vshCommandOptString(cmd, "newname", &found);
if (!found)
goto cleanup;
origxml = virStorageVolGetXMLDesc(origvol, 0);
if (!origxml)
goto cleanup;
newxml = makeCloneXML(origxml, name);
if (!newxml) {
vshPrint(ctl, "%s", _("Failed to allocate XML buffer"));
goto cleanup;
}
newvol = virStorageVolCreateXMLFrom(origpool, (char *) newxml, origvol, 0);
if (newvol != NULL) {
vshPrint(ctl, _("Vol %s cloned from %s\n"),
virStorageVolGetName(newvol), virStorageVolGetName(origvol));
} else {
vshError(ctl, _("Failed to clone vol from %s"),
virStorageVolGetName(origvol));
goto cleanup;
}
ret = TRUE;
cleanup:
VIR_FREE(origxml);
xmlFree(newxml);
if (origvol)
virStorageVolFree(origvol);
if (newvol)
virStorageVolFree(newvol);
if (origpool)
virStoragePoolFree(origpool);
return ret;
}
/*
* "vol-delete" command
*/
static const vshCmdInfo info_vol_delete[] = {
{"help", N_("delete a vol")},
{"desc", N_("Delete a given vol.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_vol_delete[] = {
{"pool", VSH_OT_STRING, 0, N_("pool name or uuid")},
{"vol", VSH_OT_DATA, VSH_OFLAG_REQ, N_("vol name, key or path")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdVolDelete(vshControl *ctl, const vshCmd *cmd)
{
virStorageVolPtr vol;
int ret = TRUE;
char *name;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", &name))) {
return FALSE;
}
if (virStorageVolDelete(vol, 0) == 0) {
vshPrint(ctl, _("Vol %s deleted\n"), name);
} else {
vshError(ctl, _("Failed to delete vol %s"), name);
ret = FALSE;
}
virStorageVolFree(vol);
return ret;
}
2010-03-02 03:10:40 +00:00
/*
* "vol-wipe" command
*/
static const vshCmdInfo info_vol_wipe[] = {
{"help", N_("wipe a vol")},
{"desc", N_("Ensure data previously on a volume is not accessible to future reads")},
{NULL, NULL}
};
static const vshCmdOptDef opts_vol_wipe[] = {
{"pool", VSH_OT_STRING, 0, N_("pool name or uuid")},
{"vol", VSH_OT_DATA, VSH_OFLAG_REQ, N_("vol name, key or path")},
{NULL, 0, 0, NULL}
};
static int
cmdVolWipe(vshControl *ctl, const vshCmd *cmd)
{
virStorageVolPtr vol;
int ret = TRUE;
char *name;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", &name))) {
return FALSE;
}
if (virStorageVolWipe(vol, 0) == 0) {
vshPrint(ctl, _("Vol %s wiped\n"), name);
} else {
vshError(ctl, _("Failed to wipe vol %s"), name);
ret = FALSE;
}
virStorageVolFree(vol);
return ret;
}
/*
* "vol-info" command
*/
static const vshCmdInfo info_vol_info[] = {
{"help", N_("storage vol information")},
{"desc", N_("Returns basic information about the storage vol.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_vol_info[] = {
{"pool", VSH_OT_STRING, 0, N_("pool name or uuid")},
{"vol", VSH_OT_DATA, VSH_OFLAG_REQ, N_("vol name, key or path")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdVolInfo(vshControl *ctl, const vshCmd *cmd)
{
virStorageVolInfo info;
virStorageVolPtr vol;
int ret = TRUE;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", NULL)))
return FALSE;
vshPrint(ctl, "%-15s %s\n", _("Name:"), virStorageVolGetName(vol));
if (virStorageVolGetInfo(vol, &info) == 0) {
double val;
const char *unit;
vshPrint(ctl, "%-15s %s\n", _("Type:"),
info.type == VIR_STORAGE_VOL_FILE ?
_("file") : _("block"));
val = prettyCapacity(info.capacity, &unit);
vshPrint(ctl, "%-15s %2.2lf %s\n", _("Capacity:"), val, unit);
val = prettyCapacity(info.allocation, &unit);
vshPrint(ctl, "%-15s %2.2lf %s\n", _("Allocation:"), val, unit);
} else {
ret = FALSE;
}
virStorageVolFree(vol);
return ret;
}
/*
* "vol-dumpxml" command
*/
static const vshCmdInfo info_vol_dumpxml[] = {
{"help", N_("vol information in XML")},
{"desc", N_("Output the vol information as an XML dump to stdout.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_vol_dumpxml[] = {
{"pool", VSH_OT_STRING, 0, N_("pool name or uuid")},
{"vol", VSH_OT_DATA, VSH_OFLAG_REQ, N_("vol name, key or path")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdVolDumpXML(vshControl *ctl, const vshCmd *cmd)
{
virStorageVolPtr vol;
int ret = TRUE;
char *dump;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", NULL)))
return FALSE;
dump = virStorageVolGetXMLDesc(vol, 0);
if (dump != NULL) {
printf("%s", dump);
VIR_FREE(dump);
} else {
ret = FALSE;
}
virStorageVolFree(vol);
return ret;
}
/*
* "vol-list" command
*/
static const vshCmdInfo info_vol_list[] = {
{"help", N_("list vols")},
{"desc", N_("Returns list of vols by pool.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_vol_list[] = {
{"pool", VSH_OT_DATA, VSH_OFLAG_REQ, N_("pool name or uuid")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdVolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
{
virStoragePoolPtr pool;
int maxactive = 0, i;
char **activeNames = NULL;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
if (!(pool = vshCommandOptPool(ctl, cmd, "pool", NULL)))
return FALSE;
maxactive = virStoragePoolNumOfVolumes(pool);
if (maxactive < 0) {
virStoragePoolFree(pool);
vshError(ctl, "%s", _("Failed to list active vols"));
return FALSE;
}
if (maxactive) {
activeNames = vshMalloc(ctl, sizeof(char *) * maxactive);
if ((maxactive = virStoragePoolListVolumes(pool, activeNames,
maxactive)) < 0) {
vshError(ctl, "%s", _("Failed to list active vols"));
VIR_FREE(activeNames);
virStoragePoolFree(pool);
return FALSE;
}
qsort(&activeNames[0], maxactive, sizeof(char *), namesorter);
}
vshPrintExtra(ctl, "%-20s %-40s\n", _("Name"), _("Path"));
vshPrintExtra(ctl, "-----------------------------------------\n");
for (i = 0; i < maxactive; i++) {
virStorageVolPtr vol = virStorageVolLookupByName(pool, activeNames[i]);
char *path;
/* this kind of work with vols is not atomic operation */
if (!vol) {
VIR_FREE(activeNames[i]);
continue;
}
if ((path = virStorageVolGetPath(vol)) == NULL) {
virStorageVolFree(vol);
continue;
}
vshPrint(ctl, "%-20s %-40s\n",
virStorageVolGetName(vol),
path);
VIR_FREE(path);
virStorageVolFree(vol);
VIR_FREE(activeNames[i]);
}
VIR_FREE(activeNames);
virStoragePoolFree(pool);
return TRUE;
}
/*
* "vol-name" command
*/
static const vshCmdInfo info_vol_name[] = {
{"help", N_("convert a vol UUID to vol name")},
{"desc", ""},
{NULL, NULL}
};
static const vshCmdOptDef opts_vol_name[] = {
{"vol", VSH_OT_DATA, VSH_OFLAG_REQ, N_("vol key or path")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdVolName(vshControl *ctl, const vshCmd *cmd)
{
virStorageVolPtr vol;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
if (!(vol = vshCommandOptVolBy(ctl, cmd, "vol", "pool", NULL,
VSH_BYUUID)))
return FALSE;
vshPrint(ctl, "%s\n", virStorageVolGetName(vol));
virStorageVolFree(vol);
return TRUE;
}
/*
* "vol-key" command
*/
static const vshCmdInfo info_vol_key[] = {
{"help", N_("convert a vol UUID to vol key")},
{"desc", ""},
{NULL, NULL}
};
static const vshCmdOptDef opts_vol_key[] = {
{"vol", VSH_OT_DATA, VSH_OFLAG_REQ, N_("vol uuid")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdVolKey(vshControl *ctl, const vshCmd *cmd)
{
virStorageVolPtr vol;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
if (!(vol = vshCommandOptVolBy(ctl, cmd, "vol", "pool", NULL,
VSH_BYUUID)))
return FALSE;
vshPrint(ctl, "%s\n", virStorageVolGetKey(vol));
virStorageVolFree(vol);
return TRUE;
}
/*
* "vol-path" command
*/
static const vshCmdInfo info_vol_path[] = {
{"help", N_("convert a vol UUID to vol path")},
{"desc", ""},
{NULL, NULL}
};
static const vshCmdOptDef opts_vol_path[] = {
{"pool", VSH_OT_STRING, 0, N_("pool name or uuid")},
{"vol", VSH_OT_DATA, VSH_OFLAG_REQ, N_("vol name or key")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdVolPath(vshControl *ctl, const vshCmd *cmd)
{
virStorageVolPtr vol;
char *name = NULL;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", &name))) {
return FALSE;
}
vshPrint(ctl, "%s\n", virStorageVolGetPath(vol));
virStorageVolFree(vol);
return TRUE;
}
/*
* "secret-define" command
*/
static const vshCmdInfo info_secret_define[] = {
{"help", N_("define or modify a secret from an XML file")},
{"desc", N_("Define or modify a secret.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_secret_define[] = {
{"file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("file containing secret attributes in XML")},
{NULL, 0, 0, NULL}
};
static int
cmdSecretDefine(vshControl *ctl, const vshCmd *cmd)
{
Fix UUID handling in secrets/storage encryption APIs Convert all the secret/storage encryption APIs / wire format to handle UUIDs in raw format instead of non-canonical printable format. Guarentees data format correctness. * docs/schemas/storageencryption.rng: Make UUID mandatory for a secret and validate fully * docs/schemas/secret.rng: Fully validate UUID * include/libvirt/libvirt.h, include/libvirt/libvirt.h.in, Add virSecretLookupByUUID and virSecretGetUUID. Make virSecretGetUUIDString follow normal API design pattern * python/generator.py: Skip generation of virSecretGetUUID, virSecretGetUUIDString and virSecretLookupByUUID * python/libvir.c, python/libvirt-python-api.xml: Manual impl of virSecretGetUUID,virSecretGetUUIDString and virSecretLookupByUUID * qemud/remote.c: s/virSecretLookupByUUIDString/virSecretLookupByUUID/ Fix get_nonnull_secret/make_nonnull_secret to use unsigned char * qemud/remote_protocol.x: Fix remote_nonnull_secret to use a remote_uuid instead of remote_nonnull_string for UUID field. Rename REMOTE_PROC_SECRET_LOOKUP_BY_UUID_STRING to REMOTE_PROC_SECRET_LOOKUP_BY_UUID_STRING and make it take an remote_uuid value * qemud/remote_dispatch_args.h, qemud/remote_dispatch_prototypes.h, qemud/remote_dispatch_ret.h, qemud/remote_dispatch_table.h, qemud/remote_protocol.c, qemud/remote_protocol.h: Re-generate * src/datatypes.h, src/datatypes.c: Store UUID in raw format instead of printable. Change virGetSecret to use raw format UUID * src/driver.h: Rename virDrvSecretLookupByUUIDString to virDrvSecretLookupByUUID and use raw format UUID * src/libvirt.c: Add virSecretLookupByUUID and virSecretGetUUID and re-implement virSecretLookupByUUIDString and virSecretGetUUIDString in terms of those * src/libvirt_public.syms: Add virSecretLookupByUUID and virSecretGetUUID * src/remote_internal.c: Rename remoteSecretLookupByUUIDString to remoteSecretLookupByUUID. Fix typo in args for remoteSecretDefineXML impl. Use raw UUID format for get_nonnull_secret and make_nonnull_secret * src/storage_encryption_conf.c, src/storage_encryption_conf.h: Storage UUID in raw format, and require it to be present in XML. Use UUID parser to validate. * secret_conf.h, secret_conf.c: Generate a UUID if none is provided. Storage UUID in raw format. * src/secret_driver.c: Adjust to deal with raw UUIDs. Save secrets in a filed with printable UUID, instead of base64 UUID. * src/virsh.c: Adjust for changed public API contract of virSecretGetUUIDString. * src/storage_Backend.c: DOn't undefine secret we just generated upon successful volume creation. Fix to handle raw UUIDs. Generate a non-clashing UUID * src/qemu_driver.c: Change to use lookupByUUID instead of lookupByUUIDString
2009-09-10 16:44:12 +00:00
char *from, *buffer;
virSecretPtr res;
Fix UUID handling in secrets/storage encryption APIs Convert all the secret/storage encryption APIs / wire format to handle UUIDs in raw format instead of non-canonical printable format. Guarentees data format correctness. * docs/schemas/storageencryption.rng: Make UUID mandatory for a secret and validate fully * docs/schemas/secret.rng: Fully validate UUID * include/libvirt/libvirt.h, include/libvirt/libvirt.h.in, Add virSecretLookupByUUID and virSecretGetUUID. Make virSecretGetUUIDString follow normal API design pattern * python/generator.py: Skip generation of virSecretGetUUID, virSecretGetUUIDString and virSecretLookupByUUID * python/libvir.c, python/libvirt-python-api.xml: Manual impl of virSecretGetUUID,virSecretGetUUIDString and virSecretLookupByUUID * qemud/remote.c: s/virSecretLookupByUUIDString/virSecretLookupByUUID/ Fix get_nonnull_secret/make_nonnull_secret to use unsigned char * qemud/remote_protocol.x: Fix remote_nonnull_secret to use a remote_uuid instead of remote_nonnull_string for UUID field. Rename REMOTE_PROC_SECRET_LOOKUP_BY_UUID_STRING to REMOTE_PROC_SECRET_LOOKUP_BY_UUID_STRING and make it take an remote_uuid value * qemud/remote_dispatch_args.h, qemud/remote_dispatch_prototypes.h, qemud/remote_dispatch_ret.h, qemud/remote_dispatch_table.h, qemud/remote_protocol.c, qemud/remote_protocol.h: Re-generate * src/datatypes.h, src/datatypes.c: Store UUID in raw format instead of printable. Change virGetSecret to use raw format UUID * src/driver.h: Rename virDrvSecretLookupByUUIDString to virDrvSecretLookupByUUID and use raw format UUID * src/libvirt.c: Add virSecretLookupByUUID and virSecretGetUUID and re-implement virSecretLookupByUUIDString and virSecretGetUUIDString in terms of those * src/libvirt_public.syms: Add virSecretLookupByUUID and virSecretGetUUID * src/remote_internal.c: Rename remoteSecretLookupByUUIDString to remoteSecretLookupByUUID. Fix typo in args for remoteSecretDefineXML impl. Use raw UUID format for get_nonnull_secret and make_nonnull_secret * src/storage_encryption_conf.c, src/storage_encryption_conf.h: Storage UUID in raw format, and require it to be present in XML. Use UUID parser to validate. * secret_conf.h, secret_conf.c: Generate a UUID if none is provided. Storage UUID in raw format. * src/secret_driver.c: Adjust to deal with raw UUIDs. Save secrets in a filed with printable UUID, instead of base64 UUID. * src/virsh.c: Adjust for changed public API contract of virSecretGetUUIDString. * src/storage_Backend.c: DOn't undefine secret we just generated upon successful volume creation. Fix to handle raw UUIDs. Generate a non-clashing UUID * src/qemu_driver.c: Change to use lookupByUUID instead of lookupByUUIDString
2009-09-10 16:44:12 +00:00
char uuid[VIR_UUID_STRING_BUFLEN];
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
from = vshCommandOptString(cmd, "file", NULL);
if (!from)
return FALSE;
if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0)
return FALSE;
res = virSecretDefineXML(ctl->conn, buffer, 0);
VIR_FREE(buffer);
if (res == NULL) {
vshError(ctl, _("Failed to set attributes from %s"), from);
return FALSE;
}
Fix UUID handling in secrets/storage encryption APIs Convert all the secret/storage encryption APIs / wire format to handle UUIDs in raw format instead of non-canonical printable format. Guarentees data format correctness. * docs/schemas/storageencryption.rng: Make UUID mandatory for a secret and validate fully * docs/schemas/secret.rng: Fully validate UUID * include/libvirt/libvirt.h, include/libvirt/libvirt.h.in, Add virSecretLookupByUUID and virSecretGetUUID. Make virSecretGetUUIDString follow normal API design pattern * python/generator.py: Skip generation of virSecretGetUUID, virSecretGetUUIDString and virSecretLookupByUUID * python/libvir.c, python/libvirt-python-api.xml: Manual impl of virSecretGetUUID,virSecretGetUUIDString and virSecretLookupByUUID * qemud/remote.c: s/virSecretLookupByUUIDString/virSecretLookupByUUID/ Fix get_nonnull_secret/make_nonnull_secret to use unsigned char * qemud/remote_protocol.x: Fix remote_nonnull_secret to use a remote_uuid instead of remote_nonnull_string for UUID field. Rename REMOTE_PROC_SECRET_LOOKUP_BY_UUID_STRING to REMOTE_PROC_SECRET_LOOKUP_BY_UUID_STRING and make it take an remote_uuid value * qemud/remote_dispatch_args.h, qemud/remote_dispatch_prototypes.h, qemud/remote_dispatch_ret.h, qemud/remote_dispatch_table.h, qemud/remote_protocol.c, qemud/remote_protocol.h: Re-generate * src/datatypes.h, src/datatypes.c: Store UUID in raw format instead of printable. Change virGetSecret to use raw format UUID * src/driver.h: Rename virDrvSecretLookupByUUIDString to virDrvSecretLookupByUUID and use raw format UUID * src/libvirt.c: Add virSecretLookupByUUID and virSecretGetUUID and re-implement virSecretLookupByUUIDString and virSecretGetUUIDString in terms of those * src/libvirt_public.syms: Add virSecretLookupByUUID and virSecretGetUUID * src/remote_internal.c: Rename remoteSecretLookupByUUIDString to remoteSecretLookupByUUID. Fix typo in args for remoteSecretDefineXML impl. Use raw UUID format for get_nonnull_secret and make_nonnull_secret * src/storage_encryption_conf.c, src/storage_encryption_conf.h: Storage UUID in raw format, and require it to be present in XML. Use UUID parser to validate. * secret_conf.h, secret_conf.c: Generate a UUID if none is provided. Storage UUID in raw format. * src/secret_driver.c: Adjust to deal with raw UUIDs. Save secrets in a filed with printable UUID, instead of base64 UUID. * src/virsh.c: Adjust for changed public API contract of virSecretGetUUIDString. * src/storage_Backend.c: DOn't undefine secret we just generated upon successful volume creation. Fix to handle raw UUIDs. Generate a non-clashing UUID * src/qemu_driver.c: Change to use lookupByUUID instead of lookupByUUIDString
2009-09-10 16:44:12 +00:00
if (virSecretGetUUIDString(res, &(uuid[0])) < 0) {
vshError(ctl, "%s", _("Failed to get UUID of created secret"));
virSecretFree(res);
return FALSE;
}
vshPrint(ctl, _("Secret %s created\n"), uuid);
virSecretFree(res);
return TRUE;
}
/*
* "secret-dumpxml" command
*/
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.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_secret_dumpxml[] = {
{"secret", VSH_OT_DATA, VSH_OFLAG_REQ, N_("secret UUID")},
{NULL, 0, 0, NULL}
};
static int
cmdSecretDumpXML(vshControl *ctl, const vshCmd *cmd)
{
virSecretPtr secret;
int ret = FALSE;
char *xml;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
secret = vshCommandOptSecret(ctl, cmd, NULL);
if (secret == NULL)
return FALSE;
xml = virSecretGetXMLDesc(secret, 0);
if (xml == NULL)
goto cleanup;
printf("%s", xml);
VIR_FREE(xml);
ret = TRUE;
cleanup:
virSecretFree(secret);
return ret;
}
/*
* "secret-set-value" command
*/
static const vshCmdInfo info_secret_set_value[] = {
{"help", N_("set a secret value")},
{"desc", N_("Set a secret value.")},
{NULL, NULL}
};
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")},
{NULL, 0, 0, NULL}
};
static int
cmdSecretSetValue(vshControl *ctl, const vshCmd *cmd)
{
virSecretPtr secret;
size_t value_size;
char *base64, *value;
int found, res, ret = FALSE;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
secret = vshCommandOptSecret(ctl, cmd, NULL);
if (secret == NULL)
return FALSE;
base64 = vshCommandOptString(cmd, "base64", &found);
if (!base64)
goto cleanup;
if (!base64_decode_alloc(base64, strlen(base64), &value, &value_size)) {
vshError(ctl, "%s", _("Invalid base64 data"));
goto cleanup;
}
if (value == NULL) {
vshError(ctl, "%s", _("Failed to allocate memory"));
return FALSE;
}
res = virSecretSetValue(secret, (unsigned char *)value, value_size, 0);
memset(value, 0, value_size);
VIR_FREE(value);
if (res != 0) {
vshError(ctl, "%s", _("Failed to set secret value"));
goto cleanup;
}
vshPrint(ctl, "%s", _("Secret value set\n"));
ret = TRUE;
cleanup:
virSecretFree(secret);
return ret;
}
/*
* "secret-get-value" command
*/
static const vshCmdInfo info_secret_get_value[] = {
{"help", N_("Output a secret value")},
{"desc", N_("Output a secret value to stdout.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_secret_get_value[] = {
{"secret", VSH_OT_DATA, VSH_OFLAG_REQ, N_("secret UUID")},
{NULL, 0, 0, NULL}
};
static int
cmdSecretGetValue(vshControl *ctl, const vshCmd *cmd)
{
virSecretPtr secret;
char *base64;
unsigned char *value;
size_t value_size;
int ret = FALSE;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
secret = vshCommandOptSecret(ctl, cmd, NULL);
if (secret == NULL)
return FALSE;
value = virSecretGetValue(secret, &value_size, 0);
if (value == NULL)
goto cleanup;
base64_encode_alloc((char *)value, value_size, &base64);
memset(value, 0, value_size);
VIR_FREE(value);
if (base64 == NULL) {
vshError(ctl, "%s", _("Failed to allocate memory"));
goto cleanup;
}
printf("%s", base64);
memset(base64, 0, strlen(base64));
VIR_FREE(base64);
ret = TRUE;
cleanup:
virSecretFree(secret);
return ret;
}
/*
* "secret-undefine" command
*/
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}
};
static int
cmdSecretUndefine(vshControl *ctl, const vshCmd *cmd)
{
virSecretPtr secret;
int ret = FALSE;
char *uuid;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
secret = vshCommandOptSecret(ctl, cmd, &uuid);
if (secret == NULL)
return FALSE;
if (virSecretUndefine(secret) < 0) {
vshError(ctl, _("Failed to delete secret %s"), uuid);
goto cleanup;
}
vshPrint(ctl, _("Secret %s deleted\n"), uuid);
ret = TRUE;
cleanup:
virSecretFree(secret);
return ret;
}
/*
* "secret-list" command
*/
static const vshCmdInfo info_secret_list[] = {
{"help", N_("list secrets")},
{"desc", N_("Returns a list of secrets")},
{NULL, NULL}
};
static int
cmdSecretList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
{
int maxuuids = 0, i;
char **uuids = NULL;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
maxuuids = virConnectNumOfSecrets(ctl->conn);
if (maxuuids < 0) {
vshError(ctl, "%s", _("Failed to list secrets"));
return FALSE;
}
uuids = vshMalloc(ctl, sizeof(*uuids) * maxuuids);
maxuuids = virConnectListSecrets(ctl->conn, uuids, maxuuids);
if (maxuuids < 0) {
vshError(ctl, "%s", _("Failed to list secrets"));
VIR_FREE(uuids);
return FALSE;
}
qsort(uuids, maxuuids, sizeof(char *), namesorter);
vshPrintExtra(ctl, "%-36s %s\n", _("UUID"), _("Usage"));
vshPrintExtra(ctl, "-----------------------------------------------------------\n");
for (i = 0; i < maxuuids; i++) {
virSecretPtr sec = virSecretLookupByUUIDString(ctl->conn, uuids[i]);
const char *usageType = NULL;
if (!sec) {
VIR_FREE(uuids[i]);
continue;
}
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]);
}
VIR_FREE(uuids);
return TRUE;
}
/*
* "version" command
*/
static const vshCmdInfo info_version[] = {
{"help", N_("show version")},
{"desc", N_("Display the system version information.")},
{NULL, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdVersion(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
{
unsigned long hvVersion;
const char *hvType;
unsigned long libVersion;
unsigned long includeVersion;
unsigned long apiVersion;
int ret;
unsigned int major;
unsigned int minor;
unsigned int rel;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
hvType = virConnectGetType(ctl->conn);
if (hvType == NULL) {
vshError(ctl, "%s", _("failed to get hypervisor type"));
return FALSE;
}
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);
ret = virGetVersion(&libVersion, hvType, &apiVersion);
if (ret < 0) {
vshError(ctl, "%s", _("failed to get the library version"));
return FALSE;
}
major = libVersion / 1000000;
libVersion %= 1000000;
minor = libVersion / 1000;
rel = libVersion % 1000;
vshPrint(ctl, _("Using library: libvir %d.%d.%d\n"),
major, minor, rel);
major = apiVersion / 1000000;
apiVersion %= 1000000;
minor = apiVersion / 1000;
rel = apiVersion % 1000;
vshPrint(ctl, _("Using API: %s %d.%d.%d\n"), hvType,
major, minor, rel);
ret = virConnectGetVersion(ctl->conn, &hvVersion);
if (ret < 0) {
vshError(ctl, "%s", _("failed to get the hypervisor version"));
return FALSE;
}
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;
vshPrint(ctl, _("Running hypervisor: %s %d.%d.%d\n"),
hvType, major, minor, rel);
}
return TRUE;
}
/*
* "nodedev-list" command
*/
static const vshCmdInfo info_node_list_devices[] = {
{"help", N_("enumerate devices on this host")},
{"desc", ""},
{NULL, NULL}
};
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")},
{NULL, 0, 0, NULL}
};
#define MAX_DEPTH 100
#define INDENT_SIZE 4
#define INDENT_BUFLEN ((MAX_DEPTH * INDENT_SIZE) + 1)
static void
cmdNodeListDevicesPrint(vshControl *ctl,
char **devices,
char **parents,
int num_devices,
int devid,
int lastdev,
unsigned int depth,
unsigned int indentIdx,
char *indentBuf)
{
int i;
int nextlastdev = -1;
/* Prepare indent for this device, but not if at root */
if (depth && depth < MAX_DEPTH) {
indentBuf[indentIdx] = '+';
indentBuf[indentIdx+1] = '-';
indentBuf[indentIdx+2] = ' ';
indentBuf[indentIdx+3] = '\0';
}
/* Print this device */
vshPrint(ctl, "%s", indentBuf);
vshPrint(ctl, "%s\n", devices[devid]);
/* Update indent to show '|' or ' ' for child devices */
if (depth && depth < MAX_DEPTH) {
if (devid == lastdev)
indentBuf[indentIdx] = ' ';
else
indentBuf[indentIdx] = '|';
indentBuf[indentIdx+1] = ' ';
indentIdx+=2;
}
/* Determine the index of the last child device */
for (i = 0 ; i < num_devices ; i++) {
if (parents[i] &&
STREQ(parents[i], devices[devid])) {
nextlastdev = i;
}
}
/* If there is a child device, then print another blank line */
if (nextlastdev != -1) {
vshPrint(ctl, "%s", indentBuf);
vshPrint(ctl, " |\n");
}
/* Finally print all children */
if (depth < MAX_DEPTH)
indentBuf[indentIdx] = ' ';
for (i = 0 ; i < num_devices ; i++) {
if (depth < MAX_DEPTH) {
indentBuf[indentIdx] = ' ';
indentBuf[indentIdx+1] = ' ';
}
if (parents[i] &&
STREQ(parents[i], devices[devid]))
cmdNodeListDevicesPrint(ctl, devices, parents,
num_devices, i, nextlastdev,
depth + 1, indentIdx + 2, indentBuf);
if (depth < MAX_DEPTH)
indentBuf[indentIdx] = '\0';
}
/* 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", indentBuf);
vshPrint(ctl, "\n");
}
}
static int
cmdNodeListDevices (vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
{
char *cap;
char **devices;
int found, num_devices, i;
int tree = vshCommandOptBool(cmd, "tree");
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
cap = vshCommandOptString(cmd, "cap", &found);
if (!found)
cap = NULL;
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;
}
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;
}
2008-11-21 12:46:39 +00:00
qsort(&devices[0], num_devices, sizeof(char*), namesorter);
if (tree) {
char indentBuf[INDENT_BUFLEN];
char **parents = vshMalloc(ctl, sizeof(char *) * num_devices);
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 ? strdup(parent) : NULL;
} else {
parents[i] = NULL;
}
virNodeDeviceFree(dev);
}
for (i = 0 ; i < num_devices ; i++) {
memset(indentBuf, '\0', sizeof indentBuf);
if (parents[i] == NULL)
cmdNodeListDevicesPrint(ctl,
devices,
parents,
num_devices,
i,
i,
0,
0,
indentBuf);
}
for (i = 0 ; i < num_devices ; i++) {
VIR_FREE(devices[i]);
VIR_FREE(parents[i]);
}
VIR_FREE(parents);
} else {
for (i = 0; i < num_devices; i++) {
vshPrint(ctl, "%s\n", devices[i]);
VIR_FREE(devices[i]);
}
}
VIR_FREE(devices);
return TRUE;
}
/*
* "nodedev-dumpxml" command
*/
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.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_node_device_dumpxml[] = {
{"device", VSH_OT_DATA, VSH_OFLAG_REQ, N_("device key")},
{NULL, 0, 0, NULL}
};
static int
cmdNodeDeviceDumpXML (vshControl *ctl, const vshCmd *cmd)
{
const char *name;
virNodeDevicePtr device;
char *xml;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
if (!(name = vshCommandOptString(cmd, "device", NULL)))
return FALSE;
if (!(device = virNodeDeviceLookupByName(ctl->conn, name))) {
vshError(ctl, "%s '%s'", _("Could not find matching device"), name);
return FALSE;
}
xml = virNodeDeviceGetXMLDesc(device, 0);
if (!xml) {
virNodeDeviceFree(device);
return FALSE;
}
vshPrint(ctl, "%s\n", xml);
VIR_FREE(xml);
virNodeDeviceFree(device);
return TRUE;
}
/*
* "nodedev-dettach" command
*/
static const vshCmdInfo info_node_device_dettach[] = {
{"help", N_("dettach node device from its device driver")},
{"desc", N_("Dettach node device from its device driver before assigning to a domain.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_node_device_dettach[] = {
{"device", VSH_OT_DATA, VSH_OFLAG_REQ, N_("device key")},
{NULL, 0, 0, NULL}
};
static int
cmdNodeDeviceDettach (vshControl *ctl, const vshCmd *cmd)
{
const char *name;
virNodeDevicePtr device;
int ret = TRUE;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
if (!(name = vshCommandOptString(cmd, "device", NULL)))
return FALSE;
if (!(device = virNodeDeviceLookupByName(ctl->conn, name))) {
vshError(ctl, "%s '%s'", _("Could not find matching device"), name);
return FALSE;
}
if (virNodeDeviceDettach(device) == 0) {
vshPrint(ctl, _("Device %s dettached\n"), name);
} else {
vshError(ctl, _("Failed to dettach device %s"), name);
ret = FALSE;
}
virNodeDeviceFree(device);
return ret;
}
/*
* "nodedev-reattach" command
*/
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.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_node_device_reattach[] = {
{"device", VSH_OT_DATA, VSH_OFLAG_REQ, N_("device key")},
{NULL, 0, 0, NULL}
};
static int
cmdNodeDeviceReAttach (vshControl *ctl, const vshCmd *cmd)
{
const char *name;
virNodeDevicePtr device;
int ret = TRUE;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
if (!(name = vshCommandOptString(cmd, "device", NULL)))
return FALSE;
if (!(device = virNodeDeviceLookupByName(ctl->conn, name))) {
vshError(ctl, "%s '%s'", _("Could not find matching device"), name);
return FALSE;
}
if (virNodeDeviceReAttach(device) == 0) {
vshPrint(ctl, _("Device %s re-attached\n"), name);
} else {
vshError(ctl, _("Failed to re-attach device %s"), name);
ret = FALSE;
}
virNodeDeviceFree(device);
return ret;
}
/*
* "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}
};
static const vshCmdOptDef opts_node_device_reset[] = {
{"device", VSH_OT_DATA, VSH_OFLAG_REQ, N_("device key")},
{NULL, 0, 0, NULL}
};
static int
cmdNodeDeviceReset (vshControl *ctl, const vshCmd *cmd)
{
const char *name;
virNodeDevicePtr device;
int ret = TRUE;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
if (!(name = vshCommandOptString(cmd, "device", NULL)))
return FALSE;
if (!(device = virNodeDeviceLookupByName(ctl->conn, name))) {
vshError(ctl, "%s '%s'", _("Could not find matching device"), name);
return FALSE;
}
if (virNodeDeviceReset(device) == 0) {
vshPrint(ctl, _("Device %s reset\n"), name);
} else {
vshError(ctl, _("Failed to reset device %s"), name);
ret = FALSE;
}
virNodeDeviceFree(device);
return ret;
}
/*
* "hostkey" command
*/
static const vshCmdInfo info_hostname[] = {
{"help", N_("print the hypervisor hostname")},
{"desc", ""},
{NULL, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdHostname (vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
{
char *hostname;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
hostname = virConnectGetHostname (ctl->conn);
if (hostname == NULL) {
vshError(ctl, "%s", _("failed to get hostname"));
return FALSE;
}
vshPrint (ctl, "%s\n", hostname);
VIR_FREE(hostname);
return TRUE;
}
/*
* "uri" command
*/
static const vshCmdInfo info_uri[] = {
{"help", N_("print the hypervisor canonical URI")},
{"desc", ""},
{NULL, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdURI (vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
{
char *uri;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
uri = virConnectGetURI (ctl->conn);
if (uri == NULL) {
vshError(ctl, "%s", _("failed to get URI"));
return FALSE;
}
vshPrint (ctl, "%s\n", uri);
VIR_FREE(uri);
return TRUE;
}
/*
* "vncdisplay" command
*/
static const vshCmdInfo info_vncdisplay[] = {
{"help", N_("vnc display")},
{"desc", N_("Output the IP address and port number for the VNC display.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_vncdisplay[] = {
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdVNCDisplay(vshControl *ctl, const vshCmd *cmd)
{
xmlDocPtr xml = NULL;
xmlXPathObjectPtr obj = NULL;
xmlXPathContextPtr ctxt = NULL;
virDomainPtr dom;
int ret = FALSE;
int port = 0;
char *doc;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
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 10:26:54 +00:00
if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
return FALSE;
doc = virDomainGetXMLDesc(dom, 0);
if (!doc)
goto cleanup;
xml = xmlReadDoc((const xmlChar *) doc, "domain.xml", NULL,
XML_PARSE_NOENT | XML_PARSE_NONET |
XML_PARSE_NOWARNING);
VIR_FREE(doc);
if (!xml)
goto cleanup;
ctxt = xmlXPathNewContext(xml);
if (!ctxt)
goto cleanup;
obj = xmlXPathEval(BAD_CAST "string(/domain/devices/graphics[@type='vnc']/@port)", ctxt);
if ((obj == NULL) || (obj->type != XPATH_STRING) ||
(obj->stringval == NULL) || (obj->stringval[0] == 0)) {
goto cleanup;
}
if (virStrToLong_i((const char *)obj->stringval, NULL, 10, &port) || port < 0)
goto cleanup;
xmlXPathFreeObject(obj);
obj = xmlXPathEval(BAD_CAST "string(/domain/devices/graphics[@type='vnc']/@listen)", ctxt);
if ((obj == NULL) || (obj->type != XPATH_STRING) ||
(obj->stringval == NULL) || (obj->stringval[0] == 0) ||
STREQ((const char*)obj->stringval, "0.0.0.0")) {
vshPrint(ctl, ":%d\n", port-5900);
} else {
vshPrint(ctl, "%s:%d\n", (const char *)obj->stringval, port-5900);
}
xmlXPathFreeObject(obj);
obj = NULL;
ret = TRUE;
cleanup:
xmlXPathFreeObject(obj);
xmlXPathFreeContext(ctxt);
if (xml)
xmlFreeDoc(xml);
virDomainFree(dom);
return ret;
}
/*
* "ttyconsole" command
*/
static const vshCmdInfo info_ttyconsole[] = {
{"help", N_("tty console")},
{"desc", N_("Output the device for the TTY console.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_ttyconsole[] = {
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdTTYConsole(vshControl *ctl, const vshCmd *cmd)
{
xmlDocPtr xml = NULL;
xmlXPathObjectPtr obj = NULL;
xmlXPathContextPtr ctxt = NULL;
virDomainPtr dom;
int ret = FALSE;
char *doc;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
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 10:26:54 +00:00
if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
return FALSE;
doc = virDomainGetXMLDesc(dom, 0);
if (!doc)
goto cleanup;
xml = xmlReadDoc((const xmlChar *) doc, "domain.xml", NULL,
XML_PARSE_NOENT | XML_PARSE_NONET |
XML_PARSE_NOWARNING);
VIR_FREE(doc);
if (!xml)
goto cleanup;
ctxt = xmlXPathNewContext(xml);
if (!ctxt)
goto cleanup;
obj = xmlXPathEval(BAD_CAST "string(/domain/devices/console/@tty)", ctxt);
if ((obj == NULL) || (obj->type != XPATH_STRING) ||
(obj->stringval == NULL) || (obj->stringval[0] == 0)) {
goto cleanup;
}
vshPrint(ctl, "%s\n", (const char *)obj->stringval);
ret = TRUE;
cleanup:
xmlXPathFreeObject(obj);
xmlXPathFreeContext(ctxt);
if (xml)
xmlFreeDoc(xml);
virDomainFree(dom);
return ret;
}
/*
* "attach-device" command
*/
static const vshCmdInfo info_attach_device[] = {
{"help", N_("attach device from an XML file")},
{"desc", N_("Attach device from an XML <file>.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_attach_device[] = {
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
{"file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("XML file")},
{"persistent", VSH_OT_BOOL, 0, N_("persist device attachment")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdAttachDevice(vshControl *ctl, const vshCmd *cmd)
{
virDomainPtr dom;
char *from;
char *buffer;
int ret = TRUE;
int found;
unsigned int flags;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
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 10:26:54 +00:00
if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
return FALSE;
from = vshCommandOptString(cmd, "file", &found);
if (!found) {
vshError(ctl, "%s", _("attach-device: Missing <file> option"));
virDomainFree(dom);
return FALSE;
}
if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) {
virshReportError(ctl);
virDomainFree(dom);
2008-01-21 15:27:14 +00:00
return FALSE;
}
if (vshCommandOptBool(cmd, "persistent")) {
flags = VIR_DOMAIN_DEVICE_MODIFY_CONFIG;
if (virDomainIsActive(dom) == 1)
flags |= VIR_DOMAIN_DEVICE_MODIFY_LIVE;
ret = virDomainAttachDeviceFlags(dom, buffer, flags);
} else {
ret = virDomainAttachDevice(dom, buffer);
}
VIR_FREE(buffer);
if (ret < 0) {
vshError(ctl, _("Failed to attach device from %s"), from);
virDomainFree(dom);
return FALSE;
} else {
avoid many format string warnings Building with --disable-nls exposed many new warnings like these: virsh.c:4952: warning: format not a string literal and no format ... util.c:163: warning: format not a string literal and no format arguments All but one of the following changes add a "%s" argument before the offending _(...) argument. This was the only manual change: * src/lxc_driver.c (lxcVersion): Use %s and strerror(errno) rather than %m, to avoid a warning from gcc -Wformat-security. Add "%s" before each warned about format-string-with-no-%-directive: * src/domain_conf.c (virDomainHostdevSubsysUsbDefParseXML) (virDomainDefParseString, virDomainDefParseFile): * src/hash.c (virGetConnect, __virGetDomain, virReleaseDomain) (__virGetNetwork, virReleaseNetwork, __virGetStoragePool) (virReleaseStoragePool, __virGetStorageVol, virReleaseStorageVol): * src/lxc_container.c (lxcContainerChild): * src/lxc_driver.c (lxcDomainDefine, lxcDomainUndefine) (lxcDomainGetInfo, lxcGetOSType, lxcDomainDumpXML) (lxcSetupInterfaces, lxcDomainStart, lxcDomainCreateAndStart) (lxcVersion, lxcGetSchedulerParameters): * src/network_conf.c (virNetworkDefParseString) (virNetworkDefParseFile): * src/openvz_conf.c (openvzReadNetworkConf, openvzLoadDomains): * src/openvz_driver.c (openvzDomainDefineCmd) (openvzDomainGetInfo, openvzDomainDumpXML, openvzDomainShutdown) (openvzDomainReboot, ADD_ARG_LIT, openvzDomainDefineXML) (openvzDomainCreateXML, openvzDomainCreate, openvzDomainUndefine) (openvzDomainSetAutostart, openvzDomainGetAutostart) (openvzDomainSetVcpus): * src/qemu_driver.c (qemudDomainBlockPeek, qemudDomainMemoryPeek): * src/remote_internal.c (remoteDomainBlockPeek) (remoteDomainMemoryPeek, remoteAuthPolkit): * src/sexpr.c (sexpr_new, _string2sexpr): * src/storage_backend_disk.c (virStorageBackendDiskMakeDataVol) (virStorageBackendDiskCreateVol): * src/storage_backend_fs.c (virStorageBackendFileSystemNetFindPoolSources): * src/storage_backend_logical.c (virStorageBackendLogicalFindLVs) (virStorageBackendLogicalFindPoolSources): * src/test.c (testOpenDefault, testOpenFromFile, testOpen) (testGetDomainInfo, testDomainRestore) (testNodeGetCellsFreeMemory): * src/util.c (virExec): * src/virsh.c (cmdAttachDevice, cmdDetachDevice) (cmdAttachInterface, cmdDetachInterface, cmdAttachDisk) (cmdDetachDisk, cmdEdit): * src/xend_internal.c (do_connect, wr_sync, xend_op_ext) (urlencode, xenDaemonDomainCreateXML) (xenDaemonDomainLookupByName_ids, xenDaemonDomainLookupByID) (xenDaemonParseSxprOS, xend_parse_sexp_desc_char) (xenDaemonParseSxprChar, xenDaemonParseSxprDisks) (xenDaemonParseSxpr, sexpr_to_xend_topology, sexpr_to_domain) (xenDaemonDomainFetch, xenDaemonDomainGetAutostart) (xenDaemonDomainSetAutostart, xenDaemonDomainMigratePerform) (xenDaemonDomainDefineXML, xenDaemonGetSchedulerType) (xenDaemonGetSchedulerParameters) (xenDaemonSetSchedulerParameters, xenDaemonDomainBlockPeek) (xenDaemonFormatSxprChr, virDomainXMLDevID): * src/xm_internal.c (xenXMConfigCacheRefresh, xenXMDomainPinVcpu) (xenXMDomainCreate, xenXMDomainDefineXML) (xenXMDomainAttachDevice, xenXMDomainDetachDevice): * src/xml.c (virXPathString, virXPathNumber, virXPathLong) (virXPathULong, virXPathBoolean, virXPathNode, virXPathNodeSet): * src/xs_internal.c (xenStoreOpen):
2008-10-13 16:46:28 +00:00
vshPrint(ctl, "%s", _("Device attached successfully\n"));
}
virDomainFree(dom);
return TRUE;
}
/*
* "detach-device" command
*/
static const vshCmdInfo info_detach_device[] = {
{"help", N_("detach device from an XML file")},
{"desc", N_("Detach device from an XML <file>")},
{NULL, NULL}
};
static const vshCmdOptDef opts_detach_device[] = {
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
{"file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("XML file")},
{"persistent", VSH_OT_BOOL, 0, N_("persist device detachment")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdDetachDevice(vshControl *ctl, const vshCmd *cmd)
{
virDomainPtr dom;
char *from;
char *buffer;
int ret = TRUE;
int found;
unsigned int flags;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
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 10:26:54 +00:00
if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
return FALSE;
from = vshCommandOptString(cmd, "file", &found);
if (!found) {
vshError(ctl, "%s", _("detach-device: Missing <file> option"));
virDomainFree(dom);
return FALSE;
}
if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) {
virshReportError(ctl);
virDomainFree(dom);
2008-01-21 15:27:14 +00:00
return FALSE;
}
if (vshCommandOptBool(cmd, "persistent")) {
flags = VIR_DOMAIN_DEVICE_MODIFY_CONFIG;
if (virDomainIsActive(dom) == 1)
flags |= VIR_DOMAIN_DEVICE_MODIFY_LIVE;
ret = virDomainDetachDeviceFlags(dom, buffer, flags);
} else {
ret = virDomainDetachDevice(dom, buffer);
}
VIR_FREE(buffer);
if (ret < 0) {
vshError(ctl, _("Failed to detach device from %s"), from);
virDomainFree(dom);
return FALSE;
} else {
avoid many format string warnings Building with --disable-nls exposed many new warnings like these: virsh.c:4952: warning: format not a string literal and no format ... util.c:163: warning: format not a string literal and no format arguments All but one of the following changes add a "%s" argument before the offending _(...) argument. This was the only manual change: * src/lxc_driver.c (lxcVersion): Use %s and strerror(errno) rather than %m, to avoid a warning from gcc -Wformat-security. Add "%s" before each warned about format-string-with-no-%-directive: * src/domain_conf.c (virDomainHostdevSubsysUsbDefParseXML) (virDomainDefParseString, virDomainDefParseFile): * src/hash.c (virGetConnect, __virGetDomain, virReleaseDomain) (__virGetNetwork, virReleaseNetwork, __virGetStoragePool) (virReleaseStoragePool, __virGetStorageVol, virReleaseStorageVol): * src/lxc_container.c (lxcContainerChild): * src/lxc_driver.c (lxcDomainDefine, lxcDomainUndefine) (lxcDomainGetInfo, lxcGetOSType, lxcDomainDumpXML) (lxcSetupInterfaces, lxcDomainStart, lxcDomainCreateAndStart) (lxcVersion, lxcGetSchedulerParameters): * src/network_conf.c (virNetworkDefParseString) (virNetworkDefParseFile): * src/openvz_conf.c (openvzReadNetworkConf, openvzLoadDomains): * src/openvz_driver.c (openvzDomainDefineCmd) (openvzDomainGetInfo, openvzDomainDumpXML, openvzDomainShutdown) (openvzDomainReboot, ADD_ARG_LIT, openvzDomainDefineXML) (openvzDomainCreateXML, openvzDomainCreate, openvzDomainUndefine) (openvzDomainSetAutostart, openvzDomainGetAutostart) (openvzDomainSetVcpus): * src/qemu_driver.c (qemudDomainBlockPeek, qemudDomainMemoryPeek): * src/remote_internal.c (remoteDomainBlockPeek) (remoteDomainMemoryPeek, remoteAuthPolkit): * src/sexpr.c (sexpr_new, _string2sexpr): * src/storage_backend_disk.c (virStorageBackendDiskMakeDataVol) (virStorageBackendDiskCreateVol): * src/storage_backend_fs.c (virStorageBackendFileSystemNetFindPoolSources): * src/storage_backend_logical.c (virStorageBackendLogicalFindLVs) (virStorageBackendLogicalFindPoolSources): * src/test.c (testOpenDefault, testOpenFromFile, testOpen) (testGetDomainInfo, testDomainRestore) (testNodeGetCellsFreeMemory): * src/util.c (virExec): * src/virsh.c (cmdAttachDevice, cmdDetachDevice) (cmdAttachInterface, cmdDetachInterface, cmdAttachDisk) (cmdDetachDisk, cmdEdit): * src/xend_internal.c (do_connect, wr_sync, xend_op_ext) (urlencode, xenDaemonDomainCreateXML) (xenDaemonDomainLookupByName_ids, xenDaemonDomainLookupByID) (xenDaemonParseSxprOS, xend_parse_sexp_desc_char) (xenDaemonParseSxprChar, xenDaemonParseSxprDisks) (xenDaemonParseSxpr, sexpr_to_xend_topology, sexpr_to_domain) (xenDaemonDomainFetch, xenDaemonDomainGetAutostart) (xenDaemonDomainSetAutostart, xenDaemonDomainMigratePerform) (xenDaemonDomainDefineXML, xenDaemonGetSchedulerType) (xenDaemonGetSchedulerParameters) (xenDaemonSetSchedulerParameters, xenDaemonDomainBlockPeek) (xenDaemonFormatSxprChr, virDomainXMLDevID): * src/xm_internal.c (xenXMConfigCacheRefresh, xenXMDomainPinVcpu) (xenXMDomainCreate, xenXMDomainDefineXML) (xenXMDomainAttachDevice, xenXMDomainDetachDevice): * src/xml.c (virXPathString, virXPathNumber, virXPathLong) (virXPathULong, virXPathBoolean, virXPathNode, virXPathNodeSet): * src/xs_internal.c (xenStoreOpen):
2008-10-13 16:46:28 +00:00
vshPrint(ctl, "%s", _("Device detached successfully\n"));
}
virDomainFree(dom);
return TRUE;
}
/*
* "update-device" command
*/
static const vshCmdInfo info_update_device[] = {
{"help", N_("update device from an XML file")},
{"desc", N_("Update device from an XML <file>.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_update_device[] = {
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
{"file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("XML file")},
{"persistent", VSH_OT_BOOL, 0, N_("persist device update")},
{NULL, 0, 0, NULL}
};
static int
cmdUpdateDevice(vshControl *ctl, const vshCmd *cmd)
{
virDomainPtr dom;
char *from;
char *buffer;
int ret = TRUE;
int found;
unsigned int flags;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
return FALSE;
from = vshCommandOptString(cmd, "file", &found);
if (!found) {
vshError(ctl, "%s", _("update-device: Missing <file> option"));
virDomainFree(dom);
return FALSE;
}
if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) {
virshReportError(ctl);
virDomainFree(dom);
return FALSE;
}
if (vshCommandOptBool(cmd, "persistent")) {
flags = VIR_DOMAIN_DEVICE_MODIFY_CONFIG;
if (virDomainIsActive(dom) == 1)
flags |= VIR_DOMAIN_DEVICE_MODIFY_LIVE;
} else {
flags = VIR_DOMAIN_DEVICE_MODIFY_LIVE;
}
ret = virDomainUpdateDeviceFlags(dom, buffer, flags);
VIR_FREE(buffer);
if (ret < 0) {
vshError(ctl, _("Failed to update device from %s"), from);
virDomainFree(dom);
return FALSE;
} else {
vshPrint(ctl, "%s", _("Device updated successfully\n"));
}
virDomainFree(dom);
return TRUE;
}
/*
* "attach-interface" command
*/
static const vshCmdInfo info_attach_interface[] = {
{"help", N_("attach network interface")},
{"desc", N_("Attach new network interface.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_attach_interface[] = {
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
{"type", VSH_OT_DATA, VSH_OFLAG_REQ, N_("network interface type")},
{"source", VSH_OT_DATA, VSH_OFLAG_REQ, N_("source of network interface")},
{"target", VSH_OT_DATA, 0, N_("target network name")},
{"mac", VSH_OT_DATA, 0, N_("MAC address")},
{"script", VSH_OT_DATA, 0, N_("script used to bridge network interface")},
{"persistent", VSH_OT_BOOL, 0, N_("persist interface attachment")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdAttachInterface(vshControl *ctl, const vshCmd *cmd)
{
virDomainPtr dom = NULL;
char *mac, *target, *script, *type, *source;
int typ, ret = FALSE;
char *buf = NULL, *tmp = NULL;
unsigned int flags;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
goto cleanup;
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 10:26:54 +00:00
if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
goto cleanup;
if (!(type = vshCommandOptString(cmd, "type", NULL)))
goto cleanup;
source = vshCommandOptString(cmd, "source", NULL);
target = vshCommandOptString(cmd, "target", NULL);
mac = vshCommandOptString(cmd, "mac", NULL);
script = vshCommandOptString(cmd, "script", NULL);
/* check interface type */
if (STREQ(type, "network")) {
typ = 1;
} else if (STREQ(type, "bridge")) {
typ = 2;
} else {
vshError(ctl, _("No support %s in command 'attach-interface'"), type);
goto cleanup;
}
/* Make XML of interface */
tmp = vshMalloc(ctl, 1);
if (!tmp) goto cleanup;
buf = vshMalloc(ctl, strlen(type) + 25);
if (!buf) goto cleanup;
sprintf(buf, " <interface type='%s'>\n" , type);
tmp = vshRealloc(ctl, tmp, strlen(source) + 28);
if (!tmp) goto cleanup;
if (typ == 1) {
sprintf(tmp, " <source network='%s'/>\n", source);
} else if (typ == 2) {
sprintf(tmp, " <source bridge='%s'/>\n", source);
}
buf = vshRealloc(ctl, buf, strlen(buf) + strlen(tmp) + 1);
if (!buf) goto cleanup;
strcat(buf, tmp);
if (target != NULL) {
tmp = vshRealloc(ctl, tmp, strlen(target) + 24);
if (!tmp) goto cleanup;
sprintf(tmp, " <target dev='%s'/>\n", target);
buf = vshRealloc(ctl, buf, strlen(buf) + strlen(tmp) + 1);
if (!buf) goto cleanup;
strcat(buf, tmp);
}
if (mac != NULL) {
tmp = vshRealloc(ctl, tmp, strlen(mac) + 25);
if (!tmp) goto cleanup;
sprintf(tmp, " <mac address='%s'/>\n", mac);
buf = vshRealloc(ctl, buf, strlen(buf) + strlen(tmp) + 1);
if (!buf) goto cleanup;
strcat(buf, tmp);
}
if (script != NULL) {
tmp = vshRealloc(ctl, tmp, strlen(script) + 25);
if (!tmp) goto cleanup;
sprintf(tmp, " <script path='%s'/>\n", script);
buf = vshRealloc(ctl, buf, strlen(buf) + strlen(tmp) + 1);
if (!buf) goto cleanup;
strcat(buf, tmp);
}
buf = vshRealloc(ctl, buf, strlen(buf) + 19);
if (!buf) goto cleanup;
strcat(buf, " </interface>\n");
if (vshCommandOptBool(cmd, "persistent")) {
flags = VIR_DOMAIN_DEVICE_MODIFY_CONFIG;
if (virDomainIsActive(dom) == 1)
flags |= VIR_DOMAIN_DEVICE_MODIFY_LIVE;
ret = virDomainAttachDeviceFlags(dom, buf, flags);
} else {
ret = virDomainAttachDevice(dom, buf);
}
if (ret != 0) {
vshError(ctl, "%s", _("Failed to attach interface"));
ret = FALSE;
} else {
vshPrint(ctl, "%s", _("Interface attached successfully\n"));
ret = TRUE;
}
cleanup:
if (dom)
virDomainFree(dom);
VIR_FREE(buf);
VIR_FREE(tmp);
return ret;
}
/*
* "detach-interface" command
*/
static const vshCmdInfo info_detach_interface[] = {
{"help", N_("detach network interface")},
{"desc", N_("Detach network interface.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_detach_interface[] = {
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
{"type", VSH_OT_DATA, VSH_OFLAG_REQ, N_("network interface type")},
{"mac", VSH_OT_STRING, 0, N_("MAC address")},
{"persistent", VSH_OT_BOOL, 0, N_("persist interface detachment")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdDetachInterface(vshControl *ctl, const vshCmd *cmd)
{
virDomainPtr dom = NULL;
xmlDocPtr xml = NULL;
xmlXPathObjectPtr obj=NULL;
xmlXPathContextPtr ctxt = NULL;
xmlNodePtr cur = NULL;
xmlChar *tmp_mac = NULL;
xmlBufferPtr xml_buf = NULL;
char *doc, *mac =NULL, *type;
char buf[64];
int i = 0, diff_mac, ret = FALSE;
unsigned int flags;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
goto cleanup;
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 10:26:54 +00:00
if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
goto cleanup;
if (!(type = vshCommandOptString(cmd, "type", NULL)))
goto cleanup;
mac = vshCommandOptString(cmd, "mac", NULL);
doc = virDomainGetXMLDesc(dom, 0);
if (!doc)
goto cleanup;
xml = xmlReadDoc((const xmlChar *) doc, "domain.xml", NULL,
XML_PARSE_NOENT | XML_PARSE_NONET |
XML_PARSE_NOWARNING);
VIR_FREE(doc);
if (!xml) {
vshError(ctl, "%s", _("Failed to get interface information"));
goto cleanup;
}
ctxt = xmlXPathNewContext(xml);
if (!ctxt) {
vshError(ctl, "%s", _("Failed to get interface information"));
goto cleanup;
}
sprintf(buf, "/domain/devices/interface[@type='%s']", type);
obj = xmlXPathEval(BAD_CAST buf, ctxt);
if ((obj == NULL) || (obj->type != XPATH_NODESET) ||
(obj->nodesetval == NULL) || (obj->nodesetval->nodeNr == 0)) {
vshError(ctl, _("No found interface whose type is %s"), type);
goto cleanup;
}
if (!mac)
goto hit;
/* search mac */
for (; i < obj->nodesetval->nodeNr; i++) {
cur = obj->nodesetval->nodeTab[i]->children;
while (cur != NULL) {
if (cur->type == XML_ELEMENT_NODE && xmlStrEqual(cur->name, BAD_CAST "mac")) {
tmp_mac = xmlGetProp(cur, BAD_CAST "address");
diff_mac = virMacAddrCompare ((char *) tmp_mac, mac);
xmlFree(tmp_mac);
if (!diff_mac) {
goto hit;
}
}
cur = cur->next;
}
}
vshError(ctl, _("No found interface whose MAC address is %s"), mac);
goto cleanup;
hit:
xml_buf = xmlBufferCreate();
if (!xml_buf) {
vshError(ctl, "%s", _("Failed to allocate memory"));
goto cleanup;
}
if(xmlNodeDump(xml_buf, xml, obj->nodesetval->nodeTab[i], 0, 0) < 0){
vshError(ctl, "%s", _("Failed to create XML"));
goto cleanup;
}
if (vshCommandOptBool(cmd, "persistent")) {
flags = VIR_DOMAIN_DEVICE_MODIFY_CONFIG;
if (virDomainIsActive(dom) == 1)
flags |= VIR_DOMAIN_DEVICE_MODIFY_LIVE;
ret = virDomainDetachDeviceFlags(dom,
(char *)xmlBufferContent(xml_buf),
flags);
} else {
ret = virDomainDetachDevice(dom, (char *)xmlBufferContent(xml_buf));
}
if (ret != 0) {
vshError(ctl, "%s", _("Failed to detach interface"));
ret = FALSE;
} else {
avoid many format string warnings Building with --disable-nls exposed many new warnings like these: virsh.c:4952: warning: format not a string literal and no format ... util.c:163: warning: format not a string literal and no format arguments All but one of the following changes add a "%s" argument before the offending _(...) argument. This was the only manual change: * src/lxc_driver.c (lxcVersion): Use %s and strerror(errno) rather than %m, to avoid a warning from gcc -Wformat-security. Add "%s" before each warned about format-string-with-no-%-directive: * src/domain_conf.c (virDomainHostdevSubsysUsbDefParseXML) (virDomainDefParseString, virDomainDefParseFile): * src/hash.c (virGetConnect, __virGetDomain, virReleaseDomain) (__virGetNetwork, virReleaseNetwork, __virGetStoragePool) (virReleaseStoragePool, __virGetStorageVol, virReleaseStorageVol): * src/lxc_container.c (lxcContainerChild): * src/lxc_driver.c (lxcDomainDefine, lxcDomainUndefine) (lxcDomainGetInfo, lxcGetOSType, lxcDomainDumpXML) (lxcSetupInterfaces, lxcDomainStart, lxcDomainCreateAndStart) (lxcVersion, lxcGetSchedulerParameters): * src/network_conf.c (virNetworkDefParseString) (virNetworkDefParseFile): * src/openvz_conf.c (openvzReadNetworkConf, openvzLoadDomains): * src/openvz_driver.c (openvzDomainDefineCmd) (openvzDomainGetInfo, openvzDomainDumpXML, openvzDomainShutdown) (openvzDomainReboot, ADD_ARG_LIT, openvzDomainDefineXML) (openvzDomainCreateXML, openvzDomainCreate, openvzDomainUndefine) (openvzDomainSetAutostart, openvzDomainGetAutostart) (openvzDomainSetVcpus): * src/qemu_driver.c (qemudDomainBlockPeek, qemudDomainMemoryPeek): * src/remote_internal.c (remoteDomainBlockPeek) (remoteDomainMemoryPeek, remoteAuthPolkit): * src/sexpr.c (sexpr_new, _string2sexpr): * src/storage_backend_disk.c (virStorageBackendDiskMakeDataVol) (virStorageBackendDiskCreateVol): * src/storage_backend_fs.c (virStorageBackendFileSystemNetFindPoolSources): * src/storage_backend_logical.c (virStorageBackendLogicalFindLVs) (virStorageBackendLogicalFindPoolSources): * src/test.c (testOpenDefault, testOpenFromFile, testOpen) (testGetDomainInfo, testDomainRestore) (testNodeGetCellsFreeMemory): * src/util.c (virExec): * src/virsh.c (cmdAttachDevice, cmdDetachDevice) (cmdAttachInterface, cmdDetachInterface, cmdAttachDisk) (cmdDetachDisk, cmdEdit): * src/xend_internal.c (do_connect, wr_sync, xend_op_ext) (urlencode, xenDaemonDomainCreateXML) (xenDaemonDomainLookupByName_ids, xenDaemonDomainLookupByID) (xenDaemonParseSxprOS, xend_parse_sexp_desc_char) (xenDaemonParseSxprChar, xenDaemonParseSxprDisks) (xenDaemonParseSxpr, sexpr_to_xend_topology, sexpr_to_domain) (xenDaemonDomainFetch, xenDaemonDomainGetAutostart) (xenDaemonDomainSetAutostart, xenDaemonDomainMigratePerform) (xenDaemonDomainDefineXML, xenDaemonGetSchedulerType) (xenDaemonGetSchedulerParameters) (xenDaemonSetSchedulerParameters, xenDaemonDomainBlockPeek) (xenDaemonFormatSxprChr, virDomainXMLDevID): * src/xm_internal.c (xenXMConfigCacheRefresh, xenXMDomainPinVcpu) (xenXMDomainCreate, xenXMDomainDefineXML) (xenXMDomainAttachDevice, xenXMDomainDetachDevice): * src/xml.c (virXPathString, virXPathNumber, virXPathLong) (virXPathULong, virXPathBoolean, virXPathNode, virXPathNodeSet): * src/xs_internal.c (xenStoreOpen):
2008-10-13 16:46:28 +00:00
vshPrint(ctl, "%s", _("Interface detached successfully\n"));
ret = TRUE;
}
cleanup:
if (dom)
virDomainFree(dom);
xmlXPathFreeObject(obj);
xmlXPathFreeContext(ctxt);
if (xml)
xmlFreeDoc(xml);
if (xml_buf)
xmlBufferFree(xml_buf);
return ret;
}
/*
* "attach-disk" command
*/
static const vshCmdInfo info_attach_disk[] = {
{"help", N_("attach disk device")},
{"desc", N_("Attach new disk device.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_attach_disk[] = {
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
{"source", VSH_OT_DATA, VSH_OFLAG_REQ, N_("source of disk device")},
{"target", VSH_OT_DATA, VSH_OFLAG_REQ, N_("target of disk device")},
{"driver", VSH_OT_STRING, 0, N_("driver of disk device")},
{"subdriver", VSH_OT_STRING, 0, N_("subdriver of disk device")},
{"type", VSH_OT_STRING, 0, N_("target device type")},
{"mode", VSH_OT_STRING, 0, N_("mode of device reading and writing")},
{"persistent", VSH_OT_BOOL, 0, N_("persist disk attachment")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdAttachDisk(vshControl *ctl, const vshCmd *cmd)
{
virDomainPtr dom = NULL;
char *source, *target, *driver, *subdriver, *type, *mode;
int isFile = 0, ret = FALSE;
char *buf = NULL, *tmp = NULL;
unsigned int flags;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
goto cleanup;
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 10:26:54 +00:00
if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
goto cleanup;
if (!(source = vshCommandOptString(cmd, "source", NULL)))
goto cleanup;
if (!(target = vshCommandOptString(cmd, "target", NULL)))
goto cleanup;
driver = vshCommandOptString(cmd, "driver", NULL);
subdriver = vshCommandOptString(cmd, "subdriver", NULL);
type = vshCommandOptString(cmd, "type", NULL);
mode = vshCommandOptString(cmd, "mode", NULL);
if (driver) {
if (STREQ(driver, "file") || STREQ(driver, "tap")) {
isFile = 1;
} else if (STRNEQ(driver, "phy")) {
vshError(ctl, _("No support %s in command 'attach-disk'"), driver);
goto cleanup;
}
}
if (mode) {
if (STRNEQ(mode, "readonly") && STRNEQ(mode, "shareable")) {
vshError(ctl, _("No support %s in command 'attach-disk'"), mode);
goto cleanup;
}
}
/* Make XML of disk */
tmp = vshMalloc(ctl, 1);
if (!tmp) goto cleanup;
buf = vshMalloc(ctl, 23);
if (!buf) goto cleanup;
if (isFile) {
sprintf(buf, " <disk type='file'");
} else {
sprintf(buf, " <disk type='block'");
}
if (type) {
tmp = vshRealloc(ctl, tmp, strlen(type) + 13);
if (!tmp) goto cleanup;
sprintf(tmp, " device='%s'>\n", type);
} else {
tmp = vshRealloc(ctl, tmp, 3);
if (!tmp) goto cleanup;
sprintf(tmp, ">\n");
}
buf = vshRealloc(ctl, buf, strlen(buf) + strlen(tmp) + 1);
if (!buf) goto cleanup;
strcat(buf, tmp);
if (driver) {
tmp = vshRealloc(ctl, tmp, strlen(driver) + 22);
if (!tmp) goto cleanup;
sprintf(tmp, " <driver name='%s'", driver);
} else {
tmp = vshRealloc(ctl, tmp, 25);
if (!tmp) goto cleanup;
sprintf(tmp, " <driver name='phy'");
}
buf = vshRealloc(ctl, buf, strlen(buf) + strlen(tmp) + 1);
if (!buf) goto cleanup;
strcat(buf, tmp);
if (subdriver) {
tmp = vshRealloc(ctl, tmp, strlen(subdriver) + 12);
if (!tmp) goto cleanup;
sprintf(tmp, " type='%s'/>\n", subdriver);
} else {
tmp = vshRealloc(ctl, tmp, 4);
if (!tmp) goto cleanup;
sprintf(tmp, "/>\n");
}
buf = vshRealloc(ctl, buf, strlen(buf) + strlen(tmp) + 1);
if (!buf) goto cleanup;
strcat(buf, tmp);
tmp = vshRealloc(ctl, tmp, strlen(source) + 25);
if (!tmp) goto cleanup;
if (isFile) {
sprintf(tmp, " <source file='%s'/>\n", source);
} else {
sprintf(tmp, " <source dev='%s'/>\n", source);
}
buf = vshRealloc(ctl, buf, strlen(buf) + strlen(tmp) + 1);
if (!buf) goto cleanup;
strcat(buf, tmp);
tmp = vshRealloc(ctl, tmp, strlen(target) + 24);
if (!tmp) goto cleanup;
sprintf(tmp, " <target dev='%s'/>\n", target);
buf = vshRealloc(ctl, buf, strlen(buf) + strlen(tmp) + 1);
if (!buf) goto cleanup;
strcat(buf, tmp);
if (mode != NULL) {
tmp = vshRealloc(ctl, tmp, strlen(mode) + 11);
if (!tmp) goto cleanup;
sprintf(tmp, " <%s/>\n", mode);
buf = vshRealloc(ctl, buf, strlen(buf) + strlen(tmp) + 1);
if (!buf) goto cleanup;
strcat(buf, tmp);
}
buf = vshRealloc(ctl, buf, strlen(buf) + 13);
if (!buf) goto cleanup;
strcat(buf, " </disk>\n");
if (vshCommandOptBool(cmd, "persistent")) {
flags = VIR_DOMAIN_DEVICE_MODIFY_CONFIG;
if (virDomainIsActive(dom) == 1)
flags |= VIR_DOMAIN_DEVICE_MODIFY_LIVE;
ret = virDomainAttachDeviceFlags(dom, buf, flags);
} else {
ret = virDomainAttachDevice(dom, buf);
}
if (ret != 0) {
vshError(ctl, "%s", _("Failed to attach disk"));
ret = FALSE;
} else {
vshPrint(ctl, "%s", _("Disk attached successfully\n"));
ret = TRUE;
}
cleanup:
if (dom)
virDomainFree(dom);
VIR_FREE(buf);
VIR_FREE(tmp);
return ret;
}
/*
* "detach-disk" command
*/
static const vshCmdInfo info_detach_disk[] = {
{"help", N_("detach disk device")},
{"desc", N_("Detach disk device.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_detach_disk[] = {
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
{"target", VSH_OT_DATA, VSH_OFLAG_REQ, N_("target of disk device")},
{"persistent", VSH_OT_BOOL, 0, N_("persist disk detachment")},
{NULL, 0, 0, NULL}
};
static int
2008-08-01 13:51:18 +00:00
cmdDetachDisk(vshControl *ctl, const vshCmd *cmd)
{
xmlDocPtr xml = NULL;
xmlXPathObjectPtr obj=NULL;
xmlXPathContextPtr ctxt = NULL;
xmlNodePtr cur = NULL;
xmlChar *tmp_tgt = NULL;
xmlBufferPtr xml_buf = NULL;
virDomainPtr dom = NULL;
char *doc, *target;
int i = 0, diff_tgt, ret = FALSE;
unsigned int flags;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
goto cleanup;
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 10:26:54 +00:00
if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
goto cleanup;
if (!(target = vshCommandOptString(cmd, "target", NULL)))
goto cleanup;
doc = virDomainGetXMLDesc(dom, 0);
if (!doc)
goto cleanup;
xml = xmlReadDoc((const xmlChar *) doc, "domain.xml", NULL,
XML_PARSE_NOENT | XML_PARSE_NONET |
XML_PARSE_NOWARNING);
VIR_FREE(doc);
if (!xml) {
vshError(ctl, "%s", _("Failed to get disk information"));
goto cleanup;
}
ctxt = xmlXPathNewContext(xml);
if (!ctxt) {
vshError(ctl, "%s", _("Failed to get disk information"));
goto cleanup;
}
obj = xmlXPathEval(BAD_CAST "/domain/devices/disk", ctxt);
if ((obj == NULL) || (obj->type != XPATH_NODESET) ||
(obj->nodesetval == NULL) || (obj->nodesetval->nodeNr == 0)) {
vshError(ctl, "%s", _("Failed to get disk information"));
goto cleanup;
}
/* search target */
for (; i < obj->nodesetval->nodeNr; i++) {
cur = obj->nodesetval->nodeTab[i]->children;
while (cur != NULL) {
if (cur->type == XML_ELEMENT_NODE && xmlStrEqual(cur->name, BAD_CAST "target")) {
tmp_tgt = xmlGetProp(cur, BAD_CAST "dev");
diff_tgt = xmlStrEqual(tmp_tgt, BAD_CAST target);
xmlFree(tmp_tgt);
if (diff_tgt) {
goto hit;
}
}
cur = cur->next;
}
}
vshError(ctl, _("No found disk whose target is %s"), target);
goto cleanup;
hit:
xml_buf = xmlBufferCreate();
if (!xml_buf) {
vshError(ctl, "%s", _("Failed to allocate memory"));
goto cleanup;
}
if(xmlNodeDump(xml_buf, xml, obj->nodesetval->nodeTab[i], 0, 0) < 0){
vshError(ctl, "%s", _("Failed to create XML"));
goto cleanup;
}
if (vshCommandOptBool(cmd, "persistent")) {
flags = VIR_DOMAIN_DEVICE_MODIFY_CONFIG;
if (virDomainIsActive(dom) == 1)
flags |= VIR_DOMAIN_DEVICE_MODIFY_LIVE;
ret = virDomainDetachDeviceFlags(dom,
(char *)xmlBufferContent(xml_buf),
flags);
} else {
ret = virDomainDetachDevice(dom, (char *)xmlBufferContent(xml_buf));
}
if (ret != 0) {
vshError(ctl, "%s", _("Failed to detach disk"));
ret = FALSE;
} else {
avoid many format string warnings Building with --disable-nls exposed many new warnings like these: virsh.c:4952: warning: format not a string literal and no format ... util.c:163: warning: format not a string literal and no format arguments All but one of the following changes add a "%s" argument before the offending _(...) argument. This was the only manual change: * src/lxc_driver.c (lxcVersion): Use %s and strerror(errno) rather than %m, to avoid a warning from gcc -Wformat-security. Add "%s" before each warned about format-string-with-no-%-directive: * src/domain_conf.c (virDomainHostdevSubsysUsbDefParseXML) (virDomainDefParseString, virDomainDefParseFile): * src/hash.c (virGetConnect, __virGetDomain, virReleaseDomain) (__virGetNetwork, virReleaseNetwork, __virGetStoragePool) (virReleaseStoragePool, __virGetStorageVol, virReleaseStorageVol): * src/lxc_container.c (lxcContainerChild): * src/lxc_driver.c (lxcDomainDefine, lxcDomainUndefine) (lxcDomainGetInfo, lxcGetOSType, lxcDomainDumpXML) (lxcSetupInterfaces, lxcDomainStart, lxcDomainCreateAndStart) (lxcVersion, lxcGetSchedulerParameters): * src/network_conf.c (virNetworkDefParseString) (virNetworkDefParseFile): * src/openvz_conf.c (openvzReadNetworkConf, openvzLoadDomains): * src/openvz_driver.c (openvzDomainDefineCmd) (openvzDomainGetInfo, openvzDomainDumpXML, openvzDomainShutdown) (openvzDomainReboot, ADD_ARG_LIT, openvzDomainDefineXML) (openvzDomainCreateXML, openvzDomainCreate, openvzDomainUndefine) (openvzDomainSetAutostart, openvzDomainGetAutostart) (openvzDomainSetVcpus): * src/qemu_driver.c (qemudDomainBlockPeek, qemudDomainMemoryPeek): * src/remote_internal.c (remoteDomainBlockPeek) (remoteDomainMemoryPeek, remoteAuthPolkit): * src/sexpr.c (sexpr_new, _string2sexpr): * src/storage_backend_disk.c (virStorageBackendDiskMakeDataVol) (virStorageBackendDiskCreateVol): * src/storage_backend_fs.c (virStorageBackendFileSystemNetFindPoolSources): * src/storage_backend_logical.c (virStorageBackendLogicalFindLVs) (virStorageBackendLogicalFindPoolSources): * src/test.c (testOpenDefault, testOpenFromFile, testOpen) (testGetDomainInfo, testDomainRestore) (testNodeGetCellsFreeMemory): * src/util.c (virExec): * src/virsh.c (cmdAttachDevice, cmdDetachDevice) (cmdAttachInterface, cmdDetachInterface, cmdAttachDisk) (cmdDetachDisk, cmdEdit): * src/xend_internal.c (do_connect, wr_sync, xend_op_ext) (urlencode, xenDaemonDomainCreateXML) (xenDaemonDomainLookupByName_ids, xenDaemonDomainLookupByID) (xenDaemonParseSxprOS, xend_parse_sexp_desc_char) (xenDaemonParseSxprChar, xenDaemonParseSxprDisks) (xenDaemonParseSxpr, sexpr_to_xend_topology, sexpr_to_domain) (xenDaemonDomainFetch, xenDaemonDomainGetAutostart) (xenDaemonDomainSetAutostart, xenDaemonDomainMigratePerform) (xenDaemonDomainDefineXML, xenDaemonGetSchedulerType) (xenDaemonGetSchedulerParameters) (xenDaemonSetSchedulerParameters, xenDaemonDomainBlockPeek) (xenDaemonFormatSxprChr, virDomainXMLDevID): * src/xm_internal.c (xenXMConfigCacheRefresh, xenXMDomainPinVcpu) (xenXMDomainCreate, xenXMDomainDefineXML) (xenXMDomainAttachDevice, xenXMDomainDetachDevice): * src/xml.c (virXPathString, virXPathNumber, virXPathLong) (virXPathULong, virXPathBoolean, virXPathNode, virXPathNodeSet): * src/xs_internal.c (xenStoreOpen):
2008-10-13 16:46:28 +00:00
vshPrint(ctl, "%s", _("Disk detached successfully\n"));
ret = TRUE;
}
cleanup:
xmlXPathFreeObject(obj);
xmlXPathFreeContext(ctxt);
if (xml)
xmlFreeDoc(xml);
if (xml_buf)
xmlBufferFree(xml_buf);
if (dom)
virDomainFree(dom);
return ret;
}
/*
* "cpu-compare" command
*/
static const vshCmdInfo info_cpu_compare[] = {
{"help", N_("compare host CPU with a CPU described by an XML file")},
{"desc", N_("compare CPU with host CPU")},
{NULL, NULL}
};
static const vshCmdOptDef opts_cpu_compare[] = {
{"file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("file containing an XML CPU description")},
{NULL, 0, 0, NULL}
};
static int
cmdCPUCompare(vshControl *ctl, const vshCmd *cmd)
{
char *from;
int found;
int ret = TRUE;
char *buffer;
int result;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
from = vshCommandOptString(cmd, "file", &found);
if (!found)
return FALSE;
if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0)
return FALSE;
result = virConnectCompareCPU(ctl->conn, buffer, 0);
VIR_FREE(buffer);
switch (result) {
case VIR_CPU_COMPARE_INCOMPATIBLE:
vshPrint(ctl, _("CPU described in %s is incompatible with host CPU\n"),
from);
ret = FALSE;
break;
case VIR_CPU_COMPARE_IDENTICAL:
vshPrint(ctl, _("CPU described in %s is identical to host CPU\n"),
from);
ret = TRUE;
break;
case VIR_CPU_COMPARE_SUPERSET:
vshPrint(ctl, _("Host CPU is a superset of CPU described in %s\n"),
from);
ret = TRUE;
break;
case VIR_CPU_COMPARE_ERROR:
default:
vshError(ctl, _("Failed to compare host CPU with %s"), from);
ret = FALSE;
}
return ret;
}
/*
* "cpu-baseline" command
*/
static const vshCmdInfo info_cpu_baseline[] = {
{"help", N_("compute baseline CPU")},
{"desc", N_("Compute baseline CPU for a set of given CPUs.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_cpu_baseline[] = {
{"file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("file containing XML CPU descriptions")},
{NULL, 0, 0, NULL}
};
static int
cmdCPUBaseline(vshControl *ctl, const vshCmd *cmd)
{
char *from;
int found;
int ret = TRUE;
char *buffer;
char *result = NULL;
const char **list = NULL;
unsigned int count = 0;
xmlDocPtr doc = NULL;
xmlNodePtr node_list;
xmlXPathContextPtr ctxt = NULL;
xmlSaveCtxtPtr sctxt = NULL;
xmlBufferPtr buf = NULL;
xmlXPathObjectPtr obj = NULL;
int res, i;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
from = vshCommandOptString(cmd, "file", &found);
if (!found)
return FALSE;
if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0)
return FALSE;
doc = xmlNewDoc(NULL);
if (doc == NULL)
goto no_memory;
res = xmlParseBalancedChunkMemory(doc, NULL, NULL, 0,
(const xmlChar *)buffer, &node_list);
if (res != 0) {
vshError(ctl, _("Failed to parse XML fragment %s"), from);
ret = FALSE;
goto cleanup;
}
xmlAddChildList((xmlNodePtr) doc, node_list);
ctxt = xmlXPathNewContext(doc);
if (!ctxt)
goto no_memory;
obj = xmlXPathEval(BAD_CAST "//cpu[not(ancestor::cpu)]", ctxt);
if ((obj == NULL) || (obj->nodesetval == NULL) ||
(obj->nodesetval->nodeTab == NULL))
goto cleanup;
for (i = 0;i < obj->nodesetval->nodeNr;i++) {
buf = xmlBufferCreate();
if (buf == NULL)
goto no_memory;
sctxt = xmlSaveToBuffer(buf, NULL, 0);
if (sctxt == NULL) {
xmlBufferFree(buf);
goto no_memory;
}
xmlSaveTree(sctxt, obj->nodesetval->nodeTab[i]);
xmlSaveClose(sctxt);
list = vshRealloc(ctl, list, sizeof(char *) * (count + 1));
list[count++] = (char *) buf->content;
buf->content = NULL;
xmlBufferFree(buf);
buf = NULL;
}
if (count == 0) {
vshError(ctl, _("No host CPU specified in '%s'"), from);
ret = FALSE;
goto cleanup;
}
result = virConnectBaselineCPU(ctl->conn, list, count, 0);
if (result)
vshPrint(ctl, "%s", result);
else
ret = FALSE;
cleanup:
xmlXPathFreeObject(obj);
xmlXPathFreeContext(ctxt);
xmlFreeDoc(doc);
VIR_FREE(result);
if ((list != NULL) && (count > 0)) {
for (i = 0;i < count;i++)
VIR_FREE(list[i]);
}
VIR_FREE(list);
VIR_FREE(buffer);
return ret;
no_memory:
vshError(ctl, "%s", _("Out of memory"));
ret = FALSE;
goto cleanup;
}
/* Common code for the edit / net-edit / pool-edit functions which follow. */
static char *
editWriteToTempFile (vshControl *ctl, const char *doc)
{
char *ret;
const char *tmpdir;
int fd;
ret = malloc (PATH_MAX);
if (!ret) {
vshError(ctl, _("malloc: failed to allocate temporary file name: %s"),
strerror(errno));
return NULL;
}
tmpdir = getenv ("TMPDIR");
if (!tmpdir) tmpdir = "/tmp";
snprintf (ret, PATH_MAX, "%s/virshXXXXXX", tmpdir);
fd = mkstemp (ret);
if (fd == -1) {
vshError(ctl, _("mkstemp: failed to create temporary file: %s"),
strerror(errno));
VIR_FREE(ret);
return NULL;
}
if (safewrite (fd, doc, strlen (doc)) == -1) {
vshError(ctl, _("write: %s: failed to write to temporary file: %s"),
ret, strerror(errno));
close (fd);
unlink (ret);
VIR_FREE(ret);
return NULL;
}
if (close (fd) == -1) {
vshError(ctl, _("close: %s: failed to write or close temporary file: %s"),
ret, strerror(errno));
unlink (ret);
VIR_FREE(ret);
return NULL;
}
/* Temporary filename: caller frees. */
return ret;
}
/* Characters permitted in $EDITOR environment variable and temp filename. */
#define ACCEPTED_CHARS \
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-/_.:@"
static int
editFile (vshControl *ctl, const char *filename)
{
const char *editor;
char *command;
int command_ret;
editor = getenv ("VISUAL");
if (!editor) editor = getenv ("EDITOR");
if (!editor) editor = "vi"; /* could be cruel & default to ed(1) here */
/* 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
* is why sudo scrubs it by default).
*/
if (strspn (filename, ACCEPTED_CHARS) != strlen (filename)) {
vshError(ctl,
_("%s: temporary filename contains shell meta or other "
"unacceptable characters (is $TMPDIR wrong?)"),
filename);
return -1;
}
2008-12-23 13:03:29 +00:00
if (virAsprintf(&command, "%s %s", editor, filename) == -1) {
vshError(ctl,
2008-12-23 13:03:29 +00:00
_("virAsprintf: could not create editing command: %s"),
strerror(errno));
return -1;
}
command_ret = system (command);
if (command_ret == -1) {
vshError(ctl,
_("%s: edit command failed: %s"), command, strerror(errno));
VIR_FREE(command);
return -1;
}
if (command_ret != WEXITSTATUS (0)) {
vshError(ctl,
_("%s: command exited with non-zero status"), command);
VIR_FREE(command);
return -1;
}
VIR_FREE(command);
return 0;
}
static char *
editReadBackFile (vshControl *ctl, const char *filename)
{
char *ret;
if (virFileReadAll (filename, VIRSH_MAX_XML_FILE, &ret) == -1) {
vshError(ctl,
_("%s: failed to read temporary file: %s"),
filename, strerror(errno));
return NULL;
}
return ret;
}
#ifndef WIN32
/*
* "cd" command
*/
static const vshCmdInfo info_cd[] = {
{"help", N_("change the current directory")},
{"desc", N_("Change the current directory.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_cd[] = {
{"dir", VSH_OT_DATA, 0, N_("directory to switch to (default: home or else root)")},
{NULL, 0, 0, NULL}
};
static int
cmdCd(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
{
const char *dir;
int found;
if (!ctl->imode) {
vshError(ctl, "%s", _("cd: command valid only in interactive mode"));
return FALSE;
}
dir = vshCommandOptString(cmd, "dir", &found);
if (!found) {
uid_t uid = geteuid();
dir = virGetUserDirectory(uid);
}
if (!dir)
dir = "/";
if (chdir (dir) == -1) {
vshError(ctl, _("cd: %s: %s"), strerror(errno), dir);
return FALSE;
}
return TRUE;
}
#endif
#ifndef WIN32
/*
* "pwd" command
*/
static const vshCmdInfo info_pwd[] = {
{"help", N_("print the current directory")},
{"desc", N_("Print the current directory.")},
{NULL, NULL}
};
static int
cmdPwd(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
{
char *cwd;
size_t path_max;
int err = TRUE;
path_max = (size_t) PATH_MAX + 2;
cwd = vshMalloc (ctl, path_max);
while (cwd) {
err = getcwd (cwd, path_max) == NULL;
if (!err || errno != ERANGE)
break;
path_max *= 2;
cwd = vshRealloc (ctl, cwd, path_max);
}
if (err)
vshError(ctl, _("pwd: cannot get current directory: %s"),
strerror(errno));
else
vshPrint (ctl, _("%s\n"), cwd);
VIR_FREE(cwd);
return !err;
}
#endif
/*
* "edit" command
*/
static const vshCmdInfo info_edit[] = {
{"help", N_("edit XML configuration for a domain")},
{"desc", N_("Edit the XML configuration for a domain.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_edit[] = {
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
{NULL, 0, 0, NULL}
};
/* This function also acts as a template to generate cmdNetworkEdit
* and cmdPoolEdit functions (below) using a sed script in the Makefile.
*/
static int
cmdEdit (vshControl *ctl, const vshCmd *cmd)
{
int ret = FALSE;
virDomainPtr dom = NULL;
char *tmp = NULL;
char *doc = NULL;
char *doc_edited = NULL;
char *doc_reread = NULL;
int flags = VIR_DOMAIN_XML_SECURE | VIR_DOMAIN_XML_INACTIVE;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
goto cleanup;
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 10:26:54 +00:00
dom = vshCommandOptDomain (ctl, cmd, NULL);
if (dom == NULL)
goto cleanup;
/* Get the XML configuration of the domain. */
doc = virDomainGetXMLDesc (dom, flags);
if (!doc)
goto cleanup;
/* Create and open the temporary file. */
tmp = editWriteToTempFile (ctl, doc);
if (!tmp) goto cleanup;
/* Start the editor. */
if (editFile (ctl, tmp) == -1) goto cleanup;
/* Read back the edited file. */
doc_edited = editReadBackFile (ctl, tmp);
if (!doc_edited) goto cleanup;
unlink (tmp);
tmp = NULL;
/* Compare original XML with edited. Has it changed at all? */
if (STREQ (doc, doc_edited)) {
vshPrint (ctl, _("Domain %s XML configuration not changed.\n"),
virDomainGetName (dom));
ret = TRUE;
goto cleanup;
}
/* Now re-read the domain XML. Did someone else change it while
* it was being edited? This also catches problems such as us
* losing a connection or the domain going away.
*/
doc_reread = virDomainGetXMLDesc (dom, flags);
if (!doc_reread)
goto cleanup;
if (STRNEQ (doc, doc_reread)) {
vshError(ctl,
"%s", _("ERROR: the XML configuration was changed by another user"));
goto cleanup;
}
/* Everything checks out, so redefine the domain. */
virDomainFree (dom);
dom = virDomainDefineXML (ctl->conn, doc_edited);
if (!dom)
goto cleanup;
vshPrint (ctl, _("Domain %s XML configuration edited.\n"),
virDomainGetName(dom));
ret = TRUE;
cleanup:
if (dom)
virDomainFree (dom);
VIR_FREE(doc);
VIR_FREE(doc_edited);
VIR_FREE(doc_reread);
if (tmp) {
unlink (tmp);
VIR_FREE(tmp);
}
return ret;
}
/*
* "net-edit" command
*/
static const vshCmdInfo info_network_edit[] = {
{"help", N_("edit XML configuration for a network")},
{"desc", N_("Edit the XML configuration for a network.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_network_edit[] = {
{"network", VSH_OT_DATA, VSH_OFLAG_REQ, N_("network name, id or uuid")},
{NULL, 0, 0, NULL}
};
/* This is generated from this file by a sed script in the Makefile. */
#include "virsh-net-edit.c"
/*
* "pool-edit" command
*/
static const vshCmdInfo info_pool_edit[] = {
{"help", N_("edit XML configuration for a storage pool")},
{"desc", N_("Edit the XML configuration for a storage pool.")},
{NULL, NULL}
};
static const vshCmdOptDef opts_pool_edit[] = {
{"pool", VSH_OT_DATA, VSH_OFLAG_REQ, N_("pool name or uuid")},
{NULL, 0, 0, NULL}
};
/* This is generated from this file by a sed script in the Makefile. */
#include "virsh-pool-edit.c"
2005-12-08 10:23:34 +00:00
/*
* "quit" command
*/
static const vshCmdInfo info_quit[] = {
{"help", N_("quit this interactive terminal")},
{"desc", ""},
{NULL, NULL}
2005-12-08 10:23:34 +00:00
};
static int
2008-08-01 13:51:18 +00:00
cmdQuit(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
{
2005-12-08 10:23:34 +00:00
ctl->imode = FALSE;
return TRUE;
}
/*
* "snapshot-create" command
*/
static const vshCmdInfo info_snapshot_create[] = {
{"help", N_("Create a snapshot")},
{"desc", N_("Snapshot create")},
{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")},
{NULL, 0, 0, NULL}
};
static int
cmdSnapshotCreate(vshControl *ctl, const vshCmd *cmd)
{
virDomainPtr dom = NULL;
int ret = FALSE;
char *from;
char *buffer = NULL;
virDomainSnapshotPtr snapshot = NULL;
xmlDocPtr xml = NULL;
xmlXPathContextPtr ctxt = NULL;
char *doc = NULL;
char *name = NULL;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
goto cleanup;
dom = vshCommandOptDomain(ctl, cmd, NULL);
if (dom == NULL)
goto cleanup;
from = vshCommandOptString(cmd, "xmlfile", NULL);
if (from == NULL)
buffer = strdup("<domainsnapshot/>");
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 = virDomainSnapshotCreateXML(dom, buffer, 0);
if (snapshot == NULL)
goto cleanup;
doc = virDomainSnapshotGetXMLDesc(snapshot, 0);
if (!doc)
goto cleanup;
xml = xmlReadDoc((const xmlChar *) doc, "domainsnapshot.xml", NULL,
XML_PARSE_NOENT | XML_PARSE_NONET |
XML_PARSE_NOWARNING);
if (!xml)
goto cleanup;
ctxt = xmlXPathNewContext(xml);
if (!ctxt)
goto cleanup;
name = virXPathString("string(/domainsnapshot/name)", ctxt);
if (!name) {
vshError(ctl, "%s",
_("Could not find 'name' element in domain snapshot XML"));
goto cleanup;
}
vshPrint(ctl, _("Domain snapshot %s created"), name);
if (from)
vshPrint(ctl, _(" from '%s'"), from);
vshPrint(ctl, "\n");
ret = TRUE;
cleanup:
VIR_FREE(name);
xmlXPathFreeContext(ctxt);
if (xml)
xmlFreeDoc(xml);
if (snapshot)
virDomainSnapshotFree(snapshot);
VIR_FREE(doc);
VIR_FREE(buffer);
if (dom)
virDomainFree(dom);
return ret;
}
/*
* "snapshot-current" command
*/
static const vshCmdInfo info_snapshot_current[] = {
{"help", N_("Get the current snapshot")},
{"desc", N_("Get the current snapshot")},
{NULL, NULL}
};
static const vshCmdOptDef opts_snapshot_current[] = {
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
{NULL, 0, 0, NULL}
};
static int
cmdSnapshotCurrent(vshControl *ctl, const vshCmd *cmd)
{
virDomainPtr dom = NULL;
int ret = FALSE;
int current;
virDomainSnapshotPtr snapshot = NULL;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
goto cleanup;
dom = vshCommandOptDomain(ctl, cmd, NULL);
if (dom == NULL)
goto cleanup;
current = virDomainHasCurrentSnapshot(dom, 0);
if (current < 0)
goto cleanup;
else if (current) {
char *xml;
if (!(snapshot = virDomainSnapshotCurrent(dom, 0)))
goto cleanup;
xml = virDomainSnapshotGetXMLDesc(snapshot, 0);
if (!xml)
goto cleanup;
vshPrint(ctl, "%s", xml);
VIR_FREE(xml);
}
ret = TRUE;
cleanup:
if (snapshot)
virDomainSnapshotFree(snapshot);
if (dom)
virDomainFree(dom);
return ret;
}
/*
* "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")},
{NULL, 0, 0, NULL}
};
static int
cmdSnapshotList(vshControl *ctl, const vshCmd *cmd)
{
virDomainPtr dom = NULL;
int ret = FALSE;
int numsnaps;
char **names = NULL;
int actual;
int i;
xmlDocPtr xml = NULL;
xmlXPathContextPtr ctxt = NULL;
char *doc = NULL;
virDomainSnapshotPtr snapshot = NULL;
char *state = NULL;
long creation;
char timestr[100];
struct tm time_info;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
goto cleanup;
dom = vshCommandOptDomain(ctl, cmd, NULL);
if (dom == NULL)
goto cleanup;
numsnaps = virDomainSnapshotNum(dom, 0);
if (numsnaps < 0)
goto cleanup;
vshPrint(ctl, " %-20s %-25s %s\n", _("Name"), _("Creation Time"), _("State"));
vshPrint(ctl, "---------------------------------------------------\n");
if (numsnaps) {
if (VIR_ALLOC_N(names, numsnaps) < 0)
goto cleanup;
actual = virDomainSnapshotListNames(dom, names, numsnaps, 0);
if (actual < 0)
goto cleanup;
qsort(&names[0], actual, sizeof(char*), namesorter);
for (i = 0; i < actual; i++) {
/* free up memory from previous iterations of the loop */
VIR_FREE(state);
if (snapshot)
virDomainSnapshotFree(snapshot);
xmlXPathFreeContext(ctxt);
if (xml)
xmlFreeDoc(xml);
VIR_FREE(doc);
snapshot = virDomainSnapshotLookupByName(dom, names[i], 0);
if (snapshot == NULL)
continue;
doc = virDomainSnapshotGetXMLDesc(snapshot, 0);
if (!doc)
continue;
xml = xmlReadDoc((const xmlChar *) doc, "domainsnapshot.xml", NULL,
XML_PARSE_NOENT | XML_PARSE_NONET |
XML_PARSE_NOWARNING);
if (!xml)
continue;
ctxt = xmlXPathNewContext(xml);
if (!ctxt)
continue;
state = virXPathString("string(/domainsnapshot/state)", ctxt);
if (state == NULL)
continue;
if (virXPathLong("string(/domainsnapshot/creationTime)", ctxt,
&creation) < 0)
continue;
localtime_r(&creation, &time_info);
strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S %z", &time_info);
vshPrint(ctl, " %-20s %-25s %s\n", names[i], timestr, state);
}
}
ret = TRUE;
cleanup:
/* this frees up memory from the last iteration of the loop */
VIR_FREE(state);
if (snapshot)
virDomainSnapshotFree(snapshot);
xmlXPathFreeContext(ctxt);
if (xml)
xmlFreeDoc(xml);
VIR_FREE(doc);
VIR_FREE(names);
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")},
{NULL, 0, 0, NULL}
};
static int
cmdSnapshotDumpXML(vshControl *ctl, const vshCmd *cmd)
{
virDomainPtr dom = NULL;
int ret = FALSE;
char *name;
virDomainSnapshotPtr snapshot = NULL;
char *xml = NULL;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
goto cleanup;
dom = vshCommandOptDomain(ctl, cmd, NULL);
if (dom == NULL)
goto cleanup;
name = vshCommandOptString(cmd, "snapshotname", NULL);
if (name == NULL) {
vshError(ctl, "%s", _("missing snapshotname"));
goto cleanup;
}
snapshot = virDomainSnapshotLookupByName(dom, name, 0);
if (snapshot == NULL)
goto cleanup;
xml = virDomainSnapshotGetXMLDesc(snapshot, 0);
if (!xml)
goto cleanup;
printf("%s", xml);
ret = TRUE;
cleanup:
VIR_FREE(xml);
if (snapshot)
virDomainSnapshotFree(snapshot);
if (dom)
virDomainFree(dom);
return ret;
}
/*
* "snapshot-revert" command
*/
static const vshCmdInfo info_snapshot_revert[] = {
{"help", N_("Revert a domain to a snapshot")},
{"desc", N_("Revert domain to snapshot")},
{NULL, NULL}
};
static const vshCmdOptDef opts_snapshot_revert[] = {
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
{"snapshotname", VSH_OT_DATA, VSH_OFLAG_REQ, N_("snapshot name")},
{NULL, 0, 0, NULL}
};
static int
cmdDomainSnapshotRevert(vshControl *ctl, const vshCmd *cmd)
{
virDomainPtr dom = NULL;
int ret = FALSE;
char *name;
virDomainSnapshotPtr snapshot = NULL;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
goto cleanup;
dom = vshCommandOptDomain(ctl, cmd, NULL);
if (dom == NULL)
goto cleanup;
name = vshCommandOptString(cmd, "snapshotname", NULL);
if (name == NULL) {
vshError(ctl, "%s", _("missing snapshotname"));
goto cleanup;
}
snapshot = virDomainSnapshotLookupByName(dom, name, 0);
if (snapshot == NULL)
goto cleanup;
if (virDomainRevertToSnapshot(snapshot, 0) < 0)
goto cleanup;
ret = TRUE;
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")},
{"snapshotname", VSH_OT_DATA, VSH_OFLAG_REQ, N_("snapshot name")},
{"children", VSH_OT_BOOL, 0, N_("delete snapshot and all children")},
{NULL, 0, 0, NULL}
};
static int
cmdSnapshotDelete(vshControl *ctl, const vshCmd *cmd)
{
virDomainPtr dom = NULL;
int ret = FALSE;
char *name;
virDomainSnapshotPtr snapshot = NULL;
unsigned int flags = 0;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
goto cleanup;
dom = vshCommandOptDomain(ctl, cmd, NULL);
if (dom == NULL)
goto cleanup;
name = vshCommandOptString(cmd, "snapshotname", NULL);
if (name == NULL) {
vshError(ctl, "%s", _("missing snapshotname"));
goto cleanup;
}
if (vshCommandOptBool(cmd, "children"))
flags |= VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN;
snapshot = virDomainSnapshotLookupByName(dom, name, 0);
if (snapshot == NULL)
goto cleanup;
if (virDomainSnapshotDelete(snapshot, flags) < 0)
goto cleanup;
ret = TRUE;
cleanup:
if (snapshot)
virDomainSnapshotFree(snapshot);
if (dom)
virDomainFree(dom);
return ret;
}
2005-12-08 10:23:34 +00:00
/*
* Commands
*/
static const vshCmdDef commands[] = {
{"help", cmdHelp, opts_help, info_help},
{"attach-device", cmdAttachDevice, opts_attach_device, info_attach_device},
{"attach-disk", cmdAttachDisk, opts_attach_disk, info_attach_disk},
{"attach-interface", cmdAttachInterface, opts_attach_interface, info_attach_interface},
{"autostart", cmdAutostart, opts_autostart, info_autostart},
{"capabilities", cmdCapabilities, NULL, info_capabilities},
#ifndef WIN32
{"cd", cmdCd, opts_cd, info_cd},
#endif
{"connect", cmdConnect, opts_connect, info_connect},
#ifndef WIN32
{"console", cmdConsole, opts_console, info_console},
#endif
{"cpu-baseline", cmdCPUBaseline, opts_cpu_baseline, info_cpu_baseline},
{"cpu-compare", cmdCPUCompare, opts_cpu_compare, info_cpu_compare},
{"create", cmdCreate, opts_create, info_create},
{"start", cmdStart, opts_start, info_start},
2006-04-04 21:52:31 +00:00
{"destroy", cmdDestroy, opts_destroy, info_destroy},
{"detach-device", cmdDetachDevice, opts_detach_device, info_detach_device},
{"detach-disk", cmdDetachDisk, opts_detach_disk, info_detach_disk},
{"detach-interface", cmdDetachInterface, opts_detach_interface, info_detach_interface},
{"define", cmdDefine, opts_define, info_define},
2006-04-04 21:52:31 +00:00
{"domid", cmdDomid, opts_domid, info_domid},
2006-05-29 15:39:31 +00:00
{"domuuid", cmdDomuuid, opts_domuuid, info_domuuid},
{"dominfo", cmdDominfo, opts_dominfo, info_dominfo},
{"domjobinfo", cmdDomjobinfo, opts_domjobinfo, info_domjobinfo},
{"domjobabort", cmdDomjobabort, opts_domjobabort, info_domjobabort},
2006-04-04 21:52:31 +00:00
{"domname", cmdDomname, opts_domname, info_domname},
{"domstate", cmdDomstate, opts_domstate, info_domstate},
{"domblkstat", cmdDomblkstat, opts_domblkstat, info_domblkstat},
{"domifstat", cmdDomIfstat, opts_domifstat, info_domifstat},
{"dommemstat", cmdDomMemStat, opts_dommemstat, info_dommemstat},
2009-05-21 13:46:35 +00:00
{"domxml-from-native", cmdDomXMLFromNative, opts_domxmlfromnative, info_domxmlfromnative},
{"domxml-to-native", cmdDomXMLToNative, opts_domxmltonative, info_domxmltonative},
{"dumpxml", cmdDumpXML, opts_dumpxml, info_dumpxml},
{"edit", cmdEdit, opts_edit, info_edit},
{"find-storage-pool-sources", cmdPoolDiscoverSources,
opts_find_storage_pool_sources, info_find_storage_pool_sources},
{"find-storage-pool-sources-as", cmdPoolDiscoverSourcesAs,
opts_find_storage_pool_sources_as, info_find_storage_pool_sources_as},
{"freecell", cmdFreecell, opts_freecell, info_freecell},
{"hostname", cmdHostname, NULL, info_hostname},
{"list", cmdList, opts_list, info_list},
{"migrate", cmdMigrate, opts_migrate, info_migrate},
{"migrate-setmaxdowntime", cmdMigrateSetMaxDowntime, opts_migrate_setmaxdowntime, info_migrate_setmaxdowntime},
{"net-autostart", cmdNetworkAutostart, opts_network_autostart, info_network_autostart},
{"net-create", cmdNetworkCreate, opts_network_create, info_network_create},
{"net-define", cmdNetworkDefine, opts_network_define, info_network_define},
{"net-destroy", cmdNetworkDestroy, opts_network_destroy, info_network_destroy},
{"net-dumpxml", cmdNetworkDumpXML, opts_network_dumpxml, info_network_dumpxml},
{"net-edit", cmdNetworkEdit, opts_network_edit, info_network_edit},
{"net-list", cmdNetworkList, opts_network_list, info_network_list},
{"net-name", cmdNetworkName, opts_network_name, info_network_name},
{"net-start", cmdNetworkStart, opts_network_start, info_network_start},
{"net-undefine", cmdNetworkUndefine, opts_network_undefine, info_network_undefine},
{"net-uuid", cmdNetworkUuid, opts_network_uuid, info_network_uuid},
{"iface-list", cmdInterfaceList, opts_interface_list, info_interface_list},
{"iface-name", cmdInterfaceName, opts_interface_name, info_interface_name},
{"iface-mac", cmdInterfaceMAC, opts_interface_mac, info_interface_mac},
{"iface-dumpxml", cmdInterfaceDumpXML, opts_interface_dumpxml, info_interface_dumpxml},
{"iface-define", cmdInterfaceDefine, opts_interface_define, info_interface_define},
{"iface-undefine", cmdInterfaceUndefine, opts_interface_undefine, info_interface_undefine},
{"iface-edit", cmdInterfaceEdit, opts_interface_edit, info_interface_edit},
{"iface-start", cmdInterfaceStart, opts_interface_start, info_interface_start},
{"iface-destroy", cmdInterfaceDestroy, opts_interface_destroy, info_interface_destroy},
{"managedsave", cmdManagedSave, opts_managedsave, info_managedsave},
2006-04-04 21:52:31 +00:00
{"nodeinfo", cmdNodeinfo, NULL, info_nodeinfo},
{"nodedev-list", cmdNodeListDevices, opts_node_list_devices, info_node_list_devices},
{"nodedev-dumpxml", cmdNodeDeviceDumpXML, opts_node_device_dumpxml, info_node_device_dumpxml},
{"nodedev-dettach", cmdNodeDeviceDettach, opts_node_device_dettach, info_node_device_dettach},
{"nodedev-reattach", cmdNodeDeviceReAttach, opts_node_device_reattach, info_node_device_reattach},
{"nodedev-reset", cmdNodeDeviceReset, opts_node_device_reset, info_node_device_reset},
{"nodedev-create", cmdNodeDeviceCreate, opts_node_device_create, info_node_device_create},
{"nodedev-destroy", cmdNodeDeviceDestroy, opts_node_device_destroy, info_node_device_destroy},
{"nwfilter-define", cmdNWFilterDefine, opts_nwfilter_define, info_nwfilter_define},
{"nwfilter-undefine", cmdNWFilterUndefine, opts_nwfilter_undefine, info_nwfilter_undefine},
{"nwfilter-dumpxml", cmdNWFilterDumpXML, opts_nwfilter_dumpxml, info_nwfilter_dumpxml},
{"nwfilter-list", cmdNWFilterList, opts_nwfilter_list, info_nwfilter_list},
{"nwfilter-edit", cmdNWFilterEdit, opts_nwfilter_edit, info_nwfilter_edit},
{"pool-autostart", cmdPoolAutostart, opts_pool_autostart, info_pool_autostart},
{"pool-build", cmdPoolBuild, opts_pool_build, info_pool_build},
{"pool-create", cmdPoolCreate, opts_pool_create, info_pool_create},
2008-12-22 16:23:36 +00:00
{"pool-create-as", cmdPoolCreateAs, opts_pool_X_as, info_pool_create_as},
{"pool-define", cmdPoolDefine, opts_pool_define, info_pool_define},
2008-12-22 16:23:36 +00:00
{"pool-define-as", cmdPoolDefineAs, opts_pool_X_as, info_pool_define_as},
{"pool-destroy", cmdPoolDestroy, opts_pool_destroy, info_pool_destroy},
{"pool-delete", cmdPoolDelete, opts_pool_delete, info_pool_delete},
{"pool-dumpxml", cmdPoolDumpXML, opts_pool_dumpxml, info_pool_dumpxml},
{"pool-edit", cmdPoolEdit, opts_pool_edit, info_pool_edit},
{"pool-info", cmdPoolInfo, opts_pool_info, info_pool_info},
{"pool-list", cmdPoolList, opts_pool_list, info_pool_list},
{"pool-name", cmdPoolName, opts_pool_name, info_pool_name},
{"pool-refresh", cmdPoolRefresh, opts_pool_refresh, info_pool_refresh},
{"pool-start", cmdPoolStart, opts_pool_start, info_pool_start},
{"pool-undefine", cmdPoolUndefine, opts_pool_undefine, info_pool_undefine},
{"pool-uuid", cmdPoolUuid, opts_pool_uuid, info_pool_uuid},
{"secret-define", cmdSecretDefine, opts_secret_define, info_secret_define},
{"secret-dumpxml", cmdSecretDumpXML, opts_secret_dumpxml, info_secret_dumpxml},
{"secret-set-value", cmdSecretSetValue, opts_secret_set_value, info_secret_set_value},
{"secret-get-value", cmdSecretGetValue, opts_secret_get_value, info_secret_get_value},
{"secret-undefine", cmdSecretUndefine, opts_secret_undefine, info_secret_undefine},
{"secret-list", cmdSecretList, NULL, info_secret_list},
#ifndef WIN32
{"pwd", cmdPwd, NULL, info_pwd},
#endif
2006-04-04 21:52:31 +00:00
{"quit", cmdQuit, NULL, info_quit},
{"exit", cmdQuit, NULL, info_quit},
2006-04-04 21:52:31 +00:00
{"reboot", cmdReboot, opts_reboot, info_reboot},
{"restore", cmdRestore, opts_restore, info_restore},
{"resume", cmdResume, opts_resume, info_resume},
{"save", cmdSave, opts_save, info_save},
{"schedinfo", cmdSchedinfo, opts_schedinfo, info_schedinfo},
{"dump", cmdDump, opts_dump, info_dump},
{"shutdown", cmdShutdown, opts_shutdown, info_shutdown},
{"setmem", cmdSetmem, opts_setmem, info_setmem},
{"setmaxmem", cmdSetmaxmem, opts_setmaxmem, info_setmaxmem},
{"setvcpus", cmdSetvcpus, opts_setvcpus, info_setvcpus},
2006-04-04 21:52:31 +00:00
{"suspend", cmdSuspend, opts_suspend, info_suspend},
{"ttyconsole", cmdTTYConsole, opts_ttyconsole, info_ttyconsole},
{"undefine", cmdUndefine, opts_undefine, info_undefine},
{"update-device", cmdUpdateDevice, opts_update_device, info_update_device},
{"uri", cmdURI, NULL, info_uri},
{"vol-create", cmdVolCreate, opts_vol_create, info_vol_create},
{"vol-create-from", cmdVolCreateFrom, opts_vol_create_from, info_vol_create_from},
{"vol-create-as", cmdVolCreateAs, opts_vol_create_as, info_vol_create_as},
{"vol-clone", cmdVolClone, opts_vol_clone, info_vol_clone},
{"vol-delete", cmdVolDelete, opts_vol_delete, info_vol_delete},
2010-03-02 03:10:40 +00:00
{"vol-wipe", cmdVolWipe, opts_vol_wipe, info_vol_wipe},
{"vol-dumpxml", cmdVolDumpXML, opts_vol_dumpxml, info_vol_dumpxml},
{"vol-info", cmdVolInfo, opts_vol_info, info_vol_info},
{"vol-list", cmdVolList, opts_vol_list, info_vol_list},
{"vol-path", cmdVolPath, opts_vol_path, info_vol_path},
{"vol-name", cmdVolName, opts_vol_name, info_vol_name},
{"vol-key", cmdVolKey, opts_vol_key, info_vol_key},
{"vcpuinfo", cmdVcpuinfo, opts_vcpuinfo, info_vcpuinfo},
{"vcpupin", cmdVcpupin, opts_vcpupin, info_vcpupin},
{"version", cmdVersion, NULL, info_version},
{"vncdisplay", cmdVNCDisplay, opts_vncdisplay, info_vncdisplay},
{"snapshot-create", cmdSnapshotCreate, opts_snapshot_create, info_snapshot_create},
{"snapshot-current", cmdSnapshotCurrent, opts_snapshot_current, info_snapshot_current},
{"snapshot-delete", cmdSnapshotDelete, opts_snapshot_delete, info_snapshot_delete},
{"snapshot-dumpxml", cmdSnapshotDumpXML, opts_snapshot_dumpxml, info_snapshot_dumpxml},
{"snapshot-list", cmdSnapshotList, opts_snapshot_list, info_snapshot_list},
{"snapshot-revert", cmdDomainSnapshotRevert, opts_snapshot_revert, info_snapshot_revert},
{NULL, NULL, NULL, NULL}
2005-12-08 10:23:34 +00:00
};
/* ---------------
* Utils for work with command definition
* ---------------
*/
2005-12-08 14:22:52 +00:00
static const char *
vshCmddefGetInfo(const vshCmdDef * cmd, const char *name)
{
const vshCmdInfo *info;
2005-12-08 10:23:34 +00:00
for (info = cmd->info; info && info->name; info++) {
if (STREQ(info->name, name))
2005-12-08 10:23:34 +00:00
return info->data;
}
return NULL;
}
static const vshCmdOptDef *
vshCmddefGetOption(const vshCmdDef * cmd, const char *name)
{
const vshCmdOptDef *opt;
2005-12-08 10:23:34 +00:00
for (opt = cmd->opts; opt && opt->name; opt++)
if (STREQ(opt->name, name))
2005-12-08 10:23:34 +00:00
return opt;
return NULL;
}
static const vshCmdOptDef *
vshCmddefGetData(const vshCmdDef * cmd, int data_ct)
{
const vshCmdOptDef *opt;
2005-12-08 10:23:34 +00:00
2006-01-25 09:46:22 +00:00
for (opt = cmd->opts; opt && opt->name; opt++) {
if (opt->type == VSH_OT_DATA) {
if (data_ct == 0)
2006-01-25 09:46:22 +00:00
return opt;
else
data_ct--;
}
}
2005-12-08 10:23:34 +00:00
return NULL;
}
2006-01-25 09:46:22 +00:00
/*
* Checks for required options
*/
static int
2008-08-01 13:51:18 +00:00
vshCommandCheckOpts(vshControl *ctl, const vshCmd *cmd)
2006-01-25 09:46:22 +00:00
{
const vshCmdDef *def = cmd->def;
const vshCmdOptDef *d;
int err = 0;
2006-01-25 09:46:22 +00:00
for (d = def->opts; d && d->name; d++) {
if (d->flag & VSH_OFLAG_REQ) {
vshCmdOpt *o = cmd->opts;
int ok = 0;
while (o && ok == 0) {
2006-01-25 09:46:22 +00:00
if (o->def == d)
ok = 1;
2006-01-25 09:46:22 +00:00
o = o->next;
}
if (!ok) {
vshError(ctl,
d->type == VSH_OT_DATA ?
_("command '%s' requires <%s> option") :
_("command '%s' requires --%s option"),
def->name, d->name);
2006-01-25 09:46:22 +00:00
err = 1;
}
2006-01-25 09:46:22 +00:00
}
}
return !err;
}
static const vshCmdDef *
vshCmddefSearch(const char *cmdname)
{
const vshCmdDef *c;
2005-12-08 10:23:34 +00:00
for (c = commands; c->name; c++)
if (STREQ(c->name, cmdname))
2005-12-08 10:23:34 +00:00
return c;
return NULL;
}
static int
vshCmddefHelp(vshControl *ctl, const char *cmdname)
{
const vshCmdDef *def = vshCmddefSearch(cmdname);
2005-12-08 10:23:34 +00:00
if (!def) {
vshError(ctl, _("command '%s' doesn't exist"), cmdname);
return FALSE;
} else {
const char *desc = _(vshCmddefGetInfo(def, "desc"));
const char *help = _(vshCmddefGetInfo(def, "help"));
char buf[256];
2005-12-08 10:23:34 +00:00
fputs(_(" NAME\n"), stdout);
fprintf(stdout, " %s - %s\n", def->name, help);
fputs(_("\n SYNOPSIS\n"), stdout);
fprintf(stdout, " %s", def->name);
if (def->opts) {
const vshCmdOptDef *opt;
for (opt = def->opts; opt->name; opt++) {
const char *fmt;
if (opt->type == VSH_OT_BOOL)
fmt = "[--%s]";
else if (opt->type == VSH_OT_INT)
/* xgettext:c-format */
fmt = _("[--%s <number>]");
else if (opt->type == VSH_OT_STRING)
/* xgettext:c-format */
fmt = _("[--%s <string>]");
else if (opt->type == VSH_OT_DATA)
fmt = ((opt->flag & VSH_OFLAG_REQ) ? "<%s>" : "[<%s>]");
else
assert(0);
fputc(' ', stdout);
fprintf(stdout, fmt, opt->name);
}
2005-12-08 10:23:34 +00:00
}
fputc('\n', stdout);
if (desc[0]) {
/* Print the description only if it's not empty. */
fputs(_("\n DESCRIPTION\n"), stdout);
2005-12-08 10:23:34 +00:00
fprintf(stdout, " %s\n", desc);
}
2005-12-08 10:23:34 +00:00
if (def->opts) {
const vshCmdOptDef *opt;
fputs(_("\n OPTIONS\n"), stdout);
for (opt = def->opts; opt->name; opt++) {
if (opt->type == VSH_OT_BOOL)
2005-12-08 10:23:34 +00:00
snprintf(buf, sizeof(buf), "--%s", opt->name);
else if (opt->type == VSH_OT_INT)
snprintf(buf, sizeof(buf), _("--%s <number>"), opt->name);
else if (opt->type == VSH_OT_STRING)
snprintf(buf, sizeof(buf), _("--%s <string>"), opt->name);
else if (opt->type == VSH_OT_DATA)
2005-12-08 10:23:34 +00:00
snprintf(buf, sizeof(buf), "<%s>", opt->name);
fprintf(stdout, " %-15s %s\n", buf, _(opt->help));
}
2005-12-08 10:23:34 +00:00
}
fputc('\n', stdout);
}
return TRUE;
}
/* ---------------
* Utils for work with runtime commands data
* ---------------
*/
static void
vshCommandOptFree(vshCmdOpt * arg)
{
2005-12-08 10:23:34 +00:00
vshCmdOpt *a = arg;
while (a) {
2005-12-08 10:23:34 +00:00
vshCmdOpt *tmp = a;
2005-12-08 10:23:34 +00:00
a = a->next;
VIR_FREE(tmp->data);
VIR_FREE(tmp);
2005-12-08 10:23:34 +00:00
}
}
static void
2008-08-01 13:51:18 +00:00
vshCommandFree(vshCmd *cmd)
{
2005-12-08 10:23:34 +00:00
vshCmd *c = cmd;
while (c) {
2005-12-08 10:23:34 +00:00
vshCmd *tmp = c;
2005-12-08 10:23:34 +00:00
c = c->next;
if (tmp->opts)
vshCommandOptFree(tmp->opts);
VIR_FREE(tmp);
2005-12-08 10:23:34 +00:00
}
}
/*
* Returns option by name
*/
static vshCmdOpt *
2008-08-01 13:51:18 +00:00
vshCommandOpt(const vshCmd *cmd, const char *name)
{
2005-12-08 10:23:34 +00:00
vshCmdOpt *opt = cmd->opts;
while (opt) {
if (opt->def && STREQ(opt->def->name, name))
2005-12-08 10:23:34 +00:00
return opt;
opt = opt->next;
}
return NULL;
}
/*
* Returns option as INT
*/
static int
2008-08-01 13:51:18 +00:00
vshCommandOptInt(const vshCmd *cmd, const char *name, int *found)
{
2005-12-08 10:23:34 +00:00
vshCmdOpt *arg = vshCommandOpt(cmd, name);
int res = 0, num_found = FALSE;
char *end_p = NULL;
if ((arg != NULL) && (arg->data != NULL)) {
res = strtol(arg->data, &end_p, 10);
if ((arg->data == end_p) || (*end_p!= 0))
num_found = FALSE;
else
num_found = TRUE;
}
2005-12-08 10:23:34 +00:00
if (found)
*found = num_found;
2005-12-08 10:23:34 +00:00
return res;
}
/*
* Returns option as STRING
*/
static char *
2008-08-01 13:51:18 +00:00
vshCommandOptString(const vshCmd *cmd, const char *name, int *found)
{
2005-12-08 10:23:34 +00:00
vshCmdOpt *arg = vshCommandOpt(cmd, name);
2005-12-08 10:23:34 +00:00
if (found)
*found = arg ? TRUE : FALSE;
2006-01-25 09:46:22 +00:00
return arg && arg->data && *arg->data ? arg->data : NULL;
2005-12-08 10:23:34 +00:00
}
/*
* Returns option as long long
*/
static long long
vshCommandOptLongLong(const vshCmd *cmd, const char *name, int *found)
{
vshCmdOpt *arg = vshCommandOpt(cmd, name);
int num_found = FALSE;
long long res = 0;
char *end_p = NULL;
if ((arg != NULL) && (arg->data != NULL))
num_found = !virStrToLong_ll(arg->data, &end_p, 10, &res);
if (found)
*found = num_found;
return res;
}
#if 0
static int
2008-08-01 13:51:18 +00:00
vshCommandOptStringList(const vshCmd *cmd, const char *name, char ***data)
{
vshCmdOpt *arg = cmd->opts;
char **val = NULL;
int nval = 0;
while (arg) {
if (arg->def && STREQ(arg->def->name, name)) {
char **tmp = realloc(val, sizeof(*tmp) * (nval+1));
if (!tmp) {
VIR_FREE(val);
return -1;
}
val = tmp;
val[nval++] = arg->data;
}
arg = arg->next;
}
*data = val;
return nval;
}
#endif
2005-12-08 10:23:34 +00:00
/*
* Returns TRUE/FALSE if the option exists
*/
static int
2008-08-01 13:51:18 +00:00
vshCommandOptBool(const vshCmd *cmd, const char *name)
{
2005-12-08 10:23:34 +00:00
return vshCommandOpt(cmd, name) ? TRUE : FALSE;
}
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 10:26:54 +00: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
cmd_has_option (vshControl *ctl, const vshCmd *cmd, const char *optname)
{
/* 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) {
if (STREQ (opt->def->name, optname) && opt->def->type == VSH_OT_DATA) {
found = true;
break;
}
}
if (!found)
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 10:26:54 +00:00
cmd->def->name, optname);
return found;
}
2006-01-25 09:46:22 +00:00
2005-12-15 17:00:43 +00: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 10:26:54 +00:00
vshCommandOptDomainBy(vshControl *ctl, const vshCmd *cmd,
char **name, int flag)
{
2005-12-15 17:00:43 +00:00
virDomainPtr dom = NULL;
char *n;
2005-12-15 17:00:43 +00: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 10:26:54 +00:00
const char *optname = "domain";
if (!cmd_has_option (ctl, cmd, optname))
return NULL;
2005-12-15 17:00:43 +00:00
if (!(n = vshCommandOptString(cmd, optname, NULL))) {
vshError(ctl, "%s", _("undefined domain name or id"));
return NULL;
2005-12-15 17:00:43 +00:00
}
2006-05-22 14:38:33 +00:00
vshDebug(ctl, 5, "%s: found option <%s>: %s\n",
cmd->def->name, optname, n);
2005-12-15 17:00:43 +00:00
if (name)
*name = n;
2005-12-15 17:00:43 +00:00
/* try it by ID */
if (flag & VSH_BYID) {
if (virStrToLong_i(n, NULL, 10, &id) == 0 && id >= 0) {
2006-05-29 15:39:31 +00:00
vshDebug(ctl, 5, "%s: <%s> seems like domain ID\n",
cmd->def->name, optname);
dom = virDomainLookupByID(ctl->conn, id);
}
2006-01-25 09:46:22 +00:00
}
2006-05-22 14:38:33 +00:00
/* try it by UUID */
if (dom==NULL && (flag & VSH_BYUUID) && strlen(n)==VIR_UUID_STRING_BUFLEN-1) {
vshDebug(ctl, 5, "%s: <%s> trying as domain UUID\n",
cmd->def->name, optname);
2006-05-29 15:39:31 +00:00
dom = virDomainLookupByUUIDString(ctl->conn, n);
2006-05-22 14:38:33 +00:00
}
2005-12-15 17:00:43 +00:00
/* try it by NAME */
if (dom==NULL && (flag & VSH_BYNAME)) {
vshDebug(ctl, 5, "%s: <%s> trying as domain NAME\n",
cmd->def->name, optname);
2005-12-15 17:00:43 +00:00
dom = virDomainLookupByName(ctl->conn, n);
2006-01-25 09:46:22 +00:00
}
2006-05-22 14:38:33 +00:00
if (!dom)
vshError(ctl, _("failed to get domain '%s'"), n);
2005-12-15 17:00:43 +00:00
return dom;
}
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 10:26:54 +00:00
vshCommandOptNetworkBy(vshControl *ctl, const vshCmd *cmd,
char **name, int flag)
{
virNetworkPtr network = NULL;
char *n;
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 10:26:54 +00:00
const char *optname = "network";
if (!cmd_has_option (ctl, cmd, optname))
return NULL;
if (!(n = vshCommandOptString(cmd, optname, NULL))) {
vshError(ctl, "%s", _("undefined network name"));
return NULL;
}
vshDebug(ctl, 5, "%s: found option <%s>: %s\n",
cmd->def->name, optname, n);
if (name)
*name = n;
/* try it by UUID */
if ((flag & VSH_BYUUID) && (strlen(n) == VIR_UUID_STRING_BUFLEN-1)) {
vshDebug(ctl, 5, "%s: <%s> trying as network UUID\n",
cmd->def->name, optname);
network = virNetworkLookupByUUIDString(ctl->conn, n);
}
/* try it by NAME */
if (network==NULL && (flag & VSH_BYNAME)) {
vshDebug(ctl, 5, "%s: <%s> trying as network NAME\n",
cmd->def->name, optname);
network = virNetworkLookupByName(ctl->conn, n);
}
if (!network)
vshError(ctl, _("failed to get network '%s'"), n);
return network;
}
static virNWFilterPtr
vshCommandOptNWFilterBy(vshControl *ctl, const vshCmd *cmd,
char **name, int flag)
{
virNWFilterPtr nwfilter = NULL;
char *n;
const char *optname = "nwfilter";
if (!cmd_has_option (ctl, cmd, optname))
return NULL;
if (!(n = vshCommandOptString(cmd, optname, NULL))) {
vshError(ctl, "%s", _("undefined nwfilter name"));
return NULL;
}
vshDebug(ctl, 5, "%s: found option <%s>: %s\n",
cmd->def->name, optname, n);
if (name)
*name = n;
/* try it by UUID */
if ((flag & VSH_BYUUID) && (strlen(n) == VIR_UUID_STRING_BUFLEN-1)) {
vshDebug(ctl, 5, "%s: <%s> trying as nwfilter UUID\n",
cmd->def->name, optname);
nwfilter = virNWFilterLookupByUUIDString(ctl->conn, n);
}
/* try it by NAME */
if (nwfilter == NULL && (flag & VSH_BYNAME)) {
vshDebug(ctl, 5, "%s: <%s> trying as nwfilter NAME\n",
cmd->def->name, optname);
nwfilter = virNWFilterLookupByName(ctl->conn, n);
}
if (!nwfilter)
vshError(ctl, _("failed to get nwfilter '%s'"), n);
return nwfilter;
}
static virInterfacePtr
vshCommandOptInterfaceBy(vshControl *ctl, const vshCmd *cmd,
char **name, int flag)
{
virInterfacePtr iface = NULL;
char *n;
const char *optname = "interface";
if (!cmd_has_option (ctl, cmd, optname))
return NULL;
if (!(n = vshCommandOptString(cmd, optname, NULL))) {
vshError(ctl, "%s", _("undefined interface identifier"));
return NULL;
}
vshDebug(ctl, 5, "%s: found option <%s>: %s\n",
cmd->def->name, optname, n);
if (name)
*name = n;
/* try it by NAME */
if ((flag & VSH_BYNAME)) {
vshDebug(ctl, 5, "%s: <%s> trying as interface NAME\n",
cmd->def->name, optname);
iface = virInterfaceLookupByName(ctl->conn, n);
}
/* try it by MAC */
if ((iface == NULL) && (flag & VSH_BYMAC)) {
vshDebug(ctl, 5, "%s: <%s> trying as interface MAC\n",
cmd->def->name, optname);
iface = virInterfaceLookupByMACString(ctl->conn, n);
}
if (!iface)
vshError(ctl, _("failed to get interface '%s'"), n);
return iface;
}
static virStoragePoolPtr
2008-08-01 13:51:18 +00:00
vshCommandOptPoolBy(vshControl *ctl, const vshCmd *cmd, const char *optname,
char **name, int flag)
{
virStoragePoolPtr pool = NULL;
char *n;
if (!(n = vshCommandOptString(cmd, optname, NULL))) {
vshError(ctl, "%s", _("undefined pool name"));
return NULL;
}
vshDebug(ctl, 5, "%s: found option <%s>: %s\n",
cmd->def->name, optname, n);
if (name)
*name = n;
/* try it by UUID */
if ((flag & VSH_BYUUID) && (strlen(n) == VIR_UUID_STRING_BUFLEN-1)) {
vshDebug(ctl, 5, "%s: <%s> trying as pool UUID\n",
cmd->def->name, optname);
pool = virStoragePoolLookupByUUIDString(ctl->conn, n);
}
/* try it by NAME */
if (pool == NULL && (flag & VSH_BYNAME)) {
vshDebug(ctl, 5, "%s: <%s> trying as pool NAME\n",
cmd->def->name, optname);
pool = virStoragePoolLookupByName(ctl->conn, n);
}
if (!pool)
vshError(ctl, _("failed to get pool '%s'"), n);
return pool;
}
static virStorageVolPtr
2008-08-01 13:51:18 +00:00
vshCommandOptVolBy(vshControl *ctl, const vshCmd *cmd,
const char *optname,
const char *pooloptname,
char **name, int flag)
{
virStorageVolPtr vol = NULL;
virStoragePoolPtr pool = NULL;
char *n, *p;
int found;
if (!(n = vshCommandOptString(cmd, optname, NULL))) {
vshError(ctl, "%s", _("undefined vol name"));
return NULL;
}
if (!(p = vshCommandOptString(cmd, pooloptname, &found)) && found) {
vshError(ctl, "%s", _("undefined pool name"));
return NULL;
}
if (p)
pool = vshCommandOptPoolBy(ctl, cmd, pooloptname, name, flag);
vshDebug(ctl, 5, "%s: found option <%s>: %s\n",
cmd->def->name, optname, n);
if (name)
*name = n;
/* try it by PATH */
if (pool && (flag & VSH_BYNAME)) {
vshDebug(ctl, 5, "%s: <%s> trying as vol UUID\n",
cmd->def->name, optname);
vol = virStorageVolLookupByName(pool, n);
}
if (vol == NULL && (flag & VSH_BYUUID)) {
vshDebug(ctl, 5, "%s: <%s> trying as vol key\n",
cmd->def->name, optname);
vol = virStorageVolLookupByKey(ctl->conn, n);
}
if (vol == NULL && (flag & VSH_BYUUID)) {
vshDebug(ctl, 5, "%s: <%s> trying as vol path\n",
cmd->def->name, optname);
vol = virStorageVolLookupByPath(ctl->conn, n);
}
if (!vol)
vshError(ctl, _("failed to get vol '%s'"), n);
if (pool)
virStoragePoolFree(pool);
return vol;
}
static virSecretPtr
vshCommandOptSecret(vshControl *ctl, const vshCmd *cmd, char **name)
{
virSecretPtr secret = NULL;
char *n;
const char *optname = "secret";
if (!cmd_has_option (ctl, cmd, optname))
return NULL;
n = vshCommandOptString(cmd, optname, NULL);
if (n == NULL) {
vshError(ctl, "%s", _("undefined secret UUID"));
return NULL;
}
vshDebug(ctl, 5, "%s: found option <%s>: %s\n", cmd->def->name, optname, n);
if (name != NULL)
*name = n;
secret = virSecretLookupByUUIDString(ctl->conn, n);
if (secret == NULL)
vshError(ctl, _("failed to get secret '%s'"), n);
return secret;
}
2005-12-08 10:23:34 +00:00
/*
* Executes command(s) and returns return code from last command
*/
static int
2008-08-01 13:51:18 +00:00
vshCommandRun(vshControl *ctl, const vshCmd *cmd)
{
2005-12-08 10:23:34 +00:00
int ret = TRUE;
while (cmd) {
2005-12-08 10:23:34 +00:00
struct timeval before, after;
if ((ctl->conn == NULL) || (disconnected != 0))
vshReconnect(ctl);
2005-12-08 10:23:34 +00:00
if (ctl->timing)
GETTIMEOFDAY(&before);
2005-12-08 10:23:34 +00:00
ret = cmd->def->handler(ctl, cmd);
if (ctl->timing)
GETTIMEOFDAY(&after);
2009-02-09 14:24:06 +00:00
if (ret == FALSE)
virshReportError(ctl);
/* try to automatically catch disconnections */
if ((ret == FALSE) &&
((disconnected != 0) ||
((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)))))
vshReconnect(ctl);
if (STREQ(cmd->def->name, "quit")) /* hack ... */
2005-12-08 10:23:34 +00:00
return ret;
if (ctl->timing)
vshPrint(ctl, _("\n(Time: %.3f ms)\n\n"),
DIFF_MSEC(&after, &before));
else
2006-05-22 14:38:33 +00:00
vshPrintExtra(ctl, "\n");
2005-12-08 10:23:34 +00:00
cmd = cmd->next;
}
return ret;
}
/* ---------------
* Command string parsing
* ---------------
*/
#define VSH_TK_ERROR -1
#define VSH_TK_NONE 0
#define VSH_TK_OPTION 1
#define VSH_TK_DATA 2
#define VSH_TK_END 3
static int
2008-08-01 13:51:18 +00:00
vshCommandGetToken(vshControl *ctl, char *str, char **end, char **res)
{
2005-12-08 10:23:34 +00:00
int tk = VSH_TK_NONE;
int quote = FALSE;
int sz = 0;
char *p = str;
char *tkstr = NULL;
2005-12-08 10:23:34 +00:00
*end = NULL;
while (p && *p && (*p == ' ' || *p == '\t'))
2005-12-08 10:23:34 +00:00
p++;
if (p == NULL || *p == '\0')
2005-12-08 10:23:34 +00:00
return VSH_TK_END;
if (*p == ';') {
*end = ++p; /* = \0 or begin of next command */
2005-12-08 10:23:34 +00:00
return VSH_TK_END;
}
while (*p) {
2005-12-08 10:23:34 +00:00
/* end of token is blank space or ';' */
if ((quote == FALSE && (*p == ' ' || *p == '\t')) || *p == ';')
2005-12-08 10:23:34 +00:00
break;
2006-01-25 09:46:22 +00:00
/* end of option name could be '=' */
if (tk == VSH_TK_OPTION && *p == '=') {
p++; /* skip '=' */
2006-01-25 09:46:22 +00:00
break;
}
if (tk == VSH_TK_NONE) {
if (*p == '-' && *(p + 1) == '-' && *(p + 2)
&& c_isalnum(*(p + 2))) {
2005-12-08 10:23:34 +00:00
tk = VSH_TK_OPTION;
p += 2;
2005-12-08 10:23:34 +00:00
} else {
tk = VSH_TK_DATA;
if (*p == '"') {
quote = TRUE;
2005-12-08 10:23:34 +00:00
p++;
} else {
quote = FALSE;
}
}
tkstr = p; /* begin of token */
} else if (quote && *p == '"') {
2005-12-08 10:23:34 +00:00
quote = FALSE;
p++;
break; /* end of "..." token */
2005-12-08 10:23:34 +00:00
}
p++;
sz++;
}
if (quote) {
vshError(ctl, "%s", _("missing \""));
2005-12-08 10:23:34 +00:00
return VSH_TK_ERROR;
}
if (tkstr == NULL || *tkstr == '\0' || p == NULL)
2005-12-08 10:23:34 +00:00
return VSH_TK_END;
if (sz == 0)
2005-12-08 10:23:34 +00:00
return VSH_TK_END;
*res = vshMalloc(ctl, sz + 1);
2005-12-08 10:23:34 +00:00
memcpy(*res, tkstr, sz);
*(*res + sz) = '\0';
2005-12-08 10:23:34 +00:00
*end = p;
return tk;
}
static int
2008-08-01 13:51:18 +00:00
vshCommandParse(vshControl *ctl, char *cmdstr)
{
2005-12-08 10:23:34 +00:00
char *str;
char *tkdata = NULL;
vshCmd *clast = NULL;
vshCmdOpt *first = NULL;
2005-12-08 10:23:34 +00:00
if (ctl->cmd) {
vshCommandFree(ctl->cmd);
ctl->cmd = NULL;
}
if (cmdstr == NULL || *cmdstr == '\0')
2005-12-08 10:23:34 +00:00
return FALSE;
2005-12-08 10:23:34 +00:00
str = cmdstr;
while (str && *str) {
2005-12-08 10:23:34 +00:00
vshCmdOpt *last = NULL;
const vshCmdDef *cmd = NULL;
2005-12-08 10:23:34 +00:00
int tk = VSH_TK_NONE;
2006-01-25 09:46:22 +00:00
int data_ct = 0;
2005-12-08 10:23:34 +00:00
first = NULL;
while (tk != VSH_TK_END) {
2005-12-08 10:23:34 +00:00
char *end = NULL;
const vshCmdOptDef *opt = NULL;
2005-12-08 10:23:34 +00:00
tkdata = NULL;
2005-12-08 10:23:34 +00:00
/* get token */
tk = vshCommandGetToken(ctl, str, &end, &tkdata);
2005-12-08 10:23:34 +00:00
str = end;
if (tk == VSH_TK_END) {
VIR_FREE(tkdata);
2005-12-08 10:23:34 +00:00
break;
}
if (tk == VSH_TK_ERROR)
2005-12-08 10:23:34 +00:00
goto syntaxError;
if (cmd == NULL) {
2005-12-08 10:23:34 +00:00
/* first token must be command name */
if (tk != VSH_TK_DATA) {
vshError(ctl,
_("unexpected token (command name): '%s'"),
tkdata);
2005-12-08 10:23:34 +00:00
goto syntaxError;
}
if (!(cmd = vshCmddefSearch(tkdata))) {
vshError(ctl, _("unknown command: '%s'"), tkdata);
goto syntaxError; /* ... or ignore this command only? */
2005-12-08 10:23:34 +00:00
}
VIR_FREE(tkdata);
} else if (tk == VSH_TK_OPTION) {
2005-12-08 10:23:34 +00:00
if (!(opt = vshCmddefGetOption(cmd, tkdata))) {
vshError(ctl,
_("command '%s' doesn't support option --%s"),
cmd->name, tkdata);
2005-12-08 10:23:34 +00:00
goto syntaxError;
}
VIR_FREE(tkdata); /* option name */
2005-12-08 10:23:34 +00:00
if (opt->type != VSH_OT_BOOL) {
/* option data */
tk = vshCommandGetToken(ctl, str, &end, &tkdata);
str = end;
if (tk == VSH_TK_ERROR)
2005-12-08 10:23:34 +00:00
goto syntaxError;
if (tk != VSH_TK_DATA) {
vshError(ctl,
_("expected syntax: --%s <%s>"),
opt->name,
opt->type ==
VSH_OT_INT ? _("number") : _("string"));
2005-12-08 10:23:34 +00:00
goto syntaxError;
}
}
} else if (tk == VSH_TK_DATA) {
2006-01-25 09:46:22 +00:00
if (!(opt = vshCmddefGetData(cmd, data_ct++))) {
vshError(ctl, _("unexpected data '%s'"), tkdata);
2005-12-08 10:23:34 +00:00
goto syntaxError;
}
}
if (opt) {
/* save option */
vshCmdOpt *arg = vshMalloc(ctl, sizeof(vshCmdOpt));
2005-12-08 10:23:34 +00:00
arg->def = opt;
arg->data = tkdata;
arg->next = NULL;
tkdata = NULL;
2005-12-08 10:23:34 +00:00
if (!first)
first = arg;
if (last)
last->next = arg;
last = arg;
2006-05-22 14:38:33 +00:00
vshDebug(ctl, 4, "%s: %s(%s): %s\n",
cmd->name,
opt->name,
tk == VSH_TK_OPTION ? _("OPTION") : _("DATA"),
arg->data);
2005-12-08 10:23:34 +00:00
}
if (!str)
break;
}
/* command parsed -- allocate new struct for the command */
2005-12-08 10:23:34 +00:00
if (cmd) {
vshCmd *c = vshMalloc(ctl, sizeof(vshCmd));
2005-12-08 10:23:34 +00:00
c->opts = first;
c->def = cmd;
c->next = NULL;
if (!vshCommandCheckOpts(ctl, c)) {
VIR_FREE(c);
2006-01-25 09:46:22 +00:00
goto syntaxError;
}
2005-12-08 10:23:34 +00:00
if (!ctl->cmd)
ctl->cmd = c;
if (clast)
clast->next = c;
clast = c;
}
}
2005-12-08 10:23:34 +00:00
return TRUE;
syntaxError:
if (ctl->cmd) {
2005-12-08 10:23:34 +00:00
vshCommandFree(ctl->cmd);
ctl->cmd = NULL;
}
2005-12-08 10:23:34 +00:00
if (first)
vshCommandOptFree(first);
VIR_FREE(tkdata);
return FALSE;
2005-12-08 10:23:34 +00:00
}
/* ---------------
* Misc utils
2005-12-08 10:23:34 +00:00
* ---------------
*/
2005-12-08 14:22:52 +00:00
static const char *
vshDomainStateToString(int state)
{
2005-12-08 10:23:34 +00:00
switch (state) {
case VIR_DOMAIN_RUNNING:
return N_("running");
case VIR_DOMAIN_BLOCKED:
return N_("idle");
case VIR_DOMAIN_PAUSED:
return N_("paused");
case VIR_DOMAIN_SHUTDOWN:
return N_("in shutdown");
case VIR_DOMAIN_SHUTOFF:
return N_("shut off");
case VIR_DOMAIN_CRASHED:
return N_("crashed");
default:
;/*FALLTHROUGH*/
2005-12-08 10:23:34 +00:00
}
return N_("no state"); /* = dom0 state */
2005-12-08 10:23:34 +00:00
}
static const char *
vshDomainVcpuStateToString(int state)
{
switch (state) {
case VIR_VCPU_OFFLINE:
return N_("offline");
case VIR_VCPU_BLOCKED:
return N_("idle");
case VIR_VCPU_RUNNING:
return N_("running");
default:
;/*FALLTHROUGH*/
}
return N_("no state");
}
2005-12-08 10:23:34 +00:00
static int
2008-08-01 13:51:18 +00:00
vshConnectionUsability(vshControl *ctl, virConnectPtr conn, int showerror)
{
/* TODO: use something like virConnectionState() to
* check usability of the connection
2005-12-08 10:23:34 +00:00
*/
if (!conn) {
if (showerror)
vshError(ctl, "%s", _("no valid connection"));
2005-12-08 10:23:34 +00:00
return FALSE;
}
return TRUE;
}
2006-05-22 14:38:33 +00:00
static void
2008-08-01 13:51:18 +00:00
vshDebug(vshControl *ctl, int level, const char *format, ...)
{
2006-05-22 14:38:33 +00:00
va_list ap;
va_start(ap, format);
vshOutputLogFile(ctl, VSH_ERR_DEBUG, format, ap);
va_end(ap);
2006-05-22 14:38:33 +00:00
if (level > ctl->debug)
return;
va_start(ap, format);
vfprintf(stdout, format, ap);
va_end(ap);
2005-12-08 10:23:34 +00:00
}
static void
2008-08-01 13:51:18 +00:00
vshPrintExtra(vshControl *ctl, const char *format, ...)
{
2005-12-08 10:23:34 +00:00
va_list ap;
2006-05-22 14:38:33 +00:00
if (ctl->quiet == TRUE)
2005-12-08 10:23:34 +00:00
return;
2005-12-08 10:23:34 +00:00
va_start(ap, format);
vfprintf(stdout, format, ap);
2005-12-08 10:23:34 +00:00
va_end(ap);
}
2006-05-22 14:38:33 +00:00
2005-12-08 10:23:34 +00:00
static void
vshError(vshControl *ctl, const char *format, ...)
{
2005-12-08 10:23:34 +00:00
va_list ap;
if (ctl != NULL) {
va_start(ap, format);
vshOutputLogFile(ctl, VSH_ERR_ERROR, format, ap);
va_end(ap);
}
fputs(_("error: "), stderr);
2005-12-08 10:23:34 +00:00
va_start(ap, format);
vfprintf(stderr, format, ap);
va_end(ap);
fputc('\n', stderr);
}
static void *
2008-08-01 13:51:18 +00:00
_vshMalloc(vshControl *ctl, size_t size, const char *filename, int line)
{
void *x;
if ((x = malloc(size)))
return x;
vshError(ctl, _("%s: %d: failed to allocate %d bytes"),
filename, line, (int) size);
exit(EXIT_FAILURE);
}
static void *
2008-08-01 13:51:18 +00:00
_vshCalloc(vshControl *ctl, size_t nmemb, size_t size, const char *filename, int line)
{
void *x;
if ((x = calloc(nmemb, size)))
return x;
vshError(ctl, _("%s: %d: failed to allocate %d bytes"),
filename, line, (int) (size*nmemb));
exit(EXIT_FAILURE);
}
static void *
2008-08-01 13:51:18 +00:00
_vshRealloc(vshControl *ctl, void *ptr, size_t size, const char *filename, int line)
{
void *x;
if ((x = realloc(ptr, size)))
return x;
VIR_FREE(ptr);
vshError(ctl, _("%s: %d: failed to allocate %d bytes"),
filename, line, (int) size);
exit(EXIT_FAILURE);
}
static char *
2008-08-01 13:51:18 +00:00
_vshStrdup(vshControl *ctl, const char *s, const char *filename, int line)
{
char *x;
if (s == NULL)
return(NULL);
if ((x = strdup(s)))
return x;
vshError(ctl, _("%s: %d: failed to allocate %lu bytes"),
filename, line, (unsigned long)strlen(s));
exit(EXIT_FAILURE);
}
2005-12-08 10:23:34 +00:00
/*
* Initialize connection.
2005-12-08 10:23:34 +00:00
*/
static int
2008-08-01 13:51:18 +00:00
vshInit(vshControl *ctl)
{
2005-12-08 10:23:34 +00:00
if (ctl->conn)
return FALSE;
vshOpenLogFile(ctl);
/* set up the library error handler */
virSetErrorFunc(NULL, virshErrorHandler);
/* set up the signals handlers to catch disconnections */
vshSetupSignals();
ctl->conn = virConnectOpenAuth(ctl->name,
virConnectAuthPtrDefault,
ctl->readonly ? VIR_CONNECT_RO : 0);
/* This is not necessarily fatal. All the individual commands check
* vshConnectionUsability, except ones which don't need a connection
* such as "help".
*/
if (!ctl->conn) {
virshReportError(ctl);
vshError(ctl, "%s", _("failed to connect to the hypervisor"));
return FALSE;
}
2005-12-08 10:23:34 +00:00
return TRUE;
}
#ifndef O_SYNC
# define O_SYNC 0
#endif
#define LOGFILE_FLAGS (O_WRONLY | O_APPEND | O_CREAT | O_SYNC)
/**
* 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:
vshError(ctl, "%s",
_("failed to get the log file information"));
exit(EXIT_FAILURE);
}
} else {
if (!S_ISREG(st.st_mode)) {
vshError(ctl, "%s", _("the log path is not a file"));
exit(EXIT_FAILURE);
}
}
/* log file open */
if ((ctl->log_fd = open(ctl->logfile, LOGFILE_FLAGS, FILE_MODE)) < 0) {
vshError(ctl, "%s",
_("failed to open the log file. check the log file path"));
exit(EXIT_FAILURE);
}
}
/**
* vshOutputLogFile:
*
* Outputting an error to log file.
*/
static void
vshOutputLogFile(vshControl *ctl, int log_level, const char *msg_format, va_list ap)
{
char msg_buf[MSG_BUFFER];
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);
snprintf(msg_buf, sizeof(msg_buf),
"[%d.%02d.%02d %02d:%02d:%02d ",
(1900 + stTm->tm_year),
(1 + stTm->tm_mon),
(stTm->tm_mday),
(stTm->tm_hour),
(stTm->tm_min),
(stTm->tm_sec));
snprintf(msg_buf + strlen(msg_buf), sizeof(msg_buf) - strlen(msg_buf),
"%s] ", SIGN_NAME);
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;
}
snprintf(msg_buf + strlen(msg_buf), sizeof(msg_buf) - strlen(msg_buf),
"%s ", lvl);
vsnprintf(msg_buf + strlen(msg_buf), sizeof(msg_buf) - strlen(msg_buf),
msg_format, ap);
if (msg_buf[strlen(msg_buf) - 1] != '\n')
snprintf(msg_buf + strlen(msg_buf), sizeof(msg_buf) - strlen(msg_buf), "\n");
/* write log */
if (safewrite(ctl->log_fd, msg_buf, strlen(msg_buf)) < 0) {
vshCloseLogFile(ctl);
vshError(ctl, "%s", _("failed to write the log file"));
}
}
/**
* vshCloseLogFile:
*
* Close log file.
*/
static void
vshCloseLogFile(vshControl *ctl)
{
/* log file close */
if (ctl->log_fd >= 0) {
if (close(ctl->log_fd) < 0)
vshError(ctl, _("%s: failed to write log file: %s"),
ctl->logfile ? ctl->logfile : "?", strerror (errno));
ctl->log_fd = -1;
}
if (ctl->logfile) {
VIR_FREE(ctl->logfile);
ctl->logfile = NULL;
}
}
#ifdef USE_READLINE
2005-12-08 10:23:34 +00:00
/* -----------------
* Readline stuff
* -----------------
*/
/*
2005-12-08 10:23:34 +00:00
* Generator function for command completion. STATE lets us
* know whether to start from scratch; without any state
* (i.e. STATE == 0), then we start at the top of the list.
2005-12-08 10:23:34 +00:00
*/
static char *
vshReadlineCommandGenerator(const char *text, int state)
{
2005-12-08 10:23:34 +00:00
static int list_index, len;
2005-12-08 14:22:52 +00:00
const char *name;
2005-12-08 10:23:34 +00:00
/* If this is a new word to complete, initialize now. This
* includes saving the length of TEXT for efficiency, and
* initializing the index variable to 0.
2005-12-08 10:23:34 +00:00
*/
if (!state) {
list_index = 0;
len = strlen(text);
2005-12-08 10:23:34 +00:00
}
/* Return the next name which partially matches from the
* command list.
2005-12-08 10:23:34 +00:00
*/
2005-12-08 14:22:52 +00:00
while ((name = commands[list_index].name)) {
2005-12-08 10:23:34 +00:00
list_index++;
if (STREQLEN(name, text, len))
return vshStrdup(NULL, name);
2005-12-08 10:23:34 +00:00
}
/* If no names matched, then return NULL. */
return NULL;
}
static char *
vshReadlineOptionsGenerator(const char *text, int state)
{
2005-12-08 10:23:34 +00:00
static int list_index, len;
static const vshCmdDef *cmd = NULL;
2005-12-08 14:22:52 +00:00
const char *name;
2005-12-08 10:23:34 +00:00
if (!state) {
/* determine command name */
char *p;
char *cmdname;
if (!(p = strchr(rl_line_buffer, ' ')))
return NULL;
cmdname = vshCalloc(NULL, (p - rl_line_buffer) + 1, 1);
memcpy(cmdname, rl_line_buffer, p - rl_line_buffer);
2005-12-08 10:23:34 +00:00
cmd = vshCmddefSearch(cmdname);
list_index = 0;
len = strlen(text);
VIR_FREE(cmdname);
2005-12-08 10:23:34 +00:00
}
if (!cmd)
return NULL;
if (!cmd->opts)
return NULL;
2005-12-08 14:22:52 +00:00
while ((name = cmd->opts[list_index].name)) {
const vshCmdOptDef *opt = &cmd->opts[list_index];
2005-12-08 10:23:34 +00:00
char *res;
2005-12-08 10:23:34 +00:00
list_index++;
2005-12-08 14:22:52 +00:00
if (opt->type == VSH_OT_DATA)
2005-12-08 10:23:34 +00:00
/* ignore non --option */
continue;
2005-12-08 10:23:34 +00:00
if (len > 2) {
if (STRNEQLEN(name, text + 2, len - 2))
2005-12-08 10:23:34 +00:00
continue;
}
res = vshMalloc(NULL, strlen(name) + 3);
snprintf(res, strlen(name) + 3, "--%s", name);
2005-12-08 10:23:34 +00:00
return res;
}
/* If no names matched, then return NULL. */
return NULL;
}
static char **
vshReadlineCompletion(const char *text, int start,
int end ATTRIBUTE_UNUSED)
{
2005-12-08 10:23:34 +00:00
char **matches = (char **) NULL;
if (start == 0)
2005-12-08 10:23:34 +00:00
/* command name generator */
matches = rl_completion_matches(text, vshReadlineCommandGenerator);
2005-12-08 10:23:34 +00:00
else
/* commands options */
matches = rl_completion_matches(text, vshReadlineOptionsGenerator);
2005-12-08 10:23:34 +00:00
return matches;
}
static int
vshReadlineInit(vshControl *ctl)
{
char *userdir = NULL;
2005-12-08 10:23:34 +00: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;
/* Limit the total size of the history buffer */
stifle_history(500);
/* Prepare to read/write history from/to the ~/.virsh/history file */
userdir = virGetUserDirectory(getuid());
if (userdir == NULL)
return -1;
if (virAsprintf(&ctl->historydir, "%s/.virsh", userdir) < 0) {
vshError(ctl, "%s", _("Out of memory"));
VIR_FREE(userdir);
return -1;
}
if (virAsprintf(&ctl->historyfile, "%s/history", ctl->historydir) < 0) {
vshError(ctl, "%s", _("Out of memory"));
VIR_FREE(userdir);
return -1;
}
VIR_FREE(userdir);
read_history(ctl->historyfile);
return 0;
}
static void
vshReadlineDeinit (vshControl *ctl)
{
if (ctl->historyfile != NULL) {
if (mkdir(ctl->historydir, 0755) < 0 && errno != EEXIST) {
char ebuf[1024];
vshError(ctl, _("Failed to create '%s': %s"),
ctl->historydir, virStrerror(errno, ebuf, sizeof ebuf));
} else
write_history(ctl->historyfile);
}
VIR_FREE(ctl->historydir);
VIR_FREE(ctl->historyfile);
2005-12-08 10:23:34 +00:00
}
static char *
vshReadline (vshControl *ctl ATTRIBUTE_UNUSED, const char *prompt)
{
return readline (prompt);
}
#else /* !USE_READLINE */
static int
vshReadlineInit (vshControl *ctl ATTRIBUTE_UNUSED)
{
/* empty */
return 0;
}
static void
vshReadlineDeinit (vshControl *ctl ATTRIBUTE_UNUSED)
{
/* empty */
}
static char *
vshReadline (vshControl *ctl, const char *prompt)
{
char line[1024];
char *r;
int len;
fputs (prompt, stdout);
r = fgets (line, sizeof line, stdin);
if (r == NULL) return NULL; /* EOF */
/* Chomp trailing \n */
len = strlen (r);
if (len > 0 && r[len-1] == '\n')
r[len-1] = '\0';
return vshStrdup (ctl, r);
}
#endif /* !USE_READLINE */
2005-12-08 10:23:34 +00:00
/*
* Deinitialize virsh
2005-12-08 10:23:34 +00:00
*/
static int
2008-08-01 13:51:18 +00:00
vshDeinit(vshControl *ctl)
{
vshReadlineDeinit(ctl);
vshCloseLogFile(ctl);
VIR_FREE(ctl->name);
2005-12-08 10:23:34 +00:00
if (ctl->conn) {
if (virConnectClose(ctl->conn) != 0) {
vshError(ctl, "%s", _("failed to disconnect from the hypervisor"));
2005-12-08 10:23:34 +00:00
}
}
2007-12-01 15:45:25 +00:00
virResetLastError();
2005-12-08 10:23:34 +00:00
return TRUE;
}
2005-12-08 10:23:34 +00:00
/*
* Print usage
*/
static void
vshUsage(void)
{
const vshCmdDef *cmd;
fprintf(stdout, _("\n%s [options] [commands]\n\n"
" options:\n"
" -c | --connect <uri> hypervisor connection URI\n"
" -r | --readonly connect readonly\n"
" -d | --debug <num> debug level [0-5]\n"
" -h | --help this help\n"
" -q | --quiet quiet mode\n"
" -t | --timing print timing information\n"
" -l | --log <file> output logging to file\n"
" -v | --version program version\n\n"
" commands (non interactive mode):\n"), progname);
for (cmd = commands; cmd->name; cmd++)
fprintf(stdout,
" %-15s %s\n", cmd->name, _(vshCmddefGetInfo(cmd, "help")));
fprintf(stdout, "%s",
_("\n (specify help <command> for details about the command)\n\n"));
return;
2005-12-08 10:23:34 +00:00
}
/*
* argv[]: virsh [options] [command]
*
*/
static int
2008-08-01 13:51:18 +00:00
vshParseArgv(vshControl *ctl, int argc, char **argv)
{
2005-12-08 10:23:34 +00:00
char *last = NULL;
int i, end = 0, help = 0;
int arg, idx = 0;
2005-12-08 10:23:34 +00:00
struct option opt[] = {
{"debug", 1, 0, 'd'},
{"help", 0, 0, 'h'},
{"quiet", 0, 0, 'q'},
{"timing", 0, 0, 't'},
{"version", 0, 0, 'v'},
2006-05-29 15:39:31 +00:00
{"connect", 1, 0, 'c'},
2007-03-08 13:48:22 +00:00
{"readonly", 0, 0, 'r'},
{"log", 1, 0, 'l'},
2005-12-08 10:23:34 +00:00
{0, 0, 0, 0}
};
2005-12-08 10:23:34 +00:00
if (argc < 2)
2005-12-08 14:22:52 +00:00
return TRUE;
2006-01-25 09:46:22 +00:00
/* look for begin of the command, for example:
2005-12-08 10:23:34 +00:00
* ./virsh --debug 5 -q command --cmdoption
* <--- ^ --->
* getopt() stuff | command suff
*/
for (i = 1; i < argc; i++) {
2005-12-08 10:23:34 +00:00
if (*argv[i] != '-') {
int valid = FALSE;
2005-12-08 10:23:34 +00:00
/* non "--option" argv, is it command? */
if (last) {
struct option *o;
int sz = strlen(last);
for (o = opt; o->name; o++) {
if (o->has_arg == 1){
if (sz == 2 && *(last + 1) == o->val)
/* valid virsh short option */
valid = TRUE;
else if (sz > 2 && STREQ(o->name, last + 2))
/* valid virsh long option */
valid = TRUE;
}
2005-12-08 10:23:34 +00:00
}
}
if (!valid) {
end = i;
break;
}
}
last = argv[i];
}
end = end ? end : argc;
2005-12-08 10:23:34 +00:00
/* standard (non-command) options */
while ((arg = getopt_long(end, argv, "d:hqtc:vrl:", opt, &idx)) != -1) {
switch (arg) {
case 'd':
ctl->debug = atoi(optarg);
break;
case 'h':
help = 1;
break;
case 'q':
ctl->quiet = TRUE;
break;
case 't':
ctl->timing = TRUE;
break;
case 'c':
ctl->name = vshStrdup(ctl, optarg);
break;
case 'v':
fprintf(stdout, "%s\n", VERSION);
exit(EXIT_SUCCESS);
2007-03-08 13:48:22 +00:00
case 'r':
ctl->readonly = TRUE;
break;
case 'l':
ctl->logfile = vshStrdup(ctl, optarg);
break;
default:
vshError(ctl, _("unsupported option '-%c'. See --help."), arg);
exit(EXIT_FAILURE);
2005-12-08 10:23:34 +00:00
}
}
if (help) {
if (end < argc) {
vshError(ctl, _("extra argument '%s'. See --help."), argv[end]);
exit(EXIT_FAILURE);
}
/* list all command */
vshUsage();
2005-12-08 10:23:34 +00:00
exit(EXIT_SUCCESS);
}
2005-12-08 10:23:34 +00:00
if (argc > end) {
/* parse command */
char *cmdstr;
int sz = 0, ret;
2005-12-08 10:23:34 +00:00
ctl->imode = FALSE;
for (i = end; i < argc; i++)
sz += strlen(argv[i]) + 1; /* +1 is for blank space between items */
cmdstr = vshCalloc(ctl, sz + 1, 1);
for (i = end; i < argc; i++) {
2005-12-08 10:23:34 +00:00
strncat(cmdstr, argv[i], sz);
sz -= strlen(argv[i]);
strncat(cmdstr, " ", sz--);
}
2006-05-22 14:38:33 +00:00
vshDebug(ctl, 2, "command: \"%s\"\n", cmdstr);
2005-12-08 10:23:34 +00:00
ret = vshCommandParse(ctl, cmdstr);
VIR_FREE(cmdstr);
2005-12-08 10:23:34 +00:00
return ret;
}
return TRUE;
}
int
main(int argc, char **argv)
{
vshControl _ctl, *ctl = &_ctl;
char *defaultConn;
2005-12-08 10:23:34 +00:00
int ret = TRUE;
if (!setlocale(LC_ALL, "")) {
perror("setlocale");
2009-01-29 11:49:33 +00:00
/* failure to setup locale is not fatal */
}
if (!bindtextdomain(GETTEXT_PACKAGE, LOCALEBASEDIR)) {
perror("bindtextdomain");
return -1;
}
if (!textdomain(GETTEXT_PACKAGE)) {
perror("textdomain");
return -1;
}
if (!(progname = strrchr(argv[0], '/')))
2005-12-08 10:23:34 +00:00
progname = argv[0];
else
progname++;
2005-12-08 10:23:34 +00:00
memset(ctl, 0, sizeof(vshControl));
ctl->imode = TRUE; /* default is interactive mode */
ctl->log_fd = -1; /* Initialize log file descriptor */
2005-12-08 10:23:34 +00:00
if ((defaultConn = getenv("VIRSH_DEFAULT_CONNECT_URI"))) {
ctl->name = strdup(defaultConn);
}
2007-12-01 15:45:25 +00:00
if (!vshParseArgv(ctl, argc, argv)) {
vshDeinit(ctl);
2005-12-08 10:23:34 +00:00
exit(EXIT_FAILURE);
2007-12-01 15:45:25 +00:00
}
2007-12-01 15:45:25 +00:00
if (!vshInit(ctl)) {
vshDeinit(ctl);
2005-12-08 10:23:34 +00:00
exit(EXIT_FAILURE);
2007-12-01 15:45:25 +00:00
}
2005-12-08 10:23:34 +00:00
if (!ctl->imode) {
ret = vshCommandRun(ctl, ctl->cmd);
} else {
2005-12-08 10:23:34 +00:00
/* interactive mode */
if (!ctl->quiet) {
2006-05-22 14:38:33 +00:00
vshPrint(ctl,
_("Welcome to %s, the virtualization interactive terminal.\n\n"),
progname);
vshPrint(ctl, "%s",
_("Type: 'help' for help with commands\n"
" 'quit' to quit\n\n"));
2005-12-08 10:23:34 +00:00
}
if (vshReadlineInit(ctl) < 0) {
vshDeinit(ctl);
exit(EXIT_FAILURE);
}
2005-12-08 10:23:34 +00:00
do {
const char *prompt = ctl->readonly ? VSH_PROMPT_RO : VSH_PROMPT_RW;
ctl->cmdstr =
vshReadline(ctl, prompt);
if (ctl->cmdstr == NULL)
break; /* EOF */
2005-12-08 10:23:34 +00:00
if (*ctl->cmdstr) {
#if USE_READLINE
2005-12-08 10:23:34 +00:00
add_history(ctl->cmdstr);
#endif
2005-12-08 10:23:34 +00:00
if (vshCommandParse(ctl, ctl->cmdstr))
vshCommandRun(ctl, ctl->cmd);
}
VIR_FREE(ctl->cmdstr);
} while (ctl->imode);
2005-12-08 10:23:34 +00:00
if (ctl->cmdstr == NULL)
fputc('\n', stdout); /* line break after alone prompt */
2005-12-08 10:23:34 +00:00
}
2005-12-08 10:23:34 +00:00
vshDeinit(ctl);
exit(ret ? EXIT_SUCCESS : EXIT_FAILURE);
}