2005-11-10 16:12:31 +00:00
|
|
|
/*
|
2007-01-26 11:54:29 +00:00
|
|
|
* virsh.c: a Xen shell used to exercise the libvirt API
|
2005-11-10 16:12:31 +00:00
|
|
|
*
|
2008-02-04 14:58:47 +00:00
|
|
|
* Copyright (C) 2005, 2007-2008 Red Hat, Inc.
|
2005-11-10 16:12:31 +00:00
|
|
|
*
|
|
|
|
* 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>
|
|
|
|
*
|
2005-12-08 14:22:52 +00:00
|
|
|
*
|
|
|
|
* $Id$
|
2005-11-10 16:12:31 +00:00
|
|
|
*/
|
|
|
|
|
2008-01-29 18:15:54 +00:00
|
|
|
#include <config.h>
|
2007-12-04 18:27:52 +00:00
|
|
|
|
2006-06-26 15:02:18 +00:00
|
|
|
#include "libvirt/libvirt.h"
|
|
|
|
#include "libvirt/virterror.h"
|
2005-11-10 16:12:31 +00:00
|
|
|
#include <stdio.h>
|
2005-12-08 10:23:34 +00:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdarg.h>
|
2005-12-01 16:35:42 +00:00
|
|
|
#include <unistd.h>
|
2007-05-23 15:09:19 +00:00
|
|
|
#include <errno.h>
|
2005-12-08 10:23:34 +00:00
|
|
|
#include <getopt.h>
|
2005-12-01 16:35:42 +00:00
|
|
|
#include <sys/types.h>
|
2005-12-08 14:22:52 +00:00
|
|
|
#include <sys/time.h>
|
2005-12-08 10:23:34 +00:00
|
|
|
#include <ctype.h>
|
2006-03-30 16:08:13 +00:00
|
|
|
#include <fcntl.h>
|
2006-09-29 16:23:27 +00:00
|
|
|
#include <locale.h>
|
2007-11-29 09:18:04 +00:00
|
|
|
#include <time.h>
|
2007-06-15 15:24:20 +00:00
|
|
|
#include <limits.h>
|
2007-06-05 12:06:08 +00:00
|
|
|
#include <assert.h>
|
2007-06-06 12:24:31 +00:00
|
|
|
#include <errno.h>
|
|
|
|
#include <sys/stat.h>
|
2007-08-21 10:08:12 +00:00
|
|
|
#include <inttypes.h>
|
2007-08-07 15:26:51 +00:00
|
|
|
#include <test.h>
|
2005-12-08 10:23:34 +00:00
|
|
|
|
2007-01-26 11:54:29 +00:00
|
|
|
#include <libxml/parser.h>
|
|
|
|
#include <libxml/tree.h>
|
|
|
|
#include <libxml/xpath.h>
|
|
|
|
|
2007-12-04 18:27:52 +00:00
|
|
|
#ifdef HAVE_READLINE_READLINE_H
|
2005-12-08 10:23:34 +00:00
|
|
|
#include <readline/readline.h>
|
|
|
|
#include <readline/history.h>
|
2007-12-04 18:27:52 +00:00
|
|
|
#endif
|
2005-12-08 10:23:34 +00:00
|
|
|
|
Use safewrite in place of write, in many cases.
Also add "make syntax-check" rules to ensure no new uses sneak in.
There are many uses of write like this:
if (write (fd, xml, towrite) != towrite)
return -1;
The problem is that the syscall can succeed, yet write less than
the requested number of bytes, so the caller should retry
rather than simply failing.
This patch changes most of them to use util.c's safewrite wrapper,
which encapsulates the process. Also, there were a few cases in
which the retry loop was open-coded, and I replaced those, too.
* Makefile.maint (sc_avoid_write): New rule, to avoid recurrence.
* .x-sc_avoid_write: New file. Record two legitimate exemptions.
* qemud/qemud.c (sig_handler, qemudClientWriteBuf): Use safewrite, not write.
* src/conf.c (__virConfWriteFile): Likewise.
* src/qemu_conf.c (qemudSaveConfig, qemudSaveNetworkConfig): Likewise.
* src/qemu_driver.c (qemudWaitForMonitor, qemudStartVMDaemon)
(qemudVMData, PROC_IP_FORWARD): Likewise.
* proxy/libvirt_proxy.c: Include "util.h".
(proxyWriteClientSocket): Use safewrite.
* src/test.c (testDomainSave, testDomainCoreDump): Likewise.
* src/proxy_internal.c (virProxyWriteClientSocket): Likewise.
* src/virsh.c: Include "util-lib.h".
(vshOutputLogFile): Use safewrite.
* src/console.c: Include "util-lib.h".
(vshRunConsole): Use safewrite.
2008-02-22 15:55:04 +00:00
|
|
|
#include "buf.h"
|
2007-01-26 11:54:29 +00:00
|
|
|
#include "console.h"
|
2008-01-21 15:27:14 +00:00
|
|
|
#include "util.h"
|
Use safewrite in place of write, in many cases.
Also add "make syntax-check" rules to ensure no new uses sneak in.
There are many uses of write like this:
if (write (fd, xml, towrite) != towrite)
return -1;
The problem is that the syscall can succeed, yet write less than
the requested number of bytes, so the caller should retry
rather than simply failing.
This patch changes most of them to use util.c's safewrite wrapper,
which encapsulates the process. Also, there were a few cases in
which the retry loop was open-coded, and I replaced those, too.
* Makefile.maint (sc_avoid_write): New rule, to avoid recurrence.
* .x-sc_avoid_write: New file. Record two legitimate exemptions.
* qemud/qemud.c (sig_handler, qemudClientWriteBuf): Use safewrite, not write.
* src/conf.c (__virConfWriteFile): Likewise.
* src/qemu_conf.c (qemudSaveConfig, qemudSaveNetworkConfig): Likewise.
* src/qemu_driver.c (qemudWaitForMonitor, qemudStartVMDaemon)
(qemudVMData, PROC_IP_FORWARD): Likewise.
* proxy/libvirt_proxy.c: Include "util.h".
(proxyWriteClientSocket): Use safewrite.
* src/test.c (testDomainSave, testDomainCoreDump): Likewise.
* src/proxy_internal.c (virProxyWriteClientSocket): Likewise.
* src/virsh.c: Include "util-lib.h".
(vshOutputLogFile): Use safewrite.
* src/console.c: Include "util-lib.h".
(vshRunConsole): Use safewrite.
2008-02-22 15:55:04 +00:00
|
|
|
#include "util-lib.h"
|
2005-12-08 10:23:34 +00:00
|
|
|
|
|
|
|
static char *progname;
|
|
|
|
|
|
|
|
#ifndef TRUE
|
|
|
|
#define TRUE 1
|
|
|
|
#define FALSE 0
|
|
|
|
#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)
|
|
|
|
|
2007-06-06 12:24:31 +00:00
|
|
|
/**
|
|
|
|
* The log configuration
|
|
|
|
*/
|
|
|
|
#define MSG_BUFFER 4096
|
|
|
|
#define SIGN_NAME "virsh"
|
|
|
|
#define DIR_MODE (S_IWUSR | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) /* 0755 */
|
|
|
|
#define FILE_MODE (S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH) /* 0644 */
|
|
|
|
#define LOCK_MODE (S_IWUSR | S_IRUSR) /* 0600 */
|
|
|
|
#define LVL_DEBUG "DEBUG"
|
|
|
|
#define LVL_INFO "INFO"
|
|
|
|
#define LVL_NOTICE "NOTICE"
|
|
|
|
#define LVL_WARNING "WARNING"
|
|
|
|
#define LVL_ERROR "ERROR"
|
|
|
|
|
|
|
|
/**
|
|
|
|
* vshErrorLevel:
|
|
|
|
*
|
|
|
|
* 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;
|
|
|
|
|
2006-02-27 21:34:28 +00:00
|
|
|
/*
|
|
|
|
* The error handler for virtsh
|
|
|
|
*/
|
|
|
|
static void
|
2006-03-15 12:13:25 +00:00
|
|
|
virshErrorHandler(void *unused, virErrorPtr error)
|
|
|
|
{
|
2006-02-27 21:34:28 +00:00
|
|
|
if ((unused != NULL) || (error == NULL))
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* Suppress the VIR_ERR_NO_XEN error which fails as non-root */
|
|
|
|
if ((error->code == VIR_ERR_NO_XEN) || (error->code == VIR_ERR_OK))
|
|
|
|
return;
|
|
|
|
|
|
|
|
virDefaultErrorFunc(error);
|
|
|
|
}
|
|
|
|
|
2005-12-08 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>
|
2007-02-07 13:50:18 +00:00
|
|
|
*
|
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
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2007-02-07 13:50:18 +00:00
|
|
|
* vshCmdOptType - command option type
|
2006-03-15 12:13:25 +00:00
|
|
|
*/
|
2005-12-08 10:23:34 +00:00
|
|
|
typedef enum {
|
2006-03-15 12:13:25 +00:00
|
|
|
VSH_OT_NONE = 0, /* none */
|
|
|
|
VSH_OT_BOOL, /* boolean option */
|
|
|
|
VSH_OT_STRING, /* string option */
|
|
|
|
VSH_OT_INT, /* int option */
|
|
|
|
VSH_OT_DATA /* string data (as non-option) */
|
2005-12-08 10:23:34 +00:00
|
|
|
} vshCmdOptType;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Command Option Flags
|
|
|
|
*/
|
2006-03-15 12:13:25 +00:00
|
|
|
#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
|
|
|
|
*/
|
2006-03-15 12:13:25 +00:00
|
|
|
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
|
|
|
|
*/
|
2006-03-15 12:13:25 +00:00
|
|
|
typedef struct {
|
|
|
|
const char *name; /* the name of option */
|
|
|
|
vshCmdOptType type; /* option type */
|
|
|
|
int flag; /* flags */
|
|
|
|
const char *help; /* help string */
|
2005-12-08 10:23:34 +00:00
|
|
|
} vshCmdOptDef;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* vshCmdOpt - command options
|
|
|
|
*/
|
|
|
|
typedef struct vshCmdOpt {
|
2006-03-15 12:13:25 +00:00
|
|
|
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
|
|
|
|
*/
|
2006-03-15 12:13:25 +00:00
|
|
|
typedef struct {
|
|
|
|
const char *name;
|
|
|
|
int (*handler) (vshControl *, vshCmd *); /* command handler */
|
|
|
|
vshCmdOptDef *opts; /* definition of command options */
|
|
|
|
vshCmdInfo *info; /* details about command */
|
2005-12-08 10:23:34 +00:00
|
|
|
} vshCmdDef;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* vshCmd - parsed command
|
|
|
|
*/
|
|
|
|
typedef struct __vshCmd {
|
2006-03-15 12:13:25 +00:00
|
|
|
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 */
|
2007-06-20 17:22:09 +00:00
|
|
|
virConnectPtr conn; /* connection to hypervisor (MAY BE NULL) */
|
2006-03-15 12:13:25 +00:00
|
|
|
vshCmd *cmd; /* the current command */
|
|
|
|
char *cmdstr; /* string with command */
|
2007-12-07 14:56:37 +00:00
|
|
|
#ifndef __MINGW32__
|
2006-03-15 12:13:25 +00:00
|
|
|
uid_t uid; /* process owner */
|
2007-12-07 14:56:37 +00:00
|
|
|
#endif /* __MINGW32__ */
|
2006-03-15 12:13:25 +00:00
|
|
|
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)
|
|
|
|
*/
|
2007-06-06 12:24:31 +00:00
|
|
|
char *logfile; /* log file name */
|
|
|
|
int log_fd; /* log file descriptor */
|
2005-12-08 10:23:34 +00:00
|
|
|
} __vshControl;
|
2005-11-10 16:12:31 +00:00
|
|
|
|
2005-12-02 14:16:21 +00:00
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
static vshCmdDef commands[];
|
|
|
|
|
2007-03-19 14:20:30 +00:00
|
|
|
static void vshError(vshControl * ctl, int doexit, const char *format, ...)
|
|
|
|
ATTRIBUTE_FORMAT(printf, 3, 4);
|
2006-03-15 12:13:25 +00:00
|
|
|
static int vshInit(vshControl * ctl);
|
|
|
|
static int vshDeinit(vshControl * ctl);
|
|
|
|
static void vshUsage(vshControl * ctl, const char *cmdname);
|
2007-06-06 12:24:31 +00:00
|
|
|
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
|
|
|
|
2006-03-15 12:13:25 +00:00
|
|
|
static int vshParseArgv(vshControl * ctl, int argc, char **argv);
|
2005-12-08 10:23:34 +00:00
|
|
|
|
2006-03-15 12:13:25 +00:00
|
|
|
static const char *vshCmddefGetInfo(vshCmdDef * cmd, const char *info);
|
2005-12-08 14:22:52 +00:00
|
|
|
static vshCmdDef *vshCmddefSearch(const char *cmdname);
|
2006-03-15 12:13:25 +00:00
|
|
|
static int vshCmddefHelp(vshControl * ctl, const char *name, int withprog);
|
2005-12-08 10:23:34 +00:00
|
|
|
|
2006-03-15 12:13:25 +00:00
|
|
|
static vshCmdOpt *vshCommandOpt(vshCmd * cmd, const char *name);
|
|
|
|
static int vshCommandOptInt(vshCmd * cmd, const char *name, int *found);
|
|
|
|
static char *vshCommandOptString(vshCmd * cmd, const char *name,
|
|
|
|
int *found);
|
2008-02-20 15:29:13 +00:00
|
|
|
#if 0
|
|
|
|
static int vshCommandOptStringList(vshCmd * cmd, const char *name, char ***data);
|
|
|
|
#endif
|
2006-03-15 12:13:25 +00:00
|
|
|
static int vshCommandOptBool(vshCmd * cmd, const char *name);
|
2006-05-29 15:39:31 +00:00
|
|
|
|
2007-02-14 15:44:58 +00:00
|
|
|
#define VSH_BYID (1 << 1)
|
|
|
|
#define VSH_BYUUID (1 << 2)
|
|
|
|
#define VSH_BYNAME (1 << 3)
|
2006-05-29 15:39:31 +00:00
|
|
|
|
|
|
|
static virDomainPtr vshCommandOptDomainBy(vshControl * ctl, vshCmd * cmd,
|
2007-02-07 13:50:18 +00:00
|
|
|
const char *optname, char **name, int flag);
|
2006-05-29 15:39:31 +00:00
|
|
|
|
|
|
|
/* default is lookup by Id, Name and UUID */
|
2007-02-07 13:50:18 +00:00
|
|
|
#define vshCommandOptDomain(_ctl, _cmd, _optname, _name) \
|
|
|
|
vshCommandOptDomainBy(_ctl, _cmd, _optname, _name, \
|
2007-02-14 15:44:58 +00:00
|
|
|
VSH_BYID|VSH_BYUUID|VSH_BYNAME)
|
|
|
|
|
2007-02-14 16:53:55 +00:00
|
|
|
static virNetworkPtr vshCommandOptNetworkBy(vshControl * ctl, vshCmd * cmd,
|
|
|
|
const char *optname, char **name, int flag);
|
|
|
|
|
|
|
|
/* default is lookup by Name and UUID */
|
|
|
|
#define vshCommandOptNetwork(_ctl, _cmd, _optname, _name) \
|
|
|
|
vshCommandOptNetworkBy(_ctl, _cmd, _optname, _name, \
|
|
|
|
VSH_BYUUID|VSH_BYNAME)
|
|
|
|
|
2008-02-20 15:27:08 +00:00
|
|
|
static virStoragePoolPtr vshCommandOptPoolBy(vshControl * ctl, 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)
|
|
|
|
|
|
|
|
static virStorageVolPtr vshCommandOptVolBy(vshControl * ctl, 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)
|
|
|
|
|
2007-11-08 18:00:52 +00:00
|
|
|
static void vshPrintExtra(vshControl * ctl, const char *format, ...)
|
|
|
|
ATTRIBUTE_FORMAT(printf, 2, 3);
|
|
|
|
static void vshDebug(vshControl * ctl, int level, const char *format, ...)
|
|
|
|
ATTRIBUTE_FORMAT(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);
|
2006-08-07 14:35:20 +00:00
|
|
|
static const char *vshDomainVcpuStateToString(int state);
|
2006-03-15 12:13:25 +00:00
|
|
|
static int vshConnectionUsability(vshControl * ctl, virConnectPtr conn,
|
|
|
|
int showerror);
|
2005-12-08 10:23:34 +00:00
|
|
|
|
2006-04-06 10:33:06 +00:00
|
|
|
static void *_vshMalloc(vshControl * ctl, size_t sz, const char *filename, int line);
|
|
|
|
#define vshMalloc(_ctl, _sz) _vshMalloc(_ctl, _sz, __FILE__, __LINE__)
|
|
|
|
|
|
|
|
static void *_vshCalloc(vshControl * ctl, size_t nmemb, size_t sz, const char *filename, int line);
|
|
|
|
#define vshCalloc(_ctl, _nmemb, _sz) _vshCalloc(_ctl, _nmemb, _sz, __FILE__, __LINE__)
|
|
|
|
|
2007-06-19 09:12:55 +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__)
|
|
|
|
|
2006-04-06 10:33:06 +00:00
|
|
|
static char *_vshStrdup(vshControl * ctl, const char *s, const char *filename, int line);
|
|
|
|
#define vshStrdup(_ctl, _s) _vshStrdup(_ctl, _s, __FILE__, __LINE__)
|
|
|
|
|
2007-02-14 15:44:58 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
/* ---------------
|
|
|
|
* Commands
|
|
|
|
* ---------------
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2007-02-07 13:50:18 +00:00
|
|
|
* "help" command
|
2005-12-08 10:23:34 +00:00
|
|
|
*/
|
|
|
|
static vshCmdInfo info_help[] = {
|
2006-03-15 12:13:25 +00:00
|
|
|
{"syntax", "help [<command>]"},
|
2006-09-21 15:24:37 +00:00
|
|
|
{"help", gettext_noop("print help")},
|
|
|
|
{"desc", gettext_noop("Prints global help or command specific help.")},
|
|
|
|
|
2006-03-15 12:13:25 +00:00
|
|
|
{NULL, NULL}
|
2005-12-08 10:23:34 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_help[] = {
|
2007-06-13 09:32:44 +00:00
|
|
|
{"command", VSH_OT_DATA, 0, gettext_noop("name of command")},
|
2006-03-15 12:13:25 +00:00
|
|
|
{NULL, 0, 0, NULL}
|
2005-12-08 10:23:34 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
2006-03-15 12:13:25 +00:00
|
|
|
cmdHelp(vshControl * ctl, 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) {
|
|
|
|
vshCmdDef *def;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2008-01-16 17:13:23 +00:00
|
|
|
vshPrint(ctl, "%s", _("Commands:\n\n"));
|
2006-03-15 12:13:25 +00:00
|
|
|
for (def = commands; def->name; def++)
|
2006-05-22 14:38:33 +00:00
|
|
|
vshPrint(ctl, " %-15s %s\n", def->name,
|
2007-06-15 08:18:55 +00:00
|
|
|
N_(vshCmddefGetInfo(def, "help")));
|
2005-12-08 10:23:34 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
return vshCmddefHelp(ctl, cmdname, FALSE);
|
|
|
|
}
|
|
|
|
|
2007-02-23 08:58:25 +00:00
|
|
|
/*
|
|
|
|
* "autostart" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_autostart[] = {
|
|
|
|
{"syntax", "autostart [--disable] <domain>"},
|
|
|
|
{"help", gettext_noop("autostart a domain")},
|
|
|
|
{"desc",
|
|
|
|
gettext_noop("Configure a domain to be automatically started at boot.")},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_autostart[] = {
|
|
|
|
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
|
|
|
|
{"disable", VSH_OT_BOOL, 0, gettext_noop("disable autostarting")},
|
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdAutostart(vshControl * ctl, vshCmd * cmd)
|
|
|
|
{
|
|
|
|
virDomainPtr dom;
|
|
|
|
char *name;
|
|
|
|
int autostart;
|
|
|
|
|
|
|
|
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", &name)))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
autostart = !vshCommandOptBool(cmd, "disable");
|
|
|
|
|
|
|
|
if (virDomainSetAutostart(dom, autostart) < 0) {
|
2007-04-13 08:04:08 +00:00
|
|
|
if (autostart)
|
|
|
|
vshError(ctl, FALSE, _("Failed to mark domain %s as autostarted"),
|
|
|
|
name);
|
|
|
|
else
|
|
|
|
vshError(ctl, FALSE, _("Failed to unmark domain %s as autostarted"),
|
|
|
|
name);
|
2007-02-23 08:58:25 +00:00
|
|
|
virDomainFree(dom);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2007-04-13 08:04:08 +00:00
|
|
|
if (autostart)
|
|
|
|
vshPrint(ctl, _("Domain %s marked as autostarted\n"), name);
|
|
|
|
else
|
|
|
|
vshPrint(ctl, _("Domain %s unmarked as autostarted\n"), name);
|
2007-02-23 08:58:25 +00:00
|
|
|
|
2007-06-29 13:45:50 +00:00
|
|
|
virDomainFree(dom);
|
2007-02-23 08:58:25 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
/*
|
2007-02-07 13:50:18 +00:00
|
|
|
* "connect" command
|
2005-12-08 10:23:34 +00:00
|
|
|
*/
|
|
|
|
static vshCmdInfo info_connect[] = {
|
2006-05-29 15:39:31 +00:00
|
|
|
{"syntax", "connect [name] [--readonly]"},
|
2006-09-21 15:24:37 +00:00
|
|
|
{"help", gettext_noop("(re)connect to hypervisor")},
|
2006-03-15 12:13:25 +00:00
|
|
|
{"desc",
|
2006-09-21 15:24:37 +00:00
|
|
|
gettext_noop("Connect to local hypervisor. This is built-in command after shell start up.")},
|
2006-03-15 12:13:25 +00:00
|
|
|
{NULL, NULL}
|
2005-12-08 10:23:34 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_connect[] = {
|
2006-09-21 15:24:37 +00:00
|
|
|
{"name", VSH_OT_DATA, 0, gettext_noop("hypervisor connection URI")},
|
|
|
|
{"readonly", VSH_OT_BOOL, 0, gettext_noop("read-only connection")},
|
2006-03-15 12:13:25 +00:00
|
|
|
{NULL, 0, 0, NULL}
|
2005-12-08 10:23:34 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
2006-03-15 12:13:25 +00:00
|
|
|
cmdConnect(vshControl * ctl, vshCmd * cmd)
|
|
|
|
{
|
2005-12-08 10:23:34 +00:00
|
|
|
int ro = vshCommandOptBool(cmd, "readonly");
|
2007-02-07 13:50:18 +00:00
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
if (ctl->conn) {
|
2006-03-15 12:13:25 +00:00
|
|
|
if (virConnectClose(ctl->conn) != 0) {
|
2008-01-16 17:13:23 +00:00
|
|
|
vshError(ctl, FALSE, "%s",
|
2006-09-21 15:24:37 +00:00
|
|
|
_("Failed to disconnect from the hypervisor"));
|
2005-12-08 10:23:34 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
ctl->conn = NULL;
|
|
|
|
}
|
2007-02-07 13:50:18 +00:00
|
|
|
|
2008-01-29 17:41:07 +00:00
|
|
|
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) {
|
2006-05-29 15:39:31 +00:00
|
|
|
ctl->conn = virConnectOpen(ctl->name);
|
2007-03-08 13:48:22 +00:00
|
|
|
ctl->readonly = 0;
|
|
|
|
} else {
|
2006-05-29 15:39:31 +00:00
|
|
|
ctl->conn = virConnectOpenReadOnly(ctl->name);
|
2007-03-08 13:48:22 +00:00
|
|
|
ctl->readonly = 1;
|
|
|
|
}
|
2005-12-08 10:23:34 +00:00
|
|
|
|
|
|
|
if (!ctl->conn)
|
2008-01-16 17:13:23 +00:00
|
|
|
vshError(ctl, FALSE, "%s", _("Failed to connect to the hypervisor"));
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
return ctl->conn ? TRUE : FALSE;
|
|
|
|
}
|
|
|
|
|
2007-01-26 11:54:29 +00:00
|
|
|
/*
|
2007-02-07 13:50:18 +00:00
|
|
|
* "console" command
|
2007-01-26 11:54:29 +00:00
|
|
|
*/
|
|
|
|
static vshCmdInfo info_console[] = {
|
|
|
|
{"syntax", "console <domain>"},
|
|
|
|
{"help", gettext_noop("connect to the guest console")},
|
|
|
|
{"desc",
|
|
|
|
gettext_noop("Connect the virtual serial console for the guest")},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_console[] = {
|
|
|
|
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
|
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
2007-12-07 14:56:37 +00:00
|
|
|
#ifndef __MINGW32__
|
|
|
|
|
2007-01-26 11:54:29 +00:00
|
|
|
static int
|
|
|
|
cmdConsole(vshControl * ctl, 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;
|
|
|
|
|
|
|
|
if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", NULL)))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
doc = virDomainGetXMLDesc(dom, 0);
|
|
|
|
if (!doc)
|
2007-02-07 13:50:18 +00:00
|
|
|
goto cleanup;
|
2007-01-26 11:54:29 +00:00
|
|
|
|
|
|
|
xml = xmlReadDoc((const xmlChar *) doc, "domain.xml", NULL,
|
2007-02-07 13:50:18 +00:00
|
|
|
XML_PARSE_NOENT | XML_PARSE_NONET |
|
|
|
|
XML_PARSE_NOWARNING);
|
2007-01-26 11:54:29 +00:00
|
|
|
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) &&
|
2007-02-07 13:50:18 +00:00
|
|
|
(obj->stringval != NULL) && (obj->stringval[0] != 0))) {
|
2007-01-28 19:47:36 +00:00
|
|
|
if (vshRunConsole((const char *)obj->stringval) == 0)
|
2007-01-26 11:54:29 +00:00
|
|
|
ret = TRUE;
|
|
|
|
} else {
|
2008-01-16 17:13:23 +00:00
|
|
|
vshPrintExtra(ctl, "%s", _("No console available for domain\n"));
|
2007-01-26 11:54:29 +00:00
|
|
|
}
|
|
|
|
xmlXPathFreeObject(obj);
|
|
|
|
|
|
|
|
cleanup:
|
2008-01-29 18:23:43 +00:00
|
|
|
xmlXPathFreeContext(ctxt);
|
2007-01-26 11:54:29 +00:00
|
|
|
if (xml)
|
|
|
|
xmlFreeDoc(xml);
|
|
|
|
virDomainFree(dom);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2007-12-07 14:56:37 +00:00
|
|
|
#else /* __MINGW32__ */
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdConsole(vshControl * ctl, vshCmd * cmd ATTRIBUTE_UNUSED)
|
|
|
|
{
|
2008-01-16 17:13:23 +00:00
|
|
|
vshError (ctl, FALSE, "%s", _("console not implemented on this platform"));
|
2007-12-07 14:56:37 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* __MINGW32__ */
|
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
/*
|
|
|
|
* "list" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_list[] = {
|
2007-01-23 12:28:38 +00:00
|
|
|
{"syntax", "list [--inactive | --all]"},
|
2006-09-21 15:24:37 +00:00
|
|
|
{"help", gettext_noop("list domains")},
|
|
|
|
{"desc", gettext_noop("Returns list of domains.")},
|
2006-03-15 12:13:25 +00:00
|
|
|
{NULL, NULL}
|
2005-12-08 10:23:34 +00:00
|
|
|
};
|
|
|
|
|
2006-08-30 14:32:32 +00:00
|
|
|
static vshCmdOptDef opts_list[] = {
|
2006-09-21 15:24:37 +00:00
|
|
|
{"inactive", VSH_OT_BOOL, 0, gettext_noop("list inactive domains")},
|
|
|
|
{"all", VSH_OT_BOOL, 0, gettext_noop("list inactive & active domains")},
|
2006-08-30 14:32:32 +00:00
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
|
|
|
|
static int
|
2006-03-15 12:13:25 +00:00
|
|
|
cmdList(vshControl * ctl, vshCmd * cmd ATTRIBUTE_UNUSED)
|
|
|
|
{
|
2006-08-30 14:32:32 +00:00
|
|
|
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;
|
2006-08-30 14:32:32 +00:00
|
|
|
int maxname = 0;
|
|
|
|
inactive |= all;
|
2005-12-08 10:23:34 +00:00
|
|
|
|
|
|
|
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
|
|
|
return FALSE;
|
2007-02-07 13:50:18 +00:00
|
|
|
|
2006-08-30 14:32:32 +00:00
|
|
|
if (active) {
|
2007-02-07 13:50:18 +00:00
|
|
|
maxid = virConnectNumOfDomains(ctl->conn);
|
|
|
|
if (maxid < 0) {
|
2008-01-16 17:13:23 +00:00
|
|
|
vshError(ctl, FALSE, "%s", _("Failed to list active domains"));
|
2007-02-07 13:50:18 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
if (maxid) {
|
|
|
|
ids = vshMalloc(ctl, sizeof(int) * maxid);
|
|
|
|
|
|
|
|
if ((maxid = virConnectListDomains(ctl->conn, &ids[0], maxid)) < 0) {
|
2008-01-16 17:13:23 +00:00
|
|
|
vshError(ctl, FALSE, "%s", _("Failed to list active domains"));
|
2007-02-07 13:50:18 +00:00
|
|
|
free(ids);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2007-02-14 15:44:58 +00:00
|
|
|
qsort(&ids[0], maxid, sizeof(int), idsorter);
|
2006-08-25 22:40:33 +00:00
|
|
|
}
|
2006-08-30 14:32:32 +00:00
|
|
|
}
|
|
|
|
if (inactive) {
|
2007-02-07 13:50:18 +00:00
|
|
|
maxname = virConnectNumOfDefinedDomains(ctl->conn);
|
|
|
|
if (maxname < 0) {
|
2008-01-16 17:13:23 +00:00
|
|
|
vshError(ctl, FALSE, "%s", _("Failed to list inactive domains"));
|
2008-01-29 17:41:07 +00:00
|
|
|
free(ids);
|
2007-02-07 13:50:18 +00:00
|
|
|
return FALSE;
|
2006-08-30 14:32:32 +00:00
|
|
|
}
|
2007-02-07 13:50:18 +00:00
|
|
|
if (maxname) {
|
|
|
|
names = vshMalloc(ctl, sizeof(char *) * maxname);
|
|
|
|
|
|
|
|
if ((maxname = virConnectListDefinedDomains(ctl->conn, names, maxname)) < 0) {
|
2008-01-16 17:13:23 +00:00
|
|
|
vshError(ctl, FALSE, "%s", _("Failed to list inactive domains"));
|
2008-01-29 17:41:07 +00:00
|
|
|
free(ids);
|
2007-02-07 13:50:18 +00:00
|
|
|
free(names);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2006-09-03 17:34:04 +00:00
|
|
|
|
2007-02-14 15:44:58 +00:00
|
|
|
qsort(&names[0], maxname, sizeof(char*), namesorter);
|
2007-02-07 13:50:18 +00:00
|
|
|
}
|
2006-08-21 17:58:09 +00:00
|
|
|
}
|
2006-09-21 15:24:37 +00:00
|
|
|
vshPrintExtra(ctl, "%3s %-20s %s\n", _("Id"), _("Name"), _("State"));
|
2006-05-22 14:38:33 +00:00
|
|
|
vshPrintExtra(ctl, "----------------------------------\n");
|
2006-03-15 12:13:25 +00:00
|
|
|
|
|
|
|
for (i = 0; i < maxid; i++) {
|
2005-12-08 10:23:34 +00:00
|
|
|
virDomainInfo info;
|
|
|
|
virDomainPtr dom = virDomainLookupByID(ctl->conn, ids[i]);
|
2007-02-23 08:58:25 +00:00
|
|
|
const char *state;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
|
|
|
/* this kind of work with domains is not atomic operation */
|
2005-12-08 10:23:34 +00:00
|
|
|
if (!dom)
|
|
|
|
continue;
|
2007-02-23 08:58:25 +00:00
|
|
|
|
|
|
|
if (virDomainGetInfo(dom, &info) < 0)
|
|
|
|
state = _("no state");
|
|
|
|
else
|
2007-06-15 08:18:55 +00:00
|
|
|
state = N_(vshDomainStateToString(info.state));
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2006-05-22 14:38:33 +00:00
|
|
|
vshPrint(ctl, "%3d %-20s %s\n",
|
2006-03-15 12:13:25 +00:00
|
|
|
virDomainGetID(dom),
|
|
|
|
virDomainGetName(dom),
|
2007-02-23 08:58:25 +00:00
|
|
|
state);
|
2005-12-08 23:01:48 +00:00
|
|
|
virDomainFree(dom);
|
2005-12-08 10:23:34 +00:00
|
|
|
}
|
2006-08-30 14:32:32 +00:00
|
|
|
for (i = 0; i < maxname; i++) {
|
|
|
|
virDomainInfo info;
|
|
|
|
virDomainPtr dom = virDomainLookupByName(ctl->conn, names[i]);
|
2007-02-23 08:58:25 +00:00
|
|
|
const char *state;
|
2006-08-30 14:32:32 +00:00
|
|
|
|
|
|
|
/* this kind of work with domains is not atomic operation */
|
2007-01-23 12:28:38 +00:00
|
|
|
if (!dom) {
|
2007-02-07 13:50:18 +00:00
|
|
|
free(names[i]);
|
2006-08-30 14:32:32 +00:00
|
|
|
continue;
|
2007-02-07 13:50:18 +00:00
|
|
|
}
|
2007-02-23 08:58:25 +00:00
|
|
|
|
|
|
|
if (virDomainGetInfo(dom, &info) < 0)
|
|
|
|
state = _("no state");
|
|
|
|
else
|
2007-06-15 08:18:55 +00:00
|
|
|
state = N_(vshDomainStateToString(info.state));
|
2007-02-23 08:58:25 +00:00
|
|
|
|
|
|
|
vshPrint(ctl, "%3s %-20s %s\n", "-", names[i], state);
|
2006-09-21 15:24:37 +00:00
|
|
|
|
2006-08-30 14:32:32 +00:00
|
|
|
virDomainFree(dom);
|
2007-02-07 13:50:18 +00:00
|
|
|
free(names[i]);
|
2006-08-30 14:32:32 +00:00
|
|
|
}
|
2008-01-29 17:41:07 +00:00
|
|
|
free(ids);
|
|
|
|
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
|
|
|
*/
|
2006-04-04 21:52:31 +00:00
|
|
|
static vshCmdInfo info_domstate[] = {
|
|
|
|
{"syntax", "domstate <domain>"},
|
2006-09-21 15:24:37 +00:00
|
|
|
{"help", gettext_noop("domain state")},
|
2008-03-13 09:21:41 +00:00
|
|
|
{"desc", gettext_noop("Returns state about a domain.")},
|
2006-03-15 12:13:25 +00:00
|
|
|
{NULL, NULL}
|
2005-12-08 10:23:34 +00:00
|
|
|
};
|
|
|
|
|
2006-04-04 21:52:31 +00:00
|
|
|
static vshCmdOptDef opts_domstate[] = {
|
2006-09-21 15:24:37 +00:00
|
|
|
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
|
2006-03-15 12:13:25 +00:00
|
|
|
{NULL, 0, 0, NULL}
|
2005-12-08 10:23:34 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
2006-04-04 21:52:31 +00:00
|
|
|
cmdDomstate(vshControl * ctl, vshCmd * cmd)
|
2006-03-15 12:13:25 +00:00
|
|
|
{
|
2005-12-05 18:14:37 +00:00
|
|
|
virDomainInfo info;
|
2005-12-08 10:23:34 +00:00
|
|
|
virDomainPtr dom;
|
2005-12-15 17:00:43 +00:00
|
|
|
int ret = TRUE;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
|
|
|
return FALSE;
|
2005-12-05 18:14:37 +00:00
|
|
|
|
2005-12-15 17:00:43 +00:00
|
|
|
if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", NULL)))
|
2005-12-08 10:23:34 +00:00
|
|
|
return FALSE;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
|
|
|
if (virDomainGetInfo(dom, &info) == 0)
|
2006-05-22 14:38:33 +00:00
|
|
|
vshPrint(ctl, "%s\n",
|
2007-06-15 08:18:55 +00:00
|
|
|
N_(vshDomainStateToString(info.state)));
|
2005-12-08 10:23:34 +00:00
|
|
|
else
|
|
|
|
ret = FALSE;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-08 23:01:48 +00:00
|
|
|
virDomainFree(dom);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2007-08-21 10:08:12 +00:00
|
|
|
/* "domblkstat" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_domblkstat[] = {
|
|
|
|
{"syntax", "domblkstat <domain> <dev>"},
|
|
|
|
{"help", gettext_noop("get device block stats for a domain")},
|
|
|
|
{"desc", gettext_noop("Get device block stats for a running domain.")},
|
|
|
|
{NULL,NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_domblkstat[] = {
|
|
|
|
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
|
|
|
|
{"device", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("block device")},
|
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdDomblkstat (vshControl *ctl, vshCmd *cmd)
|
|
|
|
{
|
|
|
|
virDomainPtr dom;
|
|
|
|
char *name, *device;
|
|
|
|
struct _virDomainBlockStats stats;
|
|
|
|
|
|
|
|
if (!vshConnectionUsability (ctl, ctl->conn, TRUE))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (!(dom = vshCommandOptDomain (ctl, cmd, "domain", &name)))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (!(device = vshCommandOptString (cmd, "device", NULL)))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (virDomainBlockStats (dom, device, &stats, sizeof stats) == -1) {
|
|
|
|
vshError (ctl, FALSE, _("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 vshCmdInfo info_domifstat[] = {
|
|
|
|
{"syntax", "domifstat <domain> <dev>"},
|
|
|
|
{"help", gettext_noop("get network interface stats for a domain")},
|
|
|
|
{"desc", gettext_noop("Get network interface stats for a running domain.")},
|
|
|
|
{NULL,NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_domifstat[] = {
|
|
|
|
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
|
|
|
|
{"interface", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("interface device")},
|
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdDomIfstat (vshControl *ctl, vshCmd *cmd)
|
|
|
|
{
|
|
|
|
virDomainPtr dom;
|
|
|
|
char *name, *device;
|
|
|
|
struct _virDomainInterfaceStats stats;
|
|
|
|
|
|
|
|
if (!vshConnectionUsability (ctl, ctl->conn, TRUE))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (!(dom = vshCommandOptDomain (ctl, cmd, "domain", &name)))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (!(device = vshCommandOptString (cmd, "interface", NULL)))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (virDomainInterfaceStats (dom, device, &stats, sizeof stats) == -1) {
|
|
|
|
vshError (ctl, FALSE, _("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;
|
|
|
|
}
|
|
|
|
|
2005-12-08 23:01:48 +00:00
|
|
|
/*
|
|
|
|
* "suspend" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_suspend[] = {
|
2006-03-15 12:13:25 +00:00
|
|
|
{"syntax", "suspend <domain>"},
|
2006-09-21 15:24:37 +00:00
|
|
|
{"help", gettext_noop("suspend a domain")},
|
|
|
|
{"desc", gettext_noop("Suspend a running domain.")},
|
2006-03-15 12:13:25 +00:00
|
|
|
{NULL, NULL}
|
2005-12-08 23:01:48 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_suspend[] = {
|
2006-09-21 15:24:37 +00:00
|
|
|
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
|
2006-03-15 12:13:25 +00:00
|
|
|
{NULL, 0, 0, NULL}
|
2005-12-08 23:01:48 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
2006-03-15 12:13:25 +00:00
|
|
|
cmdSuspend(vshControl * ctl, vshCmd * cmd)
|
|
|
|
{
|
2005-12-08 23:01:48 +00:00
|
|
|
virDomainPtr dom;
|
2005-12-15 17:00:43 +00:00
|
|
|
char *name;
|
|
|
|
int ret = TRUE;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-08 23:01:48 +00:00
|
|
|
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
|
|
|
return FALSE;
|
|
|
|
|
2005-12-15 17:00:43 +00:00
|
|
|
if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", &name)))
|
2005-12-08 23:01:48 +00:00
|
|
|
return FALSE;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
|
|
|
if (virDomainSuspend(dom) == 0) {
|
2006-09-21 15:24:37 +00:00
|
|
|
vshPrint(ctl, _("Domain %s suspended\n"), name);
|
2005-12-08 23:01:48 +00:00
|
|
|
} else {
|
2006-09-21 15:24:37 +00:00
|
|
|
vshError(ctl, FALSE, _("Failed to suspend domain %s"), name);
|
2005-12-08 23:01:48 +00:00
|
|
|
ret = FALSE;
|
|
|
|
}
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-08 23:01:48 +00:00
|
|
|
virDomainFree(dom);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2006-03-30 16:08:13 +00:00
|
|
|
/*
|
|
|
|
* "create" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_create[] = {
|
|
|
|
{"syntax", "create a domain from an XML <file>"},
|
2006-09-21 15:24:37 +00:00
|
|
|
{"help", gettext_noop("create a domain from an XML file")},
|
|
|
|
{"desc", gettext_noop("Create a domain.")},
|
2006-03-30 16:08:13 +00:00
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_create[] = {
|
2007-06-15 08:18:55 +00:00
|
|
|
{"file", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("file containing an XML domain description")},
|
2006-03-30 16:08:13 +00:00
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdCreate(vshControl * ctl, vshCmd * cmd)
|
|
|
|
{
|
|
|
|
virDomainPtr dom;
|
|
|
|
char *from;
|
|
|
|
int found;
|
|
|
|
int ret = TRUE;
|
2007-05-23 15:09:19 +00:00
|
|
|
char *buffer;
|
2006-03-30 16:08:13 +00:00
|
|
|
|
|
|
|
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;
|
2007-05-23 15:09:19 +00:00
|
|
|
|
|
|
|
dom = virDomainCreateLinux(ctl->conn, buffer, 0);
|
|
|
|
free (buffer);
|
|
|
|
|
2006-03-30 16:08:13 +00:00
|
|
|
if (dom != NULL) {
|
2006-09-21 15:24:37 +00:00
|
|
|
vshPrint(ctl, _("Domain %s created from %s\n"),
|
2006-03-30 16:08:13 +00:00
|
|
|
virDomainGetName(dom), from);
|
2007-06-29 13:45:50 +00:00
|
|
|
virDomainFree(dom);
|
2006-03-30 16:08:13 +00:00
|
|
|
} else {
|
2006-09-21 15:24:37 +00:00
|
|
|
vshError(ctl, FALSE, _("Failed to create domain from %s"), from);
|
2006-03-30 16:08:13 +00:00
|
|
|
ret = FALSE;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2006-08-30 14:32:32 +00:00
|
|
|
/*
|
|
|
|
* "define" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_define[] = {
|
|
|
|
{"syntax", "define a domain from an XML <file>"},
|
2006-09-21 15:24:37 +00:00
|
|
|
{"help", gettext_noop("define (but don't start) a domain from an XML file")},
|
|
|
|
{"desc", gettext_noop("Define a domain.")},
|
2006-08-30 14:32:32 +00:00
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_define[] = {
|
2007-04-10 18:40:50 +00:00
|
|
|
{"file", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("file containing an XML domain description")},
|
2006-08-30 14:32:32 +00:00
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdDefine(vshControl * ctl, vshCmd * cmd)
|
|
|
|
{
|
|
|
|
virDomainPtr dom;
|
|
|
|
char *from;
|
|
|
|
int found;
|
|
|
|
int ret = TRUE;
|
2007-05-23 15:09:19 +00:00
|
|
|
char *buffer;
|
2006-08-30 14:32:32 +00:00
|
|
|
|
|
|
|
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;
|
2007-05-23 15:09:19 +00:00
|
|
|
|
|
|
|
dom = virDomainDefineXML(ctl->conn, buffer);
|
|
|
|
free (buffer);
|
|
|
|
|
2006-08-30 14:32:32 +00:00
|
|
|
if (dom != NULL) {
|
2006-09-21 15:24:37 +00:00
|
|
|
vshPrint(ctl, _("Domain %s defined from %s\n"),
|
2006-08-30 14:32:32 +00:00
|
|
|
virDomainGetName(dom), from);
|
2007-06-29 13:45:50 +00:00
|
|
|
virDomainFree(dom);
|
2006-08-30 14:32:32 +00:00
|
|
|
} else {
|
2006-09-21 15:24:37 +00:00
|
|
|
vshError(ctl, FALSE, _("Failed to define domain from %s"), from);
|
2006-08-30 14:32:32 +00:00
|
|
|
ret = FALSE;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* "undefine" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_undefine[] = {
|
|
|
|
{"syntax", "undefine <domain>"},
|
2006-09-21 15:24:37 +00:00
|
|
|
{"help", gettext_noop("undefine an inactive domain")},
|
|
|
|
{"desc", gettext_noop("Undefine the configuration for an inactive domain.")},
|
2006-08-30 14:32:32 +00:00
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_undefine[] = {
|
2006-09-21 15:24:37 +00:00
|
|
|
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name or uuid")},
|
2006-08-30 14:32:32 +00:00
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdUndefine(vshControl * ctl, vshCmd * cmd)
|
|
|
|
{
|
|
|
|
virDomainPtr dom;
|
|
|
|
int ret = TRUE;
|
|
|
|
char *name;
|
|
|
|
|
|
|
|
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", &name)))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (virDomainUndefine(dom) == 0) {
|
2006-09-21 15:24:37 +00:00
|
|
|
vshPrint(ctl, _("Domain %s has been undefined\n"), name);
|
2006-08-30 14:32:32 +00:00
|
|
|
} else {
|
2006-09-21 15:24:37 +00:00
|
|
|
vshError(ctl, FALSE, _("Failed to undefine domain %s"), name);
|
2006-08-30 14:32:32 +00:00
|
|
|
ret = FALSE;
|
|
|
|
}
|
|
|
|
|
2007-06-29 13:45:50 +00:00
|
|
|
virDomainFree(dom);
|
2006-08-30 14:32:32 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* "start" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_start[] = {
|
2007-01-23 12:28:38 +00:00
|
|
|
{"syntax", "start <domain>"},
|
2006-09-21 15:24:37 +00:00
|
|
|
{"help", gettext_noop("start a (previously defined) inactive domain")},
|
|
|
|
{"desc", gettext_noop("Start a domain.")},
|
2006-08-30 14:32:32 +00:00
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_start[] = {
|
2006-09-21 15:24:37 +00:00
|
|
|
{"name", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("name of the inactive domain")},
|
2006-08-30 14:32:32 +00:00
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdStart(vshControl * ctl, vshCmd * cmd)
|
|
|
|
{
|
|
|
|
virDomainPtr dom;
|
|
|
|
int ret = TRUE;
|
|
|
|
|
|
|
|
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
|
|
|
return FALSE;
|
|
|
|
|
2007-02-23 10:27:53 +00:00
|
|
|
if (!(dom = vshCommandOptDomainBy(ctl, cmd, "name", NULL, VSH_BYNAME)))
|
2006-08-30 14:32:32 +00:00
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (virDomainGetID(dom) != (unsigned int)-1) {
|
2008-01-16 17:13:23 +00:00
|
|
|
vshError(ctl, FALSE, "%s", _("Domain is already active"));
|
2007-06-29 13:45:50 +00:00
|
|
|
virDomainFree(dom);
|
2006-08-30 14:32:32 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virDomainCreate(dom) == 0) {
|
2006-09-21 15:24:37 +00:00
|
|
|
vshPrint(ctl, _("Domain %s started\n"),
|
2007-02-23 10:27:53 +00:00
|
|
|
virDomainGetName(dom));
|
2006-08-30 14:32:32 +00:00
|
|
|
} else {
|
2007-02-23 10:27:53 +00:00
|
|
|
vshError(ctl, FALSE, _("Failed to start domain %s"),
|
|
|
|
virDomainGetName(dom));
|
2006-08-30 14:32:32 +00:00
|
|
|
ret = FALSE;
|
|
|
|
}
|
2007-06-29 13:45:50 +00:00
|
|
|
virDomainFree(dom);
|
2006-08-30 14:32:32 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2006-01-20 10:00:08 +00:00
|
|
|
/*
|
|
|
|
* "save" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_save[] = {
|
2006-03-15 12:13:25 +00:00
|
|
|
{"syntax", "save <domain> <file>"},
|
2006-09-21 15:24:37 +00:00
|
|
|
{"help", gettext_noop("save a domain state to a file")},
|
|
|
|
{"desc", gettext_noop("Save a running domain.")},
|
2006-03-15 12:13:25 +00:00
|
|
|
{NULL, NULL}
|
2006-01-20 10:00:08 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_save[] = {
|
2006-09-21 15:24:37 +00:00
|
|
|
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
|
|
|
|
{"file", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("where to save the data")},
|
2006-03-15 12:13:25 +00:00
|
|
|
{NULL, 0, 0, NULL}
|
2006-01-20 10:00:08 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
2006-03-15 12:13:25 +00:00
|
|
|
cmdSave(vshControl * ctl, vshCmd * cmd)
|
|
|
|
{
|
2006-01-20 10:00:08 +00:00
|
|
|
virDomainPtr dom;
|
|
|
|
char *name;
|
|
|
|
char *to;
|
|
|
|
int ret = TRUE;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2006-01-20 10:00:08 +00:00
|
|
|
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
|
|
|
return FALSE;
|
|
|
|
|
2006-01-25 09:46:22 +00:00
|
|
|
if (!(to = vshCommandOptString(cmd, "file", NULL)))
|
2006-01-20 10:00:08 +00:00
|
|
|
return FALSE;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2006-01-20 10:00:08 +00:00
|
|
|
if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", &name)))
|
|
|
|
return FALSE;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
|
|
|
if (virDomainSave(dom, to) == 0) {
|
2006-09-21 15:24:37 +00:00
|
|
|
vshPrint(ctl, _("Domain %s saved to %s\n"), name, to);
|
2006-01-20 10:00:08 +00:00
|
|
|
} else {
|
2006-09-21 15:24:37 +00:00
|
|
|
vshError(ctl, FALSE, _("Failed to save domain %s to %s"), name, to);
|
2006-01-20 10:00:08 +00:00
|
|
|
ret = FALSE;
|
|
|
|
}
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2006-01-20 10:00:08 +00:00
|
|
|
virDomainFree(dom);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2007-06-05 12:06:08 +00:00
|
|
|
/*
|
|
|
|
* "schedinfo" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_schedinfo[] = {
|
2007-08-14 07:07:57 +00:00
|
|
|
{"syntax", "schedinfo <domain>"},
|
2007-06-05 12:06:08 +00:00
|
|
|
{"help", gettext_noop("show/set scheduler parameters")},
|
|
|
|
{"desc", gettext_noop("Show/Set scheduler parameters.")},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_schedinfo[] = {
|
|
|
|
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
|
|
|
|
{"weight", VSH_OT_INT, VSH_OFLAG_NONE, gettext_noop("weight for XEN_CREDIT")},
|
|
|
|
{"cap", VSH_OT_INT, VSH_OFLAG_NONE, gettext_noop("cap for XEN_CREDIT")},
|
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdSchedinfo(vshControl * ctl, vshCmd * cmd)
|
|
|
|
{
|
|
|
|
char *schedulertype;
|
|
|
|
virDomainPtr dom;
|
2007-08-21 11:53:52 +00:00
|
|
|
virSchedParameterPtr params = NULL;
|
2007-06-05 12:06:08 +00:00
|
|
|
int i, ret;
|
|
|
|
int nparams = 0;
|
|
|
|
int nr_inputparams = 0;
|
|
|
|
int inputparams = 0;
|
|
|
|
int weightfound = 0;
|
2007-11-08 18:07:02 +00:00
|
|
|
int weight = 0;
|
2007-06-05 12:06:08 +00:00
|
|
|
int capfound = 0;
|
2007-11-08 18:07:02 +00:00
|
|
|
int cap = 0;
|
2007-06-05 12:06:08 +00:00
|
|
|
char str_weight[] = "weight";
|
|
|
|
char str_cap[] = "cap";
|
2007-08-21 11:53:52 +00:00
|
|
|
int ret_val = FALSE;
|
2007-06-05 12:06:08 +00:00
|
|
|
|
|
|
|
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", NULL)))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
/* Currently supports Xen Credit only */
|
2007-11-06 09:41:18 +00:00
|
|
|
if(vshCommandOptBool(cmd, "weight")) {
|
|
|
|
weight = vshCommandOptInt(cmd, "weight", &weightfound);
|
|
|
|
if (!weightfound) {
|
2008-01-16 17:13:23 +00:00
|
|
|
vshError(ctl, FALSE, "%s", _("Invalid value of weight"));
|
2007-11-06 09:41:18 +00:00
|
|
|
goto cleanup;
|
|
|
|
} else {
|
|
|
|
nr_inputparams++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(vshCommandOptBool(cmd, "cap")) {
|
|
|
|
cap = vshCommandOptInt(cmd, "cap", &capfound);
|
|
|
|
if (!capfound) {
|
2008-01-16 17:13:23 +00:00
|
|
|
vshError(ctl, FALSE, "%s", _("Invalid value of cap"));
|
2007-11-06 09:41:18 +00:00
|
|
|
goto cleanup;
|
|
|
|
} else {
|
|
|
|
nr_inputparams++;
|
|
|
|
}
|
|
|
|
}
|
2007-06-05 12:06:08 +00:00
|
|
|
|
|
|
|
params = vshMalloc(ctl, sizeof (virSchedParameter) * nr_inputparams);
|
2007-06-29 13:45:50 +00:00
|
|
|
if (params == NULL) {
|
2007-08-21 11:53:52 +00:00
|
|
|
goto cleanup;
|
2007-06-29 13:45:50 +00:00
|
|
|
}
|
2007-06-05 12:06:08 +00:00
|
|
|
|
|
|
|
if (weightfound) {
|
|
|
|
strncpy(params[inputparams].field,str_weight,sizeof(str_weight));
|
|
|
|
params[inputparams].type = VIR_DOMAIN_SCHED_FIELD_UINT;
|
|
|
|
params[inputparams].value.ui = weight;
|
2008-02-05 19:27:37 +00:00
|
|
|
inputparams++;
|
2007-06-05 12:06:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (capfound) {
|
|
|
|
strncpy(params[inputparams].field,str_cap,sizeof(str_cap));
|
|
|
|
params[inputparams].type = VIR_DOMAIN_SCHED_FIELD_UINT;
|
|
|
|
params[inputparams].value.ui = cap;
|
|
|
|
inputparams++;
|
|
|
|
}
|
|
|
|
/* End Currently supports Xen Credit only */
|
|
|
|
|
|
|
|
assert (inputparams == nr_inputparams);
|
|
|
|
|
|
|
|
/* Set SchedulerParameters */
|
|
|
|
if (inputparams > 0) {
|
|
|
|
ret = virDomainSetSchedulerParameters(dom, params, inputparams);
|
2007-06-29 13:45:50 +00:00
|
|
|
if (ret == -1) {
|
2007-08-21 11:53:52 +00:00
|
|
|
goto cleanup;
|
2007-06-29 13:45:50 +00:00
|
|
|
}
|
2007-06-05 12:06:08 +00:00
|
|
|
}
|
|
|
|
free(params);
|
2007-08-21 11:53:52 +00:00
|
|
|
params = NULL;
|
2007-06-05 12:06:08 +00:00
|
|
|
|
|
|
|
/* Print SchedulerType */
|
|
|
|
schedulertype = virDomainGetSchedulerType(dom, &nparams);
|
|
|
|
if (schedulertype!= NULL){
|
2007-06-13 09:32:44 +00:00
|
|
|
vshPrint(ctl, "%-15s: %s\n", _("Scheduler"),
|
2007-06-05 12:06:08 +00:00
|
|
|
schedulertype);
|
|
|
|
free(schedulertype);
|
|
|
|
} else {
|
2007-06-13 09:32:44 +00:00
|
|
|
vshPrint(ctl, "%-15s: %s\n", _("Scheduler"), _("Unknown"));
|
2007-08-21 11:53:52 +00:00
|
|
|
goto cleanup;
|
2007-06-05 12:06:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Get SchedulerParameters */
|
|
|
|
params = vshMalloc(ctl, sizeof(virSchedParameter)* nparams);
|
2007-08-21 11:53:52 +00:00
|
|
|
if (params == NULL) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2007-06-05 12:06:08 +00:00
|
|
|
for (i = 0; i < nparams; i++){
|
|
|
|
params[i].type = 0;
|
|
|
|
memset (params[i].field, 0, sizeof params[i].field);
|
|
|
|
}
|
|
|
|
ret = virDomainGetSchedulerParameters(dom, params, &nparams);
|
2007-06-29 13:45:50 +00:00
|
|
|
if (ret == -1) {
|
2007-08-21 11:53:52 +00:00
|
|
|
goto cleanup;
|
2007-06-29 13:45:50 +00:00
|
|
|
}
|
2007-08-21 11:53:52 +00:00
|
|
|
ret_val = TRUE;
|
2007-06-05 12:06:08 +00:00
|
|
|
if(nparams){
|
|
|
|
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: %Ld\n", params[i].field, params[i].value.l);
|
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_SCHED_FIELD_ULLONG:
|
|
|
|
printf("%-15s: %Lu\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");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2007-08-21 11:53:52 +00:00
|
|
|
cleanup:
|
2008-01-29 17:41:07 +00:00
|
|
|
free(params);
|
2007-06-29 13:45:50 +00:00
|
|
|
virDomainFree(dom);
|
2007-08-21 11:53:52 +00:00
|
|
|
return ret_val;
|
2007-06-05 12:06:08 +00:00
|
|
|
}
|
|
|
|
|
2006-01-20 10:00:08 +00:00
|
|
|
/*
|
|
|
|
* "restore" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_restore[] = {
|
2006-03-15 12:13:25 +00:00
|
|
|
{"syntax", "restore a domain from <file>"},
|
2006-09-21 15:24:37 +00:00
|
|
|
{"help", gettext_noop("restore a domain from a saved state in a file")},
|
|
|
|
{"desc", gettext_noop("Restore a domain.")},
|
2006-03-15 12:13:25 +00:00
|
|
|
{NULL, NULL}
|
2006-01-20 10:00:08 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_restore[] = {
|
2006-09-21 15:24:37 +00:00
|
|
|
{"file", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("the state to restore")},
|
2006-03-15 12:13:25 +00:00
|
|
|
{NULL, 0, 0, NULL}
|
2006-01-20 10:00:08 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
2006-03-15 12:13:25 +00:00
|
|
|
cmdRestore(vshControl * ctl, vshCmd * cmd)
|
|
|
|
{
|
2006-01-20 10:00:08 +00:00
|
|
|
char *from;
|
|
|
|
int found;
|
|
|
|
int ret = TRUE;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2006-01-20 10:00:08 +00:00
|
|
|
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
from = vshCommandOptString(cmd, "file", &found);
|
|
|
|
if (!found)
|
|
|
|
return FALSE;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
|
|
|
if (virDomainRestore(ctl->conn, from) == 0) {
|
2006-09-21 15:24:37 +00:00
|
|
|
vshPrint(ctl, _("Domain restored from %s\n"), from);
|
2006-01-20 10:00:08 +00:00
|
|
|
} else {
|
2006-09-21 15:24:37 +00:00
|
|
|
vshError(ctl, FALSE, _("Failed to restore domain from %s"), from);
|
2006-01-20 10:00:08 +00:00
|
|
|
ret = FALSE;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2006-11-22 17:48:29 +00:00
|
|
|
/*
|
|
|
|
* "dump" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_dump[] = {
|
|
|
|
{"syntax", "dump <domain> <file>"},
|
|
|
|
{"help", gettext_noop("dump the core of a domain to a file for analysis")},
|
|
|
|
{"desc", gettext_noop("Core dump a domain.")},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_dump[] = {
|
|
|
|
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
|
|
|
|
{"file", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("where to dump the core")},
|
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdDump(vshControl * ctl, vshCmd * cmd)
|
|
|
|
{
|
|
|
|
virDomainPtr dom;
|
|
|
|
char *name;
|
|
|
|
char *to;
|
|
|
|
int ret = TRUE;
|
|
|
|
|
|
|
|
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (!(to = vshCommandOptString(cmd, "file", NULL)))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", &name)))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (virDomainCoreDump(dom, to, 0) == 0) {
|
|
|
|
vshPrint(ctl, _("Domain %s dumpd to %s\n"), name, to);
|
|
|
|
} else {
|
|
|
|
vshError(ctl, FALSE, _("Failed to core dump domain %s to %s"),
|
|
|
|
name, to);
|
|
|
|
ret = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
virDomainFree(dom);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2005-12-08 23:01:48 +00:00
|
|
|
/*
|
|
|
|
* "resume" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_resume[] = {
|
2006-03-15 12:13:25 +00:00
|
|
|
{"syntax", "resume <domain>"},
|
2006-09-21 15:24:37 +00:00
|
|
|
{"help", gettext_noop("resume a domain")},
|
|
|
|
{"desc", gettext_noop("Resume a previously suspended domain.")},
|
2006-03-15 12:13:25 +00:00
|
|
|
{NULL, NULL}
|
2005-12-08 23:01:48 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_resume[] = {
|
2006-09-21 15:24:37 +00:00
|
|
|
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
|
2006-03-15 12:13:25 +00:00
|
|
|
{NULL, 0, 0, NULL}
|
2005-12-08 23:01:48 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
2006-03-15 12:13:25 +00:00
|
|
|
cmdResume(vshControl * ctl, vshCmd * cmd)
|
|
|
|
{
|
2005-12-08 23:01:48 +00:00
|
|
|
virDomainPtr dom;
|
2005-12-15 17:00:43 +00:00
|
|
|
int ret = TRUE;
|
|
|
|
char *name;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-08 23:01:48 +00:00
|
|
|
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
|
|
|
return FALSE;
|
|
|
|
|
2005-12-15 17:00:43 +00:00
|
|
|
if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", &name)))
|
2005-12-08 23:01:48 +00:00
|
|
|
return FALSE;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
|
|
|
if (virDomainResume(dom) == 0) {
|
2006-09-21 15:24:37 +00:00
|
|
|
vshPrint(ctl, _("Domain %s resumed\n"), name);
|
2005-12-08 23:01:48 +00:00
|
|
|
} else {
|
2006-09-21 15:24:37 +00:00
|
|
|
vshError(ctl, FALSE, _("Failed to resume domain %s"), name);
|
2005-12-08 23:01:48 +00:00
|
|
|
ret = FALSE;
|
|
|
|
}
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-08 23:01:48 +00:00
|
|
|
virDomainFree(dom);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2005-12-16 12:16:41 +00:00
|
|
|
/*
|
|
|
|
* "shutdown" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_shutdown[] = {
|
2006-03-15 12:13:25 +00:00
|
|
|
{"syntax", "shutdown <domain>"},
|
2006-09-21 15:24:37 +00:00
|
|
|
{"help", gettext_noop("gracefully shutdown a domain")},
|
|
|
|
{"desc", gettext_noop("Run shutdown in the target domain.")},
|
2006-03-15 12:13:25 +00:00
|
|
|
{NULL, NULL}
|
2005-12-16 12:16:41 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_shutdown[] = {
|
2006-09-21 15:24:37 +00:00
|
|
|
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
|
2006-03-15 12:13:25 +00:00
|
|
|
{NULL, 0, 0, NULL}
|
2005-12-16 12:16:41 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
2006-03-15 12:13:25 +00:00
|
|
|
cmdShutdown(vshControl * ctl, vshCmd * cmd)
|
|
|
|
{
|
2005-12-16 12:16:41 +00:00
|
|
|
virDomainPtr dom;
|
|
|
|
int ret = TRUE;
|
|
|
|
char *name;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-16 12:16:41 +00:00
|
|
|
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", &name)))
|
|
|
|
return FALSE;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
|
|
|
if (virDomainShutdown(dom) == 0) {
|
2006-09-21 15:24:37 +00:00
|
|
|
vshPrint(ctl, _("Domain %s is being shutdown\n"), name);
|
2005-12-16 12:16:41 +00:00
|
|
|
} else {
|
2006-09-21 15:24:37 +00:00
|
|
|
vshError(ctl, FALSE, _("Failed to shutdown domain %s"), name);
|
2005-12-16 12:16:41 +00:00
|
|
|
ret = FALSE;
|
|
|
|
}
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-16 12:16:41 +00:00
|
|
|
virDomainFree(dom);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2006-04-03 13:46:43 +00:00
|
|
|
/*
|
|
|
|
* "reboot" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_reboot[] = {
|
|
|
|
{"syntax", "reboot <domain>"},
|
2006-09-21 15:24:37 +00:00
|
|
|
{"help", gettext_noop("reboot a domain")},
|
|
|
|
{"desc", gettext_noop("Run a reboot command in the target domain.")},
|
2006-04-03 13:46:43 +00:00
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_reboot[] = {
|
2006-09-21 15:24:37 +00:00
|
|
|
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
|
2006-04-03 13:46:43 +00:00
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdReboot(vshControl * ctl, vshCmd * cmd)
|
|
|
|
{
|
|
|
|
virDomainPtr dom;
|
|
|
|
int ret = TRUE;
|
|
|
|
char *name;
|
|
|
|
|
|
|
|
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", &name)))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (virDomainReboot(dom, 0) == 0) {
|
2006-09-21 15:24:37 +00:00
|
|
|
vshPrint(ctl, _("Domain %s is being rebooted\n"), name);
|
2006-04-03 13:46:43 +00:00
|
|
|
} else {
|
2006-09-21 15:24:37 +00:00
|
|
|
vshError(ctl, FALSE, _("Failed to reboot domain %s"), name);
|
2006-04-03 13:46:43 +00:00
|
|
|
ret = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
virDomainFree(dom);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2005-12-08 23:01:48 +00:00
|
|
|
/*
|
|
|
|
* "destroy" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_destroy[] = {
|
2006-03-15 12:13:25 +00:00
|
|
|
{"syntax", "destroy <domain>"},
|
2006-09-21 15:24:37 +00:00
|
|
|
{"help", gettext_noop("destroy a domain")},
|
|
|
|
{"desc", gettext_noop("Destroy a given domain.")},
|
2006-03-15 12:13:25 +00:00
|
|
|
{NULL, NULL}
|
2005-12-08 23:01:48 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_destroy[] = {
|
2006-09-21 15:24:37 +00:00
|
|
|
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
|
2006-03-15 12:13:25 +00:00
|
|
|
{NULL, 0, 0, NULL}
|
2005-12-08 23:01:48 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
2006-03-15 12:13:25 +00:00
|
|
|
cmdDestroy(vshControl * ctl, vshCmd * cmd)
|
|
|
|
{
|
2005-12-08 23:01:48 +00:00
|
|
|
virDomainPtr dom;
|
2005-12-15 17:00:43 +00:00
|
|
|
int ret = TRUE;
|
|
|
|
char *name;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-08 23:01:48 +00:00
|
|
|
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
|
|
|
return FALSE;
|
|
|
|
|
2005-12-15 17:00:43 +00:00
|
|
|
if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", &name)))
|
2005-12-08 23:01:48 +00:00
|
|
|
return FALSE;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
|
|
|
if (virDomainDestroy(dom) == 0) {
|
2006-09-21 15:24:37 +00:00
|
|
|
vshPrint(ctl, _("Domain %s destroyed\n"), name);
|
2005-12-08 23:01:48 +00:00
|
|
|
} else {
|
2006-09-21 15:24:37 +00:00
|
|
|
vshError(ctl, FALSE, _("Failed to destroy domain %s"), name);
|
2005-12-08 23:01:48 +00:00
|
|
|
ret = FALSE;
|
|
|
|
virDomainFree(dom);
|
|
|
|
}
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2006-04-04 14:37:32 +00:00
|
|
|
* "dominfo" command
|
2005-12-08 10:23:34 +00:00
|
|
|
*/
|
2006-04-04 14:37:32 +00:00
|
|
|
static vshCmdInfo info_dominfo[] = {
|
|
|
|
{"syntax", "dominfo <domain>"},
|
2006-09-21 15:24:37 +00:00
|
|
|
{"help", gettext_noop("domain information")},
|
|
|
|
{"desc", gettext_noop("Returns basic information about the domain.")},
|
2006-03-15 12:13:25 +00:00
|
|
|
{NULL, NULL}
|
2005-12-08 10:23:34 +00:00
|
|
|
};
|
|
|
|
|
2006-04-04 14:37:32 +00:00
|
|
|
static vshCmdOptDef opts_dominfo[] = {
|
2006-09-21 15:24:37 +00:00
|
|
|
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
|
2006-03-15 12:13:25 +00:00
|
|
|
{NULL, 0, 0, NULL}
|
2005-12-08 10:23:34 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
2006-04-04 14:37:32 +00:00
|
|
|
cmdDominfo(vshControl * ctl, vshCmd * cmd)
|
2006-03-15 12:13:25 +00:00
|
|
|
{
|
2005-12-08 10:23:34 +00:00
|
|
|
virDomainInfo info;
|
|
|
|
virDomainPtr dom;
|
2005-12-15 17:00:43 +00:00
|
|
|
int ret = TRUE;
|
2006-09-03 17:34:04 +00:00
|
|
|
unsigned int id;
|
Mon Jan 23 14:36:18 IST 2007 Mark McLoughlin <markmc@redhat.com>
* include/libvirt/libvirt.h.in: add VIR_UUID_BUFLEN and
VIR_UUID_STRING_BUFLEN
* libvirt/proxy/libvirt_proxy.c, libvirt/src/hash.c,
libvirt/src/internal.h, libvirt/src/libvirt.c,
libvirt/src/proxy_internal.c, libvirt/src/test.c,
libvirt/src/virsh.c, libvirt/src/xend_internal.c,
libvirt/src/xm_internal.c, libvirt/src/xml.c,
libvirt/python/libvir.c: use them
2007-01-23 14:39:45 +00:00
|
|
|
char *str, uuid[VIR_UUID_STRING_BUFLEN];
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
|
|
|
return FALSE;
|
|
|
|
|
2005-12-15 17:00:43 +00:00
|
|
|
if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", NULL)))
|
2005-12-08 10:23:34 +00:00
|
|
|
return FALSE;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2006-09-03 17:34:04 +00:00
|
|
|
id = virDomainGetID(dom);
|
|
|
|
if (id == ((unsigned int)-1))
|
2007-02-07 13:50:18 +00:00
|
|
|
vshPrint(ctl, "%-15s %s\n", _("Id:"), "-");
|
2006-09-03 17:34:04 +00:00
|
|
|
else
|
2007-02-07 13:50:18 +00:00
|
|
|
vshPrint(ctl, "%-15s %d\n", _("Id:"), id);
|
2006-09-21 15:24:37 +00:00
|
|
|
vshPrint(ctl, "%-15s %s\n", _("Name:"), virDomainGetName(dom));
|
|
|
|
|
2006-05-22 14:38:33 +00:00
|
|
|
if (virDomainGetUUIDString(dom, &uuid[0])==0)
|
2006-09-21 15:24:37 +00:00
|
|
|
vshPrint(ctl, "%-15s %s\n", _("UUID:"), uuid);
|
2006-03-15 12:13:25 +00:00
|
|
|
|
|
|
|
if ((str = virDomainGetOSType(dom))) {
|
2006-09-21 15:24:37 +00:00
|
|
|
vshPrint(ctl, "%-15s %s\n", _("OS Type:"), str);
|
2006-03-15 12:13:25 +00:00
|
|
|
free(str);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virDomainGetInfo(dom, &info) == 0) {
|
2006-09-21 15:24:37 +00:00
|
|
|
vshPrint(ctl, "%-15s %s\n", _("State:"),
|
2007-06-15 08:18:55 +00:00
|
|
|
N_(vshDomainStateToString(info.state)));
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2006-09-21 15:24:37 +00:00
|
|
|
vshPrint(ctl, "%-15s %d\n", _("CPU(s):"), info.nrVirtCpu);
|
2006-03-15 12:13:25 +00:00
|
|
|
|
|
|
|
if (info.cpuTime != 0) {
|
2007-02-07 13:50:18 +00:00
|
|
|
double cpuUsed = info.cpuTime;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2006-06-13 19:08:40 +00:00
|
|
|
cpuUsed /= 1000000000.0;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2006-09-21 15:24:37 +00:00
|
|
|
vshPrint(ctl, "%-15s %.1lfs\n", _("CPU time:"), cpuUsed);
|
2005-12-08 10:23:34 +00:00
|
|
|
}
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2007-03-15 14:27:09 +00:00
|
|
|
if (info.maxMem != UINT_MAX)
|
|
|
|
vshPrint(ctl, "%-15s %lu kB\n", _("Max memory:"),
|
2006-03-15 12:13:25 +00:00
|
|
|
info.maxMem);
|
2007-03-15 14:27:09 +00:00
|
|
|
else
|
|
|
|
vshPrint(ctl, "%-15s %-15s\n", _("Max memory:"),
|
|
|
|
_("no limit"));
|
|
|
|
|
2007-02-07 13:50:18 +00:00
|
|
|
vshPrint(ctl, "%-15s %lu kB\n", _("Used memory:"),
|
2006-03-15 12:13:25 +00:00
|
|
|
info.memory);
|
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
} else {
|
|
|
|
ret = FALSE;
|
|
|
|
}
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-08 23:01:48 +00:00
|
|
|
virDomainFree(dom);
|
2005-12-08 10:23:34 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2007-09-28 14:28:12 +00:00
|
|
|
/*
|
|
|
|
* "freecell" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_freecell[] = {
|
|
|
|
{"syntax", "freecell [<cellno>]"},
|
|
|
|
{"help", gettext_noop("NUMA free memory")},
|
|
|
|
{"desc", gettext_noop("display available free memory for the NUMA cell.")},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_freecell[] = {
|
|
|
|
{"cellno", VSH_OT_DATA, 0, gettext_noop("NUMA cell number")},
|
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdFreecell(vshControl * ctl, 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) {
|
2007-09-30 13:22:16 +00:00
|
|
|
memory = virNodeGetFreeMemory(ctl->conn);
|
|
|
|
} else {
|
|
|
|
ret = virNodeGetCellsFreeMemory(ctl->conn, &memory, cell, 1);
|
|
|
|
if (ret != 1)
|
|
|
|
return FALSE;
|
2007-09-28 14:28:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (cell == -1)
|
|
|
|
vshPrint(ctl, "%s: %llu kB\n", _("Total"), memory);
|
|
|
|
else
|
|
|
|
vshPrint(ctl, "%d: %llu kB\n", cell, memory);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2006-08-07 14:35:20 +00:00
|
|
|
/*
|
|
|
|
* "vcpuinfo" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_vcpuinfo[] = {
|
|
|
|
{"syntax", "vcpuinfo <domain>"},
|
2006-09-21 15:24:37 +00:00
|
|
|
{"help", gettext_noop("domain vcpu information")},
|
|
|
|
{"desc", gettext_noop("Returns basic information about the domain virtual CPUs.")},
|
2006-08-07 14:35:20 +00:00
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_vcpuinfo[] = {
|
2006-09-21 15:24:37 +00:00
|
|
|
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
|
2006-08-07 14:35:20 +00:00
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdVcpuinfo(vshControl * ctl, vshCmd * cmd)
|
|
|
|
{
|
|
|
|
virDomainInfo info;
|
|
|
|
virDomainPtr dom;
|
|
|
|
virNodeInfo nodeinfo;
|
|
|
|
virVcpuInfoPtr cpuinfo;
|
|
|
|
unsigned char *cpumap;
|
|
|
|
int ncpus;
|
|
|
|
size_t cpumaplen;
|
|
|
|
int ret = TRUE;
|
|
|
|
|
|
|
|
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", NULL)))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (virNodeGetInfo(ctl->conn, &nodeinfo) != 0) {
|
|
|
|
virDomainFree(dom);
|
2007-02-07 13:50:18 +00:00
|
|
|
return FALSE;
|
2006-08-07 14:35:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (virDomainGetInfo(dom, &info) != 0) {
|
|
|
|
virDomainFree(dom);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2007-03-22 18:30:57 +00:00
|
|
|
cpuinfo = vshMalloc(ctl, sizeof(virVcpuInfo)*info.nrVirtCpu);
|
2006-08-07 14:35:20 +00:00
|
|
|
cpumaplen = VIR_CPU_MAPLEN(VIR_NODEINFO_MAXCPUS(nodeinfo));
|
2007-03-22 18:30:57 +00:00
|
|
|
cpumap = vshMalloc(ctl, info.nrVirtCpu * cpumaplen);
|
2006-08-07 14:35:20 +00:00
|
|
|
|
2007-02-07 13:50:18 +00:00
|
|
|
if ((ncpus = virDomainGetVcpus(dom,
|
|
|
|
cpuinfo, info.nrVirtCpu,
|
|
|
|
cpumap, cpumaplen)) >= 0) {
|
2006-08-07 14:35:20 +00:00
|
|
|
int n;
|
2007-02-07 13:50:18 +00:00
|
|
|
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:"),
|
2007-06-15 08:18:55 +00:00
|
|
|
N_(vshDomainVcpuStateToString(cpuinfo[n].state)));
|
2007-02-07 13:50:18 +00:00
|
|
|
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");
|
|
|
|
}
|
|
|
|
}
|
2006-08-07 14:35:20 +00:00
|
|
|
} else {
|
2007-06-15 08:18:55 +00:00
|
|
|
if (info.state == VIR_DOMAIN_SHUTOFF) {
|
2008-01-16 17:13:23 +00:00
|
|
|
vshError(ctl, FALSE, "%s",
|
2007-06-15 08:18:55 +00:00
|
|
|
_("Domain shut off, virtual CPUs not present."));
|
|
|
|
}
|
2006-08-07 14:35:20 +00:00
|
|
|
ret = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
free(cpumap);
|
|
|
|
free(cpuinfo);
|
|
|
|
virDomainFree(dom);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* "vcpupin" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_vcpupin[] = {
|
2007-06-19 09:32:04 +00:00
|
|
|
{"syntax", "vcpupin <domain> <vcpu> <cpulist>"},
|
2006-09-21 15:24:37 +00:00
|
|
|
{"help", gettext_noop("control domain vcpu affinity")},
|
|
|
|
{"desc", gettext_noop("Pin domain VCPUs to host physical CPUs.")},
|
2006-08-07 14:35:20 +00:00
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_vcpupin[] = {
|
2006-09-21 15:24:37 +00:00
|
|
|
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
|
|
|
|
{"vcpu", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("vcpu number")},
|
|
|
|
{"cpulist", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("host cpu number(s) (comma separated)")},
|
2006-08-07 14:35:20 +00:00
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdVcpupin(vshControl * ctl, vshCmd * cmd)
|
|
|
|
{
|
|
|
|
virDomainInfo info;
|
|
|
|
virDomainPtr dom;
|
|
|
|
virNodeInfo nodeinfo;
|
|
|
|
int vcpu;
|
|
|
|
char *cpulist;
|
|
|
|
int ret = TRUE;
|
|
|
|
int vcpufound = 0;
|
|
|
|
unsigned char *cpumap;
|
|
|
|
int cpumaplen;
|
2007-06-19 09:32:04 +00:00
|
|
|
int i;
|
|
|
|
enum { expect_num, expect_num_or_comma } state;
|
2006-08-07 14:35:20 +00:00
|
|
|
|
|
|
|
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", NULL)))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
vcpu = vshCommandOptInt(cmd, "vcpu", &vcpufound);
|
|
|
|
if (!vcpufound) {
|
2008-03-04 19:59:56 +00:00
|
|
|
vshError(ctl, FALSE, _("vcpupin: Invalid or missing vCPU number."));
|
2006-08-07 14:35:20 +00:00
|
|
|
virDomainFree(dom);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(cpulist = vshCommandOptString(cmd, "cpulist", NULL))) {
|
|
|
|
virDomainFree(dom);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2007-02-07 13:50:18 +00:00
|
|
|
|
2006-08-07 14:35:20 +00:00
|
|
|
if (virNodeGetInfo(ctl->conn, &nodeinfo) != 0) {
|
|
|
|
virDomainFree(dom);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virDomainGetInfo(dom, &info) != 0) {
|
|
|
|
virDomainFree(dom);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (vcpu >= info.nrVirtCpu) {
|
|
|
|
virDomainFree(dom);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2007-06-19 09:32:04 +00:00
|
|
|
/* Check that the cpulist parameter is a comma-separated list of
|
|
|
|
* numbers and give an intelligent error message if not.
|
|
|
|
*/
|
|
|
|
if (cpulist[0] == '\0') {
|
2008-01-16 17:13:23 +00:00
|
|
|
vshError(ctl, FALSE, "%s", _("cpulist: Invalid format. Empty string."));
|
2007-06-19 09:32:04 +00:00
|
|
|
virDomainFree (dom);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
state = expect_num;
|
|
|
|
for (i = 0; cpulist[i]; i++) {
|
|
|
|
switch (state) {
|
|
|
|
case expect_num:
|
|
|
|
if (!isdigit (cpulist[i])) {
|
|
|
|
vshError( ctl, FALSE, _("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 (!isdigit (cpulist[i])) {
|
|
|
|
vshError(ctl, FALSE, _("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, FALSE, _("cpulist: %s: Invalid format. Trailing comma at position %d."), cpulist, i);
|
|
|
|
virDomainFree (dom);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2006-08-07 14:35:20 +00:00
|
|
|
cpumaplen = VIR_CPU_MAPLEN(VIR_NODEINFO_MAXCPUS(nodeinfo));
|
2007-03-22 18:30:57 +00:00
|
|
|
cpumap = vshCalloc(ctl, 1, cpumaplen);
|
2006-08-07 14:35:20 +00:00
|
|
|
|
|
|
|
do {
|
|
|
|
unsigned int cpu = atoi(cpulist);
|
|
|
|
|
|
|
|
if (cpu < VIR_NODEINFO_MAXCPUS(nodeinfo)) {
|
|
|
|
VIR_USE_CPU(cpumap, cpu);
|
2007-03-22 10:27:54 +00:00
|
|
|
} else {
|
|
|
|
vshError(ctl, FALSE, _("Physical CPU %d doesn't exist."), cpu);
|
|
|
|
free(cpumap);
|
|
|
|
virDomainFree(dom);
|
|
|
|
return FALSE;
|
2006-08-07 14:35:20 +00:00
|
|
|
}
|
2007-06-15 13:44:19 +00:00
|
|
|
cpulist = strchr(cpulist, ',');
|
2006-08-07 14:35:20 +00:00
|
|
|
if (cpulist)
|
|
|
|
cpulist++;
|
|
|
|
} while (cpulist);
|
|
|
|
|
|
|
|
if (virDomainPinVcpu(dom, vcpu, cpumap, cpumaplen) != 0) {
|
|
|
|
ret = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
free(cpumap);
|
|
|
|
virDomainFree(dom);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2006-08-16 17:30:33 +00:00
|
|
|
/*
|
|
|
|
* "setvcpus" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_setvcpus[] = {
|
|
|
|
{"syntax", "setvcpus <domain> <count>"},
|
2006-09-21 15:24:37 +00:00
|
|
|
{"help", gettext_noop("change number of virtual CPUs")},
|
2008-03-13 09:21:41 +00:00
|
|
|
{"desc", gettext_noop("Change the number of virtual CPUs in the guest domain.")},
|
2006-08-16 17:30:33 +00:00
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_setvcpus[] = {
|
2006-09-21 15:24:37 +00:00
|
|
|
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
|
|
|
|
{"count", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("number of virtual CPUs")},
|
2006-08-16 17:30:33 +00:00
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdSetvcpus(vshControl * ctl, vshCmd * cmd)
|
|
|
|
{
|
|
|
|
virDomainPtr dom;
|
|
|
|
int count;
|
2007-03-08 08:31:07 +00:00
|
|
|
int maxcpu;
|
2006-08-16 17:30:33 +00:00
|
|
|
int ret = TRUE;
|
|
|
|
|
|
|
|
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", NULL)))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
count = vshCommandOptInt(cmd, "count", &count);
|
2007-08-15 10:18:33 +00:00
|
|
|
if (count <= 0) {
|
2008-01-16 17:13:23 +00:00
|
|
|
vshError(ctl, FALSE, "%s", _("Invalid number of virtual CPUs."));
|
2006-08-16 17:30:33 +00:00
|
|
|
virDomainFree(dom);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2007-03-08 08:31:07 +00:00
|
|
|
maxcpu = virDomainGetMaxVcpus(dom);
|
2007-08-15 10:18:33 +00:00
|
|
|
if (maxcpu <= 0) {
|
2007-03-08 08:31:07 +00:00
|
|
|
virDomainFree(dom);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (count > maxcpu) {
|
2008-01-16 17:13:23 +00:00
|
|
|
vshError(ctl, FALSE, "%s", _("Too many virtual CPUs."));
|
2007-03-08 08:31:07 +00:00
|
|
|
virDomainFree(dom);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2006-08-16 17:30:33 +00:00
|
|
|
if (virDomainSetVcpus(dom, count) != 0) {
|
|
|
|
ret = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
virDomainFree(dom);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* "setmemory" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_setmem[] = {
|
2007-04-02 11:56:38 +00:00
|
|
|
{"syntax", "setmem <domain> <kilobytes>"},
|
2006-09-21 15:24:37 +00:00
|
|
|
{"help", gettext_noop("change memory allocation")},
|
|
|
|
{"desc", gettext_noop("Change the current memory allocation in the guest domain.")},
|
2006-08-16 17:30:33 +00:00
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_setmem[] = {
|
2006-09-21 15:24:37 +00:00
|
|
|
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
|
2007-04-02 11:56:38 +00:00
|
|
|
{"kilobytes", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("number of kilobytes of memory")},
|
2006-08-16 17:30:33 +00:00
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdSetmem(vshControl * ctl, vshCmd * cmd)
|
|
|
|
{
|
|
|
|
virDomainPtr dom;
|
2007-06-18 08:33:08 +00:00
|
|
|
virDomainInfo info;
|
2007-04-02 11:56:38 +00:00
|
|
|
int kilobytes;
|
2006-08-16 17:30:33 +00:00
|
|
|
int ret = TRUE;
|
|
|
|
|
|
|
|
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", NULL)))
|
|
|
|
return FALSE;
|
|
|
|
|
2007-04-02 11:56:38 +00:00
|
|
|
kilobytes = vshCommandOptInt(cmd, "kilobytes", &kilobytes);
|
|
|
|
if (kilobytes <= 0) {
|
2006-08-16 17:30:33 +00:00
|
|
|
virDomainFree(dom);
|
2007-04-02 11:56:38 +00:00
|
|
|
vshError(ctl, FALSE, _("Invalid value of %d for memory size"), kilobytes);
|
2006-08-16 17:30:33 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2007-06-18 08:33:08 +00:00
|
|
|
if (virDomainGetInfo(dom, &info) != 0) {
|
|
|
|
virDomainFree(dom);
|
2008-01-16 17:13:23 +00:00
|
|
|
vshError(ctl, FALSE, "%s", _("Unable to verify MaxMemorySize"));
|
2007-06-18 08:33:08 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (kilobytes > info.maxMem) {
|
|
|
|
virDomainFree(dom);
|
|
|
|
vshError(ctl, FALSE, _("Invalid value of %d for memory size"), kilobytes);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2007-04-02 11:56:38 +00:00
|
|
|
if (virDomainSetMemory(dom, kilobytes) != 0) {
|
2006-08-16 17:30:33 +00:00
|
|
|
ret = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
virDomainFree(dom);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* "setmaxmem" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_setmaxmem[] = {
|
2007-04-02 11:56:38 +00:00
|
|
|
{"syntax", "setmaxmem <domain> <kilobytes>"},
|
2006-09-21 15:24:37 +00:00
|
|
|
{"help", gettext_noop("change maximum memory limit")},
|
|
|
|
{"desc", gettext_noop("Change the maximum memory allocation limit in the guest domain.")},
|
2006-08-16 17:30:33 +00:00
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_setmaxmem[] = {
|
2006-09-21 15:24:37 +00:00
|
|
|
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
|
2007-04-10 18:40:50 +00:00
|
|
|
{"kilobytes", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("maximum memory limit in kilobytes")},
|
2006-08-16 17:30:33 +00:00
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdSetmaxmem(vshControl * ctl, vshCmd * cmd)
|
|
|
|
{
|
|
|
|
virDomainPtr dom;
|
2007-06-18 08:33:08 +00:00
|
|
|
virDomainInfo info;
|
2007-04-02 11:56:38 +00:00
|
|
|
int kilobytes;
|
2006-08-16 17:30:33 +00:00
|
|
|
int ret = TRUE;
|
|
|
|
|
|
|
|
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", NULL)))
|
|
|
|
return FALSE;
|
|
|
|
|
2007-04-02 11:56:38 +00:00
|
|
|
kilobytes = vshCommandOptInt(cmd, "kilobytes", &kilobytes);
|
|
|
|
if (kilobytes <= 0) {
|
2006-08-16 17:30:33 +00:00
|
|
|
virDomainFree(dom);
|
2007-04-02 11:56:38 +00:00
|
|
|
vshError(ctl, FALSE, _("Invalid value of %d for memory size"), kilobytes);
|
2006-08-16 17:30:33 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2007-06-18 08:33:08 +00:00
|
|
|
if (virDomainGetInfo(dom, &info) != 0) {
|
|
|
|
virDomainFree(dom);
|
2008-01-16 17:13:23 +00:00
|
|
|
vshError(ctl, FALSE, "%s", _("Unable to verify current MemorySize"));
|
2007-06-18 08:33:08 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (kilobytes < info.memory) {
|
|
|
|
if (virDomainSetMemory(dom, kilobytes) != 0) {
|
|
|
|
virDomainFree(dom);
|
2008-01-16 17:13:23 +00:00
|
|
|
vshError(ctl, FALSE, "%s", _("Unable to shrink current MemorySize"));
|
2007-06-18 08:33:08 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-04-02 11:56:38 +00:00
|
|
|
if (virDomainSetMaxMemory(dom, kilobytes) != 0) {
|
2008-01-16 17:13:23 +00:00
|
|
|
vshError(ctl, FALSE, "%s", _("Unable to change MaxMemorySize"));
|
2006-08-16 17:30:33 +00:00
|
|
|
ret = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
virDomainFree(dom);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2006-04-04 14:37:32 +00:00
|
|
|
/*
|
|
|
|
* "nodeinfo" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_nodeinfo[] = {
|
|
|
|
{"syntax", "nodeinfo"},
|
2006-09-21 15:24:37 +00:00
|
|
|
{"help", gettext_noop("node information")},
|
|
|
|
{"desc", gettext_noop("Returns basic information about the node.")},
|
2006-04-04 14:37:32 +00:00
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdNodeinfo(vshControl * ctl, vshCmd * cmd ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virNodeInfo info;
|
2006-09-21 15:24:37 +00:00
|
|
|
|
2006-04-04 14:37:32 +00:00
|
|
|
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (virNodeGetInfo(ctl->conn, &info) < 0) {
|
2008-01-16 17:13:23 +00:00
|
|
|
vshError(ctl, FALSE, "%s", _("failed to get node information"));
|
2006-09-21 15:24:37 +00:00
|
|
|
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);
|
|
|
|
|
2006-04-04 14:37:32 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2007-03-15 17:24:56 +00:00
|
|
|
/*
|
|
|
|
* "capabilities" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_capabilities[] = {
|
|
|
|
{"syntax", "capabilities"},
|
|
|
|
{"help", gettext_noop("capabilities")},
|
|
|
|
{"desc", gettext_noop("Returns capabilities of hypervisor/driver.")},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdCapabilities (vshControl * ctl, vshCmd * cmd ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
char *caps;
|
|
|
|
|
|
|
|
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if ((caps = virConnectGetCapabilities (ctl->conn)) == NULL) {
|
2008-01-16 17:13:23 +00:00
|
|
|
vshError(ctl, FALSE, "%s", _("failed to get capabilities"));
|
2007-03-15 17:24:56 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
vshPrint (ctl, "%s\n", caps);
|
2008-01-30 19:57:54 +00:00
|
|
|
free (caps);
|
2007-03-15 17:24:56 +00:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2005-12-13 16:22:05 +00:00
|
|
|
/*
|
|
|
|
* "dumpxml" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_dumpxml[] = {
|
2007-05-03 16:03:02 +00:00
|
|
|
{"syntax", "dumpxml <domain>"},
|
2006-09-21 15:24:37 +00:00
|
|
|
{"help", gettext_noop("domain information in XML")},
|
2007-04-10 18:40:50 +00:00
|
|
|
{"desc", gettext_noop("Output the domain information as an XML dump to stdout.")},
|
2006-03-15 12:13:25 +00:00
|
|
|
{NULL, NULL}
|
2005-12-13 16:22:05 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_dumpxml[] = {
|
2006-09-21 15:24:37 +00:00
|
|
|
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
|
2006-03-15 12:13:25 +00:00
|
|
|
{NULL, 0, 0, NULL}
|
2005-12-13 16:22:05 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
2006-03-15 12:13:25 +00:00
|
|
|
cmdDumpXML(vshControl * ctl, vshCmd * cmd)
|
|
|
|
{
|
2005-12-13 16:22:05 +00:00
|
|
|
virDomainPtr dom;
|
2005-12-15 17:00:43 +00:00
|
|
|
int ret = TRUE;
|
2005-12-13 16:22:05 +00:00
|
|
|
char *dump;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-13 16:22:05 +00:00
|
|
|
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
|
|
|
return FALSE;
|
|
|
|
|
2005-12-15 17:00:43 +00:00
|
|
|
if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", NULL)))
|
2005-12-13 16:22:05 +00:00
|
|
|
return FALSE;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-13 16:22:05 +00:00
|
|
|
dump = virDomainGetXMLDesc(dom, 0);
|
|
|
|
if (dump != NULL) {
|
|
|
|
printf("%s", dump);
|
|
|
|
free(dump);
|
|
|
|
} else {
|
|
|
|
ret = FALSE;
|
|
|
|
}
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-13 16:22:05 +00:00
|
|
|
virDomainFree(dom);
|
|
|
|
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
|
|
|
*/
|
2006-04-04 21:52:31 +00:00
|
|
|
static vshCmdInfo info_domname[] = {
|
2006-05-29 15:39:31 +00:00
|
|
|
{"syntax", "domname <domain>"},
|
2006-09-21 15:24:37 +00:00
|
|
|
{"help", gettext_noop("convert a domain id or UUID to domain name")},
|
2006-03-15 12:13:25 +00:00
|
|
|
{NULL, NULL}
|
2005-12-08 10:23:34 +00:00
|
|
|
};
|
|
|
|
|
2006-04-04 21:52:31 +00:00
|
|
|
static vshCmdOptDef opts_domname[] = {
|
2006-09-21 15:24:37 +00:00
|
|
|
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain id or uuid")},
|
2006-03-15 12:13:25 +00:00
|
|
|
{NULL, 0, 0, NULL}
|
2005-12-08 10:23:34 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
2006-04-04 21:52:31 +00:00
|
|
|
cmdDomname(vshControl * ctl, vshCmd * cmd)
|
2006-03-15 12:13:25 +00:00
|
|
|
{
|
2005-12-08 10:23:34 +00:00
|
|
|
virDomainPtr dom;
|
|
|
|
|
|
|
|
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
|
|
|
return FALSE;
|
2007-02-07 13:50:18 +00:00
|
|
|
if (!(dom = vshCommandOptDomainBy(ctl, cmd, "domain", NULL,
|
2007-02-14 15:44:58 +00:00
|
|
|
VSH_BYID|VSH_BYUUID)))
|
2005-12-08 10:23:34 +00:00
|
|
|
return FALSE;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
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
|
|
|
*/
|
2006-04-04 21:52:31 +00:00
|
|
|
static vshCmdInfo info_domid[] = {
|
2006-05-29 15:39:31 +00:00
|
|
|
{"syntax", "domid <domain>"},
|
2006-09-21 15:24:37 +00:00
|
|
|
{"help", gettext_noop("convert a domain name or UUID to domain id")},
|
2006-03-15 12:13:25 +00:00
|
|
|
{NULL, NULL}
|
2005-12-08 10:23:34 +00:00
|
|
|
};
|
|
|
|
|
2006-04-04 21:52:31 +00:00
|
|
|
static vshCmdOptDef opts_domid[] = {
|
2006-09-21 15:24:37 +00:00
|
|
|
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name or uuid")},
|
2006-03-15 12:13:25 +00:00
|
|
|
{NULL, 0, 0, NULL}
|
2005-12-08 10:23:34 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
2006-04-04 21:52:31 +00:00
|
|
|
cmdDomid(vshControl * ctl, vshCmd * cmd)
|
2006-03-15 12:13:25 +00:00
|
|
|
{
|
2005-12-05 11:16:07 +00:00
|
|
|
virDomainPtr dom;
|
2006-09-03 17:34:04 +00:00
|
|
|
unsigned int id;
|
2005-12-08 10:23:34 +00:00
|
|
|
|
|
|
|
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
|
|
|
return FALSE;
|
2007-02-07 13:50:18 +00:00
|
|
|
if (!(dom = vshCommandOptDomainBy(ctl, cmd, "domain", NULL,
|
2007-02-14 15:44:58 +00:00
|
|
|
VSH_BYNAME|VSH_BYUUID)))
|
2005-12-08 10:23:34 +00:00
|
|
|
return FALSE;
|
2007-02-07 13:50:18 +00:00
|
|
|
|
2006-09-03 17:34:04 +00:00
|
|
|
id = virDomainGetID(dom);
|
|
|
|
if (id == ((unsigned int)-1))
|
2007-02-07 13:50:18 +00:00
|
|
|
vshPrint(ctl, "%s\n", "-");
|
2006-09-03 17:34:04 +00:00
|
|
|
else
|
2007-02-07 13:50:18 +00:00
|
|
|
vshPrint(ctl, "%d\n", id);
|
2006-05-29 15:39:31 +00:00
|
|
|
virDomainFree(dom);
|
|
|
|
return TRUE;
|
|
|
|
}
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2006-05-29 15:39:31 +00:00
|
|
|
/*
|
|
|
|
* "domuuid" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_domuuid[] = {
|
|
|
|
{"syntax", "domuuid <domain>"},
|
2006-09-21 15:24:37 +00:00
|
|
|
{"help", gettext_noop("convert a domain name or id to domain UUID")},
|
2006-05-29 15:39:31 +00:00
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_domuuid[] = {
|
2006-09-21 15:24:37 +00:00
|
|
|
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain id or name")},
|
2006-05-29 15:39:31 +00:00
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdDomuuid(vshControl * ctl, vshCmd * cmd)
|
|
|
|
{
|
|
|
|
virDomainPtr dom;
|
Mon Jan 23 14:36:18 IST 2007 Mark McLoughlin <markmc@redhat.com>
* include/libvirt/libvirt.h.in: add VIR_UUID_BUFLEN and
VIR_UUID_STRING_BUFLEN
* libvirt/proxy/libvirt_proxy.c, libvirt/src/hash.c,
libvirt/src/internal.h, libvirt/src/libvirt.c,
libvirt/src/proxy_internal.c, libvirt/src/test.c,
libvirt/src/virsh.c, libvirt/src/xend_internal.c,
libvirt/src/xm_internal.c, libvirt/src/xml.c,
libvirt/python/libvir.c: use them
2007-01-23 14:39:45 +00:00
|
|
|
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;
|
2006-09-21 15:24:37 +00:00
|
|
|
if (!(dom = vshCommandOptDomainBy(ctl, cmd, "domain", NULL,
|
2007-02-14 15:44:58 +00:00
|
|
|
VSH_BYNAME|VSH_BYID)))
|
2006-05-29 15:39:31 +00:00
|
|
|
return FALSE;
|
2006-09-21 15:24:37 +00:00
|
|
|
|
2006-05-29 15:39:31 +00:00
|
|
|
if (virDomainGetUUIDString(dom, uuid) != -1)
|
|
|
|
vshPrint(ctl, "%s\n", uuid);
|
|
|
|
else
|
2008-01-16 17:13:23 +00:00
|
|
|
vshError(ctl, FALSE, "%s", _("failed to get domain UUID"));
|
2006-09-21 15:24:37 +00:00
|
|
|
|
2008-01-30 19:58:59 +00:00
|
|
|
virDomainFree(dom);
|
2005-12-08 10:23:34 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2007-08-21 09:31:12 +00:00
|
|
|
/*
|
|
|
|
* "migrate" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_migrate[] = {
|
|
|
|
{"syntax", "migrate [--live] <domain> <desturi> [<migrateuri>]"},
|
|
|
|
{"help", gettext_noop("migrate domain to another host")},
|
|
|
|
{"desc", gettext_noop("Migrate domain to another host. Add --live for live migration.")},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_migrate[] = {
|
|
|
|
{"live", VSH_OT_BOOL, 0, gettext_noop("live migration")},
|
|
|
|
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
|
|
|
|
{"desturi", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("connection URI of the destination host")},
|
|
|
|
{"migrateuri", VSH_OT_DATA, 0, gettext_noop("migration URI, usually can be omitted")},
|
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdMigrate (vshControl *ctl, vshCmd *cmd)
|
|
|
|
{
|
|
|
|
virDomainPtr dom = NULL;
|
|
|
|
const char *desturi;
|
|
|
|
const char *migrateuri;
|
|
|
|
int flags = 0, found, ret = FALSE;
|
|
|
|
virConnectPtr dconn = NULL;
|
|
|
|
virDomainPtr ddom = NULL;
|
|
|
|
|
|
|
|
if (!vshConnectionUsability (ctl, ctl->conn, TRUE))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (!(dom = vshCommandOptDomain (ctl, cmd, "domain", NULL)))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
desturi = vshCommandOptString (cmd, "desturi", &found);
|
|
|
|
if (!found) {
|
2008-01-16 17:13:23 +00:00
|
|
|
vshError (ctl, FALSE, "%s", _("migrate: Missing desturi"));
|
2007-08-21 09:31:12 +00:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
migrateuri = vshCommandOptString (cmd, "migrateuri", &found);
|
|
|
|
if (!found) migrateuri = NULL;
|
|
|
|
|
|
|
|
if (vshCommandOptBool (cmd, "live"))
|
|
|
|
flags |= VIR_MIGRATE_LIVE;
|
|
|
|
|
|
|
|
/* Temporarily connect to the destination host. */
|
|
|
|
dconn = virConnectOpen (desturi);
|
|
|
|
if (!dconn) goto done;
|
|
|
|
|
|
|
|
/* Migrate. */
|
|
|
|
ddom = virDomainMigrate (dom, dconn, flags, NULL, migrateuri, 0);
|
|
|
|
if (!ddom) goto done;
|
|
|
|
|
|
|
|
ret = TRUE;
|
|
|
|
|
|
|
|
done:
|
|
|
|
if (dom) virDomainFree (dom);
|
|
|
|
if (ddom) virDomainFree (ddom);
|
|
|
|
if (dconn) virConnectClose (dconn);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2007-02-23 08:58:25 +00:00
|
|
|
/*
|
|
|
|
* "net-autostart" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_network_autostart[] = {
|
|
|
|
{"syntax", "net-autostart [--disable] <network>"},
|
|
|
|
{"help", gettext_noop("autostart a network")},
|
|
|
|
{"desc",
|
|
|
|
gettext_noop("Configure a network to be automatically started at boot.")},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_network_autostart[] = {
|
|
|
|
{"network", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("network name or uuid")},
|
|
|
|
{"disable", VSH_OT_BOOL, 0, gettext_noop("disable autostarting")},
|
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdNetworkAutostart(vshControl * ctl, vshCmd * cmd)
|
|
|
|
{
|
|
|
|
virNetworkPtr network;
|
|
|
|
char *name;
|
|
|
|
int autostart;
|
|
|
|
|
|
|
|
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (!(network = vshCommandOptNetwork(ctl, cmd, "network", &name)))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
autostart = !vshCommandOptBool(cmd, "disable");
|
|
|
|
|
|
|
|
if (virNetworkSetAutostart(network, autostart) < 0) {
|
2007-04-13 08:04:08 +00:00
|
|
|
if (autostart)
|
|
|
|
vshError(ctl, FALSE, _("failed to mark network %s as autostarted"),
|
|
|
|
name);
|
|
|
|
else
|
|
|
|
vshError(ctl, FALSE,_("failed to unmark network %s as autostarted"),
|
|
|
|
name);
|
2007-02-23 08:58:25 +00:00
|
|
|
virNetworkFree(network);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2007-04-13 08:04:08 +00:00
|
|
|
if (autostart)
|
|
|
|
vshPrint(ctl, _("Network %s marked as autostarted\n"), name);
|
|
|
|
else
|
|
|
|
vshPrint(ctl, _("Network %s unmarked as autostarted\n"), name);
|
2007-02-23 08:58:25 +00:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
2006-05-29 15:39:31 +00:00
|
|
|
|
2007-02-14 16:53:55 +00:00
|
|
|
/*
|
|
|
|
* "net-create" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_network_create[] = {
|
|
|
|
{"syntax", "create a network from an XML <file>"},
|
|
|
|
{"help", gettext_noop("create a network from an XML file")},
|
|
|
|
{"desc", gettext_noop("Create a network.")},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_network_create[] = {
|
|
|
|
{"file", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("file containing an XML network description")},
|
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdNetworkCreate(vshControl * ctl, vshCmd * cmd)
|
|
|
|
{
|
|
|
|
virNetworkPtr network;
|
|
|
|
char *from;
|
|
|
|
int found;
|
|
|
|
int ret = TRUE;
|
2007-05-23 15:09:19 +00:00
|
|
|
char *buffer;
|
2007-02-14 16:53:55 +00:00
|
|
|
|
|
|
|
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;
|
2007-05-23 15:09:19 +00:00
|
|
|
|
|
|
|
network = virNetworkCreateXML(ctl->conn, buffer);
|
|
|
|
free (buffer);
|
|
|
|
|
2007-02-14 16:53:55 +00:00
|
|
|
if (network != NULL) {
|
|
|
|
vshPrint(ctl, _("Network %s created from %s\n"),
|
|
|
|
virNetworkGetName(network), from);
|
|
|
|
} else {
|
|
|
|
vshError(ctl, FALSE, _("Failed to create network from %s"), from);
|
|
|
|
ret = FALSE;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* "net-define" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_network_define[] = {
|
|
|
|
{"syntax", "define a network from an XML <file>"},
|
|
|
|
{"help", gettext_noop("define (but don't start) a network from an XML file")},
|
|
|
|
{"desc", gettext_noop("Define a network.")},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_network_define[] = {
|
2007-04-10 18:40:50 +00:00
|
|
|
{"file", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("file containing an XML network description")},
|
2007-02-14 16:53:55 +00:00
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdNetworkDefine(vshControl * ctl, vshCmd * cmd)
|
|
|
|
{
|
|
|
|
virNetworkPtr network;
|
|
|
|
char *from;
|
|
|
|
int found;
|
|
|
|
int ret = TRUE;
|
2007-05-23 15:09:19 +00:00
|
|
|
char *buffer;
|
2007-02-14 16:53:55 +00:00
|
|
|
|
|
|
|
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;
|
2007-05-23 15:09:19 +00:00
|
|
|
|
|
|
|
network = virNetworkDefineXML(ctl->conn, buffer);
|
|
|
|
free (buffer);
|
|
|
|
|
2007-02-14 16:53:55 +00:00
|
|
|
if (network != NULL) {
|
|
|
|
vshPrint(ctl, _("Network %s defined from %s\n"),
|
|
|
|
virNetworkGetName(network), from);
|
|
|
|
} else {
|
|
|
|
vshError(ctl, FALSE, _("Failed to define network from %s"), from);
|
|
|
|
ret = FALSE;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* "net-destroy" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_network_destroy[] = {
|
|
|
|
{"syntax", "net-destroy <network>"},
|
|
|
|
{"help", gettext_noop("destroy a network")},
|
|
|
|
{"desc", gettext_noop("Destroy a given network.")},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_network_destroy[] = {
|
|
|
|
{"network", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("network name, id or uuid")},
|
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdNetworkDestroy(vshControl * ctl, vshCmd * cmd)
|
|
|
|
{
|
|
|
|
virNetworkPtr network;
|
|
|
|
int ret = TRUE;
|
|
|
|
char *name;
|
|
|
|
|
|
|
|
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (!(network = vshCommandOptNetwork(ctl, cmd, "network", &name)))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (virNetworkDestroy(network) == 0) {
|
|
|
|
vshPrint(ctl, _("Network %s destroyed\n"), name);
|
|
|
|
} else {
|
|
|
|
vshError(ctl, FALSE, _("Failed to destroy network %s"), name);
|
|
|
|
ret = FALSE;
|
|
|
|
virNetworkFree(network);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* "net-dumpxml" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_network_dumpxml[] = {
|
2007-05-03 16:03:02 +00:00
|
|
|
{"syntax", "net-dumpxml <network>"},
|
2007-02-14 16:53:55 +00:00
|
|
|
{"help", gettext_noop("network information in XML")},
|
2007-04-10 18:40:50 +00:00
|
|
|
{"desc", gettext_noop("Output the network information as an XML dump to stdout.")},
|
2007-02-14 16:53:55 +00:00
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_network_dumpxml[] = {
|
|
|
|
{"network", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("network name, id or uuid")},
|
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdNetworkDumpXML(vshControl * ctl, vshCmd * cmd)
|
|
|
|
{
|
|
|
|
virNetworkPtr network;
|
|
|
|
int ret = TRUE;
|
|
|
|
char *dump;
|
|
|
|
|
|
|
|
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (!(network = vshCommandOptNetwork(ctl, cmd, "network", NULL)))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
dump = virNetworkGetXMLDesc(network, 0);
|
|
|
|
if (dump != NULL) {
|
|
|
|
printf("%s", dump);
|
|
|
|
free(dump);
|
|
|
|
} else {
|
|
|
|
ret = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
virNetworkFree(network);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* "net-list" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_network_list[] = {
|
|
|
|
{"syntax", "net-list [ --inactive | --all ]"},
|
|
|
|
{"help", gettext_noop("list networks")},
|
|
|
|
{"desc", gettext_noop("Returns list of networks.")},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_network_list[] = {
|
|
|
|
{"inactive", VSH_OT_BOOL, 0, gettext_noop("list inactive networks")},
|
|
|
|
{"all", VSH_OT_BOOL, 0, gettext_noop("list inactive & active networks")},
|
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdNetworkList(vshControl * ctl, 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;
|
2007-02-14 16:53:55 +00:00
|
|
|
inactive |= all;
|
|
|
|
|
|
|
|
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (active) {
|
2007-02-20 18:25:46 +00:00
|
|
|
maxactive = virConnectNumOfNetworks(ctl->conn);
|
|
|
|
if (maxactive < 0) {
|
2008-01-16 17:13:23 +00:00
|
|
|
vshError(ctl, FALSE, "%s", _("Failed to list active networks"));
|
2007-02-20 18:25:46 +00:00
|
|
|
return FALSE;
|
2007-02-14 16:53:55 +00:00
|
|
|
}
|
2007-02-20 18:25:46 +00:00
|
|
|
if (maxactive) {
|
2007-03-09 13:44:24 +00:00
|
|
|
activeNames = vshMalloc(ctl, sizeof(char *) * maxactive);
|
2007-02-20 18:25:46 +00:00
|
|
|
|
2007-03-09 13:44:24 +00:00
|
|
|
if ((maxactive = virConnectListNetworks(ctl->conn, activeNames,
|
|
|
|
maxactive)) < 0) {
|
2008-01-16 17:13:23 +00:00
|
|
|
vshError(ctl, FALSE, "%s", _("Failed to list active networks"));
|
2007-02-20 18:25:46 +00:00
|
|
|
free(activeNames);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2007-02-14 16:53:55 +00:00
|
|
|
|
2007-03-09 13:44:24 +00:00
|
|
|
qsort(&activeNames[0], maxactive, sizeof(char *), namesorter);
|
2007-02-20 18:25:46 +00:00
|
|
|
}
|
2007-02-14 16:53:55 +00:00
|
|
|
}
|
|
|
|
if (inactive) {
|
2007-02-20 18:25:46 +00:00
|
|
|
maxinactive = virConnectNumOfDefinedNetworks(ctl->conn);
|
|
|
|
if (maxinactive < 0) {
|
2008-01-16 17:13:23 +00:00
|
|
|
vshError(ctl, FALSE, "%s", _("Failed to list inactive networks"));
|
2008-01-29 17:41:07 +00:00
|
|
|
free(activeNames);
|
2007-02-20 18:25:46 +00:00
|
|
|
return FALSE;
|
2007-02-14 16:53:55 +00:00
|
|
|
}
|
2007-02-20 18:25:46 +00:00
|
|
|
if (maxinactive) {
|
|
|
|
inactiveNames = vshMalloc(ctl, sizeof(char *) * maxinactive);
|
|
|
|
|
|
|
|
if ((maxinactive = virConnectListDefinedNetworks(ctl->conn, inactiveNames, maxinactive)) < 0) {
|
2008-01-16 17:13:23 +00:00
|
|
|
vshError(ctl, FALSE, "%s", _("Failed to list inactive networks"));
|
2008-01-29 17:41:07 +00:00
|
|
|
free(activeNames);
|
2007-02-20 18:25:46 +00:00
|
|
|
free(inactiveNames);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2007-02-14 16:53:55 +00:00
|
|
|
|
2007-02-20 18:25:46 +00:00
|
|
|
qsort(&inactiveNames[0], maxinactive, sizeof(char*), namesorter);
|
|
|
|
}
|
2007-02-14 16:53:55 +00:00
|
|
|
}
|
2007-02-23 08:58:25 +00:00
|
|
|
vshPrintExtra(ctl, "%-20s %-10s %-10s\n", _("Name"), _("State"), _("Autostart"));
|
|
|
|
vshPrintExtra(ctl, "-----------------------------------------\n");
|
2007-02-14 16:53:55 +00:00
|
|
|
|
|
|
|
for (i = 0; i < maxactive; i++) {
|
|
|
|
virNetworkPtr network = virNetworkLookupByName(ctl->conn, activeNames[i]);
|
2007-02-23 08:58:25 +00:00
|
|
|
const char *autostartStr;
|
|
|
|
int autostart = 0;
|
2007-02-14 16:53:55 +00:00
|
|
|
|
|
|
|
/* this kind of work with networks is not atomic operation */
|
|
|
|
if (!network) {
|
|
|
|
free(activeNames[i]);
|
|
|
|
continue;
|
2007-02-20 18:25:46 +00:00
|
|
|
}
|
2007-02-14 16:53:55 +00:00
|
|
|
|
2007-02-23 08:58:25 +00:00
|
|
|
if (virNetworkGetAutostart(network, &autostart) < 0)
|
|
|
|
autostartStr = _("no autostart");
|
|
|
|
else
|
|
|
|
autostartStr = autostart ? "yes" : "no";
|
|
|
|
|
|
|
|
vshPrint(ctl, "%-20s %-10s %-10s\n",
|
|
|
|
virNetworkGetName(network),
|
|
|
|
_("active"),
|
|
|
|
autostartStr);
|
2007-02-14 16:53:55 +00:00
|
|
|
virNetworkFree(network);
|
|
|
|
free(activeNames[i]);
|
|
|
|
}
|
|
|
|
for (i = 0; i < maxinactive; i++) {
|
|
|
|
virNetworkPtr network = virNetworkLookupByName(ctl->conn, inactiveNames[i]);
|
2007-02-23 08:58:25 +00:00
|
|
|
const char *autostartStr;
|
|
|
|
int autostart = 0;
|
2007-02-14 16:53:55 +00:00
|
|
|
|
|
|
|
/* this kind of work with networks is not atomic operation */
|
|
|
|
if (!network) {
|
|
|
|
free(inactiveNames[i]);
|
|
|
|
continue;
|
2007-02-20 18:25:46 +00:00
|
|
|
}
|
2007-02-14 16:53:55 +00:00
|
|
|
|
2007-02-23 08:58:25 +00:00
|
|
|
if (virNetworkGetAutostart(network, &autostart) < 0)
|
|
|
|
autostartStr = _("no autostart");
|
|
|
|
else
|
|
|
|
autostartStr = autostart ? "yes" : "no";
|
|
|
|
|
|
|
|
vshPrint(ctl, "%-20s %s %s\n",
|
|
|
|
inactiveNames[i],
|
|
|
|
_("inactive"),
|
|
|
|
autostartStr);
|
2007-02-14 16:53:55 +00:00
|
|
|
|
|
|
|
virNetworkFree(network);
|
|
|
|
free(inactiveNames[i]);
|
|
|
|
}
|
2008-01-29 17:41:07 +00:00
|
|
|
free(activeNames);
|
|
|
|
free(inactiveNames);
|
2007-02-14 16:53:55 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* "net-name" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_network_name[] = {
|
|
|
|
{"syntax", "net-name <network>"},
|
|
|
|
{"help", gettext_noop("convert a network UUID to network name")},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_network_name[] = {
|
|
|
|
{"network", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("network uuid")},
|
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdNetworkName(vshControl * ctl, vshCmd * cmd)
|
|
|
|
{
|
|
|
|
virNetworkPtr network;
|
|
|
|
|
|
|
|
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
|
|
|
return FALSE;
|
|
|
|
if (!(network = vshCommandOptNetworkBy(ctl, cmd, "network", NULL,
|
|
|
|
VSH_BYUUID)))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
vshPrint(ctl, "%s\n", virNetworkGetName(network));
|
|
|
|
virNetworkFree(network);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* "net-start" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_network_start[] = {
|
|
|
|
{"syntax", "start <network>"},
|
|
|
|
{"help", gettext_noop("start a (previously defined) inactive network")},
|
|
|
|
{"desc", gettext_noop("Start a network.")},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_network_start[] = {
|
|
|
|
{"name", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("name of the inactive network")},
|
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdNetworkStart(vshControl * ctl, vshCmd * cmd)
|
|
|
|
{
|
|
|
|
virNetworkPtr network;
|
|
|
|
int ret = TRUE;
|
|
|
|
|
|
|
|
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
|
|
|
return FALSE;
|
|
|
|
|
2007-02-23 10:27:53 +00:00
|
|
|
if (!(network = vshCommandOptNetworkBy(ctl, cmd, "name", NULL, VSH_BYNAME)))
|
|
|
|
return FALSE;
|
2007-02-14 16:53:55 +00:00
|
|
|
|
|
|
|
if (virNetworkCreate(network) == 0) {
|
|
|
|
vshPrint(ctl, _("Network %s started\n"),
|
2007-02-23 10:27:53 +00:00
|
|
|
virNetworkGetName(network));
|
2007-02-14 16:53:55 +00:00
|
|
|
} else {
|
2007-02-23 10:27:53 +00:00
|
|
|
vshError(ctl, FALSE, _("Failed to start network %s"),
|
|
|
|
virNetworkGetName(network));
|
2007-02-14 16:53:55 +00:00
|
|
|
ret = FALSE;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* "net-undefine" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_network_undefine[] = {
|
|
|
|
{"syntax", "net-undefine <network>"},
|
|
|
|
{"help", gettext_noop("undefine an inactive network")},
|
|
|
|
{"desc", gettext_noop("Undefine the configuration for an inactive network.")},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_network_undefine[] = {
|
|
|
|
{"network", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("network name or uuid")},
|
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdNetworkUndefine(vshControl * ctl, vshCmd * cmd)
|
|
|
|
{
|
|
|
|
virNetworkPtr network;
|
|
|
|
int ret = TRUE;
|
|
|
|
char *name;
|
|
|
|
|
|
|
|
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (!(network = vshCommandOptNetwork(ctl, cmd, "network", &name)))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (virNetworkUndefine(network) == 0) {
|
|
|
|
vshPrint(ctl, _("Network %s has been undefined\n"), name);
|
|
|
|
} else {
|
|
|
|
vshError(ctl, FALSE, _("Failed to undefine network %s"), name);
|
|
|
|
ret = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* "net-uuid" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_network_uuid[] = {
|
|
|
|
{"syntax", "net-uuid <network>"},
|
|
|
|
{"help", gettext_noop("convert a network name to network UUID")},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_network_uuid[] = {
|
|
|
|
{"network", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("network name")},
|
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdNetworkUuid(vshControl * ctl, vshCmd * cmd)
|
|
|
|
{
|
|
|
|
virNetworkPtr network;
|
|
|
|
char uuid[VIR_UUID_STRING_BUFLEN];
|
|
|
|
|
|
|
|
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (!(network = vshCommandOptNetworkBy(ctl, cmd, "network", NULL,
|
|
|
|
VSH_BYNAME)))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (virNetworkGetUUIDString(network, uuid) != -1)
|
|
|
|
vshPrint(ctl, "%s\n", uuid);
|
|
|
|
else
|
2008-01-16 17:13:23 +00:00
|
|
|
vshError(ctl, FALSE, "%s", _("failed to get network UUID"));
|
2007-02-14 16:53:55 +00:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-20 15:27:08 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2005-12-08 13:26:52 +00:00
|
|
|
/*
|
2008-02-20 15:27:08 +00:00
|
|
|
* "pool-autostart" command
|
2005-12-08 13:26:52 +00:00
|
|
|
*/
|
2008-02-20 15:27:08 +00:00
|
|
|
static vshCmdInfo info_pool_autostart[] = {
|
|
|
|
{"syntax", "pool-autostart [--disable] <pool>"},
|
|
|
|
{"help", gettext_noop("autostart a pool")},
|
|
|
|
{"desc",
|
|
|
|
gettext_noop("Configure a pool to be automatically started at boot.")},
|
2006-03-15 12:13:25 +00:00
|
|
|
{NULL, NULL}
|
2005-12-08 13:26:52 +00:00
|
|
|
};
|
|
|
|
|
2008-02-20 15:27:08 +00:00
|
|
|
static vshCmdOptDef opts_pool_autostart[] = {
|
|
|
|
{"pool", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("pool name or uuid")},
|
|
|
|
{"disable", VSH_OT_BOOL, 0, gettext_noop("disable autostarting")},
|
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
2005-12-08 13:26:52 +00:00
|
|
|
|
|
|
|
static int
|
2008-02-20 15:27:08 +00:00
|
|
|
cmdPoolAutostart(vshControl * ctl, vshCmd * cmd)
|
2006-03-15 12:13:25 +00:00
|
|
|
{
|
2008-02-20 15:27:08 +00:00
|
|
|
virStoragePoolPtr pool;
|
|
|
|
char *name;
|
|
|
|
int autostart;
|
2005-12-08 13:26:52 +00:00
|
|
|
|
|
|
|
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
|
|
|
return FALSE;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2008-02-20 15:27:08 +00:00
|
|
|
if (!(pool = vshCommandOptPool(ctl, cmd, "pool", &name)))
|
2005-12-08 13:26:52 +00:00
|
|
|
return FALSE;
|
|
|
|
|
2008-02-20 15:27:08 +00:00
|
|
|
autostart = !vshCommandOptBool(cmd, "disable");
|
2005-12-08 15:08:46 +00:00
|
|
|
|
2008-02-20 15:27:08 +00:00
|
|
|
if (virStoragePoolSetAutostart(pool, autostart) < 0) {
|
|
|
|
if (autostart)
|
|
|
|
vshError(ctl, FALSE, _("failed to mark pool %s as autostarted"),
|
|
|
|
name);
|
|
|
|
else
|
|
|
|
vshError(ctl, FALSE,_("failed to unmark pool %s as autostarted"),
|
|
|
|
name);
|
|
|
|
virStoragePoolFree(pool);
|
2005-12-08 15:08:46 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2008-02-20 15:27:08 +00:00
|
|
|
if (autostart)
|
|
|
|
vshPrint(ctl, _("Pool %s marked as autostarted\n"), name);
|
|
|
|
else
|
|
|
|
vshPrint(ctl, _("Pool %s unmarked as autostarted\n"), name);
|
2005-12-08 13:26:52 +00:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2007-01-26 11:54:29 +00:00
|
|
|
/*
|
2008-02-20 15:27:08 +00:00
|
|
|
* "pool-create" command
|
2007-06-26 11:42:46 +00:00
|
|
|
*/
|
2008-02-20 15:27:08 +00:00
|
|
|
static vshCmdInfo info_pool_create[] = {
|
|
|
|
{"syntax", "create a pool from an XML <file>"},
|
|
|
|
{"help", gettext_noop("create a pool from an XML file")},
|
|
|
|
{"desc", gettext_noop("Create a pool.")},
|
2007-06-26 11:42:46 +00:00
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
2008-02-20 15:27:08 +00:00
|
|
|
static vshCmdOptDef opts_pool_create[] = {
|
|
|
|
{"file", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("file containing an XML pool description")},
|
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
2007-06-26 11:42:46 +00:00
|
|
|
static int
|
2008-02-20 15:27:08 +00:00
|
|
|
cmdPoolCreate(vshControl * ctl, vshCmd * cmd)
|
2007-06-26 11:42:46 +00:00
|
|
|
{
|
2008-02-20 15:27:08 +00:00
|
|
|
virStoragePoolPtr pool;
|
|
|
|
char *from;
|
|
|
|
int found;
|
|
|
|
int ret = TRUE;
|
|
|
|
char *buffer;
|
2007-06-26 11:42:46 +00:00
|
|
|
|
|
|
|
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
|
|
|
return FALSE;
|
|
|
|
|
2008-02-20 15:27:08 +00:00
|
|
|
from = vshCommandOptString(cmd, "file", &found);
|
|
|
|
if (!found)
|
2007-06-26 11:42:46 +00:00
|
|
|
return FALSE;
|
|
|
|
|
2008-02-20 15:27:08 +00:00
|
|
|
if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0)
|
|
|
|
return FALSE;
|
2007-06-26 11:42:46 +00:00
|
|
|
|
2008-02-20 15:27:08 +00:00
|
|
|
pool = virStoragePoolCreateXML(ctl->conn, buffer, 0);
|
|
|
|
free (buffer);
|
|
|
|
|
|
|
|
if (pool != NULL) {
|
|
|
|
vshPrint(ctl, _("Pool %s created from %s\n"),
|
|
|
|
virStoragePoolGetName(pool), from);
|
|
|
|
} else {
|
|
|
|
vshError(ctl, FALSE, _("Failed to create pool from %s"), from);
|
|
|
|
ret = FALSE;
|
|
|
|
}
|
|
|
|
return ret;
|
2007-06-26 11:42:46 +00:00
|
|
|
}
|
|
|
|
|
2008-02-20 15:29:13 +00:00
|
|
|
/*
|
|
|
|
* "pool-create-as" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_pool_create_as[] = {
|
|
|
|
{"syntax", "pool-create-as <name> <type>"},
|
|
|
|
{"help", gettext_noop("create a pool from a set of args")},
|
|
|
|
{"desc", gettext_noop("Create a pool.")},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_pool_create_as[] = {
|
|
|
|
{"name", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("name of the pool")},
|
|
|
|
{"type", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("type of the pool")},
|
|
|
|
{"source-host", VSH_OT_DATA, 0, gettext_noop("source-host for underlying storage")},
|
|
|
|
{"source-path", VSH_OT_DATA, 0, gettext_noop("source path for underlying storage")},
|
|
|
|
{"source-dev", VSH_OT_DATA, 0, gettext_noop("source device for underlying storage")},
|
|
|
|
{"target", VSH_OT_DATA, 0, gettext_noop("target for underlying storage")},
|
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdPoolCreateAs(vshControl * ctl, vshCmd * cmd)
|
|
|
|
{
|
|
|
|
virStoragePoolPtr pool;
|
|
|
|
int found;
|
|
|
|
char *name, *type, *srcHost, *srcPath, *srcDev, *target;
|
|
|
|
virBuffer buf;
|
|
|
|
|
|
|
|
memset(&buf, 0, sizeof(buf));
|
|
|
|
|
|
|
|
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
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);
|
|
|
|
target = vshCommandOptString(cmd, "target", &found);
|
|
|
|
|
|
|
|
if (virBufferVSprintf(&buf, "<pool type='%s'>\n", type) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (virBufferVSprintf(&buf, " <name>%s</name>\n", name) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (srcHost || srcPath || srcDev) {
|
|
|
|
if (virBufferAddLit(&buf, " <source>\n") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (srcHost &&
|
|
|
|
virBufferVSprintf(&buf, " <host name='%s'>\n", srcHost) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (srcPath &&
|
|
|
|
virBufferVSprintf(&buf, " <dir path='%s'/>\n", srcPath) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (srcDev &&
|
|
|
|
virBufferVSprintf(&buf, " <device path='%s'/>\n", srcDev) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virBufferAddLit(&buf, " </source>\n") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
if (target) {
|
|
|
|
if (virBufferAddLit(&buf, " <target>\n") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (virBufferVSprintf(&buf, " <path>%s</path>\n", target) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (virBufferAddLit(&buf, " </target>\n") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
if (virBufferAddLit(&buf, "</pool>\n") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
pool = virStoragePoolCreateXML(ctl->conn, buf.content, 0);
|
|
|
|
free (buf.content);
|
|
|
|
|
|
|
|
if (pool != NULL) {
|
|
|
|
vshPrint(ctl, _("Pool %s created\n"), name);
|
|
|
|
virStoragePoolFree(pool);
|
|
|
|
return TRUE;
|
|
|
|
} else {
|
|
|
|
vshError(ctl, FALSE, _("Failed to create pool %s"), name);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
free(buf.content);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2008-02-20 15:27:08 +00:00
|
|
|
|
2007-06-26 11:42:46 +00:00
|
|
|
/*
|
2008-02-20 15:27:08 +00:00
|
|
|
* "pool-define" command
|
2007-06-26 11:42:46 +00:00
|
|
|
*/
|
2008-02-20 15:27:08 +00:00
|
|
|
static vshCmdInfo info_pool_define[] = {
|
|
|
|
{"syntax", "define a pool from an XML <file>"},
|
|
|
|
{"help", gettext_noop("define (but don't start) a pool from an XML file")},
|
|
|
|
{"desc", gettext_noop("Define a pool.")},
|
2007-06-26 11:42:46 +00:00
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
2008-02-20 15:27:08 +00:00
|
|
|
static vshCmdOptDef opts_pool_define[] = {
|
|
|
|
{"file", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("file containing an XML pool description")},
|
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
2007-06-26 11:42:46 +00:00
|
|
|
static int
|
2008-02-20 15:27:08 +00:00
|
|
|
cmdPoolDefine(vshControl * ctl, vshCmd * cmd)
|
2007-06-26 11:42:46 +00:00
|
|
|
{
|
2008-02-20 15:27:08 +00:00
|
|
|
virStoragePoolPtr pool;
|
|
|
|
char *from;
|
|
|
|
int found;
|
|
|
|
int ret = TRUE;
|
|
|
|
char *buffer;
|
2007-06-26 11:42:46 +00:00
|
|
|
|
|
|
|
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
|
|
|
return FALSE;
|
|
|
|
|
2008-02-20 15:27:08 +00:00
|
|
|
from = vshCommandOptString(cmd, "file", &found);
|
|
|
|
if (!found)
|
2007-06-26 11:42:46 +00:00
|
|
|
return FALSE;
|
|
|
|
|
2008-02-20 15:27:08 +00:00
|
|
|
if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0)
|
|
|
|
return FALSE;
|
2007-06-26 11:42:46 +00:00
|
|
|
|
2008-02-20 15:27:08 +00:00
|
|
|
pool = virStoragePoolDefineXML(ctl->conn, buffer, 0);
|
|
|
|
free (buffer);
|
|
|
|
|
|
|
|
if (pool != NULL) {
|
|
|
|
vshPrint(ctl, _("Pool %s defined from %s\n"),
|
|
|
|
virStoragePoolGetName(pool), from);
|
|
|
|
} else {
|
|
|
|
vshError(ctl, FALSE, _("Failed to define pool from %s"), from);
|
|
|
|
ret = FALSE;
|
|
|
|
}
|
|
|
|
return ret;
|
2007-06-26 11:42:46 +00:00
|
|
|
}
|
|
|
|
|
2008-02-20 15:27:08 +00:00
|
|
|
|
2008-02-20 15:29:13 +00:00
|
|
|
/*
|
|
|
|
* "pool-define-as" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_pool_define_as[] = {
|
|
|
|
{"syntax", "pool-define-as <name> <type>"},
|
|
|
|
{"help", gettext_noop("define a pool from a set of args")},
|
|
|
|
{"desc", gettext_noop("Define a pool.")},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_pool_define_as[] = {
|
|
|
|
{"name", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("name of the pool")},
|
|
|
|
{"type", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("type of the pool")},
|
|
|
|
{"source-host", VSH_OT_DATA, 0, gettext_noop("source-host for underlying storage")},
|
|
|
|
{"source-path", VSH_OT_DATA, 0, gettext_noop("source path for underlying storage")},
|
|
|
|
{"source-dev", VSH_OT_DATA, 0, gettext_noop("source device for underlying storage")},
|
|
|
|
{"target", VSH_OT_DATA, 0, gettext_noop("target for underlying storage")},
|
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdPoolDefineAs(vshControl * ctl, vshCmd * cmd)
|
|
|
|
{
|
|
|
|
virStoragePoolPtr pool;
|
|
|
|
int found;
|
|
|
|
char *name, *type, *srcHost, *srcPath, *srcDev, *target;
|
|
|
|
virBuffer buf;
|
|
|
|
|
|
|
|
memset(&buf, 0, sizeof(buf));
|
|
|
|
|
|
|
|
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
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);
|
|
|
|
target = vshCommandOptString(cmd, "target", &found);
|
|
|
|
|
|
|
|
if (virBufferVSprintf(&buf, "<pool type='%s'>\n", type) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (virBufferVSprintf(&buf, " <name>%s</name>\n", name) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (srcHost || srcPath || srcDev) {
|
|
|
|
if (virBufferAddLit(&buf, " <source>\n") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (srcHost &&
|
|
|
|
virBufferVSprintf(&buf, " <host>%s</host>\n", srcHost) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (srcPath &&
|
|
|
|
virBufferVSprintf(&buf, " <path>%s</path>\n", srcPath) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (srcDev &&
|
|
|
|
virBufferVSprintf(&buf, " <device>%s</device>\n", srcDev) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virBufferAddLit(&buf, " </source>\n") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
if (target) {
|
|
|
|
if (virBufferAddLit(&buf, " <target>\n") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (virBufferVSprintf(&buf, " <path>%s</path>\n", target) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (virBufferAddLit(&buf, " </target>\n") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
if (virBufferAddLit(&buf, "</pool>\n") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
pool = virStoragePoolDefineXML(ctl->conn, buf.content, 0);
|
|
|
|
free (buf.content);
|
|
|
|
|
|
|
|
if (pool != NULL) {
|
|
|
|
vshPrint(ctl, _("Pool %s defined\n"), name);
|
|
|
|
virStoragePoolFree(pool);
|
|
|
|
return TRUE;
|
|
|
|
} else {
|
|
|
|
vshError(ctl, FALSE, _("Failed to define pool %s"), name);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
free(buf.content);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-06-26 11:42:46 +00:00
|
|
|
/*
|
2008-02-20 15:27:08 +00:00
|
|
|
* "pool-build" command
|
2007-01-26 11:54:29 +00:00
|
|
|
*/
|
2008-02-20 15:27:08 +00:00
|
|
|
static vshCmdInfo info_pool_build[] = {
|
|
|
|
{"syntax", "pool-build <pool>"},
|
|
|
|
{"help", gettext_noop("build a pool")},
|
|
|
|
{"desc", gettext_noop("Build a given pool.")},
|
2007-01-26 11:54:29 +00:00
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
2008-02-20 15:27:08 +00:00
|
|
|
static vshCmdOptDef opts_pool_build[] = {
|
|
|
|
{"pool", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("pool name or uuid")},
|
2007-01-26 11:54:29 +00:00
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
2008-02-20 15:27:08 +00:00
|
|
|
cmdPoolBuild(vshControl * ctl, vshCmd * cmd)
|
2007-01-26 11:54:29 +00:00
|
|
|
{
|
2008-02-20 15:27:08 +00:00
|
|
|
virStoragePoolPtr pool;
|
|
|
|
int ret = TRUE;
|
|
|
|
char *name;
|
2007-01-26 11:54:29 +00:00
|
|
|
|
|
|
|
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
|
|
|
return FALSE;
|
|
|
|
|
2008-02-20 15:27:08 +00:00
|
|
|
if (!(pool = vshCommandOptPool(ctl, cmd, "pool", &name)))
|
2007-01-26 11:54:29 +00:00
|
|
|
return FALSE;
|
|
|
|
|
2008-02-20 15:27:08 +00:00
|
|
|
if (virStoragePoolBuild(pool, 0) == 0) {
|
|
|
|
vshPrint(ctl, _("Pool %s builded\n"), name);
|
2007-01-26 11:54:29 +00:00
|
|
|
} else {
|
2008-02-20 15:27:08 +00:00
|
|
|
vshError(ctl, FALSE, _("Failed to build pool %s"), name);
|
|
|
|
ret = FALSE;
|
|
|
|
virStoragePoolFree(pool);
|
2007-01-26 11:54:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2008-02-20 15:27:08 +00:00
|
|
|
|
2007-07-26 08:41:16 +00:00
|
|
|
/*
|
2008-02-20 15:27:08 +00:00
|
|
|
* "pool-destroy" command
|
2007-07-26 08:41:16 +00:00
|
|
|
*/
|
2008-02-20 15:27:08 +00:00
|
|
|
static vshCmdInfo info_pool_destroy[] = {
|
|
|
|
{"syntax", "pool-destroy <pool>"},
|
|
|
|
{"help", gettext_noop("destroy a pool")},
|
|
|
|
{"desc", gettext_noop("Destroy a given pool.")},
|
2007-07-26 08:41:16 +00:00
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
2008-02-20 15:27:08 +00:00
|
|
|
static vshCmdOptDef opts_pool_destroy[] = {
|
|
|
|
{"pool", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("pool name or uuid")},
|
2007-07-26 08:41:16 +00:00
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
2008-02-20 15:27:08 +00:00
|
|
|
cmdPoolDestroy(vshControl * ctl, vshCmd * cmd)
|
2007-07-26 08:41:16 +00:00
|
|
|
{
|
2008-02-20 15:27:08 +00:00
|
|
|
virStoragePoolPtr pool;
|
|
|
|
int ret = TRUE;
|
|
|
|
char *name;
|
2007-07-26 08:41:16 +00:00
|
|
|
|
|
|
|
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
|
|
|
return FALSE;
|
|
|
|
|
2008-02-20 15:27:08 +00:00
|
|
|
if (!(pool = vshCommandOptPool(ctl, cmd, "pool", &name)))
|
2007-07-26 08:41:16 +00:00
|
|
|
return FALSE;
|
|
|
|
|
2008-02-20 15:27:08 +00:00
|
|
|
if (virStoragePoolDestroy(pool) == 0) {
|
|
|
|
vshPrint(ctl, _("Pool %s destroyed\n"), name);
|
|
|
|
} else {
|
|
|
|
vshError(ctl, FALSE, _("Failed to destroy pool %s"), name);
|
|
|
|
ret = FALSE;
|
|
|
|
virStoragePoolFree(pool);
|
2007-07-26 08:41:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2008-02-20 15:27:08 +00:00
|
|
|
|
2007-05-23 15:09:19 +00:00
|
|
|
/*
|
2008-02-20 15:27:08 +00:00
|
|
|
* "pool-delete" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_pool_delete[] = {
|
|
|
|
{"syntax", "pool-delete <pool>"},
|
|
|
|
{"help", gettext_noop("delete a pool")},
|
|
|
|
{"desc", gettext_noop("Delete a given pool.")},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_pool_delete[] = {
|
|
|
|
{"pool", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("pool name or uuid")},
|
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdPoolDelete(vshControl * ctl, 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) {
|
2008-03-14 15:21:15 +00:00
|
|
|
vshPrint(ctl, _("Pool %s deleted\n"), name);
|
2008-02-20 15:27:08 +00:00
|
|
|
} else {
|
|
|
|
vshError(ctl, FALSE, _("Failed to delete pool %s"), name);
|
|
|
|
ret = FALSE;
|
|
|
|
virStoragePoolFree(pool);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* "pool-refresh" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_pool_refresh[] = {
|
|
|
|
{"syntax", "pool-refresh <pool>"},
|
|
|
|
{"help", gettext_noop("refresh a pool")},
|
|
|
|
{"desc", gettext_noop("Refresh a given pool.")},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_pool_refresh[] = {
|
|
|
|
{"pool", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("pool name or uuid")},
|
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdPoolRefresh(vshControl * ctl, 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, FALSE, _("Failed to refresh pool %s"), name);
|
|
|
|
ret = FALSE;
|
|
|
|
}
|
|
|
|
virStoragePoolFree(pool);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* "pool-dumpxml" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_pool_dumpxml[] = {
|
|
|
|
{"syntax", "pool-dumpxml <pool>"},
|
|
|
|
{"help", gettext_noop("pool information in XML")},
|
|
|
|
{"desc", gettext_noop("Output the pool information as an XML dump to stdout.")},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_pool_dumpxml[] = {
|
|
|
|
{"pool", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("pool name or uuid")},
|
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdPoolDumpXML(vshControl * ctl, 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);
|
|
|
|
free(dump);
|
|
|
|
} else {
|
|
|
|
ret = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
virStoragePoolFree(pool);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* "pool-list" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_pool_list[] = {
|
|
|
|
{"syntax", "pool-list [ --inactive | --all ]"},
|
|
|
|
{"help", gettext_noop("list pools")},
|
|
|
|
{"desc", gettext_noop("Returns list of pools.")},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_pool_list[] = {
|
|
|
|
{"inactive", VSH_OT_BOOL, 0, gettext_noop("list inactive pools")},
|
|
|
|
{"all", VSH_OT_BOOL, 0, gettext_noop("list inactive & active pools")},
|
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdPoolList(vshControl * ctl, 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, FALSE, "%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, FALSE, "%s", _("Failed to list active pools"));
|
|
|
|
free(activeNames);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
qsort(&activeNames[0], maxactive, sizeof(char *), namesorter);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (inactive) {
|
|
|
|
maxinactive = virConnectNumOfDefinedStoragePools(ctl->conn);
|
|
|
|
if (maxinactive < 0) {
|
|
|
|
vshError(ctl, FALSE, "%s", _("Failed to list inactive pools"));
|
|
|
|
free(activeNames);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
if (maxinactive) {
|
|
|
|
inactiveNames = vshMalloc(ctl, sizeof(char *) * maxinactive);
|
|
|
|
|
|
|
|
if ((maxinactive = virConnectListDefinedStoragePools(ctl->conn, inactiveNames, maxinactive)) < 0) {
|
|
|
|
vshError(ctl, FALSE, "%s", _("Failed to list inactive pools"));
|
|
|
|
free(activeNames);
|
|
|
|
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) {
|
|
|
|
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);
|
|
|
|
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) {
|
|
|
|
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);
|
|
|
|
free(inactiveNames[i]);
|
|
|
|
}
|
|
|
|
free(activeNames);
|
|
|
|
free(inactiveNames);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
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));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* "pool-info" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_pool_info[] = {
|
|
|
|
{"syntax", "pool-info <pool>"},
|
|
|
|
{"help", gettext_noop("storage pool information")},
|
|
|
|
{"desc", gettext_noop("Returns basic information about the storage pool.")},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_pool_info[] = {
|
|
|
|
{"pool", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("pool name or uuid")},
|
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdPoolInfo(vshControl * ctl, 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 vshCmdInfo info_pool_name[] = {
|
|
|
|
{"syntax", "pool-name <pool>"},
|
|
|
|
{"help", gettext_noop("convert a pool UUID to pool name")},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_pool_name[] = {
|
|
|
|
{"pool", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("pool uuid")},
|
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdPoolName(vshControl * ctl, 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 vshCmdInfo info_pool_start[] = {
|
|
|
|
{"syntax", "start <pool>"},
|
|
|
|
{"help", gettext_noop("start a (previously defined) inactive pool")},
|
|
|
|
{"desc", gettext_noop("Start a pool.")},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_pool_start[] = {
|
|
|
|
{"name", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("name of the inactive pool")},
|
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdPoolStart(vshControl * ctl, vshCmd * cmd)
|
|
|
|
{
|
|
|
|
virStoragePoolPtr pool;
|
|
|
|
int ret = TRUE;
|
|
|
|
|
|
|
|
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (!(pool = vshCommandOptPoolBy(ctl, cmd, "name", NULL, VSH_BYNAME)))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (virStoragePoolCreate(pool, 0) == 0) {
|
|
|
|
vshPrint(ctl, _("Pool %s started\n"),
|
|
|
|
virStoragePoolGetName(pool));
|
|
|
|
} else {
|
|
|
|
vshError(ctl, FALSE, _("Failed to start pool %s"),
|
|
|
|
virStoragePoolGetName(pool));
|
|
|
|
ret = FALSE;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-20 15:29:13 +00:00
|
|
|
/*
|
|
|
|
* "vol-create-as" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_vol_create_as[] = {
|
2008-03-14 15:21:15 +00:00
|
|
|
{"syntax", "vol-create-as <pool> <name> <capacity>"},
|
|
|
|
{"help", gettext_noop("create a volume from a set of args")},
|
2008-02-20 15:29:13 +00:00
|
|
|
{"desc", gettext_noop("Create a vol.")},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_vol_create_as[] = {
|
|
|
|
{"pool", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("pool name")},
|
2008-03-14 15:21:15 +00:00
|
|
|
{"name", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("name of the volume")},
|
2008-02-20 15:29:13 +00:00
|
|
|
{"capacity", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("size of the vol with optional k,M,G,T suffix")},
|
|
|
|
{"allocation", VSH_OT_DATA, 0, gettext_noop("initial allocation size with optional k,M,G,T suffix")},
|
|
|
|
{"format", VSH_OT_DATA, 0, gettext_noop("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) {
|
|
|
|
/* Delibrate 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
|
|
|
|
cmdVolCreateAs(vshControl * ctl, vshCmd * cmd)
|
|
|
|
{
|
|
|
|
virStoragePoolPtr pool;
|
|
|
|
virStorageVolPtr vol;
|
|
|
|
int found;
|
|
|
|
char *name, *capacityStr, *allocationStr, *format;
|
|
|
|
unsigned long long capacity, allocation = 0;
|
|
|
|
virBuffer buf;
|
|
|
|
|
|
|
|
memset(&buf, 0, sizeof(buf));
|
|
|
|
|
|
|
|
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, FALSE, _("Malformed size %s"), capacityStr);
|
|
|
|
|
|
|
|
allocationStr = vshCommandOptString(cmd, "allocation", &found);
|
|
|
|
if (allocationStr &&
|
|
|
|
cmdVolSize(allocationStr, &allocation) < 0)
|
|
|
|
vshError(ctl, FALSE, _("Malformed size %s"), allocationStr);
|
|
|
|
|
|
|
|
format = vshCommandOptString(cmd, "format", &found);
|
|
|
|
|
|
|
|
if (virBufferAddLit(&buf, "<volume>\n") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (virBufferVSprintf(&buf, " <name>%s</name>\n", name) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (virBufferVSprintf(&buf, " <capacity>%llu</capacity>\n", capacity) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (allocationStr &&
|
|
|
|
virBufferVSprintf(&buf, " <allocation>%llu</allocation>\n", allocation) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (format) {
|
|
|
|
if (virBufferAddLit(&buf, " <target>\n") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (format)
|
|
|
|
if (virBufferVSprintf(&buf, " <format type='%s'/>\n",format) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (virBufferAddLit(&buf, " </target>\n") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
if (virBufferAddLit(&buf, "</volume>\n") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
vol = virStorageVolCreateXML(pool, buf.content, 0);
|
|
|
|
free (buf.content);
|
|
|
|
virStoragePoolFree(pool);
|
|
|
|
|
|
|
|
if (vol != NULL) {
|
|
|
|
vshPrint(ctl, _("Vol %s created\n"), name);
|
|
|
|
virStorageVolFree(vol);
|
|
|
|
return TRUE;
|
|
|
|
} else {
|
|
|
|
vshError(ctl, FALSE, _("Failed to create vol %s"), name);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
free(buf.content);
|
|
|
|
virStoragePoolFree(pool);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-20 15:27:08 +00:00
|
|
|
/*
|
|
|
|
* "pool-undefine" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_pool_undefine[] = {
|
|
|
|
{"syntax", "pool-undefine <pool>"},
|
|
|
|
{"help", gettext_noop("undefine an inactive pool")},
|
|
|
|
{"desc", gettext_noop("Undefine the configuration for an inactive pool.")},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_pool_undefine[] = {
|
|
|
|
{"pool", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("pool name or uuid")},
|
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdPoolUndefine(vshControl * ctl, 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, FALSE, _("Failed to undefine pool %s"), name);
|
|
|
|
ret = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* "pool-uuid" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_pool_uuid[] = {
|
|
|
|
{"syntax", "pool-uuid <pool>"},
|
|
|
|
{"help", gettext_noop("convert a pool name to pool UUID")},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_pool_uuid[] = {
|
|
|
|
{"pool", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("pool name")},
|
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdPoolUuid(vshControl * ctl, 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, FALSE, "%s", _("failed to get pool UUID"));
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* "vol-create" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_vol_create[] = {
|
|
|
|
{"syntax", "create <file>"},
|
|
|
|
{"help", gettext_noop("create a vol from an XML file")},
|
|
|
|
{"desc", gettext_noop("Create a vol.")},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_vol_create[] = {
|
|
|
|
{"pool", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("pool name")},
|
|
|
|
{"file", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("file containing an XML vol description")},
|
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdVolCreate(vshControl * ctl, 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) {
|
|
|
|
virStoragePoolFree(pool);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
vol = virStorageVolCreateXML(pool, buffer, 0);
|
|
|
|
free (buffer);
|
|
|
|
virStoragePoolFree(pool);
|
|
|
|
|
|
|
|
if (vol != NULL) {
|
|
|
|
vshPrint(ctl, _("Vol %s created from %s\n"),
|
|
|
|
virStorageVolGetName(vol), from);
|
|
|
|
virStorageVolFree(vol);
|
|
|
|
} else {
|
|
|
|
vshError(ctl, FALSE, _("Failed to create vol from %s"), from);
|
|
|
|
ret = FALSE;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* "vol-delete" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_vol_delete[] = {
|
|
|
|
{"syntax", "vol-delete <vol>"},
|
|
|
|
{"help", gettext_noop("delete a vol")},
|
|
|
|
{"desc", gettext_noop("Delete a given vol.")},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_vol_delete[] = {
|
|
|
|
{"pool", VSH_OT_STRING, 0, gettext_noop("pool name or uuid")},
|
|
|
|
{"vol", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("vol name, key or path")},
|
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdVolDelete(vshControl * ctl, 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) {
|
2008-03-14 15:21:15 +00:00
|
|
|
vshPrint(ctl, _("Vol %s deleted\n"), name);
|
2008-02-20 15:27:08 +00:00
|
|
|
} else {
|
|
|
|
vshError(ctl, FALSE, _("Failed to delete vol %s"), name);
|
|
|
|
ret = FALSE;
|
|
|
|
virStorageVolFree(vol);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* "vol-info" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_vol_info[] = {
|
|
|
|
{"syntax", "vol-info <vol>"},
|
|
|
|
{"help", gettext_noop("storage vol information")},
|
|
|
|
{"desc", gettext_noop("Returns basic information about the storage vol.")},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_vol_info[] = {
|
|
|
|
{"pool", VSH_OT_STRING, 0, gettext_noop("pool name or uuid")},
|
|
|
|
{"vol", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("vol name, key or path")},
|
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdVolInfo(vshControl * ctl, 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 vshCmdInfo info_vol_dumpxml[] = {
|
|
|
|
{"syntax", "vol-dumpxml <vol>"},
|
|
|
|
{"help", gettext_noop("vol information in XML")},
|
|
|
|
{"desc", gettext_noop("Output the vol information as an XML dump to stdout.")},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_vol_dumpxml[] = {
|
|
|
|
{"pool", VSH_OT_STRING, 0, gettext_noop("pool name or uuid")},
|
|
|
|
{"vol", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("vol name, key or path")},
|
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdVolDumpXML(vshControl * ctl, 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);
|
|
|
|
free(dump);
|
|
|
|
} else {
|
|
|
|
ret = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
virStorageVolFree(vol);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* "vol-list" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_vol_list[] = {
|
|
|
|
{"syntax", "vol-list <pool>"},
|
|
|
|
{"help", gettext_noop("list vols")},
|
|
|
|
{"desc", gettext_noop("Returns list of vols by pool.")},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_vol_list[] = {
|
|
|
|
{"pool", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("pool name or uuid")},
|
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdVolList(vshControl * ctl, 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, FALSE, "%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, FALSE, "%s", _("Failed to list active vols"));
|
|
|
|
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) {
|
|
|
|
free(activeNames[i]);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((path = virStorageVolGetPath(vol)) == NULL) {
|
|
|
|
virStorageVolFree(vol);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
vshPrint(ctl, "%-20s %-40s\n",
|
|
|
|
virStorageVolGetName(vol),
|
|
|
|
path);
|
|
|
|
free(path);
|
|
|
|
virStorageVolFree(vol);
|
|
|
|
free(activeNames[i]);
|
|
|
|
}
|
|
|
|
free(activeNames);
|
|
|
|
virStoragePoolFree(pool);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* "vol-name" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_vol_name[] = {
|
|
|
|
{"syntax", "vol-name <vol>"},
|
|
|
|
{"help", gettext_noop("convert a vol UUID to vol name")},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_vol_name[] = {
|
|
|
|
{"vol", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("vol key or path")},
|
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdVolName(vshControl * ctl, 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 vshCmdInfo info_vol_key[] = {
|
|
|
|
{"syntax", "vol-key <vol>"},
|
|
|
|
{"help", gettext_noop("convert a vol UUID to vol key")},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_vol_key[] = {
|
|
|
|
{"vol", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("vol uuid")},
|
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdVolKey(vshControl * ctl, vshCmd * cmd)
|
|
|
|
{
|
|
|
|
virStorageVolPtr vol;
|
|
|
|
|
|
|
|
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (!(vol = vshCommandOptVolBy(ctl, cmd, "vol", NULL, NULL,
|
|
|
|
VSH_BYUUID)))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
vshPrint(ctl, "%s\n", virStorageVolGetKey(vol));
|
|
|
|
virStorageVolFree(vol);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* "vol-path" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_vol_path[] = {
|
|
|
|
{"syntax", "vol-path <pool> <vol>"},
|
|
|
|
{"help", gettext_noop("convert a vol UUID to vol path")},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_vol_path[] = {
|
|
|
|
{"pool", VSH_OT_STRING, 0, gettext_noop("pool name or uuid")},
|
|
|
|
{"vol", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("vol name or key")},
|
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdVolPath(vshControl * ctl, 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", virStorageVolGetPath(vol));
|
|
|
|
virStorageVolFree(vol);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* "version" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_version[] = {
|
|
|
|
{"syntax", "version"},
|
|
|
|
{"help", gettext_noop("show version")},
|
|
|
|
{"desc", gettext_noop("Display the system version information.")},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdVersion(vshControl * ctl, 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, FALSE, "%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, FALSE, "%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, FALSE, "%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;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* "hostkey" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_hostname[] = {
|
|
|
|
{"syntax", "hostname"},
|
|
|
|
{"help", gettext_noop("print the hypervisor hostname")},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdHostname (vshControl *ctl, vshCmd *cmd ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
char *hostname;
|
|
|
|
|
|
|
|
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
hostname = virConnectGetHostname (ctl->conn);
|
|
|
|
if (hostname == NULL) {
|
|
|
|
vshError(ctl, FALSE, "%s", _("failed to get hostname"));
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
vshPrint (ctl, "%s\n", hostname);
|
|
|
|
free (hostname);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* "uri" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_uri[] = {
|
|
|
|
{"syntax", "uri"},
|
|
|
|
{"help", gettext_noop("print the hypervisor canonical URI")},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdURI (vshControl *ctl, vshCmd *cmd ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
char *uri;
|
|
|
|
|
|
|
|
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
uri = virConnectGetURI (ctl->conn);
|
|
|
|
if (uri == NULL) {
|
|
|
|
vshError(ctl, FALSE, "%s", _("failed to get URI"));
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
vshPrint (ctl, "%s\n", uri);
|
|
|
|
free (uri);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* "vncdisplay" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_vncdisplay[] = {
|
|
|
|
{"syntax", "vncdisplay <domain>"},
|
|
|
|
{"help", gettext_noop("vnc display")},
|
|
|
|
{"desc", gettext_noop("Output the IP address and port number for the VNC display.")},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_vncdisplay[] = {
|
|
|
|
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
|
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdVNCDisplay(vshControl * ctl, 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;
|
|
|
|
|
|
|
|
if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", 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);
|
|
|
|
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) ||
|
|
|
|
!strcmp((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 vshCmdInfo info_ttyconsole[] = {
|
|
|
|
{"syntax", "ttyconsole <domain>"},
|
|
|
|
{"help", gettext_noop("tty console")},
|
|
|
|
{"desc", gettext_noop("Output the device for the TTY console.")},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_ttyconsole[] = {
|
|
|
|
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
|
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdTTYConsole(vshControl * ctl, 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;
|
|
|
|
|
|
|
|
if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", 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);
|
|
|
|
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);
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
xmlXPathFreeObject(obj);
|
|
|
|
xmlXPathFreeContext(ctxt);
|
|
|
|
if (xml)
|
|
|
|
xmlFreeDoc(xml);
|
|
|
|
virDomainFree(dom);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* "attach-device" command
|
2007-05-23 15:09:19 +00:00
|
|
|
*/
|
|
|
|
static vshCmdInfo info_attach_device[] = {
|
|
|
|
{"syntax", "attach-device <domain> <file> "},
|
|
|
|
{"help", gettext_noop("attach device from an XML file")},
|
|
|
|
{"desc", gettext_noop("Attach device from an XML <file>.")},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_attach_device[] = {
|
|
|
|
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
|
|
|
|
{"file", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("XML file")},
|
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdAttachDevice(vshControl * ctl, vshCmd * cmd)
|
|
|
|
{
|
|
|
|
virDomainPtr dom;
|
|
|
|
char *from;
|
|
|
|
char *buffer;
|
|
|
|
int ret = TRUE;
|
|
|
|
int found;
|
|
|
|
|
|
|
|
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", NULL)))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
from = vshCommandOptString(cmd, "file", &found);
|
|
|
|
if (!found) {
|
|
|
|
virDomainFree(dom);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2008-01-30 19:58:59 +00:00
|
|
|
if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) {
|
|
|
|
virDomainFree(dom);
|
2008-01-21 15:27:14 +00:00
|
|
|
return FALSE;
|
2008-01-30 19:58:59 +00:00
|
|
|
}
|
2007-05-23 15:09:19 +00:00
|
|
|
|
|
|
|
ret = virDomainAttachDevice(dom, buffer);
|
|
|
|
free (buffer);
|
|
|
|
|
|
|
|
if (ret < 0) {
|
|
|
|
vshError(ctl, FALSE, _("Failed to attach device from %s"), from);
|
|
|
|
virDomainFree(dom);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
virDomainFree(dom);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* "detach-device" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_detach_device[] = {
|
|
|
|
{"syntax", "detach-device <domain> <file> "},
|
|
|
|
{"help", gettext_noop("detach device from an XML file")},
|
|
|
|
{"desc", gettext_noop("Detach device from an XML <file>")},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_detach_device[] = {
|
|
|
|
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
|
|
|
|
{"file", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("XML file")},
|
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdDetachDevice(vshControl * ctl, vshCmd * cmd)
|
|
|
|
{
|
|
|
|
virDomainPtr dom;
|
|
|
|
char *from;
|
|
|
|
char *buffer;
|
|
|
|
int ret = TRUE;
|
|
|
|
int found;
|
|
|
|
|
|
|
|
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", NULL)))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
from = vshCommandOptString(cmd, "file", &found);
|
|
|
|
if (!found) {
|
|
|
|
virDomainFree(dom);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2008-01-30 19:58:59 +00:00
|
|
|
if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) {
|
|
|
|
virDomainFree(dom);
|
2008-01-21 15:27:14 +00:00
|
|
|
return FALSE;
|
2008-01-30 19:58:59 +00:00
|
|
|
}
|
2007-05-23 15:09:19 +00:00
|
|
|
|
|
|
|
ret = virDomainDetachDevice(dom, buffer);
|
|
|
|
free (buffer);
|
|
|
|
|
|
|
|
if (ret < 0) {
|
|
|
|
vshError(ctl, FALSE, _("Failed to detach device from %s"), from);
|
|
|
|
virDomainFree(dom);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
virDomainFree(dom);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2007-01-26 11:54:29 +00:00
|
|
|
|
2007-06-19 09:12:55 +00:00
|
|
|
/*
|
|
|
|
* "attach-interface" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_attach_interface[] = {
|
|
|
|
{"syntax", "attach-interface <domain> <type> <source> [--target <target>] [--mac <mac>] [--script <script>] "},
|
|
|
|
{"help", gettext_noop("attach network interface")},
|
|
|
|
{"desc", gettext_noop("Attach new network interface.")},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_attach_interface[] = {
|
|
|
|
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
|
|
|
|
{"type", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("network interface type")},
|
|
|
|
{"source", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("source of network interface")},
|
|
|
|
{"target", VSH_OT_DATA, 0, gettext_noop("target network name")},
|
2008-03-13 09:21:41 +00:00
|
|
|
{"mac", VSH_OT_DATA, 0, gettext_noop("MAC address")},
|
2007-06-19 09:12:55 +00:00
|
|
|
{"script", VSH_OT_DATA, 0, gettext_noop("script used to bridge network interface")},
|
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdAttachInterface(vshControl * ctl, vshCmd * cmd)
|
|
|
|
{
|
|
|
|
virDomainPtr dom = NULL;
|
|
|
|
char *mac, *target, *script, *type, *source;
|
|
|
|
int typ, ret = FALSE;
|
|
|
|
char *buf = NULL, *tmp = NULL;
|
|
|
|
|
|
|
|
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", 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 (strcmp(type, "network") == 0) {
|
|
|
|
typ = 1;
|
|
|
|
} else if (strcmp(type, "bridge") == 0) {
|
|
|
|
typ = 2;
|
|
|
|
} else {
|
|
|
|
vshError(ctl, FALSE, _("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 (virDomainAttachDevice(dom, buf))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = TRUE;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (dom)
|
|
|
|
virDomainFree(dom);
|
2008-01-29 17:41:07 +00:00
|
|
|
free(buf);
|
|
|
|
free(tmp);
|
2007-06-19 09:12:55 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* "detach-interface" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_detach_interface[] = {
|
|
|
|
{"syntax", "detach-interface <domain> <type> [--mac <mac>] "},
|
|
|
|
{"help", gettext_noop("detach network interface")},
|
|
|
|
{"desc", gettext_noop("Detach network interface.")},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_detach_interface[] = {
|
|
|
|
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
|
|
|
|
{"type", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("network interface type")},
|
2008-03-13 09:21:41 +00:00
|
|
|
{"mac", VSH_OT_DATA, 0, gettext_noop("MAC address")},
|
2007-06-19 09:12:55 +00:00
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdDetachInterface(vshControl * ctl, 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;
|
|
|
|
|
|
|
|
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", 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);
|
|
|
|
free(doc);
|
|
|
|
if (!xml) {
|
2008-01-16 17:13:23 +00:00
|
|
|
vshError(ctl, FALSE, "%s", _("Failed to get interface information"));
|
2007-06-19 09:12:55 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
ctxt = xmlXPathNewContext(xml);
|
|
|
|
if (!ctxt) {
|
2008-01-16 17:13:23 +00:00
|
|
|
vshError(ctl, FALSE, "%s", _("Failed to get interface information"));
|
2007-06-19 09:12:55 +00:00
|
|
|
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, FALSE, _("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");
|
2008-02-27 16:14:44 +00:00
|
|
|
diff_mac = virMacAddrCompare ((char *) tmp_mac, mac);
|
2007-06-19 09:12:55 +00:00
|
|
|
xmlFree(tmp_mac);
|
|
|
|
if (!diff_mac) {
|
|
|
|
goto hit;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
cur = cur->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
vshError(ctl, FALSE, _("No found interface whose MAC address is %s"), mac);
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
hit:
|
|
|
|
xml_buf = xmlBufferCreate();
|
|
|
|
if (!xml_buf) {
|
2008-01-16 17:13:23 +00:00
|
|
|
vshError(ctl, FALSE, "%s", _("Failed to allocate memory"));
|
2007-06-19 09:12:55 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(xmlNodeDump(xml_buf, xml, obj->nodesetval->nodeTab[i], 0, 0) < 0){
|
2008-01-16 17:13:23 +00:00
|
|
|
vshError(ctl, FALSE, "%s", _("Failed to create XML"));
|
2007-06-19 09:12:55 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = virDomainDetachDevice(dom, (char *)xmlBufferContent(xml_buf));
|
|
|
|
if (ret != 0)
|
|
|
|
ret = FALSE;
|
|
|
|
else
|
|
|
|
ret = TRUE;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (dom)
|
|
|
|
virDomainFree(dom);
|
2008-02-07 16:49:29 +00:00
|
|
|
xmlXPathFreeObject(obj);
|
2008-01-29 18:23:43 +00:00
|
|
|
xmlXPathFreeContext(ctxt);
|
2007-06-19 09:12:55 +00:00
|
|
|
if (xml)
|
|
|
|
xmlFreeDoc(xml);
|
|
|
|
if (xml_buf)
|
|
|
|
xmlBufferFree(xml_buf);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* "attach-disk" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_attach_disk[] = {
|
|
|
|
{"syntax", "attach-disk <domain> <source> <target> [--driver <driver>] [--subdriver <subdriver>] [--type <type>] [--mode <mode>] "},
|
|
|
|
{"help", gettext_noop("attach disk device")},
|
|
|
|
{"desc", gettext_noop("Attach new disk device.")},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_attach_disk[] = {
|
|
|
|
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
|
|
|
|
{"source", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("source of disk device")},
|
|
|
|
{"target", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("target of disk device")},
|
|
|
|
{"driver", VSH_OT_DATA, 0, gettext_noop("driver of disk device")},
|
|
|
|
{"subdriver", VSH_OT_DATA, 0, gettext_noop("subdriver of disk device")},
|
|
|
|
{"type", VSH_OT_DATA, 0, gettext_noop("target device type")},
|
|
|
|
{"mode", VSH_OT_DATA, 0, gettext_noop("mode of device reading and writing")},
|
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdAttachDisk(vshControl * ctl, vshCmd * cmd)
|
|
|
|
{
|
|
|
|
virDomainPtr dom = NULL;
|
|
|
|
char *source, *target, *driver, *subdriver, *type, *mode;
|
|
|
|
int isFile = 0, ret = FALSE;
|
|
|
|
char *buf = NULL, *tmp = NULL;
|
|
|
|
|
|
|
|
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", 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 (type) {
|
|
|
|
if (strcmp(type, "cdrom") && strcmp(type, "disk")) {
|
|
|
|
vshError(ctl, FALSE, _("No support %s in command 'attach-disk'"), type);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (driver) {
|
|
|
|
if (!strcmp(driver, "file") || !strcmp(driver, "tap")) {
|
|
|
|
isFile = 1;
|
|
|
|
} else if (strcmp(driver, "phy")) {
|
|
|
|
vshError(ctl, FALSE, _("No support %s in command 'attach-disk'"), driver);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mode) {
|
|
|
|
if (strcmp(mode, "readonly") && strcmp(mode, "shareable")) {
|
|
|
|
vshError(ctl, FALSE, _("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 (virDomainAttachDevice(dom, buf))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = TRUE;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (dom)
|
|
|
|
virDomainFree(dom);
|
2008-01-29 17:41:07 +00:00
|
|
|
free(buf);
|
|
|
|
free(tmp);
|
2007-06-19 09:12:55 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* "detach-disk" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_detach_disk[] = {
|
|
|
|
{"syntax", "detach-disk <domain> <target> "},
|
|
|
|
{"help", gettext_noop("detach disk device")},
|
|
|
|
{"desc", gettext_noop("Detach disk device.")},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static vshCmdOptDef opts_detach_disk[] = {
|
|
|
|
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
|
|
|
|
{"target", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("target of disk device")},
|
|
|
|
{NULL, 0, 0, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmdDetachDisk(vshControl * ctl, 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;
|
|
|
|
|
|
|
|
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", 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);
|
|
|
|
free(doc);
|
|
|
|
if (!xml) {
|
2008-01-16 17:13:23 +00:00
|
|
|
vshError(ctl, FALSE, "%s", _("Failed to get disk information"));
|
2007-06-19 09:12:55 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
ctxt = xmlXPathNewContext(xml);
|
|
|
|
if (!ctxt) {
|
2008-01-16 17:13:23 +00:00
|
|
|
vshError(ctl, FALSE, "%s", _("Failed to get disk information"));
|
2007-06-19 09:12:55 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
obj = xmlXPathEval(BAD_CAST "/domain/devices/disk", ctxt);
|
|
|
|
if ((obj == NULL) || (obj->type != XPATH_NODESET) ||
|
|
|
|
(obj->nodesetval == NULL) || (obj->nodesetval->nodeNr == 0)) {
|
2008-01-16 17:13:23 +00:00
|
|
|
vshError(ctl, FALSE, "%s", _("Failed to get disk information"));
|
2007-06-19 09:12:55 +00:00
|
|
|
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, FALSE, _("No found disk whose target is %s"), target);
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
hit:
|
|
|
|
xml_buf = xmlBufferCreate();
|
|
|
|
if (!xml_buf) {
|
2008-01-16 17:13:23 +00:00
|
|
|
vshError(ctl, FALSE, "%s", _("Failed to allocate memory"));
|
2007-06-19 09:12:55 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(xmlNodeDump(xml_buf, xml, obj->nodesetval->nodeTab[i], 0, 0) < 0){
|
2008-01-16 17:13:23 +00:00
|
|
|
vshError(ctl, FALSE, "%s", _("Failed to create XML"));
|
2007-06-19 09:12:55 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = virDomainDetachDevice(dom, (char *)xmlBufferContent(xml_buf));
|
|
|
|
if (ret != 0)
|
|
|
|
ret = FALSE;
|
|
|
|
else
|
|
|
|
ret = TRUE;
|
|
|
|
|
|
|
|
cleanup:
|
2008-02-07 16:49:29 +00:00
|
|
|
xmlXPathFreeObject(obj);
|
2008-01-29 18:23:43 +00:00
|
|
|
xmlXPathFreeContext(ctxt);
|
2007-06-19 09:12:55 +00:00
|
|
|
if (xml)
|
|
|
|
xmlFreeDoc(xml);
|
|
|
|
if (xml_buf)
|
|
|
|
xmlBufferFree(xml_buf);
|
|
|
|
if (dom)
|
|
|
|
virDomainFree(dom);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
/*
|
|
|
|
* "quit" command
|
|
|
|
*/
|
|
|
|
static vshCmdInfo info_quit[] = {
|
2006-03-15 12:13:25 +00:00
|
|
|
{"syntax", "quit"},
|
2006-09-21 15:24:37 +00:00
|
|
|
{"help", gettext_noop("quit this interactive terminal")},
|
2006-03-15 12:13:25 +00:00
|
|
|
{NULL, NULL}
|
2005-12-08 10:23:34 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
2006-03-15 12:13:25 +00:00
|
|
|
cmdQuit(vshControl * ctl, vshCmd * cmd ATTRIBUTE_UNUSED)
|
|
|
|
{
|
2005-12-08 10:23:34 +00:00
|
|
|
ctl->imode = FALSE;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Commands
|
|
|
|
*/
|
|
|
|
static vshCmdDef commands[] = {
|
2007-06-20 17:22:09 +00:00
|
|
|
{"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},
|
2007-02-23 08:58:25 +00:00
|
|
|
{"autostart", cmdAutostart, opts_autostart, info_autostart},
|
2007-03-15 17:24:56 +00:00
|
|
|
{"capabilities", cmdCapabilities, NULL, info_capabilities},
|
2006-03-15 12:13:25 +00:00
|
|
|
{"connect", cmdConnect, opts_connect, info_connect},
|
2007-01-26 11:54:29 +00:00
|
|
|
{"console", cmdConsole, opts_console, info_console},
|
2006-03-30 16:08:13 +00:00
|
|
|
{"create", cmdCreate, opts_create, info_create},
|
2006-08-30 14:32:32 +00:00
|
|
|
{"start", cmdStart, opts_start, info_start},
|
2006-04-04 21:52:31 +00:00
|
|
|
{"destroy", cmdDestroy, opts_destroy, info_destroy},
|
2007-06-20 17:22:09 +00:00
|
|
|
{"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},
|
2006-08-30 14:32:32 +00:00
|
|
|
{"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},
|
2006-04-04 14:37:32 +00:00
|
|
|
{"dominfo", cmdDominfo, opts_dominfo, info_dominfo},
|
2006-04-04 21:52:31 +00:00
|
|
|
{"domname", cmdDomname, opts_domname, info_domname},
|
|
|
|
{"domstate", cmdDomstate, opts_domstate, info_domstate},
|
2007-08-21 10:08:12 +00:00
|
|
|
{"domblkstat", cmdDomblkstat, opts_domblkstat, info_domblkstat},
|
|
|
|
{"domifstat", cmdDomIfstat, opts_domifstat, info_domifstat},
|
2006-03-15 12:13:25 +00:00
|
|
|
{"dumpxml", cmdDumpXML, opts_dumpxml, info_dumpxml},
|
2007-09-28 14:28:12 +00:00
|
|
|
{"freecell", cmdFreecell, opts_freecell, info_freecell},
|
2007-06-26 11:42:46 +00:00
|
|
|
{"hostname", cmdHostname, NULL, info_hostname},
|
2006-08-30 14:32:32 +00:00
|
|
|
{"list", cmdList, opts_list, info_list},
|
2007-08-21 09:31:12 +00:00
|
|
|
{"migrate", cmdMigrate, opts_migrate, info_migrate},
|
2008-02-20 15:27:08 +00:00
|
|
|
|
2007-02-23 08:58:25 +00:00
|
|
|
{"net-autostart", cmdNetworkAutostart, opts_network_autostart, info_network_autostart},
|
2007-02-14 16:53:55 +00:00
|
|
|
{"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-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},
|
2006-04-04 21:52:31 +00:00
|
|
|
{"nodeinfo", cmdNodeinfo, NULL, info_nodeinfo},
|
2008-02-20 15:27:08 +00:00
|
|
|
|
|
|
|
{"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-02-20 15:29:13 +00:00
|
|
|
{"pool-create-as", cmdPoolCreateAs, opts_pool_create_as, info_pool_create_as},
|
2008-02-20 15:27:08 +00:00
|
|
|
{"pool-define", cmdPoolDefine, opts_pool_define, info_pool_define},
|
2008-02-20 15:29:13 +00:00
|
|
|
{"pool-define-as", cmdPoolDefineAs, opts_pool_define_as, info_pool_define_as},
|
2008-02-20 15:27:08 +00:00
|
|
|
{"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-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},
|
|
|
|
|
2006-04-04 21:52:31 +00:00
|
|
|
{"quit", cmdQuit, NULL, info_quit},
|
|
|
|
{"reboot", cmdReboot, opts_reboot, info_reboot},
|
|
|
|
{"restore", cmdRestore, opts_restore, info_restore},
|
2006-03-15 12:13:25 +00:00
|
|
|
{"resume", cmdResume, opts_resume, info_resume},
|
|
|
|
{"save", cmdSave, opts_save, info_save},
|
2007-06-05 12:06:08 +00:00
|
|
|
{"schedinfo", cmdSchedinfo, opts_schedinfo, info_schedinfo},
|
2006-11-22 17:48:29 +00:00
|
|
|
{"dump", cmdDump, opts_dump, info_dump},
|
2006-03-15 12:13:25 +00:00
|
|
|
{"shutdown", cmdShutdown, opts_shutdown, info_shutdown},
|
2006-08-16 17:30:33 +00:00
|
|
|
{"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},
|
2007-07-26 08:41:16 +00:00
|
|
|
{"ttyconsole", cmdTTYConsole, opts_ttyconsole, info_ttyconsole},
|
2006-08-30 14:32:32 +00:00
|
|
|
{"undefine", cmdUndefine, opts_undefine, info_undefine},
|
2007-06-26 11:42:46 +00:00
|
|
|
{"uri", cmdURI, NULL, info_uri},
|
2008-02-20 15:27:08 +00:00
|
|
|
|
|
|
|
{"vol-create", cmdVolCreate, opts_vol_create, info_vol_create},
|
2008-02-20 15:29:13 +00:00
|
|
|
{"vol-create-as", cmdVolCreateAs, opts_vol_create_as, info_vol_create_as},
|
2008-02-20 15:27:08 +00:00
|
|
|
{"vol-delete", cmdVolDelete, opts_vol_delete, info_vol_delete},
|
|
|
|
{"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},
|
|
|
|
|
2006-08-07 14:35:20 +00:00
|
|
|
{"vcpuinfo", cmdVcpuinfo, opts_vcpuinfo, info_vcpuinfo},
|
|
|
|
{"vcpupin", cmdVcpupin, opts_vcpupin, info_vcpupin},
|
2006-03-15 12:13:25 +00:00
|
|
|
{"version", cmdVersion, NULL, info_version},
|
2007-01-26 11:54:29 +00:00
|
|
|
{"vncdisplay", cmdVNCDisplay, opts_vncdisplay, info_vncdisplay},
|
2006-03-15 12:13:25 +00:00
|
|
|
{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 *
|
2006-03-15 12:13:25 +00:00
|
|
|
vshCmddefGetInfo(vshCmdDef * cmd, const char *name)
|
|
|
|
{
|
2005-12-08 10:23:34 +00:00
|
|
|
vshCmdInfo *info;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
for (info = cmd->info; info && info->name; info++) {
|
2006-03-15 12:13:25 +00:00
|
|
|
if (strcmp(info->name, name) == 0)
|
2005-12-08 10:23:34 +00:00
|
|
|
return info->data;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static vshCmdOptDef *
|
2006-03-15 12:13:25 +00:00
|
|
|
vshCmddefGetOption(vshCmdDef * cmd, const char *name)
|
|
|
|
{
|
2005-12-08 10:23:34 +00:00
|
|
|
vshCmdOptDef *opt;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
for (opt = cmd->opts; opt && opt->name; opt++)
|
2006-03-15 12:13:25 +00:00
|
|
|
if (strcmp(opt->name, name) == 0)
|
2005-12-08 10:23:34 +00:00
|
|
|
return opt;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static vshCmdOptDef *
|
2006-03-15 12:13:25 +00:00
|
|
|
vshCmddefGetData(vshCmdDef * cmd, int data_ct)
|
|
|
|
{
|
2005-12-08 10:23:34 +00:00
|
|
|
vshCmdOptDef *opt;
|
|
|
|
|
2006-01-25 09:46:22 +00:00
|
|
|
for (opt = cmd->opts; opt && opt->name; opt++) {
|
2006-03-15 12:13:25 +00:00
|
|
|
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
|
|
|
|
*/
|
2006-03-15 12:13:25 +00:00
|
|
|
static int
|
|
|
|
vshCommandCheckOpts(vshControl * ctl, vshCmd * cmd)
|
2006-01-25 09:46:22 +00:00
|
|
|
{
|
|
|
|
vshCmdDef *def = cmd->def;
|
|
|
|
vshCmdOptDef *d;
|
2006-03-15 12:13:25 +00:00
|
|
|
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;
|
2006-03-15 12:13:25 +00:00
|
|
|
int ok = 0;
|
|
|
|
|
|
|
|
while (o && ok == 0) {
|
2006-01-25 09:46:22 +00:00
|
|
|
if (o->def == d)
|
2006-03-15 12:13:25 +00:00
|
|
|
ok = 1;
|
2006-01-25 09:46:22 +00:00
|
|
|
o = o->next;
|
|
|
|
}
|
|
|
|
if (!ok) {
|
2006-03-15 12:13:25 +00:00
|
|
|
vshError(ctl, FALSE,
|
|
|
|
d->type == VSH_OT_DATA ?
|
2006-09-21 15:24:37 +00:00
|
|
|
_("command '%s' requires <%s> option") :
|
2007-02-07 13:50:18 +00:00
|
|
|
_("command '%s' requires --%s option"),
|
2006-03-15 12:13:25 +00:00
|
|
|
def->name, d->name);
|
2006-01-25 09:46:22 +00:00
|
|
|
err = 1;
|
|
|
|
}
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2006-01-25 09:46:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return !err;
|
|
|
|
}
|
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
static vshCmdDef *
|
2006-03-15 12:13:25 +00:00
|
|
|
vshCmddefSearch(const char *cmdname)
|
|
|
|
{
|
2005-12-08 10:23:34 +00:00
|
|
|
vshCmdDef *c;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
for (c = commands; c->name; c++)
|
2006-03-15 12:13:25 +00:00
|
|
|
if (strcmp(c->name, cmdname) == 0)
|
2005-12-08 10:23:34 +00:00
|
|
|
return c;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2006-03-15 12:13:25 +00:00
|
|
|
vshCmddefHelp(vshControl * ctl, const char *cmdname, int withprog)
|
|
|
|
{
|
2005-12-08 10:23:34 +00:00
|
|
|
vshCmdDef *def = vshCmddefSearch(cmdname);
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
if (!def) {
|
2006-09-21 15:24:37 +00:00
|
|
|
vshError(ctl, FALSE, _("command '%s' doesn't exist"), cmdname);
|
2006-03-15 12:13:25 +00:00
|
|
|
return FALSE;
|
|
|
|
} else {
|
2005-12-08 10:23:34 +00:00
|
|
|
vshCmdOptDef *opt;
|
2007-06-15 08:18:55 +00:00
|
|
|
const char *desc = N_(vshCmddefGetInfo(def, "desc"));
|
|
|
|
const char *help = N_(vshCmddefGetInfo(def, "help"));
|
2005-12-08 14:22:52 +00:00
|
|
|
const char *syntax = vshCmddefGetInfo(def, "syntax");
|
2005-12-08 10:23:34 +00:00
|
|
|
|
2006-09-21 15:24:37 +00:00
|
|
|
fputs(_(" NAME\n"), stdout);
|
2006-03-15 12:13:25 +00:00
|
|
|
fprintf(stdout, " %s - %s\n", def->name, help);
|
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
if (syntax) {
|
2007-06-13 09:32:44 +00:00
|
|
|
fputs(_("\n SYNOPSIS\n"), stdout);
|
2005-12-08 10:23:34 +00:00
|
|
|
if (!withprog)
|
|
|
|
fprintf(stdout, " %s\n", syntax);
|
|
|
|
else
|
|
|
|
fprintf(stdout, " %s %s\n", progname, syntax);
|
|
|
|
}
|
|
|
|
if (desc) {
|
2006-09-21 15:24:37 +00:00
|
|
|
fputs(_("\n DESCRIPTION\n"), stdout);
|
2005-12-08 10:23:34 +00:00
|
|
|
fprintf(stdout, " %s\n", desc);
|
|
|
|
}
|
|
|
|
if (def->opts) {
|
2006-09-21 15:24:37 +00:00
|
|
|
fputs(_("\n OPTIONS\n"), stdout);
|
2006-03-15 12:13:25 +00:00
|
|
|
for (opt = def->opts; opt->name; opt++) {
|
2005-12-08 10:23:34 +00:00
|
|
|
char buf[256];
|
2006-03-15 12:13:25 +00:00
|
|
|
|
|
|
|
if (opt->type == VSH_OT_BOOL)
|
2005-12-08 10:23:34 +00:00
|
|
|
snprintf(buf, sizeof(buf), "--%s", opt->name);
|
2006-03-15 12:13:25 +00:00
|
|
|
else if (opt->type == VSH_OT_INT)
|
2006-09-21 15:24:37 +00:00
|
|
|
snprintf(buf, sizeof(buf), _("--%s <number>"), opt->name);
|
2006-03-15 12:13:25 +00:00
|
|
|
else if (opt->type == VSH_OT_STRING)
|
2006-09-21 15:24:37 +00:00
|
|
|
snprintf(buf, sizeof(buf), _("--%s <string>"), opt->name);
|
2006-03-15 12:13:25 +00:00
|
|
|
else if (opt->type == VSH_OT_DATA)
|
2005-12-08 10:23:34 +00:00
|
|
|
snprintf(buf, sizeof(buf), "<%s>", opt->name);
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2007-06-15 08:18:55 +00:00
|
|
|
fprintf(stdout, " %-15s %s\n", buf, N_(opt->help));
|
2006-03-15 12:13:25 +00:00
|
|
|
}
|
2005-12-08 10:23:34 +00:00
|
|
|
}
|
|
|
|
fputc('\n', stdout);
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ---------------
|
|
|
|
* Utils for work with runtime commands data
|
|
|
|
* ---------------
|
|
|
|
*/
|
2006-03-15 12:13:25 +00:00
|
|
|
static void
|
|
|
|
vshCommandOptFree(vshCmdOpt * arg)
|
|
|
|
{
|
2005-12-08 10:23:34 +00:00
|
|
|
vshCmdOpt *a = arg;
|
|
|
|
|
2006-03-15 12:13:25 +00:00
|
|
|
while (a) {
|
2005-12-08 10:23:34 +00:00
|
|
|
vshCmdOpt *tmp = a;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
a = a->next;
|
|
|
|
|
2008-01-29 17:41:07 +00:00
|
|
|
free(tmp->data);
|
2005-12-08 10:23:34 +00:00
|
|
|
free(tmp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2006-03-15 12:13:25 +00:00
|
|
|
vshCommandFree(vshCmd * cmd)
|
|
|
|
{
|
2005-12-08 10:23:34 +00:00
|
|
|
vshCmd *c = cmd;
|
|
|
|
|
2006-03-15 12:13:25 +00:00
|
|
|
while (c) {
|
2005-12-08 10:23:34 +00:00
|
|
|
vshCmd *tmp = c;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
c = c->next;
|
|
|
|
|
|
|
|
if (tmp->opts)
|
|
|
|
vshCommandOptFree(tmp->opts);
|
|
|
|
free(tmp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Returns option by name
|
|
|
|
*/
|
|
|
|
static vshCmdOpt *
|
2006-03-15 12:13:25 +00:00
|
|
|
vshCommandOpt(vshCmd * cmd, const char *name)
|
|
|
|
{
|
2005-12-08 10:23:34 +00:00
|
|
|
vshCmdOpt *opt = cmd->opts;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
|
|
|
while (opt) {
|
|
|
|
if (opt->def && strcmp(opt->def->name, name) == 0)
|
2005-12-08 10:23:34 +00:00
|
|
|
return opt;
|
|
|
|
opt = opt->next;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Returns option as INT
|
|
|
|
*/
|
|
|
|
static int
|
2006-03-15 12:13:25 +00:00
|
|
|
vshCommandOptInt(vshCmd * cmd, const char *name, int *found)
|
|
|
|
{
|
2005-12-08 10:23:34 +00:00
|
|
|
vshCmdOpt *arg = vshCommandOpt(cmd, name);
|
2007-08-16 13:21:36 +00:00
|
|
|
int res = 0, num_found = FALSE;
|
|
|
|
char *end_p = NULL;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2007-08-16 13:21:36 +00:00
|
|
|
if ((arg != NULL) && (arg->data != NULL)) {
|
|
|
|
res = strtol(arg->data, &end_p, 10);
|
2007-11-08 16:14:12 +00:00
|
|
|
if ((arg->data == end_p) || (*end_p!= 0))
|
|
|
|
num_found = FALSE;
|
|
|
|
else
|
|
|
|
num_found = TRUE;
|
2007-08-16 13:21:36 +00:00
|
|
|
}
|
2005-12-08 10:23:34 +00:00
|
|
|
if (found)
|
2007-08-16 13:21:36 +00:00
|
|
|
*found = num_found;
|
2005-12-08 10:23:34 +00:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Returns option as STRING
|
|
|
|
*/
|
|
|
|
static char *
|
2006-03-15 12:13:25 +00:00
|
|
|
vshCommandOptString(vshCmd * cmd, const char *name, int *found)
|
|
|
|
{
|
2005-12-08 10:23:34 +00:00
|
|
|
vshCmdOpt *arg = vshCommandOpt(cmd, name);
|
2006-03-15 12:13:25 +00:00
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2008-02-20 15:29:13 +00:00
|
|
|
#if 0
|
|
|
|
static int
|
|
|
|
vshCommandOptStringList(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) {
|
|
|
|
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
|
2006-03-15 12:13:25 +00:00
|
|
|
vshCommandOptBool(vshCmd * cmd, const char *name)
|
|
|
|
{
|
2005-12-08 10:23:34 +00:00
|
|
|
return vshCommandOpt(cmd, name) ? TRUE : FALSE;
|
|
|
|
}
|
|
|
|
|
2006-01-25 09:46:22 +00:00
|
|
|
|
2005-12-15 17:00:43 +00:00
|
|
|
static virDomainPtr
|
2006-05-29 15:39:31 +00:00
|
|
|
vshCommandOptDomainBy(vshControl * ctl, vshCmd * cmd, const char *optname,
|
2007-02-07 13:50:18 +00:00
|
|
|
char **name, int flag)
|
2006-03-15 12:13:25 +00:00
|
|
|
{
|
2005-12-15 17:00:43 +00:00
|
|
|
virDomainPtr dom = NULL;
|
2007-11-12 14:00:32 +00:00
|
|
|
char *n;
|
2005-12-15 17:00:43 +00:00
|
|
|
int id;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-15 17:00:43 +00:00
|
|
|
if (!(n = vshCommandOptString(cmd, optname, NULL))) {
|
2008-01-16 17:13:23 +00:00
|
|
|
vshError(ctl, FALSE, "%s", _("undefined domain name or id"));
|
2006-03-15 12:13:25 +00:00
|
|
|
return NULL;
|
2005-12-15 17:00:43 +00:00
|
|
|
}
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2006-05-22 14:38:33 +00:00
|
|
|
vshDebug(ctl, 5, "%s: found option <%s>: %s\n",
|
2006-03-15 12:13:25 +00:00
|
|
|
cmd->def->name, optname, n);
|
|
|
|
|
2005-12-15 17:00:43 +00:00
|
|
|
if (name)
|
|
|
|
*name = n;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-15 17:00:43 +00:00
|
|
|
/* try it by ID */
|
2007-02-14 15:44:58 +00:00
|
|
|
if (flag & VSH_BYID) {
|
2008-02-08 09:15:16 +00:00
|
|
|
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 */
|
2007-02-14 15:44:58 +00:00
|
|
|
if (dom==NULL && (flag & VSH_BYUUID) && strlen(n)==VIR_UUID_STRING_BUFLEN-1) {
|
2006-05-22 14:38:33 +00:00
|
|
|
vshDebug(ctl, 5, "%s: <%s> tring as domain UUID\n",
|
2007-02-07 13:50:18 +00:00
|
|
|
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 */
|
2007-02-14 15:44:58 +00:00
|
|
|
if (dom==NULL && (flag & VSH_BYNAME)) {
|
2006-05-22 14:38:33 +00:00
|
|
|
vshDebug(ctl, 5, "%s: <%s> tring as domain NAME\n",
|
2006-03-15 12:13:25 +00:00
|
|
|
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
|
|
|
|
2006-03-15 12:13:25 +00:00
|
|
|
if (!dom)
|
2006-09-21 15:24:37 +00:00
|
|
|
vshError(ctl, FALSE, _("failed to get domain '%s'"), n);
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-15 17:00:43 +00:00
|
|
|
return dom;
|
|
|
|
}
|
|
|
|
|
2007-02-14 16:53:55 +00:00
|
|
|
static virNetworkPtr
|
|
|
|
vshCommandOptNetworkBy(vshControl * ctl, vshCmd * cmd, const char *optname,
|
|
|
|
char **name, int flag)
|
|
|
|
{
|
|
|
|
virNetworkPtr network = NULL;
|
|
|
|
char *n;
|
|
|
|
|
|
|
|
if (!(n = vshCommandOptString(cmd, optname, NULL))) {
|
2008-01-16 17:13:23 +00:00
|
|
|
vshError(ctl, FALSE, "%s", _("undefined network name"));
|
2007-02-14 16:53:55 +00:00
|
|
|
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 (network==NULL && (flag & VSH_BYUUID) && strlen(n)==VIR_UUID_STRING_BUFLEN-1) {
|
|
|
|
vshDebug(ctl, 5, "%s: <%s> tring 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> tring as network NAME\n",
|
|
|
|
cmd->def->name, optname);
|
|
|
|
network = virNetworkLookupByName(ctl->conn, n);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!network)
|
|
|
|
vshError(ctl, FALSE, _("failed to get network '%s'"), n);
|
|
|
|
|
|
|
|
return network;
|
|
|
|
}
|
|
|
|
|
2008-02-20 15:27:08 +00:00
|
|
|
static virStoragePoolPtr
|
|
|
|
vshCommandOptPoolBy(vshControl * ctl, vshCmd * cmd, const char *optname,
|
|
|
|
char **name, int flag)
|
|
|
|
{
|
|
|
|
virStoragePoolPtr pool = NULL;
|
|
|
|
char *n;
|
|
|
|
|
|
|
|
if (!(n = vshCommandOptString(cmd, optname, NULL))) {
|
|
|
|
vshError(ctl, FALSE, "%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 (pool==NULL && (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, FALSE, _("failed to get pool '%s'"), n);
|
|
|
|
|
|
|
|
return pool;
|
|
|
|
}
|
|
|
|
|
|
|
|
static virStorageVolPtr
|
|
|
|
vshCommandOptVolBy(vshControl * ctl, 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, FALSE, "%s", _("undefined vol name"));
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(p = vshCommandOptString(cmd, pooloptname, &found)) && found) {
|
|
|
|
vshError(ctl, FALSE, "%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, FALSE, _("failed to get vol '%s'"), n);
|
|
|
|
|
|
|
|
if (pool)
|
|
|
|
virStoragePoolFree(pool);
|
|
|
|
|
|
|
|
return vol;
|
|
|
|
}
|
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
/*
|
|
|
|
* Executes command(s) and returns return code from last command
|
|
|
|
*/
|
|
|
|
static int
|
2006-03-15 12:13:25 +00:00
|
|
|
vshCommandRun(vshControl * ctl, vshCmd * cmd)
|
|
|
|
{
|
2005-12-08 10:23:34 +00:00
|
|
|
int ret = TRUE;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
|
|
|
while (cmd) {
|
2005-12-08 10:23:34 +00:00
|
|
|
struct timeval before, after;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
if (ctl->timing)
|
|
|
|
GETTIMEOFDAY(&before);
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
ret = cmd->def->handler(ctl, cmd);
|
|
|
|
|
|
|
|
if (ctl->timing)
|
|
|
|
GETTIMEOFDAY(&after);
|
2006-03-15 12:13:25 +00:00
|
|
|
|
|
|
|
if (strcmp(cmd->def->name, "quit") == 0) /* hack ... */
|
2005-12-08 10:23:34 +00:00
|
|
|
return ret;
|
|
|
|
|
|
|
|
if (ctl->timing)
|
2006-09-21 15:24:37 +00:00
|
|
|
vshPrint(ctl, _("\n(Time: %.3f ms)\n\n"),
|
2006-03-15 12:13:25 +00:00
|
|
|
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
|
|
|
|
|
2006-03-15 12:13:25 +00:00
|
|
|
static int
|
|
|
|
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;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
*end = NULL;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2007-07-04 09:16:23 +00:00
|
|
|
while (p && *p && (*p == ' ' || *p == '\t'))
|
2005-12-08 10:23:34 +00:00
|
|
|
p++;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
|
|
|
if (p == NULL || *p == '\0')
|
2005-12-08 10:23:34 +00:00
|
|
|
return VSH_TK_END;
|
2006-03-15 12:13:25 +00:00
|
|
|
if (*p == ';') {
|
|
|
|
*end = ++p; /* = \0 or begi of next command */
|
2005-12-08 10:23:34 +00:00
|
|
|
return VSH_TK_END;
|
|
|
|
}
|
2006-03-15 12:13:25 +00:00
|
|
|
while (*p) {
|
2005-12-08 10:23:34 +00:00
|
|
|
/* end of token is blank space or ';' */
|
2007-07-04 09:16:23 +00:00
|
|
|
if ((quote == FALSE && (*p == ' ' || *p == '\t')) || *p == ';')
|
2005-12-08 10:23:34 +00:00
|
|
|
break;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2006-01-25 09:46:22 +00:00
|
|
|
/* end of option name could be '=' */
|
2006-03-15 12:13:25 +00:00
|
|
|
if (tk == VSH_TK_OPTION && *p == '=') {
|
|
|
|
p++; /* skip '=' */
|
2006-01-25 09:46:22 +00:00
|
|
|
break;
|
|
|
|
}
|
2006-03-15 12:13:25 +00:00
|
|
|
|
|
|
|
if (tk == VSH_TK_NONE) {
|
|
|
|
if (*p == '-' && *(p + 1) == '-' && *(p + 2)
|
|
|
|
&& isalnum((unsigned char) *(p + 2))) {
|
2005-12-08 10:23:34 +00:00
|
|
|
tk = VSH_TK_OPTION;
|
2006-03-15 12:13:25 +00:00
|
|
|
p += 2;
|
2005-12-08 10:23:34 +00:00
|
|
|
} else {
|
|
|
|
tk = VSH_TK_DATA;
|
2006-03-15 12:13:25 +00:00
|
|
|
if (*p == '"') {
|
|
|
|
quote = TRUE;
|
2005-12-08 10:23:34 +00:00
|
|
|
p++;
|
|
|
|
} else {
|
|
|
|
quote = FALSE;
|
|
|
|
}
|
|
|
|
}
|
2006-03-15 12:13:25 +00:00
|
|
|
tkstr = p; /* begin of token */
|
|
|
|
} else if (quote && *p == '"') {
|
2005-12-08 10:23:34 +00:00
|
|
|
quote = FALSE;
|
|
|
|
p++;
|
2006-03-15 12:13:25 +00:00
|
|
|
break; /* end of "..." token */
|
2005-12-08 10:23:34 +00:00
|
|
|
}
|
|
|
|
p++;
|
|
|
|
sz++;
|
|
|
|
}
|
|
|
|
if (quote) {
|
2008-01-16 17:13:23 +00:00
|
|
|
vshError(ctl, FALSE, "%s", _("missing \""));
|
2005-12-08 10:23:34 +00:00
|
|
|
return VSH_TK_ERROR;
|
|
|
|
}
|
2006-03-15 12:13:25 +00:00
|
|
|
if (tkstr == NULL || *tkstr == '\0' || p == NULL)
|
2005-12-08 10:23:34 +00:00
|
|
|
return VSH_TK_END;
|
2006-03-15 12:13:25 +00:00
|
|
|
if (sz == 0)
|
2005-12-08 10:23:34 +00:00
|
|
|
return VSH_TK_END;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2006-04-06 10:33:06 +00:00
|
|
|
*res = vshMalloc(ctl, sz + 1);
|
2005-12-08 10:23:34 +00:00
|
|
|
memcpy(*res, tkstr, sz);
|
2006-03-15 12:13:25 +00:00
|
|
|
*(*res + sz) = '\0';
|
2005-12-08 10:23:34 +00:00
|
|
|
|
|
|
|
*end = p;
|
|
|
|
return tk;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2006-03-15 12:13:25 +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;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
if (ctl->cmd) {
|
|
|
|
vshCommandFree(ctl->cmd);
|
|
|
|
ctl->cmd = NULL;
|
|
|
|
}
|
2006-03-15 12:13:25 +00:00
|
|
|
|
|
|
|
if (cmdstr == NULL || *cmdstr == '\0')
|
2005-12-08 10:23:34 +00:00
|
|
|
return FALSE;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
str = cmdstr;
|
2006-03-15 12:13:25 +00:00
|
|
|
while (str && *str) {
|
2005-12-08 10:23:34 +00:00
|
|
|
vshCmdOpt *last = NULL;
|
|
|
|
vshCmdDef *cmd = NULL;
|
|
|
|
int tk = VSH_TK_NONE;
|
2006-01-25 09:46:22 +00:00
|
|
|
int data_ct = 0;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
first = NULL;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
|
|
|
while (tk != VSH_TK_END) {
|
2005-12-08 10:23:34 +00:00
|
|
|
char *end = NULL;
|
|
|
|
vshCmdOptDef *opt = NULL;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
tkdata = NULL;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
/* get token */
|
|
|
|
tk = vshCommandGetToken(ctl, str, &end, &tkdata);
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
str = end;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
|
|
|
if (tk == VSH_TK_END)
|
2005-12-08 10:23:34 +00:00
|
|
|
break;
|
2006-03-15 12:13:25 +00:00
|
|
|
if (tk == VSH_TK_ERROR)
|
2005-12-08 10:23:34 +00:00
|
|
|
goto syntaxError;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
|
|
|
if (cmd == NULL) {
|
2005-12-08 10:23:34 +00:00
|
|
|
/* first token must be command name */
|
2006-03-15 12:13:25 +00:00
|
|
|
if (tk != VSH_TK_DATA) {
|
|
|
|
vshError(ctl, FALSE,
|
2006-09-21 15:24:37 +00:00
|
|
|
_("unexpected token (command name): '%s'"),
|
2006-03-15 12:13:25 +00:00
|
|
|
tkdata);
|
2005-12-08 10:23:34 +00:00
|
|
|
goto syntaxError;
|
|
|
|
}
|
|
|
|
if (!(cmd = vshCmddefSearch(tkdata))) {
|
2006-09-21 15:24:37 +00:00
|
|
|
vshError(ctl, FALSE, _("unknown command: '%s'"), tkdata);
|
2006-03-15 12:13:25 +00:00
|
|
|
goto syntaxError; /* ... or ignore this command only? */
|
2005-12-08 10:23:34 +00:00
|
|
|
}
|
|
|
|
free(tkdata);
|
2006-03-15 12:13:25 +00:00
|
|
|
} else if (tk == VSH_TK_OPTION) {
|
2005-12-08 10:23:34 +00:00
|
|
|
if (!(opt = vshCmddefGetOption(cmd, tkdata))) {
|
|
|
|
vshError(ctl, FALSE,
|
2006-09-21 15:24:37 +00:00
|
|
|
_("command '%s' doesn't support option --%s"),
|
2006-03-15 12:13:25 +00:00
|
|
|
cmd->name, tkdata);
|
2005-12-08 10:23:34 +00:00
|
|
|
goto syntaxError;
|
|
|
|
}
|
2006-03-15 12:13:25 +00:00
|
|
|
free(tkdata); /* option name */
|
2005-12-08 10:23:34 +00:00
|
|
|
tkdata = NULL;
|
|
|
|
|
|
|
|
if (opt->type != VSH_OT_BOOL) {
|
|
|
|
/* option data */
|
|
|
|
tk = vshCommandGetToken(ctl, str, &end, &tkdata);
|
2006-03-15 12:13:25 +00:00
|
|
|
str = end;
|
|
|
|
if (tk == VSH_TK_ERROR)
|
2005-12-08 10:23:34 +00:00
|
|
|
goto syntaxError;
|
2006-03-15 12:13:25 +00:00
|
|
|
if (tk != VSH_TK_DATA) {
|
2005-12-08 10:23:34 +00:00
|
|
|
vshError(ctl, FALSE,
|
2006-09-21 15:24:37 +00:00
|
|
|
_("expected syntax: --%s <%s>"),
|
2006-03-15 12:13:25 +00:00
|
|
|
opt->name,
|
|
|
|
opt->type ==
|
2006-09-21 15:24:37 +00:00
|
|
|
VSH_OT_INT ? _("number") : _("string"));
|
2005-12-08 10:23:34 +00:00
|
|
|
goto syntaxError;
|
|
|
|
}
|
|
|
|
}
|
2006-03-15 12:13:25 +00:00
|
|
|
} else if (tk == VSH_TK_DATA) {
|
2006-01-25 09:46:22 +00:00
|
|
|
if (!(opt = vshCmddefGetData(cmd, data_ct++))) {
|
2006-09-21 15:24:37 +00:00
|
|
|
vshError(ctl, FALSE, _("unexpected data '%s'"), tkdata);
|
2005-12-08 10:23:34 +00:00
|
|
|
goto syntaxError;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (opt) {
|
|
|
|
/* save option */
|
2006-04-06 10:33:06 +00:00
|
|
|
vshCmdOpt *arg = vshMalloc(ctl, sizeof(vshCmdOpt));
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
arg->def = opt;
|
|
|
|
arg->data = tkdata;
|
|
|
|
arg->next = NULL;
|
|
|
|
tkdata = NULL;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
if (!first)
|
|
|
|
first = arg;
|
|
|
|
if (last)
|
|
|
|
last->next = arg;
|
|
|
|
last = arg;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2006-05-22 14:38:33 +00:00
|
|
|
vshDebug(ctl, 4, "%s: %s(%s): %s\n",
|
2006-03-15 12:13:25 +00:00
|
|
|
cmd->name,
|
|
|
|
opt->name,
|
2006-09-21 15:24:37 +00:00
|
|
|
tk == VSH_TK_OPTION ? _("OPTION") : _("DATA"),
|
2006-03-15 12:13:25 +00:00
|
|
|
arg->data);
|
2005-12-08 10:23:34 +00:00
|
|
|
}
|
|
|
|
if (!str)
|
|
|
|
break;
|
|
|
|
}
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
/* commad parsed -- allocate new struct for the command */
|
|
|
|
if (cmd) {
|
2006-04-06 10:33:06 +00:00
|
|
|
vshCmd *c = vshMalloc(ctl, sizeof(vshCmd));
|
2006-03-30 12:14:40 +00:00
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
c->opts = first;
|
|
|
|
c->def = cmd;
|
|
|
|
c->next = NULL;
|
|
|
|
|
2007-05-29 13:55:19 +00:00
|
|
|
if (!vshCommandCheckOpts(ctl, c)) {
|
2008-01-29 17:41:07 +00:00
|
|
|
free(c);
|
2006-01-25 09:46:22 +00:00
|
|
|
goto syntaxError;
|
2007-05-29 13:55:19 +00:00
|
|
|
}
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
if (!ctl->cmd)
|
|
|
|
ctl->cmd = c;
|
|
|
|
if (clast)
|
|
|
|
clast->next = c;
|
|
|
|
clast = c;
|
|
|
|
}
|
|
|
|
}
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
return TRUE;
|
|
|
|
|
2007-02-07 13:50:18 +00:00
|
|
|
syntaxError:
|
2005-12-08 10:23:34 +00:00
|
|
|
if (ctl->cmd)
|
|
|
|
vshCommandFree(ctl->cmd);
|
|
|
|
if (first)
|
|
|
|
vshCommandOptFree(first);
|
2008-01-29 17:41:07 +00:00
|
|
|
free(tkdata);
|
2006-03-15 12:13:25 +00:00
|
|
|
return FALSE;
|
2005-12-08 10:23:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ---------------
|
2007-02-07 13:50:18 +00:00
|
|
|
* Misc utils
|
2005-12-08 10:23:34 +00:00
|
|
|
* ---------------
|
|
|
|
*/
|
2005-12-08 14:22:52 +00:00
|
|
|
static const char *
|
2006-03-15 12:13:25 +00:00
|
|
|
vshDomainStateToString(int state)
|
|
|
|
{
|
2005-12-08 10:23:34 +00:00
|
|
|
switch (state) {
|
2007-02-07 13:50:18 +00:00
|
|
|
case VIR_DOMAIN_RUNNING:
|
|
|
|
return gettext_noop("running");
|
|
|
|
case VIR_DOMAIN_BLOCKED:
|
|
|
|
return gettext_noop("blocked");
|
|
|
|
case VIR_DOMAIN_PAUSED:
|
|
|
|
return gettext_noop("paused");
|
|
|
|
case VIR_DOMAIN_SHUTDOWN:
|
|
|
|
return gettext_noop("in shutdown");
|
|
|
|
case VIR_DOMAIN_SHUTOFF:
|
|
|
|
return gettext_noop("shut off");
|
|
|
|
case VIR_DOMAIN_CRASHED:
|
|
|
|
return gettext_noop("crashed");
|
|
|
|
default:
|
2007-09-29 18:16:26 +00:00
|
|
|
;/*FALLTHROUGH*/
|
2005-12-08 10:23:34 +00:00
|
|
|
}
|
2007-09-29 18:16:26 +00:00
|
|
|
return gettext_noop("no state"); /* = dom0 state */
|
2005-12-08 10:23:34 +00:00
|
|
|
}
|
|
|
|
|
2006-08-07 14:35:20 +00:00
|
|
|
static const char *
|
|
|
|
vshDomainVcpuStateToString(int state)
|
|
|
|
{
|
|
|
|
switch (state) {
|
2007-02-07 13:50:18 +00:00
|
|
|
case VIR_VCPU_OFFLINE:
|
|
|
|
return gettext_noop("offline");
|
|
|
|
case VIR_VCPU_BLOCKED:
|
|
|
|
return gettext_noop("blocked");
|
|
|
|
case VIR_VCPU_RUNNING:
|
|
|
|
return gettext_noop("running");
|
|
|
|
default:
|
2007-09-29 18:16:26 +00:00
|
|
|
;/*FALLTHROUGH*/
|
2006-08-07 14:35:20 +00:00
|
|
|
}
|
2007-09-29 18:16:26 +00:00
|
|
|
return gettext_noop("no state");
|
2006-08-07 14:35:20 +00:00
|
|
|
}
|
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
static int
|
2006-03-15 12:13:25 +00:00
|
|
|
vshConnectionUsability(vshControl * ctl, virConnectPtr conn, int showerror)
|
|
|
|
{
|
2007-02-07 13:50:18 +00:00
|
|
|
/* TODO: use something like virConnectionState() to
|
|
|
|
* check usability of the connection
|
2005-12-08 10:23:34 +00:00
|
|
|
*/
|
|
|
|
if (!conn) {
|
|
|
|
if (showerror)
|
2008-01-16 17:13:23 +00:00
|
|
|
vshError(ctl, FALSE, "%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
|
|
|
|
vshDebug(vshControl * ctl, int level, const char *format, ...)
|
2006-03-15 12:13:25 +00:00
|
|
|
{
|
2006-05-22 14:38:33 +00:00
|
|
|
va_list ap;
|
|
|
|
|
2007-06-06 12:24:31 +00:00
|
|
|
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
|
2006-05-22 14:38:33 +00:00
|
|
|
vshPrintExtra(vshControl * ctl, const char *format, ...)
|
2006-03-15 12:13:25 +00:00
|
|
|
{
|
2005-12-08 10:23:34 +00:00
|
|
|
va_list ap;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2006-05-22 14:38:33 +00:00
|
|
|
if (ctl->quiet == TRUE)
|
2005-12-08 10:23:34 +00:00
|
|
|
return;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
va_start(ap, format);
|
2006-04-06 10:33:06 +00:00
|
|
|
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
|
2006-03-15 12:13:25 +00:00
|
|
|
vshError(vshControl * ctl, int doexit, const char *format, ...)
|
|
|
|
{
|
2005-12-08 10:23:34 +00:00
|
|
|
va_list ap;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2007-06-06 12:24:31 +00:00
|
|
|
va_start(ap, format);
|
|
|
|
vshOutputLogFile(ctl, VSH_ERR_ERROR, format, ap);
|
|
|
|
va_end(ap);
|
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
if (doexit)
|
2006-09-21 15:24:37 +00:00
|
|
|
fprintf(stderr, _("%s: error: "), progname);
|
2005-12-08 10:23:34 +00:00
|
|
|
else
|
2006-09-21 15:24:37 +00:00
|
|
|
fputs(_("error: "), stderr);
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
va_start(ap, format);
|
|
|
|
vfprintf(stderr, format, ap);
|
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
fputc('\n', stderr);
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
if (doexit) {
|
2006-04-06 10:33:06 +00:00
|
|
|
if (ctl)
|
|
|
|
vshDeinit(ctl);
|
2005-12-08 10:23:34 +00:00
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-04-06 10:33:06 +00:00
|
|
|
static void *
|
|
|
|
_vshMalloc(vshControl * ctl, size_t size, const char *filename, int line)
|
|
|
|
{
|
|
|
|
void *x;
|
|
|
|
|
|
|
|
if ((x = malloc(size)))
|
|
|
|
return x;
|
2006-09-21 15:24:37 +00:00
|
|
|
vshError(ctl, TRUE, _("%s: %d: failed to allocate %d bytes"),
|
2007-02-07 13:50:18 +00:00
|
|
|
filename, line, (int) size);
|
2006-04-06 10:33:06 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void *
|
|
|
|
_vshCalloc(vshControl * ctl, size_t nmemb, size_t size, const char *filename, int line)
|
|
|
|
{
|
|
|
|
void *x;
|
|
|
|
|
|
|
|
if ((x = calloc(nmemb, size)))
|
|
|
|
return x;
|
2006-09-21 15:24:37 +00:00
|
|
|
vshError(ctl, TRUE, _("%s: %d: failed to allocate %d bytes"),
|
2007-02-07 13:50:18 +00:00
|
|
|
filename, line, (int) (size*nmemb));
|
2006-04-06 10:33:06 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2007-06-19 09:12:55 +00:00
|
|
|
static void *
|
|
|
|
_vshRealloc(vshControl * ctl, void *ptr, size_t size, const char *filename, int line)
|
|
|
|
{
|
|
|
|
void *x;
|
|
|
|
|
|
|
|
if ((x = realloc(ptr, size)))
|
|
|
|
return x;
|
|
|
|
free(ptr);
|
|
|
|
vshError(ctl, TRUE, _("%s: %d: failed to allocate %d bytes"),
|
|
|
|
filename, line, (int) size);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2006-04-06 10:33:06 +00:00
|
|
|
static char *
|
|
|
|
_vshStrdup(vshControl * ctl, const char *s, const char *filename, int line)
|
|
|
|
{
|
|
|
|
char *x;
|
|
|
|
|
2007-04-26 10:20:57 +00:00
|
|
|
if (s == NULL)
|
|
|
|
return(NULL);
|
2006-04-06 10:33:06 +00:00
|
|
|
if ((x = strdup(s)))
|
|
|
|
return x;
|
2007-03-19 14:20:30 +00:00
|
|
|
vshError(ctl, TRUE, _("%s: %d: failed to allocate %lu bytes"),
|
|
|
|
filename, line, (unsigned long)strlen(s));
|
2006-04-06 10:33:06 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
/*
|
2007-06-20 17:22:09 +00:00
|
|
|
* Initialize connection.
|
2005-12-08 10:23:34 +00:00
|
|
|
*/
|
|
|
|
static int
|
2006-03-15 12:13:25 +00:00
|
|
|
vshInit(vshControl * ctl)
|
|
|
|
{
|
2005-12-08 10:23:34 +00:00
|
|
|
if (ctl->conn)
|
|
|
|
return FALSE;
|
|
|
|
|
2007-12-07 14:56:37 +00:00
|
|
|
#ifndef __MINGW32__
|
2005-12-08 10:23:34 +00:00
|
|
|
ctl->uid = getuid();
|
2007-12-07 14:56:37 +00:00
|
|
|
#endif
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2007-06-06 12:24:31 +00:00
|
|
|
vshOpenLogFile(ctl);
|
|
|
|
|
2006-02-27 21:34:28 +00:00
|
|
|
/* set up the library error handler */
|
|
|
|
virSetErrorFunc(NULL, virshErrorHandler);
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2007-12-05 18:55:04 +00:00
|
|
|
ctl->conn = virConnectOpenAuth(ctl->name,
|
|
|
|
virConnectAuthPtrDefault,
|
|
|
|
ctl->readonly ? VIR_CONNECT_RO : 0);
|
|
|
|
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2007-06-20 17:22:09 +00:00
|
|
|
/* This is not necessarily fatal. All the individual commands check
|
|
|
|
* vshConnectionUsability, except ones which don't need a connection
|
|
|
|
* such as "help".
|
|
|
|
*/
|
2007-12-05 16:24:22 +00:00
|
|
|
if (!ctl->conn) {
|
2008-01-16 17:13:23 +00:00
|
|
|
vshError(ctl, FALSE, "%s", _("failed to connect to the hypervisor"));
|
2007-12-05 16:24:22 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
2005-12-08 10:23:34 +00:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2007-12-07 14:56:37 +00:00
|
|
|
#ifndef O_SYNC
|
|
|
|
#define O_SYNC 0
|
|
|
|
#endif
|
|
|
|
#define LOGFILE_FLAGS (O_WRONLY | O_APPEND | O_CREAT | O_SYNC)
|
|
|
|
|
2007-06-06 12:24:31 +00:00
|
|
|
/**
|
|
|
|
* vshOpenLogFile:
|
|
|
|
*
|
|
|
|
* Open log file.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
vshOpenLogFile(vshControl *ctl)
|
|
|
|
{
|
|
|
|
struct stat st;
|
|
|
|
|
|
|
|
if (ctl->logfile == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* check log file */
|
|
|
|
if (stat(ctl->logfile, &st) == -1) {
|
|
|
|
switch (errno) {
|
|
|
|
case ENOENT:
|
|
|
|
break;
|
|
|
|
default:
|
2008-01-16 17:13:23 +00:00
|
|
|
vshError(ctl, TRUE, "%s",
|
|
|
|
_("failed to get the log file information"));
|
2007-06-06 12:24:31 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (!S_ISREG(st.st_mode)) {
|
2008-01-16 17:13:23 +00:00
|
|
|
vshError(ctl, TRUE, "%s", _("the log path is not a file"));
|
2007-06-06 12:24:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* log file open */
|
2007-12-07 14:56:37 +00:00
|
|
|
if ((ctl->log_fd = open(ctl->logfile, LOGFILE_FLAGS, FILE_MODE)) < 0) {
|
2008-01-16 17:13:23 +00:00
|
|
|
vshError(ctl, TRUE, "%s",
|
|
|
|
_("failed to open the log file. check the log file path"));
|
2007-06-06 12:24:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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 */
|
Use safewrite in place of write, in many cases.
Also add "make syntax-check" rules to ensure no new uses sneak in.
There are many uses of write like this:
if (write (fd, xml, towrite) != towrite)
return -1;
The problem is that the syscall can succeed, yet write less than
the requested number of bytes, so the caller should retry
rather than simply failing.
This patch changes most of them to use util.c's safewrite wrapper,
which encapsulates the process. Also, there were a few cases in
which the retry loop was open-coded, and I replaced those, too.
* Makefile.maint (sc_avoid_write): New rule, to avoid recurrence.
* .x-sc_avoid_write: New file. Record two legitimate exemptions.
* qemud/qemud.c (sig_handler, qemudClientWriteBuf): Use safewrite, not write.
* src/conf.c (__virConfWriteFile): Likewise.
* src/qemu_conf.c (qemudSaveConfig, qemudSaveNetworkConfig): Likewise.
* src/qemu_driver.c (qemudWaitForMonitor, qemudStartVMDaemon)
(qemudVMData, PROC_IP_FORWARD): Likewise.
* proxy/libvirt_proxy.c: Include "util.h".
(proxyWriteClientSocket): Use safewrite.
* src/test.c (testDomainSave, testDomainCoreDump): Likewise.
* src/proxy_internal.c (virProxyWriteClientSocket): Likewise.
* src/virsh.c: Include "util-lib.h".
(vshOutputLogFile): Use safewrite.
* src/console.c: Include "util-lib.h".
(vshRunConsole): Use safewrite.
2008-02-22 15:55:04 +00:00
|
|
|
if (safewrite(ctl->log_fd, msg_buf, strlen(msg_buf)) < 0) {
|
2007-06-06 12:24:31 +00:00
|
|
|
vshCloseLogFile(ctl);
|
2008-01-16 17:13:23 +00:00
|
|
|
vshError(ctl, FALSE, "%s", _("failed to write the log file"));
|
2007-06-06 12:24:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* vshCloseLogFile:
|
|
|
|
*
|
|
|
|
* Close log file.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
vshCloseLogFile(vshControl *ctl)
|
|
|
|
{
|
|
|
|
/* log file close */
|
|
|
|
if (ctl->log_fd >= 0) {
|
2007-11-28 13:22:33 +00:00
|
|
|
if (close(ctl->log_fd) < 0)
|
2007-11-28 14:22:30 +00:00
|
|
|
vshError(ctl, FALSE, _("%s: failed to write log file: %s"),
|
2007-11-28 13:22:33 +00:00
|
|
|
ctl->logfile ? ctl->logfile : "?", strerror (errno));
|
2007-06-06 12:24:31 +00:00
|
|
|
ctl->log_fd = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ctl->logfile) {
|
|
|
|
free(ctl->logfile);
|
|
|
|
ctl->logfile = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-12-06 10:24:52 +00:00
|
|
|
#ifdef USE_READLINE
|
2007-12-04 18:27:52 +00:00
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
/* -----------------
|
|
|
|
* Readline stuff
|
|
|
|
* -----------------
|
|
|
|
*/
|
|
|
|
|
2007-02-07 13:50:18 +00:00
|
|
|
/*
|
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
|
2007-02-07 13:50:18 +00:00
|
|
|
* (i.e. STATE == 0), then we start at the top of the list.
|
2005-12-08 10:23:34 +00:00
|
|
|
*/
|
|
|
|
static char *
|
2006-03-15 12:13:25 +00:00
|
|
|
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
|
2007-02-07 13:50:18 +00:00
|
|
|
* initializing the index variable to 0.
|
2005-12-08 10:23:34 +00:00
|
|
|
*/
|
|
|
|
if (!state) {
|
|
|
|
list_index = 0;
|
2006-03-15 12:13:25 +00:00
|
|
|
len = strlen(text);
|
2005-12-08 10:23:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Return the next name which partially matches from the
|
2007-02-07 13:50:18 +00:00
|
|
|
* 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++;
|
2006-03-15 12:13:25 +00:00
|
|
|
if (strncmp(name, text, len) == 0)
|
2006-04-06 10:33:06 +00:00
|
|
|
return vshStrdup(NULL, name);
|
2005-12-08 10:23:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* If no names matched, then return NULL. */
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *
|
2006-03-15 12:13:25 +00:00
|
|
|
vshReadlineOptionsGenerator(const char *text, int state)
|
|
|
|
{
|
2005-12-08 10:23:34 +00:00
|
|
|
static int list_index, len;
|
|
|
|
static 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;
|
|
|
|
|
2006-04-06 10:33:06 +00:00
|
|
|
cmdname = vshCalloc(NULL, (p - rl_line_buffer) + 1, 1);
|
2006-03-15 12:13:25 +00:00
|
|
|
memcpy(cmdname, rl_line_buffer, p - rl_line_buffer);
|
2005-12-08 10:23:34 +00:00
|
|
|
|
|
|
|
cmd = vshCmddefSearch(cmdname);
|
|
|
|
list_index = 0;
|
2006-03-15 12:13:25 +00:00
|
|
|
len = strlen(text);
|
2005-12-08 10:23:34 +00:00
|
|
|
free(cmdname);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!cmd)
|
|
|
|
return NULL;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2007-02-27 15:35:50 +00:00
|
|
|
if (!cmd->opts)
|
|
|
|
return NULL;
|
|
|
|
|
2005-12-08 14:22:52 +00:00
|
|
|
while ((name = cmd->opts[list_index].name)) {
|
2005-12-08 10:23:34 +00:00
|
|
|
vshCmdOptDef *opt = &cmd->opts[list_index];
|
|
|
|
char *res;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
list_index++;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
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;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
if (len > 2) {
|
2006-03-15 12:13:25 +00:00
|
|
|
if (strncmp(name, text + 2, len - 2))
|
2005-12-08 10:23:34 +00:00
|
|
|
continue;
|
|
|
|
}
|
2006-04-06 10:33:06 +00:00
|
|
|
res = vshMalloc(NULL, strlen(name) + 3);
|
2007-03-23 16:15:07 +00:00
|
|
|
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 **
|
2006-03-15 12:13:25 +00:00
|
|
|
vshReadlineCompletion(const char *text, int start,
|
|
|
|
int end ATTRIBUTE_UNUSED)
|
|
|
|
{
|
2005-12-08 10:23:34 +00:00
|
|
|
char **matches = (char **) NULL;
|
|
|
|
|
2006-03-15 12:13:25 +00:00
|
|
|
if (start == 0)
|
2005-12-08 10:23:34 +00:00
|
|
|
/* command name generator */
|
2006-03-15 12:13:25 +00:00
|
|
|
matches = rl_completion_matches(text, vshReadlineCommandGenerator);
|
2005-12-08 10:23:34 +00:00
|
|
|
else
|
|
|
|
/* commands options */
|
2006-03-15 12:13:25 +00:00
|
|
|
matches = rl_completion_matches(text, vshReadlineOptionsGenerator);
|
2005-12-08 10:23:34 +00:00
|
|
|
return matches;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2006-03-15 12:13:25 +00:00
|
|
|
vshReadlineInit(void)
|
|
|
|
{
|
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;
|
|
|
|
}
|
|
|
|
|
2007-12-04 18:27:52 +00:00
|
|
|
static char *
|
|
|
|
vshReadline (vshControl *ctl ATTRIBUTE_UNUSED, const char *prompt)
|
|
|
|
{
|
|
|
|
return readline (prompt);
|
|
|
|
}
|
|
|
|
|
2007-12-06 10:24:52 +00:00
|
|
|
#else /* !USE_READLINE */
|
2007-12-04 18:27:52 +00:00
|
|
|
|
|
|
|
static void
|
|
|
|
vshReadlineInit (void)
|
|
|
|
{
|
|
|
|
/* 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);
|
|
|
|
}
|
|
|
|
|
2007-12-06 10:24:52 +00:00
|
|
|
#endif /* !USE_READLINE */
|
2007-12-04 18:27:52 +00:00
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
/*
|
2008-02-04 14:58:47 +00:00
|
|
|
* Deinitialize virsh
|
2005-12-08 10:23:34 +00:00
|
|
|
*/
|
|
|
|
static int
|
2006-03-15 12:13:25 +00:00
|
|
|
vshDeinit(vshControl * ctl)
|
|
|
|
{
|
2007-06-06 12:24:31 +00:00
|
|
|
vshCloseLogFile(ctl);
|
2008-01-29 17:41:07 +00:00
|
|
|
free(ctl->name);
|
2005-12-08 10:23:34 +00:00
|
|
|
if (ctl->conn) {
|
2006-03-15 12:13:25 +00:00
|
|
|
if (virConnectClose(ctl->conn) != 0) {
|
|
|
|
ctl->conn = NULL; /* prevent recursive call from vshError() */
|
2008-02-04 14:58:47 +00:00
|
|
|
vshError(ctl, TRUE, "%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;
|
|
|
|
}
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
/*
|
|
|
|
* Print usage
|
|
|
|
*/
|
|
|
|
static void
|
2006-03-15 12:13:25 +00:00
|
|
|
vshUsage(vshControl * ctl, const char *cmdname)
|
|
|
|
{
|
2005-12-08 10:23:34 +00:00
|
|
|
vshCmdDef *cmd;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
/* global help */
|
|
|
|
if (!cmdname) {
|
2006-09-21 15:24:37 +00:00
|
|
|
fprintf(stdout, _("\n%s [options] [commands]\n\n"
|
2007-02-07 13:50:18 +00:00
|
|
|
" options:\n"
|
|
|
|
" -c | --connect <uri> hypervisor connection URI\n"
|
2007-03-08 13:48:22 +00:00
|
|
|
" -r | --readonly connect readonly\n"
|
2007-02-07 13:50:18 +00:00
|
|
|
" -d | --debug <num> debug level [0-5]\n"
|
|
|
|
" -h | --help this help\n"
|
|
|
|
" -q | --quiet quiet mode\n"
|
|
|
|
" -t | --timing print timing information\n"
|
2007-06-06 12:24:31 +00:00
|
|
|
" -l | --log <file> output logging to file\n"
|
2007-02-07 13:50:18 +00:00
|
|
|
" -v | --version program version\n\n"
|
|
|
|
" commands (non interactive mode):\n"), progname);
|
2006-03-15 12:13:25 +00:00
|
|
|
|
|
|
|
for (cmd = commands; cmd->name; cmd++)
|
|
|
|
fprintf(stdout,
|
2007-06-15 08:18:55 +00:00
|
|
|
" %-15s %s\n", cmd->name, N_(vshCmddefGetInfo(cmd,
|
2007-02-07 13:50:18 +00:00
|
|
|
"help")));
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2008-01-16 17:13:23 +00:00
|
|
|
fprintf(stdout, "%s",
|
2007-07-06 15:05:19 +00:00
|
|
|
_("\n (specify help <command> for details about the command)\n\n"));
|
2005-12-08 10:23:34 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!vshCmddefHelp(ctl, cmdname, TRUE))
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* argv[]: virsh [options] [command]
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
static int
|
2006-03-15 12:13:25 +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;
|
2006-03-15 12:13:25 +00:00
|
|
|
int arg, idx = 0;
|
2005-12-08 10:23:34 +00:00
|
|
|
struct option opt[] = {
|
2006-03-15 12:13:25 +00:00
|
|
|
{"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'},
|
2007-06-06 12:24:31 +00:00
|
|
|
{"log", 1, 0, 'l'},
|
2005-12-08 10:23:34 +00:00
|
|
|
{0, 0, 0, 0}
|
2006-03-15 12:13:25 +00:00
|
|
|
};
|
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
|
|
|
|
if (argc < 2)
|
2005-12-08 14:22:52 +00:00
|
|
|
return TRUE;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
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
|
|
|
|
*/
|
2006-03-15 12:13:25 +00:00
|
|
|
for (i = 1; i < argc; i++) {
|
2005-12-08 10:23:34 +00:00
|
|
|
if (*argv[i] != '-') {
|
|
|
|
int valid = FALSE;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
/* non "--option" argv, is it command? */
|
|
|
|
if (last) {
|
|
|
|
struct option *o;
|
|
|
|
int sz = strlen(last);
|
2006-03-15 12:13:25 +00:00
|
|
|
|
|
|
|
for (o = opt; o->name; o++) {
|
2007-02-27 15:32:18 +00:00
|
|
|
if (o->has_arg == 1){
|
|
|
|
if (sz == 2 && *(last + 1) == o->val)
|
|
|
|
/* valid virsh short option */
|
|
|
|
valid = TRUE;
|
|
|
|
else if (sz > 2 && strcmp(o->name, last + 2) == 0)
|
|
|
|
/* valid virsh long option */
|
|
|
|
valid = TRUE;
|
|
|
|
}
|
2005-12-08 10:23:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!valid) {
|
|
|
|
end = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
last = argv[i];
|
|
|
|
}
|
2007-09-29 18:16:26 +00:00
|
|
|
end = end ? end : argc;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
/* standard (non-command) options */
|
2007-06-06 12:24:31 +00:00
|
|
|
while ((arg = getopt_long(end, argv, "d:hqtc:vrl:", opt, &idx)) != -1) {
|
2006-03-15 12:13:25 +00:00
|
|
|
switch (arg) {
|
2007-02-07 13:50:18 +00:00
|
|
|
case 'd':
|
|
|
|
ctl->debug = atoi(optarg);
|
|
|
|
break;
|
|
|
|
case 'h':
|
|
|
|
help = 1;
|
|
|
|
break;
|
|
|
|
case 'q':
|
|
|
|
ctl->quiet = TRUE;
|
|
|
|
break;
|
|
|
|
case 't':
|
|
|
|
ctl->timing = TRUE;
|
|
|
|
break;
|
|
|
|
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;
|
2007-06-06 12:24:31 +00:00
|
|
|
case 'l':
|
|
|
|
ctl->logfile = vshStrdup(ctl, optarg);
|
|
|
|
break;
|
2007-02-07 13:50:18 +00:00
|
|
|
default:
|
|
|
|
vshError(ctl, TRUE,
|
|
|
|
_("unsupported option '-%c'. See --help."), arg);
|
|
|
|
break;
|
2005-12-08 10:23:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (help) {
|
|
|
|
/* global or command specific help */
|
|
|
|
vshUsage(ctl, argc > end ? argv[end] : NULL);
|
|
|
|
exit(EXIT_SUCCESS);
|
2006-03-15 12:13:25 +00:00
|
|
|
}
|
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
if (argc > end) {
|
|
|
|
/* parse command */
|
|
|
|
char *cmdstr;
|
2006-03-15 12:13:25 +00:00
|
|
|
int sz = 0, ret;
|
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
ctl->imode = FALSE;
|
|
|
|
|
2006-03-15 12:13:25 +00:00
|
|
|
for (i = end; i < argc; i++)
|
|
|
|
sz += strlen(argv[i]) + 1; /* +1 is for blank space between items */
|
|
|
|
|
2006-04-06 10:33:06 +00:00
|
|
|
cmdstr = vshCalloc(ctl, sz + 1, 1);
|
2006-03-15 12:13:25 +00:00
|
|
|
|
|
|
|
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);
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
free(cmdstr);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2006-03-15 12:13:25 +00:00
|
|
|
int
|
|
|
|
main(int argc, char **argv)
|
|
|
|
{
|
|
|
|
vshControl _ctl, *ctl = &_ctl;
|
2006-08-25 22:40:33 +00:00
|
|
|
char *defaultConn;
|
2005-12-08 10:23:34 +00:00
|
|
|
int ret = TRUE;
|
|
|
|
|
2006-09-21 15:24:37 +00:00
|
|
|
if (!setlocale(LC_ALL, "")) {
|
|
|
|
perror("setlocale");
|
2007-02-07 13:50:18 +00:00
|
|
|
return -1;
|
2006-09-21 15:24:37 +00:00
|
|
|
}
|
|
|
|
if (!bindtextdomain(GETTEXT_PACKAGE, LOCALEBASEDIR)) {
|
|
|
|
perror("bindtextdomain");
|
2007-02-07 13:50:18 +00:00
|
|
|
return -1;
|
2006-09-21 15:24:37 +00:00
|
|
|
}
|
|
|
|
if (!textdomain(GETTEXT_PACKAGE)) {
|
|
|
|
perror("textdomain");
|
2007-02-07 13:50:18 +00:00
|
|
|
return -1;
|
2006-09-21 15:24:37 +00:00
|
|
|
}
|
|
|
|
|
2006-03-15 12:13:25 +00:00
|
|
|
if (!(progname = strrchr(argv[0], '/')))
|
2005-12-08 10:23:34 +00:00
|
|
|
progname = argv[0];
|
|
|
|
else
|
|
|
|
progname++;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
memset(ctl, 0, sizeof(vshControl));
|
2006-03-15 12:13:25 +00:00
|
|
|
ctl->imode = TRUE; /* default is interactive mode */
|
2007-06-06 12:24:31 +00:00
|
|
|
ctl->log_fd = -1; /* Initialize log file descriptor */
|
2005-12-08 10:23:34 +00:00
|
|
|
|
2006-08-25 22:40:33 +00:00
|
|
|
if ((defaultConn = getenv("VIRSH_DEFAULT_CONNECT_URI"))) {
|
2007-02-07 13:50:18 +00:00
|
|
|
ctl->name = strdup(defaultConn);
|
2006-08-25 22:40:33 +00:00
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
2006-03-15 12:13: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
|
|
|
}
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
if (!ctl->imode) {
|
2006-03-15 12:13:25 +00:00
|
|
|
ret = vshCommandRun(ctl, ctl->cmd);
|
2005-12-01 16:35:42 +00:00
|
|
|
} else {
|
2005-12-08 10:23:34 +00:00
|
|
|
/* interactive mode */
|
|
|
|
if (!ctl->quiet) {
|
2006-05-22 14:38:33 +00:00
|
|
|
vshPrint(ctl,
|
2006-09-21 15:24:37 +00:00
|
|
|
_("Welcome to %s, the virtualization interactive terminal.\n\n"),
|
2006-03-15 12:13:25 +00:00
|
|
|
progname);
|
2008-01-16 17:13:23 +00:00
|
|
|
vshPrint(ctl, "%s",
|
2006-09-21 15:24:37 +00:00
|
|
|
_("Type: 'help' for help with commands\n"
|
2007-02-07 13:50:18 +00:00
|
|
|
" 'quit' to quit\n\n"));
|
2005-12-08 10:23:34 +00:00
|
|
|
}
|
2005-12-08 14:22:52 +00:00
|
|
|
vshReadlineInit();
|
2005-12-08 10:23:34 +00:00
|
|
|
do {
|
2007-12-06 16:36:21 +00:00
|
|
|
const char *prompt = ctl->readonly ? VSH_PROMPT_RO : VSH_PROMPT_RW;
|
2006-03-15 12:13:25 +00:00
|
|
|
ctl->cmdstr =
|
2007-12-06 16:36:21 +00:00
|
|
|
vshReadline(ctl, prompt);
|
2006-03-15 12:13:25 +00:00
|
|
|
if (ctl->cmdstr == NULL)
|
|
|
|
break; /* EOF */
|
2005-12-08 10:23:34 +00:00
|
|
|
if (*ctl->cmdstr) {
|
2007-12-06 10:24:52 +00:00
|
|
|
#if USE_READLINE
|
2005-12-08 10:23:34 +00:00
|
|
|
add_history(ctl->cmdstr);
|
2007-12-04 18:27:52 +00:00
|
|
|
#endif
|
2005-12-08 10:23:34 +00:00
|
|
|
if (vshCommandParse(ctl, ctl->cmdstr))
|
|
|
|
vshCommandRun(ctl, ctl->cmd);
|
|
|
|
}
|
|
|
|
free(ctl->cmdstr);
|
|
|
|
ctl->cmdstr = NULL;
|
2006-03-15 12:13:25 +00:00
|
|
|
} while (ctl->imode);
|
2005-12-08 10:23:34 +00:00
|
|
|
|
2006-03-15 12:13:25 +00:00
|
|
|
if (ctl->cmdstr == NULL)
|
|
|
|
fputc('\n', stdout); /* line break after alone prompt */
|
2005-12-08 10:23:34 +00:00
|
|
|
}
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
vshDeinit(ctl);
|
|
|
|
exit(ret ? EXIT_SUCCESS : EXIT_FAILURE);
|
2005-11-10 16:12:31 +00:00
|
|
|
}
|
2005-12-08 10:23:34 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* vim: set tabstop=4:
|
|
|
|
* vim: set shiftwidth=4:
|
|
|
|
* vim: set expandtab:
|
|
|
|
*/
|
2007-02-07 13:50:18 +00:00
|
|
|
/*
|
|
|
|
* Local variables:
|
|
|
|
* indent-tabs-mode: nil
|
|
|
|
* c-indent-level: 4
|
|
|
|
* c-basic-offset: 4
|
|
|
|
* tab-width: 4
|
|
|
|
* End:
|
|
|
|
*/
|