[libvirt] [PATCH 00/13] Move generic virsh data to a separate module vsh

The idea behind this is that in order to introduce virt-admin client (and later some commands/APIs), there are lots of methods in virsh that can be easily reused by other potential clients like command and command argument passing or error reporting. !!! IMPORTANT !!! These patches cannot be compiled separately, the series is split more or less logically into chunks only to be more readable by the reviewer. I started this at least 4 times from scratch and still haven't found a way that splitting virsh could be done with several independent applicable commits, rather than having one massive commit in the end. Erik Skultety (13): tools: Introduce new client generic module vsh vsh: Remove client specific data, only generic data are kept tools: apply s/vshX/virshX to all virsh specific data virsh: remove generic data, only client specific are kept virsh: Rename client specific methods in virsh.h vsh: vshControl now includes client private data and client specific progname vsh: Make use of introduced private data vsh: Introduce client hooks vsh: Make use of newly introduced client side hooks vsh: Introduce new global initializer vsh: Make separated generic methods public virsh: Introduce connection handler tools: Update makefile to include 'vsh' sources as well cfg.mk | 2 +- po/POTFILES.in | 3 +- tools/Makefile.am | 4 + tools/virsh-console.c | 13 +- tools/virsh-console.h | 8 +- tools/virsh-domain-monitor.c | 201 ++-- tools/virsh-domain-monitor.h | 4 +- tools/virsh-domain.c | 532 +++++---- tools/virsh-domain.h | 14 +- tools/virsh-edit.c | 8 +- tools/virsh-host.c | 131 ++- tools/virsh-interface.c | 80 +- tools/virsh-interface.h | 12 +- tools/virsh-network.c | 72 +- tools/virsh-network.h | 10 +- tools/virsh-nodedev.c | 37 +- tools/virsh-nwfilter.c | 33 +- tools/virsh-nwfilter.h | 10 +- tools/virsh-pool.c | 104 +- tools/virsh-pool.h | 10 +- tools/virsh-secret.c | 27 +- tools/virsh-snapshot.c | 75 +- tools/virsh-volume.c | 103 +- tools/virsh-volume.h | 14 +- tools/virsh.c | 2673 ++++-------------------------------------- tools/virsh.h | 481 +------- tools/vsh.c | 2332 ++++++++++++++++++++++++++++++++++++ tools/vsh.h | 489 ++++++++ 28 files changed, 3906 insertions(+), 3576 deletions(-) create mode 100644 tools/vsh.c create mode 100644 tools/vsh.h -- 1.9.3

In order to share as much virsh' logic as possible with upcomming virt-admin client we need to split virsh logic into virsh specific and client generic features. This patch only introduces these file that are identical to the virsh.{c,h} --- cfg.mk | 2 +- po/POTFILES.in | 3 +- tools/vsh.c | 3800 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ tools/vsh.h | 527 ++++++++ 4 files changed, 4330 insertions(+), 2 deletions(-) create mode 100644 tools/vsh.c create mode 100644 tools/vsh.h diff --git a/cfg.mk b/cfg.mk index 0d1a03c..f26191f 100644 --- a/cfg.mk +++ b/cfg.mk @@ -1086,7 +1086,7 @@ $(srcdir)/src/admin/admin_client.h: $(srcdir)/src/admin/admin_protocol.x $(MAKE) -C src admin/admin_client.h # List all syntax-check exemptions: -exclude_file_name_regexp--sc_avoid_strcase = ^tools/virsh\.h$$ +exclude_file_name_regexp--sc_avoid_strcase = ^tools/(virsh|vsh)\.h$$ _src1=libvirt-stream|fdstream|qemu/qemu_monitor|util/(vircommand|virfile)|xen/xend_internal|rpc/virnetsocket|lxc/lxc_controller|locking/lock_daemon _test1=shunloadtest|virnettlscontexttest|virnettlssessiontest|vircgroupmock diff --git a/po/POTFILES.in b/po/POTFILES.in index a75f5ae..e0d1014 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -258,7 +258,6 @@ src/xenconfig/xen_xm.c tests/virpolkittest.c tools/libvirt-guests.sh.in tools/virsh.c -tools/virsh.h tools/virsh-console.c tools/virsh-domain-monitor.c tools/virsh-domain.c @@ -277,3 +276,5 @@ tools/virt-host-validate-lxc.c tools/virt-host-validate-qemu.c tools/virt-host-validate.c tools/virt-login-shell.c +tools/vsh.c +tools/vsh.h diff --git a/tools/vsh.c b/tools/vsh.c new file mode 100644 index 0000000..609c8f3 --- /dev/null +++ b/tools/vsh.c @@ -0,0 +1,3800 @@ +/* + * vsh.c: common data to be used by clients to exercise the libvirt API + * + * Copyright (C) 2005, 2007-2015 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + * + * Daniel Veillard <veillard@redhat.com> + * Karel Zak <kzak@redhat.com> + * Daniel P. Berrange <berrange@redhat.com> + */ + +#include <config.h> +#include "vsh.h" + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <unistd.h> +#include <errno.h> +#include <getopt.h> +#include <sys/time.h> +#include "c-ctype.h" +#include <fcntl.h> +#include <locale.h> +#include <time.h> +#include <limits.h> +#include <sys/stat.h> +#include <inttypes.h> +#include <strings.h> +#include <signal.h> + +#if WITH_READLINE +# include <readline/readline.h> +# include <readline/history.h> +#endif + +#include "internal.h" +#include "virerror.h" +#include "virbuffer.h" +#include "viralloc.h" +#include <libvirt/libvirt-qemu.h> +#include <libvirt/libvirt-lxc.h> +#include "virfile.h" +#include "configmake.h" +#include "virthread.h" +#include "vircommand.h" +#include "conf/domain_conf.h" +#include "virtypedparam.h" +#include "virstring.h" + +#include "virsh-console.h" +#include "virsh-domain.h" +#include "virsh-domain-monitor.h" +#include "virsh-host.h" +#include "virsh-interface.h" +#include "virsh-network.h" +#include "virsh-nodedev.h" +#include "virsh-nwfilter.h" +#include "virsh-pool.h" +#include "virsh-secret.h" +#include "virsh-snapshot.h" +#include "virsh-volume.h" + +/* Gnulib doesn't guarantee SA_SIGINFO support. */ +#ifndef SA_SIGINFO +# define SA_SIGINFO 0 +#endif + +static char *progname; + +static const vshCmdGrp cmdGroups[]; + +/* Bypass header poison */ +#undef strdup + +void * +_vshMalloc(vshControl *ctl, size_t size, const char *filename, int line) +{ + char *x; + + if (VIR_ALLOC_N(x, size) == 0) + return x; + vshError(ctl, _("%s: %d: failed to allocate %d bytes"), + filename, line, (int) size); + exit(EXIT_FAILURE); +} + +void * +_vshCalloc(vshControl *ctl, size_t nmemb, size_t size, const char *filename, + int line) +{ + char *x; + + if (!xalloc_oversized(nmemb, size) && + VIR_ALLOC_N(x, nmemb * size) == 0) + return x; + vshError(ctl, _("%s: %d: failed to allocate %d bytes"), + filename, line, (int) (size*nmemb)); + exit(EXIT_FAILURE); +} + +char * +_vshStrdup(vshControl *ctl, const char *s, const char *filename, int line) +{ + char *x; + + if (VIR_STRDUP(x, s) >= 0) + return x; + vshError(ctl, _("%s: %d: failed to allocate %lu bytes"), + filename, line, (unsigned long)strlen(s)); + exit(EXIT_FAILURE); +} + +/* Poison the raw allocating identifiers in favor of our vsh variants. */ +#define strdup use_vshStrdup_instead_of_strdup + +int +vshNameSorter(const void *a, const void *b) +{ + const char **sa = (const char**)a; + const char **sb = (const char**)b; + + return vshStrcasecmp(*sa, *sb); +} + +double +vshPrettyCapacity(unsigned long long val, const char **unit) +{ + double limit = 1024; + + if (val < limit) { + *unit = "B"; + return val; + } + limit *= 1024; + if (val < limit) { + *unit = "KiB"; + return val / (limit / 1024); + } + limit *= 1024; + if (val < limit) { + *unit = "MiB"; + return val / (limit / 1024); + } + limit *= 1024; + if (val < limit) { + *unit = "GiB"; + return val / (limit / 1024); + } + limit *= 1024; + if (val < limit) { + *unit = "TiB"; + return val / (limit / 1024); + } + limit *= 1024; + if (val < limit) { + *unit = "PiB"; + return val / (limit / 1024); + } + limit *= 1024; + *unit = "EiB"; + return val / (limit / 1024); +} + +/* + * Convert the strings separated by ',' into array. The returned + * array is a NULL terminated string list. The caller has to free + * the array using virStringFreeList or a similar method. + * + * Returns the length of the filled array on success, or -1 + * on error. + */ +int +vshStringToArray(const char *str, + char ***array) +{ + char *str_copied = vshStrdup(NULL, str); + char *str_tok = NULL; + char *tmp; + unsigned int nstr_tokens = 0; + char **arr = NULL; + size_t len = strlen(str_copied); + + /* tokenize the string from user and save its parts into an array */ + nstr_tokens = 1; + + /* count the delimiters, recognizing ,, as an escape for a + * literal comma */ + str_tok = str_copied; + while ((str_tok = strchr(str_tok, ','))) { + if (str_tok[1] == ',') + str_tok++; + else + nstr_tokens++; + str_tok++; + } + + /* reserve the NULL element at the end */ + if (VIR_ALLOC_N(arr, nstr_tokens + 1) < 0) { + VIR_FREE(str_copied); + return -1; + } + + /* tokenize the input string, while treating ,, as a literal comma */ + nstr_tokens = 0; + tmp = str_tok = str_copied; + while ((tmp = strchr(tmp, ','))) { + if (tmp[1] == ',') { + memmove(&tmp[1], &tmp[2], len - (tmp - str_copied) - 2 + 1); + len--; + tmp++; + continue; + } + *tmp++ = '\0'; + arr[nstr_tokens++] = vshStrdup(NULL, str_tok); + str_tok = tmp; + } + arr[nstr_tokens++] = vshStrdup(NULL, str_tok); + + *array = arr; + VIR_FREE(str_copied); + return nstr_tokens; +} + +virErrorPtr last_error; + +/* + * Quieten libvirt until we're done with the command. + */ +static void +virshErrorHandler(void *unused ATTRIBUTE_UNUSED, virErrorPtr error) +{ + virFreeError(last_error); + last_error = virSaveLastError(); + if (virGetEnvAllowSUID("VIRSH_DEBUG") != NULL) + virDefaultErrorFunc(error); +} + +/* Store a libvirt error that is from a helper API that doesn't raise errors + * so it doesn't get overwritten */ +void +vshSaveLibvirtError(void) +{ + virFreeError(last_error); + last_error = virSaveLastError(); +} + +/* + * Reset libvirt error on graceful fallback paths + */ +void +vshResetLibvirtError(void) +{ + virFreeError(last_error); + last_error = NULL; +} + +/* + * Report an error when a command finishes. This is better than before + * (when correct operation would report errors), but it has some + * problems: we lose the smarter formatting of virDefaultErrorFunc(), + * and it can become harder to debug problems, if errors get reported + * twice during one command. This case shouldn't really happen anyway, + * and it's IMHO a bug that libvirt does that sometimes. + */ +void +vshReportError(vshControl *ctl) +{ + if (last_error == NULL) { + /* Calling directly into libvirt util functions won't trigger the + * error callback (which sets last_error), so check it ourselves. + * + * If the returned error has CODE_OK, this most likely means that + * no error was ever raised, so just ignore */ + last_error = virSaveLastError(); + if (!last_error || last_error->code == VIR_ERR_OK) + goto out; + } + + if (last_error->code == VIR_ERR_OK) { + vshError(ctl, "%s", _("unknown error")); + goto out; + } + + vshError(ctl, "%s", last_error->message); + + out: + vshResetLibvirtError(); +} + +/* + * Detection of disconnections and automatic reconnection support + */ +static int disconnected; /* we may have been disconnected */ + +/* + * vshCatchDisconnect: + * + * We get here when the connection was closed. We can't do much in the + * handler, just save the fact it was raised. + */ +static void +vshCatchDisconnect(virConnectPtr conn ATTRIBUTE_UNUSED, + int reason, + void *opaque ATTRIBUTE_UNUSED) +{ + if (reason != VIR_CONNECT_CLOSE_REASON_CLIENT) + disconnected++; +} + +/* Main Function which should be used for connecting. + * This function properly handles keepalive settings. */ +virConnectPtr +vshConnect(vshControl *ctl, const char *uri, bool readonly) +{ + virConnectPtr c = NULL; + int interval = 5; /* Default */ + int count = 6; /* Default */ + bool keepalive_forced = false; + + if (ctl->keepalive_interval >= 0) { + interval = ctl->keepalive_interval; + keepalive_forced = true; + } + if (ctl->keepalive_count >= 0) { + count = ctl->keepalive_count; + keepalive_forced = true; + } + + c = virConnectOpenAuth(uri, virConnectAuthPtrDefault, + readonly ? VIR_CONNECT_RO : 0); + if (!c) + return NULL; + + if (interval > 0 && + virConnectSetKeepAlive(c, interval, count) != 0) { + if (keepalive_forced) { + vshError(ctl, "%s", + _("Cannot setup keepalive on connection " + "as requested, disconnecting")); + virConnectClose(c); + return NULL; + } + vshDebug(ctl, VSH_ERR_INFO, "%s", + _("Failed to setup keepalive on connection\n")); + } + + return c; +} + +/* + * vshReconnect: + * + * Reconnect after a disconnect from libvirtd + * + */ +static void +vshReconnect(vshControl *ctl) +{ + bool connected = false; + + if (ctl->conn) { + int ret; + + connected = true; + + virConnectUnregisterCloseCallback(ctl->conn, vshCatchDisconnect); + ret = virConnectClose(ctl->conn); + if (ret < 0) + vshError(ctl, "%s", _("Failed to disconnect from the hypervisor")); + else if (ret > 0) + vshError(ctl, "%s", _("One or more references were leaked after " + "disconnect from the hypervisor")); + } + + ctl->conn = vshConnect(ctl, ctl->name, ctl->readonly); + + if (!ctl->conn) { + if (disconnected) + vshError(ctl, "%s", _("Failed to reconnect to the hypervisor")); + else + vshError(ctl, "%s", _("failed to connect to the hypervisor")); + } else { + if (virConnectRegisterCloseCallback(ctl->conn, vshCatchDisconnect, + NULL, NULL) < 0) + vshError(ctl, "%s", _("Unable to register disconnect callback")); + if (connected) + vshError(ctl, "%s", _("Reconnected to the hypervisor")); + } + disconnected = 0; + ctl->useGetInfo = false; + ctl->useSnapshotOld = false; + ctl->blockJobNoBytes = false; +} + + +/* + * "connect" command + */ +static const vshCmdInfo info_connect[] = { + {.name = "help", + .data = N_("(re)connect to hypervisor") + }, + {.name = "desc", + .data = N_("Connect to local hypervisor. This is built-in " + "command after shell start up.") + }, + {.name = NULL} +}; + +static const vshCmdOptDef opts_connect[] = { + {.name = "name", + .type = VSH_OT_STRING, + .flags = VSH_OFLAG_EMPTY_OK, + .help = N_("hypervisor connection URI") + }, + {.name = "readonly", + .type = VSH_OT_BOOL, + .help = N_("read-only connection") + }, + {.name = NULL} +}; + +static bool +cmdConnect(vshControl *ctl, const vshCmd *cmd) +{ + bool ro = vshCommandOptBool(cmd, "readonly"); + const char *name = NULL; + + if (ctl->conn) { + int ret; + + virConnectUnregisterCloseCallback(ctl->conn, vshCatchDisconnect); + ret = virConnectClose(ctl->conn); + if (ret < 0) + vshError(ctl, "%s", _("Failed to disconnect from the hypervisor")); + else if (ret > 0) + vshError(ctl, "%s", _("One or more references were leaked after " + "disconnect from the hypervisor")); + ctl->conn = NULL; + } + + VIR_FREE(ctl->name); + if (vshCommandOptStringReq(ctl, cmd, "name", &name) < 0) + return false; + + ctl->name = vshStrdup(ctl, name); + + ctl->useGetInfo = false; + ctl->useSnapshotOld = false; + ctl->blockJobNoBytes = false; + ctl->readonly = ro; + + ctl->conn = vshConnect(ctl, ctl->name, ctl->readonly); + + if (!ctl->conn) { + vshError(ctl, "%s", _("Failed to connect to the hypervisor")); + return false; + } + + if (virConnectRegisterCloseCallback(ctl->conn, vshCatchDisconnect, + NULL, NULL) < 0) + vshError(ctl, "%s", _("Unable to register disconnect callback")); + + return true; +} + + +#ifndef WIN32 +static void +vshPrintRaw(vshControl *ctl, ...) +{ + va_list ap; + char *key; + + va_start(ap, ctl); + while ((key = va_arg(ap, char *)) != NULL) + vshPrint(ctl, "%s\r\n", key); + va_end(ap); +} + +/** + * vshAskReedit: + * @msg: Question to ask user + * + * Ask user if he wants to return to previously + * edited file. + * + * Returns 'y' if he wants to + * 'n' if he doesn't want to + * 'i' if he wants to try defining it again while ignoring validation + * 'f' if he forcibly wants to + * -1 on error + * 0 otherwise + */ +int +vshAskReedit(vshControl *ctl, const char *msg, bool relax_avail) +{ + int c = -1; + + if (!isatty(STDIN_FILENO)) + return -1; + + vshReportError(ctl); + + if (vshTTYMakeRaw(ctl, false) < 0) + return -1; + + while (true) { + vshPrint(ctl, "\r%s %s %s: ", msg, _("Try again?"), + relax_avail ? "[y,n,i,f,?]" : "[y,n,f,?]"); + c = c_tolower(getchar()); + + if (c == '?') { + vshPrintRaw(ctl, + "", + _("y - yes, start editor again"), + _("n - no, throw away my changes"), + NULL); + + if (relax_avail) { + vshPrintRaw(ctl, + _("i - turn off validation and try to redefine again"), + NULL); + } + + vshPrintRaw(ctl, + _("f - force, try to redefine again"), + _("? - print this help"), + NULL); + continue; + } else if (c == 'y' || c == 'n' || c == 'f' || + (relax_avail && c == 'i')) { + break; + } + } + + vshTTYRestore(ctl); + + vshPrint(ctl, "\r\n"); + return c; +} +#else /* WIN32 */ +int +vshAskReedit(vshControl *ctl, + const char *msg ATTRIBUTE_UNUSED, + bool relax_avail ATTRIBUTE_UNUSED) +{ + vshDebug(ctl, VSH_ERR_WARNING, "%s", _("This function is not " + "supported on WIN32 platform")); + return 0; +} +#endif /* WIN32 */ + +int vshStreamSink(virStreamPtr st ATTRIBUTE_UNUSED, + const char *bytes, size_t nbytes, void *opaque) +{ + int *fd = opaque; + + return safewrite(*fd, bytes, nbytes); +} + +/* --------------- + * Commands + * --------------- + */ + +/* + * "help" command + */ +static const vshCmdInfo info_help[] = { + {.name = "help", + .data = N_("print help") + }, + {.name = "desc", + .data = N_("Prints global help, command specific help, or help for a\n" + " group of related commands") + }, + {.name = NULL} +}; + +static const vshCmdOptDef opts_help[] = { + {.name = "command", + .type = VSH_OT_STRING, + .help = N_("Prints global help, command specific help, or help for a group of related commands") + }, + {.name = NULL} +}; + +static bool +cmdHelp(vshControl *ctl, const vshCmd *cmd) + { + const char *name = NULL; + + if (vshCommandOptString(ctl, cmd, "command", &name) <= 0) { + const vshCmdGrp *grp; + const vshCmdDef *def; + + vshPrint(ctl, "%s", _("Grouped commands:\n\n")); + + for (grp = cmdGroups; grp->name; grp++) { + vshPrint(ctl, _(" %s (help keyword '%s'):\n"), grp->name, + grp->keyword); + + for (def = grp->commands; def->name; def++) { + if (def->flags & VSH_CMD_FLAG_ALIAS) + continue; + vshPrint(ctl, " %-30s %s\n", def->name, + _(vshCmddefGetInfo(def, "help"))); + } + + vshPrint(ctl, "\n"); + } + + return true; + } + + if (vshCmddefSearch(name)) { + return vshCmddefHelp(ctl, name); + } else if (vshCmdGrpSearch(name)) { + return vshCmdGrpHelp(ctl, name); + } else { + vshError(ctl, _("command or command group '%s' doesn't exist"), name); + return false; + } +} + +/* Tree listing helpers. */ + +static int +vshTreePrintInternal(vshControl *ctl, + vshTreeLookup lookup, + void *opaque, + int num_devices, + int devid, + int lastdev, + bool root, + virBufferPtr indent) +{ + size_t i; + int nextlastdev = -1; + int ret = -1; + const char *dev = (lookup)(devid, false, opaque); + + if (virBufferError(indent)) + goto cleanup; + + /* Print this device, with indent if not at root */ + vshPrint(ctl, "%s%s%s\n", virBufferCurrentContent(indent), + root ? "" : "+- ", dev); + + /* Update indent to show '|' or ' ' for child devices */ + if (!root) { + virBufferAddChar(indent, devid == lastdev ? ' ' : '|'); + virBufferAddChar(indent, ' '); + if (virBufferError(indent)) + goto cleanup; + } + + /* Determine the index of the last child device */ + for (i = 0; i < num_devices; i++) { + const char *parent = (lookup)(i, true, opaque); + + if (parent && STREQ(parent, dev)) + nextlastdev = i; + } + + /* If there is a child device, then print another blank line */ + if (nextlastdev != -1) + vshPrint(ctl, "%s |\n", virBufferCurrentContent(indent)); + + /* Finally print all children */ + virBufferAddLit(indent, " "); + if (virBufferError(indent)) + goto cleanup; + for (i = 0; i < num_devices; i++) { + const char *parent = (lookup)(i, true, opaque); + + if (parent && STREQ(parent, dev) && + vshTreePrintInternal(ctl, lookup, opaque, + num_devices, i, nextlastdev, + false, indent) < 0) + goto cleanup; + } + virBufferTrim(indent, " ", -1); + + /* If there was no child device, and we're the last in + * a list of devices, then print another blank line */ + if (nextlastdev == -1 && devid == lastdev) + vshPrint(ctl, "%s\n", virBufferCurrentContent(indent)); + + if (!root) + virBufferTrim(indent, NULL, 2); + ret = 0; + cleanup: + return ret; +} + +int +vshTreePrint(vshControl *ctl, vshTreeLookup lookup, void *opaque, + int num_devices, int devid) +{ + int ret; + virBuffer indent = VIR_BUFFER_INITIALIZER; + + ret = vshTreePrintInternal(ctl, lookup, opaque, num_devices, + devid, devid, true, &indent); + if (ret < 0) + vshError(ctl, "%s", _("Failed to complete tree listing")); + virBufferFreeAndReset(&indent); + return ret; +} + +/* Common code for the edit / net-edit / pool-edit functions which follow. */ +char * +vshEditWriteToTempFile(vshControl *ctl, const char *doc) +{ + char *ret; + const char *tmpdir; + int fd; + char ebuf[1024]; + + tmpdir = virGetEnvBlockSUID("TMPDIR"); + if (!tmpdir) tmpdir = "/tmp"; + if (virAsprintf(&ret, "%s/virshXXXXXX.xml", tmpdir) < 0) { + vshError(ctl, "%s", _("out of memory")); + return NULL; + } + fd = mkostemps(ret, 4, O_CLOEXEC); + if (fd == -1) { + vshError(ctl, _("mkostemps: failed to create temporary file: %s"), + virStrerror(errno, ebuf, sizeof(ebuf))); + VIR_FREE(ret); + return NULL; + } + + if (safewrite(fd, doc, strlen(doc)) == -1) { + vshError(ctl, _("write: %s: failed to write to temporary file: %s"), + ret, virStrerror(errno, ebuf, sizeof(ebuf))); + VIR_FORCE_CLOSE(fd); + unlink(ret); + VIR_FREE(ret); + return NULL; + } + if (VIR_CLOSE(fd) < 0) { + vshError(ctl, _("close: %s: failed to write or close temporary file: %s"), + ret, virStrerror(errno, ebuf, sizeof(ebuf))); + unlink(ret); + VIR_FREE(ret); + return NULL; + } + + /* Temporary filename: caller frees. */ + return ret; +} + +/* Characters permitted in $EDITOR environment variable and temp filename. */ +#define ACCEPTED_CHARS \ + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-/_.:@" + +int +vshEditFile(vshControl *ctl, const char *filename) +{ + const char *editor; + virCommandPtr cmd; + int ret = -1; + int outfd = STDOUT_FILENO; + int errfd = STDERR_FILENO; + + editor = virGetEnvBlockSUID("VISUAL"); + if (!editor) + editor = virGetEnvBlockSUID("EDITOR"); + if (!editor) + editor = DEFAULT_EDITOR; + + /* Check that filename doesn't contain shell meta-characters, and + * if it does, refuse to run. Follow the Unix conventions for + * EDITOR: the user can intentionally specify command options, so + * we don't protect any shell metacharacters there. Lots more + * than virsh will misbehave if EDITOR has bogus contents (which + * is why sudo scrubs it by default). Conversely, if the editor + * is safe, we can run it directly rather than wasting a shell. + */ + if (strspn(editor, ACCEPTED_CHARS) != strlen(editor)) { + if (strspn(filename, ACCEPTED_CHARS) != strlen(filename)) { + vshError(ctl, + _("%s: temporary filename contains shell meta or other " + "unacceptable characters (is $TMPDIR wrong?)"), + filename); + return -1; + } + cmd = virCommandNewArgList("sh", "-c", NULL); + virCommandAddArgFormat(cmd, "%s %s", editor, filename); + } else { + cmd = virCommandNewArgList(editor, filename, NULL); + } + + virCommandSetInputFD(cmd, STDIN_FILENO); + virCommandSetOutputFD(cmd, &outfd); + virCommandSetErrorFD(cmd, &errfd); + if (virCommandRunAsync(cmd, NULL) < 0 || + virCommandWait(cmd, NULL) < 0) { + vshReportError(ctl); + goto cleanup; + } + ret = 0; + + cleanup: + virCommandFree(cmd); + return ret; +} + +char * +vshEditReadBackFile(vshControl *ctl, const char *filename) +{ + char *ret; + char ebuf[1024]; + + if (virFileReadAll(filename, VSH_MAX_XML_FILE, &ret) == -1) { + vshError(ctl, + _("%s: failed to read temporary file: %s"), + filename, virStrerror(errno, ebuf, sizeof(ebuf))); + return NULL; + } + return ret; +} + + +/* + * "cd" command + */ +static const vshCmdInfo info_cd[] = { + {.name = "help", + .data = N_("change the current directory") + }, + {.name = "desc", + .data = N_("Change the current directory.") + }, + {.name = NULL} +}; + +static const vshCmdOptDef opts_cd[] = { + {.name = "dir", + .type = VSH_OT_STRING, + .help = N_("directory to switch to (default: home or else root)") + }, + {.name = NULL} +}; + +static bool +cmdCd(vshControl *ctl, const vshCmd *cmd) +{ + const char *dir = NULL; + char *dir_malloced = NULL; + bool ret = true; + char ebuf[1024]; + + if (!ctl->imode) { + vshError(ctl, "%s", _("cd: command valid only in interactive mode")); + return false; + } + + if (vshCommandOptString(ctl, cmd, "dir", &dir) <= 0) + dir = dir_malloced = virGetUserDirectory(); + if (!dir) + dir = "/"; + + if (chdir(dir) == -1) { + vshError(ctl, _("cd: %s: %s"), + virStrerror(errno, ebuf, sizeof(ebuf)), dir); + ret = false; + } + + VIR_FREE(dir_malloced); + return ret; +} + +/* + * "pwd" command + */ +static const vshCmdInfo info_pwd[] = { + {.name = "help", + .data = N_("print the current directory") + }, + {.name = "desc", + .data = N_("Print the current directory.") + }, + {.name = NULL} +}; + +static bool +cmdPwd(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) +{ + char *cwd; + bool ret = true; + char ebuf[1024]; + + cwd = getcwd(NULL, 0); + if (!cwd) { + vshError(ctl, _("pwd: cannot get current directory: %s"), + virStrerror(errno, ebuf, sizeof(ebuf))); + ret = false; + } else { + vshPrint(ctl, _("%s\n"), cwd); + VIR_FREE(cwd); + } + + return ret; +} + +/* + * "echo" command + */ +static const vshCmdInfo info_echo[] = { + {.name = "help", + .data = N_("echo arguments") + }, + {.name = "desc", + .data = N_("Echo back arguments, possibly with quoting.") + }, + {.name = NULL} +}; + +static const vshCmdOptDef opts_echo[] = { + {.name = "shell", + .type = VSH_OT_BOOL, + .help = N_("escape for shell use") + }, + {.name = "xml", + .type = VSH_OT_BOOL, + .help = N_("escape for XML use") + }, + {.name = "str", + .type = VSH_OT_ALIAS, + .help = "string" + }, + {.name = "hi", + .type = VSH_OT_ALIAS, + .help = "string=hello" + }, + {.name = "string", + .type = VSH_OT_ARGV, + .help = N_("arguments to echo") + }, + {.name = NULL} +}; + +/* Exists mainly for debugging virsh, but also handy for adding back + * quotes for later evaluation. + */ +static bool +cmdEcho(vshControl *ctl, const vshCmd *cmd) +{ + bool shell = false; + bool xml = false; + int count = 0; + const vshCmdOpt *opt = NULL; + char *arg; + virBuffer buf = VIR_BUFFER_INITIALIZER; + + if (vshCommandOptBool(cmd, "shell")) + shell = true; + if (vshCommandOptBool(cmd, "xml")) + xml = true; + + while ((opt = vshCommandOptArgv(ctl, cmd, opt))) { + char *str; + virBuffer xmlbuf = VIR_BUFFER_INITIALIZER; + + arg = opt->data; + + if (count) + virBufferAddChar(&buf, ' '); + + if (xml) { + virBufferEscapeString(&xmlbuf, "%s", arg); + if (virBufferError(&xmlbuf)) { + vshPrint(ctl, "%s", _("Failed to allocate XML buffer")); + return false; + } + str = virBufferContentAndReset(&xmlbuf); + } else { + str = vshStrdup(ctl, arg); + } + + if (shell) + virBufferEscapeShell(&buf, str); + else + virBufferAdd(&buf, str, -1); + count++; + VIR_FREE(str); + } + + if (virBufferError(&buf)) { + vshPrint(ctl, "%s", _("Failed to allocate XML buffer")); + return false; + } + arg = virBufferContentAndReset(&buf); + if (arg) + vshPrint(ctl, "%s", arg); + VIR_FREE(arg); + return true; +} + +/* + * "quit" command + */ +static const vshCmdInfo info_quit[] = { + {.name = "help", + .data = N_("quit this interactive terminal") + }, + {.name = "desc", + .data = "" + }, + {.name = NULL} +}; + +static bool +cmdQuit(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) +{ + ctl->imode = false; + return true; +} + +/* --------------- + * Utils for work with command definition + * --------------- + */ +const char * +vshCmddefGetInfo(const vshCmdDef * cmd, const char *name) +{ + const vshCmdInfo *info; + + for (info = cmd->info; info && info->name; info++) { + if (STREQ(info->name, name)) + return info->data; + } + return NULL; +} + +/* Validate that the options associated with cmd can be parsed. */ +static int +vshCmddefOptParse(const vshCmdDef *cmd, uint32_t *opts_need_arg, + uint32_t *opts_required) +{ + size_t i; + bool optional = false; + + *opts_need_arg = 0; + *opts_required = 0; + + if (!cmd->opts) + return 0; + + for (i = 0; cmd->opts[i].name; i++) { + const vshCmdOptDef *opt = &cmd->opts[i]; + + if (i > 31) + return -1; /* too many options */ + if (opt->type == VSH_OT_BOOL) { + optional = true; + if (opt->flags & VSH_OFLAG_REQ) + return -1; /* bool options can't be mandatory */ + continue; + } + if (opt->type == VSH_OT_ALIAS) { + size_t j; + char *name = (char *)opt->help; /* cast away const */ + char *p; + + if (opt->flags || !opt->help) + return -1; /* alias options are tracked by the original name */ + if ((p = strchr(name, '=')) && + VIR_STRNDUP(name, name, p - name) < 0) + return -1; + for (j = i + 1; cmd->opts[j].name; j++) { + if (STREQ(name, cmd->opts[j].name) && + cmd->opts[j].type != VSH_OT_ALIAS) + break; + } + if (name != opt->help) { + VIR_FREE(name); + /* If alias comes with value, replacement must not be bool */ + if (cmd->opts[j].type == VSH_OT_BOOL) + return -1; + } + if (!cmd->opts[j].name) + return -1; /* alias option must map to a later option name */ + continue; + } + if (opt->flags & VSH_OFLAG_REQ_OPT) { + if (opt->flags & VSH_OFLAG_REQ) + *opts_required |= 1 << i; + else + optional = true; + continue; + } + + *opts_need_arg |= 1 << i; + if (opt->flags & VSH_OFLAG_REQ) { + if (optional && opt->type != VSH_OT_ARGV) + return -1; /* mandatory options must be listed first */ + *opts_required |= 1 << i; + } else { + optional = true; + } + + if (opt->type == VSH_OT_ARGV && cmd->opts[i + 1].name) + return -1; /* argv option must be listed last */ + } + return 0; +} + +static vshCmdOptDef helpopt = { + .name = "help", + .type = VSH_OT_BOOL, + .help = N_("print help for this function") +}; +static const vshCmdOptDef * +vshCmddefGetOption(vshControl *ctl, const vshCmdDef *cmd, const char *name, + uint32_t *opts_seen, int *opt_index, char **optstr) +{ + size_t i; + const vshCmdOptDef *ret = NULL; + char *alias = NULL; + + if (STREQ(name, helpopt.name)) + return &helpopt; + + for (i = 0; cmd->opts && cmd->opts[i].name; i++) { + const vshCmdOptDef *opt = &cmd->opts[i]; + + if (STREQ(opt->name, name)) { + if (opt->type == VSH_OT_ALIAS) { + char *value; + + /* Two types of replacements: + opt->help = "string": straight replacement of name + opt->help = "string=value": treat boolean flag as + alias of option and its default value */ + sa_assert(!alias); + if (VIR_STRDUP(alias, opt->help) < 0) + goto cleanup; + name = alias; + if ((value = strchr(name, '='))) { + *value = '\0'; + if (*optstr) { + vshError(ctl, _("invalid '=' after option --%s"), + opt->name); + goto cleanup; + } + if (VIR_STRDUP(*optstr, value + 1) < 0) + goto cleanup; + } + continue; + } + if ((*opts_seen & (1 << i)) && opt->type != VSH_OT_ARGV) { + vshError(ctl, _("option --%s already seen"), name); + goto cleanup; + } + *opts_seen |= 1 << i; + *opt_index = i; + ret = opt; + goto cleanup; + } + } + + if (STRNEQ(cmd->name, "help")) { + vshError(ctl, _("command '%s' doesn't support option --%s"), + cmd->name, name); + } + cleanup: + VIR_FREE(alias); + return ret; +} + +static const vshCmdOptDef * +vshCmddefGetData(const vshCmdDef *cmd, uint32_t *opts_need_arg, + uint32_t *opts_seen) +{ + size_t i; + const vshCmdOptDef *opt; + + if (!*opts_need_arg) + return NULL; + + /* Grab least-significant set bit */ + i = ffs(*opts_need_arg) - 1; + opt = &cmd->opts[i]; + if (opt->type != VSH_OT_ARGV) + *opts_need_arg &= ~(1 << i); + *opts_seen |= 1 << i; + return opt; +} + +/* + * Checks for required options + */ +static int +vshCommandCheckOpts(vshControl *ctl, const vshCmd *cmd, uint32_t opts_required, + uint32_t opts_seen) +{ + const vshCmdDef *def = cmd->def; + size_t i; + + opts_required &= ~opts_seen; + if (!opts_required) + return 0; + + for (i = 0; def->opts[i].name; i++) { + if (opts_required & (1 << i)) { + const vshCmdOptDef *opt = &def->opts[i]; + + vshError(ctl, + opt->type == VSH_OT_DATA || opt->type == VSH_OT_ARGV ? + _("command '%s' requires <%s> option") : + _("command '%s' requires --%s option"), + def->name, opt->name); + } + } + return -1; +} + +const vshCmdDef * +vshCmddefSearch(const char *cmdname) +{ + const vshCmdGrp *g; + const vshCmdDef *c; + + for (g = cmdGroups; g->name; g++) { + for (c = g->commands; c->name; c++) { + if (STREQ(c->name, cmdname)) + return c; + } + } + + return NULL; +} + +const vshCmdGrp * +vshCmdGrpSearch(const char *grpname) +{ + const vshCmdGrp *g; + + for (g = cmdGroups; g->name; g++) { + if (STREQ(g->name, grpname) || STREQ(g->keyword, grpname)) + return g; + } + + return NULL; +} + +bool +vshCmdGrpHelp(vshControl *ctl, const char *grpname) +{ + const vshCmdGrp *grp = vshCmdGrpSearch(grpname); + const vshCmdDef *cmd = NULL; + + if (!grp) { + vshError(ctl, _("command group '%s' doesn't exist"), grpname); + return false; + } else { + vshPrint(ctl, _(" %s (help keyword '%s'):\n"), grp->name, + grp->keyword); + + for (cmd = grp->commands; cmd->name; cmd++) { + if (cmd->flags & VSH_CMD_FLAG_ALIAS) + continue; + vshPrint(ctl, " %-30s %s\n", cmd->name, + _(vshCmddefGetInfo(cmd, "help"))); + } + } + + return true; +} + +bool +vshCmddefHelp(vshControl *ctl, const char *cmdname) +{ + const vshCmdDef *def = vshCmddefSearch(cmdname); + + if (!def) { + vshError(ctl, _("command '%s' doesn't exist"), cmdname); + return false; + } else { + /* Don't translate desc if it is "". */ + const char *desc = vshCmddefGetInfo(def, "desc"); + const char *help = _(vshCmddefGetInfo(def, "help")); + char buf[256]; + uint32_t opts_need_arg; + uint32_t opts_required; + bool shortopt = false; /* true if 'arg' works instead of '--opt arg' */ + + if (vshCmddefOptParse(def, &opts_need_arg, &opts_required)) { + vshError(ctl, _("internal error: bad options in command: '%s'"), + def->name); + return false; + } + + fputs(_(" NAME\n"), stdout); + fprintf(stdout, " %s - %s\n", def->name, help); + + fputs(_("\n SYNOPSIS\n"), stdout); + fprintf(stdout, " %s", def->name); + if (def->opts) { + const vshCmdOptDef *opt; + for (opt = def->opts; opt->name; opt++) { + const char *fmt = "%s"; + switch (opt->type) { + case VSH_OT_BOOL: + fmt = "[--%s]"; + break; + case VSH_OT_INT: + /* xgettext:c-format */ + fmt = ((opt->flags & VSH_OFLAG_REQ) ? "<%s>" + : _("[--%s <number>]")); + if (!(opt->flags & VSH_OFLAG_REQ_OPT)) + shortopt = true; + break; + case VSH_OT_STRING: + /* xgettext:c-format */ + fmt = _("[--%s <string>]"); + if (!(opt->flags & VSH_OFLAG_REQ_OPT)) + shortopt = true; + break; + case VSH_OT_DATA: + fmt = ((opt->flags & VSH_OFLAG_REQ) ? "<%s>" : "[<%s>]"); + if (!(opt->flags & VSH_OFLAG_REQ_OPT)) + shortopt = true; + break; + case VSH_OT_ARGV: + /* xgettext:c-format */ + if (shortopt) { + fmt = (opt->flags & VSH_OFLAG_REQ) + ? _("{[--%s] <string>}...") + : _("[[--%s] <string>]..."); + } else { + fmt = (opt->flags & VSH_OFLAG_REQ) ? _("<%s>...") + : _("[<%s>]..."); + } + break; + case VSH_OT_ALIAS: + /* aliases are intentionally undocumented */ + continue; + } + fputc(' ', stdout); + fprintf(stdout, fmt, opt->name); + } + } + fputc('\n', stdout); + + if (desc[0]) { + /* Print the description only if it's not empty. */ + fputs(_("\n DESCRIPTION\n"), stdout); + fprintf(stdout, " %s\n", _(desc)); + } + + if (def->opts && def->opts->name) { + const vshCmdOptDef *opt; + fputs(_("\n OPTIONS\n"), stdout); + for (opt = def->opts; opt->name; opt++) { + switch (opt->type) { + case VSH_OT_BOOL: + snprintf(buf, sizeof(buf), "--%s", opt->name); + break; + case VSH_OT_INT: + snprintf(buf, sizeof(buf), + (opt->flags & VSH_OFLAG_REQ) ? _("[--%s] <number>") + : _("--%s <number>"), opt->name); + break; + case VSH_OT_STRING: + /* OT_STRING should never be VSH_OFLAG_REQ */ + if (opt->flags & VSH_OFLAG_REQ) { + vshError(ctl, + _("internal error: bad options in command: '%s'"), + def->name); + return false; + } + snprintf(buf, sizeof(buf), _("--%s <string>"), opt->name); + break; + case VSH_OT_DATA: + /* OT_DATA should always be VSH_OFLAG_REQ */ + if (!(opt->flags & VSH_OFLAG_REQ)) { + vshError(ctl, + _("internal error: bad options in command: '%s'"), + def->name); + return false; + } + snprintf(buf, sizeof(buf), _("[--%s] <string>"), + opt->name); + break; + case VSH_OT_ARGV: + snprintf(buf, sizeof(buf), + shortopt ? _("[--%s] <string>") : _("<%s>"), + opt->name); + break; + case VSH_OT_ALIAS: + continue; + } + + fprintf(stdout, " %-15s %s\n", buf, _(opt->help)); + } + } + fputc('\n', stdout); + } + return true; +} + +/* --------------- + * Utils for work with runtime commands data + * --------------- + */ +static void +vshCommandOptFree(vshCmdOpt * arg) +{ + vshCmdOpt *a = arg; + + while (a) { + vshCmdOpt *tmp = a; + + a = a->next; + + VIR_FREE(tmp->data); + VIR_FREE(tmp); + } +} + +static void +vshCommandFree(vshCmd *cmd) +{ + vshCmd *c = cmd; + + while (c) { + vshCmd *tmp = c; + + c = c->next; + + if (tmp->opts) + vshCommandOptFree(tmp->opts); + VIR_FREE(tmp); + } +} + +/** + * vshCommandOpt: + * @cmd: parsed command line to search + * @name: option name to search for + * @opt: result of the search + * @needData: true if option must be non-boolean + * + * Look up an option passed to CMD by NAME. Returns 1 with *OPT set + * to the option if found, 0 with *OPT set to NULL if the name is + * valid and the option is not required, -1 with *OPT set to NULL if + * the option is required but not present, and assert if NAME is not + * valid (which indicates a programming error). No error messages are + * issued if a value is returned. + */ +static int +vshCommandOpt(const vshCmd *cmd, const char *name, vshCmdOpt **opt, + bool needData) +{ + vshCmdOpt *candidate = cmd->opts; + const vshCmdOptDef *valid = cmd->def->opts; + int ret = 0; + + /* See if option is valid and/or required. */ + *opt = NULL; + while (valid) { + assert(valid->name); + if (STREQ(name, valid->name)) + break; + valid++; + } + assert(!needData || valid->type != VSH_OT_BOOL); + if (valid->flags & VSH_OFLAG_REQ) + ret = -1; + + /* See if option is present on command line. */ + while (candidate) { + if (STREQ(candidate->def->name, name)) { + *opt = candidate; + ret = 1; + break; + } + candidate = candidate->next; + } + return ret; +} + +/** + * vshCommandOptInt: + * @ctl virsh control structure + * @cmd command reference + * @name option name + * @value result + * + * Convert option to int. + * On error, a message is displayed. + * + * Return value: + * >0 if option found and valid (@value updated) + * 0 if option not found and not required (@value untouched) + * <0 in all other cases (@value untouched) + */ +int +vshCommandOptInt(vshControl *ctl, const vshCmd *cmd, + const char *name, int *value) +{ + vshCmdOpt *arg; + int ret; + + if ((ret = vshCommandOpt(cmd, name, &arg, true)) <= 0) + return ret; + + if ((ret = virStrToLong_i(arg->data, NULL, 10, value)) < 0) + vshError(ctl, + _("Numeric value '%s' for <%s> option is malformed or out of range"), + arg->data, name); + else + ret = 1; + + return ret; +} + +static int +vshCommandOptUIntInternal(vshControl *ctl, + const vshCmd *cmd, + const char *name, + unsigned int *value, + bool wrap) +{ + vshCmdOpt *arg; + int ret; + + if ((ret = vshCommandOpt(cmd, name, &arg, true)) <= 0) + return ret; + + if (wrap) + ret = virStrToLong_ui(arg->data, NULL, 10, value); + else + ret = virStrToLong_uip(arg->data, NULL, 10, value); + if (ret < 0) + vshError(ctl, + _("Numeric value '%s' for <%s> option is malformed or out of range"), + arg->data, name); + else + ret = 1; + + return ret; +} + +/** + * vshCommandOptUInt: + * @ctl virsh control structure + * @cmd command reference + * @name option name + * @value result + * + * Convert option to unsigned int, reject negative numbers + * See vshCommandOptInt() + */ +int +vshCommandOptUInt(vshControl *ctl, const vshCmd *cmd, + const char *name, unsigned int *value) +{ + return vshCommandOptUIntInternal(ctl, cmd, name, value, false); +} + +/** + * vshCommandOptUIntWrap: + * @ctl virsh control structure + * @cmd command reference + * @name option name + * @value result + * + * Convert option to unsigned int, wraps negative numbers to positive + * See vshCommandOptInt() + */ +int +vshCommandOptUIntWrap(vshControl *ctl, const vshCmd *cmd, + const char *name, unsigned int *value) +{ + return vshCommandOptUIntInternal(ctl, cmd, name, value, true); +} + +static int +vshCommandOptULInternal(vshControl *ctl, + const vshCmd *cmd, + const char *name, + unsigned long *value, + bool wrap) +{ + vshCmdOpt *arg; + int ret; + + if ((ret = vshCommandOpt(cmd, name, &arg, true)) <= 0) + return ret; + + if (wrap) + ret = virStrToLong_ul(arg->data, NULL, 10, value); + else + ret = virStrToLong_ulp(arg->data, NULL, 10, value); + if (ret < 0) + vshError(ctl, + _("Numeric value '%s' for <%s> option is malformed or out of range"), + arg->data, name); + else + ret = 1; + + return ret; +} + +/* + * vshCommandOptUL: + * @ctl virsh control structure + * @cmd command reference + * @name option name + * @value result + * + * Convert option to unsigned long + * See vshCommandOptInt() + */ +int +vshCommandOptUL(vshControl *ctl, const vshCmd *cmd, + const char *name, unsigned long *value) +{ + return vshCommandOptULInternal(ctl, cmd, name, value, false); +} + +/** + * vshCommandOptULWrap: + * @ctl virsh control structure + * @cmd command reference + * @name option name + * @value result + * + * Convert option to unsigned long, wraps negative numbers to positive + * See vshCommandOptInt() + */ +int +vshCommandOptULWrap(vshControl *ctl, const vshCmd *cmd, + const char *name, unsigned long *value) +{ + return vshCommandOptULInternal(ctl, cmd, name, value, true); +} + +/** + * vshCommandOptString: + * @ctl virsh control structure + * @cmd command reference + * @name option name + * @value result + * + * Returns option as STRING + * Return value: + * >0 if option found and valid (@value updated) + * 0 if option not found and not required (@value untouched) + * <0 in all other cases (@value untouched) + */ +int +vshCommandOptString(vshControl *ctl ATTRIBUTE_UNUSED, const vshCmd *cmd, + const char *name, const char **value) +{ + vshCmdOpt *arg; + int ret; + + if ((ret = vshCommandOpt(cmd, name, &arg, true)) <= 0) + return ret; + + if (!*arg->data && !(arg->def->flags & VSH_OFLAG_EMPTY_OK)) + return -1; + *value = arg->data; + return 1; +} + +/** + * vshCommandOptStringReq: + * @ctl virsh control structure + * @cmd command structure + * @name option name + * @value result (updated to NULL or the option argument) + * + * Gets a option argument as string. + * + * Returns 0 on success or when the option is not present and not + * required, *value is set to the option argument. On error -1 is + * returned and error message printed. + */ +int +vshCommandOptStringReq(vshControl *ctl, + const vshCmd *cmd, + const char *name, + const char **value) +{ + vshCmdOpt *arg; + int ret; + const char *error = NULL; + + /* clear out the value */ + *value = NULL; + + ret = vshCommandOpt(cmd, name, &arg, true); + /* option is not required and not present */ + if (ret == 0) + return 0; + /* this should not be propagated here, just to be sure */ + if (ret == -1) + error = N_("Mandatory option not present"); + else if (!*arg->data && !(arg->def->flags & VSH_OFLAG_EMPTY_OK)) + error = N_("Option argument is empty"); + + if (error) { + vshError(ctl, _("Failed to get option '%s': %s"), name, _(error)); + return -1; + } + + *value = arg->data; + return 0; +} + +/** + * vshCommandOptLongLong: + * @ctl virsh control structure + * @cmd command reference + * @name option name + * @value result + * + * Returns option as long long + * See vshCommandOptInt() + */ +int +vshCommandOptLongLong(vshControl *ctl, const vshCmd *cmd, + const char *name, long long *value) +{ + vshCmdOpt *arg; + int ret; + + if ((ret = vshCommandOpt(cmd, name, &arg, true)) <= 0) + return ret; + + if ((ret = virStrToLong_ll(arg->data, NULL, 10, value)) < 0) + vshError(ctl, + _("Numeric value '%s' for <%s> option is malformed or out of range"), + arg->data, name); + else + ret = 1; + + return ret; +} + +static int +vshCommandOptULongLongInternal(vshControl *ctl, + const vshCmd *cmd, + const char *name, + unsigned long long *value, + bool wrap) +{ + vshCmdOpt *arg; + int ret; + + if ((ret = vshCommandOpt(cmd, name, &arg, true)) <= 0) + return ret; + + if (wrap) + ret = virStrToLong_ull(arg->data, NULL, 10, value); + else + ret = virStrToLong_ullp(arg->data, NULL, 10, value); + if (ret < 0) + vshError(ctl, + _("Numeric value '%s' for <%s> option is malformed or out of range"), + arg->data, name); + else + ret = 1; + + return ret; +} + +/** + * vshCommandOptULongLong: + * @ctl virsh control structure + * @cmd command reference + * @name option name + * @value result + * + * Returns option as long long, rejects negative numbers + * See vshCommandOptInt() + */ +int +vshCommandOptULongLong(vshControl *ctl, const vshCmd *cmd, + const char *name, unsigned long long *value) +{ + return vshCommandOptULongLongInternal(ctl, cmd, name, value, false); +} + +/** + * vshCommandOptULongLongWrap: + * @ctl virsh control structure + * @cmd command reference + * @name option name + * @value result + * + * Returns option as long long, wraps negative numbers to positive + * See vshCommandOptInt() + */ +int +vshCommandOptULongLongWrap(vshControl *ctl, const vshCmd *cmd, + const char *name, unsigned long long *value) +{ + return vshCommandOptULongLongInternal(ctl, cmd, name, value, true); +} + +/** + * vshCommandOptScaledInt: + * @ctl virsh control structure + * @cmd command reference + * @name option name + * @value result + * @scale default of 1 or 1024, if no suffix is present + * @max maximum value permitted + * + * Returns option as long long, scaled according to suffix + * See vshCommandOptInt() + */ +int +vshCommandOptScaledInt(vshControl *ctl, const vshCmd *cmd, + const char *name, unsigned long long *value, + int scale, unsigned long long max) +{ + vshCmdOpt *arg; + char *end; + int ret; + + if ((ret = vshCommandOpt(cmd, name, &arg, true)) <= 0) + return ret; + if (virStrToLong_ullp(arg->data, &end, 10, value) < 0 || + virScaleInteger(value, end, scale, max) < 0) + { + vshError(ctl, + _("Numeric value '%s' for <%s> option is malformed or out of range"), + arg->data, name); + ret = -1; + } else { + ret = 1; + } + + return ret; +} + + +/** + * vshCommandOptBool: + * @cmd command reference + * @name option name + * + * Returns true/false if the option exists. Note that this does NOT + * validate whether the option is actually boolean, or even whether + * name is legal; so that this can be used to probe whether a data + * option is present without actually using that data. + */ +bool +vshCommandOptBool(const vshCmd *cmd, const char *name) +{ + vshCmdOpt *dummy; + + return vshCommandOpt(cmd, name, &dummy, false) == 1; +} + +/** + * vshCommandOptArgv: + * @ctl virsh control structure + * @cmd command reference + * @opt starting point for the search + * + * Returns the next argv argument after OPT (or the first one if OPT + * is NULL), or NULL if no more are present. + * + * Requires that a VSH_OT_ARGV option be last in the + * list of supported options in CMD->def->opts. + */ +const vshCmdOpt * +vshCommandOptArgv(vshControl *ctl ATTRIBUTE_UNUSED, const vshCmd *cmd, + const vshCmdOpt *opt) +{ + opt = opt ? opt->next : cmd->opts; + + while (opt) { + if (opt->def->type == VSH_OT_ARGV) + return opt; + opt = opt->next; + } + return NULL; +} + +/* + * vshCommandOptTimeoutToMs: + * @ctl virsh control structure + * @cmd command reference + * @timeout result + * + * Parse an optional --timeout parameter in seconds, but store the + * value of the timeout in milliseconds. + * See vshCommandOptInt() + */ +int +vshCommandOptTimeoutToMs(vshControl *ctl, const vshCmd *cmd, int *timeout) +{ + int ret; + unsigned int utimeout; + + if ((ret = vshCommandOptUInt(ctl, cmd, "timeout", &utimeout)) <= 0) + return ret; + + /* Ensure that the timeout is not zero and that we can convert + * it from seconds to milliseconds without overflowing. */ + if (utimeout == 0 || utimeout > INT_MAX / 1000) { + vshError(ctl, + _("Numeric value '%u' for <%s> option is malformed or out of range"), + utimeout, + "timeout"); + ret = -1; + } else { + *timeout = ((int) utimeout) * 1000; + } + + return ret; +} + +static bool +vshConnectionUsability(vshControl *ctl, virConnectPtr conn) +{ + if (!conn || + virConnectIsAlive(conn) == 0) { + vshError(ctl, "%s", _("no valid connection")); + return false; + } + + /* The connection is considered dead only if + * virConnectIsAlive() successfuly says so. + */ + vshResetLibvirtError(); + + return true; +} + +/* + * Executes command(s) and returns return code from last command + */ +static bool +vshCommandRun(vshControl *ctl, const vshCmd *cmd) +{ + bool ret = true; + + while (cmd) { + struct timeval before, after; + bool enable_timing = ctl->timing; + + if ((ctl->conn == NULL || disconnected) && + !(cmd->def->flags & VSH_CMD_FLAG_NOCONNECT)) + vshReconnect(ctl); + + if (enable_timing) + GETTIMEOFDAY(&before); + + if ((cmd->def->flags & VSH_CMD_FLAG_NOCONNECT) || + vshConnectionUsability(ctl, ctl->conn)) { + ret = cmd->def->handler(ctl, cmd); + } else { + /* connection is not usable, return error */ + ret = false; + } + + if (enable_timing) + GETTIMEOFDAY(&after); + + /* try to automatically catch disconnections */ + if (!ret && + ((last_error != NULL) && + (((last_error->code == VIR_ERR_SYSTEM_ERROR) && + (last_error->domain == VIR_FROM_REMOTE)) || + (last_error->code == VIR_ERR_RPC) || + (last_error->code == VIR_ERR_NO_CONNECT) || + (last_error->code == VIR_ERR_INVALID_CONN)))) + disconnected++; + + if (!ret) + vshReportError(ctl); + + if (STREQ(cmd->def->name, "quit") || + STREQ(cmd->def->name, "exit")) /* hack ... */ + return ret; + + if (enable_timing) { + double diff_ms = (((after.tv_sec - before.tv_sec) * 1000.0) + + ((after.tv_usec - before.tv_usec) / 1000.0)); + + vshPrint(ctl, _("\n(Time: %.3f ms)\n\n"), diff_ms); + } else { + vshPrintExtra(ctl, "\n"); + } + cmd = cmd->next; + } + return ret; +} + +/* --------------- + * Command parsing + * --------------- + */ + +typedef enum { + VSH_TK_ERROR, /* Failed to parse a token */ + VSH_TK_ARG, /* Arbitrary argument, might be option or empty */ + VSH_TK_SUBCMD_END, /* Separation between commands */ + VSH_TK_END /* No more commands */ +} vshCommandToken; + +typedef struct _vshCommandParser vshCommandParser; +struct _vshCommandParser { + vshCommandToken(*getNextArg)(vshControl *, vshCommandParser *, + char **); + /* vshCommandStringGetArg() */ + char *pos; + /* vshCommandArgvGetArg() */ + char **arg_pos; + char **arg_end; +}; + +static bool +vshCommandParse(vshControl *ctl, vshCommandParser *parser) +{ + char *tkdata = NULL; + vshCmd *clast = NULL; + vshCmdOpt *first = NULL; + + if (ctl->cmd) { + vshCommandFree(ctl->cmd); + ctl->cmd = NULL; + } + + while (1) { + vshCmdOpt *last = NULL; + const vshCmdDef *cmd = NULL; + vshCommandToken tk; + bool data_only = false; + uint32_t opts_need_arg = 0; + uint32_t opts_required = 0; + uint32_t opts_seen = 0; + + first = NULL; + + while (1) { + const vshCmdOptDef *opt = NULL; + + tkdata = NULL; + tk = parser->getNextArg(ctl, parser, &tkdata); + + if (tk == VSH_TK_ERROR) + goto syntaxError; + if (tk != VSH_TK_ARG) { + VIR_FREE(tkdata); + break; + } + + if (cmd == NULL) { + /* first token must be command name */ + if (!(cmd = vshCmddefSearch(tkdata))) { + vshError(ctl, _("unknown command: '%s'"), tkdata); + goto syntaxError; /* ... or ignore this command only? */ + } + if (vshCmddefOptParse(cmd, &opts_need_arg, + &opts_required) < 0) { + vshError(ctl, + _("internal error: bad options in command: '%s'"), + tkdata); + goto syntaxError; + } + VIR_FREE(tkdata); + } else if (data_only) { + goto get_data; + } else if (tkdata[0] == '-' && tkdata[1] == '-' && + c_isalnum(tkdata[2])) { + char *optstr = strchr(tkdata + 2, '='); + int opt_index = 0; + + if (optstr) { + *optstr = '\0'; /* convert the '=' to '\0' */ + optstr = vshStrdup(ctl, optstr + 1); + } + /* Special case 'help' to ignore all spurious options */ + if (!(opt = vshCmddefGetOption(ctl, cmd, tkdata + 2, + &opts_seen, &opt_index, + &optstr))) { + VIR_FREE(optstr); + if (STREQ(cmd->name, "help")) + continue; + goto syntaxError; + } + VIR_FREE(tkdata); + + if (opt->type != VSH_OT_BOOL) { + /* option data */ + if (optstr) + tkdata = optstr; + else + tk = parser->getNextArg(ctl, parser, &tkdata); + if (tk == VSH_TK_ERROR) + goto syntaxError; + if (tk != VSH_TK_ARG) { + vshError(ctl, + _("expected syntax: --%s <%s>"), + opt->name, + opt->type == + VSH_OT_INT ? _("number") : _("string")); + goto syntaxError; + } + if (opt->type != VSH_OT_ARGV) + opts_need_arg &= ~(1 << opt_index); + } else { + tkdata = NULL; + if (optstr) { + vshError(ctl, _("invalid '=' after option --%s"), + opt->name); + VIR_FREE(optstr); + goto syntaxError; + } + } + } else if (tkdata[0] == '-' && tkdata[1] == '-' && + tkdata[2] == '\0') { + data_only = true; + continue; + } else { + get_data: + /* Special case 'help' to ignore spurious data */ + if (!(opt = vshCmddefGetData(cmd, &opts_need_arg, + &opts_seen)) && + STRNEQ(cmd->name, "help")) { + vshError(ctl, _("unexpected data '%s'"), tkdata); + goto syntaxError; + } + } + if (opt) { + /* save option */ + vshCmdOpt *arg = vshMalloc(ctl, sizeof(vshCmdOpt)); + + arg->def = opt; + arg->data = tkdata; + arg->next = NULL; + tkdata = NULL; + + if (!first) + first = arg; + if (last) + last->next = arg; + last = arg; + + vshDebug(ctl, VSH_ERR_INFO, "%s: %s(%s): %s\n", + cmd->name, + opt->name, + opt->type != VSH_OT_BOOL ? _("optdata") : _("bool"), + opt->type != VSH_OT_BOOL ? arg->data : _("(none)")); + } + } + + /* command parsed -- allocate new struct for the command */ + if (cmd) { + vshCmd *c = vshMalloc(ctl, sizeof(vshCmd)); + vshCmdOpt *tmpopt = first; + + /* if we encountered --help, replace parsed command with + * 'help <cmdname>' */ + for (tmpopt = first; tmpopt; tmpopt = tmpopt->next) { + if (STRNEQ(tmpopt->def->name, "help")) + continue; + + vshCommandOptFree(first); + first = vshMalloc(ctl, sizeof(vshCmdOpt)); + first->def = &(opts_help[0]); + first->data = vshStrdup(ctl, cmd->name); + first->next = NULL; + + cmd = vshCmddefSearch("help"); + opts_required = 0; + opts_seen = 0; + break; + } + + c->opts = first; + c->def = cmd; + c->next = NULL; + + if (vshCommandCheckOpts(ctl, c, opts_required, opts_seen) < 0) { + VIR_FREE(c); + goto syntaxError; + } + + if (!ctl->cmd) + ctl->cmd = c; + if (clast) + clast->next = c; + clast = c; + } + + if (tk == VSH_TK_END) + break; + } + + return true; + + syntaxError: + if (ctl->cmd) { + vshCommandFree(ctl->cmd); + ctl->cmd = NULL; + } + if (first) + vshCommandOptFree(first); + VIR_FREE(tkdata); + return false; +} + +/* -------------------- + * Command argv parsing + * -------------------- + */ + +static vshCommandToken ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) +vshCommandArgvGetArg(vshControl *ctl, vshCommandParser *parser, char **res) +{ + if (parser->arg_pos == parser->arg_end) { + *res = NULL; + return VSH_TK_END; + } + + *res = vshStrdup(ctl, *parser->arg_pos); + parser->arg_pos++; + return VSH_TK_ARG; +} + +static bool +vshCommandArgvParse(vshControl *ctl, int nargs, char **argv) +{ + vshCommandParser parser; + + if (nargs <= 0) + return false; + + parser.arg_pos = argv; + parser.arg_end = argv + nargs; + parser.getNextArg = vshCommandArgvGetArg; + return vshCommandParse(ctl, &parser); +} + +/* ---------------------- + * Command string parsing + * ---------------------- + */ + +static vshCommandToken ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) +vshCommandStringGetArg(vshControl *ctl, vshCommandParser *parser, char **res) +{ + bool single_quote = false; + bool double_quote = false; + int sz = 0; + char *p = parser->pos; + char *q = vshStrdup(ctl, p); + + *res = q; + + while (*p && (*p == ' ' || *p == '\t')) + p++; + + if (*p == '\0') + return VSH_TK_END; + if (*p == ';') { + parser->pos = ++p; /* = \0 or begin of next command */ + return VSH_TK_SUBCMD_END; + } + + while (*p) { + /* end of token is blank space or ';' */ + if (!double_quote && !single_quote && + (*p == ' ' || *p == '\t' || *p == ';')) + break; + + if (!double_quote && *p == '\'') { /* single quote */ + single_quote = !single_quote; + p++; + continue; + } else if (!single_quote && *p == '\\') { /* escape */ + /* + * The same as the bash, a \ in "" is an escaper, + * but a \ in '' is not an escaper. + */ + p++; + if (*p == '\0') { + vshError(ctl, "%s", _("dangling \\")); + return VSH_TK_ERROR; + } + } else if (!single_quote && *p == '"') { /* double quote */ + double_quote = !double_quote; + p++; + continue; + } + + *q++ = *p++; + sz++; + } + if (double_quote) { + vshError(ctl, "%s", _("missing \"")); + return VSH_TK_ERROR; + } + + *q = '\0'; + parser->pos = p; + return VSH_TK_ARG; +} + +static bool +vshCommandStringParse(vshControl *ctl, char *cmdstr) +{ + vshCommandParser parser; + + if (cmdstr == NULL || *cmdstr == '\0') + return false; + + parser.pos = cmdstr; + parser.getNextArg = vshCommandStringGetArg; + return vshCommandParse(ctl, &parser); +} + +/* --------------- + * Misc utils + * --------------- + */ +int +vshDomainState(vshControl *ctl, virDomainPtr dom, int *reason) +{ + virDomainInfo info; + + if (reason) + *reason = -1; + + if (!ctl->useGetInfo) { + int state; + if (virDomainGetState(dom, &state, reason, 0) < 0) { + virErrorPtr err = virGetLastError(); + if (err && err->code == VIR_ERR_NO_SUPPORT) + ctl->useGetInfo = true; + else + return -1; + } else { + return state; + } + } + + /* fall back to virDomainGetInfo if virDomainGetState is not supported */ + if (virDomainGetInfo(dom, &info) < 0) + return -1; + else + return info.state; +} + +/* Return a non-NULL string representation of a typed parameter; exit + * if we are out of memory. */ +char * +vshGetTypedParamValue(vshControl *ctl, virTypedParameterPtr item) +{ + int ret = 0; + char *str = NULL; + + switch (item->type) { + case VIR_TYPED_PARAM_INT: + ret = virAsprintf(&str, "%d", item->value.i); + break; + + case VIR_TYPED_PARAM_UINT: + ret = virAsprintf(&str, "%u", item->value.ui); + break; + + case VIR_TYPED_PARAM_LLONG: + ret = virAsprintf(&str, "%lld", item->value.l); + break; + + case VIR_TYPED_PARAM_ULLONG: + ret = virAsprintf(&str, "%llu", item->value.ul); + break; + + case VIR_TYPED_PARAM_DOUBLE: + ret = virAsprintf(&str, "%f", item->value.d); + break; + + case VIR_TYPED_PARAM_BOOLEAN: + str = vshStrdup(ctl, item->value.b ? _("yes") : _("no")); + break; + + case VIR_TYPED_PARAM_STRING: + str = vshStrdup(ctl, item->value.s); + break; + + default: + vshError(ctl, _("unimplemented parameter type %d"), item->type); + } + + if (ret < 0) { + vshError(ctl, "%s", _("Out of memory")); + exit(EXIT_FAILURE); + } + return str; +} + +void +vshDebug(vshControl *ctl, int level, const char *format, ...) +{ + va_list ap; + char *str; + + /* Aligning log levels to that of libvirt. + * Traces with levels >= user-specified-level + * gets logged into file + */ + if (level < ctl->debug) + return; + + va_start(ap, format); + vshOutputLogFile(ctl, level, format, ap); + va_end(ap); + + va_start(ap, format); + if (virVasprintf(&str, format, ap) < 0) { + /* Skip debug messages on low memory */ + va_end(ap); + return; + } + va_end(ap); + fputs(str, stdout); + VIR_FREE(str); +} + +void +vshPrintExtra(vshControl *ctl, const char *format, ...) +{ + va_list ap; + char *str; + + if (ctl && ctl->quiet) + return; + + va_start(ap, format); + if (virVasprintf(&str, format, ap) < 0) { + vshError(ctl, "%s", _("Out of memory")); + va_end(ap); + return; + } + va_end(ap); + fputs(str, stdout); + VIR_FREE(str); +} + + +bool +vshTTYIsInterruptCharacter(vshControl *ctl ATTRIBUTE_UNUSED, + const char chr ATTRIBUTE_UNUSED) +{ +#ifndef WIN32 + if (ctl->istty && + ctl->termattr.c_cc[VINTR] == chr) + return true; +#endif + + return false; +} + + +bool +vshTTYAvailable(vshControl *ctl) +{ + return ctl->istty; +} + + +int +vshTTYDisableInterrupt(vshControl *ctl ATTRIBUTE_UNUSED) +{ +#ifndef WIN32 + struct termios termset = ctl->termattr; + + if (!ctl->istty) + return -1; + + /* check if we need to set the terminal */ + if (termset.c_cc[VINTR] == _POSIX_VDISABLE) + return 0; + + termset.c_cc[VINTR] = _POSIX_VDISABLE; + termset.c_lflag &= ~ICANON; + + if (tcsetattr(STDIN_FILENO, TCSANOW, &termset) < 0) + return -1; +#endif + + return 0; +} + + +int +vshTTYRestore(vshControl *ctl ATTRIBUTE_UNUSED) +{ +#ifndef WIN32 + if (!ctl->istty) + return 0; + + if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &ctl->termattr) < 0) + return -1; +#endif + + return 0; +} + + +#if !defined(WIN32) && !defined(HAVE_CFMAKERAW) +/* provide fallback in case cfmakeraw isn't available */ +static void +cfmakeraw(struct termios *attr) +{ + attr->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP + | INLCR | IGNCR | ICRNL | IXON); + attr->c_oflag &= ~OPOST; + attr->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); + attr->c_cflag &= ~(CSIZE | PARENB); + attr->c_cflag |= CS8; +} +#endif /* !WIN32 && !HAVE_CFMAKERAW */ + + +int +vshTTYMakeRaw(vshControl *ctl ATTRIBUTE_UNUSED, + bool report_errors ATTRIBUTE_UNUSED) +{ +#ifndef WIN32 + struct termios rawattr = ctl->termattr; + char ebuf[1024]; + + if (!ctl->istty) { + if (report_errors) { + vshError(ctl, "%s", + _("unable to make terminal raw: console isn't a tty")); + } + + return -1; + } + + cfmakeraw(&rawattr); + + if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &rawattr) < 0) { + if (report_errors) + vshError(ctl, _("unable to set tty attributes: %s"), + virStrerror(errno, ebuf, sizeof(ebuf))); + return -1; + } +#endif + + return 0; +} + + +void +vshError(vshControl *ctl, const char *format, ...) +{ + va_list ap; + char *str; + + if (ctl != NULL) { + va_start(ap, format); + vshOutputLogFile(ctl, VSH_ERR_ERROR, format, ap); + va_end(ap); + } + + /* Most output is to stdout, but if someone ran virsh 2>&1, then + * printing to stderr will not interleave correctly with stdout + * unless we flush between every transition between streams. */ + fflush(stdout); + fputs(_("error: "), stderr); + + va_start(ap, format); + /* We can't recursively call vshError on an OOM situation, so ignore + failure here. */ + ignore_value(virVasprintf(&str, format, ap)); + va_end(ap); + + fprintf(stderr, "%s\n", NULLSTR(str)); + fflush(stderr); + VIR_FREE(str); +} + + +static void +vshEventLoop(void *opaque) +{ + vshControl *ctl = opaque; + + while (1) { + bool quit; + virMutexLock(&ctl->lock); + quit = ctl->quit; + virMutexUnlock(&ctl->lock); + + if (quit) + break; + + if (virEventRunDefaultImpl() < 0) + vshReportError(ctl); + } +} + + +/* + * Helpers for waiting for a libvirt event. + */ + +/* We want to use SIGINT to cancel a wait; but as signal handlers + * don't have an opaque argument, we have to use static storage. */ +static int vshEventFd = -1; +static struct sigaction vshEventOldAction; + + +/* Signal handler installed in vshEventStart, removed in vshEventCleanup. */ +static void +vshEventInt(int sig ATTRIBUTE_UNUSED, + siginfo_t *siginfo ATTRIBUTE_UNUSED, + void *context ATTRIBUTE_UNUSED) +{ + char reason = VSH_EVENT_INTERRUPT; + if (vshEventFd >= 0) + ignore_value(safewrite(vshEventFd, &reason, 1)); +} + + +/* Event loop handler used to limit length of waiting for any other event. */ +static void +vshEventTimeout(int timer ATTRIBUTE_UNUSED, + void *opaque) +{ + vshControl *ctl = opaque; + char reason = VSH_EVENT_TIMEOUT; + + if (ctl->eventPipe[1] >= 0) + ignore_value(safewrite(ctl->eventPipe[1], &reason, 1)); +} + + +/** + * vshEventStart: + * @ctl virsh command struct + * @timeout_ms max wait time in milliseconds, or 0 for indefinite + * + * Set up a wait for a libvirt event. The wait can be canceled by + * SIGINT or by calling vshEventDone() in your event handler. If + * @timeout_ms is positive, the wait will also end if the timeout + * expires. Call vshEventWait() to block the main thread (the event + * handler runs in the event loop thread). When done (including if + * there was an error registering for an event), use vshEventCleanup() + * to quit waiting. Returns 0 on success, -1 on failure. */ +int +vshEventStart(vshControl *ctl, int timeout_ms) +{ + struct sigaction action; + + assert(ctl->eventPipe[0] == -1 && ctl->eventPipe[1] == -1 && + vshEventFd == -1 && ctl->eventTimerId >= 0); + if (pipe2(ctl->eventPipe, O_CLOEXEC) < 0) { + char ebuf[1024]; + + vshError(ctl, _("failed to create pipe: %s"), + virStrerror(errno, ebuf, sizeof(ebuf))); + return -1; + } + vshEventFd = ctl->eventPipe[1]; + + action.sa_sigaction = vshEventInt; + action.sa_flags = SA_SIGINFO; + sigemptyset(&action.sa_mask); + sigaction(SIGINT, &action, &vshEventOldAction); + + if (timeout_ms) + virEventUpdateTimeout(ctl->eventTimerId, timeout_ms); + + return 0; +} + + +/** + * vshEventDone: + * @ctl virsh command struct + * + * Call this from an event callback to let the main thread quit + * blocking on further events. + */ +void +vshEventDone(vshControl *ctl) +{ + char reason = VSH_EVENT_DONE; + + if (ctl->eventPipe[1] >= 0) + ignore_value(safewrite(ctl->eventPipe[1], &reason, 1)); +} + + +/** + * vshEventWait: + * @ctl virsh command struct + * + * Call this in the main thread after calling vshEventStart() then + * registering for one or more events. This call will block until + * SIGINT, the timeout registered at the start, or until one of your + * event handlers calls vshEventDone(). Returns an enum VSH_EVENT_* + * stating how the wait concluded, or -1 on error. + */ +int +vshEventWait(vshControl *ctl) +{ + char buf; + int rv; + + assert(ctl->eventPipe[0] >= 0); + while ((rv = read(ctl->eventPipe[0], &buf, 1)) < 0 && errno == EINTR); + if (rv != 1) { + char ebuf[1024]; + + if (!rv) + errno = EPIPE; + vshError(ctl, _("failed to determine loop exit status: %s"), + virStrerror(errno, ebuf, sizeof(ebuf))); + return -1; + } + return buf; +} + + +/** + * vshEventCleanup: + * @ctl virsh command struct + * + * Call at the end of any function that has used vshEventStart(), to + * tear down any remaining SIGINT or timeout handlers. + */ +void +vshEventCleanup(vshControl *ctl) +{ + if (vshEventFd >= 0) { + sigaction(SIGINT, &vshEventOldAction, NULL); + vshEventFd = -1; + } + VIR_FORCE_CLOSE(ctl->eventPipe[0]); + VIR_FORCE_CLOSE(ctl->eventPipe[1]); + virEventUpdateTimeout(ctl->eventTimerId, -1); +} + + +/* + * Initialize debug settings. + */ +static void +vshInitDebug(vshControl *ctl) +{ + const char *debugEnv; + + if (ctl->debug == VSH_DEBUG_DEFAULT) { + /* log level not set from commandline, check env variable */ + debugEnv = virGetEnvAllowSUID("VIRSH_DEBUG"); + if (debugEnv) { + int debug; + if (virStrToLong_i(debugEnv, NULL, 10, &debug) < 0 || + debug < VSH_ERR_DEBUG || debug > VSH_ERR_ERROR) { + vshError(ctl, "%s", + _("VIRSH_DEBUG not set with a valid numeric value")); + } else { + ctl->debug = debug; + } + } + } + + if (ctl->logfile == NULL) { + /* log file not set from cmdline */ + debugEnv = virGetEnvBlockSUID("VIRSH_LOG_FILE"); + if (debugEnv && *debugEnv) { + ctl->logfile = vshStrdup(ctl, debugEnv); + vshOpenLogFile(ctl); + } + } +} + +/* + * Initialize connection. + */ +static bool +vshInit(vshControl *ctl) +{ + /* Since we have the commandline arguments parsed, we need to + * re-initialize all the debugging to make it work properly */ + vshInitDebug(ctl); + + if (ctl->conn) + return false; + + /* set up the library error handler */ + virSetErrorFunc(NULL, virshErrorHandler); + + if (virEventRegisterDefaultImpl() < 0) + return false; + + if (virThreadCreate(&ctl->eventLoop, true, vshEventLoop, ctl) < 0) + return false; + ctl->eventLoopStarted = true; + + if ((ctl->eventTimerId = virEventAddTimeout(-1, vshEventTimeout, ctl, + NULL)) < 0) + return false; + + if (ctl->name) { + vshReconnect(ctl); + /* Connecting to a named connection must succeed, but we delay + * connecting to the default connection until we need it + * (since the first command might be 'connect' which allows a + * non-default connection, or might be 'help' which needs no + * connection). + */ + if (!ctl->conn) { + vshReportError(ctl); + return false; + } + } + + return true; +} + +#define LOGFILE_FLAGS (O_WRONLY | O_APPEND | O_CREAT | O_SYNC) + +/** + * vshOpenLogFile: + * + * Open log file. + */ +void +vshOpenLogFile(vshControl *ctl) +{ + if (ctl->logfile == NULL) + return; + + if ((ctl->log_fd = open(ctl->logfile, LOGFILE_FLAGS, FILE_MODE)) < 0) { + vshError(ctl, "%s", + _("failed to open the log file. check the log file path")); + exit(EXIT_FAILURE); + } +} + +/** + * vshOutputLogFile: + * + * Outputting an error to log file. + */ +void +vshOutputLogFile(vshControl *ctl, int log_level, const char *msg_format, + va_list ap) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + char *str = NULL; + size_t len; + const char *lvl = ""; + time_t stTime; + struct tm stTm; + + if (ctl->log_fd == -1) + return; + + /** + * create log format + * + * [YYYY.MM.DD HH:MM:SS SIGNATURE PID] LOG_LEVEL message + */ + time(&stTime); + localtime_r(&stTime, &stTm); + virBufferAsprintf(&buf, "[%d.%02d.%02d %02d:%02d:%02d %s %d] ", + (1900 + stTm.tm_year), + (1 + stTm.tm_mon), + stTm.tm_mday, + stTm.tm_hour, + stTm.tm_min, + stTm.tm_sec, + SIGN_NAME, + (int) getpid()); + switch (log_level) { + case VSH_ERR_DEBUG: + lvl = LVL_DEBUG; + break; + case VSH_ERR_INFO: + lvl = LVL_INFO; + break; + case VSH_ERR_NOTICE: + lvl = LVL_INFO; + break; + case VSH_ERR_WARNING: + lvl = LVL_WARNING; + break; + case VSH_ERR_ERROR: + lvl = LVL_ERROR; + break; + default: + lvl = LVL_DEBUG; + break; + } + virBufferAsprintf(&buf, "%s ", lvl); + virBufferVasprintf(&buf, msg_format, ap); + virBufferAddChar(&buf, '\n'); + + if (virBufferError(&buf)) + goto error; + + str = virBufferContentAndReset(&buf); + len = strlen(str); + if (len > 1 && str[len - 2] == '\n') { + str[len - 1] = '\0'; + len--; + } + + /* write log */ + if (safewrite(ctl->log_fd, str, len) < 0) + goto error; + + VIR_FREE(str); + return; + + error: + vshCloseLogFile(ctl); + vshError(ctl, "%s", _("failed to write the log file")); + virBufferFreeAndReset(&buf); + VIR_FREE(str); +} + +/** + * vshCloseLogFile: + * + * Close log file. + */ +void +vshCloseLogFile(vshControl *ctl) +{ + char ebuf[1024]; + + /* log file close */ + if (VIR_CLOSE(ctl->log_fd) < 0) { + vshError(ctl, _("%s: failed to write log file: %s"), + ctl->logfile ? ctl->logfile : "?", + virStrerror(errno, ebuf, sizeof(ebuf))); + } + + if (ctl->logfile) { + VIR_FREE(ctl->logfile); + ctl->logfile = NULL; + } +} + +#if WITH_READLINE + +/* ----------------- + * Readline stuff + * ----------------- + */ + +/* + * Generator function for command completion. STATE lets us + * know whether to start from scratch; without any state + * (i.e. STATE == 0), then we start at the top of the list. + */ +static char * +vshReadlineCommandGenerator(const char *text, int state) +{ + static int grp_list_index, cmd_list_index, len; + const char *name; + const vshCmdGrp *grp; + const vshCmdDef *cmds; + + if (!state) { + grp_list_index = 0; + cmd_list_index = 0; + len = strlen(text); + } + + grp = cmdGroups; + + /* Return the next name which partially matches from the + * command list. + */ + while (grp[grp_list_index].name) { + cmds = grp[grp_list_index].commands; + + if (cmds[cmd_list_index].name) { + while ((name = cmds[cmd_list_index].name)) { + cmd_list_index++; + + if (STREQLEN(name, text, len)) + return vshStrdup(NULL, name); + } + } else { + cmd_list_index = 0; + grp_list_index++; + } + } + + /* If no names matched, then return NULL. */ + return NULL; +} + +static char * +vshReadlineOptionsGenerator(const char *text, int state) +{ + static int list_index, len; + static const vshCmdDef *cmd; + const char *name; + + if (!state) { + /* determine command name */ + char *p; + char *cmdname; + + if (!(p = strchr(rl_line_buffer, ' '))) + return NULL; + + cmdname = vshCalloc(NULL, (p - rl_line_buffer) + 1, 1); + memcpy(cmdname, rl_line_buffer, p - rl_line_buffer); + + cmd = vshCmddefSearch(cmdname); + list_index = 0; + len = strlen(text); + VIR_FREE(cmdname); + } + + if (!cmd) + return NULL; + + if (!cmd->opts) + return NULL; + + while ((name = cmd->opts[list_index].name)) { + const vshCmdOptDef *opt = &cmd->opts[list_index]; + char *res; + + list_index++; + + if (opt->type == VSH_OT_DATA || opt->type == VSH_OT_ARGV) + /* ignore non --option */ + continue; + + if (len > 2) { + if (STRNEQLEN(name, text + 2, len - 2)) + continue; + } + res = vshMalloc(NULL, strlen(name) + 3); + snprintf(res, strlen(name) + 3, "--%s", name); + return res; + } + + /* If no names matched, then return NULL. */ + return NULL; +} + +static char ** +vshReadlineCompletion(const char *text, int start, + int end ATTRIBUTE_UNUSED) +{ + char **matches = (char **) NULL; + + if (start == 0) + /* command name generator */ + matches = rl_completion_matches(text, vshReadlineCommandGenerator); + else + /* commands options */ + matches = rl_completion_matches(text, vshReadlineOptionsGenerator); + return matches; +} + +# define VIRSH_HISTSIZE_MAX 500000 + +static int +vshReadlineInit(vshControl *ctl) +{ + char *userdir = NULL; + int max_history = 500; + const char *histsize_str; + + /* Allow conditional parsing of the ~/.inputrc file. + * Work around ancient readline 4.1 (hello Mac OS X), + * which declared it as 'char *' instead of 'const char *'. + */ + rl_readline_name = (char *) "virsh"; + + /* Tell the completer that we want a crack first. */ + rl_attempted_completion_function = vshReadlineCompletion; + + /* Limit the total size of the history buffer */ + if ((histsize_str = virGetEnvBlockSUID("VIRSH_HISTSIZE"))) { + if (virStrToLong_i(histsize_str, NULL, 10, &max_history) < 0) { + vshError(ctl, "%s", _("Bad $VIRSH_HISTSIZE value.")); + VIR_FREE(userdir); + return -1; + } else if (max_history > VIRSH_HISTSIZE_MAX || max_history < 0) { + vshError(ctl, _("$VIRSH_HISTSIZE value should be between 0 and %d"), + VIRSH_HISTSIZE_MAX); + VIR_FREE(userdir); + return -1; + } + } + stifle_history(max_history); + + /* Prepare to read/write history from/to the $XDG_CACHE_HOME/virsh/history file */ + userdir = virGetUserCacheDirectory(); + + if (userdir == NULL) { + vshError(ctl, "%s", _("Could not determine home directory")); + return -1; + } + + if (virAsprintf(&ctl->historydir, "%s/virsh", userdir) < 0) { + vshError(ctl, "%s", _("Out of memory")); + VIR_FREE(userdir); + return -1; + } + + if (virAsprintf(&ctl->historyfile, "%s/history", ctl->historydir) < 0) { + vshError(ctl, "%s", _("Out of memory")); + VIR_FREE(userdir); + return -1; + } + + VIR_FREE(userdir); + + read_history(ctl->historyfile); + + return 0; +} + +static void +vshReadlineDeinit(vshControl *ctl) +{ + if (ctl->historyfile != NULL) { + if (virFileMakePathWithMode(ctl->historydir, 0755) < 0 && + errno != EEXIST) { + char ebuf[1024]; + vshError(ctl, _("Failed to create '%s': %s"), + ctl->historydir, virStrerror(errno, ebuf, sizeof(ebuf))); + } else { + write_history(ctl->historyfile); + } + } + + VIR_FREE(ctl->historydir); + VIR_FREE(ctl->historyfile); +} + +static char * +vshReadline(vshControl *ctl ATTRIBUTE_UNUSED, const char *prompt) +{ + return readline(prompt); +} + +#else /* !WITH_READLINE */ + +static int +vshReadlineInit(vshControl *ctl ATTRIBUTE_UNUSED) +{ + /* empty */ + return 0; +} + +static void +vshReadlineDeinit(vshControl *ctl ATTRIBUTE_UNUSED) +{ + /* empty */ +} + +static char * +vshReadline(vshControl *ctl, const char *prompt) +{ + char line[1024]; + char *r; + int len; + + fputs(prompt, stdout); + r = fgets(line, sizeof(line), stdin); + if (r == NULL) return NULL; /* EOF */ + + /* Chomp trailing \n */ + len = strlen(r); + if (len > 0 && r[len-1] == '\n') + r[len-1] = '\0'; + + return vshStrdup(ctl, r); +} + +#endif /* !WITH_READLINE */ + +static void +vshDeinitTimer(int timer ATTRIBUTE_UNUSED, void *opaque ATTRIBUTE_UNUSED) +{ + /* nothing to be done here */ +} + +/* + * Deinitialize virsh + */ +static bool +vshDeinit(vshControl *ctl) +{ + vshReadlineDeinit(ctl); + vshCloseLogFile(ctl); + VIR_FREE(ctl->name); + if (ctl->conn) { + int ret; + virConnectUnregisterCloseCallback(ctl->conn, vshCatchDisconnect); + ret = virConnectClose(ctl->conn); + if (ret < 0) + vshError(ctl, "%s", _("Failed to disconnect from the hypervisor")); + else if (ret > 0) + vshError(ctl, "%s", _("One or more references were leaked after " + "disconnect from the hypervisor")); + } + virResetLastError(); + + if (ctl->eventLoopStarted) { + int timer; + + virMutexLock(&ctl->lock); + ctl->quit = true; + /* HACK: Add a dummy timeout to break event loop */ + timer = virEventAddTimeout(0, vshDeinitTimer, NULL, NULL); + virMutexUnlock(&ctl->lock); + + virThreadJoin(&ctl->eventLoop); + + if (timer != -1) + virEventRemoveTimeout(timer); + + if (ctl->eventTimerId != -1) + virEventRemoveTimeout(ctl->eventTimerId); + + ctl->eventLoopStarted = false; + } + + virMutexDestroy(&ctl->lock); + + return true; +} + +/* + * Print usage + */ +static void +vshUsage(void) +{ + const vshCmdGrp *grp; + const vshCmdDef *cmd; + + fprintf(stdout, _("\n%s [options]... [<command_string>]" + "\n%s [options]... <command> [args...]\n\n" + " options:\n" + " -c | --connect=URI hypervisor connection URI\n" + " -d | --debug=NUM debug level [0-4]\n" + " -e | --escape <char> set escape sequence for console\n" + " -h | --help this help\n" + " -k | --keepalive-interval=NUM\n" + " keepalive interval in seconds, 0 for disable\n" + " -K | --keepalive-count=NUM\n" + " number of possible missed keepalive messages\n" + " -l | --log=FILE output logging to file\n" + " -q | --quiet quiet mode\n" + " -r | --readonly connect readonly\n" + " -t | --timing print timing information\n" + " -v short version\n" + " -V long version\n" + " --version[=TYPE] version, TYPE is short or long (default short)\n" + " commands (non interactive mode):\n\n"), progname, progname); + + for (grp = cmdGroups; grp->name; grp++) { + fprintf(stdout, _(" %s (help keyword '%s')\n"), + grp->name, grp->keyword); + for (cmd = grp->commands; cmd->name; cmd++) { + if (cmd->flags & VSH_CMD_FLAG_ALIAS) + continue; + fprintf(stdout, + " %-30s %s\n", cmd->name, + _(vshCmddefGetInfo(cmd, "help"))); + } + fprintf(stdout, "\n"); + } + + fprintf(stdout, "%s", + _("\n (specify help <group> for details about the commands in the group)\n")); + fprintf(stdout, "%s", + _("\n (specify help <command> for details about the command)\n\n")); + return; +} + +/* + * Show version and options compiled in + */ +static void +vshShowVersion(vshControl *ctl ATTRIBUTE_UNUSED) +{ + /* FIXME - list a copyright blurb, as in GNU programs? */ + vshPrint(ctl, _("Virsh command line tool of libvirt %s\n"), VERSION); + vshPrint(ctl, _("See web site at %s\n\n"), "http://libvirt.org/"); + + vshPrint(ctl, "%s", _("Compiled with support for:\n")); + vshPrint(ctl, "%s", _(" Hypervisors:")); +#ifdef WITH_QEMU + vshPrint(ctl, " QEMU/KVM"); +#endif +#ifdef WITH_LXC + vshPrint(ctl, " LXC"); +#endif +#ifdef WITH_UML + vshPrint(ctl, " UML"); +#endif +#ifdef WITH_XEN + vshPrint(ctl, " Xen"); +#endif +#ifdef WITH_LIBXL + vshPrint(ctl, " LibXL"); +#endif +#ifdef WITH_OPENVZ + vshPrint(ctl, " OpenVZ"); +#endif +#ifdef WITH_VMWARE + vshPrint(ctl, " VMWare"); +#endif +#ifdef WITH_PHYP + vshPrint(ctl, " PHYP"); +#endif +#ifdef WITH_VBOX + vshPrint(ctl, " VirtualBox"); +#endif +#ifdef WITH_ESX + vshPrint(ctl, " ESX"); +#endif +#ifdef WITH_HYPERV + vshPrint(ctl, " Hyper-V"); +#endif +#ifdef WITH_XENAPI + vshPrint(ctl, " XenAPI"); +#endif +#ifdef WITH_BHYVE + vshPrint(ctl, " Bhyve"); +#endif +#ifdef WITH_TEST + vshPrint(ctl, " Test"); +#endif + vshPrint(ctl, "\n"); + + vshPrint(ctl, "%s", _(" Networking:")); +#ifdef WITH_REMOTE + vshPrint(ctl, " Remote"); +#endif +#ifdef WITH_NETWORK + vshPrint(ctl, " Network"); +#endif +#ifdef WITH_BRIDGE + vshPrint(ctl, " Bridging"); +#endif +#if defined(WITH_INTERFACE) + vshPrint(ctl, " Interface"); +# if defined(WITH_NETCF) + vshPrint(ctl, " netcf"); +# elif defined(WITH_UDEV) + vshPrint(ctl, " udev"); +# endif +#endif +#ifdef WITH_NWFILTER + vshPrint(ctl, " Nwfilter"); +#endif +#ifdef WITH_VIRTUALPORT + vshPrint(ctl, " VirtualPort"); +#endif + vshPrint(ctl, "\n"); + + vshPrint(ctl, "%s", _(" Storage:")); +#ifdef WITH_STORAGE_DIR + vshPrint(ctl, " Dir"); +#endif +#ifdef WITH_STORAGE_DISK + vshPrint(ctl, " Disk"); +#endif +#ifdef WITH_STORAGE_FS + vshPrint(ctl, " Filesystem"); +#endif +#ifdef WITH_STORAGE_SCSI + vshPrint(ctl, " SCSI"); +#endif +#ifdef WITH_STORAGE_MPATH + vshPrint(ctl, " Multipath"); +#endif +#ifdef WITH_STORAGE_ISCSI + vshPrint(ctl, " iSCSI"); +#endif +#ifdef WITH_STORAGE_LVM + vshPrint(ctl, " LVM"); +#endif +#ifdef WITH_STORAGE_RBD + vshPrint(ctl, " RBD"); +#endif +#ifdef WITH_STORAGE_SHEEPDOG + vshPrint(ctl, " Sheepdog"); +#endif +#ifdef WITH_STORAGE_GLUSTER + vshPrint(ctl, " Gluster"); +#endif + vshPrint(ctl, "\n"); + + vshPrint(ctl, "%s", _(" Miscellaneous:")); +#ifdef WITH_LIBVIRTD + vshPrint(ctl, " Daemon"); +#endif +#ifdef WITH_NODE_DEVICES + vshPrint(ctl, " Nodedev"); +#endif +#ifdef WITH_SECDRIVER_APPARMOR + vshPrint(ctl, " AppArmor"); +#endif +#ifdef WITH_SECDRIVER_SELINUX + vshPrint(ctl, " SELinux"); +#endif +#ifdef WITH_SECRETS + vshPrint(ctl, " Secrets"); +#endif +#ifdef ENABLE_DEBUG + vshPrint(ctl, " Debug"); +#endif +#ifdef WITH_DTRACE_PROBES + vshPrint(ctl, " DTrace"); +#endif +#if WITH_READLINE + vshPrint(ctl, " Readline"); +#endif +#ifdef WITH_DRIVER_MODULES + vshPrint(ctl, " Modular"); +#endif + vshPrint(ctl, "\n"); +} + +static bool +vshAllowedEscapeChar(char c) +{ + /* Allowed escape characters: + * a-z A-Z @ [ \ ] ^ _ + */ + return ('a' <= c && c <= 'z') || + ('@' <= c && c <= '_'); +} + +/* + * argv[]: virsh [options] [command] + * + */ +static bool +vshParseArgv(vshControl *ctl, int argc, char **argv) +{ + int arg, len, debug, keepalive; + size_t i; + int longindex = -1; + struct option opt[] = { + {"connect", required_argument, NULL, 'c'}, + {"debug", required_argument, NULL, 'd'}, + {"escape", required_argument, NULL, 'e'}, + {"help", no_argument, NULL, 'h'}, + {"keepalive-interval", required_argument, NULL, 'k'}, + {"keepalive-count", required_argument, NULL, 'K'}, + {"log", required_argument, NULL, 'l'}, + {"quiet", no_argument, NULL, 'q'}, + {"readonly", no_argument, NULL, 'r'}, + {"timing", no_argument, NULL, 't'}, + {"version", optional_argument, NULL, 'v'}, + {NULL, 0, NULL, 0} + }; + + /* Standard (non-command) options. The leading + ensures that no + * argument reordering takes place, so that command options are + * not confused with top-level virsh options. */ + while ((arg = getopt_long(argc, argv, "+:c:d:e:hk:K:l:qrtvV", opt, &longindex)) != -1) { + switch (arg) { + case 'c': + VIR_FREE(ctl->name); + ctl->name = vshStrdup(ctl, optarg); + break; + case 'd': + if (virStrToLong_i(optarg, NULL, 10, &debug) < 0) { + vshError(ctl, _("option %s takes a numeric argument"), + longindex == -1 ? "-d" : "--debug"); + exit(EXIT_FAILURE); + } + if (debug < VSH_ERR_DEBUG || debug > VSH_ERR_ERROR) + vshError(ctl, _("ignoring debug level %d out of range [%d-%d]"), + debug, VSH_ERR_DEBUG, VSH_ERR_ERROR); + else + ctl->debug = debug; + break; + case 'e': + len = strlen(optarg); + + if ((len == 2 && *optarg == '^' && + vshAllowedEscapeChar(optarg[1])) || + (len == 1 && *optarg != '^')) { + ctl->escapeChar = optarg; + } else { + vshError(ctl, _("Invalid string '%s' for escape sequence"), + optarg); + exit(EXIT_FAILURE); + } + break; + case 'h': + vshUsage(); + exit(EXIT_SUCCESS); + break; + case 'k': + if (virStrToLong_i(optarg, NULL, 0, &keepalive) < 0) { + vshError(ctl, + _("Invalid value for option %s"), + longindex == -1 ? "-k" : "--keepalive-interval"); + exit(EXIT_FAILURE); + } + + if (keepalive < 0) { + vshError(ctl, + _("option %s requires a positive integer argument"), + longindex == -1 ? "-k" : "--keepalive-interval"); + exit(EXIT_FAILURE); + } + ctl->keepalive_interval = keepalive; + break; + case 'K': + if (virStrToLong_i(optarg, NULL, 0, &keepalive) < 0) { + vshError(ctl, + _("Invalid value for option %s"), + longindex == -1 ? "-K" : "--keepalive-count"); + exit(EXIT_FAILURE); + } + + if (keepalive < 0) { + vshError(ctl, + _("option %s requires a positive integer argument"), + longindex == -1 ? "-K" : "--keepalive-count"); + exit(EXIT_FAILURE); + } + ctl->keepalive_count = keepalive; + break; + case 'l': + vshCloseLogFile(ctl); + ctl->logfile = vshStrdup(ctl, optarg); + vshOpenLogFile(ctl); + break; + case 'q': + ctl->quiet = true; + break; + case 't': + ctl->timing = true; + break; + case 'r': + ctl->readonly = true; + break; + case 'v': + if (STRNEQ_NULLABLE(optarg, "long")) { + puts(VERSION); + exit(EXIT_SUCCESS); + } + /* fall through */ + case 'V': + vshShowVersion(ctl); + exit(EXIT_SUCCESS); + case ':': + for (i = 0; opt[i].name != NULL; i++) { + if (opt[i].val == optopt) + break; + } + if (opt[i].name) + vshError(ctl, _("option '-%c'/'--%s' requires an argument"), + optopt, opt[i].name); + else + vshError(ctl, _("option '-%c' requires an argument"), optopt); + exit(EXIT_FAILURE); + case '?': + if (optopt) + vshError(ctl, _("unsupported option '-%c'. See --help."), optopt); + else + vshError(ctl, _("unsupported option '%s'. See --help."), argv[optind - 1]); + exit(EXIT_FAILURE); + default: + vshError(ctl, _("unknown option")); + exit(EXIT_FAILURE); + } + longindex = -1; + } + + if (argc > optind) { + /* parse command */ + ctl->imode = false; + if (argc - optind == 1) { + vshDebug(ctl, VSH_ERR_INFO, "commands: \"%s\"\n", argv[optind]); + return vshCommandStringParse(ctl, argv[optind]); + } else { + return vshCommandArgvParse(ctl, argc - optind, argv + optind); + } + } + return true; +} + +static const vshCmdDef virshCmds[] = { + {.name = "cd", + .handler = cmdCd, + .opts = opts_cd, + .info = info_cd, + .flags = VSH_CMD_FLAG_NOCONNECT + }, + {.name = "connect", + .handler = cmdConnect, + .opts = opts_connect, + .info = info_connect, + .flags = VSH_CMD_FLAG_NOCONNECT + }, + {.name = "echo", + .handler = cmdEcho, + .opts = opts_echo, + .info = info_echo, + .flags = VSH_CMD_FLAG_NOCONNECT + }, + {.name = "exit", + .handler = cmdQuit, + .opts = NULL, + .info = info_quit, + .flags = VSH_CMD_FLAG_NOCONNECT + }, + {.name = "help", + .handler = cmdHelp, + .opts = opts_help, + .info = info_help, + .flags = VSH_CMD_FLAG_NOCONNECT + }, + {.name = "pwd", + .handler = cmdPwd, + .opts = NULL, + .info = info_pwd, + .flags = VSH_CMD_FLAG_NOCONNECT + }, + {.name = "quit", + .handler = cmdQuit, + .opts = NULL, + .info = info_quit, + .flags = VSH_CMD_FLAG_NOCONNECT + }, + {.name = NULL} +}; + +static const vshCmdGrp cmdGroups[] = { + {VSH_CMD_GRP_DOM_MANAGEMENT, "domain", domManagementCmds}, + {VSH_CMD_GRP_DOM_MONITORING, "monitor", domMonitoringCmds}, + {VSH_CMD_GRP_HOST_AND_HV, "host", hostAndHypervisorCmds}, + {VSH_CMD_GRP_IFACE, "interface", ifaceCmds}, + {VSH_CMD_GRP_NWFILTER, "filter", nwfilterCmds}, + {VSH_CMD_GRP_NETWORK, "network", networkCmds}, + {VSH_CMD_GRP_NODEDEV, "nodedev", nodedevCmds}, + {VSH_CMD_GRP_SECRET, "secret", secretCmds}, + {VSH_CMD_GRP_SNAPSHOT, "snapshot", snapshotCmds}, + {VSH_CMD_GRP_STORAGE_POOL, "pool", storagePoolCmds}, + {VSH_CMD_GRP_STORAGE_VOL, "volume", storageVolCmds}, + {VSH_CMD_GRP_VIRSH, "virsh", virshCmds}, + {NULL, NULL, NULL} +}; + +int +main(int argc, char **argv) +{ + vshControl _ctl, *ctl = &_ctl; + const char *defaultConn; + bool ret = true; + + memset(ctl, 0, sizeof(vshControl)); + ctl->imode = true; /* default is interactive mode */ + ctl->log_fd = -1; /* Initialize log file descriptor */ + ctl->debug = VSH_DEBUG_DEFAULT; + ctl->escapeChar = "^]"; /* Same default as telnet */ + + /* In order to distinguish default from setting to 0 */ + ctl->keepalive_interval = -1; + ctl->keepalive_count = -1; + + ctl->eventPipe[0] = -1; + ctl->eventPipe[1] = -1; + ctl->eventTimerId = -1; + + if (!setlocale(LC_ALL, "")) { + perror("setlocale"); + /* failure to setup locale is not fatal */ + } + if (!bindtextdomain(PACKAGE, LOCALEDIR)) { + perror("bindtextdomain"); + return EXIT_FAILURE; + } + if (!textdomain(PACKAGE)) { + perror("textdomain"); + return EXIT_FAILURE; + } + + if (isatty(STDIN_FILENO)) { + ctl->istty = true; + +#ifndef WIN32 + if (tcgetattr(STDIN_FILENO, &ctl->termattr) < 0) + ctl->istty = false; +#endif + } + + if (virMutexInit(&ctl->lock) < 0) { + vshError(ctl, "%s", _("Failed to initialize mutex")); + return EXIT_FAILURE; + } + + if (virInitialize() < 0) { + vshError(ctl, "%s", _("Failed to initialize libvirt")); + return EXIT_FAILURE; + } + + virFileActivateDirOverride(argv[0]); + + if (!(progname = strrchr(argv[0], '/'))) + progname = argv[0]; + else + progname++; + + if ((defaultConn = virGetEnvBlockSUID("VIRSH_DEFAULT_CONNECT_URI"))) + ctl->name = vshStrdup(ctl, defaultConn); + + vshInitDebug(ctl); + + if (!vshParseArgv(ctl, argc, argv) || + !vshInit(ctl)) { + vshDeinit(ctl); + exit(EXIT_FAILURE); + } + + if (!ctl->imode) { + ret = vshCommandRun(ctl, ctl->cmd); + } else { + /* interactive mode */ + if (!ctl->quiet) { + vshPrint(ctl, + _("Welcome to %s, the virtualization interactive terminal.\n\n"), + progname); + vshPrint(ctl, "%s", + _("Type: 'help' for help with commands\n" + " 'quit' to quit\n\n")); + } + + if (vshReadlineInit(ctl) < 0) { + vshDeinit(ctl); + exit(EXIT_FAILURE); + } + + do { + const char *prompt = ctl->readonly ? VSH_PROMPT_RO : VSH_PROMPT_RW; + ctl->cmdstr = + vshReadline(ctl, prompt); + if (ctl->cmdstr == NULL) + break; /* EOF */ + if (*ctl->cmdstr) { +#if WITH_READLINE + add_history(ctl->cmdstr); +#endif + if (vshCommandStringParse(ctl, ctl->cmdstr)) + vshCommandRun(ctl, ctl->cmd); + } + VIR_FREE(ctl->cmdstr); + } while (ctl->imode); + + if (ctl->cmdstr == NULL) + fputc('\n', stdout); /* line break after alone prompt */ + } + + vshDeinit(ctl); + exit(ret ? EXIT_SUCCESS : EXIT_FAILURE); +} diff --git a/tools/vsh.h b/tools/vsh.h new file mode 100644 index 0000000..345eb99 --- /dev/null +++ b/tools/vsh.h @@ -0,0 +1,527 @@ +/* + * vsh.h: common data to be used by clients to exercise the libvirt API + * + * Copyright (C) 2005, 2007-2015 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + * + * Daniel Veillard <veillard@redhat.com> + * Karel Zak <kzak@redhat.com> + * Daniel P. Berrange <berrange@redhat.com> + */ + +#ifndef VSH_H +# define VSH_H + +# include <stdio.h> +# include <stdlib.h> +# include <string.h> +# include <stdarg.h> +# include <unistd.h> +# include <sys/stat.h> +# include <termios.h> + +# include "internal.h" +# include "virerror.h" +# include "virthread.h" + +# define VSH_MAX_XML_FILE (10*1024*1024) + +# define VSH_PROMPT_RW "virsh # " +# define VSH_PROMPT_RO "virsh > " + +# define VIR_FROM_THIS VIR_FROM_NONE + +# define GETTIMEOFDAY(T) gettimeofday(T, NULL) + +# define VSH_MATCH(FLAG) (flags & (FLAG)) + +/** + * The log configuration + */ +# define MSG_BUFFER 4096 +# define SIGN_NAME "virsh" +# define DIR_MODE (S_IWUSR | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) /* 0755 */ +# define FILE_MODE (S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH) /* 0644 */ +# define LOCK_MODE (S_IWUSR | S_IRUSR) /* 0600 */ +# define LVL_DEBUG "DEBUG" +# define LVL_INFO "INFO" +# define LVL_NOTICE "NOTICE" +# define LVL_WARNING "WARNING" +# define LVL_ERROR "ERROR" + +/** + * vshErrorLevel: + * + * Indicates the level of a log message + */ +typedef enum { + VSH_ERR_DEBUG = 0, + VSH_ERR_INFO, + VSH_ERR_NOTICE, + VSH_ERR_WARNING, + VSH_ERR_ERROR +} vshErrorLevel; + +# define VSH_DEBUG_DEFAULT VSH_ERR_ERROR + +/* + * virsh command line grammar: + * + * command_line = <command>\n | <command>; <command>; ... + * + * command = <keyword> <option> [--] <data> + * + * option = <bool_option> | <int_option> | <string_option> + * data = <string> + * + * bool_option = --optionname + * int_option = --optionname <number> | --optionname=<number> + * string_option = --optionname <string> | --optionname=<string> + * + * keyword = [a-zA-Z][a-zA-Z-]* + * number = [0-9]+ + * string = ('[^']*'|"([^\\"]|\\.)*"|([^ \t\n\\'"]|\\.))+ + * + */ + +/* + * vshCmdOptType - command option type + */ +typedef enum { + VSH_OT_BOOL, /* optional boolean option */ + VSH_OT_STRING, /* optional string option */ + VSH_OT_INT, /* optional or mandatory int option */ + VSH_OT_DATA, /* string data (as non-option) */ + VSH_OT_ARGV, /* remaining arguments */ + VSH_OT_ALIAS, /* alternate spelling for a later argument */ +} vshCmdOptType; + +/* + * Command group types + */ +# define VSH_CMD_GRP_DOM_MANAGEMENT "Domain Management" +# define VSH_CMD_GRP_DOM_MONITORING "Domain Monitoring" +# define VSH_CMD_GRP_STORAGE_POOL "Storage Pool" +# define VSH_CMD_GRP_STORAGE_VOL "Storage Volume" +# define VSH_CMD_GRP_NETWORK "Networking" +# define VSH_CMD_GRP_NODEDEV "Node Device" +# define VSH_CMD_GRP_IFACE "Interface" +# define VSH_CMD_GRP_NWFILTER "Network Filter" +# define VSH_CMD_GRP_SECRET "Secret" +# define VSH_CMD_GRP_SNAPSHOT "Snapshot" +# define VSH_CMD_GRP_HOST_AND_HV "Host and Hypervisor" +# define VSH_CMD_GRP_VIRSH "Virsh itself" + +/* + * Command Option Flags + */ +enum { + VSH_OFLAG_NONE = 0, /* without flags */ + VSH_OFLAG_REQ = (1 << 0), /* option required */ + VSH_OFLAG_EMPTY_OK = (1 << 1), /* empty string option allowed */ + VSH_OFLAG_REQ_OPT = (1 << 2), /* --optionname required */ +}; + +/* forward declarations */ +typedef struct _vshCmd vshCmd; +typedef struct _vshCmdDef vshCmdDef; +typedef struct _vshCmdGrp vshCmdGrp; +typedef struct _vshCmdInfo vshCmdInfo; +typedef struct _vshCmdOpt vshCmdOpt; +typedef struct _vshCmdOptDef vshCmdOptDef; +typedef struct _vshControl vshControl; +typedef struct _vshCtrlData vshCtrlData; + +typedef char **(*vshCompleter)(unsigned int flags); + +/* + * vshCmdInfo -- name/value pair for information about command + * + * Commands should have at least the following names: + * "help" - short description of command + * "desc" - description of command, or empty string + */ +struct _vshCmdInfo { + const char *name; /* name of information, or NULL for list end */ + const char *data; /* non-NULL information */ +}; + +/* + * vshCmdOptDef - command option definition + */ +struct _vshCmdOptDef { + const char *name; /* the name of option, or NULL for list end */ + vshCmdOptType type; /* option type */ + unsigned int flags; /* flags */ + const char *help; /* non-NULL help string; or for VSH_OT_ALIAS + * the name of a later public option */ + vshCompleter completer; /* option completer */ + unsigned int completer_flags; /* option completer flags */ +}; + +/* + * vshCmdOpt - command options + * + * After parsing a command, all arguments to the command have been + * collected into a list of these objects. + */ +struct _vshCmdOpt { + const vshCmdOptDef *def; /* non-NULL pointer to option definition */ + char *data; /* allocated data, or NULL for bool option */ + vshCmdOpt *next; +}; + +/* + * Command Usage Flags + */ +enum { + VSH_CMD_FLAG_NOCONNECT = (1 << 0), /* no prior connection needed */ + VSH_CMD_FLAG_ALIAS = (1 << 1), /* command is an alias */ +}; + +/* + * vshCmdDef - command definition + */ +struct _vshCmdDef { + const char *name; /* name of command, or NULL for list end */ + bool (*handler) (vshControl *, const vshCmd *); /* command handler */ + const vshCmdOptDef *opts; /* definition of command options */ + const vshCmdInfo *info; /* details about command */ + unsigned int flags; /* bitwise OR of VSH_CMD_FLAG */ +}; + +/* + * vshCmd - parsed command + */ +struct _vshCmd { + const vshCmdDef *def; /* command definition */ + vshCmdOpt *opts; /* list of command arguments */ + vshCmd *next; /* next command */ +}; + +/* + * vshControl + */ +struct _vshControl { + char *name; /* connection name */ + virConnectPtr conn; /* connection to hypervisor (MAY BE NULL) */ + vshCmd *cmd; /* the current command */ + char *cmdstr; /* string with command */ + bool imode; /* interactive mode? */ + bool quiet; /* quiet mode */ + int debug; /* print debug messages? */ + bool timing; /* print timing info? */ + bool readonly; /* connect readonly (first time only, not + * during explicit connect command) + */ + char *logfile; /* log file name */ + int log_fd; /* log file descriptor */ + char *historydir; /* readline history directory name */ + char *historyfile; /* readline history file name */ + bool useGetInfo; /* must use virDomainGetInfo, since + virDomainGetState is not supported */ + bool useSnapshotOld; /* cannot use virDomainSnapshotGetParent or + virDomainSnapshotNumChildren */ + bool blockJobNoBytes; /* true if _BANDWIDTH_BYTE blockjob flags + are missing */ + virThread eventLoop; + virMutex lock; + bool eventLoopStarted; + bool quit; + int eventPipe[2]; /* Write-to-self pipe to end waiting for an + * event to occur */ + int eventTimerId; /* id of event loop timeout registration */ + + const char *escapeChar; /* String representation of + console escape character */ + + int keepalive_interval; /* Client keepalive interval */ + int keepalive_count; /* Client keepalive count */ + +# ifndef WIN32 + struct termios termattr; /* settings of the tty terminal */ +# endif + bool istty; /* is the terminal a tty */ +}; + +struct _vshCmdGrp { + const char *name; /* name of group, or NULL for list end */ + const char *keyword; /* help keyword */ + const vshCmdDef *commands; +}; + +void vshError(vshControl *ctl, const char *format, ...) + ATTRIBUTE_FMT_PRINTF(2, 3); +void vshOpenLogFile(vshControl *ctl); +void vshOutputLogFile(vshControl *ctl, int log_level, const char *format, + va_list ap) + ATTRIBUTE_FMT_PRINTF(3, 0); +void vshCloseLogFile(vshControl *ctl); + +virConnectPtr vshConnect(vshControl *ctl, const char *uri, bool readonly); + +const char *vshCmddefGetInfo(const vshCmdDef *cmd, const char *info); +const vshCmdDef *vshCmddefSearch(const char *cmdname); +bool vshCmddefHelp(vshControl *ctl, const char *name); +const vshCmdGrp *vshCmdGrpSearch(const char *grpname); +bool vshCmdGrpHelp(vshControl *ctl, const char *name); + +int vshCommandOptInt(vshControl *ctl, const vshCmd *cmd, + const char *name, int *value) + ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK; +int vshCommandOptUInt(vshControl *ctl, const vshCmd *cmd, + const char *name, unsigned int *value) + ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK; +int vshCommandOptUIntWrap(vshControl *ctl, const vshCmd *cmd, + const char *name, unsigned int *value) + ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK; +int vshCommandOptUL(vshControl *ctl, const vshCmd *cmd, + const char *name, unsigned long *value) + ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK; +int vshCommandOptULWrap(vshControl *ctl, const vshCmd *cmd, + const char *name, unsigned long *value) + ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK; +int vshCommandOptString(vshControl *ctl, const vshCmd *cmd, + const char *name, const char **value) + ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK; +int vshCommandOptStringReq(vshControl *ctl, const vshCmd *cmd, + const char *name, const char **value) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) + ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK; +int vshCommandOptLongLong(vshControl *ctl, const vshCmd *cmd, + const char *name, long long *value) + ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK; +int vshCommandOptULongLong(vshControl *ctl, const vshCmd *cmd, + const char *name, unsigned long long *value) + ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK; +int vshCommandOptULongLongWrap(vshControl *ctl, const vshCmd *cmd, + const char *name, unsigned long long *value) + ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK; +int vshCommandOptScaledInt(vshControl *ctl, const vshCmd *cmd, + const char *name, unsigned long long *value, + int scale, unsigned long long max) + ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK; +bool vshCommandOptBool(const vshCmd *cmd, const char *name); +const vshCmdOpt *vshCommandOptArgv(vshControl *ctl, const vshCmd *cmd, + const vshCmdOpt *opt); +int vshCommandOptTimeoutToMs(vshControl *ctl, const vshCmd *cmd, int *timeout); + +/* Filter flags for various vshCommandOpt*By() functions */ +typedef enum { + VSH_BYID = (1 << 1), + VSH_BYUUID = (1 << 2), + VSH_BYNAME = (1 << 3), + VSH_BYMAC = (1 << 4), +} vshLookupByFlags; + +/* Given an index, return either the name of that device (non-NULL) or + * of its parent (NULL if a root). */ +typedef const char * (*vshTreeLookup)(int devid, bool parent, void *opaque); +int vshTreePrint(vshControl *ctl, vshTreeLookup lookup, void *opaque, + int num_devices, int devid); + +void vshPrintExtra(vshControl *ctl, const char *format, ...) + ATTRIBUTE_FMT_PRINTF(2, 3); +void vshDebug(vshControl *ctl, int level, const char *format, ...) + ATTRIBUTE_FMT_PRINTF(3, 4); + +/* XXX: add batch support */ +# define vshPrint(_ctl, ...) vshPrintExtra(NULL, __VA_ARGS__) + +/* User visible sort, so we want locale-specific case comparison. */ +# define vshStrcasecmp(S1, S2) strcasecmp(S1, S2) +int vshNameSorter(const void *a, const void *b); + +int vshDomainState(vshControl *ctl, virDomainPtr dom, int *reason); +virTypedParameterPtr vshFindTypedParamByName(const char *name, + virTypedParameterPtr list, + int count); +char *vshGetTypedParamValue(vshControl *ctl, virTypedParameterPtr item) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); + +char *vshEditWriteToTempFile(vshControl *ctl, const char *doc); +int vshEditFile(vshControl *ctl, const char *filename); +char *vshEditReadBackFile(vshControl *ctl, const char *filename); +int vshAskReedit(vshControl *ctl, const char *msg, bool relax_avail); +int vshStreamSink(virStreamPtr st, const char *bytes, size_t nbytes, + void *opaque); +double vshPrettyCapacity(unsigned long long val, const char **unit); +int vshStringToArray(const char *str, char ***array); + +/* Typedefs, function prototypes for job progress reporting. + * There are used by some long lingering commands like + * migrate, dump, save, managedsave. + */ +struct _vshCtrlData { + vshControl *ctl; + const vshCmd *cmd; + int writefd; + virConnectPtr dconn; +}; + +/* error handling */ +extern virErrorPtr last_error; +void vshReportError(vshControl *ctl); +void vshResetLibvirtError(void); +void vshSaveLibvirtError(void); + +/* terminal modifications */ +bool vshTTYIsInterruptCharacter(vshControl *ctl, const char chr); +int vshTTYDisableInterrupt(vshControl *ctl); +int vshTTYRestore(vshControl *ctl); +int vshTTYMakeRaw(vshControl *ctl, bool report_errors); +bool vshTTYAvailable(vshControl *ctl); + +/* waiting for events */ +enum { + VSH_EVENT_INTERRUPT, + VSH_EVENT_TIMEOUT, + VSH_EVENT_DONE, +}; +int vshEventStart(vshControl *ctl, int timeout_ms); +void vshEventDone(vshControl *ctl); +int vshEventWait(vshControl *ctl); +void vshEventCleanup(vshControl *ctl); + +/* allocation wrappers */ +void *_vshMalloc(vshControl *ctl, size_t sz, const char *filename, int line); +# define vshMalloc(_ctl, _sz) _vshMalloc(_ctl, _sz, __FILE__, __LINE__) + +void *_vshCalloc(vshControl *ctl, size_t nmemb, size_t sz, + const char *filename, int line); +# define vshCalloc(_ctl, _nmemb, _sz) \ + _vshCalloc(_ctl, _nmemb, _sz, __FILE__, __LINE__) + +char *_vshStrdup(vshControl *ctl, const char *s, const char *filename, + int line); +# define vshStrdup(_ctl, _s) _vshStrdup(_ctl, _s, __FILE__, __LINE__) + +/* Poison the raw allocating identifiers in favor of our vsh variants. */ +# undef malloc +# undef calloc +# undef realloc +# undef strdup +# define malloc use_vshMalloc_instead_of_malloc +# define calloc use_vshCalloc_instead_of_calloc +# define realloc use_vshRealloc_instead_of_realloc +# define strdup use_vshStrdup_instead_of_strdup + +/* Macros to help dealing with mutually exclusive options. */ + +/* VSH_EXCLUSIVE_OPTIONS_EXPR: + * + * @NAME1: String containing the name of the option. + * @EXPR1: Expression to validate the variable (boolean variable) + * @NAME2: String containing the name of the option. + * @EXPR2: Expression to validate the variable (boolean variable) + * + * Reject mutually exclusive command options in virsh. Use the + * provided expression to check the variables. + * + * This helper does an early return and therefore it has to be called + * before anything that would require cleanup. + */ +# define VSH_EXCLUSIVE_OPTIONS_EXPR(NAME1, EXPR1, NAME2, EXPR2) \ + if ((EXPR1) && (EXPR2)) { \ + vshError(ctl, _("Options --%s and --%s are mutually exclusive"), \ + NAME1, NAME2); \ + return false; \ + } + +/* VSH_EXCLUSIVE_OPTIONS: + * + * @NAME1: String containing the name of the option. + * @NAME2: String containing the name of the option. + * + * Reject mutually exclusive command options in virsh. Use the + * vshCommandOptBool call to request them. + * + * This helper does an early return and therefore it has to be called + * before anything that would require cleanup. + */ +# define VSH_EXCLUSIVE_OPTIONS(NAME1, NAME2) \ + VSH_EXCLUSIVE_OPTIONS_EXPR(NAME1, vshCommandOptBool(cmd, NAME1), \ + NAME2, vshCommandOptBool(cmd, NAME2)) + +/* VSH_EXCLUSIVE_OPTIONS_VAR: + * + * @VARNAME1: Boolean variable containing the value of the option of same name + * @VARNAME2: Boolean variable containing the value of the option of same name + * + * Reject mutually exclusive command options in virsh. Check in variables that + * contain the value and have same name as the option. + * + * This helper does an early return and therefore it has to be called + * before anything that would require cleanup. + */ +# define VSH_EXCLUSIVE_OPTIONS_VAR(VARNAME1, VARNAME2) \ + VSH_EXCLUSIVE_OPTIONS_EXPR(#VARNAME1, VARNAME1, #VARNAME2, VARNAME2) + +/* Macros to help dealing with required options. */ + +/* VSH_REQUIRE_OPTION_EXPR: + * + * @NAME1: String containing the name of the option. + * @EXPR1: Expression to validate the variable (boolean variable). + * @NAME2: String containing the name of required option. + * @EXPR2: Expression to validate the variable (boolean variable). + * + * Check if required command options in virsh was set. Use the + * provided expression to check the variables. + * + * This helper does an early return and therefore it has to be called + * before anything that would require cleanup. + */ +# define VSH_REQUIRE_OPTION_EXPR(NAME1, EXPR1, NAME2, EXPR2) \ + do { \ + if ((EXPR1) && !(EXPR2)) { \ + vshError(ctl, _("Option --%s is required by option --%s"), \ + NAME2, NAME1); \ + return false; \ + } \ + } while (0) + +/* VSH_REQUIRE_OPTION: + * + * @NAME1: String containing the name of the option. + * @NAME2: String containing the name of required option. + * + * Check if required command options in virsh was set. Use the + * vshCommandOptBool call to request them. + * + * This helper does an early return and therefore it has to be called + * before anything that would require cleanup. + */ +# define VSH_REQUIRE_OPTION(NAME1, NAME2) \ + VSH_REQUIRE_OPTION_EXPR(NAME1, vshCommandOptBool(cmd, NAME1), \ + NAME2, vshCommandOptBool(cmd, NAME2)) + +/* VSH_REQUIRE_OPTION_VAR: + * + * @VARNAME1: Boolean variable containing the value of the option of same name. + * @VARNAME2: Boolean variable containing the value of required option of + * same name. + * + * Check if required command options in virsh was set. Check in variables + * that contain the value and have same name as the option. + * + * This helper does an early return and therefore it has to be called + * before anything that would require cleanup. + */ +# define VSH_REQUIRE_OPTION_VAR(VARNAME1, VARNAME2) \ + VSH_REQUIRE_OPTION_EXPR(#VARNAME1, VARNAME1, #VARNAME2, VARNAME2) + +#endif /* VSH_H */ -- 1.9.3

Virt shell (vsh) started as a copy of virsh, but it needs to be split from virsh, so remove all virsh specific data that cannot/need not be used with other potential clients like virt-admin --- tools/vsh.c | 1505 +---------------------------------------------------------- tools/vsh.h | 66 +-- 2 files changed, 9 insertions(+), 1562 deletions(-) diff --git a/tools/vsh.c b/tools/vsh.c index 609c8f3..8ef04b9 100644 --- a/tools/vsh.c +++ b/tools/vsh.c @@ -32,7 +32,6 @@ #include <stdarg.h> #include <unistd.h> #include <errno.h> -#include <getopt.h> #include <sys/time.h> #include "c-ctype.h" #include <fcntl.h> @@ -63,27 +62,12 @@ #include "virtypedparam.h" #include "virstring.h" -#include "virsh-console.h" -#include "virsh-domain.h" -#include "virsh-domain-monitor.h" -#include "virsh-host.h" -#include "virsh-interface.h" -#include "virsh-network.h" -#include "virsh-nodedev.h" -#include "virsh-nwfilter.h" -#include "virsh-pool.h" -#include "virsh-secret.h" -#include "virsh-snapshot.h" -#include "virsh-volume.h" - /* Gnulib doesn't guarantee SA_SIGINFO support. */ #ifndef SA_SIGINFO # define SA_SIGINFO 0 #endif -static char *progname; - -static const vshCmdGrp cmdGroups[]; +static const vshCmdGrp *cmdGroups; /* Bypass header poison */ #undef strdup @@ -138,44 +122,6 @@ vshNameSorter(const void *a, const void *b) return vshStrcasecmp(*sa, *sb); } -double -vshPrettyCapacity(unsigned long long val, const char **unit) -{ - double limit = 1024; - - if (val < limit) { - *unit = "B"; - return val; - } - limit *= 1024; - if (val < limit) { - *unit = "KiB"; - return val / (limit / 1024); - } - limit *= 1024; - if (val < limit) { - *unit = "MiB"; - return val / (limit / 1024); - } - limit *= 1024; - if (val < limit) { - *unit = "GiB"; - return val / (limit / 1024); - } - limit *= 1024; - if (val < limit) { - *unit = "TiB"; - return val / (limit / 1024); - } - limit *= 1024; - if (val < limit) { - *unit = "PiB"; - return val / (limit / 1024); - } - limit *= 1024; - *unit = "EiB"; - return val / (limit / 1024); -} /* * Convert the strings separated by ',' into array. The returned @@ -299,743 +245,14 @@ vshReportError(vshControl *ctl) vshError(ctl, "%s", last_error->message); - out: - vshResetLibvirtError(); -} - -/* - * Detection of disconnections and automatic reconnection support - */ -static int disconnected; /* we may have been disconnected */ - -/* - * vshCatchDisconnect: - * - * We get here when the connection was closed. We can't do much in the - * handler, just save the fact it was raised. - */ -static void -vshCatchDisconnect(virConnectPtr conn ATTRIBUTE_UNUSED, - int reason, - void *opaque ATTRIBUTE_UNUSED) -{ - if (reason != VIR_CONNECT_CLOSE_REASON_CLIENT) - disconnected++; -} - -/* Main Function which should be used for connecting. - * This function properly handles keepalive settings. */ -virConnectPtr -vshConnect(vshControl *ctl, const char *uri, bool readonly) -{ - virConnectPtr c = NULL; - int interval = 5; /* Default */ - int count = 6; /* Default */ - bool keepalive_forced = false; - - if (ctl->keepalive_interval >= 0) { - interval = ctl->keepalive_interval; - keepalive_forced = true; - } - if (ctl->keepalive_count >= 0) { - count = ctl->keepalive_count; - keepalive_forced = true; - } - - c = virConnectOpenAuth(uri, virConnectAuthPtrDefault, - readonly ? VIR_CONNECT_RO : 0); - if (!c) - return NULL; - - if (interval > 0 && - virConnectSetKeepAlive(c, interval, count) != 0) { - if (keepalive_forced) { - vshError(ctl, "%s", - _("Cannot setup keepalive on connection " - "as requested, disconnecting")); - virConnectClose(c); - return NULL; - } - vshDebug(ctl, VSH_ERR_INFO, "%s", - _("Failed to setup keepalive on connection\n")); - } - - return c; -} - -/* - * vshReconnect: - * - * Reconnect after a disconnect from libvirtd - * - */ -static void -vshReconnect(vshControl *ctl) -{ - bool connected = false; - - if (ctl->conn) { - int ret; - - connected = true; - - virConnectUnregisterCloseCallback(ctl->conn, vshCatchDisconnect); - ret = virConnectClose(ctl->conn); - if (ret < 0) - vshError(ctl, "%s", _("Failed to disconnect from the hypervisor")); - else if (ret > 0) - vshError(ctl, "%s", _("One or more references were leaked after " - "disconnect from the hypervisor")); - } - - ctl->conn = vshConnect(ctl, ctl->name, ctl->readonly); - - if (!ctl->conn) { - if (disconnected) - vshError(ctl, "%s", _("Failed to reconnect to the hypervisor")); - else - vshError(ctl, "%s", _("failed to connect to the hypervisor")); - } else { - if (virConnectRegisterCloseCallback(ctl->conn, vshCatchDisconnect, - NULL, NULL) < 0) - vshError(ctl, "%s", _("Unable to register disconnect callback")); - if (connected) - vshError(ctl, "%s", _("Reconnected to the hypervisor")); - } - disconnected = 0; - ctl->useGetInfo = false; - ctl->useSnapshotOld = false; - ctl->blockJobNoBytes = false; -} - - -/* - * "connect" command - */ -static const vshCmdInfo info_connect[] = { - {.name = "help", - .data = N_("(re)connect to hypervisor") - }, - {.name = "desc", - .data = N_("Connect to local hypervisor. This is built-in " - "command after shell start up.") - }, - {.name = NULL} -}; - -static const vshCmdOptDef opts_connect[] = { - {.name = "name", - .type = VSH_OT_STRING, - .flags = VSH_OFLAG_EMPTY_OK, - .help = N_("hypervisor connection URI") - }, - {.name = "readonly", - .type = VSH_OT_BOOL, - .help = N_("read-only connection") - }, - {.name = NULL} -}; - -static bool -cmdConnect(vshControl *ctl, const vshCmd *cmd) -{ - bool ro = vshCommandOptBool(cmd, "readonly"); - const char *name = NULL; - - if (ctl->conn) { - int ret; - - virConnectUnregisterCloseCallback(ctl->conn, vshCatchDisconnect); - ret = virConnectClose(ctl->conn); - if (ret < 0) - vshError(ctl, "%s", _("Failed to disconnect from the hypervisor")); - else if (ret > 0) - vshError(ctl, "%s", _("One or more references were leaked after " - "disconnect from the hypervisor")); - ctl->conn = NULL; - } - - VIR_FREE(ctl->name); - if (vshCommandOptStringReq(ctl, cmd, "name", &name) < 0) - return false; - - ctl->name = vshStrdup(ctl, name); - - ctl->useGetInfo = false; - ctl->useSnapshotOld = false; - ctl->blockJobNoBytes = false; - ctl->readonly = ro; - - ctl->conn = vshConnect(ctl, ctl->name, ctl->readonly); - - if (!ctl->conn) { - vshError(ctl, "%s", _("Failed to connect to the hypervisor")); - return false; - } - - if (virConnectRegisterCloseCallback(ctl->conn, vshCatchDisconnect, - NULL, NULL) < 0) - vshError(ctl, "%s", _("Unable to register disconnect callback")); - - return true; -} - - -#ifndef WIN32 -static void -vshPrintRaw(vshControl *ctl, ...) -{ - va_list ap; - char *key; - - va_start(ap, ctl); - while ((key = va_arg(ap, char *)) != NULL) - vshPrint(ctl, "%s\r\n", key); - va_end(ap); -} - -/** - * vshAskReedit: - * @msg: Question to ask user - * - * Ask user if he wants to return to previously - * edited file. - * - * Returns 'y' if he wants to - * 'n' if he doesn't want to - * 'i' if he wants to try defining it again while ignoring validation - * 'f' if he forcibly wants to - * -1 on error - * 0 otherwise - */ -int -vshAskReedit(vshControl *ctl, const char *msg, bool relax_avail) -{ - int c = -1; - - if (!isatty(STDIN_FILENO)) - return -1; - - vshReportError(ctl); - - if (vshTTYMakeRaw(ctl, false) < 0) - return -1; - - while (true) { - vshPrint(ctl, "\r%s %s %s: ", msg, _("Try again?"), - relax_avail ? "[y,n,i,f,?]" : "[y,n,f,?]"); - c = c_tolower(getchar()); - - if (c == '?') { - vshPrintRaw(ctl, - "", - _("y - yes, start editor again"), - _("n - no, throw away my changes"), - NULL); - - if (relax_avail) { - vshPrintRaw(ctl, - _("i - turn off validation and try to redefine again"), - NULL); - } - - vshPrintRaw(ctl, - _("f - force, try to redefine again"), - _("? - print this help"), - NULL); - continue; - } else if (c == 'y' || c == 'n' || c == 'f' || - (relax_avail && c == 'i')) { - break; - } - } - - vshTTYRestore(ctl); - - vshPrint(ctl, "\r\n"); - return c; -} -#else /* WIN32 */ -int -vshAskReedit(vshControl *ctl, - const char *msg ATTRIBUTE_UNUSED, - bool relax_avail ATTRIBUTE_UNUSED) -{ - vshDebug(ctl, VSH_ERR_WARNING, "%s", _("This function is not " - "supported on WIN32 platform")); - return 0; -} -#endif /* WIN32 */ - -int vshStreamSink(virStreamPtr st ATTRIBUTE_UNUSED, - const char *bytes, size_t nbytes, void *opaque) -{ - int *fd = opaque; - - return safewrite(*fd, bytes, nbytes); -} - -/* --------------- - * Commands - * --------------- - */ - -/* - * "help" command - */ -static const vshCmdInfo info_help[] = { - {.name = "help", - .data = N_("print help") - }, - {.name = "desc", - .data = N_("Prints global help, command specific help, or help for a\n" - " group of related commands") - }, - {.name = NULL} -}; - -static const vshCmdOptDef opts_help[] = { - {.name = "command", - .type = VSH_OT_STRING, - .help = N_("Prints global help, command specific help, or help for a group of related commands") - }, - {.name = NULL} -}; - -static bool -cmdHelp(vshControl *ctl, const vshCmd *cmd) - { - const char *name = NULL; - - if (vshCommandOptString(ctl, cmd, "command", &name) <= 0) { - const vshCmdGrp *grp; - const vshCmdDef *def; - - vshPrint(ctl, "%s", _("Grouped commands:\n\n")); - - for (grp = cmdGroups; grp->name; grp++) { - vshPrint(ctl, _(" %s (help keyword '%s'):\n"), grp->name, - grp->keyword); - - for (def = grp->commands; def->name; def++) { - if (def->flags & VSH_CMD_FLAG_ALIAS) - continue; - vshPrint(ctl, " %-30s %s\n", def->name, - _(vshCmddefGetInfo(def, "help"))); - } - - vshPrint(ctl, "\n"); - } - - return true; - } - - if (vshCmddefSearch(name)) { - return vshCmddefHelp(ctl, name); - } else if (vshCmdGrpSearch(name)) { - return vshCmdGrpHelp(ctl, name); - } else { - vshError(ctl, _("command or command group '%s' doesn't exist"), name); - return false; - } -} - -/* Tree listing helpers. */ - -static int -vshTreePrintInternal(vshControl *ctl, - vshTreeLookup lookup, - void *opaque, - int num_devices, - int devid, - int lastdev, - bool root, - virBufferPtr indent) -{ - size_t i; - int nextlastdev = -1; - int ret = -1; - const char *dev = (lookup)(devid, false, opaque); - - if (virBufferError(indent)) - goto cleanup; - - /* Print this device, with indent if not at root */ - vshPrint(ctl, "%s%s%s\n", virBufferCurrentContent(indent), - root ? "" : "+- ", dev); - - /* Update indent to show '|' or ' ' for child devices */ - if (!root) { - virBufferAddChar(indent, devid == lastdev ? ' ' : '|'); - virBufferAddChar(indent, ' '); - if (virBufferError(indent)) - goto cleanup; - } - - /* Determine the index of the last child device */ - for (i = 0; i < num_devices; i++) { - const char *parent = (lookup)(i, true, opaque); - - if (parent && STREQ(parent, dev)) - nextlastdev = i; - } - - /* If there is a child device, then print another blank line */ - if (nextlastdev != -1) - vshPrint(ctl, "%s |\n", virBufferCurrentContent(indent)); - - /* Finally print all children */ - virBufferAddLit(indent, " "); - if (virBufferError(indent)) - goto cleanup; - for (i = 0; i < num_devices; i++) { - const char *parent = (lookup)(i, true, opaque); - - if (parent && STREQ(parent, dev) && - vshTreePrintInternal(ctl, lookup, opaque, - num_devices, i, nextlastdev, - false, indent) < 0) - goto cleanup; - } - virBufferTrim(indent, " ", -1); - - /* If there was no child device, and we're the last in - * a list of devices, then print another blank line */ - if (nextlastdev == -1 && devid == lastdev) - vshPrint(ctl, "%s\n", virBufferCurrentContent(indent)); - - if (!root) - virBufferTrim(indent, NULL, 2); - ret = 0; - cleanup: - return ret; -} - -int -vshTreePrint(vshControl *ctl, vshTreeLookup lookup, void *opaque, - int num_devices, int devid) -{ - int ret; - virBuffer indent = VIR_BUFFER_INITIALIZER; - - ret = vshTreePrintInternal(ctl, lookup, opaque, num_devices, - devid, devid, true, &indent); - if (ret < 0) - vshError(ctl, "%s", _("Failed to complete tree listing")); - virBufferFreeAndReset(&indent); - return ret; -} - -/* Common code for the edit / net-edit / pool-edit functions which follow. */ -char * -vshEditWriteToTempFile(vshControl *ctl, const char *doc) -{ - char *ret; - const char *tmpdir; - int fd; - char ebuf[1024]; - - tmpdir = virGetEnvBlockSUID("TMPDIR"); - if (!tmpdir) tmpdir = "/tmp"; - if (virAsprintf(&ret, "%s/virshXXXXXX.xml", tmpdir) < 0) { - vshError(ctl, "%s", _("out of memory")); - return NULL; - } - fd = mkostemps(ret, 4, O_CLOEXEC); - if (fd == -1) { - vshError(ctl, _("mkostemps: failed to create temporary file: %s"), - virStrerror(errno, ebuf, sizeof(ebuf))); - VIR_FREE(ret); - return NULL; - } - - if (safewrite(fd, doc, strlen(doc)) == -1) { - vshError(ctl, _("write: %s: failed to write to temporary file: %s"), - ret, virStrerror(errno, ebuf, sizeof(ebuf))); - VIR_FORCE_CLOSE(fd); - unlink(ret); - VIR_FREE(ret); - return NULL; - } - if (VIR_CLOSE(fd) < 0) { - vshError(ctl, _("close: %s: failed to write or close temporary file: %s"), - ret, virStrerror(errno, ebuf, sizeof(ebuf))); - unlink(ret); - VIR_FREE(ret); - return NULL; - } - - /* Temporary filename: caller frees. */ - return ret; -} - -/* Characters permitted in $EDITOR environment variable and temp filename. */ -#define ACCEPTED_CHARS \ - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-/_.:@" - -int -vshEditFile(vshControl *ctl, const char *filename) -{ - const char *editor; - virCommandPtr cmd; - int ret = -1; - int outfd = STDOUT_FILENO; - int errfd = STDERR_FILENO; - - editor = virGetEnvBlockSUID("VISUAL"); - if (!editor) - editor = virGetEnvBlockSUID("EDITOR"); - if (!editor) - editor = DEFAULT_EDITOR; - - /* Check that filename doesn't contain shell meta-characters, and - * if it does, refuse to run. Follow the Unix conventions for - * EDITOR: the user can intentionally specify command options, so - * we don't protect any shell metacharacters there. Lots more - * than virsh will misbehave if EDITOR has bogus contents (which - * is why sudo scrubs it by default). Conversely, if the editor - * is safe, we can run it directly rather than wasting a shell. - */ - if (strspn(editor, ACCEPTED_CHARS) != strlen(editor)) { - if (strspn(filename, ACCEPTED_CHARS) != strlen(filename)) { - vshError(ctl, - _("%s: temporary filename contains shell meta or other " - "unacceptable characters (is $TMPDIR wrong?)"), - filename); - return -1; - } - cmd = virCommandNewArgList("sh", "-c", NULL); - virCommandAddArgFormat(cmd, "%s %s", editor, filename); - } else { - cmd = virCommandNewArgList(editor, filename, NULL); - } - - virCommandSetInputFD(cmd, STDIN_FILENO); - virCommandSetOutputFD(cmd, &outfd); - virCommandSetErrorFD(cmd, &errfd); - if (virCommandRunAsync(cmd, NULL) < 0 || - virCommandWait(cmd, NULL) < 0) { - vshReportError(ctl); - goto cleanup; - } - ret = 0; - - cleanup: - virCommandFree(cmd); - return ret; -} - -char * -vshEditReadBackFile(vshControl *ctl, const char *filename) -{ - char *ret; - char ebuf[1024]; - - if (virFileReadAll(filename, VSH_MAX_XML_FILE, &ret) == -1) { - vshError(ctl, - _("%s: failed to read temporary file: %s"), - filename, virStrerror(errno, ebuf, sizeof(ebuf))); - return NULL; - } - return ret; -} - - -/* - * "cd" command - */ -static const vshCmdInfo info_cd[] = { - {.name = "help", - .data = N_("change the current directory") - }, - {.name = "desc", - .data = N_("Change the current directory.") - }, - {.name = NULL} -}; - -static const vshCmdOptDef opts_cd[] = { - {.name = "dir", - .type = VSH_OT_STRING, - .help = N_("directory to switch to (default: home or else root)") - }, - {.name = NULL} -}; - -static bool -cmdCd(vshControl *ctl, const vshCmd *cmd) -{ - const char *dir = NULL; - char *dir_malloced = NULL; - bool ret = true; - char ebuf[1024]; - - if (!ctl->imode) { - vshError(ctl, "%s", _("cd: command valid only in interactive mode")); - return false; - } - - if (vshCommandOptString(ctl, cmd, "dir", &dir) <= 0) - dir = dir_malloced = virGetUserDirectory(); - if (!dir) - dir = "/"; - - if (chdir(dir) == -1) { - vshError(ctl, _("cd: %s: %s"), - virStrerror(errno, ebuf, sizeof(ebuf)), dir); - ret = false; - } - - VIR_FREE(dir_malloced); - return ret; -} - -/* - * "pwd" command - */ -static const vshCmdInfo info_pwd[] = { - {.name = "help", - .data = N_("print the current directory") - }, - {.name = "desc", - .data = N_("Print the current directory.") - }, - {.name = NULL} -}; - -static bool -cmdPwd(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) -{ - char *cwd; - bool ret = true; - char ebuf[1024]; - - cwd = getcwd(NULL, 0); - if (!cwd) { - vshError(ctl, _("pwd: cannot get current directory: %s"), - virStrerror(errno, ebuf, sizeof(ebuf))); - ret = false; - } else { - vshPrint(ctl, _("%s\n"), cwd); - VIR_FREE(cwd); - } - - return ret; -} - -/* - * "echo" command - */ -static const vshCmdInfo info_echo[] = { - {.name = "help", - .data = N_("echo arguments") - }, - {.name = "desc", - .data = N_("Echo back arguments, possibly with quoting.") - }, - {.name = NULL} -}; - -static const vshCmdOptDef opts_echo[] = { - {.name = "shell", - .type = VSH_OT_BOOL, - .help = N_("escape for shell use") - }, - {.name = "xml", - .type = VSH_OT_BOOL, - .help = N_("escape for XML use") - }, - {.name = "str", - .type = VSH_OT_ALIAS, - .help = "string" - }, - {.name = "hi", - .type = VSH_OT_ALIAS, - .help = "string=hello" - }, - {.name = "string", - .type = VSH_OT_ARGV, - .help = N_("arguments to echo") - }, - {.name = NULL} -}; - -/* Exists mainly for debugging virsh, but also handy for adding back - * quotes for later evaluation. - */ -static bool -cmdEcho(vshControl *ctl, const vshCmd *cmd) -{ - bool shell = false; - bool xml = false; - int count = 0; - const vshCmdOpt *opt = NULL; - char *arg; - virBuffer buf = VIR_BUFFER_INITIALIZER; - - if (vshCommandOptBool(cmd, "shell")) - shell = true; - if (vshCommandOptBool(cmd, "xml")) - xml = true; - - while ((opt = vshCommandOptArgv(ctl, cmd, opt))) { - char *str; - virBuffer xmlbuf = VIR_BUFFER_INITIALIZER; - - arg = opt->data; - - if (count) - virBufferAddChar(&buf, ' '); - - if (xml) { - virBufferEscapeString(&xmlbuf, "%s", arg); - if (virBufferError(&xmlbuf)) { - vshPrint(ctl, "%s", _("Failed to allocate XML buffer")); - return false; - } - str = virBufferContentAndReset(&xmlbuf); - } else { - str = vshStrdup(ctl, arg); - } - - if (shell) - virBufferEscapeShell(&buf, str); - else - virBufferAdd(&buf, str, -1); - count++; - VIR_FREE(str); - } - - if (virBufferError(&buf)) { - vshPrint(ctl, "%s", _("Failed to allocate XML buffer")); - return false; - } - arg = virBufferContentAndReset(&buf); - if (arg) - vshPrint(ctl, "%s", arg); - VIR_FREE(arg); - return true; + out: + vshResetLibvirtError(); } /* - * "quit" command + * Detection of disconnections and automatic reconnection support */ -static const vshCmdInfo info_quit[] = { - {.name = "help", - .data = N_("quit this interactive terminal") - }, - {.name = "desc", - .data = "" - }, - {.name = NULL} -}; - -static bool -cmdQuit(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) -{ - ctl->imode = false; - return true; -} +static int disconnected; /* we may have been disconnected */ /* --------------- * Utils for work with command definition @@ -1906,56 +1123,6 @@ vshCommandOptArgv(vshControl *ctl ATTRIBUTE_UNUSED, const vshCmd *cmd, return NULL; } -/* - * vshCommandOptTimeoutToMs: - * @ctl virsh control structure - * @cmd command reference - * @timeout result - * - * Parse an optional --timeout parameter in seconds, but store the - * value of the timeout in milliseconds. - * See vshCommandOptInt() - */ -int -vshCommandOptTimeoutToMs(vshControl *ctl, const vshCmd *cmd, int *timeout) -{ - int ret; - unsigned int utimeout; - - if ((ret = vshCommandOptUInt(ctl, cmd, "timeout", &utimeout)) <= 0) - return ret; - - /* Ensure that the timeout is not zero and that we can convert - * it from seconds to milliseconds without overflowing. */ - if (utimeout == 0 || utimeout > INT_MAX / 1000) { - vshError(ctl, - _("Numeric value '%u' for <%s> option is malformed or out of range"), - utimeout, - "timeout"); - ret = -1; - } else { - *timeout = ((int) utimeout) * 1000; - } - - return ret; -} - -static bool -vshConnectionUsability(vshControl *ctl, virConnectPtr conn) -{ - if (!conn || - virConnectIsAlive(conn) == 0) { - vshError(ctl, "%s", _("no valid connection")); - return false; - } - - /* The connection is considered dead only if - * virConnectIsAlive() successfuly says so. - */ - vshResetLibvirtError(); - - return true; -} /* * Executes command(s) and returns return code from last command @@ -2187,13 +1354,14 @@ vshCommandParse(vshControl *ctl, vshCommandParser *parser) if (STRNEQ(tmpopt->def->name, "help")) continue; + const vshCmdDef *help = vshCmddefSearch("help"); vshCommandOptFree(first); first = vshMalloc(ctl, sizeof(vshCmdOpt)); - first->def = &(opts_help[0]); + first->def = help->opts; first->data = vshStrdup(ctl, cmd->name); first->next = NULL; - cmd = vshCmddefSearch("help"); + cmd = help; opts_required = 0; opts_seen = 0; break; @@ -2346,33 +1514,6 @@ vshCommandStringParse(vshControl *ctl, char *cmdstr) * Misc utils * --------------- */ -int -vshDomainState(vshControl *ctl, virDomainPtr dom, int *reason) -{ - virDomainInfo info; - - if (reason) - *reason = -1; - - if (!ctl->useGetInfo) { - int state; - if (virDomainGetState(dom, &state, reason, 0) < 0) { - virErrorPtr err = virGetLastError(); - if (err && err->code == VIR_ERR_NO_SUPPORT) - ctl->useGetInfo = true; - else - return -1; - } else { - return state; - } - } - - /* fall back to virDomainGetInfo if virDomainGetState is not supported */ - if (virDomainGetInfo(dom, &info) < 0) - return -1; - else - return info.state; -} /* Return a non-NULL string representation of a typed parameter; exit * if we are out of memory. */ @@ -2803,49 +1944,6 @@ vshInitDebug(vshControl *ctl) } } -/* - * Initialize connection. - */ -static bool -vshInit(vshControl *ctl) -{ - /* Since we have the commandline arguments parsed, we need to - * re-initialize all the debugging to make it work properly */ - vshInitDebug(ctl); - - if (ctl->conn) - return false; - - /* set up the library error handler */ - virSetErrorFunc(NULL, virshErrorHandler); - - if (virEventRegisterDefaultImpl() < 0) - return false; - - if (virThreadCreate(&ctl->eventLoop, true, vshEventLoop, ctl) < 0) - return false; - ctl->eventLoopStarted = true; - - if ((ctl->eventTimerId = virEventAddTimeout(-1, vshEventTimeout, ctl, - NULL)) < 0) - return false; - - if (ctl->name) { - vshReconnect(ctl); - /* Connecting to a named connection must succeed, but we delay - * connecting to the default connection until we need it - * (since the first command might be 'connect' which allows a - * non-default connection, or might be 'help' which needs no - * connection). - */ - if (!ctl->conn) { - vshReportError(ctl); - return false; - } - } - - return true; -} #define LOGFILE_FLAGS (O_WRONLY | O_APPEND | O_CREAT | O_SYNC) @@ -3211,590 +2309,3 @@ vshReadline(vshControl *ctl, const char *prompt) } #endif /* !WITH_READLINE */ - -static void -vshDeinitTimer(int timer ATTRIBUTE_UNUSED, void *opaque ATTRIBUTE_UNUSED) -{ - /* nothing to be done here */ -} - -/* - * Deinitialize virsh - */ -static bool -vshDeinit(vshControl *ctl) -{ - vshReadlineDeinit(ctl); - vshCloseLogFile(ctl); - VIR_FREE(ctl->name); - if (ctl->conn) { - int ret; - virConnectUnregisterCloseCallback(ctl->conn, vshCatchDisconnect); - ret = virConnectClose(ctl->conn); - if (ret < 0) - vshError(ctl, "%s", _("Failed to disconnect from the hypervisor")); - else if (ret > 0) - vshError(ctl, "%s", _("One or more references were leaked after " - "disconnect from the hypervisor")); - } - virResetLastError(); - - if (ctl->eventLoopStarted) { - int timer; - - virMutexLock(&ctl->lock); - ctl->quit = true; - /* HACK: Add a dummy timeout to break event loop */ - timer = virEventAddTimeout(0, vshDeinitTimer, NULL, NULL); - virMutexUnlock(&ctl->lock); - - virThreadJoin(&ctl->eventLoop); - - if (timer != -1) - virEventRemoveTimeout(timer); - - if (ctl->eventTimerId != -1) - virEventRemoveTimeout(ctl->eventTimerId); - - ctl->eventLoopStarted = false; - } - - virMutexDestroy(&ctl->lock); - - return true; -} - -/* - * Print usage - */ -static void -vshUsage(void) -{ - const vshCmdGrp *grp; - const vshCmdDef *cmd; - - fprintf(stdout, _("\n%s [options]... [<command_string>]" - "\n%s [options]... <command> [args...]\n\n" - " options:\n" - " -c | --connect=URI hypervisor connection URI\n" - " -d | --debug=NUM debug level [0-4]\n" - " -e | --escape <char> set escape sequence for console\n" - " -h | --help this help\n" - " -k | --keepalive-interval=NUM\n" - " keepalive interval in seconds, 0 for disable\n" - " -K | --keepalive-count=NUM\n" - " number of possible missed keepalive messages\n" - " -l | --log=FILE output logging to file\n" - " -q | --quiet quiet mode\n" - " -r | --readonly connect readonly\n" - " -t | --timing print timing information\n" - " -v short version\n" - " -V long version\n" - " --version[=TYPE] version, TYPE is short or long (default short)\n" - " commands (non interactive mode):\n\n"), progname, progname); - - for (grp = cmdGroups; grp->name; grp++) { - fprintf(stdout, _(" %s (help keyword '%s')\n"), - grp->name, grp->keyword); - for (cmd = grp->commands; cmd->name; cmd++) { - if (cmd->flags & VSH_CMD_FLAG_ALIAS) - continue; - fprintf(stdout, - " %-30s %s\n", cmd->name, - _(vshCmddefGetInfo(cmd, "help"))); - } - fprintf(stdout, "\n"); - } - - fprintf(stdout, "%s", - _("\n (specify help <group> for details about the commands in the group)\n")); - fprintf(stdout, "%s", - _("\n (specify help <command> for details about the command)\n\n")); - return; -} - -/* - * Show version and options compiled in - */ -static void -vshShowVersion(vshControl *ctl ATTRIBUTE_UNUSED) -{ - /* FIXME - list a copyright blurb, as in GNU programs? */ - vshPrint(ctl, _("Virsh command line tool of libvirt %s\n"), VERSION); - vshPrint(ctl, _("See web site at %s\n\n"), "http://libvirt.org/"); - - vshPrint(ctl, "%s", _("Compiled with support for:\n")); - vshPrint(ctl, "%s", _(" Hypervisors:")); -#ifdef WITH_QEMU - vshPrint(ctl, " QEMU/KVM"); -#endif -#ifdef WITH_LXC - vshPrint(ctl, " LXC"); -#endif -#ifdef WITH_UML - vshPrint(ctl, " UML"); -#endif -#ifdef WITH_XEN - vshPrint(ctl, " Xen"); -#endif -#ifdef WITH_LIBXL - vshPrint(ctl, " LibXL"); -#endif -#ifdef WITH_OPENVZ - vshPrint(ctl, " OpenVZ"); -#endif -#ifdef WITH_VMWARE - vshPrint(ctl, " VMWare"); -#endif -#ifdef WITH_PHYP - vshPrint(ctl, " PHYP"); -#endif -#ifdef WITH_VBOX - vshPrint(ctl, " VirtualBox"); -#endif -#ifdef WITH_ESX - vshPrint(ctl, " ESX"); -#endif -#ifdef WITH_HYPERV - vshPrint(ctl, " Hyper-V"); -#endif -#ifdef WITH_XENAPI - vshPrint(ctl, " XenAPI"); -#endif -#ifdef WITH_BHYVE - vshPrint(ctl, " Bhyve"); -#endif -#ifdef WITH_TEST - vshPrint(ctl, " Test"); -#endif - vshPrint(ctl, "\n"); - - vshPrint(ctl, "%s", _(" Networking:")); -#ifdef WITH_REMOTE - vshPrint(ctl, " Remote"); -#endif -#ifdef WITH_NETWORK - vshPrint(ctl, " Network"); -#endif -#ifdef WITH_BRIDGE - vshPrint(ctl, " Bridging"); -#endif -#if defined(WITH_INTERFACE) - vshPrint(ctl, " Interface"); -# if defined(WITH_NETCF) - vshPrint(ctl, " netcf"); -# elif defined(WITH_UDEV) - vshPrint(ctl, " udev"); -# endif -#endif -#ifdef WITH_NWFILTER - vshPrint(ctl, " Nwfilter"); -#endif -#ifdef WITH_VIRTUALPORT - vshPrint(ctl, " VirtualPort"); -#endif - vshPrint(ctl, "\n"); - - vshPrint(ctl, "%s", _(" Storage:")); -#ifdef WITH_STORAGE_DIR - vshPrint(ctl, " Dir"); -#endif -#ifdef WITH_STORAGE_DISK - vshPrint(ctl, " Disk"); -#endif -#ifdef WITH_STORAGE_FS - vshPrint(ctl, " Filesystem"); -#endif -#ifdef WITH_STORAGE_SCSI - vshPrint(ctl, " SCSI"); -#endif -#ifdef WITH_STORAGE_MPATH - vshPrint(ctl, " Multipath"); -#endif -#ifdef WITH_STORAGE_ISCSI - vshPrint(ctl, " iSCSI"); -#endif -#ifdef WITH_STORAGE_LVM - vshPrint(ctl, " LVM"); -#endif -#ifdef WITH_STORAGE_RBD - vshPrint(ctl, " RBD"); -#endif -#ifdef WITH_STORAGE_SHEEPDOG - vshPrint(ctl, " Sheepdog"); -#endif -#ifdef WITH_STORAGE_GLUSTER - vshPrint(ctl, " Gluster"); -#endif - vshPrint(ctl, "\n"); - - vshPrint(ctl, "%s", _(" Miscellaneous:")); -#ifdef WITH_LIBVIRTD - vshPrint(ctl, " Daemon"); -#endif -#ifdef WITH_NODE_DEVICES - vshPrint(ctl, " Nodedev"); -#endif -#ifdef WITH_SECDRIVER_APPARMOR - vshPrint(ctl, " AppArmor"); -#endif -#ifdef WITH_SECDRIVER_SELINUX - vshPrint(ctl, " SELinux"); -#endif -#ifdef WITH_SECRETS - vshPrint(ctl, " Secrets"); -#endif -#ifdef ENABLE_DEBUG - vshPrint(ctl, " Debug"); -#endif -#ifdef WITH_DTRACE_PROBES - vshPrint(ctl, " DTrace"); -#endif -#if WITH_READLINE - vshPrint(ctl, " Readline"); -#endif -#ifdef WITH_DRIVER_MODULES - vshPrint(ctl, " Modular"); -#endif - vshPrint(ctl, "\n"); -} - -static bool -vshAllowedEscapeChar(char c) -{ - /* Allowed escape characters: - * a-z A-Z @ [ \ ] ^ _ - */ - return ('a' <= c && c <= 'z') || - ('@' <= c && c <= '_'); -} - -/* - * argv[]: virsh [options] [command] - * - */ -static bool -vshParseArgv(vshControl *ctl, int argc, char **argv) -{ - int arg, len, debug, keepalive; - size_t i; - int longindex = -1; - struct option opt[] = { - {"connect", required_argument, NULL, 'c'}, - {"debug", required_argument, NULL, 'd'}, - {"escape", required_argument, NULL, 'e'}, - {"help", no_argument, NULL, 'h'}, - {"keepalive-interval", required_argument, NULL, 'k'}, - {"keepalive-count", required_argument, NULL, 'K'}, - {"log", required_argument, NULL, 'l'}, - {"quiet", no_argument, NULL, 'q'}, - {"readonly", no_argument, NULL, 'r'}, - {"timing", no_argument, NULL, 't'}, - {"version", optional_argument, NULL, 'v'}, - {NULL, 0, NULL, 0} - }; - - /* Standard (non-command) options. The leading + ensures that no - * argument reordering takes place, so that command options are - * not confused with top-level virsh options. */ - while ((arg = getopt_long(argc, argv, "+:c:d:e:hk:K:l:qrtvV", opt, &longindex)) != -1) { - switch (arg) { - case 'c': - VIR_FREE(ctl->name); - ctl->name = vshStrdup(ctl, optarg); - break; - case 'd': - if (virStrToLong_i(optarg, NULL, 10, &debug) < 0) { - vshError(ctl, _("option %s takes a numeric argument"), - longindex == -1 ? "-d" : "--debug"); - exit(EXIT_FAILURE); - } - if (debug < VSH_ERR_DEBUG || debug > VSH_ERR_ERROR) - vshError(ctl, _("ignoring debug level %d out of range [%d-%d]"), - debug, VSH_ERR_DEBUG, VSH_ERR_ERROR); - else - ctl->debug = debug; - break; - case 'e': - len = strlen(optarg); - - if ((len == 2 && *optarg == '^' && - vshAllowedEscapeChar(optarg[1])) || - (len == 1 && *optarg != '^')) { - ctl->escapeChar = optarg; - } else { - vshError(ctl, _("Invalid string '%s' for escape sequence"), - optarg); - exit(EXIT_FAILURE); - } - break; - case 'h': - vshUsage(); - exit(EXIT_SUCCESS); - break; - case 'k': - if (virStrToLong_i(optarg, NULL, 0, &keepalive) < 0) { - vshError(ctl, - _("Invalid value for option %s"), - longindex == -1 ? "-k" : "--keepalive-interval"); - exit(EXIT_FAILURE); - } - - if (keepalive < 0) { - vshError(ctl, - _("option %s requires a positive integer argument"), - longindex == -1 ? "-k" : "--keepalive-interval"); - exit(EXIT_FAILURE); - } - ctl->keepalive_interval = keepalive; - break; - case 'K': - if (virStrToLong_i(optarg, NULL, 0, &keepalive) < 0) { - vshError(ctl, - _("Invalid value for option %s"), - longindex == -1 ? "-K" : "--keepalive-count"); - exit(EXIT_FAILURE); - } - - if (keepalive < 0) { - vshError(ctl, - _("option %s requires a positive integer argument"), - longindex == -1 ? "-K" : "--keepalive-count"); - exit(EXIT_FAILURE); - } - ctl->keepalive_count = keepalive; - break; - case 'l': - vshCloseLogFile(ctl); - ctl->logfile = vshStrdup(ctl, optarg); - vshOpenLogFile(ctl); - break; - case 'q': - ctl->quiet = true; - break; - case 't': - ctl->timing = true; - break; - case 'r': - ctl->readonly = true; - break; - case 'v': - if (STRNEQ_NULLABLE(optarg, "long")) { - puts(VERSION); - exit(EXIT_SUCCESS); - } - /* fall through */ - case 'V': - vshShowVersion(ctl); - exit(EXIT_SUCCESS); - case ':': - for (i = 0; opt[i].name != NULL; i++) { - if (opt[i].val == optopt) - break; - } - if (opt[i].name) - vshError(ctl, _("option '-%c'/'--%s' requires an argument"), - optopt, opt[i].name); - else - vshError(ctl, _("option '-%c' requires an argument"), optopt); - exit(EXIT_FAILURE); - case '?': - if (optopt) - vshError(ctl, _("unsupported option '-%c'. See --help."), optopt); - else - vshError(ctl, _("unsupported option '%s'. See --help."), argv[optind - 1]); - exit(EXIT_FAILURE); - default: - vshError(ctl, _("unknown option")); - exit(EXIT_FAILURE); - } - longindex = -1; - } - - if (argc > optind) { - /* parse command */ - ctl->imode = false; - if (argc - optind == 1) { - vshDebug(ctl, VSH_ERR_INFO, "commands: \"%s\"\n", argv[optind]); - return vshCommandStringParse(ctl, argv[optind]); - } else { - return vshCommandArgvParse(ctl, argc - optind, argv + optind); - } - } - return true; -} - -static const vshCmdDef virshCmds[] = { - {.name = "cd", - .handler = cmdCd, - .opts = opts_cd, - .info = info_cd, - .flags = VSH_CMD_FLAG_NOCONNECT - }, - {.name = "connect", - .handler = cmdConnect, - .opts = opts_connect, - .info = info_connect, - .flags = VSH_CMD_FLAG_NOCONNECT - }, - {.name = "echo", - .handler = cmdEcho, - .opts = opts_echo, - .info = info_echo, - .flags = VSH_CMD_FLAG_NOCONNECT - }, - {.name = "exit", - .handler = cmdQuit, - .opts = NULL, - .info = info_quit, - .flags = VSH_CMD_FLAG_NOCONNECT - }, - {.name = "help", - .handler = cmdHelp, - .opts = opts_help, - .info = info_help, - .flags = VSH_CMD_FLAG_NOCONNECT - }, - {.name = "pwd", - .handler = cmdPwd, - .opts = NULL, - .info = info_pwd, - .flags = VSH_CMD_FLAG_NOCONNECT - }, - {.name = "quit", - .handler = cmdQuit, - .opts = NULL, - .info = info_quit, - .flags = VSH_CMD_FLAG_NOCONNECT - }, - {.name = NULL} -}; - -static const vshCmdGrp cmdGroups[] = { - {VSH_CMD_GRP_DOM_MANAGEMENT, "domain", domManagementCmds}, - {VSH_CMD_GRP_DOM_MONITORING, "monitor", domMonitoringCmds}, - {VSH_CMD_GRP_HOST_AND_HV, "host", hostAndHypervisorCmds}, - {VSH_CMD_GRP_IFACE, "interface", ifaceCmds}, - {VSH_CMD_GRP_NWFILTER, "filter", nwfilterCmds}, - {VSH_CMD_GRP_NETWORK, "network", networkCmds}, - {VSH_CMD_GRP_NODEDEV, "nodedev", nodedevCmds}, - {VSH_CMD_GRP_SECRET, "secret", secretCmds}, - {VSH_CMD_GRP_SNAPSHOT, "snapshot", snapshotCmds}, - {VSH_CMD_GRP_STORAGE_POOL, "pool", storagePoolCmds}, - {VSH_CMD_GRP_STORAGE_VOL, "volume", storageVolCmds}, - {VSH_CMD_GRP_VIRSH, "virsh", virshCmds}, - {NULL, NULL, NULL} -}; - -int -main(int argc, char **argv) -{ - vshControl _ctl, *ctl = &_ctl; - const char *defaultConn; - bool ret = true; - - memset(ctl, 0, sizeof(vshControl)); - ctl->imode = true; /* default is interactive mode */ - ctl->log_fd = -1; /* Initialize log file descriptor */ - ctl->debug = VSH_DEBUG_DEFAULT; - ctl->escapeChar = "^]"; /* Same default as telnet */ - - /* In order to distinguish default from setting to 0 */ - ctl->keepalive_interval = -1; - ctl->keepalive_count = -1; - - ctl->eventPipe[0] = -1; - ctl->eventPipe[1] = -1; - ctl->eventTimerId = -1; - - if (!setlocale(LC_ALL, "")) { - perror("setlocale"); - /* failure to setup locale is not fatal */ - } - if (!bindtextdomain(PACKAGE, LOCALEDIR)) { - perror("bindtextdomain"); - return EXIT_FAILURE; - } - if (!textdomain(PACKAGE)) { - perror("textdomain"); - return EXIT_FAILURE; - } - - if (isatty(STDIN_FILENO)) { - ctl->istty = true; - -#ifndef WIN32 - if (tcgetattr(STDIN_FILENO, &ctl->termattr) < 0) - ctl->istty = false; -#endif - } - - if (virMutexInit(&ctl->lock) < 0) { - vshError(ctl, "%s", _("Failed to initialize mutex")); - return EXIT_FAILURE; - } - - if (virInitialize() < 0) { - vshError(ctl, "%s", _("Failed to initialize libvirt")); - return EXIT_FAILURE; - } - - virFileActivateDirOverride(argv[0]); - - if (!(progname = strrchr(argv[0], '/'))) - progname = argv[0]; - else - progname++; - - if ((defaultConn = virGetEnvBlockSUID("VIRSH_DEFAULT_CONNECT_URI"))) - ctl->name = vshStrdup(ctl, defaultConn); - - vshInitDebug(ctl); - - if (!vshParseArgv(ctl, argc, argv) || - !vshInit(ctl)) { - vshDeinit(ctl); - exit(EXIT_FAILURE); - } - - if (!ctl->imode) { - ret = vshCommandRun(ctl, ctl->cmd); - } else { - /* interactive mode */ - if (!ctl->quiet) { - vshPrint(ctl, - _("Welcome to %s, the virtualization interactive terminal.\n\n"), - progname); - vshPrint(ctl, "%s", - _("Type: 'help' for help with commands\n" - " 'quit' to quit\n\n")); - } - - if (vshReadlineInit(ctl) < 0) { - vshDeinit(ctl); - exit(EXIT_FAILURE); - } - - do { - const char *prompt = ctl->readonly ? VSH_PROMPT_RO : VSH_PROMPT_RW; - ctl->cmdstr = - vshReadline(ctl, prompt); - if (ctl->cmdstr == NULL) - break; /* EOF */ - if (*ctl->cmdstr) { -#if WITH_READLINE - add_history(ctl->cmdstr); -#endif - if (vshCommandStringParse(ctl, ctl->cmdstr)) - vshCommandRun(ctl, ctl->cmd); - } - VIR_FREE(ctl->cmdstr); - } while (ctl->imode); - - if (ctl->cmdstr == NULL) - fputc('\n', stdout); /* line break after alone prompt */ - } - - vshDeinit(ctl); - exit(ret ? EXIT_SUCCESS : EXIT_FAILURE); -} diff --git a/tools/vsh.h b/tools/vsh.h index 345eb99..4b99b65 100644 --- a/tools/vsh.h +++ b/tools/vsh.h @@ -37,11 +37,6 @@ # include "virerror.h" # include "virthread.h" -# define VSH_MAX_XML_FILE (10*1024*1024) - -# define VSH_PROMPT_RW "virsh # " -# define VSH_PROMPT_RO "virsh > " - # define VIR_FROM_THIS VIR_FROM_NONE # define GETTIMEOFDAY(T) gettimeofday(T, NULL) @@ -52,7 +47,6 @@ * The log configuration */ # define MSG_BUFFER 4096 -# define SIGN_NAME "virsh" # define DIR_MODE (S_IWUSR | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) /* 0755 */ # define FILE_MODE (S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH) /* 0644 */ # define LOCK_MODE (S_IWUSR | S_IRUSR) /* 0600 */ @@ -110,22 +104,6 @@ typedef enum { } vshCmdOptType; /* - * Command group types - */ -# define VSH_CMD_GRP_DOM_MANAGEMENT "Domain Management" -# define VSH_CMD_GRP_DOM_MONITORING "Domain Monitoring" -# define VSH_CMD_GRP_STORAGE_POOL "Storage Pool" -# define VSH_CMD_GRP_STORAGE_VOL "Storage Volume" -# define VSH_CMD_GRP_NETWORK "Networking" -# define VSH_CMD_GRP_NODEDEV "Node Device" -# define VSH_CMD_GRP_IFACE "Interface" -# define VSH_CMD_GRP_NWFILTER "Network Filter" -# define VSH_CMD_GRP_SECRET "Secret" -# define VSH_CMD_GRP_SNAPSHOT "Snapshot" -# define VSH_CMD_GRP_HOST_AND_HV "Host and Hypervisor" -# define VSH_CMD_GRP_VIRSH "Virsh itself" - -/* * Command Option Flags */ enum { @@ -143,7 +121,6 @@ typedef struct _vshCmdInfo vshCmdInfo; typedef struct _vshCmdOpt vshCmdOpt; typedef struct _vshCmdOptDef vshCmdOptDef; typedef struct _vshControl vshControl; -typedef struct _vshCtrlData vshCtrlData; typedef char **(*vshCompleter)(unsigned int flags); @@ -217,26 +194,16 @@ struct _vshCmd { */ struct _vshControl { char *name; /* connection name */ - virConnectPtr conn; /* connection to hypervisor (MAY BE NULL) */ vshCmd *cmd; /* the current command */ char *cmdstr; /* string with command */ bool imode; /* interactive mode? */ bool quiet; /* quiet mode */ - int debug; /* print debug messages? */ bool timing; /* print timing info? */ - bool readonly; /* connect readonly (first time only, not - * during explicit connect command) - */ + int debug; /* print debug messages? */ char *logfile; /* log file name */ int log_fd; /* log file descriptor */ char *historydir; /* readline history directory name */ char *historyfile; /* readline history file name */ - bool useGetInfo; /* must use virDomainGetInfo, since - virDomainGetState is not supported */ - bool useSnapshotOld; /* cannot use virDomainSnapshotGetParent or - virDomainSnapshotNumChildren */ - bool blockJobNoBytes; /* true if _BANDWIDTH_BYTE blockjob flags - are missing */ virThread eventLoop; virMutex lock; bool eventLoopStarted; @@ -245,9 +212,6 @@ struct _vshControl { * event to occur */ int eventTimerId; /* id of event loop timeout registration */ - const char *escapeChar; /* String representation of - console escape character */ - int keepalive_interval; /* Client keepalive interval */ int keepalive_count; /* Client keepalive count */ @@ -271,8 +235,6 @@ void vshOutputLogFile(vshControl *ctl, int log_level, const char *format, ATTRIBUTE_FMT_PRINTF(3, 0); void vshCloseLogFile(vshControl *ctl); -virConnectPtr vshConnect(vshControl *ctl, const char *uri, bool readonly); - const char *vshCmddefGetInfo(const vshCmdDef *cmd, const char *info); const vshCmdDef *vshCmddefSearch(const char *cmdname); bool vshCmddefHelp(vshControl *ctl, const char *name); @@ -317,7 +279,6 @@ int vshCommandOptScaledInt(vshControl *ctl, const vshCmd *cmd, bool vshCommandOptBool(const vshCmd *cmd, const char *name); const vshCmdOpt *vshCommandOptArgv(vshControl *ctl, const vshCmd *cmd, const vshCmdOpt *opt); -int vshCommandOptTimeoutToMs(vshControl *ctl, const vshCmd *cmd, int *timeout); /* Filter flags for various vshCommandOpt*By() functions */ typedef enum { @@ -327,12 +288,6 @@ typedef enum { VSH_BYMAC = (1 << 4), } vshLookupByFlags; -/* Given an index, return either the name of that device (non-NULL) or - * of its parent (NULL if a root). */ -typedef const char * (*vshTreeLookup)(int devid, bool parent, void *opaque); -int vshTreePrint(vshControl *ctl, vshTreeLookup lookup, void *opaque, - int num_devices, int devid); - void vshPrintExtra(vshControl *ctl, const char *format, ...) ATTRIBUTE_FMT_PRINTF(2, 3); void vshDebug(vshControl *ctl, int level, const char *format, ...) @@ -345,33 +300,14 @@ void vshDebug(vshControl *ctl, int level, const char *format, ...) # define vshStrcasecmp(S1, S2) strcasecmp(S1, S2) int vshNameSorter(const void *a, const void *b); -int vshDomainState(vshControl *ctl, virDomainPtr dom, int *reason); virTypedParameterPtr vshFindTypedParamByName(const char *name, virTypedParameterPtr list, int count); char *vshGetTypedParamValue(vshControl *ctl, virTypedParameterPtr item) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); -char *vshEditWriteToTempFile(vshControl *ctl, const char *doc); -int vshEditFile(vshControl *ctl, const char *filename); -char *vshEditReadBackFile(vshControl *ctl, const char *filename); -int vshAskReedit(vshControl *ctl, const char *msg, bool relax_avail); -int vshStreamSink(virStreamPtr st, const char *bytes, size_t nbytes, - void *opaque); -double vshPrettyCapacity(unsigned long long val, const char **unit); int vshStringToArray(const char *str, char ***array); -/* Typedefs, function prototypes for job progress reporting. - * There are used by some long lingering commands like - * migrate, dump, save, managedsave. - */ -struct _vshCtrlData { - vshControl *ctl; - const vshCmd *cmd; - int writefd; - virConnectPtr dconn; -}; - /* error handling */ extern virErrorPtr last_error; void vshReportError(vshControl *ctl); -- 1.9.3

The very opposite action to removing client specific data from vsh. As all the generic methods/structures/variables have been moved to vsh, there's no need for them in virsh. --- tools/virsh.c | 2393 ++++----------------------------------------------------- tools/virsh.h | 428 ----------- tools/vsh.c | 2 +- 3 files changed, 140 insertions(+), 2683 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index f293d0f..9280b40 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -25,7 +25,6 @@ #include <config.h> #include "virsh.h" -#include <assert.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -41,7 +40,6 @@ #include <limits.h> #include <sys/stat.h> #include <inttypes.h> -#include <strings.h> #include <signal.h> #if WITH_READLINE @@ -85,59 +83,6 @@ static char *progname; static const vshCmdGrp cmdGroups[]; -/* Bypass header poison */ -#undef strdup - -void * -_vshMalloc(vshControl *ctl, size_t size, const char *filename, int line) -{ - char *x; - - if (VIR_ALLOC_N(x, size) == 0) - return x; - vshError(ctl, _("%s: %d: failed to allocate %d bytes"), - filename, line, (int) size); - exit(EXIT_FAILURE); -} - -void * -_vshCalloc(vshControl *ctl, size_t nmemb, size_t size, const char *filename, - int line) -{ - char *x; - - if (!xalloc_oversized(nmemb, size) && - VIR_ALLOC_N(x, nmemb * size) == 0) - return x; - vshError(ctl, _("%s: %d: failed to allocate %d bytes"), - filename, line, (int) (size*nmemb)); - exit(EXIT_FAILURE); -} - -char * -_vshStrdup(vshControl *ctl, const char *s, const char *filename, int line) -{ - char *x; - - if (VIR_STRDUP(x, s) >= 0) - return x; - vshError(ctl, _("%s: %d: failed to allocate %lu bytes"), - filename, line, (unsigned long)strlen(s)); - exit(EXIT_FAILURE); -} - -/* Poison the raw allocating identifiers in favor of our vsh variants. */ -#define strdup use_vshStrdup_instead_of_strdup - -int -vshNameSorter(const void *a, const void *b) -{ - const char **sa = (const char**)a; - const char **sb = (const char**)b; - - return vshStrcasecmp(*sa, *sb); -} - double virshPrettyCapacity(unsigned long long val, const char **unit) { @@ -913,25 +858,10 @@ cmdQuit(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) } /* --------------- - * Utils for work with command definition + * Utils for work with runtime commands data * --------------- */ -const char * -vshCmddefGetInfo(const vshCmdDef * cmd, const char *name) -{ - const vshCmdInfo *info; - - for (info = cmd->info; info && info->name; info++) { - if (STREQ(info->name, name)) - return info->data; - } - return NULL; -} -/* Validate that the options associated with cmd can be parsed. */ -static int -vshCmddefOptParse(const vshCmdDef *cmd, uint32_t *opts_need_arg, - uint32_t *opts_required) /* * virshCommandOptTimeoutToMs: * @ctl virsh control structure @@ -945,2253 +875,211 @@ vshCmddefOptParse(const vshCmdDef *cmd, uint32_t *opts_need_arg, int virshCommandOptTimeoutToMs(vshControl *ctl, const vshCmd *cmd, int *timeout) { - size_t i; - bool optional = false; - - *opts_need_arg = 0; - *opts_required = 0; - - if (!cmd->opts) - return 0; - - for (i = 0; cmd->opts[i].name; i++) { - const vshCmdOptDef *opt = &cmd->opts[i]; - - if (i > 31) - return -1; /* too many options */ - if (opt->type == VSH_OT_BOOL) { - optional = true; - if (opt->flags & VSH_OFLAG_REQ) - return -1; /* bool options can't be mandatory */ - continue; - } - if (opt->type == VSH_OT_ALIAS) { - size_t j; - char *name = (char *)opt->help; /* cast away const */ - char *p; - - if (opt->flags || !opt->help) - return -1; /* alias options are tracked by the original name */ - if ((p = strchr(name, '=')) && - VIR_STRNDUP(name, name, p - name) < 0) - return -1; - for (j = i + 1; cmd->opts[j].name; j++) { - if (STREQ(name, cmd->opts[j].name) && - cmd->opts[j].type != VSH_OT_ALIAS) - break; - } - if (name != opt->help) { - VIR_FREE(name); - /* If alias comes with value, replacement must not be bool */ - if (cmd->opts[j].type == VSH_OT_BOOL) - return -1; - } - if (!cmd->opts[j].name) - return -1; /* alias option must map to a later option name */ - continue; - } - if (opt->flags & VSH_OFLAG_REQ_OPT) { - if (opt->flags & VSH_OFLAG_REQ) - *opts_required |= 1 << i; - else - optional = true; - continue; - } + int ret; + unsigned int utimeout; - *opts_need_arg |= 1 << i; - if (opt->flags & VSH_OFLAG_REQ) { - if (optional && opt->type != VSH_OT_ARGV) - return -1; /* mandatory options must be listed first */ - *opts_required |= 1 << i; - } else { - optional = true; - } + if ((ret = vshCommandOptUInt(ctl, cmd, "timeout", &utimeout)) <= 0) + return ret; - if (opt->type == VSH_OT_ARGV && cmd->opts[i + 1].name) - return -1; /* argv option must be listed last */ + /* Ensure that the timeout is not zero and that we can convert + * it from seconds to milliseconds without overflowing. */ + if (utimeout == 0 || utimeout > INT_MAX / 1000) { + vshError(ctl, + _("Numeric value '%u' for <%s> option is malformed or out of range"), + utimeout, + "timeout"); + ret = -1; + } else { + *timeout = ((int) utimeout) * 1000; } - return 0; + + return ret; } -static vshCmdOptDef helpopt = { - .name = "help", - .type = VSH_OT_BOOL, - .help = N_("print help for this function") -}; -static const vshCmdOptDef * -vshCmddefGetOption(vshControl *ctl, const vshCmdDef *cmd, const char *name, - uint32_t *opts_seen, int *opt_index, char **optstr) static bool virshConnectionUsability(vshControl *ctl, virConnectPtr conn) { - size_t i; - const vshCmdOptDef *ret = NULL; - char *alias = NULL; - - if (STREQ(name, helpopt.name)) - return &helpopt; - - for (i = 0; cmd->opts && cmd->opts[i].name; i++) { - const vshCmdOptDef *opt = &cmd->opts[i]; - - if (STREQ(opt->name, name)) { - if (opt->type == VSH_OT_ALIAS) { - char *value; - - /* Two types of replacements: - opt->help = "string": straight replacement of name - opt->help = "string=value": treat boolean flag as - alias of option and its default value */ - sa_assert(!alias); - if (VIR_STRDUP(alias, opt->help) < 0) - goto cleanup; - name = alias; - if ((value = strchr(name, '='))) { - *value = '\0'; - if (*optstr) { - vshError(ctl, _("invalid '=' after option --%s"), - opt->name); - goto cleanup; - } - if (VIR_STRDUP(*optstr, value + 1) < 0) - goto cleanup; - } - continue; - } - if ((*opts_seen & (1 << i)) && opt->type != VSH_OT_ARGV) { - vshError(ctl, _("option --%s already seen"), name); - goto cleanup; - } - *opts_seen |= 1 << i; - *opt_index = i; - ret = opt; - goto cleanup; - } + if (!conn || + virConnectIsAlive(conn) == 0) { + vshError(ctl, "%s", _("no valid connection")); + return false; } - if (STRNEQ(cmd->name, "help")) { - vshError(ctl, _("command '%s' doesn't support option --%s"), - cmd->name, name); - } - cleanup: - VIR_FREE(alias); - return ret; + /* The connection is considered dead only if + * virConnectIsAlive() successfuly says so. + */ + vshResetLibvirtError(); + + return true; } -static const vshCmdOptDef * -vshCmddefGetData(const vshCmdDef *cmd, uint32_t *opts_need_arg, - uint32_t *opts_seen) { - size_t i; - const vshCmdOptDef *opt; - if (!*opts_need_arg) - return NULL; - /* Grab least-significant set bit */ - i = ffs(*opts_need_arg) - 1; - opt = &cmd->opts[i]; - if (opt->type != VSH_OT_ARGV) - *opts_need_arg &= ~(1 << i); - *opts_seen |= 1 << i; - return opt; } -/* - * Checks for required options +/* --------------- + * Misc utils + * --------------- */ -static int -vshCommandCheckOpts(vshControl *ctl, const vshCmd *cmd, uint32_t opts_required, - uint32_t opts_seen) int virshDomainState(vshControl *ctl, virDomainPtr dom, int *reason) { - const vshCmdDef *def = cmd->def; - size_t i; - - opts_required &= ~opts_seen; - if (!opts_required) - return 0; + virDomainInfo info; + virshControlPtr priv = ctl->privData; - for (i = 0; def->opts[i].name; i++) { - if (opts_required & (1 << i)) { - const vshCmdOptDef *opt = &def->opts[i]; + if (reason) + *reason = -1; - vshError(ctl, - opt->type == VSH_OT_DATA || opt->type == VSH_OT_ARGV ? - _("command '%s' requires <%s> option") : - _("command '%s' requires --%s option"), - def->name, opt->name); + if (!priv->useGetInfo) { + int state; + if (virDomainGetState(dom, &state, reason, 0) < 0) { + virErrorPtr err = virGetLastError(); + if (err && err->code == VIR_ERR_NO_SUPPORT) + priv->useGetInfo = true; + else + return -1; + } else { + return state; } } - return -1; + + /* fall back to virDomainGetInfo if virDomainGetState is not supported */ + if (virDomainGetInfo(dom, &info) < 0) + return -1; + else + return info.state; } -const vshCmdDef * -vshCmddefSearch(const char *cmdname) /* * Initialize connection. */ static bool virshInit(vshControl *ctl) { - const vshCmdGrp *g; - const vshCmdDef *c; - - for (g = cmdGroups; g->name; g++) { - for (c = g->commands; c->name; c++) { - if (STREQ(c->name, cmdname)) - return c; - } - } + virshControlPtr priv = ctl->privData; - return NULL; -} + /* Since we have the commandline arguments parsed, we need to + * re-initialize all the debugging to make it work properly */ + vshInitDebug(ctl); -const vshCmdGrp * -vshCmdGrpSearch(const char *grpname) -{ - const vshCmdGrp *g; + if (priv->conn) + return false; - for (g = cmdGroups; g->name; g++) { - if (STREQ(g->name, grpname) || STREQ(g->keyword, grpname)) - return g; - } + /* set up the library error handler */ + virSetErrorFunc(NULL, vshErrorHandler); - return NULL; -} + if (virEventRegisterDefaultImpl() < 0) + return false; -bool -vshCmdGrpHelp(vshControl *ctl, const char *grpname) -{ - const vshCmdGrp *grp = vshCmdGrpSearch(grpname); - const vshCmdDef *cmd = NULL; + if (virThreadCreate(&ctl->eventLoop, true, vshEventLoop, ctl) < 0) + return false; + ctl->eventLoopStarted = true; - if (!grp) { - vshError(ctl, _("command group '%s' doesn't exist"), grpname); + if ((ctl->eventTimerId = virEventAddTimeout(-1, vshEventTimeout, ctl, + NULL)) < 0) return false; - } else { - vshPrint(ctl, _(" %s (help keyword '%s'):\n"), grp->name, - grp->keyword); - for (cmd = grp->commands; cmd->name; cmd++) { - if (cmd->flags & VSH_CMD_FLAG_ALIAS) - continue; - vshPrint(ctl, " %-30s %s\n", cmd->name, - _(vshCmddefGetInfo(cmd, "help"))); + if (ctl->name) { + virshReconnect(ctl); + /* Connecting to a named connection must succeed, but we delay + * connecting to the default connection until we need it + * (since the first command might be 'connect' which allows a + * non-default connection, or might be 'help' which needs no + * connection). + */ + if (!priv->conn) { + vshReportError(ctl); + return false; } } return true; } -bool -vshCmddefHelp(vshControl *ctl, const char *cmdname) static void virshDeinitTimer(int timer ATTRIBUTE_UNUSED, void *opaque ATTRIBUTE_UNUSED) { - const vshCmdDef *def = vshCmddefSearch(cmdname); - - if (!def) { - vshError(ctl, _("command '%s' doesn't exist"), cmdname); - return false; - } else { - /* Don't translate desc if it is "". */ - const char *desc = vshCmddefGetInfo(def, "desc"); - const char *help = _(vshCmddefGetInfo(def, "help")); - char buf[256]; - uint32_t opts_need_arg; - uint32_t opts_required; - bool shortopt = false; /* true if 'arg' works instead of '--opt arg' */ - - if (vshCmddefOptParse(def, &opts_need_arg, &opts_required)) { - vshError(ctl, _("internal error: bad options in command: '%s'"), - def->name); - return false; - } - - fputs(_(" NAME\n"), stdout); - fprintf(stdout, " %s - %s\n", def->name, help); - - fputs(_("\n SYNOPSIS\n"), stdout); - fprintf(stdout, " %s", def->name); - if (def->opts) { - const vshCmdOptDef *opt; - for (opt = def->opts; opt->name; opt++) { - const char *fmt = "%s"; - switch (opt->type) { - case VSH_OT_BOOL: - fmt = "[--%s]"; - break; - case VSH_OT_INT: - /* xgettext:c-format */ - fmt = ((opt->flags & VSH_OFLAG_REQ) ? "<%s>" - : _("[--%s <number>]")); - if (!(opt->flags & VSH_OFLAG_REQ_OPT)) - shortopt = true; - break; - case VSH_OT_STRING: - /* xgettext:c-format */ - fmt = _("[--%s <string>]"); - if (!(opt->flags & VSH_OFLAG_REQ_OPT)) - shortopt = true; - break; - case VSH_OT_DATA: - fmt = ((opt->flags & VSH_OFLAG_REQ) ? "<%s>" : "[<%s>]"); - if (!(opt->flags & VSH_OFLAG_REQ_OPT)) - shortopt = true; - break; - case VSH_OT_ARGV: - /* xgettext:c-format */ - if (shortopt) { - fmt = (opt->flags & VSH_OFLAG_REQ) - ? _("{[--%s] <string>}...") - : _("[[--%s] <string>]..."); - } else { - fmt = (opt->flags & VSH_OFLAG_REQ) ? _("<%s>...") - : _("[<%s>]..."); - } - break; - case VSH_OT_ALIAS: - /* aliases are intentionally undocumented */ - continue; - } - fputc(' ', stdout); - fprintf(stdout, fmt, opt->name); - } - } - fputc('\n', stdout); - - if (desc[0]) { - /* Print the description only if it's not empty. */ - fputs(_("\n DESCRIPTION\n"), stdout); - fprintf(stdout, " %s\n", _(desc)); - } - - if (def->opts && def->opts->name) { - const vshCmdOptDef *opt; - fputs(_("\n OPTIONS\n"), stdout); - for (opt = def->opts; opt->name; opt++) { - switch (opt->type) { - case VSH_OT_BOOL: - snprintf(buf, sizeof(buf), "--%s", opt->name); - break; - case VSH_OT_INT: - snprintf(buf, sizeof(buf), - (opt->flags & VSH_OFLAG_REQ) ? _("[--%s] <number>") - : _("--%s <number>"), opt->name); - break; - case VSH_OT_STRING: - /* OT_STRING should never be VSH_OFLAG_REQ */ - if (opt->flags & VSH_OFLAG_REQ) { - vshError(ctl, - _("internal error: bad options in command: '%s'"), - def->name); - return false; - } - snprintf(buf, sizeof(buf), _("--%s <string>"), opt->name); - break; - case VSH_OT_DATA: - /* OT_DATA should always be VSH_OFLAG_REQ */ - if (!(opt->flags & VSH_OFLAG_REQ)) { - vshError(ctl, - _("internal error: bad options in command: '%s'"), - def->name); - return false; - } - snprintf(buf, sizeof(buf), _("[--%s] <string>"), - opt->name); - break; - case VSH_OT_ARGV: - snprintf(buf, sizeof(buf), - shortopt ? _("[--%s] <string>") : _("<%s>"), - opt->name); - break; - case VSH_OT_ALIAS: - continue; - } - - fprintf(stdout, " %-15s %s\n", buf, _(opt->help)); - } - } - fputc('\n', stdout); - } - return true; + /* nothing to be done here */ } -/* --------------- - * Utils for work with runtime commands data - * --------------- +/* + * Deinitialize virsh */ -static void -vshCommandOptFree(vshCmdOpt * arg) static bool virshDeinit(vshControl *ctl) { - vshCmdOpt *a = arg; + virshControlPtr priv = ctl->privData; - while (a) { - vshCmdOpt *tmp = a; + vshReadlineDeinit(ctl); + vshCloseLogFile(ctl); + VIR_FREE(ctl->name); + if (priv->conn) { + int ret; + virConnectUnregisterCloseCallback(priv->conn, virshCatchDisconnect); + ret = virConnectClose(priv->conn); + if (ret < 0) + vshError(ctl, "%s", _("Failed to disconnect from the hypervisor")); + else if (ret > 0) + vshError(ctl, "%s", _("One or more references were leaked after " + "disconnect from the hypervisor")); + } + virResetLastError(); - a = a->next; + if (ctl->eventLoopStarted) { + int timer; - VIR_FREE(tmp->data); - VIR_FREE(tmp); - } -} + virMutexLock(&ctl->lock); + ctl->quit = true; + /* HACK: Add a dummy timeout to break event loop */ + timer = virEventAddTimeout(0, virshDeinitTimer, NULL, NULL); + virMutexUnlock(&ctl->lock); -static void -vshCommandFree(vshCmd *cmd) -{ - vshCmd *c = cmd; + virThreadJoin(&ctl->eventLoop); - while (c) { - vshCmd *tmp = c; + if (timer != -1) + virEventRemoveTimeout(timer); - c = c->next; + if (ctl->eventTimerId != -1) + virEventRemoveTimeout(ctl->eventTimerId); - if (tmp->opts) - vshCommandOptFree(tmp->opts); - VIR_FREE(tmp); + ctl->eventLoopStarted = false; } -} -/** - * vshCommandOpt: - * @cmd: parsed command line to search - * @name: option name to search for - * @opt: result of the search - * @needData: true if option must be non-boolean - * - * Look up an option passed to CMD by NAME. Returns 1 with *OPT set - * to the option if found, 0 with *OPT set to NULL if the name is - * valid and the option is not required, -1 with *OPT set to NULL if - * the option is required but not present, and assert if NAME is not - * valid (which indicates a programming error). No error messages are - * issued if a value is returned. - */ -static int -vshCommandOpt(const vshCmd *cmd, const char *name, vshCmdOpt **opt, - bool needData) -{ - vshCmdOpt *candidate = cmd->opts; - const vshCmdOptDef *valid = cmd->def->opts; - int ret = 0; - - /* See if option is valid and/or required. */ - *opt = NULL; - while (valid) { - assert(valid->name); - if (STREQ(name, valid->name)) - break; - valid++; - } - assert(!needData || valid->type != VSH_OT_BOOL); - if (valid->flags & VSH_OFLAG_REQ) - ret = -1; + virMutexDestroy(&ctl->lock); - /* See if option is present on command line. */ - while (candidate) { - if (STREQ(candidate->def->name, name)) { - *opt = candidate; - ret = 1; - break; - } - candidate = candidate->next; - } - return ret; + return true; } -/** - * vshCommandOptInt: - * @ctl virsh control structure - * @cmd command reference - * @name option name - * @value result - * - * Convert option to int. - * On error, a message is displayed. - * - * Return value: - * >0 if option found and valid (@value updated) - * 0 if option not found and not required (@value untouched) - * <0 in all other cases (@value untouched) +/* + * Print usage */ -int -vshCommandOptInt(vshControl *ctl, const vshCmd *cmd, - const char *name, int *value) +static void +virshUsage(void) { - vshCmdOpt *arg; - int ret; - - if ((ret = vshCommandOpt(cmd, name, &arg, true)) <= 0) - return ret; + const vshCmdGrp *grp; + const vshCmdDef *cmd; - if ((ret = virStrToLong_i(arg->data, NULL, 10, value)) < 0) - vshError(ctl, - _("Numeric value '%s' for <%s> option is malformed or out of range"), - arg->data, name); - else - ret = 1; - - return ret; -} - -static int -vshCommandOptUIntInternal(vshControl *ctl, - const vshCmd *cmd, - const char *name, - unsigned int *value, - bool wrap) -{ - vshCmdOpt *arg; - int ret; - - if ((ret = vshCommandOpt(cmd, name, &arg, true)) <= 0) - return ret; - - if (wrap) - ret = virStrToLong_ui(arg->data, NULL, 10, value); - else - ret = virStrToLong_uip(arg->data, NULL, 10, value); - if (ret < 0) - vshError(ctl, - _("Numeric value '%s' for <%s> option is malformed or out of range"), - arg->data, name); - else - ret = 1; - - return ret; -} - -/** - * vshCommandOptUInt: - * @ctl virsh control structure - * @cmd command reference - * @name option name - * @value result - * - * Convert option to unsigned int, reject negative numbers - * See vshCommandOptInt() - */ -int -vshCommandOptUInt(vshControl *ctl, const vshCmd *cmd, - const char *name, unsigned int *value) -{ - return vshCommandOptUIntInternal(ctl, cmd, name, value, false); -} - -/** - * vshCommandOptUIntWrap: - * @ctl virsh control structure - * @cmd command reference - * @name option name - * @value result - * - * Convert option to unsigned int, wraps negative numbers to positive - * See vshCommandOptInt() - */ -int -vshCommandOptUIntWrap(vshControl *ctl, const vshCmd *cmd, - const char *name, unsigned int *value) -{ - return vshCommandOptUIntInternal(ctl, cmd, name, value, true); -} - -static int -vshCommandOptULInternal(vshControl *ctl, - const vshCmd *cmd, - const char *name, - unsigned long *value, - bool wrap) -{ - vshCmdOpt *arg; - int ret; - - if ((ret = vshCommandOpt(cmd, name, &arg, true)) <= 0) - return ret; - - if (wrap) - ret = virStrToLong_ul(arg->data, NULL, 10, value); - else - ret = virStrToLong_ulp(arg->data, NULL, 10, value); - if (ret < 0) - vshError(ctl, - _("Numeric value '%s' for <%s> option is malformed or out of range"), - arg->data, name); - else - ret = 1; - - return ret; -} - -/* - * vshCommandOptUL: - * @ctl virsh control structure - * @cmd command reference - * @name option name - * @value result - * - * Convert option to unsigned long - * See vshCommandOptInt() - */ -int -vshCommandOptUL(vshControl *ctl, const vshCmd *cmd, - const char *name, unsigned long *value) -{ - return vshCommandOptULInternal(ctl, cmd, name, value, false); -} - -/** - * vshCommandOptULWrap: - * @ctl virsh control structure - * @cmd command reference - * @name option name - * @value result - * - * Convert option to unsigned long, wraps negative numbers to positive - * See vshCommandOptInt() - */ -int -vshCommandOptULWrap(vshControl *ctl, const vshCmd *cmd, - const char *name, unsigned long *value) -{ - return vshCommandOptULInternal(ctl, cmd, name, value, true); -} - -/** - * vshCommandOptString: - * @ctl virsh control structure - * @cmd command reference - * @name option name - * @value result - * - * Returns option as STRING - * Return value: - * >0 if option found and valid (@value updated) - * 0 if option not found and not required (@value untouched) - * <0 in all other cases (@value untouched) - */ -int -vshCommandOptString(vshControl *ctl ATTRIBUTE_UNUSED, const vshCmd *cmd, - const char *name, const char **value) -{ - vshCmdOpt *arg; - int ret; - - if ((ret = vshCommandOpt(cmd, name, &arg, true)) <= 0) - return ret; - - if (!*arg->data && !(arg->def->flags & VSH_OFLAG_EMPTY_OK)) - return -1; - *value = arg->data; - return 1; -} - -/** - * vshCommandOptStringReq: - * @ctl virsh control structure - * @cmd command structure - * @name option name - * @value result (updated to NULL or the option argument) - * - * Gets a option argument as string. - * - * Returns 0 on success or when the option is not present and not - * required, *value is set to the option argument. On error -1 is - * returned and error message printed. - */ -int -vshCommandOptStringReq(vshControl *ctl, - const vshCmd *cmd, - const char *name, - const char **value) -{ - vshCmdOpt *arg; - int ret; - const char *error = NULL; - - /* clear out the value */ - *value = NULL; - - ret = vshCommandOpt(cmd, name, &arg, true); - /* option is not required and not present */ - if (ret == 0) - return 0; - /* this should not be propagated here, just to be sure */ - if (ret == -1) - error = N_("Mandatory option not present"); - else if (!*arg->data && !(arg->def->flags & VSH_OFLAG_EMPTY_OK)) - error = N_("Option argument is empty"); - - if (error) { - vshError(ctl, _("Failed to get option '%s': %s"), name, _(error)); - return -1; - } - - *value = arg->data; - return 0; -} - -/** - * vshCommandOptLongLong: - * @ctl virsh control structure - * @cmd command reference - * @name option name - * @value result - * - * Returns option as long long - * See vshCommandOptInt() - */ -int -vshCommandOptLongLong(vshControl *ctl, const vshCmd *cmd, - const char *name, long long *value) -{ - vshCmdOpt *arg; - int ret; - - if ((ret = vshCommandOpt(cmd, name, &arg, true)) <= 0) - return ret; - - if ((ret = virStrToLong_ll(arg->data, NULL, 10, value)) < 0) - vshError(ctl, - _("Numeric value '%s' for <%s> option is malformed or out of range"), - arg->data, name); - else - ret = 1; - - return ret; -} - -static int -vshCommandOptULongLongInternal(vshControl *ctl, - const vshCmd *cmd, - const char *name, - unsigned long long *value, - bool wrap) -{ - vshCmdOpt *arg; - int ret; - - if ((ret = vshCommandOpt(cmd, name, &arg, true)) <= 0) - return ret; - - if (wrap) - ret = virStrToLong_ull(arg->data, NULL, 10, value); - else - ret = virStrToLong_ullp(arg->data, NULL, 10, value); - if (ret < 0) - vshError(ctl, - _("Numeric value '%s' for <%s> option is malformed or out of range"), - arg->data, name); - else - ret = 1; - - return ret; -} - -/** - * vshCommandOptULongLong: - * @ctl virsh control structure - * @cmd command reference - * @name option name - * @value result - * - * Returns option as long long, rejects negative numbers - * See vshCommandOptInt() - */ -int -vshCommandOptULongLong(vshControl *ctl, const vshCmd *cmd, - const char *name, unsigned long long *value) -{ - return vshCommandOptULongLongInternal(ctl, cmd, name, value, false); -} - -/** - * vshCommandOptULongLongWrap: - * @ctl virsh control structure - * @cmd command reference - * @name option name - * @value result - * - * Returns option as long long, wraps negative numbers to positive - * See vshCommandOptInt() - */ -int -vshCommandOptULongLongWrap(vshControl *ctl, const vshCmd *cmd, - const char *name, unsigned long long *value) -{ - return vshCommandOptULongLongInternal(ctl, cmd, name, value, true); -} - -/** - * vshCommandOptScaledInt: - * @ctl virsh control structure - * @cmd command reference - * @name option name - * @value result - * @scale default of 1 or 1024, if no suffix is present - * @max maximum value permitted - * - * Returns option as long long, scaled according to suffix - * See vshCommandOptInt() - */ -int -vshCommandOptScaledInt(vshControl *ctl, const vshCmd *cmd, - const char *name, unsigned long long *value, - int scale, unsigned long long max) -{ - vshCmdOpt *arg; - char *end; - int ret; - - if ((ret = vshCommandOpt(cmd, name, &arg, true)) <= 0) - return ret; - if (virStrToLong_ullp(arg->data, &end, 10, value) < 0 || - virScaleInteger(value, end, scale, max) < 0) - { - vshError(ctl, - _("Numeric value '%s' for <%s> option is malformed or out of range"), - arg->data, name); - ret = -1; - } else { - ret = 1; - } - - return ret; -} - - -/** - * vshCommandOptBool: - * @cmd command reference - * @name option name - * - * Returns true/false if the option exists. Note that this does NOT - * validate whether the option is actually boolean, or even whether - * name is legal; so that this can be used to probe whether a data - * option is present without actually using that data. - */ -bool -vshCommandOptBool(const vshCmd *cmd, const char *name) -{ - vshCmdOpt *dummy; - - return vshCommandOpt(cmd, name, &dummy, false) == 1; -} - -/** - * vshCommandOptArgv: - * @ctl virsh control structure - * @cmd command reference - * @opt starting point for the search - * - * Returns the next argv argument after OPT (or the first one if OPT - * is NULL), or NULL if no more are present. - * - * Requires that a VSH_OT_ARGV option be last in the - * list of supported options in CMD->def->opts. - */ -const vshCmdOpt * -vshCommandOptArgv(vshControl *ctl ATTRIBUTE_UNUSED, const vshCmd *cmd, - const vshCmdOpt *opt) -{ - opt = opt ? opt->next : cmd->opts; - - while (opt) { - if (opt->def->type == VSH_OT_ARGV) - return opt; - opt = opt->next; - } - return NULL; -} - -/* - * vshCommandOptTimeoutToMs: - * @ctl virsh control structure - * @cmd command reference - * @timeout result - * - * Parse an optional --timeout parameter in seconds, but store the - * value of the timeout in milliseconds. - * See vshCommandOptInt() - */ -int -vshCommandOptTimeoutToMs(vshControl *ctl, const vshCmd *cmd, int *timeout) -{ - int ret; - unsigned int utimeout; - - if ((ret = vshCommandOptUInt(ctl, cmd, "timeout", &utimeout)) <= 0) - return ret; - - /* Ensure that the timeout is not zero and that we can convert - * it from seconds to milliseconds without overflowing. */ - if (utimeout == 0 || utimeout > INT_MAX / 1000) { - vshError(ctl, - _("Numeric value '%u' for <%s> option is malformed or out of range"), - utimeout, - "timeout"); - ret = -1; - } else { - *timeout = ((int) utimeout) * 1000; - } - - return ret; -} - -static bool -vshConnectionUsability(vshControl *ctl, virConnectPtr conn) -{ - if (!conn || - virConnectIsAlive(conn) == 0) { - vshError(ctl, "%s", _("no valid connection")); - return false; - } - - /* The connection is considered dead only if - * virConnectIsAlive() successfuly says so. - */ - vshResetLibvirtError(); - - return true; -} - -/* - * Executes command(s) and returns return code from last command - */ -static bool -vshCommandRun(vshControl *ctl, const vshCmd *cmd) -{ - bool ret = true; - - while (cmd) { - struct timeval before, after; - bool enable_timing = ctl->timing; - - if ((ctl->conn == NULL || disconnected) && - !(cmd->def->flags & VSH_CMD_FLAG_NOCONNECT)) - vshReconnect(ctl); - - if (enable_timing) - GETTIMEOFDAY(&before); - - if ((cmd->def->flags & VSH_CMD_FLAG_NOCONNECT) || - vshConnectionUsability(ctl, ctl->conn)) { - ret = cmd->def->handler(ctl, cmd); - } else { - /* connection is not usable, return error */ - ret = false; - } - - if (enable_timing) - GETTIMEOFDAY(&after); - - /* try to automatically catch disconnections */ - if (!ret && - ((last_error != NULL) && - (((last_error->code == VIR_ERR_SYSTEM_ERROR) && - (last_error->domain == VIR_FROM_REMOTE)) || - (last_error->code == VIR_ERR_RPC) || - (last_error->code == VIR_ERR_NO_CONNECT) || - (last_error->code == VIR_ERR_INVALID_CONN)))) - disconnected++; - - if (!ret) - vshReportError(ctl); - - if (STREQ(cmd->def->name, "quit") || - STREQ(cmd->def->name, "exit")) /* hack ... */ - return ret; - - if (enable_timing) { - double diff_ms = (((after.tv_sec - before.tv_sec) * 1000.0) + - ((after.tv_usec - before.tv_usec) / 1000.0)); - - vshPrint(ctl, _("\n(Time: %.3f ms)\n\n"), diff_ms); - } else { - vshPrintExtra(ctl, "\n"); - } - cmd = cmd->next; - } - return ret; -} - -/* --------------- - * Command parsing - * --------------- - */ - -typedef enum { - VSH_TK_ERROR, /* Failed to parse a token */ - VSH_TK_ARG, /* Arbitrary argument, might be option or empty */ - VSH_TK_SUBCMD_END, /* Separation between commands */ - VSH_TK_END /* No more commands */ -} vshCommandToken; - -typedef struct _vshCommandParser vshCommandParser; -struct _vshCommandParser { - vshCommandToken(*getNextArg)(vshControl *, vshCommandParser *, - char **); - /* vshCommandStringGetArg() */ - char *pos; - /* vshCommandArgvGetArg() */ - char **arg_pos; - char **arg_end; -}; - -static bool -vshCommandParse(vshControl *ctl, vshCommandParser *parser) -{ - char *tkdata = NULL; - vshCmd *clast = NULL; - vshCmdOpt *first = NULL; - - if (ctl->cmd) { - vshCommandFree(ctl->cmd); - ctl->cmd = NULL; - } - - while (1) { - vshCmdOpt *last = NULL; - const vshCmdDef *cmd = NULL; - vshCommandToken tk; - bool data_only = false; - uint32_t opts_need_arg = 0; - uint32_t opts_required = 0; - uint32_t opts_seen = 0; - - first = NULL; - - while (1) { - const vshCmdOptDef *opt = NULL; - - tkdata = NULL; - tk = parser->getNextArg(ctl, parser, &tkdata); - - if (tk == VSH_TK_ERROR) - goto syntaxError; - if (tk != VSH_TK_ARG) { - VIR_FREE(tkdata); - break; - } - - if (cmd == NULL) { - /* first token must be command name */ - if (!(cmd = vshCmddefSearch(tkdata))) { - vshError(ctl, _("unknown command: '%s'"), tkdata); - goto syntaxError; /* ... or ignore this command only? */ - } - if (vshCmddefOptParse(cmd, &opts_need_arg, - &opts_required) < 0) { - vshError(ctl, - _("internal error: bad options in command: '%s'"), - tkdata); - goto syntaxError; - } - VIR_FREE(tkdata); - } else if (data_only) { - goto get_data; - } else if (tkdata[0] == '-' && tkdata[1] == '-' && - c_isalnum(tkdata[2])) { - char *optstr = strchr(tkdata + 2, '='); - int opt_index = 0; - - if (optstr) { - *optstr = '\0'; /* convert the '=' to '\0' */ - optstr = vshStrdup(ctl, optstr + 1); - } - /* Special case 'help' to ignore all spurious options */ - if (!(opt = vshCmddefGetOption(ctl, cmd, tkdata + 2, - &opts_seen, &opt_index, - &optstr))) { - VIR_FREE(optstr); - if (STREQ(cmd->name, "help")) - continue; - goto syntaxError; - } - VIR_FREE(tkdata); - - if (opt->type != VSH_OT_BOOL) { - /* option data */ - if (optstr) - tkdata = optstr; - else - tk = parser->getNextArg(ctl, parser, &tkdata); - if (tk == VSH_TK_ERROR) - goto syntaxError; - if (tk != VSH_TK_ARG) { - vshError(ctl, - _("expected syntax: --%s <%s>"), - opt->name, - opt->type == - VSH_OT_INT ? _("number") : _("string")); - goto syntaxError; - } - if (opt->type != VSH_OT_ARGV) - opts_need_arg &= ~(1 << opt_index); - } else { - tkdata = NULL; - if (optstr) { - vshError(ctl, _("invalid '=' after option --%s"), - opt->name); - VIR_FREE(optstr); - goto syntaxError; - } - } - } else if (tkdata[0] == '-' && tkdata[1] == '-' && - tkdata[2] == '\0') { - data_only = true; - continue; - } else { - get_data: - /* Special case 'help' to ignore spurious data */ - if (!(opt = vshCmddefGetData(cmd, &opts_need_arg, - &opts_seen)) && - STRNEQ(cmd->name, "help")) { - vshError(ctl, _("unexpected data '%s'"), tkdata); - goto syntaxError; - } - } - if (opt) { - /* save option */ - vshCmdOpt *arg = vshMalloc(ctl, sizeof(vshCmdOpt)); - - arg->def = opt; - arg->data = tkdata; - arg->next = NULL; - tkdata = NULL; - - if (!first) - first = arg; - if (last) - last->next = arg; - last = arg; - - vshDebug(ctl, VSH_ERR_INFO, "%s: %s(%s): %s\n", - cmd->name, - opt->name, - opt->type != VSH_OT_BOOL ? _("optdata") : _("bool"), - opt->type != VSH_OT_BOOL ? arg->data : _("(none)")); - } - } - - /* command parsed -- allocate new struct for the command */ - if (cmd) { - vshCmd *c = vshMalloc(ctl, sizeof(vshCmd)); - vshCmdOpt *tmpopt = first; - - /* if we encountered --help, replace parsed command with - * 'help <cmdname>' */ - for (tmpopt = first; tmpopt; tmpopt = tmpopt->next) { - if (STRNEQ(tmpopt->def->name, "help")) - continue; - - vshCommandOptFree(first); - first = vshMalloc(ctl, sizeof(vshCmdOpt)); - first->def = &(opts_help[0]); - first->data = vshStrdup(ctl, cmd->name); - first->next = NULL; - - cmd = vshCmddefSearch("help"); - opts_required = 0; - opts_seen = 0; - break; - } - - c->opts = first; - c->def = cmd; - c->next = NULL; - - if (vshCommandCheckOpts(ctl, c, opts_required, opts_seen) < 0) { - VIR_FREE(c); - goto syntaxError; - } - - if (!ctl->cmd) - ctl->cmd = c; - if (clast) - clast->next = c; - clast = c; - } - - if (tk == VSH_TK_END) - break; - } - - return true; - - syntaxError: - if (ctl->cmd) { - vshCommandFree(ctl->cmd); - ctl->cmd = NULL; - } - if (first) - vshCommandOptFree(first); - VIR_FREE(tkdata); - return false; -} - -/* -------------------- - * Command argv parsing - * -------------------- - */ - -static vshCommandToken ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) -vshCommandArgvGetArg(vshControl *ctl, vshCommandParser *parser, char **res) -{ - if (parser->arg_pos == parser->arg_end) { - *res = NULL; - return VSH_TK_END; - } - - *res = vshStrdup(ctl, *parser->arg_pos); - parser->arg_pos++; - return VSH_TK_ARG; -} - -static bool -vshCommandArgvParse(vshControl *ctl, int nargs, char **argv) -{ - vshCommandParser parser; - - if (nargs <= 0) - return false; - - parser.arg_pos = argv; - parser.arg_end = argv + nargs; - parser.getNextArg = vshCommandArgvGetArg; - return vshCommandParse(ctl, &parser); -} - -/* ---------------------- - * Command string parsing - * ---------------------- - */ - -static vshCommandToken ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) -vshCommandStringGetArg(vshControl *ctl, vshCommandParser *parser, char **res) -{ - bool single_quote = false; - bool double_quote = false; - int sz = 0; - char *p = parser->pos; - char *q = vshStrdup(ctl, p); - - *res = q; - - while (*p && (*p == ' ' || *p == '\t')) - p++; - - if (*p == '\0') - return VSH_TK_END; - if (*p == ';') { - parser->pos = ++p; /* = \0 or begin of next command */ - return VSH_TK_SUBCMD_END; - } - - while (*p) { - /* end of token is blank space or ';' */ - if (!double_quote && !single_quote && - (*p == ' ' || *p == '\t' || *p == ';')) - break; - - if (!double_quote && *p == '\'') { /* single quote */ - single_quote = !single_quote; - p++; - continue; - } else if (!single_quote && *p == '\\') { /* escape */ - /* - * The same as the bash, a \ in "" is an escaper, - * but a \ in '' is not an escaper. - */ - p++; - if (*p == '\0') { - vshError(ctl, "%s", _("dangling \\")); - return VSH_TK_ERROR; - } - } else if (!single_quote && *p == '"') { /* double quote */ - double_quote = !double_quote; - p++; - continue; - } - - *q++ = *p++; - sz++; - } - if (double_quote) { - vshError(ctl, "%s", _("missing \"")); - return VSH_TK_ERROR; - } - - *q = '\0'; - parser->pos = p; - return VSH_TK_ARG; -} - -static bool -vshCommandStringParse(vshControl *ctl, char *cmdstr) -{ - vshCommandParser parser; - - if (cmdstr == NULL || *cmdstr == '\0') - return false; - - parser.pos = cmdstr; - parser.getNextArg = vshCommandStringGetArg; - return vshCommandParse(ctl, &parser); -} - -/* --------------- - * Misc utils - * --------------- - */ -int -vshDomainState(vshControl *ctl, virDomainPtr dom, int *reason) -{ - virDomainInfo info; - - if (reason) - *reason = -1; - - if (!ctl->useGetInfo) { - int state; - if (virDomainGetState(dom, &state, reason, 0) < 0) { - virErrorPtr err = virGetLastError(); - if (err && err->code == VIR_ERR_NO_SUPPORT) - ctl->useGetInfo = true; - else - return -1; - } else { - return state; - } - } - - /* fall back to virDomainGetInfo if virDomainGetState is not supported */ - if (virDomainGetInfo(dom, &info) < 0) - return -1; - else - return info.state; -} - -/* Return a non-NULL string representation of a typed parameter; exit - * if we are out of memory. */ -char * -vshGetTypedParamValue(vshControl *ctl, virTypedParameterPtr item) -{ - int ret = 0; - char *str = NULL; - - switch (item->type) { - case VIR_TYPED_PARAM_INT: - ret = virAsprintf(&str, "%d", item->value.i); - break; - - case VIR_TYPED_PARAM_UINT: - ret = virAsprintf(&str, "%u", item->value.ui); - break; - - case VIR_TYPED_PARAM_LLONG: - ret = virAsprintf(&str, "%lld", item->value.l); - break; - - case VIR_TYPED_PARAM_ULLONG: - ret = virAsprintf(&str, "%llu", item->value.ul); - break; - - case VIR_TYPED_PARAM_DOUBLE: - ret = virAsprintf(&str, "%f", item->value.d); - break; - - case VIR_TYPED_PARAM_BOOLEAN: - str = vshStrdup(ctl, item->value.b ? _("yes") : _("no")); - break; - - case VIR_TYPED_PARAM_STRING: - str = vshStrdup(ctl, item->value.s); - break; - - default: - vshError(ctl, _("unimplemented parameter type %d"), item->type); - } - - if (ret < 0) { - vshError(ctl, "%s", _("Out of memory")); - exit(EXIT_FAILURE); - } - return str; -} - -void -vshDebug(vshControl *ctl, int level, const char *format, ...) -{ - va_list ap; - char *str; - - /* Aligning log levels to that of libvirt. - * Traces with levels >= user-specified-level - * gets logged into file - */ - if (level < ctl->debug) - return; - - va_start(ap, format); - vshOutputLogFile(ctl, level, format, ap); - va_end(ap); - - va_start(ap, format); - if (virVasprintf(&str, format, ap) < 0) { - /* Skip debug messages on low memory */ - va_end(ap); - return; - } - va_end(ap); - fputs(str, stdout); - VIR_FREE(str); -} - -void -vshPrintExtra(vshControl *ctl, const char *format, ...) -{ - va_list ap; - char *str; - - if (ctl && ctl->quiet) - return; - - va_start(ap, format); - if (virVasprintf(&str, format, ap) < 0) { - vshError(ctl, "%s", _("Out of memory")); - va_end(ap); - return; - } - va_end(ap); - fputs(str, stdout); - VIR_FREE(str); -} - - -bool -vshTTYIsInterruptCharacter(vshControl *ctl ATTRIBUTE_UNUSED, - const char chr ATTRIBUTE_UNUSED) -{ -#ifndef WIN32 - if (ctl->istty && - ctl->termattr.c_cc[VINTR] == chr) - return true; -#endif - - return false; -} - - -bool -vshTTYAvailable(vshControl *ctl) -{ - return ctl->istty; -} - - -int -vshTTYDisableInterrupt(vshControl *ctl ATTRIBUTE_UNUSED) -{ -#ifndef WIN32 - struct termios termset = ctl->termattr; - - if (!ctl->istty) - return -1; - - /* check if we need to set the terminal */ - if (termset.c_cc[VINTR] == _POSIX_VDISABLE) - return 0; - - termset.c_cc[VINTR] = _POSIX_VDISABLE; - termset.c_lflag &= ~ICANON; - - if (tcsetattr(STDIN_FILENO, TCSANOW, &termset) < 0) - return -1; -#endif - - return 0; -} - - -int -vshTTYRestore(vshControl *ctl ATTRIBUTE_UNUSED) -{ -#ifndef WIN32 - if (!ctl->istty) - return 0; - - if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &ctl->termattr) < 0) - return -1; -#endif - - return 0; -} - - -#if !defined(WIN32) && !defined(HAVE_CFMAKERAW) -/* provide fallback in case cfmakeraw isn't available */ -static void -cfmakeraw(struct termios *attr) -{ - attr->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP - | INLCR | IGNCR | ICRNL | IXON); - attr->c_oflag &= ~OPOST; - attr->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); - attr->c_cflag &= ~(CSIZE | PARENB); - attr->c_cflag |= CS8; -} -#endif /* !WIN32 && !HAVE_CFMAKERAW */ - - -int -vshTTYMakeRaw(vshControl *ctl ATTRIBUTE_UNUSED, - bool report_errors ATTRIBUTE_UNUSED) -{ -#ifndef WIN32 - struct termios rawattr = ctl->termattr; - char ebuf[1024]; - - if (!ctl->istty) { - if (report_errors) { - vshError(ctl, "%s", - _("unable to make terminal raw: console isn't a tty")); - } - - return -1; - } - - cfmakeraw(&rawattr); - - if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &rawattr) < 0) { - if (report_errors) - vshError(ctl, _("unable to set tty attributes: %s"), - virStrerror(errno, ebuf, sizeof(ebuf))); - return -1; - } -#endif - - return 0; -} - - -void -vshError(vshControl *ctl, const char *format, ...) -{ - va_list ap; - char *str; - - if (ctl != NULL) { - va_start(ap, format); - vshOutputLogFile(ctl, VSH_ERR_ERROR, format, ap); - va_end(ap); - } - - /* Most output is to stdout, but if someone ran virsh 2>&1, then - * printing to stderr will not interleave correctly with stdout - * unless we flush between every transition between streams. */ - fflush(stdout); - fputs(_("error: "), stderr); - - va_start(ap, format); - /* We can't recursively call vshError on an OOM situation, so ignore - failure here. */ - ignore_value(virVasprintf(&str, format, ap)); - va_end(ap); - - fprintf(stderr, "%s\n", NULLSTR(str)); - fflush(stderr); - VIR_FREE(str); -} - - -static void -vshEventLoop(void *opaque) -{ - vshControl *ctl = opaque; - - while (1) { - bool quit; - virMutexLock(&ctl->lock); - quit = ctl->quit; - virMutexUnlock(&ctl->lock); - - if (quit) - break; - - if (virEventRunDefaultImpl() < 0) - vshReportError(ctl); - } -} - - -/* - * Helpers for waiting for a libvirt event. - */ - -/* We want to use SIGINT to cancel a wait; but as signal handlers - * don't have an opaque argument, we have to use static storage. */ -static int vshEventFd = -1; -static struct sigaction vshEventOldAction; - - -/* Signal handler installed in vshEventStart, removed in vshEventCleanup. */ -static void -vshEventInt(int sig ATTRIBUTE_UNUSED, - siginfo_t *siginfo ATTRIBUTE_UNUSED, - void *context ATTRIBUTE_UNUSED) -{ - char reason = VSH_EVENT_INTERRUPT; - if (vshEventFd >= 0) - ignore_value(safewrite(vshEventFd, &reason, 1)); -} - - -/* Event loop handler used to limit length of waiting for any other event. */ -static void -vshEventTimeout(int timer ATTRIBUTE_UNUSED, - void *opaque) -{ - vshControl *ctl = opaque; - char reason = VSH_EVENT_TIMEOUT; - - if (ctl->eventPipe[1] >= 0) - ignore_value(safewrite(ctl->eventPipe[1], &reason, 1)); -} - - -/** - * vshEventStart: - * @ctl virsh command struct - * @timeout_ms max wait time in milliseconds, or 0 for indefinite - * - * Set up a wait for a libvirt event. The wait can be canceled by - * SIGINT or by calling vshEventDone() in your event handler. If - * @timeout_ms is positive, the wait will also end if the timeout - * expires. Call vshEventWait() to block the main thread (the event - * handler runs in the event loop thread). When done (including if - * there was an error registering for an event), use vshEventCleanup() - * to quit waiting. Returns 0 on success, -1 on failure. */ -int -vshEventStart(vshControl *ctl, int timeout_ms) -{ - struct sigaction action; - - assert(ctl->eventPipe[0] == -1 && ctl->eventPipe[1] == -1 && - vshEventFd == -1 && ctl->eventTimerId >= 0); - if (pipe2(ctl->eventPipe, O_CLOEXEC) < 0) { - char ebuf[1024]; - - vshError(ctl, _("failed to create pipe: %s"), - virStrerror(errno, ebuf, sizeof(ebuf))); - return -1; - } - vshEventFd = ctl->eventPipe[1]; - - action.sa_sigaction = vshEventInt; - action.sa_flags = SA_SIGINFO; - sigemptyset(&action.sa_mask); - sigaction(SIGINT, &action, &vshEventOldAction); - - if (timeout_ms) - virEventUpdateTimeout(ctl->eventTimerId, timeout_ms); - - return 0; -} - - -/** - * vshEventDone: - * @ctl virsh command struct - * - * Call this from an event callback to let the main thread quit - * blocking on further events. - */ -void -vshEventDone(vshControl *ctl) -{ - char reason = VSH_EVENT_DONE; - - if (ctl->eventPipe[1] >= 0) - ignore_value(safewrite(ctl->eventPipe[1], &reason, 1)); -} - - -/** - * vshEventWait: - * @ctl virsh command struct - * - * Call this in the main thread after calling vshEventStart() then - * registering for one or more events. This call will block until - * SIGINT, the timeout registered at the start, or until one of your - * event handlers calls vshEventDone(). Returns an enum VSH_EVENT_* - * stating how the wait concluded, or -1 on error. - */ -int -vshEventWait(vshControl *ctl) -{ - char buf; - int rv; - - assert(ctl->eventPipe[0] >= 0); - while ((rv = read(ctl->eventPipe[0], &buf, 1)) < 0 && errno == EINTR); - if (rv != 1) { - char ebuf[1024]; - - if (!rv) - errno = EPIPE; - vshError(ctl, _("failed to determine loop exit status: %s"), - virStrerror(errno, ebuf, sizeof(ebuf))); - return -1; - } - return buf; -} - - -/** - * vshEventCleanup: - * @ctl virsh command struct - * - * Call at the end of any function that has used vshEventStart(), to - * tear down any remaining SIGINT or timeout handlers. - */ -void -vshEventCleanup(vshControl *ctl) -{ - if (vshEventFd >= 0) { - sigaction(SIGINT, &vshEventOldAction, NULL); - vshEventFd = -1; - } - VIR_FORCE_CLOSE(ctl->eventPipe[0]); - VIR_FORCE_CLOSE(ctl->eventPipe[1]); - virEventUpdateTimeout(ctl->eventTimerId, -1); -} - - -/* - * Initialize debug settings. - */ -static void -vshInitDebug(vshControl *ctl) -{ - const char *debugEnv; - - if (ctl->debug == VSH_DEBUG_DEFAULT) { - /* log level not set from commandline, check env variable */ - debugEnv = virGetEnvAllowSUID("VIRSH_DEBUG"); - if (debugEnv) { - int debug; - if (virStrToLong_i(debugEnv, NULL, 10, &debug) < 0 || - debug < VSH_ERR_DEBUG || debug > VSH_ERR_ERROR) { - vshError(ctl, "%s", - _("VIRSH_DEBUG not set with a valid numeric value")); - } else { - ctl->debug = debug; - } - } - } - - if (ctl->logfile == NULL) { - /* log file not set from cmdline */ - debugEnv = virGetEnvBlockSUID("VIRSH_LOG_FILE"); - if (debugEnv && *debugEnv) { - ctl->logfile = vshStrdup(ctl, debugEnv); - vshOpenLogFile(ctl); - } - } -} - -/* - * Initialize connection. - */ -static bool -vshInit(vshControl *ctl) -{ - /* Since we have the commandline arguments parsed, we need to - * re-initialize all the debugging to make it work properly */ - vshInitDebug(ctl); - - if (ctl->conn) - return false; - - /* set up the library error handler */ - virSetErrorFunc(NULL, virshErrorHandler); - - if (virEventRegisterDefaultImpl() < 0) - return false; - - if (virThreadCreate(&ctl->eventLoop, true, vshEventLoop, ctl) < 0) - return false; - ctl->eventLoopStarted = true; - - if ((ctl->eventTimerId = virEventAddTimeout(-1, vshEventTimeout, ctl, - NULL)) < 0) - return false; - - if (ctl->name) { - vshReconnect(ctl); - /* Connecting to a named connection must succeed, but we delay - * connecting to the default connection until we need it - * (since the first command might be 'connect' which allows a - * non-default connection, or might be 'help' which needs no - * connection). - */ - if (!ctl->conn) { - vshReportError(ctl); - return false; - } - } - - return true; -} - -#define LOGFILE_FLAGS (O_WRONLY | O_APPEND | O_CREAT | O_SYNC) - -/** - * vshOpenLogFile: - * - * Open log file. - */ -void -vshOpenLogFile(vshControl *ctl) -{ - if (ctl->logfile == NULL) - return; - - if ((ctl->log_fd = open(ctl->logfile, LOGFILE_FLAGS, FILE_MODE)) < 0) { - vshError(ctl, "%s", - _("failed to open the log file. check the log file path")); - exit(EXIT_FAILURE); - } -} - -/** - * vshOutputLogFile: - * - * Outputting an error to log file. - */ -void -vshOutputLogFile(vshControl *ctl, int log_level, const char *msg_format, - va_list ap) -{ - virBuffer buf = VIR_BUFFER_INITIALIZER; - char *str = NULL; - size_t len; - const char *lvl = ""; - time_t stTime; - struct tm stTm; - - if (ctl->log_fd == -1) - return; - - /** - * create log format - * - * [YYYY.MM.DD HH:MM:SS SIGNATURE PID] LOG_LEVEL message - */ - time(&stTime); - localtime_r(&stTime, &stTm); - virBufferAsprintf(&buf, "[%d.%02d.%02d %02d:%02d:%02d %s %d] ", - (1900 + stTm.tm_year), - (1 + stTm.tm_mon), - stTm.tm_mday, - stTm.tm_hour, - stTm.tm_min, - stTm.tm_sec, - SIGN_NAME, - (int) getpid()); - switch (log_level) { - case VSH_ERR_DEBUG: - lvl = LVL_DEBUG; - break; - case VSH_ERR_INFO: - lvl = LVL_INFO; - break; - case VSH_ERR_NOTICE: - lvl = LVL_INFO; - break; - case VSH_ERR_WARNING: - lvl = LVL_WARNING; - break; - case VSH_ERR_ERROR: - lvl = LVL_ERROR; - break; - default: - lvl = LVL_DEBUG; - break; - } - virBufferAsprintf(&buf, "%s ", lvl); - virBufferVasprintf(&buf, msg_format, ap); - virBufferAddChar(&buf, '\n'); - - if (virBufferError(&buf)) - goto error; - - str = virBufferContentAndReset(&buf); - len = strlen(str); - if (len > 1 && str[len - 2] == '\n') { - str[len - 1] = '\0'; - len--; - } - - /* write log */ - if (safewrite(ctl->log_fd, str, len) < 0) - goto error; - - VIR_FREE(str); - return; - - error: - vshCloseLogFile(ctl); - vshError(ctl, "%s", _("failed to write the log file")); - virBufferFreeAndReset(&buf); - VIR_FREE(str); -} - -/** - * vshCloseLogFile: - * - * Close log file. - */ -void -vshCloseLogFile(vshControl *ctl) -{ - char ebuf[1024]; - - /* log file close */ - if (VIR_CLOSE(ctl->log_fd) < 0) { - vshError(ctl, _("%s: failed to write log file: %s"), - ctl->logfile ? ctl->logfile : "?", - virStrerror(errno, ebuf, sizeof(ebuf))); - } - - if (ctl->logfile) { - VIR_FREE(ctl->logfile); - ctl->logfile = NULL; - } -} - -#if WITH_READLINE - -/* ----------------- - * Readline stuff - * ----------------- - */ - -/* - * Generator function for command completion. STATE lets us - * know whether to start from scratch; without any state - * (i.e. STATE == 0), then we start at the top of the list. - */ -static char * -vshReadlineCommandGenerator(const char *text, int state) -{ - static int grp_list_index, cmd_list_index, len; - const char *name; - const vshCmdGrp *grp; - const vshCmdDef *cmds; - - if (!state) { - grp_list_index = 0; - cmd_list_index = 0; - len = strlen(text); - } - - grp = cmdGroups; - - /* Return the next name which partially matches from the - * command list. - */ - while (grp[grp_list_index].name) { - cmds = grp[grp_list_index].commands; - - if (cmds[cmd_list_index].name) { - while ((name = cmds[cmd_list_index].name)) { - cmd_list_index++; - - if (STREQLEN(name, text, len)) - return vshStrdup(NULL, name); - } - } else { - cmd_list_index = 0; - grp_list_index++; - } - } - - /* If no names matched, then return NULL. */ - return NULL; -} - -static char * -vshReadlineOptionsGenerator(const char *text, int state) -{ - static int list_index, len; - static const vshCmdDef *cmd; - const char *name; - - if (!state) { - /* determine command name */ - char *p; - char *cmdname; - - if (!(p = strchr(rl_line_buffer, ' '))) - return NULL; - - cmdname = vshCalloc(NULL, (p - rl_line_buffer) + 1, 1); - memcpy(cmdname, rl_line_buffer, p - rl_line_buffer); - - cmd = vshCmddefSearch(cmdname); - list_index = 0; - len = strlen(text); - VIR_FREE(cmdname); - } - - if (!cmd) - return NULL; - - if (!cmd->opts) - return NULL; - - while ((name = cmd->opts[list_index].name)) { - const vshCmdOptDef *opt = &cmd->opts[list_index]; - char *res; - - list_index++; - - if (opt->type == VSH_OT_DATA || opt->type == VSH_OT_ARGV) - /* ignore non --option */ - continue; - - if (len > 2) { - if (STRNEQLEN(name, text + 2, len - 2)) - continue; - } - res = vshMalloc(NULL, strlen(name) + 3); - snprintf(res, strlen(name) + 3, "--%s", name); - return res; - } - - /* If no names matched, then return NULL. */ - return NULL; -} - -static char ** -vshReadlineCompletion(const char *text, int start, - int end ATTRIBUTE_UNUSED) -{ - char **matches = (char **) NULL; - - if (start == 0) - /* command name generator */ - matches = rl_completion_matches(text, vshReadlineCommandGenerator); - else - /* commands options */ - matches = rl_completion_matches(text, vshReadlineOptionsGenerator); - return matches; -} - -# define VIRSH_HISTSIZE_MAX 500000 - -static int -vshReadlineInit(vshControl *ctl) -{ - char *userdir = NULL; - int max_history = 500; - const char *histsize_str; - - /* Allow conditional parsing of the ~/.inputrc file. - * Work around ancient readline 4.1 (hello Mac OS X), - * which declared it as 'char *' instead of 'const char *'. - */ - rl_readline_name = (char *) "virsh"; - - /* Tell the completer that we want a crack first. */ - rl_attempted_completion_function = vshReadlineCompletion; - - /* Limit the total size of the history buffer */ - if ((histsize_str = virGetEnvBlockSUID("VIRSH_HISTSIZE"))) { - if (virStrToLong_i(histsize_str, NULL, 10, &max_history) < 0) { - vshError(ctl, "%s", _("Bad $VIRSH_HISTSIZE value.")); - VIR_FREE(userdir); - return -1; - } else if (max_history > VIRSH_HISTSIZE_MAX || max_history < 0) { - vshError(ctl, _("$VIRSH_HISTSIZE value should be between 0 and %d"), - VIRSH_HISTSIZE_MAX); - VIR_FREE(userdir); - return -1; - } - } - stifle_history(max_history); - - /* Prepare to read/write history from/to the $XDG_CACHE_HOME/virsh/history file */ - userdir = virGetUserCacheDirectory(); - - if (userdir == NULL) { - vshError(ctl, "%s", _("Could not determine home directory")); - return -1; - } - - if (virAsprintf(&ctl->historydir, "%s/virsh", userdir) < 0) { - vshError(ctl, "%s", _("Out of memory")); - VIR_FREE(userdir); - return -1; - } - - if (virAsprintf(&ctl->historyfile, "%s/history", ctl->historydir) < 0) { - vshError(ctl, "%s", _("Out of memory")); - VIR_FREE(userdir); - return -1; - } - - VIR_FREE(userdir); - - read_history(ctl->historyfile); - - return 0; -} - -static void -vshReadlineDeinit(vshControl *ctl) -{ - if (ctl->historyfile != NULL) { - if (virFileMakePathWithMode(ctl->historydir, 0755) < 0 && - errno != EEXIST) { - char ebuf[1024]; - vshError(ctl, _("Failed to create '%s': %s"), - ctl->historydir, virStrerror(errno, ebuf, sizeof(ebuf))); - } else { - write_history(ctl->historyfile); - } - } - - VIR_FREE(ctl->historydir); - VIR_FREE(ctl->historyfile); -} - -static char * -vshReadline(vshControl *ctl ATTRIBUTE_UNUSED, const char *prompt) -{ - return readline(prompt); -} - -#else /* !WITH_READLINE */ - -static int -vshReadlineInit(vshControl *ctl ATTRIBUTE_UNUSED) -{ - /* empty */ - return 0; -} - -static void -vshReadlineDeinit(vshControl *ctl ATTRIBUTE_UNUSED) -{ - /* empty */ -} - -static char * -vshReadline(vshControl *ctl, const char *prompt) -{ - char line[1024]; - char *r; - int len; - - fputs(prompt, stdout); - r = fgets(line, sizeof(line), stdin); - if (r == NULL) return NULL; /* EOF */ - - /* Chomp trailing \n */ - len = strlen(r); - if (len > 0 && r[len-1] == '\n') - r[len-1] = '\0'; - - return vshStrdup(ctl, r); -} - -#endif /* !WITH_READLINE */ - -static void -vshDeinitTimer(int timer ATTRIBUTE_UNUSED, void *opaque ATTRIBUTE_UNUSED) -{ - /* nothing to be done here */ -} - -/* - * Deinitialize virsh - */ -static bool -vshDeinit(vshControl *ctl) -{ - vshReadlineDeinit(ctl); - vshCloseLogFile(ctl); - VIR_FREE(ctl->name); - if (ctl->conn) { - int ret; - virConnectUnregisterCloseCallback(ctl->conn, vshCatchDisconnect); - ret = virConnectClose(ctl->conn); - if (ret < 0) - vshError(ctl, "%s", _("Failed to disconnect from the hypervisor")); - else if (ret > 0) - vshError(ctl, "%s", _("One or more references were leaked after " - "disconnect from the hypervisor")); - } - virResetLastError(); - - if (ctl->eventLoopStarted) { - int timer; - - virMutexLock(&ctl->lock); - ctl->quit = true; - /* HACK: Add a dummy timeout to break event loop */ - timer = virEventAddTimeout(0, virshDeinitTimer, NULL, NULL); - virMutexUnlock(&ctl->lock); - - virThreadJoin(&ctl->eventLoop); - - if (timer != -1) - virEventRemoveTimeout(timer); - - if (ctl->eventTimerId != -1) - virEventRemoveTimeout(ctl->eventTimerId); - - ctl->eventLoopStarted = false; - } - - virMutexDestroy(&ctl->lock); - - return true; -} - -/* - * Print usage - */ -static void -virshUsage(void) -{ - const vshCmdGrp *grp; - const vshCmdDef *cmd; - - fprintf(stdout, _("\n%s [options]... [<command_string>]" - "\n%s [options]... <command> [args...]\n\n" - " options:\n" - " -c | --connect=URI hypervisor connection URI\n" - " -d | --debug=NUM debug level [0-4]\n" - " -e | --escape <char> set escape sequence for console\n" - " -h | --help this help\n" - " -k | --keepalive-interval=NUM\n" - " keepalive interval in seconds, 0 for disable\n" - " -K | --keepalive-count=NUM\n" - " number of possible missed keepalive messages\n" - " -l | --log=FILE output logging to file\n" - " -q | --quiet quiet mode\n" - " -r | --readonly connect readonly\n" - " -t | --timing print timing information\n" - " -v short version\n" - " -V long version\n" - " --version[=TYPE] version, TYPE is short or long (default short)\n" - " commands (non interactive mode):\n\n"), progname, progname); + fprintf(stdout, _("\n%s [options]... [<command_string>]" + "\n%s [options]... <command> [args...]\n\n" + " options:\n" + " -c | --connect=URI hypervisor connection URI\n" + " -d | --debug=NUM debug level [0-4]\n" + " -e | --escape <char> set escape sequence for console\n" + " -h | --help this help\n" + " -k | --keepalive-interval=NUM\n" + " keepalive interval in seconds, 0 for disable\n" + " -K | --keepalive-count=NUM\n" + " number of possible missed keepalive messages\n" + " -l | --log=FILE output logging to file\n" + " -q | --quiet quiet mode\n" + " -r | --readonly connect readonly\n" + " -t | --timing print timing information\n" + " -v short version\n" + " -V long version\n" + " --version[=TYPE] version, TYPE is short or long (default short)\n" + " commands (non interactive mode):\n\n"), progname, + progname); for (grp = cmdGroups; grp->name; grp++) { fprintf(stdout, _(" %s (help keyword '%s')\n"), @@ -3641,15 +1529,11 @@ main(int argc, char **argv) virFileActivateDirOverride(argv[0]); - if (!(progname = strrchr(argv[0], '/'))) - progname = argv[0]; - else - progname++; - if ((defaultConn = virGetEnvBlockSUID("VIRSH_DEFAULT_CONNECT_URI"))) ctl->name = vshStrdup(ctl, defaultConn); - vshInitDebug(ctl); + if (vshInit(ctl, &hooks, cmdGroups) < 0) + exit(EXIT_FAILURE); if (!virshParseArgv(ctl, argc, argv) || !virshInit(ctl)) { @@ -3676,7 +1560,8 @@ main(int argc, char **argv) } do { - const char *prompt = ctl->readonly ? VSH_PROMPT_RO : VSH_PROMPT_RW; + const char *prompt = virshCtl.readonly ? VIRSH_PROMPT_RO + : VIRSH_PROMPT_RW; ctl->cmdstr = vshReadline(ctl, prompt); if (ctl->cmdstr == NULL) diff --git a/tools/virsh.h b/tools/virsh.h index 945eb23..15a938e 100644 --- a/tools/virsh.h +++ b/tools/virsh.h @@ -44,141 +44,9 @@ # define VIR_FROM_THIS VIR_FROM_NONE -# define GETTIMEOFDAY(T) gettimeofday(T, NULL) - -# define VSH_MATCH(FLAG) (flags & (FLAG)) - -/** - * The log configuration - */ -# define MSG_BUFFER 4096 -# define SIGN_NAME "virsh" -# define DIR_MODE (S_IWUSR | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) /* 0755 */ -# define FILE_MODE (S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH) /* 0644 */ -# define LOCK_MODE (S_IWUSR | S_IRUSR) /* 0600 */ -# define LVL_DEBUG "DEBUG" -# define LVL_INFO "INFO" -# define LVL_NOTICE "NOTICE" -# define LVL_WARNING "WARNING" -# define LVL_ERROR "ERROR" - -/** - * vshErrorLevel: - * - * Indicates the level of a log message - */ -typedef enum { - VSH_ERR_DEBUG = 0, - VSH_ERR_INFO, - VSH_ERR_NOTICE, - VSH_ERR_WARNING, - VSH_ERR_ERROR -} vshErrorLevel; - -# define VSH_DEBUG_DEFAULT VSH_ERR_ERROR - -/* - * virsh command line grammar: - * - * command_line = <command>\n | <command>; <command>; ... - * - * command = <keyword> <option> [--] <data> - * - * option = <bool_option> | <int_option> | <string_option> - * data = <string> - * - * bool_option = --optionname - * int_option = --optionname <number> | --optionname=<number> - * string_option = --optionname <string> | --optionname=<string> - * - * keyword = [a-zA-Z][a-zA-Z-]* - * number = [0-9]+ - * string = ('[^']*'|"([^\\"]|\\.)*"|([^ \t\n\\'"]|\\.))+ - * - */ - -/* - * vshCmdOptType - command option type - */ -typedef enum { - VSH_OT_BOOL, /* optional boolean option */ - VSH_OT_STRING, /* optional string option */ - VSH_OT_INT, /* optional or mandatory int option */ - VSH_OT_DATA, /* string data (as non-option) */ - VSH_OT_ARGV, /* remaining arguments */ - VSH_OT_ALIAS, /* alternate spelling for a later argument */ -} vshCmdOptType; - /* * Command group types */ - -/* - * Command Option Flags - */ -enum { - VSH_OFLAG_NONE = 0, /* without flags */ - VSH_OFLAG_REQ = (1 << 0), /* option required */ - VSH_OFLAG_EMPTY_OK = (1 << 1), /* empty string option allowed */ - VSH_OFLAG_REQ_OPT = (1 << 2), /* --optionname required */ -}; - -/* forward declarations */ -typedef struct _vshCmd vshCmd; -typedef struct _vshCmdDef vshCmdDef; -typedef struct _vshCmdGrp vshCmdGrp; -typedef struct _vshCmdInfo vshCmdInfo; -typedef struct _vshCmdOpt vshCmdOpt; -typedef struct _vshCmdOptDef vshCmdOptDef; -typedef struct _vshControl vshControl; -typedef struct _vshCtrlData vshCtrlData; - -typedef char **(*vshCompleter)(unsigned int flags); - -/* - * vshCmdInfo -- name/value pair for information about command - * - * Commands should have at least the following names: - * "help" - short description of command - * "desc" - description of command, or empty string - */ -struct _vshCmdInfo { - const char *name; /* name of information, or NULL for list end */ - const char *data; /* non-NULL information */ -}; - -/* - * vshCmdOptDef - command option definition - */ -struct _vshCmdOptDef { - const char *name; /* the name of option, or NULL for list end */ - vshCmdOptType type; /* option type */ - unsigned int flags; /* flags */ - const char *help; /* non-NULL help string; or for VSH_OT_ALIAS - * the name of a later public option */ - vshCompleter completer; /* option completer */ - unsigned int completer_flags; /* option completer flags */ -}; - -/* - * vshCmdOpt - command options - * - * After parsing a command, all arguments to the command have been - * collected into a list of these objects. - */ -struct _vshCmdOpt { - const vshCmdOptDef *def; /* non-NULL pointer to option definition */ - char *data; /* allocated data, or NULL for bool option */ - vshCmdOpt *next; -}; - -/* - * Command Usage Flags - */ -enum { - VSH_CMD_FLAG_NOCONNECT = (1 << 0), /* no prior connection needed */ - VSH_CMD_FLAG_ALIAS = (1 << 1), /* command is an alias */ -}; # define VIRSH_CMD_GRP_DOM_MANAGEMENT "Domain Management" # define VIRSH_CMD_GRP_DOM_MONITORING "Domain Monitoring" # define VIRSH_CMD_GRP_STORAGE_POOL "Storage Pool" @@ -192,175 +60,26 @@ enum { # define VIRSH_CMD_GRP_HOST_AND_HV "Host and Hypervisor" # define VIRSH_CMD_GRP_VIRSH "Virsh itself" -/* - * vshCmdDef - command definition - */ -struct _vshCmdDef { - const char *name; /* name of command, or NULL for list end */ - bool (*handler) (vshControl *, const vshCmd *); /* command handler */ - const vshCmdOptDef *opts; /* definition of command options */ - const vshCmdInfo *info; /* details about command */ - unsigned int flags; /* bitwise OR of VSH_CMD_FLAG */ -}; -/* - * vshCmd - parsed command - */ -struct _vshCmd { - const vshCmdDef *def; /* command definition */ - vshCmdOpt *opts; /* list of command arguments */ - vshCmd *next; /* next command */ -}; /* * vshControl */ - char *name; /* connection name */ struct _virshControl { virConnectPtr conn; /* connection to hypervisor (MAY BE NULL) */ - vshCmd *cmd; /* the current command */ - char *cmdstr; /* string with command */ - bool imode; /* interactive mode? */ - bool quiet; /* quiet mode */ - int debug; /* print debug messages? */ - bool timing; /* print timing info? */ bool readonly; /* connect readonly (first time only, not * during explicit connect command) */ - char *logfile; /* log file name */ - int log_fd; /* log file descriptor */ - char *historydir; /* readline history directory name */ - char *historyfile; /* readline history file name */ bool useGetInfo; /* must use virDomainGetInfo, since virDomainGetState is not supported */ bool useSnapshotOld; /* cannot use virDomainSnapshotGetParent or virDomainSnapshotNumChildren */ bool blockJobNoBytes; /* true if _BANDWIDTH_BYTE blockjob flags are missing */ - virThread eventLoop; - virMutex lock; - bool eventLoopStarted; - bool quit; - int eventPipe[2]; /* Write-to-self pipe to end waiting for an - * event to occur */ - int eventTimerId; /* id of event loop timeout registration */ - const char *escapeChar; /* String representation of console escape character */ - - int keepalive_interval; /* Client keepalive interval */ - int keepalive_count; /* Client keepalive count */ - -# ifndef WIN32 - struct termios termattr; /* settings of the tty terminal */ -# endif - bool istty; /* is the terminal a tty */ -}; - -struct _vshCmdGrp { - const char *name; /* name of group, or NULL for list end */ - const char *keyword; /* help keyword */ - const vshCmdDef *commands; }; -void vshError(vshControl *ctl, const char *format, ...) - ATTRIBUTE_FMT_PRINTF(2, 3); -void vshOpenLogFile(vshControl *ctl); -void vshOutputLogFile(vshControl *ctl, int log_level, const char *format, - va_list ap) - ATTRIBUTE_FMT_PRINTF(3, 0); -void vshCloseLogFile(vshControl *ctl); - -virConnectPtr vshConnect(vshControl *ctl, const char *uri, bool readonly); - -const char *vshCmddefGetInfo(const vshCmdDef *cmd, const char *info); -const vshCmdDef *vshCmddefSearch(const char *cmdname); -bool vshCmddefHelp(vshControl *ctl, const char *name); -const vshCmdGrp *vshCmdGrpSearch(const char *grpname); -bool vshCmdGrpHelp(vshControl *ctl, const char *name); - -int vshCommandOptInt(vshControl *ctl, const vshCmd *cmd, - const char *name, int *value) - ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK; -int vshCommandOptUInt(vshControl *ctl, const vshCmd *cmd, - const char *name, unsigned int *value) - ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK; -int vshCommandOptUIntWrap(vshControl *ctl, const vshCmd *cmd, - const char *name, unsigned int *value) - ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK; -int vshCommandOptUL(vshControl *ctl, const vshCmd *cmd, - const char *name, unsigned long *value) - ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK; -int vshCommandOptULWrap(vshControl *ctl, const vshCmd *cmd, - const char *name, unsigned long *value) - ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK; -int vshCommandOptString(vshControl *ctl, const vshCmd *cmd, - const char *name, const char **value) - ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK; -int vshCommandOptStringReq(vshControl *ctl, const vshCmd *cmd, - const char *name, const char **value) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) - ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK; -int vshCommandOptLongLong(vshControl *ctl, const vshCmd *cmd, - const char *name, long long *value) - ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK; -int vshCommandOptULongLong(vshControl *ctl, const vshCmd *cmd, - const char *name, unsigned long long *value) - ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK; -int vshCommandOptULongLongWrap(vshControl *ctl, const vshCmd *cmd, - const char *name, unsigned long long *value) - ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK; -int vshCommandOptScaledInt(vshControl *ctl, const vshCmd *cmd, - const char *name, unsigned long long *value, - int scale, unsigned long long max) - ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK; -bool vshCommandOptBool(const vshCmd *cmd, const char *name); -const vshCmdOpt *vshCommandOptArgv(vshControl *ctl, const vshCmd *cmd, - const vshCmdOpt *opt); -int vshCommandOptTimeoutToMs(vshControl *ctl, const vshCmd *cmd, int *timeout); - -/* Filter flags for various vshCommandOpt*By() functions */ -typedef enum { - VSH_BYID = (1 << 1), - VSH_BYUUID = (1 << 2), - VSH_BYNAME = (1 << 3), - VSH_BYMAC = (1 << 4), -} vshLookupByFlags; - -/* Given an index, return either the name of that device (non-NULL) or - * of its parent (NULL if a root). */ -typedef const char * (*vshTreeLookup)(int devid, bool parent, void *opaque); -int vshTreePrint(vshControl *ctl, vshTreeLookup lookup, void *opaque, - int num_devices, int devid); - -void vshPrintExtra(vshControl *ctl, const char *format, ...) - ATTRIBUTE_FMT_PRINTF(2, 3); -void vshDebug(vshControl *ctl, int level, const char *format, ...) - ATTRIBUTE_FMT_PRINTF(3, 4); - -/* XXX: add batch support */ -# define vshPrint(_ctl, ...) vshPrintExtra(NULL, __VA_ARGS__) - -/* User visible sort, so we want locale-specific case comparison. */ -# define vshStrcasecmp(S1, S2) strcasecmp(S1, S2) -int vshNameSorter(const void *a, const void *b); - -int vshDomainState(vshControl *ctl, virDomainPtr dom, int *reason); -virTypedParameterPtr vshFindTypedParamByName(const char *name, - virTypedParameterPtr list, - int count); -char *vshGetTypedParamValue(vshControl *ctl, virTypedParameterPtr item) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); - -char *vshEditWriteToTempFile(vshControl *ctl, const char *doc); -int vshEditFile(vshControl *ctl, const char *filename); -char *vshEditReadBackFile(vshControl *ctl, const char *filename); -int vshAskReedit(vshControl *ctl, const char *msg, bool relax_avail); -int vshStreamSink(virStreamPtr st, const char *bytes, size_t nbytes, - void *opaque); -double vshPrettyCapacity(unsigned long long val, const char **unit); -int vshStringToArray(const char *str, char ***array); - /* Typedefs, function prototypes for job progress reporting. * There are used by some long lingering commands like * migrate, dump, save, managedsave. @@ -372,156 +91,9 @@ struct _virshCtrlData { virConnectPtr dconn; }; -/* error handling */ -extern virErrorPtr last_error; -void vshReportError(vshControl *ctl); -void vshResetLibvirtError(void); -void vshSaveLibvirtError(void); - -/* terminal modifications */ -bool vshTTYIsInterruptCharacter(vshControl *ctl, const char chr); -int vshTTYDisableInterrupt(vshControl *ctl); -int vshTTYRestore(vshControl *ctl); -int vshTTYMakeRaw(vshControl *ctl, bool report_errors); -bool vshTTYAvailable(vshControl *ctl); - -/* waiting for events */ -enum { - VSH_EVENT_INTERRUPT, - VSH_EVENT_TIMEOUT, - VSH_EVENT_DONE, -}; -int vshEventStart(vshControl *ctl, int timeout_ms); -void vshEventDone(vshControl *ctl); -int vshEventWait(vshControl *ctl); -void vshEventCleanup(vshControl *ctl); - -/* allocation wrappers */ -void *_vshMalloc(vshControl *ctl, size_t sz, const char *filename, int line); -# define vshMalloc(_ctl, _sz) _vshMalloc(_ctl, _sz, __FILE__, __LINE__) - -void *_vshCalloc(vshControl *ctl, size_t nmemb, size_t sz, - const char *filename, int line); -# define vshCalloc(_ctl, _nmemb, _sz) \ - _vshCalloc(_ctl, _nmemb, _sz, __FILE__, __LINE__) - -char *_vshStrdup(vshControl *ctl, const char *s, const char *filename, - int line); -# define vshStrdup(_ctl, _s) _vshStrdup(_ctl, _s, __FILE__, __LINE__) - -/* Poison the raw allocating identifiers in favor of our vsh variants. */ -# undef malloc -# undef calloc -# undef realloc -# undef strdup -# define malloc use_vshMalloc_instead_of_malloc -# define calloc use_vshCalloc_instead_of_calloc -# define realloc use_vshRealloc_instead_of_realloc -# define strdup use_vshStrdup_instead_of_strdup - -/* Macros to help dealing with mutually exclusive options. */ - -/* VSH_EXCLUSIVE_OPTIONS_EXPR: - * - * @NAME1: String containing the name of the option. - * @EXPR1: Expression to validate the variable (boolean variable) - * @NAME2: String containing the name of the option. - * @EXPR2: Expression to validate the variable (boolean variable) - * - * Reject mutually exclusive command options in virsh. Use the - * provided expression to check the variables. - * - * This helper does an early return and therefore it has to be called - * before anything that would require cleanup. - */ -# define VSH_EXCLUSIVE_OPTIONS_EXPR(NAME1, EXPR1, NAME2, EXPR2) \ - if ((EXPR1) && (EXPR2)) { \ - vshError(ctl, _("Options --%s and --%s are mutually exclusive"), \ - NAME1, NAME2); \ - return false; \ - } - -/* VSH_EXCLUSIVE_OPTIONS: - * - * @NAME1: String containing the name of the option. - * @NAME2: String containing the name of the option. - * - * Reject mutually exclusive command options in virsh. Use the - * vshCommandOptBool call to request them. - * - * This helper does an early return and therefore it has to be called - * before anything that would require cleanup. - */ -# define VSH_EXCLUSIVE_OPTIONS(NAME1, NAME2) \ - VSH_EXCLUSIVE_OPTIONS_EXPR(NAME1, vshCommandOptBool(cmd, NAME1), \ - NAME2, vshCommandOptBool(cmd, NAME2)) -/* VSH_EXCLUSIVE_OPTIONS_VAR: - * - * @VARNAME1: Boolean variable containing the value of the option of same name - * @VARNAME2: Boolean variable containing the value of the option of same name - * - * Reject mutually exclusive command options in virsh. Check in variables that - * contain the value and have same name as the option. - * - * This helper does an early return and therefore it has to be called - * before anything that would require cleanup. - */ -# define VSH_EXCLUSIVE_OPTIONS_VAR(VARNAME1, VARNAME2) \ - VSH_EXCLUSIVE_OPTIONS_EXPR(#VARNAME1, VARNAME1, #VARNAME2, VARNAME2) -/* Macros to help dealing with required options. */ -/* VSH_REQUIRE_OPTION_EXPR: - * - * @NAME1: String containing the name of the option. - * @EXPR1: Expression to validate the variable (boolean variable). - * @NAME2: String containing the name of required option. - * @EXPR2: Expression to validate the variable (boolean variable). - * - * Check if required command options in virsh was set. Use the - * provided expression to check the variables. - * - * This helper does an early return and therefore it has to be called - * before anything that would require cleanup. - */ -# define VSH_REQUIRE_OPTION_EXPR(NAME1, EXPR1, NAME2, EXPR2) \ - do { \ - if ((EXPR1) && !(EXPR2)) { \ - vshError(ctl, _("Option --%s is required by option --%s"), \ - NAME2, NAME1); \ - return false; \ - } \ - } while (0) - -/* VSH_REQUIRE_OPTION: - * - * @NAME1: String containing the name of the option. - * @NAME2: String containing the name of required option. - * - * Check if required command options in virsh was set. Use the - * vshCommandOptBool call to request them. - * - * This helper does an early return and therefore it has to be called - * before anything that would require cleanup. - */ -# define VSH_REQUIRE_OPTION(NAME1, NAME2) \ - VSH_REQUIRE_OPTION_EXPR(NAME1, vshCommandOptBool(cmd, NAME1), \ - NAME2, vshCommandOptBool(cmd, NAME2)) -/* VSH_REQUIRE_OPTION_VAR: - * - * @VARNAME1: Boolean variable containing the value of the option of same name. - * @VARNAME2: Boolean variable containing the value of required option of - * same name. - * - * Check if required command options in virsh was set. Check in variables - * that contain the value and have same name as the option. - * - * This helper does an early return and therefore it has to be called - * before anything that would require cleanup. - */ -# define VSH_REQUIRE_OPTION_VAR(VARNAME1, VARNAME2) \ - VSH_REQUIRE_OPTION_EXPR(#VARNAME1, VARNAME1, #VARNAME2, VARNAME2) #endif /* VIRSH_H */ diff --git a/tools/vsh.c b/tools/vsh.c index b1d8dbc..71c8344 100644 --- a/tools/vsh.c +++ b/tools/vsh.c @@ -1998,7 +1998,7 @@ vshOutputLogFile(vshControl *ctl, int log_level, const char *msg_format, stTm.tm_hour, stTm.tm_min, stTm.tm_sec, - SIGN_NAME, + ctl->progname, (int) getpid()); switch (log_level) { case VSH_ERR_DEBUG: -- 1.9.3

--- tools/virsh.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tools/virsh.h b/tools/virsh.h index 15a938e..d10ed66 100644 --- a/tools/virsh.h +++ b/tools/virsh.h @@ -36,6 +36,7 @@ # include "internal.h" # include "virerror.h" # include "virthread.h" +# include "vsh.h" # define VIRSH_MAX_XML_FILE (10*1024*1024) @@ -60,7 +61,10 @@ # define VIRSH_CMD_GRP_HOST_AND_HV "Host and Hypervisor" # define VIRSH_CMD_GRP_VIRSH "Virsh itself" +typedef struct _virshControl virshControl; +typedef virshControl *virshControlPtr; +typedef struct _virshCtrlData virshCtrlData; /* * vshControl @@ -91,9 +95,24 @@ struct _virshCtrlData { virConnectPtr dconn; }; +virConnectPtr virshConnect(vshControl *ctl, const char *uri, bool readonly); +int virshCommandOptTimeoutToMs(vshControl *ctl, const vshCmd *cmd, int *timeout); +/* Given an index, return either the name of that device (non-NULL) or + * of its parent (NULL if a root). */ +typedef const char * (*vshTreeLookup)(int devid, bool parent, void *opaque); +int virshTreePrint(vshControl *ctl, vshTreeLookup lookup, void *opaque, + int num_devices, int devid); +int virshDomainState(vshControl *ctl, virDomainPtr dom, int *reason); +char *virshEditWriteToTempFile(vshControl *ctl, const char *doc); +int virshEditFile(vshControl *ctl, const char *filename); +char *virshEditReadBackFile(vshControl *ctl, const char *filename); +int virshAskReedit(vshControl *ctl, const char *msg, bool relax_avail); +int virshStreamSink(virStreamPtr st, const char *bytes, size_t nbytes, + void *opaque); +double virshPrettyCapacity(unsigned long long val, const char **unit); #endif /* VIRSH_H */ -- 1.9.3

For our new generic methods, it's highly sufficient to use generic vshControl structure only, however this doesn't apply for clients themselves. They need their own control structure and we need a valid reference to them, so why not store them as generic private data that only the client can process. --- tools/vsh.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/vsh.h b/tools/vsh.h index 76704a1..aaeb086 100644 --- a/tools/vsh.h +++ b/tools/vsh.h @@ -194,6 +194,7 @@ struct _vshCmd { */ struct _vshControl { char *name; /* connection name */ + char *progname; /* program name */ vshCmd *cmd; /* the current command */ char *cmdstr; /* string with command */ bool imode; /* interactive mode? */ @@ -219,6 +220,9 @@ struct _vshControl { struct termios termattr; /* settings of the tty terminal */ # endif bool istty; /* is the terminal a tty */ + void *privData; /* client specific data */ +}; + }; struct _vshCmdGrp { -- 1.9.3

--- tools/virsh-console.c | 3 +- tools/virsh-domain-monitor.c | 23 +++++---- tools/virsh-domain.c | 110 +++++++++++++++++++++++++++---------------- tools/virsh-host.c | 78 ++++++++++++++++++------------ tools/virsh-interface.c | 46 +++++++++++------- tools/virsh-network.c | 36 ++++++++------ tools/virsh-nodedev.c | 31 +++++++----- tools/virsh-nwfilter.c | 21 +++++---- tools/virsh-pool.c | 44 ++++++++++------- tools/virsh-secret.c | 15 +++--- tools/virsh-snapshot.c | 25 +++++----- tools/virsh-volume.c | 17 ++++--- tools/virsh.c | 57 +++++++++++++--------- 13 files changed, 311 insertions(+), 195 deletions(-) diff --git a/tools/virsh-console.c b/tools/virsh-console.c index 86ba456..c1927c2 100644 --- a/tools/virsh-console.c +++ b/tools/virsh-console.c @@ -311,6 +311,7 @@ virshRunConsole(vshControl *ctl, unsigned int flags) { virConsolePtr con = NULL; + virshControlPtr priv = ctl->privData; int ret = -1; struct sigaction old_sigquit; @@ -341,7 +342,7 @@ virshRunConsole(vshControl *ctl, if (VIR_ALLOC(con) < 0) goto cleanup; - con->escapeChar = virshGetEscapeChar(ctl->escapeChar); + con->escapeChar = virshGetEscapeChar(priv->escapeChar); con->st = virStreamNew(virDomainGetConnect(dom), VIR_STREAM_NONBLOCK); if (!con->st) diff --git a/tools/virsh-domain-monitor.c b/tools/virsh-domain-monitor.c index 1f53428..0762d6e 100644 --- a/tools/virsh-domain-monitor.c +++ b/tools/virsh-domain-monitor.c @@ -1210,6 +1210,7 @@ cmdDominfo(vshControl *ctl, const vshCmd *cmd) unsigned int id; char *str, uuid[VIR_UUID_STRING_BUFLEN]; int has_managed_save = 0; + virshControlPtr priv = ctl->privData; if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; @@ -1281,7 +1282,7 @@ cmdDominfo(vshControl *ctl, const vshCmd *cmd) /* Security model and label information */ memset(&secmodel, 0, sizeof(secmodel)); - if (virNodeGetSecurityModel(ctl->conn, &secmodel) == -1) { + if (virNodeGetSecurityModel(priv->conn, &secmodel) == -1) { if (last_error->code != VIR_ERR_NO_SUPPORT) { virDomainFree(dom); return false; @@ -1568,9 +1569,10 @@ virshDomainListCollect(vshControl *ctl, unsigned int flags) int state; int nsnap; int mansave; + virshControlPtr priv = ctl->privData; /* try the list with flags support (0.9.13 and later) */ - if ((ret = virConnectListAllDomains(ctl->conn, &list->domains, + if ((ret = virConnectListAllDomains(priv->conn, &list->domains, flags)) >= 0) { list->ndomains = ret; goto finished; @@ -1588,7 +1590,7 @@ virshDomainListCollect(vshControl *ctl, unsigned int flags) VIR_CONNECT_LIST_DOMAINS_INACTIVE); vshResetLibvirtError(); - if ((ret = virConnectListAllDomains(ctl->conn, &list->domains, + if ((ret = virConnectListAllDomains(priv->conn, &list->domains, newflags)) >= 0) { list->ndomains = ret; goto filter; @@ -1607,7 +1609,7 @@ virshDomainListCollect(vshControl *ctl, unsigned int flags) /* list active domains, if necessary */ if (!VSH_MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_ACTIVE) || VSH_MATCH(VIR_CONNECT_LIST_DOMAINS_ACTIVE)) { - if ((nids = virConnectNumOfDomains(ctl->conn)) < 0) { + if ((nids = virConnectNumOfDomains(priv->conn)) < 0) { vshError(ctl, "%s", _("Failed to list active domains")); goto cleanup; } @@ -1615,7 +1617,7 @@ virshDomainListCollect(vshControl *ctl, unsigned int flags) if (nids) { ids = vshMalloc(ctl, sizeof(int) * nids); - if ((nids = virConnectListDomains(ctl->conn, ids, nids)) < 0) { + if ((nids = virConnectListDomains(priv->conn, ids, nids)) < 0) { vshError(ctl, "%s", _("Failed to list active domains")); goto cleanup; } @@ -1624,7 +1626,7 @@ virshDomainListCollect(vshControl *ctl, unsigned int flags) if (!VSH_MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_ACTIVE) || VSH_MATCH(VIR_CONNECT_LIST_DOMAINS_INACTIVE)) { - if ((nnames = virConnectNumOfDefinedDomains(ctl->conn)) < 0) { + if ((nnames = virConnectNumOfDefinedDomains(priv->conn)) < 0) { vshError(ctl, "%s", _("Failed to list inactive domains")); goto cleanup; } @@ -1632,7 +1634,7 @@ virshDomainListCollect(vshControl *ctl, unsigned int flags) if (nnames) { names = vshMalloc(ctl, sizeof(char *) * nnames); - if ((nnames = virConnectListDefinedDomains(ctl->conn, names, + if ((nnames = virConnectListDefinedDomains(priv->conn, names, nnames)) < 0) { vshError(ctl, "%s", _("Failed to list inactive domains")); goto cleanup; @@ -1645,14 +1647,14 @@ virshDomainListCollect(vshControl *ctl, unsigned int flags) /* get active domains */ for (i = 0; i < nids; i++) { - if (!(dom = virDomainLookupByID(ctl->conn, ids[i]))) + if (!(dom = virDomainLookupByID(priv->conn, ids[i]))) continue; list->domains[list->ndomains++] = dom; } /* get inactive domains */ for (i = 0; i < nnames; i++) { - if (!(dom = virDomainLookupByName(ctl->conn, names[i]))) + if (!(dom = virDomainLookupByName(priv->conn, names[i]))) continue; list->domains[list->ndomains++] = dom; } @@ -2106,6 +2108,7 @@ cmdDomstats(vshControl *ctl, const vshCmd *cmd) int flags = 0; const vshCmdOpt *opt = NULL; bool ret = false; + virshControlPtr priv = ctl->privData; if (vshCommandOptBool(cmd, "state")) stats |= VIR_DOMAIN_STATS_STATE; @@ -2175,7 +2178,7 @@ cmdDomstats(vshControl *ctl, const vshCmd *cmd) flags) < 0) goto cleanup; } else { - if ((virConnectGetAllDomainStats(ctl->conn, + if ((virConnectGetAllDomainStats(priv->conn, stats, &records, flags)) < 0) diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index bf53a24..cbe213e 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -71,13 +71,14 @@ virshLookupDomainInternal(vshControl *ctl, virDomainPtr dom = NULL; int id; virCheckFlags(VSH_BYID | VSH_BYUUID | VSH_BYNAME, NULL); + virshControlPtr priv = ctl->privData; /* try it by ID */ if (flags & VSH_BYID) { if (virStrToLong_i(name, NULL, 10, &id) == 0 && id >= 0) { vshDebug(ctl, VSH_ERR_DEBUG, "%s: <domain> looks like ID\n", cmdname); - dom = virDomainLookupByID(ctl->conn, id); + dom = virDomainLookupByID(priv->conn, id); } } @@ -86,14 +87,14 @@ virshLookupDomainInternal(vshControl *ctl, strlen(name) == VIR_UUID_STRING_BUFLEN-1) { vshDebug(ctl, VSH_ERR_DEBUG, "%s: <domain> trying as domain UUID\n", cmdname); - dom = virDomainLookupByUUIDString(ctl->conn, name); + dom = virDomainLookupByUUIDString(priv->conn, name); } /* try it by NAME */ if (!dom && (flags & VSH_BYNAME)) { vshDebug(ctl, VSH_ERR_DEBUG, "%s: <domain> trying as domain NAME\n", cmdname); - dom = virDomainLookupByName(ctl->conn, name); + dom = virDomainLookupByName(priv->conn, name); } if (!dom) @@ -1898,6 +1899,7 @@ cmdBlockCommit(vshControl *ctl, const vshCmd *cmd) int abort_flags = 0; int status = -1; int cb_id = -1; + virshControlPtr priv = ctl->privData; blocking |= vshCommandOptBool(cmd, "timeout") || pivot || finish; if (blocking) { @@ -1930,7 +1932,7 @@ cmdBlockCommit(vshControl *ctl, const vshCmd *cmd) virConnectDomainEventGenericCallback cb = VIR_DOMAIN_EVENT_CALLBACK(virshBlockJobStatusHandler); - if ((cb_id = virConnectDomainEventRegisterAny(ctl->conn, + if ((cb_id = virConnectDomainEventRegisterAny(priv->conn, dom, VIR_DOMAIN_EVENT_ID_BLOCK_JOB, cb, @@ -2025,7 +2027,7 @@ cmdBlockCommit(vshControl *ctl, const vshCmd *cmd) if (blocking) sigaction(SIGINT, &old_sig_action, NULL); if (cb_id >= 0) - virConnectDomainEventDeregisterAny(ctl->conn, cb_id); + virConnectDomainEventDeregisterAny(priv->conn, cb_id); return ret; } @@ -2151,6 +2153,7 @@ cmdBlockCopy(vshControl *ctl, const vshCmd *cmd) int nparams = 0; int status = -1; int cb_id = -1; + virshControlPtr priv = ctl->privData; if (vshCommandOptStringReq(ctl, cmd, "path", &path) < 0) return false; @@ -2194,7 +2197,7 @@ cmdBlockCopy(vshControl *ctl, const vshCmd *cmd) virConnectDomainEventGenericCallback cb = VIR_DOMAIN_EVENT_CALLBACK(virshBlockJobStatusHandler); - if ((cb_id = virConnectDomainEventRegisterAny(ctl->conn, + if ((cb_id = virConnectDomainEventRegisterAny(priv->conn, dom, VIR_DOMAIN_EVENT_ID_BLOCK_JOB, cb, @@ -2376,7 +2379,7 @@ cmdBlockCopy(vshControl *ctl, const vshCmd *cmd) if (blocking) sigaction(SIGINT, &old_sig_action, NULL); if (cb_id >= 0) - virConnectDomainEventDeregisterAny(ctl->conn, cb_id); + virConnectDomainEventDeregisterAny(priv->conn, cb_id); return ret; } @@ -2468,6 +2471,7 @@ cmdBlockJob(vshControl *ctl, const vshCmd *cmd) const char *path; unsigned int flags = 0; unsigned long long speed; + virshControlPtr priv = ctl->privData; if (abortMode + infoMode + bandwidth > 1) { vshError(ctl, "%s", @@ -2495,14 +2499,14 @@ cmdBlockJob(vshControl *ctl, const vshCmd *cmd) /* If bytes were requested, or if raw mode is not forcing a MiB/s * query and cache can't prove failure, then query bytes/sec. */ - if (bytes || !(raw || ctl->blockJobNoBytes)) { + if (bytes || !(raw || priv->blockJobNoBytes)) { flags |= VIR_DOMAIN_BLOCK_JOB_INFO_BANDWIDTH_BYTES; rc = virDomainGetBlockJobInfo(dom, path, &info, flags); if (rc < 0) { /* Check for particular errors, let all the rest be fatal. */ switch (last_error->code) { case VIR_ERR_INVALID_ARG: - ctl->blockJobNoBytes = true; + priv->blockJobNoBytes = true; /* fallthrough */ case VIR_ERR_OVERFLOW: if (!bytes && !raw) { @@ -2636,6 +2640,7 @@ cmdBlockPull(vshControl *ctl, const vshCmd *cmd) int abort_flags = 0; int status = -1; int cb_id = -1; + virshControlPtr priv = ctl->privData; if (blocking) { if (virshCommandOptTimeoutToMs(ctl, cmd, &timeout) < 0) @@ -2664,7 +2669,7 @@ cmdBlockPull(vshControl *ctl, const vshCmd *cmd) virConnectDomainEventGenericCallback cb = VIR_DOMAIN_EVENT_CALLBACK(virshBlockJobStatusHandler); - if ((cb_id = virConnectDomainEventRegisterAny(ctl->conn, + if ((cb_id = virConnectDomainEventRegisterAny(priv->conn, dom, VIR_DOMAIN_EVENT_ID_BLOCK_JOB, cb, @@ -2736,7 +2741,7 @@ cmdBlockPull(vshControl *ctl, const vshCmd *cmd) if (blocking) sigaction(SIGINT, &old_sig_action, NULL); if (cb_id >= 0) - virConnectDomainEventDeregisterAny(ctl->conn, cb_id); + virConnectDomainEventDeregisterAny(priv->conn, cb_id); return ret; } @@ -2849,6 +2854,7 @@ cmdRunConsole(vshControl *ctl, virDomainPtr dom, { bool ret = false; int state; + virshControlPtr priv = ctl->privData; if ((state = virshDomainState(ctl, dom, NULL)) < 0) { vshError(ctl, "%s", _("Unable to get domain status")); @@ -2866,7 +2872,7 @@ cmdRunConsole(vshControl *ctl, virDomainPtr dom, } vshPrintExtra(ctl, _("Connected to domain %s\n"), virDomainGetName(dom)); - vshPrintExtra(ctl, _("Escape character is %s\n"), ctl->escapeChar); + vshPrintExtra(ctl, _("Escape character is %s\n"), priv->escapeChar); fflush(stdout); if (virshRunConsole(ctl, dom, name, flags) == 0) ret = true; @@ -3562,6 +3568,7 @@ cmdUndefine(vshControl *ctl, const vshCmd *cmd) char *pool = NULL; size_t i; size_t j; + virshControlPtr priv = ctl->privData; ignore_value(vshCommandOptString(ctl, cmd, "storage", &vol_string)); @@ -3717,7 +3724,7 @@ cmdUndefine(vshControl *ctl, const vshCmd *cmd) continue; } - if (!(storagepool = virStoragePoolLookupByName(ctl->conn, + if (!(storagepool = virStoragePoolLookupByName(priv->conn, pool))) { vshPrint(ctl, _("Storage pool '%s' for volume '%s' not found."), @@ -3730,7 +3737,7 @@ cmdUndefine(vshControl *ctl, const vshCmd *cmd) virStoragePoolFree(storagepool); } else { - vol.vol = virStorageVolLookupByPath(ctl->conn, source); + vol.vol = virStorageVolLookupByPath(priv->conn, source); } if (!vol.vol) { @@ -4357,6 +4364,7 @@ cmdSaveImageDumpxml(vshControl *ctl, const vshCmd *cmd) bool ret = false; unsigned int flags = 0; char *xml = NULL; + virshControlPtr priv = ctl->privData; if (vshCommandOptBool(cmd, "security-info")) flags |= VIR_DOMAIN_XML_SECURE; @@ -4364,7 +4372,7 @@ cmdSaveImageDumpxml(vshControl *ctl, const vshCmd *cmd) if (vshCommandOptStringReq(ctl, cmd, "file", &file) < 0) return false; - xml = virDomainSaveImageGetXMLDesc(ctl->conn, file, flags); + xml = virDomainSaveImageGetXMLDesc(priv->conn, file, flags); if (!xml) goto cleanup; @@ -4419,6 +4427,7 @@ cmdSaveImageDefine(vshControl *ctl, const vshCmd *cmd) const char *xmlfile = NULL; char *xml = NULL; unsigned int flags = 0; + virshControlPtr priv = ctl->privData; if (vshCommandOptBool(cmd, "running")) flags |= VIR_DOMAIN_SAVE_RUNNING; @@ -4434,7 +4443,7 @@ cmdSaveImageDefine(vshControl *ctl, const vshCmd *cmd) if (virFileReadAll(xmlfile, VIRSH_MAX_XML_FILE, &xml) < 0) goto cleanup; - if (virDomainSaveImageDefineXML(ctl->conn, file, xml, flags) < 0) { + if (virDomainSaveImageDefineXML(priv->conn, file, xml, flags) < 0) { vshError(ctl, _("Failed to update %s"), file); goto cleanup; } @@ -4484,6 +4493,7 @@ cmdSaveImageEdit(vshControl *ctl, const vshCmd *cmd) bool ret = false; unsigned int getxml_flags = VIR_DOMAIN_XML_SECURE; unsigned int define_flags = 0; + virshControlPtr priv = ctl->privData; if (vshCommandOptBool(cmd, "running")) define_flags |= VIR_DOMAIN_SAVE_RUNNING; @@ -4503,7 +4513,7 @@ cmdSaveImageEdit(vshControl *ctl, const vshCmd *cmd) return false; #define EDIT_GET_XML \ - virDomainSaveImageGetXMLDesc(ctl->conn, file, getxml_flags) + virDomainSaveImageGetXMLDesc(priv->conn, file, getxml_flags) #define EDIT_NOT_CHANGED \ do { \ vshPrint(ctl, _("Saved image %s XML configuration " \ @@ -4512,7 +4522,7 @@ cmdSaveImageEdit(vshControl *ctl, const vshCmd *cmd) goto edit_cleanup; \ } while (0) #define EDIT_DEFINE \ - (virDomainSaveImageDefineXML(ctl->conn, file, doc_edited, define_flags) == 0) + (virDomainSaveImageDefineXML(priv->conn, file, doc_edited, define_flags) == 0) #include "virsh-edit.c" vshPrint(ctl, _("State file %s edited.\n"), file); @@ -5002,6 +5012,7 @@ cmdRestore(vshControl *ctl, const vshCmd *cmd) unsigned int flags = 0; const char *xmlfile = NULL; char *xml = NULL; + virshControlPtr priv = ctl->privData; if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0) return false; @@ -5021,8 +5032,8 @@ cmdRestore(vshControl *ctl, const vshCmd *cmd) goto cleanup; if (((flags || xml) - ? virDomainRestoreFlags(ctl->conn, from, xml, flags) - : virDomainRestore(ctl->conn, from)) < 0) { + ? virDomainRestoreFlags(priv->conn, from, xml, flags) + : virDomainRestore(priv->conn, from)) < 0) { vshError(ctl, _("Failed to restore domain from %s"), from); goto cleanup; } @@ -5298,6 +5309,7 @@ cmdScreenshot(vshControl *ctl, const vshCmd *cmd) bool created = false; bool generated = false; char *mime = NULL; + virshControlPtr priv = ctl->privData; if (vshCommandOptStringReq(ctl, cmd, "file", (const char **) &file) < 0) return false; @@ -5308,7 +5320,7 @@ cmdScreenshot(vshControl *ctl, const vshCmd *cmd) if (!(dom = virshCommandOptDomain(ctl, cmd, &name))) return false; - if (!(st = virStreamNew(ctl->conn, 0))) + if (!(st = virStreamNew(priv->conn, 0))) goto cleanup; mime = virDomainScreenshot(dom, st, screen, flags); @@ -6264,11 +6276,12 @@ cmdVcpuinfo(vshControl *ctl, const vshCmd *cmd) bool ret = false; bool pretty = vshCommandOptBool(cmd, "pretty"); int n, m; + virshControlPtr priv = ctl->privData; if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; - if ((maxcpu = virshNodeGetCPUCount(ctl->conn)) < 0) + if ((maxcpu = virshNodeGetCPUCount(priv->conn)) < 0) goto cleanup; if (virDomainGetInfo(dom, &info) != 0) @@ -6447,6 +6460,7 @@ cmdVcpuPin(vshControl *ctl, const vshCmd *cmd) bool current = vshCommandOptBool(cmd, "current"); int got_vcpu; unsigned int flags = VIR_DOMAIN_AFFECT_CURRENT; + virshControlPtr priv = ctl->privData; VSH_EXCLUSIVE_OPTIONS_VAR(current, live); VSH_EXCLUSIVE_OPTIONS_VAR(current, config); @@ -6474,7 +6488,7 @@ cmdVcpuPin(vshControl *ctl, const vshCmd *cmd) return false; } - if ((maxcpu = virshNodeGetCPUCount(ctl->conn)) < 0) + if ((maxcpu = virshNodeGetCPUCount(priv->conn)) < 0) return false; if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) @@ -6589,6 +6603,7 @@ cmdEmulatorPin(vshControl *ctl, const vshCmd *cmd) bool current = vshCommandOptBool(cmd, "current"); bool query = false; /* Query mode if no cpulist */ unsigned int flags = VIR_DOMAIN_AFFECT_CURRENT; + virshControlPtr priv = ctl->privData; VSH_EXCLUSIVE_OPTIONS_VAR(current, live); VSH_EXCLUSIVE_OPTIONS_VAR(current, config); @@ -6610,7 +6625,7 @@ cmdEmulatorPin(vshControl *ctl, const vshCmd *cmd) } query = !cpulist; - if ((maxcpu = virshNodeGetCPUCount(ctl->conn)) < 0) { + if ((maxcpu = virshNodeGetCPUCount(priv->conn)) < 0) { virDomainFree(dom); return false; } @@ -6794,6 +6809,7 @@ cmdIOThreadInfo(vshControl *ctl, const vshCmd *cmd) size_t i; int maxcpu; unsigned int flags = VIR_DOMAIN_AFFECT_CURRENT; + virshControlPtr priv = ctl->privData; VSH_EXCLUSIVE_OPTIONS_VAR(current, live); VSH_EXCLUSIVE_OPTIONS_VAR(current, config); @@ -6806,7 +6822,7 @@ cmdIOThreadInfo(vshControl *ctl, const vshCmd *cmd) if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; - if ((maxcpu = virshNodeGetCPUCount(ctl->conn)) < 0) + if ((maxcpu = virshNodeGetCPUCount(priv->conn)) < 0) goto cleanup; if ((niothreads = virDomainGetIOThreadInfo(dom, &info, flags)) < 0) { @@ -6894,6 +6910,7 @@ cmdIOThreadPin(vshControl *ctl, const vshCmd *cmd) unsigned char *cpumap = NULL; int cpumaplen; unsigned int flags = VIR_DOMAIN_AFFECT_CURRENT; + virshControlPtr priv = ctl->privData; VSH_EXCLUSIVE_OPTIONS_VAR(current, live); VSH_EXCLUSIVE_OPTIONS_VAR(current, config); @@ -6914,7 +6931,7 @@ cmdIOThreadPin(vshControl *ctl, const vshCmd *cmd) goto cleanup; } - if ((maxcpu = virshNodeGetCPUCount(ctl->conn)) < 0) + if ((maxcpu = virshNodeGetCPUCount(priv->conn)) < 0) goto cleanup; if (!(cpumap = vshParseCPUList(ctl, &cpumaplen, cpulist, maxcpu))) @@ -7126,6 +7143,7 @@ cmdCPUCompare(vshControl *ctl, const vshCmd *cmd) xmlDocPtr xml = NULL; xmlXPathContextPtr ctxt = NULL; xmlNodePtr node; + virshControlPtr priv = ctl->privData; if (vshCommandOptBool(cmd, "error")) flags |= VIR_CONNECT_COMPARE_CPU_FAIL_INCOMPATIBLE; @@ -7153,7 +7171,7 @@ cmdCPUCompare(vshControl *ctl, const vshCmd *cmd) goto cleanup; } - result = virConnectCompareCPU(ctl->conn, snippet, flags); + result = virConnectCompareCPU(priv->conn, snippet, flags); switch (result) { case VIR_CPU_COMPARE_INCOMPATIBLE: @@ -7235,6 +7253,7 @@ cmdCPUBaseline(vshControl *ctl, const vshCmd *cmd) xmlXPathContextPtr ctxt = NULL; virBuffer buf = VIR_BUFFER_INITIALIZER; size_t i; + virshControlPtr priv = ctl->privData; if (vshCommandOptBool(cmd, "features")) flags |= VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES; @@ -7277,7 +7296,7 @@ cmdCPUBaseline(vshControl *ctl, const vshCmd *cmd) } } - result = virConnectBaselineCPU(ctl->conn, + result = virConnectBaselineCPU(priv->conn, (const char **)list, count, flags); if (result) { @@ -7551,6 +7570,7 @@ cmdCreate(vshControl *ctl, const vshCmd *cmd) unsigned int flags = 0; size_t nfds = 0; int *fds = NULL; + virshControlPtr priv = ctl->privData; if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0) return false; @@ -7569,9 +7589,9 @@ cmdCreate(vshControl *ctl, const vshCmd *cmd) flags |= VIR_DOMAIN_START_VALIDATE; if (nfds) - dom = virDomainCreateXMLWithFiles(ctl->conn, buffer, nfds, fds, flags); + dom = virDomainCreateXMLWithFiles(priv->conn, buffer, nfds, fds, flags); else - dom = virDomainCreateXML(ctl->conn, buffer, flags); + dom = virDomainCreateXML(priv->conn, buffer, flags); if (!dom) { vshError(ctl, _("Failed to create domain from %s"), from); @@ -7627,6 +7647,7 @@ cmdDefine(vshControl *ctl, const vshCmd *cmd) bool ret = true; char *buffer; unsigned int flags = 0; + virshControlPtr priv = ctl->privData; if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0) return false; @@ -7638,9 +7659,9 @@ cmdDefine(vshControl *ctl, const vshCmd *cmd) return false; if (flags) - dom = virDomainDefineXMLFlags(ctl->conn, buffer, flags); + dom = virDomainDefineXMLFlags(priv->conn, buffer, flags); else - dom = virDomainDefineXML(ctl->conn, buffer); + dom = virDomainDefineXML(priv->conn, buffer); VIR_FREE(buffer); if (dom != NULL) { @@ -9016,6 +9037,7 @@ cmdQemuMonitorEvent(vshControl *ctl, const vshCmd *cmd) int timeout = 0; const char *event = NULL; virshQemuEventData data; + virshControlPtr priv = ctl->privData; if (vshCommandOptBool(cmd, "regex")) flags |= VIR_CONNECT_DOMAIN_QEMU_MONITOR_EVENT_REGISTER_REGEX; @@ -9036,7 +9058,7 @@ cmdQemuMonitorEvent(vshControl *ctl, const vshCmd *cmd) if (vshEventStart(ctl, timeout) < 0) goto cleanup; - if ((eventId = virConnectDomainQemuMonitorEventRegister(ctl->conn, dom, + if ((eventId = virConnectDomainQemuMonitorEventRegister(priv->conn, dom, event, vshEventPrint, &data, NULL, @@ -9061,7 +9083,7 @@ cmdQemuMonitorEvent(vshControl *ctl, const vshCmd *cmd) cleanup: vshEventCleanup(ctl); if (eventId >= 0 && - virConnectDomainQemuMonitorEventDeregister(ctl->conn, eventId) < 0) + virConnectDomainQemuMonitorEventDeregister(priv->conn, eventId) < 0) ret = false; if (dom) virDomainFree(dom); @@ -9098,11 +9120,12 @@ cmdQemuAttach(vshControl *ctl, const vshCmd *cmd) bool ret = false; unsigned int flags = 0; unsigned int pid_value; /* API uses unsigned int, not pid_t */ + virshControlPtr priv = ctl->privData; if (vshCommandOptUInt(ctl, cmd, "pid", &pid_value) <= 0) goto cleanup; - if (!(dom = virDomainQemuAttach(ctl->conn, pid_value, flags))) { + if (!(dom = virDomainQemuAttach(priv->conn, pid_value, flags))) { vshError(ctl, _("Failed to attach to pid %u"), pid_value); goto cleanup; } @@ -9289,6 +9312,7 @@ cmdLxcEnterNamespace(vshControl *ctl, const vshCmd *cmd) bool setlabel = true; virSecurityModelPtr secmodel = NULL; virSecurityLabelPtr seclabel = NULL; + virshControlPtr priv = ctl->privData; dom = virshCommandOptDomain(ctl, cmd, NULL); if (dom == NULL) @@ -9322,7 +9346,7 @@ cmdLxcEnterNamespace(vshControl *ctl, const vshCmd *cmd) vshError(ctl, "%s", _("Failed to allocate security label")); goto cleanup; } - if (virNodeGetSecurityModel(ctl->conn, secmodel) < 0) + if (virNodeGetSecurityModel(priv->conn, secmodel) < 0) goto cleanup; if (virDomainGetSecurityLabel(dom, seclabel) < 0) goto cleanup; @@ -9495,6 +9519,7 @@ cmdDomXMLFromNative(vshControl *ctl, const vshCmd *cmd) char *configData; char *xmlData; unsigned int flags = 0; + virshControlPtr priv = ctl->privData; if (vshCommandOptStringReq(ctl, cmd, "format", &format) < 0 || vshCommandOptStringReq(ctl, cmd, "config", &configFile) < 0) @@ -9503,7 +9528,7 @@ cmdDomXMLFromNative(vshControl *ctl, const vshCmd *cmd) if (virFileReadAll(configFile, VIRSH_MAX_XML_FILE, &configData) < 0) return false; - xmlData = virConnectDomainXMLFromNative(ctl->conn, format, configData, flags); + xmlData = virConnectDomainXMLFromNative(priv->conn, format, configData, flags); if (xmlData != NULL) { vshPrint(ctl, "%s", xmlData); VIR_FREE(xmlData); @@ -9551,6 +9576,7 @@ cmdDomXMLToNative(vshControl *ctl, const vshCmd *cmd) char *configData; char *xmlData; unsigned int flags = 0; + virshControlPtr priv = ctl->privData; if (vshCommandOptStringReq(ctl, cmd, "format", &format) < 0 || vshCommandOptStringReq(ctl, cmd, "xml", &xmlFile) < 0) @@ -9559,7 +9585,7 @@ cmdDomXMLToNative(vshControl *ctl, const vshCmd *cmd) if (virFileReadAll(xmlFile, VIRSH_MAX_XML_FILE, &xmlData) < 0) return false; - configData = virConnectDomainXMLToNative(ctl->conn, format, xmlData, flags); + configData = virConnectDomainXMLToNative(priv->conn, format, xmlData, flags); if (configData != NULL) { vshPrint(ctl, "%s", configData); VIR_FREE(configData); @@ -11528,6 +11554,7 @@ cmdEdit(vshControl *ctl, const vshCmd *cmd) virDomainPtr dom_edited = NULL; unsigned int query_flags = VIR_DOMAIN_XML_SECURE | VIR_DOMAIN_XML_INACTIVE; unsigned int define_flags = VIR_DOMAIN_DEFINE_VALIDATE; + virshControlPtr priv = ctl->privData; dom = virshCommandOptDomain(ctl, cmd, NULL); if (dom == NULL) @@ -11545,7 +11572,7 @@ cmdEdit(vshControl *ctl, const vshCmd *cmd) goto edit_cleanup; \ } while (0) #define EDIT_DEFINE \ - (dom_edited = virshDomainDefine(ctl->conn, doc_edited, define_flags)) + (dom_edited = virshDomainDefine(priv->conn, doc_edited, define_flags)) #define EDIT_RELAX \ do { \ define_flags &= ~VIR_DOMAIN_DEFINE_VALIDATE; \ @@ -12243,6 +12270,7 @@ cmdEvent(vshControl *ctl, const vshCmd *cmd) bool all = vshCommandOptBool(cmd, "all"); bool loop = vshCommandOptBool(cmd, "loop"); int count = 0; + virshControlPtr priv = ctl->privData; if (vshCommandOptBool(cmd, "list")) { for (event = 0; event < VIR_DOMAIN_EVENT_ID_LAST; event++) @@ -12294,7 +12322,7 @@ cmdEvent(vshControl *ctl, const vshCmd *cmd) goto cleanup; for (i = 0; i < (all ? VIR_DOMAIN_EVENT_ID_LAST : 1); i++) { - if ((data[i].id = virConnectDomainEventRegisterAny(ctl->conn, dom, + if ((data[i].id = virConnectDomainEventRegisterAny(priv->conn, dom, all ? i : event, data[i].cb->cb, &data[i], @@ -12330,7 +12358,7 @@ cmdEvent(vshControl *ctl, const vshCmd *cmd) if (data) { for (i = 0; i < (all ? VIR_DOMAIN_EVENT_ID_LAST : 1); i++) { if (data[i].id >= 0 && - virConnectDomainEventDeregisterAny(ctl->conn, data[i].id) < 0) + virConnectDomainEventDeregisterAny(priv->conn, data[i].id) < 0) ret = false; } VIR_FREE(data); diff --git a/tools/virsh-host.c b/tools/virsh-host.c index 24341ae..d725ee0 100644 --- a/tools/virsh-host.c +++ b/tools/virsh-host.c @@ -57,8 +57,9 @@ static bool cmdCapabilities(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) { char *caps; + virshControlPtr priv = ctl->privData; - if ((caps = virConnectGetCapabilities(ctl->conn)) == NULL) { + if ((caps = virConnectGetCapabilities(priv->conn)) == NULL) { vshError(ctl, "%s", _("failed to get capabilities")); return false; } @@ -111,6 +112,7 @@ cmdDomCapabilities(vshControl *ctl, const vshCmd *cmd) const char *arch = NULL; const char *machine = NULL; const unsigned int flags = 0; /* No flags so far */ + virshControlPtr priv = ctl->privData; if (vshCommandOptStringReq(ctl, cmd, "virttype", &virttype) < 0 || vshCommandOptStringReq(ctl, cmd, "emulatorbin", &emulatorbin) < 0 || @@ -118,7 +120,7 @@ cmdDomCapabilities(vshControl *ctl, const vshCmd *cmd) vshCommandOptStringReq(ctl, cmd, "machine", &machine) < 0) return ret; - caps = virConnectGetDomainCapabilities(ctl->conn, emulatorbin, + caps = virConnectGetDomainCapabilities(priv->conn, emulatorbin, arch, machine, virttype, flags); if (!caps) { vshError(ctl, "%s", _("failed to get emulator capabilities")); @@ -173,6 +175,7 @@ cmdFreecell(vshControl *ctl, const vshCmd *cmd) char *cap_xml = NULL; xmlDocPtr xml = NULL; xmlXPathContextPtr ctxt = NULL; + virshControlPtr priv = ctl->privData; VSH_EXCLUSIVE_OPTIONS_VAR(all, cellno); @@ -180,7 +183,7 @@ cmdFreecell(vshControl *ctl, const vshCmd *cmd) return false; if (all) { - if (!(cap_xml = virConnectGetCapabilities(ctl->conn))) { + if (!(cap_xml = virConnectGetCapabilities(priv->conn))) { vshError(ctl, "%s", _("unable to get node capabilities")); goto cleanup; } @@ -213,7 +216,7 @@ cmdFreecell(vshControl *ctl, const vshCmd *cmd) } VIR_FREE(val); nodes_id[i] = id; - if (virNodeGetCellsFreeMemory(ctl->conn, &(nodes_free[i]), + if (virNodeGetCellsFreeMemory(priv->conn, &(nodes_free[i]), id, 1) != 1) { vshError(ctl, _("failed to get free memory for NUMA node " "number: %lu"), id); @@ -231,12 +234,12 @@ cmdFreecell(vshControl *ctl, const vshCmd *cmd) vshPrintExtra(ctl, "%5s: %10llu KiB\n", _("Total"), memory/1024); } else { if (cellno) { - if (virNodeGetCellsFreeMemory(ctl->conn, &memory, cell, 1) != 1) + if (virNodeGetCellsFreeMemory(priv->conn, &memory, cell, 1) != 1) goto cleanup; vshPrint(ctl, "%d: %llu KiB\n", cell, (memory/1024)); } else { - if ((memory = virNodeGetFreeMemory(ctl->conn)) == 0) + if ((memory = virNodeGetFreeMemory(priv->conn)) == 0) goto cleanup; vshPrint(ctl, "%s: %llu KiB\n", _("Total"), (memory/1024)); @@ -304,6 +307,7 @@ cmdFreepages(vshControl *ctl, const vshCmd *cmd) bool all = vshCommandOptBool(cmd, "all"); bool cellno = vshCommandOptBool(cmd, "cellno"); bool pagesz = vshCommandOptBool(cmd, "pagesize"); + virshControlPtr priv = ctl->privData; VSH_EXCLUSIVE_OPTIONS_VAR(all, cellno); @@ -312,7 +316,7 @@ cmdFreepages(vshControl *ctl, const vshCmd *cmd) kibibytes = VIR_DIV_UP(bytes, 1024); if (all) { - if (!(cap_xml = virConnectGetCapabilities(ctl->conn))) { + if (!(cap_xml = virConnectGetCapabilities(priv->conn))) { vshError(ctl, "%s", _("unable to get node capabilities")); goto cleanup; } @@ -367,7 +371,7 @@ cmdFreepages(vshControl *ctl, const vshCmd *cmd) } VIR_FREE(val); - if (virNodeGetFreePages(ctl->conn, npages, pagesize, + if (virNodeGetFreePages(priv->conn, npages, pagesize, cell, 1, counts, 0) < 0) goto cleanup; @@ -403,7 +407,8 @@ cmdFreepages(vshControl *ctl, const vshCmd *cmd) counts = vshMalloc(ctl, sizeof(*counts)); - if (virNodeGetFreePages(ctl->conn, 1, pagesize, cell, 1, counts, 0) < 0) + if (virNodeGetFreePages(priv->conn, 1, pagesize, + cell, 1, counts, 0) < 0) goto cleanup; vshPrint(ctl, "%uKiB: %lld\n", *pagesize, counts[0]); @@ -475,6 +480,7 @@ cmdAllocpages(vshControl *ctl, const vshCmd *cmd) xmlDocPtr xml = NULL; xmlXPathContextPtr ctxt = NULL; xmlNodePtr *nodes = NULL; + virshControlPtr priv = ctl->privData; VSH_EXCLUSIVE_OPTIONS_VAR(all, cellno); @@ -494,7 +500,7 @@ cmdAllocpages(vshControl *ctl, const vshCmd *cmd) unsigned long nodes_cnt; size_t i; - if (!(cap_xml = virConnectGetCapabilities(ctl->conn))) { + if (!(cap_xml = virConnectGetCapabilities(priv->conn))) { vshError(ctl, "%s", _("unable to get node capabilities")); goto cleanup; } @@ -524,12 +530,12 @@ cmdAllocpages(vshControl *ctl, const vshCmd *cmd) } VIR_FREE(val); - if (virNodeAllocPages(ctl->conn, 1, pageSizes, + if (virNodeAllocPages(priv->conn, 1, pageSizes, pageCounts, id, 1, flags) < 0) goto cleanup; } } else { - if (virNodeAllocPages(ctl->conn, 1, pageSizes, pageCounts, + if (virNodeAllocPages(priv->conn, 1, pageSizes, pageCounts, startCell, cellCount, flags) < 0) goto cleanup; } @@ -570,11 +576,12 @@ cmdMaxvcpus(vshControl *ctl, const vshCmd *cmd) { const char *type = NULL; int vcpus; + virshControlPtr priv = ctl->privData; if (vshCommandOptStringReq(ctl, cmd, "type", &type) < 0) return false; - if ((vcpus = virConnectGetMaxVcpus(ctl->conn, type)) < 0) + if ((vcpus = virConnectGetMaxVcpus(priv->conn, type)) < 0) return false; vshPrint(ctl, "%d\n", vcpus); @@ -599,8 +606,9 @@ static bool cmdNodeinfo(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) { virNodeInfo info; + virshControlPtr priv = ctl->privData; - if (virNodeGetInfo(ctl->conn, &info) < 0) { + if (virNodeGetInfo(priv->conn, &info) < 0) { vshError(ctl, "%s", _("failed to get node information")); return false; } @@ -646,8 +654,9 @@ cmdNodeCpuMap(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) unsigned int online; bool pretty = vshCommandOptBool(cmd, "pretty"); bool ret = false; + virshControlPtr priv = ctl->privData; - cpunum = virNodeGetCPUMap(ctl->conn, &cpumap, &online, 0); + cpunum = virNodeGetCPUMap(priv->conn, &cpumap, &online, 0); if (cpunum < 0) { vshError(ctl, "%s", _("Unable to get cpu map")); goto cleanup; @@ -741,11 +750,12 @@ cmdNodeCpuStats(vshControl *ctl, const vshCmd *cmd) bool ret = false; unsigned long long cpu_stats[VIRSH_CPU_LAST] = { 0 }; bool present[VIRSH_CPU_LAST] = { false }; + virshControlPtr priv = ctl->privData; if (vshCommandOptInt(ctl, cmd, "cpu", &cpuNum) < 0) return false; - if (virNodeGetCPUStats(ctl->conn, cpuNum, NULL, &nparams, 0) != 0) { + if (virNodeGetCPUStats(priv->conn, cpuNum, NULL, &nparams, 0) != 0) { vshError(ctl, "%s", _("Unable to get number of cpu stats")); return false; @@ -759,7 +769,7 @@ cmdNodeCpuStats(vshControl *ctl, const vshCmd *cmd) params = vshCalloc(ctl, nparams, sizeof(*params)); for (i = 0; i < 2; i++) { - if (virNodeGetCPUStats(ctl->conn, cpuNum, params, &nparams, 0) != 0) { + if (virNodeGetCPUStats(priv->conn, cpuNum, params, &nparams, 0) != 0) { vshError(ctl, "%s", _("Unable to get node cpu stats")); goto cleanup; } @@ -851,12 +861,13 @@ cmdNodeMemStats(vshControl *ctl, const vshCmd *cmd) int cellNum = VIR_NODE_MEMORY_STATS_ALL_CELLS; virNodeMemoryStatsPtr params = NULL; bool ret = false; + virshControlPtr priv = ctl->privData; if (vshCommandOptInt(ctl, cmd, "cell", &cellNum) < 0) return false; /* get the number of memory parameters */ - if (virNodeGetMemoryStats(ctl->conn, cellNum, NULL, &nparams, 0) != 0) { + if (virNodeGetMemoryStats(priv->conn, cellNum, NULL, &nparams, 0) != 0) { vshError(ctl, "%s", _("Unable to get number of memory stats")); goto cleanup; @@ -870,7 +881,7 @@ cmdNodeMemStats(vshControl *ctl, const vshCmd *cmd) /* now go get all the memory parameters */ params = vshCalloc(ctl, nparams, sizeof(*params)); - if (virNodeGetMemoryStats(ctl->conn, cellNum, params, &nparams, 0) != 0) { + if (virNodeGetMemoryStats(priv->conn, cellNum, params, &nparams, 0) != 0) { vshError(ctl, "%s", _("Unable to get memory stats")); goto cleanup; } @@ -920,6 +931,7 @@ cmdNodeSuspend(vshControl *ctl, const vshCmd *cmd) const char *target = NULL; unsigned int suspendTarget; long long duration; + virshControlPtr priv = ctl->privData; if (vshCommandOptStringReq(ctl, cmd, "target", &target) < 0) return false; @@ -943,7 +955,7 @@ cmdNodeSuspend(vshControl *ctl, const vshCmd *cmd) return false; } - if (virNodeSuspendForDuration(ctl->conn, suspendTarget, duration, 0) < 0) { + if (virNodeSuspendForDuration(priv->conn, suspendTarget, duration, 0) < 0) { vshError(ctl, "%s", _("The host was not suspended")); return false; } @@ -967,8 +979,9 @@ static bool cmdSysinfo(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) { char *sysinfo; + virshControlPtr priv = ctl->privData; - sysinfo = virConnectGetSysinfo(ctl->conn, 0); + sysinfo = virConnectGetSysinfo(priv->conn, 0); if (sysinfo == NULL) { vshError(ctl, "%s", _("failed to get sysinfo")); return false; @@ -997,8 +1010,9 @@ static bool cmdHostname(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) { char *hostname; + virshControlPtr priv = ctl->privData; - hostname = virConnectGetHostname(ctl->conn); + hostname = virConnectGetHostname(priv->conn); if (hostname == NULL) { vshError(ctl, "%s", _("failed to get hostname")); return false; @@ -1027,8 +1041,9 @@ static bool cmdURI(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) { char *uri; + virshControlPtr priv = ctl->privData; - uri = virConnectGetURI(ctl->conn); + uri = virConnectGetURI(priv->conn); if (uri == NULL) { vshError(ctl, "%s", _("failed to get URI")); return false; @@ -1069,11 +1084,12 @@ cmdCPUModelNames(vshControl *ctl, const vshCmd *cmd) size_t i; int nmodels; const char *arch = NULL; + virshControlPtr priv = ctl->privData; if (vshCommandOptStringReq(ctl, cmd, "arch", &arch) < 0) return false; - nmodels = virConnectGetCPUModelNames(ctl->conn, arch, &models, 0); + nmodels = virConnectGetCPUModelNames(priv->conn, arch, &models, 0); if (nmodels < 0) { vshError(ctl, "%s", _("failed to get CPU model names")); return false; @@ -1122,8 +1138,9 @@ cmdVersion(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) unsigned int major; unsigned int minor; unsigned int rel; + virshControlPtr priv = ctl->privData; - hvType = virConnectGetType(ctl->conn); + hvType = virConnectGetType(priv->conn); if (hvType == NULL) { vshError(ctl, "%s", _("failed to get hypervisor type")); return false; @@ -1156,7 +1173,7 @@ cmdVersion(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) vshPrint(ctl, _("Using API: %s %d.%d.%d\n"), hvType, major, minor, rel); - ret = virConnectGetVersion(ctl->conn, &hvVersion); + ret = virConnectGetVersion(priv->conn, &hvVersion); if (ret < 0) { vshError(ctl, "%s", _("failed to get the hypervisor version")); return false; @@ -1175,7 +1192,7 @@ cmdVersion(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) } if (vshCommandOptBool(cmd, "daemon")) { - ret = virConnectGetLibVersion(ctl->conn, &daemonVersion); + ret = virConnectGetLibVersion(priv->conn, &daemonVersion); if (ret < 0) { vshError(ctl, "%s", _("failed to get the daemon version")); } else { @@ -1228,6 +1245,7 @@ cmdNodeMemoryTune(vshControl *ctl, const vshCmd *cmd) bool ret = false; int rc = -1; size_t i; + virshControlPtr priv = ctl->privData; if ((rc = vshCommandOptUInt(ctl, cmd, "shm-pages-to-scan", &value)) < 0) { goto cleanup; @@ -1258,7 +1276,7 @@ cmdNodeMemoryTune(vshControl *ctl, const vshCmd *cmd) if (nparams == 0) { /* Get the number of memory parameters */ - if (virNodeGetMemoryParameters(ctl->conn, NULL, &nparams, flags) != 0) { + if (virNodeGetMemoryParameters(priv->conn, NULL, &nparams, flags) != 0) { vshError(ctl, "%s", _("Unable to get number of memory parameters")); goto cleanup; @@ -1271,7 +1289,7 @@ cmdNodeMemoryTune(vshControl *ctl, const vshCmd *cmd) /* Now go get all the memory parameters */ params = vshCalloc(ctl, nparams, sizeof(*params)); - if (virNodeGetMemoryParameters(ctl->conn, params, &nparams, flags) != 0) { + if (virNodeGetMemoryParameters(priv->conn, params, &nparams, flags) != 0) { vshError(ctl, "%s", _("Unable to get memory parameters")); goto cleanup; } @@ -1286,7 +1304,7 @@ cmdNodeMemoryTune(vshControl *ctl, const vshCmd *cmd) VIR_FREE(str); } } else { - if (virNodeSetMemoryParameters(ctl->conn, params, nparams, flags) != 0) + if (virNodeSetMemoryParameters(priv->conn, params, nparams, flags) != 0) goto error; } diff --git a/tools/virsh-interface.c b/tools/virsh-interface.c index 8b085cd..9a00070 100644 --- a/tools/virsh-interface.c +++ b/tools/virsh-interface.c @@ -50,6 +50,7 @@ virshCommandOptInterfaceBy(vshControl *ctl, const vshCmd *cmd, bool is_mac = false; virMacAddr dummy; virCheckFlags(VSH_BYNAME | VSH_BYMAC, NULL); + virshControlPtr priv = ctl->privData; if (!optname) optname = "interface"; @@ -70,13 +71,13 @@ virshCommandOptInterfaceBy(vshControl *ctl, const vshCmd *cmd, if (!is_mac && (flags & VSH_BYNAME)) { vshDebug(ctl, VSH_ERR_DEBUG, "%s: <%s> trying as interface NAME\n", cmd->def->name, optname); - iface = virInterfaceLookupByName(ctl->conn, n); + iface = virInterfaceLookupByName(priv->conn, n); /* try it by MAC */ } else if (is_mac && (flags & VSH_BYMAC)) { vshDebug(ctl, VSH_ERR_DEBUG, "%s: <%s> trying as interface MAC\n", cmd->def->name, optname); - iface = virInterfaceLookupByMACString(ctl->conn, n); + iface = virInterfaceLookupByMACString(priv->conn, n); } if (!iface) @@ -114,6 +115,7 @@ cmdInterfaceEdit(vshControl *ctl, const vshCmd *cmd) virInterfacePtr iface = NULL; virInterfacePtr iface_edited = NULL; unsigned int flags = VIR_INTERFACE_XML_INACTIVE; + virshControlPtr priv = ctl->privData; iface = virshCommandOptInterface(ctl, cmd, NULL); if (iface == NULL) @@ -128,7 +130,7 @@ cmdInterfaceEdit(vshControl *ctl, const vshCmd *cmd) goto edit_cleanup; \ } while (0) #define EDIT_DEFINE \ - (iface_edited = virInterfaceDefineXML(ctl->conn, doc_edited, 0)) + (iface_edited = virInterfaceDefineXML(priv->conn, doc_edited, 0)) #include "virsh-edit.c" vshPrint(ctl, _("Interface %s XML configuration edited.\n"), @@ -197,9 +199,10 @@ vshInterfaceListCollect(vshControl *ctl, int nActiveIfaces = 0; int nInactiveIfaces = 0; int nAllIfaces = 0; + virshControlPtr priv = ctl->privData; /* try the list with flags support (0.10.2 and later) */ - if ((ret = virConnectListAllInterfaces(ctl->conn, + if ((ret = virConnectListAllInterfaces(priv->conn, &list->ifaces, flags)) >= 0) { list->nifaces = ret; @@ -220,7 +223,7 @@ vshInterfaceListCollect(vshControl *ctl, vshResetLibvirtError(); if (flags & VIR_CONNECT_LIST_INTERFACES_ACTIVE) { - nActiveIfaces = virConnectNumOfInterfaces(ctl->conn); + nActiveIfaces = virConnectNumOfInterfaces(priv->conn); if (nActiveIfaces < 0) { vshError(ctl, "%s", _("Failed to list active interfaces")); goto cleanup; @@ -228,7 +231,7 @@ vshInterfaceListCollect(vshControl *ctl, if (nActiveIfaces) { activeNames = vshMalloc(ctl, sizeof(char *) * nActiveIfaces); - if ((nActiveIfaces = virConnectListInterfaces(ctl->conn, activeNames, + if ((nActiveIfaces = virConnectListInterfaces(priv->conn, activeNames, nActiveIfaces)) < 0) { vshError(ctl, "%s", _("Failed to list active interfaces")); goto cleanup; @@ -237,7 +240,7 @@ vshInterfaceListCollect(vshControl *ctl, } if (flags & VIR_CONNECT_LIST_INTERFACES_INACTIVE) { - nInactiveIfaces = virConnectNumOfDefinedInterfaces(ctl->conn); + nInactiveIfaces = virConnectNumOfDefinedInterfaces(priv->conn); if (nInactiveIfaces < 0) { vshError(ctl, "%s", _("Failed to list inactive interfaces")); goto cleanup; @@ -246,7 +249,7 @@ vshInterfaceListCollect(vshControl *ctl, inactiveNames = vshMalloc(ctl, sizeof(char *) * nInactiveIfaces); if ((nInactiveIfaces = - virConnectListDefinedInterfaces(ctl->conn, inactiveNames, + virConnectListDefinedInterfaces(priv->conn, inactiveNames, nInactiveIfaces)) < 0) { vshError(ctl, "%s", _("Failed to list inactive interfaces")); goto cleanup; @@ -266,7 +269,7 @@ vshInterfaceListCollect(vshControl *ctl, /* get active interfaces */ for (i = 0; i < nActiveIfaces; i++) { - if (!(iface = virInterfaceLookupByName(ctl->conn, activeNames[i]))) { + if (!(iface = virInterfaceLookupByName(priv->conn, activeNames[i]))) { vshResetLibvirtError(); continue; } @@ -275,7 +278,7 @@ vshInterfaceListCollect(vshControl *ctl, /* get inactive interfaces */ for (i = 0; i < nInactiveIfaces; i++) { - if (!(iface = virInterfaceLookupByName(ctl->conn, inactiveNames[i]))) { + if (!(iface = virInterfaceLookupByName(priv->conn, inactiveNames[i]))) { vshResetLibvirtError(); continue; } @@ -530,6 +533,7 @@ cmdInterfaceDefine(vshControl *ctl, const vshCmd *cmd) const char *from = NULL; bool ret = true; char *buffer; + virshControlPtr priv = ctl->privData; if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0) return false; @@ -537,7 +541,7 @@ cmdInterfaceDefine(vshControl *ctl, const vshCmd *cmd) if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) return false; - iface = virInterfaceDefineXML(ctl->conn, buffer, 0); + iface = virInterfaceDefineXML(priv->conn, buffer, 0); VIR_FREE(buffer); if (iface != NULL) { @@ -702,7 +706,9 @@ static const vshCmdOptDef opts_interface_begin[] = { static bool cmdInterfaceBegin(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) { - if (virInterfaceChangeBegin(ctl->conn, 0) < 0) { + virshControlPtr priv = ctl->privData; + + if (virInterfaceChangeBegin(priv->conn, 0) < 0) { vshError(ctl, "%s", _("Failed to begin network config change transaction")); return false; } @@ -731,7 +737,9 @@ static const vshCmdOptDef opts_interface_commit[] = { static bool cmdInterfaceCommit(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) { - if (virInterfaceChangeCommit(ctl->conn, 0) < 0) { + virshControlPtr priv = ctl->privData; + + if (virInterfaceChangeCommit(priv->conn, 0) < 0) { vshError(ctl, "%s", _("Failed to commit network config change transaction")); return false; } @@ -760,7 +768,9 @@ static const vshCmdOptDef opts_interface_rollback[] = { static bool cmdInterfaceRollback(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) { - if (virInterfaceChangeRollback(ctl->conn, 0) < 0) { + virshControlPtr priv = ctl->privData; + + if (virInterfaceChangeRollback(priv->conn, 0) < 0) { vshError(ctl, "%s", _("Failed to rollback network config change transaction")); return false; } @@ -823,6 +833,7 @@ cmdInterfaceBridge(vshControl *ctl, const vshCmd *cmd) xmlDocPtr xml_doc = NULL; xmlXPathContextPtr ctxt = NULL; xmlNodePtr top_node, br_node, if_node, cur; + virshControlPtr priv = ctl->privData; /* Get a handle to the original device */ if (!(if_handle = virshCommandOptInterfaceBy(ctl, cmd, "interface", @@ -835,7 +846,7 @@ cmdInterfaceBridge(vshControl *ctl, const vshCmd *cmd) goto cleanup; /* make sure "new" device doesn't already exist */ - if ((br_handle = virInterfaceLookupByName(ctl->conn, br_name))) { + if ((br_handle = virInterfaceLookupByName(priv->conn, br_name))) { vshError(ctl, _("Network device %s already exists"), br_name); goto cleanup; } @@ -969,7 +980,7 @@ cmdInterfaceBridge(vshControl *ctl, const vshCmd *cmd) /* br_xml is the new interface to define. It will automatically undefine the * independent original interface. */ - if (!(br_handle = virInterfaceDefineXML(ctl->conn, (char *) br_xml, 0))) { + if (!(br_handle = virInterfaceDefineXML(priv->conn, (char *) br_xml, 0))) { vshError(ctl, _("Failed to define new bridge interface %s"), br_name); goto cleanup; @@ -1043,6 +1054,7 @@ cmdInterfaceUnbridge(vshControl *ctl, const vshCmd *cmd) xmlDocPtr xml_doc = NULL; xmlXPathContextPtr ctxt = NULL; xmlNodePtr top_node, if_node, cur; + virshControlPtr priv = ctl->privData; /* Get a handle to the original device */ if (!(br_handle = virshCommandOptInterfaceBy(ctl, cmd, "bridge", @@ -1170,7 +1182,7 @@ cmdInterfaceUnbridge(vshControl *ctl, const vshCmd *cmd) /* if_xml is the new interface to define. */ - if (!(if_handle = virInterfaceDefineXML(ctl->conn, (char *) if_xml, 0))) { + if (!(if_handle = virInterfaceDefineXML(priv->conn, (char *) if_xml, 0))) { vshError(ctl, _("Failed to define new interface %s"), if_name); goto cleanup; } diff --git a/tools/virsh-network.c b/tools/virsh-network.c index 79909d9..4e3eee5 100644 --- a/tools/virsh-network.c +++ b/tools/virsh-network.c @@ -41,6 +41,7 @@ virshCommandOptNetworkBy(vshControl *ctl, const vshCmd *cmd, const char *n = NULL; const char *optname = "network"; virCheckFlags(VSH_BYUUID | VSH_BYNAME, NULL); + virshControlPtr priv = ctl->privData; if (vshCommandOptStringReq(ctl, cmd, optname, &n) < 0) return NULL; @@ -55,13 +56,13 @@ virshCommandOptNetworkBy(vshControl *ctl, const vshCmd *cmd, if ((flags & VSH_BYUUID) && strlen(n) == VIR_UUID_STRING_BUFLEN-1) { vshDebug(ctl, VSH_ERR_DEBUG, "%s: <%s> trying as network UUID\n", cmd->def->name, optname); - network = virNetworkLookupByUUIDString(ctl->conn, n); + network = virNetworkLookupByUUIDString(priv->conn, n); } /* try it by NAME */ if (!network && (flags & VSH_BYNAME)) { vshDebug(ctl, VSH_ERR_DEBUG, "%s: <%s> trying as network NAME\n", cmd->def->name, optname); - network = virNetworkLookupByName(ctl->conn, n); + network = virNetworkLookupByName(priv->conn, n); } if (!network) @@ -155,6 +156,7 @@ cmdNetworkCreate(vshControl *ctl, const vshCmd *cmd) const char *from = NULL; bool ret = true; char *buffer; + virshControlPtr priv = ctl->privData; if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0) return false; @@ -162,7 +164,7 @@ cmdNetworkCreate(vshControl *ctl, const vshCmd *cmd) if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) return false; - network = virNetworkCreateXML(ctl->conn, buffer); + network = virNetworkCreateXML(priv->conn, buffer); VIR_FREE(buffer); if (network != NULL) { @@ -206,6 +208,7 @@ cmdNetworkDefine(vshControl *ctl, const vshCmd *cmd) const char *from = NULL; bool ret = true; char *buffer; + virshControlPtr priv = ctl->privData; if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0) return false; @@ -213,7 +216,7 @@ cmdNetworkDefine(vshControl *ctl, const vshCmd *cmd) if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) return false; - network = virNetworkDefineXML(ctl->conn, buffer); + network = virNetworkDefineXML(priv->conn, buffer); VIR_FREE(buffer); if (network != NULL) { @@ -442,9 +445,10 @@ vshNetworkListCollect(vshControl *ctl, int nActiveNets = 0; int nInactiveNets = 0; int nAllNets = 0; + virshControlPtr priv = ctl->privData; /* try the list with flags support (0.10.2 and later) */ - if ((ret = virConnectListAllNetworks(ctl->conn, + if ((ret = virConnectListAllNetworks(priv->conn, &list->nets, flags)) >= 0) { list->nnets = ret; @@ -461,7 +465,7 @@ vshNetworkListCollect(vshControl *ctl, VIR_CONNECT_LIST_NETWORKS_INACTIVE); vshResetLibvirtError(); - if ((ret = virConnectListAllNetworks(ctl->conn, &list->nets, + if ((ret = virConnectListAllNetworks(priv->conn, &list->nets, newflags)) >= 0) { list->nnets = ret; goto filter; @@ -480,7 +484,7 @@ vshNetworkListCollect(vshControl *ctl, /* Get the number of active networks */ if (!VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_FILTERS_ACTIVE) || VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_ACTIVE)) { - if ((nActiveNets = virConnectNumOfNetworks(ctl->conn)) < 0) { + if ((nActiveNets = virConnectNumOfNetworks(priv->conn)) < 0) { vshError(ctl, "%s", _("Failed to get the number of active networks")); goto cleanup; } @@ -489,7 +493,7 @@ vshNetworkListCollect(vshControl *ctl, /* Get the number of inactive networks */ if (!VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_FILTERS_ACTIVE) || VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_INACTIVE)) { - if ((nInactiveNets = virConnectNumOfDefinedNetworks(ctl->conn)) < 0) { + if ((nInactiveNets = virConnectNumOfDefinedNetworks(priv->conn)) < 0) { vshError(ctl, "%s", _("Failed to get the number of inactive networks")); goto cleanup; } @@ -505,7 +509,7 @@ vshNetworkListCollect(vshControl *ctl, /* Retrieve a list of active network names */ if (!VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_FILTERS_ACTIVE) || VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_ACTIVE)) { - if (virConnectListNetworks(ctl->conn, + if (virConnectListNetworks(priv->conn, names, nActiveNets) < 0) { vshError(ctl, "%s", _("Failed to list active networks")); goto cleanup; @@ -515,7 +519,7 @@ vshNetworkListCollect(vshControl *ctl, /* Add the inactive networks to the end of the name list */ if (!VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_FILTERS_ACTIVE) || VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_ACTIVE)) { - if (virConnectListDefinedNetworks(ctl->conn, + if (virConnectListDefinedNetworks(priv->conn, &names[nActiveNets], nInactiveNets) < 0) { vshError(ctl, "%s", _("Failed to list inactive networks")); @@ -528,14 +532,14 @@ vshNetworkListCollect(vshControl *ctl, /* get active networks */ for (i = 0; i < nActiveNets; i++) { - if (!(net = virNetworkLookupByName(ctl->conn, names[i]))) + if (!(net = virNetworkLookupByName(priv->conn, names[i]))) continue; list->nets[list->nnets++] = net; } /* get inactive networks */ for (i = 0; i < nInactiveNets; i++) { - if (!(net = virNetworkLookupByName(ctl->conn, names[i]))) + if (!(net = virNetworkLookupByName(priv->conn, names[i]))) continue; list->nets[list->nnets++] = net; } @@ -1123,6 +1127,7 @@ cmdNetworkEdit(vshControl *ctl, const vshCmd *cmd) bool ret = false; virNetworkPtr network = NULL; virNetworkPtr network_edited = NULL; + virshControlPtr priv = ctl->privData; network = virshCommandOptNetwork(ctl, cmd, NULL); if (network == NULL) @@ -1137,7 +1142,7 @@ cmdNetworkEdit(vshControl *ctl, const vshCmd *cmd) goto edit_cleanup; \ } while (0) #define EDIT_DEFINE \ - (network_edited = virNetworkDefineXML(ctl->conn, doc_edited)) + (network_edited = virNetworkDefineXML(priv->conn, doc_edited)) #include "virsh-edit.c" vshPrint(ctl, _("Network %s XML configuration edited.\n"), @@ -1247,6 +1252,7 @@ cmdNetworkEvent(vshControl *ctl, const vshCmd *cmd) vshNetEventData data; const char *eventName = NULL; int event; + virshControlPtr priv = ctl->privData; if (vshCommandOptBool(cmd, "list")) { size_t i; @@ -1278,7 +1284,7 @@ cmdNetworkEvent(vshControl *ctl, const vshCmd *cmd) if (vshEventStart(ctl, timeout) < 0) goto cleanup; - if ((eventId = virConnectNetworkEventRegisterAny(ctl->conn, net, event, + if ((eventId = virConnectNetworkEventRegisterAny(priv->conn, net, event, VIR_NETWORK_EVENT_CALLBACK(vshEventLifecyclePrint), &data, NULL)) < 0) goto cleanup; @@ -1301,7 +1307,7 @@ cmdNetworkEvent(vshControl *ctl, const vshCmd *cmd) cleanup: vshEventCleanup(ctl); if (eventId >= 0 && - virConnectNetworkEventDeregisterAny(ctl->conn, eventId) < 0) + virConnectNetworkEventDeregisterAny(priv->conn, eventId) < 0) ret = false; if (net) virNetworkFree(net); diff --git a/tools/virsh-nodedev.c b/tools/virsh-nodedev.c index adf4423..d81afcf 100644 --- a/tools/virsh-nodedev.c +++ b/tools/virsh-nodedev.c @@ -65,6 +65,7 @@ cmdNodeDeviceCreate(vshControl *ctl, const vshCmd *cmd) const char *from = NULL; bool ret = true; char *buffer; + virshControlPtr priv = ctl->privData; if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0) return false; @@ -72,7 +73,7 @@ cmdNodeDeviceCreate(vshControl *ctl, const vshCmd *cmd) if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) return false; - dev = virNodeDeviceCreateXML(ctl->conn, buffer, 0); + dev = virNodeDeviceCreateXML(priv->conn, buffer, 0); VIR_FREE(buffer); if (dev != NULL) { @@ -123,6 +124,7 @@ cmdNodeDeviceDestroy(vshControl *ctl, const vshCmd *cmd) const char *device_value = NULL; char **arr = NULL; int narr; + virshControlPtr priv = ctl->privData; if (vshCommandOptStringReq(ctl, cmd, "device", &device_value) < 0) return false; @@ -137,9 +139,9 @@ cmdNodeDeviceDestroy(vshControl *ctl, const vshCmd *cmd) if (!virValidateWWN(arr[0]) || !virValidateWWN(arr[1])) goto cleanup; - dev = virNodeDeviceLookupSCSIHostByWWN(ctl->conn, arr[0], arr[1], 0); + dev = virNodeDeviceLookupSCSIHostByWWN(priv->conn, arr[0], arr[1], 0); } else { - dev = virNodeDeviceLookupByName(ctl->conn, device_value); + dev = virNodeDeviceLookupByName(priv->conn, device_value); } if (!dev) { @@ -227,9 +229,10 @@ vshNodeDeviceListCollect(vshControl *ctl, size_t deleted = 0; int ndevices = 0; char **names = NULL; + virshControlPtr priv = ctl->privData; /* try the list with flags support (0.10.2 and later) */ - if ((ret = virConnectListAllNodeDevices(ctl->conn, + if ((ret = virConnectListAllNodeDevices(priv->conn, &list->devices, flags)) >= 0) { list->ndevices = ret; @@ -249,7 +252,7 @@ vshNodeDeviceListCollect(vshControl *ctl, /* fall back to old method (0.10.1 and older) */ vshResetLibvirtError(); - ndevices = virNodeNumOfDevices(ctl->conn, NULL, 0); + ndevices = virNodeNumOfDevices(priv->conn, NULL, 0); if (ndevices < 0) { vshError(ctl, "%s", _("Failed to count node devices")); goto cleanup; @@ -260,7 +263,7 @@ vshNodeDeviceListCollect(vshControl *ctl, names = vshMalloc(ctl, sizeof(char *) * ndevices); - ndevices = virNodeListDevices(ctl->conn, NULL, names, ndevices, 0); + ndevices = virNodeListDevices(priv->conn, NULL, names, ndevices, 0); if (ndevices < 0) { vshError(ctl, "%s", _("Failed to list node devices")); goto cleanup; @@ -271,7 +274,7 @@ vshNodeDeviceListCollect(vshControl *ctl, /* get the node devices */ for (i = 0; i < ndevices; i++) { - if (!(device = virNodeDeviceLookupByName(ctl->conn, names[i]))) + if (!(device = virNodeDeviceLookupByName(priv->conn, names[i]))) continue; list->devices[list->ndevices++] = device; } @@ -534,6 +537,7 @@ cmdNodeDeviceDumpXML(vshControl *ctl, const vshCmd *cmd) char **arr = NULL; int narr; bool ret = false; + virshControlPtr priv = ctl->privData; if (vshCommandOptStringReq(ctl, cmd, "device", &device_value) < 0) return false; @@ -548,9 +552,9 @@ cmdNodeDeviceDumpXML(vshControl *ctl, const vshCmd *cmd) if (!virValidateWWN(arr[0]) || !virValidateWWN(arr[1])) goto cleanup; - device = virNodeDeviceLookupSCSIHostByWWN(ctl->conn, arr[0], arr[1], 0); + device = virNodeDeviceLookupSCSIHostByWWN(priv->conn, arr[0], arr[1], 0); } else { - device = virNodeDeviceLookupByName(ctl->conn, device_value); + device = virNodeDeviceLookupByName(priv->conn, device_value); } if (!device) { @@ -606,13 +610,14 @@ cmdNodeDeviceDetach(vshControl *ctl, const vshCmd *cmd) const char *driverName = NULL; virNodeDevicePtr device; bool ret = true; + virshControlPtr priv = ctl->privData; if (vshCommandOptStringReq(ctl, cmd, "device", &name) < 0) return false; ignore_value(vshCommandOptString(ctl, cmd, "driver", &driverName)); - if (!(device = virNodeDeviceLookupByName(ctl->conn, name))) { + if (!(device = virNodeDeviceLookupByName(priv->conn, name))) { vshError(ctl, _("Could not find matching device '%s'"), name); return false; } @@ -666,11 +671,12 @@ cmdNodeDeviceReAttach(vshControl *ctl, const vshCmd *cmd) const char *name = NULL; virNodeDevicePtr device; bool ret = true; + virshControlPtr priv = ctl->privData; if (vshCommandOptStringReq(ctl, cmd, "device", &name) < 0) return false; - if (!(device = virNodeDeviceLookupByName(ctl->conn, name))) { + if (!(device = virNodeDeviceLookupByName(priv->conn, name))) { vshError(ctl, _("Could not find matching device '%s'"), name); return false; } @@ -715,11 +721,12 @@ cmdNodeDeviceReset(vshControl *ctl, const vshCmd *cmd) const char *name = NULL; virNodeDevicePtr device; bool ret = true; + virshControlPtr priv = ctl->privData; if (vshCommandOptStringReq(ctl, cmd, "device", &name) < 0) return false; - if (!(device = virNodeDeviceLookupByName(ctl->conn, name))) { + if (!(device = virNodeDeviceLookupByName(priv->conn, name))) { vshError(ctl, _("Could not find matching device '%s'"), name); return false; } diff --git a/tools/virsh-nwfilter.c b/tools/virsh-nwfilter.c index d2c8a79..8c64ac4 100644 --- a/tools/virsh-nwfilter.c +++ b/tools/virsh-nwfilter.c @@ -39,6 +39,8 @@ virshCommandOptNWFilterBy(vshControl *ctl, const vshCmd *cmd, virNWFilterPtr nwfilter = NULL; const char *n = NULL; const char *optname = "nwfilter"; + virshControlPtr priv = ctl->privData; + virCheckFlags(VSH_BYUUID | VSH_BYNAME, NULL); if (vshCommandOptStringReq(ctl, cmd, optname, &n) < 0) @@ -54,13 +56,13 @@ virshCommandOptNWFilterBy(vshControl *ctl, const vshCmd *cmd, if ((flags & VSH_BYUUID) && strlen(n) == VIR_UUID_STRING_BUFLEN-1) { vshDebug(ctl, VSH_ERR_DEBUG, "%s: <%s> trying as nwfilter UUID\n", cmd->def->name, optname); - nwfilter = virNWFilterLookupByUUIDString(ctl->conn, n); + nwfilter = virNWFilterLookupByUUIDString(priv->conn, n); } /* try it by NAME */ if (!nwfilter && (flags & VSH_BYNAME)) { vshDebug(ctl, VSH_ERR_DEBUG, "%s: <%s> trying as nwfilter NAME\n", cmd->def->name, optname); - nwfilter = virNWFilterLookupByName(ctl->conn, n); + nwfilter = virNWFilterLookupByName(priv->conn, n); } if (!nwfilter) @@ -98,6 +100,7 @@ cmdNWFilterDefine(vshControl *ctl, const vshCmd *cmd) const char *from = NULL; bool ret = true; char *buffer; + virshControlPtr priv = ctl->privData; if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0) return false; @@ -105,7 +108,7 @@ cmdNWFilterDefine(vshControl *ctl, const vshCmd *cmd) if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) return false; - nwfilter = virNWFilterDefineXML(ctl->conn, buffer); + nwfilter = virNWFilterDefineXML(priv->conn, buffer); VIR_FREE(buffer); if (nwfilter != NULL) { @@ -255,9 +258,10 @@ vshNWFilterListCollect(vshControl *ctl, size_t deleted = 0; int nfilters = 0; char **names = NULL; + virshControlPtr priv = ctl->privData; /* try the list with flags support (0.10.2 and later) */ - if ((ret = virConnectListAllNWFilters(ctl->conn, + if ((ret = virConnectListAllNWFilters(priv->conn, &list->filters, flags)) >= 0) { list->nfilters = ret; @@ -279,7 +283,7 @@ vshNWFilterListCollect(vshControl *ctl, /* fall back to old method (0.9.13 and older) */ vshResetLibvirtError(); - nfilters = virConnectNumOfNWFilters(ctl->conn); + nfilters = virConnectNumOfNWFilters(priv->conn); if (nfilters < 0) { vshError(ctl, "%s", _("Failed to count network filters")); goto cleanup; @@ -290,7 +294,7 @@ vshNWFilterListCollect(vshControl *ctl, names = vshMalloc(ctl, sizeof(char *) * nfilters); - nfilters = virConnectListNWFilters(ctl->conn, names, nfilters); + nfilters = virConnectListNWFilters(priv->conn, names, nfilters); if (nfilters < 0) { vshError(ctl, "%s", _("Failed to list network filters")); goto cleanup; @@ -301,7 +305,7 @@ vshNWFilterListCollect(vshControl *ctl, /* get the network filters */ for (i = 0; i < nfilters; i++) { - if (!(filter = virNWFilterLookupByName(ctl->conn, names[i]))) + if (!(filter = virNWFilterLookupByName(priv->conn, names[i]))) continue; list->filters[list->nfilters++] = filter; } @@ -406,6 +410,7 @@ cmdNWFilterEdit(vshControl *ctl, const vshCmd *cmd) bool ret = false; virNWFilterPtr nwfilter = NULL; virNWFilterPtr nwfilter_edited = NULL; + virshControlPtr priv = ctl->privData; nwfilter = virshCommandOptNWFilter(ctl, cmd, NULL); if (nwfilter == NULL) @@ -421,7 +426,7 @@ cmdNWFilterEdit(vshControl *ctl, const vshCmd *cmd) goto edit_cleanup; \ } while (0) #define EDIT_DEFINE \ - (nwfilter_edited = virNWFilterDefineXML(ctl->conn, doc_edited)) + (nwfilter_edited = virNWFilterDefineXML(priv->conn, doc_edited)) #include "virsh-edit.c" vshPrint(ctl, _("Network filter %s XML configuration edited.\n"), diff --git a/tools/virsh-pool.c b/tools/virsh-pool.c index 19c1f28..f87b73c 100644 --- a/tools/virsh-pool.c +++ b/tools/virsh-pool.c @@ -39,6 +39,8 @@ virshCommandOptPoolBy(vshControl *ctl, const vshCmd *cmd, const char *optname, { virStoragePoolPtr pool = NULL; const char *n = NULL; + virshControlPtr priv = ctl->privData; + virCheckFlags(VSH_BYUUID | VSH_BYNAME, NULL); if (vshCommandOptStringReq(ctl, cmd, optname, &n) < 0) @@ -54,13 +56,13 @@ virshCommandOptPoolBy(vshControl *ctl, const vshCmd *cmd, const char *optname, if ((flags & VSH_BYUUID) && strlen(n) == VIR_UUID_STRING_BUFLEN-1) { vshDebug(ctl, VSH_ERR_DEBUG, "%s: <%s> trying as pool UUID\n", cmd->def->name, optname); - pool = virStoragePoolLookupByUUIDString(ctl->conn, n); + pool = virStoragePoolLookupByUUIDString(priv->conn, n); } /* try it by NAME */ if (!pool && (flags & VSH_BYNAME)) { vshDebug(ctl, VSH_ERR_DEBUG, "%s: <%s> trying as pool NAME\n", cmd->def->name, optname); - pool = virStoragePoolLookupByName(ctl->conn, n); + pool = virStoragePoolLookupByName(priv->conn, n); } if (!pool) @@ -154,6 +156,7 @@ cmdPoolCreate(vshControl *ctl, const vshCmd *cmd) const char *from = NULL; bool ret = true; char *buffer; + virshControlPtr priv = ctl->privData; if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0) return false; @@ -161,7 +164,7 @@ cmdPoolCreate(vshControl *ctl, const vshCmd *cmd) if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) return false; - pool = virStoragePoolCreateXML(ctl->conn, buffer, 0); + pool = virStoragePoolCreateXML(priv->conn, buffer, 0); VIR_FREE(buffer); if (pool != NULL) { @@ -365,6 +368,7 @@ cmdPoolCreateAs(vshControl *ctl, const vshCmd *cmd) const char *name; char *xml; bool printXML = vshCommandOptBool(cmd, "print-xml"); + virshControlPtr priv = ctl->privData; if (!vshBuildPoolXML(ctl, cmd, &name, &xml)) return false; @@ -373,7 +377,7 @@ cmdPoolCreateAs(vshControl *ctl, const vshCmd *cmd) vshPrint(ctl, "%s", xml); VIR_FREE(xml); } else { - pool = virStoragePoolCreateXML(ctl->conn, xml, 0); + pool = virStoragePoolCreateXML(priv->conn, xml, 0); VIR_FREE(xml); if (pool != NULL) { @@ -417,6 +421,7 @@ cmdPoolDefine(vshControl *ctl, const vshCmd *cmd) const char *from = NULL; bool ret = true; char *buffer; + virshControlPtr priv = ctl->privData; if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0) return false; @@ -424,7 +429,7 @@ cmdPoolDefine(vshControl *ctl, const vshCmd *cmd) if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) return false; - pool = virStoragePoolDefineXML(ctl->conn, buffer, 0); + pool = virStoragePoolDefineXML(priv->conn, buffer, 0); VIR_FREE(buffer); if (pool != NULL) { @@ -458,6 +463,7 @@ cmdPoolDefineAs(vshControl *ctl, const vshCmd *cmd) const char *name; char *xml; bool printXML = vshCommandOptBool(cmd, "print-xml"); + virshControlPtr priv = ctl->privData; if (!vshBuildPoolXML(ctl, cmd, &name, &xml)) return false; @@ -466,7 +472,7 @@ cmdPoolDefineAs(vshControl *ctl, const vshCmd *cmd) vshPrint(ctl, "%s", xml); VIR_FREE(xml); } else { - pool = virStoragePoolDefineXML(ctl->conn, xml, 0); + pool = virStoragePoolDefineXML(priv->conn, xml, 0); VIR_FREE(xml); if (pool != NULL) { @@ -774,9 +780,10 @@ vshStoragePoolListCollect(vshControl *ctl, int nActivePools = 0; int nInactivePools = 0; int nAllPools = 0; + virshControlPtr priv = ctl->privData; /* try the list with flags support (0.10.2 and later) */ - if ((ret = virConnectListAllStoragePools(ctl->conn, + if ((ret = virConnectListAllStoragePools(priv->conn, &list->pools, flags)) >= 0) { list->npools = ret; @@ -792,7 +799,7 @@ vshStoragePoolListCollect(vshControl *ctl, unsigned int newflags = flags & (VIR_CONNECT_LIST_STORAGE_POOLS_ACTIVE | VIR_CONNECT_LIST_STORAGE_POOLS_INACTIVE); vshResetLibvirtError(); - if ((ret = virConnectListAllStoragePools(ctl->conn, &list->pools, + if ((ret = virConnectListAllStoragePools(priv->conn, &list->pools, newflags)) >= 0) { list->npools = ret; goto filter; @@ -818,7 +825,7 @@ vshStoragePoolListCollect(vshControl *ctl, /* Get the number of active pools */ if (!VSH_MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_ACTIVE) || VSH_MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_ACTIVE)) { - if ((nActivePools = virConnectNumOfStoragePools(ctl->conn)) < 0) { + if ((nActivePools = virConnectNumOfStoragePools(priv->conn)) < 0) { vshError(ctl, "%s", _("Failed to get the number of active pools ")); goto cleanup; } @@ -827,7 +834,7 @@ vshStoragePoolListCollect(vshControl *ctl, /* Get the number of inactive pools */ if (!VSH_MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_ACTIVE) || VSH_MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_INACTIVE)) { - if ((nInactivePools = virConnectNumOfDefinedStoragePools(ctl->conn)) < 0) { + if ((nInactivePools = virConnectNumOfDefinedStoragePools(priv->conn)) < 0) { vshError(ctl, "%s", _("Failed to get the number of inactive pools")); goto cleanup; } @@ -843,7 +850,7 @@ vshStoragePoolListCollect(vshControl *ctl, /* Retrieve a list of active storage pool names */ if (!VSH_MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_ACTIVE) || VSH_MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_ACTIVE)) { - if (virConnectListStoragePools(ctl->conn, + if (virConnectListStoragePools(priv->conn, names, nActivePools) < 0) { vshError(ctl, "%s", _("Failed to list active pools")); goto cleanup; @@ -853,7 +860,7 @@ vshStoragePoolListCollect(vshControl *ctl, /* Add the inactive storage pools to the end of the name list */ if (!VSH_MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_ACTIVE) || VSH_MATCH(VIR_CONNECT_LIST_STORAGE_POOLS_ACTIVE)) { - if (virConnectListDefinedStoragePools(ctl->conn, + if (virConnectListDefinedStoragePools(priv->conn, &names[nActivePools], nInactivePools) < 0) { vshError(ctl, "%s", _("Failed to list inactive pools")); @@ -866,14 +873,14 @@ vshStoragePoolListCollect(vshControl *ctl, /* get active pools */ for (i = 0; i < nActivePools; i++) { - if (!(pool = virStoragePoolLookupByName(ctl->conn, names[i]))) + if (!(pool = virStoragePoolLookupByName(priv->conn, names[i]))) continue; list->pools[list->npools++] = pool; } /* get inactive pools */ for (i = 0; i < nInactivePools; i++) { - if (!(pool = virStoragePoolLookupByName(ctl->conn, names[i]))) + if (!(pool = virStoragePoolLookupByName(priv->conn, names[i]))) continue; list->pools[list->npools++] = pool; } @@ -1416,6 +1423,7 @@ cmdPoolDiscoverSourcesAs(vshControl * ctl, const vshCmd * cmd ATTRIBUTE_UNUSED) char *srcSpec = NULL; char *srcList; const char *initiator = NULL; + virshControlPtr priv = ctl->privData; if (vshCommandOptStringReq(ctl, cmd, "type", &type) < 0 || vshCommandOptStringReq(ctl, cmd, "host", &host) < 0 || @@ -1453,7 +1461,7 @@ cmdPoolDiscoverSourcesAs(vshControl * ctl, const vshCmd * cmd ATTRIBUTE_UNUSED) srcSpec = virBufferContentAndReset(&buf); } - srcList = virConnectFindStoragePoolSources(ctl->conn, type, srcSpec, 0); + srcList = virConnectFindStoragePoolSources(priv->conn, type, srcSpec, 0); VIR_FREE(srcSpec); if (srcList == NULL) { vshError(ctl, _("Failed to find any %s pool sources"), type); @@ -1496,6 +1504,7 @@ cmdPoolDiscoverSources(vshControl * ctl, const vshCmd * cmd ATTRIBUTE_UNUSED) { const char *type = NULL, *srcSpecFile = NULL; char *srcSpec = NULL, *srcList; + virshControlPtr priv = ctl->privData; if (vshCommandOptStringReq(ctl, cmd, "type", &type) < 0) return false; @@ -1507,7 +1516,7 @@ cmdPoolDiscoverSources(vshControl * ctl, const vshCmd * cmd ATTRIBUTE_UNUSED) &srcSpec) < 0) return false; - srcList = virConnectFindStoragePoolSources(ctl->conn, type, srcSpec, 0); + srcList = virConnectFindStoragePoolSources(priv->conn, type, srcSpec, 0); VIR_FREE(srcSpec); if (srcList == NULL) { vshError(ctl, _("Failed to find any %s pool sources"), type); @@ -1790,6 +1799,7 @@ cmdPoolEdit(vshControl *ctl, const vshCmd *cmd) virStoragePoolPtr pool_edited = NULL; unsigned int flags = VIR_STORAGE_XML_INACTIVE; char *tmp_desc = NULL; + virshControlPtr priv = ctl->privData; pool = virshCommandOptPool(ctl, cmd, "pool", NULL); if (pool == NULL) @@ -1816,7 +1826,7 @@ cmdPoolEdit(vshControl *ctl, const vshCmd *cmd) goto edit_cleanup; \ } while (0) #define EDIT_DEFINE \ - (pool_edited = virStoragePoolDefineXML(ctl->conn, doc_edited, 0)) + (pool_edited = virStoragePoolDefineXML(priv->conn, doc_edited, 0)) #include "virsh-edit.c" vshPrint(ctl, _("Pool %s XML configuration edited.\n"), diff --git a/tools/virsh-secret.c b/tools/virsh-secret.c index d78ef9d..e1fec56 100644 --- a/tools/virsh-secret.c +++ b/tools/virsh-secret.c @@ -40,6 +40,7 @@ virshCommandOptSecret(vshControl *ctl, const vshCmd *cmd, const char **name) virSecretPtr secret = NULL; const char *n = NULL; const char *optname = "secret"; + virshControlPtr priv = ctl->privData; if (vshCommandOptStringReq(ctl, cmd, optname, &n) < 0) return NULL; @@ -50,7 +51,7 @@ virshCommandOptSecret(vshControl *ctl, const vshCmd *cmd, const char **name) if (name != NULL) *name = n; - secret = virSecretLookupByUUIDString(ctl->conn, n); + secret = virSecretLookupByUUIDString(priv->conn, n); if (secret == NULL) vshError(ctl, _("failed to get secret '%s'"), n); @@ -88,6 +89,7 @@ cmdSecretDefine(vshControl *ctl, const vshCmd *cmd) virSecretPtr res; char uuid[VIR_UUID_STRING_BUFLEN]; bool ret = false; + virshControlPtr priv = ctl->privData; if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0) return false; @@ -95,7 +97,7 @@ cmdSecretDefine(vshControl *ctl, const vshCmd *cmd) if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) return false; - if (!(res = virSecretDefineXML(ctl->conn, buffer, 0))) { + if (!(res = virSecretDefineXML(priv->conn, buffer, 0))) { vshError(ctl, _("Failed to set attributes from %s"), from); goto cleanup; } @@ -383,9 +385,10 @@ vshSecretListCollect(vshControl *ctl, size_t deleted = 0; int nsecrets = 0; char **uuids = NULL; + virshControlPtr priv = ctl->privData; /* try the list with flags support (0.10.2 and later) */ - if ((ret = virConnectListAllSecrets(ctl->conn, + if ((ret = virConnectListAllSecrets(priv->conn, &list->secrets, flags)) >= 0) { list->nsecrets = ret; @@ -410,7 +413,7 @@ vshSecretListCollect(vshControl *ctl, goto cleanup; } - nsecrets = virConnectNumOfSecrets(ctl->conn); + nsecrets = virConnectNumOfSecrets(priv->conn); if (nsecrets < 0) { vshError(ctl, "%s", _("Failed to count secrets")); goto cleanup; @@ -421,7 +424,7 @@ vshSecretListCollect(vshControl *ctl, uuids = vshMalloc(ctl, sizeof(char *) * nsecrets); - nsecrets = virConnectListSecrets(ctl->conn, uuids, nsecrets); + nsecrets = virConnectListSecrets(priv->conn, uuids, nsecrets); if (nsecrets < 0) { vshError(ctl, "%s", _("Failed to list secrets")); goto cleanup; @@ -432,7 +435,7 @@ vshSecretListCollect(vshControl *ctl, /* get the secrets */ for (i = 0; i < nsecrets; i++) { - if (!(secret = virSecretLookupByUUIDString(ctl->conn, uuids[i]))) + if (!(secret = virSecretLookupByUUIDString(priv->conn, uuids[i]))) continue; list->secrets[list->nsecrets++] = secret; } diff --git a/tools/virsh-snapshot.c b/tools/virsh-snapshot.c index 5130479..839a322 100644 --- a/tools/virsh-snapshot.c +++ b/tools/virsh-snapshot.c @@ -763,11 +763,12 @@ vshGetSnapshotParent(vshControl *ctl, virDomainSnapshotPtr snapshot, xmlDocPtr xmldoc = NULL; xmlXPathContextPtr ctxt = NULL; int ret = -1; + virshControlPtr priv = ctl->privData; *parent_name = NULL; /* Try new API, since it is faster. */ - if (!ctl->useSnapshotOld) { + if (!priv->useSnapshotOld) { parent = virDomainSnapshotGetParent(snapshot, 0); if (parent) { /* API works, and virDomainSnapshotGetName will succeed */ @@ -781,7 +782,7 @@ vshGetSnapshotParent(vshControl *ctl, virDomainSnapshotPtr snapshot, goto cleanup; } /* API didn't work, fall back to XML scraping. */ - ctl->useSnapshotOld = true; + priv->useSnapshotOld = true; } xml = virDomainSnapshotGetXMLDesc(snapshot, 0); @@ -914,6 +915,7 @@ cmdSnapshotInfo(vshControl *ctl, const vshCmd *cmd) unsigned int flags; int current; int metadata; + virshControlPtr priv = ctl->privData; dom = virshCommandOptDomain(ctl, cmd, NULL); if (dom == NULL) @@ -996,7 +998,7 @@ cmdSnapshotInfo(vshControl *ctl, const vshCmd *cmd) /* Children, Descendants. After this point, the fallback to * compute children is too expensive, so we gracefully quit if the * APIs don't exist. */ - if (ctl->useSnapshotOld) { + if (priv->useSnapshotOld) { ret = true; goto cleanup; } @@ -1108,9 +1110,10 @@ vshSnapshotListCollect(vshControl *ctl, virDomainPtr dom, int deleted = 0; bool filter_fallback = false; unsigned int flags = orig_flags; + virshControlPtr priv = ctl->privData; /* Try the interface available in 0.9.13 and newer. */ - if (!ctl->useSnapshotOld) { + if (!priv->useSnapshotOld) { if (from) count = virDomainSnapshotListAllChildren(from, &snaps, flags); else @@ -1212,13 +1215,13 @@ vshSnapshotListCollect(vshControl *ctl, virDomainPtr dom, flags |= VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS; /* Determine if we can use the new child listing API. */ - if (ctl->useSnapshotOld || + if (priv->useSnapshotOld || ((count = virDomainSnapshotNumChildren(from, flags)) < 0 && last_error->code == VIR_ERR_NO_SUPPORT)) { /* We can emulate --from. */ /* XXX can we also emulate --leaves? */ vshResetLibvirtError(); - ctl->useSnapshotOld = true; + priv->useSnapshotOld = true; flags &= ~VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS; goto global; } @@ -1253,7 +1256,7 @@ vshSnapshotListCollect(vshControl *ctl, virDomainPtr dom, names = vshCalloc(ctl, sizeof(*names), count); /* Now that we have a count, collect the list. */ - if (from && !ctl->useSnapshotOld) { + if (from && !priv->useSnapshotOld) { if (tree) { if (count) count = virDomainSnapshotListChildrenNames(from, names + 1, @@ -1285,9 +1288,9 @@ vshSnapshotListCollect(vshControl *ctl, virDomainPtr dom, * --from together put from as the first element without a parent; * with the old API we still need to do a post-process filtering * based on all parent information. */ - if (tree || (from && ctl->useSnapshotOld) || roots) { - for (i = (from && !ctl->useSnapshotOld); i < count; i++) { - if (from && ctl->useSnapshotOld && STREQ(names[i], fromname)) { + if (tree || (from && priv->useSnapshotOld) || roots) { + for (i = (from && !priv->useSnapshotOld); i < count; i++) { + if (from && priv->useSnapshotOld && STREQ(names[i], fromname)) { start_index = i; if (tree) continue; @@ -1310,7 +1313,7 @@ vshSnapshotListCollect(vshControl *ctl, virDomainPtr dom, if (tree) goto success; - if (ctl->useSnapshotOld && descendants) { + if (priv->useSnapshotOld && descendants) { bool changed = false; bool remaining = false; diff --git a/tools/virsh-volume.c b/tools/virsh-volume.c index 21b7fb0..11b54ce 100644 --- a/tools/virsh-volume.c +++ b/tools/virsh-volume.c @@ -51,6 +51,8 @@ virshCommandOptVolBy(vshControl *ctl, const vshCmd *cmd, virStorageVolPtr vol = NULL; virStoragePoolPtr pool = NULL; const char *n = NULL, *p = NULL; + virshControlPtr priv = ctl->privData; + virCheckFlags(VSH_BYUUID | VSH_BYNAME, NULL); if (vshCommandOptStringReq(ctl, cmd, optname, &n) < 0) @@ -87,13 +89,13 @@ virshCommandOptVolBy(vshControl *ctl, const vshCmd *cmd, if (!vol && (flags & VSH_BYUUID)) { vshDebug(ctl, VSH_ERR_DEBUG, "%s: <%s> trying as vol key\n", cmd->def->name, optname); - vol = virStorageVolLookupByKey(ctl->conn, n); + vol = virStorageVolLookupByKey(priv->conn, n); } /* try it by path */ if (!vol && (flags & VSH_BYUUID)) { vshDebug(ctl, VSH_ERR_DEBUG, "%s: <%s> trying as vol path\n", cmd->def->name, optname); - vol = virStorageVolLookupByPath(ctl->conn, n); + vol = virStorageVolLookupByPath(priv->conn, n); } if (!vol) { @@ -201,6 +203,7 @@ cmdVolCreateAs(vshControl *ctl, const vshCmd *cmd) unsigned long long capacity, allocation = 0; virBuffer buf = VIR_BUFFER_INITIALIZER; unsigned long flags = 0; + virshControlPtr priv = ctl->privData; if (vshCommandOptBool(cmd, "prealloc-metadata")) flags |= VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA; @@ -265,7 +268,7 @@ cmdVolCreateAs(vshControl *ctl, const vshCmd *cmd) vshDebug(ctl, VSH_ERR_DEBUG, "%s: Look up backing store volume '%s' as key\n", cmd->def->name, snapshotStrVol); - snapVol = virStorageVolLookupByKey(ctl->conn, snapshotStrVol); + snapVol = virStorageVolLookupByKey(priv->conn, snapshotStrVol); if (snapVol) vshDebug(ctl, VSH_ERR_DEBUG, "%s: Backing store volume found using '%s' as key\n", @@ -277,7 +280,7 @@ cmdVolCreateAs(vshControl *ctl, const vshCmd *cmd) vshDebug(ctl, VSH_ERR_DEBUG, "%s: Look up backing store volume '%s' as path\n", cmd->def->name, snapshotStrVol); - snapVol = virStorageVolLookupByPath(ctl->conn, snapshotStrVol); + snapVol = virStorageVolLookupByPath(priv->conn, snapshotStrVol); if (snapVol) vshDebug(ctl, VSH_ERR_DEBUG, "%s: Backing store volume found using '%s' as path\n", @@ -692,6 +695,7 @@ cmdVolUpload(vshControl *ctl, const vshCmd *cmd) virStreamPtr st = NULL; const char *name = NULL; unsigned long long offset = 0, length = 0; + virshControlPtr priv = ctl->privData; if (vshCommandOptULongLong(ctl, cmd, "offset", &offset) < 0) return false; @@ -710,7 +714,7 @@ cmdVolUpload(vshControl *ctl, const vshCmd *cmd) goto cleanup; } - if (!(st = virStreamNew(ctl->conn, 0))) { + if (!(st = virStreamNew(priv->conn, 0))) { vshError(ctl, _("cannot create a new stream")); goto cleanup; } @@ -797,6 +801,7 @@ cmdVolDownload(vshControl *ctl, const vshCmd *cmd) const char *name = NULL; unsigned long long offset = 0, length = 0; bool created = false; + virshControlPtr priv = ctl->privData; if (vshCommandOptULongLong(ctl, cmd, "offset", &offset) < 0) return false; @@ -820,7 +825,7 @@ cmdVolDownload(vshControl *ctl, const vshCmd *cmd) created = true; } - if (!(st = virStreamNew(ctl->conn, 0))) { + if (!(st = virStreamNew(priv->conn, 0))) { vshError(ctl, _("cannot create a new stream")); goto cleanup; } diff --git a/tools/virsh.c b/tools/virsh.c index 9280b40..404deb8 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -192,10 +192,10 @@ static void virshReconnect(vshControl *ctl) { bool connected = false; + virshControlPtr priv = ctl->privData; - if (ctl->conn) { + if (priv->conn) { int ret; - connected = true; virConnectUnregisterCloseCallback(priv->conn, virshCatchDisconnect); @@ -207,24 +207,24 @@ virshReconnect(vshControl *ctl) "disconnect from the hypervisor")); } - ctl->conn = virshConnect(ctl, ctl->name, ctl->readonly); + priv->conn = virshConnect(ctl, ctl->name, priv->readonly); - if (!ctl->conn) { + if (!priv->conn) { if (disconnected) vshError(ctl, "%s", _("Failed to reconnect to the hypervisor")); else vshError(ctl, "%s", _("failed to connect to the hypervisor")); } else { - if (virConnectRegisterCloseCallback(ctl->conn, virshCatchDisconnect, + if (virConnectRegisterCloseCallback(priv->conn, virshCatchDisconnect, NULL, NULL) < 0) vshError(ctl, "%s", _("Unable to register disconnect callback")); if (connected) vshError(ctl, "%s", _("Reconnected to the hypervisor")); } disconnected = 0; - ctl->useGetInfo = false; - ctl->useSnapshotOld = false; - ctl->blockJobNoBytes = false; + priv->useGetInfo = false; + priv->useSnapshotOld = false; + priv->blockJobNoBytes = false; } @@ -260,18 +260,19 @@ cmdConnect(vshControl *ctl, const vshCmd *cmd) { bool ro = vshCommandOptBool(cmd, "readonly"); const char *name = NULL; + virshControlPtr priv = ctl->privData; - if (ctl->conn) { + if (priv->conn) { int ret; - ret = virConnectClose(ctl->conn); virConnectUnregisterCloseCallback(priv->conn, virshCatchDisconnect); + ret = virConnectClose(priv->conn); if (ret < 0) vshError(ctl, "%s", _("Failed to disconnect from the hypervisor")); else if (ret > 0) vshError(ctl, "%s", _("One or more references were leaked after " "disconnect from the hypervisor")); - ctl->conn = NULL; + priv->conn = NULL; } VIR_FREE(ctl->name); @@ -280,19 +281,19 @@ cmdConnect(vshControl *ctl, const vshCmd *cmd) ctl->name = vshStrdup(ctl, name); - ctl->useGetInfo = false; - ctl->useSnapshotOld = false; - ctl->blockJobNoBytes = false; - ctl->readonly = ro; + priv->useGetInfo = false; + priv->useSnapshotOld = false; + priv->blockJobNoBytes = false; + priv->readonly = ro; - ctl->conn = virshConnect(ctl, ctl->name, ctl->readonly); + priv->conn = virshConnect(ctl, ctl->name, priv->readonly); - if (!ctl->conn) { + if (!priv->conn) { vshError(ctl, "%s", _("Failed to connect to the hypervisor")); return false; } - if (virConnectRegisterCloseCallback(ctl->conn, virshCatchDisconnect, + if (virConnectRegisterCloseCallback(priv->conn, virshCatchDisconnect, NULL, NULL) < 0) vshError(ctl, "%s", _("Unable to register disconnect callback")); @@ -1267,6 +1268,7 @@ virshParseArgv(vshControl *ctl, int argc, char **argv) int arg, len, debug, keepalive; size_t i; int longindex = -1; + virshControlPtr priv = ctl->privData; struct option opt[] = { {"connect", required_argument, NULL, 'c'}, {"debug", required_argument, NULL, 'd'}, @@ -1309,7 +1311,7 @@ virshParseArgv(vshControl *ctl, int argc, char **argv) if ((len == 2 && *optarg == '^' && virshAllowedEscapeChar(optarg[1])) || (len == 1 && *optarg != '^')) { - ctl->escapeChar = optarg; + priv->escapeChar = optarg; } else { vshError(ctl, _("Invalid string '%s' for escape sequence"), optarg); @@ -1364,7 +1366,7 @@ virshParseArgv(vshControl *ctl, int argc, char **argv) ctl->timing = true; break; case 'r': - ctl->readonly = true; + priv->readonly = true; break; case 'v': if (STRNEQ_NULLABLE(optarg, "long")) { @@ -1474,18 +1476,23 @@ static const vshCmdGrp cmdGroups[] = { {NULL, NULL, NULL} }; +static const vshClientHooks hooks = { + .connHandler = virshConnectionHandler +}; + int main(int argc, char **argv) { vshControl _ctl, *ctl = &_ctl; + virshControl virshCtl; const char *defaultConn; bool ret = true; memset(ctl, 0, sizeof(vshControl)); + memset(&virshCtl, 0, sizeof(virshControl)); ctl->imode = true; /* default is interactive mode */ ctl->log_fd = -1; /* Initialize log file descriptor */ ctl->debug = VSH_DEBUG_DEFAULT; - ctl->escapeChar = "^]"; /* Same default as telnet */ /* In order to distinguish default from setting to 0 */ ctl->keepalive_interval = -1; @@ -1494,6 +1501,14 @@ main(int argc, char **argv) ctl->eventPipe[0] = -1; ctl->eventPipe[1] = -1; ctl->eventTimerId = -1; + virshCtl.escapeChar = "^]"; /* Same default as telnet */ + ctl->privData = &virshCtl; + + if (!(progname = strrchr(argv[0], '/'))) + progname = argv[0]; + else + progname++; + ctl->progname = progname; if (!setlocale(LC_ALL, "")) { perror("setlocale"); -- 1.9.3

--- tools/virsh.c | 1 + tools/vsh.c | 1 + tools/vsh.h | 6 ++++++ 3 files changed, 8 insertions(+) diff --git a/tools/virsh.c b/tools/virsh.c index 404deb8..017a669 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -82,6 +82,7 @@ static char *progname; static const vshCmdGrp cmdGroups[]; +static const vshClientHooks hooks; double virshPrettyCapacity(unsigned long long val, const char **unit) diff --git a/tools/vsh.c b/tools/vsh.c index 71c8344..5f8461c 100644 --- a/tools/vsh.c +++ b/tools/vsh.c @@ -67,6 +67,7 @@ # define SA_SIGINFO 0 #endif +static const vshClientHooks *hooks; static const vshCmdGrp *cmdGroups; /* Bypass header poison */ diff --git a/tools/vsh.h b/tools/vsh.h index aaeb086..eae38d5 100644 --- a/tools/vsh.h +++ b/tools/vsh.h @@ -114,6 +114,7 @@ enum { }; /* forward declarations */ +typedef struct _vshClientHooks vshClientHooks; typedef struct _vshCmd vshCmd; typedef struct _vshCmdDef vshCmdDef; typedef struct _vshCmdGrp vshCmdGrp; @@ -223,6 +224,11 @@ struct _vshControl { void *privData; /* client specific data */ }; +typedef void * +(*vshConnectionHook)(vshControl *ctl); + +struct _vshClientHooks { + vshConnectionHook connHandler; }; struct _vshCmdGrp { -- 1.9.3

--- tools/vsh.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/tools/vsh.c b/tools/vsh.c index 5f8461c..4eb5de2 100644 --- a/tools/vsh.c +++ b/tools/vsh.c @@ -1137,15 +1137,11 @@ vshCommandRun(vshControl *ctl, const vshCmd *cmd) struct timeval before, after; bool enable_timing = ctl->timing; - if ((ctl->conn == NULL || disconnected) && - !(cmd->def->flags & VSH_CMD_FLAG_NOCONNECT)) - vshReconnect(ctl); - if (enable_timing) GETTIMEOFDAY(&before); if ((cmd->def->flags & VSH_CMD_FLAG_NOCONNECT) || - vshConnectionUsability(ctl, ctl->conn)) { + (hooks && hooks->connHandler && hooks->connHandler(ctl))) { ret = cmd->def->handler(ctl, cmd); } else { /* connection is not usable, return error */ -- 1.9.3

Right now, there's very little to do in global initializer besides registering client hooks, but there's a potential to have some more features that will need to be properly initialized beforehand (exporting vshControl pointer only would definitely make use of this). --- tools/vsh.c | 24 ++++++++++++++++++++++++ tools/vsh.h | 3 +++ 2 files changed, 27 insertions(+) diff --git a/tools/vsh.c b/tools/vsh.c index 4eb5de2..ed1fdb9 100644 --- a/tools/vsh.c +++ b/tools/vsh.c @@ -1942,6 +1942,30 @@ vshInitDebug(vshControl *ctl) } +/* + * Initialize global data + */ +int +vshInit(vshControl *ctl, + const vshClientHooks *clhooks, + const vshCmdGrp *clgrps) +{ + if (!clhooks || !clhooks->connHandler) { + vshError(ctl, "%s", _("client hooks must not be NULL")); + return -1; + } + + if (!clgrps) { + vshError(ctl, "%s", _("command groups must not be NULL")); + return -1; + } + + hooks = clhooks; + cmdGroups = clgrps; + vshInitDebug(ctl); + return 0; +} + #define LOGFILE_FLAGS (O_WRONLY | O_APPEND | O_CREAT | O_SYNC) /** diff --git a/tools/vsh.h b/tools/vsh.h index eae38d5..6bf742d 100644 --- a/tools/vsh.h +++ b/tools/vsh.h @@ -300,6 +300,9 @@ typedef enum { void vshPrintExtra(vshControl *ctl, const char *format, ...) ATTRIBUTE_FMT_PRINTF(2, 3); +int vshInit(vshControl *ctl, const vshClientHooks *clhooks, + const vshCmdGrp *clgrps) + ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); void vshDebug(vshControl *ctl, int level, const char *format, ...) ATTRIBUTE_FMT_PRINTF(3, 4); -- 1.9.3

Earlier, we have moved virsh generic methods into vsh module, but to make them really usable by other clients, they cannot be defined as static. --- tools/vsh.c | 22 +++++++++++----------- tools/vsh.h | 16 ++++++++++++++-- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/tools/vsh.c b/tools/vsh.c index ed1fdb9..9b810c9 100644 --- a/tools/vsh.c +++ b/tools/vsh.c @@ -1128,7 +1128,7 @@ vshCommandOptArgv(vshControl *ctl ATTRIBUTE_UNUSED, const vshCmd *cmd, /* * Executes command(s) and returns return code from last command */ -static bool +bool vshCommandRun(vshControl *ctl, const vshCmd *cmd) { bool ret = true; @@ -1415,7 +1415,7 @@ vshCommandArgvGetArg(vshControl *ctl, vshCommandParser *parser, char **res) return VSH_TK_ARG; } -static bool +bool vshCommandArgvParse(vshControl *ctl, int nargs, char **argv) { vshCommandParser parser; @@ -1494,7 +1494,7 @@ vshCommandStringGetArg(vshControl *ctl, vshCommandParser *parser, char **res) return VSH_TK_ARG; } -static bool +bool vshCommandStringParse(vshControl *ctl, char *cmdstr) { vshCommandParser parser; @@ -1745,7 +1745,7 @@ vshError(vshControl *ctl, const char *format, ...) } -static void +void vshEventLoop(void *opaque) { vshControl *ctl = opaque; @@ -1788,7 +1788,7 @@ vshEventInt(int sig ATTRIBUTE_UNUSED, /* Event loop handler used to limit length of waiting for any other event. */ -static void +void vshEventTimeout(int timer ATTRIBUTE_UNUSED, void *opaque) { @@ -1911,7 +1911,7 @@ vshEventCleanup(vshControl *ctl) /* * Initialize debug settings. */ -static void +void vshInitDebug(vshControl *ctl) { const char *debugEnv; @@ -2213,7 +2213,7 @@ vshReadlineCompletion(const char *text, int start, # define VIRSH_HISTSIZE_MAX 500000 -static int +int vshReadlineInit(vshControl *ctl) { char *userdir = NULL; @@ -2271,7 +2271,7 @@ vshReadlineInit(vshControl *ctl) return 0; } -static void +void vshReadlineDeinit(vshControl *ctl) { if (ctl->historyfile != NULL) { @@ -2289,7 +2289,7 @@ vshReadlineDeinit(vshControl *ctl) VIR_FREE(ctl->historyfile); } -static char * +char * vshReadline(vshControl *ctl ATTRIBUTE_UNUSED, const char *prompt) { return readline(prompt); @@ -2297,14 +2297,14 @@ vshReadline(vshControl *ctl ATTRIBUTE_UNUSED, const char *prompt) #else /* !WITH_READLINE */ -static int +int vshReadlineInit(vshControl *ctl ATTRIBUTE_UNUSED) { /* empty */ return 0; } -static void +void vshReadlineDeinit(vshControl *ctl ATTRIBUTE_UNUSED) { /* empty */ diff --git a/tools/vsh.h b/tools/vsh.h index 6bf742d..1ad0287 100644 --- a/tools/vsh.h +++ b/tools/vsh.h @@ -287,8 +287,12 @@ int vshCommandOptScaledInt(vshControl *ctl, const vshCmd *cmd, int scale, unsigned long long max) ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK; bool vshCommandOptBool(const vshCmd *cmd, const char *name); +bool vshCommandRun(vshControl *ctl, const vshCmd *cmd); +bool vshCommandStringParse(vshControl *ctl, char *cmdstr); + const vshCmdOpt *vshCommandOptArgv(vshControl *ctl, const vshCmd *cmd, const vshCmdOpt *opt); +bool vshCommandArgvParse(vshControl *ctl, int nargs, char **argv); /* Filter flags for various vshCommandOpt*By() functions */ typedef enum { @@ -303,6 +307,7 @@ void vshPrintExtra(vshControl *ctl, const char *format, ...) int vshInit(vshControl *ctl, const vshClientHooks *clhooks, const vshCmdGrp *clgrps) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); +void vshInitDebug(vshControl *ctl); void vshDebug(vshControl *ctl, int level, const char *format, ...) ATTRIBUTE_FMT_PRINTF(3, 4); @@ -341,10 +346,17 @@ enum { VSH_EVENT_TIMEOUT, VSH_EVENT_DONE, }; -int vshEventStart(vshControl *ctl, int timeout_ms); +void vshEventCleanup(vshControl *ctl); void vshEventDone(vshControl *ctl); +void vshEventLoop(void *opaque); +int vshEventStart(vshControl *ctl, int timeout_ms); +void vshEventTimeout(int timer, void *opaque); int vshEventWait(vshControl *ctl); -void vshEventCleanup(vshControl *ctl); + +/* readline */ +char * vshReadline(vshControl *ctl, const char *prompt); +int vshReadlineInit(vshControl *ctl); +void vshReadlineDeinit(vshControl *ctl); /* allocation wrappers */ void *_vshMalloc(vshControl *ctl, size_t sz, const char *filename, int line); -- 1.9.3

Before any virsh command can be executed, client connection to daemon needs to be checked, i.e. first we try to reconnect if needed and then check the connection usability which is connection type specific. This handler is registered as client hook. --- tools/virsh.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tools/virsh.c b/tools/virsh.c index 017a669..fcbd553 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -915,9 +915,17 @@ virshConnectionUsability(vshControl *ctl, virConnectPtr conn) return true; } +static void * +virshConnectionHandler(vshControl *ctl) { + virshControlPtr priv = ctl->privData; + if (!priv->conn || disconnected) + virshReconnect(ctl); + if (virshConnectionUsability(ctl, priv->conn)) + return priv->conn; + return NULL; } /* --------------- -- 1.9.3

--- tools/Makefile.am | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/Makefile.am b/tools/Makefile.am index 93d642d..03e9339 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -179,7 +179,11 @@ virt_login_shell_CFLAGS = \ $(PIE_CFLAGS) \ $(COVERAGE_CFLAGS) +virt_shell_SOURCES = \ + vsh.c vsh.h + virsh_SOURCES = \ + $(virt_shell_SOURCES) \ virsh.c virsh.h \ virsh-console.c virsh-console.h \ virsh-domain.c virsh-domain.h \ -- 1.9.3

On 29.06.2015 17:37, Erik Skultety wrote:
The idea behind this is that in order to introduce virt-admin client (and later some commands/APIs), there are lots of methods in virsh that can be easily reused by other potential clients like command and command argument passing or error reporting.
!!! IMPORTANT !!! These patches cannot be compiled separately, the series is split more or less logically into chunks only to be more readable by the reviewer. I started this at least 4 times from scratch and still haven't found a way that splitting virsh could be done with several independent applicable commits, rather than having one massive commit in the end.
Erik Skultety (13): tools: Introduce new client generic module vsh vsh: Remove client specific data, only generic data are kept tools: apply s/vshX/virshX to all virsh specific data virsh: remove generic data, only client specific are kept virsh: Rename client specific methods in virsh.h vsh: vshControl now includes client private data and client specific progname vsh: Make use of introduced private data vsh: Introduce client hooks vsh: Make use of newly introduced client side hooks vsh: Introduce new global initializer vsh: Make separated generic methods public virsh: Introduce connection handler tools: Update makefile to include 'vsh' sources as well
cfg.mk | 2 +- po/POTFILES.in | 3 +- tools/Makefile.am | 4 + tools/virsh-console.c | 13 +- tools/virsh-console.h | 8 +- tools/virsh-domain-monitor.c | 201 ++-- tools/virsh-domain-monitor.h | 4 +- tools/virsh-domain.c | 532 +++++---- tools/virsh-domain.h | 14 +- tools/virsh-edit.c | 8 +- tools/virsh-host.c | 131 ++- tools/virsh-interface.c | 80 +- tools/virsh-interface.h | 12 +- tools/virsh-network.c | 72 +- tools/virsh-network.h | 10 +- tools/virsh-nodedev.c | 37 +- tools/virsh-nwfilter.c | 33 +- tools/virsh-nwfilter.h | 10 +- tools/virsh-pool.c | 104 +- tools/virsh-pool.h | 10 +- tools/virsh-secret.c | 27 +- tools/virsh-snapshot.c | 75 +- tools/virsh-volume.c | 103 +- tools/virsh-volume.h | 14 +- tools/virsh.c | 2673 ++++-------------------------------------- tools/virsh.h | 481 +------- tools/vsh.c | 2332 ++++++++++++++++++++++++++++++++++++ tools/vsh.h | 489 ++++++++ 28 files changed, 3906 insertions(+), 3576 deletions(-) create mode 100644 tools/vsh.c create mode 100644 tools/vsh.h
This is rather big change. Do you perhaps have a public repo with all the patches applied? Michal

On 30.06.2015 16:12, Michal Privoznik wrote:
On 29.06.2015 17:37, Erik Skultety wrote:
The idea behind this is that in order to introduce virt-admin client (and later some commands/APIs), there are lots of methods in virsh that can be easily reused by other potential clients like command and command argument passing or error reporting.
!!! IMPORTANT !!! These patches cannot be compiled separately, the series is split more or less logically into chunks only to be more readable by the reviewer. I started this at least 4 times from scratch and still haven't found a way that splitting virsh could be done with several independent applicable commits, rather than having one massive commit in the end.
Erik Skultety (13): tools: Introduce new client generic module vsh vsh: Remove client specific data, only generic data are kept tools: apply s/vshX/virshX to all virsh specific data virsh: remove generic data, only client specific are kept virsh: Rename client specific methods in virsh.h vsh: vshControl now includes client private data and client specific progname vsh: Make use of introduced private data vsh: Introduce client hooks vsh: Make use of newly introduced client side hooks vsh: Introduce new global initializer vsh: Make separated generic methods public virsh: Introduce connection handler tools: Update makefile to include 'vsh' sources as well
cfg.mk | 2 +- po/POTFILES.in | 3 +- tools/Makefile.am | 4 + tools/virsh-console.c | 13 +- tools/virsh-console.h | 8 +- tools/virsh-domain-monitor.c | 201 ++-- tools/virsh-domain-monitor.h | 4 +- tools/virsh-domain.c | 532 +++++---- tools/virsh-domain.h | 14 +- tools/virsh-edit.c | 8 +- tools/virsh-host.c | 131 ++- tools/virsh-interface.c | 80 +- tools/virsh-interface.h | 12 +- tools/virsh-network.c | 72 +- tools/virsh-network.h | 10 +- tools/virsh-nodedev.c | 37 +- tools/virsh-nwfilter.c | 33 +- tools/virsh-nwfilter.h | 10 +- tools/virsh-pool.c | 104 +- tools/virsh-pool.h | 10 +- tools/virsh-secret.c | 27 +- tools/virsh-snapshot.c | 75 +- tools/virsh-volume.c | 103 +- tools/virsh-volume.h | 14 +- tools/virsh.c | 2673 ++++-------------------------------------- tools/virsh.h | 481 +------- tools/vsh.c | 2332 ++++++++++++++++++++++++++++++++++++ tools/vsh.h | 489 ++++++++ 28 files changed, 3906 insertions(+), 3576 deletions(-) create mode 100644 tools/vsh.c create mode 100644 tools/vsh.h
This is rather big change. Do you perhaps have a public repo with all the patches applied?
I've also noticed 03/13 is missing. Michal

This is rather big change. Do you perhaps have a public repo with all the patches applied?
I've also noticed 03/13 is missing.
Michal
I do have it in my inbox (I always CC myself when sending patches), I've also sent another copy earlier today... still nothing. I have no idea, where the problem might be. Erik

This is rather big change. Do you perhaps have a public repo with all the patches applied?
Michal
I forked libvirt mirror repo on github and pushed as my local branch virt-shell https://github.com/eskultety/libvirt/tree/virt-shell. Erik

Since majority of virsh methods should be generic enough to be used by other clients, it's much easier to rename virsh specific data to virshX than doing this vice versa. --- tools/virsh-console.c | 12 +- tools/virsh-console.h | 8 +- tools/virsh-domain-monitor.c | 178 +++++++++--------- tools/virsh-domain-monitor.h | 4 +- tools/virsh-domain.c | 434 +++++++++++++++++++++---------------------- tools/virsh-domain.h | 14 +- tools/virsh-edit.c | 8 +- tools/virsh-host.c | 53 +++--- tools/virsh-interface.c | 34 ++-- tools/virsh-interface.h | 12 +- tools/virsh-network.c | 36 ++-- tools/virsh-network.h | 10 +- tools/virsh-nodedev.c | 6 +- tools/virsh-nwfilter.c | 12 +- tools/virsh-nwfilter.h | 10 +- tools/virsh-pool.c | 60 +++--- tools/virsh-pool.h | 10 +- tools/virsh-secret.c | 12 +- tools/virsh-snapshot.c | 50 ++--- tools/virsh-volume.c | 86 ++++----- tools/virsh-volume.h | 14 +- tools/virsh.c | 302 ++++++++++-------------------- tools/virsh.h | 34 ++-- tools/vsh.c | 4 +- tools/vsh.h | 1 + 25 files changed, 654 insertions(+), 750 deletions(-) diff --git a/tools/virsh-console.c b/tools/virsh-console.c index f0faf8c..86ba456 100644 --- a/tools/virsh-console.c +++ b/tools/virsh-console.c @@ -295,7 +295,7 @@ virConsoleEventOnStdout(int watch ATTRIBUTE_UNUSED, static char -vshGetEscapeChar(const char *s) +virshGetEscapeChar(const char *s) { if (*s == '^') return CONTROL(c_toupper(s[1])); @@ -305,10 +305,10 @@ vshGetEscapeChar(const char *s) int -vshRunConsole(vshControl *ctl, - virDomainPtr dom, - const char *dev_name, - unsigned int flags) +virshRunConsole(vshControl *ctl, + virDomainPtr dom, + const char *dev_name, + unsigned int flags) { virConsolePtr con = NULL; int ret = -1; @@ -341,7 +341,7 @@ vshRunConsole(vshControl *ctl, if (VIR_ALLOC(con) < 0) goto cleanup; - con->escapeChar = vshGetEscapeChar(ctl->escapeChar); + con->escapeChar = virshGetEscapeChar(ctl->escapeChar); con->st = virStreamNew(virDomainGetConnect(dom), VIR_STREAM_NONBLOCK); if (!con->st) diff --git a/tools/virsh-console.h b/tools/virsh-console.h index 5b82e28..598d353 100644 --- a/tools/virsh-console.h +++ b/tools/virsh-console.h @@ -28,10 +28,10 @@ # include <virsh.h> -int vshRunConsole(vshControl *ctl, - virDomainPtr dom, - const char *dev_name, - unsigned int flags); +int virshRunConsole(vshControl *ctl, + virDomainPtr dom, + const char *dev_name, + unsigned int flags); # endif /* !WIN32 */ diff --git a/tools/virsh-domain-monitor.c b/tools/virsh-domain-monitor.c index 1d4dc25..1f53428 100644 --- a/tools/virsh-domain-monitor.c +++ b/tools/virsh-domain-monitor.c @@ -40,24 +40,24 @@ #include "virxml.h" #include "virstring.h" -VIR_ENUM_DECL(vshDomainIOError) -VIR_ENUM_IMPL(vshDomainIOError, +VIR_ENUM_DECL(virshDomainIOError) +VIR_ENUM_IMPL(virshDomainIOError, VIR_DOMAIN_DISK_ERROR_LAST, N_("no error"), N_("unspecified error"), N_("no space")) static const char * -vshDomainIOErrorToString(int error) +virshDomainIOErrorToString(int error) { - const char *str = vshDomainIOErrorTypeToString(error); + const char *str = virshDomainIOErrorTypeToString(error); return str ? _(str) : _("unknown error"); } /* extract description or title from domain xml */ char * -vshGetDomainDescription(vshControl *ctl, virDomainPtr dom, bool title, - unsigned int flags) +virshGetDomainDescription(vshControl *ctl, virDomainPtr dom, bool title, + unsigned int flags) { char *desc = NULL; char *domxml = NULL; @@ -113,8 +113,8 @@ vshGetDomainDescription(vshControl *ctl, virDomainPtr dom, bool title, return desc; } -VIR_ENUM_DECL(vshDomainControlState) -VIR_ENUM_IMPL(vshDomainControlState, +VIR_ENUM_DECL(virshDomainControlState) +VIR_ENUM_IMPL(virshDomainControlState, VIR_DOMAIN_CONTROL_LAST, N_("ok"), N_("background job"), @@ -122,14 +122,14 @@ VIR_ENUM_IMPL(vshDomainControlState, N_("error")) static const char * -vshDomainControlStateToString(int state) +virshDomainControlStateToString(int state) { - const char *str = vshDomainControlStateTypeToString(state); + const char *str = virshDomainControlStateTypeToString(state); return str ? _(str) : _("unknown"); } -VIR_ENUM_DECL(vshDomainControlErrorReason) -VIR_ENUM_IMPL(vshDomainControlErrorReason, +VIR_ENUM_DECL(virshDomainControlErrorReason) +VIR_ENUM_IMPL(virshDomainControlErrorReason, VIR_DOMAIN_CONTROL_ERROR_REASON_LAST, "", N_("unknown"), @@ -137,14 +137,14 @@ VIR_ENUM_IMPL(vshDomainControlErrorReason, N_("internal (locking) error")) static const char * -vshDomainControlErrorReasonToString(int reason) +virshDomainControlErrorReasonToString(int reason) { - const char *ret = vshDomainControlErrorReasonTypeToString(reason); + const char *ret = virshDomainControlErrorReasonTypeToString(reason); return ret ? _(ret) : _("unknown"); } -VIR_ENUM_DECL(vshDomainState) -VIR_ENUM_IMPL(vshDomainState, +VIR_ENUM_DECL(virshDomainState) +VIR_ENUM_IMPL(virshDomainState, VIR_DOMAIN_LAST, N_("no state"), N_("running"), @@ -156,19 +156,19 @@ VIR_ENUM_IMPL(vshDomainState, N_("pmsuspended")) static const char * -vshDomainStateToString(int state) +virshDomainStateToString(int state) { - const char *str = vshDomainStateTypeToString(state); + const char *str = virshDomainStateTypeToString(state); return str ? _(str) : _("no state"); } -VIR_ENUM_DECL(vshDomainNostateReason) -VIR_ENUM_IMPL(vshDomainNostateReason, +VIR_ENUM_DECL(virshDomainNostateReason) +VIR_ENUM_IMPL(virshDomainNostateReason, VIR_DOMAIN_NOSTATE_LAST, N_("unknown")) -VIR_ENUM_DECL(vshDomainRunningReason) -VIR_ENUM_IMPL(vshDomainRunningReason, +VIR_ENUM_DECL(virshDomainRunningReason) +VIR_ENUM_IMPL(virshDomainRunningReason, VIR_DOMAIN_RUNNING_LAST, N_("unknown"), N_("booted"), @@ -181,13 +181,13 @@ VIR_ENUM_IMPL(vshDomainRunningReason, N_("event wakeup"), N_("crashed")) -VIR_ENUM_DECL(vshDomainBlockedReason) -VIR_ENUM_IMPL(vshDomainBlockedReason, +VIR_ENUM_DECL(virshDomainBlockedReason) +VIR_ENUM_IMPL(virshDomainBlockedReason, VIR_DOMAIN_BLOCKED_LAST, N_("unknown")) -VIR_ENUM_DECL(vshDomainPausedReason) -VIR_ENUM_IMPL(vshDomainPausedReason, +VIR_ENUM_DECL(virshDomainPausedReason) +VIR_ENUM_IMPL(virshDomainPausedReason, VIR_DOMAIN_PAUSED_LAST, N_("unknown"), N_("user"), @@ -202,14 +202,14 @@ VIR_ENUM_IMPL(vshDomainPausedReason, N_("crashed"), N_("starting up")) -VIR_ENUM_DECL(vshDomainShutdownReason) -VIR_ENUM_IMPL(vshDomainShutdownReason, +VIR_ENUM_DECL(virshDomainShutdownReason) +VIR_ENUM_IMPL(virshDomainShutdownReason, VIR_DOMAIN_SHUTDOWN_LAST, N_("unknown"), N_("user")) -VIR_ENUM_DECL(vshDomainShutoffReason) -VIR_ENUM_IMPL(vshDomainShutoffReason, +VIR_ENUM_DECL(virshDomainShutoffReason) +VIR_ENUM_IMPL(virshDomainShutoffReason, VIR_DOMAIN_SHUTOFF_LAST, N_("unknown"), N_("shutdown"), @@ -220,45 +220,45 @@ VIR_ENUM_IMPL(vshDomainShutoffReason, N_("failed"), N_("from snapshot")) -VIR_ENUM_DECL(vshDomainCrashedReason) -VIR_ENUM_IMPL(vshDomainCrashedReason, +VIR_ENUM_DECL(virshDomainCrashedReason) +VIR_ENUM_IMPL(virshDomainCrashedReason, VIR_DOMAIN_CRASHED_LAST, N_("unknown"), N_("panicked")) -VIR_ENUM_DECL(vshDomainPMSuspendedReason) -VIR_ENUM_IMPL(vshDomainPMSuspendedReason, +VIR_ENUM_DECL(virshDomainPMSuspendedReason) +VIR_ENUM_IMPL(virshDomainPMSuspendedReason, VIR_DOMAIN_PMSUSPENDED_LAST, N_("unknown")) static const char * -vshDomainStateReasonToString(int state, int reason) +virshDomainStateReasonToString(int state, int reason) { const char *str = NULL; switch ((virDomainState) state) { case VIR_DOMAIN_NOSTATE: - str = vshDomainNostateReasonTypeToString(reason); + str = virshDomainNostateReasonTypeToString(reason); break; case VIR_DOMAIN_RUNNING: - str = vshDomainRunningReasonTypeToString(reason); + str = virshDomainRunningReasonTypeToString(reason); break; case VIR_DOMAIN_BLOCKED: - str = vshDomainBlockedReasonTypeToString(reason); + str = virshDomainBlockedReasonTypeToString(reason); break; case VIR_DOMAIN_PAUSED: - str = vshDomainPausedReasonTypeToString(reason); + str = virshDomainPausedReasonTypeToString(reason); break; case VIR_DOMAIN_SHUTDOWN: - str = vshDomainShutdownReasonTypeToString(reason); + str = virshDomainShutdownReasonTypeToString(reason); break; case VIR_DOMAIN_SHUTOFF: - str = vshDomainShutoffReasonTypeToString(reason); + str = virshDomainShutoffReasonTypeToString(reason); break; case VIR_DOMAIN_CRASHED: - str = vshDomainCrashedReasonTypeToString(reason); + str = virshDomainCrashedReasonTypeToString(reason); break; case VIR_DOMAIN_PMSUSPENDED: - str = vshDomainPMSuspendedReasonTypeToString(reason); + str = virshDomainPMSuspendedReasonTypeToString(reason); break; case VIR_DOMAIN_LAST: ; @@ -329,7 +329,7 @@ cmdDomMemStat(vshControl *ctl, const vshCmd *cmd) if (live) flags |= VIR_DOMAIN_AFFECT_LIVE; - if (!(dom = vshCommandOptDomain(ctl, cmd, &name))) + if (!(dom = virshCommandOptDomain(ctl, cmd, &name))) return false; /* If none of the options were specified and we're active @@ -423,7 +423,7 @@ cmdDomblkinfo(vshControl *ctl, const vshCmd *cmd) bool ret = false; const char *device = NULL; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; if (vshCommandOptStringReq(ctl, cmd, "device", &device) < 0) @@ -492,7 +492,7 @@ cmdDomblklist(vshControl *ctl, const vshCmd *cmd) details = vshCommandOptBool(cmd, "details"); - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; xml = virDomainGetXMLDesc(dom, flags); @@ -608,7 +608,7 @@ cmdDomiflist(vshControl *ctl, const vshCmd *cmd) if (vshCommandOptBool(cmd, "inactive")) flags |= VIR_DOMAIN_XML_INACTIVE; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; xml = virDomainGetXMLDesc(dom, flags); @@ -726,7 +726,7 @@ cmdDomIfGetLink(vshControl *ctl, const vshCmd *cmd) if (vshCommandOptStringReq(ctl, cmd, "interface", &iface) < 0) return false; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; if (vshCommandOptBool(cmd, "config")) @@ -815,7 +815,7 @@ cmdDomControl(vshControl *ctl, const vshCmd *cmd) bool ret = true; virDomainControlInfo info; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; if (virDomainGetControlInfo(dom, &info, 0) < 0) { @@ -826,15 +826,15 @@ cmdDomControl(vshControl *ctl, const vshCmd *cmd) if (info.state != VIR_DOMAIN_CONTROL_OK && info.state != VIR_DOMAIN_CONTROL_ERROR) { vshPrint(ctl, "%s (%0.3fs)\n", - vshDomainControlStateToString(info.state), + virshDomainControlStateToString(info.state), info.stateTime / 1000.0); } else if (info.state == VIR_DOMAIN_CONTROL_ERROR && info.details > 0) { vshPrint(ctl, "%s: %s\n", - vshDomainControlStateToString(info.state), - vshDomainControlErrorReasonToString(info.details)); + virshDomainControlStateToString(info.state), + virshDomainControlErrorReasonToString(info.details)); } else { vshPrint(ctl, "%s\n", - vshDomainControlStateToString(info.state)); + virshDomainControlStateToString(info.state)); } cleanup: @@ -927,7 +927,7 @@ cmdDomblkstat(vshControl *ctl, const vshCmd *cmd) bool ret = false; bool human = vshCommandOptBool(cmd, "human"); /* human readable output */ - if (!(dom = vshCommandOptDomain(ctl, cmd, &name))) + if (!(dom = virshCommandOptDomain(ctl, cmd, &name))) return false; /* device argument is optional now. if it's missing, supply empty @@ -1068,7 +1068,7 @@ cmdDomIfstat(vshControl *ctl, const vshCmd *cmd) virDomainInterfaceStatsStruct stats; bool ret = false; - if (!(dom = vshCommandOptDomain(ctl, cmd, &name))) + if (!(dom = virshCommandOptDomain(ctl, cmd, &name))) return false; if (vshCommandOptStringReq(ctl, cmd, "interface", &device) < 0) @@ -1142,7 +1142,7 @@ cmdDomBlkError(vshControl *ctl, const vshCmd *cmd) int count; bool ret = false; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; if ((count = virDomainGetDiskErrors(dom, NULL, 0, 0)) < 0) @@ -1163,7 +1163,7 @@ cmdDomBlkError(vshControl *ctl, const vshCmd *cmd) for (i = 0; i < count; i++) { vshPrint(ctl, "%s: %s\n", disks[i].disk, - vshDomainIOErrorToString(disks[i].error)); + virshDomainIOErrorToString(disks[i].error)); } } @@ -1211,7 +1211,7 @@ cmdDominfo(vshControl *ctl, const vshCmd *cmd) char *str, uuid[VIR_UUID_STRING_BUFLEN]; int has_managed_save = 0; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; id = virDomainGetID(dom); @@ -1231,7 +1231,7 @@ cmdDominfo(vshControl *ctl, const vshCmd *cmd) if (virDomainGetInfo(dom, &info) == 0) { vshPrint(ctl, "%-15s %s\n", _("State:"), - vshDomainStateToString(info.state)); + virshDomainStateToString(info.state)); vshPrint(ctl, "%-15s %d\n", _("CPU(s):"), info.nrVirtCpu); @@ -1351,21 +1351,21 @@ cmdDomstate(vshControl *ctl, const vshCmd *cmd) bool showReason = vshCommandOptBool(cmd, "reason"); int state, reason; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; - if ((state = vshDomainState(ctl, dom, &reason)) < 0) { + if ((state = virshDomainState(ctl, dom, &reason)) < 0) { ret = false; goto cleanup; } if (showReason) { vshPrint(ctl, "%s (%s)\n", - vshDomainStateToString(state), - vshDomainStateReasonToString(state, reason)); + virshDomainStateToString(state), + virshDomainStateReasonToString(state, reason)); } else { vshPrint(ctl, "%s\n", - vshDomainStateToString(state)); + virshDomainStateToString(state)); } cleanup: @@ -1429,7 +1429,7 @@ cmdDomTime(vshControl *ctl, const vshCmd *cmd) VSH_EXCLUSIVE_OPTIONS("time", "sync"); VSH_EXCLUSIVE_OPTIONS("now", "sync"); - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; rv = vshCommandOptLongLong(ctl, cmd, "time", &seconds); @@ -1496,7 +1496,7 @@ static const vshCmdInfo info_list[] = { /* compare domains, pack NULLed ones at the end*/ static int -vshDomainSorter(const void *a, const void *b) +virshDomainSorter(const void *a, const void *b) { virDomainPtr *da = (virDomainPtr *) a; virDomainPtr *db = (virDomainPtr *) b; @@ -1529,14 +1529,14 @@ vshDomainSorter(const void *a, const void *b) return 1; } -struct vshDomainList { +struct virshDomainList { virDomainPtr *domains; size_t ndomains; }; -typedef struct vshDomainList *vshDomainListPtr; +typedef struct virshDomainList *virshDomainListPtr; static void -vshDomainListFree(vshDomainListPtr domlist) +virshDomainListFree(virshDomainListPtr domlist) { size_t i; @@ -1550,10 +1550,10 @@ vshDomainListFree(vshDomainListPtr domlist) VIR_FREE(domlist); } -static vshDomainListPtr -vshDomainListCollect(vshControl *ctl, unsigned int flags) +static virshDomainListPtr +virshDomainListCollect(vshControl *ctl, unsigned int flags) { - vshDomainListPtr list = vshMalloc(ctl, sizeof(*list)); + virshDomainListPtr list = vshMalloc(ctl, sizeof(*list)); size_t i; int ret; int *ids = NULL; @@ -1747,7 +1747,7 @@ vshDomainListCollect(vshControl *ctl, unsigned int flags) /* sort the list */ if (list->domains && list->ndomains) qsort(list->domains, list->ndomains, sizeof(*list->domains), - vshDomainSorter); + virshDomainSorter); /* truncate the list if filter simulation deleted entries */ if (deleted) @@ -1760,7 +1760,7 @@ vshDomainListCollect(vshControl *ctl, unsigned int flags) VIR_FREE(names[i]); if (!success) { - vshDomainListFree(list); + virshDomainListFree(list); list = NULL; } @@ -1865,7 +1865,7 @@ cmdList(vshControl *ctl, const vshCmd *cmd) char uuid[VIR_UUID_STRING_BUFLEN]; int state; bool ret = false; - vshDomainListPtr list = NULL; + virshDomainListPtr list = NULL; virDomainPtr dom; char id_buf[INT_BUFSIZE_BOUND(unsigned int)]; unsigned int id; @@ -1906,7 +1906,7 @@ cmdList(vshControl *ctl, const vshCmd *cmd) if (!optUUID && !optName) optTable = true; - if (!(list = vshDomainListCollect(ctl, flags))) + if (!(list = virshDomainListCollect(ctl, flags))) goto cleanup; /* print table header in legacy mode */ @@ -1931,7 +1931,7 @@ cmdList(vshControl *ctl, const vshCmd *cmd) else ignore_value(virStrcpyStatic(id_buf, "-")); - state = vshDomainState(ctl, dom, NULL); + state = virshDomainState(ctl, dom, NULL); /* Domain could've been removed in the meantime */ if (state < 0) @@ -1943,19 +1943,21 @@ cmdList(vshControl *ctl, const vshCmd *cmd) if (optTable) { if (optTitle) { - if (!(title = vshGetDomainDescription(ctl, dom, true, 0))) + if (!(title = virshGetDomainDescription(ctl, dom, true, 0))) goto cleanup; vshPrint(ctl, " %-5s %-30s %-10s %-20s\n", id_buf, virDomainGetName(dom), - state == -2 ? _("saved") : vshDomainStateToString(state), + state == -2 ? _("saved") + : virshDomainStateToString(state), title); VIR_FREE(title); } else { vshPrint(ctl, " %-5s %-30s %s\n", id_buf, virDomainGetName(dom), - state == -2 ? _("saved") : vshDomainStateToString(state)); + state == -2 ? _("saved") + : virshDomainStateToString(state)); } } else if (optUUID) { if (virDomainGetUUIDString(dom, uuid) < 0) { @@ -1970,7 +1972,7 @@ cmdList(vshControl *ctl, const vshCmd *cmd) ret = true; cleanup: - vshDomainListFree(list); + virshDomainListFree(list); return ret; } #undef FILTER @@ -2067,9 +2069,9 @@ static const vshCmdOptDef opts_domstats[] = { static bool -vshDomainStatsPrintRecord(vshControl *ctl ATTRIBUTE_UNUSED, - virDomainStatsRecordPtr record, - bool raw ATTRIBUTE_UNUSED) +virshDomainStatsPrintRecord(vshControl *ctl ATTRIBUTE_UNUSED, + virDomainStatsRecordPtr record, + bool raw ATTRIBUTE_UNUSED) { char *param; size_t i; @@ -2159,8 +2161,8 @@ cmdDomstats(vshControl *ctl, const vshCmd *cmd) ndoms = 1; while ((opt = vshCommandOptArgv(ctl, cmd, opt))) { - if (!(dom = vshLookupDomainBy(ctl, opt->data, - VSH_BYID | VSH_BYUUID | VSH_BYNAME))) + if (!(dom = virshLookupDomainBy(ctl, opt->data, + VSH_BYID | VSH_BYUUID | VSH_BYNAME))) goto cleanup; if (VIR_INSERT_ELEMENT(domlist, ndoms - 1, ndoms, dom) < 0) @@ -2181,7 +2183,7 @@ cmdDomstats(vshControl *ctl, const vshCmd *cmd) } for (next = records; *next; next++) { - if (!vshDomainStatsPrintRecord(ctl, *next, raw)) + if (!virshDomainStatsPrintRecord(ctl, *next, raw)) goto cleanup; } @@ -2234,7 +2236,7 @@ cmdDomIfAddr(vshControl *ctl, const vshCmd *cmd) const char *sourcestr = NULL; int source = VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LEASE; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; if (vshCommandOptString(ctl, cmd, "interface", &ifacestr) < 0) diff --git a/tools/virsh-domain-monitor.h b/tools/virsh-domain-monitor.h index 9df3a8c..08ccab5 100644 --- a/tools/virsh-domain-monitor.h +++ b/tools/virsh-domain-monitor.h @@ -28,8 +28,8 @@ # include "virsh.h" -char *vshGetDomainDescription(vshControl *ctl, virDomainPtr dom, - bool title, unsigned int flags) +char *virshGetDomainDescription(vshControl *ctl, virDomainPtr dom, + bool title, unsigned int flags) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK; extern const vshCmdDef domMonitoringCmds[]; diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index 27d62e9..bf53a24 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -63,10 +63,10 @@ static virDomainPtr -vshLookupDomainInternal(vshControl *ctl, - const char *cmdname, - const char *name, - unsigned int flags) +virshLookupDomainInternal(vshControl *ctl, + const char *cmdname, + const char *name, + unsigned int flags) { virDomainPtr dom = NULL; int id; @@ -104,17 +104,17 @@ vshLookupDomainInternal(vshControl *ctl, virDomainPtr -vshLookupDomainBy(vshControl *ctl, +virshLookupDomainBy(vshControl *ctl, const char *name, unsigned int flags) { - return vshLookupDomainInternal(ctl, "unknown", name, flags); + return virshLookupDomainInternal(ctl, "unknown", name, flags); } virDomainPtr -vshCommandOptDomainBy(vshControl *ctl, const vshCmd *cmd, - const char **name, unsigned int flags) +virshCommandOptDomainBy(vshControl *ctl, const vshCmd *cmd, + const char **name, unsigned int flags) { const char *n = NULL; const char *optname = "domain"; @@ -128,11 +128,11 @@ vshCommandOptDomainBy(vshControl *ctl, const vshCmd *cmd, if (name) *name = n; - return vshLookupDomainInternal(ctl, cmd->def->name, n, flags); + return virshLookupDomainInternal(ctl, cmd->def->name, n, flags); } static virDomainPtr -vshDomainDefine(virConnectPtr conn, const char *xml, unsigned int flags) +virshDomainDefine(virConnectPtr conn, const char *xml, unsigned int flags) { virDomainPtr dom; if (flags) { @@ -153,17 +153,17 @@ vshDomainDefine(virConnectPtr conn, const char *xml, unsigned int flags) return dom; } -VIR_ENUM_DECL(vshDomainVcpuState) -VIR_ENUM_IMPL(vshDomainVcpuState, +VIR_ENUM_DECL(virshDomainVcpuState) +VIR_ENUM_IMPL(virshDomainVcpuState, VIR_VCPU_LAST, N_("offline"), N_("running"), N_("blocked")) static const char * -vshDomainVcpuStateToString(int state) +virshDomainVcpuStateToString(int state) { - const char *str = vshDomainVcpuStateTypeToString(state); + const char *str = virshDomainVcpuStateTypeToString(state); return str ? _(str) : _("no state"); } @@ -173,7 +173,7 @@ vshDomainVcpuStateToString(int state) * if needed. */ static int -vshNodeGetCPUCount(virConnectPtr conn) +virshNodeGetCPUCount(virConnectPtr conn) { int ret; virNodeInfo nodeinfo; @@ -254,7 +254,7 @@ cmdAttachDevice(vshControl *ctl, const vshCmd *cmd) if (live) flags |= VIR_DOMAIN_AFFECT_LIVE; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0) @@ -264,7 +264,7 @@ cmdAttachDevice(vshControl *ctl, const vshCmd *cmd) virDomainIsActive(dom) == 1) flags |= VIR_DOMAIN_AFFECT_LIVE; - if (virFileReadAll(from, VSH_MAX_XML_FILE, &buffer) < 0) { + if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) { vshReportError(ctl); goto cleanup; } @@ -762,7 +762,7 @@ cmdAttachDisk(vshControl *ctl, const vshCmd *cmd) goto cleanup; } - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) goto cleanup; if (persistent && @@ -925,7 +925,7 @@ cmdAttachInterface(vshControl *ctl, const vshCmd *cmd) if (live) flags |= VIR_DOMAIN_AFFECT_LIVE; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; if (persistent && @@ -1095,7 +1095,7 @@ cmdAutostart(vshControl *ctl, const vshCmd *cmd) const char *name; int autostart; - if (!(dom = vshCommandOptDomain(ctl, cmd, &name))) + if (!(dom = virshCommandOptDomain(ctl, cmd, &name))) return false; autostart = !vshCommandOptBool(cmd, "disable"); @@ -1286,7 +1286,7 @@ cmdBlkdeviotune(vshControl *ctl, const vshCmd *cmd) if (live) flags |= VIR_DOMAIN_AFFECT_LIVE; - if (!(dom = vshCommandOptDomain(ctl, cmd, &name))) + if (!(dom = virshCommandOptDomain(ctl, cmd, &name))) goto cleanup; if (vshCommandOptStringReq(ctl, cmd, "device", &disk) < 0) @@ -1548,7 +1548,7 @@ cmdBlkiotune(vshControl * ctl, const vshCmd * cmd) if (live) flags |= VIR_DOMAIN_AFFECT_LIVE; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; if ((rv = vshCommandOptInt(ctl, cmd, "weight", &weight)) < 0) { @@ -1665,15 +1665,15 @@ cmdBlkiotune(vshControl * ctl, const vshCmd * cmd) } typedef enum { - VSH_CMD_BLOCK_JOB_ABORT, - VSH_CMD_BLOCK_JOB_SPEED, - VSH_CMD_BLOCK_JOB_PULL, - VSH_CMD_BLOCK_JOB_COMMIT, -} vshCmdBlockJobMode; + VIRSH_CMD_BLOCK_JOB_ABORT, + VIRSH_CMD_BLOCK_JOB_SPEED, + VIRSH_CMD_BLOCK_JOB_PULL, + VIRSH_CMD_BLOCK_JOB_COMMIT, +} virshCmdBlockJobMode; static bool blockJobImpl(vshControl *ctl, const vshCmd *cmd, - vshCmdBlockJobMode mode, virDomainPtr *pdom) + virshCmdBlockJobMode mode, virDomainPtr *pdom) { virDomainPtr dom = NULL; const char *path; @@ -1683,7 +1683,7 @@ blockJobImpl(vshControl *ctl, const vshCmd *cmd, const char *top = NULL; unsigned int flags = 0; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) goto cleanup; if (vshCommandOptStringReq(ctl, cmd, "path", &path) < 0) @@ -1693,7 +1693,7 @@ blockJobImpl(vshControl *ctl, const vshCmd *cmd, goto cleanup; switch (mode) { - case VSH_CMD_BLOCK_JOB_ABORT: + case VIRSH_CMD_BLOCK_JOB_ABORT: if (vshCommandOptBool(cmd, "async")) flags |= VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC; if (vshCommandOptBool(cmd, "pivot")) @@ -1701,11 +1701,11 @@ blockJobImpl(vshControl *ctl, const vshCmd *cmd, if (virDomainBlockJobAbort(dom, path, flags) < 0) goto cleanup; break; - case VSH_CMD_BLOCK_JOB_SPEED: + case VIRSH_CMD_BLOCK_JOB_SPEED: if (virDomainBlockJobSetSpeed(dom, path, bandwidth, 0) < 0) goto cleanup; break; - case VSH_CMD_BLOCK_JOB_PULL: + case VIRSH_CMD_BLOCK_JOB_PULL: if (vshCommandOptStringReq(ctl, cmd, "base", &base) < 0) goto cleanup; if (vshCommandOptBool(cmd, "keep-relative")) @@ -1720,7 +1720,7 @@ blockJobImpl(vshControl *ctl, const vshCmd *cmd, } break; - case VSH_CMD_BLOCK_JOB_COMMIT: + case VIRSH_CMD_BLOCK_JOB_COMMIT: if (vshCommandOptStringReq(ctl, cmd, "base", &base) < 0 || vshCommandOptStringReq(ctl, cmd, "top", &top) < 0) goto cleanup; @@ -1750,8 +1750,8 @@ blockJobImpl(vshControl *ctl, const vshCmd *cmd, } static void -vshPrintJobProgress(const char *label, unsigned long long remaining, - unsigned long long total) +virshPrintJobProgress(const char *label, unsigned long long remaining, + unsigned long long total) { int progress; @@ -1787,12 +1787,12 @@ static void vshCatchInt(int sig ATTRIBUTE_UNUSED, } static void -vshBlockJobStatusHandler(virConnectPtr conn ATTRIBUTE_UNUSED, - virDomainPtr dom ATTRIBUTE_UNUSED, - const char *disk ATTRIBUTE_UNUSED, - int type ATTRIBUTE_UNUSED, - int status, - void *opaque) +virshBlockJobStatusHandler(virConnectPtr conn ATTRIBUTE_UNUSED, + virDomainPtr dom ATTRIBUTE_UNUSED, + const char *disk ATTRIBUTE_UNUSED, + int type ATTRIBUTE_UNUSED, + int status, + void *opaque) { *(int *) opaque = status; } @@ -1905,7 +1905,7 @@ cmdBlockCommit(vshControl *ctl, const vshCmd *cmd) vshError(ctl, "%s", _("cannot mix --pivot and --keep-overlay")); return false; } - if (vshCommandOptTimeoutToMs(ctl, cmd, &timeout) < 0) + if (virshCommandOptTimeoutToMs(ctl, cmd, &timeout) < 0) return false; if (vshCommandOptStringReq(ctl, cmd, "path", &path) < 0) return false; @@ -1928,7 +1928,7 @@ cmdBlockCommit(vshControl *ctl, const vshCmd *cmd) } virConnectDomainEventGenericCallback cb = - VIR_DOMAIN_EVENT_CALLBACK(vshBlockJobStatusHandler); + VIR_DOMAIN_EVENT_CALLBACK(virshBlockJobStatusHandler); if ((cb_id = virConnectDomainEventRegisterAny(ctl->conn, dom, @@ -1938,7 +1938,7 @@ cmdBlockCommit(vshControl *ctl, const vshCmd *cmd) NULL)) < 0) vshResetLibvirtError(); - if (!blockJobImpl(ctl, cmd, VSH_CMD_BLOCK_JOB_COMMIT, &dom)) + if (!blockJobImpl(ctl, cmd, VIRSH_CMD_BLOCK_JOB_COMMIT, &dom)) goto cleanup; if (!blocking) { @@ -1965,8 +1965,8 @@ cmdBlockCommit(vshControl *ctl, const vshCmd *cmd) break; if (verbose) - vshPrintJobProgress(_("Block Commit"), - info.end - info.cur, info.end); + virshPrintJobProgress(_("Block Commit"), + info.end - info.cur, info.end); if (active && info.cur == info.end) break; @@ -1996,7 +1996,7 @@ cmdBlockCommit(vshControl *ctl, const vshCmd *cmd) if (verbose && !quit) { /* printf [100 %] */ - vshPrintJobProgress(_("Block Commit"), 0, 1); + virshPrintJobProgress(_("Block Commit"), 0, 1); } if (!quit && pivot) { abort_flags |= VIR_DOMAIN_BLOCK_JOB_ABORT_PIVOT; @@ -2171,7 +2171,7 @@ cmdBlockCopy(vshControl *ctl, const vshCmd *cmd) vshError(ctl, "%s", _("cannot mix --pivot and --finish")); return false; } - if (vshCommandOptTimeoutToMs(ctl, cmd, &timeout) < 0) + if (virshCommandOptTimeoutToMs(ctl, cmd, &timeout) < 0) return false; if (vshCommandOptBool(cmd, "async")) abort_flags |= VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC; @@ -2192,7 +2192,7 @@ cmdBlockCopy(vshControl *ctl, const vshCmd *cmd) } virConnectDomainEventGenericCallback cb = - VIR_DOMAIN_EVENT_CALLBACK(vshBlockJobStatusHandler); + VIR_DOMAIN_EVENT_CALLBACK(virshBlockJobStatusHandler); if ((cb_id = virConnectDomainEventRegisterAny(ctl->conn, dom, @@ -2202,7 +2202,7 @@ cmdBlockCopy(vshControl *ctl, const vshCmd *cmd) NULL)) < 0) vshResetLibvirtError(); - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) goto cleanup; /* XXX: Parse bandwidth as scaled input, rather than forcing @@ -2217,7 +2217,7 @@ cmdBlockCopy(vshControl *ctl, const vshCmd *cmd) goto cleanup; if (xml) { - if (virFileReadAll(xml, VSH_MAX_XML_FILE, &xmlstr) < 0) { + if (virFileReadAll(xml, VIRSH_MAX_XML_FILE, &xmlstr) < 0) { vshReportError(ctl); goto cleanup; } @@ -2319,7 +2319,7 @@ cmdBlockCopy(vshControl *ctl, const vshCmd *cmd) } if (verbose) - vshPrintJobProgress(_("Block Copy"), info.end - info.cur, info.end); + virshPrintJobProgress(_("Block Copy"), info.end - info.cur, info.end); if (info.cur == info.end) break; @@ -2481,12 +2481,12 @@ cmdBlockJob(vshControl *ctl, const vshCmd *cmd) } if (abortMode) - return blockJobImpl(ctl, cmd, VSH_CMD_BLOCK_JOB_ABORT, NULL); + return blockJobImpl(ctl, cmd, VIRSH_CMD_BLOCK_JOB_ABORT, NULL); if (bandwidth) - return blockJobImpl(ctl, cmd, VSH_CMD_BLOCK_JOB_SPEED, NULL); + return blockJobImpl(ctl, cmd, VIRSH_CMD_BLOCK_JOB_SPEED, NULL); /* Everything below here is for --info mode */ - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) goto cleanup; /* XXX Allow path to be optional to list info on all devices at once */ @@ -2546,11 +2546,11 @@ cmdBlockJob(vshControl *ctl, const vshCmd *cmd) vshDomainBlockJobTypeToString(info.type), info.bandwidth, info.cur, info.end); } else { - vshPrintJobProgress(vshDomainBlockJobToString(info.type), - info.end - info.cur, info.end); + virshPrintJobProgress(vshDomainBlockJobToString(info.type), + info.end - info.cur, info.end); if (speed) { const char *unit; - double val = vshPrettyCapacity(speed, &unit); + double val = virshPrettyCapacity(speed, &unit); vshPrint(ctl, _(" Bandwidth limit: %llu bytes/s (%-.3lf %s/s)"), speed, val, unit); } @@ -2638,7 +2638,7 @@ cmdBlockPull(vshControl *ctl, const vshCmd *cmd) int cb_id = -1; if (blocking) { - if (vshCommandOptTimeoutToMs(ctl, cmd, &timeout) < 0) + if (virshCommandOptTimeoutToMs(ctl, cmd, &timeout) < 0) return false; if (vshCommandOptStringReq(ctl, cmd, "path", &path) < 0) return false; @@ -2662,7 +2662,7 @@ cmdBlockPull(vshControl *ctl, const vshCmd *cmd) } virConnectDomainEventGenericCallback cb = - VIR_DOMAIN_EVENT_CALLBACK(vshBlockJobStatusHandler); + VIR_DOMAIN_EVENT_CALLBACK(virshBlockJobStatusHandler); if ((cb_id = virConnectDomainEventRegisterAny(ctl->conn, dom, @@ -2672,7 +2672,7 @@ cmdBlockPull(vshControl *ctl, const vshCmd *cmd) NULL)) < 0) vshResetLibvirtError(); - if (!blockJobImpl(ctl, cmd, VSH_CMD_BLOCK_JOB_PULL, &dom)) + if (!blockJobImpl(ctl, cmd, VIRSH_CMD_BLOCK_JOB_PULL, &dom)) goto cleanup; if (!blocking) { @@ -2697,7 +2697,7 @@ cmdBlockPull(vshControl *ctl, const vshCmd *cmd) break; if (verbose) - vshPrintJobProgress(_("Block Pull"), info.end - info.cur, info.end); + virshPrintJobProgress(_("Block Pull"), info.end - info.cur, info.end); GETTIMEOFDAY(&curr); if (intCaught || (timeout && @@ -2725,7 +2725,7 @@ cmdBlockPull(vshControl *ctl, const vshCmd *cmd) if (verbose && !quit) { /* printf [100 %] */ - vshPrintJobProgress(_("Block Pull"), 0, 1); + virshPrintJobProgress(_("Block Pull"), 0, 1); } vshPrint(ctl, "\n%s", quit ? _("Pull aborted") : _("Pull complete")); @@ -2793,7 +2793,7 @@ cmdBlockResize(vshControl *ctl, const vshCmd *cmd) else flags |= VIR_DOMAIN_BLOCK_RESIZE_BYTES; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; if (virDomainBlockResize(dom, path, size, flags) < 0) { @@ -2850,7 +2850,7 @@ cmdRunConsole(vshControl *ctl, virDomainPtr dom, bool ret = false; int state; - if ((state = vshDomainState(ctl, dom, NULL)) < 0) { + if ((state = virshDomainState(ctl, dom, NULL)) < 0) { vshError(ctl, "%s", _("Unable to get domain status")); goto cleanup; } @@ -2868,7 +2868,7 @@ cmdRunConsole(vshControl *ctl, virDomainPtr dom, vshPrintExtra(ctl, _("Connected to domain %s\n"), virDomainGetName(dom)); vshPrintExtra(ctl, _("Escape character is %s\n"), ctl->escapeChar); fflush(stdout); - if (vshRunConsole(ctl, dom, name, flags) == 0) + if (virshRunConsole(ctl, dom, name, flags) == 0) ret = true; cleanup: @@ -2886,7 +2886,7 @@ cmdConsole(vshControl *ctl, const vshCmd *cmd) unsigned int flags = 0; const char *name = NULL; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; if (vshCommandOptStringReq(ctl, cmd, "devname", &name) < 0) /* sc_prohibit_devname */ @@ -2966,7 +2966,7 @@ cmdDomIfSetLink(vshControl *ctl, const vshCmd *cmd) xmlNodePtr cur = NULL; char *xml_buf = NULL; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; if (vshCommandOptStringReq(ctl, cmd, "interface", &iface) < 0 || @@ -3164,7 +3164,7 @@ cmdDomIftune(vshControl *ctl, const vshCmd *cmd) if (live) flags |= VIR_DOMAIN_AFFECT_LIVE; - if (!(dom = vshCommandOptDomain(ctl, cmd, &name))) + if (!(dom = virshCommandOptDomain(ctl, cmd, &name))) return false; if (vshCommandOptStringReq(ctl, cmd, "interface", &device) < 0) @@ -3322,7 +3322,7 @@ cmdSuspend(vshControl *ctl, const vshCmd *cmd) const char *name; bool ret = true; - if (!(dom = vshCommandOptDomain(ctl, cmd, &name))) + if (!(dom = virshCommandOptDomain(ctl, cmd, &name))) return false; if (virDomainSuspend(dom) == 0) { @@ -3383,7 +3383,7 @@ cmdDomPMSuspend(vshControl *ctl, const vshCmd *cmd) unsigned int suspendTarget; unsigned long long duration = 0; - if (!(dom = vshCommandOptDomain(ctl, cmd, &name))) + if (!(dom = virshCommandOptDomain(ctl, cmd, &name))) return false; if (vshCommandOptULongLong(ctl, cmd, "duration", &duration) < 0) @@ -3451,7 +3451,7 @@ cmdDomPMWakeup(vshControl *ctl, const vshCmd *cmd) bool ret = false; unsigned int flags = 0; - if (!(dom = vshCommandOptDomain(ctl, cmd, &name))) + if (!(dom = virshCommandOptDomain(ctl, cmd, &name))) return false; if (virDomainPMWakeup(dom, flags) < 0) { @@ -3583,7 +3583,7 @@ cmdUndefine(vshControl *ctl, const vshCmd *cmd) if (nvram) flags |= VIR_DOMAIN_UNDEFINE_NVRAM; - if (!(dom = vshCommandOptDomain(ctl, cmd, &name))) + if (!(dom = virshCommandOptDomain(ctl, cmd, &name))) return false; /* Do some flag manipulation. The goal here is to disable bits @@ -3988,8 +3988,8 @@ cmdStart(vshControl *ctl, const vshCmd *cmd) size_t nfds = 0; int *fds = NULL; - if (!(dom = vshCommandOptDomainBy(ctl, cmd, NULL, - VSH_BYNAME | VSH_BYUUID))) + if (!(dom = virshCommandOptDomainBy(ctl, cmd, NULL, + VSH_BYNAME | VSH_BYUUID))) return false; if (virDomainGetID(dom) != (unsigned int)-1) { @@ -4108,7 +4108,7 @@ static const vshCmdOptDef opts_save[] = { static void doSave(void *opaque) { - vshCtrlData *data = opaque; + virshCtrlData *data = opaque; vshControl *ctl = data->ctl; const vshCmd *cmd = data->cmd; char ret = '1'; @@ -4138,11 +4138,11 @@ doSave(void *opaque) if (vshCommandOptStringReq(ctl, cmd, "xml", &xmlfile) < 0) goto out; - if (!(dom = vshCommandOptDomain(ctl, cmd, &name))) + if (!(dom = virshCommandOptDomain(ctl, cmd, &name))) goto out; if (xmlfile && - virFileReadAll(xmlfile, VSH_MAX_XML_FILE, &xml) < 0) { + virFileReadAll(xmlfile, VIRSH_MAX_XML_FILE, &xml) < 0) { vshReportError(ctl); goto out; } @@ -4220,7 +4220,7 @@ vshWatchJob(vshControl *ctl, retchar == '0') { if (verbose) { /* print [100 %] */ - vshPrintJobProgress(label, 0, 1); + virshPrintJobProgress(label, 0, 1); } break; } @@ -4255,8 +4255,8 @@ vshWatchJob(vshControl *ctl, pthread_sigmask(SIG_SETMASK, &oldsigmask, NULL); if (ret == 0) { if (verbose) - vshPrintJobProgress(label, jobinfo.dataRemaining, - jobinfo.dataTotal); + virshPrintJobProgress(label, jobinfo.dataRemaining, + jobinfo.dataTotal); if (!jobStarted && (jobinfo.type == VIR_DOMAIN_JOB_BOUNDED || @@ -4286,11 +4286,11 @@ cmdSave(vshControl *ctl, const vshCmd *cmd) int p[2] = {-1. -1}; virThread workerThread; bool verbose = false; - vshCtrlData data; + virshCtrlData data; const char *to = NULL; const char *name = NULL; - if (!(dom = vshCommandOptDomain(ctl, cmd, &name))) + if (!(dom = virshCommandOptDomain(ctl, cmd, &name))) return false; if (vshCommandOptStringReq(ctl, cmd, "file", &to) < 0) @@ -4431,7 +4431,7 @@ cmdSaveImageDefine(vshControl *ctl, const vshCmd *cmd) if (vshCommandOptStringReq(ctl, cmd, "xml", &xmlfile) < 0) return false; - if (virFileReadAll(xmlfile, VSH_MAX_XML_FILE, &xml) < 0) + if (virFileReadAll(xmlfile, VIRSH_MAX_XML_FILE, &xml) < 0) goto cleanup; if (virDomainSaveImageDefineXML(ctl->conn, file, xml, flags) < 0) { @@ -4567,7 +4567,7 @@ static void doManagedsave(void *opaque) { char ret = '1'; - vshCtrlData *data = opaque; + virshCtrlData *data = opaque; vshControl *ctl = data->ctl; const vshCmd *cmd = data->cmd; virDomainPtr dom = NULL; @@ -4587,7 +4587,7 @@ doManagedsave(void *opaque) if (vshCommandOptBool(cmd, "paused")) flags |= VIR_DOMAIN_SAVE_PAUSED; - if (!(dom = vshCommandOptDomain(ctl, cmd, &name))) + if (!(dom = virshCommandOptDomain(ctl, cmd, &name))) goto out; if (virDomainManagedSave(dom, flags) < 0) { @@ -4612,10 +4612,10 @@ cmdManagedSave(vshControl *ctl, const vshCmd *cmd) bool ret = false; bool verbose = false; const char *name = NULL; - vshCtrlData data; + virshCtrlData data; virThread workerThread; - if (!(dom = vshCommandOptDomain(ctl, cmd, &name))) + if (!(dom = virshCommandOptDomain(ctl, cmd, &name))) return false; if (vshCommandOptBool(cmd, "verbose")) @@ -4679,7 +4679,7 @@ cmdManagedSaveRemove(vshControl *ctl, const vshCmd *cmd) bool ret = false; int hassave; - if (!(dom = vshCommandOptDomain(ctl, cmd, &name))) + if (!(dom = virshCommandOptDomain(ctl, cmd, &name))) return false; hassave = virDomainHasManagedSaveImage(dom, 0); @@ -4876,7 +4876,7 @@ cmdSchedinfo(vshControl *ctl, const vshCmd *cmd) if (live) flags |= VIR_DOMAIN_AFFECT_LIVE; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; /* Print SchedulerType */ @@ -5017,7 +5017,7 @@ cmdRestore(vshControl *ctl, const vshCmd *cmd) return false; if (xmlfile && - virFileReadAll(xmlfile, VSH_MAX_XML_FILE, &xml) < 0) + virFileReadAll(xmlfile, VIRSH_MAX_XML_FILE, &xml) < 0) goto cleanup; if (((flags || xml) @@ -5094,7 +5094,7 @@ static void doDump(void *opaque) { char ret = '1'; - vshCtrlData *data = opaque; + virshCtrlData *data = opaque; vshControl *ctl = data->ctl; const vshCmd *cmd = data->cmd; virDomainPtr dom = NULL; @@ -5113,7 +5113,7 @@ doDump(void *opaque) if (vshCommandOptStringReq(ctl, cmd, "file", &to) < 0) goto out; - if (!(dom = vshCommandOptDomain(ctl, cmd, &name))) + if (!(dom = virshCommandOptDomain(ctl, cmd, &name))) goto out; if (vshCommandOptBool(cmd, "live")) @@ -5181,10 +5181,10 @@ cmdDump(vshControl *ctl, const vshCmd *cmd) bool verbose = false; const char *name = NULL; const char *to = NULL; - vshCtrlData data; + virshCtrlData data; virThread workerThread; - if (!(dom = vshCommandOptDomain(ctl, cmd, &name))) + if (!(dom = virshCommandOptDomain(ctl, cmd, &name))) return false; if (vshCommandOptStringReq(ctl, cmd, "file", &to) < 0) @@ -5305,7 +5305,7 @@ cmdScreenshot(vshControl *ctl, const vshCmd *cmd) if (vshCommandOptUInt(ctl, cmd, "screen", &screen) < 0) return false; - if (!(dom = vshCommandOptDomain(ctl, cmd, &name))) + if (!(dom = virshCommandOptDomain(ctl, cmd, &name))) return false; if (!(st = virStreamNew(ctl->conn, 0))) @@ -5333,7 +5333,7 @@ cmdScreenshot(vshControl *ctl, const vshCmd *cmd) created = true; } - if (virStreamRecvAll(st, vshStreamSink, &fd) < 0) { + if (virStreamRecvAll(st, virshStreamSink, &fd) < 0) { vshError(ctl, _("could not receive data from domain %s"), name); goto cleanup; } @@ -5419,7 +5419,7 @@ cmdSetUserPassword(vshControl *ctl, const vshCmd *cmd) if (vshCommandOptStringReq(ctl, cmd, "password", &password) < 0) return false; - if (!(dom = vshCommandOptDomain(ctl, cmd, &name))) + if (!(dom = virshCommandOptDomain(ctl, cmd, &name))) return false; if (virDomainSetUserPassword(dom, user, password, flags) < 0) @@ -5461,7 +5461,7 @@ cmdResume(vshControl *ctl, const vshCmd *cmd) bool ret = true; const char *name; - if (!(dom = vshCommandOptDomain(ctl, cmd, &name))) + if (!(dom = virshCommandOptDomain(ctl, cmd, &name))) return false; if (virDomainResume(dom) == 0) { @@ -5542,7 +5542,7 @@ cmdShutdown(vshControl *ctl, const vshCmd *cmd) tmp++; } - if (!(dom = vshCommandOptDomain(ctl, cmd, &name))) + if (!(dom = virshCommandOptDomain(ctl, cmd, &name))) goto cleanup; if (flags) @@ -5630,7 +5630,7 @@ cmdReboot(vshControl *ctl, const vshCmd *cmd) tmp++; } - if (!(dom = vshCommandOptDomain(ctl, cmd, &name))) + if (!(dom = virshCommandOptDomain(ctl, cmd, &name))) goto cleanup; if (virDomainReboot(dom, flags) == 0) { @@ -5677,7 +5677,7 @@ cmdReset(vshControl *ctl, const vshCmd *cmd) bool ret = true; const char *name; - if (!(dom = vshCommandOptDomain(ctl, cmd, &name))) + if (!(dom = virshCommandOptDomain(ctl, cmd, &name))) return false; if (virDomainReset(dom, 0) == 0) { @@ -5748,7 +5748,7 @@ cmdDomjobinfo(vshControl *ctl, const vshCmd *cmd) unsigned int flags = 0; int rc; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; if (vshCommandOptBool(cmd, "completed")) @@ -5830,20 +5830,20 @@ cmdDomjobinfo(vshControl *ctl, const vshCmd *cmd) info.timeRemaining); if (info.dataTotal || info.dataRemaining || info.dataProcessed) { - val = vshPrettyCapacity(info.dataProcessed, &unit); + val = virshPrettyCapacity(info.dataProcessed, &unit); vshPrint(ctl, "%-17s %-.3lf %s\n", _("Data processed:"), val, unit); - val = vshPrettyCapacity(info.dataRemaining, &unit); + val = virshPrettyCapacity(info.dataRemaining, &unit); vshPrint(ctl, "%-17s %-.3lf %s\n", _("Data remaining:"), val, unit); - val = vshPrettyCapacity(info.dataTotal, &unit); + val = virshPrettyCapacity(info.dataTotal, &unit); vshPrint(ctl, "%-17s %-.3lf %s\n", _("Data total:"), val, unit); } if (info.memTotal || info.memRemaining || info.memProcessed) { - val = vshPrettyCapacity(info.memProcessed, &unit); + val = virshPrettyCapacity(info.memProcessed, &unit); vshPrint(ctl, "%-17s %-.3lf %s\n", _("Memory processed:"), val, unit); - val = vshPrettyCapacity(info.memRemaining, &unit); + val = virshPrettyCapacity(info.memRemaining, &unit); vshPrint(ctl, "%-17s %-.3lf %s\n", _("Memory remaining:"), val, unit); - val = vshPrettyCapacity(info.memTotal, &unit); + val = virshPrettyCapacity(info.memTotal, &unit); vshPrint(ctl, "%-17s %-.3lf %s\n", _("Memory total:"), val, unit); if ((rc = virTypedParamsGetULLong(params, nparams, @@ -5851,18 +5851,18 @@ cmdDomjobinfo(vshControl *ctl, const vshCmd *cmd) &value)) < 0) { goto save_error; } else if (rc && value) { - val = vshPrettyCapacity(value, &unit); + val = virshPrettyCapacity(value, &unit); vshPrint(ctl, "%-17s %-.3lf %s/s\n", _("Memory bandwidth:"), val, unit); } } if (info.fileTotal || info.fileRemaining || info.fileProcessed) { - val = vshPrettyCapacity(info.fileProcessed, &unit); + val = virshPrettyCapacity(info.fileProcessed, &unit); vshPrint(ctl, "%-17s %-.3lf %s\n", _("File processed:"), val, unit); - val = vshPrettyCapacity(info.fileRemaining, &unit); + val = virshPrettyCapacity(info.fileRemaining, &unit); vshPrint(ctl, "%-17s %-.3lf %s\n", _("File remaining:"), val, unit); - val = vshPrettyCapacity(info.fileTotal, &unit); + val = virshPrettyCapacity(info.fileTotal, &unit); vshPrint(ctl, "%-17s %-.3lf %s\n", _("File total:"), val, unit); if ((rc = virTypedParamsGetULLong(params, nparams, @@ -5870,7 +5870,7 @@ cmdDomjobinfo(vshControl *ctl, const vshCmd *cmd) &value)) < 0) { goto save_error; } else if (rc && value) { - val = vshPrettyCapacity(value, &unit); + val = virshPrettyCapacity(value, &unit); vshPrint(ctl, "%-17s %-.3lf %s/s\n", _("File bandwidth:"), val, unit); } @@ -5895,7 +5895,7 @@ cmdDomjobinfo(vshControl *ctl, const vshCmd *cmd) &value)) < 0) { goto save_error; } else if (rc) { - val = vshPrettyCapacity(value, &unit); + val = virshPrettyCapacity(value, &unit); vshPrint(ctl, "%-17s %-.3lf %s\n", _("Normal data:"), val, unit); } @@ -5932,7 +5932,7 @@ cmdDomjobinfo(vshControl *ctl, const vshCmd *cmd) &value)) < 0) { goto save_error; } else if (rc) { - val = vshPrettyCapacity(value, &unit); + val = virshPrettyCapacity(value, &unit); vshPrint(ctl, "%-17s %-.3lf %s\n", _("Compression cache:"), val, unit); } if ((rc = virTypedParamsGetULLong(params, nparams, @@ -5940,7 +5940,7 @@ cmdDomjobinfo(vshControl *ctl, const vshCmd *cmd) &value)) < 0) { goto save_error; } else if (rc) { - val = vshPrettyCapacity(value, &unit); + val = virshPrettyCapacity(value, &unit); vshPrint(ctl, "%-17s %-.3lf %s\n", _("Compressed data:"), val, unit); } if ((rc = virTypedParamsGetULLong(params, nparams, @@ -6005,7 +6005,7 @@ cmdDomjobabort(vshControl *ctl, const vshCmd *cmd) virDomainPtr dom; bool ret = true; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; if (virDomainAbortJob(dom) < 0) @@ -6188,7 +6188,7 @@ cmdVcpucount(vshControl *ctl, const vshCmd *cmd) if (guest) flags |= VIR_DOMAIN_VCPU_GUEST; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; if (all) { @@ -6265,10 +6265,10 @@ cmdVcpuinfo(vshControl *ctl, const vshCmd *cmd) bool pretty = vshCommandOptBool(cmd, "pretty"); int n, m; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; - if ((maxcpu = vshNodeGetCPUCount(ctl->conn)) < 0) + if ((maxcpu = virshNodeGetCPUCount(ctl->conn)) < 0) goto cleanup; if (virDomainGetInfo(dom, &info) != 0) @@ -6297,7 +6297,7 @@ cmdVcpuinfo(vshControl *ctl, const vshCmd *cmd) if (cpuinfo) { vshPrint(ctl, "%-15s %d\n", _("CPU:"), cpuinfo[n].cpu); vshPrint(ctl, "%-15s %s\n", _("State:"), - vshDomainVcpuStateToString(cpuinfo[n].state)); + virshDomainVcpuStateToString(cpuinfo[n].state)); if (cpuinfo[n].cpuTime != 0) { double cpuUsed = cpuinfo[n].cpuTime; @@ -6474,10 +6474,10 @@ cmdVcpuPin(vshControl *ctl, const vshCmd *cmd) return false; } - if ((maxcpu = vshNodeGetCPUCount(ctl->conn)) < 0) + if ((maxcpu = virshNodeGetCPUCount(ctl->conn)) < 0) return false; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; /* Query mode: show CPU affinity information then exit.*/ @@ -6601,7 +6601,7 @@ cmdEmulatorPin(vshControl *ctl, const vshCmd *cmd) if (!current && !live && !config) flags = -1; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; if (vshCommandOptStringReq(ctl, cmd, "cpulist", &cpulist) < 0) { @@ -6610,7 +6610,7 @@ cmdEmulatorPin(vshControl *ctl, const vshCmd *cmd) } query = !cpulist; - if ((maxcpu = vshNodeGetCPUCount(ctl->conn)) < 0) { + if ((maxcpu = virshNodeGetCPUCount(ctl->conn)) < 0) { virDomainFree(dom); return false; } @@ -6727,7 +6727,7 @@ cmdSetvcpus(vshControl *ctl, const vshCmd *cmd) if (maximum) flags |= VIR_DOMAIN_VCPU_MAXIMUM; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; if (vshCommandOptInt(ctl, cmd, "count", &count) < 0 || count <= 0) @@ -6803,10 +6803,10 @@ cmdIOThreadInfo(vshControl *ctl, const vshCmd *cmd) if (live) flags |= VIR_DOMAIN_AFFECT_LIVE; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; - if ((maxcpu = vshNodeGetCPUCount(ctl->conn)) < 0) + if ((maxcpu = virshNodeGetCPUCount(ctl->conn)) < 0) goto cleanup; if ((niothreads = virDomainGetIOThreadInfo(dom, &info, flags)) < 0) { @@ -6903,7 +6903,7 @@ cmdIOThreadPin(vshControl *ctl, const vshCmd *cmd) if (live) flags |= VIR_DOMAIN_AFFECT_LIVE; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; if (vshCommandOptUInt(ctl, cmd, "iothread", &iothread_id) < 0) @@ -6914,7 +6914,7 @@ cmdIOThreadPin(vshControl *ctl, const vshCmd *cmd) goto cleanup; } - if ((maxcpu = vshNodeGetCPUCount(ctl->conn)) < 0) + if ((maxcpu = virshNodeGetCPUCount(ctl->conn)) < 0) goto cleanup; if (!(cpumap = vshParseCPUList(ctl, &cpumaplen, cpulist, maxcpu))) @@ -6990,7 +6990,7 @@ cmdIOThreadAdd(vshControl *ctl, const vshCmd *cmd) if (live) flags |= VIR_DOMAIN_AFFECT_LIVE; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; if (vshCommandOptInt(ctl, cmd, "id", &iothread_id) < 0) @@ -7068,7 +7068,7 @@ cmdIOThreadDel(vshControl *ctl, const vshCmd *cmd) if (live) flags |= VIR_DOMAIN_AFFECT_LIVE; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; if (vshCommandOptInt(ctl, cmd, "id", &iothread_id) < 0) @@ -7133,7 +7133,7 @@ cmdCPUCompare(vshControl *ctl, const vshCmd *cmd) if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0) return false; - if (virFileReadAll(from, VSH_MAX_XML_FILE, &buffer) < 0) + if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) return false; /* try to extract the CPU element from as it would appear in a domain XML*/ @@ -7244,7 +7244,7 @@ cmdCPUBaseline(vshControl *ctl, const vshCmd *cmd) if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0) return false; - if (virFileReadAll(from, VSH_MAX_XML_FILE, &buffer) < 0) + if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) return false; /* add a separate container around the xml */ @@ -7351,7 +7351,7 @@ cmdCPUStats(vshControl *ctl, const vshCmd *cmd) bool ret = false; int rv = 0; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; show_total = vshCommandOptBool(cmd, "total"); @@ -7555,7 +7555,7 @@ cmdCreate(vshControl *ctl, const vshCmd *cmd) if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0) return false; - if (virFileReadAll(from, VSH_MAX_XML_FILE, &buffer) < 0) + if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) return false; if (cmdStartGetFDs(ctl, cmd, &nfds, &fds) < 0) @@ -7634,7 +7634,7 @@ cmdDefine(vshControl *ctl, const vshCmd *cmd) if (vshCommandOptBool(cmd, "validate")) flags |= VIR_DOMAIN_DEFINE_VALIDATE; - if (virFileReadAll(from, VSH_MAX_XML_FILE, &buffer) < 0) + if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) return false; if (flags) @@ -7689,7 +7689,7 @@ cmdDestroy(vshControl *ctl, const vshCmd *cmd) unsigned int flags = 0; int result; - if (!(dom = vshCommandOptDomain(ctl, cmd, &name))) + if (!(dom = virshCommandOptDomain(ctl, cmd, &name))) return false; if (vshCommandOptBool(cmd, "graceful")) @@ -7788,10 +7788,10 @@ cmdDesc(vshControl *ctl, const vshCmd *cmd) if (live) flags |= VIR_DOMAIN_AFFECT_LIVE; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; - if ((state = vshDomainState(ctl, dom, NULL)) < 0) + if ((state = virshDomainState(ctl, dom, NULL)) < 0) goto cleanup; while ((opt = vshCommandOptArgv(ctl, cmd, opt))) { @@ -7814,7 +7814,7 @@ cmdDesc(vshControl *ctl, const vshCmd *cmd) if (edit || desc) { if (!desc) { - desc = vshGetDomainDescription(ctl, dom, title, + desc = virshGetDomainDescription(ctl, dom, title, config?VIR_DOMAIN_XML_INACTIVE:0); if (!desc) goto cleanup; @@ -7822,15 +7822,15 @@ cmdDesc(vshControl *ctl, const vshCmd *cmd) if (edit) { /* Create and open the temporary file. */ - if (!(tmp = vshEditWriteToTempFile(ctl, desc))) + if (!(tmp = virshEditWriteToTempFile(ctl, desc))) goto cleanup; /* Start the editor. */ - if (vshEditFile(ctl, tmp) == -1) + if (virshEditFile(ctl, tmp) == -1) goto cleanup; /* Read back the edited file. */ - if (!(desc_edited = vshEditReadBackFile(ctl, tmp))) + if (!(desc_edited = virshEditReadBackFile(ctl, tmp))) goto cleanup; /* strip a possible newline at the end of file; some @@ -7865,7 +7865,7 @@ cmdDesc(vshControl *ctl, const vshCmd *cmd) title ? _("Domain title updated successfully") : _("Domain description updated successfully")); } else { - desc = vshGetDomainDescription(ctl, dom, title, + desc = virshGetDomainDescription(ctl, dom, title, config?VIR_DOMAIN_XML_INACTIVE:0); if (!desc) goto cleanup; @@ -7991,7 +7991,7 @@ cmdMetadata(vshControl *ctl, const vshCmd *cmd) if (live) flags |= VIR_DOMAIN_AFFECT_LIVE; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; if (vshCommandOptStringReq(ctl, cmd, "uri", &uri) < 0 || @@ -8077,7 +8077,7 @@ cmdInjectNMI(vshControl *ctl, const vshCmd *cmd) virDomainPtr dom; bool ret = true; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; if (virDomainInjectNMI(dom, 0) < 0) @@ -8147,7 +8147,7 @@ cmdSendKey(vshControl *ctl, const vshCmd *cmd) int keycode; unsigned int keycodes[VIR_DOMAIN_SEND_KEY_MAX_KEYS]; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; if (vshCommandOptString(ctl, cmd, "codeset", &codeset_option) <= 0) @@ -8272,7 +8272,7 @@ cmdSendProcessSignal(vshControl *ctl, const vshCmd *cmd) long long pid_value; int signum; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; if (vshCommandOptLongLong(ctl, cmd, "pid", &pid_value) < 0) @@ -8363,7 +8363,7 @@ cmdSetmem(vshControl *ctl, const vshCmd *cmd) if (!current && !live && !config) flags = -1; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; /* The API expects 'unsigned long' KiB, so depending on whether we @@ -8457,7 +8457,7 @@ cmdSetmaxmem(vshControl *ctl, const vshCmd *cmd) if (!current && !live && !config) flags = -1; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; /* The API expects 'unsigned long' KiB, so depending on whether we @@ -8605,7 +8605,7 @@ cmdMemtune(vshControl *ctl, const vshCmd *cmd) if (live) flags |= VIR_DOMAIN_AFFECT_LIVE; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; #define PARSE_MEMTUNE_PARAM(NAME, FIELD) \ @@ -8747,7 +8747,7 @@ cmdNumatune(vshControl * ctl, const vshCmd * cmd) if (live) flags |= VIR_DOMAIN_AFFECT_LIVE; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; if (vshCommandOptStringReq(ctl, cmd, "nodeset", &nodeset) < 0) @@ -8876,7 +8876,7 @@ cmdQemuMonitorCommand(vshControl *ctl, const vshCmd *cmd) bool pad = false; virJSONValuePtr pretty = NULL; - dom = vshCommandOptDomain(ctl, cmd, NULL); + dom = virshCommandOptDomain(ctl, cmd, NULL); if (dom == NULL) goto cleanup; @@ -8931,20 +8931,20 @@ cmdQemuMonitorCommand(vshControl *ctl, const vshCmd *cmd) * "qemu-monitor-event" command */ -struct vshQemuEventData { +struct virshQemuEventData { vshControl *ctl; bool loop; bool pretty; int count; }; -typedef struct vshQemuEventData vshQemuEventData; +typedef struct virshQemuEventData virshQemuEventData; static void vshEventPrint(virConnectPtr conn ATTRIBUTE_UNUSED, virDomainPtr dom, const char *event, long long seconds, unsigned int micros, const char *details, void *opaque) { - vshQemuEventData *data = opaque; + virshQemuEventData *data = opaque; virJSONValuePtr pretty = NULL; char *str = NULL; @@ -9015,7 +9015,7 @@ cmdQemuMonitorEvent(vshControl *ctl, const vshCmd *cmd) int eventId = -1; int timeout = 0; const char *event = NULL; - vshQemuEventData data; + virshQemuEventData data; if (vshCommandOptBool(cmd, "regex")) flags |= VIR_CONNECT_DOMAIN_QEMU_MONITOR_EVENT_REGISTER_REGEX; @@ -9026,13 +9026,13 @@ cmdQemuMonitorEvent(vshControl *ctl, const vshCmd *cmd) data.loop = vshCommandOptBool(cmd, "loop"); data.pretty = vshCommandOptBool(cmd, "pretty"); data.count = 0; - if (vshCommandOptTimeoutToMs(ctl, cmd, &timeout) < 0) + if (virshCommandOptTimeoutToMs(ctl, cmd, &timeout) < 0) return false; if (vshCommandOptString(ctl, cmd, "event", &event) < 0) return false; if (vshCommandOptBool(cmd, "domain")) - dom = vshCommandOptDomain(ctl, cmd, NULL); + dom = virshCommandOptDomain(ctl, cmd, NULL); if (vshEventStart(ctl, timeout) < 0) goto cleanup; @@ -9175,7 +9175,7 @@ cmdQemuAgentCommand(vshControl *ctl, const vshCmd *cmd) bool pad = false; virJSONValuePtr pretty = NULL; - dom = vshCommandOptDomain(ctl, cmd, NULL); + dom = virshCommandOptDomain(ctl, cmd, NULL); if (dom == NULL) goto cleanup; @@ -9290,7 +9290,7 @@ cmdLxcEnterNamespace(vshControl *ctl, const vshCmd *cmd) virSecurityModelPtr secmodel = NULL; virSecurityLabelPtr seclabel = NULL; - dom = vshCommandOptDomain(ctl, cmd, NULL); + dom = virshCommandOptDomain(ctl, cmd, NULL); if (dom == NULL) goto cleanup; @@ -9444,7 +9444,7 @@ cmdDumpXML(vshControl *ctl, const vshCmd *cmd) if (migratable) flags |= VIR_DOMAIN_XML_MIGRATABLE; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; dump = virDomainGetXMLDesc(dom, flags); @@ -9500,7 +9500,7 @@ cmdDomXMLFromNative(vshControl *ctl, const vshCmd *cmd) vshCommandOptStringReq(ctl, cmd, "config", &configFile) < 0) return false; - if (virFileReadAll(configFile, VSH_MAX_XML_FILE, &configData) < 0) + if (virFileReadAll(configFile, VIRSH_MAX_XML_FILE, &configData) < 0) return false; xmlData = virConnectDomainXMLFromNative(ctl->conn, format, configData, flags); @@ -9556,7 +9556,7 @@ cmdDomXMLToNative(vshControl *ctl, const vshCmd *cmd) vshCommandOptStringReq(ctl, cmd, "xml", &xmlFile) < 0) return false; - if (virFileReadAll(xmlFile, VSH_MAX_XML_FILE, &xmlData) < 0) + if (virFileReadAll(xmlFile, VIRSH_MAX_XML_FILE, &xmlData) < 0) return false; configData = virConnectDomainXMLToNative(ctl->conn, format, xmlData, flags); @@ -9598,8 +9598,8 @@ cmdDomname(vshControl *ctl, const vshCmd *cmd) { virDomainPtr dom; - if (!(dom = vshCommandOptDomainBy(ctl, cmd, NULL, - VSH_BYID|VSH_BYUUID))) + if (!(dom = virshCommandOptDomainBy(ctl, cmd, NULL, + VSH_BYID|VSH_BYUUID))) return false; vshPrint(ctl, "%s\n", virDomainGetName(dom)); @@ -9635,8 +9635,8 @@ cmdDomid(vshControl *ctl, const vshCmd *cmd) virDomainPtr dom; unsigned int id; - if (!(dom = vshCommandOptDomainBy(ctl, cmd, NULL, - VSH_BYNAME|VSH_BYUUID))) + if (!(dom = virshCommandOptDomainBy(ctl, cmd, NULL, + VSH_BYNAME|VSH_BYUUID))) return false; id = virDomainGetID(dom); @@ -9676,8 +9676,8 @@ cmdDomuuid(vshControl *ctl, const vshCmd *cmd) virDomainPtr dom; char uuid[VIR_UUID_STRING_BUFLEN]; - if (!(dom = vshCommandOptDomainBy(ctl, cmd, NULL, - VSH_BYNAME|VSH_BYID))) + if (!(dom = virshCommandOptDomainBy(ctl, cmd, NULL, + VSH_BYNAME|VSH_BYID))) return false; if (virDomainGetUUIDString(dom, uuid) != -1) @@ -9824,7 +9824,7 @@ doMigrate(void *opaque) const char *desturi = NULL; const char *opt = NULL; unsigned int flags = 0; - vshCtrlData *data = opaque; + virshCtrlData *data = opaque; vshControl *ctl = data->ctl; const vshCmd *cmd = data->cmd; sigset_t sigmask, oldsigmask; @@ -9838,7 +9838,7 @@ doMigrate(void *opaque) if (pthread_sigmask(SIG_BLOCK, &sigmask, &oldsigmask) < 0) goto out_sig; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) goto out; if (vshCommandOptStringReq(ctl, cmd, "desturi", &desturi) < 0) @@ -9896,7 +9896,7 @@ doMigrate(void *opaque) if (opt) { char *xml; - if (virFileReadAll(opt, VSH_MAX_XML_FILE, &xml) < 0) { + if (virFileReadAll(opt, VIRSH_MAX_XML_FILE, &xml) < 0) { vshError(ctl, _("cannot read file '%s'"), opt); goto save_error; } @@ -9998,9 +9998,9 @@ cmdMigrate(vshControl *ctl, const vshCmd *cmd) bool functionReturn = false; int timeout = 0; bool live_flag = false; - vshCtrlData data = { .dconn = NULL }; + virshCtrlData data = { .dconn = NULL }; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; if (vshCommandOptBool(cmd, "verbose")) @@ -10008,7 +10008,7 @@ cmdMigrate(vshControl *ctl, const vshCmd *cmd) if (vshCommandOptBool(cmd, "live")) live_flag = true; - if (vshCommandOptTimeoutToMs(ctl, cmd, &timeout) < 0) { + if (virshCommandOptTimeoutToMs(ctl, cmd, &timeout) < 0) { goto cleanup; } else if (timeout > 0 && !live_flag) { vshError(ctl, "%s", @@ -10033,7 +10033,7 @@ cmdMigrate(vshControl *ctl, const vshCmd *cmd) if (vshCommandOptStringReq(ctl, cmd, "desturi", &desturi) < 0) goto cleanup; - dconn = vshConnect(ctl, desturi, false); + dconn = virshConnect(ctl, desturi, false); if (!dconn) goto cleanup; @@ -10093,7 +10093,7 @@ cmdMigrateSetMaxDowntime(vshControl *ctl, const vshCmd *cmd) long long downtime = 0; bool ret = false; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; if (vshCommandOptLongLong(ctl, cmd, "downtime", &downtime) < 0) @@ -10151,7 +10151,7 @@ cmdMigrateCompCache(vshControl *ctl, const vshCmd *cmd) double value; int rc; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; rc = vshCommandOptULongLong(ctl, cmd, "size", &size); @@ -10165,7 +10165,7 @@ cmdMigrateCompCache(vshControl *ctl, const vshCmd *cmd) if (virDomainMigrateGetCompressionCache(dom, &size, 0) < 0) goto cleanup; - value = vshPrettyCapacity(size, &unit); + value = virshPrettyCapacity(size, &unit); vshPrint(ctl, _("Compression cache: %.3lf %s"), value, unit); ret = true; @@ -10209,7 +10209,7 @@ cmdMigrateSetMaxSpeed(vshControl *ctl, const vshCmd *cmd) unsigned long bandwidth = 0; bool ret = false; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; if (vshCommandOptULWrap(ctl, cmd, "bandwidth", &bandwidth) < 0) @@ -10254,7 +10254,7 @@ cmdMigrateGetMaxSpeed(vshControl *ctl, const vshCmd *cmd) unsigned long bandwidth; bool ret = false; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; if (virDomainMigrateGetMaxSpeed(dom, &bandwidth, 0) < 0) @@ -10324,7 +10324,7 @@ cmdDomDisplay(vshControl *ctl, const vshCmd *cmd) const char *xpath_fmt = "string(/domain/devices/graphics[@type='%s']/%s)"; virSocketAddr addr; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; if (!virDomainIsActive(dom)) { @@ -10526,7 +10526,7 @@ cmdVNCDisplay(vshControl *ctl, const vshCmd *cmd) char *doc = NULL; char *listen_addr = NULL; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; /* Check if the domain is active and don't rely on -1 for this */ @@ -10610,7 +10610,7 @@ cmdTTYConsole(vshControl *ctl, const vshCmd *cmd) bool ret = false; char *doc; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; doc = virDomainGetXMLDesc(dom, 0); @@ -10667,7 +10667,7 @@ cmdDomHostname(vshControl *ctl, const vshCmd *cmd) virDomainPtr dom; bool ret = false; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; hostname = virDomainGetHostname(dom, 0); @@ -10868,7 +10868,7 @@ cmdDetachDevice(vshControl *ctl, const vshCmd *cmd) if (live) flags |= VIR_DOMAIN_AFFECT_LIVE; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; if (persistent && @@ -10878,7 +10878,7 @@ cmdDetachDevice(vshControl *ctl, const vshCmd *cmd) if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0) goto cleanup; - if (virFileReadAll(from, VSH_MAX_XML_FILE, &buffer) < 0) { + if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) { vshReportError(ctl); goto cleanup; } @@ -10972,7 +10972,7 @@ cmdUpdateDevice(vshControl *ctl, const vshCmd *cmd) if (live) flags |= VIR_DOMAIN_AFFECT_LIVE; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0) @@ -10982,7 +10982,7 @@ cmdUpdateDevice(vshControl *ctl, const vshCmd *cmd) virDomainIsActive(dom) == 1) flags |= VIR_DOMAIN_AFFECT_LIVE; - if (virFileReadAll(from, VSH_MAX_XML_FILE, &buffer) < 0) { + if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) { vshReportError(ctl); goto cleanup; } @@ -11083,7 +11083,7 @@ cmdDetachInterface(vshControl *ctl, const vshCmd *cmd) if (live) flags |= VIR_DOMAIN_AFFECT_LIVE; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; if (vshCommandOptStringReq(ctl, cmd, "type", &type) < 0) @@ -11186,14 +11186,14 @@ cmdDetachInterface(vshControl *ctl, const vshCmd *cmd) } typedef enum { - VSH_FIND_DISK_NORMAL, - VSH_FIND_DISK_CHANGEABLE, + VIRSH_FIND_DISK_NORMAL, + VIRSH_FIND_DISK_CHANGEABLE, } vshFindDiskType; /* Helper function to find disk device in XML doc. Returns the disk * node on success, or NULL on failure. Caller must free the result * @path: Fully-qualified path or target of disk device. - * @type: Either VSH_FIND_DISK_NORMAL or VSH_FIND_DISK_CHANGEABLE. + * @type: Either VIRSH_FIND_DISK_NORMAL or VIRSH_FIND_DISK_CHANGEABLE. */ static xmlNodePtr vshFindDisk(const char *doc, @@ -11226,7 +11226,7 @@ vshFindDisk(const char *doc, for (i = 0; i < obj->nodesetval->nodeNr; i++) { bool is_supported = true; - if (type == VSH_FIND_DISK_CHANGEABLE) { + if (type == VIRSH_FIND_DISK_CHANGEABLE) { xmlNodePtr n = obj->nodesetval->nodeTab[i]; is_supported = false; @@ -11281,9 +11281,9 @@ vshFindDisk(const char *doc, } typedef enum { - VSH_UPDATE_DISK_XML_EJECT, - VSH_UPDATE_DISK_XML_INSERT, - VSH_UPDATE_DISK_XML_UPDATE, + VIRSH_UPDATE_DISK_XML_EJECT, + VIRSH_UPDATE_DISK_XML_INSERT, + VIRSH_UPDATE_DISK_XML_UPDATE, } vshUpdateDiskXMLType; /* Helper function to prepare disk XML. Could be used for disk @@ -11320,7 +11320,7 @@ vshUpdateDiskXML(xmlNodePtr disk_node, break; } - if (type == VSH_UPDATE_DISK_XML_EJECT) { + if (type == VIRSH_UPDATE_DISK_XML_EJECT) { if (!source) { vshError(NULL, _("The disk device '%s' doesn't have media"), target); goto cleanup; @@ -11334,7 +11334,7 @@ vshUpdateDiskXML(xmlNodePtr disk_node, goto cleanup; } - if (type == VSH_UPDATE_DISK_XML_INSERT && source) { + if (type == VIRSH_UPDATE_DISK_XML_INSERT && source) { vshError(NULL, _("The disk device '%s' already has media"), target); goto cleanup; } @@ -11447,7 +11447,7 @@ cmdDetachDisk(vshControl *ctl, const vshCmd *cmd) if (live) flags |= VIR_DOMAIN_AFFECT_LIVE; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; if (vshCommandOptStringReq(ctl, cmd, "target", &target) < 0) @@ -11465,7 +11465,7 @@ cmdDetachDisk(vshControl *ctl, const vshCmd *cmd) virDomainIsActive(dom) == 1) flags |= VIR_DOMAIN_AFFECT_LIVE; - if (!(disk_node = vshFindDisk(doc, target, VSH_FIND_DISK_NORMAL))) + if (!(disk_node = vshFindDisk(doc, target, VIRSH_FIND_DISK_NORMAL))) goto cleanup; if (!(disk_xml = virXMLNodeToString(NULL, disk_node))) { @@ -11529,7 +11529,7 @@ cmdEdit(vshControl *ctl, const vshCmd *cmd) unsigned int query_flags = VIR_DOMAIN_XML_SECURE | VIR_DOMAIN_XML_INACTIVE; unsigned int define_flags = VIR_DOMAIN_DEFINE_VALIDATE; - dom = vshCommandOptDomain(ctl, cmd, NULL); + dom = virshCommandOptDomain(ctl, cmd, NULL); if (dom == NULL) goto cleanup; @@ -11545,7 +11545,7 @@ cmdEdit(vshControl *ctl, const vshCmd *cmd) goto edit_cleanup; \ } while (0) #define EDIT_DEFINE \ - (dom_edited = vshDomainDefine(ctl->conn, doc_edited, define_flags)) + (dom_edited = virshDomainDefine(ctl->conn, doc_edited, define_flags)) #define EDIT_RELAX \ do { \ define_flags &= ~VIR_DOMAIN_DEFINE_VALIDATE; \ @@ -12285,11 +12285,11 @@ cmdEvent(vshControl *ctl, const vshCmd *cmd) data[0].cb = &vshEventCallbacks[event]; data[0].id = -1; } - if (vshCommandOptTimeoutToMs(ctl, cmd, &timeout) < 0) + if (virshCommandOptTimeoutToMs(ctl, cmd, &timeout) < 0) goto cleanup; if (vshCommandOptBool(cmd, "domain")) - dom = vshCommandOptDomain(ctl, cmd, NULL); + dom = virshCommandOptDomain(ctl, cmd, NULL); if (vshEventStart(ctl, timeout) < 0) goto cleanup; @@ -12448,19 +12448,19 @@ cmdChangeMedia(vshControl *ctl, const vshCmd *cmd) } if (eject) { - update_type = VSH_UPDATE_DISK_XML_EJECT; + update_type = VIRSH_UPDATE_DISK_XML_EJECT; action = "eject"; success_msg = _("Successfully ejected media."); } if (insert) { - update_type = VSH_UPDATE_DISK_XML_INSERT; + update_type = VIRSH_UPDATE_DISK_XML_INSERT; action = "insert"; success_msg = _("Successfully inserted media."); } if (update || (!eject && !insert)) { - update_type = VSH_UPDATE_DISK_XML_UPDATE; + update_type = VIRSH_UPDATE_DISK_XML_UPDATE; action = "update"; success_msg = _("Successfully updated media."); } @@ -12475,7 +12475,7 @@ cmdChangeMedia(vshControl *ctl, const vshCmd *cmd) if (force) flags |= VIR_DOMAIN_DEVICE_MODIFY_FORCE; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; if (vshCommandOptStringReq(ctl, cmd, "path", &path) < 0) @@ -12488,7 +12488,7 @@ cmdChangeMedia(vshControl *ctl, const vshCmd *cmd) if (!doc) goto cleanup; - if (!(disk_node = vshFindDisk(doc, path, VSH_FIND_DISK_CHANGEABLE))) + if (!(disk_node = vshFindDisk(doc, path, VIRSH_FIND_DISK_CHANGEABLE))) goto cleanup; if (!(disk_xml = vshUpdateDiskXML(disk_node, source, block, path, @@ -12552,7 +12552,7 @@ cmdDomFSTrim(vshControl *ctl, const vshCmd *cmd) const char *mountPoint = NULL; unsigned int flags = 0; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return ret; if (vshCommandOptULongLong(ctl, cmd, "minimum", &minimum) < 0) @@ -12604,7 +12604,7 @@ cmdDomFSFreeze(vshControl *ctl, const vshCmd *cmd) const char **mountpoints = NULL; size_t nmountpoints = 0; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; while ((opt = vshCommandOptArgv(ctl, cmd, opt))) { @@ -12661,7 +12661,7 @@ cmdDomFSThaw(vshControl *ctl, const vshCmd *cmd) const char **mountpoints = NULL; size_t nmountpoints = 0; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; while ((opt = vshCommandOptArgv(ctl, cmd, opt))) { @@ -12714,7 +12714,7 @@ cmdDomFSInfo(vshControl *ctl, const vshCmd *cmd) size_t i, j; virDomainFSInfoPtr *info; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; ret = virDomainGetFSInfo(dom, &info, 0); diff --git a/tools/virsh-domain.h b/tools/virsh-domain.h index f46538f..2f3ec30 100644 --- a/tools/virsh-domain.h +++ b/tools/virsh-domain.h @@ -28,16 +28,16 @@ # include "virsh.h" -virDomainPtr vshLookupDomainBy(vshControl *ctl, - const char *name, - unsigned int flags); +virDomainPtr virshLookupDomainBy(vshControl *ctl, + const char *name, + unsigned int flags); -virDomainPtr vshCommandOptDomainBy(vshControl *ctl, const vshCmd *cmd, - const char **name, unsigned int flags); +virDomainPtr virshCommandOptDomainBy(vshControl *ctl, const vshCmd *cmd, + const char **name, unsigned int flags); /* default is lookup by Id, Name and UUID */ -# define vshCommandOptDomain(_ctl, _cmd, _name) \ - vshCommandOptDomainBy(_ctl, _cmd, _name, VSH_BYID|VSH_BYUUID|VSH_BYNAME) +# define virshCommandOptDomain(_ctl, _cmd, _name) \ + virshCommandOptDomainBy(_ctl, _cmd, _name, VSH_BYID|VSH_BYUUID|VSH_BYNAME) extern const vshCmdDef domManagementCmds[]; diff --git a/tools/virsh-edit.c b/tools/virsh-edit.c index 1b39cb7..49d4a5a 100644 --- a/tools/virsh-edit.c +++ b/tools/virsh-edit.c @@ -70,7 +70,7 @@ do { goto edit_cleanup; /* Create and open the temporary file. */ - tmp = vshEditWriteToTempFile(ctl, doc); + tmp = virshEditWriteToTempFile(ctl, doc); if (!tmp) goto edit_cleanup; @@ -81,12 +81,12 @@ do { #endif /* Start the editor. */ - if (vshEditFile(ctl, tmp) == -1) + if (virshEditFile(ctl, tmp) == -1) goto edit_cleanup; /* Read back the edited file. */ VIR_FREE(doc_edited); - doc_edited = vshEditReadBackFile(ctl, tmp); + doc_edited = virshEditReadBackFile(ctl, tmp); if (!doc_edited) goto edit_cleanup; @@ -118,7 +118,7 @@ do { msg = _("Failed."); if (msg) { - int c = vshAskReedit(ctl, msg, relax_avail); + int c = virshAskReedit(ctl, msg, relax_avail); switch (c) { case 'y': goto reedit; diff --git a/tools/virsh-host.c b/tools/virsh-host.c index 66f7fd9..24341ae 100644 --- a/tools/virsh-host.c +++ b/tools/virsh-host.c @@ -703,17 +703,17 @@ static const vshCmdOptDef opts_node_cpustats[] = { }; typedef enum { - VSH_CPU_USER, - VSH_CPU_SYSTEM, - VSH_CPU_IDLE, - VSH_CPU_IOWAIT, - VSH_CPU_INTR, - VSH_CPU_USAGE, - VSH_CPU_LAST -} vshCPUStats; - -VIR_ENUM_DECL(vshCPUStats); -VIR_ENUM_IMPL(vshCPUStats, VSH_CPU_LAST, + VIRSH_CPU_USER, + VIRSH_CPU_SYSTEM, + VIRSH_CPU_IDLE, + VIRSH_CPU_IOWAIT, + VIRSH_CPU_INTR, + VIRSH_CPU_USAGE, + VIRSH_CPU_LAST +} virshCPUStats; + +VIR_ENUM_DECL(virshCPUStats); +VIR_ENUM_IMPL(virshCPUStats, VIRSH_CPU_LAST, VIR_NODE_CPU_STATS_USER, VIR_NODE_CPU_STATS_KERNEL, VIR_NODE_CPU_STATS_IDLE, @@ -721,7 +721,7 @@ VIR_ENUM_IMPL(vshCPUStats, VSH_CPU_LAST, VIR_NODE_CPU_STATS_INTR, VIR_NODE_CPU_STATS_UTILIZATION); -const char *vshCPUOutput[] = { +const char *virshCPUOutput[] = { N_("user:"), N_("system:"), N_("idle:"), @@ -739,8 +739,8 @@ cmdNodeCpuStats(vshControl *ctl, const vshCmd *cmd) virNodeCPUStatsPtr params; int nparams = 0; bool ret = false; - unsigned long long cpu_stats[VSH_CPU_LAST] = { 0 }; - bool present[VSH_CPU_LAST] = { false }; + unsigned long long cpu_stats[VIRSH_CPU_LAST] = { 0 }; + bool present[VIRSH_CPU_LAST] = { false }; if (vshCommandOptInt(ctl, cmd, "cpu", &cpuNum) < 0) return false; @@ -765,7 +765,7 @@ cmdNodeCpuStats(vshControl *ctl, const vshCmd *cmd) } for (j = 0; j < nparams; j++) { - int field = vshCPUStatsTypeFromString(params[j].field); + int field = virshCPUStatsTypeFromString(params[j].field); if (field < 0) continue; @@ -778,34 +778,37 @@ cmdNodeCpuStats(vshControl *ctl, const vshCmd *cmd) } } - if (present[VSH_CPU_USAGE] || !flag_percent) + if (present[VIRSH_CPU_USAGE] || !flag_percent) break; sleep(1); } if (!flag_percent) { - for (i = 0; i < VSH_CPU_USAGE; i++) { + for (i = 0; i < VIRSH_CPU_USAGE; i++) { if (present[i]) { - vshPrint(ctl, "%-15s %20llu\n", _(vshCPUOutput[i]), + vshPrint(ctl, "%-15s %20llu\n", _(virshCPUOutput[i]), cpu_stats[i]); } } } else { - if (present[VSH_CPU_USAGE]) { - vshPrint(ctl, "%-15s %5.1llu%%\n", _("usage:"), cpu_stats[VSH_CPU_USAGE]); - vshPrint(ctl, "%-15s %5.1llu%%\n", _("idle:"), 100 - cpu_stats[VSH_CPU_USAGE]); + if (present[VIRSH_CPU_USAGE]) { + vshPrint(ctl, "%-15s %5.1llu%%\n", + _("usage:"), cpu_stats[VIRSH_CPU_USAGE]); + vshPrint(ctl, "%-15s %5.1llu%%\n", + _("idle:"), 100 - cpu_stats[VIRSH_CPU_USAGE]); } else { double usage, total_time = 0; - for (i = 0; i < VSH_CPU_USAGE; i++) + for (i = 0; i < VIRSH_CPU_USAGE; i++) total_time += cpu_stats[i]; - usage = (cpu_stats[VSH_CPU_USER] + cpu_stats[VSH_CPU_SYSTEM]) / total_time * 100; + usage = (cpu_stats[VIRSH_CPU_USER] + cpu_stats[VIRSH_CPU_SYSTEM]) + / total_time * 100; vshPrint(ctl, "%-15s %5.1lf%%\n", _("usage:"), usage); - for (i = 0; i < VSH_CPU_USAGE; i++) { + for (i = 0; i < VIRSH_CPU_USAGE; i++) { if (present[i]) { - vshPrint(ctl, "%-15s %5.1lf%%\n", _(vshCPUOutput[i]), + vshPrint(ctl, "%-15s %5.1lf%%\n", _(virshCPUOutput[i]), cpu_stats[i] / total_time * 100); } } diff --git a/tools/virsh-interface.c b/tools/virsh-interface.c index 6ad5345..8b085cd 100644 --- a/tools/virsh-interface.c +++ b/tools/virsh-interface.c @@ -41,9 +41,9 @@ #include "virstring.h" virInterfacePtr -vshCommandOptInterfaceBy(vshControl *ctl, const vshCmd *cmd, - const char *optname, - const char **name, unsigned int flags) +virshCommandOptInterfaceBy(vshControl *ctl, const vshCmd *cmd, + const char *optname, + const char **name, unsigned int flags) { virInterfacePtr iface = NULL; const char *n = NULL; @@ -115,7 +115,7 @@ cmdInterfaceEdit(vshControl *ctl, const vshCmd *cmd) virInterfacePtr iface_edited = NULL; unsigned int flags = VIR_INTERFACE_XML_INACTIVE; - iface = vshCommandOptInterface(ctl, cmd, NULL); + iface = virshCommandOptInterface(ctl, cmd, NULL); if (iface == NULL) goto cleanup; @@ -402,8 +402,8 @@ cmdInterfaceName(vshControl *ctl, const vshCmd *cmd) { virInterfacePtr iface; - if (!(iface = vshCommandOptInterfaceBy(ctl, cmd, NULL, NULL, - VSH_BYMAC))) + if (!(iface = virshCommandOptInterfaceBy(ctl, cmd, NULL, NULL, + VSH_BYMAC))) return false; vshPrint(ctl, "%s\n", virInterfaceGetName(iface)); @@ -438,8 +438,8 @@ cmdInterfaceMAC(vshControl *ctl, const vshCmd *cmd) { virInterfacePtr iface; - if (!(iface = vshCommandOptInterfaceBy(ctl, cmd, NULL, NULL, - VSH_BYNAME))) + if (!(iface = virshCommandOptInterfaceBy(ctl, cmd, NULL, NULL, + VSH_BYNAME))) return false; vshPrint(ctl, "%s\n", virInterfaceGetMACString(iface)); @@ -485,7 +485,7 @@ cmdInterfaceDumpXML(vshControl *ctl, const vshCmd *cmd) if (inactive) flags |= VIR_INTERFACE_XML_INACTIVE; - if (!(iface = vshCommandOptInterface(ctl, cmd, NULL))) + if (!(iface = virshCommandOptInterface(ctl, cmd, NULL))) return false; dump = virInterfaceGetXMLDesc(iface, flags); @@ -534,7 +534,7 @@ cmdInterfaceDefine(vshControl *ctl, const vshCmd *cmd) if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0) return false; - if (virFileReadAll(from, VSH_MAX_XML_FILE, &buffer) < 0) + if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) return false; iface = virInterfaceDefineXML(ctl->conn, buffer, 0); @@ -580,7 +580,7 @@ cmdInterfaceUndefine(vshControl *ctl, const vshCmd *cmd) bool ret = true; const char *name; - if (!(iface = vshCommandOptInterface(ctl, cmd, &name))) + if (!(iface = virshCommandOptInterface(ctl, cmd, &name))) return false; if (virInterfaceUndefine(iface) == 0) { @@ -623,7 +623,7 @@ cmdInterfaceStart(vshControl *ctl, const vshCmd *cmd) bool ret = true; const char *name; - if (!(iface = vshCommandOptInterface(ctl, cmd, &name))) + if (!(iface = virshCommandOptInterface(ctl, cmd, &name))) return false; if (virInterfaceCreate(iface, 0) == 0) { @@ -666,7 +666,7 @@ cmdInterfaceDestroy(vshControl *ctl, const vshCmd *cmd) bool ret = true; const char *name; - if (!(iface = vshCommandOptInterface(ctl, cmd, &name))) + if (!(iface = virshCommandOptInterface(ctl, cmd, &name))) return false; if (virInterfaceDestroy(iface, 0) == 0) { @@ -825,8 +825,8 @@ cmdInterfaceBridge(vshControl *ctl, const vshCmd *cmd) xmlNodePtr top_node, br_node, if_node, cur; /* Get a handle to the original device */ - if (!(if_handle = vshCommandOptInterfaceBy(ctl, cmd, "interface", - &if_name, VSH_BYNAME))) { + if (!(if_handle = virshCommandOptInterfaceBy(ctl, cmd, "interface", + &if_name, VSH_BYNAME))) { goto cleanup; } @@ -1045,8 +1045,8 @@ cmdInterfaceUnbridge(vshControl *ctl, const vshCmd *cmd) xmlNodePtr top_node, if_node, cur; /* Get a handle to the original device */ - if (!(br_handle = vshCommandOptInterfaceBy(ctl, cmd, "bridge", - &br_name, VSH_BYNAME))) { + if (!(br_handle = virshCommandOptInterfaceBy(ctl, cmd, "bridge", + &br_name, VSH_BYNAME))) { goto cleanup; } diff --git a/tools/virsh-interface.h b/tools/virsh-interface.h index 6272aab..be756ec 100644 --- a/tools/virsh-interface.h +++ b/tools/virsh-interface.h @@ -28,14 +28,14 @@ # include "virsh.h" -virInterfacePtr vshCommandOptInterfaceBy(vshControl *ctl, const vshCmd *cmd, - const char *optname, - const char **name, unsigned int flags); +virInterfacePtr virshCommandOptInterfaceBy(vshControl *ctl, const vshCmd *cmd, + const char *optname, + const char **name, unsigned int flags); /* default is lookup by Name and MAC */ -# define vshCommandOptInterface(_ctl, _cmd, _name) \ - vshCommandOptInterfaceBy(_ctl, _cmd, NULL, _name, \ - VSH_BYMAC|VSH_BYNAME) +# define virshCommandOptInterface(_ctl, _cmd, _name) \ + virshCommandOptInterfaceBy(_ctl, _cmd, NULL, _name, \ + VSH_BYMAC|VSH_BYNAME) extern const vshCmdDef ifaceCmds[]; diff --git a/tools/virsh-network.c b/tools/virsh-network.c index 66123c4..79909d9 100644 --- a/tools/virsh-network.c +++ b/tools/virsh-network.c @@ -34,8 +34,8 @@ #include "conf/network_conf.h" virNetworkPtr -vshCommandOptNetworkBy(vshControl *ctl, const vshCmd *cmd, - const char **name, unsigned int flags) +virshCommandOptNetworkBy(vshControl *ctl, const vshCmd *cmd, + const char **name, unsigned int flags) { virNetworkPtr network = NULL; const char *n = NULL; @@ -103,7 +103,7 @@ cmdNetworkAutostart(vshControl *ctl, const vshCmd *cmd) const char *name; int autostart; - if (!(network = vshCommandOptNetwork(ctl, cmd, &name))) + if (!(network = virshCommandOptNetwork(ctl, cmd, &name))) return false; autostart = !vshCommandOptBool(cmd, "disable"); @@ -159,7 +159,7 @@ cmdNetworkCreate(vshControl *ctl, const vshCmd *cmd) if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0) return false; - if (virFileReadAll(from, VSH_MAX_XML_FILE, &buffer) < 0) + if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) return false; network = virNetworkCreateXML(ctl->conn, buffer); @@ -210,7 +210,7 @@ cmdNetworkDefine(vshControl *ctl, const vshCmd *cmd) if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0) return false; - if (virFileReadAll(from, VSH_MAX_XML_FILE, &buffer) < 0) + if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) return false; network = virNetworkDefineXML(ctl->conn, buffer); @@ -256,7 +256,7 @@ cmdNetworkDestroy(vshControl *ctl, const vshCmd *cmd) bool ret = true; const char *name; - if (!(network = vshCommandOptNetwork(ctl, cmd, &name))) + if (!(network = virshCommandOptNetwork(ctl, cmd, &name))) return false; if (virNetworkDestroy(network) == 0) { @@ -305,7 +305,7 @@ cmdNetworkDumpXML(vshControl *ctl, const vshCmd *cmd) unsigned int flags = 0; int inactive; - if (!(network = vshCommandOptNetwork(ctl, cmd, NULL))) + if (!(network = virshCommandOptNetwork(ctl, cmd, NULL))) return false; inactive = vshCommandOptBool(cmd, "inactive"); @@ -357,7 +357,7 @@ cmdNetworkInfo(vshControl *ctl, const vshCmd *cmd) int active = -1; char *bridge = NULL; - if (!(network = vshCommandOptNetwork(ctl, cmd, NULL))) + if (!(network = virshCommandOptNetwork(ctl, cmd, NULL))) return false; vshPrint(ctl, "%-15s %s\n", _("Name:"), virNetworkGetName(network)); @@ -768,7 +768,7 @@ cmdNetworkName(vshControl *ctl, const vshCmd *cmd) { virNetworkPtr network; - if (!(network = vshCommandOptNetworkBy(ctl, cmd, NULL, + if (!(network = virshCommandOptNetworkBy(ctl, cmd, NULL, VSH_BYUUID))) return false; @@ -806,7 +806,7 @@ cmdNetworkStart(vshControl *ctl, const vshCmd *cmd) bool ret = true; const char *name = NULL; - if (!(network = vshCommandOptNetwork(ctl, cmd, &name))) + if (!(network = virshCommandOptNetwork(ctl, cmd, &name))) return false; if (virNetworkCreate(network) == 0) { @@ -848,7 +848,7 @@ cmdNetworkUndefine(vshControl *ctl, const vshCmd *cmd) bool ret = true; const char *name; - if (!(network = vshCommandOptNetwork(ctl, cmd, &name))) + if (!(network = virshCommandOptNetwork(ctl, cmd, &name))) return false; if (virNetworkUndefine(network) == 0) { @@ -943,7 +943,7 @@ cmdNetworkUpdate(vshControl *ctl, const vshCmd *cmd) unsigned int flags = 0; const char *affected; - if (!(network = vshCommandOptNetwork(ctl, cmd, NULL))) + if (!(network = virshCommandOptNetwork(ctl, cmd, NULL))) return false; if (vshCommandOptStringReq(ctl, cmd, "command", &commandStr) < 0) @@ -986,7 +986,7 @@ cmdNetworkUpdate(vshControl *ctl, const vshCmd *cmd) /* contents of xmldata is actually the name of a file that * contains the xml. */ - if (virFileReadAll(xml, VSH_MAX_XML_FILE, &xmlFromFile) < 0) + if (virFileReadAll(xml, VIRSH_MAX_XML_FILE, &xmlFromFile) < 0) goto cleanup; /* NB: the original xml is just a const char * that points * to a string owned by the vshCmd object, and will be freed @@ -1066,7 +1066,7 @@ cmdNetworkUuid(vshControl *ctl, const vshCmd *cmd) virNetworkPtr network; char uuid[VIR_UUID_STRING_BUFLEN]; - if (!(network = vshCommandOptNetworkBy(ctl, cmd, NULL, + if (!(network = virshCommandOptNetworkBy(ctl, cmd, NULL, VSH_BYNAME))) return false; @@ -1124,7 +1124,7 @@ cmdNetworkEdit(vshControl *ctl, const vshCmd *cmd) virNetworkPtr network = NULL; virNetworkPtr network_edited = NULL; - network = vshCommandOptNetwork(ctl, cmd, NULL); + network = virshCommandOptNetwork(ctl, cmd, NULL); if (network == NULL) goto cleanup; @@ -1270,11 +1270,11 @@ cmdNetworkEvent(vshControl *ctl, const vshCmd *cmd) data.ctl = ctl; data.loop = vshCommandOptBool(cmd, "loop"); data.count = 0; - if (vshCommandOptTimeoutToMs(ctl, cmd, &timeout) < 0) + if (virshCommandOptTimeoutToMs(ctl, cmd, &timeout) < 0) return false; if (vshCommandOptBool(cmd, "network")) - net = vshCommandOptNetwork(ctl, cmd, NULL); + net = virshCommandOptNetwork(ctl, cmd, NULL); if (vshEventStart(ctl, timeout) < 0) goto cleanup; @@ -1369,7 +1369,7 @@ cmdNetworkDHCPLeases(vshControl *ctl, const vshCmd *cmd) if (vshCommandOptString(ctl, cmd, "mac", &mac) < 0) return false; - if (!(network = vshCommandOptNetwork(ctl, cmd, &name))) + if (!(network = virshCommandOptNetwork(ctl, cmd, &name))) return false; if ((nleases = virNetworkGetDHCPLeases(network, mac, &leases, flags)) < 0) { diff --git a/tools/virsh-network.h b/tools/virsh-network.h index 3beeeb9..49823a8 100644 --- a/tools/virsh-network.h +++ b/tools/virsh-network.h @@ -29,13 +29,13 @@ # include "virsh.h" virNetworkPtr -vshCommandOptNetworkBy(vshControl *ctl, const vshCmd *cmd, - const char **name, unsigned int flags); +virshCommandOptNetworkBy(vshControl *ctl, const vshCmd *cmd, + const char **name, unsigned int flags); /* default is lookup by Name and UUID */ -# define vshCommandOptNetwork(_ctl, _cmd, _name) \ - vshCommandOptNetworkBy(_ctl, _cmd, _name, \ - VSH_BYUUID|VSH_BYNAME) +# define virshCommandOptNetwork(_ctl, _cmd, _name) \ + virshCommandOptNetworkBy(_ctl, _cmd, _name, \ + VSH_BYUUID|VSH_BYNAME) extern const vshCmdDef networkCmds[]; diff --git a/tools/virsh-nodedev.c b/tools/virsh-nodedev.c index 8c578d1..adf4423 100644 --- a/tools/virsh-nodedev.c +++ b/tools/virsh-nodedev.c @@ -69,7 +69,7 @@ cmdNodeDeviceCreate(vshControl *ctl, const vshCmd *cmd) if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0) return false; - if (virFileReadAll(from, VSH_MAX_XML_FILE, &buffer) < 0) + if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) return false; dev = virNodeDeviceCreateXML(ctl->conn, buffer, 0); @@ -480,8 +480,8 @@ cmdNodeListDevices(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) for (i = 0; i < list->ndevices; i++) { if (parents[i] == NULL && - vshTreePrint(ctl, vshNodeListLookup, &arrays, - list->ndevices, i) < 0) + virshTreePrint(ctl, vshNodeListLookup, &arrays, + list->ndevices, i) < 0) ret = false; } diff --git a/tools/virsh-nwfilter.c b/tools/virsh-nwfilter.c index 63c1c7e..d2c8a79 100644 --- a/tools/virsh-nwfilter.c +++ b/tools/virsh-nwfilter.c @@ -33,8 +33,8 @@ #include "virutil.h" virNWFilterPtr -vshCommandOptNWFilterBy(vshControl *ctl, const vshCmd *cmd, - const char **name, unsigned int flags) +virshCommandOptNWFilterBy(vshControl *ctl, const vshCmd *cmd, + const char **name, unsigned int flags) { virNWFilterPtr nwfilter = NULL; const char *n = NULL; @@ -102,7 +102,7 @@ cmdNWFilterDefine(vshControl *ctl, const vshCmd *cmd) if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0) return false; - if (virFileReadAll(from, VSH_MAX_XML_FILE, &buffer) < 0) + if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) return false; nwfilter = virNWFilterDefineXML(ctl->conn, buffer); @@ -148,7 +148,7 @@ cmdNWFilterUndefine(vshControl *ctl, const vshCmd *cmd) bool ret = true; const char *name; - if (!(nwfilter = vshCommandOptNWFilter(ctl, cmd, &name))) + if (!(nwfilter = virshCommandOptNWFilter(ctl, cmd, &name))) return false; if (virNWFilterUndefine(nwfilter) == 0) { @@ -191,7 +191,7 @@ cmdNWFilterDumpXML(vshControl *ctl, const vshCmd *cmd) bool ret = true; char *dump; - if (!(nwfilter = vshCommandOptNWFilter(ctl, cmd, NULL))) + if (!(nwfilter = virshCommandOptNWFilter(ctl, cmd, NULL))) return false; dump = virNWFilterGetXMLDesc(nwfilter, 0); @@ -407,7 +407,7 @@ cmdNWFilterEdit(vshControl *ctl, const vshCmd *cmd) virNWFilterPtr nwfilter = NULL; virNWFilterPtr nwfilter_edited = NULL; - nwfilter = vshCommandOptNWFilter(ctl, cmd, NULL); + nwfilter = virshCommandOptNWFilter(ctl, cmd, NULL); if (nwfilter == NULL) goto cleanup; diff --git a/tools/virsh-nwfilter.h b/tools/virsh-nwfilter.h index a9a995f..a570813 100644 --- a/tools/virsh-nwfilter.h +++ b/tools/virsh-nwfilter.h @@ -29,13 +29,13 @@ # include "virsh.h" virNWFilterPtr -vshCommandOptNWFilterBy(vshControl *ctl, const vshCmd *cmd, - const char **name, unsigned int flags); +virshCommandOptNWFilterBy(vshControl *ctl, const vshCmd *cmd, + const char **name, unsigned int flags); /* default is lookup by Name and UUID */ -# define vshCommandOptNWFilter(_ctl, _cmd, _name) \ - vshCommandOptNWFilterBy(_ctl, _cmd, _name, \ - VSH_BYUUID|VSH_BYNAME) +# define virshCommandOptNWFilter(_ctl, _cmd, _name) \ + virshCommandOptNWFilterBy(_ctl, _cmd, _name, \ + VSH_BYUUID|VSH_BYNAME) extern const vshCmdDef nwfilterCmds[]; diff --git a/tools/virsh-pool.c b/tools/virsh-pool.c index b420fe2..19c1f28 100644 --- a/tools/virsh-pool.c +++ b/tools/virsh-pool.c @@ -34,8 +34,8 @@ #include "virstring.h" virStoragePoolPtr -vshCommandOptPoolBy(vshControl *ctl, const vshCmd *cmd, const char *optname, - const char **name, unsigned int flags) +virshCommandOptPoolBy(vshControl *ctl, const vshCmd *cmd, const char *optname, + const char **name, unsigned int flags) { virStoragePoolPtr pool = NULL; const char *n = NULL; @@ -102,7 +102,7 @@ cmdPoolAutostart(vshControl *ctl, const vshCmd *cmd) const char *name; int autostart; - if (!(pool = vshCommandOptPool(ctl, cmd, "pool", &name))) + if (!(pool = virshCommandOptPool(ctl, cmd, "pool", &name))) return false; autostart = !vshCommandOptBool(cmd, "disable"); @@ -158,7 +158,7 @@ cmdPoolCreate(vshControl *ctl, const vshCmd *cmd) if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0) return false; - if (virFileReadAll(from, VSH_MAX_XML_FILE, &buffer) < 0) + if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) return false; pool = virStoragePoolCreateXML(ctl->conn, buffer, 0); @@ -421,7 +421,7 @@ cmdPoolDefine(vshControl *ctl, const vshCmd *cmd) if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0) return false; - if (virFileReadAll(from, VSH_MAX_XML_FILE, &buffer) < 0) + if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) return false; pool = virStoragePoolDefineXML(ctl->conn, buffer, 0); @@ -518,7 +518,7 @@ cmdPoolBuild(vshControl *ctl, const vshCmd *cmd) const char *name; unsigned int flags = 0; - if (!(pool = vshCommandOptPool(ctl, cmd, "pool", &name))) + if (!(pool = virshCommandOptPool(ctl, cmd, "pool", &name))) return false; if (vshCommandOptBool(cmd, "no-overwrite")) @@ -568,7 +568,7 @@ cmdPoolDestroy(vshControl *ctl, const vshCmd *cmd) bool ret = true; const char *name; - if (!(pool = vshCommandOptPool(ctl, cmd, "pool", &name))) + if (!(pool = virshCommandOptPool(ctl, cmd, "pool", &name))) return false; if (virStoragePoolDestroy(pool) == 0) { @@ -611,7 +611,7 @@ cmdPoolDelete(vshControl *ctl, const vshCmd *cmd) bool ret = true; const char *name; - if (!(pool = vshCommandOptPool(ctl, cmd, "pool", &name))) + if (!(pool = virshCommandOptPool(ctl, cmd, "pool", &name))) return false; if (virStoragePoolDelete(pool, 0) == 0) { @@ -654,7 +654,7 @@ cmdPoolRefresh(vshControl *ctl, const vshCmd *cmd) bool ret = true; const char *name; - if (!(pool = vshCommandOptPool(ctl, cmd, "pool", &name))) + if (!(pool = virshCommandOptPool(ctl, cmd, "pool", &name))) return false; if (virStoragePoolRefresh(pool, 0) == 0) { @@ -706,7 +706,7 @@ cmdPoolDumpXML(vshControl *ctl, const vshCmd *cmd) if (inactive) flags |= VIR_STORAGE_XML_INACTIVE; - if (!(pool = vshCommandOptPool(ctl, cmd, "pool", NULL))) + if (!(pool = virshCommandOptPool(ctl, cmd, "pool", NULL))) return false; dump = virStoragePoolGetXMLDesc(pool, flags); @@ -946,8 +946,8 @@ vshStoragePoolListCollect(vshControl *ctl, } -VIR_ENUM_DECL(vshStoragePoolState) -VIR_ENUM_IMPL(vshStoragePoolState, +VIR_ENUM_DECL(virshStoragePoolState) +VIR_ENUM_IMPL(virshStoragePoolState, VIR_STORAGE_POOL_STATE_LAST, N_("inactive"), N_("building"), @@ -956,9 +956,9 @@ VIR_ENUM_IMPL(vshStoragePoolState, N_("inaccessible")) static const char * -vshStoragePoolStateToString(int state) +virshStoragePoolStateToString(int state) { - const char *str = vshStoragePoolStateTypeToString(state); + const char *str = virshStoragePoolStateTypeToString(state); return str ? _(str) : _("unknown"); } @@ -1168,7 +1168,7 @@ cmdPoolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) } else { /* Decide which state string to display */ if (details) { - const char *state = vshStoragePoolStateToString(info.state); + const char *state = virshStoragePoolStateToString(info.state); poolInfoTexts[i].state = vshStrdup(ctl, state); @@ -1178,17 +1178,17 @@ cmdPoolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) double val; const char *unit; - val = vshPrettyCapacity(info.capacity, &unit); + val = virshPrettyCapacity(info.capacity, &unit); if (virAsprintf(&poolInfoTexts[i].capacity, "%.2lf %s", val, unit) < 0) goto cleanup; - val = vshPrettyCapacity(info.allocation, &unit); + val = virshPrettyCapacity(info.allocation, &unit); if (virAsprintf(&poolInfoTexts[i].allocation, "%.2lf %s", val, unit) < 0) goto cleanup; - val = vshPrettyCapacity(info.available, &unit); + val = virshPrettyCapacity(info.available, &unit); if (virAsprintf(&poolInfoTexts[i].available, "%.2lf %s", val, unit) < 0) goto cleanup; @@ -1503,7 +1503,7 @@ cmdPoolDiscoverSources(vshControl * ctl, const vshCmd * cmd ATTRIBUTE_UNUSED) if (vshCommandOptStringReq(ctl, cmd, "srcSpec", &srcSpecFile) < 0) return false; - if (srcSpecFile && virFileReadAll(srcSpecFile, VSH_MAX_XML_FILE, + if (srcSpecFile && virFileReadAll(srcSpecFile, VIRSH_MAX_XML_FILE, &srcSpec) < 0) return false; @@ -1551,7 +1551,7 @@ cmdPoolInfo(vshControl *ctl, const vshCmd *cmd) bool ret = true; char uuid[VIR_UUID_STRING_BUFLEN]; - if (!(pool = vshCommandOptPool(ctl, cmd, "pool", NULL))) + if (!(pool = virshCommandOptPool(ctl, cmd, "pool", NULL))) return false; vshPrint(ctl, "%-15s %s\n", _("Name:"), virStoragePoolGetName(pool)); @@ -1563,7 +1563,7 @@ cmdPoolInfo(vshControl *ctl, const vshCmd *cmd) double val; const char *unit; vshPrint(ctl, "%-15s %s\n", _("State:"), - vshStoragePoolStateToString(info.state)); + virshStoragePoolStateToString(info.state)); /* Check and display whether the pool is persistent or not */ persistent = virStoragePoolIsPersistent(pool); @@ -1582,13 +1582,13 @@ cmdPoolInfo(vshControl *ctl, const vshCmd *cmd) if (info.state == VIR_STORAGE_POOL_RUNNING || info.state == VIR_STORAGE_POOL_DEGRADED) { - val = vshPrettyCapacity(info.capacity, &unit); + val = virshPrettyCapacity(info.capacity, &unit); vshPrint(ctl, "%-15s %2.2lf %s\n", _("Capacity:"), val, unit); - val = vshPrettyCapacity(info.allocation, &unit); + val = virshPrettyCapacity(info.allocation, &unit); vshPrint(ctl, "%-15s %2.2lf %s\n", _("Allocation:"), val, unit); - val = vshPrettyCapacity(info.available, &unit); + val = virshPrettyCapacity(info.available, &unit); vshPrint(ctl, "%-15s %2.2lf %s\n", _("Available:"), val, unit); } } else { @@ -1626,8 +1626,7 @@ cmdPoolName(vshControl *ctl, const vshCmd *cmd) { virStoragePoolPtr pool; - if (!(pool = vshCommandOptPoolBy(ctl, cmd, "pool", NULL, - VSH_BYUUID))) + if (!(pool = virshCommandOptPoolBy(ctl, cmd, "pool", NULL, VSH_BYUUID))) return false; vshPrint(ctl, "%s\n", virStoragePoolGetName(pool)); @@ -1664,7 +1663,7 @@ cmdPoolStart(vshControl *ctl, const vshCmd *cmd) bool ret = true; const char *name = NULL; - if (!(pool = vshCommandOptPool(ctl, cmd, "pool", &name))) + if (!(pool = virshCommandOptPool(ctl, cmd, "pool", &name))) return false; if (virStoragePoolCreate(pool, 0) == 0) { @@ -1707,7 +1706,7 @@ cmdPoolUndefine(vshControl *ctl, const vshCmd *cmd) bool ret = true; const char *name; - if (!(pool = vshCommandOptPool(ctl, cmd, "pool", &name))) + if (!(pool = virshCommandOptPool(ctl, cmd, "pool", &name))) return false; if (virStoragePoolUndefine(pool) == 0) { @@ -1749,8 +1748,7 @@ cmdPoolUuid(vshControl *ctl, const vshCmd *cmd) virStoragePoolPtr pool; char uuid[VIR_UUID_STRING_BUFLEN]; - if (!(pool = vshCommandOptPoolBy(ctl, cmd, "pool", NULL, - VSH_BYNAME))) + if (!(pool = virshCommandOptPoolBy(ctl, cmd, "pool", NULL, VSH_BYNAME))) return false; if (virStoragePoolGetUUIDString(pool, uuid) != -1) @@ -1793,7 +1791,7 @@ cmdPoolEdit(vshControl *ctl, const vshCmd *cmd) unsigned int flags = VIR_STORAGE_XML_INACTIVE; char *tmp_desc = NULL; - pool = vshCommandOptPool(ctl, cmd, "pool", NULL); + pool = virshCommandOptPool(ctl, cmd, "pool", NULL); if (pool == NULL) goto cleanup; diff --git a/tools/virsh-pool.h b/tools/virsh-pool.h index 4f6759c..b5b0836 100644 --- a/tools/virsh-pool.h +++ b/tools/virsh-pool.h @@ -29,13 +29,13 @@ # include "virsh.h" virStoragePoolPtr -vshCommandOptPoolBy(vshControl *ctl, const vshCmd *cmd, const char *optname, - const char **name, unsigned int flags); +virshCommandOptPoolBy(vshControl *ctl, const vshCmd *cmd, const char *optname, + const char **name, unsigned int flags); /* default is lookup by Name and UUID */ -# define vshCommandOptPool(_ctl, _cmd, _optname, _name) \ - vshCommandOptPoolBy(_ctl, _cmd, _optname, _name, \ - VSH_BYUUID|VSH_BYNAME) +# define virshCommandOptPool(_ctl, _cmd, _optname, _name) \ + virshCommandOptPoolBy(_ctl, _cmd, _optname, _name, \ + VSH_BYUUID|VSH_BYNAME) extern const vshCmdDef storagePoolCmds[]; diff --git a/tools/virsh-secret.c b/tools/virsh-secret.c index c6ceabd..d78ef9d 100644 --- a/tools/virsh-secret.c +++ b/tools/virsh-secret.c @@ -35,7 +35,7 @@ #include "conf/secret_conf.h" static virSecretPtr -vshCommandOptSecret(vshControl *ctl, const vshCmd *cmd, const char **name) +virshCommandOptSecret(vshControl *ctl, const vshCmd *cmd, const char **name) { virSecretPtr secret = NULL; const char *n = NULL; @@ -92,7 +92,7 @@ cmdSecretDefine(vshControl *ctl, const vshCmd *cmd) if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0) return false; - if (virFileReadAll(from, VSH_MAX_XML_FILE, &buffer) < 0) + if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) return false; if (!(res = virSecretDefineXML(ctl->conn, buffer, 0))) { @@ -144,7 +144,7 @@ cmdSecretDumpXML(vshControl *ctl, const vshCmd *cmd) bool ret = false; char *xml; - secret = vshCommandOptSecret(ctl, cmd, NULL); + secret = virshCommandOptSecret(ctl, cmd, NULL); if (secret == NULL) return false; @@ -197,7 +197,7 @@ cmdSecretSetValue(vshControl *ctl, const vshCmd *cmd) int res; bool ret = false; - if (!(secret = vshCommandOptSecret(ctl, cmd, NULL))) + if (!(secret = virshCommandOptSecret(ctl, cmd, NULL))) return false; if (vshCommandOptStringReq(ctl, cmd, "base64", &base64) < 0) @@ -259,7 +259,7 @@ cmdSecretGetValue(vshControl *ctl, const vshCmd *cmd) size_t value_size; bool ret = false; - secret = vshCommandOptSecret(ctl, cmd, NULL); + secret = virshCommandOptSecret(ctl, cmd, NULL); if (secret == NULL) return false; @@ -314,7 +314,7 @@ cmdSecretUndefine(vshControl *ctl, const vshCmd *cmd) bool ret = false; const char *uuid; - secret = vshCommandOptSecret(ctl, cmd, &uuid); + secret = virshCommandOptSecret(ctl, cmd, &uuid); if (secret == NULL) return false; diff --git a/tools/virsh-snapshot.c b/tools/virsh-snapshot.c index de84175..5130479 100644 --- a/tools/virsh-snapshot.c +++ b/tools/virsh-snapshot.c @@ -44,8 +44,8 @@ /* Helper for snapshot-create and snapshot-create-as */ static bool -vshSnapshotCreate(vshControl *ctl, virDomainPtr dom, const char *buffer, - unsigned int flags, const char *from) +virshSnapshotCreate(vshControl *ctl, virDomainPtr dom, const char *buffer, + unsigned int flags, const char *from) { bool ret = false; virDomainSnapshotPtr snapshot; @@ -199,7 +199,7 @@ cmdSnapshotCreate(vshControl *ctl, const vshCmd *cmd) if (vshCommandOptBool(cmd, "live")) flags |= VIR_DOMAIN_SNAPSHOT_CREATE_LIVE; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) goto cleanup; if (vshCommandOptStringReq(ctl, cmd, "xmlfile", &from) < 0) @@ -207,13 +207,13 @@ cmdSnapshotCreate(vshControl *ctl, const vshCmd *cmd) if (!from) { buffer = vshStrdup(ctl, "<domainsnapshot/>"); } else { - if (virFileReadAll(from, VSH_MAX_XML_FILE, &buffer) < 0) { + if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) { vshSaveLibvirtError(); goto cleanup; } } - ret = vshSnapshotCreate(ctl, dom, buffer, flags, from); + ret = virshSnapshotCreate(ctl, dom, buffer, flags, from); cleanup: VIR_FREE(buffer); @@ -419,7 +419,7 @@ cmdSnapshotCreateAs(vshControl *ctl, const vshCmd *cmd) if (vshCommandOptBool(cmd, "live")) flags |= VIR_DOMAIN_SNAPSHOT_CREATE_LIVE; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; if (vshCommandOptStringReq(ctl, cmd, "name", &name) < 0 || @@ -463,7 +463,7 @@ cmdSnapshotCreateAs(vshControl *ctl, const vshCmd *cmd) goto cleanup; } - ret = vshSnapshotCreate(ctl, dom, buffer, flags, NULL); + ret = virshSnapshotCreate(ctl, dom, buffer, flags, NULL); cleanup: virBufferFreeAndReset(&buf); @@ -568,7 +568,7 @@ cmdSnapshotEdit(vshControl *ctl, const vshCmd *cmd) vshCommandOptBool(cmd, "snapshotname")) define_flags |= VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; if (vshLookupSnapshot(ctl, cmd, "snapshotname", false, dom, @@ -682,7 +682,7 @@ cmdSnapshotCurrent(vshControl *ctl, const vshCmd *cmd) VSH_EXCLUSIVE_OPTIONS("name", "snapshotname"); - if (!(dom = vshCommandOptDomain(ctl, cmd, &domname))) + if (!(dom = virshCommandOptDomain(ctl, cmd, &domname))) return false; if (vshCommandOptStringReq(ctl, cmd, "snapshotname", &snapshotname) < 0) @@ -915,7 +915,7 @@ cmdSnapshotInfo(vshControl *ctl, const vshCmd *cmd) int current; int metadata; - dom = vshCommandOptDomain(ctl, cmd, NULL); + dom = virshCommandOptDomain(ctl, cmd, NULL); if (dom == NULL) return false; @@ -1051,10 +1051,10 @@ struct vshSnapshotList { struct vshSnap *snaps; int nsnaps; }; -typedef struct vshSnapshotList *vshSnapshotListPtr; +typedef struct vshSnapshotList *virshSnapshotListPtr; static void -vshSnapshotListFree(vshSnapshotListPtr snaplist) +vshSnapshotListFree(virshSnapshotListPtr snaplist) { size_t i; @@ -1090,7 +1090,7 @@ vshSnapSorter(const void *a, const void *b) * list is limited to descendants of the given snapshot. If FLAGS is * given, the list is filtered. If TREE is specified, then all but * FROM or the roots will also have parent information. */ -static vshSnapshotListPtr +static virshSnapshotListPtr vshSnapshotListCollect(vshControl *ctl, virDomainPtr dom, virDomainSnapshotPtr from, unsigned int orig_flags, bool tree) @@ -1101,8 +1101,8 @@ vshSnapshotListCollect(vshControl *ctl, virDomainPtr dom, bool descendants = false; bool roots = false; virDomainSnapshotPtr *snaps; - vshSnapshotListPtr snaplist = vshMalloc(ctl, sizeof(*snaplist)); - vshSnapshotListPtr ret = NULL; + virshSnapshotListPtr snaplist = vshMalloc(ctl, sizeof(*snaplist)); + virshSnapshotListPtr ret = NULL; const char *fromname = NULL; int start_index = -1; int deleted = 0; @@ -1416,9 +1416,9 @@ vshSnapshotListCollect(vshControl *ctl, virDomainPtr dom, } static const char * -vshSnapshotListLookup(int id, bool parent, void *opaque) +virshSnapshotListLookup(int id, bool parent, void *opaque) { - vshSnapshotListPtr snaplist = opaque; + virshSnapshotListPtr snaplist = opaque; if (parent) return snaplist->snaps[id].parent; return virDomainSnapshotGetName(snaplist->snaps[id].snap); @@ -1536,7 +1536,7 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd) const char *from_snap = NULL; char *parent_snap = NULL; virDomainSnapshotPtr start = NULL; - vshSnapshotListPtr snaplist = NULL; + virshSnapshotListPtr snaplist = NULL; VSH_EXCLUSIVE_OPTIONS_VAR(tree, name); VSH_EXCLUSIVE_OPTIONS_VAR(parent, roots); @@ -1585,7 +1585,7 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd) flags |= VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS; } - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; if ((from || current) && @@ -1611,8 +1611,8 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd) if (tree) { for (i = 0; i < snaplist->nsnaps; i++) { if (!snaplist->snaps[i].parent && - vshTreePrint(ctl, vshSnapshotListLookup, snaplist, - snaplist->nsnaps, i) < 0) + virshTreePrint(ctl, virshSnapshotListLookup, snaplist, + snaplist->nsnaps, i) < 0) goto cleanup; } ret = true; @@ -1735,7 +1735,7 @@ cmdSnapshotDumpXML(vshControl *ctl, const vshCmd *cmd) if (vshCommandOptStringReq(ctl, cmd, "snapshotname", &name) < 0) return false; - if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; if (!(snapshot = virDomainSnapshotLookupByName(dom, name, 0))) @@ -1795,7 +1795,7 @@ cmdSnapshotParent(vshControl *ctl, const vshCmd *cmd) virDomainSnapshotPtr snapshot = NULL; char *parent = NULL; - dom = vshCommandOptDomain(ctl, cmd, NULL); + dom = virshCommandOptDomain(ctl, cmd, NULL); if (dom == NULL) goto cleanup; @@ -1888,7 +1888,7 @@ cmdDomainSnapshotRevert(vshControl *ctl, const vshCmd *cmd) if (vshCommandOptBool(cmd, "force")) force = true; - dom = vshCommandOptDomain(ctl, cmd, NULL); + dom = virshCommandOptDomain(ctl, cmd, NULL); if (dom == NULL) goto cleanup; @@ -1968,7 +1968,7 @@ cmdSnapshotDelete(vshControl *ctl, const vshCmd *cmd) virDomainSnapshotPtr snapshot = NULL; unsigned int flags = 0; - dom = vshCommandOptDomain(ctl, cmd, NULL); + dom = virshCommandOptDomain(ctl, cmd, NULL); if (dom == NULL) goto cleanup; diff --git a/tools/virsh-volume.c b/tools/virsh-volume.c index bb1bfc2..21b7fb0 100644 --- a/tools/virsh-volume.c +++ b/tools/virsh-volume.c @@ -43,10 +43,10 @@ #include "virstring.h" virStorageVolPtr -vshCommandOptVolBy(vshControl *ctl, const vshCmd *cmd, - const char *optname, - const char *pooloptname, - const char **name, unsigned int flags) +virshCommandOptVolBy(vshControl *ctl, const vshCmd *cmd, + const char *optname, + const char *pooloptname, + const char **name, unsigned int flags) { virStorageVolPtr vol = NULL; virStoragePoolPtr pool = NULL; @@ -61,7 +61,7 @@ vshCommandOptVolBy(vshControl *ctl, const vshCmd *cmd, return NULL; if (p) { - if (!(pool = vshCommandOptPoolBy(ctl, cmd, pooloptname, name, flags))) + if (!(pool = virshCommandOptPoolBy(ctl, cmd, pooloptname, name, flags))) return NULL; if (virStoragePoolIsActive(pool) != 1) { @@ -205,7 +205,7 @@ cmdVolCreateAs(vshControl *ctl, const vshCmd *cmd) if (vshCommandOptBool(cmd, "prealloc-metadata")) flags |= VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA; - if (!(pool = vshCommandOptPool(ctl, cmd, "pool", NULL))) + if (!(pool = virshCommandOptPool(ctl, cmd, "pool", NULL))) return false; if (vshCommandOptStringReq(ctl, cmd, "name", &name) < 0) @@ -380,13 +380,13 @@ cmdVolCreate(vshControl *ctl, const vshCmd *cmd) if (vshCommandOptBool(cmd, "prealloc-metadata")) flags |= VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA; - if (!(pool = vshCommandOptPool(ctl, cmd, "pool", NULL))) + if (!(pool = virshCommandOptPool(ctl, cmd, "pool", NULL))) return false; if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0) goto cleanup; - if (virFileReadAll(from, VSH_MAX_XML_FILE, &buffer) < 0) { + if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) { vshSaveLibvirtError(); goto cleanup; } @@ -460,7 +460,7 @@ cmdVolCreateFrom(vshControl *ctl, const vshCmd *cmd) char *buffer = NULL; unsigned int flags = 0; - if (!(pool = vshCommandOptPool(ctl, cmd, "pool", NULL))) + if (!(pool = virshCommandOptPool(ctl, cmd, "pool", NULL))) goto cleanup; if (vshCommandOptBool(cmd, "prealloc-metadata")) @@ -472,10 +472,10 @@ cmdVolCreateFrom(vshControl *ctl, const vshCmd *cmd) if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0) goto cleanup; - if (!(inputvol = vshCommandOptVol(ctl, cmd, "vol", "inputpool", NULL))) + if (!(inputvol = virshCommandOptVol(ctl, cmd, "vol", "inputpool", NULL))) goto cleanup; - if (virFileReadAll(from, VSH_MAX_XML_FILE, &buffer) < 0) { + if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) { vshReportError(ctl); goto cleanup; } @@ -581,7 +581,7 @@ cmdVolClone(vshControl *ctl, const vshCmd *cmd) bool ret = false; unsigned int flags = 0; - if (!(origvol = vshCommandOptVol(ctl, cmd, "vol", "pool", NULL))) + if (!(origvol = virshCommandOptVol(ctl, cmd, "vol", "pool", NULL))) goto cleanup; if (vshCommandOptBool(cmd, "prealloc-metadata")) @@ -699,7 +699,7 @@ cmdVolUpload(vshControl *ctl, const vshCmd *cmd) if (vshCommandOptULongLongWrap(ctl, cmd, "length", &length) < 0) return false; - if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", &name))) + if (!(vol = virshCommandOptVol(ctl, cmd, "vol", "pool", &name))) return false; if (vshCommandOptStringReq(ctl, cmd, "file", &file) < 0) @@ -804,7 +804,7 @@ cmdVolDownload(vshControl *ctl, const vshCmd *cmd) if (vshCommandOptULongLongWrap(ctl, cmd, "length", &length) < 0) return false; - if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", &name))) + if (!(vol = virshCommandOptVol(ctl, cmd, "vol", "pool", &name))) return false; if (vshCommandOptStringReq(ctl, cmd, "file", &file) < 0) @@ -830,7 +830,7 @@ cmdVolDownload(vshControl *ctl, const vshCmd *cmd) goto cleanup; } - if (virStreamRecvAll(st, vshStreamSink, &fd) < 0) { + if (virStreamRecvAll(st, virshStreamSink, &fd) < 0) { vshError(ctl, _("cannot receive data from volume %s"), name); goto cleanup; } @@ -892,7 +892,7 @@ cmdVolDelete(vshControl *ctl, const vshCmd *cmd) bool ret = true; const char *name; - if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", &name))) + if (!(vol = virshCommandOptVol(ctl, cmd, "vol", "pool", &name))) return false; if (virStorageVolDelete(vol, 0) == 0) { @@ -951,7 +951,7 @@ cmdVolWipe(vshControl *ctl, const vshCmd *cmd) int algorithm = VIR_STORAGE_VOL_WIPE_ALG_ZERO; int funcRet; - if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", &name))) + if (!(vol = virshCommandOptVol(ctl, cmd, "vol", "pool", &name))) return false; if (vshCommandOptStringReq(ctl, cmd, "algorithm", &algorithm_str) < 0) @@ -1032,7 +1032,7 @@ cmdVolInfo(vshControl *ctl, const vshCmd *cmd) virStorageVolPtr vol; bool ret = true; - if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", NULL))) + if (!(vol = virshCommandOptVol(ctl, cmd, "vol", "pool", NULL))) return false; vshPrint(ctl, "%-15s %s\n", _("Name:"), virStorageVolGetName(vol)); @@ -1044,10 +1044,10 @@ cmdVolInfo(vshControl *ctl, const vshCmd *cmd) vshPrint(ctl, "%-15s %s\n", _("Type:"), vshVolumeTypeToString(info.type)); - val = vshPrettyCapacity(info.capacity, &unit); + val = virshPrettyCapacity(info.capacity, &unit); vshPrint(ctl, "%-15s %2.2lf %s\n", _("Capacity:"), val, unit); - val = vshPrettyCapacity(info.allocation, &unit); + val = virshPrettyCapacity(info.allocation, &unit); vshPrint(ctl, "%-15s %2.2lf %s\n", _("Allocation:"), val, unit); } else { ret = false; @@ -1115,7 +1115,7 @@ cmdVolResize(vshControl *ctl, const vshCmd *cmd) if (vshCommandOptBool(cmd, "shrink")) flags |= VIR_STORAGE_VOL_RESIZE_SHRINK; - if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", NULL))) + if (!(vol = virshCommandOptVol(ctl, cmd, "vol", "pool", NULL))) return false; if (vshCommandOptStringReq(ctl, cmd, "capacity", &capacityStr) < 0) @@ -1194,7 +1194,7 @@ cmdVolDumpXML(vshControl *ctl, const vshCmd *cmd) bool ret = true; char *dump; - if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", NULL))) + if (!(vol = virshCommandOptVol(ctl, cmd, "vol", "pool", NULL))) return false; dump = virStorageVolGetXMLDesc(vol, 0); @@ -1225,14 +1225,14 @@ vshStorageVolSorter(const void *a, const void *b) virStorageVolGetName(*vb)); } -struct vshStorageVolList { +struct virshStorageVolList { virStorageVolPtr *vols; size_t nvols; }; -typedef struct vshStorageVolList *vshStorageVolListPtr; +typedef struct virshStorageVolList *virshStorageVolListPtr; static void -vshStorageVolListFree(vshStorageVolListPtr list) +virshStorageVolListFree(virshStorageVolListPtr list) { size_t i; @@ -1246,12 +1246,12 @@ vshStorageVolListFree(vshStorageVolListPtr list) VIR_FREE(list); } -static vshStorageVolListPtr -vshStorageVolListCollect(vshControl *ctl, - virStoragePoolPtr pool, - unsigned int flags) +static virshStorageVolListPtr +virshStorageVolListCollect(vshControl *ctl, + virStoragePoolPtr pool, + unsigned int flags) { - vshStorageVolListPtr list = vshMalloc(ctl, sizeof(*list)); + virshStorageVolListPtr list = vshMalloc(ctl, sizeof(*list)); size_t i; char **names = NULL; virStorageVolPtr vol = NULL; @@ -1328,7 +1328,7 @@ vshStorageVolListCollect(vshControl *ctl, VIR_FREE(names); if (!success) { - vshStorageVolListFree(list); + virshStorageVolListFree(list); list = NULL; } @@ -1383,13 +1383,13 @@ cmdVolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) char *type; }; struct volInfoText *volInfoTexts = NULL; - vshStorageVolListPtr list = NULL; + virshStorageVolListPtr list = NULL; /* Look up the pool information given to us by the user */ - if (!(pool = vshCommandOptPool(ctl, cmd, "pool", NULL))) + if (!(pool = virshCommandOptPool(ctl, cmd, "pool", NULL))) return false; - if (!(list = vshStorageVolListCollect(ctl, pool, 0))) + if (!(list = virshStorageVolListCollect(ctl, pool, 0))) goto cleanup; if (list->nvols > 0) @@ -1420,12 +1420,12 @@ cmdVolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) volInfoTexts[i].type = vshStrdup(ctl, vshVolumeTypeToString(volumeInfo.type)); - val = vshPrettyCapacity(volumeInfo.capacity, &unit); + val = virshPrettyCapacity(volumeInfo.capacity, &unit); if (virAsprintf(&volInfoTexts[i].capacity, "%.2lf %s", val, unit) < 0) goto cleanup; - val = vshPrettyCapacity(volumeInfo.allocation, &unit); + val = virshPrettyCapacity(volumeInfo.allocation, &unit); if (virAsprintf(&volInfoTexts[i].allocation, "%.2lf %s", val, unit) < 0) goto cleanup; @@ -1571,7 +1571,7 @@ cmdVolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) VIR_FREE(outputStr); VIR_FREE(volInfoTexts); virStoragePoolFree(pool); - vshStorageVolListFree(list); + virshStorageVolListFree(list); /* Return the desired value */ return ret; @@ -1604,8 +1604,8 @@ cmdVolName(vshControl *ctl, const vshCmd *cmd) { virStorageVolPtr vol; - if (!(vol = vshCommandOptVolBy(ctl, cmd, "vol", NULL, NULL, - VSH_BYUUID))) + if (!(vol = virshCommandOptVolBy(ctl, cmd, "vol", NULL, NULL, + VSH_BYUUID))) return false; vshPrint(ctl, "%s\n", virStorageVolGetName(vol)); @@ -1647,8 +1647,8 @@ cmdVolPool(vshControl *ctl, const vshCmd *cmd) char uuid[VIR_UUID_STRING_BUFLEN]; /* Use the supplied string to locate the volume */ - if (!(vol = vshCommandOptVolBy(ctl, cmd, "vol", NULL, NULL, - VSH_BYUUID))) { + if (!(vol = virshCommandOptVolBy(ctl, cmd, "vol", NULL, NULL, + VSH_BYUUID))) { return false; } @@ -1707,7 +1707,7 @@ cmdVolKey(vshControl *ctl, const vshCmd *cmd) { virStorageVolPtr vol; - if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", NULL))) + if (!(vol = virshCommandOptVol(ctl, cmd, "vol", "pool", NULL))) return false; vshPrint(ctl, "%s\n", virStorageVolGetKey(vol)); @@ -1747,7 +1747,7 @@ cmdVolPath(vshControl *ctl, const vshCmd *cmd) virStorageVolPtr vol; char * StorageVolPath; - if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", NULL))) + if (!(vol = virshCommandOptVol(ctl, cmd, "vol", "pool", NULL))) return false; if ((StorageVolPath = virStorageVolGetPath(vol)) == NULL) { diff --git a/tools/virsh-volume.h b/tools/virsh-volume.h index b719d7f..be56928 100644 --- a/tools/virsh-volume.h +++ b/tools/virsh-volume.h @@ -28,15 +28,15 @@ # include "virsh.h" -virStorageVolPtr vshCommandOptVolBy(vshControl *ctl, const vshCmd *cmd, - const char *optname, - const char *pooloptname, - const char **name, unsigned int flags); +virStorageVolPtr virshCommandOptVolBy(vshControl *ctl, const vshCmd *cmd, + const char *optname, + const char *pooloptname, + const char **name, unsigned int flags); /* default is lookup by Name and UUID */ -# define vshCommandOptVol(_ctl, _cmd, _optname, _pooloptname, _name) \ - vshCommandOptVolBy(_ctl, _cmd, _optname, _pooloptname, _name, \ - VSH_BYUUID|VSH_BYNAME) +# define virshCommandOptVol(_ctl, _cmd, _optname, _pooloptname, _name) \ + virshCommandOptVolBy(_ctl, _cmd, _optname, _pooloptname, _name, \ + VSH_BYUUID|VSH_BYNAME) extern const vshCmdDef storageVolCmds[]; diff --git a/tools/virsh.c b/tools/virsh.c index e833b26..f293d0f 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -139,7 +139,7 @@ vshNameSorter(const void *a, const void *b) } double -vshPrettyCapacity(unsigned long long val, const char **unit) +virshPrettyCapacity(unsigned long long val, const char **unit) { double limit = 1024; @@ -178,146 +178,20 @@ vshPrettyCapacity(unsigned long long val, const char **unit) } /* - * Convert the strings separated by ',' into array. The returned - * array is a NULL terminated string list. The caller has to free - * the array using virStringFreeList or a similar method. - * - * Returns the length of the filled array on success, or -1 - * on error. - */ -int -vshStringToArray(const char *str, - char ***array) -{ - char *str_copied = vshStrdup(NULL, str); - char *str_tok = NULL; - char *tmp; - unsigned int nstr_tokens = 0; - char **arr = NULL; - size_t len = strlen(str_copied); - - /* tokenize the string from user and save its parts into an array */ - nstr_tokens = 1; - - /* count the delimiters, recognizing ,, as an escape for a - * literal comma */ - str_tok = str_copied; - while ((str_tok = strchr(str_tok, ','))) { - if (str_tok[1] == ',') - str_tok++; - else - nstr_tokens++; - str_tok++; - } - - /* reserve the NULL element at the end */ - if (VIR_ALLOC_N(arr, nstr_tokens + 1) < 0) { - VIR_FREE(str_copied); - return -1; - } - - /* tokenize the input string, while treating ,, as a literal comma */ - nstr_tokens = 0; - tmp = str_tok = str_copied; - while ((tmp = strchr(tmp, ','))) { - if (tmp[1] == ',') { - memmove(&tmp[1], &tmp[2], len - (tmp - str_copied) - 2 + 1); - len--; - tmp++; - continue; - } - *tmp++ = '\0'; - arr[nstr_tokens++] = vshStrdup(NULL, str_tok); - str_tok = tmp; - } - arr[nstr_tokens++] = vshStrdup(NULL, str_tok); - - *array = arr; - VIR_FREE(str_copied); - return nstr_tokens; -} - -virErrorPtr last_error; - -/* - * Quieten libvirt until we're done with the command. - */ -static void -virshErrorHandler(void *unused ATTRIBUTE_UNUSED, virErrorPtr error) -{ - virFreeError(last_error); - last_error = virSaveLastError(); - if (virGetEnvAllowSUID("VIRSH_DEBUG") != NULL) - virDefaultErrorFunc(error); -} - -/* Store a libvirt error that is from a helper API that doesn't raise errors - * so it doesn't get overwritten */ -void -vshSaveLibvirtError(void) -{ - virFreeError(last_error); - last_error = virSaveLastError(); -} - -/* - * Reset libvirt error on graceful fallback paths - */ -void -vshResetLibvirtError(void) -{ - virFreeError(last_error); - last_error = NULL; -} - -/* - * Report an error when a command finishes. This is better than before - * (when correct operation would report errors), but it has some - * problems: we lose the smarter formatting of virDefaultErrorFunc(), - * and it can become harder to debug problems, if errors get reported - * twice during one command. This case shouldn't really happen anyway, - * and it's IMHO a bug that libvirt does that sometimes. - */ -void -vshReportError(vshControl *ctl) -{ - if (last_error == NULL) { - /* Calling directly into libvirt util functions won't trigger the - * error callback (which sets last_error), so check it ourselves. - * - * If the returned error has CODE_OK, this most likely means that - * no error was ever raised, so just ignore */ - last_error = virSaveLastError(); - if (!last_error || last_error->code == VIR_ERR_OK) - goto out; - } - - if (last_error->code == VIR_ERR_OK) { - vshError(ctl, "%s", _("unknown error")); - goto out; - } - - vshError(ctl, "%s", last_error->message); - - out: - vshResetLibvirtError(); -} - -/* * Detection of disconnections and automatic reconnection support */ static int disconnected; /* we may have been disconnected */ /* - * vshCatchDisconnect: + * virshCatchDisconnect: * * We get here when the connection was closed. We can't do much in the * handler, just save the fact it was raised. */ static void -vshCatchDisconnect(virConnectPtr conn ATTRIBUTE_UNUSED, - int reason, - void *opaque ATTRIBUTE_UNUSED) +virshCatchDisconnect(virConnectPtr conn ATTRIBUTE_UNUSED, + int reason, + void *opaque ATTRIBUTE_UNUSED) { if (reason != VIR_CONNECT_CLOSE_REASON_CLIENT) disconnected++; @@ -326,7 +200,7 @@ vshCatchDisconnect(virConnectPtr conn ATTRIBUTE_UNUSED, /* Main Function which should be used for connecting. * This function properly handles keepalive settings. */ virConnectPtr -vshConnect(vshControl *ctl, const char *uri, bool readonly) +virshConnect(vshControl *ctl, const char *uri, bool readonly) { virConnectPtr c = NULL; int interval = 5; /* Default */ @@ -364,13 +238,13 @@ vshConnect(vshControl *ctl, const char *uri, bool readonly) } /* - * vshReconnect: + * virshReconnect: * * Reconnect after a disconnect from libvirtd * */ static void -vshReconnect(vshControl *ctl) +virshReconnect(vshControl *ctl) { bool connected = false; @@ -379,8 +253,8 @@ vshReconnect(vshControl *ctl) connected = true; - virConnectUnregisterCloseCallback(ctl->conn, vshCatchDisconnect); - ret = virConnectClose(ctl->conn); + virConnectUnregisterCloseCallback(priv->conn, virshCatchDisconnect); + ret = virConnectClose(priv->conn); if (ret < 0) vshError(ctl, "%s", _("Failed to disconnect from the hypervisor")); else if (ret > 0) @@ -388,7 +262,7 @@ vshReconnect(vshControl *ctl) "disconnect from the hypervisor")); } - ctl->conn = vshConnect(ctl, ctl->name, ctl->readonly); + ctl->conn = virshConnect(ctl, ctl->name, ctl->readonly); if (!ctl->conn) { if (disconnected) @@ -396,7 +270,7 @@ vshReconnect(vshControl *ctl) else vshError(ctl, "%s", _("failed to connect to the hypervisor")); } else { - if (virConnectRegisterCloseCallback(ctl->conn, vshCatchDisconnect, + if (virConnectRegisterCloseCallback(ctl->conn, virshCatchDisconnect, NULL, NULL) < 0) vshError(ctl, "%s", _("Unable to register disconnect callback")); if (connected) @@ -445,8 +319,8 @@ cmdConnect(vshControl *ctl, const vshCmd *cmd) if (ctl->conn) { int ret; - virConnectUnregisterCloseCallback(ctl->conn, vshCatchDisconnect); ret = virConnectClose(ctl->conn); + virConnectUnregisterCloseCallback(priv->conn, virshCatchDisconnect); if (ret < 0) vshError(ctl, "%s", _("Failed to disconnect from the hypervisor")); else if (ret > 0) @@ -466,14 +340,14 @@ cmdConnect(vshControl *ctl, const vshCmd *cmd) ctl->blockJobNoBytes = false; ctl->readonly = ro; - ctl->conn = vshConnect(ctl, ctl->name, ctl->readonly); + ctl->conn = virshConnect(ctl, ctl->name, ctl->readonly); if (!ctl->conn) { vshError(ctl, "%s", _("Failed to connect to the hypervisor")); return false; } - if (virConnectRegisterCloseCallback(ctl->conn, vshCatchDisconnect, + if (virConnectRegisterCloseCallback(ctl->conn, virshCatchDisconnect, NULL, NULL) < 0) vshError(ctl, "%s", _("Unable to register disconnect callback")); @@ -483,7 +357,7 @@ cmdConnect(vshControl *ctl, const vshCmd *cmd) #ifndef WIN32 static void -vshPrintRaw(vshControl *ctl, ...) +virshPrintRaw(vshControl *ctl, ...) { va_list ap; char *key; @@ -509,7 +383,7 @@ vshPrintRaw(vshControl *ctl, ...) * 0 otherwise */ int -vshAskReedit(vshControl *ctl, const char *msg, bool relax_avail) +virshAskReedit(vshControl *ctl, const char *msg, bool relax_avail) { int c = -1; @@ -527,22 +401,23 @@ vshAskReedit(vshControl *ctl, const char *msg, bool relax_avail) c = c_tolower(getchar()); if (c == '?') { - vshPrintRaw(ctl, - "", - _("y - yes, start editor again"), - _("n - no, throw away my changes"), - NULL); + virshPrintRaw(ctl, + "", + _("y - yes, start editor again"), + _("n - no, throw away my changes"), + NULL); if (relax_avail) { - vshPrintRaw(ctl, - _("i - turn off validation and try to redefine again"), - NULL); + virshPrintRaw(ctl, + _("i - turn off validation and try to redefine " + "again"), + NULL); } - vshPrintRaw(ctl, - _("f - force, try to redefine again"), - _("? - print this help"), - NULL); + virshPrintRaw(ctl, + _("f - force, try to redefine again"), + _("? - print this help"), + NULL); continue; } else if (c == 'y' || c == 'n' || c == 'f' || (relax_avail && c == 'i')) { @@ -557,9 +432,9 @@ vshAskReedit(vshControl *ctl, const char *msg, bool relax_avail) } #else /* WIN32 */ int -vshAskReedit(vshControl *ctl, - const char *msg ATTRIBUTE_UNUSED, - bool relax_avail ATTRIBUTE_UNUSED) +virshAskReedit(vshControl *ctl, + const char *msg ATTRIBUTE_UNUSED, + bool relax_avail ATTRIBUTE_UNUSED) { vshDebug(ctl, VSH_ERR_WARNING, "%s", _("This function is not " "supported on WIN32 platform")); @@ -567,8 +442,8 @@ vshAskReedit(vshControl *ctl, } #endif /* WIN32 */ -int vshStreamSink(virStreamPtr st ATTRIBUTE_UNUSED, - const char *bytes, size_t nbytes, void *opaque) +int virshStreamSink(virStreamPtr st ATTRIBUTE_UNUSED, + const char *bytes, size_t nbytes, void *opaque) { int *fd = opaque; @@ -643,14 +518,14 @@ cmdHelp(vshControl *ctl, const vshCmd *cmd) /* Tree listing helpers. */ static int -vshTreePrintInternal(vshControl *ctl, - vshTreeLookup lookup, - void *opaque, - int num_devices, - int devid, - int lastdev, - bool root, - virBufferPtr indent) +virshTreePrintInternal(vshControl *ctl, + vshTreeLookup lookup, + void *opaque, + int num_devices, + int devid, + int lastdev, + bool root, + virBufferPtr indent) { size_t i; int nextlastdev = -1; @@ -692,7 +567,7 @@ vshTreePrintInternal(vshControl *ctl, const char *parent = (lookup)(i, true, opaque); if (parent && STREQ(parent, dev) && - vshTreePrintInternal(ctl, lookup, opaque, + virshTreePrintInternal(ctl, lookup, opaque, num_devices, i, nextlastdev, false, indent) < 0) goto cleanup; @@ -712,13 +587,13 @@ vshTreePrintInternal(vshControl *ctl, } int -vshTreePrint(vshControl *ctl, vshTreeLookup lookup, void *opaque, - int num_devices, int devid) +virshTreePrint(vshControl *ctl, vshTreeLookup lookup, void *opaque, + int num_devices, int devid) { int ret; virBuffer indent = VIR_BUFFER_INITIALIZER; - ret = vshTreePrintInternal(ctl, lookup, opaque, num_devices, + ret = virshTreePrintInternal(ctl, lookup, opaque, num_devices, devid, devid, true, &indent); if (ret < 0) vshError(ctl, "%s", _("Failed to complete tree listing")); @@ -728,7 +603,7 @@ vshTreePrint(vshControl *ctl, vshTreeLookup lookup, void *opaque, /* Common code for the edit / net-edit / pool-edit functions which follow. */ char * -vshEditWriteToTempFile(vshControl *ctl, const char *doc) +virshEditWriteToTempFile(vshControl *ctl, const char *doc) { char *ret; const char *tmpdir; @@ -774,7 +649,7 @@ vshEditWriteToTempFile(vshControl *ctl, const char *doc) "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-/_.:@" int -vshEditFile(vshControl *ctl, const char *filename) +virshEditFile(vshControl *ctl, const char *filename) { const char *editor; virCommandPtr cmd; @@ -826,12 +701,12 @@ vshEditFile(vshControl *ctl, const char *filename) } char * -vshEditReadBackFile(vshControl *ctl, const char *filename) +virshEditReadBackFile(vshControl *ctl, const char *filename) { char *ret; char ebuf[1024]; - if (virFileReadAll(filename, VSH_MAX_XML_FILE, &ret) == -1) { + if (virFileReadAll(filename, VIRSH_MAX_XML_FILE, &ret) == -1) { vshError(ctl, _("%s: failed to read temporary file: %s"), filename, virStrerror(errno, ebuf, sizeof(ebuf))); @@ -1057,6 +932,18 @@ vshCmddefGetInfo(const vshCmdDef * cmd, const char *name) static int vshCmddefOptParse(const vshCmdDef *cmd, uint32_t *opts_need_arg, uint32_t *opts_required) +/* + * virshCommandOptTimeoutToMs: + * @ctl virsh control structure + * @cmd command reference + * @timeout result + * + * Parse an optional --timeout parameter in seconds, but store the + * value of the timeout in milliseconds. + * See vshCommandOptInt() + */ +int +virshCommandOptTimeoutToMs(vshControl *ctl, const vshCmd *cmd, int *timeout) { size_t i; bool optional = false; @@ -1134,6 +1021,8 @@ static vshCmdOptDef helpopt = { static const vshCmdOptDef * vshCmddefGetOption(vshControl *ctl, const vshCmdDef *cmd, const char *name, uint32_t *opts_seen, int *opt_index, char **optstr) +static bool +virshConnectionUsability(vshControl *ctl, virConnectPtr conn) { size_t i; const vshCmdOptDef *ret = NULL; @@ -1214,6 +1103,8 @@ vshCmddefGetData(const vshCmdDef *cmd, uint32_t *opts_need_arg, static int vshCommandCheckOpts(vshControl *ctl, const vshCmd *cmd, uint32_t opts_required, uint32_t opts_seen) +int +virshDomainState(vshControl *ctl, virDomainPtr dom, int *reason) { const vshCmdDef *def = cmd->def; size_t i; @@ -1238,6 +1129,11 @@ vshCommandCheckOpts(vshControl *ctl, const vshCmd *cmd, uint32_t opts_required, const vshCmdDef * vshCmddefSearch(const char *cmdname) +/* + * Initialize connection. + */ +static bool +virshInit(vshControl *ctl) { const vshCmdGrp *g; const vshCmdDef *c; @@ -1291,6 +1187,8 @@ vshCmdGrpHelp(vshControl *ctl, const char *grpname) bool vshCmddefHelp(vshControl *ctl, const char *cmdname) +static void +virshDeinitTimer(int timer ATTRIBUTE_UNUSED, void *opaque ATTRIBUTE_UNUSED) { const vshCmdDef *def = vshCmddefSearch(cmdname); @@ -1427,6 +1325,8 @@ vshCmddefHelp(vshControl *ctl, const char *cmdname) */ static void vshCommandOptFree(vshCmdOpt * arg) +static bool +virshDeinit(vshControl *ctl) { vshCmdOpt *a = arg; @@ -3245,7 +3145,7 @@ vshDeinit(vshControl *ctl) virMutexLock(&ctl->lock); ctl->quit = true; /* HACK: Add a dummy timeout to break event loop */ - timer = virEventAddTimeout(0, vshDeinitTimer, NULL, NULL); + timer = virEventAddTimeout(0, virshDeinitTimer, NULL, NULL); virMutexUnlock(&ctl->lock); virThreadJoin(&ctl->eventLoop); @@ -3268,7 +3168,7 @@ vshDeinit(vshControl *ctl) * Print usage */ static void -vshUsage(void) +virshUsage(void) { const vshCmdGrp *grp; const vshCmdDef *cmd; @@ -3317,7 +3217,7 @@ vshUsage(void) * Show version and options compiled in */ static void -vshShowVersion(vshControl *ctl ATTRIBUTE_UNUSED) +virshShowVersion(vshControl *ctl ATTRIBUTE_UNUSED) { /* FIXME - list a copyright blurb, as in GNU programs? */ vshPrint(ctl, _("Virsh command line tool of libvirt %s\n"), VERSION); @@ -3460,7 +3360,7 @@ vshShowVersion(vshControl *ctl ATTRIBUTE_UNUSED) } static bool -vshAllowedEscapeChar(char c) +virshAllowedEscapeChar(char c) { /* Allowed escape characters: * a-z A-Z @ [ \ ] ^ _ @@ -3474,7 +3374,7 @@ vshAllowedEscapeChar(char c) * */ static bool -vshParseArgv(vshControl *ctl, int argc, char **argv) +virshParseArgv(vshControl *ctl, int argc, char **argv) { int arg, len, debug, keepalive; size_t i; @@ -3519,7 +3419,7 @@ vshParseArgv(vshControl *ctl, int argc, char **argv) len = strlen(optarg); if ((len == 2 && *optarg == '^' && - vshAllowedEscapeChar(optarg[1])) || + virshAllowedEscapeChar(optarg[1])) || (len == 1 && *optarg != '^')) { ctl->escapeChar = optarg; } else { @@ -3529,7 +3429,7 @@ vshParseArgv(vshControl *ctl, int argc, char **argv) } break; case 'h': - vshUsage(); + virshUsage(); exit(EXIT_SUCCESS); break; case 'k': @@ -3585,7 +3485,7 @@ vshParseArgv(vshControl *ctl, int argc, char **argv) } /* fall through */ case 'V': - vshShowVersion(ctl); + virshShowVersion(ctl); exit(EXIT_SUCCESS); case ':': for (i = 0; opt[i].name != NULL; i++) { @@ -3671,18 +3571,18 @@ static const vshCmdDef virshCmds[] = { }; static const vshCmdGrp cmdGroups[] = { - {VSH_CMD_GRP_DOM_MANAGEMENT, "domain", domManagementCmds}, - {VSH_CMD_GRP_DOM_MONITORING, "monitor", domMonitoringCmds}, - {VSH_CMD_GRP_HOST_AND_HV, "host", hostAndHypervisorCmds}, - {VSH_CMD_GRP_IFACE, "interface", ifaceCmds}, - {VSH_CMD_GRP_NWFILTER, "filter", nwfilterCmds}, - {VSH_CMD_GRP_NETWORK, "network", networkCmds}, - {VSH_CMD_GRP_NODEDEV, "nodedev", nodedevCmds}, - {VSH_CMD_GRP_SECRET, "secret", secretCmds}, - {VSH_CMD_GRP_SNAPSHOT, "snapshot", snapshotCmds}, - {VSH_CMD_GRP_STORAGE_POOL, "pool", storagePoolCmds}, - {VSH_CMD_GRP_STORAGE_VOL, "volume", storageVolCmds}, - {VSH_CMD_GRP_VIRSH, "virsh", virshCmds}, + {VIRSH_CMD_GRP_DOM_MANAGEMENT, "domain", domManagementCmds}, + {VIRSH_CMD_GRP_DOM_MONITORING, "monitor", domMonitoringCmds}, + {VIRSH_CMD_GRP_HOST_AND_HV, "host", hostAndHypervisorCmds}, + {VIRSH_CMD_GRP_IFACE, "interface", ifaceCmds}, + {VIRSH_CMD_GRP_NWFILTER, "filter", nwfilterCmds}, + {VIRSH_CMD_GRP_NETWORK, "network", networkCmds}, + {VIRSH_CMD_GRP_NODEDEV, "nodedev", nodedevCmds}, + {VIRSH_CMD_GRP_SECRET, "secret", secretCmds}, + {VIRSH_CMD_GRP_SNAPSHOT, "snapshot", snapshotCmds}, + {VIRSH_CMD_GRP_STORAGE_POOL, "pool", storagePoolCmds}, + {VIRSH_CMD_GRP_STORAGE_VOL, "volume", storageVolCmds}, + {VIRSH_CMD_GRP_VIRSH, "virsh", virshCmds}, {NULL, NULL, NULL} }; @@ -3751,9 +3651,9 @@ main(int argc, char **argv) vshInitDebug(ctl); - if (!vshParseArgv(ctl, argc, argv) || - !vshInit(ctl)) { - vshDeinit(ctl); + if (!virshParseArgv(ctl, argc, argv) || + !virshInit(ctl)) { + virshDeinit(ctl); exit(EXIT_FAILURE); } @@ -3771,7 +3671,7 @@ main(int argc, char **argv) } if (vshReadlineInit(ctl) < 0) { - vshDeinit(ctl); + virshDeinit(ctl); exit(EXIT_FAILURE); } @@ -3795,6 +3695,6 @@ main(int argc, char **argv) fputc('\n', stdout); /* line break after alone prompt */ } - vshDeinit(ctl); + virshDeinit(ctl); exit(ret ? EXIT_SUCCESS : EXIT_FAILURE); } diff --git a/tools/virsh.h b/tools/virsh.h index 977b0fc..945eb23 100644 --- a/tools/virsh.h +++ b/tools/virsh.h @@ -37,10 +37,10 @@ # include "virerror.h" # include "virthread.h" -# define VSH_MAX_XML_FILE (10*1024*1024) +# define VIRSH_MAX_XML_FILE (10*1024*1024) -# define VSH_PROMPT_RW "virsh # " -# define VSH_PROMPT_RO "virsh > " +# define VIRSH_PROMPT_RW "virsh # " +# define VIRSH_PROMPT_RO "virsh > " # define VIR_FROM_THIS VIR_FROM_NONE @@ -112,18 +112,6 @@ typedef enum { /* * Command group types */ -# define VSH_CMD_GRP_DOM_MANAGEMENT "Domain Management" -# define VSH_CMD_GRP_DOM_MONITORING "Domain Monitoring" -# define VSH_CMD_GRP_STORAGE_POOL "Storage Pool" -# define VSH_CMD_GRP_STORAGE_VOL "Storage Volume" -# define VSH_CMD_GRP_NETWORK "Networking" -# define VSH_CMD_GRP_NODEDEV "Node Device" -# define VSH_CMD_GRP_IFACE "Interface" -# define VSH_CMD_GRP_NWFILTER "Network Filter" -# define VSH_CMD_GRP_SECRET "Secret" -# define VSH_CMD_GRP_SNAPSHOT "Snapshot" -# define VSH_CMD_GRP_HOST_AND_HV "Host and Hypervisor" -# define VSH_CMD_GRP_VIRSH "Virsh itself" /* * Command Option Flags @@ -191,6 +179,18 @@ enum { VSH_CMD_FLAG_NOCONNECT = (1 << 0), /* no prior connection needed */ VSH_CMD_FLAG_ALIAS = (1 << 1), /* command is an alias */ }; +# define VIRSH_CMD_GRP_DOM_MANAGEMENT "Domain Management" +# define VIRSH_CMD_GRP_DOM_MONITORING "Domain Monitoring" +# define VIRSH_CMD_GRP_STORAGE_POOL "Storage Pool" +# define VIRSH_CMD_GRP_STORAGE_VOL "Storage Volume" +# define VIRSH_CMD_GRP_NETWORK "Networking" +# define VIRSH_CMD_GRP_NODEDEV "Node Device" +# define VIRSH_CMD_GRP_IFACE "Interface" +# define VIRSH_CMD_GRP_NWFILTER "Network Filter" +# define VIRSH_CMD_GRP_SECRET "Secret" +# define VIRSH_CMD_GRP_SNAPSHOT "Snapshot" +# define VIRSH_CMD_GRP_HOST_AND_HV "Host and Hypervisor" +# define VIRSH_CMD_GRP_VIRSH "Virsh itself" /* * vshCmdDef - command definition @@ -215,8 +215,8 @@ struct _vshCmd { /* * vshControl */ -struct _vshControl { char *name; /* connection name */ +struct _virshControl { virConnectPtr conn; /* connection to hypervisor (MAY BE NULL) */ vshCmd *cmd; /* the current command */ char *cmdstr; /* string with command */ @@ -365,7 +365,7 @@ int vshStringToArray(const char *str, char ***array); * There are used by some long lingering commands like * migrate, dump, save, managedsave. */ -struct _vshCtrlData { +struct _virshCtrlData { vshControl *ctl; const vshCmd *cmd; int writefd; diff --git a/tools/vsh.c b/tools/vsh.c index 8ef04b9..b1d8dbc 100644 --- a/tools/vsh.c +++ b/tools/vsh.c @@ -188,8 +188,8 @@ virErrorPtr last_error; /* * Quieten libvirt until we're done with the command. */ -static void -virshErrorHandler(void *unused ATTRIBUTE_UNUSED, virErrorPtr error) +void +vshErrorHandler(void *opaque ATTRIBUTE_UNUSED, virErrorPtr error) { virFreeError(last_error); last_error = virSaveLastError(); diff --git a/tools/vsh.h b/tools/vsh.h index 4b99b65..76704a1 100644 --- a/tools/vsh.h +++ b/tools/vsh.h @@ -310,6 +310,7 @@ int vshStringToArray(const char *str, char ***array); /* error handling */ extern virErrorPtr last_error; +void vshErrorHandler(void *opaque, virErrorPtr error); void vshReportError(vshControl *ctl); void vshResetLibvirtError(void); void vshSaveLibvirtError(void); -- 1.9.3

On Mon, Jun 29, 2015 at 05:37:34PM +0200, Erik Skultety wrote:
The idea behind this is that in order to introduce virt-admin client (and later some commands/APIs), there are lots of methods in virsh that can be easily reused by other potential clients like command and command argument passing or error reporting.
!!! IMPORTANT !!! These patches cannot be compiled separately, the series is split more or less logically into chunks only to be more readable by the reviewer. I started this at least 4 times from scratch and still haven't found a way that splitting virsh could be done with several independent applicable commits, rather than having one massive commit in the end.
Actually, I found out this is easier to review as a one patch with various diff options used for various parts of the patch. Some questions and suggestions below. Why vshClientHooks and vshCmdGrp aren't in the vshControl struct? If we move the client helpers into a library (I think this stuff can be in src/util/virshell.c for example), then it won't be thread-safe. Moving those to the control structure will also be cleaner. Some things are still broken up, like readline stuff. It should be either completely hidden or completely exposed. For example, vshReadline{Init,Deinit} should be moved into vsh{Init,Deinit}. Commands from former virshCmds (except connect) should be in vsh.c so each client can use them in their cmdGroups definition without re-implementing them. vsh is not doing the argument parsing, but that's be fine. I would, at least, wrap some options in a function that can be called from multiple clients, but that's one of the nice-to-have things that can be done later. vshInit() is declared with ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); but handles passed NULLs properly, that declaration should be fixed. Also there are some whitespace problems (e.g. with parameters of virshLookupDomainBy), but considering how many of them are there inside the files already, it's nothing compared to the size of this refactor. The exclude_file_name_regexp--sc_avoid_strcase should only contain ^tools/vsh\.h$$, not virsh.h. Anyway, here's a list of things that should be changed (either from virsh to vsh or vice versa) split into categories (feel free to disagree with any): Totally: - virshCommandOptTimeoutToMs - VIRSH_MAX_XML_FILE - virshPrettyCapacity - vshFindDisk - vshSnapshotListCollect Most likely: - vshCatchInt - virshPrintJobProgress - virshTreePrint(internal) with virshTreeLookup typedef - virshPrintRaw - virshAskReedit - virshEdit* - virshAllowedEscapeChar Maybe (i.e. not needed now, but might be nice): - virshWatchJob - virsh-edit stuff - vshLookupByFlags And of course all of the below: - vshDomainBlockJob - vshDomainJob - vshDomainEvent - vshDomainEventDefined - vshDomainEventUndefined - vshDomainEventStarted - vshDomainEventSuspended - vshDomainEventResumed - vshDomainEventStopped - vshDomainEventShutdown - vshDomainEventPMSuspended - vshDomainEventCrashed - vshDomainEventWatchdog - vshDomainEventIOError - vshGraphicsPhase - vshGraphicsAddress - vshDomainBlockJobStatus - vshDomainEventDiskChange - vshDomainEventTrayChange - vshEventAgentLifecycleState - vshEventAgentLifecycleReason - vshNetworkEvent - vshNetworkEventId - vshStorageVol - vshUpdateDiskXMLType - vshFindDiskType - vshUndefineVolume Martin

Actually, I found out this is easier to review as a one patch with various diff options used for various parts of the patch. Some questions and suggestions below.
Why vshClientHooks and vshCmdGrp aren't in the vshControl struct? If we move the client helpers into a library (I think this stuff can be in src/util/virshell.c for example), then it won't be thread-safe. Moving those to the control structure will also be cleaner.
It would be nice, but since readline-defined user callbacks do not contain any opaque argument in their signature, you can only rely on statically declared data, therefore you can't do this with command groups, although it does work for client hooks at least.
Some things are still broken up, like readline stuff. It should be either completely hidden or completely exposed. For example, vshReadline{Init,Deinit} should be moved into vsh{Init,Deinit}.
Commands from former virshCmds (except connect) should be in vsh.c so each client can use them in their cmdGroups definition without re-implementing them.
Well, I thought off 2 possible approaches how to tackle this one. The first one is (though not my favorite) to simply move handler implementations and structures initialization to vsh.c. As we do specify all the command groups and options in fixed arrays, we would have to create a completely new group for the generic commands available to every client. In virsh for example, that would leave us with 'connect' command only which we should create a separate group to make it all work. To be honest, I don't like this idea at all. The other idea however, might be nicer, but much more complex and it's for a debate if we really want that and if so, I think it should be a separate follow-up patch, definitely not part of v2. So, the idea is to implement command group register mechanism using linked lists. That way, each client would have to register every group individually. And because lists are easily extensible, we could just add the 'connect' command to the 'virsh' group by implementing some internal APIs to command group management (add/update/whatever).
vsh is not doing the argument parsing, but that's be fine. I would, at least, wrap some options in a function that can be called from multiple clients, but that's one of the nice-to-have things that can be done later.
There is a reason for this. In my opinion, each client should be responsible for parsing their own command line arguments. It doesn't really matter that all the clients most likely will implement usage, help, connect arguments...Being generic in this case would require each client to provide their callbacks for generic options, their specific options list and callbacks to handle these specific options as well. Maybe I just don't see it the way you see it :), but I still think, in this specific case we shouldn't try to split the code even more.
vshInit() is declared with ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); but handles passed NULLs properly, that declaration should be fixed.
Fixed in v2.
Also there are some whitespace problems (e.g. with parameters of virshLookupDomainBy), but considering how many of them are there inside the files already, it's nothing compared to the size of this refactor.
I tried to fix in v2 as many as I could find.
The exclude_file_name_regexp--sc_avoid_strcase should only contain ^tools/vsh\.h$$, not virsh.h.
Fixed.
Anyway, here's a list of things that should be changed (either from virsh to vsh or vice versa) split into categories (feel free to disagree with any):
Totally: - virshCommandOptTimeoutToMs ^^ Something tells me I overlooked this one and pushed v2 to my forked repo without it...Sigh, v3 it is.. - VIRSH_MAX_XML_FILE - virshPrettyCapacity - vshFindDisk - vshSnapshotListCollect
Most likely: - vshCatchInt - virshPrintJobProgress ^^currently this is only used for migration and blockjobs and so far, we haven't talked about some time consuming admin jobs, so I'd say either we leave it for good or we can move it to the lib some time later (possibly with virsh-edit stuff, see below)
- virshTreePrint(internal) with virshTreeLookup typedef - virshPrintRaw - virshAskReedit - virshEdit* - virshAllowedEscapeChar ^^ This one should be client dependent, whatever the reasons to different allowed sets of escape chars might be
Maybe (i.e. not needed now, but might be nice): - virshWatchJob - virsh-edit stuff ^^ I'm not sure how you meant this one, did you mean just renaming the macros inside and the module itself or you meant a complete refactor, spliting the module, etc.??? - vshLookupByFlags
And of course all of the below: - vshDomainBlockJob - vshDomainJob - vshDomainEvent - vshDomainEventDefined - vshDomainEventUndefined - vshDomainEventStarted - vshDomainEventSuspended - vshDomainEventResumed - vshDomainEventStopped - vshDomainEventShutdown - vshDomainEventPMSuspended - vshDomainEventCrashed - vshDomainEventWatchdog - vshDomainEventIOError - vshGraphicsPhase - vshGraphicsAddress - vshDomainBlockJobStatus - vshDomainEventDiskChange - vshDomainEventTrayChange - vshEventAgentLifecycleState - vshEventAgentLifecycleReason - vshNetworkEvent - vshNetworkEventId - vshStorageVol - vshUpdateDiskXMLType - vshFindDiskType - vshUndefineVolume ^Wow, there is quite a lot of these..As I went through the list I found out, the list is much longer, shame on me.
Erik

[getting back to this after *loong* time, sorry] On Fri, Jul 17, 2015 at 02:30:20PM +0200, Erik Skultety wrote:
Actually, I found out this is easier to review as a one patch with various diff options used for various parts of the patch. Some questions and suggestions below.
Why vshClientHooks and vshCmdGrp aren't in the vshControl struct? If we move the client helpers into a library (I think this stuff can be in src/util/virshell.c for example), then it won't be thread-safe. Moving those to the control structure will also be cleaner.
It would be nice, but since readline-defined user callbacks do not contain any opaque argument in their signature, you can only rely on statically declared data, therefore you can't do this with command groups, although it does work for client hooks at least.
That's fair. Let's keep it as a static global then.
Some things are still broken up, like readline stuff. It should be either completely hidden or completely exposed. For example, vshReadline{Init,Deinit} should be moved into vsh{Init,Deinit}.
Commands from former virshCmds (except connect) should be in vsh.c so each client can use them in their cmdGroups definition without re-implementing them.
Well, I thought off 2 possible approaches how to tackle this one. The first one is (though not my favorite) to simply move handler implementations and structures initialization to vsh.c. As we do specify all the command groups and options in fixed arrays, we would have to create a completely new group for the generic commands available to every client. In virsh for example, that would leave us with 'connect' command only which we should create a separate group to make it all work. To be honest, I don't like this idea at all.
Me neither.
The other idea however, might be nicer, but much more complex and it's for a debate if we really want that and if so, I think it should be a separate follow-up patch, definitely not part of v2. So, the idea is to implement command group register mechanism using linked lists. That way, each client would have to register every group individually. And because lists are easily extensible, we could just add the 'connect' command to the 'virsh' group by implementing some internal APIs to command group management (add/update/whatever).
That's nice, but I had a different thing in mind. I though that vsh.c would create and export common command definitions and it'd be up to the client whether it uses them in one of its command groups or not. Easier than the first version and more extensible then the second one.
vsh is not doing the argument parsing, but that's be fine. I would, at least, wrap some options in a function that can be called from multiple clients, but that's one of the nice-to-have things that can be done later.
There is a reason for this. In my opinion, each client should be responsible for parsing their own command line arguments. It doesn't really matter that all the clients most likely will implement usage, help, connect arguments...Being generic in this case would require each client to provide their callbacks for generic options, their specific options list and callbacks to handle these specific options as well. Maybe I just don't see it the way you see it :), but I still think, in this specific case we shouldn't try to split the code even more.
I saw it the other way around. I thought there could be a teeny tiny function for parsing common arguments that all clients *could* call, but as I said, that's not necessary and not thought through. Just a possible future idea.
vshInit() is declared with ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); but handles passed NULLs properly, that declaration should be fixed.
Fixed in v2.
Also there are some whitespace problems (e.g. with parameters of virshLookupDomainBy), but considering how many of them are there inside the files already, it's nothing compared to the size of this refactor.
I tried to fix in v2 as many as I could find.
The exclude_file_name_regexp--sc_avoid_strcase should only contain ^tools/vsh\.h$$, not virsh.h.
Fixed.
Anyway, here's a list of things that should be changed (either from virsh to vsh or vice versa) split into categories (feel free to disagree with any):
Totally: - virshCommandOptTimeoutToMs ^^ Something tells me I overlooked this one and pushed v2 to my forked repo without it...Sigh, v3 it is.. - VIRSH_MAX_XML_FILE - virshPrettyCapacity - vshFindDisk - vshSnapshotListCollect
Most likely: - vshCatchInt - virshPrintJobProgress ^^currently this is only used for migration and blockjobs and so far, we haven't talked about some time consuming admin jobs, so I'd say either we leave it for good or we can move it to the lib some time later (possibly with virsh-edit stuff, see below)
We can, yes. I'm just really afraid of these two clients having more and more re-implemented in both of them. Basically I don't want these to end up as qemu and lxc drivers :)
- virshTreePrint(internal) with virshTreeLookup typedef - virshPrintRaw - virshAskReedit - virshEdit* - virshAllowedEscapeChar ^^ This one should be client dependent, whatever the reasons to different allowed sets of escape chars might be
Maybe (i.e. not needed now, but might be nice): - virshWatchJob - virsh-edit stuff ^^ I'm not sure how you meant this one, did you mean just renaming the macros inside and the module itself or you meant a complete refactor, spliting the module, etc.???
I meant just a rename. Martin
participants (3)
-
Erik Skultety
-
Martin Kletzander
-
Michal Privoznik