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 static char *progname
;
62 #define VIRSH_MAX_XML_FILE 10*1024*1024
64 #define VSH_PROMPT_RW "virsh # "
65 #define VSH_PROMPT_RO "virsh > "
67 #define GETTIMEOFDAY(T) gettimeofday(T, NULL)
68 #define DIFF_MSEC(T, U) \
69 ((((int) ((T)->tv_sec - (U)->tv_sec)) * 1000000.0 + \
70 ((int) ((T)->tv_usec - (U)->tv_usec))) / 1000.0)
73 * The log configuration
75 #define MSG_BUFFER 4096
76 #define SIGN_NAME "virsh"
77 #define DIR_MODE (S_IWUSR | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) /* 0755 */
78 #define FILE_MODE (S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH) /* 0644 */
79 #define LOCK_MODE (S_IWUSR | S_IRUSR) /* 0600 */
80 #define LVL_DEBUG "DEBUG"
81 #define LVL_INFO "INFO"
82 #define LVL_NOTICE "NOTICE"
83 #define LVL_WARNING "WARNING"
84 #define LVL_ERROR "ERROR"
89 * Indicates the level of a log message
100 * virsh command line grammar:
102 * command_line = <command>\n | <command>; <command>; ...
104 * command = <keyword> <option> [--] <data>
106 * option = <bool_option> | <int_option> | <string_option>
109 * bool_option = --optionname
110 * int_option = --optionname <number> | --optionname=<number>
111 * string_option = --optionname <string> | --optionname=<string>
113 * keyword = [a-zA-Z][a-zA-Z-]*
115 * string = ('[^']*'|"([^\\"]|\\.)*"|([^ \t\n\\'"]|\\.))+
120 * vshCmdOptType - command option type
123 VSH_OT_BOOL
, /* optional boolean option */
124 VSH_OT_STRING
, /* optional string option */
125 VSH_OT_INT
, /* optional or mandatory int option */
126 VSH_OT_DATA
, /* string data (as non-option) */
127 VSH_OT_ARGV
/* remaining arguments, opt->name should be "" */
131 * Command Option Flags
133 #define VSH_OFLAG_NONE 0 /* without flags */
134 #define VSH_OFLAG_REQ (1 << 1) /* option required */
137 typedef struct __vshControl vshControl
;
138 typedef struct __vshCmd vshCmd
;
141 * vshCmdInfo -- information about command
144 const char *name
; /* name of information */
145 const char *data
; /* information */
149 * vshCmdOptDef - command option definition
152 const char *name
; /* the name of option */
153 vshCmdOptType type
; /* option type */
154 int flag
; /* flags */
155 const char *help
; /* help string */
159 * vshCmdOpt - command options
161 typedef struct vshCmdOpt
{
162 const vshCmdOptDef
*def
; /* pointer to relevant option */
163 char *data
; /* allocated data */
164 struct vshCmdOpt
*next
;
168 * vshCmdDef - command definition
172 int (*handler
) (vshControl
*, const vshCmd
*); /* command handler */
173 const vshCmdOptDef
*opts
; /* definition of command options */
174 const vshCmdInfo
*info
; /* details about command */
178 * vshCmd - parsed command
180 typedef struct __vshCmd
{
181 const vshCmdDef
*def
; /* command definition */
182 vshCmdOpt
*opts
; /* list of command arguments */
183 struct __vshCmd
*next
; /* next command */
189 typedef struct __vshControl
{
190 char *name
; /* connection name */
191 virConnectPtr conn
; /* connection to hypervisor (MAY BE NULL) */
192 vshCmd
*cmd
; /* the current command */
193 char *cmdstr
; /* string with command */
194 int imode
; /* interactive mode? */
195 int quiet
; /* quiet mode */
196 int debug
; /* print debug messages? */
197 int timing
; /* print timing info? */
198 int readonly
; /* connect readonly (first time only, not
199 * during explicit connect command)
201 char *logfile
; /* log file name */
202 int log_fd
; /* log file descriptor */
203 char *historydir
; /* readline history directory name */
204 char *historyfile
; /* readline history file name */
208 static const vshCmdDef commands
[];
210 static void vshError(vshControl
*ctl
, const char *format
, ...)
211 ATTRIBUTE_FMT_PRINTF(2, 3);
212 static int vshInit(vshControl
*ctl
);
213 static int vshDeinit(vshControl
*ctl
);
214 static void vshUsage(void);
215 static void vshOpenLogFile(vshControl
*ctl
);
216 static void vshOutputLogFile(vshControl
*ctl
, int log_level
, const char *format
, va_list ap
);
217 static void vshCloseLogFile(vshControl
*ctl
);
219 static int vshParseArgv(vshControl
*ctl
, int argc
, char **argv
);
221 static const char *vshCmddefGetInfo(const vshCmdDef
*cmd
, const char *info
);
222 static const vshCmdDef
*vshCmddefSearch(const char *cmdname
);
223 static int vshCmddefHelp(vshControl
*ctl
, const char *name
);
225 static vshCmdOpt
*vshCommandOpt(const vshCmd
*cmd
, const char *name
);
226 static int vshCommandOptInt(const vshCmd
*cmd
, const char *name
, int *found
);
227 static unsigned long vshCommandOptUL(const vshCmd
*cmd
, const char *name
,
229 static char *vshCommandOptString(const vshCmd
*cmd
, const char *name
,
231 static long long vshCommandOptLongLong(const vshCmd
*cmd
, const char *name
,
233 static int vshCommandOptBool(const vshCmd
*cmd
, const char *name
);
234 static char *vshCommandOptArgv(const vshCmd
*cmd
, int count
);
236 #define VSH_BYID (1 << 1)
237 #define VSH_BYUUID (1 << 2)
238 #define VSH_BYNAME (1 << 3)
239 #define VSH_BYMAC (1 << 4)
241 static virDomainPtr
vshCommandOptDomainBy(vshControl
*ctl
, const vshCmd
*cmd
,
242 char **name
, int flag
);
244 /* default is lookup by Id, Name and UUID */
245 #define vshCommandOptDomain(_ctl, _cmd, _name) \
246 vshCommandOptDomainBy(_ctl, _cmd, _name, VSH_BYID|VSH_BYUUID|VSH_BYNAME)
248 static virNetworkPtr
vshCommandOptNetworkBy(vshControl
*ctl
, const vshCmd
*cmd
,
249 char **name
, int flag
);
251 /* default is lookup by Name and UUID */
252 #define vshCommandOptNetwork(_ctl, _cmd, _name) \
253 vshCommandOptNetworkBy(_ctl, _cmd, _name, \
254 VSH_BYUUID|VSH_BYNAME)
256 static virNWFilterPtr
vshCommandOptNWFilterBy(vshControl
*ctl
, const vshCmd
*cmd
,
257 char **name
, int flag
);
259 /* default is lookup by Name and UUID */
260 #define vshCommandOptNWFilter(_ctl, _cmd, _name) \
261 vshCommandOptNWFilterBy(_ctl, _cmd, _name, \
262 VSH_BYUUID|VSH_BYNAME)
264 static virInterfacePtr
vshCommandOptInterfaceBy(vshControl
*ctl
, const vshCmd
*cmd
,
265 char **name
, int flag
);
267 /* default is lookup by Name and MAC */
268 #define vshCommandOptInterface(_ctl, _cmd, _name) \
269 vshCommandOptInterfaceBy(_ctl, _cmd, _name, \
270 VSH_BYMAC|VSH_BYNAME)
272 static virStoragePoolPtr
vshCommandOptPoolBy(vshControl
*ctl
, const vshCmd
*cmd
,
273 const char *optname
, char **name
, int flag
);
275 /* default is lookup by Name and UUID */
276 #define vshCommandOptPool(_ctl, _cmd, _optname, _name) \
277 vshCommandOptPoolBy(_ctl, _cmd, _optname, _name, \
278 VSH_BYUUID|VSH_BYNAME)
280 static virStorageVolPtr
vshCommandOptVolBy(vshControl
*ctl
, const vshCmd
*cmd
,
282 const char *pooloptname
,
283 char **name
, int flag
);
285 /* default is lookup by Name and UUID */
286 #define vshCommandOptVol(_ctl, _cmd,_optname, _pooloptname, _name) \
287 vshCommandOptVolBy(_ctl, _cmd, _optname, _pooloptname, _name, \
288 VSH_BYUUID|VSH_BYNAME)
290 static virSecretPtr
vshCommandOptSecret(vshControl
*ctl
, const vshCmd
*cmd
,
293 static void vshPrintExtra(vshControl
*ctl
, const char *format
, ...)
294 ATTRIBUTE_FMT_PRINTF(2, 3);
295 static void vshDebug(vshControl
*ctl
, int level
, const char *format
, ...)
296 ATTRIBUTE_FMT_PRINTF(3, 4);
298 /* XXX: add batch support */
299 #define vshPrint(_ctl, ...) fprintf(stdout, __VA_ARGS__)
301 static const char *vshDomainStateToString(int state
);
302 static const char *vshDomainVcpuStateToString(int state
);
303 static int vshConnectionUsability(vshControl
*ctl
, virConnectPtr conn
);
305 static char *editWriteToTempFile (vshControl
*ctl
, const char *doc
);
306 static int editFile (vshControl
*ctl
, const char *filename
);
307 static char *editReadBackFile (vshControl
*ctl
, const char *filename
);
309 static void *_vshMalloc(vshControl
*ctl
, size_t sz
, const char *filename
, int line
);
310 #define vshMalloc(_ctl, _sz) _vshMalloc(_ctl, _sz, __FILE__, __LINE__)
312 static void *_vshCalloc(vshControl
*ctl
, size_t nmemb
, size_t sz
, const char *filename
, int line
);
313 #define vshCalloc(_ctl, _nmemb, _sz) _vshCalloc(_ctl, _nmemb, _sz, __FILE__, __LINE__)
315 static void *_vshRealloc(vshControl
*ctl
, void *ptr
, size_t sz
, const char *filename
, int line
);
316 #define vshRealloc(_ctl, _ptr, _sz) _vshRealloc(_ctl, _ptr, _sz, __FILE__, __LINE__)
318 static char *_vshStrdup(vshControl
*ctl
, const char *s
, const char *filename
, int line
);
319 #define vshStrdup(_ctl, _s) _vshStrdup(_ctl, _s, __FILE__, __LINE__)
322 _vshMalloc(vshControl
*ctl
, size_t size
, const char *filename
, int line
)
326 if ((x
= malloc(size
)))
328 vshError(ctl
, _("%s: %d: failed to allocate %d bytes"),
329 filename
, line
, (int) size
);
334 _vshCalloc(vshControl
*ctl
, size_t nmemb
, size_t size
, const char *filename
, int line
)
338 if ((x
= calloc(nmemb
, size
)))
340 vshError(ctl
, _("%s: %d: failed to allocate %d bytes"),
341 filename
, line
, (int) (size
*nmemb
));
346 _vshRealloc(vshControl
*ctl
, void *ptr
, size_t size
, const char *filename
, int line
)
350 if ((x
= realloc(ptr
, size
)))
353 vshError(ctl
, _("%s: %d: failed to allocate %d bytes"),
354 filename
, line
, (int) size
);
359 _vshStrdup(vshControl
*ctl
, const char *s
, const char *filename
, int line
)
367 vshError(ctl
, _("%s: %d: failed to allocate %lu bytes"),
368 filename
, line
, (unsigned long)strlen(s
));
372 /* Poison the raw allocating identifiers in favor of our vsh variants. */
377 #define malloc use_vshMalloc_instead_of_malloc
378 #define calloc use_vshCalloc_instead_of_calloc
379 #define realloc use_vshRealloc_instead_of_realloc
380 #define strdup use_vshStrdup_instead_of_strdup
382 static int idsorter(const void *a
, const void *b
) {
383 const int *ia
= (const int *)a
;
384 const int *ib
= (const int *)b
;
392 static int namesorter(const void *a
, const void *b
) {
393 const char **sa
= (const char**)a
;
394 const char **sb
= (const char**)b
;
396 return strcasecmp(*sa
, *sb
);
400 prettyCapacity(unsigned long long val
,
405 } else if (val
< (1024.0l * 1024.0l)) {
407 return (((double)val
/ 1024.0l));
408 } else if (val
< (1024.0l * 1024.0l * 1024.0l)) {
410 return ((double)val
/ (1024.0l * 1024.0l));
411 } else if (val
< (1024.0l * 1024.0l * 1024.0l * 1024.0l)) {
413 return ((double)val
/ (1024.0l * 1024.0l * 1024.0l));
416 return ((double)val
/ (1024.0l * 1024.0l * 1024.0l * 1024.0l));
421 static virErrorPtr last_error
;
424 * Quieten libvirt until we're done with the command.
427 virshErrorHandler(void *unused ATTRIBUTE_UNUSED
, virErrorPtr error
)
429 virFreeError(last_error
);
430 last_error
= virSaveLastError();
431 if (getenv("VIRSH_DEBUG") != NULL
)
432 virDefaultErrorFunc(error
);
436 * Report an error when a command finishes. This is better than before
437 * (when correct operation would report errors), but it has some
438 * problems: we lose the smarter formatting of virDefaultErrorFunc(),
439 * and it can become harder to debug problems, if errors get reported
440 * twice during one command. This case shouldn't really happen anyway,
441 * and it's IMHO a bug that libvirt does that sometimes.
444 virshReportError(vshControl
*ctl
)
446 if (last_error
== NULL
) {
447 /* Calling directly into libvirt util functions won't trigger the
448 * error callback (which sets last_error), so check it ourselves.
450 * If the returned error has CODE_OK, this most likely means that
451 * no error was ever raised, so just ignore */
452 last_error
= virSaveLastError();
453 if (!last_error
|| last_error
->code
== VIR_ERR_OK
)
457 if (last_error
->code
== VIR_ERR_OK
) {
458 vshError(ctl
, "%s", _("unknown error"));
462 vshError(ctl
, "%s", last_error
->message
);
465 virFreeError(last_error
);
470 * Detection of disconnections and automatic reconnection support
472 static int disconnected
= 0; /* we may have been disconnected */
476 * vshCatchDisconnect:
478 * We get here when a SIGPIPE is being raised, we can't do much in the
479 * handler, just save the fact it was raised
481 static void vshCatchDisconnect(int sig
, siginfo_t
* siginfo
,
482 void* context ATTRIBUTE_UNUSED
) {
483 if ((sig
== SIGPIPE
) || (siginfo
->si_signo
== SIGPIPE
))
490 * Catch SIGPIPE signals which may arise when disconnection
491 * from libvirtd occurs
494 vshSetupSignals(void) {
495 struct sigaction sig_action
;
497 sig_action
.sa_sigaction
= vshCatchDisconnect
;
498 sig_action
.sa_flags
= SA_SIGINFO
;
499 sigemptyset(&sig_action
.sa_mask
);
501 sigaction(SIGPIPE
, &sig_action
, NULL
);
505 vshSetupSignals(void) {}
511 * Reconnect after a disconnect from libvirtd
515 vshReconnect(vshControl
*ctl
) {
516 if (ctl
->conn
!= NULL
)
517 virConnectClose(ctl
->conn
);
519 ctl
->conn
= virConnectOpenAuth(ctl
->name
,
520 virConnectAuthPtrDefault
,
521 ctl
->readonly
? VIR_CONNECT_RO
: 0);
523 vshError(ctl
, "%s", _("Failed to reconnect to the hypervisor"));
525 vshError(ctl
, "%s", _("Reconnected to the hypervisor"));
537 static const vshCmdInfo info_help
[] = {
538 {"help", N_("print help")},
539 {"desc", N_("Prints global help or command specific help.")},
544 static const vshCmdOptDef opts_help
[] = {
545 {"command", VSH_OT_DATA
, 0, N_("name of command")},
550 cmdHelp(vshControl
*ctl
, const vshCmd
*cmd
)
552 const char *cmdname
= vshCommandOptString(cmd
, "command", NULL
);
555 const vshCmdDef
*def
;
557 vshPrint(ctl
, "%s", _("Commands:\n\n"));
558 for (def
= commands
; def
->name
; def
++)
559 vshPrint(ctl
, " %-15s %s\n", def
->name
,
560 _(vshCmddefGetInfo(def
, "help")));
563 return vshCmddefHelp(ctl
, cmdname
);
567 * "autostart" command
569 static const vshCmdInfo info_autostart
[] = {
570 {"help", N_("autostart a domain")},
572 N_("Configure a domain to be automatically started at boot.")},
576 static const vshCmdOptDef opts_autostart
[] = {
577 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
578 {"disable", VSH_OT_BOOL
, 0, N_("disable autostarting")},
583 cmdAutostart(vshControl
*ctl
, const vshCmd
*cmd
)
589 if (!vshConnectionUsability(ctl
, ctl
->conn
))
592 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, &name
)))
595 autostart
= !vshCommandOptBool(cmd
, "disable");
597 if (virDomainSetAutostart(dom
, autostart
) < 0) {
599 vshError(ctl
, _("Failed to mark domain %s as autostarted"), name
);
601 vshError(ctl
, _("Failed to unmark domain %s as autostarted"), name
);
607 vshPrint(ctl
, _("Domain %s marked as autostarted\n"), name
);
609 vshPrint(ctl
, _("Domain %s unmarked as autostarted\n"), name
);
618 static const vshCmdInfo info_connect
[] = {
619 {"help", N_("(re)connect to hypervisor")},
621 N_("Connect to local hypervisor. This is built-in command after shell start up.")},
625 static const vshCmdOptDef opts_connect
[] = {
626 {"name", VSH_OT_DATA
, 0, N_("hypervisor connection URI")},
627 {"readonly", VSH_OT_BOOL
, 0, N_("read-only connection")},
632 cmdConnect(vshControl
*ctl
, const vshCmd
*cmd
)
634 int ro
= vshCommandOptBool(cmd
, "readonly");
638 if (virConnectClose(ctl
->conn
) != 0) {
639 vshError(ctl
, "%s", _("Failed to disconnect from the hypervisor"));
646 name
= vshCommandOptString(cmd
, "name", NULL
);
649 ctl
->name
= vshStrdup(ctl
, name
);
657 ctl
->conn
= virConnectOpenAuth(ctl
->name
, virConnectAuthPtrDefault
,
658 ctl
->readonly
? VIR_CONNECT_RO
: 0);
661 vshError(ctl
, "%s", _("Failed to connect to the hypervisor"));
663 return ctl
->conn
? TRUE
: FALSE
;
671 static const vshCmdInfo info_console
[] = {
672 {"help", N_("connect to the guest console")},
674 N_("Connect the virtual serial console for the guest")},
678 static const vshCmdOptDef opts_console
[] = {
679 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
684 cmdRunConsole(vshControl
*ctl
, virDomainPtr dom
)
686 xmlDocPtr xml
= NULL
;
687 xmlXPathObjectPtr obj
= NULL
;
688 xmlXPathContextPtr ctxt
= NULL
;
691 char *thatHost
= NULL
;
692 char *thisHost
= NULL
;
693 virDomainInfo dominfo
;
695 if (!(thisHost
= virGetHostname(ctl
->conn
))) {
696 vshError(ctl
, "%s", _("Failed to get local hostname"));
700 if (!(thatHost
= virConnectGetHostname(ctl
->conn
))) {
701 vshError(ctl
, "%s", _("Failed to get connection hostname"));
705 if (STRNEQ(thisHost
, thatHost
)) {
706 vshError(ctl
, "%s", _("Cannot connect to a remote console device"));
710 if (virDomainGetInfo(dom
, &dominfo
) < 0) {
711 vshError(ctl
, "%s", _("Unable to get domain status"));
715 if (dominfo
.state
== VIR_DOMAIN_SHUTOFF
) {
716 vshError(ctl
, "%s", _("The domain is not running"));
720 doc
= virDomainGetXMLDesc(dom
, 0);
724 xml
= xmlReadDoc((const xmlChar
*) doc
, "domain.xml", NULL
,
725 XML_PARSE_NOENT
| XML_PARSE_NONET
|
726 XML_PARSE_NOWARNING
);
730 ctxt
= xmlXPathNewContext(xml
);
734 obj
= xmlXPathEval(BAD_CAST
"string(/domain/devices/console/@tty)", ctxt
);
735 if ((obj
!= NULL
) && ((obj
->type
== XPATH_STRING
) &&
736 (obj
->stringval
!= NULL
) && (obj
->stringval
[0] != 0))) {
737 vshPrintExtra(ctl
, _("Connected to domain %s\n"), virDomainGetName(dom
));
738 vshPrintExtra(ctl
, "%s", _("Escape character is ^]\n"));
739 if (vshRunConsole((const char *)obj
->stringval
) == 0)
742 vshPrintExtra(ctl
, "%s", _("No console available for domain\n"));
744 xmlXPathFreeObject(obj
);
747 xmlXPathFreeContext(ctxt
);
757 cmdConsole(vshControl
*ctl
, const vshCmd
*cmd
)
762 if (!vshConnectionUsability(ctl
, ctl
->conn
))
765 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, NULL
)))
768 ret
= cmdRunConsole(ctl
, dom
);
780 static const vshCmdInfo info_list
[] = {
781 {"help", N_("list domains")},
782 {"desc", N_("Returns list of domains.")},
786 static const vshCmdOptDef opts_list
[] = {
787 {"inactive", VSH_OT_BOOL
, 0, N_("list inactive domains")},
788 {"all", VSH_OT_BOOL
, 0, N_("list inactive & active domains")},
794 cmdList(vshControl
*ctl
, const vshCmd
*cmd ATTRIBUTE_UNUSED
)
796 int inactive
= vshCommandOptBool(cmd
, "inactive");
797 int all
= vshCommandOptBool(cmd
, "all");
798 int active
= !inactive
|| all
? 1 : 0;
799 int *ids
= NULL
, maxid
= 0, i
;
804 if (!vshConnectionUsability(ctl
, ctl
->conn
))
808 maxid
= virConnectNumOfDomains(ctl
->conn
);
810 vshError(ctl
, "%s", _("Failed to list active domains"));
814 ids
= vshMalloc(ctl
, sizeof(int) * maxid
);
816 if ((maxid
= virConnectListDomains(ctl
->conn
, &ids
[0], maxid
)) < 0) {
817 vshError(ctl
, "%s", _("Failed to list active domains"));
822 qsort(&ids
[0], maxid
, sizeof(int), idsorter
);
826 maxname
= virConnectNumOfDefinedDomains(ctl
->conn
);
828 vshError(ctl
, "%s", _("Failed to list inactive domains"));
833 names
= vshMalloc(ctl
, sizeof(char *) * maxname
);
835 if ((maxname
= virConnectListDefinedDomains(ctl
->conn
, names
, maxname
)) < 0) {
836 vshError(ctl
, "%s", _("Failed to list inactive domains"));
842 qsort(&names
[0], maxname
, sizeof(char*), namesorter
);
845 vshPrintExtra(ctl
, "%3s %-20s %s\n", _("Id"), _("Name"), _("State"));
846 vshPrintExtra(ctl
, "----------------------------------\n");
848 for (i
= 0; i
< maxid
; i
++) {
850 virDomainPtr dom
= virDomainLookupByID(ctl
->conn
, ids
[i
]);
853 /* this kind of work with domains is not atomic operation */
857 if (virDomainGetInfo(dom
, &info
) < 0)
858 state
= _("no state");
860 state
= _(vshDomainStateToString(info
.state
));
862 vshPrint(ctl
, "%3d %-20s %s\n",
864 virDomainGetName(dom
),
868 for (i
= 0; i
< maxname
; i
++) {
870 virDomainPtr dom
= virDomainLookupByName(ctl
->conn
, names
[i
]);
873 /* this kind of work with domains is not atomic operation */
879 if (virDomainGetInfo(dom
, &info
) < 0)
880 state
= _("no state");
882 state
= _(vshDomainStateToString(info
.state
));
884 vshPrint(ctl
, "%3s %-20s %s\n", "-", names
[i
], state
);
897 static const vshCmdInfo info_domstate
[] = {
898 {"help", N_("domain state")},
899 {"desc", N_("Returns state about a domain.")},
903 static const vshCmdOptDef opts_domstate
[] = {
904 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
909 cmdDomstate(vshControl
*ctl
, const vshCmd
*cmd
)
915 if (!vshConnectionUsability(ctl
, ctl
->conn
))
918 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, NULL
)))
921 if (virDomainGetInfo(dom
, &info
) == 0)
922 vshPrint(ctl
, "%s\n",
923 _(vshDomainStateToString(info
.state
)));
931 /* "domblkstat" command
933 static const vshCmdInfo info_domblkstat
[] = {
934 {"help", N_("get device block stats for a domain")},
935 {"desc", N_("Get device block stats for a running domain.")},
939 static const vshCmdOptDef opts_domblkstat
[] = {
940 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
941 {"device", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("block device")},
946 cmdDomblkstat (vshControl
*ctl
, const vshCmd
*cmd
)
950 struct _virDomainBlockStats stats
;
952 if (!vshConnectionUsability (ctl
, ctl
->conn
))
955 if (!(dom
= vshCommandOptDomain (ctl
, cmd
, &name
)))
958 if (!(device
= vshCommandOptString (cmd
, "device", NULL
))) {
963 if (virDomainBlockStats (dom
, device
, &stats
, sizeof stats
) == -1) {
964 vshError(ctl
, _("Failed to get block stats %s %s"), name
, device
);
969 if (stats
.rd_req
>= 0)
970 vshPrint (ctl
, "%s rd_req %lld\n", device
, stats
.rd_req
);
972 if (stats
.rd_bytes
>= 0)
973 vshPrint (ctl
, "%s rd_bytes %lld\n", device
, stats
.rd_bytes
);
975 if (stats
.wr_req
>= 0)
976 vshPrint (ctl
, "%s wr_req %lld\n", device
, stats
.wr_req
);
978 if (stats
.wr_bytes
>= 0)
979 vshPrint (ctl
, "%s wr_bytes %lld\n", device
, stats
.wr_bytes
);
982 vshPrint (ctl
, "%s errs %lld\n", device
, stats
.errs
);
988 /* "domifstat" command
990 static const vshCmdInfo info_domifstat
[] = {
991 {"help", N_("get network interface stats for a domain")},
992 {"desc", N_("Get network interface stats for a running domain.")},
996 static const vshCmdOptDef opts_domifstat
[] = {
997 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
998 {"interface", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("interface device")},
1003 cmdDomIfstat (vshControl
*ctl
, const vshCmd
*cmd
)
1006 char *name
, *device
;
1007 struct _virDomainInterfaceStats stats
;
1009 if (!vshConnectionUsability (ctl
, ctl
->conn
))
1012 if (!(dom
= vshCommandOptDomain (ctl
, cmd
, &name
)))
1015 if (!(device
= vshCommandOptString (cmd
, "interface", NULL
))) {
1020 if (virDomainInterfaceStats (dom
, device
, &stats
, sizeof stats
) == -1) {
1021 vshError(ctl
, _("Failed to get interface stats %s %s"), name
, device
);
1026 if (stats
.rx_bytes
>= 0)
1027 vshPrint (ctl
, "%s rx_bytes %lld\n", device
, stats
.rx_bytes
);
1029 if (stats
.rx_packets
>= 0)
1030 vshPrint (ctl
, "%s rx_packets %lld\n", device
, stats
.rx_packets
);
1032 if (stats
.rx_errs
>= 0)
1033 vshPrint (ctl
, "%s rx_errs %lld\n", device
, stats
.rx_errs
);
1035 if (stats
.rx_drop
>= 0)
1036 vshPrint (ctl
, "%s rx_drop %lld\n", device
, stats
.rx_drop
);
1038 if (stats
.tx_bytes
>= 0)
1039 vshPrint (ctl
, "%s tx_bytes %lld\n", device
, stats
.tx_bytes
);
1041 if (stats
.tx_packets
>= 0)
1042 vshPrint (ctl
, "%s tx_packets %lld\n", device
, stats
.tx_packets
);
1044 if (stats
.tx_errs
>= 0)
1045 vshPrint (ctl
, "%s tx_errs %lld\n", device
, stats
.tx_errs
);
1047 if (stats
.tx_drop
>= 0)
1048 vshPrint (ctl
, "%s tx_drop %lld\n", device
, stats
.tx_drop
);
1055 * "dommemstats" command
1057 static const vshCmdInfo info_dommemstat
[] = {
1058 {"help", N_("get memory statistics for a domain")},
1059 {"desc", N_("Get memory statistics for a runnng domain.")},
1063 static const vshCmdOptDef opts_dommemstat
[] = {
1064 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
1069 cmdDomMemStat(vshControl
*ctl
, const vshCmd
*cmd
)
1073 struct _virDomainMemoryStat stats
[VIR_DOMAIN_MEMORY_STAT_NR
];
1074 unsigned int nr_stats
, i
;
1076 if (!vshConnectionUsability(ctl
, ctl
->conn
))
1079 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, &name
)))
1082 nr_stats
= virDomainMemoryStats (dom
, stats
, VIR_DOMAIN_MEMORY_STAT_NR
, 0);
1083 if (nr_stats
== -1) {
1084 vshError(ctl
, _("Failed to get memory statistics for domain %s"), name
);
1089 for (i
= 0; i
< nr_stats
; i
++) {
1090 if (stats
[i
].tag
== VIR_DOMAIN_MEMORY_STAT_SWAP_IN
)
1091 vshPrint (ctl
, "swap_in %llu\n", stats
[i
].val
);
1092 if (stats
[i
].tag
== VIR_DOMAIN_MEMORY_STAT_SWAP_OUT
)
1093 vshPrint (ctl
, "swap_out %llu\n", stats
[i
].val
);
1094 if (stats
[i
].tag
== VIR_DOMAIN_MEMORY_STAT_MAJOR_FAULT
)
1095 vshPrint (ctl
, "major_fault %llu\n", stats
[i
].val
);
1096 if (stats
[i
].tag
== VIR_DOMAIN_MEMORY_STAT_MINOR_FAULT
)
1097 vshPrint (ctl
, "minor_fault %llu\n", stats
[i
].val
);
1098 if (stats
[i
].tag
== VIR_DOMAIN_MEMORY_STAT_UNUSED
)
1099 vshPrint (ctl
, "unused %llu\n", stats
[i
].val
);
1100 if (stats
[i
].tag
== VIR_DOMAIN_MEMORY_STAT_AVAILABLE
)
1101 vshPrint (ctl
, "available %llu\n", stats
[i
].val
);
1109 * "domblkinfo" command
1111 static const vshCmdInfo info_domblkinfo
[] = {
1112 {"help", N_("domain block device size information")},
1113 {"desc", N_("Get block device size info for a domain.")},
1117 static const vshCmdOptDef opts_domblkinfo
[] = {
1118 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
1119 {"device", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("block device")},
1124 cmdDomblkinfo(vshControl
*ctl
, const vshCmd
*cmd
)
1126 virDomainBlockInfo info
;
1131 if (!vshConnectionUsability(ctl
, ctl
->conn
))
1134 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, NULL
)))
1137 if (!(device
= vshCommandOptString (cmd
, "device", NULL
))) {
1142 if (virDomainGetBlockInfo(dom
, device
, &info
, 0) < 0) {
1147 vshPrint(ctl
, "%-15s %llu\n", _("Capacity:"), info
.capacity
);
1148 vshPrint(ctl
, "%-15s %llu\n", _("Allocation:"), info
.allocation
);
1149 vshPrint(ctl
, "%-15s %llu\n", _("Physical:"), info
.physical
);
1158 static const vshCmdInfo info_suspend
[] = {
1159 {"help", N_("suspend a domain")},
1160 {"desc", N_("Suspend a running domain.")},
1164 static const vshCmdOptDef opts_suspend
[] = {
1165 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
1170 cmdSuspend(vshControl
*ctl
, const vshCmd
*cmd
)
1176 if (!vshConnectionUsability(ctl
, ctl
->conn
))
1179 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, &name
)))
1182 if (virDomainSuspend(dom
) == 0) {
1183 vshPrint(ctl
, _("Domain %s suspended\n"), name
);
1185 vshError(ctl
, _("Failed to suspend domain %s"), name
);
1196 static const vshCmdInfo info_create
[] = {
1197 {"help", N_("create a domain from an XML file")},
1198 {"desc", N_("Create a domain.")},
1202 static const vshCmdOptDef opts_create
[] = {
1203 {"file", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("file containing an XML domain description")},
1205 {"console", VSH_OT_BOOL
, 0, N_("attach to console after creation")},
1207 {"paused", VSH_OT_BOOL
, 0, N_("leave the guest paused after creation")},
1212 cmdCreate(vshControl
*ctl
, const vshCmd
*cmd
)
1220 int console
= vshCommandOptBool(cmd
, "console");
1222 unsigned int flags
= VIR_DOMAIN_NONE
;
1224 if (!vshConnectionUsability(ctl
, ctl
->conn
))
1227 from
= vshCommandOptString(cmd
, "file", &found
);
1231 if (virFileReadAll(from
, VIRSH_MAX_XML_FILE
, &buffer
) < 0)
1234 if (vshCommandOptBool(cmd
, "paused"))
1235 flags
|= VIR_DOMAIN_START_PAUSED
;
1237 dom
= virDomainCreateXML(ctl
->conn
, buffer
, flags
);
1241 vshPrint(ctl
, _("Domain %s created from %s\n"),
1242 virDomainGetName(dom
), from
);
1245 cmdRunConsole(ctl
, dom
);
1249 vshError(ctl
, _("Failed to create domain from %s"), from
);
1258 static const vshCmdInfo info_define
[] = {
1259 {"help", N_("define (but don't start) a domain from an XML file")},
1260 {"desc", N_("Define a domain.")},
1264 static const vshCmdOptDef opts_define
[] = {
1265 {"file", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("file containing an XML domain description")},
1270 cmdDefine(vshControl
*ctl
, const vshCmd
*cmd
)
1278 if (!vshConnectionUsability(ctl
, ctl
->conn
))
1281 from
= vshCommandOptString(cmd
, "file", &found
);
1285 if (virFileReadAll(from
, VIRSH_MAX_XML_FILE
, &buffer
) < 0)
1288 dom
= virDomainDefineXML(ctl
->conn
, buffer
);
1292 vshPrint(ctl
, _("Domain %s defined from %s\n"),
1293 virDomainGetName(dom
), from
);
1296 vshError(ctl
, _("Failed to define domain from %s"), from
);
1303 * "undefine" command
1305 static const vshCmdInfo info_undefine
[] = {
1306 {"help", N_("undefine an inactive domain")},
1307 {"desc", N_("Undefine the configuration for an inactive domain.")},
1311 static const vshCmdOptDef opts_undefine
[] = {
1312 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name or uuid")},
1317 cmdUndefine(vshControl
*ctl
, const vshCmd
*cmd
)
1325 if (!vshConnectionUsability(ctl
, ctl
->conn
))
1328 name
= vshCommandOptString(cmd
, "domain", &found
);
1332 if (name
&& virStrToLong_i(name
, NULL
, 10, &id
) == 0
1333 && id
>= 0 && (dom
= virDomainLookupByID(ctl
->conn
, id
))) {
1335 _("a running domain like %s cannot be undefined;\n"
1336 "to undefine, first shutdown then undefine"
1337 " using its name or UUID"),
1342 if (!(dom
= vshCommandOptDomainBy(ctl
, cmd
, &name
,
1343 VSH_BYNAME
|VSH_BYUUID
)))
1346 if (virDomainUndefine(dom
) == 0) {
1347 vshPrint(ctl
, _("Domain %s has been undefined\n"), name
);
1349 vshError(ctl
, _("Failed to undefine domain %s"), name
);
1361 static const vshCmdInfo info_start
[] = {
1362 {"help", N_("start a (previously defined) inactive domain")},
1363 {"desc", N_("Start a domain, either from the last managedsave\n"
1364 " state, or via a fresh boot if no managedsave state\n"
1369 static const vshCmdOptDef opts_start
[] = {
1370 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("name of the inactive domain")},
1372 {"console", VSH_OT_BOOL
, 0, N_("attach to console after creation")},
1374 {"paused", VSH_OT_BOOL
, 0, N_("leave the guest paused after creation")},
1379 cmdStart(vshControl
*ctl
, const vshCmd
*cmd
)
1384 int console
= vshCommandOptBool(cmd
, "console");
1386 unsigned int flags
= VIR_DOMAIN_NONE
;
1388 if (!vshConnectionUsability(ctl
, ctl
->conn
))
1391 if (!(dom
= vshCommandOptDomainBy(ctl
, cmd
, NULL
, VSH_BYNAME
)))
1394 if (virDomainGetID(dom
) != (unsigned int)-1) {
1395 vshError(ctl
, "%s", _("Domain is already active"));
1400 if (vshCommandOptBool(cmd
, "paused"))
1401 flags
|= VIR_DOMAIN_START_PAUSED
;
1403 /* Prefer older API unless we have to pass a flag. */
1404 if ((flags
? virDomainCreateWithFlags(dom
, flags
)
1405 : virDomainCreate(dom
)) == 0) {
1406 vshPrint(ctl
, _("Domain %s started\n"),
1407 virDomainGetName(dom
));
1410 cmdRunConsole(ctl
, dom
);
1413 vshError(ctl
, _("Failed to start domain %s"), virDomainGetName(dom
));
1423 static const vshCmdInfo info_save
[] = {
1424 {"help", N_("save a domain state to a file")},
1425 {"desc", N_("Save a running domain.")},
1429 static const vshCmdOptDef opts_save
[] = {
1430 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
1431 {"file", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("where to save the data")},
1436 cmdSave(vshControl
*ctl
, const vshCmd
*cmd
)
1443 if (!vshConnectionUsability(ctl
, ctl
->conn
))
1446 if (!(to
= vshCommandOptString(cmd
, "file", NULL
)))
1449 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, &name
)))
1452 if (virDomainSave(dom
, to
) == 0) {
1453 vshPrint(ctl
, _("Domain %s saved to %s\n"), name
, to
);
1455 vshError(ctl
, _("Failed to save domain %s to %s"), name
, to
);
1464 * "managedsave" command
1466 static const vshCmdInfo info_managedsave
[] = {
1467 {"help", N_("managed save of a domain state")},
1468 {"desc", N_("Save and destroy a running domain, so it can be restarted from\n"
1469 " the same state at a later time. When the virsh 'start'\n"
1470 " command is next run for the domain, it will automatically\n"
1471 " be started from this saved state.")},
1475 static const vshCmdOptDef opts_managedsave
[] = {
1476 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
1481 cmdManagedSave(vshControl
*ctl
, const vshCmd
*cmd
)
1487 if (!vshConnectionUsability(ctl
, ctl
->conn
))
1490 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, &name
)))
1493 if (virDomainManagedSave(dom
, 0) == 0) {
1494 vshPrint(ctl
, _("Domain %s state saved by libvirt\n"), name
);
1496 vshError(ctl
, _("Failed to save domain %s state"), name
);
1505 * "managedsave-remove" command
1507 static const vshCmdInfo info_managedsaveremove
[] = {
1508 {"help", N_("Remove managed save of a domain")},
1509 {"desc", N_("Remove an existing managed save state file from a domain")},
1513 static const vshCmdOptDef opts_managedsaveremove
[] = {
1514 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
1519 cmdManagedSaveRemove(vshControl
*ctl
, const vshCmd
*cmd
)
1526 if (!vshConnectionUsability(ctl
, ctl
->conn
))
1529 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, &name
)))
1532 hassave
= virDomainHasManagedSaveImage(dom
, 0);
1534 vshError(ctl
, "%s", _("Failed to check for domain managed save image"));
1539 if (virDomainManagedSaveRemove(dom
, 0) < 0) {
1540 vshError(ctl
, _("Failed to remove managed save image for domain %s"),
1545 vshPrint(ctl
, _("Removed managedsave image for domain %s"), name
);
1548 vshPrint(ctl
, _("Domain %s has no manage save image; removal skipped"),
1559 * "schedinfo" command
1561 static const vshCmdInfo info_schedinfo
[] = {
1562 {"help", N_("show/set scheduler parameters")},
1563 {"desc", N_("Show/Set scheduler parameters.")},
1567 static const vshCmdOptDef opts_schedinfo
[] = {
1568 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
1569 {"set", VSH_OT_STRING
, VSH_OFLAG_NONE
, N_("parameter=value")},
1570 {"weight", VSH_OT_INT
, VSH_OFLAG_NONE
, N_("weight for XEN_CREDIT")},
1571 {"cap", VSH_OT_INT
, VSH_OFLAG_NONE
, N_("cap for XEN_CREDIT")},
1576 cmdSchedInfoUpdate(vshControl
*ctl
, const vshCmd
*cmd
,
1577 virSchedParameterPtr param
)
1582 /* Legacy 'weight' parameter */
1583 if (STREQ(param
->field
, "weight") &&
1584 param
->type
== VIR_DOMAIN_SCHED_FIELD_UINT
&&
1585 vshCommandOptBool(cmd
, "weight")) {
1587 val
= vshCommandOptInt(cmd
, "weight", &found
);
1589 vshError(ctl
, "%s", _("Invalid value of weight"));
1592 param
->value
.ui
= val
;
1597 /* Legacy 'cap' parameter */
1598 if (STREQ(param
->field
, "cap") &&
1599 param
->type
== VIR_DOMAIN_SCHED_FIELD_UINT
&&
1600 vshCommandOptBool(cmd
, "cap")) {
1602 val
= vshCommandOptInt(cmd
, "cap", &found
);
1604 vshError(ctl
, "%s", _("Invalid value of cap"));
1607 param
->value
.ui
= val
;
1612 if ((data
= vshCommandOptString(cmd
, "set", NULL
))) {
1613 char *val
= strchr(data
, '=');
1616 vshError(ctl
, "%s", _("Invalid syntax for --set, expecting name=value"));
1620 match
= STREQ(data
, param
->field
);
1627 switch (param
->type
) {
1628 case VIR_DOMAIN_SCHED_FIELD_INT
:
1629 if (virStrToLong_i(val
, NULL
, 10, ¶m
->value
.i
) < 0) {
1631 _("Invalid value for parameter, expecting an int"));
1635 case VIR_DOMAIN_SCHED_FIELD_UINT
:
1636 if (virStrToLong_ui(val
, NULL
, 10, ¶m
->value
.ui
) < 0) {
1638 _("Invalid value for parameter, expecting an unsigned int"));
1642 case VIR_DOMAIN_SCHED_FIELD_LLONG
:
1643 if (virStrToLong_ll(val
, NULL
, 10, ¶m
->value
.l
) < 0) {
1645 _("Invalid value for parameter, expecting a long long"));
1649 case VIR_DOMAIN_SCHED_FIELD_ULLONG
:
1650 if (virStrToLong_ull(val
, NULL
, 10, ¶m
->value
.ul
) < 0) {
1652 _("Invalid value for parameter, expecting an unsigned long long"));
1656 case VIR_DOMAIN_SCHED_FIELD_DOUBLE
:
1657 if (virStrToDouble(val
, NULL
, ¶m
->value
.d
) < 0) {
1658 vshError(ctl
, "%s", _("Invalid value for parameter, expecting a double"));
1662 case VIR_DOMAIN_SCHED_FIELD_BOOLEAN
:
1663 param
->value
.b
= STREQ(val
, "0") ? 0 : 1;
1673 cmdSchedinfo(vshControl
*ctl
, const vshCmd
*cmd
)
1675 char *schedulertype
;
1677 virSchedParameterPtr params
= NULL
;
1681 int ret_val
= FALSE
;
1683 if (!vshConnectionUsability(ctl
, ctl
->conn
))
1686 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, NULL
)))
1689 /* Print SchedulerType */
1690 schedulertype
= virDomainGetSchedulerType(dom
, &nparams
);
1691 if (schedulertype
!= NULL
){
1692 vshPrint(ctl
, "%-15s: %s\n", _("Scheduler"),
1694 VIR_FREE(schedulertype
);
1696 vshPrint(ctl
, "%-15s: %s\n", _("Scheduler"), _("Unknown"));
1701 params
= vshMalloc(ctl
, sizeof(virSchedParameter
)* nparams
);
1703 memset(params
, 0, sizeof(virSchedParameter
)* nparams
);
1704 ret
= virDomainGetSchedulerParameters(dom
, params
, &nparams
);
1708 /* See if any params are being set */
1709 for (i
= 0; i
< nparams
; i
++){
1710 ret
= cmdSchedInfoUpdate(ctl
, cmd
, &(params
[i
]));
1718 /* Update parameters & refresh data */
1720 ret
= virDomainSetSchedulerParameters(dom
, params
, nparams
);
1724 ret
= virDomainGetSchedulerParameters(dom
, params
, &nparams
);
1728 /* See if we've tried to --set var=val. If so, the fact that
1729 we reach this point (with update == 0) means that "var" did
1730 not match any of the settable parameters. Report the error. */
1731 char *var_value_pair
= vshCommandOptString(cmd
, "set", NULL
);
1732 if (var_value_pair
) {
1733 vshError(ctl
, _("invalid scheduler option: %s"),
1740 for (i
= 0; i
< nparams
; i
++){
1741 switch (params
[i
].type
) {
1742 case VIR_DOMAIN_SCHED_FIELD_INT
:
1743 vshPrint(ctl
, "%-15s: %d\n", params
[i
].field
, params
[i
].value
.i
);
1745 case VIR_DOMAIN_SCHED_FIELD_UINT
:
1746 vshPrint(ctl
, "%-15s: %u\n", params
[i
].field
, params
[i
].value
.ui
);
1748 case VIR_DOMAIN_SCHED_FIELD_LLONG
:
1749 vshPrint(ctl
, "%-15s: %lld\n", params
[i
].field
, params
[i
].value
.l
);
1751 case VIR_DOMAIN_SCHED_FIELD_ULLONG
:
1752 vshPrint(ctl
, "%-15s: %llu\n", params
[i
].field
, params
[i
].value
.ul
);
1754 case VIR_DOMAIN_SCHED_FIELD_DOUBLE
:
1755 vshPrint(ctl
, "%-15s: %f\n", params
[i
].field
, params
[i
].value
.d
);
1757 case VIR_DOMAIN_SCHED_FIELD_BOOLEAN
:
1758 vshPrint(ctl
, "%-15s: %d\n", params
[i
].field
, params
[i
].value
.b
);
1761 vshPrint(ctl
, "not implemented scheduler parameter type\n");
1775 static const vshCmdInfo info_restore
[] = {
1776 {"help", N_("restore a domain from a saved state in a file")},
1777 {"desc", N_("Restore a domain.")},
1781 static const vshCmdOptDef opts_restore
[] = {
1782 {"file", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("the state to restore")},
1787 cmdRestore(vshControl
*ctl
, const vshCmd
*cmd
)
1793 if (!vshConnectionUsability(ctl
, ctl
->conn
))
1796 from
= vshCommandOptString(cmd
, "file", &found
);
1800 if (virDomainRestore(ctl
->conn
, from
) == 0) {
1801 vshPrint(ctl
, _("Domain restored from %s\n"), from
);
1803 vshError(ctl
, _("Failed to restore domain from %s"), from
);
1812 static const vshCmdInfo info_dump
[] = {
1813 {"help", N_("dump the core of a domain to a file for analysis")},
1814 {"desc", N_("Core dump a domain.")},
1818 static const vshCmdOptDef opts_dump
[] = {
1819 {"live", VSH_OT_BOOL
, 0, N_("perform a live core dump if supported")},
1820 {"crash", VSH_OT_BOOL
, 0, N_("crash the domain after core dump")},
1821 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
1822 {"file", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("where to dump the core")},
1827 cmdDump(vshControl
*ctl
, const vshCmd
*cmd
)
1835 if (!vshConnectionUsability(ctl
, ctl
->conn
))
1838 if (!(to
= vshCommandOptString(cmd
, "file", NULL
)))
1841 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, &name
)))
1844 if (vshCommandOptBool (cmd
, "live"))
1845 flags
|= VIR_DUMP_LIVE
;
1846 if (vshCommandOptBool (cmd
, "crash"))
1847 flags
|= VIR_DUMP_CRASH
;
1849 if (virDomainCoreDump(dom
, to
, flags
) == 0) {
1850 vshPrint(ctl
, _("Domain %s dumped to %s\n"), name
, to
);
1852 vshError(ctl
, _("Failed to core dump domain %s to %s"), name
, to
);
1863 static const vshCmdInfo info_resume
[] = {
1864 {"help", N_("resume a domain")},
1865 {"desc", N_("Resume a previously suspended domain.")},
1869 static const vshCmdOptDef opts_resume
[] = {
1870 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
1875 cmdResume(vshControl
*ctl
, const vshCmd
*cmd
)
1881 if (!vshConnectionUsability(ctl
, ctl
->conn
))
1884 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, &name
)))
1887 if (virDomainResume(dom
) == 0) {
1888 vshPrint(ctl
, _("Domain %s resumed\n"), name
);
1890 vshError(ctl
, _("Failed to resume domain %s"), name
);
1899 * "shutdown" command
1901 static const vshCmdInfo info_shutdown
[] = {
1902 {"help", N_("gracefully shutdown a domain")},
1903 {"desc", N_("Run shutdown in the target domain.")},
1907 static const vshCmdOptDef opts_shutdown
[] = {
1908 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
1913 cmdShutdown(vshControl
*ctl
, const vshCmd
*cmd
)
1919 if (!vshConnectionUsability(ctl
, ctl
->conn
))
1922 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, &name
)))
1925 if (virDomainShutdown(dom
) == 0) {
1926 vshPrint(ctl
, _("Domain %s is being shutdown\n"), name
);
1928 vshError(ctl
, _("Failed to shutdown domain %s"), name
);
1939 static const vshCmdInfo info_reboot
[] = {
1940 {"help", N_("reboot a domain")},
1941 {"desc", N_("Run a reboot command in the target domain.")},
1945 static const vshCmdOptDef opts_reboot
[] = {
1946 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
1951 cmdReboot(vshControl
*ctl
, const vshCmd
*cmd
)
1957 if (!vshConnectionUsability(ctl
, ctl
->conn
))
1960 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, &name
)))
1963 if (virDomainReboot(dom
, 0) == 0) {
1964 vshPrint(ctl
, _("Domain %s is being rebooted\n"), name
);
1966 vshError(ctl
, _("Failed to reboot domain %s"), name
);
1977 static const vshCmdInfo info_destroy
[] = {
1978 {"help", N_("destroy a domain")},
1979 {"desc", N_("Destroy a given domain.")},
1983 static const vshCmdOptDef opts_destroy
[] = {
1984 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
1989 cmdDestroy(vshControl
*ctl
, const vshCmd
*cmd
)
1995 if (!vshConnectionUsability(ctl
, ctl
->conn
))
1998 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, &name
)))
2001 if (virDomainDestroy(dom
) == 0) {
2002 vshPrint(ctl
, _("Domain %s destroyed\n"), name
);
2004 vshError(ctl
, _("Failed to destroy domain %s"), name
);
2015 static const vshCmdInfo info_dominfo
[] = {
2016 {"help", N_("domain information")},
2017 {"desc", N_("Returns basic information about the domain.")},
2021 static const vshCmdOptDef opts_dominfo
[] = {
2022 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
2027 cmdDominfo(vshControl
*ctl
, const vshCmd
*cmd
)
2031 virSecurityModel secmodel
;
2032 virSecurityLabel seclabel
;
2034 int ret
= TRUE
, autostart
;
2036 char *str
, uuid
[VIR_UUID_STRING_BUFLEN
];
2038 if (!vshConnectionUsability(ctl
, ctl
->conn
))
2041 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, NULL
)))
2044 id
= virDomainGetID(dom
);
2045 if (id
== ((unsigned int)-1))
2046 vshPrint(ctl
, "%-15s %s\n", _("Id:"), "-");
2048 vshPrint(ctl
, "%-15s %d\n", _("Id:"), id
);
2049 vshPrint(ctl
, "%-15s %s\n", _("Name:"), virDomainGetName(dom
));
2051 if (virDomainGetUUIDString(dom
, &uuid
[0])==0)
2052 vshPrint(ctl
, "%-15s %s\n", _("UUID:"), uuid
);
2054 if ((str
= virDomainGetOSType(dom
))) {
2055 vshPrint(ctl
, "%-15s %s\n", _("OS Type:"), str
);
2059 if (virDomainGetInfo(dom
, &info
) == 0) {
2060 vshPrint(ctl
, "%-15s %s\n", _("State:"),
2061 _(vshDomainStateToString(info
.state
)));
2063 vshPrint(ctl
, "%-15s %d\n", _("CPU(s):"), info
.nrVirtCpu
);
2065 if (info
.cpuTime
!= 0) {
2066 double cpuUsed
= info
.cpuTime
;
2068 cpuUsed
/= 1000000000.0;
2070 vshPrint(ctl
, "%-15s %.1lfs\n", _("CPU time:"), cpuUsed
);
2073 if (info
.maxMem
!= UINT_MAX
)
2074 vshPrint(ctl
, "%-15s %lu kB\n", _("Max memory:"),
2077 vshPrint(ctl
, "%-15s %s\n", _("Max memory:"),
2080 vshPrint(ctl
, "%-15s %lu kB\n", _("Used memory:"),
2087 /* Check and display whether the domain is persistent or not */
2088 persistent
= virDomainIsPersistent(dom
);
2089 vshDebug(ctl
, 5, "Domain persistent flag value: %d\n", persistent
);
2091 vshPrint(ctl
, "%-15s %s\n", _("Persistent:"), _("unknown"));
2093 vshPrint(ctl
, "%-15s %s\n", _("Persistent:"), persistent
? _("yes") : _("no"));
2095 /* Check and display whether the domain autostarts or not */
2096 if (!virDomainGetAutostart(dom
, &autostart
)) {
2097 vshPrint(ctl
, "%-15s %s\n", _("Autostart:"),
2098 autostart
? _("enable") : _("disable") );
2101 /* Security model and label information */
2102 memset(&secmodel
, 0, sizeof secmodel
);
2103 if (virNodeGetSecurityModel(ctl
->conn
, &secmodel
) == -1) {
2104 if (last_error
->code
!= VIR_ERR_NO_SUPPORT
) {
2109 /* Only print something if a security model is active */
2110 if (secmodel
.model
[0] != '\0') {
2111 vshPrint(ctl
, "%-15s %s\n", _("Security model:"), secmodel
.model
);
2112 vshPrint(ctl
, "%-15s %s\n", _("Security DOI:"), secmodel
.doi
);
2114 /* Security labels are only valid for active domains */
2115 memset(&seclabel
, 0, sizeof seclabel
);
2116 if (virDomainGetSecurityLabel(dom
, &seclabel
) == -1) {
2120 if (seclabel
.label
[0] != '\0')
2121 vshPrint(ctl
, "%-15s %s (%s)\n", _("Security label:"),
2122 seclabel
.label
, seclabel
.enforcing
? "enforcing" : "permissive");
2131 * "domjobinfo" command
2133 static const vshCmdInfo info_domjobinfo
[] = {
2134 {"help", N_("domain job information")},
2135 {"desc", N_("Returns information about jobs running on a domain.")},
2139 static const vshCmdOptDef opts_domjobinfo
[] = {
2140 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
2146 cmdDomjobinfo(vshControl
*ctl
, const vshCmd
*cmd
)
2148 virDomainJobInfo info
;
2152 if (!vshConnectionUsability(ctl
, ctl
->conn
))
2155 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, NULL
)))
2158 if (virDomainGetJobInfo(dom
, &info
) == 0) {
2162 vshPrint(ctl
, "%-17s ", _("Job type:"));
2163 switch (info
.type
) {
2164 case VIR_DOMAIN_JOB_BOUNDED
:
2165 vshPrint(ctl
, "%-12s\n", _("Bounded"));
2168 case VIR_DOMAIN_JOB_UNBOUNDED
:
2169 vshPrint(ctl
, "%-12s\n", _("Unbounded"));
2172 case VIR_DOMAIN_JOB_NONE
:
2174 vshPrint(ctl
, "%-12s\n", _("None"));
2178 vshPrint(ctl
, "%-17s %-12llu ms\n", _("Time elapsed:"), info
.timeElapsed
);
2179 if (info
.type
== VIR_DOMAIN_JOB_BOUNDED
)
2180 vshPrint(ctl
, "%-17s %-12llu ms\n", _("Time remaining:"), info
.timeRemaining
);
2181 if (info
.dataTotal
|| info
.dataRemaining
|| info
.dataProcessed
) {
2182 val
= prettyCapacity(info
.dataProcessed
, &unit
);
2183 vshPrint(ctl
, "%-17s %-.3lf %s\n", _("Data processed:"), val
, unit
);
2184 val
= prettyCapacity(info
.dataRemaining
, &unit
);
2185 vshPrint(ctl
, "%-17s %-.3lf %s\n", _("Data remaining:"), val
, unit
);
2186 val
= prettyCapacity(info
.dataTotal
, &unit
);
2187 vshPrint(ctl
, "%-17s %-.3lf %s\n", _("Data total:"), val
, unit
);
2189 if (info
.memTotal
|| info
.memRemaining
|| info
.memProcessed
) {
2190 val
= prettyCapacity(info
.memProcessed
, &unit
);
2191 vshPrint(ctl
, "%-17s %-.3lf %s\n", _("Memory processed:"), val
, unit
);
2192 val
= prettyCapacity(info
.memRemaining
, &unit
);
2193 vshPrint(ctl
, "%-17s %-.3lf %s\n", _("Memory remaining:"), val
, unit
);
2194 val
= prettyCapacity(info
.memTotal
, &unit
);
2195 vshPrint(ctl
, "%-17s %-.3lf %s\n", _("Memory total:"), val
, unit
);
2197 if (info
.fileTotal
|| info
.fileRemaining
|| info
.fileProcessed
) {
2198 val
= prettyCapacity(info
.fileProcessed
, &unit
);
2199 vshPrint(ctl
, "%-17s %-.3lf %s\n", _("File processed:"), val
, unit
);
2200 val
= prettyCapacity(info
.fileRemaining
, &unit
);
2201 vshPrint(ctl
, "%-17s %-.3lf %s\n", _("File remaining:"), val
, unit
);
2202 val
= prettyCapacity(info
.fileTotal
, &unit
);
2203 vshPrint(ctl
, "%-17s %-.3lf %s\n", _("File total:"), val
, unit
);
2214 * "domjobabort" command
2216 static const vshCmdInfo info_domjobabort
[] = {
2217 {"help", N_("abort active domain job")},
2218 {"desc", N_("Aborts the currently running domain job")},
2222 static const vshCmdOptDef opts_domjobabort
[] = {
2223 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
2228 cmdDomjobabort(vshControl
*ctl
, const vshCmd
*cmd
)
2233 if (!vshConnectionUsability(ctl
, ctl
->conn
))
2236 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, NULL
)))
2239 if (virDomainAbortJob(dom
) < 0)
2247 * "freecell" command
2249 static const vshCmdInfo info_freecell
[] = {
2250 {"help", N_("NUMA free memory")},
2251 {"desc", N_("display available free memory for the NUMA cell.")},
2255 static const vshCmdOptDef opts_freecell
[] = {
2256 {"cellno", VSH_OT_INT
, 0, N_("NUMA cell number")},
2261 cmdFreecell(vshControl
*ctl
, const vshCmd
*cmd
)
2264 int cell
, cell_given
;
2265 unsigned long long memory
;
2267 if (!vshConnectionUsability(ctl
, ctl
->conn
))
2270 cell
= vshCommandOptInt(cmd
, "cellno", &cell_given
);
2272 memory
= virNodeGetFreeMemory(ctl
->conn
);
2276 ret
= virNodeGetCellsFreeMemory(ctl
->conn
, &memory
, cell
, 1);
2282 vshPrint(ctl
, "%s: %llu kB\n", _("Total"), (memory
/1024));
2284 vshPrint(ctl
, "%d: %llu kB\n", cell
, (memory
/1024));
2290 * "maxvcpus" command
2292 static const vshCmdInfo info_maxvcpus
[] = {
2293 {"help", N_("connection vcpu maximum")},
2294 {"desc", N_("Show maximum number of virtual CPUs for guests on this connection.")},
2298 static const vshCmdOptDef opts_maxvcpus
[] = {
2299 {"type", VSH_OT_STRING
, 0, N_("domain type")},
2304 cmdMaxvcpus(vshControl
*ctl
, const vshCmd
*cmd
)
2309 type
= vshCommandOptString(cmd
, "type", NULL
);
2311 if (!vshConnectionUsability(ctl
, ctl
->conn
))
2314 vcpus
= virConnectGetMaxVcpus(ctl
->conn
, type
);
2317 vshPrint(ctl
, "%d\n", vcpus
);
2323 * "vcpucount" command
2325 static const vshCmdInfo info_vcpucount
[] = {
2326 {"help", N_("domain vcpu counts")},
2327 {"desc", N_("Returns the number of virtual CPUs used by the domain.")},
2331 static const vshCmdOptDef opts_vcpucount
[] = {
2332 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
2333 {"maximum", VSH_OT_BOOL
, 0, N_("get maximum cap on vcpus")},
2334 {"current", VSH_OT_BOOL
, 0, N_("get current vcpu usage")},
2335 {"config", VSH_OT_BOOL
, 0, N_("get value to be used on next boot")},
2336 {"live", VSH_OT_BOOL
, 0, N_("get value from running domain")},
2341 cmdVcpucount(vshControl
*ctl
, const vshCmd
*cmd
)
2345 int maximum
= vshCommandOptBool(cmd
, "maximum");
2346 int current
= vshCommandOptBool(cmd
, "current");
2347 int config
= vshCommandOptBool(cmd
, "config");
2348 int live
= vshCommandOptBool(cmd
, "live");
2349 bool all
= maximum
+ current
+ config
+ live
== 0;
2352 if (maximum
&& current
) {
2354 _("--maximum and --current cannot both be specified"));
2357 if (config
&& live
) {
2359 _("--config and --live cannot both be specified"));
2362 /* We want one of each pair of mutually exclusive options; that
2363 * is, use of flags requires exactly two options. */
2364 if (maximum
+ current
+ config
+ live
== 1) {
2366 _("when using --%s, either --%s or --%s must be specified"),
2367 (maximum
? "maximum" : current
? "current"
2368 : config
? "config" : "live"),
2369 maximum
+ current
? "config" : "maximum",
2370 maximum
+ current
? "live" : "current");
2374 if (!vshConnectionUsability(ctl
, ctl
->conn
))
2377 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, NULL
)))
2380 /* In all cases, try the new API first; if it fails because we are
2381 * talking to an older client, try a fallback API before giving
2383 if (all
|| (maximum
&& config
)) {
2384 count
= virDomainGetVcpusFlags(dom
, (VIR_DOMAIN_VCPU_MAXIMUM
|
2385 VIR_DOMAIN_VCPU_CONFIG
));
2386 if (count
< 0 && (last_error
->code
== VIR_ERR_NO_SUPPORT
2387 || last_error
->code
== VIR_ERR_INVALID_ARG
)) {
2389 char *xml
= virDomainGetXMLDesc(dom
, VIR_DOMAIN_XML_INACTIVE
);
2390 if (xml
&& (tmp
= strstr(xml
, "<vcpu"))) {
2391 tmp
= strchr(tmp
, '>');
2392 if (!tmp
|| virStrToLong_i(tmp
+ 1, &tmp
, 10, &count
) < 0)
2399 virshReportError(ctl
);
2402 vshPrint(ctl
, "%-12s %-12s %3d\n", _("maximum"), _("config"),
2405 vshPrint(ctl
, "%d\n", count
);
2407 virFreeError(last_error
);
2411 if (all
|| (maximum
&& live
)) {
2412 count
= virDomainGetVcpusFlags(dom
, (VIR_DOMAIN_VCPU_MAXIMUM
|
2413 VIR_DOMAIN_VCPU_LIVE
));
2414 if (count
< 0 && (last_error
->code
== VIR_ERR_NO_SUPPORT
2415 || last_error
->code
== VIR_ERR_INVALID_ARG
)) {
2416 count
= virDomainGetMaxVcpus(dom
);
2420 virshReportError(ctl
);
2423 vshPrint(ctl
, "%-12s %-12s %3d\n", _("maximum"), _("live"),
2426 vshPrint(ctl
, "%d\n", count
);
2428 virFreeError(last_error
);
2432 if (all
|| (current
&& config
)) {
2433 count
= virDomainGetVcpusFlags(dom
, VIR_DOMAIN_VCPU_CONFIG
);
2434 if (count
< 0 && (last_error
->code
== VIR_ERR_NO_SUPPORT
2435 || last_error
->code
== VIR_ERR_INVALID_ARG
)) {
2437 char *xml
= virDomainGetXMLDesc(dom
, VIR_DOMAIN_XML_INACTIVE
);
2438 if (xml
&& (tmp
= strstr(xml
, "<vcpu"))) {
2439 end
= strchr(tmp
, '>');
2442 tmp
= strstr(tmp
, "current=");
2446 tmp
+= strlen("current=");
2447 tmp
+= *tmp
== '\'' || *tmp
== '"';
2450 if (!tmp
|| virStrToLong_i(tmp
, &tmp
, 10, &count
) < 0)
2457 virshReportError(ctl
);
2460 vshPrint(ctl
, "%-12s %-12s %3d\n", _("current"), _("config"),
2463 vshPrint(ctl
, "%d\n", count
);
2465 virFreeError(last_error
);
2469 if (all
|| (current
&& live
)) {
2470 count
= virDomainGetVcpusFlags(dom
, VIR_DOMAIN_VCPU_LIVE
);
2471 if (count
< 0 && (last_error
->code
== VIR_ERR_NO_SUPPORT
2472 || last_error
->code
== VIR_ERR_INVALID_ARG
)) {
2474 if (virDomainGetInfo(dom
, &info
) == 0)
2475 count
= info
.nrVirtCpu
;
2479 virshReportError(ctl
);
2482 vshPrint(ctl
, "%-12s %-12s %3d\n", _("current"), _("live"),
2485 vshPrint(ctl
, "%d\n", count
);
2487 virFreeError(last_error
);
2496 * "vcpuinfo" command
2498 static const vshCmdInfo info_vcpuinfo
[] = {
2499 {"help", N_("detailed domain vcpu information")},
2500 {"desc", N_("Returns basic information about the domain virtual CPUs.")},
2504 static const vshCmdOptDef opts_vcpuinfo
[] = {
2505 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
2510 cmdVcpuinfo(vshControl
*ctl
, const vshCmd
*cmd
)
2514 virNodeInfo nodeinfo
;
2515 virVcpuInfoPtr cpuinfo
;
2516 unsigned char *cpumap
;
2521 if (!vshConnectionUsability(ctl
, ctl
->conn
))
2524 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, NULL
)))
2527 if (virNodeGetInfo(ctl
->conn
, &nodeinfo
) != 0) {
2532 if (virDomainGetInfo(dom
, &info
) != 0) {
2537 cpuinfo
= vshMalloc(ctl
, sizeof(virVcpuInfo
)*info
.nrVirtCpu
);
2538 cpumaplen
= VIR_CPU_MAPLEN(VIR_NODEINFO_MAXCPUS(nodeinfo
));
2539 cpumap
= vshMalloc(ctl
, info
.nrVirtCpu
* cpumaplen
);
2541 if ((ncpus
= virDomainGetVcpus(dom
,
2542 cpuinfo
, info
.nrVirtCpu
,
2543 cpumap
, cpumaplen
)) >= 0) {
2545 for (n
= 0 ; n
< ncpus
; n
++) {
2547 vshPrint(ctl
, "%-15s %d\n", _("VCPU:"), n
);
2548 vshPrint(ctl
, "%-15s %d\n", _("CPU:"), cpuinfo
[n
].cpu
);
2549 vshPrint(ctl
, "%-15s %s\n", _("State:"),
2550 _(vshDomainVcpuStateToString(cpuinfo
[n
].state
)));
2551 if (cpuinfo
[n
].cpuTime
!= 0) {
2552 double cpuUsed
= cpuinfo
[n
].cpuTime
;
2554 cpuUsed
/= 1000000000.0;
2556 vshPrint(ctl
, "%-15s %.1lfs\n", _("CPU time:"), cpuUsed
);
2558 vshPrint(ctl
, "%-15s ", _("CPU Affinity:"));
2559 for (m
= 0 ; m
< VIR_NODEINFO_MAXCPUS(nodeinfo
) ; m
++) {
2560 vshPrint(ctl
, "%c", VIR_CPU_USABLE(cpumap
, cpumaplen
, n
, m
) ? 'y' : '-');
2562 vshPrint(ctl
, "\n");
2563 if (n
< (ncpus
- 1)) {
2564 vshPrint(ctl
, "\n");
2568 if (info
.state
== VIR_DOMAIN_SHUTOFF
) {
2570 _("Domain shut off, virtual CPUs not present."));
2584 static const vshCmdInfo info_vcpupin
[] = {
2585 {"help", N_("control domain vcpu affinity")},
2586 {"desc", N_("Pin domain VCPUs to host physical CPUs.")},
2590 static const vshCmdOptDef opts_vcpupin
[] = {
2591 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
2592 {"vcpu", VSH_OT_INT
, VSH_OFLAG_REQ
, N_("vcpu number")},
2593 {"cpulist", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("host cpu number(s) (comma separated)")},
2598 cmdVcpupin(vshControl
*ctl
, const vshCmd
*cmd
)
2602 virNodeInfo nodeinfo
;
2607 unsigned char *cpumap
;
2610 enum { expect_num
, expect_num_or_comma
} state
;
2612 if (!vshConnectionUsability(ctl
, ctl
->conn
))
2615 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, NULL
)))
2618 vcpu
= vshCommandOptInt(cmd
, "vcpu", &vcpufound
);
2620 vshError(ctl
, "%s", _("vcpupin: Invalid or missing vCPU number."));
2625 if (!(cpulist
= vshCommandOptString(cmd
, "cpulist", NULL
))) {
2630 if (virNodeGetInfo(ctl
->conn
, &nodeinfo
) != 0) {
2635 if (virDomainGetInfo(dom
, &info
) != 0) {
2636 vshError(ctl
, "%s", _("vcpupin: failed to get domain informations."));
2641 if (vcpu
>= info
.nrVirtCpu
) {
2642 vshError(ctl
, "%s", _("vcpupin: Invalid vCPU number."));
2647 /* Check that the cpulist parameter is a comma-separated list of
2648 * numbers and give an intelligent error message if not.
2650 if (cpulist
[0] == '\0') {
2651 vshError(ctl
, "%s", _("cpulist: Invalid format. Empty string."));
2652 virDomainFree (dom
);
2657 for (i
= 0; cpulist
[i
]; i
++) {
2660 if (!c_isdigit (cpulist
[i
])) {
2661 vshError(ctl
, _("cpulist: %s: Invalid format. Expecting "
2662 "digit at position %d (near '%c')."),
2663 cpulist
, i
, cpulist
[i
]);
2664 virDomainFree (dom
);
2667 state
= expect_num_or_comma
;
2669 case expect_num_or_comma
:
2670 if (cpulist
[i
] == ',')
2672 else if (!c_isdigit (cpulist
[i
])) {
2673 vshError(ctl
, _("cpulist: %s: Invalid format. Expecting "
2674 "digit or comma at position %d (near '%c')."),
2675 cpulist
, i
, cpulist
[i
]);
2676 virDomainFree (dom
);
2681 if (state
== expect_num
) {
2682 vshError(ctl
, _("cpulist: %s: Invalid format. Trailing comma "
2685 virDomainFree (dom
);
2689 cpumaplen
= VIR_CPU_MAPLEN(VIR_NODEINFO_MAXCPUS(nodeinfo
));
2690 cpumap
= vshCalloc(ctl
, 1, cpumaplen
);
2693 unsigned int cpu
= atoi(cpulist
);
2695 if (cpu
< VIR_NODEINFO_MAXCPUS(nodeinfo
)) {
2696 VIR_USE_CPU(cpumap
, cpu
);
2698 vshError(ctl
, _("Physical CPU %d doesn't exist."), cpu
);
2703 cpulist
= strchr(cpulist
, ',');
2708 if (virDomainPinVcpu(dom
, vcpu
, cpumap
, cpumaplen
) != 0) {
2718 * "setvcpus" command
2720 static const vshCmdInfo info_setvcpus
[] = {
2721 {"help", N_("change number of virtual CPUs")},
2722 {"desc", N_("Change the number of virtual CPUs in the guest domain.")},
2726 static const vshCmdOptDef opts_setvcpus
[] = {
2727 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
2728 {"count", VSH_OT_INT
, VSH_OFLAG_REQ
, N_("number of virtual CPUs")},
2729 {"maximum", VSH_OT_BOOL
, 0, N_("set maximum limit on next boot")},
2730 {"config", VSH_OT_BOOL
, 0, N_("affect next boot")},
2731 {"live", VSH_OT_BOOL
, 0, N_("affect running domain")},
2736 cmdSetvcpus(vshControl
*ctl
, const vshCmd
*cmd
)
2741 int maximum
= vshCommandOptBool(cmd
, "maximum");
2742 int config
= vshCommandOptBool(cmd
, "config");
2743 int live
= vshCommandOptBool(cmd
, "live");
2744 int flags
= ((maximum
? VIR_DOMAIN_VCPU_MAXIMUM
: 0) |
2745 (config
? VIR_DOMAIN_VCPU_CONFIG
: 0) |
2746 (live
? VIR_DOMAIN_VCPU_LIVE
: 0));
2748 if (!vshConnectionUsability(ctl
, ctl
->conn
))
2751 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, NULL
)))
2754 count
= vshCommandOptInt(cmd
, "count", &count
);
2757 if (virDomainSetVcpus(dom
, count
) != 0) {
2761 if (virDomainSetVcpusFlags(dom
, count
, flags
) < 0) {
2771 * "setmemory" command
2773 static const vshCmdInfo info_setmem
[] = {
2774 {"help", N_("change memory allocation")},
2775 {"desc", N_("Change the current memory allocation in the guest domain.")},
2779 static const vshCmdOptDef opts_setmem
[] = {
2780 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
2781 {"kilobytes", VSH_OT_INT
, VSH_OFLAG_REQ
, N_("number of kilobytes of memory")},
2786 cmdSetmem(vshControl
*ctl
, const vshCmd
*cmd
)
2790 unsigned long kilobytes
;
2793 if (!vshConnectionUsability(ctl
, ctl
->conn
))
2796 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, NULL
)))
2799 kilobytes
= vshCommandOptUL(cmd
, "kilobytes", NULL
);
2800 if (kilobytes
<= 0) {
2802 vshError(ctl
, _("Invalid value of %lu for memory size"), kilobytes
);
2806 if (virDomainGetInfo(dom
, &info
) != 0) {
2808 vshError(ctl
, "%s", _("Unable to verify MaxMemorySize"));
2812 if (kilobytes
> info
.maxMem
) {
2814 vshError(ctl
, _("Requested memory size %lu kb is larger than maximum of %lu kb"),
2815 kilobytes
, info
.maxMem
);
2819 if (virDomainSetMemory(dom
, kilobytes
) != 0) {
2828 * "setmaxmem" command
2830 static const vshCmdInfo info_setmaxmem
[] = {
2831 {"help", N_("change maximum memory limit")},
2832 {"desc", N_("Change the maximum memory allocation limit in the guest domain.")},
2836 static const vshCmdOptDef opts_setmaxmem
[] = {
2837 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
2838 {"kilobytes", VSH_OT_INT
, VSH_OFLAG_REQ
, N_("maximum memory limit in kilobytes")},
2843 cmdSetmaxmem(vshControl
*ctl
, const vshCmd
*cmd
)
2850 if (!vshConnectionUsability(ctl
, ctl
->conn
))
2853 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, NULL
)))
2856 kilobytes
= vshCommandOptInt(cmd
, "kilobytes", &kilobytes
);
2857 if (kilobytes
<= 0) {
2859 vshError(ctl
, _("Invalid value of %d for memory size"), kilobytes
);
2863 if (virDomainGetInfo(dom
, &info
) != 0) {
2865 vshError(ctl
, "%s", _("Unable to verify current MemorySize"));
2869 if (virDomainSetMaxMemory(dom
, kilobytes
) != 0) {
2870 vshError(ctl
, "%s", _("Unable to change MaxMemorySize"));
2875 if (kilobytes
< info
.memory
) {
2876 if (virDomainSetMemory(dom
, kilobytes
) != 0) {
2877 vshError(ctl
, "%s", _("Unable to shrink current MemorySize"));
2889 static const vshCmdInfo info_memtune
[] = {
2890 {"help", N_("Get/Set memory paramters")},
2891 {"desc", N_("Get/Set the current memory paramters for the guest domain.\n" \
2892 " To get the memory parameters use following command: \n\n" \
2893 " virsh # memtune <domain>")},
2897 static const vshCmdOptDef opts_memtune
[] = {
2898 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
2899 {"hard-limit", VSH_OT_INT
, VSH_OFLAG_NONE
,
2900 N_("Max memory in kilobytes")},
2901 {"soft-limit", VSH_OT_INT
, VSH_OFLAG_NONE
,
2902 N_("Memory during contention in kilobytes")},
2903 {"swap-hard-limit", VSH_OT_INT
, VSH_OFLAG_NONE
,
2904 N_("Max swap in kilobytes")},
2905 {"min-guarantee", VSH_OT_INT
, VSH_OFLAG_NONE
,
2906 N_("Min guaranteed memory in kilobytes")},
2911 cmdMemtune(vshControl
* ctl
, const vshCmd
* cmd
)
2914 long long hard_limit
, soft_limit
, swap_hard_limit
, min_guarantee
;
2917 virMemoryParameterPtr params
= NULL
, temp
= NULL
;
2920 if (!vshConnectionUsability(ctl
, ctl
->conn
))
2923 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, NULL
)))
2927 vshCommandOptLongLong(cmd
, "hard-limit", NULL
);
2932 vshCommandOptLongLong(cmd
, "soft-limit", NULL
);
2937 vshCommandOptLongLong(cmd
, "swap-hard-limit", NULL
);
2938 if (swap_hard_limit
)
2942 vshCommandOptLongLong(cmd
, "min-guarantee", NULL
);
2947 /* get the number of memory parameters */
2948 if (virDomainGetMemoryParameters(dom
, NULL
, &nparams
, 0) != 0) {
2950 _("Unable to get number of memory parameters"));
2955 /* nothing to output */
2960 /* now go get all the memory parameters */
2961 params
= vshCalloc(ctl
, nparams
, sizeof(*params
));
2962 if (virDomainGetMemoryParameters(dom
, params
, &nparams
, 0) != 0) {
2963 vshError(ctl
, "%s", _("Unable to get memory parameters"));
2967 for (i
= 0; i
< nparams
; i
++) {
2968 switch (params
[i
].type
) {
2969 case VIR_DOMAIN_MEMORY_PARAM_INT
:
2970 vshPrint(ctl
, "%-15s: %d\n", params
[i
].field
,
2973 case VIR_DOMAIN_MEMORY_PARAM_UINT
:
2974 vshPrint(ctl
, "%-15s: %u\n", params
[i
].field
,
2975 params
[i
].value
.ui
);
2977 case VIR_DOMAIN_MEMORY_PARAM_LLONG
:
2978 vshPrint(ctl
, "%-15s: %lld\n", params
[i
].field
,
2981 case VIR_DOMAIN_MEMORY_PARAM_ULLONG
:
2982 vshPrint(ctl
, "%-15s: %llu\n", params
[i
].field
,
2983 params
[i
].value
.ul
);
2985 case VIR_DOMAIN_MEMORY_PARAM_DOUBLE
:
2986 vshPrint(ctl
, "%-15s: %f\n", params
[i
].field
,
2989 case VIR_DOMAIN_MEMORY_PARAM_BOOLEAN
:
2990 vshPrint(ctl
, "%-15s: %d\n", params
[i
].field
,
2994 vshPrint(ctl
, "unimplemented memory parameter type\n");
3000 /* set the memory parameters */
3001 params
= vshCalloc(ctl
, nparams
, sizeof(*params
));
3003 for (i
= 0; i
< nparams
; i
++) {
3005 temp
->type
= VIR_DOMAIN_MEMORY_PARAM_ULLONG
;
3008 * Some magic here, this is used to fill the params structure with
3009 * the valid arguments passed, after filling the particular
3010 * argument we purposely make them 0, so on the next pass it goes
3011 * to the next valid argument and so on.
3014 temp
->value
.ul
= soft_limit
;
3015 strncpy(temp
->field
, VIR_DOMAIN_MEMORY_SOFT_LIMIT
,
3016 sizeof(temp
->field
));
3018 } else if (hard_limit
) {
3019 temp
->value
.ul
= hard_limit
;
3020 strncpy(temp
->field
, VIR_DOMAIN_MEMORY_HARD_LIMIT
,
3021 sizeof(temp
->field
));
3023 } else if (swap_hard_limit
) {
3024 temp
->value
.ul
= swap_hard_limit
;
3025 strncpy(temp
->field
, VIR_DOMAIN_MEMORY_SWAP_HARD_LIMIT
,
3026 sizeof(temp
->field
));
3027 swap_hard_limit
= 0;
3028 } else if (min_guarantee
) {
3029 temp
->value
.ul
= min_guarantee
;
3030 strncpy(temp
->field
, VIR_DOMAIN_MEMORY_MIN_GUARANTEE
,
3031 sizeof(temp
->field
));
3035 if (virDomainSetMemoryParameters(dom
, params
, nparams
, 0) != 0)
3036 vshError(ctl
, "%s", _("Unable to change memory parameters"));
3048 * "nodeinfo" command
3050 static const vshCmdInfo info_nodeinfo
[] = {
3051 {"help", N_("node information")},
3052 {"desc", N_("Returns basic information about the node.")},
3057 cmdNodeinfo(vshControl
*ctl
, const vshCmd
*cmd ATTRIBUTE_UNUSED
)
3061 if (!vshConnectionUsability(ctl
, ctl
->conn
))
3064 if (virNodeGetInfo(ctl
->conn
, &info
) < 0) {
3065 vshError(ctl
, "%s", _("failed to get node information"));
3068 vshPrint(ctl
, "%-20s %s\n", _("CPU model:"), info
.model
);
3069 vshPrint(ctl
, "%-20s %d\n", _("CPU(s):"), info
.cpus
);
3070 vshPrint(ctl
, "%-20s %d MHz\n", _("CPU frequency:"), info
.mhz
);
3071 vshPrint(ctl
, "%-20s %d\n", _("CPU socket(s):"), info
.sockets
);
3072 vshPrint(ctl
, "%-20s %d\n", _("Core(s) per socket:"), info
.cores
);
3073 vshPrint(ctl
, "%-20s %d\n", _("Thread(s) per core:"), info
.threads
);
3074 vshPrint(ctl
, "%-20s %d\n", _("NUMA cell(s):"), info
.nodes
);
3075 vshPrint(ctl
, "%-20s %lu kB\n", _("Memory size:"), info
.memory
);
3081 * "capabilities" command
3083 static const vshCmdInfo info_capabilities
[] = {
3084 {"help", N_("capabilities")},
3085 {"desc", N_("Returns capabilities of hypervisor/driver.")},
3090 cmdCapabilities (vshControl
*ctl
, const vshCmd
*cmd ATTRIBUTE_UNUSED
)
3094 if (!vshConnectionUsability(ctl
, ctl
->conn
))
3097 if ((caps
= virConnectGetCapabilities (ctl
->conn
)) == NULL
) {
3098 vshError(ctl
, "%s", _("failed to get capabilities"));
3101 vshPrint (ctl
, "%s\n", caps
);
3110 static const vshCmdInfo info_dumpxml
[] = {
3111 {"help", N_("domain information in XML")},
3112 {"desc", N_("Output the domain information as an XML dump to stdout.")},
3116 static const vshCmdOptDef opts_dumpxml
[] = {
3117 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
3118 {"inactive", VSH_OT_BOOL
, 0, N_("show inactive defined XML")},
3119 {"security-info", VSH_OT_BOOL
, 0, N_("include security sensitive information in XML dump")},
3120 {"update-cpu", VSH_OT_BOOL
, 0, N_("update guest CPU according to host CPU")},
3125 cmdDumpXML(vshControl
*ctl
, const vshCmd
*cmd
)
3131 int inactive
= vshCommandOptBool(cmd
, "inactive");
3132 int secure
= vshCommandOptBool(cmd
, "security-info");
3133 int update
= vshCommandOptBool(cmd
, "update-cpu");
3136 flags
|= VIR_DOMAIN_XML_INACTIVE
;
3138 flags
|= VIR_DOMAIN_XML_SECURE
;
3140 flags
|= VIR_DOMAIN_XML_UPDATE_CPU
;
3142 if (!vshConnectionUsability(ctl
, ctl
->conn
))
3145 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, NULL
)))
3148 dump
= virDomainGetXMLDesc(dom
, flags
);
3150 vshPrint(ctl
, "%s", dump
);
3161 * "domxml-from-native" command
3163 static const vshCmdInfo info_domxmlfromnative
[] = {
3164 {"help", N_("Convert native config to domain XML")},
3165 {"desc", N_("Convert native guest configuration format to domain XML format.")},
3169 static const vshCmdOptDef opts_domxmlfromnative
[] = {
3170 {"format", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("source config data format")},
3171 {"config", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("config data file to import from")},
3176 cmdDomXMLFromNative(vshControl
*ctl
, const vshCmd
*cmd
)
3185 if (!vshConnectionUsability(ctl
, ctl
->conn
))
3188 format
= vshCommandOptString(cmd
, "format", NULL
);
3189 configFile
= vshCommandOptString(cmd
, "config", NULL
);
3191 if (virFileReadAll(configFile
, 1024*1024, &configData
) < 0)
3194 xmlData
= virConnectDomainXMLFromNative(ctl
->conn
, format
, configData
, flags
);
3195 if (xmlData
!= NULL
) {
3196 vshPrint(ctl
, "%s", xmlData
);
3206 * "domxml-to-native" command
3208 static const vshCmdInfo info_domxmltonative
[] = {
3209 {"help", N_("Convert domain XML to native config")},
3210 {"desc", N_("Convert domain XML config to a native guest configuration format.")},
3214 static const vshCmdOptDef opts_domxmltonative
[] = {
3215 {"format", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("target config data type format")},
3216 {"xml", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("xml data file to export from")},
3221 cmdDomXMLToNative(vshControl
*ctl
, const vshCmd
*cmd
)
3230 if (!vshConnectionUsability(ctl
, ctl
->conn
))
3233 format
= vshCommandOptString(cmd
, "format", NULL
);
3234 xmlFile
= vshCommandOptString(cmd
, "xml", NULL
);
3236 if (virFileReadAll(xmlFile
, 1024*1024, &xmlData
) < 0)
3239 configData
= virConnectDomainXMLToNative(ctl
->conn
, format
, xmlData
, flags
);
3240 if (configData
!= NULL
) {
3241 vshPrint(ctl
, "%s", configData
);
3242 VIR_FREE(configData
);
3253 static const vshCmdInfo info_domname
[] = {
3254 {"help", N_("convert a domain id or UUID to domain name")},
3259 static const vshCmdOptDef opts_domname
[] = {
3260 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain id or uuid")},
3265 cmdDomname(vshControl
*ctl
, const vshCmd
*cmd
)
3269 if (!vshConnectionUsability(ctl
, ctl
->conn
))
3271 if (!(dom
= vshCommandOptDomainBy(ctl
, cmd
, NULL
,
3272 VSH_BYID
|VSH_BYUUID
)))
3275 vshPrint(ctl
, "%s\n", virDomainGetName(dom
));
3283 static const vshCmdInfo info_domid
[] = {
3284 {"help", N_("convert a domain name or UUID to domain id")},
3289 static const vshCmdOptDef opts_domid
[] = {
3290 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name or uuid")},
3295 cmdDomid(vshControl
*ctl
, const vshCmd
*cmd
)
3300 if (!vshConnectionUsability(ctl
, ctl
->conn
))
3302 if (!(dom
= vshCommandOptDomainBy(ctl
, cmd
, NULL
,
3303 VSH_BYNAME
|VSH_BYUUID
)))
3306 id
= virDomainGetID(dom
);
3307 if (id
== ((unsigned int)-1))
3308 vshPrint(ctl
, "%s\n", "-");
3310 vshPrint(ctl
, "%d\n", id
);
3318 static const vshCmdInfo info_domuuid
[] = {
3319 {"help", N_("convert a domain name or id to domain UUID")},
3324 static const vshCmdOptDef opts_domuuid
[] = {
3325 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain id or name")},
3330 cmdDomuuid(vshControl
*ctl
, const vshCmd
*cmd
)
3333 char uuid
[VIR_UUID_STRING_BUFLEN
];
3335 if (!vshConnectionUsability(ctl
, ctl
->conn
))
3337 if (!(dom
= vshCommandOptDomainBy(ctl
, cmd
, NULL
,
3338 VSH_BYNAME
|VSH_BYID
)))
3341 if (virDomainGetUUIDString(dom
, uuid
) != -1)
3342 vshPrint(ctl
, "%s\n", uuid
);
3344 vshError(ctl
, "%s", _("failed to get domain UUID"));
3353 static const vshCmdInfo info_migrate
[] = {
3354 {"help", N_("migrate domain to another host")},
3355 {"desc", N_("Migrate domain to another host. Add --live for live migration.")},
3359 static const vshCmdOptDef opts_migrate
[] = {
3360 {"live", VSH_OT_BOOL
, 0, N_("live migration")},
3361 {"p2p", VSH_OT_BOOL
, 0, N_("peer-2-peer migration")},
3362 {"direct", VSH_OT_BOOL
, 0, N_("direct migration")},
3363 {"tunnelled", VSH_OT_BOOL
, 0, N_("tunnelled migration")},
3364 {"persistent", VSH_OT_BOOL
, 0, N_("persist VM on destination")},
3365 {"undefinesource", VSH_OT_BOOL
, 0, N_("undefine VM on source")},
3366 {"suspend", VSH_OT_BOOL
, 0, N_("do not restart the domain on the destination host")},
3367 {"copy-storage-all", VSH_OT_BOOL
, 0, N_("migration with non-shared storage with full disk copy")},
3368 {"copy-storage-inc", VSH_OT_BOOL
, 0, N_("migration with non-shared storage with incremental copy (same base image shared between source and destination)")},
3369 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
3370 {"desturi", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("connection URI of the destination host")},
3371 {"migrateuri", VSH_OT_DATA
, 0, N_("migration URI, usually can be omitted")},
3372 {"dname", VSH_OT_DATA
, 0, N_("rename to new name during migration (if supported)")},
3377 cmdMigrate (vshControl
*ctl
, const vshCmd
*cmd
)
3379 virDomainPtr dom
= NULL
;
3380 const char *desturi
;
3381 const char *migrateuri
;
3383 int flags
= 0, found
, ret
= FALSE
;
3385 if (!vshConnectionUsability (ctl
, ctl
->conn
))
3388 if (!(dom
= vshCommandOptDomain (ctl
, cmd
, NULL
)))
3391 desturi
= vshCommandOptString (cmd
, "desturi", &found
);
3395 migrateuri
= vshCommandOptString (cmd
, "migrateuri", NULL
);
3397 dname
= vshCommandOptString (cmd
, "dname", NULL
);
3399 if (vshCommandOptBool (cmd
, "live"))
3400 flags
|= VIR_MIGRATE_LIVE
;
3401 if (vshCommandOptBool (cmd
, "p2p"))
3402 flags
|= VIR_MIGRATE_PEER2PEER
;
3403 if (vshCommandOptBool (cmd
, "tunnelled"))
3404 flags
|= VIR_MIGRATE_TUNNELLED
;
3406 if (vshCommandOptBool (cmd
, "persistent"))
3407 flags
|= VIR_MIGRATE_PERSIST_DEST
;
3408 if (vshCommandOptBool (cmd
, "undefinesource"))
3409 flags
|= VIR_MIGRATE_UNDEFINE_SOURCE
;
3411 if (vshCommandOptBool (cmd
, "suspend"))
3412 flags
|= VIR_MIGRATE_PAUSED
;
3414 if (vshCommandOptBool (cmd
, "copy-storage-all"))
3415 flags
|= VIR_MIGRATE_NON_SHARED_DISK
;
3417 if (vshCommandOptBool (cmd
, "copy-storage-inc"))
3418 flags
|= VIR_MIGRATE_NON_SHARED_INC
;
3420 if ((flags
& VIR_MIGRATE_PEER2PEER
) ||
3421 vshCommandOptBool (cmd
, "direct")) {
3422 /* For peer2peer migration or direct migration we only expect one URI
3423 * a libvirt URI, or a hypervisor specific URI. */
3425 if (migrateuri
!= NULL
) {
3426 vshError(ctl
, "%s", _("migrate: Unexpected migrateuri for peer2peer/direct migration"));
3430 if (virDomainMigrateToURI (dom
, desturi
, flags
, dname
, 0) == 0)
3433 /* For traditional live migration, connect to the destination host directly. */
3434 virConnectPtr dconn
= NULL
;
3435 virDomainPtr ddom
= NULL
;
3437 dconn
= virConnectOpenAuth (desturi
, virConnectAuthPtrDefault
, 0);
3438 if (!dconn
) goto done
;
3440 ddom
= virDomainMigrate (dom
, dconn
, flags
, dname
, migrateuri
, 0);
3442 virDomainFree(ddom
);
3445 virConnectClose (dconn
);
3449 if (dom
) virDomainFree (dom
);
3454 * "migrate-setmaxdowntime" command
3456 static const vshCmdInfo info_migrate_setmaxdowntime
[] = {
3457 {"help", N_("set maximum tolerable downtime")},
3458 {"desc", N_("Set maximum tolerable downtime of a domain which is being live-migrated to another host.")},
3462 static const vshCmdOptDef opts_migrate_setmaxdowntime
[] = {
3463 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
3464 {"downtime", VSH_OT_INT
, VSH_OFLAG_REQ
, N_("maximum tolerable downtime (in milliseconds) for migration")},
3469 cmdMigrateSetMaxDowntime(vshControl
*ctl
, const vshCmd
*cmd
)
3471 virDomainPtr dom
= NULL
;
3476 if (!vshConnectionUsability(ctl
, ctl
->conn
))
3479 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, NULL
)))
3482 downtime
= vshCommandOptLongLong(cmd
, "downtime", &found
);
3483 if (!found
|| downtime
< 1) {
3484 vshError(ctl
, "%s", _("migrate: Invalid downtime"));
3488 if (virDomainMigrateSetMaxDowntime(dom
, downtime
, 0))
3499 * "net-autostart" command
3501 static const vshCmdInfo info_network_autostart
[] = {
3502 {"help", N_("autostart a network")},
3504 N_("Configure a network to be automatically started at boot.")},
3508 static const vshCmdOptDef opts_network_autostart
[] = {
3509 {"network", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("network name or uuid")},
3510 {"disable", VSH_OT_BOOL
, 0, N_("disable autostarting")},
3515 cmdNetworkAutostart(vshControl
*ctl
, const vshCmd
*cmd
)
3517 virNetworkPtr network
;
3521 if (!vshConnectionUsability(ctl
, ctl
->conn
))
3524 if (!(network
= vshCommandOptNetwork(ctl
, cmd
, &name
)))
3527 autostart
= !vshCommandOptBool(cmd
, "disable");
3529 if (virNetworkSetAutostart(network
, autostart
) < 0) {
3531 vshError(ctl
, _("failed to mark network %s as autostarted"), name
);
3533 vshError(ctl
, _("failed to unmark network %s as autostarted"), name
);
3534 virNetworkFree(network
);
3539 vshPrint(ctl
, _("Network %s marked as autostarted\n"), name
);
3541 vshPrint(ctl
, _("Network %s unmarked as autostarted\n"), name
);
3543 virNetworkFree(network
);
3548 * "net-create" command
3550 static const vshCmdInfo info_network_create
[] = {
3551 {"help", N_("create a network from an XML file")},
3552 {"desc", N_("Create a network.")},
3556 static const vshCmdOptDef opts_network_create
[] = {
3557 {"file", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("file containing an XML network description")},
3562 cmdNetworkCreate(vshControl
*ctl
, const vshCmd
*cmd
)
3564 virNetworkPtr network
;
3570 if (!vshConnectionUsability(ctl
, ctl
->conn
))
3573 from
= vshCommandOptString(cmd
, "file", &found
);
3577 if (virFileReadAll(from
, VIRSH_MAX_XML_FILE
, &buffer
) < 0)
3580 network
= virNetworkCreateXML(ctl
->conn
, buffer
);
3583 if (network
!= NULL
) {
3584 vshPrint(ctl
, _("Network %s created from %s\n"),
3585 virNetworkGetName(network
), from
);
3586 virNetworkFree(network
);
3588 vshError(ctl
, _("Failed to create network from %s"), from
);
3596 * "net-define" command
3598 static const vshCmdInfo info_network_define
[] = {
3599 {"help", N_("define (but don't start) a network from an XML file")},
3600 {"desc", N_("Define a network.")},
3604 static const vshCmdOptDef opts_network_define
[] = {
3605 {"file", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("file containing an XML network description")},
3610 cmdNetworkDefine(vshControl
*ctl
, const vshCmd
*cmd
)
3612 virNetworkPtr network
;
3618 if (!vshConnectionUsability(ctl
, ctl
->conn
))
3621 from
= vshCommandOptString(cmd
, "file", &found
);
3625 if (virFileReadAll(from
, VIRSH_MAX_XML_FILE
, &buffer
) < 0)
3628 network
= virNetworkDefineXML(ctl
->conn
, buffer
);
3631 if (network
!= NULL
) {
3632 vshPrint(ctl
, _("Network %s defined from %s\n"),
3633 virNetworkGetName(network
), from
);
3634 virNetworkFree(network
);
3636 vshError(ctl
, _("Failed to define network from %s"), from
);
3644 * "net-destroy" command
3646 static const vshCmdInfo info_network_destroy
[] = {
3647 {"help", N_("destroy a network")},
3648 {"desc", N_("Destroy a given network.")},
3652 static const vshCmdOptDef opts_network_destroy
[] = {
3653 {"network", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("network name, id or uuid")},
3658 cmdNetworkDestroy(vshControl
*ctl
, const vshCmd
*cmd
)
3660 virNetworkPtr network
;
3664 if (!vshConnectionUsability(ctl
, ctl
->conn
))
3667 if (!(network
= vshCommandOptNetwork(ctl
, cmd
, &name
)))
3670 if (virNetworkDestroy(network
) == 0) {
3671 vshPrint(ctl
, _("Network %s destroyed\n"), name
);
3673 vshError(ctl
, _("Failed to destroy network %s"), name
);
3677 virNetworkFree(network
);
3683 * "net-dumpxml" command
3685 static const vshCmdInfo info_network_dumpxml
[] = {
3686 {"help", N_("network information in XML")},
3687 {"desc", N_("Output the network information as an XML dump to stdout.")},
3691 static const vshCmdOptDef opts_network_dumpxml
[] = {
3692 {"network", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("network name, id or uuid")},
3697 cmdNetworkDumpXML(vshControl
*ctl
, const vshCmd
*cmd
)
3699 virNetworkPtr network
;
3703 if (!vshConnectionUsability(ctl
, ctl
->conn
))
3706 if (!(network
= vshCommandOptNetwork(ctl
, cmd
, NULL
)))
3709 dump
= virNetworkGetXMLDesc(network
, 0);
3711 vshPrint(ctl
, "%s", dump
);
3717 virNetworkFree(network
);
3723 * "iface-edit" command
3725 static const vshCmdInfo info_interface_edit
[] = {
3726 {"help", N_("edit XML configuration for a physical host interface")},
3727 {"desc", N_("Edit the XML configuration for a physical host interface.")},
3731 static const vshCmdOptDef opts_interface_edit
[] = {
3732 {"interface", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("interface name or MAC address")},
3737 cmdInterfaceEdit (vshControl
*ctl
, const vshCmd
*cmd
)
3740 virInterfacePtr iface
= NULL
;
3743 char *doc_edited
= NULL
;
3744 char *doc_reread
= NULL
;
3745 int flags
= VIR_INTERFACE_XML_INACTIVE
;
3747 if (!vshConnectionUsability(ctl
, ctl
->conn
))
3750 iface
= vshCommandOptInterface (ctl
, cmd
, NULL
);
3754 /* Get the XML configuration of the interface. */
3755 doc
= virInterfaceGetXMLDesc (iface
, flags
);
3759 /* Create and open the temporary file. */
3760 tmp
= editWriteToTempFile (ctl
, doc
);
3761 if (!tmp
) goto cleanup
;
3763 /* Start the editor. */
3764 if (editFile (ctl
, tmp
) == -1) goto cleanup
;
3766 /* Read back the edited file. */
3767 doc_edited
= editReadBackFile (ctl
, tmp
);
3768 if (!doc_edited
) goto cleanup
;
3770 /* Compare original XML with edited. Has it changed at all? */
3771 if (STREQ (doc
, doc_edited
)) {
3772 vshPrint (ctl
, _("Interface %s XML configuration not changed.\n"),
3773 virInterfaceGetName (iface
));
3778 /* Now re-read the interface XML. Did someone else change it while
3779 * it was being edited? This also catches problems such as us
3780 * losing a connection or the interface going away.
3782 doc_reread
= virInterfaceGetXMLDesc (iface
, flags
);
3786 if (STRNEQ (doc
, doc_reread
)) {
3788 _("ERROR: the XML configuration was changed by another user"));
3792 /* Everything checks out, so redefine the interface. */
3793 virInterfaceFree (iface
);
3794 iface
= virInterfaceDefineXML (ctl
->conn
, doc_edited
, 0);
3798 vshPrint (ctl
, _("Interface %s XML configuration edited.\n"),
3799 virInterfaceGetName(iface
));
3805 virInterfaceFree (iface
);
3808 VIR_FREE(doc_edited
);
3809 VIR_FREE(doc_reread
);
3820 * "net-list" command
3822 static const vshCmdInfo info_network_list
[] = {
3823 {"help", N_("list networks")},
3824 {"desc", N_("Returns list of networks.")},
3828 static const vshCmdOptDef opts_network_list
[] = {
3829 {"inactive", VSH_OT_BOOL
, 0, N_("list inactive networks")},
3830 {"all", VSH_OT_BOOL
, 0, N_("list inactive & active networks")},
3835 cmdNetworkList(vshControl
*ctl
, const vshCmd
*cmd ATTRIBUTE_UNUSED
)
3837 int inactive
= vshCommandOptBool(cmd
, "inactive");
3838 int all
= vshCommandOptBool(cmd
, "all");
3839 int active
= !inactive
|| all
? 1 : 0;
3840 int maxactive
= 0, maxinactive
= 0, i
;
3841 char **activeNames
= NULL
, **inactiveNames
= NULL
;
3844 if (!vshConnectionUsability(ctl
, ctl
->conn
))
3848 maxactive
= virConnectNumOfNetworks(ctl
->conn
);
3849 if (maxactive
< 0) {
3850 vshError(ctl
, "%s", _("Failed to list active networks"));
3854 activeNames
= vshMalloc(ctl
, sizeof(char *) * maxactive
);
3856 if ((maxactive
= virConnectListNetworks(ctl
->conn
, activeNames
,
3858 vshError(ctl
, "%s", _("Failed to list active networks"));
3859 VIR_FREE(activeNames
);
3863 qsort(&activeNames
[0], maxactive
, sizeof(char *), namesorter
);
3867 maxinactive
= virConnectNumOfDefinedNetworks(ctl
->conn
);
3868 if (maxinactive
< 0) {
3869 vshError(ctl
, "%s", _("Failed to list inactive networks"));
3870 VIR_FREE(activeNames
);
3874 inactiveNames
= vshMalloc(ctl
, sizeof(char *) * maxinactive
);
3877 virConnectListDefinedNetworks(ctl
->conn
, inactiveNames
,
3878 maxinactive
)) < 0) {
3879 vshError(ctl
, "%s", _("Failed to list inactive networks"));
3880 VIR_FREE(activeNames
);
3881 VIR_FREE(inactiveNames
);
3885 qsort(&inactiveNames
[0], maxinactive
, sizeof(char*), namesorter
);
3888 vshPrintExtra(ctl
, "%-20s %-10s %s\n", _("Name"), _("State"),
3890 vshPrintExtra(ctl
, "-----------------------------------------\n");
3892 for (i
= 0; i
< maxactive
; i
++) {
3893 virNetworkPtr network
=
3894 virNetworkLookupByName(ctl
->conn
, activeNames
[i
]);
3895 const char *autostartStr
;
3898 /* this kind of work with networks is not atomic operation */
3900 VIR_FREE(activeNames
[i
]);
3904 if (virNetworkGetAutostart(network
, &autostart
) < 0)
3905 autostartStr
= _("no autostart");
3907 autostartStr
= autostart
? _("yes") : _("no");
3909 vshPrint(ctl
, "%-20s %-10s %-10s\n",
3910 virNetworkGetName(network
),
3913 virNetworkFree(network
);
3914 VIR_FREE(activeNames
[i
]);
3916 for (i
= 0; i
< maxinactive
; i
++) {
3917 virNetworkPtr network
= virNetworkLookupByName(ctl
->conn
, inactiveNames
[i
]);
3918 const char *autostartStr
;
3921 /* this kind of work with networks is not atomic operation */
3923 VIR_FREE(inactiveNames
[i
]);
3927 if (virNetworkGetAutostart(network
, &autostart
) < 0)
3928 autostartStr
= _("no autostart");
3930 autostartStr
= autostart
? _("yes") : _("no");
3932 vshPrint(ctl
, "%-20s %-10s %-10s\n",
3937 virNetworkFree(network
);
3938 VIR_FREE(inactiveNames
[i
]);
3940 VIR_FREE(activeNames
);
3941 VIR_FREE(inactiveNames
);
3947 * "net-name" command
3949 static const vshCmdInfo info_network_name
[] = {
3950 {"help", N_("convert a network UUID to network name")},
3955 static const vshCmdOptDef opts_network_name
[] = {
3956 {"network", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("network uuid")},
3961 cmdNetworkName(vshControl
*ctl
, const vshCmd
*cmd
)
3963 virNetworkPtr network
;
3965 if (!vshConnectionUsability(ctl
, ctl
->conn
))
3967 if (!(network
= vshCommandOptNetworkBy(ctl
, cmd
, NULL
,
3971 vshPrint(ctl
, "%s\n", virNetworkGetName(network
));
3972 virNetworkFree(network
);
3978 * "net-start" command
3980 static const vshCmdInfo info_network_start
[] = {
3981 {"help", N_("start a (previously defined) inactive network")},
3982 {"desc", N_("Start a network.")},
3986 static const vshCmdOptDef opts_network_start
[] = {
3987 {"network", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("name of the inactive network")},
3992 cmdNetworkStart(vshControl
*ctl
, const vshCmd
*cmd
)
3994 virNetworkPtr network
;
3997 if (!vshConnectionUsability(ctl
, ctl
->conn
))
4000 if (!(network
= vshCommandOptNetworkBy(ctl
, cmd
, NULL
, VSH_BYNAME
)))
4003 if (virNetworkCreate(network
) == 0) {
4004 vshPrint(ctl
, _("Network %s started\n"),
4005 virNetworkGetName(network
));
4007 vshError(ctl
, _("Failed to start network %s"),
4008 virNetworkGetName(network
));
4011 virNetworkFree(network
);
4017 * "net-undefine" command
4019 static const vshCmdInfo info_network_undefine
[] = {
4020 {"help", N_("undefine an inactive network")},
4021 {"desc", N_("Undefine the configuration for an inactive network.")},
4025 static const vshCmdOptDef opts_network_undefine
[] = {
4026 {"network", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("network name or uuid")},
4031 cmdNetworkUndefine(vshControl
*ctl
, const vshCmd
*cmd
)
4033 virNetworkPtr network
;
4037 if (!vshConnectionUsability(ctl
, ctl
->conn
))
4040 if (!(network
= vshCommandOptNetwork(ctl
, cmd
, &name
)))
4043 if (virNetworkUndefine(network
) == 0) {
4044 vshPrint(ctl
, _("Network %s has been undefined\n"), name
);
4046 vshError(ctl
, _("Failed to undefine network %s"), name
);
4050 virNetworkFree(network
);
4056 * "net-uuid" command
4058 static const vshCmdInfo info_network_uuid
[] = {
4059 {"help", N_("convert a network name to network UUID")},
4064 static const vshCmdOptDef opts_network_uuid
[] = {
4065 {"network", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("network name")},
4070 cmdNetworkUuid(vshControl
*ctl
, const vshCmd
*cmd
)
4072 virNetworkPtr network
;
4073 char uuid
[VIR_UUID_STRING_BUFLEN
];
4075 if (!vshConnectionUsability(ctl
, ctl
->conn
))
4078 if (!(network
= vshCommandOptNetworkBy(ctl
, cmd
, NULL
,
4082 if (virNetworkGetUUIDString(network
, uuid
) != -1)
4083 vshPrint(ctl
, "%s\n", uuid
);
4085 vshError(ctl
, "%s", _("failed to get network UUID"));
4087 virNetworkFree(network
);
4092 /**************************************************************************/
4094 * "iface-list" command
4096 static const vshCmdInfo info_interface_list
[] = {
4097 {"help", N_("list physical host interfaces")},
4098 {"desc", N_("Returns list of physical host interfaces.")},
4102 static const vshCmdOptDef opts_interface_list
[] = {
4103 {"inactive", VSH_OT_BOOL
, 0, N_("list inactive interfaces")},
4104 {"all", VSH_OT_BOOL
, 0, N_("list inactive & active interfaces")},
4108 cmdInterfaceList(vshControl
*ctl
, const vshCmd
*cmd ATTRIBUTE_UNUSED
)
4110 int inactive
= vshCommandOptBool(cmd
, "inactive");
4111 int all
= vshCommandOptBool(cmd
, "all");
4112 int active
= !inactive
|| all
? 1 : 0;
4113 int maxactive
= 0, maxinactive
= 0, i
;
4114 char **activeNames
= NULL
, **inactiveNames
= NULL
;
4117 if (!vshConnectionUsability(ctl
, ctl
->conn
))
4121 maxactive
= virConnectNumOfInterfaces(ctl
->conn
);
4122 if (maxactive
< 0) {
4123 vshError(ctl
, "%s", _("Failed to list active interfaces"));
4127 activeNames
= vshMalloc(ctl
, sizeof(char *) * maxactive
);
4129 if ((maxactive
= virConnectListInterfaces(ctl
->conn
, activeNames
,
4131 vshError(ctl
, "%s", _("Failed to list active interfaces"));
4132 VIR_FREE(activeNames
);
4136 qsort(&activeNames
[0], maxactive
, sizeof(char *), namesorter
);
4140 maxinactive
= virConnectNumOfDefinedInterfaces(ctl
->conn
);
4141 if (maxinactive
< 0) {
4142 vshError(ctl
, "%s", _("Failed to list inactive interfaces"));
4143 VIR_FREE(activeNames
);
4147 inactiveNames
= vshMalloc(ctl
, sizeof(char *) * maxinactive
);
4150 virConnectListDefinedInterfaces(ctl
->conn
, inactiveNames
,
4151 maxinactive
)) < 0) {
4152 vshError(ctl
, "%s", _("Failed to list inactive interfaces"));
4153 VIR_FREE(activeNames
);
4154 VIR_FREE(inactiveNames
);
4158 qsort(&inactiveNames
[0], maxinactive
, sizeof(char*), namesorter
);
4161 vshPrintExtra(ctl
, "%-20s %-10s %s\n", _("Name"), _("State"),
4163 vshPrintExtra(ctl
, "--------------------------------------------\n");
4165 for (i
= 0; i
< maxactive
; i
++) {
4166 virInterfacePtr iface
=
4167 virInterfaceLookupByName(ctl
->conn
, activeNames
[i
]);
4169 /* this kind of work with interfaces is not atomic */
4171 VIR_FREE(activeNames
[i
]);
4175 vshPrint(ctl
, "%-20s %-10s %s\n",
4176 virInterfaceGetName(iface
),
4178 virInterfaceGetMACString(iface
));
4179 virInterfaceFree(iface
);
4180 VIR_FREE(activeNames
[i
]);
4182 for (i
= 0; i
< maxinactive
; i
++) {
4183 virInterfacePtr iface
=
4184 virInterfaceLookupByName(ctl
->conn
, inactiveNames
[i
]);
4186 /* this kind of work with interfaces is not atomic */
4188 VIR_FREE(inactiveNames
[i
]);
4192 vshPrint(ctl
, "%-20s %-10s %s\n",
4193 virInterfaceGetName(iface
),
4195 virInterfaceGetMACString(iface
));
4196 virInterfaceFree(iface
);
4197 VIR_FREE(inactiveNames
[i
]);
4199 VIR_FREE(activeNames
);
4200 VIR_FREE(inactiveNames
);
4206 * "iface-name" command
4208 static const vshCmdInfo info_interface_name
[] = {
4209 {"help", N_("convert an interface MAC address to interface name")},
4214 static const vshCmdOptDef opts_interface_name
[] = {
4215 {"interface", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("interface mac")},
4220 cmdInterfaceName(vshControl
*ctl
, const vshCmd
*cmd
)
4222 virInterfacePtr iface
;
4224 if (!vshConnectionUsability(ctl
, ctl
->conn
))
4226 if (!(iface
= vshCommandOptInterfaceBy(ctl
, cmd
, NULL
,
4230 vshPrint(ctl
, "%s\n", virInterfaceGetName(iface
));
4231 virInterfaceFree(iface
);
4236 * "iface-mac" command
4238 static const vshCmdInfo info_interface_mac
[] = {
4239 {"help", N_("convert an interface name to interface MAC address")},
4244 static const vshCmdOptDef opts_interface_mac
[] = {
4245 {"interface", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("interface name")},
4250 cmdInterfaceMAC(vshControl
*ctl
, const vshCmd
*cmd
)
4252 virInterfacePtr iface
;
4254 if (!vshConnectionUsability(ctl
, ctl
->conn
))
4256 if (!(iface
= vshCommandOptInterfaceBy(ctl
, cmd
, NULL
,
4260 vshPrint(ctl
, "%s\n", virInterfaceGetMACString(iface
));
4261 virInterfaceFree(iface
);
4266 * "iface-dumpxml" command
4268 static const vshCmdInfo info_interface_dumpxml
[] = {
4269 {"help", N_("interface information in XML")},
4270 {"desc", N_("Output the physical host interface information as an XML dump to stdout.")},
4274 static const vshCmdOptDef opts_interface_dumpxml
[] = {
4275 {"interface", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("interface name or MAC address")},
4276 {"inactive", VSH_OT_BOOL
, 0, N_("show inactive defined XML")},
4281 cmdInterfaceDumpXML(vshControl
*ctl
, const vshCmd
*cmd
)
4283 virInterfacePtr iface
;
4287 int inactive
= vshCommandOptBool(cmd
, "inactive");
4290 flags
|= VIR_INTERFACE_XML_INACTIVE
;
4292 if (!vshConnectionUsability(ctl
, ctl
->conn
))
4295 if (!(iface
= vshCommandOptInterface(ctl
, cmd
, NULL
)))
4298 dump
= virInterfaceGetXMLDesc(iface
, flags
);
4300 vshPrint(ctl
, "%s", dump
);
4306 virInterfaceFree(iface
);
4311 * "iface-define" command
4313 static const vshCmdInfo info_interface_define
[] = {
4314 {"help", N_("define (but don't start) a physical host interface from an XML file")},
4315 {"desc", N_("Define a physical host interface.")},
4319 static const vshCmdOptDef opts_interface_define
[] = {
4320 {"file", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("file containing an XML interface description")},
4325 cmdInterfaceDefine(vshControl
*ctl
, const vshCmd
*cmd
)
4327 virInterfacePtr iface
;
4333 if (!vshConnectionUsability(ctl
, ctl
->conn
))
4336 from
= vshCommandOptString(cmd
, "file", &found
);
4340 if (virFileReadAll(from
, VIRSH_MAX_XML_FILE
, &buffer
) < 0)
4343 iface
= virInterfaceDefineXML(ctl
->conn
, buffer
, 0);
4346 if (iface
!= NULL
) {
4347 vshPrint(ctl
, _("Interface %s defined from %s\n"),
4348 virInterfaceGetName(iface
), from
);
4349 virInterfaceFree (iface
);
4351 vshError(ctl
, _("Failed to define interface from %s"), from
);
4358 * "iface-undefine" command
4360 static const vshCmdInfo info_interface_undefine
[] = {
4361 {"help", N_("undefine a physical host interface (remove it from configuration)")},
4362 {"desc", N_("undefine an interface.")},
4366 static const vshCmdOptDef opts_interface_undefine
[] = {
4367 {"interface", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("interface name or MAC address")},
4372 cmdInterfaceUndefine(vshControl
*ctl
, const vshCmd
*cmd
)
4374 virInterfacePtr iface
;
4378 if (!vshConnectionUsability(ctl
, ctl
->conn
))
4381 if (!(iface
= vshCommandOptInterface(ctl
, cmd
, &name
)))
4384 if (virInterfaceUndefine(iface
) == 0) {
4385 vshPrint(ctl
, _("Interface %s undefined\n"), name
);
4387 vshError(ctl
, _("Failed to undefine interface %s"), name
);
4391 virInterfaceFree(iface
);
4396 * "iface-start" command
4398 static const vshCmdInfo info_interface_start
[] = {
4399 {"help", N_("start a physical host interface (enable it / \"if-up\")")},
4400 {"desc", N_("start a physical host interface.")},
4404 static const vshCmdOptDef opts_interface_start
[] = {
4405 {"interface", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("interface name or MAC address")},
4410 cmdInterfaceStart(vshControl
*ctl
, const vshCmd
*cmd
)
4412 virInterfacePtr iface
;
4416 if (!vshConnectionUsability(ctl
, ctl
->conn
))
4419 if (!(iface
= vshCommandOptInterface(ctl
, cmd
, &name
)))
4422 if (virInterfaceCreate(iface
, 0) == 0) {
4423 vshPrint(ctl
, _("Interface %s started\n"), name
);
4425 vshError(ctl
, _("Failed to start interface %s"), name
);
4429 virInterfaceFree(iface
);
4434 * "iface-destroy" command
4436 static const vshCmdInfo info_interface_destroy
[] = {
4437 {"help", N_("destroy a physical host interface (disable it / \"if-down\")")},
4438 {"desc", N_("destroy a physical host interface.")},
4442 static const vshCmdOptDef opts_interface_destroy
[] = {
4443 {"interface", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("interface name or MAC address")},
4448 cmdInterfaceDestroy(vshControl
*ctl
, const vshCmd
*cmd
)
4450 virInterfacePtr iface
;
4454 if (!vshConnectionUsability(ctl
, ctl
->conn
))
4457 if (!(iface
= vshCommandOptInterface(ctl
, cmd
, &name
)))
4460 if (virInterfaceDestroy(iface
, 0) == 0) {
4461 vshPrint(ctl
, _("Interface %s destroyed\n"), name
);
4463 vshError(ctl
, _("Failed to destroy interface %s"), name
);
4467 virInterfaceFree(iface
);
4473 * "nwfilter-define" command
4475 static const vshCmdInfo info_nwfilter_define
[] = {
4476 {"help", N_("define or update a network filter from an XML file")},
4477 {"desc", N_("Define a new network filter or update an existing one.")},
4481 static const vshCmdOptDef opts_nwfilter_define
[] = {
4482 {"file", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("file containing an XML network filter description")},
4487 cmdNWFilterDefine(vshControl
*ctl
, const vshCmd
*cmd
)
4489 virNWFilterPtr nwfilter
;
4495 if (!vshConnectionUsability(ctl
, ctl
->conn
))
4498 from
= vshCommandOptString(cmd
, "file", &found
);
4502 if (virFileReadAll(from
, VIRSH_MAX_XML_FILE
, &buffer
) < 0)
4505 nwfilter
= virNWFilterDefineXML(ctl
->conn
, buffer
);
4508 if (nwfilter
!= NULL
) {
4509 vshPrint(ctl
, _("Network filter %s defined from %s\n"),
4510 virNWFilterGetName(nwfilter
), from
);
4511 virNWFilterFree(nwfilter
);
4513 vshError(ctl
, _("Failed to define network filter from %s"), from
);
4521 * "nwfilter-undefine" command
4523 static const vshCmdInfo info_nwfilter_undefine
[] = {
4524 {"help", N_("undefine a network filter")},
4525 {"desc", N_("Undefine a given network filter.")},
4529 static const vshCmdOptDef opts_nwfilter_undefine
[] = {
4530 {"nwfilter", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("network filter name or uuid")},
4535 cmdNWFilterUndefine(vshControl
*ctl
, const vshCmd
*cmd
)
4537 virNWFilterPtr nwfilter
;
4541 if (!vshConnectionUsability(ctl
, ctl
->conn
))
4544 if (!(nwfilter
= vshCommandOptNWFilter(ctl
, cmd
, &name
)))
4547 if (virNWFilterUndefine(nwfilter
) == 0) {
4548 vshPrint(ctl
, _("Network filter %s undefined\n"), name
);
4550 vshError(ctl
, _("Failed to undefine network filter %s"), name
);
4554 virNWFilterFree(nwfilter
);
4560 * "nwfilter-dumpxml" command
4562 static const vshCmdInfo info_nwfilter_dumpxml
[] = {
4563 {"help", N_("network filter information in XML")},
4564 {"desc", N_("Output the network filter information as an XML dump to stdout.")},
4568 static const vshCmdOptDef opts_nwfilter_dumpxml
[] = {
4569 {"nwfilter", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("network filter name or uuid")},
4574 cmdNWFilterDumpXML(vshControl
*ctl
, const vshCmd
*cmd
)
4576 virNWFilterPtr nwfilter
;
4580 if (!vshConnectionUsability(ctl
, ctl
->conn
))
4583 if (!(nwfilter
= vshCommandOptNWFilter(ctl
, cmd
, NULL
)))
4586 dump
= virNWFilterGetXMLDesc(nwfilter
, 0);
4588 vshPrint(ctl
, "%s", dump
);
4594 virNWFilterFree(nwfilter
);
4599 * "nwfilter-list" command
4601 static const vshCmdInfo info_nwfilter_list
[] = {
4602 {"help", N_("list network filters")},
4603 {"desc", N_("Returns list of network filters.")},
4607 static const vshCmdOptDef opts_nwfilter_list
[] = {
4612 cmdNWFilterList(vshControl
*ctl
, const vshCmd
*cmd ATTRIBUTE_UNUSED
)
4616 char uuid
[VIR_UUID_STRING_BUFLEN
];
4618 if (!vshConnectionUsability(ctl
, ctl
->conn
))
4621 numfilters
= virConnectNumOfNWFilters(ctl
->conn
);
4622 if (numfilters
< 0) {
4623 vshError(ctl
, "%s", _("Failed to list network filters"));
4627 names
= vshMalloc(ctl
, sizeof(char *) * numfilters
);
4629 if ((numfilters
= virConnectListNWFilters(ctl
->conn
, names
,
4631 vshError(ctl
, "%s", _("Failed to list network filters"));
4636 qsort(&names
[0], numfilters
, sizeof(char *), namesorter
);
4638 vshPrintExtra(ctl
, "%-36s %-20s \n", _("UUID"), _("Name"));
4640 "----------------------------------------------------------------\n");
4642 for (i
= 0; i
< numfilters
; i
++) {
4643 virNWFilterPtr nwfilter
=
4644 virNWFilterLookupByName(ctl
->conn
, names
[i
]);
4646 /* this kind of work with networks is not atomic operation */
4652 virNWFilterGetUUIDString(nwfilter
, uuid
);
4653 vshPrint(ctl
, "%-36s %-20s\n",
4655 virNWFilterGetName(nwfilter
));
4656 virNWFilterFree(nwfilter
);
4666 * "nwfilter-edit" command
4668 static const vshCmdInfo info_nwfilter_edit
[] = {
4669 {"help", N_("edit XML configuration for a network filter")},
4670 {"desc", N_("Edit the XML configuration for a network filter.")},
4674 static const vshCmdOptDef opts_nwfilter_edit
[] = {
4675 {"nwfilter", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("network filter name or uuid")},
4680 cmdNWFilterEdit (vshControl
*ctl
, const vshCmd
*cmd
)
4683 virNWFilterPtr nwfilter
= NULL
;
4686 char *doc_edited
= NULL
;
4687 char *doc_reread
= NULL
;
4689 if (!vshConnectionUsability(ctl
, ctl
->conn
))
4692 nwfilter
= vshCommandOptNWFilter (ctl
, cmd
, NULL
);
4693 if (nwfilter
== NULL
)
4696 /* Get the XML configuration of the interface. */
4697 doc
= virNWFilterGetXMLDesc (nwfilter
, 0);
4701 /* Create and open the temporary file. */
4702 tmp
= editWriteToTempFile (ctl
, doc
);
4703 if (!tmp
) goto cleanup
;
4705 /* Start the editor. */
4706 if (editFile (ctl
, tmp
) == -1) goto cleanup
;
4708 /* Read back the edited file. */
4709 doc_edited
= editReadBackFile (ctl
, tmp
);
4710 if (!doc_edited
) goto cleanup
;
4712 /* Compare original XML with edited. Has it changed at all? */
4713 if (STREQ (doc
, doc_edited
)) {
4714 vshPrint (ctl
, _("Network filter %s XML configuration not changed.\n"),
4715 virNWFilterGetName (nwfilter
));
4720 /* Now re-read the network filter XML. Did someone else change it while
4721 * it was being edited? This also catches problems such as us
4722 * losing a connection or the interface going away.
4724 doc_reread
= virNWFilterGetXMLDesc (nwfilter
, 0);
4728 if (STRNEQ (doc
, doc_reread
)) {
4730 _("ERROR: the XML configuration was changed by another user"));
4734 /* Everything checks out, so redefine the interface. */
4735 virNWFilterFree (nwfilter
);
4736 nwfilter
= virNWFilterDefineXML (ctl
->conn
, doc_edited
);
4740 vshPrint (ctl
, _("Network filter %s XML configuration edited.\n"),
4741 virNWFilterGetName(nwfilter
));
4747 virNWFilterFree (nwfilter
);
4750 VIR_FREE(doc_edited
);
4751 VIR_FREE(doc_reread
);
4762 /**************************************************************************/
4764 * "pool-autostart" command
4766 static const vshCmdInfo info_pool_autostart
[] = {
4767 {"help", N_("autostart a pool")},
4769 N_("Configure a pool to be automatically started at boot.")},
4773 static const vshCmdOptDef opts_pool_autostart
[] = {
4774 {"pool", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("pool name or uuid")},
4775 {"disable", VSH_OT_BOOL
, 0, N_("disable autostarting")},
4780 cmdPoolAutostart(vshControl
*ctl
, const vshCmd
*cmd
)
4782 virStoragePoolPtr pool
;
4786 if (!vshConnectionUsability(ctl
, ctl
->conn
))
4789 if (!(pool
= vshCommandOptPool(ctl
, cmd
, "pool", &name
)))
4792 autostart
= !vshCommandOptBool(cmd
, "disable");
4794 if (virStoragePoolSetAutostart(pool
, autostart
) < 0) {
4796 vshError(ctl
, _("failed to mark pool %s as autostarted"), name
);
4798 vshError(ctl
, _("failed to unmark pool %s as autostarted"), name
);
4799 virStoragePoolFree(pool
);
4804 vshPrint(ctl
, _("Pool %s marked as autostarted\n"), name
);
4806 vshPrint(ctl
, _("Pool %s unmarked as autostarted\n"), name
);
4808 virStoragePoolFree(pool
);
4813 * "pool-create" command
4815 static const vshCmdInfo info_pool_create
[] = {
4816 {"help", N_("create a pool from an XML file")},
4817 {"desc", N_("Create a pool.")},
4821 static const vshCmdOptDef opts_pool_create
[] = {
4822 {"file", VSH_OT_DATA
, VSH_OFLAG_REQ
,
4823 N_("file containing an XML pool description")},
4828 cmdPoolCreate(vshControl
*ctl
, const vshCmd
*cmd
)
4830 virStoragePoolPtr pool
;
4836 if (!vshConnectionUsability(ctl
, ctl
->conn
))
4839 from
= vshCommandOptString(cmd
, "file", &found
);
4843 if (virFileReadAll(from
, VIRSH_MAX_XML_FILE
, &buffer
) < 0)
4846 pool
= virStoragePoolCreateXML(ctl
->conn
, buffer
, 0);
4850 vshPrint(ctl
, _("Pool %s created from %s\n"),
4851 virStoragePoolGetName(pool
), from
);
4852 virStoragePoolFree(pool
);
4854 vshError(ctl
, _("Failed to create pool from %s"), from
);
4862 * "nodedev-create" command
4864 static const vshCmdInfo info_node_device_create
[] = {
4865 {"help", N_("create a device defined "
4866 "by an XML file on the node")},
4867 {"desc", N_("Create a device on the node. Note that this "
4868 "command creates devices on the physical host "
4869 "that can then be assigned to a virtual machine.")},
4873 static const vshCmdOptDef opts_node_device_create
[] = {
4874 {"file", VSH_OT_DATA
, VSH_OFLAG_REQ
,
4875 N_("file containing an XML description of the device")},
4880 cmdNodeDeviceCreate(vshControl
*ctl
, const vshCmd
*cmd
)
4882 virNodeDevicePtr dev
= NULL
;
4888 if (!vshConnectionUsability(ctl
, ctl
->conn
))
4891 from
= vshCommandOptString(cmd
, "file", &found
);
4896 if (virFileReadAll(from
, VIRSH_MAX_XML_FILE
, &buffer
) < 0)
4899 dev
= virNodeDeviceCreateXML(ctl
->conn
, buffer
, 0);
4903 vshPrint(ctl
, _("Node device %s created from %s\n"),
4904 virNodeDeviceGetName(dev
), from
);
4905 virNodeDeviceFree(dev
);
4907 vshError(ctl
, _("Failed to create node device from %s"), from
);
4916 * "nodedev-destroy" command
4918 static const vshCmdInfo info_node_device_destroy
[] = {
4919 {"help", N_("destroy a device on the node")},
4920 {"desc", N_("Destroy a device on the node. Note that this "
4921 "command destroys devices on the physical host ")},
4925 static const vshCmdOptDef opts_node_device_destroy
[] = {
4926 {"name", VSH_OT_DATA
, VSH_OFLAG_REQ
,
4927 N_("name of the device to be destroyed")},
4932 cmdNodeDeviceDestroy(vshControl
*ctl
, const vshCmd
*cmd
)
4934 virNodeDevicePtr dev
= NULL
;
4939 if (!vshConnectionUsability(ctl
, ctl
->conn
)) {
4943 name
= vshCommandOptString(cmd
, "name", &found
);
4948 dev
= virNodeDeviceLookupByName(ctl
->conn
, name
);
4950 if (virNodeDeviceDestroy(dev
) == 0) {
4951 vshPrint(ctl
, _("Destroyed node device '%s'\n"), name
);
4953 vshError(ctl
, _("Failed to destroy node device '%s'"), name
);
4957 virNodeDeviceFree(dev
);
4963 * XML Building helper for pool-define-as and pool-create-as
4965 static const vshCmdOptDef opts_pool_X_as
[] = {
4966 {"name", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("name of the pool")},
4967 {"print-xml", VSH_OT_BOOL
, 0, N_("print XML document, but don't define/create")},
4968 {"type", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("type of the pool")},
4969 {"source-host", VSH_OT_DATA
, 0, N_("source-host for underlying storage")},
4970 {"source-path", VSH_OT_DATA
, 0, N_("source path for underlying storage")},
4971 {"source-dev", VSH_OT_DATA
, 0, N_("source device for underlying storage")},
4972 {"source-name", VSH_OT_DATA
, 0, N_("source name for underlying storage")},
4973 {"target", VSH_OT_DATA
, 0, N_("target for underlying storage")},
4974 {"source-format", VSH_OT_STRING
, 0, N_("format for underlying storage")},
4978 static int buildPoolXML(const vshCmd
*cmd
, char **retname
, char **xml
) {
4981 char *name
, *type
, *srcHost
, *srcPath
, *srcDev
, *srcName
, *srcFormat
, *target
;
4982 virBuffer buf
= VIR_BUFFER_INITIALIZER
;
4984 name
= vshCommandOptString(cmd
, "name", &found
);
4987 type
= vshCommandOptString(cmd
, "type", &found
);
4991 srcHost
= vshCommandOptString(cmd
, "source-host", &found
);
4992 srcPath
= vshCommandOptString(cmd
, "source-path", &found
);
4993 srcDev
= vshCommandOptString(cmd
, "source-dev", &found
);
4994 srcName
= vshCommandOptString(cmd
, "source-name", &found
);
4995 srcFormat
= vshCommandOptString(cmd
, "source-format", &found
);
4996 target
= vshCommandOptString(cmd
, "target", &found
);
4998 virBufferVSprintf(&buf
, "<pool type='%s'>\n", type
);
4999 virBufferVSprintf(&buf
, " <name>%s</name>\n", name
);
5000 if (srcHost
|| srcPath
|| srcDev
) {
5001 virBufferAddLit(&buf
, " <source>\n");
5004 virBufferVSprintf(&buf
, " <host name='%s'/>\n", srcHost
);
5006 virBufferVSprintf(&buf
, " <dir path='%s'/>\n", srcPath
);
5008 virBufferVSprintf(&buf
, " <device path='%s'/>\n", srcDev
);
5010 virBufferVSprintf(&buf
, " <format type='%s'/>\n", srcFormat
);
5012 virBufferVSprintf(&buf
, " <name>%s</name>\n", srcName
);
5014 virBufferAddLit(&buf
, " </source>\n");
5017 virBufferAddLit(&buf
, " <target>\n");
5018 virBufferVSprintf(&buf
, " <path>%s</path>\n", target
);
5019 virBufferAddLit(&buf
, " </target>\n");
5021 virBufferAddLit(&buf
, "</pool>\n");
5023 if (virBufferError(&buf
)) {
5024 vshPrint(ctl
, "%s", _("Failed to allocate XML buffer"));
5028 *xml
= virBufferContentAndReset(&buf
);
5033 virBufferFreeAndReset(&buf
);
5038 * "pool-create-as" command
5040 static const vshCmdInfo info_pool_create_as
[] = {
5041 {"help", N_("create a pool from a set of args")},
5042 {"desc", N_("Create a pool.")},
5047 cmdPoolCreateAs(vshControl
*ctl
, const vshCmd
*cmd
)
5049 virStoragePoolPtr pool
;
5051 int printXML
= vshCommandOptBool(cmd
, "print-xml");
5053 if (!vshConnectionUsability(ctl
, ctl
->conn
))
5056 if (!buildPoolXML(cmd
, &name
, &xml
))
5060 vshPrint(ctl
, "%s", xml
);
5063 pool
= virStoragePoolCreateXML(ctl
->conn
, xml
, 0);
5067 vshPrint(ctl
, _("Pool %s created\n"), name
);
5068 virStoragePoolFree(pool
);
5070 vshError(ctl
, _("Failed to create pool %s"), name
);
5079 * "pool-define" command
5081 static const vshCmdInfo info_pool_define
[] = {
5082 {"help", N_("define (but don't start) a pool from an XML file")},
5083 {"desc", N_("Define a pool.")},
5087 static const vshCmdOptDef opts_pool_define
[] = {
5088 {"file", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("file containing an XML pool description")},
5093 cmdPoolDefine(vshControl
*ctl
, const vshCmd
*cmd
)
5095 virStoragePoolPtr pool
;
5101 if (!vshConnectionUsability(ctl
, ctl
->conn
))
5104 from
= vshCommandOptString(cmd
, "file", &found
);
5108 if (virFileReadAll(from
, VIRSH_MAX_XML_FILE
, &buffer
) < 0)
5111 pool
= virStoragePoolDefineXML(ctl
->conn
, buffer
, 0);
5115 vshPrint(ctl
, _("Pool %s defined from %s\n"),
5116 virStoragePoolGetName(pool
), from
);
5117 virStoragePoolFree(pool
);
5119 vshError(ctl
, _("Failed to define pool from %s"), from
);
5127 * "pool-define-as" command
5129 static const vshCmdInfo info_pool_define_as
[] = {
5130 {"help", N_("define a pool from a set of args")},
5131 {"desc", N_("Define a pool.")},
5136 cmdPoolDefineAs(vshControl
*ctl
, const vshCmd
*cmd
)
5138 virStoragePoolPtr pool
;
5140 int printXML
= vshCommandOptBool(cmd
, "print-xml");
5142 if (!vshConnectionUsability(ctl
, ctl
->conn
))
5145 if (!buildPoolXML(cmd
, &name
, &xml
))
5149 vshPrint(ctl
, "%s", xml
);
5152 pool
= virStoragePoolDefineXML(ctl
->conn
, xml
, 0);
5156 vshPrint(ctl
, _("Pool %s defined\n"), name
);
5157 virStoragePoolFree(pool
);
5159 vshError(ctl
, _("Failed to define pool %s"), name
);
5168 * "pool-build" command
5170 static const vshCmdInfo info_pool_build
[] = {
5171 {"help", N_("build a pool")},
5172 {"desc", N_("Build a given pool.")},
5176 static const vshCmdOptDef opts_pool_build
[] = {
5177 {"pool", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("pool name or uuid")},
5182 cmdPoolBuild(vshControl
*ctl
, const vshCmd
*cmd
)
5184 virStoragePoolPtr pool
;
5188 if (!vshConnectionUsability(ctl
, ctl
->conn
))
5191 if (!(pool
= vshCommandOptPool(ctl
, cmd
, "pool", &name
)))
5194 if (virStoragePoolBuild(pool
, 0) == 0) {
5195 vshPrint(ctl
, _("Pool %s built\n"), name
);
5197 vshError(ctl
, _("Failed to build pool %s"), name
);
5201 virStoragePoolFree(pool
);
5208 * "pool-destroy" command
5210 static const vshCmdInfo info_pool_destroy
[] = {
5211 {"help", N_("destroy a pool")},
5212 {"desc", N_("Destroy a given pool.")},
5216 static const vshCmdOptDef opts_pool_destroy
[] = {
5217 {"pool", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("pool name or uuid")},
5222 cmdPoolDestroy(vshControl
*ctl
, const vshCmd
*cmd
)
5224 virStoragePoolPtr pool
;
5228 if (!vshConnectionUsability(ctl
, ctl
->conn
))
5231 if (!(pool
= vshCommandOptPool(ctl
, cmd
, "pool", &name
)))
5234 if (virStoragePoolDestroy(pool
) == 0) {
5235 vshPrint(ctl
, _("Pool %s destroyed\n"), name
);
5237 vshError(ctl
, _("Failed to destroy pool %s"), name
);
5241 virStoragePoolFree(pool
);
5247 * "pool-delete" command
5249 static const vshCmdInfo info_pool_delete
[] = {
5250 {"help", N_("delete a pool")},
5251 {"desc", N_("Delete a given pool.")},
5255 static const vshCmdOptDef opts_pool_delete
[] = {
5256 {"pool", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("pool name or uuid")},
5261 cmdPoolDelete(vshControl
*ctl
, const vshCmd
*cmd
)
5263 virStoragePoolPtr pool
;
5267 if (!vshConnectionUsability(ctl
, ctl
->conn
))
5270 if (!(pool
= vshCommandOptPool(ctl
, cmd
, "pool", &name
)))
5273 if (virStoragePoolDelete(pool
, 0) == 0) {
5274 vshPrint(ctl
, _("Pool %s deleted\n"), name
);
5276 vshError(ctl
, _("Failed to delete pool %s"), name
);
5280 virStoragePoolFree(pool
);
5286 * "pool-refresh" command
5288 static const vshCmdInfo info_pool_refresh
[] = {
5289 {"help", N_("refresh a pool")},
5290 {"desc", N_("Refresh a given pool.")},
5294 static const vshCmdOptDef opts_pool_refresh
[] = {
5295 {"pool", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("pool name or uuid")},
5300 cmdPoolRefresh(vshControl
*ctl
, const vshCmd
*cmd
)
5302 virStoragePoolPtr pool
;
5306 if (!vshConnectionUsability(ctl
, ctl
->conn
))
5309 if (!(pool
= vshCommandOptPool(ctl
, cmd
, "pool", &name
)))
5312 if (virStoragePoolRefresh(pool
, 0) == 0) {
5313 vshPrint(ctl
, _("Pool %s refreshed\n"), name
);
5315 vshError(ctl
, _("Failed to refresh pool %s"), name
);
5318 virStoragePoolFree(pool
);
5325 * "pool-dumpxml" command
5327 static const vshCmdInfo info_pool_dumpxml
[] = {
5328 {"help", N_("pool information in XML")},
5329 {"desc", N_("Output the pool information as an XML dump to stdout.")},
5333 static const vshCmdOptDef opts_pool_dumpxml
[] = {
5334 {"pool", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("pool name or uuid")},
5339 cmdPoolDumpXML(vshControl
*ctl
, const vshCmd
*cmd
)
5341 virStoragePoolPtr pool
;
5345 if (!vshConnectionUsability(ctl
, ctl
->conn
))
5348 if (!(pool
= vshCommandOptPool(ctl
, cmd
, "pool", NULL
)))
5351 dump
= virStoragePoolGetXMLDesc(pool
, 0);
5353 vshPrint(ctl
, "%s", dump
);
5359 virStoragePoolFree(pool
);
5365 * "pool-list" command
5367 static const vshCmdInfo info_pool_list
[] = {
5368 {"help", N_("list pools")},
5369 {"desc", N_("Returns list of pools.")},
5373 static const vshCmdOptDef opts_pool_list
[] = {
5374 {"inactive", VSH_OT_BOOL
, 0, N_("list inactive pools")},
5375 {"all", VSH_OT_BOOL
, 0, N_("list inactive & active pools")},
5376 {"details", VSH_OT_BOOL
, 0, N_("display extended details for pools")},
5381 cmdPoolList(vshControl
*ctl
, const vshCmd
*cmd ATTRIBUTE_UNUSED
)
5383 virStoragePoolInfo info
;
5384 char **poolNames
= NULL
;
5385 int i
, functionReturn
, ret
;
5386 int numActivePools
= 0, numInactivePools
= 0, numAllPools
= 0;
5387 size_t stringLength
= 0, nameStrLength
= 0;
5388 size_t autostartStrLength
= 0, persistStrLength
= 0;
5389 size_t stateStrLength
= 0, capStrLength
= 0;
5390 size_t allocStrLength
= 0, availStrLength
= 0;
5391 struct poolInfoText
{
5399 struct poolInfoText
*poolInfoTexts
= NULL
;
5401 /* Determine the options passed by the user */
5402 int all
= vshCommandOptBool(cmd
, "all");
5403 int details
= vshCommandOptBool(cmd
, "details");
5404 int inactive
= vshCommandOptBool(cmd
, "inactive");
5405 int active
= !inactive
|| all
? 1 : 0;
5408 /* Check the connection to libvirtd daemon is still working */
5409 if (!vshConnectionUsability(ctl
, ctl
->conn
))
5412 /* Retrieve the number of active storage pools */
5414 numActivePools
= virConnectNumOfStoragePools(ctl
->conn
);
5415 if (numActivePools
< 0) {
5416 vshError(ctl
, "%s", _("Failed to list active pools"));
5421 /* Retrieve the number of inactive storage pools */
5423 numInactivePools
= virConnectNumOfDefinedStoragePools(ctl
->conn
);
5424 if (numInactivePools
< 0) {
5425 vshError(ctl
, "%s", _("Failed to list inactive pools"));
5430 /* Determine the total number of pools to list */
5431 numAllPools
= numActivePools
+ numInactivePools
;
5433 /* Allocate memory for arrays of storage pool names and info */
5434 poolNames
= vshCalloc(ctl
, numAllPools
, sizeof(*poolNames
));
5436 vshCalloc(ctl
, numAllPools
, sizeof(*poolInfoTexts
));
5438 /* Retrieve a list of active storage pool names */
5440 if ((virConnectListStoragePools(ctl
->conn
,
5441 poolNames
, numActivePools
)) < 0) {
5442 vshError(ctl
, "%s", _("Failed to list active pools"));
5443 VIR_FREE(poolInfoTexts
);
5444 VIR_FREE(poolNames
);
5449 /* Add the inactive storage pools to the end of the name list */
5451 if ((virConnectListDefinedStoragePools(ctl
->conn
,
5452 &poolNames
[numActivePools
],
5453 numInactivePools
)) < 0) {
5454 vshError(ctl
, "%s", _("Failed to list inactive pools"));
5455 VIR_FREE(poolInfoTexts
);
5456 VIR_FREE(poolNames
);
5461 /* Sort the storage pool names */
5462 qsort(poolNames
, numAllPools
, sizeof(*poolNames
), namesorter
);
5464 /* Collect the storage pool information for display */
5465 for (i
= 0; i
< numAllPools
; i
++) {
5466 int autostart
= 0, persistent
= 0;
5468 /* Retrieve a pool object, looking it up by name */
5469 virStoragePoolPtr pool
= virStoragePoolLookupByName(ctl
->conn
,
5472 VIR_FREE(poolNames
[i
]);
5476 /* Retrieve the autostart status of the pool */
5477 if (virStoragePoolGetAutostart(pool
, &autostart
) < 0)
5478 poolInfoTexts
[i
].autostart
= vshStrdup(ctl
, _("no autostart"));
5480 poolInfoTexts
[i
].autostart
= vshStrdup(ctl
, autostart
?
5481 _("yes") : _("no"));
5483 /* Retrieve the persistence status of the pool */
5485 persistent
= virStoragePoolIsPersistent(pool
);
5486 vshDebug(ctl
, 5, "Persistent flag value: %d\n", persistent
);
5488 poolInfoTexts
[i
].persistent
= vshStrdup(ctl
, _("unknown"));
5490 poolInfoTexts
[i
].persistent
= vshStrdup(ctl
, persistent
?
5491 _("yes") : _("no"));
5493 /* Keep the length of persistent string if longest so far */
5494 stringLength
= strlen(poolInfoTexts
[i
].persistent
);
5495 if (stringLength
> persistStrLength
)
5496 persistStrLength
= stringLength
;
5499 /* Collect further extended information about the pool */
5500 if (virStoragePoolGetInfo(pool
, &info
) != 0) {
5501 /* Something went wrong retrieving pool info, cope with it */
5502 vshError(ctl
, "%s", _("Could not retrieve pool information"));
5503 poolInfoTexts
[i
].state
= vshStrdup(ctl
, _("unknown"));
5505 poolInfoTexts
[i
].capacity
= vshStrdup(ctl
, _("unknown"));
5506 poolInfoTexts
[i
].allocation
= vshStrdup(ctl
, _("unknown"));
5507 poolInfoTexts
[i
].available
= vshStrdup(ctl
, _("unknown"));
5510 /* Decide which state string to display */
5512 /* --details option was specified, we're using detailed state
5514 switch (info
.state
) {
5515 case VIR_STORAGE_POOL_INACTIVE
:
5516 poolInfoTexts
[i
].state
= vshStrdup(ctl
, _("inactive"));
5518 case VIR_STORAGE_POOL_BUILDING
:
5519 poolInfoTexts
[i
].state
= vshStrdup(ctl
, _("building"));
5521 case VIR_STORAGE_POOL_RUNNING
:
5522 poolInfoTexts
[i
].state
= vshStrdup(ctl
, _("running"));
5524 case VIR_STORAGE_POOL_DEGRADED
:
5525 poolInfoTexts
[i
].state
= vshStrdup(ctl
, _("degraded"));
5527 case VIR_STORAGE_POOL_INACCESSIBLE
:
5528 poolInfoTexts
[i
].state
= vshStrdup(ctl
, _("inaccessible"));
5532 /* Create the pool size related strings */
5533 if (info
.state
== VIR_STORAGE_POOL_RUNNING
||
5534 info
.state
== VIR_STORAGE_POOL_DEGRADED
) {
5538 /* Create the capacity output string */
5539 val
= prettyCapacity(info
.capacity
, &unit
);
5540 ret
= virAsprintf(&poolInfoTexts
[i
].capacity
,
5541 "%.2lf %s", val
, unit
);
5543 /* An error occurred creating the string, return */
5544 goto asprintf_failure
;
5547 /* Create the allocation output string */
5548 val
= prettyCapacity(info
.allocation
, &unit
);
5549 ret
= virAsprintf(&poolInfoTexts
[i
].allocation
,
5550 "%.2lf %s", val
, unit
);
5552 /* An error occurred creating the string, return */
5553 goto asprintf_failure
;
5556 /* Create the available space output string */
5557 val
= prettyCapacity(info
.available
, &unit
);
5558 ret
= virAsprintf(&poolInfoTexts
[i
].available
,
5559 "%.2lf %s", val
, unit
);
5561 /* An error occurred creating the string, return */
5562 goto asprintf_failure
;
5565 /* Capacity related information isn't available */
5566 poolInfoTexts
[i
].capacity
= vshStrdup(ctl
, _("-"));
5567 poolInfoTexts
[i
].allocation
= vshStrdup(ctl
, _("-"));
5568 poolInfoTexts
[i
].available
= vshStrdup(ctl
, _("-"));
5571 /* Keep the length of capacity string if longest so far */
5572 stringLength
= strlen(poolInfoTexts
[i
].capacity
);
5573 if (stringLength
> capStrLength
)
5574 capStrLength
= stringLength
;
5576 /* Keep the length of allocation string if longest so far */
5577 stringLength
= strlen(poolInfoTexts
[i
].allocation
);
5578 if (stringLength
> allocStrLength
)
5579 allocStrLength
= stringLength
;
5581 /* Keep the length of available string if longest so far */
5582 stringLength
= strlen(poolInfoTexts
[i
].available
);
5583 if (stringLength
> availStrLength
)
5584 availStrLength
= stringLength
;
5586 /* --details option was not specified, only active/inactive
5587 * state strings are used */
5588 if (info
.state
== VIR_STORAGE_POOL_INACTIVE
)
5589 poolInfoTexts
[i
].state
= vshStrdup(ctl
, _("inactive"));
5591 poolInfoTexts
[i
].state
= vshStrdup(ctl
, _("active"));
5595 /* Keep the length of name string if longest so far */
5596 stringLength
= strlen(poolNames
[i
]);
5597 if (stringLength
> nameStrLength
)
5598 nameStrLength
= stringLength
;
5600 /* Keep the length of state string if longest so far */
5601 stringLength
= strlen(poolInfoTexts
[i
].state
);
5602 if (stringLength
> stateStrLength
)
5603 stateStrLength
= stringLength
;
5605 /* Keep the length of autostart string if longest so far */
5606 stringLength
= strlen(poolInfoTexts
[i
].autostart
);
5607 if (stringLength
> autostartStrLength
)
5608 autostartStrLength
= stringLength
;
5610 /* Free the pool object */
5611 virStoragePoolFree(pool
);
5614 /* If the --details option wasn't selected, we output the pool
5615 * info using the fixed string format from previous versions to
5616 * maintain backward compatibility.
5619 /* Output basic info then return if --details option not selected */
5621 /* Output old style header */
5622 vshPrintExtra(ctl
, "%-20s %-10s %-10s\n", _("Name"), _("State"),
5624 vshPrintExtra(ctl
, "-----------------------------------------\n");
5626 /* Output old style pool info */
5627 for (i
= 0; i
< numAllPools
; i
++) {
5628 vshPrint(ctl
, "%-20s %-10s %-10s\n",
5630 poolInfoTexts
[i
].state
,
5631 poolInfoTexts
[i
].autostart
);
5634 /* Cleanup and return */
5635 functionReturn
= TRUE
;
5639 /* We only get here if the --details option was selected. */
5641 /* Use the length of name header string if it's longest */
5642 stringLength
= strlen(_("Name"));
5643 if (stringLength
> nameStrLength
)
5644 nameStrLength
= stringLength
;
5646 /* Use the length of state header string if it's longest */
5647 stringLength
= strlen(_("State"));
5648 if (stringLength
> stateStrLength
)
5649 stateStrLength
= stringLength
;
5651 /* Use the length of autostart header string if it's longest */
5652 stringLength
= strlen(_("Autostart"));
5653 if (stringLength
> autostartStrLength
)
5654 autostartStrLength
= stringLength
;
5656 /* Use the length of persistent header string if it's longest */
5657 stringLength
= strlen(_("Persistent"));
5658 if (stringLength
> persistStrLength
)
5659 persistStrLength
= stringLength
;
5661 /* Use the length of capacity header string if it's longest */
5662 stringLength
= strlen(_("Capacity"));
5663 if (stringLength
> capStrLength
)
5664 capStrLength
= stringLength
;
5666 /* Use the length of allocation header string if it's longest */
5667 stringLength
= strlen(_("Allocation"));
5668 if (stringLength
> allocStrLength
)
5669 allocStrLength
= stringLength
;
5671 /* Use the length of available header string if it's longest */
5672 stringLength
= strlen(_("Available"));
5673 if (stringLength
> availStrLength
)
5674 availStrLength
= stringLength
;
5676 /* Display the string lengths for debugging. */
5677 vshDebug(ctl
, 5, "Longest name string = %lu chars\n",
5678 (unsigned long) nameStrLength
);
5679 vshDebug(ctl
, 5, "Longest state string = %lu chars\n",
5680 (unsigned long) stateStrLength
);
5681 vshDebug(ctl
, 5, "Longest autostart string = %lu chars\n",
5682 (unsigned long) autostartStrLength
);
5683 vshDebug(ctl
, 5, "Longest persistent string = %lu chars\n",
5684 (unsigned long) persistStrLength
);
5685 vshDebug(ctl
, 5, "Longest capacity string = %lu chars\n",
5686 (unsigned long) capStrLength
);
5687 vshDebug(ctl
, 5, "Longest allocation string = %lu chars\n",
5688 (unsigned long) allocStrLength
);
5689 vshDebug(ctl
, 5, "Longest available string = %lu chars\n",
5690 (unsigned long) availStrLength
);
5692 /* Create the output template. Each column is sized according to
5693 * the longest string.
5696 ret
= virAsprintf(&outputStr
,
5697 "%%-%lus %%-%lus %%-%lus %%-%lus %%%lus %%%lus %%%lus\n",
5698 (unsigned long) nameStrLength
,
5699 (unsigned long) stateStrLength
,
5700 (unsigned long) autostartStrLength
,
5701 (unsigned long) persistStrLength
,
5702 (unsigned long) capStrLength
,
5703 (unsigned long) allocStrLength
,
5704 (unsigned long) availStrLength
);
5706 /* An error occurred creating the string, return */
5707 goto asprintf_failure
;
5710 /* Display the header */
5711 vshPrint(ctl
, outputStr
, _("Name"), _("State"), _("Autostart"),
5712 _("Persistent"), _("Capacity"), _("Allocation"), _("Available"));
5713 for (i
= nameStrLength
+ stateStrLength
+ autostartStrLength
5714 + persistStrLength
+ capStrLength
5715 + allocStrLength
+ availStrLength
5717 vshPrintExtra(ctl
, "-");
5718 vshPrintExtra(ctl
, "\n");
5720 /* Display the pool info rows */
5721 for (i
= 0; i
< numAllPools
; i
++) {
5722 vshPrint(ctl
, outputStr
,
5724 poolInfoTexts
[i
].state
,
5725 poolInfoTexts
[i
].autostart
,
5726 poolInfoTexts
[i
].persistent
,
5727 poolInfoTexts
[i
].capacity
,
5728 poolInfoTexts
[i
].allocation
,
5729 poolInfoTexts
[i
].available
);
5732 /* Cleanup and return */
5733 functionReturn
= TRUE
;
5738 /* Display an appropriate error message then cleanup and return */
5741 /* Couldn't allocate memory */
5742 vshError(ctl
, "%s", _("Out of memory"));
5745 /* Some other error */
5746 vshError(ctl
, _("virAsprintf failed (errno %d)"), errno
);
5748 functionReturn
= FALSE
;
5752 /* Safely free the memory allocated in this function */
5753 for (i
= 0; i
< numAllPools
; i
++) {
5754 /* Cleanup the memory for one pool info structure */
5755 VIR_FREE(poolInfoTexts
[i
].state
);
5756 VIR_FREE(poolInfoTexts
[i
].autostart
);
5757 VIR_FREE(poolInfoTexts
[i
].persistent
);
5758 VIR_FREE(poolInfoTexts
[i
].capacity
);
5759 VIR_FREE(poolInfoTexts
[i
].allocation
);
5760 VIR_FREE(poolInfoTexts
[i
].available
);
5761 VIR_FREE(poolNames
[i
]);
5764 /* Cleanup the memory for the initial arrays*/
5765 VIR_FREE(poolInfoTexts
);
5766 VIR_FREE(poolNames
);
5768 /* Return the desired value */
5769 return functionReturn
;
5773 * "find-storage-pool-sources-as" command
5775 static const vshCmdInfo info_find_storage_pool_sources_as
[] = {
5776 {"help", N_("find potential storage pool sources")},
5777 {"desc", N_("Returns XML <sources> document.")},
5781 static const vshCmdOptDef opts_find_storage_pool_sources_as
[] = {
5782 {"type", VSH_OT_DATA
, VSH_OFLAG_REQ
,
5783 N_("type of storage pool sources to find")},
5784 {"host", VSH_OT_DATA
, VSH_OFLAG_NONE
, N_("optional host to query")},
5785 {"port", VSH_OT_DATA
, VSH_OFLAG_NONE
, N_("optional port to query")},
5790 cmdPoolDiscoverSourcesAs(vshControl
* ctl
, const vshCmd
* cmd ATTRIBUTE_UNUSED
)
5793 char *srcSpec
= NULL
;
5797 type
= vshCommandOptString(cmd
, "type", &found
);
5800 host
= vshCommandOptString(cmd
, "host", &found
);
5804 if (!vshConnectionUsability(ctl
, ctl
->conn
))
5808 size_t hostlen
= strlen(host
);
5809 char *port
= vshCommandOptString(cmd
, "port", &found
);
5812 port
= strrchr(host
, ':');
5815 hostlen
= port
- host
- 1;
5821 virAsprintf(&srcSpec
,
5822 "<source><host name='%.*s' port='%s'/></source>",
5823 (int)hostlen
, host
, port
) :
5824 virAsprintf(&srcSpec
,
5825 "<source><host name='%.*s'/></source>",
5826 (int)hostlen
, host
);
5830 vshError(ctl
, "%s", _("Out of memory"));
5833 vshError(ctl
, _("virAsprintf failed (errno %d)"), errno
);
5839 srcList
= virConnectFindStoragePoolSources(ctl
->conn
, type
, srcSpec
, 0);
5841 if (srcList
== NULL
) {
5842 vshError(ctl
, _("Failed to find any %s pool sources"), type
);
5845 vshPrint(ctl
, "%s", srcList
);
5853 * "find-storage-pool-sources" command
5855 static const vshCmdInfo info_find_storage_pool_sources
[] = {
5856 {"help", N_("discover potential storage pool sources")},
5857 {"desc", N_("Returns XML <sources> document.")},
5861 static const vshCmdOptDef opts_find_storage_pool_sources
[] = {
5862 {"type", VSH_OT_DATA
, VSH_OFLAG_REQ
,
5863 N_("type of storage pool sources to discover")},
5864 {"srcSpec", VSH_OT_DATA
, VSH_OFLAG_NONE
,
5865 N_("optional file of source xml to query for pools")},
5870 cmdPoolDiscoverSources(vshControl
* ctl
, const vshCmd
* cmd ATTRIBUTE_UNUSED
)
5872 char *type
, *srcSpecFile
, *srcList
;
5873 char *srcSpec
= NULL
;
5876 type
= vshCommandOptString(cmd
, "type", &found
);
5879 srcSpecFile
= vshCommandOptString(cmd
, "srcSpec", &found
);
5883 if (!vshConnectionUsability(ctl
, ctl
->conn
))
5886 if (srcSpecFile
&& virFileReadAll(srcSpecFile
, VIRSH_MAX_XML_FILE
, &srcSpec
) < 0)
5889 srcList
= virConnectFindStoragePoolSources(ctl
->conn
, type
, srcSpec
, 0);
5891 if (srcList
== NULL
) {
5892 vshError(ctl
, _("Failed to find any %s pool sources"), type
);
5895 vshPrint(ctl
, "%s", srcList
);
5903 * "pool-info" command
5905 static const vshCmdInfo info_pool_info
[] = {
5906 {"help", N_("storage pool information")},
5907 {"desc", N_("Returns basic information about the storage pool.")},
5911 static const vshCmdOptDef opts_pool_info
[] = {
5912 {"pool", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("pool name or uuid")},
5917 cmdPoolInfo(vshControl
*ctl
, const vshCmd
*cmd
)
5919 virStoragePoolInfo info
;
5920 virStoragePoolPtr pool
;
5924 char uuid
[VIR_UUID_STRING_BUFLEN
];
5926 if (!vshConnectionUsability(ctl
, ctl
->conn
))
5929 if (!(pool
= vshCommandOptPool(ctl
, cmd
, "pool", NULL
)))
5932 vshPrint(ctl
, "%-15s %s\n", _("Name:"), virStoragePoolGetName(pool
));
5934 if (virStoragePoolGetUUIDString(pool
, &uuid
[0])==0)
5935 vshPrint(ctl
, "%-15s %s\n", _("UUID:"), uuid
);
5937 if (virStoragePoolGetInfo(pool
, &info
) == 0) {
5940 switch (info
.state
) {
5941 case VIR_STORAGE_POOL_INACTIVE
:
5942 vshPrint(ctl
, "%-15s %s\n", _("State:"),
5945 case VIR_STORAGE_POOL_BUILDING
:
5946 vshPrint(ctl
, "%-15s %s\n", _("State:"),
5949 case VIR_STORAGE_POOL_RUNNING
:
5950 vshPrint(ctl
, "%-15s %s\n", _("State:"),
5953 case VIR_STORAGE_POOL_DEGRADED
:
5954 vshPrint(ctl
, "%-15s %s\n", _("State:"),
5957 case VIR_STORAGE_POOL_INACCESSIBLE
:
5958 vshPrint(ctl
, "%-15s %s\n", _("State:"),
5963 /* Check and display whether the pool is persistent or not */
5964 persistent
= virStoragePoolIsPersistent(pool
);
5965 vshDebug(ctl
, 5, "Pool persistent flag value: %d\n", persistent
);
5967 vshPrint(ctl
, "%-15s %s\n", _("Persistent:"), _("unknown"));
5969 vshPrint(ctl
, "%-15s %s\n", _("Persistent:"), persistent
? _("yes") : _("no"));
5971 /* Check and display whether the pool is autostarted or not */
5972 virStoragePoolGetAutostart(pool
, &autostart
);
5973 vshDebug(ctl
, 5, "Pool autostart flag value: %d\n", autostart
);
5975 vshPrint(ctl
, "%-15s %s\n", _("Autostart:"), _("no autostart"));
5977 vshPrint(ctl
, "%-15s %s\n", _("Autostart:"), autostart
? _("yes") : _("no"));
5979 if (info
.state
== VIR_STORAGE_POOL_RUNNING
||
5980 info
.state
== VIR_STORAGE_POOL_DEGRADED
) {
5981 val
= prettyCapacity(info
.capacity
, &unit
);
5982 vshPrint(ctl
, "%-15s %2.2lf %s\n", _("Capacity:"), val
, unit
);
5984 val
= prettyCapacity(info
.allocation
, &unit
);
5985 vshPrint(ctl
, "%-15s %2.2lf %s\n", _("Allocation:"), val
, unit
);
5987 val
= prettyCapacity(info
.available
, &unit
);
5988 vshPrint(ctl
, "%-15s %2.2lf %s\n", _("Available:"), val
, unit
);
5994 virStoragePoolFree(pool
);
6000 * "pool-name" command
6002 static const vshCmdInfo info_pool_name
[] = {
6003 {"help", N_("convert a pool UUID to pool name")},
6008 static const vshCmdOptDef opts_pool_name
[] = {
6009 {"pool", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("pool uuid")},
6014 cmdPoolName(vshControl
*ctl
, const vshCmd
*cmd
)
6016 virStoragePoolPtr pool
;
6018 if (!vshConnectionUsability(ctl
, ctl
->conn
))
6020 if (!(pool
= vshCommandOptPoolBy(ctl
, cmd
, "pool", NULL
,
6024 vshPrint(ctl
, "%s\n", virStoragePoolGetName(pool
));
6025 virStoragePoolFree(pool
);
6031 * "pool-start" command
6033 static const vshCmdInfo info_pool_start
[] = {
6034 {"help", N_("start a (previously defined) inactive pool")},
6035 {"desc", N_("Start a pool.")},
6039 static const vshCmdOptDef opts_pool_start
[] = {
6040 {"pool", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("name of the inactive pool")},
6045 cmdPoolStart(vshControl
*ctl
, const vshCmd
*cmd
)
6047 virStoragePoolPtr pool
;
6050 if (!vshConnectionUsability(ctl
, ctl
->conn
))
6053 if (!(pool
= vshCommandOptPoolBy(ctl
, cmd
, "pool", NULL
, VSH_BYNAME
)))
6056 if (virStoragePoolCreate(pool
, 0) == 0) {
6057 vshPrint(ctl
, _("Pool %s started\n"),
6058 virStoragePoolGetName(pool
));
6060 vshError(ctl
, _("Failed to start pool %s"), virStoragePoolGetName(pool
));
6064 virStoragePoolFree(pool
);
6070 * "vol-create-as" command
6072 static const vshCmdInfo info_vol_create_as
[] = {
6073 {"help", N_("create a volume from a set of args")},
6074 {"desc", N_("Create a vol.")},
6078 static const vshCmdOptDef opts_vol_create_as
[] = {
6079 {"pool", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("pool name")},
6080 {"name", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("name of the volume")},
6081 {"capacity", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("size of the vol with optional k,M,G,T suffix")},
6082 {"allocation", VSH_OT_STRING
, 0, N_("initial allocation size with optional k,M,G,T suffix")},
6083 {"format", VSH_OT_STRING
, 0, N_("file format type raw,bochs,qcow,qcow2,vmdk")},
6084 {"backing-vol", VSH_OT_STRING
, 0, N_("the backing volume if taking a snapshot")},
6085 {"backing-vol-format", VSH_OT_STRING
, 0, N_("format of backing volume if taking a snapshot")},
6089 static int cmdVolSize(const char *data
, unsigned long long *val
)
6092 if (virStrToLong_ull(data
, &end
, 10, val
) < 0)
6096 /* Deliberate fallthrough cases here :-) */
6118 cmdVolCreateAs(vshControl
*ctl
, const vshCmd
*cmd
)
6120 virStoragePoolPtr pool
;
6121 virStorageVolPtr vol
;
6124 char *name
, *capacityStr
, *allocationStr
, *format
;
6125 char *snapshotStrVol
, *snapshotStrFormat
;
6126 unsigned long long capacity
, allocation
= 0;
6127 virBuffer buf
= VIR_BUFFER_INITIALIZER
;
6129 if (!vshConnectionUsability(ctl
, ctl
->conn
))
6132 if (!(pool
= vshCommandOptPoolBy(ctl
, cmd
, "pool", NULL
,
6136 name
= vshCommandOptString(cmd
, "name", &found
);
6140 capacityStr
= vshCommandOptString(cmd
, "capacity", &found
);
6143 if (cmdVolSize(capacityStr
, &capacity
) < 0)
6144 vshError(ctl
, _("Malformed size %s"), capacityStr
);
6146 allocationStr
= vshCommandOptString(cmd
, "allocation", &found
);
6147 if (allocationStr
&&
6148 cmdVolSize(allocationStr
, &allocation
) < 0)
6149 vshError(ctl
, _("Malformed size %s"), allocationStr
);
6151 format
= vshCommandOptString(cmd
, "format", &found
);
6152 snapshotStrVol
= vshCommandOptString(cmd
, "backing-vol", &found
);
6153 snapshotStrFormat
= vshCommandOptString(cmd
, "backing-vol-format", &found
);
6155 virBufferAddLit(&buf
, "<volume>\n");
6156 virBufferVSprintf(&buf
, " <name>%s</name>\n", name
);
6157 virBufferVSprintf(&buf
, " <capacity>%llu</capacity>\n", capacity
);
6159 virBufferVSprintf(&buf
, " <allocation>%llu</allocation>\n", allocation
);
6162 virBufferAddLit(&buf
, " <target>\n");
6163 virBufferVSprintf(&buf
, " <format type='%s'/>\n",format
);
6164 virBufferAddLit(&buf
, " </target>\n");
6167 /* Convert the snapshot parameters into backingStore XML */
6168 if (snapshotStrVol
) {
6169 /* Lookup snapshot backing volume. Try the backing-vol
6170 * parameter as a name */
6171 vshDebug(ctl
, 5, "%s: Look up backing store volume '%s' as name\n",
6172 cmd
->def
->name
, snapshotStrVol
);
6173 virStorageVolPtr snapVol
= virStorageVolLookupByName(pool
, snapshotStrVol
);
6175 vshDebug(ctl
, 5, "%s: Backing store volume found using '%s' as name\n",
6176 cmd
->def
->name
, snapshotStrVol
);
6178 if (snapVol
== NULL
) {
6179 /* Snapshot backing volume not found by name. Try the
6180 * backing-vol parameter as a key */
6181 vshDebug(ctl
, 5, "%s: Look up backing store volume '%s' as key\n",
6182 cmd
->def
->name
, snapshotStrVol
);
6183 snapVol
= virStorageVolLookupByKey(ctl
->conn
, snapshotStrVol
);
6185 vshDebug(ctl
, 5, "%s: Backing store volume found using '%s' as key\n",
6186 cmd
->def
->name
, snapshotStrVol
);
6188 if (snapVol
== NULL
) {
6189 /* Snapshot backing volume not found by key. Try the
6190 * backing-vol parameter as a path */
6191 vshDebug(ctl
, 5, "%s: Look up backing store volume '%s' as path\n",
6192 cmd
->def
->name
, snapshotStrVol
);
6193 snapVol
= virStorageVolLookupByPath(ctl
->conn
, snapshotStrVol
);
6195 vshDebug(ctl
, 5, "%s: Backing store volume found using '%s' as path\n",
6196 cmd
->def
->name
, snapshotStrVol
);
6198 if (snapVol
== NULL
) {
6199 vshError(ctl
, _("failed to get vol '%s'"), snapshotStrVol
);
6203 char *snapshotStrVolPath
;
6204 if ((snapshotStrVolPath
= virStorageVolGetPath(snapVol
)) == NULL
) {
6205 virStorageVolFree(snapVol
);
6209 /* Create XML for the backing store */
6210 virBufferAddLit(&buf
, " <backingStore>\n");
6211 virBufferVSprintf(&buf
, " <path>%s</path>\n",snapshotStrVolPath
);
6212 if (snapshotStrFormat
)
6213 virBufferVSprintf(&buf
, " <format type='%s'/>\n",snapshotStrFormat
);
6214 virBufferAddLit(&buf
, " </backingStore>\n");
6216 /* Cleanup snapshot allocations */
6217 VIR_FREE(snapshotStrVolPath
);
6218 virStorageVolFree(snapVol
);
6221 virBufferAddLit(&buf
, "</volume>\n");
6223 if (virBufferError(&buf
)) {
6224 vshPrint(ctl
, "%s", _("Failed to allocate XML buffer"));
6227 xml
= virBufferContentAndReset(&buf
);
6228 vol
= virStorageVolCreateXML(pool
, xml
, 0);
6230 virStoragePoolFree(pool
);
6233 vshPrint(ctl
, _("Vol %s created\n"), name
);
6234 virStorageVolFree(vol
);
6237 vshError(ctl
, _("Failed to create vol %s"), name
);
6242 virBufferFreeAndReset(&buf
);
6243 virStoragePoolFree(pool
);
6249 * "pool-undefine" command
6251 static const vshCmdInfo info_pool_undefine
[] = {
6252 {"help", N_("undefine an inactive pool")},
6253 {"desc", N_("Undefine the configuration for an inactive pool.")},
6257 static const vshCmdOptDef opts_pool_undefine
[] = {
6258 {"pool", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("pool name or uuid")},
6263 cmdPoolUndefine(vshControl
*ctl
, const vshCmd
*cmd
)
6265 virStoragePoolPtr pool
;
6269 if (!vshConnectionUsability(ctl
, ctl
->conn
))
6272 if (!(pool
= vshCommandOptPool(ctl
, cmd
, "pool", &name
)))
6275 if (virStoragePoolUndefine(pool
) == 0) {
6276 vshPrint(ctl
, _("Pool %s has been undefined\n"), name
);
6278 vshError(ctl
, _("Failed to undefine pool %s"), name
);
6282 virStoragePoolFree(pool
);
6288 * "pool-uuid" command
6290 static const vshCmdInfo info_pool_uuid
[] = {
6291 {"help", N_("convert a pool name to pool UUID")},
6296 static const vshCmdOptDef opts_pool_uuid
[] = {
6297 {"pool", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("pool name")},
6302 cmdPoolUuid(vshControl
*ctl
, const vshCmd
*cmd
)
6304 virStoragePoolPtr pool
;
6305 char uuid
[VIR_UUID_STRING_BUFLEN
];
6307 if (!vshConnectionUsability(ctl
, ctl
->conn
))
6310 if (!(pool
= vshCommandOptPoolBy(ctl
, cmd
, "pool", NULL
,
6314 if (virStoragePoolGetUUIDString(pool
, uuid
) != -1)
6315 vshPrint(ctl
, "%s\n", uuid
);
6317 vshError(ctl
, "%s", _("failed to get pool UUID"));
6319 virStoragePoolFree(pool
);
6325 * "vol-create" command
6327 static const vshCmdInfo info_vol_create
[] = {
6328 {"help", N_("create a vol from an XML file")},
6329 {"desc", N_("Create a vol.")},
6333 static const vshCmdOptDef opts_vol_create
[] = {
6334 {"pool", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("pool name")},
6335 {"file", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("file containing an XML vol description")},
6340 cmdVolCreate(vshControl
*ctl
, const vshCmd
*cmd
)
6342 virStoragePoolPtr pool
;
6343 virStorageVolPtr vol
;
6349 if (!vshConnectionUsability(ctl
, ctl
->conn
))
6352 if (!(pool
= vshCommandOptPoolBy(ctl
, cmd
, "pool", NULL
,
6356 from
= vshCommandOptString(cmd
, "file", &found
);
6358 virStoragePoolFree(pool
);
6362 if (virFileReadAll(from
, VIRSH_MAX_XML_FILE
, &buffer
) < 0) {
6363 virshReportError(ctl
);
6364 virStoragePoolFree(pool
);
6368 vol
= virStorageVolCreateXML(pool
, buffer
, 0);
6370 virStoragePoolFree(pool
);
6373 vshPrint(ctl
, _("Vol %s created from %s\n"),
6374 virStorageVolGetName(vol
), from
);
6375 virStorageVolFree(vol
);
6377 vshError(ctl
, _("Failed to create vol from %s"), from
);
6384 * "vol-create-from" command
6386 static const vshCmdInfo info_vol_create_from
[] = {
6387 {"help", N_("create a vol, using another volume as input")},
6388 {"desc", N_("Create a vol from an existing volume.")},
6392 static const vshCmdOptDef opts_vol_create_from
[] = {
6393 {"pool", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("pool name")},
6394 {"file", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("file containing an XML vol description")},
6395 {"inputpool", VSH_OT_STRING
, 0, N_("pool name or uuid of the input volume's pool")},
6396 {"vol", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("input vol name or key")},
6401 cmdVolCreateFrom(vshControl
*ctl
, const vshCmd
*cmd
)
6403 virStoragePoolPtr pool
= NULL
;
6404 virStorageVolPtr newvol
= NULL
, inputvol
= NULL
;
6408 char *buffer
= NULL
;
6410 if (!vshConnectionUsability(ctl
, ctl
->conn
))
6413 if (!(pool
= vshCommandOptPoolBy(ctl
, cmd
, "pool", NULL
, VSH_BYNAME
)))
6416 from
= vshCommandOptString(cmd
, "file", &found
);
6421 if (!(inputvol
= vshCommandOptVol(ctl
, cmd
, "vol", "inputpool", NULL
)))
6424 if (virFileReadAll(from
, VIRSH_MAX_XML_FILE
, &buffer
) < 0) {
6425 virshReportError(ctl
);
6429 newvol
= virStorageVolCreateXMLFrom(pool
, buffer
, inputvol
, 0);
6431 if (newvol
!= NULL
) {
6432 vshPrint(ctl
, _("Vol %s created from input vol %s\n"),
6433 virStorageVolGetName(newvol
), virStorageVolGetName(inputvol
));
6435 vshError(ctl
, _("Failed to create vol from %s"), from
);
6443 virStoragePoolFree(pool
);
6445 virStorageVolFree(inputvol
);
6447 virStorageVolFree(newvol
);
6452 makeCloneXML(char *origxml
, char *newname
) {
6454 xmlDocPtr doc
= NULL
;
6455 xmlXPathContextPtr ctxt
= NULL
;
6456 xmlXPathObjectPtr obj
= NULL
;
6457 xmlChar
*newxml
= NULL
;
6460 doc
= xmlReadDoc((const xmlChar
*) origxml
, "domain.xml", NULL
,
6461 XML_PARSE_NOENT
| XML_PARSE_NONET
| XML_PARSE_NOWARNING
);
6464 ctxt
= xmlXPathNewContext(doc
);
6468 obj
= xmlXPathEval(BAD_CAST
"/volume/name", ctxt
);
6469 if ((obj
== NULL
) || (obj
->nodesetval
== NULL
) ||
6470 (obj
->nodesetval
->nodeTab
== NULL
))
6473 xmlNodeSetContent(obj
->nodesetval
->nodeTab
[0], (const xmlChar
*)newname
);
6474 xmlDocDumpMemory(doc
, &newxml
, &size
);
6477 xmlXPathFreeObject(obj
);
6478 xmlXPathFreeContext(ctxt
);
6484 * "vol-clone" command
6486 static const vshCmdInfo info_vol_clone
[] = {
6487 {"help", N_("clone a volume.")},
6488 {"desc", N_("Clone an existing volume.")},
6492 static const vshCmdOptDef opts_vol_clone
[] = {
6493 {"pool", VSH_OT_STRING
, 0, N_("pool name or uuid")},
6494 {"vol", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("orig vol name or key")},
6495 {"newname", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("clone name")},
6500 cmdVolClone(vshControl
*ctl
, const vshCmd
*cmd
)
6502 virStoragePoolPtr origpool
= NULL
;
6503 virStorageVolPtr origvol
= NULL
, newvol
= NULL
;
6504 char *name
, *origxml
= NULL
;
6505 xmlChar
*newxml
= NULL
;
6509 if (!vshConnectionUsability(ctl
, ctl
->conn
))
6512 if (!(origvol
= vshCommandOptVol(ctl
, cmd
, "vol", "pool", NULL
)))
6515 origpool
= virStoragePoolLookupByVolume(origvol
);
6517 vshError(ctl
, "%s", _("failed to get parent pool"));
6521 name
= vshCommandOptString(cmd
, "newname", &found
);
6525 origxml
= virStorageVolGetXMLDesc(origvol
, 0);
6529 newxml
= makeCloneXML(origxml
, name
);
6531 vshPrint(ctl
, "%s", _("Failed to allocate XML buffer"));
6535 newvol
= virStorageVolCreateXMLFrom(origpool
, (char *) newxml
, origvol
, 0);
6537 if (newvol
!= NULL
) {
6538 vshPrint(ctl
, _("Vol %s cloned from %s\n"),
6539 virStorageVolGetName(newvol
), virStorageVolGetName(origvol
));
6541 vshError(ctl
, _("Failed to clone vol from %s"),
6542 virStorageVolGetName(origvol
));
6552 virStorageVolFree(origvol
);
6554 virStorageVolFree(newvol
);
6556 virStoragePoolFree(origpool
);
6561 * "vol-delete" command
6563 static const vshCmdInfo info_vol_delete
[] = {
6564 {"help", N_("delete a vol")},
6565 {"desc", N_("Delete a given vol.")},
6569 static const vshCmdOptDef opts_vol_delete
[] = {
6570 {"pool", VSH_OT_STRING
, 0, N_("pool name or uuid")},
6571 {"vol", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("vol name, key or path")},
6576 cmdVolDelete(vshControl
*ctl
, const vshCmd
*cmd
)
6578 virStorageVolPtr vol
;
6582 if (!vshConnectionUsability(ctl
, ctl
->conn
))
6585 if (!(vol
= vshCommandOptVol(ctl
, cmd
, "vol", "pool", &name
))) {
6589 if (virStorageVolDelete(vol
, 0) == 0) {
6590 vshPrint(ctl
, _("Vol %s deleted\n"), name
);
6592 vshError(ctl
, _("Failed to delete vol %s"), name
);
6596 virStorageVolFree(vol
);
6602 * "vol-wipe" command
6604 static const vshCmdInfo info_vol_wipe
[] = {
6605 {"help", N_("wipe a vol")},
6606 {"desc", N_("Ensure data previously on a volume is not accessible to future reads")},
6610 static const vshCmdOptDef opts_vol_wipe
[] = {
6611 {"pool", VSH_OT_STRING
, 0, N_("pool name or uuid")},
6612 {"vol", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("vol name, key or path")},
6617 cmdVolWipe(vshControl
*ctl
, const vshCmd
*cmd
)
6619 virStorageVolPtr vol
;
6623 if (!vshConnectionUsability(ctl
, ctl
->conn
))
6626 if (!(vol
= vshCommandOptVol(ctl
, cmd
, "vol", "pool", &name
))) {
6630 if (virStorageVolWipe(vol
, 0) == 0) {
6631 vshPrint(ctl
, _("Vol %s wiped\n"), name
);
6633 vshError(ctl
, _("Failed to wipe vol %s"), name
);
6637 virStorageVolFree(vol
);
6643 * "vol-info" command
6645 static const vshCmdInfo info_vol_info
[] = {
6646 {"help", N_("storage vol information")},
6647 {"desc", N_("Returns basic information about the storage vol.")},
6651 static const vshCmdOptDef opts_vol_info
[] = {
6652 {"pool", VSH_OT_STRING
, 0, N_("pool name or uuid")},
6653 {"vol", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("vol name, key or path")},
6658 cmdVolInfo(vshControl
*ctl
, const vshCmd
*cmd
)
6660 virStorageVolInfo info
;
6661 virStorageVolPtr vol
;
6664 if (!vshConnectionUsability(ctl
, ctl
->conn
))
6667 if (!(vol
= vshCommandOptVol(ctl
, cmd
, "vol", "pool", NULL
)))
6670 vshPrint(ctl
, "%-15s %s\n", _("Name:"), virStorageVolGetName(vol
));
6672 if (virStorageVolGetInfo(vol
, &info
) == 0) {
6675 vshPrint(ctl
, "%-15s %s\n", _("Type:"),
6676 info
.type
== VIR_STORAGE_VOL_FILE
?
6677 _("file") : _("block"));
6679 val
= prettyCapacity(info
.capacity
, &unit
);
6680 vshPrint(ctl
, "%-15s %2.2lf %s\n", _("Capacity:"), val
, unit
);
6682 val
= prettyCapacity(info
.allocation
, &unit
);
6683 vshPrint(ctl
, "%-15s %2.2lf %s\n", _("Allocation:"), val
, unit
);
6688 virStorageVolFree(vol
);
6694 * "vol-dumpxml" command
6696 static const vshCmdInfo info_vol_dumpxml
[] = {
6697 {"help", N_("vol information in XML")},
6698 {"desc", N_("Output the vol information as an XML dump to stdout.")},
6702 static const vshCmdOptDef opts_vol_dumpxml
[] = {
6703 {"pool", VSH_OT_STRING
, 0, N_("pool name or uuid")},
6704 {"vol", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("vol name, key or path")},
6709 cmdVolDumpXML(vshControl
*ctl
, const vshCmd
*cmd
)
6711 virStorageVolPtr vol
;
6715 if (!vshConnectionUsability(ctl
, ctl
->conn
))
6718 if (!(vol
= vshCommandOptVol(ctl
, cmd
, "vol", "pool", NULL
)))
6721 dump
= virStorageVolGetXMLDesc(vol
, 0);
6723 vshPrint(ctl
, "%s", dump
);
6729 virStorageVolFree(vol
);
6735 * "vol-list" command
6737 static const vshCmdInfo info_vol_list
[] = {
6738 {"help", N_("list vols")},
6739 {"desc", N_("Returns list of vols by pool.")},
6743 static const vshCmdOptDef opts_vol_list
[] = {
6744 {"pool", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("pool name or uuid")},
6745 {"details", VSH_OT_BOOL
, 0, N_("display extended details for volumes")},
6750 cmdVolList(vshControl
*ctl
, const vshCmd
*cmd ATTRIBUTE_UNUSED
)
6752 virStorageVolInfo volumeInfo
;
6753 virStoragePoolPtr pool
;
6754 char **activeNames
= NULL
;
6755 char *outputStr
= NULL
;
6758 int details
= vshCommandOptBool(cmd
, "details");
6759 int numVolumes
= 0, i
;
6760 int ret
, functionReturn
;
6761 int stringLength
= 0;
6762 size_t allocStrLength
= 0, capStrLength
= 0;
6763 size_t nameStrLength
= 0, pathStrLength
= 0;
6764 size_t typeStrLength
= 0;
6765 struct volInfoText
{
6771 struct volInfoText
*volInfoTexts
= NULL
;
6773 /* Check the connection to libvirtd daemon is still working */
6774 if (!vshConnectionUsability(ctl
, ctl
->conn
))
6777 /* Look up the pool information given to us by the user */
6778 if (!(pool
= vshCommandOptPool(ctl
, cmd
, "pool", NULL
)))
6781 /* Determine the number of volumes in the pool */
6782 numVolumes
= virStoragePoolNumOfVolumes(pool
);
6784 /* Retrieve the list of volume names in the pool */
6785 if (numVolumes
> 0) {
6786 activeNames
= vshCalloc(ctl
, numVolumes
, sizeof(*activeNames
));
6787 if ((numVolumes
= virStoragePoolListVolumes(pool
, activeNames
,
6789 vshError(ctl
, "%s", _("Failed to list active vols"));
6790 VIR_FREE(activeNames
);
6791 virStoragePoolFree(pool
);
6795 /* Sort the volume names */
6796 qsort(&activeNames
[0], numVolumes
, sizeof(*activeNames
), namesorter
);
6798 /* Set aside memory for volume information pointers */
6799 volInfoTexts
= vshCalloc(ctl
, numVolumes
, sizeof(*volInfoTexts
));
6802 /* Collect the rest of the volume information for display */
6803 for (i
= 0; i
< numVolumes
; i
++) {
6804 /* Retrieve volume info */
6805 virStorageVolPtr vol
= virStorageVolLookupByName(pool
,
6808 /* Retrieve the volume path */
6809 if ((volInfoTexts
[i
].path
= virStorageVolGetPath(vol
)) == NULL
) {
6810 /* Something went wrong retrieving a volume path, cope with it */
6811 volInfoTexts
[i
].path
= vshStrdup(ctl
, _("unknown"));
6814 /* If requested, retrieve volume type and sizing information */
6816 if (virStorageVolGetInfo(vol
, &volumeInfo
) != 0) {
6817 /* Something went wrong retrieving volume info, cope with it */
6818 volInfoTexts
[i
].allocation
= vshStrdup(ctl
, _("unknown"));
6819 volInfoTexts
[i
].capacity
= vshStrdup(ctl
, _("unknown"));
6820 volInfoTexts
[i
].type
= vshStrdup(ctl
, _("unknown"));
6822 /* Convert the returned volume info into output strings */
6825 if (volumeInfo
.type
== VIR_STORAGE_VOL_FILE
)
6826 volInfoTexts
[i
].type
= vshStrdup(ctl
, _("file"));
6828 volInfoTexts
[i
].type
= vshStrdup(ctl
, _("block"));
6830 /* Create the capacity output string */
6831 val
= prettyCapacity(volumeInfo
.capacity
, &unit
);
6832 ret
= virAsprintf(&volInfoTexts
[i
].capacity
,
6833 "%.2lf %s", val
, unit
);
6835 /* An error occurred creating the string, return */
6836 goto asprintf_failure
;
6839 /* Create the allocation output string */
6840 val
= prettyCapacity(volumeInfo
.allocation
, &unit
);
6841 ret
= virAsprintf(&volInfoTexts
[i
].allocation
,
6842 "%.2lf %s", val
, unit
);
6844 /* An error occurred creating the string, return */
6845 goto asprintf_failure
;
6849 /* Remember the largest length for each output string.
6850 * This lets us displaying header and volume information rows
6851 * using a single, properly sized, printf style output string.
6854 /* Keep the length of name string if longest so far */
6855 stringLength
= strlen(activeNames
[i
]);
6856 if (stringLength
> nameStrLength
)
6857 nameStrLength
= stringLength
;
6859 /* Keep the length of path string if longest so far */
6860 stringLength
= strlen(volInfoTexts
[i
].path
);
6861 if (stringLength
> pathStrLength
)
6862 pathStrLength
= stringLength
;
6864 /* Keep the length of type string if longest so far */
6865 stringLength
= strlen(volInfoTexts
[i
].type
);
6866 if (stringLength
> typeStrLength
)
6867 typeStrLength
= stringLength
;
6869 /* Keep the length of capacity string if longest so far */
6870 stringLength
= strlen(volInfoTexts
[i
].capacity
);
6871 if (stringLength
> capStrLength
)
6872 capStrLength
= stringLength
;
6874 /* Keep the length of allocation string if longest so far */
6875 stringLength
= strlen(volInfoTexts
[i
].allocation
);
6876 if (stringLength
> allocStrLength
)
6877 allocStrLength
= stringLength
;
6880 /* Cleanup memory allocation */
6881 virStorageVolFree(vol
);
6884 /* If the --details option wasn't selected, we output the volume
6885 * info using the fixed string format from previous versions to
6886 * maintain backward compatibility.
6889 /* Output basic info then return if --details option not selected */
6891 /* The old output format */
6892 vshPrintExtra(ctl
, "%-20s %-40s\n", _("Name"), _("Path"));
6893 vshPrintExtra(ctl
, "-----------------------------------------\n");
6894 for (i
= 0; i
< numVolumes
; i
++) {
6895 vshPrint(ctl
, "%-20s %-40s\n", activeNames
[i
],
6896 volInfoTexts
[i
].path
);
6899 /* Cleanup and return */
6900 functionReturn
= TRUE
;
6904 /* We only get here if the --details option was selected. */
6906 /* Use the length of name header string if it's longest */
6907 stringLength
= strlen(_("Name"));
6908 if (stringLength
> nameStrLength
)
6909 nameStrLength
= stringLength
;
6911 /* Use the length of path header string if it's longest */
6912 stringLength
= strlen(_("Path"));
6913 if (stringLength
> pathStrLength
)
6914 pathStrLength
= stringLength
;
6916 /* Use the length of type header string if it's longest */
6917 stringLength
= strlen(_("Type"));
6918 if (stringLength
> typeStrLength
)
6919 typeStrLength
= stringLength
;
6921 /* Use the length of capacity header string if it's longest */
6922 stringLength
= strlen(_("Capacity"));
6923 if (stringLength
> capStrLength
)
6924 capStrLength
= stringLength
;
6926 /* Use the length of allocation header string if it's longest */
6927 stringLength
= strlen(_("Allocation"));
6928 if (stringLength
> allocStrLength
)
6929 allocStrLength
= stringLength
;
6931 /* Display the string lengths for debugging */
6932 vshDebug(ctl
, 5, "Longest name string = %zu chars\n", nameStrLength
);
6933 vshDebug(ctl
, 5, "Longest path string = %zu chars\n", pathStrLength
);
6934 vshDebug(ctl
, 5, "Longest type string = %zu chars\n", typeStrLength
);
6935 vshDebug(ctl
, 5, "Longest capacity string = %zu chars\n", capStrLength
);
6936 vshDebug(ctl
, 5, "Longest allocation string = %zu chars\n", allocStrLength
);
6938 /* Create the output template */
6939 ret
= virAsprintf(&outputStr
,
6940 "%%-%lus %%-%lus %%-%lus %%%lus %%%lus\n",
6941 (unsigned long) nameStrLength
,
6942 (unsigned long) pathStrLength
,
6943 (unsigned long) typeStrLength
,
6944 (unsigned long) capStrLength
,
6945 (unsigned long) allocStrLength
);
6947 /* An error occurred creating the string, return */
6948 goto asprintf_failure
;
6951 /* Display the header */
6952 vshPrint(ctl
, outputStr
, _("Name"), _("Path"), _("Type"),
6953 ("Capacity"), _("Allocation"));
6954 for (i
= nameStrLength
+ pathStrLength
+ typeStrLength
6955 + capStrLength
+ allocStrLength
6957 vshPrintExtra(ctl
, "-");
6958 vshPrintExtra(ctl
, "\n");
6960 /* Display the volume info rows */
6961 for (i
= 0; i
< numVolumes
; i
++) {
6962 vshPrint(ctl
, outputStr
,
6964 volInfoTexts
[i
].path
,
6965 volInfoTexts
[i
].type
,
6966 volInfoTexts
[i
].capacity
,
6967 volInfoTexts
[i
].allocation
);
6970 /* Cleanup and return */
6971 functionReturn
= TRUE
;
6976 /* Display an appropriate error message then cleanup and return */
6979 /* Couldn't allocate memory */
6980 vshError(ctl
, "%s", _("Out of memory"));
6983 /* Some other error */
6984 vshError(ctl
, _("virAsprintf failed (errno %d)"), errno
);
6986 functionReturn
= FALSE
;
6990 /* Safely free the memory allocated in this function */
6991 for (i
= 0; i
< numVolumes
; i
++) {
6992 /* Cleanup the memory for one volume info structure per loop */
6993 VIR_FREE(volInfoTexts
[i
].path
);
6994 VIR_FREE(volInfoTexts
[i
].type
);
6995 VIR_FREE(volInfoTexts
[i
].capacity
);
6996 VIR_FREE(volInfoTexts
[i
].allocation
);
6997 VIR_FREE(activeNames
[i
]);
7000 /* Cleanup remaining memory */
7001 VIR_FREE(outputStr
);
7002 VIR_FREE(volInfoTexts
);
7003 VIR_FREE(activeNames
);
7004 virStoragePoolFree(pool
);
7006 /* Return the desired value */
7007 return functionReturn
;
7012 * "vol-name" command
7014 static const vshCmdInfo info_vol_name
[] = {
7015 {"help", N_("returns the volume name for a given volume key or path")},
7020 static const vshCmdOptDef opts_vol_name
[] = {
7021 {"vol", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("volume key or path")},
7026 cmdVolName(vshControl
*ctl
, const vshCmd
*cmd
)
7028 virStorageVolPtr vol
;
7030 if (!vshConnectionUsability(ctl
, ctl
->conn
))
7033 if (!(vol
= vshCommandOptVolBy(ctl
, cmd
, "vol", "pool", NULL
,
7037 vshPrint(ctl
, "%s\n", virStorageVolGetName(vol
));
7038 virStorageVolFree(vol
);
7044 * "vol-pool" command
7046 static const vshCmdInfo info_vol_pool
[] = {
7047 {"help", N_("returns the storage pool for a given volume key or path")},
7052 static const vshCmdOptDef opts_vol_pool
[] = {
7053 {"uuid", VSH_OT_BOOL
, 0, N_("return the pool uuid rather than pool name")},
7054 {"vol", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("volume key or path")},
7059 cmdVolPool(vshControl
*ctl
, const vshCmd
*cmd
)
7061 virStoragePoolPtr pool
;
7062 virStorageVolPtr vol
;
7063 char uuid
[VIR_UUID_STRING_BUFLEN
];
7065 /* Check the connection to libvirtd daemon is still working */
7066 if (!vshConnectionUsability(ctl
, ctl
->conn
))
7069 /* Use the supplied string to locate the volume */
7070 if (!(vol
= vshCommandOptVolBy(ctl
, cmd
, "vol", "pool", NULL
,
7075 /* Look up the parent storage pool for the volume */
7076 pool
= virStoragePoolLookupByVolume(vol
);
7078 vshError(ctl
, "%s", _("failed to get parent pool"));
7079 virStorageVolFree(vol
);
7083 /* Return the requested details of the parent storage pool */
7084 if (vshCommandOptBool(cmd
, "uuid")) {
7085 /* Retrieve and return pool UUID string */
7086 if (virStoragePoolGetUUIDString(pool
, &uuid
[0]) == 0)
7087 vshPrint(ctl
, "%s\n", uuid
);
7089 /* Return the storage pool name */
7090 vshPrint(ctl
, "%s\n", virStoragePoolGetName(pool
));
7094 virStorageVolFree(vol
);
7095 virStoragePoolFree(pool
);
7103 static const vshCmdInfo info_vol_key
[] = {
7104 {"help", N_("returns the volume key for a given volume name or path")},
7109 static const vshCmdOptDef opts_vol_key
[] = {
7110 {"pool", VSH_OT_STRING
, 0, N_("pool name or uuid")},
7111 {"vol", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("volume name or path")},
7116 cmdVolKey(vshControl
*ctl
, const vshCmd
*cmd
)
7118 virStorageVolPtr vol
;
7120 if (!vshConnectionUsability(ctl
, ctl
->conn
))
7123 if (!(vol
= vshCommandOptVol(ctl
, cmd
, "vol", "pool", NULL
)))
7126 vshPrint(ctl
, "%s\n", virStorageVolGetKey(vol
));
7127 virStorageVolFree(vol
);
7134 * "vol-path" command
7136 static const vshCmdInfo info_vol_path
[] = {
7137 {"help", N_("returns the volume path for a given volume name or key")},
7142 static const vshCmdOptDef opts_vol_path
[] = {
7143 {"pool", VSH_OT_STRING
, 0, N_("pool name or uuid")},
7144 {"vol", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("volume name or key")},
7149 cmdVolPath(vshControl
*ctl
, const vshCmd
*cmd
)
7151 virStorageVolPtr vol
;
7154 if (!vshConnectionUsability(ctl
, ctl
->conn
))
7157 if (!(vol
= vshCommandOptVol(ctl
, cmd
, "vol", "pool", &name
))) {
7161 vshPrint(ctl
, "%s\n", virStorageVolGetPath(vol
));
7162 virStorageVolFree(vol
);
7168 * "secret-define" command
7170 static const vshCmdInfo info_secret_define
[] = {
7171 {"help", N_("define or modify a secret from an XML file")},
7172 {"desc", N_("Define or modify a secret.")},
7176 static const vshCmdOptDef opts_secret_define
[] = {
7177 {"file", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("file containing secret attributes in XML")},
7182 cmdSecretDefine(vshControl
*ctl
, const vshCmd
*cmd
)
7184 char *from
, *buffer
;
7186 char uuid
[VIR_UUID_STRING_BUFLEN
];
7188 if (!vshConnectionUsability(ctl
, ctl
->conn
))
7191 from
= vshCommandOptString(cmd
, "file", NULL
);
7195 if (virFileReadAll(from
, VIRSH_MAX_XML_FILE
, &buffer
) < 0)
7198 res
= virSecretDefineXML(ctl
->conn
, buffer
, 0);
7202 vshError(ctl
, _("Failed to set attributes from %s"), from
);
7205 if (virSecretGetUUIDString(res
, &(uuid
[0])) < 0) {
7206 vshError(ctl
, "%s", _("Failed to get UUID of created secret"));
7210 vshPrint(ctl
, _("Secret %s created\n"), uuid
);
7216 * "secret-dumpxml" command
7218 static const vshCmdInfo info_secret_dumpxml
[] = {
7219 {"help", N_("secret attributes in XML")},
7220 {"desc", N_("Output attributes of a secret as an XML dump to stdout.")},
7224 static const vshCmdOptDef opts_secret_dumpxml
[] = {
7225 {"secret", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("secret UUID")},
7230 cmdSecretDumpXML(vshControl
*ctl
, const vshCmd
*cmd
)
7232 virSecretPtr secret
;
7236 if (!vshConnectionUsability(ctl
, ctl
->conn
))
7239 secret
= vshCommandOptSecret(ctl
, cmd
, NULL
);
7243 xml
= virSecretGetXMLDesc(secret
, 0);
7246 vshPrint(ctl
, "%s", xml
);
7251 virSecretFree(secret
);
7256 * "secret-set-value" command
7258 static const vshCmdInfo info_secret_set_value
[] = {
7259 {"help", N_("set a secret value")},
7260 {"desc", N_("Set a secret value.")},
7264 static const vshCmdOptDef opts_secret_set_value
[] = {
7265 {"secret", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("secret UUID")},
7266 {"base64", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("base64-encoded secret value")},
7271 cmdSecretSetValue(vshControl
*ctl
, const vshCmd
*cmd
)
7273 virSecretPtr secret
;
7275 char *base64
, *value
;
7276 int found
, res
, ret
= FALSE
;
7278 if (!vshConnectionUsability(ctl
, ctl
->conn
))
7281 secret
= vshCommandOptSecret(ctl
, cmd
, NULL
);
7285 base64
= vshCommandOptString(cmd
, "base64", &found
);
7289 if (!base64_decode_alloc(base64
, strlen(base64
), &value
, &value_size
)) {
7290 vshError(ctl
, "%s", _("Invalid base64 data"));
7293 if (value
== NULL
) {
7294 vshError(ctl
, "%s", _("Failed to allocate memory"));
7298 res
= virSecretSetValue(secret
, (unsigned char *)value
, value_size
, 0);
7299 memset(value
, 0, value_size
);
7303 vshError(ctl
, "%s", _("Failed to set secret value"));
7306 vshPrint(ctl
, "%s", _("Secret value set\n"));
7310 virSecretFree(secret
);
7315 * "secret-get-value" command
7317 static const vshCmdInfo info_secret_get_value
[] = {
7318 {"help", N_("Output a secret value")},
7319 {"desc", N_("Output a secret value to stdout.")},
7323 static const vshCmdOptDef opts_secret_get_value
[] = {
7324 {"secret", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("secret UUID")},
7329 cmdSecretGetValue(vshControl
*ctl
, const vshCmd
*cmd
)
7331 virSecretPtr secret
;
7333 unsigned char *value
;
7337 if (!vshConnectionUsability(ctl
, ctl
->conn
))
7340 secret
= vshCommandOptSecret(ctl
, cmd
, NULL
);
7344 value
= virSecretGetValue(secret
, &value_size
, 0);
7348 base64_encode_alloc((char *)value
, value_size
, &base64
);
7349 memset(value
, 0, value_size
);
7352 if (base64
== NULL
) {
7353 vshError(ctl
, "%s", _("Failed to allocate memory"));
7356 vshPrint(ctl
, "%s", base64
);
7357 memset(base64
, 0, strlen(base64
));
7362 virSecretFree(secret
);
7367 * "secret-undefine" command
7369 static const vshCmdInfo info_secret_undefine
[] = {
7370 {"help", N_("undefine a secret")},
7371 {"desc", N_("Undefine a secret.")},
7375 static const vshCmdOptDef opts_secret_undefine
[] = {
7376 {"secret", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("secret UUID")},
7381 cmdSecretUndefine(vshControl
*ctl
, const vshCmd
*cmd
)
7383 virSecretPtr secret
;
7387 if (!vshConnectionUsability(ctl
, ctl
->conn
))
7390 secret
= vshCommandOptSecret(ctl
, cmd
, &uuid
);
7394 if (virSecretUndefine(secret
) < 0) {
7395 vshError(ctl
, _("Failed to delete secret %s"), uuid
);
7398 vshPrint(ctl
, _("Secret %s deleted\n"), uuid
);
7402 virSecretFree(secret
);
7407 * "secret-list" command
7409 static const vshCmdInfo info_secret_list
[] = {
7410 {"help", N_("list secrets")},
7411 {"desc", N_("Returns a list of secrets")},
7416 cmdSecretList(vshControl
*ctl
, const vshCmd
*cmd ATTRIBUTE_UNUSED
)
7418 int maxuuids
= 0, i
;
7419 char **uuids
= NULL
;
7421 if (!vshConnectionUsability(ctl
, ctl
->conn
))
7424 maxuuids
= virConnectNumOfSecrets(ctl
->conn
);
7426 vshError(ctl
, "%s", _("Failed to list secrets"));
7429 uuids
= vshMalloc(ctl
, sizeof(*uuids
) * maxuuids
);
7431 maxuuids
= virConnectListSecrets(ctl
->conn
, uuids
, maxuuids
);
7433 vshError(ctl
, "%s", _("Failed to list secrets"));
7438 qsort(uuids
, maxuuids
, sizeof(char *), namesorter
);
7440 vshPrintExtra(ctl
, "%-36s %s\n", _("UUID"), _("Usage"));
7441 vshPrintExtra(ctl
, "-----------------------------------------------------------\n");
7443 for (i
= 0; i
< maxuuids
; i
++) {
7444 virSecretPtr sec
= virSecretLookupByUUIDString(ctl
->conn
, uuids
[i
]);
7445 const char *usageType
= NULL
;
7452 switch (virSecretGetUsageType(sec
)) {
7453 case VIR_SECRET_USAGE_TYPE_VOLUME
:
7454 usageType
= _("Volume");
7459 vshPrint(ctl
, "%-36s %s %s\n",
7460 uuids
[i
], usageType
,
7461 virSecretGetUsageID(sec
));
7463 vshPrint(ctl
, "%-36s %s\n",
7464 uuids
[i
], _("Unused"));
7477 static const vshCmdInfo info_version
[] = {
7478 {"help", N_("show version")},
7479 {"desc", N_("Display the system version information.")},
7485 cmdVersion(vshControl
*ctl
, const vshCmd
*cmd ATTRIBUTE_UNUSED
)
7487 unsigned long hvVersion
;
7489 unsigned long libVersion
;
7490 unsigned long includeVersion
;
7491 unsigned long apiVersion
;
7497 if (!vshConnectionUsability(ctl
, ctl
->conn
))
7500 hvType
= virConnectGetType(ctl
->conn
);
7501 if (hvType
== NULL
) {
7502 vshError(ctl
, "%s", _("failed to get hypervisor type"));
7506 includeVersion
= LIBVIR_VERSION_NUMBER
;
7507 major
= includeVersion
/ 1000000;
7508 includeVersion
%= 1000000;
7509 minor
= includeVersion
/ 1000;
7510 rel
= includeVersion
% 1000;
7511 vshPrint(ctl
, _("Compiled against library: libvir %d.%d.%d\n"),
7514 ret
= virGetVersion(&libVersion
, hvType
, &apiVersion
);
7516 vshError(ctl
, "%s", _("failed to get the library version"));
7519 major
= libVersion
/ 1000000;
7520 libVersion
%= 1000000;
7521 minor
= libVersion
/ 1000;
7522 rel
= libVersion
% 1000;
7523 vshPrint(ctl
, _("Using library: libvir %d.%d.%d\n"),
7526 major
= apiVersion
/ 1000000;
7527 apiVersion
%= 1000000;
7528 minor
= apiVersion
/ 1000;
7529 rel
= apiVersion
% 1000;
7530 vshPrint(ctl
, _("Using API: %s %d.%d.%d\n"), hvType
,
7533 ret
= virConnectGetVersion(ctl
->conn
, &hvVersion
);
7535 vshError(ctl
, "%s", _("failed to get the hypervisor version"));
7538 if (hvVersion
== 0) {
7540 _("Cannot extract running %s hypervisor version\n"), hvType
);
7542 major
= hvVersion
/ 1000000;
7543 hvVersion
%= 1000000;
7544 minor
= hvVersion
/ 1000;
7545 rel
= hvVersion
% 1000;
7547 vshPrint(ctl
, _("Running hypervisor: %s %d.%d.%d\n"),
7548 hvType
, major
, minor
, rel
);
7554 * "nodedev-list" command
7556 static const vshCmdInfo info_node_list_devices
[] = {
7557 {"help", N_("enumerate devices on this host")},
7562 static const vshCmdOptDef opts_node_list_devices
[] = {
7563 {"tree", VSH_OT_BOOL
, 0, N_("list devices in a tree")},
7564 {"cap", VSH_OT_STRING
, VSH_OFLAG_NONE
, N_("capability name")},
7568 #define MAX_DEPTH 100
7569 #define INDENT_SIZE 4
7570 #define INDENT_BUFLEN ((MAX_DEPTH * INDENT_SIZE) + 1)
7573 cmdNodeListDevicesPrint(vshControl
*ctl
,
7580 unsigned int indentIdx
,
7584 int nextlastdev
= -1;
7586 /* Prepare indent for this device, but not if at root */
7587 if (depth
&& depth
< MAX_DEPTH
) {
7588 indentBuf
[indentIdx
] = '+';
7589 indentBuf
[indentIdx
+1] = '-';
7590 indentBuf
[indentIdx
+2] = ' ';
7591 indentBuf
[indentIdx
+3] = '\0';
7594 /* Print this device */
7595 vshPrint(ctl
, "%s", indentBuf
);
7596 vshPrint(ctl
, "%s\n", devices
[devid
]);
7599 /* Update indent to show '|' or ' ' for child devices */
7600 if (depth
&& depth
< MAX_DEPTH
) {
7601 if (devid
== lastdev
)
7602 indentBuf
[indentIdx
] = ' ';
7604 indentBuf
[indentIdx
] = '|';
7605 indentBuf
[indentIdx
+1] = ' ';
7609 /* Determine the index of the last child device */
7610 for (i
= 0 ; i
< num_devices
; i
++) {
7612 STREQ(parents
[i
], devices
[devid
])) {
7617 /* If there is a child device, then print another blank line */
7618 if (nextlastdev
!= -1) {
7619 vshPrint(ctl
, "%s", indentBuf
);
7620 vshPrint(ctl
, " |\n");
7623 /* Finally print all children */
7624 if (depth
< MAX_DEPTH
)
7625 indentBuf
[indentIdx
] = ' ';
7626 for (i
= 0 ; i
< num_devices
; i
++) {
7627 if (depth
< MAX_DEPTH
) {
7628 indentBuf
[indentIdx
] = ' ';
7629 indentBuf
[indentIdx
+1] = ' ';
7632 STREQ(parents
[i
], devices
[devid
]))
7633 cmdNodeListDevicesPrint(ctl
, devices
, parents
,
7634 num_devices
, i
, nextlastdev
,
7635 depth
+ 1, indentIdx
+ 2, indentBuf
);
7636 if (depth
< MAX_DEPTH
)
7637 indentBuf
[indentIdx
] = '\0';
7640 /* If there was no child device, and we're the last in
7641 * a list of devices, then print another blank line */
7642 if (nextlastdev
== -1 && devid
== lastdev
) {
7643 vshPrint(ctl
, "%s", indentBuf
);
7644 vshPrint(ctl
, "\n");
7649 cmdNodeListDevices (vshControl
*ctl
, const vshCmd
*cmd ATTRIBUTE_UNUSED
)
7653 int found
, num_devices
, i
;
7654 int tree
= vshCommandOptBool(cmd
, "tree");
7656 if (!vshConnectionUsability(ctl
, ctl
->conn
))
7659 cap
= vshCommandOptString(cmd
, "cap", &found
);
7663 num_devices
= virNodeNumOfDevices(ctl
->conn
, cap
, 0);
7664 if (num_devices
< 0) {
7665 vshError(ctl
, "%s", _("Failed to count node devices"));
7667 } else if (num_devices
== 0) {
7671 devices
= vshMalloc(ctl
, sizeof(char *) * num_devices
);
7673 virNodeListDevices(ctl
->conn
, cap
, devices
, num_devices
, 0);
7674 if (num_devices
< 0) {
7675 vshError(ctl
, "%s", _("Failed to list node devices"));
7679 qsort(&devices
[0], num_devices
, sizeof(char*), namesorter
);
7681 char indentBuf
[INDENT_BUFLEN
];
7682 char **parents
= vshMalloc(ctl
, sizeof(char *) * num_devices
);
7683 for (i
= 0; i
< num_devices
; i
++) {
7684 virNodeDevicePtr dev
= virNodeDeviceLookupByName(ctl
->conn
, devices
[i
]);
7685 if (dev
&& STRNEQ(devices
[i
], "computer")) {
7686 const char *parent
= virNodeDeviceGetParent(dev
);
7687 parents
[i
] = parent
? vshStrdup(ctl
, parent
) : NULL
;
7691 virNodeDeviceFree(dev
);
7693 for (i
= 0 ; i
< num_devices
; i
++) {
7694 memset(indentBuf
, '\0', sizeof indentBuf
);
7695 if (parents
[i
] == NULL
)
7696 cmdNodeListDevicesPrint(ctl
,
7706 for (i
= 0 ; i
< num_devices
; i
++) {
7707 VIR_FREE(devices
[i
]);
7708 VIR_FREE(parents
[i
]);
7712 for (i
= 0; i
< num_devices
; i
++) {
7713 vshPrint(ctl
, "%s\n", devices
[i
]);
7714 VIR_FREE(devices
[i
]);
7722 * "nodedev-dumpxml" command
7724 static const vshCmdInfo info_node_device_dumpxml
[] = {
7725 {"help", N_("node device details in XML")},
7726 {"desc", N_("Output the node device details as an XML dump to stdout.")},
7731 static const vshCmdOptDef opts_node_device_dumpxml
[] = {
7732 {"device", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("device key")},
7737 cmdNodeDeviceDumpXML (vshControl
*ctl
, const vshCmd
*cmd
)
7740 virNodeDevicePtr device
;
7743 if (!vshConnectionUsability(ctl
, ctl
->conn
))
7745 if (!(name
= vshCommandOptString(cmd
, "device", NULL
)))
7747 if (!(device
= virNodeDeviceLookupByName(ctl
->conn
, name
))) {
7748 vshError(ctl
, "%s '%s'", _("Could not find matching device"), name
);
7752 xml
= virNodeDeviceGetXMLDesc(device
, 0);
7754 virNodeDeviceFree(device
);
7758 vshPrint(ctl
, "%s\n", xml
);
7760 virNodeDeviceFree(device
);
7765 * "nodedev-dettach" command
7767 static const vshCmdInfo info_node_device_dettach
[] = {
7768 {"help", N_("dettach node device from its device driver")},
7769 {"desc", N_("Dettach node device from its device driver before assigning to a domain.")},
7774 static const vshCmdOptDef opts_node_device_dettach
[] = {
7775 {"device", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("device key")},
7780 cmdNodeDeviceDettach (vshControl
*ctl
, const vshCmd
*cmd
)
7783 virNodeDevicePtr device
;
7786 if (!vshConnectionUsability(ctl
, ctl
->conn
))
7788 if (!(name
= vshCommandOptString(cmd
, "device", NULL
)))
7790 if (!(device
= virNodeDeviceLookupByName(ctl
->conn
, name
))) {
7791 vshError(ctl
, "%s '%s'", _("Could not find matching device"), name
);
7795 if (virNodeDeviceDettach(device
) == 0) {
7796 vshPrint(ctl
, _("Device %s dettached\n"), name
);
7798 vshError(ctl
, _("Failed to dettach device %s"), name
);
7801 virNodeDeviceFree(device
);
7806 * "nodedev-reattach" command
7808 static const vshCmdInfo info_node_device_reattach
[] = {
7809 {"help", N_("reattach node device to its device driver")},
7810 {"desc", N_("Reattach node device to its device driver once released by the domain.")},
7815 static const vshCmdOptDef opts_node_device_reattach
[] = {
7816 {"device", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("device key")},
7821 cmdNodeDeviceReAttach (vshControl
*ctl
, const vshCmd
*cmd
)
7824 virNodeDevicePtr device
;
7827 if (!vshConnectionUsability(ctl
, ctl
->conn
))
7829 if (!(name
= vshCommandOptString(cmd
, "device", NULL
)))
7831 if (!(device
= virNodeDeviceLookupByName(ctl
->conn
, name
))) {
7832 vshError(ctl
, "%s '%s'", _("Could not find matching device"), name
);
7836 if (virNodeDeviceReAttach(device
) == 0) {
7837 vshPrint(ctl
, _("Device %s re-attached\n"), name
);
7839 vshError(ctl
, _("Failed to re-attach device %s"), name
);
7842 virNodeDeviceFree(device
);
7847 * "nodedev-reset" command
7849 static const vshCmdInfo info_node_device_reset
[] = {
7850 {"help", N_("reset node device")},
7851 {"desc", N_("Reset node device before or after assigning to a domain.")},
7856 static const vshCmdOptDef opts_node_device_reset
[] = {
7857 {"device", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("device key")},
7862 cmdNodeDeviceReset (vshControl
*ctl
, const vshCmd
*cmd
)
7865 virNodeDevicePtr device
;
7868 if (!vshConnectionUsability(ctl
, ctl
->conn
))
7870 if (!(name
= vshCommandOptString(cmd
, "device", NULL
)))
7872 if (!(device
= virNodeDeviceLookupByName(ctl
->conn
, name
))) {
7873 vshError(ctl
, "%s '%s'", _("Could not find matching device"), name
);
7877 if (virNodeDeviceReset(device
) == 0) {
7878 vshPrint(ctl
, _("Device %s reset\n"), name
);
7880 vshError(ctl
, _("Failed to reset device %s"), name
);
7883 virNodeDeviceFree(device
);
7890 static const vshCmdInfo info_hostname
[] = {
7891 {"help", N_("print the hypervisor hostname")},
7897 cmdHostname (vshControl
*ctl
, const vshCmd
*cmd ATTRIBUTE_UNUSED
)
7901 if (!vshConnectionUsability(ctl
, ctl
->conn
))
7904 hostname
= virConnectGetHostname (ctl
->conn
);
7905 if (hostname
== NULL
) {
7906 vshError(ctl
, "%s", _("failed to get hostname"));
7910 vshPrint (ctl
, "%s\n", hostname
);
7919 static const vshCmdInfo info_uri
[] = {
7920 {"help", N_("print the hypervisor canonical URI")},
7926 cmdURI (vshControl
*ctl
, const vshCmd
*cmd ATTRIBUTE_UNUSED
)
7930 if (!vshConnectionUsability(ctl
, ctl
->conn
))
7933 uri
= virConnectGetURI (ctl
->conn
);
7935 vshError(ctl
, "%s", _("failed to get URI"));
7939 vshPrint (ctl
, "%s\n", uri
);
7946 * "vncdisplay" command
7948 static const vshCmdInfo info_vncdisplay
[] = {
7949 {"help", N_("vnc display")},
7950 {"desc", N_("Output the IP address and port number for the VNC display.")},
7954 static const vshCmdOptDef opts_vncdisplay
[] = {
7955 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
7960 cmdVNCDisplay(vshControl
*ctl
, const vshCmd
*cmd
)
7962 xmlDocPtr xml
= NULL
;
7963 xmlXPathObjectPtr obj
= NULL
;
7964 xmlXPathContextPtr ctxt
= NULL
;
7970 if (!vshConnectionUsability(ctl
, ctl
->conn
))
7973 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, NULL
)))
7976 doc
= virDomainGetXMLDesc(dom
, 0);
7980 xml
= xmlReadDoc((const xmlChar
*) doc
, "domain.xml", NULL
,
7981 XML_PARSE_NOENT
| XML_PARSE_NONET
|
7982 XML_PARSE_NOWARNING
);
7986 ctxt
= xmlXPathNewContext(xml
);
7990 obj
= xmlXPathEval(BAD_CAST
"string(/domain/devices/graphics[@type='vnc']/@port)", ctxt
);
7991 if ((obj
== NULL
) || (obj
->type
!= XPATH_STRING
) ||
7992 (obj
->stringval
== NULL
) || (obj
->stringval
[0] == 0)) {
7995 if (virStrToLong_i((const char *)obj
->stringval
, NULL
, 10, &port
) || port
< 0)
7997 xmlXPathFreeObject(obj
);
7999 obj
= xmlXPathEval(BAD_CAST
"string(/domain/devices/graphics[@type='vnc']/@listen)", ctxt
);
8000 if ((obj
== NULL
) || (obj
->type
!= XPATH_STRING
) ||
8001 (obj
->stringval
== NULL
) || (obj
->stringval
[0] == 0) ||
8002 STREQ((const char*)obj
->stringval
, "0.0.0.0")) {
8003 vshPrint(ctl
, ":%d\n", port
-5900);
8005 vshPrint(ctl
, "%s:%d\n", (const char *)obj
->stringval
, port
-5900);
8007 xmlXPathFreeObject(obj
);
8012 xmlXPathFreeObject(obj
);
8013 xmlXPathFreeContext(ctxt
);
8021 * "ttyconsole" command
8023 static const vshCmdInfo info_ttyconsole
[] = {
8024 {"help", N_("tty console")},
8025 {"desc", N_("Output the device for the TTY console.")},
8029 static const vshCmdOptDef opts_ttyconsole
[] = {
8030 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
8035 cmdTTYConsole(vshControl
*ctl
, const vshCmd
*cmd
)
8037 xmlDocPtr xml
= NULL
;
8038 xmlXPathObjectPtr obj
= NULL
;
8039 xmlXPathContextPtr ctxt
= NULL
;
8044 if (!vshConnectionUsability(ctl
, ctl
->conn
))
8047 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, NULL
)))
8050 doc
= virDomainGetXMLDesc(dom
, 0);
8054 xml
= xmlReadDoc((const xmlChar
*) doc
, "domain.xml", NULL
,
8055 XML_PARSE_NOENT
| XML_PARSE_NONET
|
8056 XML_PARSE_NOWARNING
);
8060 ctxt
= xmlXPathNewContext(xml
);
8064 obj
= xmlXPathEval(BAD_CAST
"string(/domain/devices/console/@tty)", ctxt
);
8065 if ((obj
== NULL
) || (obj
->type
!= XPATH_STRING
) ||
8066 (obj
->stringval
== NULL
) || (obj
->stringval
[0] == 0)) {
8069 vshPrint(ctl
, "%s\n", (const char *)obj
->stringval
);
8073 xmlXPathFreeObject(obj
);
8074 xmlXPathFreeContext(ctxt
);
8082 * "attach-device" command
8084 static const vshCmdInfo info_attach_device
[] = {
8085 {"help", N_("attach device from an XML file")},
8086 {"desc", N_("Attach device from an XML <file>.")},
8090 static const vshCmdOptDef opts_attach_device
[] = {
8091 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
8092 {"file", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("XML file")},
8093 {"persistent", VSH_OT_BOOL
, 0, N_("persist device attachment")},
8098 cmdAttachDevice(vshControl
*ctl
, const vshCmd
*cmd
)
8107 if (!vshConnectionUsability(ctl
, ctl
->conn
))
8110 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, NULL
)))
8113 from
= vshCommandOptString(cmd
, "file", &found
);
8119 if (virFileReadAll(from
, VIRSH_MAX_XML_FILE
, &buffer
) < 0) {
8120 virshReportError(ctl
);
8125 if (vshCommandOptBool(cmd
, "persistent")) {
8126 flags
= VIR_DOMAIN_DEVICE_MODIFY_CONFIG
;
8127 if (virDomainIsActive(dom
) == 1)
8128 flags
|= VIR_DOMAIN_DEVICE_MODIFY_LIVE
;
8129 ret
= virDomainAttachDeviceFlags(dom
, buffer
, flags
);
8131 ret
= virDomainAttachDevice(dom
, buffer
);
8136 vshError(ctl
, _("Failed to attach device from %s"), from
);
8140 vshPrint(ctl
, "%s", _("Device attached successfully\n"));
8149 * "detach-device" command
8151 static const vshCmdInfo info_detach_device
[] = {
8152 {"help", N_("detach device from an XML file")},
8153 {"desc", N_("Detach device from an XML <file>")},
8157 static const vshCmdOptDef opts_detach_device
[] = {
8158 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
8159 {"file", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("XML file")},
8160 {"persistent", VSH_OT_BOOL
, 0, N_("persist device detachment")},
8165 cmdDetachDevice(vshControl
*ctl
, const vshCmd
*cmd
)
8174 if (!vshConnectionUsability(ctl
, ctl
->conn
))
8177 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, NULL
)))
8180 from
= vshCommandOptString(cmd
, "file", &found
);
8186 if (virFileReadAll(from
, VIRSH_MAX_XML_FILE
, &buffer
) < 0) {
8187 virshReportError(ctl
);
8192 if (vshCommandOptBool(cmd
, "persistent")) {
8193 flags
= VIR_DOMAIN_DEVICE_MODIFY_CONFIG
;
8194 if (virDomainIsActive(dom
) == 1)
8195 flags
|= VIR_DOMAIN_DEVICE_MODIFY_LIVE
;
8196 ret
= virDomainDetachDeviceFlags(dom
, buffer
, flags
);
8198 ret
= virDomainDetachDevice(dom
, buffer
);
8203 vshError(ctl
, _("Failed to detach device from %s"), from
);
8207 vshPrint(ctl
, "%s", _("Device detached successfully\n"));
8216 * "update-device" command
8218 static const vshCmdInfo info_update_device
[] = {
8219 {"help", N_("update device from an XML file")},
8220 {"desc", N_("Update device from an XML <file>.")},
8224 static const vshCmdOptDef opts_update_device
[] = {
8225 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
8226 {"file", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("XML file")},
8227 {"persistent", VSH_OT_BOOL
, 0, N_("persist device update")},
8232 cmdUpdateDevice(vshControl
*ctl
, const vshCmd
*cmd
)
8241 if (!vshConnectionUsability(ctl
, ctl
->conn
))
8244 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, NULL
)))
8247 from
= vshCommandOptString(cmd
, "file", &found
);
8253 if (virFileReadAll(from
, VIRSH_MAX_XML_FILE
, &buffer
) < 0) {
8254 virshReportError(ctl
);
8259 if (vshCommandOptBool(cmd
, "persistent")) {
8260 flags
= VIR_DOMAIN_DEVICE_MODIFY_CONFIG
;
8261 if (virDomainIsActive(dom
) == 1)
8262 flags
|= VIR_DOMAIN_DEVICE_MODIFY_LIVE
;
8264 flags
= VIR_DOMAIN_DEVICE_MODIFY_LIVE
;
8266 ret
= virDomainUpdateDeviceFlags(dom
, buffer
, flags
);
8270 vshError(ctl
, _("Failed to update device from %s"), from
);
8274 vshPrint(ctl
, "%s", _("Device updated successfully\n"));
8283 * "attach-interface" command
8285 static const vshCmdInfo info_attach_interface
[] = {
8286 {"help", N_("attach network interface")},
8287 {"desc", N_("Attach new network interface.")},
8291 static const vshCmdOptDef opts_attach_interface
[] = {
8292 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
8293 {"type", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("network interface type")},
8294 {"source", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("source of network interface")},
8295 {"target", VSH_OT_DATA
, 0, N_("target network name")},
8296 {"mac", VSH_OT_DATA
, 0, N_("MAC address")},
8297 {"script", VSH_OT_DATA
, 0, N_("script used to bridge network interface")},
8298 {"model", VSH_OT_DATA
, 0, N_("model type")},
8299 {"persistent", VSH_OT_BOOL
, 0, N_("persist interface attachment")},
8304 cmdAttachInterface(vshControl
*ctl
, const vshCmd
*cmd
)
8306 virDomainPtr dom
= NULL
;
8307 char *mac
, *target
, *script
, *type
, *source
, *model
;
8308 int typ
, ret
= FALSE
;
8310 virBuffer buf
= VIR_BUFFER_INITIALIZER
;
8313 if (!vshConnectionUsability(ctl
, ctl
->conn
))
8316 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, NULL
)))
8319 if (!(type
= vshCommandOptString(cmd
, "type", NULL
)))
8322 source
= vshCommandOptString(cmd
, "source", NULL
);
8323 target
= vshCommandOptString(cmd
, "target", NULL
);
8324 mac
= vshCommandOptString(cmd
, "mac", NULL
);
8325 script
= vshCommandOptString(cmd
, "script", NULL
);
8326 model
= vshCommandOptString(cmd
, "model", NULL
);
8328 /* check interface type */
8329 if (STREQ(type
, "network")) {
8331 } else if (STREQ(type
, "bridge")) {
8334 vshError(ctl
, _("No support for %s in command 'attach-interface'"),
8339 /* Make XML of interface */
8340 virBufferVSprintf(&buf
, "<interface type='%s'>\n", type
);
8343 virBufferVSprintf(&buf
, " <source network='%s'/>\n", source
);
8345 virBufferVSprintf(&buf
, " <source bridge='%s'/>\n", source
);
8348 virBufferVSprintf(&buf
, " <target dev='%s'/>\n", target
);
8350 virBufferVSprintf(&buf
, " <mac address='%s'/>\n", mac
);
8352 virBufferVSprintf(&buf
, " <script path='%s'/>\n", script
);
8354 virBufferVSprintf(&buf
, " <model type='%s'/>\n", model
);
8356 virBufferAddLit(&buf
, "</interface>\n");
8358 if (virBufferError(&buf
)) {
8359 vshPrint(ctl
, "%s", _("Failed to allocate XML buffer"));
8363 xml
= virBufferContentAndReset(&buf
);
8365 if (vshCommandOptBool(cmd
, "persistent")) {
8366 flags
= VIR_DOMAIN_DEVICE_MODIFY_CONFIG
;
8367 if (virDomainIsActive(dom
) == 1)
8368 flags
|= VIR_DOMAIN_DEVICE_MODIFY_LIVE
;
8369 ret
= virDomainAttachDeviceFlags(dom
, xml
, flags
);
8371 ret
= virDomainAttachDevice(dom
, xml
);
8377 vshError(ctl
, "%s", _("Failed to attach interface"));
8380 vshPrint(ctl
, "%s", _("Interface attached successfully\n"));
8387 virBufferFreeAndReset(&buf
);
8392 * "detach-interface" command
8394 static const vshCmdInfo info_detach_interface
[] = {
8395 {"help", N_("detach network interface")},
8396 {"desc", N_("Detach network interface.")},
8400 static const vshCmdOptDef opts_detach_interface
[] = {
8401 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
8402 {"type", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("network interface type")},
8403 {"mac", VSH_OT_STRING
, 0, N_("MAC address")},
8404 {"persistent", VSH_OT_BOOL
, 0, N_("persist interface detachment")},
8409 cmdDetachInterface(vshControl
*ctl
, const vshCmd
*cmd
)
8411 virDomainPtr dom
= NULL
;
8412 xmlDocPtr xml
= NULL
;
8413 xmlXPathObjectPtr obj
=NULL
;
8414 xmlXPathContextPtr ctxt
= NULL
;
8415 xmlNodePtr cur
= NULL
;
8416 xmlChar
*tmp_mac
= NULL
;
8417 xmlBufferPtr xml_buf
= NULL
;
8418 char *doc
, *mac
=NULL
, *type
;
8420 int i
= 0, diff_mac
, ret
= FALSE
;
8423 if (!vshConnectionUsability(ctl
, ctl
->conn
))
8426 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, NULL
)))
8429 if (!(type
= vshCommandOptString(cmd
, "type", NULL
)))
8432 mac
= vshCommandOptString(cmd
, "mac", NULL
);
8434 doc
= virDomainGetXMLDesc(dom
, 0);
8438 xml
= xmlReadDoc((const xmlChar
*) doc
, "domain.xml", NULL
,
8439 XML_PARSE_NOENT
| XML_PARSE_NONET
|
8440 XML_PARSE_NOWARNING
);
8443 vshError(ctl
, "%s", _("Failed to get interface information"));
8446 ctxt
= xmlXPathNewContext(xml
);
8448 vshError(ctl
, "%s", _("Failed to get interface information"));
8452 sprintf(buf
, "/domain/devices/interface[@type='%s']", type
);
8453 obj
= xmlXPathEval(BAD_CAST buf
, ctxt
);
8454 if ((obj
== NULL
) || (obj
->type
!= XPATH_NODESET
) ||
8455 (obj
->nodesetval
== NULL
) || (obj
->nodesetval
->nodeNr
== 0)) {
8456 vshError(ctl
, _("No found interface whose type is %s"), type
);
8464 for (; i
< obj
->nodesetval
->nodeNr
; i
++) {
8465 cur
= obj
->nodesetval
->nodeTab
[i
]->children
;
8466 while (cur
!= NULL
) {
8467 if (cur
->type
== XML_ELEMENT_NODE
&& xmlStrEqual(cur
->name
, BAD_CAST
"mac")) {
8468 tmp_mac
= xmlGetProp(cur
, BAD_CAST
"address");
8469 diff_mac
= virMacAddrCompare ((char *) tmp_mac
, mac
);
8478 vshError(ctl
, _("No found interface whose MAC address is %s"), mac
);
8482 xml_buf
= xmlBufferCreate();
8484 vshError(ctl
, "%s", _("Failed to allocate memory"));
8488 if(xmlNodeDump(xml_buf
, xml
, obj
->nodesetval
->nodeTab
[i
], 0, 0) < 0){
8489 vshError(ctl
, "%s", _("Failed to create XML"));
8493 if (vshCommandOptBool(cmd
, "persistent")) {
8494 flags
= VIR_DOMAIN_DEVICE_MODIFY_CONFIG
;
8495 if (virDomainIsActive(dom
) == 1)
8496 flags
|= VIR_DOMAIN_DEVICE_MODIFY_LIVE
;
8497 ret
= virDomainDetachDeviceFlags(dom
,
8498 (char *)xmlBufferContent(xml_buf
),
8501 ret
= virDomainDetachDevice(dom
, (char *)xmlBufferContent(xml_buf
));
8505 vshError(ctl
, "%s", _("Failed to detach interface"));
8508 vshPrint(ctl
, "%s", _("Interface detached successfully\n"));
8515 xmlXPathFreeObject(obj
);
8516 xmlXPathFreeContext(ctxt
);
8520 xmlBufferFree(xml_buf
);
8525 * "attach-disk" command
8527 static const vshCmdInfo info_attach_disk
[] = {
8528 {"help", N_("attach disk device")},
8529 {"desc", N_("Attach new disk device.")},
8533 static const vshCmdOptDef opts_attach_disk
[] = {
8534 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
8535 {"source", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("source of disk device")},
8536 {"target", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("target of disk device")},
8537 {"driver", VSH_OT_STRING
, 0, N_("driver of disk device")},
8538 {"subdriver", VSH_OT_STRING
, 0, N_("subdriver of disk device")},
8539 {"type", VSH_OT_STRING
, 0, N_("target device type")},
8540 {"mode", VSH_OT_STRING
, 0, N_("mode of device reading and writing")},
8541 {"persistent", VSH_OT_BOOL
, 0, N_("persist disk attachment")},
8542 {"sourcetype", VSH_OT_STRING
, 0, N_("type of source (block|file)")},
8547 cmdAttachDisk(vshControl
*ctl
, const vshCmd
*cmd
)
8549 virDomainPtr dom
= NULL
;
8550 char *source
, *target
, *driver
, *subdriver
, *type
, *mode
;
8551 int isFile
= 0, ret
= FALSE
;
8554 virBuffer buf
= VIR_BUFFER_INITIALIZER
;
8557 if (!vshConnectionUsability(ctl
, ctl
->conn
))
8560 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, NULL
)))
8563 if (!(source
= vshCommandOptString(cmd
, "source", NULL
)))
8566 if (!(target
= vshCommandOptString(cmd
, "target", NULL
)))
8569 driver
= vshCommandOptString(cmd
, "driver", NULL
);
8570 subdriver
= vshCommandOptString(cmd
, "subdriver", NULL
);
8571 type
= vshCommandOptString(cmd
, "type", NULL
);
8572 mode
= vshCommandOptString(cmd
, "mode", NULL
);
8573 stype
= vshCommandOptString(cmd
, "sourcetype", NULL
);
8576 if (driver
&& (STREQ(driver
, "file") || STREQ(driver
, "tap")))
8578 } else if (STREQ(stype
, "file")) {
8580 } else if (STRNEQ(stype
, "block")) {
8581 vshError(ctl
, _("Unknown source type: '%s'"), stype
);
8586 if (STRNEQ(mode
, "readonly") && STRNEQ(mode
, "shareable")) {
8587 vshError(ctl
, _("No support for %s in command 'attach-disk'"),
8593 /* Make XML of disk */
8594 virBufferVSprintf(&buf
, "<disk type='%s'",
8595 (isFile
) ? "file" : "block");
8597 virBufferVSprintf(&buf
, " device='%s'", type
);
8598 virBufferAddLit(&buf
, ">\n");
8600 virBufferVSprintf(&buf
, " <driver name='%s'",
8601 (driver
) ? driver
: "phy");
8603 virBufferVSprintf(&buf
, " type='%s'", subdriver
);
8604 virBufferAddLit(&buf
, "/>\n");
8606 virBufferVSprintf(&buf
, " <source %s='%s'/>\n",
8607 (isFile
) ? "file" : "dev",
8609 virBufferVSprintf(&buf
, " <target dev='%s'/>\n", target
);
8611 virBufferVSprintf(&buf
, " <%s/>\n", mode
);
8613 virBufferAddLit(&buf
, "</disk>\n");
8615 if (virBufferError(&buf
)) {
8616 vshPrint(ctl
, "%s", _("Failed to allocate XML buffer"));
8620 xml
= virBufferContentAndReset(&buf
);
8622 if (vshCommandOptBool(cmd
, "persistent")) {
8623 flags
= VIR_DOMAIN_DEVICE_MODIFY_CONFIG
;
8624 if (virDomainIsActive(dom
) == 1)
8625 flags
|= VIR_DOMAIN_DEVICE_MODIFY_LIVE
;
8626 ret
= virDomainAttachDeviceFlags(dom
, xml
, flags
);
8628 ret
= virDomainAttachDevice(dom
, xml
);
8634 vshError(ctl
, "%s", _("Failed to attach disk"));
8637 vshPrint(ctl
, "%s", _("Disk attached successfully\n"));
8644 virBufferFreeAndReset(&buf
);
8649 * "detach-disk" command
8651 static const vshCmdInfo info_detach_disk
[] = {
8652 {"help", N_("detach disk device")},
8653 {"desc", N_("Detach disk device.")},
8657 static const vshCmdOptDef opts_detach_disk
[] = {
8658 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
8659 {"target", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("target of disk device")},
8660 {"persistent", VSH_OT_BOOL
, 0, N_("persist disk detachment")},
8665 cmdDetachDisk(vshControl
*ctl
, const vshCmd
*cmd
)
8667 xmlDocPtr xml
= NULL
;
8668 xmlXPathObjectPtr obj
=NULL
;
8669 xmlXPathContextPtr ctxt
= NULL
;
8670 xmlNodePtr cur
= NULL
;
8671 xmlChar
*tmp_tgt
= NULL
;
8672 xmlBufferPtr xml_buf
= NULL
;
8673 virDomainPtr dom
= NULL
;
8675 int i
= 0, diff_tgt
, ret
= FALSE
;
8678 if (!vshConnectionUsability(ctl
, ctl
->conn
))
8681 if (!(dom
= vshCommandOptDomain(ctl
, cmd
, NULL
)))
8684 if (!(target
= vshCommandOptString(cmd
, "target", NULL
)))
8687 doc
= virDomainGetXMLDesc(dom
, 0);
8691 xml
= xmlReadDoc((const xmlChar
*) doc
, "domain.xml", NULL
,
8692 XML_PARSE_NOENT
| XML_PARSE_NONET
|
8693 XML_PARSE_NOWARNING
);
8696 vshError(ctl
, "%s", _("Failed to get disk information"));
8699 ctxt
= xmlXPathNewContext(xml
);
8701 vshError(ctl
, "%s", _("Failed to get disk information"));
8705 obj
= xmlXPathEval(BAD_CAST
"/domain/devices/disk", ctxt
);
8706 if ((obj
== NULL
) || (obj
->type
!= XPATH_NODESET
) ||
8707 (obj
->nodesetval
== NULL
) || (obj
->nodesetval
->nodeNr
== 0)) {
8708 vshError(ctl
, "%s", _("Failed to get disk information"));
8713 for (; i
< obj
->nodesetval
->nodeNr
; i
++) {
8714 cur
= obj
->nodesetval
->nodeTab
[i
]->children
;
8715 while (cur
!= NULL
) {
8716 if (cur
->type
== XML_ELEMENT_NODE
&& xmlStrEqual(cur
->name
, BAD_CAST
"target")) {
8717 tmp_tgt
= xmlGetProp(cur
, BAD_CAST
"dev");
8718 diff_tgt
= xmlStrEqual(tmp_tgt
, BAD_CAST target
);
8727 vshError(ctl
, _("No found disk whose target is %s"), target
);
8731 xml_buf
= xmlBufferCreate();
8733 vshError(ctl
, "%s", _("Failed to allocate memory"));
8737 if(xmlNodeDump(xml_buf
, xml
, obj
->nodesetval
->nodeTab
[i
], 0, 0) < 0){
8738 vshError(ctl
, "%s", _("Failed to create XML"));
8742 if (vshCommandOptBool(cmd
, "persistent")) {
8743 flags
= VIR_DOMAIN_DEVICE_MODIFY_CONFIG
;
8744 if (virDomainIsActive(dom
) == 1)
8745 flags
|= VIR_DOMAIN_DEVICE_MODIFY_LIVE
;
8746 ret
= virDomainDetachDeviceFlags(dom
,
8747 (char *)xmlBufferContent(xml_buf
),
8750 ret
= virDomainDetachDevice(dom
, (char *)xmlBufferContent(xml_buf
));
8754 vshError(ctl
, "%s", _("Failed to detach disk"));
8757 vshPrint(ctl
, "%s", _("Disk detached successfully\n"));
8762 xmlXPathFreeObject(obj
);
8763 xmlXPathFreeContext(ctxt
);
8767 xmlBufferFree(xml_buf
);
8774 * "cpu-compare" command
8776 static const vshCmdInfo info_cpu_compare
[] = {
8777 {"help", N_("compare host CPU with a CPU described by an XML file")},
8778 {"desc", N_("compare CPU with host CPU")},
8782 static const vshCmdOptDef opts_cpu_compare
[] = {
8783 {"file", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("file containing an XML CPU description")},
8788 cmdCPUCompare(vshControl
*ctl
, const vshCmd
*cmd
)
8796 if (!vshConnectionUsability(ctl
, ctl
->conn
))
8799 from
= vshCommandOptString(cmd
, "file", &found
);
8803 if (virFileReadAll(from
, VIRSH_MAX_XML_FILE
, &buffer
) < 0)
8806 result
= virConnectCompareCPU(ctl
->conn
, buffer
, 0);
8810 case VIR_CPU_COMPARE_INCOMPATIBLE
:
8811 vshPrint(ctl
, _("CPU described in %s is incompatible with host CPU\n"),
8816 case VIR_CPU_COMPARE_IDENTICAL
:
8817 vshPrint(ctl
, _("CPU described in %s is identical to host CPU\n"),
8822 case VIR_CPU_COMPARE_SUPERSET
:
8823 vshPrint(ctl
, _("Host CPU is a superset of CPU described in %s\n"),
8828 case VIR_CPU_COMPARE_ERROR
:
8830 vshError(ctl
, _("Failed to compare host CPU with %s"), from
);
8838 * "cpu-baseline" command
8840 static const vshCmdInfo info_cpu_baseline
[] = {
8841 {"help", N_("compute baseline CPU")},
8842 {"desc", N_("Compute baseline CPU for a set of given CPUs.")},
8846 static const vshCmdOptDef opts_cpu_baseline
[] = {
8847 {"file", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("file containing XML CPU descriptions")},
8852 cmdCPUBaseline(vshControl
*ctl
, const vshCmd
*cmd
)
8858 char *result
= NULL
;
8859 const char **list
= NULL
;
8860 unsigned int count
= 0;
8861 xmlDocPtr doc
= NULL
;
8862 xmlNodePtr node_list
;
8863 xmlXPathContextPtr ctxt
= NULL
;
8864 xmlSaveCtxtPtr sctxt
= NULL
;
8865 xmlBufferPtr buf
= NULL
;
8866 xmlXPathObjectPtr obj
= NULL
;
8869 if (!vshConnectionUsability(ctl
, ctl
->conn
))
8872 from
= vshCommandOptString(cmd
, "file", &found
);
8876 if (virFileReadAll(from
, VIRSH_MAX_XML_FILE
, &buffer
) < 0)
8879 doc
= xmlNewDoc(NULL
);
8883 res
= xmlParseBalancedChunkMemory(doc
, NULL
, NULL
, 0,
8884 (const xmlChar
*)buffer
, &node_list
);
8886 vshError(ctl
, _("Failed to parse XML fragment %s"), from
);
8891 xmlAddChildList((xmlNodePtr
) doc
, node_list
);
8893 ctxt
= xmlXPathNewContext(doc
);
8897 obj
= xmlXPathEval(BAD_CAST
"//cpu[not(ancestor::cpu)]", ctxt
);
8898 if ((obj
== NULL
) || (obj
->nodesetval
== NULL
) ||
8899 (obj
->nodesetval
->nodeTab
== NULL
))
8902 for (i
= 0;i
< obj
->nodesetval
->nodeNr
;i
++) {
8903 buf
= xmlBufferCreate();
8906 sctxt
= xmlSaveToBuffer(buf
, NULL
, 0);
8907 if (sctxt
== NULL
) {
8912 xmlSaveTree(sctxt
, obj
->nodesetval
->nodeTab
[i
]);
8913 xmlSaveClose(sctxt
);
8915 list
= vshRealloc(ctl
, list
, sizeof(char *) * (count
+ 1));
8916 list
[count
++] = (char *) buf
->content
;
8917 buf
->content
= NULL
;
8923 vshError(ctl
, _("No host CPU specified in '%s'"), from
);
8928 result
= virConnectBaselineCPU(ctl
->conn
, list
, count
, 0);
8931 vshPrint(ctl
, "%s", result
);
8936 xmlXPathFreeObject(obj
);
8937 xmlXPathFreeContext(ctxt
);
8940 if ((list
!= NULL
) && (count
> 0)) {
8941 for (i
= 0;i
< count
;i
++)
8950 vshError(ctl
, "%s", _("Out of memory"));
8955 /* Common code for the edit / net-edit / pool-edit functions which follow. */
8957 editWriteToTempFile (vshControl
*ctl
, const char *doc
)
8963 ret
= vshMalloc(ctl
, PATH_MAX
);
8965 tmpdir
= getenv ("TMPDIR");
8966 if (!tmpdir
) tmpdir
= "/tmp";
8967 snprintf (ret
, PATH_MAX
, "%s/virshXXXXXX", tmpdir
);
8970 vshError(ctl
, _("mkstemp: failed to create temporary file: %s"),
8976 if (safewrite (fd
, doc
, strlen (doc
)) == -1) {
8977 vshError(ctl
, _("write: %s: failed to write to temporary file: %s"),
8978 ret
, strerror(errno
));
8984 if (close (fd
) == -1) {
8985 vshError(ctl
, _("close: %s: failed to write or close temporary file: %s"),
8986 ret
, strerror(errno
));
8992 /* Temporary filename: caller frees. */
8996 /* Characters permitted in $EDITOR environment variable and temp filename. */
8997 #define ACCEPTED_CHARS \
8998 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-/_.:@"
9001 editFile (vshControl
*ctl
, const char *filename
)
9007 editor
= getenv ("VISUAL");
9008 if (!editor
) editor
= getenv ("EDITOR");
9009 if (!editor
) editor
= "vi"; /* could be cruel & default to ed(1) here */
9011 /* Check that filename doesn't contain shell meta-characters, and
9012 * if it does, refuse to run. Follow the Unix conventions for
9013 * EDITOR: the user can intentionally specify command options, so
9014 * we don't protect any shell metacharacters there. Lots more
9015 * than virsh will misbehave if EDITOR has bogus contents (which
9016 * is why sudo scrubs it by default).
9018 if (strspn (filename
, ACCEPTED_CHARS
) != strlen (filename
)) {
9020 _("%s: temporary filename contains shell meta or other "
9021 "unacceptable characters (is $TMPDIR wrong?)"),
9026 if (virAsprintf(&command
, "%s %s", editor
, filename
) == -1) {
9028 _("virAsprintf: could not create editing command: %s"),
9033 command_ret
= system (command
);
9034 if (command_ret
== -1) {
9036 _("%s: edit command failed: %s"), command
, strerror(errno
));
9040 if (WEXITSTATUS(command_ret
) != 0) {
9042 _("%s: command exited with non-zero status"), command
);
9051 editReadBackFile (vshControl
*ctl
, const char *filename
)
9055 if (virFileReadAll (filename
, VIRSH_MAX_XML_FILE
, &ret
) == -1) {
9057 _("%s: failed to read temporary file: %s"),
9058 filename
, strerror(errno
));
9069 static const vshCmdInfo info_cd
[] = {
9070 {"help", N_("change the current directory")},
9071 {"desc", N_("Change the current directory.")},
9075 static const vshCmdOptDef opts_cd
[] = {
9076 {"dir", VSH_OT_DATA
, 0, N_("directory to switch to (default: home or else root)")},
9081 cmdCd(vshControl
*ctl
, const vshCmd
*cmd ATTRIBUTE_UNUSED
)
9087 vshError(ctl
, "%s", _("cd: command valid only in interactive mode"));
9091 dir
= vshCommandOptString(cmd
, "dir", &found
);
9093 uid_t uid
= geteuid();
9094 dir
= virGetUserDirectory(uid
);
9099 if (chdir (dir
) == -1) {
9100 vshError(ctl
, _("cd: %s: %s"), strerror(errno
), dir
);
9113 static const vshCmdInfo info_pwd
[] = {
9114 {"help", N_("print the current directory")},
9115 {"desc", N_("Print the current directory.")},
9120 cmdPwd(vshControl
*ctl
, const vshCmd
*cmd ATTRIBUTE_UNUSED
)
9126 path_max
= (size_t) PATH_MAX
+ 2;
9127 cwd
= vshMalloc (ctl
, path_max
);
9129 err
= getcwd (cwd
, path_max
) == NULL
;
9130 if (!err
|| errno
!= ERANGE
)
9134 cwd
= vshRealloc (ctl
, cwd
, path_max
);
9138 vshError(ctl
, _("pwd: cannot get current directory: %s"),
9141 vshPrint (ctl
, _("%s\n"), cwd
);
9151 static const vshCmdInfo info_echo
[] = {
9152 {"help", N_("echo arguments")},
9153 {"desc", N_("Echo back arguments, possibly with quoting.")},
9157 static const vshCmdOptDef opts_echo
[] = {
9158 {"shell", VSH_OT_BOOL
, 0, N_("escape for shell use")},
9159 {"xml", VSH_OT_BOOL
, 0, N_("escape for XML use")},
9160 {"", VSH_OT_ARGV
, 0, N_("arguments to echo")},
9164 /* Exists mainly for debugging virsh, but also handy for adding back
9165 * quotes for later evaluation.
9168 cmdEcho (vshControl
*ctl ATTRIBUTE_UNUSED
, const vshCmd
*cmd
)
9174 virBuffer buf
= VIR_BUFFER_INITIALIZER
;
9176 if (vshCommandOptBool(cmd
, "shell"))
9178 if (vshCommandOptBool(cmd
, "xml"))
9181 while ((arg
= vshCommandOptArgv(cmd
, count
)) != NULL
) {
9182 bool close_quote
= false;
9186 virBufferAddChar(&buf
, ' ');
9187 /* Add outer '' only if arg included shell metacharacters. */
9189 (strpbrk(arg
, "\r\t\n !\"#$&'()*;<>?[\\]^`{|}~") || !*arg
)) {
9190 virBufferAddChar(&buf
, '\'');
9194 virBufferEscapeString(&buf
, "%s", arg
);
9196 if (shell
&& (q
= strchr(arg
, '\''))) {
9198 virBufferAdd(&buf
, arg
, q
- arg
);
9199 virBufferAddLit(&buf
, "'\\''");
9201 q
= strchr(arg
, '\'');
9204 virBufferAdd(&buf
, arg
, strlen(arg
));
9207 virBufferAddChar(&buf
, '\'');
9211 if (virBufferError(&buf
)) {
9212 vshPrint(ctl
, "%s", _("Failed to allocate XML buffer"));
9215 arg
= virBufferContentAndReset(&buf
);
9217 vshPrint(ctl
, "%s", arg
);
9225 static const vshCmdInfo info_edit
[] = {
9226 {"help", N_("edit XML configuration for a domain")},
9227 {"desc", N_("Edit the XML configuration for a domain.")},
9231 static const vshCmdOptDef opts_edit
[] = {
9232 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
9236 /* This function also acts as a template to generate cmdNetworkEdit
9237 * and cmdPoolEdit functions (below) using a sed script in the Makefile.
9240 cmdEdit (vshControl
*ctl
, const vshCmd
*cmd
)
9243 virDomainPtr dom
= NULL
;
9246 char *doc_edited
= NULL
;
9247 char *doc_reread
= NULL
;
9248 int flags
= VIR_DOMAIN_XML_SECURE
| VIR_DOMAIN_XML_INACTIVE
;
9250 if (!vshConnectionUsability(ctl
, ctl
->conn
))
9253 dom
= vshCommandOptDomain (ctl
, cmd
, NULL
);
9257 /* Get the XML configuration of the domain. */
9258 doc
= virDomainGetXMLDesc (dom
, flags
);
9262 /* Create and open the temporary file. */
9263 tmp
= editWriteToTempFile (ctl
, doc
);
9264 if (!tmp
) goto cleanup
;
9266 /* Start the editor. */
9267 if (editFile (ctl
, tmp
) == -1) goto cleanup
;
9269 /* Read back the edited file. */
9270 doc_edited
= editReadBackFile (ctl
, tmp
);
9271 if (!doc_edited
) goto cleanup
;
9273 /* Compare original XML with edited. Has it changed at all? */
9274 if (STREQ (doc
, doc_edited
)) {
9275 vshPrint (ctl
, _("Domain %s XML configuration not changed.\n"),
9276 virDomainGetName (dom
));
9281 /* Now re-read the domain XML. Did someone else change it while
9282 * it was being edited? This also catches problems such as us
9283 * losing a connection or the domain going away.
9285 doc_reread
= virDomainGetXMLDesc (dom
, flags
);
9289 if (STRNEQ (doc
, doc_reread
)) {
9291 "%s", _("ERROR: the XML configuration was changed by another user"));
9295 /* Everything checks out, so redefine the domain. */
9296 virDomainFree (dom
);
9297 dom
= virDomainDefineXML (ctl
->conn
, doc_edited
);
9301 vshPrint (ctl
, _("Domain %s XML configuration edited.\n"),
9302 virDomainGetName(dom
));
9308 virDomainFree (dom
);
9311 VIR_FREE(doc_edited
);
9312 VIR_FREE(doc_reread
);
9323 * "net-edit" command
9325 static const vshCmdInfo info_network_edit
[] = {
9326 {"help", N_("edit XML configuration for a network")},
9327 {"desc", N_("Edit the XML configuration for a network.")},
9331 static const vshCmdOptDef opts_network_edit
[] = {
9332 {"network", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("network name, id or uuid")},
9336 /* This is generated from this file by a sed script in the Makefile. */
9337 #include "virsh-net-edit.c"
9340 * "pool-edit" command
9342 static const vshCmdInfo info_pool_edit
[] = {
9343 {"help", N_("edit XML configuration for a storage pool")},
9344 {"desc", N_("Edit the XML configuration for a storage pool.")},
9348 static const vshCmdOptDef opts_pool_edit
[] = {
9349 {"pool", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("pool name or uuid")},
9353 /* This is generated from this file by a sed script in the Makefile. */
9354 #include "virsh-pool-edit.c"
9359 static const vshCmdInfo info_quit
[] = {
9360 {"help", N_("quit this interactive terminal")},
9366 cmdQuit(vshControl
*ctl
, const vshCmd
*cmd ATTRIBUTE_UNUSED
)
9373 * "snapshot-create" command
9375 static const vshCmdInfo info_snapshot_create
[] = {
9376 {"help", N_("Create a snapshot")},
9377 {"desc", N_("Snapshot create")},
9381 static const vshCmdOptDef opts_snapshot_create
[] = {
9382 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
9383 {"xmlfile", VSH_OT_DATA
, 0, N_("domain snapshot XML")},
9388 cmdSnapshotCreate(vshControl
*ctl
, const vshCmd
*cmd
)
9390 virDomainPtr dom
= NULL
;
9393 char *buffer
= NULL
;
9394 virDomainSnapshotPtr snapshot
= NULL
;
9395 xmlDocPtr xml
= NULL
;
9396 xmlXPathContextPtr ctxt
= NULL
;
9400 if (!vshConnectionUsability(ctl
, ctl
->conn
))
9403 dom
= vshCommandOptDomain(ctl
, cmd
, NULL
);
9407 from
= vshCommandOptString(cmd
, "xmlfile", NULL
);
9409 buffer
= vshStrdup(ctl
, "<domainsnapshot/>");
9411 if (virFileReadAll(from
, VIRSH_MAX_XML_FILE
, &buffer
) < 0) {
9412 /* we have to report the error here because during cleanup
9413 * we'll run through virDomainFree(), which loses the
9416 virshReportError(ctl
);
9420 if (buffer
== NULL
) {
9421 vshError(ctl
, "%s", _("Out of memory"));
9425 snapshot
= virDomainSnapshotCreateXML(dom
, buffer
, 0);
9426 if (snapshot
== NULL
)
9429 doc
= virDomainSnapshotGetXMLDesc(snapshot
, 0);
9433 xml
= xmlReadDoc((const xmlChar
*) doc
, "domainsnapshot.xml", NULL
,
9434 XML_PARSE_NOENT
| XML_PARSE_NONET
|
9435 XML_PARSE_NOWARNING
);
9438 ctxt
= xmlXPathNewContext(xml
);
9442 name
= virXPathString("string(/domainsnapshot/name)", ctxt
);
9445 _("Could not find 'name' element in domain snapshot XML"));
9449 vshPrint(ctl
, _("Domain snapshot %s created"), name
);
9451 vshPrint(ctl
, _(" from '%s'"), from
);
9452 vshPrint(ctl
, "\n");
9458 xmlXPathFreeContext(ctxt
);
9462 virDomainSnapshotFree(snapshot
);
9472 * "snapshot-current" command
9474 static const vshCmdInfo info_snapshot_current
[] = {
9475 {"help", N_("Get the current snapshot")},
9476 {"desc", N_("Get the current snapshot")},
9480 static const vshCmdOptDef opts_snapshot_current
[] = {
9481 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
9486 cmdSnapshotCurrent(vshControl
*ctl
, const vshCmd
*cmd
)
9488 virDomainPtr dom
= NULL
;
9491 virDomainSnapshotPtr snapshot
= NULL
;
9493 if (!vshConnectionUsability(ctl
, ctl
->conn
))
9496 dom
= vshCommandOptDomain(ctl
, cmd
, NULL
);
9500 current
= virDomainHasCurrentSnapshot(dom
, 0);
9506 if (!(snapshot
= virDomainSnapshotCurrent(dom
, 0)))
9509 xml
= virDomainSnapshotGetXMLDesc(snapshot
, 0);
9513 vshPrint(ctl
, "%s", xml
);
9521 virDomainSnapshotFree(snapshot
);
9529 * "snapshot-list" command
9531 static const vshCmdInfo info_snapshot_list
[] = {
9532 {"help", N_("List snapshots for a domain")},
9533 {"desc", N_("Snapshot List")},
9537 static const vshCmdOptDef opts_snapshot_list
[] = {
9538 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
9543 cmdSnapshotList(vshControl
*ctl
, const vshCmd
*cmd
)
9545 virDomainPtr dom
= NULL
;
9548 char **names
= NULL
;
9551 xmlDocPtr xml
= NULL
;
9552 xmlXPathContextPtr ctxt
= NULL
;
9554 virDomainSnapshotPtr snapshot
= NULL
;
9558 struct tm time_info
;
9560 if (!vshConnectionUsability(ctl
, ctl
->conn
))
9563 dom
= vshCommandOptDomain(ctl
, cmd
, NULL
);
9567 numsnaps
= virDomainSnapshotNum(dom
, 0);
9572 vshPrint(ctl
, " %-20s %-25s %s\n", _("Name"), _("Creation Time"), _("State"));
9573 vshPrint(ctl
, "---------------------------------------------------\n");
9576 if (VIR_ALLOC_N(names
, numsnaps
) < 0)
9579 actual
= virDomainSnapshotListNames(dom
, names
, numsnaps
, 0);
9583 qsort(&names
[0], actual
, sizeof(char*), namesorter
);
9585 for (i
= 0; i
< actual
; i
++) {
9586 /* free up memory from previous iterations of the loop */
9589 virDomainSnapshotFree(snapshot
);
9590 xmlXPathFreeContext(ctxt
);
9595 snapshot
= virDomainSnapshotLookupByName(dom
, names
[i
], 0);
9596 if (snapshot
== NULL
)
9599 doc
= virDomainSnapshotGetXMLDesc(snapshot
, 0);
9603 xml
= xmlReadDoc((const xmlChar
*) doc
, "domainsnapshot.xml", NULL
,
9604 XML_PARSE_NOENT
| XML_PARSE_NONET
|
9605 XML_PARSE_NOWARNING
);
9608 ctxt
= xmlXPathNewContext(xml
);
9612 state
= virXPathString("string(/domainsnapshot/state)", ctxt
);
9615 if (virXPathLong("string(/domainsnapshot/creationTime)", ctxt
,
9618 localtime_r(&creation
, &time_info
);
9619 strftime(timestr
, sizeof(timestr
), "%Y-%m-%d %H:%M:%S %z", &time_info
);
9621 vshPrint(ctl
, " %-20s %-25s %s\n", names
[i
], timestr
, state
);
9628 /* this frees up memory from the last iteration of the loop */
9631 virDomainSnapshotFree(snapshot
);
9632 xmlXPathFreeContext(ctxt
);
9636 for (i
= 0; i
< actual
; i
++)
9646 * "snapshot-dumpxml" command
9648 static const vshCmdInfo info_snapshot_dumpxml
[] = {
9649 {"help", N_("Dump XML for a domain snapshot")},
9650 {"desc", N_("Snapshot Dump XML")},
9654 static const vshCmdOptDef opts_snapshot_dumpxml
[] = {
9655 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
9656 {"snapshotname", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("snapshot name")},
9661 cmdSnapshotDumpXML(vshControl
*ctl
, const vshCmd
*cmd
)
9663 virDomainPtr dom
= NULL
;
9666 virDomainSnapshotPtr snapshot
= NULL
;
9669 if (!vshConnectionUsability(ctl
, ctl
->conn
))
9672 dom
= vshCommandOptDomain(ctl
, cmd
, NULL
);
9676 name
= vshCommandOptString(cmd
, "snapshotname", NULL
);
9680 snapshot
= virDomainSnapshotLookupByName(dom
, name
, 0);
9681 if (snapshot
== NULL
)
9684 xml
= virDomainSnapshotGetXMLDesc(snapshot
, 0);
9688 vshPrint(ctl
, "%s", xml
);
9695 virDomainSnapshotFree(snapshot
);
9703 * "snapshot-revert" command
9705 static const vshCmdInfo info_snapshot_revert
[] = {
9706 {"help", N_("Revert a domain to a snapshot")},
9707 {"desc", N_("Revert domain to snapshot")},
9711 static const vshCmdOptDef opts_snapshot_revert
[] = {
9712 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
9713 {"snapshotname", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("snapshot name")},
9718 cmdDomainSnapshotRevert(vshControl
*ctl
, const vshCmd
*cmd
)
9720 virDomainPtr dom
= NULL
;
9723 virDomainSnapshotPtr snapshot
= NULL
;
9725 if (!vshConnectionUsability(ctl
, ctl
->conn
))
9728 dom
= vshCommandOptDomain(ctl
, cmd
, NULL
);
9732 name
= vshCommandOptString(cmd
, "snapshotname", NULL
);
9736 snapshot
= virDomainSnapshotLookupByName(dom
, name
, 0);
9737 if (snapshot
== NULL
)
9740 if (virDomainRevertToSnapshot(snapshot
, 0) < 0)
9747 virDomainSnapshotFree(snapshot
);
9755 * "snapshot-delete" command
9757 static const vshCmdInfo info_snapshot_delete
[] = {
9758 {"help", N_("Delete a domain snapshot")},
9759 {"desc", N_("Snapshot Delete")},
9763 static const vshCmdOptDef opts_snapshot_delete
[] = {
9764 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
9765 {"snapshotname", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("snapshot name")},
9766 {"children", VSH_OT_BOOL
, 0, N_("delete snapshot and all children")},
9771 cmdSnapshotDelete(vshControl
*ctl
, const vshCmd
*cmd
)
9773 virDomainPtr dom
= NULL
;
9776 virDomainSnapshotPtr snapshot
= NULL
;
9777 unsigned int flags
= 0;
9779 if (!vshConnectionUsability(ctl
, ctl
->conn
))
9782 dom
= vshCommandOptDomain(ctl
, cmd
, NULL
);
9786 name
= vshCommandOptString(cmd
, "snapshotname", NULL
);
9790 if (vshCommandOptBool(cmd
, "children"))
9791 flags
|= VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN
;
9793 snapshot
= virDomainSnapshotLookupByName(dom
, name
, 0);
9794 if (snapshot
== NULL
)
9797 if (virDomainSnapshotDelete(snapshot
, flags
) < 0)
9804 virDomainSnapshotFree(snapshot
);
9812 * "qemu-monitor-command" command
9814 static const vshCmdInfo info_qemu_monitor_command
[] = {
9815 {"help", N_("Qemu Monitor Command")},
9816 {"desc", N_("Qemu Monitor Command")},
9820 static const vshCmdOptDef opts_qemu_monitor_command
[] = {
9821 {"domain", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("domain name, id or uuid")},
9822 {"cmd", VSH_OT_DATA
, VSH_OFLAG_REQ
, N_("command")},
9827 cmdQemuMonitorCommand(vshControl
*ctl
, const vshCmd
*cmd
)
9829 virDomainPtr dom
= NULL
;
9832 char *result
= NULL
;
9834 if (!vshConnectionUsability(ctl
, ctl
->conn
))
9837 dom
= vshCommandOptDomain(ctl
, cmd
, NULL
);
9841 monitor_cmd
= vshCommandOptString(cmd
, "cmd", NULL
);
9842 if (monitor_cmd
== NULL
) {
9843 vshError(ctl
, "%s", _("missing monitor command"));
9847 if (virDomainQemuMonitorCommand(dom
, monitor_cmd
, &result
, 0) < 0)
9850 printf("%s\n", result
);
9866 static const vshCmdDef commands
[] = {
9867 {"help", cmdHelp
, opts_help
, info_help
},
9868 {"attach-device", cmdAttachDevice
, opts_attach_device
, info_attach_device
},
9869 {"attach-disk", cmdAttachDisk
, opts_attach_disk
, info_attach_disk
},
9870 {"attach-interface", cmdAttachInterface
, opts_attach_interface
, info_attach_interface
},
9871 {"autostart", cmdAutostart
, opts_autostart
, info_autostart
},
9872 {"capabilities", cmdCapabilities
, NULL
, info_capabilities
},
9874 {"cd", cmdCd
, opts_cd
, info_cd
},
9876 {"connect", cmdConnect
, opts_connect
, info_connect
},
9878 {"console", cmdConsole
, opts_console
, info_console
},
9880 {"cpu-baseline", cmdCPUBaseline
, opts_cpu_baseline
, info_cpu_baseline
},
9881 {"cpu-compare", cmdCPUCompare
, opts_cpu_compare
, info_cpu_compare
},
9882 {"create", cmdCreate
, opts_create
, info_create
},
9883 {"start", cmdStart
, opts_start
, info_start
},
9884 {"destroy", cmdDestroy
, opts_destroy
, info_destroy
},
9885 {"detach-device", cmdDetachDevice
, opts_detach_device
, info_detach_device
},
9886 {"detach-disk", cmdDetachDisk
, opts_detach_disk
, info_detach_disk
},
9887 {"detach-interface", cmdDetachInterface
, opts_detach_interface
, info_detach_interface
},
9888 {"define", cmdDefine
, opts_define
, info_define
},
9889 {"domid", cmdDomid
, opts_domid
, info_domid
},
9890 {"domuuid", cmdDomuuid
, opts_domuuid
, info_domuuid
},
9891 {"dominfo", cmdDominfo
, opts_dominfo
, info_dominfo
},
9892 {"domjobinfo", cmdDomjobinfo
, opts_domjobinfo
, info_domjobinfo
},
9893 {"domjobabort", cmdDomjobabort
, opts_domjobabort
, info_domjobabort
},
9894 {"domname", cmdDomname
, opts_domname
, info_domname
},
9895 {"domstate", cmdDomstate
, opts_domstate
, info_domstate
},
9896 {"domblkstat", cmdDomblkstat
, opts_domblkstat
, info_domblkstat
},
9897 {"domifstat", cmdDomIfstat
, opts_domifstat
, info_domifstat
},
9898 {"dommemstat", cmdDomMemStat
, opts_dommemstat
, info_dommemstat
},
9899 {"domblkinfo", cmdDomblkinfo
, opts_domblkinfo
, info_domblkinfo
},
9900 {"domxml-from-native", cmdDomXMLFromNative
, opts_domxmlfromnative
, info_domxmlfromnative
},
9901 {"domxml-to-native", cmdDomXMLToNative
, opts_domxmltonative
, info_domxmltonative
},
9902 {"dumpxml", cmdDumpXML
, opts_dumpxml
, info_dumpxml
},
9903 {"echo", cmdEcho
, opts_echo
, info_echo
},
9904 {"edit", cmdEdit
, opts_edit
, info_edit
},
9905 {"find-storage-pool-sources", cmdPoolDiscoverSources
,
9906 opts_find_storage_pool_sources
, info_find_storage_pool_sources
},
9907 {"find-storage-pool-sources-as", cmdPoolDiscoverSourcesAs
,
9908 opts_find_storage_pool_sources_as
, info_find_storage_pool_sources_as
},
9909 {"freecell", cmdFreecell
, opts_freecell
, info_freecell
},
9910 {"hostname", cmdHostname
, NULL
, info_hostname
},
9911 {"list", cmdList
, opts_list
, info_list
},
9912 {"maxvcpus", cmdMaxvcpus
, opts_maxvcpus
, info_maxvcpus
},
9913 {"migrate", cmdMigrate
, opts_migrate
, info_migrate
},
9914 {"migrate-setmaxdowntime", cmdMigrateSetMaxDowntime
, opts_migrate_setmaxdowntime
, info_migrate_setmaxdowntime
},
9916 {"net-autostart", cmdNetworkAutostart
, opts_network_autostart
, info_network_autostart
},
9917 {"net-create", cmdNetworkCreate
, opts_network_create
, info_network_create
},
9918 {"net-define", cmdNetworkDefine
, opts_network_define
, info_network_define
},
9919 {"net-destroy", cmdNetworkDestroy
, opts_network_destroy
, info_network_destroy
},
9920 {"net-dumpxml", cmdNetworkDumpXML
, opts_network_dumpxml
, info_network_dumpxml
},
9921 {"net-edit", cmdNetworkEdit
, opts_network_edit
, info_network_edit
},
9922 {"net-list", cmdNetworkList
, opts_network_list
, info_network_list
},
9923 {"net-name", cmdNetworkName
, opts_network_name
, info_network_name
},
9924 {"net-start", cmdNetworkStart
, opts_network_start
, info_network_start
},
9925 {"net-undefine", cmdNetworkUndefine
, opts_network_undefine
, info_network_undefine
},
9926 {"net-uuid", cmdNetworkUuid
, opts_network_uuid
, info_network_uuid
},
9928 {"iface-list", cmdInterfaceList
, opts_interface_list
, info_interface_list
},
9929 {"iface-name", cmdInterfaceName
, opts_interface_name
, info_interface_name
},
9930 {"iface-mac", cmdInterfaceMAC
, opts_interface_mac
, info_interface_mac
},
9931 {"iface-dumpxml", cmdInterfaceDumpXML
, opts_interface_dumpxml
, info_interface_dumpxml
},
9932 {"iface-define", cmdInterfaceDefine
, opts_interface_define
, info_interface_define
},
9933 {"iface-undefine", cmdInterfaceUndefine
, opts_interface_undefine
, info_interface_undefine
},
9934 {"iface-edit", cmdInterfaceEdit
, opts_interface_edit
, info_interface_edit
},
9935 {"iface-start", cmdInterfaceStart
, opts_interface_start
, info_interface_start
},
9936 {"iface-destroy", cmdInterfaceDestroy
, opts_interface_destroy
, info_interface_destroy
},
9938 {"managedsave", cmdManagedSave
, opts_managedsave
, info_managedsave
},
9939 {"managedsave-remove", cmdManagedSaveRemove
, opts_managedsaveremove
, info_managedsaveremove
},
9941 {"nodeinfo", cmdNodeinfo
, NULL
, info_nodeinfo
},
9943 {"nodedev-list", cmdNodeListDevices
, opts_node_list_devices
, info_node_list_devices
},
9944 {"nodedev-dumpxml", cmdNodeDeviceDumpXML
, opts_node_device_dumpxml
, info_node_device_dumpxml
},
9945 {"nodedev-dettach", cmdNodeDeviceDettach
, opts_node_device_dettach
, info_node_device_dettach
},
9946 {"nodedev-reattach", cmdNodeDeviceReAttach
, opts_node_device_reattach
, info_node_device_reattach
},
9947 {"nodedev-reset", cmdNodeDeviceReset
, opts_node_device_reset
, info_node_device_reset
},
9948 {"nodedev-create", cmdNodeDeviceCreate
, opts_node_device_create
, info_node_device_create
},
9949 {"nodedev-destroy", cmdNodeDeviceDestroy
, opts_node_device_destroy
, info_node_device_destroy
},
9951 {"nwfilter-define", cmdNWFilterDefine
, opts_nwfilter_define
, info_nwfilter_define
},
9952 {"nwfilter-undefine", cmdNWFilterUndefine
, opts_nwfilter_undefine
, info_nwfilter_undefine
},
9953 {"nwfilter-dumpxml", cmdNWFilterDumpXML
, opts_nwfilter_dumpxml
, info_nwfilter_dumpxml
},
9954 {"nwfilter-list", cmdNWFilterList
, opts_nwfilter_list
, info_nwfilter_list
},
9955 {"nwfilter-edit", cmdNWFilterEdit
, opts_nwfilter_edit
, info_nwfilter_edit
},
9957 {"pool-autostart", cmdPoolAutostart
, opts_pool_autostart
, info_pool_autostart
},
9958 {"pool-build", cmdPoolBuild
, opts_pool_build
, info_pool_build
},
9959 {"pool-create", cmdPoolCreate
, opts_pool_create
, info_pool_create
},
9960 {"pool-create-as", cmdPoolCreateAs
, opts_pool_X_as
, info_pool_create_as
},
9961 {"pool-define", cmdPoolDefine
, opts_pool_define
, info_pool_define
},
9962 {"pool-define-as", cmdPoolDefineAs
, opts_pool_X_as
, info_pool_define_as
},
9963 {"pool-destroy", cmdPoolDestroy
, opts_pool_destroy
, info_pool_destroy
},
9964 {"pool-delete", cmdPoolDelete
, opts_pool_delete
, info_pool_delete
},
9965 {"pool-dumpxml", cmdPoolDumpXML
, opts_pool_dumpxml
, info_pool_dumpxml
},
9966 {"pool-edit", cmdPoolEdit
, opts_pool_edit
, info_pool_edit
},
9967 {"pool-info", cmdPoolInfo
, opts_pool_info
, info_pool_info
},
9968 {"pool-list", cmdPoolList
, opts_pool_list
, info_pool_list
},
9969 {"pool-name", cmdPoolName
, opts_pool_name
, info_pool_name
},
9970 {"pool-refresh", cmdPoolRefresh
, opts_pool_refresh
, info_pool_refresh
},
9971 {"pool-start", cmdPoolStart
, opts_pool_start
, info_pool_start
},
9972 {"pool-undefine", cmdPoolUndefine
, opts_pool_undefine
, info_pool_undefine
},
9973 {"pool-uuid", cmdPoolUuid
, opts_pool_uuid
, info_pool_uuid
},
9975 {"secret-define", cmdSecretDefine
, opts_secret_define
, info_secret_define
},
9976 {"secret-dumpxml", cmdSecretDumpXML
, opts_secret_dumpxml
, info_secret_dumpxml
},
9977 {"secret-set-value", cmdSecretSetValue
, opts_secret_set_value
, info_secret_set_value
},
9978 {"secret-get-value", cmdSecretGetValue
, opts_secret_get_value
, info_secret_get_value
},
9979 {"secret-undefine", cmdSecretUndefine
, opts_secret_undefine
, info_secret_undefine
},
9980 {"secret-list", cmdSecretList
, NULL
, info_secret_list
},
9984 {"pwd", cmdPwd
, NULL
, info_pwd
},
9986 {"quit", cmdQuit
, NULL
, info_quit
},
9987 {"exit", cmdQuit
, NULL
, info_quit
},
9988 {"reboot", cmdReboot
, opts_reboot
, info_reboot
},
9989 {"restore", cmdRestore
, opts_restore
, info_restore
},
9990 {"resume", cmdResume
, opts_resume
, info_resume
},
9991 {"save", cmdSave
, opts_save
, info_save
},
9992 {"schedinfo", cmdSchedinfo
, opts_schedinfo
, info_schedinfo
},
9993 {"dump", cmdDump
, opts_dump
, info_dump
},
9994 {"shutdown", cmdShutdown
, opts_shutdown
, info_shutdown
},
9995 {"setmem", cmdSetmem
, opts_setmem
, info_setmem
},
9996 {"setmaxmem", cmdSetmaxmem
, opts_setmaxmem
, info_setmaxmem
},
9997 {"memtune", cmdMemtune
, opts_memtune
, info_memtune
},
9998 {"setvcpus", cmdSetvcpus
, opts_setvcpus
, info_setvcpus
},
9999 {"suspend", cmdSuspend
, opts_suspend
, info_suspend
},
10000 {"ttyconsole", cmdTTYConsole
, opts_ttyconsole
, info_ttyconsole
},
10001 {"undefine", cmdUndefine
, opts_undefine
, info_undefine
},
10002 {"update-device", cmdUpdateDevice
, opts_update_device
, info_update_device
},
10003 {"uri", cmdURI
, NULL
, info_uri
},
10005 {"vol-create", cmdVolCreate
, opts_vol_create
, info_vol_create
},
10006 {"vol-create-from", cmdVolCreateFrom
, opts_vol_create_from
, info_vol_create_from
},
10007 {"vol-create-as", cmdVolCreateAs
, opts_vol_create_as
, info_vol_create_as
},
10008 {"vol-clone", cmdVolClone
, opts_vol_clone
, info_vol_clone
},
10009 {"vol-delete", cmdVolDelete
, opts_vol_delete
, info_vol_delete
},
10010 {"vol-wipe", cmdVolWipe
, opts_vol_wipe
, info_vol_wipe
},
10011 {"vol-dumpxml", cmdVolDumpXML
, opts_vol_dumpxml
, info_vol_dumpxml
},
10012 {"vol-info", cmdVolInfo
, opts_vol_info
, info_vol_info
},
10013 {"vol-list", cmdVolList
, opts_vol_list
, info_vol_list
},
10014 {"vol-pool", cmdVolPool
, opts_vol_pool
, info_vol_pool
},
10015 {"vol-path", cmdVolPath
, opts_vol_path
, info_vol_path
},
10016 {"vol-name", cmdVolName
, opts_vol_name
, info_vol_name
},
10017 {"vol-key", cmdVolKey
, opts_vol_key
, info_vol_key
},
10019 {"vcpucount", cmdVcpucount
, opts_vcpucount
, info_vcpucount
},
10020 {"vcpuinfo", cmdVcpuinfo
, opts_vcpuinfo
, info_vcpuinfo
},
10021 {"vcpupin", cmdVcpupin
, opts_vcpupin
, info_vcpupin
},
10022 {"version", cmdVersion
, NULL
, info_version
},
10023 {"vncdisplay", cmdVNCDisplay
, opts_vncdisplay
, info_vncdisplay
},
10025 {"snapshot-create", cmdSnapshotCreate
, opts_snapshot_create
, info_snapshot_create
},
10026 {"snapshot-current", cmdSnapshotCurrent
, opts_snapshot_current
, info_snapshot_current
},
10027 {"snapshot-delete", cmdSnapshotDelete
, opts_snapshot_delete
, info_snapshot_delete
},
10028 {"snapshot-dumpxml", cmdSnapshotDumpXML
, opts_snapshot_dumpxml
, info_snapshot_dumpxml
},
10029 {"snapshot-list", cmdSnapshotList
, opts_snapshot_list
, info_snapshot_list
},
10030 {"snapshot-revert", cmdDomainSnapshotRevert
, opts_snapshot_revert
, info_snapshot_revert
},
10032 {"qemu-monitor-command", cmdQemuMonitorCommand
, opts_qemu_monitor_command
, info_qemu_monitor_command
},
10034 {NULL
, NULL
, NULL
, NULL
}
10038 * Utils for work with command definition
10041 static const char *
10042 vshCmddefGetInfo(const vshCmdDef
* cmd
, const char *name
)
10044 const vshCmdInfo
*info
;
10046 for (info
= cmd
->info
; info
&& info
->name
; info
++) {
10047 if (STREQ(info
->name
, name
))
10053 static const vshCmdOptDef
*
10054 vshCmddefGetOption(const vshCmdDef
* cmd
, const char *name
)
10056 const vshCmdOptDef
*opt
;
10058 for (opt
= cmd
->opts
; opt
&& opt
->name
; opt
++)
10059 if (STREQ(opt
->name
, name
))
10064 static const vshCmdOptDef
*
10065 vshCmddefGetData(const vshCmdDef
* cmd
, int data_ct
)
10067 const vshCmdOptDef
*opt
;
10069 for (opt
= cmd
->opts
; opt
&& opt
->name
; opt
++) {
10070 if (opt
->type
>= VSH_OT_DATA
||
10071 (opt
->type
== VSH_OT_INT
&& (opt
->flag
& VSH_OFLAG_REQ
))) {
10072 if (data_ct
== 0 || opt
->type
== VSH_OT_ARGV
)
10082 * Checks for required options
10085 vshCommandCheckOpts(vshControl
*ctl
, const vshCmd
*cmd
)
10087 const vshCmdDef
*def
= cmd
->def
;
10088 const vshCmdOptDef
*d
;
10091 for (d
= def
->opts
; d
&& d
->name
; d
++) {
10092 if (d
->flag
& VSH_OFLAG_REQ
) {
10093 vshCmdOpt
*o
= cmd
->opts
;
10096 while (o
&& ok
== 0) {
10103 d
->type
== VSH_OT_DATA
?
10104 _("command '%s' requires <%s> option") :
10105 _("command '%s' requires --%s option"),
10106 def
->name
, d
->name
);
10115 static const vshCmdDef
*
10116 vshCmddefSearch(const char *cmdname
)
10118 const vshCmdDef
*c
;
10120 for (c
= commands
; c
->name
; c
++)
10121 if (STREQ(c
->name
, cmdname
))
10127 vshCmddefHelp(vshControl
*ctl
, const char *cmdname
)
10129 const vshCmdDef
*def
= vshCmddefSearch(cmdname
);
10132 vshError(ctl
, _("command '%s' doesn't exist"), cmdname
);
10135 const char *desc
= _(vshCmddefGetInfo(def
, "desc"));
10136 const char *help
= _(vshCmddefGetInfo(def
, "help"));
10139 fputs(_(" NAME\n"), stdout
);
10140 fprintf(stdout
, " %s - %s\n", def
->name
, help
);
10142 fputs(_("\n SYNOPSIS\n"), stdout
);
10143 fprintf(stdout
, " %s", def
->name
);
10145 const vshCmdOptDef
*opt
;
10146 for (opt
= def
->opts
; opt
->name
; opt
++) {
10148 switch (opt
->type
) {
10153 /* xgettext:c-format */
10154 fmt
= ((opt
->flag
& VSH_OFLAG_REQ
) ? "<%s>"
10155 : _("[--%s <number>]"));
10157 case VSH_OT_STRING
:
10158 /* xgettext:c-format */
10159 fmt
= _("[--%s <string>]");
10162 fmt
= ((opt
->flag
& VSH_OFLAG_REQ
) ? "<%s>" : "[<%s>]");
10165 /* xgettext:c-format */
10166 fmt
= _("[<string>]...");
10171 fputc(' ', stdout
);
10172 fprintf(stdout
, fmt
, opt
->name
);
10175 fputc('\n', stdout
);
10178 /* Print the description only if it's not empty. */
10179 fputs(_("\n DESCRIPTION\n"), stdout
);
10180 fprintf(stdout
, " %s\n", desc
);
10184 const vshCmdOptDef
*opt
;
10185 fputs(_("\n OPTIONS\n"), stdout
);
10186 for (opt
= def
->opts
; opt
->name
; opt
++) {
10187 switch (opt
->type
) {
10189 snprintf(buf
, sizeof(buf
), "--%s", opt
->name
);
10192 snprintf(buf
, sizeof(buf
),
10193 (opt
->flag
& VSH_OFLAG_REQ
) ? _("[--%s] <number>")
10194 : _("--%s <number>"), opt
->name
);
10196 case VSH_OT_STRING
:
10197 /* OT_STRING should never be VSH_OFLAG_REQ */
10198 snprintf(buf
, sizeof(buf
), _("--%s <string>"), opt
->name
);
10201 snprintf(buf
, sizeof(buf
), _("[--%s] <string>"),
10205 /* Not really an option. */
10211 fprintf(stdout
, " %-15s %s\n", buf
, _(opt
->help
));
10214 fputc('\n', stdout
);
10220 * Utils for work with runtime commands data
10224 vshCommandOptFree(vshCmdOpt
* arg
)
10226 vshCmdOpt
*a
= arg
;
10229 vshCmdOpt
*tmp
= a
;
10233 VIR_FREE(tmp
->data
);
10239 vshCommandFree(vshCmd
*cmd
)
10249 vshCommandOptFree(tmp
->opts
);
10255 * Returns option by name
10258 vshCommandOpt(const vshCmd
*cmd
, const char *name
)
10260 vshCmdOpt
*opt
= cmd
->opts
;
10263 if (opt
->def
&& STREQ(opt
->def
->name
, name
))
10271 * Returns option as INT
10274 vshCommandOptInt(const vshCmd
*cmd
, const char *name
, int *found
)
10276 vshCmdOpt
*arg
= vshCommandOpt(cmd
, name
);
10277 int res
= 0, num_found
= FALSE
;
10278 char *end_p
= NULL
;
10280 if ((arg
!= NULL
) && (arg
->data
!= NULL
)) {
10281 res
= strtol(arg
->data
, &end_p
, 10);
10282 if ((arg
->data
== end_p
) || (*end_p
!= 0))
10288 *found
= num_found
;
10292 static unsigned long
10293 vshCommandOptUL(const vshCmd
*cmd
, const char *name
, int *found
)
10295 vshCmdOpt
*arg
= vshCommandOpt(cmd
, name
);
10296 unsigned long res
= 0;
10297 int num_found
= FALSE
;
10298 char *end_p
= NULL
;
10300 if ((arg
!= NULL
) && (arg
->data
!= NULL
)) {
10301 res
= strtoul(arg
->data
, &end_p
, 10);
10302 if ((arg
->data
== end_p
) || (*end_p
!= 0))
10308 *found
= num_found
;
10313 * Returns option as STRING
10316 vshCommandOptString(const vshCmd
*cmd
, const char *name
, int *found
)
10318 vshCmdOpt
*arg
= vshCommandOpt(cmd
, name
);
10321 *found
= arg
? TRUE
: FALSE
;
10323 if (arg
&& arg
->data
&& *arg
->data
)
10326 if (arg
&& arg
->def
&& ((arg
->def
->flag
) & VSH_OFLAG_REQ
))
10327 vshError(NULL
, _("Missing required option '%s'"), name
);
10333 * Returns option as long long
10336 vshCommandOptLongLong(const vshCmd
*cmd
, const char *name
, int *found
)
10338 vshCmdOpt
*arg
= vshCommandOpt(cmd
, name
);
10339 int num_found
= FALSE
;
10341 char *end_p
= NULL
;
10343 if ((arg
!= NULL
) && (arg
->data
!= NULL
))
10344 num_found
= !virStrToLong_ll(arg
->data
, &end_p
, 10, &res
);
10346 *found
= num_found
;
10351 * Returns TRUE/FALSE if the option exists
10354 vshCommandOptBool(const vshCmd
*cmd
, const char *name
)
10356 return vshCommandOpt(cmd
, name
) ? TRUE
: FALSE
;
10360 * Returns the COUNT argv argument, or NULL after last argument.
10362 * Requires that a VSH_OT_ARGV option with the name "" be last in the
10363 * list of supported options in CMD->def->opts.
10366 vshCommandOptArgv(const vshCmd
*cmd
, int count
)
10368 vshCmdOpt
*opt
= cmd
->opts
;
10371 if (opt
->def
&& opt
->def
->type
== VSH_OT_ARGV
) {
10380 /* Determine whether CMD->opts includes an option with name OPTNAME.
10381 If not, give a diagnostic and return false.
10382 If so, return true. */
10384 cmd_has_option (vshControl
*ctl
, const vshCmd
*cmd
, const char *optname
)
10386 /* Iterate through cmd->opts, to ensure that there is an entry
10387 with name OPTNAME and type VSH_OT_DATA. */
10388 bool found
= false;
10389 const vshCmdOpt
*opt
;
10390 for (opt
= cmd
->opts
; opt
; opt
= opt
->next
) {
10391 if (STREQ (opt
->def
->name
, optname
) && opt
->def
->type
== VSH_OT_DATA
) {
10398 vshError(ctl
, _("internal error: virsh %s: no %s VSH_OT_DATA option"),
10399 cmd
->def
->name
, optname
);
10403 static virDomainPtr
10404 vshCommandOptDomainBy(vshControl
*ctl
, const vshCmd
*cmd
,
10405 char **name
, int flag
)
10407 virDomainPtr dom
= NULL
;
10410 const char *optname
= "domain";
10411 if (!cmd_has_option (ctl
, cmd
, optname
))
10414 if (!(n
= vshCommandOptString(cmd
, optname
, NULL
)))
10417 vshDebug(ctl
, 5, "%s: found option <%s>: %s\n",
10418 cmd
->def
->name
, optname
, n
);
10424 if (flag
& VSH_BYID
) {
10425 if (virStrToLong_i(n
, NULL
, 10, &id
) == 0 && id
>= 0) {
10426 vshDebug(ctl
, 5, "%s: <%s> seems like domain ID\n",
10427 cmd
->def
->name
, optname
);
10428 dom
= virDomainLookupByID(ctl
->conn
, id
);
10431 /* try it by UUID */
10432 if (dom
==NULL
&& (flag
& VSH_BYUUID
) && strlen(n
)==VIR_UUID_STRING_BUFLEN
-1) {
10433 vshDebug(ctl
, 5, "%s: <%s> trying as domain UUID\n",
10434 cmd
->def
->name
, optname
);
10435 dom
= virDomainLookupByUUIDString(ctl
->conn
, n
);
10437 /* try it by NAME */
10438 if (dom
==NULL
&& (flag
& VSH_BYNAME
)) {
10439 vshDebug(ctl
, 5, "%s: <%s> trying as domain NAME\n",
10440 cmd
->def
->name
, optname
);
10441 dom
= virDomainLookupByName(ctl
->conn
, n
);
10445 vshError(ctl
, _("failed to get domain '%s'"), n
);
10450 static virNetworkPtr
10451 vshCommandOptNetworkBy(vshControl
*ctl
, const vshCmd
*cmd
,
10452 char **name
, int flag
)
10454 virNetworkPtr network
= NULL
;
10456 const char *optname
= "network";
10457 if (!cmd_has_option (ctl
, cmd
, optname
))
10460 if (!(n
= vshCommandOptString(cmd
, optname
, NULL
)))
10463 vshDebug(ctl
, 5, "%s: found option <%s>: %s\n",
10464 cmd
->def
->name
, optname
, n
);
10469 /* try it by UUID */
10470 if ((flag
& VSH_BYUUID
) && (strlen(n
) == VIR_UUID_STRING_BUFLEN
-1)) {
10471 vshDebug(ctl
, 5, "%s: <%s> trying as network UUID\n",
10472 cmd
->def
->name
, optname
);
10473 network
= virNetworkLookupByUUIDString(ctl
->conn
, n
);
10475 /* try it by NAME */
10476 if (network
==NULL
&& (flag
& VSH_BYNAME
)) {
10477 vshDebug(ctl
, 5, "%s: <%s> trying as network NAME\n",
10478 cmd
->def
->name
, optname
);
10479 network
= virNetworkLookupByName(ctl
->conn
, n
);
10483 vshError(ctl
, _("failed to get network '%s'"), n
);
10489 static virNWFilterPtr
10490 vshCommandOptNWFilterBy(vshControl
*ctl
, const vshCmd
*cmd
,
10491 char **name
, int flag
)
10493 virNWFilterPtr nwfilter
= NULL
;
10495 const char *optname
= "nwfilter";
10496 if (!cmd_has_option (ctl
, cmd
, optname
))
10499 if (!(n
= vshCommandOptString(cmd
, optname
, NULL
)))
10502 vshDebug(ctl
, 5, "%s: found option <%s>: %s\n",
10503 cmd
->def
->name
, optname
, n
);
10508 /* try it by UUID */
10509 if ((flag
& VSH_BYUUID
) && (strlen(n
) == VIR_UUID_STRING_BUFLEN
-1)) {
10510 vshDebug(ctl
, 5, "%s: <%s> trying as nwfilter UUID\n",
10511 cmd
->def
->name
, optname
);
10512 nwfilter
= virNWFilterLookupByUUIDString(ctl
->conn
, n
);
10514 /* try it by NAME */
10515 if (nwfilter
== NULL
&& (flag
& VSH_BYNAME
)) {
10516 vshDebug(ctl
, 5, "%s: <%s> trying as nwfilter NAME\n",
10517 cmd
->def
->name
, optname
);
10518 nwfilter
= virNWFilterLookupByName(ctl
->conn
, n
);
10522 vshError(ctl
, _("failed to get nwfilter '%s'"), n
);
10527 static virInterfacePtr
10528 vshCommandOptInterfaceBy(vshControl
*ctl
, const vshCmd
*cmd
,
10529 char **name
, int flag
)
10531 virInterfacePtr iface
= NULL
;
10533 const char *optname
= "interface";
10534 if (!cmd_has_option (ctl
, cmd
, optname
))
10537 if (!(n
= vshCommandOptString(cmd
, optname
, NULL
)))
10540 vshDebug(ctl
, 5, "%s: found option <%s>: %s\n",
10541 cmd
->def
->name
, optname
, n
);
10546 /* try it by NAME */
10547 if ((flag
& VSH_BYNAME
)) {
10548 vshDebug(ctl
, 5, "%s: <%s> trying as interface NAME\n",
10549 cmd
->def
->name
, optname
);
10550 iface
= virInterfaceLookupByName(ctl
->conn
, n
);
10552 /* try it by MAC */
10553 if ((iface
== NULL
) && (flag
& VSH_BYMAC
)) {
10554 vshDebug(ctl
, 5, "%s: <%s> trying as interface MAC\n",
10555 cmd
->def
->name
, optname
);
10556 iface
= virInterfaceLookupByMACString(ctl
->conn
, n
);
10560 vshError(ctl
, _("failed to get interface '%s'"), n
);
10565 static virStoragePoolPtr
10566 vshCommandOptPoolBy(vshControl
*ctl
, const vshCmd
*cmd
, const char *optname
,
10567 char **name
, int flag
)
10569 virStoragePoolPtr pool
= NULL
;
10572 if (!(n
= vshCommandOptString(cmd
, optname
, NULL
)))
10575 vshDebug(ctl
, 5, "%s: found option <%s>: %s\n",
10576 cmd
->def
->name
, optname
, n
);
10581 /* try it by UUID */
10582 if ((flag
& VSH_BYUUID
) && (strlen(n
) == VIR_UUID_STRING_BUFLEN
-1)) {
10583 vshDebug(ctl
, 5, "%s: <%s> trying as pool UUID\n",
10584 cmd
->def
->name
, optname
);
10585 pool
= virStoragePoolLookupByUUIDString(ctl
->conn
, n
);
10587 /* try it by NAME */
10588 if (pool
== NULL
&& (flag
& VSH_BYNAME
)) {
10589 vshDebug(ctl
, 5, "%s: <%s> trying as pool NAME\n",
10590 cmd
->def
->name
, optname
);
10591 pool
= virStoragePoolLookupByName(ctl
->conn
, n
);
10595 vshError(ctl
, _("failed to get pool '%s'"), n
);
10600 static virStorageVolPtr
10601 vshCommandOptVolBy(vshControl
*ctl
, const vshCmd
*cmd
,
10602 const char *optname
,
10603 const char *pooloptname
,
10604 char **name
, int flag
)
10606 virStorageVolPtr vol
= NULL
;
10607 virStoragePoolPtr pool
= NULL
;
10611 if (!(n
= vshCommandOptString(cmd
, optname
, NULL
)))
10614 if (!(p
= vshCommandOptString(cmd
, pooloptname
, &found
)) && found
)
10618 pool
= vshCommandOptPoolBy(ctl
, cmd
, pooloptname
, name
, flag
);
10620 vshDebug(ctl
, 5, "%s: found option <%s>: %s\n",
10621 cmd
->def
->name
, optname
, n
);
10626 /* try it by name */
10627 if (pool
&& (flag
& VSH_BYNAME
)) {
10628 vshDebug(ctl
, 5, "%s: <%s> trying as vol name\n",
10629 cmd
->def
->name
, optname
);
10630 vol
= virStorageVolLookupByName(pool
, n
);
10632 /* try it by key */
10633 if (vol
== NULL
&& (flag
& VSH_BYUUID
)) {
10634 vshDebug(ctl
, 5, "%s: <%s> trying as vol key\n",
10635 cmd
->def
->name
, optname
);
10636 vol
= virStorageVolLookupByKey(ctl
->conn
, n
);
10638 /* try it by path */
10639 if (vol
== NULL
&& (flag
& VSH_BYUUID
)) {
10640 vshDebug(ctl
, 5, "%s: <%s> trying as vol path\n",
10641 cmd
->def
->name
, optname
);
10642 vol
= virStorageVolLookupByPath(ctl
->conn
, n
);
10646 vshError(ctl
, _("failed to get vol '%s'"), n
);
10649 virStoragePoolFree(pool
);
10654 static virSecretPtr
10655 vshCommandOptSecret(vshControl
*ctl
, const vshCmd
*cmd
, char **name
)
10657 virSecretPtr secret
= NULL
;
10659 const char *optname
= "secret";
10661 if (!cmd_has_option (ctl
, cmd
, optname
))
10664 n
= vshCommandOptString(cmd
, optname
, NULL
);
10668 vshDebug(ctl
, 5, "%s: found option <%s>: %s\n", cmd
->def
->name
, optname
, n
);
10673 secret
= virSecretLookupByUUIDString(ctl
->conn
, n
);
10675 if (secret
== NULL
)
10676 vshError(ctl
, _("failed to get secret '%s'"), n
);
10682 * Executes command(s) and returns return code from last command
10685 vshCommandRun(vshControl
*ctl
, const vshCmd
*cmd
)
10690 struct timeval before
, after
;
10691 bool enable_timing
= ctl
->timing
;
10693 if ((ctl
->conn
== NULL
) || (disconnected
!= 0))
10697 GETTIMEOFDAY(&before
);
10699 ret
= cmd
->def
->handler(ctl
, cmd
);
10702 GETTIMEOFDAY(&after
);
10705 virshReportError(ctl
);
10707 /* try to automatically catch disconnections */
10708 if ((ret
== FALSE
) &&
10709 ((disconnected
!= 0) ||
10710 ((last_error
!= NULL
) &&
10711 (((last_error
->code
== VIR_ERR_SYSTEM_ERROR
) &&
10712 (last_error
->domain
== VIR_FROM_REMOTE
)) ||
10713 (last_error
->code
== VIR_ERR_RPC
) ||
10714 (last_error
->code
== VIR_ERR_NO_CONNECT
) ||
10715 (last_error
->code
== VIR_ERR_INVALID_CONN
)))))
10718 if (STREQ(cmd
->def
->name
, "quit")) /* hack ... */
10722 vshPrint(ctl
, _("\n(Time: %.3f ms)\n\n"),
10723 DIFF_MSEC(&after
, &before
));
10725 vshPrintExtra(ctl
, "\n");
10737 VSH_TK_ERROR
, /* Failed to parse a token */
10738 VSH_TK_ARG
, /* Arbitrary argument, might be option or empty */
10739 VSH_TK_SUBCMD_END
, /* Separation between commands */
10740 VSH_TK_END
/* No more commands */
10743 typedef struct __vshCommandParser
{
10744 vshCommandToken (*getNextArg
)(vshControl
*, struct __vshCommandParser
*,
10746 /* vshCommandStringGetArg() */
10748 /* vshCommandArgvGetArg() */
10751 } vshCommandParser
;
10754 vshCommandParse(vshControl
*ctl
, vshCommandParser
*parser
)
10756 char *tkdata
= NULL
;
10757 vshCmd
*clast
= NULL
;
10758 vshCmdOpt
*first
= NULL
;
10761 vshCommandFree(ctl
->cmd
);
10766 vshCmdOpt
*last
= NULL
;
10767 const vshCmdDef
*cmd
= NULL
;
10768 vshCommandToken tk
;
10769 bool data_only
= false;
10775 const vshCmdOptDef
*opt
= NULL
;
10778 tk
= parser
->getNextArg(ctl
, parser
, &tkdata
);
10780 if (tk
== VSH_TK_ERROR
)
10782 if (tk
!= VSH_TK_ARG
)
10786 /* first token must be command name */
10787 if (!(cmd
= vshCmddefSearch(tkdata
))) {
10788 vshError(ctl
, _("unknown command: '%s'"), tkdata
);
10789 goto syntaxError
; /* ... or ignore this command only? */
10792 } else if (data_only
) {
10794 } else if (tkdata
[0] == '-' && tkdata
[1] == '-' &&
10795 c_isalnum(tkdata
[2])) {
10796 char *optstr
= strchr(tkdata
+ 2, '=');
10798 *optstr
= '\0'; /* convert the '=' to '\0' */
10799 optstr
= vshStrdup(ctl
, optstr
+ 1);
10801 if (!(opt
= vshCmddefGetOption(cmd
, tkdata
+ 2))) {
10803 _("command '%s' doesn't support option --%s"),
10804 cmd
->name
, tkdata
+ 2);
10810 if (opt
->type
!= VSH_OT_BOOL
) {
10815 tk
= parser
->getNextArg(ctl
, parser
, &tkdata
);
10816 if (tk
== VSH_TK_ERROR
)
10818 if (tk
!= VSH_TK_ARG
) {
10820 _("expected syntax: --%s <%s>"),
10823 VSH_OT_INT
? _("number") : _("string"));
10829 vshError(ctl
, _("invalid '=' after option --%s"),
10835 } else if (tkdata
[0] == '-' && tkdata
[1] == '-' &&
10836 tkdata
[2] == '\0') {
10841 if (!(opt
= vshCmddefGetData(cmd
, data_ct
++))) {
10842 vshError(ctl
, _("unexpected data '%s'"), tkdata
);
10848 vshCmdOpt
*arg
= vshMalloc(ctl
, sizeof(vshCmdOpt
));
10851 arg
->data
= tkdata
;
10861 vshDebug(ctl
, 4, "%s: %s(%s): %s\n",
10864 opt
->type
!= VSH_OT_BOOL
? _("optdata") : _("bool"),
10865 opt
->type
!= VSH_OT_BOOL
? arg
->data
: _("(none)"));
10869 /* command parsed -- allocate new struct for the command */
10871 vshCmd
*c
= vshMalloc(ctl
, sizeof(vshCmd
));
10877 if (!vshCommandCheckOpts(ctl
, c
)) {
10889 if (tk
== VSH_TK_END
)
10897 vshCommandFree(ctl
->cmd
);
10901 vshCommandOptFree(first
);
10906 /* --------------------
10907 * Command argv parsing
10908 * --------------------
10911 static vshCommandToken
ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
10912 vshCommandArgvGetArg(vshControl
*ctl
, vshCommandParser
*parser
, char **res
)
10914 if (parser
->arg_pos
== parser
->arg_end
) {
10919 *res
= vshStrdup(ctl
, *parser
->arg_pos
);
10924 static int vshCommandArgvParse(vshControl
*ctl
, int nargs
, char **argv
)
10926 vshCommandParser parser
;
10931 parser
.arg_pos
= argv
;
10932 parser
.arg_end
= argv
+ nargs
;
10933 parser
.getNextArg
= vshCommandArgvGetArg
;
10934 return vshCommandParse(ctl
, &parser
);
10937 /* ----------------------
10938 * Command string parsing
10939 * ----------------------
10942 static vshCommandToken
ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
10943 vshCommandStringGetArg(vshControl
*ctl
, vshCommandParser
*parser
, char **res
)
10945 bool single_quote
= false;
10946 bool double_quote
= false;
10948 char *p
= parser
->pos
;
10949 char *q
= vshStrdup(ctl
, p
);
10953 while (*p
&& (*p
== ' ' || *p
== '\t'))
10959 parser
->pos
= ++p
; /* = \0 or begin of next command */
10960 return VSH_TK_SUBCMD_END
;
10964 /* end of token is blank space or ';' */
10965 if (!double_quote
&& !single_quote
&&
10966 (*p
== ' ' || *p
== '\t' || *p
== ';'))
10969 if (!double_quote
&& *p
== '\'') { /* single quote */
10970 single_quote
= !single_quote
;
10973 } else if (!single_quote
&& *p
== '\\') { /* escape */
10975 * The same as the bash, a \ in "" is an escaper,
10976 * but a \ in '' is not an escaper.
10980 vshError(ctl
, "%s", _("dangling \\"));
10981 return VSH_TK_ERROR
;
10983 } else if (!single_quote
&& *p
== '"') { /* double quote */
10984 double_quote
= !double_quote
;
10992 if (double_quote
) {
10993 vshError(ctl
, "%s", _("missing \""));
10994 return VSH_TK_ERROR
;
11002 static int vshCommandStringParse(vshControl
*ctl
, char *cmdstr
)
11004 vshCommandParser parser
;
11006 if (cmdstr
== NULL
|| *cmdstr
== '\0')
11009 parser
.pos
= cmdstr
;
11010 parser
.getNextArg
= vshCommandStringGetArg
;
11011 return vshCommandParse(ctl
, &parser
);
11018 static const char *
11019 vshDomainStateToString(int state
)
11022 case VIR_DOMAIN_RUNNING
:
11023 return N_("running");
11024 case VIR_DOMAIN_BLOCKED
:
11026 case VIR_DOMAIN_PAUSED
:
11027 return N_("paused");
11028 case VIR_DOMAIN_SHUTDOWN
:
11029 return N_("in shutdown");
11030 case VIR_DOMAIN_SHUTOFF
:
11031 return N_("shut off");
11032 case VIR_DOMAIN_CRASHED
:
11033 return N_("crashed");
11037 return N_("no state"); /* = dom0 state */
11040 static const char *
11041 vshDomainVcpuStateToString(int state
)
11044 case VIR_VCPU_OFFLINE
:
11045 return N_("offline");
11046 case VIR_VCPU_BLOCKED
:
11048 case VIR_VCPU_RUNNING
:
11049 return N_("running");
11053 return N_("no state");
11057 vshConnectionUsability(vshControl
*ctl
, virConnectPtr conn
)
11059 /* TODO: use something like virConnectionState() to
11060 * check usability of the connection
11063 vshError(ctl
, "%s", _("no valid connection"));
11070 vshDebug(vshControl
*ctl
, int level
, const char *format
, ...)
11074 va_start(ap
, format
);
11075 vshOutputLogFile(ctl
, VSH_ERR_DEBUG
, format
, ap
);
11078 if (level
> ctl
->debug
)
11081 va_start(ap
, format
);
11082 vfprintf(stdout
, format
, ap
);
11087 vshPrintExtra(vshControl
*ctl
, const char *format
, ...)
11091 if (ctl
->quiet
== TRUE
)
11094 va_start(ap
, format
);
11095 vfprintf(stdout
, format
, ap
);
11101 vshError(vshControl
*ctl
, const char *format
, ...)
11106 va_start(ap
, format
);
11107 vshOutputLogFile(ctl
, VSH_ERR_ERROR
, format
, ap
);
11111 fputs(_("error: "), stderr
);
11113 va_start(ap
, format
);
11114 vfprintf(stderr
, format
, ap
);
11117 fputc('\n', stderr
);
11121 * Initialize connection.
11124 vshInit(vshControl
*ctl
)
11129 vshOpenLogFile(ctl
);
11131 /* set up the library error handler */
11132 virSetErrorFunc(NULL
, virshErrorHandler
);
11134 /* set up the signals handlers to catch disconnections */
11137 ctl
->conn
= virConnectOpenAuth(ctl
->name
,
11138 virConnectAuthPtrDefault
,
11139 ctl
->readonly
? VIR_CONNECT_RO
: 0);
11142 /* This is not necessarily fatal. All the individual commands check
11143 * vshConnectionUsability, except ones which don't need a connection
11147 virshReportError(ctl
);
11148 vshError(ctl
, "%s", _("failed to connect to the hypervisor"));
11155 #define LOGFILE_FLAGS (O_WRONLY | O_APPEND | O_CREAT | O_SYNC)
11163 vshOpenLogFile(vshControl
*ctl
)
11167 if (ctl
->logfile
== NULL
)
11170 /* check log file */
11171 if (stat(ctl
->logfile
, &st
) == -1) {
11176 vshError(ctl
, "%s",
11177 _("failed to get the log file information"));
11178 exit(EXIT_FAILURE
);
11181 if (!S_ISREG(st
.st_mode
)) {
11182 vshError(ctl
, "%s", _("the log path is not a file"));
11183 exit(EXIT_FAILURE
);
11187 /* log file open */
11188 if ((ctl
->log_fd
= open(ctl
->logfile
, LOGFILE_FLAGS
, FILE_MODE
)) < 0) {
11189 vshError(ctl
, "%s",
11190 _("failed to open the log file. check the log file path"));
11191 exit(EXIT_FAILURE
);
11196 * vshOutputLogFile:
11198 * Outputting an error to log file.
11201 vshOutputLogFile(vshControl
*ctl
, int log_level
, const char *msg_format
, va_list ap
)
11203 char msg_buf
[MSG_BUFFER
];
11204 const char *lvl
= "";
11205 struct timeval stTimeval
;
11208 if (ctl
->log_fd
== -1)
11212 * create log format
11214 * [YYYY.MM.DD HH:MM:SS SIGNATURE PID] LOG_LEVEL message
11216 gettimeofday(&stTimeval
, NULL
);
11217 stTm
= localtime(&stTimeval
.tv_sec
);
11218 snprintf(msg_buf
, sizeof(msg_buf
),
11219 "[%d.%02d.%02d %02d:%02d:%02d ",
11220 (1900 + stTm
->tm_year
),
11221 (1 + stTm
->tm_mon
),
11226 snprintf(msg_buf
+ strlen(msg_buf
), sizeof(msg_buf
) - strlen(msg_buf
),
11227 "%s] ", SIGN_NAME
);
11228 switch (log_level
) {
11229 case VSH_ERR_DEBUG
:
11235 case VSH_ERR_NOTICE
:
11238 case VSH_ERR_WARNING
:
11241 case VSH_ERR_ERROR
:
11248 snprintf(msg_buf
+ strlen(msg_buf
), sizeof(msg_buf
) - strlen(msg_buf
),
11250 vsnprintf(msg_buf
+ strlen(msg_buf
), sizeof(msg_buf
) - strlen(msg_buf
),
11253 if (msg_buf
[strlen(msg_buf
) - 1] != '\n')
11254 snprintf(msg_buf
+ strlen(msg_buf
), sizeof(msg_buf
) - strlen(msg_buf
), "\n");
11257 if (safewrite(ctl
->log_fd
, msg_buf
, strlen(msg_buf
)) < 0) {
11258 vshCloseLogFile(ctl
);
11259 vshError(ctl
, "%s", _("failed to write the log file"));
11269 vshCloseLogFile(vshControl
*ctl
)
11271 /* log file close */
11272 if (ctl
->log_fd
>= 0) {
11273 if (close(ctl
->log_fd
) < 0)
11274 vshError(ctl
, _("%s: failed to write log file: %s"),
11275 ctl
->logfile
? ctl
->logfile
: "?", strerror (errno
));
11279 if (ctl
->logfile
) {
11280 VIR_FREE(ctl
->logfile
);
11281 ctl
->logfile
= NULL
;
11285 #ifdef USE_READLINE
11287 /* -----------------
11289 * -----------------
11293 * Generator function for command completion. STATE lets us
11294 * know whether to start from scratch; without any state
11295 * (i.e. STATE == 0), then we start at the top of the list.
11298 vshReadlineCommandGenerator(const char *text
, int state
)
11300 static int list_index
, len
;
11303 /* If this is a new word to complete, initialize now. This
11304 * includes saving the length of TEXT for efficiency, and
11305 * initializing the index variable to 0.
11309 len
= strlen(text
);
11312 /* Return the next name which partially matches from the
11315 while ((name
= commands
[list_index
].name
)) {
11317 if (STREQLEN(name
, text
, len
))
11318 return vshStrdup(NULL
, name
);
11321 /* If no names matched, then return NULL. */
11326 vshReadlineOptionsGenerator(const char *text
, int state
)
11328 static int list_index
, len
;
11329 static const vshCmdDef
*cmd
= NULL
;
11333 /* determine command name */
11337 if (!(p
= strchr(rl_line_buffer
, ' ')))
11340 cmdname
= vshCalloc(NULL
, (p
- rl_line_buffer
) + 1, 1);
11341 memcpy(cmdname
, rl_line_buffer
, p
- rl_line_buffer
);
11343 cmd
= vshCmddefSearch(cmdname
);
11345 len
= strlen(text
);
11355 while ((name
= cmd
->opts
[list_index
].name
)) {
11356 const vshCmdOptDef
*opt
= &cmd
->opts
[list_index
];
11361 if (opt
->type
== VSH_OT_DATA
)
11362 /* ignore non --option */
11366 if (STRNEQLEN(name
, text
+ 2, len
- 2))
11369 res
= vshMalloc(NULL
, strlen(name
) + 3);
11370 snprintf(res
, strlen(name
) + 3, "--%s", name
);
11374 /* If no names matched, then return NULL. */
11379 vshReadlineCompletion(const char *text
, int start
,
11380 int end ATTRIBUTE_UNUSED
)
11382 char **matches
= (char **) NULL
;
11385 /* command name generator */
11386 matches
= rl_completion_matches(text
, vshReadlineCommandGenerator
);
11388 /* commands options */
11389 matches
= rl_completion_matches(text
, vshReadlineOptionsGenerator
);
11395 vshReadlineInit(vshControl
*ctl
)
11397 char *userdir
= NULL
;
11399 /* Allow conditional parsing of the ~/.inputrc file. */
11400 rl_readline_name
= "virsh";
11402 /* Tell the completer that we want a crack first. */
11403 rl_attempted_completion_function
= vshReadlineCompletion
;
11405 /* Limit the total size of the history buffer */
11406 stifle_history(500);
11408 /* Prepare to read/write history from/to the ~/.virsh/history file */
11409 userdir
= virGetUserDirectory(getuid());
11411 if (userdir
== NULL
)
11414 if (virAsprintf(&ctl
->historydir
, "%s/.virsh", userdir
) < 0) {
11415 vshError(ctl
, "%s", _("Out of memory"));
11420 if (virAsprintf(&ctl
->historyfile
, "%s/history", ctl
->historydir
) < 0) {
11421 vshError(ctl
, "%s", _("Out of memory"));
11428 read_history(ctl
->historyfile
);
11434 vshReadlineDeinit (vshControl
*ctl
)
11436 if (ctl
->historyfile
!= NULL
) {
11437 if (mkdir(ctl
->historydir
, 0755) < 0 && errno
!= EEXIST
) {
11439 vshError(ctl
, _("Failed to create '%s': %s"),
11440 ctl
->historydir
, virStrerror(errno
, ebuf
, sizeof ebuf
));
11442 write_history(ctl
->historyfile
);
11445 VIR_FREE(ctl
->historydir
);
11446 VIR_FREE(ctl
->historyfile
);
11450 vshReadline (vshControl
*ctl ATTRIBUTE_UNUSED
, const char *prompt
)
11452 return readline (prompt
);
11455 #else /* !USE_READLINE */
11458 vshReadlineInit (vshControl
*ctl ATTRIBUTE_UNUSED
)
11465 vshReadlineDeinit (vshControl
*ctl ATTRIBUTE_UNUSED
)
11471 vshReadline (vshControl
*ctl
, const char *prompt
)
11477 fputs (prompt
, stdout
);
11478 r
= fgets (line
, sizeof line
, stdin
);
11479 if (r
== NULL
) return NULL
; /* EOF */
11481 /* Chomp trailing \n */
11483 if (len
> 0 && r
[len
-1] == '\n')
11486 return vshStrdup (ctl
, r
);
11489 #endif /* !USE_READLINE */
11492 * Deinitialize virsh
11495 vshDeinit(vshControl
*ctl
)
11497 vshReadlineDeinit(ctl
);
11498 vshCloseLogFile(ctl
);
11499 VIR_FREE(ctl
->name
);
11501 if (virConnectClose(ctl
->conn
) != 0) {
11502 vshError(ctl
, "%s", _("failed to disconnect from the hypervisor"));
11505 virResetLastError();
11516 const vshCmdDef
*cmd
;
11517 fprintf(stdout
, _("\n%s [options]... [<command_string>]"
11518 "\n%s [options]... <command> [args...]\n\n"
11520 " -c | --connect <uri> hypervisor connection URI\n"
11521 " -r | --readonly connect readonly\n"
11522 " -d | --debug <num> debug level [0-5]\n"
11523 " -h | --help this help\n"
11524 " -q | --quiet quiet mode\n"
11525 " -t | --timing print timing information\n"
11526 " -l | --log <file> output logging to file\n"
11527 " -v | --version program version\n\n"
11528 " commands (non interactive mode):\n"), progname
, progname
);
11530 for (cmd
= commands
; cmd
->name
; cmd
++)
11532 " %-15s %s\n", cmd
->name
, _(vshCmddefGetInfo(cmd
, "help")));
11534 fprintf(stdout
, "%s",
11535 _("\n (specify help <command> for details about the command)\n\n"));
11540 * argv[]: virsh [options] [command]
11544 vshParseArgv(vshControl
*ctl
, int argc
, char **argv
)
11548 struct option opt
[] = {
11549 {"debug", 1, 0, 'd'},
11550 {"help", 0, 0, 'h'},
11551 {"quiet", 0, 0, 'q'},
11552 {"timing", 0, 0, 't'},
11553 {"version", 0, 0, 'v'},
11554 {"connect", 1, 0, 'c'},
11555 {"readonly", 0, 0, 'r'},
11556 {"log", 1, 0, 'l'},
11560 /* Standard (non-command) options. The leading + ensures that no
11561 * argument reordering takes place, so that command options are
11562 * not confused with top-level virsh options. */
11563 while ((arg
= getopt_long(argc
, argv
, "+d:hqtc:vrl:", opt
, NULL
)) != -1) {
11566 if (virStrToLong_i(optarg
, NULL
, 10, &ctl
->debug
) < 0) {
11567 vshError(ctl
, "%s", _("option -d takes a numeric argument"));
11568 exit(EXIT_FAILURE
);
11578 ctl
->timing
= TRUE
;
11581 ctl
->name
= vshStrdup(ctl
, optarg
);
11584 /* FIXME - list a copyright blurb, as in GNU programs? */
11586 exit(EXIT_SUCCESS
);
11588 ctl
->readonly
= TRUE
;
11591 ctl
->logfile
= vshStrdup(ctl
, optarg
);
11594 vshError(ctl
, _("unsupported option '-%c'. See --help."), arg
);
11595 exit(EXIT_FAILURE
);
11600 if (optind
< argc
) {
11601 vshError(ctl
, _("extra argument '%s'. See --help."), argv
[optind
]);
11602 exit(EXIT_FAILURE
);
11605 /* list all command */
11607 exit(EXIT_SUCCESS
);
11610 if (argc
> optind
) {
11611 /* parse command */
11612 ctl
->imode
= FALSE
;
11613 if (argc
- optind
== 1) {
11614 vshDebug(ctl
, 2, "commands: \"%s\"\n", argv
[optind
]);
11615 return vshCommandStringParse(ctl
, argv
[optind
]);
11617 return vshCommandArgvParse(ctl
, argc
- optind
, argv
+ optind
);
11624 main(int argc
, char **argv
)
11626 vshControl _ctl
, *ctl
= &_ctl
;
11630 if (!setlocale(LC_ALL
, "")) {
11631 perror("setlocale");
11632 /* failure to setup locale is not fatal */
11634 if (!bindtextdomain(GETTEXT_PACKAGE
, LOCALEBASEDIR
)) {
11635 perror("bindtextdomain");
11638 if (!textdomain(GETTEXT_PACKAGE
)) {
11639 perror("textdomain");
11643 if (!(progname
= strrchr(argv
[0], '/')))
11644 progname
= argv
[0];
11648 memset(ctl
, 0, sizeof(vshControl
));
11649 ctl
->imode
= TRUE
; /* default is interactive mode */
11650 ctl
->log_fd
= -1; /* Initialize log file descriptor */
11652 if ((defaultConn
= getenv("VIRSH_DEFAULT_CONNECT_URI"))) {
11653 ctl
->name
= vshStrdup(ctl
, defaultConn
);
11656 if (!vshParseArgv(ctl
, argc
, argv
)) {
11658 exit(EXIT_FAILURE
);
11661 if (!vshInit(ctl
)) {
11663 exit(EXIT_FAILURE
);
11667 ret
= vshCommandRun(ctl
, ctl
->cmd
);
11669 /* interactive mode */
11672 _("Welcome to %s, the virtualization interactive terminal.\n\n"),
11674 vshPrint(ctl
, "%s",
11675 _("Type: 'help' for help with commands\n"
11676 " 'quit' to quit\n\n"));
11679 if (vshReadlineInit(ctl
) < 0) {
11681 exit(EXIT_FAILURE
);
11685 const char *prompt
= ctl
->readonly
? VSH_PROMPT_RO
: VSH_PROMPT_RW
;
11687 vshReadline(ctl
, prompt
);
11688 if (ctl
->cmdstr
== NULL
)
11690 if (*ctl
->cmdstr
) {
11692 add_history(ctl
->cmdstr
);
11694 if (vshCommandStringParse(ctl
, ctl
->cmdstr
))
11695 vshCommandRun(ctl
, ctl
->cmd
);
11697 VIR_FREE(ctl
->cmdstr
);
11698 } while (ctl
->imode
);
11700 if (ctl
->cmdstr
== NULL
)
11701 fputc('\n', stdout
); /* line break after alone prompt */
11705 exit(ret
? EXIT_SUCCESS
: EXIT_FAILURE
);