2 * virsh.c: a shell to exercise the libvirt API
4 * Copyright (C) 2005, 2007-2010 Red Hat, Inc.
6 * See COPYING.LIB for the License of this software
8 * Daniel Veillard <veillard@redhat.com>
9 * Karel Zak <kzak@redhat.com>
10 * Daniel P. Berrange <berrange@redhat.com>
22 #include <sys/types.h>
35 #include <libxml/parser.h>
36 #include <libxml/tree.h>
37 #include <libxml/xpath.h>
38 #include <libxml/xmlsave.h>
40 #ifdef HAVE_READLINE_READLINE_H
41 # include <readline/readline.h>
42 # include <readline/history.h>
46 #include "virterror_internal.h"
53 #include "libvirt/libvirt-qemu.h"
55 #include "../daemon/event.h"
56 #include "configmake.h"
58 static char *progname
;
65 #define VIRSH_MAX_XML_FILE 10*1024*1024
67 #define VSH_PROMPT_RW "virsh # "
68 #define VSH_PROMPT_RO "virsh > "
70 #define GETTIMEOFDAY(T) gettimeofday(T, NULL)
71 #define DIFF_MSEC(T, U) \
72 ((((int) ((T)->tv_sec - (U)->tv_sec)) * 1000000.0 + \
73 ((int) ((T)->tv_usec - (U)->tv_usec))) / 1000.0)
76 * The log configuration
78 #define MSG_BUFFER 4096
79 #define SIGN_NAME "virsh"
80 #define DIR_MODE (S_IWUSR | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) /* 0755 */
81 #define FILE_MODE (S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH) /* 0644 */
82 #define LOCK_MODE (S_IWUSR | S_IRUSR) /* 0600 */
83 #define LVL_DEBUG "DEBUG"
84 #define LVL_INFO "INFO"
85 #define LVL_NOTICE "NOTICE"
86 #define LVL_WARNING "WARNING"
87 #define LVL_ERROR "ERROR"
92 * Indicates the level of a log message
103 * virsh command line grammar:
105 * command_line = <command>\n | <command>; <command>; ...
107 * command = <keyword> <option> [--] <data>
109 * option = <bool_option> | <int_option> | <string_option>
112 * bool_option = --optionname
113 * int_option = --optionname <number> | --optionname=<number>
114 * string_option = --optionname <string> | --optionname=<string>
116 * keyword = [a-zA-Z][a-zA-Z-]*
118 * string = ('[^']*'|"([^\\"]|\\.)*"|([^ \t\n\\'"]|\\.))+
123 * vshCmdOptType - command option type
126 VSH_OT_BOOL
, /* optional boolean option */
127 VSH_OT_STRING
, /* optional string option */
128 VSH_OT_INT
, /* optional or mandatory int option */
129 VSH_OT_DATA
, /* string data (as non-option) */
130 VSH_OT_ARGV
/* remaining arguments, opt->name should be "" */
134 * Command group types
136 #define VSH_CMD_GRP_DOM_MANAGEMENT "Domain Management"
137 #define VSH_CMD_GRP_DOM_MONITORING "Domain Monitoring"
138 #define VSH_CMD_GRP_STORAGE_POOL "Storage Pool"
139 #define VSH_CMD_GRP_STORAGE_VOL "Storage Volume"
140 #define VSH_CMD_GRP_NETWORK "Networking"
141 #define VSH_CMD_GRP_NODEDEV "Node Device"
142 #define VSH_CMD_GRP_IFACE "Interface"
143 #define VSH_CMD_GRP_NWFILTER "Network Filter"
144 #define VSH_CMD_GRP_SECRET "Secret"
145 #define VSH_CMD_GRP_SNAPSHOT "Snapshot"
146 #define VSH_CMD_GRP_HOST_AND_HV "Host and Hypervisor"
147 #define VSH_CMD_GRP_VIRSH "Virsh itself"
150 * Command Option Flags
152 #define VSH_OFLAG_NONE 0 /* without flags */
153 #define VSH_OFLAG_REQ (1 << 1) /* option required */
156 typedef struct __vshControl vshControl
;
157 typedef struct __vshCmd vshCmd
;
160 * vshCmdInfo -- information about command
163 const char *name
; /* name of information */
164 const char *data
; /* information */
168 * vshCmdOptDef - command option definition
171 const char *name
; /* the name of option */
172 vshCmdOptType type
; /* option type */
173 int flag
; /* flags */
174 const char *help
; /* help string */
178 * vshCmdOpt - command options
180 typedef struct vshCmdOpt
{
181 const vshCmdOptDef
*def
; /* pointer to relevant option */
182 char *data
; /* allocated data */
183 struct vshCmdOpt
*next
;
187 * vshCmdDef - command definition
191 int (*handler
) (vshControl
*, const vshCmd
*); /* command handler */
192 const vshCmdOptDef
*opts
; /* definition of command options */
193 const vshCmdInfo
*info
; /* details about command */
197 * vshCmd - parsed command
199 typedef struct __vshCmd
{
200 const vshCmdDef
*def
; /* command definition */
201 vshCmdOpt
*opts
; /* list of command arguments */
202 struct __vshCmd
*next
; /* next command */
208 typedef struct __vshControl
{
209 char *name
; /* connection name */
210 virConnectPtr conn
; /* connection to hypervisor (MAY BE NULL) */
211 vshCmd
*cmd
; /* the current command */
212 char *cmdstr
; /* string with command */
213 int imode
; /* interactive mode? */
214 int quiet
; /* quiet mode */
215 int debug
; /* print debug messages? */
216 int timing
; /* print timing info? */
217 int readonly
; /* connect readonly (first time only, not
218 * during explicit connect command)
220 char *logfile
; /* log file name */
221 int log_fd
; /* log file descriptor */
222 char *historydir
; /* readline history directory name */
223 char *historyfile
; /* readline history file name */
226 typedef struct vshCmdGrp
{
228 const char *keyword
; /* help keyword */
229 const vshCmdDef
*commands
;
232 static const vshCmdGrp cmdGroups
[];
234 static void vshError(vshControl
*ctl
, const char *format
, ...)
235 ATTRIBUTE_FMT_PRINTF(2, 3);
236 static int vshInit(vshControl
*ctl
);
237 static int vshDeinit(vshControl
*ctl
);
238 static void vshUsage(void);
239 static void vshOpenLogFile(vshControl
*ctl
);
240 static void vshOutputLogFile(vshControl
*ctl
, int log_level
, const char *format
, va_list ap
);
241 static void vshCloseLogFile(vshControl
*ctl
);
243 static int vshParseArgv(vshControl
*ctl
, int argc
, char **argv
);
245 static const char *vshCmddefGetInfo(const vshCmdDef
*cmd
, const char *info
);
246 static const vshCmdDef
*vshCmddefSearch(const char *cmdname
);
247 static int vshCmddefHelp(vshControl
*ctl
, const char *name
);
248 static const vshCmdGrp
*vshCmdGrpSearch(const char *grpname
);
249 static int vshCmdGrpHelp(vshControl
*ctl
, const char *name
);
251 static vshCmdOpt
*vshCommandOpt(const vshCmd
*cmd
, const char *name
);
252 static int vshCommandOptInt(const vshCmd
*cmd
, const char *name
, int *found
);
253 static unsigned long vshCommandOptUL(const vshCmd
*cmd
, const char *name
,
255 static char *vshCommandOptString(const vshCmd
*cmd
, const char *name
,
257 static long long vshCommandOptLongLong(const vshCmd
*cmd
, const char *name
,
259 static int vshCommandOptBool(const vshCmd
*cmd
, const char *name
);
260 static char *vshCommandOptArgv(const vshCmd
*cmd
, int count
);
262 #define VSH_BYID (1 << 1)
263 #define VSH_BYUUID (1 << 2)
264 #define VSH_BYNAME (1 << 3)
265 #define VSH_BYMAC (1 << 4)
267 static virDomainPtr
vshCommandOptDomainBy(vshControl
*ctl
, const vshCmd
*cmd
,
268 char **name
, int flag
);
270 /* default is lookup by Id, Name and UUID */
271 #define vshCommandOptDomain(_ctl, _cmd, _name) \
272 vshCommandOptDomainBy(_ctl, _cmd, _name, VSH_BYID|VSH_BYUUID|VSH_BYNAME)
274 static virNetworkPtr
vshCommandOptNetworkBy(vshControl
*ctl
, const vshCmd
*cmd
,
275 char **name
, int flag
);
277 /* default is lookup by Name and UUID */
278 #define vshCommandOptNetwork(_ctl, _cmd, _name) \
279 vshCommandOptNetworkBy(_ctl, _cmd, _name, \
280 VSH_BYUUID|VSH_BYNAME)
282 static virNWFilterPtr
vshCommandOptNWFilterBy(vshControl
*ctl
, const vshCmd
*cmd
,
283 char **name
, int flag
);
285 /* default is lookup by Name and UUID */
286 #define vshCommandOptNWFilter(_ctl, _cmd, _name) \
287 vshCommandOptNWFilterBy(_ctl, _cmd, _name, \
288 VSH_BYUUID|VSH_BYNAME)
290 static virInterfacePtr
vshCommandOptInterfaceBy(vshControl
*ctl
, const vshCmd
*cmd
,
291 char **name
, int flag
);
293 /* default is lookup by Name and MAC */
294 #define vshCommandOptInterface(_ctl, _cmd, _name) \
295 vshCommandOptInterfaceBy(_ctl, _cmd, _name, \
296 VSH_BYMAC|VSH_BYNAME)
298 static virStoragePoolPtr
vshCommandOptPoolBy(vshControl
*ctl
, const vshCmd
*cmd
,
299 const char *optname
, char **name
, int flag
);
301 /* default is lookup by Name and UUID */
302 #define vshCommandOptPool(_ctl, _cmd, _optname, _name) \
303 vshCommandOptPoolBy(_ctl, _cmd, _optname, _name, \
304 VSH_BYUUID|VSH_BYNAME)
306 static virStorageVolPtr
vshCommandOptVolBy(vshControl
*ctl
, const vshCmd
*cmd
,
308 const char *pooloptname
,
309 char **name
, int flag
);
311 /* default is lookup by Name and UUID */
312 #define vshCommandOptVol(_ctl, _cmd,_optname, _pooloptname, _name) \
313 vshCommandOptVolBy(_ctl, _cmd, _optname, _pooloptname, _name, \
314 VSH_BYUUID|VSH_BYNAME)
316 static virSecretPtr
vshCommandOptSecret(vshControl
*ctl
, const vshCmd
*cmd
,
319 static void vshPrintExtra(vshControl
*ctl
, const char *format
, ...)
320 ATTRIBUTE_FMT_PRINTF(2, 3);
321 static void vshDebug(vshControl
*ctl
, int level
, const char *format
, ...)
322 ATTRIBUTE_FMT_PRINTF(3, 4);
324 /* XXX: add batch support */
325 #define vshPrint(_ctl, ...) fprintf(stdout, __VA_ARGS__)
327 static const char *vshDomainStateToString(int state
);
328 static const char *vshDomainVcpuStateToString(int state
);
329 static int vshConnectionUsability(vshControl
*ctl
, virConnectPtr conn
);
331 static char *editWriteToTempFile (vshControl
*ctl
, const char *doc
);
332 static int editFile (vshControl
*ctl
, const char *filename
);
333 static char *editReadBackFile (vshControl
*ctl
, const char *filename
);
335 static void *_vshMalloc(vshControl
*ctl
, size_t sz
, const char *filename
, int line
);
336 #define vshMalloc(_ctl, _sz) _vshMalloc(_ctl, _sz, __FILE__, __LINE__)
338 static void *_vshCalloc(vshControl
*ctl
, size_t nmemb
, size_t sz
, const char *filename
, int line
);
339 #define vshCalloc(_ctl, _nmemb, _sz) _vshCalloc(_ctl, _nmemb, _sz, __FILE__, __LINE__)
341 static void *_vshRealloc(vshControl
*ctl
, void *ptr
, size_t sz
, const char *filename
, int line
);
342 #define vshRealloc(_ctl, _ptr, _sz) _vshRealloc(_ctl, _ptr, _sz, __FILE__, __LINE__)
344 static char *_vshStrdup(vshControl
*ctl
, const char *s
, const char *filename
, int line
);
345 #define vshStrdup(_ctl, _s) _vshStrdup(_ctl, _s, __FILE__, __LINE__)
348 _vshMalloc(vshControl
*ctl
, size_t size
, const char *filename
, int line
)
352 if ((x
= malloc(size
)))
354 vshError(ctl
, _("%s: %d: failed to allocate %d bytes"),
355 filename
, line
, (int) size
);
360 _vshCalloc(vshControl
*ctl
, size_t nmemb
, size_t size
, const char *filename
, int line
)
364 if ((x
= calloc(nmemb
, size
)))
366 vshError(ctl
, _("%s: %d: failed to allocate %d bytes"),
367 filename
, line
, (int) (size
*nmemb
));
372 _vshRealloc(vshControl
*ctl
, void *ptr
, size_t size
, const char *filename
, int line
)
376 if ((x
= realloc(ptr
, size
)))
379 vshError(ctl
, _("%s: %d: failed to allocate %d bytes"),
380 filename
, line
, (int) size
);
385 _vshStrdup(vshControl
*ctl
, const char *s
, const char *filename
, int line
)
393 vshError(ctl
, _("%s: %d: failed to allocate %lu bytes"),
394 filename
, line
, (unsigned long)strlen(s
));
398 /* Poison the raw allocating identifiers in favor of our vsh variants. */
403 #define malloc use_vshMalloc_instead_of_malloc
404 #define calloc use_vshCalloc_instead_of_calloc
405 #define realloc use_vshRealloc_instead_of_realloc
406 #define strdup use_vshStrdup_instead_of_strdup
408 static int idsorter(const void *a
, const void *b
) {
409 const int *ia
= (const int *)a
;
410 const int *ib
= (const int *)b
;
418 static int namesorter(const void *a
, const void *b
) {
419 const char **sa
= (const char**)a
;
420 const char **sb
= (const char**)b
;
422 return strcasecmp(*sa
, *sb
);
426 prettyCapacity(unsigned long long val
,
431 } else if (val
< (1024.0l * 1024.0l)) {
433 return (((double)val
/ 1024.0l));
434 } else if (val
< (1024.0l * 1024.0l * 1024.0l)) {
436 return ((double)val
/ (1024.0l * 1024.0l));
437 } else if (val
< (1024.0l * 1024.0l * 1024.0l * 1024.0l)) {
439 return ((double)val
/ (1024.0l * 1024.0l * 1024.0l));
442 return ((double)val
/ (1024.0l * 1024.0l * 1024.0l * 1024.0l));
447 static virErrorPtr last_error
;
450 * Quieten libvirt until we're done with the command.
453 virshErrorHandler(void *unused ATTRIBUTE_UNUSED
, virErrorPtr error
)
455 virFreeError(last_error
);
456 last_error
= virSaveLastError();
457 if (getenv("VIRSH_DEBUG") != NULL
)
458 virDefaultErrorFunc(error
);
462 * Report an error when a command finishes. This is better than before
463 * (when correct operation would report errors), but it has some
464 * problems: we lose the smarter formatting of virDefaultErrorFunc(),
465 * and it can become harder to debug problems, if errors get reported
466 * twice during one command. This case shouldn't really happen anyway,
467 * and it's IMHO a bug that libvirt does that sometimes.
470 virshReportError(vshControl
*ctl
)
472 if (last_error
== NULL
) {
473 /* Calling directly into libvirt util functions won't trigger the
474 * error callback (which sets last_error), so check it ourselves.
476 * If the returned error has CODE_OK, this most likely means that
477 * no error was ever raised, so just ignore */
478 last_error
= virSaveLastError();
479 if (!last_error
|| last_error
->code
== VIR_ERR_OK
)
483 if (last_error
->code
== VIR_ERR_OK
) {
484 vshError(ctl
, "%s", _("unknown error"));
488 vshError(ctl
, "%s", last_error
->message
);
491 virFreeError(last_error
);
496 * Detection of disconnections and automatic reconnection support
498 static int disconnected
= 0; /* we may have been disconnected */
502 * vshCatchDisconnect:
504 * We get here when a SIGPIPE is being raised, we can't do much in the
505 * handler, just save the fact it was raised
507 static void vshCatchDisconnect(int sig
, siginfo_t
* siginfo
,
508 void* context ATTRIBUTE_UNUSED
) {
509 if ((sig
== SIGPIPE
) || (siginfo
->si_signo
== SIGPIPE
))
516 * Catch SIGPIPE signals which may arise when disconnection
517 * from libvirtd occurs
520 vshSetupSignals(void) {
521 struct sigaction sig_action
;
523 sig_action
.sa_sigaction
= vshCatchDisconnect
;
524 sig_action
.sa_flags
= SA_SIGINFO
;
525 sigemptyset(&sig_action
.sa_mask
);
527 sigaction(SIGPIPE
, &sig_action
, NULL
);
531 vshSetupSignals(void) {}
537 * Reconnect after a disconnect from libvirtd
541 vshReconnect(vshControl
*ctl
) {
542 if (ctl
->conn
!= NULL
)
543 virConnectClose(ctl
->conn
);
545 ctl
->conn
= virConnectOpenAuth(ctl
->name
,
546 virConnectAuthPtrDefault
,
547 ctl
->readonly
? VIR_CONNECT_RO
: 0);
549 vshError(ctl
, "%s", _("Failed to reconnect to the hypervisor"));
551 vshError(ctl
, "%s", _("Reconnected to the hypervisor"));
563 static const vshCmdInfo info_help
[] = {
564 {"help", N_("print help")},
565 {"desc", N_("Prints global help, command specific help, or help for a\n"
566 " group of related commands")},
571 static const vshCmdOptDef opts_help
[] = {
572 {"command", VSH_OT_DATA
, 0, N_("Prints global help or command specific help.")},
573 {"group", VSH_OT_DATA
, 0, N_("Prints global help or help for a group of related commands.")},
578 cmdHelp(vshControl
*ctl
, const vshCmd
*cmd
)
584 name
= vshCommandOptString(cmd
, "command", NULL
);
587 name
= vshCommandOptString(cmd
, "group", NULL
);
590 const vshCmdGrp
*grp
;
591 const vshCmdDef
*def
;
593 vshPrint(ctl
, "%s", _("Grouped commands:\n\n"));
595 for (grp
= cmdGroups
; grp
->name
; grp
++) {
596 vshPrint(ctl
, _(" %s (help keyword '%s'):\n"), grp
->name
,
599 for (def
= grp
->commands
; def
->name
; def
++)
600 vshPrint(ctl
, " %-30s %s\n", def
->name
,
601 _(vshCmddefGetInfo(def
, "help")));
609 if ((c
= vshCmddefSearch(name
))) {
610 return vshCmddefHelp(ctl
, name
);
611 } else if ((g
= vshCmdGrpSearch(name
))) {
612 return vshCmdGrpHelp(ctl
, name
);
614 vshError(ctl
, _("command or command group '%s' doesn't exist"), name
);
620 * "autostart" command
622 static const vshCmdInfo info_autostart
[] = {
623 {"help", N_("autostart a domain")},
625 N_("Configure a domain to be automatically started at boot.")},
629 static const vshCmdOptDef opts_autostart
[] = {
630 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
631 {"disable", VSH_OT_BOOL
, 0, N_("disable autostarting")},
636 cmdAutostart(vshControl
*ctl
, const vshCmd
*cmd
)
642 if (!vshConnectionUsability(ctl
, ctl
->conn
))
645 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, &name
)))
648 autostart
= !vshCommandOptBool(cmd
, "disable");
650 if (virDomainSetAutostart(dom
, autostart
) < 0) {
652 vshError(ctl
, _("Failed to mark domain %s as autostarted"), name
);
654 vshError(ctl
, _("Failed to unmark domain %s as autostarted"), name
);
660 vshPrint(ctl
, _("Domain %s marked as autostarted\n"), name
);
662 vshPrint(ctl
, _("Domain %s unmarked as autostarted\n"), name
);
671 static const vshCmdInfo info_connect
[] = {
672 {"help", N_("(re)connect to hypervisor")},
674 N_("Connect to local hypervisor. This is built-in command after shell start up.")},
678 static const vshCmdOptDef opts_connect
[] = {
679 {"name", VSH_OT_DATA
, 0, N_("hypervisor connection URI")},
680 {"readonly", VSH_OT_BOOL
, 0, N_("read-only connection")},
685 cmdConnect(vshControl
*ctl
, const vshCmd
*cmd
)
687 int ro
= vshCommandOptBool(cmd
, "readonly");
692 if ((ret
= virConnectClose(ctl
->conn
)) != 0) {
693 vshError(ctl
, _("Failed to disconnect from the hypervisor, %d leaked reference(s)"), ret
);
700 name
= vshCommandOptString(cmd
, "name", NULL
);
703 ctl
->name
= vshStrdup(ctl
, name
);
711 ctl
->conn
= virConnectOpenAuth(ctl
->name
, virConnectAuthPtrDefault
,
712 ctl
->readonly
? VIR_CONNECT_RO
: 0);
715 vshError(ctl
, "%s", _("Failed to connect to the hypervisor"));
717 return ctl
->conn
? TRUE
: FALSE
;
725 static const vshCmdInfo info_console
[] = {
726 {"help", N_("connect to the guest console")},
728 N_("Connect the virtual serial console for the guest")},
732 static const vshCmdOptDef opts_console
[] = {
733 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
734 {"devname", VSH_OT_STRING
, 0, N_("character device name")},
739 cmdRunConsole(vshControl
*ctl
, virDomainPtr dom
, const char *devname
)
742 virDomainInfo dominfo
;
744 if (virDomainGetInfo(dom
, &dominfo
) < 0) {
745 vshError(ctl
, "%s", _("Unable to get domain status"));
749 if (dominfo
.state
== VIR_DOMAIN_SHUTOFF
) {
750 vshError(ctl
, "%s", _("The domain is not running"));
754 vshPrintExtra(ctl
, _("Connected to domain %s\n"), virDomainGetName(dom
));
755 vshPrintExtra(ctl
, "%s", _("Escape character is ^]\n"));
756 if (vshRunConsole(dom
, devname
) == 0)
765 cmdConsole(vshControl
*ctl
, const vshCmd
*cmd
)
771 if (!vshConnectionUsability(ctl
, ctl
->conn
))
774 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, NULL
)))
777 devname
= vshCommandOptString(cmd
, "devname", NULL
);
779 ret
= cmdRunConsole(ctl
, dom
, devname
);
791 static const vshCmdInfo info_list
[] = {
792 {"help", N_("list domains")},
793 {"desc", N_("Returns list of domains.")},
797 static const vshCmdOptDef opts_list
[] = {
798 {"inactive", VSH_OT_BOOL
, 0, N_("list inactive domains")},
799 {"all", VSH_OT_BOOL
, 0, N_("list inactive & active domains")},
805 cmdList(vshControl
*ctl
, const vshCmd
*cmd ATTRIBUTE_UNUSED
)
807 int inactive
= vshCommandOptBool(cmd
, "inactive");
808 int all
= vshCommandOptBool(cmd
, "all");
809 int active
= !inactive
|| all
? 1 : 0;
810 int *ids
= NULL
, maxid
= 0, i
;
815 if (!vshConnectionUsability(ctl
, ctl
->conn
))
819 maxid
= virConnectNumOfDomains(ctl
->conn
);
821 vshError(ctl
, "%s", _("Failed to list active domains"));
825 ids
= vshMalloc(ctl
, sizeof(int) * maxid
);
827 if ((maxid
= virConnectListDomains(ctl
->conn
, &ids
[0], maxid
)) < 0) {
828 vshError(ctl
, "%s", _("Failed to list active domains"));
833 qsort(&ids
[0], maxid
, sizeof(int), idsorter
);
837 maxname
= virConnectNumOfDefinedDomains(ctl
->conn
);
839 vshError(ctl
, "%s", _("Failed to list inactive domains"));
844 names
= vshMalloc(ctl
, sizeof(char *) * maxname
);
846 if ((maxname
= virConnectListDefinedDomains(ctl
->conn
, names
, maxname
)) < 0) {
847 vshError(ctl
, "%s", _("Failed to list inactive domains"));
853 qsort(&names
[0], maxname
, sizeof(char*), namesorter
);
856 vshPrintExtra(ctl
, "%3s %-20s %s\n", _("Id"), _("Name"), _("State"));
857 vshPrintExtra(ctl
, "----------------------------------\n");
859 for (i
= 0; i
< maxid
; i
++) {
861 virDomainPtr dom
= virDomainLookupByID(ctl
->conn
, ids
[i
]);
864 /* this kind of work with domains is not atomic operation */
868 if (virDomainGetInfo(dom
, &info
) < 0)
869 state
= _("no state");
871 state
= _(vshDomainStateToString(info
.state
));
873 vshPrint(ctl
, "%3d %-20s %s\n",
875 virDomainGetName(dom
),
879 for (i
= 0; i
< maxname
; i
++) {
881 virDomainPtr dom
= virDomainLookupByName(ctl
->conn
, names
[i
]);
884 /* this kind of work with domains is not atomic operation */
890 if (virDomainGetInfo(dom
, &info
) < 0)
891 state
= _("no state");
893 state
= _(vshDomainStateToString(info
.state
));
895 vshPrint(ctl
, "%3s %-20s %s\n", "-", names
[i
], state
);
908 static const vshCmdInfo info_domstate
[] = {
909 {"help", N_("domain state")},
910 {"desc", N_("Returns state about a domain.")},
914 static const vshCmdOptDef opts_domstate
[] = {
915 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
920 cmdDomstate(vshControl
*ctl
, const vshCmd
*cmd
)
926 if (!vshConnectionUsability(ctl
, ctl
->conn
))
929 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, NULL
)))
932 if (virDomainGetInfo(dom
, &info
) == 0)
933 vshPrint(ctl
, "%s\n",
934 _(vshDomainStateToString(info
.state
)));
942 /* "domblkstat" command
944 static const vshCmdInfo info_domblkstat
[] = {
945 {"help", N_("get device block stats for a domain")},
946 {"desc", N_("Get device block stats for a running domain.")},
950 static const vshCmdOptDef opts_domblkstat
[] = {
951 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
952 {"device", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("block device")},
957 cmdDomblkstat (vshControl
*ctl
, const vshCmd
*cmd
)
961 struct _virDomainBlockStats stats
;
963 if (!vshConnectionUsability (ctl
, ctl
->conn
))
966 if (!(dom
= vshCommandOptDomain (ctl
, cmd
, &name
)))
969 if (!(device
= vshCommandOptString (cmd
, "device", NULL
))) {
974 if (virDomainBlockStats (dom
, device
, &stats
, sizeof stats
) == -1) {
975 vshError(ctl
, _("Failed to get block stats %s %s"), name
, device
);
980 if (stats
.rd_req
>= 0)
981 vshPrint (ctl
, "%s rd_req %lld\n", device
, stats
.rd_req
);
983 if (stats
.rd_bytes
>= 0)
984 vshPrint (ctl
, "%s rd_bytes %lld\n", device
, stats
.rd_bytes
);
986 if (stats
.wr_req
>= 0)
987 vshPrint (ctl
, "%s wr_req %lld\n", device
, stats
.wr_req
);
989 if (stats
.wr_bytes
>= 0)
990 vshPrint (ctl
, "%s wr_bytes %lld\n", device
, stats
.wr_bytes
);
993 vshPrint (ctl
, "%s errs %lld\n", device
, stats
.errs
);
999 /* "domifstat" command
1001 static const vshCmdInfo info_domifstat
[] = {
1002 {"help", N_("get network interface stats for a domain")},
1003 {"desc", N_("Get network interface stats for a running domain.")},
1007 static const vshCmdOptDef opts_domifstat
[] = {
1008 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
1009 {"interface", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("interface device")},
1014 cmdDomIfstat (vshControl
*ctl
, const vshCmd
*cmd
)
1017 char *name
, *device
;
1018 struct _virDomainInterfaceStats stats
;
1020 if (!vshConnectionUsability (ctl
, ctl
->conn
))
1023 if (!(dom
= vshCommandOptDomain (ctl
, cmd
, &name
)))
1026 if (!(device
= vshCommandOptString (cmd
, "interface", NULL
))) {
1031 if (virDomainInterfaceStats (dom
, device
, &stats
, sizeof stats
) == -1) {
1032 vshError(ctl
, _("Failed to get interface stats %s %s"), name
, device
);
1037 if (stats
.rx_bytes
>= 0)
1038 vshPrint (ctl
, "%s rx_bytes %lld\n", device
, stats
.rx_bytes
);
1040 if (stats
.rx_packets
>= 0)
1041 vshPrint (ctl
, "%s rx_packets %lld\n", device
, stats
.rx_packets
);
1043 if (stats
.rx_errs
>= 0)
1044 vshPrint (ctl
, "%s rx_errs %lld\n", device
, stats
.rx_errs
);
1046 if (stats
.rx_drop
>= 0)
1047 vshPrint (ctl
, "%s rx_drop %lld\n", device
, stats
.rx_drop
);
1049 if (stats
.tx_bytes
>= 0)
1050 vshPrint (ctl
, "%s tx_bytes %lld\n", device
, stats
.tx_bytes
);
1052 if (stats
.tx_packets
>= 0)
1053 vshPrint (ctl
, "%s tx_packets %lld\n", device
, stats
.tx_packets
);
1055 if (stats
.tx_errs
>= 0)
1056 vshPrint (ctl
, "%s tx_errs %lld\n", device
, stats
.tx_errs
);
1058 if (stats
.tx_drop
>= 0)
1059 vshPrint (ctl
, "%s tx_drop %lld\n", device
, stats
.tx_drop
);
1066 * "dommemstats" command
1068 static const vshCmdInfo info_dommemstat
[] = {
1069 {"help", N_("get memory statistics for a domain")},
1070 {"desc", N_("Get memory statistics for a runnng domain.")},
1074 static const vshCmdOptDef opts_dommemstat
[] = {
1075 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
1080 cmdDomMemStat(vshControl
*ctl
, const vshCmd
*cmd
)
1084 struct _virDomainMemoryStat stats
[VIR_DOMAIN_MEMORY_STAT_NR
];
1085 unsigned int nr_stats
, i
;
1087 if (!vshConnectionUsability(ctl
, ctl
->conn
))
1090 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, &name
)))
1093 nr_stats
= virDomainMemoryStats (dom
, stats
, VIR_DOMAIN_MEMORY_STAT_NR
, 0);
1094 if (nr_stats
== -1) {
1095 vshError(ctl
, _("Failed to get memory statistics for domain %s"), name
);
1100 for (i
= 0; i
< nr_stats
; i
++) {
1101 if (stats
[i
].tag
== VIR_DOMAIN_MEMORY_STAT_SWAP_IN
)
1102 vshPrint (ctl
, "swap_in %llu\n", stats
[i
].val
);
1103 if (stats
[i
].tag
== VIR_DOMAIN_MEMORY_STAT_SWAP_OUT
)
1104 vshPrint (ctl
, "swap_out %llu\n", stats
[i
].val
);
1105 if (stats
[i
].tag
== VIR_DOMAIN_MEMORY_STAT_MAJOR_FAULT
)
1106 vshPrint (ctl
, "major_fault %llu\n", stats
[i
].val
);
1107 if (stats
[i
].tag
== VIR_DOMAIN_MEMORY_STAT_MINOR_FAULT
)
1108 vshPrint (ctl
, "minor_fault %llu\n", stats
[i
].val
);
1109 if (stats
[i
].tag
== VIR_DOMAIN_MEMORY_STAT_UNUSED
)
1110 vshPrint (ctl
, "unused %llu\n", stats
[i
].val
);
1111 if (stats
[i
].tag
== VIR_DOMAIN_MEMORY_STAT_AVAILABLE
)
1112 vshPrint (ctl
, "available %llu\n", stats
[i
].val
);
1120 * "domblkinfo" command
1122 static const vshCmdInfo info_domblkinfo
[] = {
1123 {"help", N_("domain block device size information")},
1124 {"desc", N_("Get block device size info for a domain.")},
1128 static const vshCmdOptDef opts_domblkinfo
[] = {
1129 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
1130 {"device", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("block device")},
1135 cmdDomblkinfo(vshControl
*ctl
, const vshCmd
*cmd
)
1137 virDomainBlockInfo info
;
1142 if (!vshConnectionUsability(ctl
, ctl
->conn
))
1145 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, NULL
)))
1148 if (!(device
= vshCommandOptString (cmd
, "device", NULL
))) {
1153 if (virDomainGetBlockInfo(dom
, device
, &info
, 0) < 0) {
1158 vshPrint(ctl
, "%-15s %llu\n", _("Capacity:"), info
.capacity
);
1159 vshPrint(ctl
, "%-15s %llu\n", _("Allocation:"), info
.allocation
);
1160 vshPrint(ctl
, "%-15s %llu\n", _("Physical:"), info
.physical
);
1169 static const vshCmdInfo info_suspend
[] = {
1170 {"help", N_("suspend a domain")},
1171 {"desc", N_("Suspend a running domain.")},
1175 static const vshCmdOptDef opts_suspend
[] = {
1176 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
1181 cmdSuspend(vshControl
*ctl
, const vshCmd
*cmd
)
1187 if (!vshConnectionUsability(ctl
, ctl
->conn
))
1190 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, &name
)))
1193 if (virDomainSuspend(dom
) == 0) {
1194 vshPrint(ctl
, _("Domain %s suspended\n"), name
);
1196 vshError(ctl
, _("Failed to suspend domain %s"), name
);
1207 static const vshCmdInfo info_create
[] = {
1208 {"help", N_("create a domain from an XML file")},
1209 {"desc", N_("Create a domain.")},
1213 static const vshCmdOptDef opts_create
[] = {
1214 {"file", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("file containing an XML domain description")},
1216 {"console", VSH_OT_BOOL
, 0, N_("attach to console after creation")},
1218 {"paused", VSH_OT_BOOL
, 0, N_("leave the guest paused after creation")},
1223 cmdCreate(vshControl
*ctl
, const vshCmd
*cmd
)
1231 int console
= vshCommandOptBool(cmd
, "console");
1233 unsigned int flags
= VIR_DOMAIN_NONE
;
1235 if (!vshConnectionUsability(ctl
, ctl
->conn
))
1238 from
= vshCommandOptString(cmd
, "file", &found
);
1242 if (virFileReadAll(from
, VIRSH_MAX_XML_FILE
, &buffer
) < 0)
1245 if (vshCommandOptBool(cmd
, "paused"))
1246 flags
|= VIR_DOMAIN_START_PAUSED
;
1248 dom
= virDomainCreateXML(ctl
->conn
, buffer
, flags
);
1252 vshPrint(ctl
, _("Domain %s created from %s\n"),
1253 virDomainGetName(dom
), from
);
1256 cmdRunConsole(ctl
, dom
, NULL
);
1260 vshError(ctl
, _("Failed to create domain from %s"), from
);
1269 static const vshCmdInfo info_define
[] = {
1270 {"help", N_("define (but don't start) a domain from an XML file")},
1271 {"desc", N_("Define a domain.")},
1275 static const vshCmdOptDef opts_define
[] = {
1276 {"file", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("file containing an XML domain description")},
1281 cmdDefine(vshControl
*ctl
, const vshCmd
*cmd
)
1289 if (!vshConnectionUsability(ctl
, ctl
->conn
))
1292 from
= vshCommandOptString(cmd
, "file", &found
);
1296 if (virFileReadAll(from
, VIRSH_MAX_XML_FILE
, &buffer
) < 0)
1299 dom
= virDomainDefineXML(ctl
->conn
, buffer
);
1303 vshPrint(ctl
, _("Domain %s defined from %s\n"),
1304 virDomainGetName(dom
), from
);
1307 vshError(ctl
, _("Failed to define domain from %s"), from
);
1314 * "undefine" command
1316 static const vshCmdInfo info_undefine
[] = {
1317 {"help", N_("undefine an inactive domain")},
1318 {"desc", N_("Undefine the configuration for an inactive domain.")},
1322 static const vshCmdOptDef opts_undefine
[] = {
1323 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name or uuid")},
1328 cmdUndefine(vshControl
*ctl
, const vshCmd
*cmd
)
1336 if (!vshConnectionUsability(ctl
, ctl
->conn
))
1339 name
= vshCommandOptString(cmd
, "domain", &found
);
1343 if (name
&& virStrToLong_i(name
, NULL
, 10, &id
) == 0
1344 && id
>= 0 && (dom
= virDomainLookupByID(ctl
->conn
, id
))) {
1346 _("a running domain like %s cannot be undefined;\n"
1347 "to undefine, first shutdown then undefine"
1348 " using its name or UUID"),
1353 if (!(dom
= vshCommandOptDomainBy(ctl
, cmd
, &name
,
1354 VSH_BYNAME
|VSH_BYUUID
)))
1357 if (virDomainUndefine(dom
) == 0) {
1358 vshPrint(ctl
, _("Domain %s has been undefined\n"), name
);
1360 vshError(ctl
, _("Failed to undefine domain %s"), name
);
1372 static const vshCmdInfo info_start
[] = {
1373 {"help", N_("start a (previously defined) inactive domain")},
1374 {"desc", N_("Start a domain, either from the last managedsave\n"
1375 " state, or via a fresh boot if no managedsave state\n"
1380 static const vshCmdOptDef opts_start
[] = {
1381 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("name of the inactive domain")},
1383 {"console", VSH_OT_BOOL
, 0, N_("attach to console after creation")},
1385 {"paused", VSH_OT_BOOL
, 0, N_("leave the guest paused after creation")},
1390 cmdStart(vshControl
*ctl
, const vshCmd
*cmd
)
1395 int console
= vshCommandOptBool(cmd
, "console");
1397 unsigned int flags
= VIR_DOMAIN_NONE
;
1399 if (!vshConnectionUsability(ctl
, ctl
->conn
))
1402 if (!(dom
= vshCommandOptDomainBy(ctl
, cmd
, NULL
, VSH_BYNAME
)))
1405 if (virDomainGetID(dom
) != (unsigned int)-1) {
1406 vshError(ctl
, "%s", _("Domain is already active"));
1411 if (vshCommandOptBool(cmd
, "paused"))
1412 flags
|= VIR_DOMAIN_START_PAUSED
;
1414 /* Prefer older API unless we have to pass a flag. */
1415 if ((flags
? virDomainCreateWithFlags(dom
, flags
)
1416 : virDomainCreate(dom
)) == 0) {
1417 vshPrint(ctl
, _("Domain %s started\n"),
1418 virDomainGetName(dom
));
1421 cmdRunConsole(ctl
, dom
, NULL
);
1424 vshError(ctl
, _("Failed to start domain %s"), virDomainGetName(dom
));
1434 static const vshCmdInfo info_save
[] = {
1435 {"help", N_("save a domain state to a file")},
1436 {"desc", N_("Save a running domain.")},
1440 static const vshCmdOptDef opts_save
[] = {
1441 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
1442 {"file", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("where to save the data")},
1447 cmdSave(vshControl
*ctl
, const vshCmd
*cmd
)
1454 if (!vshConnectionUsability(ctl
, ctl
->conn
))
1457 if (!(to
= vshCommandOptString(cmd
, "file", NULL
)))
1460 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, &name
)))
1463 if (virDomainSave(dom
, to
) == 0) {
1464 vshPrint(ctl
, _("Domain %s saved to %s\n"), name
, to
);
1466 vshError(ctl
, _("Failed to save domain %s to %s"), name
, to
);
1475 * "managedsave" command
1477 static const vshCmdInfo info_managedsave
[] = {
1478 {"help", N_("managed save of a domain state")},
1479 {"desc", N_("Save and destroy a running domain, so it can be restarted from\n"
1480 " the same state at a later time. When the virsh 'start'\n"
1481 " command is next run for the domain, it will automatically\n"
1482 " be started from this saved state.")},
1486 static const vshCmdOptDef opts_managedsave
[] = {
1487 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
1492 cmdManagedSave(vshControl
*ctl
, const vshCmd
*cmd
)
1498 if (!vshConnectionUsability(ctl
, ctl
->conn
))
1501 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, &name
)))
1504 if (virDomainManagedSave(dom
, 0) == 0) {
1505 vshPrint(ctl
, _("Domain %s state saved by libvirt\n"), name
);
1507 vshError(ctl
, _("Failed to save domain %s state"), name
);
1516 * "managedsave-remove" command
1518 static const vshCmdInfo info_managedsaveremove
[] = {
1519 {"help", N_("Remove managed save of a domain")},
1520 {"desc", N_("Remove an existing managed save state file from a domain")},
1524 static const vshCmdOptDef opts_managedsaveremove
[] = {
1525 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
1530 cmdManagedSaveRemove(vshControl
*ctl
, const vshCmd
*cmd
)
1537 if (!vshConnectionUsability(ctl
, ctl
->conn
))
1540 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, &name
)))
1543 hassave
= virDomainHasManagedSaveImage(dom
, 0);
1545 vshError(ctl
, "%s", _("Failed to check for domain managed save image"));
1550 if (virDomainManagedSaveRemove(dom
, 0) < 0) {
1551 vshError(ctl
, _("Failed to remove managed save image for domain %s"),
1556 vshPrint(ctl
, _("Removed managedsave image for domain %s"), name
);
1559 vshPrint(ctl
, _("Domain %s has no manage save image; removal skipped"),
1570 * "schedinfo" command
1572 static const vshCmdInfo info_schedinfo
[] = {
1573 {"help", N_("show/set scheduler parameters")},
1574 {"desc", N_("Show/Set scheduler parameters.")},
1578 static const vshCmdOptDef opts_schedinfo
[] = {
1579 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
1580 {"set", VSH_OT_STRING
, VSH_OFLAG_NONE
, N_("parameter=value")},
1581 {"weight", VSH_OT_INT
, VSH_OFLAG_NONE
, N_("weight for XEN_CREDIT")},
1582 {"cap", VSH_OT_INT
, VSH_OFLAG_NONE
, N_("cap for XEN_CREDIT")},
1587 cmdSchedInfoUpdate(vshControl
*ctl
, const vshCmd
*cmd
,
1588 virSchedParameterPtr param
)
1593 /* Legacy 'weight' parameter */
1594 if (STREQ(param
->field
, "weight") &&
1595 param
->type
== VIR_DOMAIN_SCHED_FIELD_UINT
&&
1596 vshCommandOptBool(cmd
, "weight")) {
1598 val
= vshCommandOptInt(cmd
, "weight", &found
);
1600 vshError(ctl
, "%s", _("Invalid value of weight"));
1603 param
->value
.ui
= val
;
1608 /* Legacy 'cap' parameter */
1609 if (STREQ(param
->field
, "cap") &&
1610 param
->type
== VIR_DOMAIN_SCHED_FIELD_UINT
&&
1611 vshCommandOptBool(cmd
, "cap")) {
1613 val
= vshCommandOptInt(cmd
, "cap", &found
);
1615 vshError(ctl
, "%s", _("Invalid value of cap"));
1618 param
->value
.ui
= val
;
1623 if ((data
= vshCommandOptString(cmd
, "set", NULL
))) {
1624 char *val
= strchr(data
, '=');
1627 vshError(ctl
, "%s", _("Invalid syntax for --set, expecting name=value"));
1631 match
= STREQ(data
, param
->field
);
1638 switch (param
->type
) {
1639 case VIR_DOMAIN_SCHED_FIELD_INT
:
1640 if (virStrToLong_i(val
, NULL
, 10, ¶m
->value
.i
) < 0) {
1642 _("Invalid value for parameter, expecting an int"));
1646 case VIR_DOMAIN_SCHED_FIELD_UINT
:
1647 if (virStrToLong_ui(val
, NULL
, 10, ¶m
->value
.ui
) < 0) {
1649 _("Invalid value for parameter, expecting an unsigned int"));
1653 case VIR_DOMAIN_SCHED_FIELD_LLONG
:
1654 if (virStrToLong_ll(val
, NULL
, 10, ¶m
->value
.l
) < 0) {
1656 _("Invalid value for parameter, expecting a long long"));
1660 case VIR_DOMAIN_SCHED_FIELD_ULLONG
:
1661 if (virStrToLong_ull(val
, NULL
, 10, ¶m
->value
.ul
) < 0) {
1663 _("Invalid value for parameter, expecting an unsigned long long"));
1667 case VIR_DOMAIN_SCHED_FIELD_DOUBLE
:
1668 if (virStrToDouble(val
, NULL
, ¶m
->value
.d
) < 0) {
1669 vshError(ctl
, "%s", _("Invalid value for parameter, expecting a double"));
1673 case VIR_DOMAIN_SCHED_FIELD_BOOLEAN
:
1674 param
->value
.b
= STREQ(val
, "0") ? 0 : 1;
1684 cmdSchedinfo(vshControl
*ctl
, const vshCmd
*cmd
)
1686 char *schedulertype
;
1688 virSchedParameterPtr params
= NULL
;
1692 int ret_val
= FALSE
;
1694 if (!vshConnectionUsability(ctl
, ctl
->conn
))
1697 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, NULL
)))
1700 /* Print SchedulerType */
1701 schedulertype
= virDomainGetSchedulerType(dom
, &nparams
);
1702 if (schedulertype
!= NULL
){
1703 vshPrint(ctl
, "%-15s: %s\n", _("Scheduler"),
1705 VIR_FREE(schedulertype
);
1707 vshPrint(ctl
, "%-15s: %s\n", _("Scheduler"), _("Unknown"));
1712 params
= vshMalloc(ctl
, sizeof(virSchedParameter
)* nparams
);
1714 memset(params
, 0, sizeof(virSchedParameter
)* nparams
);
1715 ret
= virDomainGetSchedulerParameters(dom
, params
, &nparams
);
1719 /* See if any params are being set */
1720 for (i
= 0; i
< nparams
; i
++){
1721 ret
= cmdSchedInfoUpdate(ctl
, cmd
, &(params
[i
]));
1729 /* Update parameters & refresh data */
1731 ret
= virDomainSetSchedulerParameters(dom
, params
, nparams
);
1735 ret
= virDomainGetSchedulerParameters(dom
, params
, &nparams
);
1739 /* See if we've tried to --set var=val. If so, the fact that
1740 we reach this point (with update == 0) means that "var" did
1741 not match any of the settable parameters. Report the error. */
1742 char *var_value_pair
= vshCommandOptString(cmd
, "set", NULL
);
1743 if (var_value_pair
) {
1744 vshError(ctl
, _("invalid scheduler option: %s"),
1751 for (i
= 0; i
< nparams
; i
++){
1752 switch (params
[i
].type
) {
1753 case VIR_DOMAIN_SCHED_FIELD_INT
:
1754 vshPrint(ctl
, "%-15s: %d\n", params
[i
].field
, params
[i
].value
.i
);
1756 case VIR_DOMAIN_SCHED_FIELD_UINT
:
1757 vshPrint(ctl
, "%-15s: %u\n", params
[i
].field
, params
[i
].value
.ui
);
1759 case VIR_DOMAIN_SCHED_FIELD_LLONG
:
1760 vshPrint(ctl
, "%-15s: %lld\n", params
[i
].field
, params
[i
].value
.l
);
1762 case VIR_DOMAIN_SCHED_FIELD_ULLONG
:
1763 vshPrint(ctl
, "%-15s: %llu\n", params
[i
].field
, params
[i
].value
.ul
);
1765 case VIR_DOMAIN_SCHED_FIELD_DOUBLE
:
1766 vshPrint(ctl
, "%-15s: %f\n", params
[i
].field
, params
[i
].value
.d
);
1768 case VIR_DOMAIN_SCHED_FIELD_BOOLEAN
:
1769 vshPrint(ctl
, "%-15s: %d\n", params
[i
].field
, params
[i
].value
.b
);
1772 vshPrint(ctl
, "not implemented scheduler parameter type\n");
1786 static const vshCmdInfo info_restore
[] = {
1787 {"help", N_("restore a domain from a saved state in a file")},
1788 {"desc", N_("Restore a domain.")},
1792 static const vshCmdOptDef opts_restore
[] = {
1793 {"file", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("the state to restore")},
1798 cmdRestore(vshControl
*ctl
, const vshCmd
*cmd
)
1804 if (!vshConnectionUsability(ctl
, ctl
->conn
))
1807 from
= vshCommandOptString(cmd
, "file", &found
);
1811 if (virDomainRestore(ctl
->conn
, from
) == 0) {
1812 vshPrint(ctl
, _("Domain restored from %s\n"), from
);
1814 vshError(ctl
, _("Failed to restore domain from %s"), from
);
1823 static const vshCmdInfo info_dump
[] = {
1824 {"help", N_("dump the core of a domain to a file for analysis")},
1825 {"desc", N_("Core dump a domain.")},
1829 static const vshCmdOptDef opts_dump
[] = {
1830 {"live", VSH_OT_BOOL
, 0, N_("perform a live core dump if supported")},
1831 {"crash", VSH_OT_BOOL
, 0, N_("crash the domain after core dump")},
1832 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
1833 {"file", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("where to dump the core")},
1838 cmdDump(vshControl
*ctl
, const vshCmd
*cmd
)
1846 if (!vshConnectionUsability(ctl
, ctl
->conn
))
1849 if (!(to
= vshCommandOptString(cmd
, "file", NULL
)))
1852 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, &name
)))
1855 if (vshCommandOptBool (cmd
, "live"))
1856 flags
|= VIR_DUMP_LIVE
;
1857 if (vshCommandOptBool (cmd
, "crash"))
1858 flags
|= VIR_DUMP_CRASH
;
1860 if (virDomainCoreDump(dom
, to
, flags
) == 0) {
1861 vshPrint(ctl
, _("Domain %s dumped to %s\n"), name
, to
);
1863 vshError(ctl
, _("Failed to core dump domain %s to %s"), name
, to
);
1874 static const vshCmdInfo info_resume
[] = {
1875 {"help", N_("resume a domain")},
1876 {"desc", N_("Resume a previously suspended domain.")},
1880 static const vshCmdOptDef opts_resume
[] = {
1881 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
1886 cmdResume(vshControl
*ctl
, const vshCmd
*cmd
)
1892 if (!vshConnectionUsability(ctl
, ctl
->conn
))
1895 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, &name
)))
1898 if (virDomainResume(dom
) == 0) {
1899 vshPrint(ctl
, _("Domain %s resumed\n"), name
);
1901 vshError(ctl
, _("Failed to resume domain %s"), name
);
1910 * "shutdown" command
1912 static const vshCmdInfo info_shutdown
[] = {
1913 {"help", N_("gracefully shutdown a domain")},
1914 {"desc", N_("Run shutdown in the target domain.")},
1918 static const vshCmdOptDef opts_shutdown
[] = {
1919 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
1924 cmdShutdown(vshControl
*ctl
, const vshCmd
*cmd
)
1930 if (!vshConnectionUsability(ctl
, ctl
->conn
))
1933 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, &name
)))
1936 if (virDomainShutdown(dom
) == 0) {
1937 vshPrint(ctl
, _("Domain %s is being shutdown\n"), name
);
1939 vshError(ctl
, _("Failed to shutdown domain %s"), name
);
1950 static const vshCmdInfo info_reboot
[] = {
1951 {"help", N_("reboot a domain")},
1952 {"desc", N_("Run a reboot command in the target domain.")},
1956 static const vshCmdOptDef opts_reboot
[] = {
1957 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
1962 cmdReboot(vshControl
*ctl
, const vshCmd
*cmd
)
1968 if (!vshConnectionUsability(ctl
, ctl
->conn
))
1971 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, &name
)))
1974 if (virDomainReboot(dom
, 0) == 0) {
1975 vshPrint(ctl
, _("Domain %s is being rebooted\n"), name
);
1977 vshError(ctl
, _("Failed to reboot domain %s"), name
);
1988 static const vshCmdInfo info_destroy
[] = {
1989 {"help", N_("destroy a domain")},
1990 {"desc", N_("Destroy a given domain.")},
1994 static const vshCmdOptDef opts_destroy
[] = {
1995 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
2000 cmdDestroy(vshControl
*ctl
, const vshCmd
*cmd
)
2006 if (!vshConnectionUsability(ctl
, ctl
->conn
))
2009 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, &name
)))
2012 if (virDomainDestroy(dom
) == 0) {
2013 vshPrint(ctl
, _("Domain %s destroyed\n"), name
);
2015 vshError(ctl
, _("Failed to destroy domain %s"), name
);
2026 static const vshCmdInfo info_dominfo
[] = {
2027 {"help", N_("domain information")},
2028 {"desc", N_("Returns basic information about the domain.")},
2032 static const vshCmdOptDef opts_dominfo
[] = {
2033 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
2038 cmdDominfo(vshControl
*ctl
, const vshCmd
*cmd
)
2042 virSecurityModel secmodel
;
2043 virSecurityLabel seclabel
;
2045 int ret
= TRUE
, autostart
;
2047 char *str
, uuid
[VIR_UUID_STRING_BUFLEN
];
2049 if (!vshConnectionUsability(ctl
, ctl
->conn
))
2052 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, NULL
)))
2055 id
= virDomainGetID(dom
);
2056 if (id
== ((unsigned int)-1))
2057 vshPrint(ctl
, "%-15s %s\n", _("Id:"), "-");
2059 vshPrint(ctl
, "%-15s %d\n", _("Id:"), id
);
2060 vshPrint(ctl
, "%-15s %s\n", _("Name:"), virDomainGetName(dom
));
2062 if (virDomainGetUUIDString(dom
, &uuid
[0])==0)
2063 vshPrint(ctl
, "%-15s %s\n", _("UUID:"), uuid
);
2065 if ((str
= virDomainGetOSType(dom
))) {
2066 vshPrint(ctl
, "%-15s %s\n", _("OS Type:"), str
);
2070 if (virDomainGetInfo(dom
, &info
) == 0) {
2071 vshPrint(ctl
, "%-15s %s\n", _("State:"),
2072 _(vshDomainStateToString(info
.state
)));
2074 vshPrint(ctl
, "%-15s %d\n", _("CPU(s):"), info
.nrVirtCpu
);
2076 if (info
.cpuTime
!= 0) {
2077 double cpuUsed
= info
.cpuTime
;
2079 cpuUsed
/= 1000000000.0;
2081 vshPrint(ctl
, "%-15s %.1lfs\n", _("CPU time:"), cpuUsed
);
2084 if (info
.maxMem
!= UINT_MAX
)
2085 vshPrint(ctl
, "%-15s %lu kB\n", _("Max memory:"),
2088 vshPrint(ctl
, "%-15s %s\n", _("Max memory:"),
2091 vshPrint(ctl
, "%-15s %lu kB\n", _("Used memory:"),
2098 /* Check and display whether the domain is persistent or not */
2099 persistent
= virDomainIsPersistent(dom
);
2100 vshDebug(ctl
, 5, "Domain persistent flag value: %d\n", persistent
);
2102 vshPrint(ctl
, "%-15s %s\n", _("Persistent:"), _("unknown"));
2104 vshPrint(ctl
, "%-15s %s\n", _("Persistent:"), persistent
? _("yes") : _("no"));
2106 /* Check and display whether the domain autostarts or not */
2107 if (!virDomainGetAutostart(dom
, &autostart
)) {
2108 vshPrint(ctl
, "%-15s %s\n", _("Autostart:"),
2109 autostart
? _("enable") : _("disable") );
2112 /* Security model and label information */
2113 memset(&secmodel
, 0, sizeof secmodel
);
2114 if (virNodeGetSecurityModel(ctl
->conn
, &secmodel
) == -1) {
2115 if (last_error
->code
!= VIR_ERR_NO_SUPPORT
) {
2120 /* Only print something if a security model is active */
2121 if (secmodel
.model
[0] != '\0') {
2122 vshPrint(ctl
, "%-15s %s\n", _("Security model:"), secmodel
.model
);
2123 vshPrint(ctl
, "%-15s %s\n", _("Security DOI:"), secmodel
.doi
);
2125 /* Security labels are only valid for active domains */
2126 memset(&seclabel
, 0, sizeof seclabel
);
2127 if (virDomainGetSecurityLabel(dom
, &seclabel
) == -1) {
2131 if (seclabel
.label
[0] != '\0')
2132 vshPrint(ctl
, "%-15s %s (%s)\n", _("Security label:"),
2133 seclabel
.label
, seclabel
.enforcing
? "enforcing" : "permissive");
2142 * "domjobinfo" command
2144 static const vshCmdInfo info_domjobinfo
[] = {
2145 {"help", N_("domain job information")},
2146 {"desc", N_("Returns information about jobs running on a domain.")},
2150 static const vshCmdOptDef opts_domjobinfo
[] = {
2151 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
2157 cmdDomjobinfo(vshControl
*ctl
, const vshCmd
*cmd
)
2159 virDomainJobInfo info
;
2163 if (!vshConnectionUsability(ctl
, ctl
->conn
))
2166 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, NULL
)))
2169 if (virDomainGetJobInfo(dom
, &info
) == 0) {
2173 vshPrint(ctl
, "%-17s ", _("Job type:"));
2174 switch (info
.type
) {
2175 case VIR_DOMAIN_JOB_BOUNDED
:
2176 vshPrint(ctl
, "%-12s\n", _("Bounded"));
2179 case VIR_DOMAIN_JOB_UNBOUNDED
:
2180 vshPrint(ctl
, "%-12s\n", _("Unbounded"));
2183 case VIR_DOMAIN_JOB_NONE
:
2185 vshPrint(ctl
, "%-12s\n", _("None"));
2189 vshPrint(ctl
, "%-17s %-12llu ms\n", _("Time elapsed:"), info
.timeElapsed
);
2190 if (info
.type
== VIR_DOMAIN_JOB_BOUNDED
)
2191 vshPrint(ctl
, "%-17s %-12llu ms\n", _("Time remaining:"), info
.timeRemaining
);
2192 if (info
.dataTotal
|| info
.dataRemaining
|| info
.dataProcessed
) {
2193 val
= prettyCapacity(info
.dataProcessed
, &unit
);
2194 vshPrint(ctl
, "%-17s %-.3lf %s\n", _("Data processed:"), val
, unit
);
2195 val
= prettyCapacity(info
.dataRemaining
, &unit
);
2196 vshPrint(ctl
, "%-17s %-.3lf %s\n", _("Data remaining:"), val
, unit
);
2197 val
= prettyCapacity(info
.dataTotal
, &unit
);
2198 vshPrint(ctl
, "%-17s %-.3lf %s\n", _("Data total:"), val
, unit
);
2200 if (info
.memTotal
|| info
.memRemaining
|| info
.memProcessed
) {
2201 val
= prettyCapacity(info
.memProcessed
, &unit
);
2202 vshPrint(ctl
, "%-17s %-.3lf %s\n", _("Memory processed:"), val
, unit
);
2203 val
= prettyCapacity(info
.memRemaining
, &unit
);
2204 vshPrint(ctl
, "%-17s %-.3lf %s\n", _("Memory remaining:"), val
, unit
);
2205 val
= prettyCapacity(info
.memTotal
, &unit
);
2206 vshPrint(ctl
, "%-17s %-.3lf %s\n", _("Memory total:"), val
, unit
);
2208 if (info
.fileTotal
|| info
.fileRemaining
|| info
.fileProcessed
) {
2209 val
= prettyCapacity(info
.fileProcessed
, &unit
);
2210 vshPrint(ctl
, "%-17s %-.3lf %s\n", _("File processed:"), val
, unit
);
2211 val
= prettyCapacity(info
.fileRemaining
, &unit
);
2212 vshPrint(ctl
, "%-17s %-.3lf %s\n", _("File remaining:"), val
, unit
);
2213 val
= prettyCapacity(info
.fileTotal
, &unit
);
2214 vshPrint(ctl
, "%-17s %-.3lf %s\n", _("File total:"), val
, unit
);
2225 * "domjobabort" command
2227 static const vshCmdInfo info_domjobabort
[] = {
2228 {"help", N_("abort active domain job")},
2229 {"desc", N_("Aborts the currently running domain job")},
2233 static const vshCmdOptDef opts_domjobabort
[] = {
2234 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
2239 cmdDomjobabort(vshControl
*ctl
, const vshCmd
*cmd
)
2244 if (!vshConnectionUsability(ctl
, ctl
->conn
))
2247 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, NULL
)))
2250 if (virDomainAbortJob(dom
) < 0)
2258 * "freecell" command
2260 static const vshCmdInfo info_freecell
[] = {
2261 {"help", N_("NUMA free memory")},
2262 {"desc", N_("display available free memory for the NUMA cell.")},
2266 static const vshCmdOptDef opts_freecell
[] = {
2267 {"cellno", VSH_OT_INT
, 0, N_("NUMA cell number")},
2272 cmdFreecell(vshControl
*ctl
, const vshCmd
*cmd
)
2275 int cell
, cell_given
;
2276 unsigned long long memory
;
2278 if (!vshConnectionUsability(ctl
, ctl
->conn
))
2281 cell
= vshCommandOptInt(cmd
, "cellno", &cell_given
);
2283 memory
= virNodeGetFreeMemory(ctl
->conn
);
2287 ret
= virNodeGetCellsFreeMemory(ctl
->conn
, &memory
, cell
, 1);
2293 vshPrint(ctl
, "%s: %llu kB\n", _("Total"), (memory
/1024));
2295 vshPrint(ctl
, "%d: %llu kB\n", cell
, (memory
/1024));
2301 * "maxvcpus" command
2303 static const vshCmdInfo info_maxvcpus
[] = {
2304 {"help", N_("connection vcpu maximum")},
2305 {"desc", N_("Show maximum number of virtual CPUs for guests on this connection.")},
2309 static const vshCmdOptDef opts_maxvcpus
[] = {
2310 {"type", VSH_OT_STRING
, 0, N_("domain type")},
2315 cmdMaxvcpus(vshControl
*ctl
, const vshCmd
*cmd
)
2320 type
= vshCommandOptString(cmd
, "type", NULL
);
2322 if (!vshConnectionUsability(ctl
, ctl
->conn
))
2325 vcpus
= virConnectGetMaxVcpus(ctl
->conn
, type
);
2328 vshPrint(ctl
, "%d\n", vcpus
);
2334 * "vcpucount" command
2336 static const vshCmdInfo info_vcpucount
[] = {
2337 {"help", N_("domain vcpu counts")},
2338 {"desc", N_("Returns the number of virtual CPUs used by the domain.")},
2342 static const vshCmdOptDef opts_vcpucount
[] = {
2343 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
2344 {"maximum", VSH_OT_BOOL
, 0, N_("get maximum cap on vcpus")},
2345 {"current", VSH_OT_BOOL
, 0, N_("get current vcpu usage")},
2346 {"config", VSH_OT_BOOL
, 0, N_("get value to be used on next boot")},
2347 {"live", VSH_OT_BOOL
, 0, N_("get value from running domain")},
2352 cmdVcpucount(vshControl
*ctl
, const vshCmd
*cmd
)
2356 int maximum
= vshCommandOptBool(cmd
, "maximum");
2357 int current
= vshCommandOptBool(cmd
, "current");
2358 int config
= vshCommandOptBool(cmd
, "config");
2359 int live
= vshCommandOptBool(cmd
, "live");
2360 bool all
= maximum
+ current
+ config
+ live
== 0;
2363 if (maximum
&& current
) {
2365 _("--maximum and --current cannot both be specified"));
2368 if (config
&& live
) {
2370 _("--config and --live cannot both be specified"));
2373 /* We want one of each pair of mutually exclusive options; that
2374 * is, use of flags requires exactly two options. */
2375 if (maximum
+ current
+ config
+ live
== 1) {
2377 _("when using --%s, either --%s or --%s must be specified"),
2378 (maximum
? "maximum" : current
? "current"
2379 : config
? "config" : "live"),
2380 maximum
+ current
? "config" : "maximum",
2381 maximum
+ current
? "live" : "current");
2385 if (!vshConnectionUsability(ctl
, ctl
->conn
))
2388 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, NULL
)))
2391 /* In all cases, try the new API first; if it fails because we are
2392 * talking to an older client, try a fallback API before giving
2394 if (all
|| (maximum
&& config
)) {
2395 count
= virDomainGetVcpusFlags(dom
, (VIR_DOMAIN_VCPU_MAXIMUM
|
2396 VIR_DOMAIN_VCPU_CONFIG
));
2397 if (count
< 0 && (last_error
->code
== VIR_ERR_NO_SUPPORT
2398 || last_error
->code
== VIR_ERR_INVALID_ARG
)) {
2400 char *xml
= virDomainGetXMLDesc(dom
, VIR_DOMAIN_XML_INACTIVE
);
2401 if (xml
&& (tmp
= strstr(xml
, "<vcpu"))) {
2402 tmp
= strchr(tmp
, '>');
2403 if (!tmp
|| virStrToLong_i(tmp
+ 1, &tmp
, 10, &count
) < 0)
2410 virshReportError(ctl
);
2413 vshPrint(ctl
, "%-12s %-12s %3d\n", _("maximum"), _("config"),
2416 vshPrint(ctl
, "%d\n", count
);
2418 virFreeError(last_error
);
2422 if (all
|| (maximum
&& live
)) {
2423 count
= virDomainGetVcpusFlags(dom
, (VIR_DOMAIN_VCPU_MAXIMUM
|
2424 VIR_DOMAIN_VCPU_LIVE
));
2425 if (count
< 0 && (last_error
->code
== VIR_ERR_NO_SUPPORT
2426 || last_error
->code
== VIR_ERR_INVALID_ARG
)) {
2427 count
= virDomainGetMaxVcpus(dom
);
2431 virshReportError(ctl
);
2434 vshPrint(ctl
, "%-12s %-12s %3d\n", _("maximum"), _("live"),
2437 vshPrint(ctl
, "%d\n", count
);
2439 virFreeError(last_error
);
2443 if (all
|| (current
&& config
)) {
2444 count
= virDomainGetVcpusFlags(dom
, VIR_DOMAIN_VCPU_CONFIG
);
2445 if (count
< 0 && (last_error
->code
== VIR_ERR_NO_SUPPORT
2446 || last_error
->code
== VIR_ERR_INVALID_ARG
)) {
2448 char *xml
= virDomainGetXMLDesc(dom
, VIR_DOMAIN_XML_INACTIVE
);
2449 if (xml
&& (tmp
= strstr(xml
, "<vcpu"))) {
2450 end
= strchr(tmp
, '>');
2453 tmp
= strstr(tmp
, "current=");
2457 tmp
+= strlen("current=");
2458 tmp
+= *tmp
== '\'' || *tmp
== '"';
2461 if (!tmp
|| virStrToLong_i(tmp
, &tmp
, 10, &count
) < 0)
2468 virshReportError(ctl
);
2471 vshPrint(ctl
, "%-12s %-12s %3d\n", _("current"), _("config"),
2474 vshPrint(ctl
, "%d\n", count
);
2476 virFreeError(last_error
);
2480 if (all
|| (current
&& live
)) {
2481 count
= virDomainGetVcpusFlags(dom
, VIR_DOMAIN_VCPU_LIVE
);
2482 if (count
< 0 && (last_error
->code
== VIR_ERR_NO_SUPPORT
2483 || last_error
->code
== VIR_ERR_INVALID_ARG
)) {
2485 if (virDomainGetInfo(dom
, &info
) == 0)
2486 count
= info
.nrVirtCpu
;
2490 virshReportError(ctl
);
2493 vshPrint(ctl
, "%-12s %-12s %3d\n", _("current"), _("live"),
2496 vshPrint(ctl
, "%d\n", count
);
2498 virFreeError(last_error
);
2507 * "vcpuinfo" command
2509 static const vshCmdInfo info_vcpuinfo
[] = {
2510 {"help", N_("detailed domain vcpu information")},
2511 {"desc", N_("Returns basic information about the domain virtual CPUs.")},
2515 static const vshCmdOptDef opts_vcpuinfo
[] = {
2516 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
2521 cmdVcpuinfo(vshControl
*ctl
, const vshCmd
*cmd
)
2525 virNodeInfo nodeinfo
;
2526 virVcpuInfoPtr cpuinfo
;
2527 unsigned char *cpumap
;
2532 if (!vshConnectionUsability(ctl
, ctl
->conn
))
2535 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, NULL
)))
2538 if (virNodeGetInfo(ctl
->conn
, &nodeinfo
) != 0) {
2543 if (virDomainGetInfo(dom
, &info
) != 0) {
2548 cpuinfo
= vshMalloc(ctl
, sizeof(virVcpuInfo
)*info
.nrVirtCpu
);
2549 cpumaplen
= VIR_CPU_MAPLEN(VIR_NODEINFO_MAXCPUS(nodeinfo
));
2550 cpumap
= vshMalloc(ctl
, info
.nrVirtCpu
* cpumaplen
);
2552 if ((ncpus
= virDomainGetVcpus(dom
,
2553 cpuinfo
, info
.nrVirtCpu
,
2554 cpumap
, cpumaplen
)) >= 0) {
2556 for (n
= 0 ; n
< ncpus
; n
++) {
2558 vshPrint(ctl
, "%-15s %d\n", _("VCPU:"), n
);
2559 vshPrint(ctl
, "%-15s %d\n", _("CPU:"), cpuinfo
[n
].cpu
);
2560 vshPrint(ctl
, "%-15s %s\n", _("State:"),
2561 _(vshDomainVcpuStateToString(cpuinfo
[n
].state
)));
2562 if (cpuinfo
[n
].cpuTime
!= 0) {
2563 double cpuUsed
= cpuinfo
[n
].cpuTime
;
2565 cpuUsed
/= 1000000000.0;
2567 vshPrint(ctl
, "%-15s %.1lfs\n", _("CPU time:"), cpuUsed
);
2569 vshPrint(ctl
, "%-15s ", _("CPU Affinity:"));
2570 for (m
= 0 ; m
< VIR_NODEINFO_MAXCPUS(nodeinfo
) ; m
++) {
2571 vshPrint(ctl
, "%c", VIR_CPU_USABLE(cpumap
, cpumaplen
, n
, m
) ? 'y' : '-');
2573 vshPrint(ctl
, "\n");
2574 if (n
< (ncpus
- 1)) {
2575 vshPrint(ctl
, "\n");
2579 if (info
.state
== VIR_DOMAIN_SHUTOFF
) {
2581 _("Domain shut off, virtual CPUs not present."));
2595 static const vshCmdInfo info_vcpupin
[] = {
2596 {"help", N_("control domain vcpu affinity")},
2597 {"desc", N_("Pin domain VCPUs to host physical CPUs.")},
2601 static const vshCmdOptDef opts_vcpupin
[] = {
2602 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
2603 {"vcpu", VSH_OT_INT
, VSH_OFLAG_REQ
, N_("vcpu number")},
2604 {"cpulist", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("host cpu number(s) (comma separated)")},
2609 cmdVcpupin(vshControl
*ctl
, const vshCmd
*cmd
)
2613 virNodeInfo nodeinfo
;
2618 unsigned char *cpumap
;
2621 enum { expect_num
, expect_num_or_comma
} state
;
2623 if (!vshConnectionUsability(ctl
, ctl
->conn
))
2626 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, NULL
)))
2629 vcpu
= vshCommandOptInt(cmd
, "vcpu", &vcpufound
);
2631 vshError(ctl
, "%s", _("vcpupin: Invalid or missing vCPU number."));
2636 if (!(cpulist
= vshCommandOptString(cmd
, "cpulist", NULL
))) {
2641 if (virNodeGetInfo(ctl
->conn
, &nodeinfo
) != 0) {
2646 if (virDomainGetInfo(dom
, &info
) != 0) {
2647 vshError(ctl
, "%s", _("vcpupin: failed to get domain informations."));
2652 if (vcpu
>= info
.nrVirtCpu
) {
2653 vshError(ctl
, "%s", _("vcpupin: Invalid vCPU number."));
2658 /* Check that the cpulist parameter is a comma-separated list of
2659 * numbers and give an intelligent error message if not.
2661 if (cpulist
[0] == '\0') {
2662 vshError(ctl
, "%s", _("cpulist: Invalid format. Empty string."));
2663 virDomainFree (dom
);
2668 for (i
= 0; cpulist
[i
]; i
++) {
2671 if (!c_isdigit (cpulist
[i
])) {
2672 vshError(ctl
, _("cpulist: %s: Invalid format. Expecting "
2673 "digit at position %d (near '%c')."),
2674 cpulist
, i
, cpulist
[i
]);
2675 virDomainFree (dom
);
2678 state
= expect_num_or_comma
;
2680 case expect_num_or_comma
:
2681 if (cpulist
[i
] == ',')
2683 else if (!c_isdigit (cpulist
[i
])) {
2684 vshError(ctl
, _("cpulist: %s: Invalid format. Expecting "
2685 "digit or comma at position %d (near '%c')."),
2686 cpulist
, i
, cpulist
[i
]);
2687 virDomainFree (dom
);
2692 if (state
== expect_num
) {
2693 vshError(ctl
, _("cpulist: %s: Invalid format. Trailing comma "
2696 virDomainFree (dom
);
2700 cpumaplen
= VIR_CPU_MAPLEN(VIR_NODEINFO_MAXCPUS(nodeinfo
));
2701 cpumap
= vshCalloc(ctl
, 1, cpumaplen
);
2704 unsigned int cpu
= atoi(cpulist
);
2706 if (cpu
< VIR_NODEINFO_MAXCPUS(nodeinfo
)) {
2707 VIR_USE_CPU(cpumap
, cpu
);
2709 vshError(ctl
, _("Physical CPU %d doesn't exist."), cpu
);
2714 cpulist
= strchr(cpulist
, ',');
2719 if (virDomainPinVcpu(dom
, vcpu
, cpumap
, cpumaplen
) != 0) {
2729 * "setvcpus" command
2731 static const vshCmdInfo info_setvcpus
[] = {
2732 {"help", N_("change number of virtual CPUs")},
2733 {"desc", N_("Change the number of virtual CPUs in the guest domain.")},
2737 static const vshCmdOptDef opts_setvcpus
[] = {
2738 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
2739 {"count", VSH_OT_INT
, VSH_OFLAG_REQ
, N_("number of virtual CPUs")},
2740 {"maximum", VSH_OT_BOOL
, 0, N_("set maximum limit on next boot")},
2741 {"config", VSH_OT_BOOL
, 0, N_("affect next boot")},
2742 {"live", VSH_OT_BOOL
, 0, N_("affect running domain")},
2747 cmdSetvcpus(vshControl
*ctl
, const vshCmd
*cmd
)
2752 int maximum
= vshCommandOptBool(cmd
, "maximum");
2753 int config
= vshCommandOptBool(cmd
, "config");
2754 int live
= vshCommandOptBool(cmd
, "live");
2755 int flags
= ((maximum
? VIR_DOMAIN_VCPU_MAXIMUM
: 0) |
2756 (config
? VIR_DOMAIN_VCPU_CONFIG
: 0) |
2757 (live
? VIR_DOMAIN_VCPU_LIVE
: 0));
2759 if (!vshConnectionUsability(ctl
, ctl
->conn
))
2762 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, NULL
)))
2765 count
= vshCommandOptInt(cmd
, "count", &count
);
2768 if (virDomainSetVcpus(dom
, count
) != 0) {
2772 if (virDomainSetVcpusFlags(dom
, count
, flags
) < 0) {
2782 * "setmemory" command
2784 static const vshCmdInfo info_setmem
[] = {
2785 {"help", N_("change memory allocation")},
2786 {"desc", N_("Change the current memory allocation in the guest domain.")},
2790 static const vshCmdOptDef opts_setmem
[] = {
2791 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
2792 {"kilobytes", VSH_OT_INT
, VSH_OFLAG_REQ
, N_("number of kilobytes of memory")},
2797 cmdSetmem(vshControl
*ctl
, const vshCmd
*cmd
)
2801 unsigned long kilobytes
;
2804 if (!vshConnectionUsability(ctl
, ctl
->conn
))
2807 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, NULL
)))
2810 kilobytes
= vshCommandOptUL(cmd
, "kilobytes", NULL
);
2811 if (kilobytes
<= 0) {
2813 vshError(ctl
, _("Invalid value of %lu for memory size"), kilobytes
);
2817 if (virDomainGetInfo(dom
, &info
) != 0) {
2819 vshError(ctl
, "%s", _("Unable to verify MaxMemorySize"));
2823 if (kilobytes
> info
.maxMem
) {
2825 vshError(ctl
, _("Requested memory size %lu kb is larger than maximum of %lu kb"),
2826 kilobytes
, info
.maxMem
);
2830 if (virDomainSetMemory(dom
, kilobytes
) != 0) {
2839 * "setmaxmem" command
2841 static const vshCmdInfo info_setmaxmem
[] = {
2842 {"help", N_("change maximum memory limit")},
2843 {"desc", N_("Change the maximum memory allocation limit in the guest domain.")},
2847 static const vshCmdOptDef opts_setmaxmem
[] = {
2848 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
2849 {"kilobytes", VSH_OT_INT
, VSH_OFLAG_REQ
, N_("maximum memory limit in kilobytes")},
2854 cmdSetmaxmem(vshControl
*ctl
, const vshCmd
*cmd
)
2861 if (!vshConnectionUsability(ctl
, ctl
->conn
))
2864 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, NULL
)))
2867 kilobytes
= vshCommandOptInt(cmd
, "kilobytes", &kilobytes
);
2868 if (kilobytes
<= 0) {
2870 vshError(ctl
, _("Invalid value of %d for memory size"), kilobytes
);
2874 if (virDomainGetInfo(dom
, &info
) != 0) {
2876 vshError(ctl
, "%s", _("Unable to verify current MemorySize"));
2880 if (virDomainSetMaxMemory(dom
, kilobytes
) != 0) {
2881 vshError(ctl
, "%s", _("Unable to change MaxMemorySize"));
2886 if (kilobytes
< info
.memory
) {
2887 if (virDomainSetMemory(dom
, kilobytes
) != 0) {
2888 vshError(ctl
, "%s", _("Unable to shrink current MemorySize"));
2900 static const vshCmdInfo info_memtune
[] = {
2901 {"help", N_("Get/Set memory paramters")},
2902 {"desc", N_("Get/Set the current memory paramters for the guest domain.\n" \
2903 " To get the memory parameters use following command: \n\n" \
2904 " virsh # memtune <domain>")},
2908 static const vshCmdOptDef opts_memtune
[] = {
2909 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
2910 {"hard-limit", VSH_OT_INT
, VSH_OFLAG_NONE
,
2911 N_("Max memory in kilobytes")},
2912 {"soft-limit", VSH_OT_INT
, VSH_OFLAG_NONE
,
2913 N_("Memory during contention in kilobytes")},
2914 {"swap-hard-limit", VSH_OT_INT
, VSH_OFLAG_NONE
,
2915 N_("Max swap in kilobytes")},
2916 {"min-guarantee", VSH_OT_INT
, VSH_OFLAG_NONE
,
2917 N_("Min guaranteed memory in kilobytes")},
2922 cmdMemtune(vshControl
* ctl
, const vshCmd
* cmd
)
2925 long long hard_limit
, soft_limit
, swap_hard_limit
, min_guarantee
;
2928 virMemoryParameterPtr params
= NULL
, temp
= NULL
;
2931 if (!vshConnectionUsability(ctl
, ctl
->conn
))
2934 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, NULL
)))
2938 vshCommandOptLongLong(cmd
, "hard-limit", NULL
);
2943 vshCommandOptLongLong(cmd
, "soft-limit", NULL
);
2948 vshCommandOptLongLong(cmd
, "swap-hard-limit", NULL
);
2949 if (swap_hard_limit
)
2953 vshCommandOptLongLong(cmd
, "min-guarantee", NULL
);
2958 /* get the number of memory parameters */
2959 if (virDomainGetMemoryParameters(dom
, NULL
, &nparams
, 0) != 0) {
2961 _("Unable to get number of memory parameters"));
2966 /* nothing to output */
2971 /* now go get all the memory parameters */
2972 params
= vshCalloc(ctl
, nparams
, sizeof(*params
));
2973 if (virDomainGetMemoryParameters(dom
, params
, &nparams
, 0) != 0) {
2974 vshError(ctl
, "%s", _("Unable to get memory parameters"));
2978 for (i
= 0; i
< nparams
; i
++) {
2979 switch (params
[i
].type
) {
2980 case VIR_DOMAIN_MEMORY_PARAM_INT
:
2981 vshPrint(ctl
, "%-15s: %d\n", params
[i
].field
,
2984 case VIR_DOMAIN_MEMORY_PARAM_UINT
:
2985 vshPrint(ctl
, "%-15s: %u\n", params
[i
].field
,
2986 params
[i
].value
.ui
);
2988 case VIR_DOMAIN_MEMORY_PARAM_LLONG
:
2989 vshPrint(ctl
, "%-15s: %lld\n", params
[i
].field
,
2992 case VIR_DOMAIN_MEMORY_PARAM_ULLONG
:
2993 vshPrint(ctl
, "%-15s: %llu\n", params
[i
].field
,
2994 params
[i
].value
.ul
);
2996 case VIR_DOMAIN_MEMORY_PARAM_DOUBLE
:
2997 vshPrint(ctl
, "%-15s: %f\n", params
[i
].field
,
3000 case VIR_DOMAIN_MEMORY_PARAM_BOOLEAN
:
3001 vshPrint(ctl
, "%-15s: %d\n", params
[i
].field
,
3005 vshPrint(ctl
, "unimplemented memory parameter type\n");
3011 /* set the memory parameters */
3012 params
= vshCalloc(ctl
, nparams
, sizeof(*params
));
3014 for (i
= 0; i
< nparams
; i
++) {
3016 temp
->type
= VIR_DOMAIN_MEMORY_PARAM_ULLONG
;
3019 * Some magic here, this is used to fill the params structure with
3020 * the valid arguments passed, after filling the particular
3021 * argument we purposely make them 0, so on the next pass it goes
3022 * to the next valid argument and so on.
3025 temp
->value
.ul
= soft_limit
;
3026 strncpy(temp
->field
, VIR_DOMAIN_MEMORY_SOFT_LIMIT
,
3027 sizeof(temp
->field
));
3029 } else if (hard_limit
) {
3030 temp
->value
.ul
= hard_limit
;
3031 strncpy(temp
->field
, VIR_DOMAIN_MEMORY_HARD_LIMIT
,
3032 sizeof(temp
->field
));
3034 } else if (swap_hard_limit
) {
3035 temp
->value
.ul
= swap_hard_limit
;
3036 strncpy(temp
->field
, VIR_DOMAIN_MEMORY_SWAP_HARD_LIMIT
,
3037 sizeof(temp
->field
));
3038 swap_hard_limit
= 0;
3039 } else if (min_guarantee
) {
3040 temp
->value
.ul
= min_guarantee
;
3041 strncpy(temp
->field
, VIR_DOMAIN_MEMORY_MIN_GUARANTEE
,
3042 sizeof(temp
->field
));
3046 if (virDomainSetMemoryParameters(dom
, params
, nparams
, 0) != 0)
3047 vshError(ctl
, "%s", _("Unable to change memory parameters"));
3059 * "nodeinfo" command
3061 static const vshCmdInfo info_nodeinfo
[] = {
3062 {"help", N_("node information")},
3063 {"desc", N_("Returns basic information about the node.")},
3068 cmdNodeinfo(vshControl
*ctl
, const vshCmd
*cmd ATTRIBUTE_UNUSED
)
3072 if (!vshConnectionUsability(ctl
, ctl
->conn
))
3075 if (virNodeGetInfo(ctl
->conn
, &info
) < 0) {
3076 vshError(ctl
, "%s", _("failed to get node information"));
3079 vshPrint(ctl
, "%-20s %s\n", _("CPU model:"), info
.model
);
3080 vshPrint(ctl
, "%-20s %d\n", _("CPU(s):"), info
.cpus
);
3081 vshPrint(ctl
, "%-20s %d MHz\n", _("CPU frequency:"), info
.mhz
);
3082 vshPrint(ctl
, "%-20s %d\n", _("CPU socket(s):"), info
.sockets
);
3083 vshPrint(ctl
, "%-20s %d\n", _("Core(s) per socket:"), info
.cores
);
3084 vshPrint(ctl
, "%-20s %d\n", _("Thread(s) per core:"), info
.threads
);
3085 vshPrint(ctl
, "%-20s %d\n", _("NUMA cell(s):"), info
.nodes
);
3086 vshPrint(ctl
, "%-20s %lu kB\n", _("Memory size:"), info
.memory
);
3092 * "capabilities" command
3094 static const vshCmdInfo info_capabilities
[] = {
3095 {"help", N_("capabilities")},
3096 {"desc", N_("Returns capabilities of hypervisor/driver.")},
3101 cmdCapabilities (vshControl
*ctl
, const vshCmd
*cmd ATTRIBUTE_UNUSED
)
3105 if (!vshConnectionUsability(ctl
, ctl
->conn
))
3108 if ((caps
= virConnectGetCapabilities (ctl
->conn
)) == NULL
) {
3109 vshError(ctl
, "%s", _("failed to get capabilities"));
3112 vshPrint (ctl
, "%s\n", caps
);
3121 static const vshCmdInfo info_dumpxml
[] = {
3122 {"help", N_("domain information in XML")},
3123 {"desc", N_("Output the domain information as an XML dump to stdout.")},
3127 static const vshCmdOptDef opts_dumpxml
[] = {
3128 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
3129 {"inactive", VSH_OT_BOOL
, 0, N_("show inactive defined XML")},
3130 {"security-info", VSH_OT_BOOL
, 0, N_("include security sensitive information in XML dump")},
3131 {"update-cpu", VSH_OT_BOOL
, 0, N_("update guest CPU according to host CPU")},
3136 cmdDumpXML(vshControl
*ctl
, const vshCmd
*cmd
)
3142 int inactive
= vshCommandOptBool(cmd
, "inactive");
3143 int secure
= vshCommandOptBool(cmd
, "security-info");
3144 int update
= vshCommandOptBool(cmd
, "update-cpu");
3147 flags
|= VIR_DOMAIN_XML_INACTIVE
;
3149 flags
|= VIR_DOMAIN_XML_SECURE
;
3151 flags
|= VIR_DOMAIN_XML_UPDATE_CPU
;
3153 if (!vshConnectionUsability(ctl
, ctl
->conn
))
3156 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, NULL
)))
3159 dump
= virDomainGetXMLDesc(dom
, flags
);
3161 vshPrint(ctl
, "%s", dump
);
3172 * "domxml-from-native" command
3174 static const vshCmdInfo info_domxmlfromnative
[] = {
3175 {"help", N_("Convert native config to domain XML")},
3176 {"desc", N_("Convert native guest configuration format to domain XML format.")},
3180 static const vshCmdOptDef opts_domxmlfromnative
[] = {
3181 {"format", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("source config data format")},
3182 {"config", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("config data file to import from")},
3187 cmdDomXMLFromNative(vshControl
*ctl
, const vshCmd
*cmd
)
3196 if (!vshConnectionUsability(ctl
, ctl
->conn
))
3199 format
= vshCommandOptString(cmd
, "format", NULL
);
3200 configFile
= vshCommandOptString(cmd
, "config", NULL
);
3202 if (virFileReadAll(configFile
, 1024*1024, &configData
) < 0)
3205 xmlData
= virConnectDomainXMLFromNative(ctl
->conn
, format
, configData
, flags
);
3206 if (xmlData
!= NULL
) {
3207 vshPrint(ctl
, "%s", xmlData
);
3217 * "domxml-to-native" command
3219 static const vshCmdInfo info_domxmltonative
[] = {
3220 {"help", N_("Convert domain XML to native config")},
3221 {"desc", N_("Convert domain XML config to a native guest configuration format.")},
3225 static const vshCmdOptDef opts_domxmltonative
[] = {
3226 {"format", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("target config data type format")},
3227 {"xml", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("xml data file to export from")},
3232 cmdDomXMLToNative(vshControl
*ctl
, const vshCmd
*cmd
)
3241 if (!vshConnectionUsability(ctl
, ctl
->conn
))
3244 format
= vshCommandOptString(cmd
, "format", NULL
);
3245 xmlFile
= vshCommandOptString(cmd
, "xml", NULL
);
3247 if (virFileReadAll(xmlFile
, 1024*1024, &xmlData
) < 0)
3250 configData
= virConnectDomainXMLToNative(ctl
->conn
, format
, xmlData
, flags
);
3251 if (configData
!= NULL
) {
3252 vshPrint(ctl
, "%s", configData
);
3253 VIR_FREE(configData
);
3264 static const vshCmdInfo info_domname
[] = {
3265 {"help", N_("convert a domain id or UUID to domain name")},
3270 static const vshCmdOptDef opts_domname
[] = {
3271 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain id or uuid")},
3276 cmdDomname(vshControl
*ctl
, const vshCmd
*cmd
)
3280 if (!vshConnectionUsability(ctl
, ctl
->conn
))
3282 if (!(dom
= vshCommandOptDomainBy(ctl
, cmd
, NULL
,
3283 VSH_BYID
|VSH_BYUUID
)))
3286 vshPrint(ctl
, "%s\n", virDomainGetName(dom
));
3294 static const vshCmdInfo info_domid
[] = {
3295 {"help", N_("convert a domain name or UUID to domain id")},
3300 static const vshCmdOptDef opts_domid
[] = {
3301 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name or uuid")},
3306 cmdDomid(vshControl
*ctl
, const vshCmd
*cmd
)
3311 if (!vshConnectionUsability(ctl
, ctl
->conn
))
3313 if (!(dom
= vshCommandOptDomainBy(ctl
, cmd
, NULL
,
3314 VSH_BYNAME
|VSH_BYUUID
)))
3317 id
= virDomainGetID(dom
);
3318 if (id
== ((unsigned int)-1))
3319 vshPrint(ctl
, "%s\n", "-");
3321 vshPrint(ctl
, "%d\n", id
);
3329 static const vshCmdInfo info_domuuid
[] = {
3330 {"help", N_("convert a domain name or id to domain UUID")},
3335 static const vshCmdOptDef opts_domuuid
[] = {
3336 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain id or name")},
3341 cmdDomuuid(vshControl
*ctl
, const vshCmd
*cmd
)
3344 char uuid
[VIR_UUID_STRING_BUFLEN
];
3346 if (!vshConnectionUsability(ctl
, ctl
->conn
))
3348 if (!(dom
= vshCommandOptDomainBy(ctl
, cmd
, NULL
,
3349 VSH_BYNAME
|VSH_BYID
)))
3352 if (virDomainGetUUIDString(dom
, uuid
) != -1)
3353 vshPrint(ctl
, "%s\n", uuid
);
3355 vshError(ctl
, "%s", _("failed to get domain UUID"));
3364 static const vshCmdInfo info_migrate
[] = {
3365 {"help", N_("migrate domain to another host")},
3366 {"desc", N_("Migrate domain to another host. Add --live for live migration.")},
3370 static const vshCmdOptDef opts_migrate
[] = {
3371 {"live", VSH_OT_BOOL
, 0, N_("live migration")},
3372 {"p2p", VSH_OT_BOOL
, 0, N_("peer-2-peer migration")},
3373 {"direct", VSH_OT_BOOL
, 0, N_("direct migration")},
3374 {"tunnelled", VSH_OT_BOOL
, 0, N_("tunnelled migration")},
3375 {"persistent", VSH_OT_BOOL
, 0, N_("persist VM on destination")},
3376 {"undefinesource", VSH_OT_BOOL
, 0, N_("undefine VM on source")},
3377 {"suspend", VSH_OT_BOOL
, 0, N_("do not restart the domain on the destination host")},
3378 {"copy-storage-all", VSH_OT_BOOL
, 0, N_("migration with non-shared storage with full disk copy")},
3379 {"copy-storage-inc", VSH_OT_BOOL
, 0, N_("migration with non-shared storage with incremental copy (same base image shared between source and destination)")},
3380 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
3381 {"desturi", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("connection URI of the destination host")},
3382 {"migrateuri", VSH_OT_DATA
, 0, N_("migration URI, usually can be omitted")},
3383 {"dname", VSH_OT_DATA
, 0, N_("rename to new name during migration (if supported)")},
3388 cmdMigrate (vshControl
*ctl
, const vshCmd
*cmd
)
3390 virDomainPtr dom
= NULL
;
3391 const char *desturi
;
3392 const char *migrateuri
;
3394 int flags
= 0, found
, ret
= FALSE
;
3396 if (!vshConnectionUsability (ctl
, ctl
->conn
))
3399 if (!(dom
= vshCommandOptDomain (ctl
, cmd
, NULL
)))
3402 desturi
= vshCommandOptString (cmd
, "desturi", &found
);
3406 migrateuri
= vshCommandOptString (cmd
, "migrateuri", NULL
);
3408 dname
= vshCommandOptString (cmd
, "dname", NULL
);
3410 if (vshCommandOptBool (cmd
, "live"))
3411 flags
|= VIR_MIGRATE_LIVE
;
3412 if (vshCommandOptBool (cmd
, "p2p"))
3413 flags
|= VIR_MIGRATE_PEER2PEER
;
3414 if (vshCommandOptBool (cmd
, "tunnelled"))
3415 flags
|= VIR_MIGRATE_TUNNELLED
;
3417 if (vshCommandOptBool (cmd
, "persistent"))
3418 flags
|= VIR_MIGRATE_PERSIST_DEST
;
3419 if (vshCommandOptBool (cmd
, "undefinesource"))
3420 flags
|= VIR_MIGRATE_UNDEFINE_SOURCE
;
3422 if (vshCommandOptBool (cmd
, "suspend"))
3423 flags
|= VIR_MIGRATE_PAUSED
;
3425 if (vshCommandOptBool (cmd
, "copy-storage-all"))
3426 flags
|= VIR_MIGRATE_NON_SHARED_DISK
;
3428 if (vshCommandOptBool (cmd
, "copy-storage-inc"))
3429 flags
|= VIR_MIGRATE_NON_SHARED_INC
;
3431 if ((flags
& VIR_MIGRATE_PEER2PEER
) ||
3432 vshCommandOptBool (cmd
, "direct")) {
3433 /* For peer2peer migration or direct migration we only expect one URI
3434 * a libvirt URI, or a hypervisor specific URI. */
3436 if (migrateuri
!= NULL
) {
3437 vshError(ctl
, "%s", _("migrate: Unexpected migrateuri for peer2peer/direct migration"));
3441 if (virDomainMigrateToURI (dom
, desturi
, flags
, dname
, 0) == 0)
3444 /* For traditional live migration, connect to the destination host directly. */
3445 virConnectPtr dconn
= NULL
;
3446 virDomainPtr ddom
= NULL
;
3448 dconn
= virConnectOpenAuth (desturi
, virConnectAuthPtrDefault
, 0);
3449 if (!dconn
) goto done
;
3451 ddom
= virDomainMigrate (dom
, dconn
, flags
, dname
, migrateuri
, 0);
3453 virDomainFree(ddom
);
3456 virConnectClose (dconn
);
3460 if (dom
) virDomainFree (dom
);
3465 * "migrate-setmaxdowntime" command
3467 static const vshCmdInfo info_migrate_setmaxdowntime
[] = {
3468 {"help", N_("set maximum tolerable downtime")},
3469 {"desc", N_("Set maximum tolerable downtime of a domain which is being live-migrated to another host.")},
3473 static const vshCmdOptDef opts_migrate_setmaxdowntime
[] = {
3474 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
3475 {"downtime", VSH_OT_INT
, VSH_OFLAG_REQ
, N_("maximum tolerable downtime (in milliseconds) for migration")},
3480 cmdMigrateSetMaxDowntime(vshControl
*ctl
, const vshCmd
*cmd
)
3482 virDomainPtr dom
= NULL
;
3487 if (!vshConnectionUsability(ctl
, ctl
->conn
))
3490 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, NULL
)))
3493 downtime
= vshCommandOptLongLong(cmd
, "downtime", &found
);
3494 if (!found
|| downtime
< 1) {
3495 vshError(ctl
, "%s", _("migrate: Invalid downtime"));
3499 if (virDomainMigrateSetMaxDowntime(dom
, downtime
, 0))
3510 * "net-autostart" command
3512 static const vshCmdInfo info_network_autostart
[] = {
3513 {"help", N_("autostart a network")},
3515 N_("Configure a network to be automatically started at boot.")},
3519 static const vshCmdOptDef opts_network_autostart
[] = {
3520 {"network", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("network name or uuid")},
3521 {"disable", VSH_OT_BOOL
, 0, N_("disable autostarting")},
3526 cmdNetworkAutostart(vshControl
*ctl
, const vshCmd
*cmd
)
3528 virNetworkPtr network
;
3532 if (!vshConnectionUsability(ctl
, ctl
->conn
))
3535 if (!(network
= vshCommandOptNetwork(ctl
, cmd
, &name
)))
3538 autostart
= !vshCommandOptBool(cmd
, "disable");
3540 if (virNetworkSetAutostart(network
, autostart
) < 0) {
3542 vshError(ctl
, _("failed to mark network %s as autostarted"), name
);
3544 vshError(ctl
, _("failed to unmark network %s as autostarted"), name
);
3545 virNetworkFree(network
);
3550 vshPrint(ctl
, _("Network %s marked as autostarted\n"), name
);
3552 vshPrint(ctl
, _("Network %s unmarked as autostarted\n"), name
);
3554 virNetworkFree(network
);
3559 * "net-create" command
3561 static const vshCmdInfo info_network_create
[] = {
3562 {"help", N_("create a network from an XML file")},
3563 {"desc", N_("Create a network.")},
3567 static const vshCmdOptDef opts_network_create
[] = {
3568 {"file", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("file containing an XML network description")},
3573 cmdNetworkCreate(vshControl
*ctl
, const vshCmd
*cmd
)
3575 virNetworkPtr network
;
3581 if (!vshConnectionUsability(ctl
, ctl
->conn
))
3584 from
= vshCommandOptString(cmd
, "file", &found
);
3588 if (virFileReadAll(from
, VIRSH_MAX_XML_FILE
, &buffer
) < 0)
3591 network
= virNetworkCreateXML(ctl
->conn
, buffer
);
3594 if (network
!= NULL
) {
3595 vshPrint(ctl
, _("Network %s created from %s\n"),
3596 virNetworkGetName(network
), from
);
3597 virNetworkFree(network
);
3599 vshError(ctl
, _("Failed to create network from %s"), from
);
3607 * "net-define" command
3609 static const vshCmdInfo info_network_define
[] = {
3610 {"help", N_("define (but don't start) a network from an XML file")},
3611 {"desc", N_("Define a network.")},
3615 static const vshCmdOptDef opts_network_define
[] = {
3616 {"file", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("file containing an XML network description")},
3621 cmdNetworkDefine(vshControl
*ctl
, const vshCmd
*cmd
)
3623 virNetworkPtr network
;
3629 if (!vshConnectionUsability(ctl
, ctl
->conn
))
3632 from
= vshCommandOptString(cmd
, "file", &found
);
3636 if (virFileReadAll(from
, VIRSH_MAX_XML_FILE
, &buffer
) < 0)
3639 network
= virNetworkDefineXML(ctl
->conn
, buffer
);
3642 if (network
!= NULL
) {
3643 vshPrint(ctl
, _("Network %s defined from %s\n"),
3644 virNetworkGetName(network
), from
);
3645 virNetworkFree(network
);
3647 vshError(ctl
, _("Failed to define network from %s"), from
);
3655 * "net-destroy" command
3657 static const vshCmdInfo info_network_destroy
[] = {
3658 {"help", N_("destroy a network")},
3659 {"desc", N_("Destroy a given network.")},
3663 static const vshCmdOptDef opts_network_destroy
[] = {
3664 {"network", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("network name or uuid")},
3669 cmdNetworkDestroy(vshControl
*ctl
, const vshCmd
*cmd
)
3671 virNetworkPtr network
;
3675 if (!vshConnectionUsability(ctl
, ctl
->conn
))
3678 if (!(network
= vshCommandOptNetwork(ctl
, cmd
, &name
)))
3681 if (virNetworkDestroy(network
) == 0) {
3682 vshPrint(ctl
, _("Network %s destroyed\n"), name
);
3684 vshError(ctl
, _("Failed to destroy network %s"), name
);
3688 virNetworkFree(network
);
3694 * "net-dumpxml" command
3696 static const vshCmdInfo info_network_dumpxml
[] = {
3697 {"help", N_("network information in XML")},
3698 {"desc", N_("Output the network information as an XML dump to stdout.")},
3702 static const vshCmdOptDef opts_network_dumpxml
[] = {
3703 {"network", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("network name or uuid")},
3708 cmdNetworkDumpXML(vshControl
*ctl
, const vshCmd
*cmd
)
3710 virNetworkPtr network
;
3714 if (!vshConnectionUsability(ctl
, ctl
->conn
))
3717 if (!(network
= vshCommandOptNetwork(ctl
, cmd
, NULL
)))
3720 dump
= virNetworkGetXMLDesc(network
, 0);
3722 vshPrint(ctl
, "%s", dump
);
3728 virNetworkFree(network
);
3733 * "net-info" command
3735 static const vshCmdInfo info_network_info
[] = {
3736 {"help", N_("network information")},
3737 {"desc", "Returns basic information about the network"},
3741 static const vshCmdOptDef opts_network_info
[] = {
3742 {"network", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("network name")},
3747 cmdNetworkInfo(vshControl
*ctl
, const vshCmd
*cmd
)
3749 virNetworkPtr network
;
3750 char uuid
[VIR_UUID_STRING_BUFLEN
];
3752 int persistent
= -1;
3754 char *bridge
= NULL
;
3756 if (!vshConnectionUsability(ctl
, ctl
->conn
))
3759 if (!(network
= vshCommandOptNetworkBy(ctl
, cmd
, NULL
,
3763 vshPrint(ctl
, "%-15s %s\n", _("Name"), virNetworkGetName(network
));
3765 if (virNetworkGetUUIDString(network
, uuid
) == 0)
3766 vshPrint(ctl
, "%-15s %s\n", _("UUID"), uuid
);
3768 active
= virNetworkIsActive(network
);
3770 vshPrint(ctl
, "%-15s %s\n", _("Active:"), active
? _("yes") : _("no"));
3772 persistent
= virNetworkIsPersistent(network
);
3774 vshPrint(ctl
, "%-15s %s\n", _("Persistent:"), _("unknown"));
3776 vshPrint(ctl
, "%-15s %s\n", _("Persistent:"), persistent
? _("yes") : _("no"));
3778 if (virNetworkGetAutostart(network
, &autostart
) < 0)
3779 vshPrint(ctl
, "%-15s %s\n", _("Autostart:"), _("no autostart"));
3781 vshPrint(ctl
, "%-15s %s\n", _("Autostart:"), autostart
? _("yes") : _("no"));
3783 bridge
= virNetworkGetBridgeName(network
);
3785 vshPrint(ctl
, "%-15s %s\n", _("Bridge:"), bridge
);
3787 virNetworkFree(network
);
3792 * "iface-edit" command
3794 static const vshCmdInfo info_interface_edit
[] = {
3795 {"help", N_("edit XML configuration for a physical host interface")},
3796 {"desc", N_("Edit the XML configuration for a physical host interface.")},
3800 static const vshCmdOptDef opts_interface_edit
[] = {
3801 {"interface", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("interface name or MAC address")},
3806 cmdInterfaceEdit (vshControl
*ctl
, const vshCmd
*cmd
)
3809 virInterfacePtr iface
= NULL
;
3812 char *doc_edited
= NULL
;
3813 char *doc_reread
= NULL
;
3814 int flags
= VIR_INTERFACE_XML_INACTIVE
;
3816 if (!vshConnectionUsability(ctl
, ctl
->conn
))
3819 iface
= vshCommandOptInterface (ctl
, cmd
, NULL
);
3823 /* Get the XML configuration of the interface. */
3824 doc
= virInterfaceGetXMLDesc (iface
, flags
);
3828 /* Create and open the temporary file. */
3829 tmp
= editWriteToTempFile (ctl
, doc
);
3830 if (!tmp
) goto cleanup
;
3832 /* Start the editor. */
3833 if (editFile (ctl
, tmp
) == -1) goto cleanup
;
3835 /* Read back the edited file. */
3836 doc_edited
= editReadBackFile (ctl
, tmp
);
3837 if (!doc_edited
) goto cleanup
;
3839 /* Compare original XML with edited. Has it changed at all? */
3840 if (STREQ (doc
, doc_edited
)) {
3841 vshPrint (ctl
, _("Interface %s XML configuration not changed.\n"),
3842 virInterfaceGetName (iface
));
3847 /* Now re-read the interface XML. Did someone else change it while
3848 * it was being edited? This also catches problems such as us
3849 * losing a connection or the interface going away.
3851 doc_reread
= virInterfaceGetXMLDesc (iface
, flags
);
3855 if (STRNEQ (doc
, doc_reread
)) {
3857 _("ERROR: the XML configuration was changed by another user"));
3861 /* Everything checks out, so redefine the interface. */
3862 virInterfaceFree (iface
);
3863 iface
= virInterfaceDefineXML (ctl
->conn
, doc_edited
, 0);
3867 vshPrint (ctl
, _("Interface %s XML configuration edited.\n"),
3868 virInterfaceGetName(iface
));
3874 virInterfaceFree (iface
);
3877 VIR_FREE(doc_edited
);
3878 VIR_FREE(doc_reread
);
3889 * "net-list" command
3891 static const vshCmdInfo info_network_list
[] = {
3892 {"help", N_("list networks")},
3893 {"desc", N_("Returns list of networks.")},
3897 static const vshCmdOptDef opts_network_list
[] = {
3898 {"inactive", VSH_OT_BOOL
, 0, N_("list inactive networks")},
3899 {"all", VSH_OT_BOOL
, 0, N_("list inactive & active networks")},
3904 cmdNetworkList(vshControl
*ctl
, const vshCmd
*cmd ATTRIBUTE_UNUSED
)
3906 int inactive
= vshCommandOptBool(cmd
, "inactive");
3907 int all
= vshCommandOptBool(cmd
, "all");
3908 int active
= !inactive
|| all
? 1 : 0;
3909 int maxactive
= 0, maxinactive
= 0, i
;
3910 char **activeNames
= NULL
, **inactiveNames
= NULL
;
3913 if (!vshConnectionUsability(ctl
, ctl
->conn
))
3917 maxactive
= virConnectNumOfNetworks(ctl
->conn
);
3918 if (maxactive
< 0) {
3919 vshError(ctl
, "%s", _("Failed to list active networks"));
3923 activeNames
= vshMalloc(ctl
, sizeof(char *) * maxactive
);
3925 if ((maxactive
= virConnectListNetworks(ctl
->conn
, activeNames
,
3927 vshError(ctl
, "%s", _("Failed to list active networks"));
3928 VIR_FREE(activeNames
);
3932 qsort(&activeNames
[0], maxactive
, sizeof(char *), namesorter
);
3936 maxinactive
= virConnectNumOfDefinedNetworks(ctl
->conn
);
3937 if (maxinactive
< 0) {
3938 vshError(ctl
, "%s", _("Failed to list inactive networks"));
3939 VIR_FREE(activeNames
);
3943 inactiveNames
= vshMalloc(ctl
, sizeof(char *) * maxinactive
);
3946 virConnectListDefinedNetworks(ctl
->conn
, inactiveNames
,
3947 maxinactive
)) < 0) {
3948 vshError(ctl
, "%s", _("Failed to list inactive networks"));
3949 VIR_FREE(activeNames
);
3950 VIR_FREE(inactiveNames
);
3954 qsort(&inactiveNames
[0], maxinactive
, sizeof(char*), namesorter
);
3957 vshPrintExtra(ctl
, "%-20s %-10s %s\n", _("Name"), _("State"),
3959 vshPrintExtra(ctl
, "-----------------------------------------\n");
3961 for (i
= 0; i
< maxactive
; i
++) {
3962 virNetworkPtr network
=
3963 virNetworkLookupByName(ctl
->conn
, activeNames
[i
]);
3964 const char *autostartStr
;
3967 /* this kind of work with networks is not atomic operation */
3969 VIR_FREE(activeNames
[i
]);
3973 if (virNetworkGetAutostart(network
, &autostart
) < 0)
3974 autostartStr
= _("no autostart");
3976 autostartStr
= autostart
? _("yes") : _("no");
3978 vshPrint(ctl
, "%-20s %-10s %-10s\n",
3979 virNetworkGetName(network
),
3982 virNetworkFree(network
);
3983 VIR_FREE(activeNames
[i
]);
3985 for (i
= 0; i
< maxinactive
; i
++) {
3986 virNetworkPtr network
= virNetworkLookupByName(ctl
->conn
, inactiveNames
[i
]);
3987 const char *autostartStr
;
3990 /* this kind of work with networks is not atomic operation */
3992 VIR_FREE(inactiveNames
[i
]);
3996 if (virNetworkGetAutostart(network
, &autostart
) < 0)
3997 autostartStr
= _("no autostart");
3999 autostartStr
= autostart
? _("yes") : _("no");
4001 vshPrint(ctl
, "%-20s %-10s %-10s\n",
4006 virNetworkFree(network
);
4007 VIR_FREE(inactiveNames
[i
]);
4009 VIR_FREE(activeNames
);
4010 VIR_FREE(inactiveNames
);
4016 * "net-name" command
4018 static const vshCmdInfo info_network_name
[] = {
4019 {"help", N_("convert a network UUID to network name")},
4024 static const vshCmdOptDef opts_network_name
[] = {
4025 {"network", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("network uuid")},
4030 cmdNetworkName(vshControl
*ctl
, const vshCmd
*cmd
)
4032 virNetworkPtr network
;
4034 if (!vshConnectionUsability(ctl
, ctl
->conn
))
4036 if (!(network
= vshCommandOptNetworkBy(ctl
, cmd
, NULL
,
4040 vshPrint(ctl
, "%s\n", virNetworkGetName(network
));
4041 virNetworkFree(network
);
4047 * "net-start" command
4049 static const vshCmdInfo info_network_start
[] = {
4050 {"help", N_("start a (previously defined) inactive network")},
4051 {"desc", N_("Start a network.")},
4055 static const vshCmdOptDef opts_network_start
[] = {
4056 {"network", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("name of the inactive network")},
4061 cmdNetworkStart(vshControl
*ctl
, const vshCmd
*cmd
)
4063 virNetworkPtr network
;
4066 if (!vshConnectionUsability(ctl
, ctl
->conn
))
4069 if (!(network
= vshCommandOptNetworkBy(ctl
, cmd
, NULL
, VSH_BYNAME
)))
4072 if (virNetworkCreate(network
) == 0) {
4073 vshPrint(ctl
, _("Network %s started\n"),
4074 virNetworkGetName(network
));
4076 vshError(ctl
, _("Failed to start network %s"),
4077 virNetworkGetName(network
));
4080 virNetworkFree(network
);
4086 * "net-undefine" command
4088 static const vshCmdInfo info_network_undefine
[] = {
4089 {"help", N_("undefine an inactive network")},
4090 {"desc", N_("Undefine the configuration for an inactive network.")},
4094 static const vshCmdOptDef opts_network_undefine
[] = {
4095 {"network", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("network name or uuid")},
4100 cmdNetworkUndefine(vshControl
*ctl
, const vshCmd
*cmd
)
4102 virNetworkPtr network
;
4106 if (!vshConnectionUsability(ctl
, ctl
->conn
))
4109 if (!(network
= vshCommandOptNetwork(ctl
, cmd
, &name
)))
4112 if (virNetworkUndefine(network
) == 0) {
4113 vshPrint(ctl
, _("Network %s has been undefined\n"), name
);
4115 vshError(ctl
, _("Failed to undefine network %s"), name
);
4119 virNetworkFree(network
);
4125 * "net-uuid" command
4127 static const vshCmdInfo info_network_uuid
[] = {
4128 {"help", N_("convert a network name to network UUID")},
4133 static const vshCmdOptDef opts_network_uuid
[] = {
4134 {"network", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("network name")},
4139 cmdNetworkUuid(vshControl
*ctl
, const vshCmd
*cmd
)
4141 virNetworkPtr network
;
4142 char uuid
[VIR_UUID_STRING_BUFLEN
];
4144 if (!vshConnectionUsability(ctl
, ctl
->conn
))
4147 if (!(network
= vshCommandOptNetworkBy(ctl
, cmd
, NULL
,
4151 if (virNetworkGetUUIDString(network
, uuid
) != -1)
4152 vshPrint(ctl
, "%s\n", uuid
);
4154 vshError(ctl
, "%s", _("failed to get network UUID"));
4156 virNetworkFree(network
);
4161 /**************************************************************************/
4163 * "iface-list" command
4165 static const vshCmdInfo info_interface_list
[] = {
4166 {"help", N_("list physical host interfaces")},
4167 {"desc", N_("Returns list of physical host interfaces.")},
4171 static const vshCmdOptDef opts_interface_list
[] = {
4172 {"inactive", VSH_OT_BOOL
, 0, N_("list inactive interfaces")},
4173 {"all", VSH_OT_BOOL
, 0, N_("list inactive & active interfaces")},
4177 cmdInterfaceList(vshControl
*ctl
, const vshCmd
*cmd ATTRIBUTE_UNUSED
)
4179 int inactive
= vshCommandOptBool(cmd
, "inactive");
4180 int all
= vshCommandOptBool(cmd
, "all");
4181 int active
= !inactive
|| all
? 1 : 0;
4182 int maxactive
= 0, maxinactive
= 0, i
;
4183 char **activeNames
= NULL
, **inactiveNames
= NULL
;
4186 if (!vshConnectionUsability(ctl
, ctl
->conn
))
4190 maxactive
= virConnectNumOfInterfaces(ctl
->conn
);
4191 if (maxactive
< 0) {
4192 vshError(ctl
, "%s", _("Failed to list active interfaces"));
4196 activeNames
= vshMalloc(ctl
, sizeof(char *) * maxactive
);
4198 if ((maxactive
= virConnectListInterfaces(ctl
->conn
, activeNames
,
4200 vshError(ctl
, "%s", _("Failed to list active interfaces"));
4201 VIR_FREE(activeNames
);
4205 qsort(&activeNames
[0], maxactive
, sizeof(char *), namesorter
);
4209 maxinactive
= virConnectNumOfDefinedInterfaces(ctl
->conn
);
4210 if (maxinactive
< 0) {
4211 vshError(ctl
, "%s", _("Failed to list inactive interfaces"));
4212 VIR_FREE(activeNames
);
4216 inactiveNames
= vshMalloc(ctl
, sizeof(char *) * maxinactive
);
4219 virConnectListDefinedInterfaces(ctl
->conn
, inactiveNames
,
4220 maxinactive
)) < 0) {
4221 vshError(ctl
, "%s", _("Failed to list inactive interfaces"));
4222 VIR_FREE(activeNames
);
4223 VIR_FREE(inactiveNames
);
4227 qsort(&inactiveNames
[0], maxinactive
, sizeof(char*), namesorter
);
4230 vshPrintExtra(ctl
, "%-20s %-10s %s\n", _("Name"), _("State"),
4232 vshPrintExtra(ctl
, "--------------------------------------------\n");
4234 for (i
= 0; i
< maxactive
; i
++) {
4235 virInterfacePtr iface
=
4236 virInterfaceLookupByName(ctl
->conn
, activeNames
[i
]);
4238 /* this kind of work with interfaces is not atomic */
4240 VIR_FREE(activeNames
[i
]);
4244 vshPrint(ctl
, "%-20s %-10s %s\n",
4245 virInterfaceGetName(iface
),
4247 virInterfaceGetMACString(iface
));
4248 virInterfaceFree(iface
);
4249 VIR_FREE(activeNames
[i
]);
4251 for (i
= 0; i
< maxinactive
; i
++) {
4252 virInterfacePtr iface
=
4253 virInterfaceLookupByName(ctl
->conn
, inactiveNames
[i
]);
4255 /* this kind of work with interfaces is not atomic */
4257 VIR_FREE(inactiveNames
[i
]);
4261 vshPrint(ctl
, "%-20s %-10s %s\n",
4262 virInterfaceGetName(iface
),
4264 virInterfaceGetMACString(iface
));
4265 virInterfaceFree(iface
);
4266 VIR_FREE(inactiveNames
[i
]);
4268 VIR_FREE(activeNames
);
4269 VIR_FREE(inactiveNames
);
4275 * "iface-name" command
4277 static const vshCmdInfo info_interface_name
[] = {
4278 {"help", N_("convert an interface MAC address to interface name")},
4283 static const vshCmdOptDef opts_interface_name
[] = {
4284 {"interface", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("interface mac")},
4289 cmdInterfaceName(vshControl
*ctl
, const vshCmd
*cmd
)
4291 virInterfacePtr iface
;
4293 if (!vshConnectionUsability(ctl
, ctl
->conn
))
4295 if (!(iface
= vshCommandOptInterfaceBy(ctl
, cmd
, NULL
,
4299 vshPrint(ctl
, "%s\n", virInterfaceGetName(iface
));
4300 virInterfaceFree(iface
);
4305 * "iface-mac" command
4307 static const vshCmdInfo info_interface_mac
[] = {
4308 {"help", N_("convert an interface name to interface MAC address")},
4313 static const vshCmdOptDef opts_interface_mac
[] = {
4314 {"interface", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("interface name")},
4319 cmdInterfaceMAC(vshControl
*ctl
, const vshCmd
*cmd
)
4321 virInterfacePtr iface
;
4323 if (!vshConnectionUsability(ctl
, ctl
->conn
))
4325 if (!(iface
= vshCommandOptInterfaceBy(ctl
, cmd
, NULL
,
4329 vshPrint(ctl
, "%s\n", virInterfaceGetMACString(iface
));
4330 virInterfaceFree(iface
);
4335 * "iface-dumpxml" command
4337 static const vshCmdInfo info_interface_dumpxml
[] = {
4338 {"help", N_("interface information in XML")},
4339 {"desc", N_("Output the physical host interface information as an XML dump to stdout.")},
4343 static const vshCmdOptDef opts_interface_dumpxml
[] = {
4344 {"interface", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("interface name or MAC address")},
4345 {"inactive", VSH_OT_BOOL
, 0, N_("show inactive defined XML")},
4350 cmdInterfaceDumpXML(vshControl
*ctl
, const vshCmd
*cmd
)
4352 virInterfacePtr iface
;
4356 int inactive
= vshCommandOptBool(cmd
, "inactive");
4359 flags
|= VIR_INTERFACE_XML_INACTIVE
;
4361 if (!vshConnectionUsability(ctl
, ctl
->conn
))
4364 if (!(iface
= vshCommandOptInterface(ctl
, cmd
, NULL
)))
4367 dump
= virInterfaceGetXMLDesc(iface
, flags
);
4369 vshPrint(ctl
, "%s", dump
);
4375 virInterfaceFree(iface
);
4380 * "iface-define" command
4382 static const vshCmdInfo info_interface_define
[] = {
4383 {"help", N_("define (but don't start) a physical host interface from an XML file")},
4384 {"desc", N_("Define a physical host interface.")},
4388 static const vshCmdOptDef opts_interface_define
[] = {
4389 {"file", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("file containing an XML interface description")},
4394 cmdInterfaceDefine(vshControl
*ctl
, const vshCmd
*cmd
)
4396 virInterfacePtr iface
;
4402 if (!vshConnectionUsability(ctl
, ctl
->conn
))
4405 from
= vshCommandOptString(cmd
, "file", &found
);
4409 if (virFileReadAll(from
, VIRSH_MAX_XML_FILE
, &buffer
) < 0)
4412 iface
= virInterfaceDefineXML(ctl
->conn
, buffer
, 0);
4415 if (iface
!= NULL
) {
4416 vshPrint(ctl
, _("Interface %s defined from %s\n"),
4417 virInterfaceGetName(iface
), from
);
4418 virInterfaceFree (iface
);
4420 vshError(ctl
, _("Failed to define interface from %s"), from
);
4427 * "iface-undefine" command
4429 static const vshCmdInfo info_interface_undefine
[] = {
4430 {"help", N_("undefine a physical host interface (remove it from configuration)")},
4431 {"desc", N_("undefine an interface.")},
4435 static const vshCmdOptDef opts_interface_undefine
[] = {
4436 {"interface", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("interface name or MAC address")},
4441 cmdInterfaceUndefine(vshControl
*ctl
, const vshCmd
*cmd
)
4443 virInterfacePtr iface
;
4447 if (!vshConnectionUsability(ctl
, ctl
->conn
))
4450 if (!(iface
= vshCommandOptInterface(ctl
, cmd
, &name
)))
4453 if (virInterfaceUndefine(iface
) == 0) {
4454 vshPrint(ctl
, _("Interface %s undefined\n"), name
);
4456 vshError(ctl
, _("Failed to undefine interface %s"), name
);
4460 virInterfaceFree(iface
);
4465 * "iface-start" command
4467 static const vshCmdInfo info_interface_start
[] = {
4468 {"help", N_("start a physical host interface (enable it / \"if-up\")")},
4469 {"desc", N_("start a physical host interface.")},
4473 static const vshCmdOptDef opts_interface_start
[] = {
4474 {"interface", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("interface name or MAC address")},
4479 cmdInterfaceStart(vshControl
*ctl
, const vshCmd
*cmd
)
4481 virInterfacePtr iface
;
4485 if (!vshConnectionUsability(ctl
, ctl
->conn
))
4488 if (!(iface
= vshCommandOptInterface(ctl
, cmd
, &name
)))
4491 if (virInterfaceCreate(iface
, 0) == 0) {
4492 vshPrint(ctl
, _("Interface %s started\n"), name
);
4494 vshError(ctl
, _("Failed to start interface %s"), name
);
4498 virInterfaceFree(iface
);
4503 * "iface-destroy" command
4505 static const vshCmdInfo info_interface_destroy
[] = {
4506 {"help", N_("destroy a physical host interface (disable it / \"if-down\")")},
4507 {"desc", N_("destroy a physical host interface.")},
4511 static const vshCmdOptDef opts_interface_destroy
[] = {
4512 {"interface", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("interface name or MAC address")},
4517 cmdInterfaceDestroy(vshControl
*ctl
, const vshCmd
*cmd
)
4519 virInterfacePtr iface
;
4523 if (!vshConnectionUsability(ctl
, ctl
->conn
))
4526 if (!(iface
= vshCommandOptInterface(ctl
, cmd
, &name
)))
4529 if (virInterfaceDestroy(iface
, 0) == 0) {
4530 vshPrint(ctl
, _("Interface %s destroyed\n"), name
);
4532 vshError(ctl
, _("Failed to destroy interface %s"), name
);
4536 virInterfaceFree(iface
);
4542 * "nwfilter-define" command
4544 static const vshCmdInfo info_nwfilter_define
[] = {
4545 {"help", N_("define or update a network filter from an XML file")},
4546 {"desc", N_("Define a new network filter or update an existing one.")},
4550 static const vshCmdOptDef opts_nwfilter_define
[] = {
4551 {"file", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("file containing an XML network filter description")},
4556 cmdNWFilterDefine(vshControl
*ctl
, const vshCmd
*cmd
)
4558 virNWFilterPtr nwfilter
;
4564 if (!vshConnectionUsability(ctl
, ctl
->conn
))
4567 from
= vshCommandOptString(cmd
, "file", &found
);
4571 if (virFileReadAll(from
, VIRSH_MAX_XML_FILE
, &buffer
) < 0)
4574 nwfilter
= virNWFilterDefineXML(ctl
->conn
, buffer
);
4577 if (nwfilter
!= NULL
) {
4578 vshPrint(ctl
, _("Network filter %s defined from %s\n"),
4579 virNWFilterGetName(nwfilter
), from
);
4580 virNWFilterFree(nwfilter
);
4582 vshError(ctl
, _("Failed to define network filter from %s"), from
);
4590 * "nwfilter-undefine" command
4592 static const vshCmdInfo info_nwfilter_undefine
[] = {
4593 {"help", N_("undefine a network filter")},
4594 {"desc", N_("Undefine a given network filter.")},
4598 static const vshCmdOptDef opts_nwfilter_undefine
[] = {
4599 {"nwfilter", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("network filter name or uuid")},
4604 cmdNWFilterUndefine(vshControl
*ctl
, const vshCmd
*cmd
)
4606 virNWFilterPtr nwfilter
;
4610 if (!vshConnectionUsability(ctl
, ctl
->conn
))
4613 if (!(nwfilter
= vshCommandOptNWFilter(ctl
, cmd
, &name
)))
4616 if (virNWFilterUndefine(nwfilter
) == 0) {
4617 vshPrint(ctl
, _("Network filter %s undefined\n"), name
);
4619 vshError(ctl
, _("Failed to undefine network filter %s"), name
);
4623 virNWFilterFree(nwfilter
);
4629 * "nwfilter-dumpxml" command
4631 static const vshCmdInfo info_nwfilter_dumpxml
[] = {
4632 {"help", N_("network filter information in XML")},
4633 {"desc", N_("Output the network filter information as an XML dump to stdout.")},
4637 static const vshCmdOptDef opts_nwfilter_dumpxml
[] = {
4638 {"nwfilter", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("network filter name or uuid")},
4643 cmdNWFilterDumpXML(vshControl
*ctl
, const vshCmd
*cmd
)
4645 virNWFilterPtr nwfilter
;
4649 if (!vshConnectionUsability(ctl
, ctl
->conn
))
4652 if (!(nwfilter
= vshCommandOptNWFilter(ctl
, cmd
, NULL
)))
4655 dump
= virNWFilterGetXMLDesc(nwfilter
, 0);
4657 vshPrint(ctl
, "%s", dump
);
4663 virNWFilterFree(nwfilter
);
4668 * "nwfilter-list" command
4670 static const vshCmdInfo info_nwfilter_list
[] = {
4671 {"help", N_("list network filters")},
4672 {"desc", N_("Returns list of network filters.")},
4676 static const vshCmdOptDef opts_nwfilter_list
[] = {
4681 cmdNWFilterList(vshControl
*ctl
, const vshCmd
*cmd ATTRIBUTE_UNUSED
)
4685 char uuid
[VIR_UUID_STRING_BUFLEN
];
4687 if (!vshConnectionUsability(ctl
, ctl
->conn
))
4690 numfilters
= virConnectNumOfNWFilters(ctl
->conn
);
4691 if (numfilters
< 0) {
4692 vshError(ctl
, "%s", _("Failed to list network filters"));
4696 names
= vshMalloc(ctl
, sizeof(char *) * numfilters
);
4698 if ((numfilters
= virConnectListNWFilters(ctl
->conn
, names
,
4700 vshError(ctl
, "%s", _("Failed to list network filters"));
4705 qsort(&names
[0], numfilters
, sizeof(char *), namesorter
);
4707 vshPrintExtra(ctl
, "%-36s %-20s \n", _("UUID"), _("Name"));
4709 "----------------------------------------------------------------\n");
4711 for (i
= 0; i
< numfilters
; i
++) {
4712 virNWFilterPtr nwfilter
=
4713 virNWFilterLookupByName(ctl
->conn
, names
[i
]);
4715 /* this kind of work with networks is not atomic operation */
4721 virNWFilterGetUUIDString(nwfilter
, uuid
);
4722 vshPrint(ctl
, "%-36s %-20s\n",
4724 virNWFilterGetName(nwfilter
));
4725 virNWFilterFree(nwfilter
);
4735 * "nwfilter-edit" command
4737 static const vshCmdInfo info_nwfilter_edit
[] = {
4738 {"help", N_("edit XML configuration for a network filter")},
4739 {"desc", N_("Edit the XML configuration for a network filter.")},
4743 static const vshCmdOptDef opts_nwfilter_edit
[] = {
4744 {"nwfilter", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("network filter name or uuid")},
4749 cmdNWFilterEdit (vshControl
*ctl
, const vshCmd
*cmd
)
4752 virNWFilterPtr nwfilter
= NULL
;
4755 char *doc_edited
= NULL
;
4756 char *doc_reread
= NULL
;
4758 if (!vshConnectionUsability(ctl
, ctl
->conn
))
4761 nwfilter
= vshCommandOptNWFilter (ctl
, cmd
, NULL
);
4762 if (nwfilter
== NULL
)
4765 /* Get the XML configuration of the interface. */
4766 doc
= virNWFilterGetXMLDesc (nwfilter
, 0);
4770 /* Create and open the temporary file. */
4771 tmp
= editWriteToTempFile (ctl
, doc
);
4772 if (!tmp
) goto cleanup
;
4774 /* Start the editor. */
4775 if (editFile (ctl
, tmp
) == -1) goto cleanup
;
4777 /* Read back the edited file. */
4778 doc_edited
= editReadBackFile (ctl
, tmp
);
4779 if (!doc_edited
) goto cleanup
;
4781 /* Compare original XML with edited. Has it changed at all? */
4782 if (STREQ (doc
, doc_edited
)) {
4783 vshPrint (ctl
, _("Network filter %s XML configuration not changed.\n"),
4784 virNWFilterGetName (nwfilter
));
4789 /* Now re-read the network filter XML. Did someone else change it while
4790 * it was being edited? This also catches problems such as us
4791 * losing a connection or the interface going away.
4793 doc_reread
= virNWFilterGetXMLDesc (nwfilter
, 0);
4797 if (STRNEQ (doc
, doc_reread
)) {
4799 _("ERROR: the XML configuration was changed by another user"));
4803 /* Everything checks out, so redefine the interface. */
4804 virNWFilterFree (nwfilter
);
4805 nwfilter
= virNWFilterDefineXML (ctl
->conn
, doc_edited
);
4809 vshPrint (ctl
, _("Network filter %s XML configuration edited.\n"),
4810 virNWFilterGetName(nwfilter
));
4816 virNWFilterFree (nwfilter
);
4819 VIR_FREE(doc_edited
);
4820 VIR_FREE(doc_reread
);
4831 /**************************************************************************/
4833 * "pool-autostart" command
4835 static const vshCmdInfo info_pool_autostart
[] = {
4836 {"help", N_("autostart a pool")},
4838 N_("Configure a pool to be automatically started at boot.")},
4842 static const vshCmdOptDef opts_pool_autostart
[] = {
4843 {"pool", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("pool name or uuid")},
4844 {"disable", VSH_OT_BOOL
, 0, N_("disable autostarting")},
4849 cmdPoolAutostart(vshControl
*ctl
, const vshCmd
*cmd
)
4851 virStoragePoolPtr pool
;
4855 if (!vshConnectionUsability(ctl
, ctl
->conn
))
4858 if (!(pool
= vshCommandOptPool(ctl
, cmd
, "pool", &name
)))
4861 autostart
= !vshCommandOptBool(cmd
, "disable");
4863 if (virStoragePoolSetAutostart(pool
, autostart
) < 0) {
4865 vshError(ctl
, _("failed to mark pool %s as autostarted"), name
);
4867 vshError(ctl
, _("failed to unmark pool %s as autostarted"), name
);
4868 virStoragePoolFree(pool
);
4873 vshPrint(ctl
, _("Pool %s marked as autostarted\n"), name
);
4875 vshPrint(ctl
, _("Pool %s unmarked as autostarted\n"), name
);
4877 virStoragePoolFree(pool
);
4882 * "pool-create" command
4884 static const vshCmdInfo info_pool_create
[] = {
4885 {"help", N_("create a pool from an XML file")},
4886 {"desc", N_("Create a pool.")},
4890 static const vshCmdOptDef opts_pool_create
[] = {
4891 {"file", VSH_OT_DATA
, VSH_OFLAG_REQ
,
4892 N_("file containing an XML pool description")},
4897 cmdPoolCreate(vshControl
*ctl
, const vshCmd
*cmd
)
4899 virStoragePoolPtr pool
;
4905 if (!vshConnectionUsability(ctl
, ctl
->conn
))
4908 from
= vshCommandOptString(cmd
, "file", &found
);
4912 if (virFileReadAll(from
, VIRSH_MAX_XML_FILE
, &buffer
) < 0)
4915 pool
= virStoragePoolCreateXML(ctl
->conn
, buffer
, 0);
4919 vshPrint(ctl
, _("Pool %s created from %s\n"),
4920 virStoragePoolGetName(pool
), from
);
4921 virStoragePoolFree(pool
);
4923 vshError(ctl
, _("Failed to create pool from %s"), from
);
4931 * "nodedev-create" command
4933 static const vshCmdInfo info_node_device_create
[] = {
4934 {"help", N_("create a device defined "
4935 "by an XML file on the node")},
4936 {"desc", N_("Create a device on the node. Note that this "
4937 "command creates devices on the physical host "
4938 "that can then be assigned to a virtual machine.")},
4942 static const vshCmdOptDef opts_node_device_create
[] = {
4943 {"file", VSH_OT_DATA
, VSH_OFLAG_REQ
,
4944 N_("file containing an XML description of the device")},
4949 cmdNodeDeviceCreate(vshControl
*ctl
, const vshCmd
*cmd
)
4951 virNodeDevicePtr dev
= NULL
;
4957 if (!vshConnectionUsability(ctl
, ctl
->conn
))
4960 from
= vshCommandOptString(cmd
, "file", &found
);
4965 if (virFileReadAll(from
, VIRSH_MAX_XML_FILE
, &buffer
) < 0)
4968 dev
= virNodeDeviceCreateXML(ctl
->conn
, buffer
, 0);
4972 vshPrint(ctl
, _("Node device %s created from %s\n"),
4973 virNodeDeviceGetName(dev
), from
);
4974 virNodeDeviceFree(dev
);
4976 vshError(ctl
, _("Failed to create node device from %s"), from
);
4985 * "nodedev-destroy" command
4987 static const vshCmdInfo info_node_device_destroy
[] = {
4988 {"help", N_("destroy a device on the node")},
4989 {"desc", N_("Destroy a device on the node. Note that this "
4990 "command destroys devices on the physical host ")},
4994 static const vshCmdOptDef opts_node_device_destroy
[] = {
4995 {"name", VSH_OT_DATA
, VSH_OFLAG_REQ
,
4996 N_("name of the device to be destroyed")},
5001 cmdNodeDeviceDestroy(vshControl
*ctl
, const vshCmd
*cmd
)
5003 virNodeDevicePtr dev
= NULL
;
5008 if (!vshConnectionUsability(ctl
, ctl
->conn
)) {
5012 name
= vshCommandOptString(cmd
, "name", &found
);
5017 dev
= virNodeDeviceLookupByName(ctl
->conn
, name
);
5019 if (virNodeDeviceDestroy(dev
) == 0) {
5020 vshPrint(ctl
, _("Destroyed node device '%s'\n"), name
);
5022 vshError(ctl
, _("Failed to destroy node device '%s'"), name
);
5026 virNodeDeviceFree(dev
);
5032 * XML Building helper for pool-define-as and pool-create-as
5034 static const vshCmdOptDef opts_pool_X_as
[] = {
5035 {"name", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("name of the pool")},
5036 {"print-xml", VSH_OT_BOOL
, 0, N_("print XML document, but don't define/create")},
5037 {"type", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("type of the pool")},
5038 {"source-host", VSH_OT_DATA
, 0, N_("source-host for underlying storage")},
5039 {"source-path", VSH_OT_DATA
, 0, N_("source path for underlying storage")},
5040 {"source-dev", VSH_OT_DATA
, 0, N_("source device for underlying storage")},
5041 {"source-name", VSH_OT_DATA
, 0, N_("source name for underlying storage")},
5042 {"target", VSH_OT_DATA
, 0, N_("target for underlying storage")},
5043 {"source-format", VSH_OT_STRING
, 0, N_("format for underlying storage")},
5047 static int buildPoolXML(const vshCmd
*cmd
, char **retname
, char **xml
) {
5050 char *name
, *type
, *srcHost
, *srcPath
, *srcDev
, *srcName
, *srcFormat
, *target
;
5051 virBuffer buf
= VIR_BUFFER_INITIALIZER
;
5053 name
= vshCommandOptString(cmd
, "name", &found
);
5056 type
= vshCommandOptString(cmd
, "type", &found
);
5060 srcHost
= vshCommandOptString(cmd
, "source-host", &found
);
5061 srcPath
= vshCommandOptString(cmd
, "source-path", &found
);
5062 srcDev
= vshCommandOptString(cmd
, "source-dev", &found
);
5063 srcName
= vshCommandOptString(cmd
, "source-name", &found
);
5064 srcFormat
= vshCommandOptString(cmd
, "source-format", &found
);
5065 target
= vshCommandOptString(cmd
, "target", &found
);
5067 virBufferVSprintf(&buf
, "<pool type='%s'>\n", type
);
5068 virBufferVSprintf(&buf
, " <name>%s</name>\n", name
);
5069 if (srcHost
|| srcPath
|| srcDev
) {
5070 virBufferAddLit(&buf
, " <source>\n");
5073 virBufferVSprintf(&buf
, " <host name='%s'/>\n", srcHost
);
5075 virBufferVSprintf(&buf
, " <dir path='%s'/>\n", srcPath
);
5077 virBufferVSprintf(&buf
, " <device path='%s'/>\n", srcDev
);
5079 virBufferVSprintf(&buf
, " <format type='%s'/>\n", srcFormat
);
5081 virBufferVSprintf(&buf
, " <name>%s</name>\n", srcName
);
5083 virBufferAddLit(&buf
, " </source>\n");
5086 virBufferAddLit(&buf
, " <target>\n");
5087 virBufferVSprintf(&buf
, " <path>%s</path>\n", target
);
5088 virBufferAddLit(&buf
, " </target>\n");
5090 virBufferAddLit(&buf
, "</pool>\n");
5092 if (virBufferError(&buf
)) {
5093 vshPrint(ctl
, "%s", _("Failed to allocate XML buffer"));
5097 *xml
= virBufferContentAndReset(&buf
);
5102 virBufferFreeAndReset(&buf
);
5107 * "pool-create-as" command
5109 static const vshCmdInfo info_pool_create_as
[] = {
5110 {"help", N_("create a pool from a set of args")},
5111 {"desc", N_("Create a pool.")},
5116 cmdPoolCreateAs(vshControl
*ctl
, const vshCmd
*cmd
)
5118 virStoragePoolPtr pool
;
5120 int printXML
= vshCommandOptBool(cmd
, "print-xml");
5122 if (!vshConnectionUsability(ctl
, ctl
->conn
))
5125 if (!buildPoolXML(cmd
, &name
, &xml
))
5129 vshPrint(ctl
, "%s", xml
);
5132 pool
= virStoragePoolCreateXML(ctl
->conn
, xml
, 0);
5136 vshPrint(ctl
, _("Pool %s created\n"), name
);
5137 virStoragePoolFree(pool
);
5139 vshError(ctl
, _("Failed to create pool %s"), name
);
5148 * "pool-define" command
5150 static const vshCmdInfo info_pool_define
[] = {
5151 {"help", N_("define (but don't start) a pool from an XML file")},
5152 {"desc", N_("Define a pool.")},
5156 static const vshCmdOptDef opts_pool_define
[] = {
5157 {"file", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("file containing an XML pool description")},
5162 cmdPoolDefine(vshControl
*ctl
, const vshCmd
*cmd
)
5164 virStoragePoolPtr pool
;
5170 if (!vshConnectionUsability(ctl
, ctl
->conn
))
5173 from
= vshCommandOptString(cmd
, "file", &found
);
5177 if (virFileReadAll(from
, VIRSH_MAX_XML_FILE
, &buffer
) < 0)
5180 pool
= virStoragePoolDefineXML(ctl
->conn
, buffer
, 0);
5184 vshPrint(ctl
, _("Pool %s defined from %s\n"),
5185 virStoragePoolGetName(pool
), from
);
5186 virStoragePoolFree(pool
);
5188 vshError(ctl
, _("Failed to define pool from %s"), from
);
5196 * "pool-define-as" command
5198 static const vshCmdInfo info_pool_define_as
[] = {
5199 {"help", N_("define a pool from a set of args")},
5200 {"desc", N_("Define a pool.")},
5205 cmdPoolDefineAs(vshControl
*ctl
, const vshCmd
*cmd
)
5207 virStoragePoolPtr pool
;
5209 int printXML
= vshCommandOptBool(cmd
, "print-xml");
5211 if (!vshConnectionUsability(ctl
, ctl
->conn
))
5214 if (!buildPoolXML(cmd
, &name
, &xml
))
5218 vshPrint(ctl
, "%s", xml
);
5221 pool
= virStoragePoolDefineXML(ctl
->conn
, xml
, 0);
5225 vshPrint(ctl
, _("Pool %s defined\n"), name
);
5226 virStoragePoolFree(pool
);
5228 vshError(ctl
, _("Failed to define pool %s"), name
);
5237 * "pool-build" command
5239 static const vshCmdInfo info_pool_build
[] = {
5240 {"help", N_("build a pool")},
5241 {"desc", N_("Build a given pool.")},
5245 static const vshCmdOptDef opts_pool_build
[] = {
5246 {"pool", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("pool name or uuid")},
5251 cmdPoolBuild(vshControl
*ctl
, const vshCmd
*cmd
)
5253 virStoragePoolPtr pool
;
5257 if (!vshConnectionUsability(ctl
, ctl
->conn
))
5260 if (!(pool
= vshCommandOptPool(ctl
, cmd
, "pool", &name
)))
5263 if (virStoragePoolBuild(pool
, 0) == 0) {
5264 vshPrint(ctl
, _("Pool %s built\n"), name
);
5266 vshError(ctl
, _("Failed to build pool %s"), name
);
5270 virStoragePoolFree(pool
);
5277 * "pool-destroy" command
5279 static const vshCmdInfo info_pool_destroy
[] = {
5280 {"help", N_("destroy a pool")},
5281 {"desc", N_("Destroy a given pool.")},
5285 static const vshCmdOptDef opts_pool_destroy
[] = {
5286 {"pool", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("pool name or uuid")},
5291 cmdPoolDestroy(vshControl
*ctl
, const vshCmd
*cmd
)
5293 virStoragePoolPtr pool
;
5297 if (!vshConnectionUsability(ctl
, ctl
->conn
))
5300 if (!(pool
= vshCommandOptPool(ctl
, cmd
, "pool", &name
)))
5303 if (virStoragePoolDestroy(pool
) == 0) {
5304 vshPrint(ctl
, _("Pool %s destroyed\n"), name
);
5306 vshError(ctl
, _("Failed to destroy pool %s"), name
);
5310 virStoragePoolFree(pool
);
5316 * "pool-delete" command
5318 static const vshCmdInfo info_pool_delete
[] = {
5319 {"help", N_("delete a pool")},
5320 {"desc", N_("Delete a given pool.")},
5324 static const vshCmdOptDef opts_pool_delete
[] = {
5325 {"pool", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("pool name or uuid")},
5330 cmdPoolDelete(vshControl
*ctl
, const vshCmd
*cmd
)
5332 virStoragePoolPtr pool
;
5336 if (!vshConnectionUsability(ctl
, ctl
->conn
))
5339 if (!(pool
= vshCommandOptPool(ctl
, cmd
, "pool", &name
)))
5342 if (virStoragePoolDelete(pool
, 0) == 0) {
5343 vshPrint(ctl
, _("Pool %s deleted\n"), name
);
5345 vshError(ctl
, _("Failed to delete pool %s"), name
);
5349 virStoragePoolFree(pool
);
5355 * "pool-refresh" command
5357 static const vshCmdInfo info_pool_refresh
[] = {
5358 {"help", N_("refresh a pool")},
5359 {"desc", N_("Refresh a given pool.")},
5363 static const vshCmdOptDef opts_pool_refresh
[] = {
5364 {"pool", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("pool name or uuid")},
5369 cmdPoolRefresh(vshControl
*ctl
, const vshCmd
*cmd
)
5371 virStoragePoolPtr pool
;
5375 if (!vshConnectionUsability(ctl
, ctl
->conn
))
5378 if (!(pool
= vshCommandOptPool(ctl
, cmd
, "pool", &name
)))
5381 if (virStoragePoolRefresh(pool
, 0) == 0) {
5382 vshPrint(ctl
, _("Pool %s refreshed\n"), name
);
5384 vshError(ctl
, _("Failed to refresh pool %s"), name
);
5387 virStoragePoolFree(pool
);
5394 * "pool-dumpxml" command
5396 static const vshCmdInfo info_pool_dumpxml
[] = {
5397 {"help", N_("pool information in XML")},
5398 {"desc", N_("Output the pool information as an XML dump to stdout.")},
5402 static const vshCmdOptDef opts_pool_dumpxml
[] = {
5403 {"pool", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("pool name or uuid")},
5408 cmdPoolDumpXML(vshControl
*ctl
, const vshCmd
*cmd
)
5410 virStoragePoolPtr pool
;
5414 if (!vshConnectionUsability(ctl
, ctl
->conn
))
5417 if (!(pool
= vshCommandOptPool(ctl
, cmd
, "pool", NULL
)))
5420 dump
= virStoragePoolGetXMLDesc(pool
, 0);
5422 vshPrint(ctl
, "%s", dump
);
5428 virStoragePoolFree(pool
);
5434 * "pool-list" command
5436 static const vshCmdInfo info_pool_list
[] = {
5437 {"help", N_("list pools")},
5438 {"desc", N_("Returns list of pools.")},
5442 static const vshCmdOptDef opts_pool_list
[] = {
5443 {"inactive", VSH_OT_BOOL
, 0, N_("list inactive pools")},
5444 {"all", VSH_OT_BOOL
, 0, N_("list inactive & active pools")},
5445 {"details", VSH_OT_BOOL
, 0, N_("display extended details for pools")},
5450 cmdPoolList(vshControl
*ctl
, const vshCmd
*cmd ATTRIBUTE_UNUSED
)
5452 virStoragePoolInfo info
;
5453 char **poolNames
= NULL
;
5454 int i
, functionReturn
, ret
;
5455 int numActivePools
= 0, numInactivePools
= 0, numAllPools
= 0;
5456 size_t stringLength
= 0, nameStrLength
= 0;
5457 size_t autostartStrLength
= 0, persistStrLength
= 0;
5458 size_t stateStrLength
= 0, capStrLength
= 0;
5459 size_t allocStrLength
= 0, availStrLength
= 0;
5460 struct poolInfoText
{
5468 struct poolInfoText
*poolInfoTexts
= NULL
;
5470 /* Determine the options passed by the user */
5471 int all
= vshCommandOptBool(cmd
, "all");
5472 int details
= vshCommandOptBool(cmd
, "details");
5473 int inactive
= vshCommandOptBool(cmd
, "inactive");
5474 int active
= !inactive
|| all
? 1 : 0;
5477 /* Check the connection to libvirtd daemon is still working */
5478 if (!vshConnectionUsability(ctl
, ctl
->conn
))
5481 /* Retrieve the number of active storage pools */
5483 numActivePools
= virConnectNumOfStoragePools(ctl
->conn
);
5484 if (numActivePools
< 0) {
5485 vshError(ctl
, "%s", _("Failed to list active pools"));
5490 /* Retrieve the number of inactive storage pools */
5492 numInactivePools
= virConnectNumOfDefinedStoragePools(ctl
->conn
);
5493 if (numInactivePools
< 0) {
5494 vshError(ctl
, "%s", _("Failed to list inactive pools"));
5499 /* Determine the total number of pools to list */
5500 numAllPools
= numActivePools
+ numInactivePools
;
5502 /* Allocate memory for arrays of storage pool names and info */
5503 poolNames
= vshCalloc(ctl
, numAllPools
, sizeof(*poolNames
));
5505 vshCalloc(ctl
, numAllPools
, sizeof(*poolInfoTexts
));
5507 /* Retrieve a list of active storage pool names */
5509 if ((virConnectListStoragePools(ctl
->conn
,
5510 poolNames
, numActivePools
)) < 0) {
5511 vshError(ctl
, "%s", _("Failed to list active pools"));
5512 VIR_FREE(poolInfoTexts
);
5513 VIR_FREE(poolNames
);
5518 /* Add the inactive storage pools to the end of the name list */
5520 if ((virConnectListDefinedStoragePools(ctl
->conn
,
5521 &poolNames
[numActivePools
],
5522 numInactivePools
)) < 0) {
5523 vshError(ctl
, "%s", _("Failed to list inactive pools"));
5524 VIR_FREE(poolInfoTexts
);
5525 VIR_FREE(poolNames
);
5530 /* Sort the storage pool names */
5531 qsort(poolNames
, numAllPools
, sizeof(*poolNames
), namesorter
);
5533 /* Collect the storage pool information for display */
5534 for (i
= 0; i
< numAllPools
; i
++) {
5535 int autostart
= 0, persistent
= 0;
5537 /* Retrieve a pool object, looking it up by name */
5538 virStoragePoolPtr pool
= virStoragePoolLookupByName(ctl
->conn
,
5541 VIR_FREE(poolNames
[i
]);
5545 /* Retrieve the autostart status of the pool */
5546 if (virStoragePoolGetAutostart(pool
, &autostart
) < 0)
5547 poolInfoTexts
[i
].autostart
= vshStrdup(ctl
, _("no autostart"));
5549 poolInfoTexts
[i
].autostart
= vshStrdup(ctl
, autostart
?
5550 _("yes") : _("no"));
5552 /* Retrieve the persistence status of the pool */
5554 persistent
= virStoragePoolIsPersistent(pool
);
5555 vshDebug(ctl
, 5, "Persistent flag value: %d\n", persistent
);
5557 poolInfoTexts
[i
].persistent
= vshStrdup(ctl
, _("unknown"));
5559 poolInfoTexts
[i
].persistent
= vshStrdup(ctl
, persistent
?
5560 _("yes") : _("no"));
5562 /* Keep the length of persistent string if longest so far */
5563 stringLength
= strlen(poolInfoTexts
[i
].persistent
);
5564 if (stringLength
> persistStrLength
)
5565 persistStrLength
= stringLength
;
5568 /* Collect further extended information about the pool */
5569 if (virStoragePoolGetInfo(pool
, &info
) != 0) {
5570 /* Something went wrong retrieving pool info, cope with it */
5571 vshError(ctl
, "%s", _("Could not retrieve pool information"));
5572 poolInfoTexts
[i
].state
= vshStrdup(ctl
, _("unknown"));
5574 poolInfoTexts
[i
].capacity
= vshStrdup(ctl
, _("unknown"));
5575 poolInfoTexts
[i
].allocation
= vshStrdup(ctl
, _("unknown"));
5576 poolInfoTexts
[i
].available
= vshStrdup(ctl
, _("unknown"));
5579 /* Decide which state string to display */
5581 /* --details option was specified, we're using detailed state
5583 switch (info
.state
) {
5584 case VIR_STORAGE_POOL_INACTIVE
:
5585 poolInfoTexts
[i
].state
= vshStrdup(ctl
, _("inactive"));
5587 case VIR_STORAGE_POOL_BUILDING
:
5588 poolInfoTexts
[i
].state
= vshStrdup(ctl
, _("building"));
5590 case VIR_STORAGE_POOL_RUNNING
:
5591 poolInfoTexts
[i
].state
= vshStrdup(ctl
, _("running"));
5593 case VIR_STORAGE_POOL_DEGRADED
:
5594 poolInfoTexts
[i
].state
= vshStrdup(ctl
, _("degraded"));
5596 case VIR_STORAGE_POOL_INACCESSIBLE
:
5597 poolInfoTexts
[i
].state
= vshStrdup(ctl
, _("inaccessible"));
5601 /* Create the pool size related strings */
5602 if (info
.state
== VIR_STORAGE_POOL_RUNNING
||
5603 info
.state
== VIR_STORAGE_POOL_DEGRADED
) {
5607 /* Create the capacity output string */
5608 val
= prettyCapacity(info
.capacity
, &unit
);
5609 ret
= virAsprintf(&poolInfoTexts
[i
].capacity
,
5610 "%.2lf %s", val
, unit
);
5612 /* An error occurred creating the string, return */
5613 goto asprintf_failure
;
5616 /* Create the allocation output string */
5617 val
= prettyCapacity(info
.allocation
, &unit
);
5618 ret
= virAsprintf(&poolInfoTexts
[i
].allocation
,
5619 "%.2lf %s", val
, unit
);
5621 /* An error occurred creating the string, return */
5622 goto asprintf_failure
;
5625 /* Create the available space output string */
5626 val
= prettyCapacity(info
.available
, &unit
);
5627 ret
= virAsprintf(&poolInfoTexts
[i
].available
,
5628 "%.2lf %s", val
, unit
);
5630 /* An error occurred creating the string, return */
5631 goto asprintf_failure
;
5634 /* Capacity related information isn't available */
5635 poolInfoTexts
[i
].capacity
= vshStrdup(ctl
, _("-"));
5636 poolInfoTexts
[i
].allocation
= vshStrdup(ctl
, _("-"));
5637 poolInfoTexts
[i
].available
= vshStrdup(ctl
, _("-"));
5640 /* Keep the length of capacity string if longest so far */
5641 stringLength
= strlen(poolInfoTexts
[i
].capacity
);
5642 if (stringLength
> capStrLength
)
5643 capStrLength
= stringLength
;
5645 /* Keep the length of allocation string if longest so far */
5646 stringLength
= strlen(poolInfoTexts
[i
].allocation
);
5647 if (stringLength
> allocStrLength
)
5648 allocStrLength
= stringLength
;
5650 /* Keep the length of available string if longest so far */
5651 stringLength
= strlen(poolInfoTexts
[i
].available
);
5652 if (stringLength
> availStrLength
)
5653 availStrLength
= stringLength
;
5655 /* --details option was not specified, only active/inactive
5656 * state strings are used */
5657 if (info
.state
== VIR_STORAGE_POOL_INACTIVE
)
5658 poolInfoTexts
[i
].state
= vshStrdup(ctl
, _("inactive"));
5660 poolInfoTexts
[i
].state
= vshStrdup(ctl
, _("active"));
5664 /* Keep the length of name string if longest so far */
5665 stringLength
= strlen(poolNames
[i
]);
5666 if (stringLength
> nameStrLength
)
5667 nameStrLength
= stringLength
;
5669 /* Keep the length of state string if longest so far */
5670 stringLength
= strlen(poolInfoTexts
[i
].state
);
5671 if (stringLength
> stateStrLength
)
5672 stateStrLength
= stringLength
;
5674 /* Keep the length of autostart string if longest so far */
5675 stringLength
= strlen(poolInfoTexts
[i
].autostart
);
5676 if (stringLength
> autostartStrLength
)
5677 autostartStrLength
= stringLength
;
5679 /* Free the pool object */
5680 virStoragePoolFree(pool
);
5683 /* If the --details option wasn't selected, we output the pool
5684 * info using the fixed string format from previous versions to
5685 * maintain backward compatibility.
5688 /* Output basic info then return if --details option not selected */
5690 /* Output old style header */
5691 vshPrintExtra(ctl
, "%-20s %-10s %-10s\n", _("Name"), _("State"),
5693 vshPrintExtra(ctl
, "-----------------------------------------\n");
5695 /* Output old style pool info */
5696 for (i
= 0; i
< numAllPools
; i
++) {
5697 vshPrint(ctl
, "%-20s %-10s %-10s\n",
5699 poolInfoTexts
[i
].state
,
5700 poolInfoTexts
[i
].autostart
);
5703 /* Cleanup and return */
5704 functionReturn
= TRUE
;
5708 /* We only get here if the --details option was selected. */
5710 /* Use the length of name header string if it's longest */
5711 stringLength
= strlen(_("Name"));
5712 if (stringLength
> nameStrLength
)
5713 nameStrLength
= stringLength
;
5715 /* Use the length of state header string if it's longest */
5716 stringLength
= strlen(_("State"));
5717 if (stringLength
> stateStrLength
)
5718 stateStrLength
= stringLength
;
5720 /* Use the length of autostart header string if it's longest */
5721 stringLength
= strlen(_("Autostart"));
5722 if (stringLength
> autostartStrLength
)
5723 autostartStrLength
= stringLength
;
5725 /* Use the length of persistent header string if it's longest */
5726 stringLength
= strlen(_("Persistent"));
5727 if (stringLength
> persistStrLength
)
5728 persistStrLength
= stringLength
;
5730 /* Use the length of capacity header string if it's longest */
5731 stringLength
= strlen(_("Capacity"));
5732 if (stringLength
> capStrLength
)
5733 capStrLength
= stringLength
;
5735 /* Use the length of allocation header string if it's longest */
5736 stringLength
= strlen(_("Allocation"));
5737 if (stringLength
> allocStrLength
)
5738 allocStrLength
= stringLength
;
5740 /* Use the length of available header string if it's longest */
5741 stringLength
= strlen(_("Available"));
5742 if (stringLength
> availStrLength
)
5743 availStrLength
= stringLength
;
5745 /* Display the string lengths for debugging. */
5746 vshDebug(ctl
, 5, "Longest name string = %lu chars\n",
5747 (unsigned long) nameStrLength
);
5748 vshDebug(ctl
, 5, "Longest state string = %lu chars\n",
5749 (unsigned long) stateStrLength
);
5750 vshDebug(ctl
, 5, "Longest autostart string = %lu chars\n",
5751 (unsigned long) autostartStrLength
);
5752 vshDebug(ctl
, 5, "Longest persistent string = %lu chars\n",
5753 (unsigned long) persistStrLength
);
5754 vshDebug(ctl
, 5, "Longest capacity string = %lu chars\n",
5755 (unsigned long) capStrLength
);
5756 vshDebug(ctl
, 5, "Longest allocation string = %lu chars\n",
5757 (unsigned long) allocStrLength
);
5758 vshDebug(ctl
, 5, "Longest available string = %lu chars\n",
5759 (unsigned long) availStrLength
);
5761 /* Create the output template. Each column is sized according to
5762 * the longest string.
5765 ret
= virAsprintf(&outputStr
,
5766 "%%-%lus %%-%lus %%-%lus %%-%lus %%%lus %%%lus %%%lus\n",
5767 (unsigned long) nameStrLength
,
5768 (unsigned long) stateStrLength
,
5769 (unsigned long) autostartStrLength
,
5770 (unsigned long) persistStrLength
,
5771 (unsigned long) capStrLength
,
5772 (unsigned long) allocStrLength
,
5773 (unsigned long) availStrLength
);
5775 /* An error occurred creating the string, return */
5776 goto asprintf_failure
;
5779 /* Display the header */
5780 vshPrint(ctl
, outputStr
, _("Name"), _("State"), _("Autostart"),
5781 _("Persistent"), _("Capacity"), _("Allocation"), _("Available"));
5782 for (i
= nameStrLength
+ stateStrLength
+ autostartStrLength
5783 + persistStrLength
+ capStrLength
5784 + allocStrLength
+ availStrLength
5786 vshPrintExtra(ctl
, "-");
5787 vshPrintExtra(ctl
, "\n");
5789 /* Display the pool info rows */
5790 for (i
= 0; i
< numAllPools
; i
++) {
5791 vshPrint(ctl
, outputStr
,
5793 poolInfoTexts
[i
].state
,
5794 poolInfoTexts
[i
].autostart
,
5795 poolInfoTexts
[i
].persistent
,
5796 poolInfoTexts
[i
].capacity
,
5797 poolInfoTexts
[i
].allocation
,
5798 poolInfoTexts
[i
].available
);
5801 /* Cleanup and return */
5802 functionReturn
= TRUE
;
5807 /* Display an appropriate error message then cleanup and return */
5810 /* Couldn't allocate memory */
5811 vshError(ctl
, "%s", _("Out of memory"));
5814 /* Some other error */
5815 vshError(ctl
, _("virAsprintf failed (errno %d)"), errno
);
5817 functionReturn
= FALSE
;
5821 /* Safely free the memory allocated in this function */
5822 for (i
= 0; i
< numAllPools
; i
++) {
5823 /* Cleanup the memory for one pool info structure */
5824 VIR_FREE(poolInfoTexts
[i
].state
);
5825 VIR_FREE(poolInfoTexts
[i
].autostart
);
5826 VIR_FREE(poolInfoTexts
[i
].persistent
);
5827 VIR_FREE(poolInfoTexts
[i
].capacity
);
5828 VIR_FREE(poolInfoTexts
[i
].allocation
);
5829 VIR_FREE(poolInfoTexts
[i
].available
);
5830 VIR_FREE(poolNames
[i
]);
5833 /* Cleanup the memory for the initial arrays*/
5834 VIR_FREE(poolInfoTexts
);
5835 VIR_FREE(poolNames
);
5837 /* Return the desired value */
5838 return functionReturn
;
5842 * "find-storage-pool-sources-as" command
5844 static const vshCmdInfo info_find_storage_pool_sources_as
[] = {
5845 {"help", N_("find potential storage pool sources")},
5846 {"desc", N_("Returns XML <sources> document.")},
5850 static const vshCmdOptDef opts_find_storage_pool_sources_as
[] = {
5851 {"type", VSH_OT_DATA
, VSH_OFLAG_REQ
,
5852 N_("type of storage pool sources to find")},
5853 {"host", VSH_OT_DATA
, VSH_OFLAG_NONE
, N_("optional host to query")},
5854 {"port", VSH_OT_DATA
, VSH_OFLAG_NONE
, N_("optional port to query")},
5855 {"initiator", VSH_OT_DATA
, VSH_OFLAG_NONE
, N_("optional initiator IQN to use for query")},
5860 cmdPoolDiscoverSourcesAs(vshControl
* ctl
, const vshCmd
* cmd ATTRIBUTE_UNUSED
)
5863 char *srcSpec
= NULL
;
5868 type
= vshCommandOptString(cmd
, "type", &found
);
5871 host
= vshCommandOptString(cmd
, "host", &found
);
5874 initiator
= vshCommandOptString(cmd
, "initiator", &found
);
5878 if (!vshConnectionUsability(ctl
, ctl
->conn
))
5882 char *port
= vshCommandOptString(cmd
, "port", &found
);
5885 virBuffer buf
= VIR_BUFFER_INITIALIZER
;
5886 virBufferAddLit(&buf
, "<source>\n");
5887 virBufferVSprintf(&buf
, " <host name='%s'", host
);
5889 virBufferVSprintf(&buf
, " port='%s'", port
);
5890 virBufferAddLit(&buf
, "/>\n");
5892 virBufferAddLit(&buf
, " <initiator>\n");
5893 virBufferVSprintf(&buf
, " <iqn name='%s'/>\n", initiator
);
5894 virBufferAddLit(&buf
, " </initiator>\n");
5896 virBufferAddLit(&buf
, "</source>\n");
5897 if (virBufferError(&buf
)) {
5898 vshError(ctl
, "%s", _("Out of memory"));
5901 srcSpec
= virBufferContentAndReset(&buf
);
5904 srcList
= virConnectFindStoragePoolSources(ctl
->conn
, type
, srcSpec
, 0);
5906 if (srcList
== NULL
) {
5907 vshError(ctl
, _("Failed to find any %s pool sources"), type
);
5910 vshPrint(ctl
, "%s", srcList
);
5918 * "find-storage-pool-sources" command
5920 static const vshCmdInfo info_find_storage_pool_sources
[] = {
5921 {"help", N_("discover potential storage pool sources")},
5922 {"desc", N_("Returns XML <sources> document.")},
5926 static const vshCmdOptDef opts_find_storage_pool_sources
[] = {
5927 {"type", VSH_OT_DATA
, VSH_OFLAG_REQ
,
5928 N_("type of storage pool sources to discover")},
5929 {"srcSpec", VSH_OT_DATA
, VSH_OFLAG_NONE
,
5930 N_("optional file of source xml to query for pools")},
5935 cmdPoolDiscoverSources(vshControl
* ctl
, const vshCmd
* cmd ATTRIBUTE_UNUSED
)
5937 char *type
, *srcSpecFile
, *srcList
;
5938 char *srcSpec
= NULL
;
5941 type
= vshCommandOptString(cmd
, "type", &found
);
5944 srcSpecFile
= vshCommandOptString(cmd
, "srcSpec", &found
);
5948 if (!vshConnectionUsability(ctl
, ctl
->conn
))
5951 if (srcSpecFile
&& virFileReadAll(srcSpecFile
, VIRSH_MAX_XML_FILE
, &srcSpec
) < 0)
5954 srcList
= virConnectFindStoragePoolSources(ctl
->conn
, type
, srcSpec
, 0);
5956 if (srcList
== NULL
) {
5957 vshError(ctl
, _("Failed to find any %s pool sources"), type
);
5960 vshPrint(ctl
, "%s", srcList
);
5968 * "pool-info" command
5970 static const vshCmdInfo info_pool_info
[] = {
5971 {"help", N_("storage pool information")},
5972 {"desc", N_("Returns basic information about the storage pool.")},
5976 static const vshCmdOptDef opts_pool_info
[] = {
5977 {"pool", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("pool name or uuid")},
5982 cmdPoolInfo(vshControl
*ctl
, const vshCmd
*cmd
)
5984 virStoragePoolInfo info
;
5985 virStoragePoolPtr pool
;
5989 char uuid
[VIR_UUID_STRING_BUFLEN
];
5991 if (!vshConnectionUsability(ctl
, ctl
->conn
))
5994 if (!(pool
= vshCommandOptPool(ctl
, cmd
, "pool", NULL
)))
5997 vshPrint(ctl
, "%-15s %s\n", _("Name:"), virStoragePoolGetName(pool
));
5999 if (virStoragePoolGetUUIDString(pool
, &uuid
[0])==0)
6000 vshPrint(ctl
, "%-15s %s\n", _("UUID:"), uuid
);
6002 if (virStoragePoolGetInfo(pool
, &info
) == 0) {
6005 switch (info
.state
) {
6006 case VIR_STORAGE_POOL_INACTIVE
:
6007 vshPrint(ctl
, "%-15s %s\n", _("State:"),
6010 case VIR_STORAGE_POOL_BUILDING
:
6011 vshPrint(ctl
, "%-15s %s\n", _("State:"),
6014 case VIR_STORAGE_POOL_RUNNING
:
6015 vshPrint(ctl
, "%-15s %s\n", _("State:"),
6018 case VIR_STORAGE_POOL_DEGRADED
:
6019 vshPrint(ctl
, "%-15s %s\n", _("State:"),
6022 case VIR_STORAGE_POOL_INACCESSIBLE
:
6023 vshPrint(ctl
, "%-15s %s\n", _("State:"),
6028 /* Check and display whether the pool is persistent or not */
6029 persistent
= virStoragePoolIsPersistent(pool
);
6030 vshDebug(ctl
, 5, "Pool persistent flag value: %d\n", persistent
);
6032 vshPrint(ctl
, "%-15s %s\n", _("Persistent:"), _("unknown"));
6034 vshPrint(ctl
, "%-15s %s\n", _("Persistent:"), persistent
? _("yes") : _("no"));
6036 /* Check and display whether the pool is autostarted or not */
6037 virStoragePoolGetAutostart(pool
, &autostart
);
6038 vshDebug(ctl
, 5, "Pool autostart flag value: %d\n", autostart
);
6040 vshPrint(ctl
, "%-15s %s\n", _("Autostart:"), _("no autostart"));
6042 vshPrint(ctl
, "%-15s %s\n", _("Autostart:"), autostart
? _("yes") : _("no"));
6044 if (info
.state
== VIR_STORAGE_POOL_RUNNING
||
6045 info
.state
== VIR_STORAGE_POOL_DEGRADED
) {
6046 val
= prettyCapacity(info
.capacity
, &unit
);
6047 vshPrint(ctl
, "%-15s %2.2lf %s\n", _("Capacity:"), val
, unit
);
6049 val
= prettyCapacity(info
.allocation
, &unit
);
6050 vshPrint(ctl
, "%-15s %2.2lf %s\n", _("Allocation:"), val
, unit
);
6052 val
= prettyCapacity(info
.available
, &unit
);
6053 vshPrint(ctl
, "%-15s %2.2lf %s\n", _("Available:"), val
, unit
);
6059 virStoragePoolFree(pool
);
6065 * "pool-name" command
6067 static const vshCmdInfo info_pool_name
[] = {
6068 {"help", N_("convert a pool UUID to pool name")},
6073 static const vshCmdOptDef opts_pool_name
[] = {
6074 {"pool", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("pool uuid")},
6079 cmdPoolName(vshControl
*ctl
, const vshCmd
*cmd
)
6081 virStoragePoolPtr pool
;
6083 if (!vshConnectionUsability(ctl
, ctl
->conn
))
6085 if (!(pool
= vshCommandOptPoolBy(ctl
, cmd
, "pool", NULL
,
6089 vshPrint(ctl
, "%s\n", virStoragePoolGetName(pool
));
6090 virStoragePoolFree(pool
);
6096 * "pool-start" command
6098 static const vshCmdInfo info_pool_start
[] = {
6099 {"help", N_("start a (previously defined) inactive pool")},
6100 {"desc", N_("Start a pool.")},
6104 static const vshCmdOptDef opts_pool_start
[] = {
6105 {"pool", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("name of the inactive pool")},
6110 cmdPoolStart(vshControl
*ctl
, const vshCmd
*cmd
)
6112 virStoragePoolPtr pool
;
6115 if (!vshConnectionUsability(ctl
, ctl
->conn
))
6118 if (!(pool
= vshCommandOptPoolBy(ctl
, cmd
, "pool", NULL
, VSH_BYNAME
)))
6121 if (virStoragePoolCreate(pool
, 0) == 0) {
6122 vshPrint(ctl
, _("Pool %s started\n"),
6123 virStoragePoolGetName(pool
));
6125 vshError(ctl
, _("Failed to start pool %s"), virStoragePoolGetName(pool
));
6129 virStoragePoolFree(pool
);
6135 * "vol-create-as" command
6137 static const vshCmdInfo info_vol_create_as
[] = {
6138 {"help", N_("create a volume from a set of args")},
6139 {"desc", N_("Create a vol.")},
6143 static const vshCmdOptDef opts_vol_create_as
[] = {
6144 {"pool", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("pool name")},
6145 {"name", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("name of the volume")},
6146 {"capacity", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("size of the vol with optional k,M,G,T suffix")},
6147 {"allocation", VSH_OT_STRING
, 0, N_("initial allocation size with optional k,M,G,T suffix")},
6148 {"format", VSH_OT_STRING
, 0, N_("file format type raw,bochs,qcow,qcow2,vmdk")},
6149 {"backing-vol", VSH_OT_STRING
, 0, N_("the backing volume if taking a snapshot")},
6150 {"backing-vol-format", VSH_OT_STRING
, 0, N_("format of backing volume if taking a snapshot")},
6154 static int cmdVolSize(const char *data
, unsigned long long *val
)
6157 if (virStrToLong_ull(data
, &end
, 10, val
) < 0)
6161 /* Deliberate fallthrough cases here :-) */
6183 cmdVolCreateAs(vshControl
*ctl
, const vshCmd
*cmd
)
6185 virStoragePoolPtr pool
;
6186 virStorageVolPtr vol
;
6189 char *name
, *capacityStr
, *allocationStr
, *format
;
6190 char *snapshotStrVol
, *snapshotStrFormat
;
6191 unsigned long long capacity
, allocation
= 0;
6192 virBuffer buf
= VIR_BUFFER_INITIALIZER
;
6194 if (!vshConnectionUsability(ctl
, ctl
->conn
))
6197 if (!(pool
= vshCommandOptPoolBy(ctl
, cmd
, "pool", NULL
,
6201 name
= vshCommandOptString(cmd
, "name", &found
);
6205 capacityStr
= vshCommandOptString(cmd
, "capacity", &found
);
6208 if (cmdVolSize(capacityStr
, &capacity
) < 0)
6209 vshError(ctl
, _("Malformed size %s"), capacityStr
);
6211 allocationStr
= vshCommandOptString(cmd
, "allocation", &found
);
6212 if (allocationStr
&&
6213 cmdVolSize(allocationStr
, &allocation
) < 0)
6214 vshError(ctl
, _("Malformed size %s"), allocationStr
);
6216 format
= vshCommandOptString(cmd
, "format", &found
);
6217 snapshotStrVol
= vshCommandOptString(cmd
, "backing-vol", &found
);
6218 snapshotStrFormat
= vshCommandOptString(cmd
, "backing-vol-format", &found
);
6220 virBufferAddLit(&buf
, "<volume>\n");
6221 virBufferVSprintf(&buf
, " <name>%s</name>\n", name
);
6222 virBufferVSprintf(&buf
, " <capacity>%llu</capacity>\n", capacity
);
6224 virBufferVSprintf(&buf
, " <allocation>%llu</allocation>\n", allocation
);
6227 virBufferAddLit(&buf
, " <target>\n");
6228 virBufferVSprintf(&buf
, " <format type='%s'/>\n",format
);
6229 virBufferAddLit(&buf
, " </target>\n");
6232 /* Convert the snapshot parameters into backingStore XML */
6233 if (snapshotStrVol
) {
6234 /* Lookup snapshot backing volume. Try the backing-vol
6235 * parameter as a name */
6236 vshDebug(ctl
, 5, "%s: Look up backing store volume '%s' as name\n",
6237 cmd
->def
->name
, snapshotStrVol
);
6238 virStorageVolPtr snapVol
= virStorageVolLookupByName(pool
, snapshotStrVol
);
6240 vshDebug(ctl
, 5, "%s: Backing store volume found using '%s' as name\n",
6241 cmd
->def
->name
, snapshotStrVol
);
6243 if (snapVol
== NULL
) {
6244 /* Snapshot backing volume not found by name. Try the
6245 * backing-vol parameter as a key */
6246 vshDebug(ctl
, 5, "%s: Look up backing store volume '%s' as key\n",
6247 cmd
->def
->name
, snapshotStrVol
);
6248 snapVol
= virStorageVolLookupByKey(ctl
->conn
, snapshotStrVol
);
6250 vshDebug(ctl
, 5, "%s: Backing store volume found using '%s' as key\n",
6251 cmd
->def
->name
, snapshotStrVol
);
6253 if (snapVol
== NULL
) {
6254 /* Snapshot backing volume not found by key. Try the
6255 * backing-vol parameter as a path */
6256 vshDebug(ctl
, 5, "%s: Look up backing store volume '%s' as path\n",
6257 cmd
->def
->name
, snapshotStrVol
);
6258 snapVol
= virStorageVolLookupByPath(ctl
->conn
, snapshotStrVol
);
6260 vshDebug(ctl
, 5, "%s: Backing store volume found using '%s' as path\n",
6261 cmd
->def
->name
, snapshotStrVol
);
6263 if (snapVol
== NULL
) {
6264 vshError(ctl
, _("failed to get vol '%s'"), snapshotStrVol
);
6268 char *snapshotStrVolPath
;
6269 if ((snapshotStrVolPath
= virStorageVolGetPath(snapVol
)) == NULL
) {
6270 virStorageVolFree(snapVol
);
6274 /* Create XML for the backing store */
6275 virBufferAddLit(&buf
, " <backingStore>\n");
6276 virBufferVSprintf(&buf
, " <path>%s</path>\n",snapshotStrVolPath
);
6277 if (snapshotStrFormat
)
6278 virBufferVSprintf(&buf
, " <format type='%s'/>\n",snapshotStrFormat
);
6279 virBufferAddLit(&buf
, " </backingStore>\n");
6281 /* Cleanup snapshot allocations */
6282 VIR_FREE(snapshotStrVolPath
);
6283 virStorageVolFree(snapVol
);
6286 virBufferAddLit(&buf
, "</volume>\n");
6288 if (virBufferError(&buf
)) {
6289 vshPrint(ctl
, "%s", _("Failed to allocate XML buffer"));
6292 xml
= virBufferContentAndReset(&buf
);
6293 vol
= virStorageVolCreateXML(pool
, xml
, 0);
6295 virStoragePoolFree(pool
);
6298 vshPrint(ctl
, _("Vol %s created\n"), name
);
6299 virStorageVolFree(vol
);
6302 vshError(ctl
, _("Failed to create vol %s"), name
);
6307 virBufferFreeAndReset(&buf
);
6308 virStoragePoolFree(pool
);
6314 * "pool-undefine" command
6316 static const vshCmdInfo info_pool_undefine
[] = {
6317 {"help", N_("undefine an inactive pool")},
6318 {"desc", N_("Undefine the configuration for an inactive pool.")},
6322 static const vshCmdOptDef opts_pool_undefine
[] = {
6323 {"pool", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("pool name or uuid")},
6328 cmdPoolUndefine(vshControl
*ctl
, const vshCmd
*cmd
)
6330 virStoragePoolPtr pool
;
6334 if (!vshConnectionUsability(ctl
, ctl
->conn
))
6337 if (!(pool
= vshCommandOptPool(ctl
, cmd
, "pool", &name
)))
6340 if (virStoragePoolUndefine(pool
) == 0) {
6341 vshPrint(ctl
, _("Pool %s has been undefined\n"), name
);
6343 vshError(ctl
, _("Failed to undefine pool %s"), name
);
6347 virStoragePoolFree(pool
);
6353 * "pool-uuid" command
6355 static const vshCmdInfo info_pool_uuid
[] = {
6356 {"help", N_("convert a pool name to pool UUID")},
6361 static const vshCmdOptDef opts_pool_uuid
[] = {
6362 {"pool", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("pool name")},
6367 cmdPoolUuid(vshControl
*ctl
, const vshCmd
*cmd
)
6369 virStoragePoolPtr pool
;
6370 char uuid
[VIR_UUID_STRING_BUFLEN
];
6372 if (!vshConnectionUsability(ctl
, ctl
->conn
))
6375 if (!(pool
= vshCommandOptPoolBy(ctl
, cmd
, "pool", NULL
,
6379 if (virStoragePoolGetUUIDString(pool
, uuid
) != -1)
6380 vshPrint(ctl
, "%s\n", uuid
);
6382 vshError(ctl
, "%s", _("failed to get pool UUID"));
6384 virStoragePoolFree(pool
);
6390 * "vol-create" command
6392 static const vshCmdInfo info_vol_create
[] = {
6393 {"help", N_("create a vol from an XML file")},
6394 {"desc", N_("Create a vol.")},
6398 static const vshCmdOptDef opts_vol_create
[] = {
6399 {"pool", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("pool name")},
6400 {"file", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("file containing an XML vol description")},
6405 cmdVolCreate(vshControl
*ctl
, const vshCmd
*cmd
)
6407 virStoragePoolPtr pool
;
6408 virStorageVolPtr vol
;
6414 if (!vshConnectionUsability(ctl
, ctl
->conn
))
6417 if (!(pool
= vshCommandOptPoolBy(ctl
, cmd
, "pool", NULL
,
6421 from
= vshCommandOptString(cmd
, "file", &found
);
6423 virStoragePoolFree(pool
);
6427 if (virFileReadAll(from
, VIRSH_MAX_XML_FILE
, &buffer
) < 0) {
6428 virshReportError(ctl
);
6429 virStoragePoolFree(pool
);
6433 vol
= virStorageVolCreateXML(pool
, buffer
, 0);
6435 virStoragePoolFree(pool
);
6438 vshPrint(ctl
, _("Vol %s created from %s\n"),
6439 virStorageVolGetName(vol
), from
);
6440 virStorageVolFree(vol
);
6442 vshError(ctl
, _("Failed to create vol from %s"), from
);
6449 * "vol-create-from" command
6451 static const vshCmdInfo info_vol_create_from
[] = {
6452 {"help", N_("create a vol, using another volume as input")},
6453 {"desc", N_("Create a vol from an existing volume.")},
6457 static const vshCmdOptDef opts_vol_create_from
[] = {
6458 {"pool", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("pool name")},
6459 {"file", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("file containing an XML vol description")},
6460 {"inputpool", VSH_OT_STRING
, 0, N_("pool name or uuid of the input volume's pool")},
6461 {"vol", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("input vol name or key")},
6466 cmdVolCreateFrom(vshControl
*ctl
, const vshCmd
*cmd
)
6468 virStoragePoolPtr pool
= NULL
;
6469 virStorageVolPtr newvol
= NULL
, inputvol
= NULL
;
6473 char *buffer
= NULL
;
6475 if (!vshConnectionUsability(ctl
, ctl
->conn
))
6478 if (!(pool
= vshCommandOptPoolBy(ctl
, cmd
, "pool", NULL
, VSH_BYNAME
)))
6481 from
= vshCommandOptString(cmd
, "file", &found
);
6486 if (!(inputvol
= vshCommandOptVol(ctl
, cmd
, "vol", "inputpool", NULL
)))
6489 if (virFileReadAll(from
, VIRSH_MAX_XML_FILE
, &buffer
) < 0) {
6490 virshReportError(ctl
);
6494 newvol
= virStorageVolCreateXMLFrom(pool
, buffer
, inputvol
, 0);
6496 if (newvol
!= NULL
) {
6497 vshPrint(ctl
, _("Vol %s created from input vol %s\n"),
6498 virStorageVolGetName(newvol
), virStorageVolGetName(inputvol
));
6500 vshError(ctl
, _("Failed to create vol from %s"), from
);
6508 virStoragePoolFree(pool
);
6510 virStorageVolFree(inputvol
);
6512 virStorageVolFree(newvol
);
6517 makeCloneXML(char *origxml
, char *newname
) {
6519 xmlDocPtr doc
= NULL
;
6520 xmlXPathContextPtr ctxt
= NULL
;
6521 xmlXPathObjectPtr obj
= NULL
;
6522 xmlChar
*newxml
= NULL
;
6525 doc
= xmlReadDoc((const xmlChar
*) origxml
, "domain.xml", NULL
,
6526 XML_PARSE_NOENT
| XML_PARSE_NONET
| XML_PARSE_NOWARNING
);
6529 ctxt
= xmlXPathNewContext(doc
);
6533 obj
= xmlXPathEval(BAD_CAST
"/volume/name", ctxt
);
6534 if ((obj
== NULL
) || (obj
->nodesetval
== NULL
) ||
6535 (obj
->nodesetval
->nodeTab
== NULL
))
6538 xmlNodeSetContent(obj
->nodesetval
->nodeTab
[0], (const xmlChar
*)newname
);
6539 xmlDocDumpMemory(doc
, &newxml
, &size
);
6542 xmlXPathFreeObject(obj
);
6543 xmlXPathFreeContext(ctxt
);
6549 * "vol-clone" command
6551 static const vshCmdInfo info_vol_clone
[] = {
6552 {"help", N_("clone a volume.")},
6553 {"desc", N_("Clone an existing volume.")},
6557 static const vshCmdOptDef opts_vol_clone
[] = {
6558 {"pool", VSH_OT_STRING
, 0, N_("pool name or uuid")},
6559 {"vol", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("orig vol name or key")},
6560 {"newname", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("clone name")},
6565 cmdVolClone(vshControl
*ctl
, const vshCmd
*cmd
)
6567 virStoragePoolPtr origpool
= NULL
;
6568 virStorageVolPtr origvol
= NULL
, newvol
= NULL
;
6569 char *name
, *origxml
= NULL
;
6570 xmlChar
*newxml
= NULL
;
6574 if (!vshConnectionUsability(ctl
, ctl
->conn
))
6577 if (!(origvol
= vshCommandOptVol(ctl
, cmd
, "vol", "pool", NULL
)))
6580 origpool
= virStoragePoolLookupByVolume(origvol
);
6582 vshError(ctl
, "%s", _("failed to get parent pool"));
6586 name
= vshCommandOptString(cmd
, "newname", &found
);
6590 origxml
= virStorageVolGetXMLDesc(origvol
, 0);
6594 newxml
= makeCloneXML(origxml
, name
);
6596 vshPrint(ctl
, "%s", _("Failed to allocate XML buffer"));
6600 newvol
= virStorageVolCreateXMLFrom(origpool
, (char *) newxml
, origvol
, 0);
6602 if (newvol
!= NULL
) {
6603 vshPrint(ctl
, _("Vol %s cloned from %s\n"),
6604 virStorageVolGetName(newvol
), virStorageVolGetName(origvol
));
6606 vshError(ctl
, _("Failed to clone vol from %s"),
6607 virStorageVolGetName(origvol
));
6617 virStorageVolFree(origvol
);
6619 virStorageVolFree(newvol
);
6621 virStoragePoolFree(origpool
);
6626 * "vol-delete" command
6628 static const vshCmdInfo info_vol_delete
[] = {
6629 {"help", N_("delete a vol")},
6630 {"desc", N_("Delete a given vol.")},
6634 static const vshCmdOptDef opts_vol_delete
[] = {
6635 {"pool", VSH_OT_STRING
, 0, N_("pool name or uuid")},
6636 {"vol", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("vol name, key or path")},
6641 cmdVolDelete(vshControl
*ctl
, const vshCmd
*cmd
)
6643 virStorageVolPtr vol
;
6647 if (!vshConnectionUsability(ctl
, ctl
->conn
))
6650 if (!(vol
= vshCommandOptVol(ctl
, cmd
, "vol", "pool", &name
))) {
6654 if (virStorageVolDelete(vol
, 0) == 0) {
6655 vshPrint(ctl
, _("Vol %s deleted\n"), name
);
6657 vshError(ctl
, _("Failed to delete vol %s"), name
);
6661 virStorageVolFree(vol
);
6667 * "vol-wipe" command
6669 static const vshCmdInfo info_vol_wipe
[] = {
6670 {"help", N_("wipe a vol")},
6671 {"desc", N_("Ensure data previously on a volume is not accessible to future reads")},
6675 static const vshCmdOptDef opts_vol_wipe
[] = {
6676 {"pool", VSH_OT_STRING
, 0, N_("pool name or uuid")},
6677 {"vol", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("vol name, key or path")},
6682 cmdVolWipe(vshControl
*ctl
, const vshCmd
*cmd
)
6684 virStorageVolPtr vol
;
6688 if (!vshConnectionUsability(ctl
, ctl
->conn
))
6691 if (!(vol
= vshCommandOptVol(ctl
, cmd
, "vol", "pool", &name
))) {
6695 if (virStorageVolWipe(vol
, 0) == 0) {
6696 vshPrint(ctl
, _("Vol %s wiped\n"), name
);
6698 vshError(ctl
, _("Failed to wipe vol %s"), name
);
6702 virStorageVolFree(vol
);
6708 * "vol-info" command
6710 static const vshCmdInfo info_vol_info
[] = {
6711 {"help", N_("storage vol information")},
6712 {"desc", N_("Returns basic information about the storage vol.")},
6716 static const vshCmdOptDef opts_vol_info
[] = {
6717 {"pool", VSH_OT_STRING
, 0, N_("pool name or uuid")},
6718 {"vol", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("vol name, key or path")},
6723 cmdVolInfo(vshControl
*ctl
, const vshCmd
*cmd
)
6725 virStorageVolInfo info
;
6726 virStorageVolPtr vol
;
6729 if (!vshConnectionUsability(ctl
, ctl
->conn
))
6732 if (!(vol
= vshCommandOptVol(ctl
, cmd
, "vol", "pool", NULL
)))
6735 vshPrint(ctl
, "%-15s %s\n", _("Name:"), virStorageVolGetName(vol
));
6737 if (virStorageVolGetInfo(vol
, &info
) == 0) {
6740 vshPrint(ctl
, "%-15s %s\n", _("Type:"),
6741 info
.type
== VIR_STORAGE_VOL_FILE
?
6742 _("file") : _("block"));
6744 val
= prettyCapacity(info
.capacity
, &unit
);
6745 vshPrint(ctl
, "%-15s %2.2lf %s\n", _("Capacity:"), val
, unit
);
6747 val
= prettyCapacity(info
.allocation
, &unit
);
6748 vshPrint(ctl
, "%-15s %2.2lf %s\n", _("Allocation:"), val
, unit
);
6753 virStorageVolFree(vol
);
6759 * "vol-dumpxml" command
6761 static const vshCmdInfo info_vol_dumpxml
[] = {
6762 {"help", N_("vol information in XML")},
6763 {"desc", N_("Output the vol information as an XML dump to stdout.")},
6767 static const vshCmdOptDef opts_vol_dumpxml
[] = {
6768 {"pool", VSH_OT_STRING
, 0, N_("pool name or uuid")},
6769 {"vol", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("vol name, key or path")},
6774 cmdVolDumpXML(vshControl
*ctl
, const vshCmd
*cmd
)
6776 virStorageVolPtr vol
;
6780 if (!vshConnectionUsability(ctl
, ctl
->conn
))
6783 if (!(vol
= vshCommandOptVol(ctl
, cmd
, "vol", "pool", NULL
)))
6786 dump
= virStorageVolGetXMLDesc(vol
, 0);
6788 vshPrint(ctl
, "%s", dump
);
6794 virStorageVolFree(vol
);
6800 * "vol-list" command
6802 static const vshCmdInfo info_vol_list
[] = {
6803 {"help", N_("list vols")},
6804 {"desc", N_("Returns list of vols by pool.")},
6808 static const vshCmdOptDef opts_vol_list
[] = {
6809 {"pool", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("pool name or uuid")},
6810 {"details", VSH_OT_BOOL
, 0, N_("display extended details for volumes")},
6815 cmdVolList(vshControl
*ctl
, const vshCmd
*cmd ATTRIBUTE_UNUSED
)
6817 virStorageVolInfo volumeInfo
;
6818 virStoragePoolPtr pool
;
6819 char **activeNames
= NULL
;
6820 char *outputStr
= NULL
;
6823 int details
= vshCommandOptBool(cmd
, "details");
6824 int numVolumes
= 0, i
;
6825 int ret
, functionReturn
;
6826 int stringLength
= 0;
6827 size_t allocStrLength
= 0, capStrLength
= 0;
6828 size_t nameStrLength
= 0, pathStrLength
= 0;
6829 size_t typeStrLength
= 0;
6830 struct volInfoText
{
6836 struct volInfoText
*volInfoTexts
= NULL
;
6838 /* Check the connection to libvirtd daemon is still working */
6839 if (!vshConnectionUsability(ctl
, ctl
->conn
))
6842 /* Look up the pool information given to us by the user */
6843 if (!(pool
= vshCommandOptPool(ctl
, cmd
, "pool", NULL
)))
6846 /* Determine the number of volumes in the pool */
6847 numVolumes
= virStoragePoolNumOfVolumes(pool
);
6849 if (numVolumes
< 0) {
6850 vshError(ctl
, "%s", _("Failed to list storage volumes"));
6851 virStoragePoolFree(pool
);
6855 /* Retrieve the list of volume names in the pool */
6856 if (numVolumes
> 0) {
6857 activeNames
= vshCalloc(ctl
, numVolumes
, sizeof(*activeNames
));
6858 if ((numVolumes
= virStoragePoolListVolumes(pool
, activeNames
,
6860 vshError(ctl
, "%s", _("Failed to list active vols"));
6861 VIR_FREE(activeNames
);
6862 virStoragePoolFree(pool
);
6866 /* Sort the volume names */
6867 qsort(&activeNames
[0], numVolumes
, sizeof(*activeNames
), namesorter
);
6869 /* Set aside memory for volume information pointers */
6870 volInfoTexts
= vshCalloc(ctl
, numVolumes
, sizeof(*volInfoTexts
));
6873 /* Collect the rest of the volume information for display */
6874 for (i
= 0; i
< numVolumes
; i
++) {
6875 /* Retrieve volume info */
6876 virStorageVolPtr vol
= virStorageVolLookupByName(pool
,
6879 /* Retrieve the volume path */
6880 if ((volInfoTexts
[i
].path
= virStorageVolGetPath(vol
)) == NULL
) {
6881 /* Something went wrong retrieving a volume path, cope with it */
6882 volInfoTexts
[i
].path
= vshStrdup(ctl
, _("unknown"));
6885 /* If requested, retrieve volume type and sizing information */
6887 if (virStorageVolGetInfo(vol
, &volumeInfo
) != 0) {
6888 /* Something went wrong retrieving volume info, cope with it */
6889 volInfoTexts
[i
].allocation
= vshStrdup(ctl
, _("unknown"));
6890 volInfoTexts
[i
].capacity
= vshStrdup(ctl
, _("unknown"));
6891 volInfoTexts
[i
].type
= vshStrdup(ctl
, _("unknown"));
6893 /* Convert the returned volume info into output strings */
6896 if (volumeInfo
.type
== VIR_STORAGE_VOL_FILE
)
6897 volInfoTexts
[i
].type
= vshStrdup(ctl
, _("file"));
6899 volInfoTexts
[i
].type
= vshStrdup(ctl
, _("block"));
6901 /* Create the capacity output string */
6902 val
= prettyCapacity(volumeInfo
.capacity
, &unit
);
6903 ret
= virAsprintf(&volInfoTexts
[i
].capacity
,
6904 "%.2lf %s", val
, unit
);
6906 /* An error occurred creating the string, return */
6907 goto asprintf_failure
;
6910 /* Create the allocation output string */
6911 val
= prettyCapacity(volumeInfo
.allocation
, &unit
);
6912 ret
= virAsprintf(&volInfoTexts
[i
].allocation
,
6913 "%.2lf %s", val
, unit
);
6915 /* An error occurred creating the string, return */
6916 goto asprintf_failure
;
6920 /* Remember the largest length for each output string.
6921 * This lets us displaying header and volume information rows
6922 * using a single, properly sized, printf style output string.
6925 /* Keep the length of name string if longest so far */
6926 stringLength
= strlen(activeNames
[i
]);
6927 if (stringLength
> nameStrLength
)
6928 nameStrLength
= stringLength
;
6930 /* Keep the length of path string if longest so far */
6931 stringLength
= strlen(volInfoTexts
[i
].path
);
6932 if (stringLength
> pathStrLength
)
6933 pathStrLength
= stringLength
;
6935 /* Keep the length of type string if longest so far */
6936 stringLength
= strlen(volInfoTexts
[i
].type
);
6937 if (stringLength
> typeStrLength
)
6938 typeStrLength
= stringLength
;
6940 /* Keep the length of capacity string if longest so far */
6941 stringLength
= strlen(volInfoTexts
[i
].capacity
);
6942 if (stringLength
> capStrLength
)
6943 capStrLength
= stringLength
;
6945 /* Keep the length of allocation string if longest so far */
6946 stringLength
= strlen(volInfoTexts
[i
].allocation
);
6947 if (stringLength
> allocStrLength
)
6948 allocStrLength
= stringLength
;
6951 /* Cleanup memory allocation */
6952 virStorageVolFree(vol
);
6955 /* If the --details option wasn't selected, we output the volume
6956 * info using the fixed string format from previous versions to
6957 * maintain backward compatibility.
6960 /* Output basic info then return if --details option not selected */
6962 /* The old output format */
6963 vshPrintExtra(ctl
, "%-20s %-40s\n", _("Name"), _("Path"));
6964 vshPrintExtra(ctl
, "-----------------------------------------\n");
6965 for (i
= 0; i
< numVolumes
; i
++) {
6966 vshPrint(ctl
, "%-20s %-40s\n", activeNames
[i
],
6967 volInfoTexts
[i
].path
);
6970 /* Cleanup and return */
6971 functionReturn
= TRUE
;
6975 /* We only get here if the --details option was selected. */
6977 /* Use the length of name header string if it's longest */
6978 stringLength
= strlen(_("Name"));
6979 if (stringLength
> nameStrLength
)
6980 nameStrLength
= stringLength
;
6982 /* Use the length of path header string if it's longest */
6983 stringLength
= strlen(_("Path"));
6984 if (stringLength
> pathStrLength
)
6985 pathStrLength
= stringLength
;
6987 /* Use the length of type header string if it's longest */
6988 stringLength
= strlen(_("Type"));
6989 if (stringLength
> typeStrLength
)
6990 typeStrLength
= stringLength
;
6992 /* Use the length of capacity header string if it's longest */
6993 stringLength
= strlen(_("Capacity"));
6994 if (stringLength
> capStrLength
)
6995 capStrLength
= stringLength
;
6997 /* Use the length of allocation header string if it's longest */
6998 stringLength
= strlen(_("Allocation"));
6999 if (stringLength
> allocStrLength
)
7000 allocStrLength
= stringLength
;
7002 /* Display the string lengths for debugging */
7003 vshDebug(ctl
, 5, "Longest name string = %zu chars\n", nameStrLength
);
7004 vshDebug(ctl
, 5, "Longest path string = %zu chars\n", pathStrLength
);
7005 vshDebug(ctl
, 5, "Longest type string = %zu chars\n", typeStrLength
);
7006 vshDebug(ctl
, 5, "Longest capacity string = %zu chars\n", capStrLength
);
7007 vshDebug(ctl
, 5, "Longest allocation string = %zu chars\n", allocStrLength
);
7009 /* Create the output template */
7010 ret
= virAsprintf(&outputStr
,
7011 "%%-%lus %%-%lus %%-%lus %%%lus %%%lus\n",
7012 (unsigned long) nameStrLength
,
7013 (unsigned long) pathStrLength
,
7014 (unsigned long) typeStrLength
,
7015 (unsigned long) capStrLength
,
7016 (unsigned long) allocStrLength
);
7018 /* An error occurred creating the string, return */
7019 goto asprintf_failure
;
7022 /* Display the header */
7023 vshPrint(ctl
, outputStr
, _("Name"), _("Path"), _("Type"),
7024 ("Capacity"), _("Allocation"));
7025 for (i
= nameStrLength
+ pathStrLength
+ typeStrLength
7026 + capStrLength
+ allocStrLength
7028 vshPrintExtra(ctl
, "-");
7029 vshPrintExtra(ctl
, "\n");
7031 /* Display the volume info rows */
7032 for (i
= 0; i
< numVolumes
; i
++) {
7033 vshPrint(ctl
, outputStr
,
7035 volInfoTexts
[i
].path
,
7036 volInfoTexts
[i
].type
,
7037 volInfoTexts
[i
].capacity
,
7038 volInfoTexts
[i
].allocation
);
7041 /* Cleanup and return */
7042 functionReturn
= TRUE
;
7047 /* Display an appropriate error message then cleanup and return */
7050 /* Couldn't allocate memory */
7051 vshError(ctl
, "%s", _("Out of memory"));
7054 /* Some other error */
7055 vshError(ctl
, _("virAsprintf failed (errno %d)"), errno
);
7057 functionReturn
= FALSE
;
7061 /* Safely free the memory allocated in this function */
7062 for (i
= 0; i
< numVolumes
; i
++) {
7063 /* Cleanup the memory for one volume info structure per loop */
7064 VIR_FREE(volInfoTexts
[i
].path
);
7065 VIR_FREE(volInfoTexts
[i
].type
);
7066 VIR_FREE(volInfoTexts
[i
].capacity
);
7067 VIR_FREE(volInfoTexts
[i
].allocation
);
7068 VIR_FREE(activeNames
[i
]);
7071 /* Cleanup remaining memory */
7072 VIR_FREE(outputStr
);
7073 VIR_FREE(volInfoTexts
);
7074 VIR_FREE(activeNames
);
7075 virStoragePoolFree(pool
);
7077 /* Return the desired value */
7078 return functionReturn
;
7083 * "vol-name" command
7085 static const vshCmdInfo info_vol_name
[] = {
7086 {"help", N_("returns the volume name for a given volume key or path")},
7091 static const vshCmdOptDef opts_vol_name
[] = {
7092 {"vol", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("volume key or path")},
7097 cmdVolName(vshControl
*ctl
, const vshCmd
*cmd
)
7099 virStorageVolPtr vol
;
7101 if (!vshConnectionUsability(ctl
, ctl
->conn
))
7104 if (!(vol
= vshCommandOptVolBy(ctl
, cmd
, "vol", "pool", NULL
,
7108 vshPrint(ctl
, "%s\n", virStorageVolGetName(vol
));
7109 virStorageVolFree(vol
);
7115 * "vol-pool" command
7117 static const vshCmdInfo info_vol_pool
[] = {
7118 {"help", N_("returns the storage pool for a given volume key or path")},
7123 static const vshCmdOptDef opts_vol_pool
[] = {
7124 {"uuid", VSH_OT_BOOL
, 0, N_("return the pool uuid rather than pool name")},
7125 {"vol", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("volume key or path")},
7130 cmdVolPool(vshControl
*ctl
, const vshCmd
*cmd
)
7132 virStoragePoolPtr pool
;
7133 virStorageVolPtr vol
;
7134 char uuid
[VIR_UUID_STRING_BUFLEN
];
7136 /* Check the connection to libvirtd daemon is still working */
7137 if (!vshConnectionUsability(ctl
, ctl
->conn
))
7140 /* Use the supplied string to locate the volume */
7141 if (!(vol
= vshCommandOptVolBy(ctl
, cmd
, "vol", "pool", NULL
,
7146 /* Look up the parent storage pool for the volume */
7147 pool
= virStoragePoolLookupByVolume(vol
);
7149 vshError(ctl
, "%s", _("failed to get parent pool"));
7150 virStorageVolFree(vol
);
7154 /* Return the requested details of the parent storage pool */
7155 if (vshCommandOptBool(cmd
, "uuid")) {
7156 /* Retrieve and return pool UUID string */
7157 if (virStoragePoolGetUUIDString(pool
, &uuid
[0]) == 0)
7158 vshPrint(ctl
, "%s\n", uuid
);
7160 /* Return the storage pool name */
7161 vshPrint(ctl
, "%s\n", virStoragePoolGetName(pool
));
7165 virStorageVolFree(vol
);
7166 virStoragePoolFree(pool
);
7174 static const vshCmdInfo info_vol_key
[] = {
7175 {"help", N_("returns the volume key for a given volume name or path")},
7180 static const vshCmdOptDef opts_vol_key
[] = {
7181 {"pool", VSH_OT_STRING
, 0, N_("pool name or uuid")},
7182 {"vol", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("volume name or path")},
7187 cmdVolKey(vshControl
*ctl
, const vshCmd
*cmd
)
7189 virStorageVolPtr vol
;
7191 if (!vshConnectionUsability(ctl
, ctl
->conn
))
7194 if (!(vol
= vshCommandOptVol(ctl
, cmd
, "vol", "pool", NULL
)))
7197 vshPrint(ctl
, "%s\n", virStorageVolGetKey(vol
));
7198 virStorageVolFree(vol
);
7205 * "vol-path" command
7207 static const vshCmdInfo info_vol_path
[] = {
7208 {"help", N_("returns the volume path for a given volume name or key")},
7213 static const vshCmdOptDef opts_vol_path
[] = {
7214 {"pool", VSH_OT_STRING
, 0, N_("pool name or uuid")},
7215 {"vol", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("volume name or key")},
7220 cmdVolPath(vshControl
*ctl
, const vshCmd
*cmd
)
7222 virStorageVolPtr vol
;
7225 if (!vshConnectionUsability(ctl
, ctl
->conn
))
7228 if (!(vol
= vshCommandOptVol(ctl
, cmd
, "vol", "pool", &name
))) {
7232 vshPrint(ctl
, "%s\n", virStorageVolGetPath(vol
));
7233 virStorageVolFree(vol
);
7239 * "secret-define" command
7241 static const vshCmdInfo info_secret_define
[] = {
7242 {"help", N_("define or modify a secret from an XML file")},
7243 {"desc", N_("Define or modify a secret.")},
7247 static const vshCmdOptDef opts_secret_define
[] = {
7248 {"file", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("file containing secret attributes in XML")},
7253 cmdSecretDefine(vshControl
*ctl
, const vshCmd
*cmd
)
7255 char *from
, *buffer
;
7257 char uuid
[VIR_UUID_STRING_BUFLEN
];
7259 if (!vshConnectionUsability(ctl
, ctl
->conn
))
7262 from
= vshCommandOptString(cmd
, "file", NULL
);
7266 if (virFileReadAll(from
, VIRSH_MAX_XML_FILE
, &buffer
) < 0)
7269 res
= virSecretDefineXML(ctl
->conn
, buffer
, 0);
7273 vshError(ctl
, _("Failed to set attributes from %s"), from
);
7276 if (virSecretGetUUIDString(res
, &(uuid
[0])) < 0) {
7277 vshError(ctl
, "%s", _("Failed to get UUID of created secret"));
7281 vshPrint(ctl
, _("Secret %s created\n"), uuid
);
7287 * "secret-dumpxml" command
7289 static const vshCmdInfo info_secret_dumpxml
[] = {
7290 {"help", N_("secret attributes in XML")},
7291 {"desc", N_("Output attributes of a secret as an XML dump to stdout.")},
7295 static const vshCmdOptDef opts_secret_dumpxml
[] = {
7296 {"secret", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("secret UUID")},
7301 cmdSecretDumpXML(vshControl
*ctl
, const vshCmd
*cmd
)
7303 virSecretPtr secret
;
7307 if (!vshConnectionUsability(ctl
, ctl
->conn
))
7310 secret
= vshCommandOptSecret(ctl
, cmd
, NULL
);
7314 xml
= virSecretGetXMLDesc(secret
, 0);
7317 vshPrint(ctl
, "%s", xml
);
7322 virSecretFree(secret
);
7327 * "secret-set-value" command
7329 static const vshCmdInfo info_secret_set_value
[] = {
7330 {"help", N_("set a secret value")},
7331 {"desc", N_("Set a secret value.")},
7335 static const vshCmdOptDef opts_secret_set_value
[] = {
7336 {"secret", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("secret UUID")},
7337 {"base64", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("base64-encoded secret value")},
7342 cmdSecretSetValue(vshControl
*ctl
, const vshCmd
*cmd
)
7344 virSecretPtr secret
;
7346 char *base64
, *value
;
7347 int found
, res
, ret
= FALSE
;
7349 if (!vshConnectionUsability(ctl
, ctl
->conn
))
7352 secret
= vshCommandOptSecret(ctl
, cmd
, NULL
);
7356 base64
= vshCommandOptString(cmd
, "base64", &found
);
7360 if (!base64_decode_alloc(base64
, strlen(base64
), &value
, &value_size
)) {
7361 vshError(ctl
, "%s", _("Invalid base64 data"));
7364 if (value
== NULL
) {
7365 vshError(ctl
, "%s", _("Failed to allocate memory"));
7369 res
= virSecretSetValue(secret
, (unsigned char *)value
, value_size
, 0);
7370 memset(value
, 0, value_size
);
7374 vshError(ctl
, "%s", _("Failed to set secret value"));
7377 vshPrint(ctl
, "%s", _("Secret value set\n"));
7381 virSecretFree(secret
);
7386 * "secret-get-value" command
7388 static const vshCmdInfo info_secret_get_value
[] = {
7389 {"help", N_("Output a secret value")},
7390 {"desc", N_("Output a secret value to stdout.")},
7394 static const vshCmdOptDef opts_secret_get_value
[] = {
7395 {"secret", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("secret UUID")},
7400 cmdSecretGetValue(vshControl
*ctl
, const vshCmd
*cmd
)
7402 virSecretPtr secret
;
7404 unsigned char *value
;
7408 if (!vshConnectionUsability(ctl
, ctl
->conn
))
7411 secret
= vshCommandOptSecret(ctl
, cmd
, NULL
);
7415 value
= virSecretGetValue(secret
, &value_size
, 0);
7419 base64_encode_alloc((char *)value
, value_size
, &base64
);
7420 memset(value
, 0, value_size
);
7423 if (base64
== NULL
) {
7424 vshError(ctl
, "%s", _("Failed to allocate memory"));
7427 vshPrint(ctl
, "%s", base64
);
7428 memset(base64
, 0, strlen(base64
));
7433 virSecretFree(secret
);
7438 * "secret-undefine" command
7440 static const vshCmdInfo info_secret_undefine
[] = {
7441 {"help", N_("undefine a secret")},
7442 {"desc", N_("Undefine a secret.")},
7446 static const vshCmdOptDef opts_secret_undefine
[] = {
7447 {"secret", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("secret UUID")},
7452 cmdSecretUndefine(vshControl
*ctl
, const vshCmd
*cmd
)
7454 virSecretPtr secret
;
7458 if (!vshConnectionUsability(ctl
, ctl
->conn
))
7461 secret
= vshCommandOptSecret(ctl
, cmd
, &uuid
);
7465 if (virSecretUndefine(secret
) < 0) {
7466 vshError(ctl
, _("Failed to delete secret %s"), uuid
);
7469 vshPrint(ctl
, _("Secret %s deleted\n"), uuid
);
7473 virSecretFree(secret
);
7478 * "secret-list" command
7480 static const vshCmdInfo info_secret_list
[] = {
7481 {"help", N_("list secrets")},
7482 {"desc", N_("Returns a list of secrets")},
7487 cmdSecretList(vshControl
*ctl
, const vshCmd
*cmd ATTRIBUTE_UNUSED
)
7489 int maxuuids
= 0, i
;
7490 char **uuids
= NULL
;
7492 if (!vshConnectionUsability(ctl
, ctl
->conn
))
7495 maxuuids
= virConnectNumOfSecrets(ctl
->conn
);
7497 vshError(ctl
, "%s", _("Failed to list secrets"));
7500 uuids
= vshMalloc(ctl
, sizeof(*uuids
) * maxuuids
);
7502 maxuuids
= virConnectListSecrets(ctl
->conn
, uuids
, maxuuids
);
7504 vshError(ctl
, "%s", _("Failed to list secrets"));
7509 qsort(uuids
, maxuuids
, sizeof(char *), namesorter
);
7511 vshPrintExtra(ctl
, "%-36s %s\n", _("UUID"), _("Usage"));
7512 vshPrintExtra(ctl
, "-----------------------------------------------------------\n");
7514 for (i
= 0; i
< maxuuids
; i
++) {
7515 virSecretPtr sec
= virSecretLookupByUUIDString(ctl
->conn
, uuids
[i
]);
7516 const char *usageType
= NULL
;
7523 switch (virSecretGetUsageType(sec
)) {
7524 case VIR_SECRET_USAGE_TYPE_VOLUME
:
7525 usageType
= _("Volume");
7530 vshPrint(ctl
, "%-36s %s %s\n",
7531 uuids
[i
], usageType
,
7532 virSecretGetUsageID(sec
));
7534 vshPrint(ctl
, "%-36s %s\n",
7535 uuids
[i
], _("Unused"));
7548 static const vshCmdInfo info_version
[] = {
7549 {"help", N_("show version")},
7550 {"desc", N_("Display the system version information.")},
7556 cmdVersion(vshControl
*ctl
, const vshCmd
*cmd ATTRIBUTE_UNUSED
)
7558 unsigned long hvVersion
;
7560 unsigned long libVersion
;
7561 unsigned long includeVersion
;
7562 unsigned long apiVersion
;
7568 if (!vshConnectionUsability(ctl
, ctl
->conn
))
7571 hvType
= virConnectGetType(ctl
->conn
);
7572 if (hvType
== NULL
) {
7573 vshError(ctl
, "%s", _("failed to get hypervisor type"));
7577 includeVersion
= LIBVIR_VERSION_NUMBER
;
7578 major
= includeVersion
/ 1000000;
7579 includeVersion
%= 1000000;
7580 minor
= includeVersion
/ 1000;
7581 rel
= includeVersion
% 1000;
7582 vshPrint(ctl
, _("Compiled against library: libvir %d.%d.%d\n"),
7585 ret
= virGetVersion(&libVersion
, hvType
, &apiVersion
);
7587 vshError(ctl
, "%s", _("failed to get the library version"));
7590 major
= libVersion
/ 1000000;
7591 libVersion
%= 1000000;
7592 minor
= libVersion
/ 1000;
7593 rel
= libVersion
% 1000;
7594 vshPrint(ctl
, _("Using library: libvir %d.%d.%d\n"),
7597 major
= apiVersion
/ 1000000;
7598 apiVersion
%= 1000000;
7599 minor
= apiVersion
/ 1000;
7600 rel
= apiVersion
% 1000;
7601 vshPrint(ctl
, _("Using API: %s %d.%d.%d\n"), hvType
,
7604 ret
= virConnectGetVersion(ctl
->conn
, &hvVersion
);
7606 vshError(ctl
, "%s", _("failed to get the hypervisor version"));
7609 if (hvVersion
== 0) {
7611 _("Cannot extract running %s hypervisor version\n"), hvType
);
7613 major
= hvVersion
/ 1000000;
7614 hvVersion
%= 1000000;
7615 minor
= hvVersion
/ 1000;
7616 rel
= hvVersion
% 1000;
7618 vshPrint(ctl
, _("Running hypervisor: %s %d.%d.%d\n"),
7619 hvType
, major
, minor
, rel
);
7625 * "nodedev-list" command
7627 static const vshCmdInfo info_node_list_devices
[] = {
7628 {"help", N_("enumerate devices on this host")},
7633 static const vshCmdOptDef opts_node_list_devices
[] = {
7634 {"tree", VSH_OT_BOOL
, 0, N_("list devices in a tree")},
7635 {"cap", VSH_OT_STRING
, VSH_OFLAG_NONE
, N_("capability name")},
7639 #define MAX_DEPTH 100
7640 #define INDENT_SIZE 4
7641 #define INDENT_BUFLEN ((MAX_DEPTH * INDENT_SIZE) + 1)
7644 cmdNodeListDevicesPrint(vshControl
*ctl
,
7651 unsigned int indentIdx
,
7655 int nextlastdev
= -1;
7657 /* Prepare indent for this device, but not if at root */
7658 if (depth
&& depth
< MAX_DEPTH
) {
7659 indentBuf
[indentIdx
] = '+';
7660 indentBuf
[indentIdx
+1] = '-';
7661 indentBuf
[indentIdx
+2] = ' ';
7662 indentBuf
[indentIdx
+3] = '\0';
7665 /* Print this device */
7666 vshPrint(ctl
, "%s", indentBuf
);
7667 vshPrint(ctl
, "%s\n", devices
[devid
]);
7670 /* Update indent to show '|' or ' ' for child devices */
7671 if (depth
&& depth
< MAX_DEPTH
) {
7672 if (devid
== lastdev
)
7673 indentBuf
[indentIdx
] = ' ';
7675 indentBuf
[indentIdx
] = '|';
7676 indentBuf
[indentIdx
+1] = ' ';
7680 /* Determine the index of the last child device */
7681 for (i
= 0 ; i
< num_devices
; i
++) {
7683 STREQ(parents
[i
], devices
[devid
])) {
7688 /* If there is a child device, then print another blank line */
7689 if (nextlastdev
!= -1) {
7690 vshPrint(ctl
, "%s", indentBuf
);
7691 vshPrint(ctl
, " |\n");
7694 /* Finally print all children */
7695 if (depth
< MAX_DEPTH
)
7696 indentBuf
[indentIdx
] = ' ';
7697 for (i
= 0 ; i
< num_devices
; i
++) {
7698 if (depth
< MAX_DEPTH
) {
7699 indentBuf
[indentIdx
] = ' ';
7700 indentBuf
[indentIdx
+1] = ' ';
7703 STREQ(parents
[i
], devices
[devid
]))
7704 cmdNodeListDevicesPrint(ctl
, devices
, parents
,
7705 num_devices
, i
, nextlastdev
,
7706 depth
+ 1, indentIdx
+ 2, indentBuf
);
7707 if (depth
< MAX_DEPTH
)
7708 indentBuf
[indentIdx
] = '\0';
7711 /* If there was no child device, and we're the last in
7712 * a list of devices, then print another blank line */
7713 if (nextlastdev
== -1 && devid
== lastdev
) {
7714 vshPrint(ctl
, "%s", indentBuf
);
7715 vshPrint(ctl
, "\n");
7720 cmdNodeListDevices (vshControl
*ctl
, const vshCmd
*cmd ATTRIBUTE_UNUSED
)
7724 int found
, num_devices
, i
;
7725 int tree
= vshCommandOptBool(cmd
, "tree");
7727 if (!vshConnectionUsability(ctl
, ctl
->conn
))
7730 cap
= vshCommandOptString(cmd
, "cap", &found
);
7734 num_devices
= virNodeNumOfDevices(ctl
->conn
, cap
, 0);
7735 if (num_devices
< 0) {
7736 vshError(ctl
, "%s", _("Failed to count node devices"));
7738 } else if (num_devices
== 0) {
7742 devices
= vshMalloc(ctl
, sizeof(char *) * num_devices
);
7744 virNodeListDevices(ctl
->conn
, cap
, devices
, num_devices
, 0);
7745 if (num_devices
< 0) {
7746 vshError(ctl
, "%s", _("Failed to list node devices"));
7750 qsort(&devices
[0], num_devices
, sizeof(char*), namesorter
);
7752 char indentBuf
[INDENT_BUFLEN
];
7753 char **parents
= vshMalloc(ctl
, sizeof(char *) * num_devices
);
7754 for (i
= 0; i
< num_devices
; i
++) {
7755 virNodeDevicePtr dev
= virNodeDeviceLookupByName(ctl
->conn
, devices
[i
]);
7756 if (dev
&& STRNEQ(devices
[i
], "computer")) {
7757 const char *parent
= virNodeDeviceGetParent(dev
);
7758 parents
[i
] = parent
? vshStrdup(ctl
, parent
) : NULL
;
7762 virNodeDeviceFree(dev
);
7764 for (i
= 0 ; i
< num_devices
; i
++) {
7765 memset(indentBuf
, '\0', sizeof indentBuf
);
7766 if (parents
[i
] == NULL
)
7767 cmdNodeListDevicesPrint(ctl
,
7777 for (i
= 0 ; i
< num_devices
; i
++) {
7778 VIR_FREE(devices
[i
]);
7779 VIR_FREE(parents
[i
]);
7783 for (i
= 0; i
< num_devices
; i
++) {
7784 vshPrint(ctl
, "%s\n", devices
[i
]);
7785 VIR_FREE(devices
[i
]);
7793 * "nodedev-dumpxml" command
7795 static const vshCmdInfo info_node_device_dumpxml
[] = {
7796 {"help", N_("node device details in XML")},
7797 {"desc", N_("Output the node device details as an XML dump to stdout.")},
7802 static const vshCmdOptDef opts_node_device_dumpxml
[] = {
7803 {"device", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("device key")},
7808 cmdNodeDeviceDumpXML (vshControl
*ctl
, const vshCmd
*cmd
)
7811 virNodeDevicePtr device
;
7814 if (!vshConnectionUsability(ctl
, ctl
->conn
))
7816 if (!(name
= vshCommandOptString(cmd
, "device", NULL
)))
7818 if (!(device
= virNodeDeviceLookupByName(ctl
->conn
, name
))) {
7819 vshError(ctl
, "%s '%s'", _("Could not find matching device"), name
);
7823 xml
= virNodeDeviceGetXMLDesc(device
, 0);
7825 virNodeDeviceFree(device
);
7829 vshPrint(ctl
, "%s\n", xml
);
7831 virNodeDeviceFree(device
);
7836 * "nodedev-dettach" command
7838 static const vshCmdInfo info_node_device_dettach
[] = {
7839 {"help", N_("dettach node device from its device driver")},
7840 {"desc", N_("Dettach node device from its device driver before assigning to a domain.")},
7845 static const vshCmdOptDef opts_node_device_dettach
[] = {
7846 {"device", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("device key")},
7851 cmdNodeDeviceDettach (vshControl
*ctl
, const vshCmd
*cmd
)
7854 virNodeDevicePtr device
;
7857 if (!vshConnectionUsability(ctl
, ctl
->conn
))
7859 if (!(name
= vshCommandOptString(cmd
, "device", NULL
)))
7861 if (!(device
= virNodeDeviceLookupByName(ctl
->conn
, name
))) {
7862 vshError(ctl
, "%s '%s'", _("Could not find matching device"), name
);
7866 if (virNodeDeviceDettach(device
) == 0) {
7867 vshPrint(ctl
, _("Device %s dettached\n"), name
);
7869 vshError(ctl
, _("Failed to dettach device %s"), name
);
7872 virNodeDeviceFree(device
);
7877 * "nodedev-reattach" command
7879 static const vshCmdInfo info_node_device_reattach
[] = {
7880 {"help", N_("reattach node device to its device driver")},
7881 {"desc", N_("Reattach node device to its device driver once released by the domain.")},
7886 static const vshCmdOptDef opts_node_device_reattach
[] = {
7887 {"device", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("device key")},
7892 cmdNodeDeviceReAttach (vshControl
*ctl
, const vshCmd
*cmd
)
7895 virNodeDevicePtr device
;
7898 if (!vshConnectionUsability(ctl
, ctl
->conn
))
7900 if (!(name
= vshCommandOptString(cmd
, "device", NULL
)))
7902 if (!(device
= virNodeDeviceLookupByName(ctl
->conn
, name
))) {
7903 vshError(ctl
, "%s '%s'", _("Could not find matching device"), name
);
7907 if (virNodeDeviceReAttach(device
) == 0) {
7908 vshPrint(ctl
, _("Device %s re-attached\n"), name
);
7910 vshError(ctl
, _("Failed to re-attach device %s"), name
);
7913 virNodeDeviceFree(device
);
7918 * "nodedev-reset" command
7920 static const vshCmdInfo info_node_device_reset
[] = {
7921 {"help", N_("reset node device")},
7922 {"desc", N_("Reset node device before or after assigning to a domain.")},
7927 static const vshCmdOptDef opts_node_device_reset
[] = {
7928 {"device", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("device key")},
7933 cmdNodeDeviceReset (vshControl
*ctl
, const vshCmd
*cmd
)
7936 virNodeDevicePtr device
;
7939 if (!vshConnectionUsability(ctl
, ctl
->conn
))
7941 if (!(name
= vshCommandOptString(cmd
, "device", NULL
)))
7943 if (!(device
= virNodeDeviceLookupByName(ctl
->conn
, name
))) {
7944 vshError(ctl
, "%s '%s'", _("Could not find matching device"), name
);
7948 if (virNodeDeviceReset(device
) == 0) {
7949 vshPrint(ctl
, _("Device %s reset\n"), name
);
7951 vshError(ctl
, _("Failed to reset device %s"), name
);
7954 virNodeDeviceFree(device
);
7961 static const vshCmdInfo info_hostname
[] = {
7962 {"help", N_("print the hypervisor hostname")},
7968 cmdHostname (vshControl
*ctl
, const vshCmd
*cmd ATTRIBUTE_UNUSED
)
7972 if (!vshConnectionUsability(ctl
, ctl
->conn
))
7975 hostname
= virConnectGetHostname (ctl
->conn
);
7976 if (hostname
== NULL
) {
7977 vshError(ctl
, "%s", _("failed to get hostname"));
7981 vshPrint (ctl
, "%s\n", hostname
);
7990 static const vshCmdInfo info_uri
[] = {
7991 {"help", N_("print the hypervisor canonical URI")},
7997 cmdURI (vshControl
*ctl
, const vshCmd
*cmd ATTRIBUTE_UNUSED
)
8001 if (!vshConnectionUsability(ctl
, ctl
->conn
))
8004 uri
= virConnectGetURI (ctl
->conn
);
8006 vshError(ctl
, "%s", _("failed to get URI"));
8010 vshPrint (ctl
, "%s\n", uri
);
8017 * "vncdisplay" command
8019 static const vshCmdInfo info_vncdisplay
[] = {
8020 {"help", N_("vnc display")},
8021 {"desc", N_("Output the IP address and port number for the VNC display.")},
8025 static const vshCmdOptDef opts_vncdisplay
[] = {
8026 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
8031 cmdVNCDisplay(vshControl
*ctl
, const vshCmd
*cmd
)
8033 xmlDocPtr xml
= NULL
;
8034 xmlXPathObjectPtr obj
= NULL
;
8035 xmlXPathContextPtr ctxt
= NULL
;
8041 if (!vshConnectionUsability(ctl
, ctl
->conn
))
8044 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, NULL
)))
8047 doc
= virDomainGetXMLDesc(dom
, 0);
8051 xml
= xmlReadDoc((const xmlChar
*) doc
, "domain.xml", NULL
,
8052 XML_PARSE_NOENT
| XML_PARSE_NONET
|
8053 XML_PARSE_NOWARNING
);
8057 ctxt
= xmlXPathNewContext(xml
);
8061 obj
= xmlXPathEval(BAD_CAST
"string(/domain/devices/graphics[@type='vnc']/@port)", ctxt
);
8062 if ((obj
== NULL
) || (obj
->type
!= XPATH_STRING
) ||
8063 (obj
->stringval
== NULL
) || (obj
->stringval
[0] == 0)) {
8066 if (virStrToLong_i((const char *)obj
->stringval
, NULL
, 10, &port
) || port
< 0)
8068 xmlXPathFreeObject(obj
);
8070 obj
= xmlXPathEval(BAD_CAST
"string(/domain/devices/graphics[@type='vnc']/@listen)", ctxt
);
8071 if ((obj
== NULL
) || (obj
->type
!= XPATH_STRING
) ||
8072 (obj
->stringval
== NULL
) || (obj
->stringval
[0] == 0) ||
8073 STREQ((const char*)obj
->stringval
, "0.0.0.0")) {
8074 vshPrint(ctl
, ":%d\n", port
-5900);
8076 vshPrint(ctl
, "%s:%d\n", (const char *)obj
->stringval
, port
-5900);
8078 xmlXPathFreeObject(obj
);
8083 xmlXPathFreeObject(obj
);
8084 xmlXPathFreeContext(ctxt
);
8092 * "ttyconsole" command
8094 static const vshCmdInfo info_ttyconsole
[] = {
8095 {"help", N_("tty console")},
8096 {"desc", N_("Output the device for the TTY console.")},
8100 static const vshCmdOptDef opts_ttyconsole
[] = {
8101 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
8106 cmdTTYConsole(vshControl
*ctl
, const vshCmd
*cmd
)
8108 xmlDocPtr xml
= NULL
;
8109 xmlXPathObjectPtr obj
= NULL
;
8110 xmlXPathContextPtr ctxt
= NULL
;
8115 if (!vshConnectionUsability(ctl
, ctl
->conn
))
8118 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, NULL
)))
8121 doc
= virDomainGetXMLDesc(dom
, 0);
8125 xml
= xmlReadDoc((const xmlChar
*) doc
, "domain.xml", NULL
,
8126 XML_PARSE_NOENT
| XML_PARSE_NONET
|
8127 XML_PARSE_NOWARNING
);
8131 ctxt
= xmlXPathNewContext(xml
);
8135 obj
= xmlXPathEval(BAD_CAST
"string(/domain/devices/console/@tty)", ctxt
);
8136 if ((obj
== NULL
) || (obj
->type
!= XPATH_STRING
) ||
8137 (obj
->stringval
== NULL
) || (obj
->stringval
[0] == 0)) {
8140 vshPrint(ctl
, "%s\n", (const char *)obj
->stringval
);
8144 xmlXPathFreeObject(obj
);
8145 xmlXPathFreeContext(ctxt
);
8153 * "attach-device" command
8155 static const vshCmdInfo info_attach_device
[] = {
8156 {"help", N_("attach device from an XML file")},
8157 {"desc", N_("Attach device from an XML <file>.")},
8161 static const vshCmdOptDef opts_attach_device
[] = {
8162 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
8163 {"file", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("XML file")},
8164 {"persistent", VSH_OT_BOOL
, 0, N_("persist device attachment")},
8169 cmdAttachDevice(vshControl
*ctl
, const vshCmd
*cmd
)
8178 if (!vshConnectionUsability(ctl
, ctl
->conn
))
8181 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, NULL
)))
8184 from
= vshCommandOptString(cmd
, "file", &found
);
8190 if (virFileReadAll(from
, VIRSH_MAX_XML_FILE
, &buffer
) < 0) {
8191 virshReportError(ctl
);
8196 if (vshCommandOptBool(cmd
, "persistent")) {
8197 flags
= VIR_DOMAIN_DEVICE_MODIFY_CONFIG
;
8198 if (virDomainIsActive(dom
) == 1)
8199 flags
|= VIR_DOMAIN_DEVICE_MODIFY_LIVE
;
8200 ret
= virDomainAttachDeviceFlags(dom
, buffer
, flags
);
8202 ret
= virDomainAttachDevice(dom
, buffer
);
8207 vshError(ctl
, _("Failed to attach device from %s"), from
);
8211 vshPrint(ctl
, "%s", _("Device attached successfully\n"));
8220 * "detach-device" command
8222 static const vshCmdInfo info_detach_device
[] = {
8223 {"help", N_("detach device from an XML file")},
8224 {"desc", N_("Detach device from an XML <file>")},
8228 static const vshCmdOptDef opts_detach_device
[] = {
8229 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
8230 {"file", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("XML file")},
8231 {"persistent", VSH_OT_BOOL
, 0, N_("persist device detachment")},
8236 cmdDetachDevice(vshControl
*ctl
, const vshCmd
*cmd
)
8245 if (!vshConnectionUsability(ctl
, ctl
->conn
))
8248 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, NULL
)))
8251 from
= vshCommandOptString(cmd
, "file", &found
);
8257 if (virFileReadAll(from
, VIRSH_MAX_XML_FILE
, &buffer
) < 0) {
8258 virshReportError(ctl
);
8263 if (vshCommandOptBool(cmd
, "persistent")) {
8264 flags
= VIR_DOMAIN_DEVICE_MODIFY_CONFIG
;
8265 if (virDomainIsActive(dom
) == 1)
8266 flags
|= VIR_DOMAIN_DEVICE_MODIFY_LIVE
;
8267 ret
= virDomainDetachDeviceFlags(dom
, buffer
, flags
);
8269 ret
= virDomainDetachDevice(dom
, buffer
);
8274 vshError(ctl
, _("Failed to detach device from %s"), from
);
8278 vshPrint(ctl
, "%s", _("Device detached successfully\n"));
8287 * "update-device" command
8289 static const vshCmdInfo info_update_device
[] = {
8290 {"help", N_("update device from an XML file")},
8291 {"desc", N_("Update device from an XML <file>.")},
8295 static const vshCmdOptDef opts_update_device
[] = {
8296 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
8297 {"file", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("XML file")},
8298 {"persistent", VSH_OT_BOOL
, 0, N_("persist device update")},
8303 cmdUpdateDevice(vshControl
*ctl
, const vshCmd
*cmd
)
8312 if (!vshConnectionUsability(ctl
, ctl
->conn
))
8315 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, NULL
)))
8318 from
= vshCommandOptString(cmd
, "file", &found
);
8324 if (virFileReadAll(from
, VIRSH_MAX_XML_FILE
, &buffer
) < 0) {
8325 virshReportError(ctl
);
8330 if (vshCommandOptBool(cmd
, "persistent")) {
8331 flags
= VIR_DOMAIN_DEVICE_MODIFY_CONFIG
;
8332 if (virDomainIsActive(dom
) == 1)
8333 flags
|= VIR_DOMAIN_DEVICE_MODIFY_LIVE
;
8335 flags
= VIR_DOMAIN_DEVICE_MODIFY_LIVE
;
8337 ret
= virDomainUpdateDeviceFlags(dom
, buffer
, flags
);
8341 vshError(ctl
, _("Failed to update device from %s"), from
);
8345 vshPrint(ctl
, "%s", _("Device updated successfully\n"));
8354 * "attach-interface" command
8356 static const vshCmdInfo info_attach_interface
[] = {
8357 {"help", N_("attach network interface")},
8358 {"desc", N_("Attach new network interface.")},
8362 static const vshCmdOptDef opts_attach_interface
[] = {
8363 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
8364 {"type", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("network interface type")},
8365 {"source", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("source of network interface")},
8366 {"target", VSH_OT_DATA
, 0, N_("target network name")},
8367 {"mac", VSH_OT_DATA
, 0, N_("MAC address")},
8368 {"script", VSH_OT_DATA
, 0, N_("script used to bridge network interface")},
8369 {"model", VSH_OT_DATA
, 0, N_("model type")},
8370 {"persistent", VSH_OT_BOOL
, 0, N_("persist interface attachment")},
8375 cmdAttachInterface(vshControl
*ctl
, const vshCmd
*cmd
)
8377 virDomainPtr dom
= NULL
;
8378 char *mac
, *target
, *script
, *type
, *source
, *model
;
8379 int typ
, ret
= FALSE
;
8381 virBuffer buf
= VIR_BUFFER_INITIALIZER
;
8384 if (!vshConnectionUsability(ctl
, ctl
->conn
))
8387 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, NULL
)))
8390 if (!(type
= vshCommandOptString(cmd
, "type", NULL
)))
8393 source
= vshCommandOptString(cmd
, "source", NULL
);
8394 target
= vshCommandOptString(cmd
, "target", NULL
);
8395 mac
= vshCommandOptString(cmd
, "mac", NULL
);
8396 script
= vshCommandOptString(cmd
, "script", NULL
);
8397 model
= vshCommandOptString(cmd
, "model", NULL
);
8399 /* check interface type */
8400 if (STREQ(type
, "network")) {
8402 } else if (STREQ(type
, "bridge")) {
8405 vshError(ctl
, _("No support for %s in command 'attach-interface'"),
8410 /* Make XML of interface */
8411 virBufferVSprintf(&buf
, "<interface type='%s'>\n", type
);
8414 virBufferVSprintf(&buf
, " <source network='%s'/>\n", source
);
8416 virBufferVSprintf(&buf
, " <source bridge='%s'/>\n", source
);
8419 virBufferVSprintf(&buf
, " <target dev='%s'/>\n", target
);
8421 virBufferVSprintf(&buf
, " <mac address='%s'/>\n", mac
);
8423 virBufferVSprintf(&buf
, " <script path='%s'/>\n", script
);
8425 virBufferVSprintf(&buf
, " <model type='%s'/>\n", model
);
8427 virBufferAddLit(&buf
, "</interface>\n");
8429 if (virBufferError(&buf
)) {
8430 vshPrint(ctl
, "%s", _("Failed to allocate XML buffer"));
8434 xml
= virBufferContentAndReset(&buf
);
8436 if (vshCommandOptBool(cmd
, "persistent")) {
8437 flags
= VIR_DOMAIN_DEVICE_MODIFY_CONFIG
;
8438 if (virDomainIsActive(dom
) == 1)
8439 flags
|= VIR_DOMAIN_DEVICE_MODIFY_LIVE
;
8440 ret
= virDomainAttachDeviceFlags(dom
, xml
, flags
);
8442 ret
= virDomainAttachDevice(dom
, xml
);
8448 vshError(ctl
, "%s", _("Failed to attach interface"));
8451 vshPrint(ctl
, "%s", _("Interface attached successfully\n"));
8458 virBufferFreeAndReset(&buf
);
8463 * "detach-interface" command
8465 static const vshCmdInfo info_detach_interface
[] = {
8466 {"help", N_("detach network interface")},
8467 {"desc", N_("Detach network interface.")},
8471 static const vshCmdOptDef opts_detach_interface
[] = {
8472 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
8473 {"type", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("network interface type")},
8474 {"mac", VSH_OT_STRING
, 0, N_("MAC address")},
8475 {"persistent", VSH_OT_BOOL
, 0, N_("persist interface detachment")},
8480 cmdDetachInterface(vshControl
*ctl
, const vshCmd
*cmd
)
8482 virDomainPtr dom
= NULL
;
8483 xmlDocPtr xml
= NULL
;
8484 xmlXPathObjectPtr obj
=NULL
;
8485 xmlXPathContextPtr ctxt
= NULL
;
8486 xmlNodePtr cur
= NULL
;
8487 xmlBufferPtr xml_buf
= NULL
;
8488 char *doc
, *mac
=NULL
, *type
;
8490 int i
= 0, diff_mac
, ret
= FALSE
;
8493 if (!vshConnectionUsability(ctl
, ctl
->conn
))
8496 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, NULL
)))
8499 if (!(type
= vshCommandOptString(cmd
, "type", NULL
)))
8502 mac
= vshCommandOptString(cmd
, "mac", NULL
);
8504 doc
= virDomainGetXMLDesc(dom
, 0);
8508 xml
= xmlReadDoc((const xmlChar
*) doc
, "domain.xml", NULL
,
8509 XML_PARSE_NOENT
| XML_PARSE_NONET
|
8510 XML_PARSE_NOWARNING
);
8513 vshError(ctl
, "%s", _("Failed to get interface information"));
8516 ctxt
= xmlXPathNewContext(xml
);
8518 vshError(ctl
, "%s", _("Failed to get interface information"));
8522 snprintf(buf
, sizeof(buf
), "/domain/devices/interface[@type='%s']", type
);
8523 obj
= xmlXPathEval(BAD_CAST buf
, ctxt
);
8524 if ((obj
== NULL
) || (obj
->type
!= XPATH_NODESET
) ||
8525 (obj
->nodesetval
== NULL
) || (obj
->nodesetval
->nodeNr
== 0)) {
8526 vshError(ctl
, _("No found interface whose type is %s"), type
);
8534 for (; i
< obj
->nodesetval
->nodeNr
; i
++) {
8535 cur
= obj
->nodesetval
->nodeTab
[i
]->children
;
8536 while (cur
!= NULL
) {
8537 if (cur
->type
== XML_ELEMENT_NODE
&&
8538 xmlStrEqual(cur
->name
, BAD_CAST
"mac")) {
8539 char *tmp_mac
= virXMLPropString(cur
, "address");
8540 diff_mac
= virMacAddrCompare (tmp_mac
, mac
);
8549 vshError(ctl
, _("No found interface whose MAC address is %s"), mac
);
8553 xml_buf
= xmlBufferCreate();
8555 vshError(ctl
, "%s", _("Failed to allocate memory"));
8559 if(xmlNodeDump(xml_buf
, xml
, obj
->nodesetval
->nodeTab
[i
], 0, 0) < 0){
8560 vshError(ctl
, "%s", _("Failed to create XML"));
8564 if (vshCommandOptBool(cmd
, "persistent")) {
8565 flags
= VIR_DOMAIN_DEVICE_MODIFY_CONFIG
;
8566 if (virDomainIsActive(dom
) == 1)
8567 flags
|= VIR_DOMAIN_DEVICE_MODIFY_LIVE
;
8568 ret
= virDomainDetachDeviceFlags(dom
,
8569 (char *)xmlBufferContent(xml_buf
),
8572 ret
= virDomainDetachDevice(dom
, (char *)xmlBufferContent(xml_buf
));
8576 vshError(ctl
, "%s", _("Failed to detach interface"));
8579 vshPrint(ctl
, "%s", _("Interface detached successfully\n"));
8586 xmlXPathFreeObject(obj
);
8587 xmlXPathFreeContext(ctxt
);
8591 xmlBufferFree(xml_buf
);
8596 * "attach-disk" command
8598 static const vshCmdInfo info_attach_disk
[] = {
8599 {"help", N_("attach disk device")},
8600 {"desc", N_("Attach new disk device.")},
8604 static const vshCmdOptDef opts_attach_disk
[] = {
8605 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
8606 {"source", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("source of disk device")},
8607 {"target", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("target of disk device")},
8608 {"driver", VSH_OT_STRING
, 0, N_("driver of disk device")},
8609 {"subdriver", VSH_OT_STRING
, 0, N_("subdriver of disk device")},
8610 {"type", VSH_OT_STRING
, 0, N_("target device type")},
8611 {"mode", VSH_OT_STRING
, 0, N_("mode of device reading and writing")},
8612 {"persistent", VSH_OT_BOOL
, 0, N_("persist disk attachment")},
8613 {"sourcetype", VSH_OT_STRING
, 0, N_("type of source (block|file)")},
8618 cmdAttachDisk(vshControl
*ctl
, const vshCmd
*cmd
)
8620 virDomainPtr dom
= NULL
;
8621 char *source
, *target
, *driver
, *subdriver
, *type
, *mode
;
8622 int isFile
= 0, ret
= FALSE
;
8625 virBuffer buf
= VIR_BUFFER_INITIALIZER
;
8628 if (!vshConnectionUsability(ctl
, ctl
->conn
))
8631 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, NULL
)))
8634 if (!(source
= vshCommandOptString(cmd
, "source", NULL
)))
8637 if (!(target
= vshCommandOptString(cmd
, "target", NULL
)))
8640 driver
= vshCommandOptString(cmd
, "driver", NULL
);
8641 subdriver
= vshCommandOptString(cmd
, "subdriver", NULL
);
8642 type
= vshCommandOptString(cmd
, "type", NULL
);
8643 mode
= vshCommandOptString(cmd
, "mode", NULL
);
8644 stype
= vshCommandOptString(cmd
, "sourcetype", NULL
);
8647 if (driver
&& (STREQ(driver
, "file") || STREQ(driver
, "tap")))
8649 } else if (STREQ(stype
, "file")) {
8651 } else if (STRNEQ(stype
, "block")) {
8652 vshError(ctl
, _("Unknown source type: '%s'"), stype
);
8657 if (STRNEQ(mode
, "readonly") && STRNEQ(mode
, "shareable")) {
8658 vshError(ctl
, _("No support for %s in command 'attach-disk'"),
8664 /* Make XML of disk */
8665 virBufferVSprintf(&buf
, "<disk type='%s'",
8666 (isFile
) ? "file" : "block");
8668 virBufferVSprintf(&buf
, " device='%s'", type
);
8669 virBufferAddLit(&buf
, ">\n");
8671 if (driver
|| subdriver
)
8672 virBufferVSprintf(&buf
, " <driver");
8675 virBufferVSprintf(&buf
, " name='%s'", driver
);
8677 virBufferVSprintf(&buf
, " type='%s'", subdriver
);
8679 if (driver
|| subdriver
)
8680 virBufferAddLit(&buf
, "/>\n");
8682 virBufferVSprintf(&buf
, " <source %s='%s'/>\n",
8683 (isFile
) ? "file" : "dev",
8685 virBufferVSprintf(&buf
, " <target dev='%s'/>\n", target
);
8687 virBufferVSprintf(&buf
, " <%s/>\n", mode
);
8689 virBufferAddLit(&buf
, "</disk>\n");
8691 if (virBufferError(&buf
)) {
8692 vshPrint(ctl
, "%s", _("Failed to allocate XML buffer"));
8696 xml
= virBufferContentAndReset(&buf
);
8698 if (vshCommandOptBool(cmd
, "persistent")) {
8699 flags
= VIR_DOMAIN_DEVICE_MODIFY_CONFIG
;
8700 if (virDomainIsActive(dom
) == 1)
8701 flags
|= VIR_DOMAIN_DEVICE_MODIFY_LIVE
;
8702 ret
= virDomainAttachDeviceFlags(dom
, xml
, flags
);
8704 ret
= virDomainAttachDevice(dom
, xml
);
8710 vshError(ctl
, "%s", _("Failed to attach disk"));
8713 vshPrint(ctl
, "%s", _("Disk attached successfully\n"));
8720 virBufferFreeAndReset(&buf
);
8725 * "detach-disk" command
8727 static const vshCmdInfo info_detach_disk
[] = {
8728 {"help", N_("detach disk device")},
8729 {"desc", N_("Detach disk device.")},
8733 static const vshCmdOptDef opts_detach_disk
[] = {
8734 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
8735 {"target", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("target of disk device")},
8736 {"persistent", VSH_OT_BOOL
, 0, N_("persist disk detachment")},
8741 cmdDetachDisk(vshControl
*ctl
, const vshCmd
*cmd
)
8743 xmlDocPtr xml
= NULL
;
8744 xmlXPathObjectPtr obj
=NULL
;
8745 xmlXPathContextPtr ctxt
= NULL
;
8746 xmlNodePtr cur
= NULL
;
8747 xmlBufferPtr xml_buf
= NULL
;
8748 virDomainPtr dom
= NULL
;
8750 int i
= 0, diff_tgt
, ret
= FALSE
;
8753 if (!vshConnectionUsability(ctl
, ctl
->conn
))
8756 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, NULL
)))
8759 if (!(target
= vshCommandOptString(cmd
, "target", NULL
)))
8762 doc
= virDomainGetXMLDesc(dom
, 0);
8766 xml
= xmlReadDoc((const xmlChar
*) doc
, "domain.xml", NULL
,
8767 XML_PARSE_NOENT
| XML_PARSE_NONET
|
8768 XML_PARSE_NOWARNING
);
8771 vshError(ctl
, "%s", _("Failed to get disk information"));
8774 ctxt
= xmlXPathNewContext(xml
);
8776 vshError(ctl
, "%s", _("Failed to get disk information"));
8780 obj
= xmlXPathEval(BAD_CAST
"/domain/devices/disk", ctxt
);
8781 if ((obj
== NULL
) || (obj
->type
!= XPATH_NODESET
) ||
8782 (obj
->nodesetval
== NULL
) || (obj
->nodesetval
->nodeNr
== 0)) {
8783 vshError(ctl
, "%s", _("Failed to get disk information"));
8788 for (; i
< obj
->nodesetval
->nodeNr
; i
++) {
8789 cur
= obj
->nodesetval
->nodeTab
[i
]->children
;
8790 while (cur
!= NULL
) {
8791 if (cur
->type
== XML_ELEMENT_NODE
&&
8792 xmlStrEqual(cur
->name
, BAD_CAST
"target")) {
8793 char *tmp_tgt
= virXMLPropString(cur
, "dev");
8794 diff_tgt
= STREQ(tmp_tgt
, target
);
8803 vshError(ctl
, _("No found disk whose target is %s"), target
);
8807 xml_buf
= xmlBufferCreate();
8809 vshError(ctl
, "%s", _("Failed to allocate memory"));
8813 if(xmlNodeDump(xml_buf
, xml
, obj
->nodesetval
->nodeTab
[i
], 0, 0) < 0){
8814 vshError(ctl
, "%s", _("Failed to create XML"));
8818 if (vshCommandOptBool(cmd
, "persistent")) {
8819 flags
= VIR_DOMAIN_DEVICE_MODIFY_CONFIG
;
8820 if (virDomainIsActive(dom
) == 1)
8821 flags
|= VIR_DOMAIN_DEVICE_MODIFY_LIVE
;
8822 ret
= virDomainDetachDeviceFlags(dom
,
8823 (char *)xmlBufferContent(xml_buf
),
8826 ret
= virDomainDetachDevice(dom
, (char *)xmlBufferContent(xml_buf
));
8830 vshError(ctl
, "%s", _("Failed to detach disk"));
8833 vshPrint(ctl
, "%s", _("Disk detached successfully\n"));
8838 xmlXPathFreeObject(obj
);
8839 xmlXPathFreeContext(ctxt
);
8843 xmlBufferFree(xml_buf
);
8850 * "cpu-compare" command
8852 static const vshCmdInfo info_cpu_compare
[] = {
8853 {"help", N_("compare host CPU with a CPU described by an XML file")},
8854 {"desc", N_("compare CPU with host CPU")},
8858 static const vshCmdOptDef opts_cpu_compare
[] = {
8859 {"file", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("file containing an XML CPU description")},
8864 cmdCPUCompare(vshControl
*ctl
, const vshCmd
*cmd
)
8872 if (!vshConnectionUsability(ctl
, ctl
->conn
))
8875 from
= vshCommandOptString(cmd
, "file", &found
);
8879 if (virFileReadAll(from
, VIRSH_MAX_XML_FILE
, &buffer
) < 0)
8882 result
= virConnectCompareCPU(ctl
->conn
, buffer
, 0);
8886 case VIR_CPU_COMPARE_INCOMPATIBLE
:
8887 vshPrint(ctl
, _("CPU described in %s is incompatible with host CPU\n"),
8892 case VIR_CPU_COMPARE_IDENTICAL
:
8893 vshPrint(ctl
, _("CPU described in %s is identical to host CPU\n"),
8898 case VIR_CPU_COMPARE_SUPERSET
:
8899 vshPrint(ctl
, _("Host CPU is a superset of CPU described in %s\n"),
8904 case VIR_CPU_COMPARE_ERROR
:
8906 vshError(ctl
, _("Failed to compare host CPU with %s"), from
);
8914 * "cpu-baseline" command
8916 static const vshCmdInfo info_cpu_baseline
[] = {
8917 {"help", N_("compute baseline CPU")},
8918 {"desc", N_("Compute baseline CPU for a set of given CPUs.")},
8922 static const vshCmdOptDef opts_cpu_baseline
[] = {
8923 {"file", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("file containing XML CPU descriptions")},
8928 cmdCPUBaseline(vshControl
*ctl
, const vshCmd
*cmd
)
8934 char *result
= NULL
;
8935 const char **list
= NULL
;
8936 unsigned int count
= 0;
8937 xmlDocPtr doc
= NULL
;
8938 xmlNodePtr node_list
;
8939 xmlXPathContextPtr ctxt
= NULL
;
8940 xmlSaveCtxtPtr sctxt
= NULL
;
8941 xmlBufferPtr buf
= NULL
;
8942 xmlXPathObjectPtr obj
= NULL
;
8945 if (!vshConnectionUsability(ctl
, ctl
->conn
))
8948 from
= vshCommandOptString(cmd
, "file", &found
);
8952 if (virFileReadAll(from
, VIRSH_MAX_XML_FILE
, &buffer
) < 0)
8955 doc
= xmlNewDoc(NULL
);
8959 res
= xmlParseBalancedChunkMemory(doc
, NULL
, NULL
, 0,
8960 (const xmlChar
*)buffer
, &node_list
);
8962 vshError(ctl
, _("Failed to parse XML fragment %s"), from
);
8967 xmlAddChildList((xmlNodePtr
) doc
, node_list
);
8969 ctxt
= xmlXPathNewContext(doc
);
8973 obj
= xmlXPathEval(BAD_CAST
"//cpu[not(ancestor::cpu)]", ctxt
);
8974 if ((obj
== NULL
) || (obj
->nodesetval
== NULL
) ||
8975 (obj
->nodesetval
->nodeTab
== NULL
))
8978 for (i
= 0;i
< obj
->nodesetval
->nodeNr
;i
++) {
8979 buf
= xmlBufferCreate();
8982 sctxt
= xmlSaveToBuffer(buf
, NULL
, 0);
8983 if (sctxt
== NULL
) {
8988 xmlSaveTree(sctxt
, obj
->nodesetval
->nodeTab
[i
]);
8989 xmlSaveClose(sctxt
);
8991 list
= vshRealloc(ctl
, list
, sizeof(char *) * (count
+ 1));
8992 list
[count
++] = (char *) buf
->content
;
8993 buf
->content
= NULL
;
8999 vshError(ctl
, _("No host CPU specified in '%s'"), from
);
9004 result
= virConnectBaselineCPU(ctl
->conn
, list
, count
, 0);
9007 vshPrint(ctl
, "%s", result
);
9012 xmlXPathFreeObject(obj
);
9013 xmlXPathFreeContext(ctxt
);
9016 if ((list
!= NULL
) && (count
> 0)) {
9017 for (i
= 0;i
< count
;i
++)
9026 vshError(ctl
, "%s", _("Out of memory"));
9031 /* Common code for the edit / net-edit / pool-edit functions which follow. */
9033 editWriteToTempFile (vshControl
*ctl
, const char *doc
)
9039 ret
= vshMalloc(ctl
, PATH_MAX
);
9041 tmpdir
= getenv ("TMPDIR");
9042 if (!tmpdir
) tmpdir
= "/tmp";
9043 snprintf (ret
, PATH_MAX
, "%s/virshXXXXXX.xml", tmpdir
);
9044 fd
= mkstemps(ret
, 4);
9046 vshError(ctl
, _("mkstemps: failed to create temporary file: %s"),
9052 if (safewrite (fd
, doc
, strlen (doc
)) == -1) {
9053 vshError(ctl
, _("write: %s: failed to write to temporary file: %s"),
9054 ret
, strerror(errno
));
9055 VIR_FORCE_CLOSE(fd
);
9060 if (VIR_CLOSE(fd
) < 0) {
9061 vshError(ctl
, _("close: %s: failed to write or close temporary file: %s"),
9062 ret
, strerror(errno
));
9068 /* Temporary filename: caller frees. */
9072 /* Characters permitted in $EDITOR environment variable and temp filename. */
9073 #define ACCEPTED_CHARS \
9074 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-/_.:@"
9077 editFile (vshControl
*ctl
, const char *filename
)
9083 editor
= getenv ("VISUAL");
9084 if (!editor
) editor
= getenv ("EDITOR");
9085 if (!editor
) editor
= "vi"; /* could be cruel & default to ed(1) here */
9087 /* Check that filename doesn't contain shell meta-characters, and
9088 * if it does, refuse to run. Follow the Unix conventions for
9089 * EDITOR: the user can intentionally specify command options, so
9090 * we don't protect any shell metacharacters there. Lots more
9091 * than virsh will misbehave if EDITOR has bogus contents (which
9092 * is why sudo scrubs it by default).
9094 if (strspn (filename
, ACCEPTED_CHARS
) != strlen (filename
)) {
9096 _("%s: temporary filename contains shell meta or other "
9097 "unacceptable characters (is $TMPDIR wrong?)"),
9102 if (virAsprintf(&command
, "%s %s", editor
, filename
) == -1) {
9104 _("virAsprintf: could not create editing command: %s"),
9109 command_ret
= system (command
);
9110 if (command_ret
== -1) {
9112 _("%s: edit command failed: %s"), command
, strerror(errno
));
9116 if (WEXITSTATUS(command_ret
) != 0) {
9118 _("%s: command exited with non-zero status"), command
);
9127 editReadBackFile (vshControl
*ctl
, const char *filename
)
9131 if (virFileReadAll (filename
, VIRSH_MAX_XML_FILE
, &ret
) == -1) {
9133 _("%s: failed to read temporary file: %s"),
9134 filename
, strerror(errno
));
9145 static const vshCmdInfo info_cd
[] = {
9146 {"help", N_("change the current directory")},
9147 {"desc", N_("Change the current directory.")},
9151 static const vshCmdOptDef opts_cd
[] = {
9152 {"dir", VSH_OT_DATA
, 0, N_("directory to switch to (default: home or else root)")},
9157 cmdCd(vshControl
*ctl
, const vshCmd
*cmd ATTRIBUTE_UNUSED
)
9163 vshError(ctl
, "%s", _("cd: command valid only in interactive mode"));
9167 dir
= vshCommandOptString(cmd
, "dir", &found
);
9169 uid_t uid
= geteuid();
9170 dir
= virGetUserDirectory(uid
);
9175 if (chdir (dir
) == -1) {
9176 vshError(ctl
, _("cd: %s: %s"), strerror(errno
), dir
);
9189 static const vshCmdInfo info_pwd
[] = {
9190 {"help", N_("print the current directory")},
9191 {"desc", N_("Print the current directory.")},
9196 cmdPwd(vshControl
*ctl
, const vshCmd
*cmd ATTRIBUTE_UNUSED
)
9202 path_max
= (size_t) PATH_MAX
+ 2;
9203 cwd
= vshMalloc (ctl
, path_max
);
9205 err
= getcwd (cwd
, path_max
) == NULL
;
9206 if (!err
|| errno
!= ERANGE
)
9210 cwd
= vshRealloc (ctl
, cwd
, path_max
);
9214 vshError(ctl
, _("pwd: cannot get current directory: %s"),
9217 vshPrint (ctl
, _("%s\n"), cwd
);
9227 static const vshCmdInfo info_echo
[] = {
9228 {"help", N_("echo arguments")},
9229 {"desc", N_("Echo back arguments, possibly with quoting.")},
9233 static const vshCmdOptDef opts_echo
[] = {
9234 {"shell", VSH_OT_BOOL
, 0, N_("escape for shell use")},
9235 {"xml", VSH_OT_BOOL
, 0, N_("escape for XML use")},
9236 {"", VSH_OT_ARGV
, 0, N_("arguments to echo")},
9240 /* Exists mainly for debugging virsh, but also handy for adding back
9241 * quotes for later evaluation.
9244 cmdEcho (vshControl
*ctl ATTRIBUTE_UNUSED
, const vshCmd
*cmd
)
9250 virBuffer buf
= VIR_BUFFER_INITIALIZER
;
9252 if (vshCommandOptBool(cmd
, "shell"))
9254 if (vshCommandOptBool(cmd
, "xml"))
9257 while ((arg
= vshCommandOptArgv(cmd
, count
)) != NULL
) {
9258 bool close_quote
= false;
9262 virBufferAddChar(&buf
, ' ');
9263 /* Add outer '' only if arg included shell metacharacters. */
9265 (strpbrk(arg
, "\r\t\n !\"#$&'()*;<>?[\\]^`{|}~") || !*arg
)) {
9266 virBufferAddChar(&buf
, '\'');
9270 virBufferEscapeString(&buf
, "%s", arg
);
9272 if (shell
&& (q
= strchr(arg
, '\''))) {
9274 virBufferAdd(&buf
, arg
, q
- arg
);
9275 virBufferAddLit(&buf
, "'\\''");
9277 q
= strchr(arg
, '\'');
9280 virBufferAdd(&buf
, arg
, strlen(arg
));
9283 virBufferAddChar(&buf
, '\'');
9287 if (virBufferError(&buf
)) {
9288 vshPrint(ctl
, "%s", _("Failed to allocate XML buffer"));
9291 arg
= virBufferContentAndReset(&buf
);
9293 vshPrint(ctl
, "%s", arg
);
9301 static const vshCmdInfo info_edit
[] = {
9302 {"help", N_("edit XML configuration for a domain")},
9303 {"desc", N_("Edit the XML configuration for a domain.")},
9307 static const vshCmdOptDef opts_edit
[] = {
9308 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
9312 /* This function also acts as a template to generate cmdNetworkEdit
9313 * and cmdPoolEdit functions (below) using a sed script in the Makefile.
9316 cmdEdit (vshControl
*ctl
, const vshCmd
*cmd
)
9319 virDomainPtr dom
= NULL
;
9322 char *doc_edited
= NULL
;
9323 char *doc_reread
= NULL
;
9324 int flags
= VIR_DOMAIN_XML_SECURE
| VIR_DOMAIN_XML_INACTIVE
;
9326 if (!vshConnectionUsability(ctl
, ctl
->conn
))
9329 dom
= vshCommandOptDomain (ctl
, cmd
, NULL
);
9333 /* Get the XML configuration of the domain. */
9334 doc
= virDomainGetXMLDesc (dom
, flags
);
9338 /* Create and open the temporary file. */
9339 tmp
= editWriteToTempFile (ctl
, doc
);
9340 if (!tmp
) goto cleanup
;
9342 /* Start the editor. */
9343 if (editFile (ctl
, tmp
) == -1) goto cleanup
;
9345 /* Read back the edited file. */
9346 doc_edited
= editReadBackFile (ctl
, tmp
);
9347 if (!doc_edited
) goto cleanup
;
9349 /* Compare original XML with edited. Has it changed at all? */
9350 if (STREQ (doc
, doc_edited
)) {
9351 vshPrint (ctl
, _("Domain %s XML configuration not changed.\n"),
9352 virDomainGetName (dom
));
9357 /* Now re-read the domain XML. Did someone else change it while
9358 * it was being edited? This also catches problems such as us
9359 * losing a connection or the domain going away.
9361 doc_reread
= virDomainGetXMLDesc (dom
, flags
);
9365 if (STRNEQ (doc
, doc_reread
)) {
9367 "%s", _("ERROR: the XML configuration was changed by another user"));
9371 /* Everything checks out, so redefine the domain. */
9372 virDomainFree (dom
);
9373 dom
= virDomainDefineXML (ctl
->conn
, doc_edited
);
9377 vshPrint (ctl
, _("Domain %s XML configuration edited.\n"),
9378 virDomainGetName(dom
));
9384 virDomainFree (dom
);
9387 VIR_FREE(doc_edited
);
9388 VIR_FREE(doc_reread
);
9399 * "net-edit" command
9401 static const vshCmdInfo info_network_edit
[] = {
9402 {"help", N_("edit XML configuration for a network")},
9403 {"desc", N_("Edit the XML configuration for a network.")},
9407 static const vshCmdOptDef opts_network_edit
[] = {
9408 {"network", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("network name or uuid")},
9412 /* This is generated from this file by a sed script in the Makefile. */
9413 #include "virsh-net-edit.c"
9416 * "pool-edit" command
9418 static const vshCmdInfo info_pool_edit
[] = {
9419 {"help", N_("edit XML configuration for a storage pool")},
9420 {"desc", N_("Edit the XML configuration for a storage pool.")},
9424 static const vshCmdOptDef opts_pool_edit
[] = {
9425 {"pool", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("pool name or uuid")},
9429 /* This is generated from this file by a sed script in the Makefile. */
9430 #include "virsh-pool-edit.c"
9435 static const vshCmdInfo info_quit
[] = {
9436 {"help", N_("quit this interactive terminal")},
9442 cmdQuit(vshControl
*ctl
, const vshCmd
*cmd ATTRIBUTE_UNUSED
)
9449 * "snapshot-create" command
9451 static const vshCmdInfo info_snapshot_create
[] = {
9452 {"help", N_("Create a snapshot")},
9453 {"desc", N_("Snapshot create")},
9457 static const vshCmdOptDef opts_snapshot_create
[] = {
9458 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
9459 {"xmlfile", VSH_OT_DATA
, 0, N_("domain snapshot XML")},
9464 cmdSnapshotCreate(vshControl
*ctl
, const vshCmd
*cmd
)
9466 virDomainPtr dom
= NULL
;
9469 char *buffer
= NULL
;
9470 virDomainSnapshotPtr snapshot
= NULL
;
9471 xmlDocPtr xml
= NULL
;
9472 xmlXPathContextPtr ctxt
= NULL
;
9476 if (!vshConnectionUsability(ctl
, ctl
->conn
))
9479 dom
= vshCommandOptDomain(ctl
, cmd
, NULL
);
9483 from
= vshCommandOptString(cmd
, "xmlfile", NULL
);
9485 buffer
= vshStrdup(ctl
, "<domainsnapshot/>");
9487 if (virFileReadAll(from
, VIRSH_MAX_XML_FILE
, &buffer
) < 0) {
9488 /* we have to report the error here because during cleanup
9489 * we'll run through virDomainFree(), which loses the
9492 virshReportError(ctl
);
9496 if (buffer
== NULL
) {
9497 vshError(ctl
, "%s", _("Out of memory"));
9501 snapshot
= virDomainSnapshotCreateXML(dom
, buffer
, 0);
9502 if (snapshot
== NULL
)
9505 doc
= virDomainSnapshotGetXMLDesc(snapshot
, 0);
9509 xml
= xmlReadDoc((const xmlChar
*) doc
, "domainsnapshot.xml", NULL
,
9510 XML_PARSE_NOENT
| XML_PARSE_NONET
|
9511 XML_PARSE_NOWARNING
);
9514 ctxt
= xmlXPathNewContext(xml
);
9518 name
= virXPathString("string(/domainsnapshot/name)", ctxt
);
9521 _("Could not find 'name' element in domain snapshot XML"));
9525 vshPrint(ctl
, _("Domain snapshot %s created"), name
);
9527 vshPrint(ctl
, _(" from '%s'"), from
);
9528 vshPrint(ctl
, "\n");
9534 xmlXPathFreeContext(ctxt
);
9538 virDomainSnapshotFree(snapshot
);
9548 * "snapshot-current" command
9550 static const vshCmdInfo info_snapshot_current
[] = {
9551 {"help", N_("Get the current snapshot")},
9552 {"desc", N_("Get the current snapshot")},
9556 static const vshCmdOptDef opts_snapshot_current
[] = {
9557 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
9562 cmdSnapshotCurrent(vshControl
*ctl
, const vshCmd
*cmd
)
9564 virDomainPtr dom
= NULL
;
9567 virDomainSnapshotPtr snapshot
= NULL
;
9569 if (!vshConnectionUsability(ctl
, ctl
->conn
))
9572 dom
= vshCommandOptDomain(ctl
, cmd
, NULL
);
9576 current
= virDomainHasCurrentSnapshot(dom
, 0);
9582 if (!(snapshot
= virDomainSnapshotCurrent(dom
, 0)))
9585 xml
= virDomainSnapshotGetXMLDesc(snapshot
, 0);
9589 vshPrint(ctl
, "%s", xml
);
9597 virDomainSnapshotFree(snapshot
);
9605 * "snapshot-list" command
9607 static const vshCmdInfo info_snapshot_list
[] = {
9608 {"help", N_("List snapshots for a domain")},
9609 {"desc", N_("Snapshot List")},
9613 static const vshCmdOptDef opts_snapshot_list
[] = {
9614 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
9619 cmdSnapshotList(vshControl
*ctl
, const vshCmd
*cmd
)
9621 virDomainPtr dom
= NULL
;
9624 char **names
= NULL
;
9627 xmlDocPtr xml
= NULL
;
9628 xmlXPathContextPtr ctxt
= NULL
;
9630 virDomainSnapshotPtr snapshot
= NULL
;
9634 struct tm time_info
;
9636 if (!vshConnectionUsability(ctl
, ctl
->conn
))
9639 dom
= vshCommandOptDomain(ctl
, cmd
, NULL
);
9643 numsnaps
= virDomainSnapshotNum(dom
, 0);
9648 vshPrint(ctl
, " %-20s %-25s %s\n", _("Name"), _("Creation Time"), _("State"));
9649 vshPrint(ctl
, "---------------------------------------------------\n");
9652 if (VIR_ALLOC_N(names
, numsnaps
) < 0)
9655 actual
= virDomainSnapshotListNames(dom
, names
, numsnaps
, 0);
9659 qsort(&names
[0], actual
, sizeof(char*), namesorter
);
9661 for (i
= 0; i
< actual
; i
++) {
9662 /* free up memory from previous iterations of the loop */
9665 virDomainSnapshotFree(snapshot
);
9666 xmlXPathFreeContext(ctxt
);
9671 snapshot
= virDomainSnapshotLookupByName(dom
, names
[i
], 0);
9672 if (snapshot
== NULL
)
9675 doc
= virDomainSnapshotGetXMLDesc(snapshot
, 0);
9679 xml
= xmlReadDoc((const xmlChar
*) doc
, "domainsnapshot.xml", NULL
,
9680 XML_PARSE_NOENT
| XML_PARSE_NONET
|
9681 XML_PARSE_NOWARNING
);
9684 ctxt
= xmlXPathNewContext(xml
);
9688 state
= virXPathString("string(/domainsnapshot/state)", ctxt
);
9691 if (virXPathLong("string(/domainsnapshot/creationTime)", ctxt
,
9694 localtime_r(&creation
, &time_info
);
9695 strftime(timestr
, sizeof(timestr
), "%Y-%m-%d %H:%M:%S %z", &time_info
);
9697 vshPrint(ctl
, " %-20s %-25s %s\n", names
[i
], timestr
, state
);
9704 /* this frees up memory from the last iteration of the loop */
9707 virDomainSnapshotFree(snapshot
);
9708 xmlXPathFreeContext(ctxt
);
9712 for (i
= 0; i
< actual
; i
++)
9722 * "snapshot-dumpxml" command
9724 static const vshCmdInfo info_snapshot_dumpxml
[] = {
9725 {"help", N_("Dump XML for a domain snapshot")},
9726 {"desc", N_("Snapshot Dump XML")},
9730 static const vshCmdOptDef opts_snapshot_dumpxml
[] = {
9731 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
9732 {"snapshotname", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("snapshot name")},
9737 cmdSnapshotDumpXML(vshControl
*ctl
, const vshCmd
*cmd
)
9739 virDomainPtr dom
= NULL
;
9742 virDomainSnapshotPtr snapshot
= NULL
;
9745 if (!vshConnectionUsability(ctl
, ctl
->conn
))
9748 dom
= vshCommandOptDomain(ctl
, cmd
, NULL
);
9752 name
= vshCommandOptString(cmd
, "snapshotname", NULL
);
9756 snapshot
= virDomainSnapshotLookupByName(dom
, name
, 0);
9757 if (snapshot
== NULL
)
9760 xml
= virDomainSnapshotGetXMLDesc(snapshot
, 0);
9764 vshPrint(ctl
, "%s", xml
);
9771 virDomainSnapshotFree(snapshot
);
9779 * "snapshot-revert" command
9781 static const vshCmdInfo info_snapshot_revert
[] = {
9782 {"help", N_("Revert a domain to a snapshot")},
9783 {"desc", N_("Revert domain to snapshot")},
9787 static const vshCmdOptDef opts_snapshot_revert
[] = {
9788 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
9789 {"snapshotname", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("snapshot name")},
9794 cmdDomainSnapshotRevert(vshControl
*ctl
, const vshCmd
*cmd
)
9796 virDomainPtr dom
= NULL
;
9799 virDomainSnapshotPtr snapshot
= NULL
;
9801 if (!vshConnectionUsability(ctl
, ctl
->conn
))
9804 dom
= vshCommandOptDomain(ctl
, cmd
, NULL
);
9808 name
= vshCommandOptString(cmd
, "snapshotname", NULL
);
9812 snapshot
= virDomainSnapshotLookupByName(dom
, name
, 0);
9813 if (snapshot
== NULL
)
9816 if (virDomainRevertToSnapshot(snapshot
, 0) < 0)
9823 virDomainSnapshotFree(snapshot
);
9831 * "snapshot-delete" command
9833 static const vshCmdInfo info_snapshot_delete
[] = {
9834 {"help", N_("Delete a domain snapshot")},
9835 {"desc", N_("Snapshot Delete")},
9839 static const vshCmdOptDef opts_snapshot_delete
[] = {
9840 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
9841 {"snapshotname", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("snapshot name")},
9842 {"children", VSH_OT_BOOL
, 0, N_("delete snapshot and all children")},
9847 cmdSnapshotDelete(vshControl
*ctl
, const vshCmd
*cmd
)
9849 virDomainPtr dom
= NULL
;
9852 virDomainSnapshotPtr snapshot
= NULL
;
9853 unsigned int flags
= 0;
9855 if (!vshConnectionUsability(ctl
, ctl
->conn
))
9858 dom
= vshCommandOptDomain(ctl
, cmd
, NULL
);
9862 name
= vshCommandOptString(cmd
, "snapshotname", NULL
);
9866 if (vshCommandOptBool(cmd
, "children"))
9867 flags
|= VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN
;
9869 snapshot
= virDomainSnapshotLookupByName(dom
, name
, 0);
9870 if (snapshot
== NULL
)
9873 if (virDomainSnapshotDelete(snapshot
, flags
) < 0)
9880 virDomainSnapshotFree(snapshot
);
9888 * "qemu-monitor-command" command
9890 static const vshCmdInfo info_qemu_monitor_command
[] = {
9891 {"help", N_("Qemu Monitor Command")},
9892 {"desc", N_("Qemu Monitor Command")},
9896 static const vshCmdOptDef opts_qemu_monitor_command
[] = {
9897 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
9898 {"cmd", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("command")},
9903 cmdQemuMonitorCommand(vshControl
*ctl
, const vshCmd
*cmd
)
9905 virDomainPtr dom
= NULL
;
9908 char *result
= NULL
;
9910 if (!vshConnectionUsability(ctl
, ctl
->conn
))
9913 dom
= vshCommandOptDomain(ctl
, cmd
, NULL
);
9917 monitor_cmd
= vshCommandOptString(cmd
, "cmd", NULL
);
9918 if (monitor_cmd
== NULL
) {
9919 vshError(ctl
, "%s", _("missing monitor command"));
9923 if (virDomainQemuMonitorCommand(dom
, monitor_cmd
, &result
, 0) < 0)
9926 printf("%s\n", result
);
9938 static const vshCmdDef domManagementCmds
[] = {
9939 {"attach-device", cmdAttachDevice
, opts_attach_device
, info_attach_device
},
9940 {"attach-disk", cmdAttachDisk
, opts_attach_disk
, info_attach_disk
},
9941 {"attach-interface", cmdAttachInterface
, opts_attach_interface
, info_attach_interface
},
9942 {"autostart", cmdAutostart
, opts_autostart
, info_autostart
},
9944 {"console", cmdConsole
, opts_console
, info_console
},
9946 {"cpu-baseline", cmdCPUBaseline
, opts_cpu_baseline
, info_cpu_baseline
},
9947 {"cpu-compare", cmdCPUCompare
, opts_cpu_compare
, info_cpu_compare
},
9948 {"create", cmdCreate
, opts_create
, info_create
},
9949 {"define", cmdDefine
, opts_define
, info_define
},
9950 {"destroy", cmdDestroy
, opts_destroy
, info_destroy
},
9951 {"detach-device", cmdDetachDevice
, opts_detach_device
, info_detach_device
},
9952 {"detach-disk", cmdDetachDisk
, opts_detach_disk
, info_detach_disk
},
9953 {"detach-interface", cmdDetachInterface
, opts_detach_interface
, info_detach_interface
},
9954 {"domid", cmdDomid
, opts_domid
, info_domid
},
9955 {"domjobabort", cmdDomjobabort
, opts_domjobabort
, info_domjobabort
},
9956 {"domjobinfo", cmdDomjobinfo
, opts_domjobinfo
, info_domjobinfo
},
9957 {"domname", cmdDomname
, opts_domname
, info_domname
},
9958 {"domuuid", cmdDomuuid
, opts_domuuid
, info_domuuid
},
9959 {"domxml-from-native", cmdDomXMLFromNative
, opts_domxmlfromnative
, info_domxmlfromnative
},
9960 {"domxml-to-native", cmdDomXMLToNative
, opts_domxmltonative
, info_domxmltonative
},
9961 {"dump", cmdDump
, opts_dump
, info_dump
},
9962 {"dumpxml", cmdDumpXML
, opts_dumpxml
, info_dumpxml
},
9963 {"echo", cmdEcho
, opts_echo
, info_echo
},
9964 {"edit", cmdEdit
, opts_edit
, info_edit
},
9965 {"freecell", cmdFreecell
, opts_freecell
, info_freecell
},
9966 {"hostname", cmdHostname
, NULL
, info_hostname
},
9967 {"managedsave", cmdManagedSave
, opts_managedsave
, info_managedsave
},
9968 {"managedsave-remove", cmdManagedSaveRemove
, opts_managedsaveremove
, info_managedsaveremove
},
9969 {"maxvcpus", cmdMaxvcpus
, opts_maxvcpus
, info_maxvcpus
},
9970 {"memtune", cmdMemtune
, opts_memtune
, info_memtune
},
9971 {"migrate", cmdMigrate
, opts_migrate
, info_migrate
},
9972 {"migrate-setmaxdowntime", cmdMigrateSetMaxDowntime
, opts_migrate_setmaxdowntime
, info_migrate_setmaxdowntime
},
9973 {"reboot", cmdReboot
, opts_reboot
, info_reboot
},
9974 {"restore", cmdRestore
, opts_restore
, info_restore
},
9975 {"resume", cmdResume
, opts_resume
, info_resume
},
9976 {"save", cmdSave
, opts_save
, info_save
},
9977 {"schedinfo", cmdSchedinfo
, opts_schedinfo
, info_schedinfo
},
9978 {"setmaxmem", cmdSetmaxmem
, opts_setmaxmem
, info_setmaxmem
},
9979 {"setmem", cmdSetmem
, opts_setmem
, info_setmem
},
9980 {"setvcpus", cmdSetvcpus
, opts_setvcpus
, info_setvcpus
},
9981 {"shutdown", cmdShutdown
, opts_shutdown
, info_shutdown
},
9982 {"start", cmdStart
, opts_start
, info_start
},
9983 {"suspend", cmdSuspend
, opts_suspend
, info_suspend
},
9984 {"ttyconsole", cmdTTYConsole
, opts_ttyconsole
, info_ttyconsole
},
9985 {"undefine", cmdUndefine
, opts_undefine
, info_undefine
},
9986 {"update-device", cmdUpdateDevice
, opts_update_device
, info_update_device
},
9987 {"vcpucount", cmdVcpucount
, opts_vcpucount
, info_vcpucount
},
9988 {"vcpuinfo", cmdVcpuinfo
, opts_vcpuinfo
, info_vcpuinfo
},
9989 {"vcpupin", cmdVcpupin
, opts_vcpupin
, info_vcpupin
},
9990 {"version", cmdVersion
, NULL
, info_version
},
9991 {"vncdisplay", cmdVNCDisplay
, opts_vncdisplay
, info_vncdisplay
},
9992 {NULL
, NULL
, NULL
, NULL
}
9995 static const vshCmdDef domMonitoringCmds
[] = {
9996 {"domblkinfo", cmdDomblkinfo
, opts_domblkinfo
, info_domblkinfo
},
9997 {"domblkstat", cmdDomblkstat
, opts_domblkstat
, info_domblkstat
},
9998 {"domifstat", cmdDomIfstat
, opts_domifstat
, info_domifstat
},
9999 {"dominfo", cmdDominfo
, opts_dominfo
, info_dominfo
},
10000 {"dommemstat", cmdDomMemStat
, opts_dommemstat
, info_dommemstat
},
10001 {"domstate", cmdDomstate
, opts_domstate
, info_domstate
},
10002 {"list", cmdList
, opts_list
, info_list
},
10003 {NULL
, NULL
, NULL
, NULL
}
10006 static const vshCmdDef storagePoolCmds
[] = {
10007 {"find-storage-pool-sources-as", cmdPoolDiscoverSourcesAs
,
10008 opts_find_storage_pool_sources_as
, info_find_storage_pool_sources_as
},
10009 {"find-storage-pool-sources", cmdPoolDiscoverSources
,
10010 opts_find_storage_pool_sources
, info_find_storage_pool_sources
},
10011 {"pool-autostart", cmdPoolAutostart
, opts_pool_autostart
, info_pool_autostart
},
10012 {"pool-build", cmdPoolBuild
, opts_pool_build
, info_pool_build
},
10013 {"pool-create-as", cmdPoolCreateAs
, opts_pool_X_as
, info_pool_create_as
},
10014 {"pool-create", cmdPoolCreate
, opts_pool_create
, info_pool_create
},
10015 {"pool-define-as", cmdPoolDefineAs
, opts_pool_X_as
, info_pool_define_as
},
10016 {"pool-define", cmdPoolDefine
, opts_pool_define
, info_pool_define
},
10017 {"pool-delete", cmdPoolDelete
, opts_pool_delete
, info_pool_delete
},
10018 {"pool-destroy", cmdPoolDestroy
, opts_pool_destroy
, info_pool_destroy
},
10019 {"pool-dumpxml", cmdPoolDumpXML
, opts_pool_dumpxml
, info_pool_dumpxml
},
10020 {"pool-edit", cmdPoolEdit
, opts_pool_edit
, info_pool_edit
},
10021 {"pool-info", cmdPoolInfo
, opts_pool_info
, info_pool_info
},
10022 {"pool-list", cmdPoolList
, opts_pool_list
, info_pool_list
},
10023 {"pool-name", cmdPoolName
, opts_pool_name
, info_pool_name
},
10024 {"pool-refresh", cmdPoolRefresh
, opts_pool_refresh
, info_pool_refresh
},
10025 {"pool-start", cmdPoolStart
, opts_pool_start
, info_pool_start
},
10026 {"pool-undefine", cmdPoolUndefine
, opts_pool_undefine
, info_pool_undefine
},
10027 {"pool-uuid", cmdPoolUuid
, opts_pool_uuid
, info_pool_uuid
},
10028 {NULL
, NULL
, NULL
, NULL
}
10031 static const vshCmdDef storageVolCmds
[] = {
10032 {"vol-clone", cmdVolClone
, opts_vol_clone
, info_vol_clone
},
10033 {"vol-create-as", cmdVolCreateAs
, opts_vol_create_as
, info_vol_create_as
},
10034 {"vol-create", cmdVolCreate
, opts_vol_create
, info_vol_create
},
10035 {"vol-create-from", cmdVolCreateFrom
, opts_vol_create_from
, info_vol_create_from
},
10036 {"vol-delete", cmdVolDelete
, opts_vol_delete
, info_vol_delete
},
10037 {"vol-dumpxml", cmdVolDumpXML
, opts_vol_dumpxml
, info_vol_dumpxml
},
10038 {"vol-info", cmdVolInfo
, opts_vol_info
, info_vol_info
},
10039 {"vol-key", cmdVolKey
, opts_vol_key
, info_vol_key
},
10040 {"vol-list", cmdVolList
, opts_vol_list
, info_vol_list
},
10041 {"vol-name", cmdVolName
, opts_vol_name
, info_vol_name
},
10042 {"vol-path", cmdVolPath
, opts_vol_path
, info_vol_path
},
10043 {"vol-pool", cmdVolPool
, opts_vol_pool
, info_vol_pool
},
10044 {"vol-wipe", cmdVolWipe
, opts_vol_wipe
, info_vol_wipe
},
10045 {NULL
, NULL
, NULL
, NULL
}
10048 static const vshCmdDef networkCmds
[] = {
10049 {"net-autostart", cmdNetworkAutostart
, opts_network_autostart
, info_network_autostart
},
10050 {"net-create", cmdNetworkCreate
, opts_network_create
, info_network_create
},
10051 {"net-define", cmdNetworkDefine
, opts_network_define
, info_network_define
},
10052 {"net-destroy", cmdNetworkDestroy
, opts_network_destroy
, info_network_destroy
},
10053 {"net-dumpxml", cmdNetworkDumpXML
, opts_network_dumpxml
, info_network_dumpxml
},
10054 {"net-edit", cmdNetworkEdit
, opts_network_edit
, info_network_edit
},
10055 {"net-info", cmdNetworkInfo
, opts_network_info
, info_network_info
},
10056 {"net-list", cmdNetworkList
, opts_network_list
, info_network_list
},
10057 {"net-name", cmdNetworkName
, opts_network_name
, info_network_name
},
10058 {"net-start", cmdNetworkStart
, opts_network_start
, info_network_start
},
10059 {"net-undefine", cmdNetworkUndefine
, opts_network_undefine
, info_network_undefine
},
10060 {"net-uuid", cmdNetworkUuid
, opts_network_uuid
, info_network_uuid
},
10061 {NULL
, NULL
, NULL
, NULL
}
10064 static const vshCmdDef nodedevCmds
[] = {
10065 {"nodedev-create", cmdNodeDeviceCreate
, opts_node_device_create
, info_node_device_create
},
10066 {"nodedev-destroy", cmdNodeDeviceDestroy
, opts_node_device_destroy
, info_node_device_destroy
},
10067 {"nodedev-dettach", cmdNodeDeviceDettach
, opts_node_device_dettach
, info_node_device_dettach
},
10068 {"nodedev-dumpxml", cmdNodeDeviceDumpXML
, opts_node_device_dumpxml
, info_node_device_dumpxml
},
10069 {"nodedev-list", cmdNodeListDevices
, opts_node_list_devices
, info_node_list_devices
},
10070 {"nodedev-reattach", cmdNodeDeviceReAttach
, opts_node_device_reattach
, info_node_device_reattach
},
10071 {"nodedev-reset", cmdNodeDeviceReset
, opts_node_device_reset
, info_node_device_reset
},
10072 {"nodeinfo", cmdNodeinfo
, NULL
, info_nodeinfo
},
10073 {NULL
, NULL
, NULL
, NULL
}
10076 static const vshCmdDef ifaceCmds
[] = {
10077 {"iface-define", cmdInterfaceDefine
, opts_interface_define
, info_interface_define
},
10078 {"iface-destroy", cmdInterfaceDestroy
, opts_interface_destroy
, info_interface_destroy
},
10079 {"iface-dumpxml", cmdInterfaceDumpXML
, opts_interface_dumpxml
, info_interface_dumpxml
},
10080 {"iface-edit", cmdInterfaceEdit
, opts_interface_edit
, info_interface_edit
},
10081 {"iface-list", cmdInterfaceList
, opts_interface_list
, info_interface_list
},
10082 {"iface-mac", cmdInterfaceMAC
, opts_interface_mac
, info_interface_mac
},
10083 {"iface-name", cmdInterfaceName
, opts_interface_name
, info_interface_name
},
10084 {"iface-start", cmdInterfaceStart
, opts_interface_start
, info_interface_start
},
10085 {"iface-undefine", cmdInterfaceUndefine
, opts_interface_undefine
, info_interface_undefine
},
10086 {NULL
, NULL
, NULL
, NULL
}
10089 static const vshCmdDef nwfilterCmds
[] = {
10090 {"nwfilter-define", cmdNWFilterDefine
, opts_nwfilter_define
, info_nwfilter_define
},
10091 {"nwfilter-dumpxml", cmdNWFilterDumpXML
, opts_nwfilter_dumpxml
, info_nwfilter_dumpxml
},
10092 {"nwfilter-edit", cmdNWFilterEdit
, opts_nwfilter_edit
, info_nwfilter_edit
},
10093 {"nwfilter-list", cmdNWFilterList
, opts_nwfilter_list
, info_nwfilter_list
},
10094 {"nwfilter-undefine", cmdNWFilterUndefine
, opts_nwfilter_undefine
, info_nwfilter_undefine
},
10095 {NULL
, NULL
, NULL
, NULL
}
10098 static const vshCmdDef secretCmds
[] = {
10099 {"secret-define", cmdSecretDefine
, opts_secret_define
, info_secret_define
},
10100 {"secret-dumpxml", cmdSecretDumpXML
, opts_secret_dumpxml
, info_secret_dumpxml
},
10101 {"secret-get-value", cmdSecretGetValue
, opts_secret_get_value
, info_secret_get_value
},
10102 {"secret-list", cmdSecretList
, NULL
, info_secret_list
},
10103 {"secret-set-value", cmdSecretSetValue
, opts_secret_set_value
, info_secret_set_value
},
10104 {"secret-undefine", cmdSecretUndefine
, opts_secret_undefine
, info_secret_undefine
},
10105 {NULL
, NULL
, NULL
, NULL
}
10108 static const vshCmdDef virshCmds
[] = {
10110 {"cd", cmdCd
, opts_cd
, info_cd
},
10112 {"echo", cmdEcho
, opts_echo
, info_echo
},
10113 {"exit", cmdQuit
, NULL
, info_quit
},
10114 {"help", cmdHelp
, opts_help
, info_help
},
10116 {"pwd", cmdPwd
, NULL
, info_pwd
},
10118 {"quit", cmdQuit
, NULL
, info_quit
},
10119 {NULL
, NULL
, NULL
, NULL
}
10122 static const vshCmdDef snapshotCmds
[] = {
10123 {"snapshot-create", cmdSnapshotCreate
, opts_snapshot_create
, info_snapshot_create
},
10124 {"snapshot-current", cmdSnapshotCurrent
, opts_snapshot_current
, info_snapshot_current
},
10125 {"snapshot-delete", cmdSnapshotDelete
, opts_snapshot_delete
, info_snapshot_delete
},
10126 {"snapshot-dumpxml", cmdSnapshotDumpXML
, opts_snapshot_dumpxml
, info_snapshot_dumpxml
},
10127 {"snapshot-list", cmdSnapshotList
, opts_snapshot_list
, info_snapshot_list
},
10128 {"snapshot-revert", cmdDomainSnapshotRevert
, opts_snapshot_revert
, info_snapshot_revert
},
10129 {NULL
, NULL
, NULL
, NULL
}
10132 static const vshCmdDef hostAndHypervisorCmds
[] = {
10133 {"capabilities", cmdCapabilities
, NULL
, info_capabilities
},
10134 {"connect", cmdConnect
, opts_connect
, info_connect
},
10135 {"freecell", cmdFreecell
, opts_freecell
, info_freecell
},
10136 {"hostname", cmdHostname
, NULL
, info_hostname
},
10137 {"qemu-monitor-command", cmdQemuMonitorCommand
, opts_qemu_monitor_command
, info_qemu_monitor_command
},
10138 {"uri", cmdURI
, NULL
, info_uri
},
10139 {NULL
, NULL
, NULL
, NULL
}
10142 static const vshCmdGrp cmdGroups
[] = {
10143 {VSH_CMD_GRP_DOM_MANAGEMENT
, "domain", domManagementCmds
},
10144 {VSH_CMD_GRP_DOM_MONITORING
, "monitor", domMonitoringCmds
},
10145 {VSH_CMD_GRP_HOST_AND_HV
, "host", hostAndHypervisorCmds
},
10146 {VSH_CMD_GRP_IFACE
, "interface", ifaceCmds
},
10147 {VSH_CMD_GRP_NWFILTER
, "filter", nwfilterCmds
},
10148 {VSH_CMD_GRP_NETWORK
, "network", networkCmds
},
10149 {VSH_CMD_GRP_NODEDEV
, "nodedev", nodedevCmds
},
10150 {VSH_CMD_GRP_SECRET
, "secret", secretCmds
},
10151 {VSH_CMD_GRP_SNAPSHOT
, "snapshot", snapshotCmds
},
10152 {VSH_CMD_GRP_STORAGE_POOL
, "pool", storagePoolCmds
},
10153 {VSH_CMD_GRP_STORAGE_VOL
, "volume", storageVolCmds
},
10154 {VSH_CMD_GRP_VIRSH
, "virsh", virshCmds
},
10160 * Utils for work with command definition
10163 static const char *
10164 vshCmddefGetInfo(const vshCmdDef
* cmd
, const char *name
)
10166 const vshCmdInfo
*info
;
10168 for (info
= cmd
->info
; info
&& info
->name
; info
++) {
10169 if (STREQ(info
->name
, name
))
10175 static const vshCmdOptDef
*
10176 vshCmddefGetOption(const vshCmdDef
* cmd
, const char *name
)
10178 const vshCmdOptDef
*opt
;
10180 for (opt
= cmd
->opts
; opt
&& opt
->name
; opt
++)
10181 if (STREQ(opt
->name
, name
))
10186 static const vshCmdOptDef
*
10187 vshCmddefGetData(const vshCmdDef
* cmd
, int data_ct
)
10189 const vshCmdOptDef
*opt
;
10191 for (opt
= cmd
->opts
; opt
&& opt
->name
; opt
++) {
10192 if (opt
->type
>= VSH_OT_DATA
||
10193 (opt
->type
== VSH_OT_INT
&& (opt
->flag
& VSH_OFLAG_REQ
))) {
10194 if (data_ct
== 0 || opt
->type
== VSH_OT_ARGV
)
10204 * Checks for required options
10207 vshCommandCheckOpts(vshControl
*ctl
, const vshCmd
*cmd
)
10209 const vshCmdDef
*def
= cmd
->def
;
10210 const vshCmdOptDef
*d
;
10213 for (d
= def
->opts
; d
&& d
->name
; d
++) {
10214 if (d
->flag
& VSH_OFLAG_REQ
) {
10215 vshCmdOpt
*o
= cmd
->opts
;
10218 while (o
&& ok
== 0) {
10225 d
->type
== VSH_OT_DATA
?
10226 _("command '%s' requires <%s> option") :
10227 _("command '%s' requires --%s option"),
10228 def
->name
, d
->name
);
10237 static const vshCmdDef
*
10238 vshCmddefSearch(const char *cmdname
)
10240 const vshCmdGrp
*g
;
10241 const vshCmdDef
*c
;
10243 for (g
= cmdGroups
; g
->name
; g
++) {
10244 for (c
= g
->commands
; c
->name
; c
++) {
10245 if(STREQ(c
->name
, cmdname
))
10253 static const vshCmdGrp
*
10254 vshCmdGrpSearch(const char *grpname
)
10256 const vshCmdGrp
*g
;
10258 for (g
= cmdGroups
; g
->name
; g
++) {
10259 if(STREQ(g
->name
, grpname
) || STREQ(g
->keyword
, grpname
))
10267 vshCmdGrpHelp(vshControl
*ctl
, const char *grpname
)
10269 const vshCmdGrp
*grp
= vshCmdGrpSearch(grpname
);
10270 const vshCmdDef
*cmd
= NULL
;
10273 vshError(ctl
, _("command group '%s' doesn't exist"), grpname
);
10276 vshPrint(ctl
, _(" %s (help keyword '%s'):\n"), grp
->name
,
10279 for (cmd
= grp
->commands
; cmd
->name
; cmd
++) {
10280 vshPrint(ctl
, " %-30s %s\n", cmd
->name
,
10281 _(vshCmddefGetInfo(cmd
, "help")));
10289 vshCmddefHelp(vshControl
*ctl
, const char *cmdname
)
10291 const vshCmdDef
*def
= vshCmddefSearch(cmdname
);
10294 vshError(ctl
, _("command '%s' doesn't exist"), cmdname
);
10297 const char *desc
= _(vshCmddefGetInfo(def
, "desc"));
10298 const char *help
= _(vshCmddefGetInfo(def
, "help"));
10301 fputs(_(" NAME\n"), stdout
);
10302 fprintf(stdout
, " %s - %s\n", def
->name
, help
);
10304 fputs(_("\n SYNOPSIS\n"), stdout
);
10305 fprintf(stdout
, " %s", def
->name
);
10307 const vshCmdOptDef
*opt
;
10308 for (opt
= def
->opts
; opt
->name
; opt
++) {
10310 switch (opt
->type
) {
10315 /* xgettext:c-format */
10316 fmt
= ((opt
->flag
& VSH_OFLAG_REQ
) ? "<%s>"
10317 : _("[--%s <number>]"));
10319 case VSH_OT_STRING
:
10320 /* xgettext:c-format */
10321 fmt
= _("[--%s <string>]");
10324 fmt
= ((opt
->flag
& VSH_OFLAG_REQ
) ? "<%s>" : "[<%s>]");
10327 /* xgettext:c-format */
10328 fmt
= _("[<string>]...");
10333 fputc(' ', stdout
);
10334 fprintf(stdout
, fmt
, opt
->name
);
10337 fputc('\n', stdout
);
10340 /* Print the description only if it's not empty. */
10341 fputs(_("\n DESCRIPTION\n"), stdout
);
10342 fprintf(stdout
, " %s\n", desc
);
10346 const vshCmdOptDef
*opt
;
10347 fputs(_("\n OPTIONS\n"), stdout
);
10348 for (opt
= def
->opts
; opt
->name
; opt
++) {
10349 switch (opt
->type
) {
10351 snprintf(buf
, sizeof(buf
), "--%s", opt
->name
);
10354 snprintf(buf
, sizeof(buf
),
10355 (opt
->flag
& VSH_OFLAG_REQ
) ? _("[--%s] <number>")
10356 : _("--%s <number>"), opt
->name
);
10358 case VSH_OT_STRING
:
10359 /* OT_STRING should never be VSH_OFLAG_REQ */
10360 snprintf(buf
, sizeof(buf
), _("--%s <string>"), opt
->name
);
10363 snprintf(buf
, sizeof(buf
), _("[--%s] <string>"),
10367 /* Not really an option. */
10373 fprintf(stdout
, " %-15s %s\n", buf
, _(opt
->help
));
10376 fputc('\n', stdout
);
10382 * Utils for work with runtime commands data
10386 vshCommandOptFree(vshCmdOpt
* arg
)
10388 vshCmdOpt
*a
= arg
;
10391 vshCmdOpt
*tmp
= a
;
10395 VIR_FREE(tmp
->data
);
10401 vshCommandFree(vshCmd
*cmd
)
10411 vshCommandOptFree(tmp
->opts
);
10417 * Returns option by name
10420 vshCommandOpt(const vshCmd
*cmd
, const char *name
)
10422 vshCmdOpt
*opt
= cmd
->opts
;
10425 if (opt
->def
&& STREQ(opt
->def
->name
, name
))
10433 * Returns option as INT
10436 vshCommandOptInt(const vshCmd
*cmd
, const char *name
, int *found
)
10438 vshCmdOpt
*arg
= vshCommandOpt(cmd
, name
);
10439 int res
= 0, num_found
= FALSE
;
10440 char *end_p
= NULL
;
10442 if ((arg
!= NULL
) && (arg
->data
!= NULL
)) {
10443 res
= strtol(arg
->data
, &end_p
, 10);
10444 if ((arg
->data
== end_p
) || (*end_p
!= 0))
10450 *found
= num_found
;
10454 static unsigned long
10455 vshCommandOptUL(const vshCmd
*cmd
, const char *name
, int *found
)
10457 vshCmdOpt
*arg
= vshCommandOpt(cmd
, name
);
10458 unsigned long res
= 0;
10459 int num_found
= FALSE
;
10460 char *end_p
= NULL
;
10462 if ((arg
!= NULL
) && (arg
->data
!= NULL
)) {
10463 res
= strtoul(arg
->data
, &end_p
, 10);
10464 if ((arg
->data
== end_p
) || (*end_p
!= 0))
10470 *found
= num_found
;
10475 * Returns option as STRING
10478 vshCommandOptString(const vshCmd
*cmd
, const char *name
, int *found
)
10480 vshCmdOpt
*arg
= vshCommandOpt(cmd
, name
);
10483 *found
= arg
? TRUE
: FALSE
;
10485 if (arg
&& arg
->data
&& *arg
->data
)
10488 if (arg
&& arg
->def
&& ((arg
->def
->flag
) & VSH_OFLAG_REQ
))
10489 vshError(NULL
, _("Missing required option '%s'"), name
);
10495 * Returns option as long long
10498 vshCommandOptLongLong(const vshCmd
*cmd
, const char *name
, int *found
)
10500 vshCmdOpt
*arg
= vshCommandOpt(cmd
, name
);
10501 int num_found
= FALSE
;
10503 char *end_p
= NULL
;
10505 if ((arg
!= NULL
) && (arg
->data
!= NULL
))
10506 num_found
= !virStrToLong_ll(arg
->data
, &end_p
, 10, &res
);
10508 *found
= num_found
;
10513 * Returns TRUE/FALSE if the option exists
10516 vshCommandOptBool(const vshCmd
*cmd
, const char *name
)
10518 return vshCommandOpt(cmd
, name
) ? TRUE
: FALSE
;
10522 * Returns the COUNT argv argument, or NULL after last argument.
10524 * Requires that a VSH_OT_ARGV option with the name "" be last in the
10525 * list of supported options in CMD->def->opts.
10528 vshCommandOptArgv(const vshCmd
*cmd
, int count
)
10530 vshCmdOpt
*opt
= cmd
->opts
;
10533 if (opt
->def
&& opt
->def
->type
== VSH_OT_ARGV
) {
10542 /* Determine whether CMD->opts includes an option with name OPTNAME.
10543 If not, give a diagnostic and return false.
10544 If so, return true. */
10546 cmd_has_option (vshControl
*ctl
, const vshCmd
*cmd
, const char *optname
)
10548 /* Iterate through cmd->opts, to ensure that there is an entry
10549 with name OPTNAME and type VSH_OT_DATA. */
10550 bool found
= false;
10551 const vshCmdOpt
*opt
;
10552 for (opt
= cmd
->opts
; opt
; opt
= opt
->next
) {
10553 if (STREQ (opt
->def
->name
, optname
) && opt
->def
->type
== VSH_OT_DATA
) {
10560 vshError(ctl
, _("internal error: virsh %s: no %s VSH_OT_DATA option"),
10561 cmd
->def
->name
, optname
);
10565 static virDomainPtr
10566 vshCommandOptDomainBy(vshControl
*ctl
, const vshCmd
*cmd
,
10567 char **name
, int flag
)
10569 virDomainPtr dom
= NULL
;
10572 const char *optname
= "domain";
10573 if (!cmd_has_option (ctl
, cmd
, optname
))
10576 if (!(n
= vshCommandOptString(cmd
, optname
, NULL
)))
10579 vshDebug(ctl
, 5, "%s: found option <%s>: %s\n",
10580 cmd
->def
->name
, optname
, n
);
10586 if (flag
& VSH_BYID
) {
10587 if (virStrToLong_i(n
, NULL
, 10, &id
) == 0 && id
>= 0) {
10588 vshDebug(ctl
, 5, "%s: <%s> seems like domain ID\n",
10589 cmd
->def
->name
, optname
);
10590 dom
= virDomainLookupByID(ctl
->conn
, id
);
10593 /* try it by UUID */
10594 if (dom
==NULL
&& (flag
& VSH_BYUUID
) && strlen(n
)==VIR_UUID_STRING_BUFLEN
-1) {
10595 vshDebug(ctl
, 5, "%s: <%s> trying as domain UUID\n",
10596 cmd
->def
->name
, optname
);
10597 dom
= virDomainLookupByUUIDString(ctl
->conn
, n
);
10599 /* try it by NAME */
10600 if (dom
==NULL
&& (flag
& VSH_BYNAME
)) {
10601 vshDebug(ctl
, 5, "%s: <%s> trying as domain NAME\n",
10602 cmd
->def
->name
, optname
);
10603 dom
= virDomainLookupByName(ctl
->conn
, n
);
10607 vshError(ctl
, _("failed to get domain '%s'"), n
);
10612 static virNetworkPtr
10613 vshCommandOptNetworkBy(vshControl
*ctl
, const vshCmd
*cmd
,
10614 char **name
, int flag
)
10616 virNetworkPtr network
= NULL
;
10618 const char *optname
= "network";
10619 if (!cmd_has_option (ctl
, cmd
, optname
))
10622 if (!(n
= vshCommandOptString(cmd
, optname
, NULL
)))
10625 vshDebug(ctl
, 5, "%s: found option <%s>: %s\n",
10626 cmd
->def
->name
, optname
, n
);
10631 /* try it by UUID */
10632 if ((flag
& VSH_BYUUID
) && (strlen(n
) == VIR_UUID_STRING_BUFLEN
-1)) {
10633 vshDebug(ctl
, 5, "%s: <%s> trying as network UUID\n",
10634 cmd
->def
->name
, optname
);
10635 network
= virNetworkLookupByUUIDString(ctl
->conn
, n
);
10637 /* try it by NAME */
10638 if (network
==NULL
&& (flag
& VSH_BYNAME
)) {
10639 vshDebug(ctl
, 5, "%s: <%s> trying as network NAME\n",
10640 cmd
->def
->name
, optname
);
10641 network
= virNetworkLookupByName(ctl
->conn
, n
);
10645 vshError(ctl
, _("failed to get network '%s'"), n
);
10651 static virNWFilterPtr
10652 vshCommandOptNWFilterBy(vshControl
*ctl
, const vshCmd
*cmd
,
10653 char **name
, int flag
)
10655 virNWFilterPtr nwfilter
= NULL
;
10657 const char *optname
= "nwfilter";
10658 if (!cmd_has_option (ctl
, cmd
, optname
))
10661 if (!(n
= vshCommandOptString(cmd
, optname
, NULL
)))
10664 vshDebug(ctl
, 5, "%s: found option <%s>: %s\n",
10665 cmd
->def
->name
, optname
, n
);
10670 /* try it by UUID */
10671 if ((flag
& VSH_BYUUID
) && (strlen(n
) == VIR_UUID_STRING_BUFLEN
-1)) {
10672 vshDebug(ctl
, 5, "%s: <%s> trying as nwfilter UUID\n",
10673 cmd
->def
->name
, optname
);
10674 nwfilter
= virNWFilterLookupByUUIDString(ctl
->conn
, n
);
10676 /* try it by NAME */
10677 if (nwfilter
== NULL
&& (flag
& VSH_BYNAME
)) {
10678 vshDebug(ctl
, 5, "%s: <%s> trying as nwfilter NAME\n",
10679 cmd
->def
->name
, optname
);
10680 nwfilter
= virNWFilterLookupByName(ctl
->conn
, n
);
10684 vshError(ctl
, _("failed to get nwfilter '%s'"), n
);
10689 static virInterfacePtr
10690 vshCommandOptInterfaceBy(vshControl
*ctl
, const vshCmd
*cmd
,
10691 char **name
, int flag
)
10693 virInterfacePtr iface
= NULL
;
10695 const char *optname
= "interface";
10696 if (!cmd_has_option (ctl
, cmd
, optname
))
10699 if (!(n
= vshCommandOptString(cmd
, optname
, NULL
)))
10702 vshDebug(ctl
, 5, "%s: found option <%s>: %s\n",
10703 cmd
->def
->name
, optname
, n
);
10708 /* try it by NAME */
10709 if ((flag
& VSH_BYNAME
)) {
10710 vshDebug(ctl
, 5, "%s: <%s> trying as interface NAME\n",
10711 cmd
->def
->name
, optname
);
10712 iface
= virInterfaceLookupByName(ctl
->conn
, n
);
10714 /* try it by MAC */
10715 if ((iface
== NULL
) && (flag
& VSH_BYMAC
)) {
10716 vshDebug(ctl
, 5, "%s: <%s> trying as interface MAC\n",
10717 cmd
->def
->name
, optname
);
10718 iface
= virInterfaceLookupByMACString(ctl
->conn
, n
);
10722 vshError(ctl
, _("failed to get interface '%s'"), n
);
10727 static virStoragePoolPtr
10728 vshCommandOptPoolBy(vshControl
*ctl
, const vshCmd
*cmd
, const char *optname
,
10729 char **name
, int flag
)
10731 virStoragePoolPtr pool
= NULL
;
10734 if (!(n
= vshCommandOptString(cmd
, optname
, NULL
)))
10737 vshDebug(ctl
, 5, "%s: found option <%s>: %s\n",
10738 cmd
->def
->name
, optname
, n
);
10743 /* try it by UUID */
10744 if ((flag
& VSH_BYUUID
) && (strlen(n
) == VIR_UUID_STRING_BUFLEN
-1)) {
10745 vshDebug(ctl
, 5, "%s: <%s> trying as pool UUID\n",
10746 cmd
->def
->name
, optname
);
10747 pool
= virStoragePoolLookupByUUIDString(ctl
->conn
, n
);
10749 /* try it by NAME */
10750 if (pool
== NULL
&& (flag
& VSH_BYNAME
)) {
10751 vshDebug(ctl
, 5, "%s: <%s> trying as pool NAME\n",
10752 cmd
->def
->name
, optname
);
10753 pool
= virStoragePoolLookupByName(ctl
->conn
, n
);
10757 vshError(ctl
, _("failed to get pool '%s'"), n
);
10762 static virStorageVolPtr
10763 vshCommandOptVolBy(vshControl
*ctl
, const vshCmd
*cmd
,
10764 const char *optname
,
10765 const char *pooloptname
,
10766 char **name
, int flag
)
10768 virStorageVolPtr vol
= NULL
;
10769 virStoragePoolPtr pool
= NULL
;
10773 if (!(n
= vshCommandOptString(cmd
, optname
, NULL
)))
10776 if (!(p
= vshCommandOptString(cmd
, pooloptname
, &found
)) && found
)
10780 pool
= vshCommandOptPoolBy(ctl
, cmd
, pooloptname
, name
, flag
);
10782 vshDebug(ctl
, 5, "%s: found option <%s>: %s\n",
10783 cmd
->def
->name
, optname
, n
);
10788 /* try it by name */
10789 if (pool
&& (flag
& VSH_BYNAME
)) {
10790 vshDebug(ctl
, 5, "%s: <%s> trying as vol name\n",
10791 cmd
->def
->name
, optname
);
10792 vol
= virStorageVolLookupByName(pool
, n
);
10794 /* try it by key */
10795 if (vol
== NULL
&& (flag
& VSH_BYUUID
)) {
10796 vshDebug(ctl
, 5, "%s: <%s> trying as vol key\n",
10797 cmd
->def
->name
, optname
);
10798 vol
= virStorageVolLookupByKey(ctl
->conn
, n
);
10800 /* try it by path */
10801 if (vol
== NULL
&& (flag
& VSH_BYUUID
)) {
10802 vshDebug(ctl
, 5, "%s: <%s> trying as vol path\n",
10803 cmd
->def
->name
, optname
);
10804 vol
= virStorageVolLookupByPath(ctl
->conn
, n
);
10808 vshError(ctl
, _("failed to get vol '%s'"), n
);
10811 virStoragePoolFree(pool
);
10816 static virSecretPtr
10817 vshCommandOptSecret(vshControl
*ctl
, const vshCmd
*cmd
, char **name
)
10819 virSecretPtr secret
= NULL
;
10821 const char *optname
= "secret";
10823 if (!cmd_has_option (ctl
, cmd
, optname
))
10826 n
= vshCommandOptString(cmd
, optname
, NULL
);
10830 vshDebug(ctl
, 5, "%s: found option <%s>: %s\n", cmd
->def
->name
, optname
, n
);
10835 secret
= virSecretLookupByUUIDString(ctl
->conn
, n
);
10837 if (secret
== NULL
)
10838 vshError(ctl
, _("failed to get secret '%s'"), n
);
10844 * Executes command(s) and returns return code from last command
10847 vshCommandRun(vshControl
*ctl
, const vshCmd
*cmd
)
10852 struct timeval before
, after
;
10853 bool enable_timing
= ctl
->timing
;
10855 if ((ctl
->conn
== NULL
) || (disconnected
!= 0))
10859 GETTIMEOFDAY(&before
);
10861 ret
= cmd
->def
->handler(ctl
, cmd
);
10864 GETTIMEOFDAY(&after
);
10867 virshReportError(ctl
);
10869 /* try to automatically catch disconnections */
10870 if ((ret
== FALSE
) &&
10871 ((disconnected
!= 0) ||
10872 ((last_error
!= NULL
) &&
10873 (((last_error
->code
== VIR_ERR_SYSTEM_ERROR
) &&
10874 (last_error
->domain
== VIR_FROM_REMOTE
)) ||
10875 (last_error
->code
== VIR_ERR_RPC
) ||
10876 (last_error
->code
== VIR_ERR_NO_CONNECT
) ||
10877 (last_error
->code
== VIR_ERR_INVALID_CONN
)))))
10880 if (STREQ(cmd
->def
->name
, "quit")) /* hack ... */
10884 vshPrint(ctl
, _("\n(Time: %.3f ms)\n\n"),
10885 DIFF_MSEC(&after
, &before
));
10887 vshPrintExtra(ctl
, "\n");
10899 VSH_TK_ERROR
, /* Failed to parse a token */
10900 VSH_TK_ARG
, /* Arbitrary argument, might be option or empty */
10901 VSH_TK_SUBCMD_END
, /* Separation between commands */
10902 VSH_TK_END
/* No more commands */
10905 typedef struct __vshCommandParser
{
10906 vshCommandToken (*getNextArg
)(vshControl
*, struct __vshCommandParser
*,
10908 /* vshCommandStringGetArg() */
10910 /* vshCommandArgvGetArg() */
10913 } vshCommandParser
;
10916 vshCommandParse(vshControl
*ctl
, vshCommandParser
*parser
)
10918 char *tkdata
= NULL
;
10919 vshCmd
*clast
= NULL
;
10920 vshCmdOpt
*first
= NULL
;
10923 vshCommandFree(ctl
->cmd
);
10928 vshCmdOpt
*last
= NULL
;
10929 const vshCmdDef
*cmd
= NULL
;
10930 vshCommandToken tk
;
10931 bool data_only
= false;
10937 const vshCmdOptDef
*opt
= NULL
;
10940 tk
= parser
->getNextArg(ctl
, parser
, &tkdata
);
10942 if (tk
== VSH_TK_ERROR
)
10944 if (tk
!= VSH_TK_ARG
)
10948 /* first token must be command name */
10949 if (!(cmd
= vshCmddefSearch(tkdata
))) {
10950 vshError(ctl
, _("unknown command: '%s'"), tkdata
);
10951 goto syntaxError
; /* ... or ignore this command only? */
10954 } else if (data_only
) {
10956 } else if (tkdata
[0] == '-' && tkdata
[1] == '-' &&
10957 c_isalnum(tkdata
[2])) {
10958 char *optstr
= strchr(tkdata
+ 2, '=');
10960 *optstr
= '\0'; /* convert the '=' to '\0' */
10961 optstr
= vshStrdup(ctl
, optstr
+ 1);
10963 if (!(opt
= vshCmddefGetOption(cmd
, tkdata
+ 2))) {
10965 _("command '%s' doesn't support option --%s"),
10966 cmd
->name
, tkdata
+ 2);
10972 if (opt
->type
!= VSH_OT_BOOL
) {
10977 tk
= parser
->getNextArg(ctl
, parser
, &tkdata
);
10978 if (tk
== VSH_TK_ERROR
)
10980 if (tk
!= VSH_TK_ARG
) {
10982 _("expected syntax: --%s <%s>"),
10985 VSH_OT_INT
? _("number") : _("string"));
10991 vshError(ctl
, _("invalid '=' after option --%s"),
10997 } else if (tkdata
[0] == '-' && tkdata
[1] == '-' &&
10998 tkdata
[2] == '\0') {
11003 if (!(opt
= vshCmddefGetData(cmd
, data_ct
++))) {
11004 vshError(ctl
, _("unexpected data '%s'"), tkdata
);
11010 vshCmdOpt
*arg
= vshMalloc(ctl
, sizeof(vshCmdOpt
));
11013 arg
->data
= tkdata
;
11023 vshDebug(ctl
, 4, "%s: %s(%s): %s\n",
11026 opt
->type
!= VSH_OT_BOOL
? _("optdata") : _("bool"),
11027 opt
->type
!= VSH_OT_BOOL
? arg
->data
: _("(none)"));
11031 /* command parsed -- allocate new struct for the command */
11033 vshCmd
*c
= vshMalloc(ctl
, sizeof(vshCmd
));
11039 if (!vshCommandCheckOpts(ctl
, c
)) {
11051 if (tk
== VSH_TK_END
)
11059 vshCommandFree(ctl
->cmd
);
11063 vshCommandOptFree(first
);
11068 /* --------------------
11069 * Command argv parsing
11070 * --------------------
11073 static vshCommandToken
ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
11074 vshCommandArgvGetArg(vshControl
*ctl
, vshCommandParser
*parser
, char **res
)
11076 if (parser
->arg_pos
== parser
->arg_end
) {
11081 *res
= vshStrdup(ctl
, *parser
->arg_pos
);
11086 static int vshCommandArgvParse(vshControl
*ctl
, int nargs
, char **argv
)
11088 vshCommandParser parser
;
11093 parser
.arg_pos
= argv
;
11094 parser
.arg_end
= argv
+ nargs
;
11095 parser
.getNextArg
= vshCommandArgvGetArg
;
11096 return vshCommandParse(ctl
, &parser
);
11099 /* ----------------------
11100 * Command string parsing
11101 * ----------------------
11104 static vshCommandToken
ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
11105 vshCommandStringGetArg(vshControl
*ctl
, vshCommandParser
*parser
, char **res
)
11107 bool single_quote
= false;
11108 bool double_quote
= false;
11110 char *p
= parser
->pos
;
11111 char *q
= vshStrdup(ctl
, p
);
11115 while (*p
&& (*p
== ' ' || *p
== '\t'))
11121 parser
->pos
= ++p
; /* = \0 or begin of next command */
11122 return VSH_TK_SUBCMD_END
;
11126 /* end of token is blank space or ';' */
11127 if (!double_quote
&& !single_quote
&&
11128 (*p
== ' ' || *p
== '\t' || *p
== ';'))
11131 if (!double_quote
&& *p
== '\'') { /* single quote */
11132 single_quote
= !single_quote
;
11135 } else if (!single_quote
&& *p
== '\\') { /* escape */
11137 * The same as the bash, a \ in "" is an escaper,
11138 * but a \ in '' is not an escaper.
11142 vshError(ctl
, "%s", _("dangling \\"));
11143 return VSH_TK_ERROR
;
11145 } else if (!single_quote
&& *p
== '"') { /* double quote */
11146 double_quote
= !double_quote
;
11154 if (double_quote
) {
11155 vshError(ctl
, "%s", _("missing \""));
11156 return VSH_TK_ERROR
;
11164 static int vshCommandStringParse(vshControl
*ctl
, char *cmdstr
)
11166 vshCommandParser parser
;
11168 if (cmdstr
== NULL
|| *cmdstr
== '\0')
11171 parser
.pos
= cmdstr
;
11172 parser
.getNextArg
= vshCommandStringGetArg
;
11173 return vshCommandParse(ctl
, &parser
);
11180 static const char *
11181 vshDomainStateToString(int state
)
11184 case VIR_DOMAIN_RUNNING
:
11185 return N_("running");
11186 case VIR_DOMAIN_BLOCKED
:
11188 case VIR_DOMAIN_PAUSED
:
11189 return N_("paused");
11190 case VIR_DOMAIN_SHUTDOWN
:
11191 return N_("in shutdown");
11192 case VIR_DOMAIN_SHUTOFF
:
11193 return N_("shut off");
11194 case VIR_DOMAIN_CRASHED
:
11195 return N_("crashed");
11199 return N_("no state"); /* = dom0 state */
11202 static const char *
11203 vshDomainVcpuStateToString(int state
)
11206 case VIR_VCPU_OFFLINE
:
11207 return N_("offline");
11208 case VIR_VCPU_BLOCKED
:
11210 case VIR_VCPU_RUNNING
:
11211 return N_("running");
11215 return N_("no state");
11219 vshConnectionUsability(vshControl
*ctl
, virConnectPtr conn
)
11221 /* TODO: use something like virConnectionState() to
11222 * check usability of the connection
11225 vshError(ctl
, "%s", _("no valid connection"));
11232 vshDebug(vshControl
*ctl
, int level
, const char *format
, ...)
11236 va_start(ap
, format
);
11237 vshOutputLogFile(ctl
, VSH_ERR_DEBUG
, format
, ap
);
11240 if (level
> ctl
->debug
)
11243 va_start(ap
, format
);
11244 vfprintf(stdout
, format
, ap
);
11249 vshPrintExtra(vshControl
*ctl
, const char *format
, ...)
11253 if (ctl
->quiet
== TRUE
)
11256 va_start(ap
, format
);
11257 vfprintf(stdout
, format
, ap
);
11263 vshError(vshControl
*ctl
, const char *format
, ...)
11268 va_start(ap
, format
);
11269 vshOutputLogFile(ctl
, VSH_ERR_ERROR
, format
, ap
);
11273 fputs(_("error: "), stderr
);
11275 va_start(ap
, format
);
11276 vfprintf(stderr
, format
, ap
);
11279 fputc('\n', stderr
);
11283 * Initialize connection.
11286 vshInit(vshControl
*ctl
)
11291 vshOpenLogFile(ctl
);
11293 /* set up the library error handler */
11294 virSetErrorFunc(NULL
, virshErrorHandler
);
11296 /* set up the signals handlers to catch disconnections */
11299 virEventRegisterImpl(virEventAddHandleImpl
,
11300 virEventUpdateHandleImpl
,
11301 virEventRemoveHandleImpl
,
11302 virEventAddTimeoutImpl
,
11303 virEventUpdateTimeoutImpl
,
11304 virEventRemoveTimeoutImpl
);
11307 ctl
->conn
= virConnectOpenAuth(ctl
->name
,
11308 virConnectAuthPtrDefault
,
11309 ctl
->readonly
? VIR_CONNECT_RO
: 0);
11312 /* This is not necessarily fatal. All the individual commands check
11313 * vshConnectionUsability, except ones which don't need a connection
11317 virshReportError(ctl
);
11318 vshError(ctl
, "%s", _("failed to connect to the hypervisor"));
11325 #define LOGFILE_FLAGS (O_WRONLY | O_APPEND | O_CREAT | O_SYNC)
11333 vshOpenLogFile(vshControl
*ctl
)
11337 if (ctl
->logfile
== NULL
)
11340 /* check log file */
11341 if (stat(ctl
->logfile
, &st
) == -1) {
11346 vshError(ctl
, "%s",
11347 _("failed to get the log file information"));
11348 exit(EXIT_FAILURE
);
11351 if (!S_ISREG(st
.st_mode
)) {
11352 vshError(ctl
, "%s", _("the log path is not a file"));
11353 exit(EXIT_FAILURE
);
11357 /* log file open */
11358 if ((ctl
->log_fd
= open(ctl
->logfile
, LOGFILE_FLAGS
, FILE_MODE
)) < 0) {
11359 vshError(ctl
, "%s",
11360 _("failed to open the log file. check the log file path"));
11361 exit(EXIT_FAILURE
);
11366 * vshOutputLogFile:
11368 * Outputting an error to log file.
11371 vshOutputLogFile(vshControl
*ctl
, int log_level
, const char *msg_format
, va_list ap
)
11373 char msg_buf
[MSG_BUFFER
];
11374 const char *lvl
= "";
11375 struct timeval stTimeval
;
11378 if (ctl
->log_fd
== -1)
11382 * create log format
11384 * [YYYY.MM.DD HH:MM:SS SIGNATURE PID] LOG_LEVEL message
11386 gettimeofday(&stTimeval
, NULL
);
11387 stTm
= localtime(&stTimeval
.tv_sec
);
11388 snprintf(msg_buf
, sizeof(msg_buf
),
11389 "[%d.%02d.%02d %02d:%02d:%02d ",
11390 (1900 + stTm
->tm_year
),
11391 (1 + stTm
->tm_mon
),
11396 snprintf(msg_buf
+ strlen(msg_buf
), sizeof(msg_buf
) - strlen(msg_buf
),
11397 "%s] ", SIGN_NAME
);
11398 switch (log_level
) {
11399 case VSH_ERR_DEBUG
:
11405 case VSH_ERR_NOTICE
:
11408 case VSH_ERR_WARNING
:
11411 case VSH_ERR_ERROR
:
11418 snprintf(msg_buf
+ strlen(msg_buf
), sizeof(msg_buf
) - strlen(msg_buf
),
11420 vsnprintf(msg_buf
+ strlen(msg_buf
), sizeof(msg_buf
) - strlen(msg_buf
),
11423 if (msg_buf
[strlen(msg_buf
) - 1] != '\n')
11424 snprintf(msg_buf
+ strlen(msg_buf
), sizeof(msg_buf
) - strlen(msg_buf
), "\n");
11427 if (safewrite(ctl
->log_fd
, msg_buf
, strlen(msg_buf
)) < 0) {
11428 vshCloseLogFile(ctl
);
11429 vshError(ctl
, "%s", _("failed to write the log file"));
11439 vshCloseLogFile(vshControl
*ctl
)
11441 /* log file close */
11442 if (VIR_CLOSE(ctl
->log_fd
) < 0) {
11443 vshError(ctl
, _("%s: failed to write log file: %s"),
11444 ctl
->logfile
? ctl
->logfile
: "?", strerror (errno
));
11447 if (ctl
->logfile
) {
11448 VIR_FREE(ctl
->logfile
);
11449 ctl
->logfile
= NULL
;
11453 #ifdef USE_READLINE
11455 /* -----------------
11457 * -----------------
11461 * Generator function for command completion. STATE lets us
11462 * know whether to start from scratch; without any state
11463 * (i.e. STATE == 0), then we start at the top of the list.
11466 vshReadlineCommandGenerator(const char *text
, int state
)
11468 static int grp_list_index
, cmd_list_index
, len
;
11470 const vshCmdGrp
*grp
;
11471 const vshCmdDef
*cmds
;
11474 grp_list_index
= 0;
11475 cmd_list_index
= 0;
11476 len
= strlen(text
);
11481 /* Return the next name which partially matches from the
11484 while (grp
[grp_list_index
].name
) {
11485 cmds
= grp
[grp_list_index
].commands
;
11487 if (cmds
[cmd_list_index
].name
) {
11488 while ((name
= cmds
[cmd_list_index
].name
)) {
11491 if (STREQLEN(name
, text
, len
))
11492 return vshStrdup(NULL
, name
);
11495 cmd_list_index
= 0;
11500 /* If no names matched, then return NULL. */
11505 vshReadlineOptionsGenerator(const char *text
, int state
)
11507 static int list_index
, len
;
11508 static const vshCmdDef
*cmd
= NULL
;
11512 /* determine command name */
11516 if (!(p
= strchr(rl_line_buffer
, ' ')))
11519 cmdname
= vshCalloc(NULL
, (p
- rl_line_buffer
) + 1, 1);
11520 memcpy(cmdname
, rl_line_buffer
, p
- rl_line_buffer
);
11522 cmd
= vshCmddefSearch(cmdname
);
11524 len
= strlen(text
);
11534 while ((name
= cmd
->opts
[list_index
].name
)) {
11535 const vshCmdOptDef
*opt
= &cmd
->opts
[list_index
];
11540 if (opt
->type
== VSH_OT_DATA
)
11541 /* ignore non --option */
11545 if (STRNEQLEN(name
, text
+ 2, len
- 2))
11548 res
= vshMalloc(NULL
, strlen(name
) + 3);
11549 snprintf(res
, strlen(name
) + 3, "--%s", name
);
11553 /* If no names matched, then return NULL. */
11558 vshReadlineCompletion(const char *text
, int start
,
11559 int end ATTRIBUTE_UNUSED
)
11561 char **matches
= (char **) NULL
;
11564 /* command name generator */
11565 matches
= rl_completion_matches(text
, vshReadlineCommandGenerator
);
11567 /* commands options */
11568 matches
= rl_completion_matches(text
, vshReadlineOptionsGenerator
);
11574 vshReadlineInit(vshControl
*ctl
)
11576 char *userdir
= NULL
;
11578 /* Allow conditional parsing of the ~/.inputrc file. */
11579 rl_readline_name
= "virsh";
11581 /* Tell the completer that we want a crack first. */
11582 rl_attempted_completion_function
= vshReadlineCompletion
;
11584 /* Limit the total size of the history buffer */
11585 stifle_history(500);
11587 /* Prepare to read/write history from/to the ~/.virsh/history file */
11588 userdir
= virGetUserDirectory(getuid());
11590 if (userdir
== NULL
)
11593 if (virAsprintf(&ctl
->historydir
, "%s/.virsh", userdir
) < 0) {
11594 vshError(ctl
, "%s", _("Out of memory"));
11599 if (virAsprintf(&ctl
->historyfile
, "%s/history", ctl
->historydir
) < 0) {
11600 vshError(ctl
, "%s", _("Out of memory"));
11607 read_history(ctl
->historyfile
);
11613 vshReadlineDeinit (vshControl
*ctl
)
11615 if (ctl
->historyfile
!= NULL
) {
11616 if (mkdir(ctl
->historydir
, 0755) < 0 && errno
!= EEXIST
) {
11618 vshError(ctl
, _("Failed to create '%s': %s"),
11619 ctl
->historydir
, virStrerror(errno
, ebuf
, sizeof ebuf
));
11621 write_history(ctl
->historyfile
);
11624 VIR_FREE(ctl
->historydir
);
11625 VIR_FREE(ctl
->historyfile
);
11629 vshReadline (vshControl
*ctl ATTRIBUTE_UNUSED
, const char *prompt
)
11631 return readline (prompt
);
11634 #else /* !USE_READLINE */
11637 vshReadlineInit (vshControl
*ctl ATTRIBUTE_UNUSED
)
11644 vshReadlineDeinit (vshControl
*ctl ATTRIBUTE_UNUSED
)
11650 vshReadline (vshControl
*ctl
, const char *prompt
)
11656 fputs (prompt
, stdout
);
11657 r
= fgets (line
, sizeof line
, stdin
);
11658 if (r
== NULL
) return NULL
; /* EOF */
11660 /* Chomp trailing \n */
11662 if (len
> 0 && r
[len
-1] == '\n')
11665 return vshStrdup (ctl
, r
);
11668 #endif /* !USE_READLINE */
11671 * Deinitialize virsh
11674 vshDeinit(vshControl
*ctl
)
11676 vshReadlineDeinit(ctl
);
11677 vshCloseLogFile(ctl
);
11678 VIR_FREE(ctl
->name
);
11681 if ((ret
= virConnectClose(ctl
->conn
)) != 0) {
11682 vshError(ctl
, _("Failed to disconnect from the hypervisor, %d leaked reference(s)"), ret
);
11685 virResetLastError();
11696 const vshCmdGrp
*grp
;
11697 const vshCmdDef
*cmd
;
11699 fprintf(stdout
, _("\n%s [options]... [<command_string>]"
11700 "\n%s [options]... <command> [args...]\n\n"
11702 " -c | --connect <uri> hypervisor connection URI\n"
11703 " -r | --readonly connect readonly\n"
11704 " -d | --debug <num> debug level [0-5]\n"
11705 " -h | --help this help\n"
11706 " -q | --quiet quiet mode\n"
11707 " -t | --timing print timing information\n"
11708 " -l | --log <file> output logging to file\n"
11709 " -v | --version[=short] program version\n"
11710 " -V | --version=long version and full options\n\n"
11711 " commands (non interactive mode):\n\n"), progname
, progname
);
11713 for (grp
= cmdGroups
; grp
->name
; grp
++) {
11714 fprintf(stdout
, _(" %s (help keyword '%s')\n"), grp
->name
, grp
->keyword
);
11716 for (cmd
= grp
->commands
; cmd
->name
; cmd
++)
11718 " %-30s %s\n", cmd
->name
, _(vshCmddefGetInfo(cmd
, "help")));
11720 fprintf(stdout
, "\n");
11723 fprintf(stdout
, "%s",
11724 _("\n (specify help <group> for details about the commands in the group)\n"));
11725 fprintf(stdout
, "%s",
11726 _("\n (specify help <command> for details about the command)\n\n"));
11731 * Show version and options compiled in
11734 vshShowVersion(vshControl
*ctl ATTRIBUTE_UNUSED
)
11736 /* FIXME - list a copyright blurb, as in GNU programs? */
11737 vshPrint(ctl
, _("Virsh command line tool of libvirt %s\n"), VERSION
);
11738 vshPrint(ctl
, _("See web site at %s\n\n"), "http://libvirt.org/");
11740 vshPrint(ctl
, "%s", _("Compiled with support for:\n"));
11741 vshPrint(ctl
, "%s", _(" Hypervisors:"));
11743 vshPrint(ctl
, " Xen");
11746 vshPrint(ctl
, " QEmu/KVM");
11749 vshPrint(ctl
, " UML");
11752 vshPrint(ctl
, " OpenVZ");
11755 vshPrint(ctl
, " VirtualBox");
11758 vshPrint(ctl
, " XenAPI");
11761 vshPrint(ctl
, " LXC");
11764 vshPrint(ctl
, " ESX");
11767 vshPrint(ctl
, " PHYP");
11770 vshPrint(ctl
, " ONE");
11773 vshPrint(ctl
, " Test");
11775 vshPrint(ctl
, "\n");
11777 vshPrint(ctl
, "%s", _(" Networking:"));
11779 vshPrint(ctl
, " Remote");
11782 vshPrint(ctl
, " Proxy");
11784 #ifdef WITH_LIBVIRTD
11785 vshPrint(ctl
, " Daemon");
11787 #ifdef WITH_NETWORK
11788 vshPrint(ctl
, " Network");
11791 vshPrint(ctl
, " Bridging");
11794 vshPrint(ctl
, " Netcf");
11796 #ifdef WITH_NWFILTER
11797 vshPrint(ctl
, " Nwfilter");
11799 #ifdef WITH_VIRTUALPORT
11800 vshPrint(ctl
, " VirtualPort");
11802 vshPrint(ctl
, "\n");
11804 vshPrint(ctl
, "%s", _(" Storage:"));
11805 #ifdef WITH_STORAGE_DIR
11806 vshPrint(ctl
, " Dir");
11808 #ifdef WITH_STORAGE_DISK
11809 vshPrint(ctl
, " Disk");
11811 #ifdef WITH_STORAGE_FS
11812 vshPrint(ctl
, " Filesystem");
11814 #ifdef WITH_STORAGE_SCSI
11815 vshPrint(ctl
, " SCSI");
11817 #ifdef WITH_STORAGE_MPATH
11818 vshPrint(ctl
, " Multipath");
11820 #ifdef WITH_STORAGE_ISCSI
11821 vshPrint(ctl
, " iSCSI");
11823 #ifdef WITH_STORAGE_LVM
11824 vshPrint(ctl
, " LVM");
11826 vshPrint(ctl
, "\n");
11828 vshPrint(ctl
, "%s", _(" Miscellaneous:"));
11829 #ifdef ENABLE_SECDRIVER_APPARMOR
11830 vshPrint(ctl
, " AppArmor");
11832 #ifdef WITH_SECDRIVER_SELINUX
11833 vshPrint(ctl
, " SELinux");
11835 #ifdef WITH_SECRETS
11836 vshPrint(ctl
, " Secrets");
11838 #ifdef ENABLE_DEBUG
11839 vshPrint(ctl
, " Debug");
11842 vshPrint(ctl
, " DTrace");
11844 #ifdef USE_READLINE
11845 vshPrint(ctl
, " Readline");
11847 #ifdef WITH_DRIVER_MODULES
11848 vshPrint(ctl
, " Modular");
11850 vshPrint(ctl
, "\n");
11854 * argv[]: virsh [options] [command]
11858 vshParseArgv(vshControl
*ctl
, int argc
, char **argv
)
11862 struct option opt
[] = {
11863 {"debug", required_argument
, NULL
, 'd'},
11864 {"help", no_argument
, NULL
, 'h'},
11865 {"quiet", no_argument
, NULL
, 'q'},
11866 {"timing", no_argument
, NULL
, 't'},
11867 {"version", optional_argument
, NULL
, 'v'},
11868 {"connect", required_argument
, NULL
, 'c'},
11869 {"readonly", no_argument
, NULL
, 'r'},
11870 {"log", required_argument
, NULL
, 'l'},
11874 /* Standard (non-command) options. The leading + ensures that no
11875 * argument reordering takes place, so that command options are
11876 * not confused with top-level virsh options. */
11877 while ((arg
= getopt_long(argc
, argv
, "+d:hqtc:vVrl:", opt
, NULL
)) != -1) {
11880 if (virStrToLong_i(optarg
, NULL
, 10, &ctl
->debug
) < 0) {
11881 vshError(ctl
, "%s", _("option -d takes a numeric argument"));
11882 exit(EXIT_FAILURE
);
11892 ctl
->timing
= TRUE
;
11895 ctl
->name
= vshStrdup(ctl
, optarg
);
11898 if (STRNEQ_NULLABLE(optarg
, "long")) {
11900 exit(EXIT_SUCCESS
);
11904 vshShowVersion(ctl
);
11905 exit(EXIT_SUCCESS
);
11907 ctl
->readonly
= TRUE
;
11910 ctl
->logfile
= vshStrdup(ctl
, optarg
);
11913 vshError(ctl
, _("unsupported option '-%c'. See --help."), arg
);
11914 exit(EXIT_FAILURE
);
11919 if (optind
< argc
) {
11920 vshError(ctl
, _("extra argument '%s'. See --help."), argv
[optind
]);
11921 exit(EXIT_FAILURE
);
11924 /* list all command */
11926 exit(EXIT_SUCCESS
);
11929 if (argc
> optind
) {
11930 /* parse command */
11931 ctl
->imode
= FALSE
;
11932 if (argc
- optind
== 1) {
11933 vshDebug(ctl
, 2, "commands: \"%s\"\n", argv
[optind
]);
11934 return vshCommandStringParse(ctl
, argv
[optind
]);
11936 return vshCommandArgvParse(ctl
, argc
- optind
, argv
+ optind
);
11943 main(int argc
, char **argv
)
11945 vshControl _ctl
, *ctl
= &_ctl
;
11949 if (!setlocale(LC_ALL
, "")) {
11950 perror("setlocale");
11951 /* failure to setup locale is not fatal */
11953 if (!bindtextdomain(PACKAGE
, LOCALEDIR
)) {
11954 perror("bindtextdomain");
11955 return EXIT_FAILURE
;
11957 if (!textdomain(PACKAGE
)) {
11958 perror("textdomain");
11959 return EXIT_FAILURE
;
11962 if (!(progname
= strrchr(argv
[0], '/')))
11963 progname
= argv
[0];
11967 memset(ctl
, 0, sizeof(vshControl
));
11968 ctl
->imode
= TRUE
; /* default is interactive mode */
11969 ctl
->log_fd
= -1; /* Initialize log file descriptor */
11971 if ((defaultConn
= getenv("VIRSH_DEFAULT_CONNECT_URI"))) {
11972 ctl
->name
= vshStrdup(ctl
, defaultConn
);
11975 if (!vshParseArgv(ctl
, argc
, argv
)) {
11977 exit(EXIT_FAILURE
);
11980 if (!vshInit(ctl
)) {
11982 exit(EXIT_FAILURE
);
11986 ret
= vshCommandRun(ctl
, ctl
->cmd
);
11988 /* interactive mode */
11991 _("Welcome to %s, the virtualization interactive terminal.\n\n"),
11993 vshPrint(ctl
, "%s",
11994 _("Type: 'help' for help with commands\n"
11995 " 'quit' to quit\n\n"));
11998 if (vshReadlineInit(ctl
) < 0) {
12000 exit(EXIT_FAILURE
);
12004 const char *prompt
= ctl
->readonly
? VSH_PROMPT_RO
: VSH_PROMPT_RW
;
12006 vshReadline(ctl
, prompt
);
12007 if (ctl
->cmdstr
== NULL
)
12009 if (*ctl
->cmdstr
) {
12011 add_history(ctl
->cmdstr
);
12013 if (vshCommandStringParse(ctl
, ctl
->cmdstr
))
12014 vshCommandRun(ctl
, ctl
->cmd
);
12016 VIR_FREE(ctl
->cmdstr
);
12017 } while (ctl
->imode
);
12019 if (ctl
->cmdstr
== NULL
)
12020 fputc('\n', stdout
); /* line break after alone prompt */
12024 exit(ret
? EXIT_SUCCESS
: EXIT_FAILURE
);