2005-11-10 16:12:31 +00:00
|
|
|
/*
|
2010-06-09 09:00:30 +00:00
|
|
|
* virsh.c: a shell to exercise the libvirt API
|
2005-11-10 16:12:31 +00:00
|
|
|
*
|
2015-02-19 13:16:39 +00:00
|
|
|
* Copyright (C) 2005, 2007-2015 Red Hat, Inc.
|
2005-11-10 16:12:31 +00:00
|
|
|
*
|
2012-07-27 09:39:53 +00:00
|
|
|
* 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
|
2012-09-20 22:30:55 +00:00
|
|
|
* License along with this library. If not, see
|
2012-07-27 09:39:53 +00:00
|
|
|
* <http://www.gnu.org/licenses/>.
|
2005-11-10 16:12:31 +00:00
|
|
|
*/
|
|
|
|
|
2008-01-29 18:15:54 +00:00
|
|
|
#include <config.h>
|
2012-08-18 03:16:04 +00:00
|
|
|
#include "virsh.h"
|
2007-12-04 18:27:52 +00:00
|
|
|
|
2005-12-01 16:35:42 +00:00
|
|
|
#include <unistd.h>
|
2005-12-08 10:23:34 +00:00
|
|
|
#include <getopt.h>
|
2005-12-08 14:22:52 +00:00
|
|
|
#include <sys/time.h>
|
2006-03-30 16:08:13 +00:00
|
|
|
#include <fcntl.h>
|
2007-06-06 12:24:31 +00:00
|
|
|
#include <sys/stat.h>
|
2005-12-08 10:23:34 +00:00
|
|
|
|
Standardize use of header files, making internal.h primary.
* qemud/internal.h, qemud/qemud.h: Rename this file so it
doesn't conflict with src/internal.h.
* HACKING: Document how header files should be used.
* qemud/Makefile.am: Add src/ directory to includes.
* qemud/event.c, qemud/mdns.c, qemud/qemud.c, qemud/remote.c,
qemud/remote_protocol.c, qemud/remote_protocol.h,
qemud/remote_protocol.x, src/buf.c, src/libvirt.c,
src/nodeinfo.c, src/qemu_conf.c, src/qemu_driver.c,
src/stats_linux.c, src/storage_backend.c, src/storage_backend_fs.c,
src/storage_backend_iscsi.c, src/storage_backend_logical.c,
src/storage_conf.c, src/storage_driver.c, src/util.c,
src/util.h, src/virsh.c, src/virterror.c, src/xend_internal.c,
src/xml.c, tests/reconnect.c, tests/xmlrpctest.c,
tests/qparamtest.c: Standardize use of header files.
* docs/*, po/*: Rebuild docs.
2008-05-23 08:24:41 +00:00
|
|
|
#include "internal.h"
|
2012-12-13 18:21:53 +00:00
|
|
|
#include "virerror.h"
|
2012-12-12 18:06:53 +00:00
|
|
|
#include "viralloc.h"
|
2011-07-19 18:32:58 +00:00
|
|
|
#include "virfile.h"
|
2012-12-13 15:49:48 +00:00
|
|
|
#include "virthread.h"
|
2013-04-03 10:36:23 +00:00
|
|
|
#include "virstring.h"
|
2016-04-12 22:29:52 +00:00
|
|
|
#include "virgettext.h"
|
2005-12-08 10:23:34 +00:00
|
|
|
|
2019-08-22 01:42:45 +00:00
|
|
|
#include "virsh-backup.h"
|
2019-03-13 21:04:51 +00:00
|
|
|
#include "virsh-checkpoint.h"
|
2012-08-18 04:00:42 +00:00
|
|
|
#include "virsh-domain.h"
|
2022-02-21 13:02:19 +00:00
|
|
|
#include "virsh-domain-event.h"
|
2012-08-20 13:46:38 +00:00
|
|
|
#include "virsh-domain-monitor.h"
|
2012-08-20 20:01:45 +00:00
|
|
|
#include "virsh-host.h"
|
2012-08-20 20:30:53 +00:00
|
|
|
#include "virsh-interface.h"
|
2012-08-20 21:43:25 +00:00
|
|
|
#include "virsh-network.h"
|
2012-08-20 22:23:10 +00:00
|
|
|
#include "virsh-nodedev.h"
|
2012-08-20 22:56:03 +00:00
|
|
|
#include "virsh-nwfilter.h"
|
2012-08-20 22:56:53 +00:00
|
|
|
#include "virsh-pool.h"
|
2012-08-20 23:14:37 +00:00
|
|
|
#include "virsh-secret.h"
|
2012-08-20 23:29:03 +00:00
|
|
|
#include "virsh-snapshot.h"
|
2012-08-20 23:41:24 +00:00
|
|
|
#include "virsh-volume.h"
|
2012-08-18 04:00:42 +00:00
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
static char *progname;
|
|
|
|
|
2010-11-30 06:37:04 +00:00
|
|
|
static const vshCmdGrp cmdGroups[];
|
2015-06-15 16:53:58 +00:00
|
|
|
static const vshClientHooks hooks;
|
2009-02-09 14:24:06 +00:00
|
|
|
|
2010-03-05 09:59:52 +00:00
|
|
|
/*
|
|
|
|
* Detection of disconnections and automatic reconnection support
|
|
|
|
*/
|
2014-10-28 18:38:04 +00:00
|
|
|
static int disconnected; /* we may have been disconnected */
|
2010-03-05 09:59:52 +00:00
|
|
|
|
|
|
|
/*
|
2015-06-15 16:53:58 +00:00
|
|
|
* virshCatchDisconnect:
|
2010-03-05 09:59:52 +00:00
|
|
|
*
|
2012-08-02 17:15:16 +00:00
|
|
|
* We get here when the connection was closed. We can't do much in the
|
|
|
|
* handler, just save the fact it was raised.
|
2010-03-05 09:59:52 +00:00
|
|
|
*/
|
2010-03-12 10:39:24 +00:00
|
|
|
static void
|
2023-12-14 16:13:08 +00:00
|
|
|
virshCatchDisconnect(virConnectPtr conn G_GNUC_UNUSED,
|
2015-06-15 16:53:58 +00:00
|
|
|
int reason,
|
2015-09-15 14:46:07 +00:00
|
|
|
void *opaque)
|
2012-08-02 17:15:16 +00:00
|
|
|
{
|
2015-09-15 14:46:07 +00:00
|
|
|
if (reason != VIR_CONNECT_CLOSE_REASON_CLIENT) {
|
|
|
|
vshControl *ctl = opaque;
|
|
|
|
const char *str = "unknown reason";
|
|
|
|
|
|
|
|
switch ((virConnectCloseReason) reason) {
|
|
|
|
case VIR_CONNECT_CLOSE_REASON_ERROR:
|
2023-03-09 14:54:58 +00:00
|
|
|
str = N_("Disconnected from %1$s due to I/O error");
|
2015-09-15 14:46:07 +00:00
|
|
|
break;
|
|
|
|
case VIR_CONNECT_CLOSE_REASON_EOF:
|
2023-03-09 14:54:58 +00:00
|
|
|
str = N_("Disconnected from %1$s due to end of file");
|
2015-09-15 14:46:07 +00:00
|
|
|
break;
|
|
|
|
case VIR_CONNECT_CLOSE_REASON_KEEPALIVE:
|
2023-03-09 14:54:58 +00:00
|
|
|
str = N_("Disconnected from %1$s due to keepalive timeout");
|
2015-09-15 14:46:07 +00:00
|
|
|
break;
|
|
|
|
case VIR_CONNECT_CLOSE_REASON_CLIENT:
|
|
|
|
case VIR_CONNECT_CLOSE_REASON_LAST:
|
|
|
|
break;
|
|
|
|
}
|
2023-12-14 16:13:08 +00:00
|
|
|
vshError(ctl, _(str), NULLSTR(ctl->connname));
|
2015-09-15 14:46:07 +00:00
|
|
|
|
2012-08-02 17:15:16 +00:00
|
|
|
disconnected++;
|
2015-12-17 22:23:16 +00:00
|
|
|
vshEventDone(ctl);
|
2015-09-15 14:46:07 +00:00
|
|
|
}
|
2010-03-05 09:59:52 +00:00
|
|
|
}
|
|
|
|
|
2014-03-06 16:20:11 +00:00
|
|
|
/* Main Function which should be used for connecting.
|
|
|
|
* This function properly handles keepalive settings. */
|
|
|
|
virConnectPtr
|
2015-06-15 16:53:58 +00:00
|
|
|
virshConnect(vshControl *ctl, const char *uri, bool readonly)
|
2014-03-06 16:20:11 +00:00
|
|
|
{
|
|
|
|
virConnectPtr c = NULL;
|
|
|
|
int interval = 5; /* Default */
|
|
|
|
int count = 6; /* Default */
|
|
|
|
bool keepalive_forced = false;
|
2021-03-11 07:16:13 +00:00
|
|
|
virPolkitAgent *pkagent = NULL;
|
2016-02-09 19:08:42 +00:00
|
|
|
int authfail = 0;
|
2014-03-06 16:20:11 +00:00
|
|
|
|
|
|
|
if (ctl->keepalive_interval >= 0) {
|
|
|
|
interval = ctl->keepalive_interval;
|
|
|
|
keepalive_forced = true;
|
|
|
|
}
|
|
|
|
if (ctl->keepalive_count >= 0) {
|
|
|
|
count = ctl->keepalive_count;
|
|
|
|
keepalive_forced = true;
|
|
|
|
}
|
|
|
|
|
2021-11-16 14:00:19 +00:00
|
|
|
if (virPolkitAgentAvailable() &&
|
|
|
|
!(pkagent = virPolkitAgentCreate()))
|
|
|
|
virResetLastError();
|
|
|
|
|
2016-02-09 19:08:42 +00:00
|
|
|
do {
|
|
|
|
virErrorPtr err;
|
|
|
|
|
|
|
|
if ((c = virConnectOpenAuth(uri, virConnectAuthPtrDefault,
|
|
|
|
readonly ? VIR_CONNECT_RO : 0)))
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (readonly)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
err = virGetLastError();
|
2021-11-16 14:00:19 +00:00
|
|
|
/*
|
|
|
|
* If polkit agent failed starting the first time, then retry once more
|
|
|
|
* now when we know it really is needed.
|
|
|
|
*/
|
2021-11-16 13:30:07 +00:00
|
|
|
if (!pkagent &&
|
2017-05-11 13:17:09 +00:00
|
|
|
err && err->domain == VIR_FROM_POLKIT &&
|
2016-02-09 19:08:42 +00:00
|
|
|
err->code == VIR_ERR_AUTH_UNAVAILABLE) {
|
2021-11-16 13:30:07 +00:00
|
|
|
if (!(pkagent = virPolkitAgentCreate()))
|
2016-02-09 19:08:42 +00:00
|
|
|
goto cleanup;
|
|
|
|
} else if (err && err->domain == VIR_FROM_POLKIT &&
|
|
|
|
err->code == VIR_ERR_AUTH_FAILED) {
|
|
|
|
authfail++;
|
|
|
|
} else {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
virResetLastError();
|
|
|
|
/* Failure to authenticate 5 times should be enough.
|
|
|
|
* No sense prolonging the agony.
|
|
|
|
*/
|
|
|
|
} while (authfail < 5);
|
|
|
|
|
2014-03-06 16:20:11 +00:00
|
|
|
if (!c)
|
2016-02-09 19:08:42 +00:00
|
|
|
goto cleanup;
|
2014-03-06 16:20:11 +00:00
|
|
|
|
|
|
|
if (interval > 0 &&
|
|
|
|
virConnectSetKeepAlive(c, interval, count) != 0) {
|
|
|
|
if (keepalive_forced) {
|
|
|
|
vshError(ctl, "%s",
|
2023-08-24 15:04:34 +00:00
|
|
|
_("Cannot setup keepalive on connection as requested, disconnecting"));
|
2022-01-28 17:42:45 +00:00
|
|
|
g_clear_pointer(&c, virConnectClose);
|
2016-02-09 19:08:42 +00:00
|
|
|
goto cleanup;
|
2014-03-06 16:20:11 +00:00
|
|
|
}
|
|
|
|
vshDebug(ctl, VSH_ERR_INFO, "%s",
|
|
|
|
_("Failed to setup keepalive on connection\n"));
|
2020-11-12 13:31:57 +00:00
|
|
|
vshResetLibvirtError();
|
2014-03-06 16:20:11 +00:00
|
|
|
}
|
|
|
|
|
2016-02-09 19:08:42 +00:00
|
|
|
cleanup:
|
|
|
|
virPolkitAgentDestroy(pkagent);
|
2014-03-06 16:20:11 +00:00
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
2010-03-05 09:59:52 +00:00
|
|
|
/*
|
2015-06-15 16:53:58 +00:00
|
|
|
* virshReconnect:
|
2010-03-05 09:59:52 +00:00
|
|
|
*
|
2010-03-12 10:39:24 +00:00
|
|
|
* Reconnect after a disconnect from libvirtd
|
2010-03-05 09:59:52 +00:00
|
|
|
*
|
|
|
|
*/
|
2016-07-29 06:09:22 +00:00
|
|
|
static int
|
2016-04-21 12:06:10 +00:00
|
|
|
virshReconnect(vshControl *ctl, const char *name, bool readonly, bool force)
|
virsh: optimize creation of default connection
Ramon de Carvalho Valle reported a problem with:
virsh connect qemu:///system
as a non-root user. The real root problem appears to be a regression
in libvirtd being auto-started on the default qemu:///session URI;
however, the symptom points to an independent flaw in virsh - we
shouldn't be wasting efforts on making a connection if we aren't going
to be using that connection. Fixing virsh avoids Ramon's issue, while
I work in the meantime to fix the real libvirtd regression.
This patch looks big, but that's because 'gcc -Wmissing-field-initializers'
gets triggered by './autobuild.sh --enable-compile-warnings=error', so I
had to add 0 initialization to everyone (rather than my preference of
just adding the non-zero flags to virshCmds and to cmdConnect).
Meanwhile, if you use 'virsh -c URI', the connection must succeed; this
patch _only_ optimizes the default connection to be deferred to a later
point where we know if a particular command to be run needs a connection.
* tools/virsh.c (VSH_CMD_FLAG_NOCONNECT): New flag.
(vshCmdDef): Add new flags field.
(vshCommandRun): Honor new flag.
(domManagementCmds, domMonitoringCmds, storagePoolCmds)
(storageVolCmds, networkCmds, nodedevCmds, ifaceCmds)
(nwfilterCmds, secretCmds, virshCmds, snapshotCmds)
(hostAndHypervisorCmds): Populate new field.
(vshReconnect): Don't warn on initial connection.
2011-03-14 20:30:24 +00:00
|
|
|
{
|
|
|
|
bool connected = false;
|
2021-03-11 07:16:13 +00:00
|
|
|
virshControl *priv = ctl->privData;
|
2017-08-18 14:35:23 +00:00
|
|
|
|
|
|
|
/* If the flag was not specified, then it depends on whether we are
|
|
|
|
* reconnecting to the current URI (in which case we want to keep the
|
|
|
|
* readonly flag as it was) or to a specified URI in which case it
|
|
|
|
* should stay false */
|
|
|
|
if (!readonly && !name)
|
|
|
|
readonly = priv->readonly;
|
virsh: optimize creation of default connection
Ramon de Carvalho Valle reported a problem with:
virsh connect qemu:///system
as a non-root user. The real root problem appears to be a regression
in libvirtd being auto-started on the default qemu:///session URI;
however, the symptom points to an independent flaw in virsh - we
shouldn't be wasting efforts on making a connection if we aren't going
to be using that connection. Fixing virsh avoids Ramon's issue, while
I work in the meantime to fix the real libvirtd regression.
This patch looks big, but that's because 'gcc -Wmissing-field-initializers'
gets triggered by './autobuild.sh --enable-compile-warnings=error', so I
had to add 0 initialization to everyone (rather than my preference of
just adding the non-zero flags to virshCmds and to cmdConnect).
Meanwhile, if you use 'virsh -c URI', the connection must succeed; this
patch _only_ optimizes the default connection to be deferred to a later
point where we know if a particular command to be run needs a connection.
* tools/virsh.c (VSH_CMD_FLAG_NOCONNECT): New flag.
(vshCmdDef): Add new flags field.
(vshCommandRun): Honor new flag.
(domManagementCmds, domMonitoringCmds, storagePoolCmds)
(storageVolCmds, networkCmds, nodedevCmds, ifaceCmds)
(nwfilterCmds, secretCmds, virshCmds, snapshotCmds)
(hostAndHypervisorCmds): Populate new field.
(vshReconnect): Don't warn on initial connection.
2011-03-14 20:30:24 +00:00
|
|
|
|
2015-06-15 16:53:58 +00:00
|
|
|
if (priv->conn) {
|
2013-03-26 09:54:55 +00:00
|
|
|
int ret;
|
virsh: optimize creation of default connection
Ramon de Carvalho Valle reported a problem with:
virsh connect qemu:///system
as a non-root user. The real root problem appears to be a regression
in libvirtd being auto-started on the default qemu:///session URI;
however, the symptom points to an independent flaw in virsh - we
shouldn't be wasting efforts on making a connection if we aren't going
to be using that connection. Fixing virsh avoids Ramon's issue, while
I work in the meantime to fix the real libvirtd regression.
This patch looks big, but that's because 'gcc -Wmissing-field-initializers'
gets triggered by './autobuild.sh --enable-compile-warnings=error', so I
had to add 0 initialization to everyone (rather than my preference of
just adding the non-zero flags to virshCmds and to cmdConnect).
Meanwhile, if you use 'virsh -c URI', the connection must succeed; this
patch _only_ optimizes the default connection to be deferred to a later
point where we know if a particular command to be run needs a connection.
* tools/virsh.c (VSH_CMD_FLAG_NOCONNECT): New flag.
(vshCmdDef): Add new flags field.
(vshCommandRun): Honor new flag.
(domManagementCmds, domMonitoringCmds, storagePoolCmds)
(storageVolCmds, networkCmds, nodedevCmds, ifaceCmds)
(nwfilterCmds, secretCmds, virshCmds, snapshotCmds)
(hostAndHypervisorCmds): Populate new field.
(vshReconnect): Don't warn on initial connection.
2011-03-14 20:30:24 +00:00
|
|
|
connected = true;
|
2013-03-26 09:54:55 +00:00
|
|
|
|
2015-06-15 16:53:58 +00:00
|
|
|
virConnectUnregisterCloseCallback(priv->conn, virshCatchDisconnect);
|
|
|
|
ret = virConnectClose(priv->conn);
|
2013-03-26 09:54:55 +00:00
|
|
|
if (ret < 0)
|
|
|
|
vshError(ctl, "%s", _("Failed to disconnect from the hypervisor"));
|
|
|
|
else if (ret > 0)
|
2023-08-24 15:04:34 +00:00
|
|
|
vshError(ctl, "%s", _("One or more references were leaked after disconnect from the hypervisor"));
|
virsh: optimize creation of default connection
Ramon de Carvalho Valle reported a problem with:
virsh connect qemu:///system
as a non-root user. The real root problem appears to be a regression
in libvirtd being auto-started on the default qemu:///session URI;
however, the symptom points to an independent flaw in virsh - we
shouldn't be wasting efforts on making a connection if we aren't going
to be using that connection. Fixing virsh avoids Ramon's issue, while
I work in the meantime to fix the real libvirtd regression.
This patch looks big, but that's because 'gcc -Wmissing-field-initializers'
gets triggered by './autobuild.sh --enable-compile-warnings=error', so I
had to add 0 initialization to everyone (rather than my preference of
just adding the non-zero flags to virshCmds and to cmdConnect).
Meanwhile, if you use 'virsh -c URI', the connection must succeed; this
patch _only_ optimizes the default connection to be deferred to a later
point where we know if a particular command to be run needs a connection.
* tools/virsh.c (VSH_CMD_FLAG_NOCONNECT): New flag.
(vshCmdDef): Add new flags field.
(vshCommandRun): Honor new flag.
(domManagementCmds, domMonitoringCmds, storagePoolCmds)
(storageVolCmds, networkCmds, nodedevCmds, ifaceCmds)
(nwfilterCmds, secretCmds, virshCmds, snapshotCmds)
(hostAndHypervisorCmds): Populate new field.
(vshReconnect): Don't warn on initial connection.
2011-03-14 20:30:24 +00:00
|
|
|
}
|
2010-03-05 09:59:52 +00:00
|
|
|
|
2017-08-18 14:35:23 +00:00
|
|
|
priv->conn = virshConnect(ctl, name ? name : ctl->connname, readonly);
|
2014-03-06 16:20:11 +00:00
|
|
|
|
2015-06-15 16:53:58 +00:00
|
|
|
if (!priv->conn) {
|
2012-12-13 13:08:00 +00:00
|
|
|
if (disconnected)
|
|
|
|
vshError(ctl, "%s", _("Failed to reconnect to the hypervisor"));
|
|
|
|
else
|
|
|
|
vshError(ctl, "%s", _("failed to connect to the hypervisor"));
|
2016-07-29 06:09:22 +00:00
|
|
|
return -1;
|
2012-08-02 17:15:16 +00:00
|
|
|
} else {
|
2016-04-21 12:06:10 +00:00
|
|
|
if (name) {
|
|
|
|
VIR_FREE(ctl->connname);
|
2019-10-18 15:24:02 +00:00
|
|
|
ctl->connname = g_strdup(name);
|
2016-04-21 12:06:10 +00:00
|
|
|
}
|
2017-11-27 00:18:11 +00:00
|
|
|
|
2023-12-14 16:11:08 +00:00
|
|
|
if (!ctl->connname)
|
|
|
|
ctl->connname = virConnectGetURI(priv->conn);
|
|
|
|
|
2017-11-27 00:18:11 +00:00
|
|
|
priv->readonly = readonly;
|
|
|
|
|
2015-06-15 16:53:58 +00:00
|
|
|
if (virConnectRegisterCloseCallback(priv->conn, virshCatchDisconnect,
|
2015-12-17 22:23:01 +00:00
|
|
|
ctl, NULL) < 0)
|
2012-08-02 17:15:16 +00:00
|
|
|
vshError(ctl, "%s", _("Unable to register disconnect callback"));
|
2016-04-21 12:06:10 +00:00
|
|
|
if (connected && !force)
|
2012-08-02 17:15:16 +00:00
|
|
|
vshError(ctl, "%s", _("Reconnected to the hypervisor"));
|
|
|
|
}
|
2010-03-05 09:59:52 +00:00
|
|
|
disconnected = 0;
|
2015-06-15 16:53:58 +00:00
|
|
|
priv->useGetInfo = false;
|
|
|
|
priv->useSnapshotOld = false;
|
|
|
|
priv->blockJobNoBytes = false;
|
2016-07-29 06:09:22 +00:00
|
|
|
return 0;
|
2010-03-05 09:59:52 +00:00
|
|
|
}
|
2007-02-14 15:44:58 +00:00
|
|
|
|
2015-06-15 16:53:58 +00:00
|
|
|
/* ---------------
|
|
|
|
* Command Connect
|
|
|
|
* ---------------
|
2013-03-27 13:22:47 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
static const vshCmdOptDef opts_connect[] = {
|
|
|
|
{.name = "name",
|
2014-12-11 02:46:15 +00:00
|
|
|
.type = VSH_OT_STRING,
|
2024-03-14 15:58:40 +00:00
|
|
|
.positional = true,
|
2024-03-11 12:17:50 +00:00
|
|
|
.allowEmpty = true,
|
2021-09-15 15:42:08 +00:00
|
|
|
.completer = virshCompleteEmpty,
|
2013-03-27 13:22:47 +00:00
|
|
|
.help = N_("hypervisor connection URI")
|
|
|
|
},
|
|
|
|
{.name = "readonly",
|
|
|
|
.type = VSH_OT_BOOL,
|
|
|
|
.help = N_("read-only connection")
|
|
|
|
},
|
|
|
|
{.name = NULL}
|
|
|
|
};
|
|
|
|
|
2024-03-04 12:21:50 +00:00
|
|
|
static const vshCmdInfo info_connect = {
|
|
|
|
.help = N_("(re)connect to hypervisor"),
|
|
|
|
.desc = N_("Connect to local hypervisor. This is built-in "
|
|
|
|
"command after shell start up."),
|
2009-07-16 14:40:08 +00:00
|
|
|
};
|
|
|
|
|
2011-04-18 22:37:42 +00:00
|
|
|
static bool
|
2015-06-15 16:53:58 +00:00
|
|
|
cmdConnect(vshControl *ctl, const vshCmd *cmd)
|
2009-07-16 14:40:08 +00:00
|
|
|
{
|
2015-06-15 16:53:58 +00:00
|
|
|
bool ro = vshCommandOptBool(cmd, "readonly");
|
|
|
|
const char *name = NULL;
|
2016-04-20 17:56:27 +00:00
|
|
|
|
|
|
|
if (vshCommandOptStringReq(ctl, cmd, "name", &name) < 0)
|
|
|
|
return false;
|
|
|
|
|
2016-07-29 06:09:22 +00:00
|
|
|
if (virshReconnect(ctl, name, ro, true) < 0)
|
|
|
|
return false;
|
virsh: common code for waiting for an event
I plan to add 'virsh event' to virsh-domain.c and 'virsh
net-event' to virsh-network.c; but as they will share quite
a bit of common boilerplate, it's better to set that up now
in virsh.c.
* tools/virsh.h (_vshControl): Add fields.
(vshEventStart, vshEventWait, vshEventDone, vshEventCleanup): New
prototypes.
* tools/virsh.c (vshEventFd, vshEventOldAction, vshEventInt)
(vshEventTimeout): New helper variables and functions.
(vshEventStart, vshEventWait, vshEventDone, vshEventCleanup):
Implement new functions.
(vshInit, vshDeinit, main): Manage event timeout.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-02-14 22:30:23 +00:00
|
|
|
|
2015-06-15 16:53:58 +00:00
|
|
|
return true;
|
virsh: common code for waiting for an event
I plan to add 'virsh event' to virsh-domain.c and 'virsh
net-event' to virsh-network.c; but as they will share quite
a bit of common boilerplate, it's better to set that up now
in virsh.c.
* tools/virsh.h (_vshControl): Add fields.
(vshEventStart, vshEventWait, vshEventDone, vshEventCleanup): New
prototypes.
* tools/virsh.c (vshEventFd, vshEventOldAction, vshEventInt)
(vshEventTimeout): New helper variables and functions.
(vshEventStart, vshEventWait, vshEventDone, vshEventCleanup):
Implement new functions.
(vshInit, vshDeinit, main): Manage event timeout.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-02-14 22:30:23 +00:00
|
|
|
}
|
|
|
|
|
2015-06-15 16:53:58 +00:00
|
|
|
/* ---------------
|
|
|
|
* Utils for work with runtime commands data
|
|
|
|
* ---------------
|
|
|
|
*/
|
virsh: common code for waiting for an event
I plan to add 'virsh event' to virsh-domain.c and 'virsh
net-event' to virsh-network.c; but as they will share quite
a bit of common boilerplate, it's better to set that up now
in virsh.c.
* tools/virsh.h (_vshControl): Add fields.
(vshEventStart, vshEventWait, vshEventDone, vshEventCleanup): New
prototypes.
* tools/virsh.c (vshEventFd, vshEventOldAction, vshEventInt)
(vshEventTimeout): New helper variables and functions.
(vshEventStart, vshEventWait, vshEventDone, vshEventCleanup):
Implement new functions.
(vshInit, vshDeinit, main): Manage event timeout.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-02-14 22:30:23 +00:00
|
|
|
|
2015-06-15 16:53:58 +00:00
|
|
|
static bool
|
|
|
|
virshConnectionUsability(vshControl *ctl, virConnectPtr conn)
|
virsh: common code for waiting for an event
I plan to add 'virsh event' to virsh-domain.c and 'virsh
net-event' to virsh-network.c; but as they will share quite
a bit of common boilerplate, it's better to set that up now
in virsh.c.
* tools/virsh.h (_vshControl): Add fields.
(vshEventStart, vshEventWait, vshEventDone, vshEventCleanup): New
prototypes.
* tools/virsh.c (vshEventFd, vshEventOldAction, vshEventInt)
(vshEventTimeout): New helper variables and functions.
(vshEventStart, vshEventWait, vshEventDone, vshEventCleanup):
Implement new functions.
(vshInit, vshDeinit, main): Manage event timeout.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-02-14 22:30:23 +00:00
|
|
|
{
|
2015-06-15 16:53:58 +00:00
|
|
|
if (!conn ||
|
|
|
|
virConnectIsAlive(conn) == 0) {
|
|
|
|
vshError(ctl, "%s", _("no valid connection"));
|
|
|
|
return false;
|
virsh: common code for waiting for an event
I plan to add 'virsh event' to virsh-domain.c and 'virsh
net-event' to virsh-network.c; but as they will share quite
a bit of common boilerplate, it's better to set that up now
in virsh.c.
* tools/virsh.h (_vshControl): Add fields.
(vshEventStart, vshEventWait, vshEventDone, vshEventCleanup): New
prototypes.
* tools/virsh.c (vshEventFd, vshEventOldAction, vshEventInt)
(vshEventTimeout): New helper variables and functions.
(vshEventStart, vshEventWait, vshEventDone, vshEventCleanup):
Implement new functions.
(vshInit, vshDeinit, main): Manage event timeout.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-02-14 22:30:23 +00:00
|
|
|
}
|
|
|
|
|
2015-06-15 16:53:58 +00:00
|
|
|
/* The connection is considered dead only if
|
2018-12-04 17:08:14 +00:00
|
|
|
* virConnectIsAlive() successfully says so.
|
2015-06-15 16:53:58 +00:00
|
|
|
*/
|
|
|
|
vshResetLibvirtError();
|
virsh: common code for waiting for an event
I plan to add 'virsh event' to virsh-domain.c and 'virsh
net-event' to virsh-network.c; but as they will share quite
a bit of common boilerplate, it's better to set that up now
in virsh.c.
* tools/virsh.h (_vshControl): Add fields.
(vshEventStart, vshEventWait, vshEventDone, vshEventCleanup): New
prototypes.
* tools/virsh.c (vshEventFd, vshEventOldAction, vshEventInt)
(vshEventTimeout): New helper variables and functions.
(vshEventStart, vshEventWait, vshEventDone, vshEventCleanup):
Implement new functions.
(vshInit, vshDeinit, main): Manage event timeout.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-02-14 22:30:23 +00:00
|
|
|
|
2015-06-15 16:53:58 +00:00
|
|
|
return true;
|
virsh: common code for waiting for an event
I plan to add 'virsh event' to virsh-domain.c and 'virsh
net-event' to virsh-network.c; but as they will share quite
a bit of common boilerplate, it's better to set that up now
in virsh.c.
* tools/virsh.h (_vshControl): Add fields.
(vshEventStart, vshEventWait, vshEventDone, vshEventCleanup): New
prototypes.
* tools/virsh.c (vshEventFd, vshEventOldAction, vshEventInt)
(vshEventTimeout): New helper variables and functions.
(vshEventStart, vshEventWait, vshEventDone, vshEventCleanup):
Implement new functions.
(vshInit, vshDeinit, main): Manage event timeout.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-02-14 22:30:23 +00:00
|
|
|
}
|
|
|
|
|
2015-06-15 16:53:58 +00:00
|
|
|
static void *
|
|
|
|
virshConnectionHandler(vshControl *ctl)
|
virsh: common code for waiting for an event
I plan to add 'virsh event' to virsh-domain.c and 'virsh
net-event' to virsh-network.c; but as they will share quite
a bit of common boilerplate, it's better to set that up now
in virsh.c.
* tools/virsh.h (_vshControl): Add fields.
(vshEventStart, vshEventWait, vshEventDone, vshEventCleanup): New
prototypes.
* tools/virsh.c (vshEventFd, vshEventOldAction, vshEventInt)
(vshEventTimeout): New helper variables and functions.
(vshEventStart, vshEventWait, vshEventDone, vshEventCleanup):
Implement new functions.
(vshInit, vshDeinit, main): Manage event timeout.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-02-14 22:30:23 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virshControl *priv = ctl->privData;
|
virsh: common code for waiting for an event
I plan to add 'virsh event' to virsh-domain.c and 'virsh
net-event' to virsh-network.c; but as they will share quite
a bit of common boilerplate, it's better to set that up now
in virsh.c.
* tools/virsh.h (_vshControl): Add fields.
(vshEventStart, vshEventWait, vshEventDone, vshEventCleanup): New
prototypes.
* tools/virsh.c (vshEventFd, vshEventOldAction, vshEventInt)
(vshEventTimeout): New helper variables and functions.
(vshEventStart, vshEventWait, vshEventDone, vshEventCleanup):
Implement new functions.
(vshInit, vshDeinit, main): Manage event timeout.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-02-14 22:30:23 +00:00
|
|
|
|
2016-07-29 06:09:22 +00:00
|
|
|
if ((!priv->conn || disconnected) &&
|
|
|
|
virshReconnect(ctl, NULL, false, false) < 0)
|
|
|
|
return NULL;
|
virsh: common code for waiting for an event
I plan to add 'virsh event' to virsh-domain.c and 'virsh
net-event' to virsh-network.c; but as they will share quite
a bit of common boilerplate, it's better to set that up now
in virsh.c.
* tools/virsh.h (_vshControl): Add fields.
(vshEventStart, vshEventWait, vshEventDone, vshEventCleanup): New
prototypes.
* tools/virsh.c (vshEventFd, vshEventOldAction, vshEventInt)
(vshEventTimeout): New helper variables and functions.
(vshEventStart, vshEventWait, vshEventDone, vshEventCleanup):
Implement new functions.
(vshInit, vshDeinit, main): Manage event timeout.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-02-14 22:30:23 +00:00
|
|
|
|
2015-06-15 16:53:58 +00:00
|
|
|
if (virshConnectionUsability(ctl, priv->conn))
|
|
|
|
return priv->conn;
|
2016-07-29 06:09:22 +00:00
|
|
|
|
2015-06-15 16:53:58 +00:00
|
|
|
return NULL;
|
virsh: common code for waiting for an event
I plan to add 'virsh event' to virsh-domain.c and 'virsh
net-event' to virsh-network.c; but as they will share quite
a bit of common boilerplate, it's better to set that up now
in virsh.c.
* tools/virsh.h (_vshControl): Add fields.
(vshEventStart, vshEventWait, vshEventDone, vshEventCleanup): New
prototypes.
* tools/virsh.c (vshEventFd, vshEventOldAction, vshEventInt)
(vshEventTimeout): New helper variables and functions.
(vshEventStart, vshEventWait, vshEventDone, vshEventCleanup):
Implement new functions.
(vshInit, vshDeinit, main): Manage event timeout.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-02-14 22:30:23 +00:00
|
|
|
}
|
|
|
|
|
2016-06-17 17:28:12 +00:00
|
|
|
|
2013-08-21 09:02:42 +00:00
|
|
|
/*
|
|
|
|
* Initialize connection.
|
|
|
|
*/
|
|
|
|
static bool
|
2015-06-15 16:53:58 +00:00
|
|
|
virshInit(vshControl *ctl)
|
2013-08-21 09:02:42 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virshControl *priv = ctl->privData;
|
2015-06-15 16:53:58 +00:00
|
|
|
|
2013-08-27 11:19:24 +00:00
|
|
|
/* Since we have the commandline arguments parsed, we need to
|
2015-09-03 14:59:01 +00:00
|
|
|
* reload our initial settings to make debugging and readline
|
|
|
|
* work properly */
|
|
|
|
vshInitReload(ctl);
|
2013-08-27 11:19:24 +00:00
|
|
|
|
2015-06-15 16:53:58 +00:00
|
|
|
if (priv->conn)
|
2013-08-21 09:02:42 +00:00
|
|
|
return false;
|
2007-06-06 12:24:31 +00:00
|
|
|
|
2006-02-27 21:34:28 +00:00
|
|
|
/* set up the library error handler */
|
2015-06-15 16:53:58 +00:00
|
|
|
virSetErrorFunc(NULL, vshErrorHandler);
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2017-04-19 10:42:00 +00:00
|
|
|
if (virEventRegisterDefaultImpl() < 0) {
|
|
|
|
vshReportError(ctl);
|
2011-04-18 22:37:42 +00:00
|
|
|
return false;
|
2017-04-19 10:42:00 +00:00
|
|
|
}
|
2010-07-27 09:40:30 +00:00
|
|
|
|
2017-04-19 10:42:00 +00:00
|
|
|
if (virThreadCreate(&ctl->eventLoop, true, vshEventLoop, ctl) < 0) {
|
|
|
|
vshReportError(ctl);
|
2011-10-11 13:05:52 +00:00
|
|
|
return false;
|
2017-04-19 10:42:00 +00:00
|
|
|
}
|
2011-10-11 13:05:52 +00:00
|
|
|
ctl->eventLoopStarted = true;
|
|
|
|
|
virsh: common code for waiting for an event
I plan to add 'virsh event' to virsh-domain.c and 'virsh
net-event' to virsh-network.c; but as they will share quite
a bit of common boilerplate, it's better to set that up now
in virsh.c.
* tools/virsh.h (_vshControl): Add fields.
(vshEventStart, vshEventWait, vshEventDone, vshEventCleanup): New
prototypes.
* tools/virsh.c (vshEventFd, vshEventOldAction, vshEventInt)
(vshEventTimeout): New helper variables and functions.
(vshEventStart, vshEventWait, vshEventDone, vshEventCleanup):
Implement new functions.
(vshInit, vshDeinit, main): Manage event timeout.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-02-14 22:30:23 +00:00
|
|
|
if ((ctl->eventTimerId = virEventAddTimeout(-1, vshEventTimeout, ctl,
|
2017-04-19 10:42:00 +00:00
|
|
|
NULL)) < 0) {
|
|
|
|
vshReportError(ctl);
|
virsh: common code for waiting for an event
I plan to add 'virsh event' to virsh-domain.c and 'virsh
net-event' to virsh-network.c; but as they will share quite
a bit of common boilerplate, it's better to set that up now
in virsh.c.
* tools/virsh.h (_vshControl): Add fields.
(vshEventStart, vshEventWait, vshEventDone, vshEventCleanup): New
prototypes.
* tools/virsh.c (vshEventFd, vshEventOldAction, vshEventInt)
(vshEventTimeout): New helper variables and functions.
(vshEventStart, vshEventWait, vshEventDone, vshEventCleanup):
Implement new functions.
(vshInit, vshDeinit, main): Manage event timeout.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-02-14 22:30:23 +00:00
|
|
|
return false;
|
2017-04-19 10:42:00 +00:00
|
|
|
}
|
virsh: common code for waiting for an event
I plan to add 'virsh event' to virsh-domain.c and 'virsh
net-event' to virsh-network.c; but as they will share quite
a bit of common boilerplate, it's better to set that up now
in virsh.c.
* tools/virsh.h (_vshControl): Add fields.
(vshEventStart, vshEventWait, vshEventDone, vshEventCleanup): New
prototypes.
* tools/virsh.c (vshEventFd, vshEventOldAction, vshEventInt)
(vshEventTimeout): New helper variables and functions.
(vshEventStart, vshEventWait, vshEventDone, vshEventCleanup):
Implement new functions.
(vshInit, vshDeinit, main): Manage event timeout.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-02-14 22:30:23 +00:00
|
|
|
|
2015-12-10 12:46:45 +00:00
|
|
|
if (ctl->connname) {
|
virsh: optimize creation of default connection
Ramon de Carvalho Valle reported a problem with:
virsh connect qemu:///system
as a non-root user. The real root problem appears to be a regression
in libvirtd being auto-started on the default qemu:///session URI;
however, the symptom points to an independent flaw in virsh - we
shouldn't be wasting efforts on making a connection if we aren't going
to be using that connection. Fixing virsh avoids Ramon's issue, while
I work in the meantime to fix the real libvirtd regression.
This patch looks big, but that's because 'gcc -Wmissing-field-initializers'
gets triggered by './autobuild.sh --enable-compile-warnings=error', so I
had to add 0 initialization to everyone (rather than my preference of
just adding the non-zero flags to virshCmds and to cmdConnect).
Meanwhile, if you use 'virsh -c URI', the connection must succeed; this
patch _only_ optimizes the default connection to be deferred to a later
point where we know if a particular command to be run needs a connection.
* tools/virsh.c (VSH_CMD_FLAG_NOCONNECT): New flag.
(vshCmdDef): Add new flags field.
(vshCommandRun): Honor new flag.
(domManagementCmds, domMonitoringCmds, storagePoolCmds)
(storageVolCmds, networkCmds, nodedevCmds, ifaceCmds)
(nwfilterCmds, secretCmds, virshCmds, snapshotCmds)
(hostAndHypervisorCmds): Populate new field.
(vshReconnect): Don't warn on initial connection.
2011-03-14 20:30:24 +00:00
|
|
|
/* 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).
|
|
|
|
*/
|
2016-07-29 06:09:22 +00:00
|
|
|
if (virshReconnect(ctl, NULL, false, false) < 0) {
|
virsh: use common namespacing
Convert the exported items in virsh.h to use a common 'vsh' prefix.
* tools/virsh.h (VIRSH_MAX_XML_FILE): Rename...
(VSH_MAX_XML_FILE): ...and parenthesize.
(DIFF_MSEC, CTRL_CLOSE_BRACKET): Delete.
(vshUsage, vshInit, vshDeinit, vshParseArgv): Remove prototype.
(editWriteToTempFile, editFile, editReadBackFile, prettyCapacity)
(virshReportError): Rename...
(vshEditWriteToTempFile, vshEditFile, vshEditReadBackFile)
(vshPrettyCapacity, vshReportError): ...into vsh namespace.
(jobWatchTimeoutFunc): Move to virsh-domain.c.
* tools/virsh.c (vshCommandRun): Inline former DIFF_MSEC.
(main): Inline former CTRL_CLOSE_BRACKET.
(vshUsage, vshInit, vshDeinit, vshParseArgv): Make static.
(prettyCapacity, virshReportError, editWriteToTempFile, editFile):
Fix naming, and adjust usage.
(vshAskReedit, vshCommandRun, vshEventLoop, vshInit): Adjust
usage.
* tools/virsh-domain.c (cmdAttachDevice, cmdCPUCompare)
(cmdCPUBaseline, cmdCreate, cmdDefine, cmdDetachDevice)
(cmdUpdateDevice, cmdDesc, cmdUndefine, cmdStart, cmdVcpucount)
(cmdAttachDevice, cmdDomjobinfo): Likewise.
* tools/virsh-edit.c (do): Likewise.
* tools/virsh-interface.c (cmdInterfaceDefine): Likewise.
* tools/virsh-network.c (cmdNetworkCreate, cmdNetworkDefine):
Likewise.
* tools/virsh-nodedev.c (cmdNodeDeviceCreate): Likewise.
* tools/virsh-nwfilter.c (cmdNWFilterDefine): Likewise.
* tools/virsh-pool.c (cmdPoolCreate, cmdPoolDefine)
(cmdPoolDiscoverSources, cmdPoolList): Likewise.
* tools/virsh-secret.c (cmdSecretDefine): Likewise.
* tools/virsh-snapshot.c (cmdSnapshotCreate, vshSnapshotCreate)
(vshLookupSnapshot, cmdSnapshotEdit, cmdSnapshotCurrent)
(vshGetSnapshotParent): Likewise.
* tools/virsh-volume.c (cmdVolCreate, cmdVolCreateFrom)
(cmdVolInfo, cmdVolList): Likewise.
2012-08-19 04:10:17 +00:00
|
|
|
vshReportError(ctl);
|
virsh: optimize creation of default connection
Ramon de Carvalho Valle reported a problem with:
virsh connect qemu:///system
as a non-root user. The real root problem appears to be a regression
in libvirtd being auto-started on the default qemu:///session URI;
however, the symptom points to an independent flaw in virsh - we
shouldn't be wasting efforts on making a connection if we aren't going
to be using that connection. Fixing virsh avoids Ramon's issue, while
I work in the meantime to fix the real libvirtd regression.
This patch looks big, but that's because 'gcc -Wmissing-field-initializers'
gets triggered by './autobuild.sh --enable-compile-warnings=error', so I
had to add 0 initialization to everyone (rather than my preference of
just adding the non-zero flags to virshCmds and to cmdConnect).
Meanwhile, if you use 'virsh -c URI', the connection must succeed; this
patch _only_ optimizes the default connection to be deferred to a later
point where we know if a particular command to be run needs a connection.
* tools/virsh.c (VSH_CMD_FLAG_NOCONNECT): New flag.
(vshCmdDef): Add new flags field.
(vshCommandRun): Honor new flag.
(domManagementCmds, domMonitoringCmds, storagePoolCmds)
(storageVolCmds, networkCmds, nodedevCmds, ifaceCmds)
(nwfilterCmds, secretCmds, virshCmds, snapshotCmds)
(hostAndHypervisorCmds): Populate new field.
(vshReconnect): Don't warn on initial connection.
2011-03-14 20:30:24 +00:00
|
|
|
return false;
|
|
|
|
}
|
2007-12-05 16:24:22 +00:00
|
|
|
}
|
2005-12-08 10:23:34 +00:00
|
|
|
|
2011-04-18 22:37:42 +00:00
|
|
|
return true;
|
2005-12-08 10:23:34 +00:00
|
|
|
}
|
|
|
|
|
2011-11-30 19:42:20 +00:00
|
|
|
static void
|
2019-10-14 12:44:29 +00:00
|
|
|
virshDeinitTimer(int timer G_GNUC_UNUSED, void *opaque G_GNUC_UNUSED)
|
2011-11-30 19:42:20 +00:00
|
|
|
{
|
|
|
|
/* nothing to be done here */
|
|
|
|
}
|
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
/*
|
2008-02-04 14:58:47 +00:00
|
|
|
* Deinitialize virsh
|
2005-12-08 10:23:34 +00:00
|
|
|
*/
|
virsh: use common namespacing
Convert the exported items in virsh.h to use a common 'vsh' prefix.
* tools/virsh.h (VIRSH_MAX_XML_FILE): Rename...
(VSH_MAX_XML_FILE): ...and parenthesize.
(DIFF_MSEC, CTRL_CLOSE_BRACKET): Delete.
(vshUsage, vshInit, vshDeinit, vshParseArgv): Remove prototype.
(editWriteToTempFile, editFile, editReadBackFile, prettyCapacity)
(virshReportError): Rename...
(vshEditWriteToTempFile, vshEditFile, vshEditReadBackFile)
(vshPrettyCapacity, vshReportError): ...into vsh namespace.
(jobWatchTimeoutFunc): Move to virsh-domain.c.
* tools/virsh.c (vshCommandRun): Inline former DIFF_MSEC.
(main): Inline former CTRL_CLOSE_BRACKET.
(vshUsage, vshInit, vshDeinit, vshParseArgv): Make static.
(prettyCapacity, virshReportError, editWriteToTempFile, editFile):
Fix naming, and adjust usage.
(vshAskReedit, vshCommandRun, vshEventLoop, vshInit): Adjust
usage.
* tools/virsh-domain.c (cmdAttachDevice, cmdCPUCompare)
(cmdCPUBaseline, cmdCreate, cmdDefine, cmdDetachDevice)
(cmdUpdateDevice, cmdDesc, cmdUndefine, cmdStart, cmdVcpucount)
(cmdAttachDevice, cmdDomjobinfo): Likewise.
* tools/virsh-edit.c (do): Likewise.
* tools/virsh-interface.c (cmdInterfaceDefine): Likewise.
* tools/virsh-network.c (cmdNetworkCreate, cmdNetworkDefine):
Likewise.
* tools/virsh-nodedev.c (cmdNodeDeviceCreate): Likewise.
* tools/virsh-nwfilter.c (cmdNWFilterDefine): Likewise.
* tools/virsh-pool.c (cmdPoolCreate, cmdPoolDefine)
(cmdPoolDiscoverSources, cmdPoolList): Likewise.
* tools/virsh-secret.c (cmdSecretDefine): Likewise.
* tools/virsh-snapshot.c (cmdSnapshotCreate, vshSnapshotCreate)
(vshLookupSnapshot, cmdSnapshotEdit, cmdSnapshotCurrent)
(vshGetSnapshotParent): Likewise.
* tools/virsh-volume.c (cmdVolCreate, cmdVolCreateFrom)
(cmdVolInfo, cmdVolList): Likewise.
2012-08-19 04:10:17 +00:00
|
|
|
static bool
|
2015-06-15 16:53:58 +00:00
|
|
|
virshDeinit(vshControl *ctl)
|
2006-03-15 12:13:25 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virshControl *priv = ctl->privData;
|
2015-06-15 16:53:58 +00:00
|
|
|
|
|
|
|
vshDeinit(ctl);
|
2015-12-10 12:46:45 +00:00
|
|
|
VIR_FREE(ctl->connname);
|
2015-06-15 16:53:58 +00:00
|
|
|
if (priv->conn) {
|
2010-11-11 15:15:46 +00:00
|
|
|
int ret;
|
2015-06-15 16:53:58 +00:00
|
|
|
virConnectUnregisterCloseCallback(priv->conn, virshCatchDisconnect);
|
|
|
|
ret = virConnectClose(priv->conn);
|
2013-03-26 09:54:55 +00:00
|
|
|
if (ret < 0)
|
|
|
|
vshError(ctl, "%s", _("Failed to disconnect from the hypervisor"));
|
|
|
|
else if (ret > 0)
|
2023-08-24 15:04:34 +00:00
|
|
|
vshError(ctl, "%s", _("One or more references were leaked after disconnect from the hypervisor"));
|
2005-12-08 10:23:34 +00:00
|
|
|
}
|
2007-12-01 15:45:25 +00:00
|
|
|
virResetLastError();
|
|
|
|
|
2011-10-11 13:05:52 +00:00
|
|
|
if (ctl->eventLoopStarted) {
|
2022-02-08 13:59:30 +00:00
|
|
|
int timer = -1;
|
2011-11-30 19:42:20 +00:00
|
|
|
|
2022-02-08 13:59:30 +00:00
|
|
|
VIR_WITH_MUTEX_LOCK_GUARD(&ctl->lock) {
|
|
|
|
ctl->quit = true;
|
|
|
|
/* HACK: Add a dummy timeout to break event loop */
|
|
|
|
timer = virEventAddTimeout(0, virshDeinitTimer, NULL, NULL);
|
|
|
|
}
|
2011-11-30 19:42:20 +00:00
|
|
|
|
|
|
|
virThreadJoin(&ctl->eventLoop);
|
|
|
|
|
2011-10-11 13:05:52 +00:00
|
|
|
if (timer != -1)
|
|
|
|
virEventRemoveTimeout(timer);
|
|
|
|
|
virsh: common code for waiting for an event
I plan to add 'virsh event' to virsh-domain.c and 'virsh
net-event' to virsh-network.c; but as they will share quite
a bit of common boilerplate, it's better to set that up now
in virsh.c.
* tools/virsh.h (_vshControl): Add fields.
(vshEventStart, vshEventWait, vshEventDone, vshEventCleanup): New
prototypes.
* tools/virsh.c (vshEventFd, vshEventOldAction, vshEventInt)
(vshEventTimeout): New helper variables and functions.
(vshEventStart, vshEventWait, vshEventDone, vshEventCleanup):
Implement new functions.
(vshInit, vshDeinit, main): Manage event timeout.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-02-14 22:30:23 +00:00
|
|
|
if (ctl->eventTimerId != -1)
|
|
|
|
virEventRemoveTimeout(ctl->eventTimerId);
|
|
|
|
|
2011-10-11 13:05:52 +00:00
|
|
|
ctl->eventLoopStarted = false;
|
|
|
|
}
|
|
|
|
|
2011-11-30 19:42:20 +00:00
|
|
|
virMutexDestroy(&ctl->lock);
|
|
|
|
|
2011-04-18 22:37:42 +00:00
|
|
|
return true;
|
2005-12-08 10:23:34 +00:00
|
|
|
}
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
/*
|
|
|
|
* Print usage
|
|
|
|
*/
|
virsh: use common namespacing
Convert the exported items in virsh.h to use a common 'vsh' prefix.
* tools/virsh.h (VIRSH_MAX_XML_FILE): Rename...
(VSH_MAX_XML_FILE): ...and parenthesize.
(DIFF_MSEC, CTRL_CLOSE_BRACKET): Delete.
(vshUsage, vshInit, vshDeinit, vshParseArgv): Remove prototype.
(editWriteToTempFile, editFile, editReadBackFile, prettyCapacity)
(virshReportError): Rename...
(vshEditWriteToTempFile, vshEditFile, vshEditReadBackFile)
(vshPrettyCapacity, vshReportError): ...into vsh namespace.
(jobWatchTimeoutFunc): Move to virsh-domain.c.
* tools/virsh.c (vshCommandRun): Inline former DIFF_MSEC.
(main): Inline former CTRL_CLOSE_BRACKET.
(vshUsage, vshInit, vshDeinit, vshParseArgv): Make static.
(prettyCapacity, virshReportError, editWriteToTempFile, editFile):
Fix naming, and adjust usage.
(vshAskReedit, vshCommandRun, vshEventLoop, vshInit): Adjust
usage.
* tools/virsh-domain.c (cmdAttachDevice, cmdCPUCompare)
(cmdCPUBaseline, cmdCreate, cmdDefine, cmdDetachDevice)
(cmdUpdateDevice, cmdDesc, cmdUndefine, cmdStart, cmdVcpucount)
(cmdAttachDevice, cmdDomjobinfo): Likewise.
* tools/virsh-edit.c (do): Likewise.
* tools/virsh-interface.c (cmdInterfaceDefine): Likewise.
* tools/virsh-network.c (cmdNetworkCreate, cmdNetworkDefine):
Likewise.
* tools/virsh-nodedev.c (cmdNodeDeviceCreate): Likewise.
* tools/virsh-nwfilter.c (cmdNWFilterDefine): Likewise.
* tools/virsh-pool.c (cmdPoolCreate, cmdPoolDefine)
(cmdPoolDiscoverSources, cmdPoolList): Likewise.
* tools/virsh-secret.c (cmdSecretDefine): Likewise.
* tools/virsh-snapshot.c (cmdSnapshotCreate, vshSnapshotCreate)
(vshLookupSnapshot, cmdSnapshotEdit, cmdSnapshotCurrent)
(vshGetSnapshotParent): Likewise.
* tools/virsh-volume.c (cmdVolCreate, cmdVolCreateFrom)
(cmdVolInfo, cmdVolList): Likewise.
2012-08-19 04:10:17 +00:00
|
|
|
static void
|
2015-06-15 16:53:58 +00:00
|
|
|
virshUsage(void)
|
2006-03-15 12:13:25 +00:00
|
|
|
{
|
2010-11-30 06:37:04 +00:00
|
|
|
const vshCmdGrp *grp;
|
2008-08-01 12:19:56 +00:00
|
|
|
const vshCmdDef *cmd;
|
2010-11-30 06:37:04 +00:00
|
|
|
|
2023-08-28 11:07:34 +00:00
|
|
|
fprintf(stdout, _("\n"
|
|
|
|
"%1$s [options]... [<command_string>]\n"
|
|
|
|
"%2$s [options]... <command> [args...]\n"
|
|
|
|
"\n"
|
2008-12-08 13:14:48 +00:00
|
|
|
" options:\n"
|
2011-11-22 16:08:05 +00:00
|
|
|
" -c | --connect=URI hypervisor connection URI\n"
|
|
|
|
" -d | --debug=NUM debug level [0-4]\n"
|
2014-03-06 15:53:53 +00:00
|
|
|
" -e | --escape <char> set escape sequence for console\n"
|
2008-12-08 13:14:48 +00:00
|
|
|
" -h | --help this help\n"
|
2014-03-06 16:20:11 +00:00
|
|
|
" -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"
|
2014-03-06 15:53:53 +00:00
|
|
|
" -l | --log=FILE output logging to file\n"
|
2008-12-08 13:14:48 +00:00
|
|
|
" -q | --quiet quiet mode\n"
|
2014-03-06 15:53:53 +00:00
|
|
|
" -r | --readonly connect readonly\n"
|
2008-12-08 13:14:48 +00:00
|
|
|
" -t | --timing print timing information\n"
|
2011-11-22 16:08:05 +00:00
|
|
|
" -v short version\n"
|
|
|
|
" -V long version\n"
|
|
|
|
" --version[=TYPE] version, TYPE is short or long (default short)\n"
|
2015-06-15 16:53:58 +00:00
|
|
|
" commands (non interactive mode):\n\n"), progname,
|
|
|
|
progname);
|
2008-12-08 13:14:48 +00:00
|
|
|
|
2010-11-30 06:37:04 +00:00
|
|
|
for (grp = cmdGroups; grp->name; grp++) {
|
2023-03-09 14:54:58 +00:00
|
|
|
fprintf(stdout, _(" %1$s (help keyword '%2$s')\n"),
|
2012-03-16 19:23:00 +00:00
|
|
|
grp->name, grp->keyword);
|
|
|
|
for (cmd = grp->commands; cmd->name; cmd++) {
|
2024-03-01 22:14:51 +00:00
|
|
|
if (cmd->alias ||
|
2021-09-16 13:57:28 +00:00
|
|
|
cmd->flags & VSH_CMD_FLAG_HIDDEN)
|
2012-03-16 19:23:00 +00:00
|
|
|
continue;
|
2010-11-30 06:37:04 +00:00
|
|
|
fprintf(stdout,
|
2024-03-04 12:21:50 +00:00
|
|
|
" %-30s %s\n", cmd->name, _(cmd->info->help));
|
2012-03-16 19:23:00 +00:00
|
|
|
}
|
2010-11-30 06:37:04 +00:00
|
|
|
fprintf(stdout, "\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
fprintf(stdout, "%s",
|
|
|
|
_("\n (specify help <group> for details about the commands in the group)\n"));
|
2008-12-08 13:14:48 +00:00
|
|
|
fprintf(stdout, "%s",
|
|
|
|
_("\n (specify help <command> for details about the command)\n\n"));
|
|
|
|
return;
|
2005-12-08 10:23:34 +00:00
|
|
|
}
|
|
|
|
|
2010-11-08 14:03:32 +00:00
|
|
|
/*
|
|
|
|
* Show version and options compiled in
|
|
|
|
*/
|
|
|
|
static void
|
2019-10-14 12:44:29 +00:00
|
|
|
virshShowVersion(vshControl *ctl G_GNUC_UNUSED)
|
2010-11-08 14:03:32 +00:00
|
|
|
{
|
|
|
|
/* FIXME - list a copyright blurb, as in GNU programs? */
|
2023-03-09 14:54:58 +00:00
|
|
|
vshPrint(ctl, _("Virsh command line tool of libvirt %1$s\n"), VERSION);
|
|
|
|
vshPrint(ctl, _("See web site at %1$s\n\n"), "https://libvirt.org/");
|
2010-11-08 14:03:32 +00:00
|
|
|
|
2010-11-09 22:37:05 +00:00
|
|
|
vshPrint(ctl, "%s", _("Compiled with support for:\n"));
|
|
|
|
vshPrint(ctl, "%s", _(" Hypervisors:"));
|
2010-11-08 14:03:32 +00:00
|
|
|
#ifdef WITH_QEMU
|
2012-09-09 22:07:28 +00:00
|
|
|
vshPrint(ctl, " QEMU/KVM");
|
2010-11-08 14:03:32 +00:00
|
|
|
#endif
|
2012-06-26 18:31:31 +00:00
|
|
|
#ifdef WITH_LXC
|
|
|
|
vshPrint(ctl, " LXC");
|
|
|
|
#endif
|
|
|
|
#ifdef WITH_LIBXL
|
|
|
|
vshPrint(ctl, " LibXL");
|
|
|
|
#endif
|
2010-11-08 14:03:32 +00:00
|
|
|
#ifdef WITH_OPENVZ
|
|
|
|
vshPrint(ctl, " OpenVZ");
|
|
|
|
#endif
|
2021-05-12 17:01:31 +00:00
|
|
|
#ifdef WITH_CH
|
|
|
|
vshPrint(ctl, " Cloud-Hypervisor");
|
|
|
|
#endif
|
2016-03-28 13:20:40 +00:00
|
|
|
#ifdef WITH_VZ
|
|
|
|
vshPrint(ctl, " Virtuozzo");
|
|
|
|
#endif
|
2012-06-26 18:31:31 +00:00
|
|
|
#ifdef WITH_VMWARE
|
2016-02-15 14:34:24 +00:00
|
|
|
vshPrint(ctl, " VMware");
|
2010-11-08 14:03:32 +00:00
|
|
|
#endif
|
2012-06-26 18:31:31 +00:00
|
|
|
#ifdef WITH_VBOX
|
|
|
|
vshPrint(ctl, " VirtualBox");
|
2010-11-08 14:03:32 +00:00
|
|
|
#endif
|
|
|
|
#ifdef WITH_ESX
|
|
|
|
vshPrint(ctl, " ESX");
|
|
|
|
#endif
|
2012-06-26 18:31:31 +00:00
|
|
|
#ifdef WITH_HYPERV
|
|
|
|
vshPrint(ctl, " Hyper-V");
|
2010-11-08 14:03:32 +00:00
|
|
|
#endif
|
2014-06-10 18:25:10 +00:00
|
|
|
#ifdef WITH_BHYVE
|
|
|
|
vshPrint(ctl, " Bhyve");
|
|
|
|
#endif
|
2010-11-08 14:03:32 +00:00
|
|
|
#ifdef WITH_TEST
|
|
|
|
vshPrint(ctl, " Test");
|
|
|
|
#endif
|
|
|
|
vshPrint(ctl, "\n");
|
|
|
|
|
2010-11-09 22:37:05 +00:00
|
|
|
vshPrint(ctl, "%s", _(" Networking:"));
|
2010-11-08 14:03:32 +00:00
|
|
|
#ifdef WITH_REMOTE
|
|
|
|
vshPrint(ctl, " Remote");
|
|
|
|
#endif
|
|
|
|
#ifdef WITH_NETWORK
|
|
|
|
vshPrint(ctl, " Network");
|
|
|
|
#endif
|
|
|
|
#ifdef WITH_BRIDGE
|
|
|
|
vshPrint(ctl, " Bridging");
|
|
|
|
#endif
|
2012-09-18 01:27:06 +00:00
|
|
|
#if defined(WITH_INTERFACE)
|
2012-06-26 18:31:31 +00:00
|
|
|
vshPrint(ctl, " Interface");
|
2012-09-18 01:27:06 +00:00
|
|
|
# if defined(WITH_NETCF)
|
|
|
|
vshPrint(ctl, " netcf");
|
2012-09-20 14:24:47 +00:00
|
|
|
# elif defined(WITH_UDEV)
|
2012-10-06 19:20:25 +00:00
|
|
|
vshPrint(ctl, " udev");
|
2012-09-18 01:27:06 +00:00
|
|
|
# endif
|
2010-11-08 14:03:32 +00:00
|
|
|
#endif
|
|
|
|
#ifdef WITH_NWFILTER
|
|
|
|
vshPrint(ctl, " Nwfilter");
|
|
|
|
#endif
|
|
|
|
vshPrint(ctl, "\n");
|
|
|
|
|
2010-11-09 22:37:05 +00:00
|
|
|
vshPrint(ctl, "%s", _(" Storage:"));
|
2010-11-08 14:03:32 +00:00
|
|
|
#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
|
2022-11-24 07:52:25 +00:00
|
|
|
#ifdef WITH_STORAGE_ISCSI_DIRECT
|
|
|
|
vshPrint(ctl, " iSCSI-direct");
|
|
|
|
#endif
|
2010-11-08 14:03:32 +00:00
|
|
|
#ifdef WITH_STORAGE_LVM
|
|
|
|
vshPrint(ctl, " LVM");
|
2012-05-14 09:06:42 +00:00
|
|
|
#endif
|
|
|
|
#ifdef WITH_STORAGE_RBD
|
|
|
|
vshPrint(ctl, " RBD");
|
2012-07-18 19:06:58 +00:00
|
|
|
#endif
|
2013-12-12 03:08:10 +00:00
|
|
|
#ifdef WITH_STORAGE_GLUSTER
|
|
|
|
vshPrint(ctl, " Gluster");
|
2016-01-03 02:25:35 +00:00
|
|
|
#endif
|
|
|
|
#ifdef WITH_STORAGE_ZFS
|
|
|
|
vshPrint(ctl, " ZFS");
|
2017-01-17 14:10:55 +00:00
|
|
|
#endif
|
|
|
|
#ifdef WITH_STORAGE_VSTORAGE
|
2022-11-24 07:50:41 +00:00
|
|
|
vshPrint(ctl, " Virtuozzo Storage");
|
2010-11-08 14:03:32 +00:00
|
|
|
#endif
|
|
|
|
vshPrint(ctl, "\n");
|
|
|
|
|
2012-07-23 03:57:53 +00:00
|
|
|
vshPrint(ctl, "%s", _(" Miscellaneous:"));
|
2012-09-09 22:07:27 +00:00
|
|
|
#ifdef WITH_LIBVIRTD
|
|
|
|
vshPrint(ctl, " Daemon");
|
|
|
|
#endif
|
2012-07-23 03:57:53 +00:00
|
|
|
#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
|
|
|
|
vshPrint(ctl, " Debug");
|
|
|
|
#ifdef WITH_DTRACE_PROBES
|
|
|
|
vshPrint(ctl, " DTrace");
|
|
|
|
#endif
|
2013-10-04 17:51:41 +00:00
|
|
|
#if WITH_READLINE
|
2012-07-23 03:57:53 +00:00
|
|
|
vshPrint(ctl, " Readline");
|
|
|
|
#endif
|
|
|
|
vshPrint(ctl, "\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool
|
2015-06-15 16:53:58 +00:00
|
|
|
virshAllowedEscapeChar(char c)
|
2012-07-23 03:57:53 +00:00
|
|
|
{
|
|
|
|
/* Allowed escape characters:
|
|
|
|
* a-z A-Z @ [ \ ] ^ _
|
|
|
|
*/
|
|
|
|
return ('a' <= c && c <= 'z') ||
|
|
|
|
('@' <= c && c <= '_');
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* argv[]: virsh [options] [command]
|
|
|
|
*
|
|
|
|
*/
|
virsh: use common namespacing
Convert the exported items in virsh.h to use a common 'vsh' prefix.
* tools/virsh.h (VIRSH_MAX_XML_FILE): Rename...
(VSH_MAX_XML_FILE): ...and parenthesize.
(DIFF_MSEC, CTRL_CLOSE_BRACKET): Delete.
(vshUsage, vshInit, vshDeinit, vshParseArgv): Remove prototype.
(editWriteToTempFile, editFile, editReadBackFile, prettyCapacity)
(virshReportError): Rename...
(vshEditWriteToTempFile, vshEditFile, vshEditReadBackFile)
(vshPrettyCapacity, vshReportError): ...into vsh namespace.
(jobWatchTimeoutFunc): Move to virsh-domain.c.
* tools/virsh.c (vshCommandRun): Inline former DIFF_MSEC.
(main): Inline former CTRL_CLOSE_BRACKET.
(vshUsage, vshInit, vshDeinit, vshParseArgv): Make static.
(prettyCapacity, virshReportError, editWriteToTempFile, editFile):
Fix naming, and adjust usage.
(vshAskReedit, vshCommandRun, vshEventLoop, vshInit): Adjust
usage.
* tools/virsh-domain.c (cmdAttachDevice, cmdCPUCompare)
(cmdCPUBaseline, cmdCreate, cmdDefine, cmdDetachDevice)
(cmdUpdateDevice, cmdDesc, cmdUndefine, cmdStart, cmdVcpucount)
(cmdAttachDevice, cmdDomjobinfo): Likewise.
* tools/virsh-edit.c (do): Likewise.
* tools/virsh-interface.c (cmdInterfaceDefine): Likewise.
* tools/virsh-network.c (cmdNetworkCreate, cmdNetworkDefine):
Likewise.
* tools/virsh-nodedev.c (cmdNodeDeviceCreate): Likewise.
* tools/virsh-nwfilter.c (cmdNWFilterDefine): Likewise.
* tools/virsh-pool.c (cmdPoolCreate, cmdPoolDefine)
(cmdPoolDiscoverSources, cmdPoolList): Likewise.
* tools/virsh-secret.c (cmdSecretDefine): Likewise.
* tools/virsh-snapshot.c (cmdSnapshotCreate, vshSnapshotCreate)
(vshLookupSnapshot, cmdSnapshotEdit, cmdSnapshotCurrent)
(vshGetSnapshotParent): Likewise.
* tools/virsh-volume.c (cmdVolCreate, cmdVolCreateFrom)
(cmdVolInfo, cmdVolList): Likewise.
2012-08-19 04:10:17 +00:00
|
|
|
static bool
|
2015-06-15 16:53:58 +00:00
|
|
|
virshParseArgv(vshControl *ctl, int argc, char **argv)
|
2012-07-23 03:57:53 +00:00
|
|
|
{
|
2014-03-06 16:20:11 +00:00
|
|
|
int arg, len, debug, keepalive;
|
Convert 'int i' to 'size_t i' in tools/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
size_t i;
|
2013-04-29 17:12:17 +00:00
|
|
|
int longindex = -1;
|
2021-03-11 07:16:13 +00:00
|
|
|
virshControl *priv = ctl->privData;
|
2012-07-23 03:57:53 +00:00
|
|
|
struct option opt[] = {
|
2022-11-22 01:50:01 +00:00
|
|
|
{ "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 },
|
2012-07-23 03:57:53 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/* 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. */
|
2014-03-06 16:20:11 +00:00
|
|
|
while ((arg = getopt_long(argc, argv, "+:c:d:e:hk:K:l:qrtvV", opt, &longindex)) != -1) {
|
2012-07-23 03:57:53 +00:00
|
|
|
switch (arg) {
|
2014-03-06 15:53:53 +00:00
|
|
|
case 'c':
|
2015-12-10 12:46:45 +00:00
|
|
|
VIR_FREE(ctl->connname);
|
2019-10-18 15:24:02 +00:00
|
|
|
ctl->connname = g_strdup(optarg);
|
2014-03-06 15:53:53 +00:00
|
|
|
break;
|
2012-07-23 03:57:53 +00:00
|
|
|
case 'd':
|
2012-07-26 14:05:51 +00:00
|
|
|
if (virStrToLong_i(optarg, NULL, 10, &debug) < 0) {
|
2023-03-09 14:54:58 +00:00
|
|
|
vshError(ctl, _("option %1$s takes a numeric argument"),
|
2013-04-29 17:12:17 +00:00
|
|
|
longindex == -1 ? "-d" : "--debug");
|
2012-07-23 03:57:53 +00:00
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
2012-07-26 14:05:51 +00:00
|
|
|
if (debug < VSH_ERR_DEBUG || debug > VSH_ERR_ERROR)
|
2023-03-09 14:54:58 +00:00
|
|
|
vshError(ctl, _("ignoring debug level %1$d out of range [%2$d-%3$d]"),
|
2012-07-26 14:05:51 +00:00
|
|
|
debug, VSH_ERR_DEBUG, VSH_ERR_ERROR);
|
|
|
|
else
|
|
|
|
ctl->debug = debug;
|
2012-07-23 03:57:53 +00:00
|
|
|
break;
|
2014-03-06 15:53:53 +00:00
|
|
|
case 'e':
|
|
|
|
len = strlen(optarg);
|
|
|
|
|
|
|
|
if ((len == 2 && *optarg == '^' &&
|
2015-06-15 16:53:58 +00:00
|
|
|
virshAllowedEscapeChar(optarg[1])) ||
|
2014-03-06 15:53:53 +00:00
|
|
|
(len == 1 && *optarg != '^')) {
|
2015-06-15 16:53:58 +00:00
|
|
|
priv->escapeChar = optarg;
|
2014-03-06 15:53:53 +00:00
|
|
|
} else {
|
2023-03-09 14:54:58 +00:00
|
|
|
vshError(ctl, _("Invalid string '%1$s' for escape sequence"),
|
2014-03-06 15:53:53 +00:00
|
|
|
optarg);
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
break;
|
2012-07-23 03:57:53 +00:00
|
|
|
case 'h':
|
2015-06-15 16:53:58 +00:00
|
|
|
virshUsage();
|
2012-07-23 03:57:53 +00:00
|
|
|
exit(EXIT_SUCCESS);
|
|
|
|
break;
|
2014-03-06 16:20:11 +00:00
|
|
|
case 'k':
|
2014-08-27 14:20:29 +00:00
|
|
|
if (virStrToLong_i(optarg, NULL, 0, &keepalive) < 0) {
|
|
|
|
vshError(ctl,
|
2023-03-09 14:54:58 +00:00
|
|
|
_("Invalid value for option %1$s"),
|
2014-08-27 14:20:29 +00:00
|
|
|
longindex == -1 ? "-k" : "--keepalive-interval");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (keepalive < 0) {
|
|
|
|
vshError(ctl,
|
2023-03-09 14:54:58 +00:00
|
|
|
_("option %1$s requires a positive integer argument"),
|
2014-03-06 16:20:11 +00:00
|
|
|
longindex == -1 ? "-k" : "--keepalive-interval");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
ctl->keepalive_interval = keepalive;
|
|
|
|
break;
|
|
|
|
case 'K':
|
2014-08-27 14:20:29 +00:00
|
|
|
if (virStrToLong_i(optarg, NULL, 0, &keepalive) < 0) {
|
|
|
|
vshError(ctl,
|
2023-03-09 14:54:58 +00:00
|
|
|
_("Invalid value for option %1$s"),
|
2014-08-27 14:20:29 +00:00
|
|
|
longindex == -1 ? "-K" : "--keepalive-count");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (keepalive < 0) {
|
|
|
|
vshError(ctl,
|
2023-03-09 14:54:58 +00:00
|
|
|
_("option %1$s requires a positive integer argument"),
|
2014-03-06 16:20:11 +00:00
|
|
|
longindex == -1 ? "-K" : "--keepalive-count");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
ctl->keepalive_count = keepalive;
|
|
|
|
break;
|
2014-03-06 15:53:53 +00:00
|
|
|
case 'l':
|
|
|
|
vshCloseLogFile(ctl);
|
2019-10-18 15:24:02 +00:00
|
|
|
ctl->logfile = g_strdup(optarg);
|
2014-03-06 15:53:53 +00:00
|
|
|
vshOpenLogFile(ctl);
|
|
|
|
break;
|
2012-07-23 03:57:53 +00:00
|
|
|
case 'q':
|
|
|
|
ctl->quiet = true;
|
|
|
|
break;
|
|
|
|
case 't':
|
|
|
|
ctl->timing = true;
|
|
|
|
break;
|
2014-03-06 15:53:53 +00:00
|
|
|
case 'r':
|
2015-06-15 16:53:58 +00:00
|
|
|
priv->readonly = true;
|
2012-07-23 03:57:53 +00:00
|
|
|
break;
|
|
|
|
case 'v':
|
|
|
|
if (STRNEQ_NULLABLE(optarg, "long")) {
|
|
|
|
puts(VERSION);
|
|
|
|
exit(EXIT_SUCCESS);
|
|
|
|
}
|
2019-10-15 11:38:21 +00:00
|
|
|
G_GNUC_FALLTHROUGH;
|
2012-07-23 03:57:53 +00:00
|
|
|
case 'V':
|
2015-06-15 16:53:58 +00:00
|
|
|
virshShowVersion(ctl);
|
2012-07-23 03:57:53 +00:00
|
|
|
exit(EXIT_SUCCESS);
|
2013-02-19 08:50:59 +00:00
|
|
|
case ':':
|
2013-04-29 17:12:17 +00:00
|
|
|
for (i = 0; opt[i].name != NULL; i++) {
|
2013-05-01 15:07:56 +00:00
|
|
|
if (opt[i].val == optopt)
|
|
|
|
break;
|
2013-04-29 17:12:17 +00:00
|
|
|
}
|
2013-05-01 15:07:56 +00:00
|
|
|
if (opt[i].name)
|
2023-03-09 14:54:58 +00:00
|
|
|
vshError(ctl, _("option '-%1$c'/'--%2$s' requires an argument"),
|
2013-05-01 15:07:56 +00:00
|
|
|
optopt, opt[i].name);
|
|
|
|
else
|
2023-03-09 14:54:58 +00:00
|
|
|
vshError(ctl, _("option '-%1$c' requires an argument"), optopt);
|
2013-05-01 15:07:56 +00:00
|
|
|
exit(EXIT_FAILURE);
|
2013-02-19 08:50:59 +00:00
|
|
|
case '?':
|
2013-04-29 17:12:17 +00:00
|
|
|
if (optopt)
|
2023-03-09 14:54:58 +00:00
|
|
|
vshError(ctl, _("unsupported option '-%1$c'. See --help."), optopt);
|
2013-04-29 17:12:17 +00:00
|
|
|
else
|
2023-03-09 14:54:58 +00:00
|
|
|
vshError(ctl, _("unsupported option '%1$s'. See --help."), argv[optind - 1]);
|
2013-02-19 08:50:59 +00:00
|
|
|
exit(EXIT_FAILURE);
|
2012-07-23 03:57:53 +00:00
|
|
|
default:
|
2013-02-19 08:50:59 +00:00
|
|
|
vshError(ctl, _("unknown option"));
|
2012-07-23 03:57:53 +00:00
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
2013-04-29 17:12:17 +00:00
|
|
|
longindex = -1;
|
2012-07-23 03:57:53 +00:00
|
|
|
}
|
|
|
|
|
2015-09-04 09:19:55 +00:00
|
|
|
if (argc == optind) {
|
|
|
|
ctl->imode = true;
|
|
|
|
} else {
|
2012-07-23 03:57:53 +00:00
|
|
|
/* parse command */
|
|
|
|
ctl->imode = false;
|
|
|
|
if (argc - optind == 1) {
|
|
|
|
vshDebug(ctl, VSH_ERR_INFO, "commands: \"%s\"\n", argv[optind]);
|
2021-01-26 08:51:27 +00:00
|
|
|
return vshCommandStringParse(ctl, argv[optind], NULL, 0);
|
2012-07-23 03:57:53 +00:00
|
|
|
} else {
|
|
|
|
return vshCommandArgvParse(ctl, argc - optind, argv + optind);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const vshCmdDef virshCmds[] = {
|
2015-06-15 16:53:58 +00:00
|
|
|
VSH_CMD_CD,
|
|
|
|
VSH_CMD_ECHO,
|
|
|
|
VSH_CMD_EXIT,
|
|
|
|
VSH_CMD_HELP,
|
|
|
|
VSH_CMD_PWD,
|
|
|
|
VSH_CMD_QUIT,
|
2016-09-14 07:50:22 +00:00
|
|
|
VSH_CMD_SELF_TEST,
|
2017-11-01 14:34:14 +00:00
|
|
|
VSH_CMD_COMPLETE,
|
2013-03-27 13:22:47 +00:00
|
|
|
{.name = "connect",
|
|
|
|
.handler = cmdConnect,
|
|
|
|
.opts = opts_connect,
|
2024-03-04 12:21:50 +00:00
|
|
|
.info = &info_connect,
|
2013-03-27 13:22:47 +00:00
|
|
|
.flags = VSH_CMD_FLAG_NOCONNECT
|
2013-02-07 15:25:10 +00:00
|
|
|
},
|
|
|
|
{.name = NULL}
|
2012-07-23 03:57:53 +00:00
|
|
|
};
|
2011-11-22 16:08:05 +00:00
|
|
|
|
2012-07-23 03:57:53 +00:00
|
|
|
static const vshCmdGrp cmdGroups[] = {
|
2015-06-15 16:53:58 +00:00
|
|
|
{VIRSH_CMD_GRP_DOM_MANAGEMENT, "domain", domManagementCmds},
|
|
|
|
{VIRSH_CMD_GRP_DOM_MONITORING, "monitor", domMonitoringCmds},
|
2022-02-21 13:02:19 +00:00
|
|
|
{VIRSH_CMD_GRP_DOM_EVENTS, "events", domEventCmds},
|
2015-06-15 16:53:58 +00:00
|
|
|
{VIRSH_CMD_GRP_HOST_AND_HV, "host", hostAndHypervisorCmds},
|
2019-03-13 21:04:51 +00:00
|
|
|
{VIRSH_CMD_GRP_CHECKPOINT, "checkpoint", checkpointCmds},
|
2015-06-15 16:53:58 +00:00
|
|
|
{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},
|
2019-08-22 01:42:45 +00:00
|
|
|
{VIRSH_CMD_GRP_BACKUP, "backup", backupCmds},
|
2015-06-15 16:53:58 +00:00
|
|
|
{VIRSH_CMD_GRP_STORAGE_POOL, "pool", storagePoolCmds},
|
|
|
|
{VIRSH_CMD_GRP_STORAGE_VOL, "volume", storageVolCmds},
|
|
|
|
{VIRSH_CMD_GRP_VIRSH, "virsh", virshCmds},
|
2012-07-23 03:57:53 +00:00
|
|
|
{NULL, NULL, NULL}
|
|
|
|
};
|
2005-12-08 10:23:34 +00:00
|
|
|
|
2015-06-15 16:53:58 +00:00
|
|
|
static const vshClientHooks hooks = {
|
|
|
|
.connHandler = virshConnectionHandler
|
|
|
|
};
|
|
|
|
|
2006-03-15 12:13:25 +00:00
|
|
|
int
|
|
|
|
main(int argc, char **argv)
|
|
|
|
{
|
2023-08-02 12:57:44 +00:00
|
|
|
vshControl _ctl = { 0 };
|
|
|
|
vshControl *ctl = &_ctl;
|
|
|
|
virshControl virshCtl = { 0 };
|
2011-04-18 22:37:42 +00:00
|
|
|
bool ret = true;
|
2005-12-08 10:23:34 +00:00
|
|
|
|
2015-06-15 16:53:58 +00:00
|
|
|
ctl->name = "virsh"; /* hardcoded name of the binary */
|
2016-07-28 10:54:16 +00:00
|
|
|
ctl->env_prefix = "VIRSH";
|
2011-05-09 11:57:09 +00:00
|
|
|
ctl->log_fd = -1; /* Initialize log file descriptor */
|
2011-07-14 11:58:02 +00:00
|
|
|
ctl->debug = VSH_DEBUG_DEFAULT;
|
2015-06-15 16:53:58 +00:00
|
|
|
ctl->hooks = &hooks;
|
2014-03-06 16:20:11 +00:00
|
|
|
|
|
|
|
/* In order to distinguish default from setting to 0 */
|
|
|
|
ctl->keepalive_interval = -1;
|
|
|
|
ctl->keepalive_count = -1;
|
|
|
|
|
virsh: common code for waiting for an event
I plan to add 'virsh event' to virsh-domain.c and 'virsh
net-event' to virsh-network.c; but as they will share quite
a bit of common boilerplate, it's better to set that up now
in virsh.c.
* tools/virsh.h (_vshControl): Add fields.
(vshEventStart, vshEventWait, vshEventDone, vshEventCleanup): New
prototypes.
* tools/virsh.c (vshEventFd, vshEventOldAction, vshEventInt)
(vshEventTimeout): New helper variables and functions.
(vshEventStart, vshEventWait, vshEventDone, vshEventCleanup):
Implement new functions.
(vshInit, vshDeinit, main): Manage event timeout.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-02-14 22:30:23 +00:00
|
|
|
ctl->eventPipe[0] = -1;
|
|
|
|
ctl->eventPipe[1] = -1;
|
|
|
|
ctl->eventTimerId = -1;
|
2015-06-15 16:53:58 +00:00
|
|
|
virshCtl.escapeChar = "^]"; /* Same default as telnet */
|
|
|
|
ctl->privData = &virshCtl;
|
|
|
|
|
|
|
|
if (!(progname = strrchr(argv[0], '/')))
|
|
|
|
progname = argv[0];
|
|
|
|
else
|
|
|
|
progname++;
|
|
|
|
ctl->progname = progname;
|
2011-05-09 11:57:09 +00:00
|
|
|
|
2016-04-12 22:29:52 +00:00
|
|
|
if (virGettextInitialize() < 0)
|
2010-11-16 19:01:37 +00:00
|
|
|
return EXIT_FAILURE;
|
2006-09-21 15:24:37 +00:00
|
|
|
|
2013-08-29 08:36:00 +00:00
|
|
|
if (isatty(STDIN_FILENO)) {
|
|
|
|
ctl->istty = true;
|
|
|
|
|
2013-09-04 21:57:30 +00:00
|
|
|
#ifndef WIN32
|
2013-08-29 08:36:00 +00:00
|
|
|
if (tcgetattr(STDIN_FILENO, &ctl->termattr) < 0)
|
|
|
|
ctl->istty = false;
|
2013-09-04 21:57:30 +00:00
|
|
|
#endif
|
2013-08-29 08:36:00 +00:00
|
|
|
}
|
|
|
|
|
2011-11-30 19:42:20 +00:00
|
|
|
if (virMutexInit(&ctl->lock) < 0) {
|
|
|
|
vshError(ctl, "%s", _("Failed to initialize mutex"));
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
2011-05-09 11:57:09 +00:00
|
|
|
if (virInitialize() < 0) {
|
|
|
|
vshError(ctl, "%s", _("Failed to initialize libvirt"));
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
2019-08-29 10:52:08 +00:00
|
|
|
virFileActivateDirOverrideForProg(argv[0]);
|
2014-04-24 14:57:36 +00:00
|
|
|
|
2024-03-04 14:51:28 +00:00
|
|
|
if (!vshInit(ctl, cmdGroups))
|
2015-06-15 16:53:58 +00:00
|
|
|
exit(EXIT_FAILURE);
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2015-06-15 16:53:58 +00:00
|
|
|
if (!virshParseArgv(ctl, argc, argv) ||
|
|
|
|
!virshInit(ctl)) {
|
|
|
|
virshDeinit(ctl);
|
2005-12-08 10:23:34 +00:00
|
|
|
exit(EXIT_FAILURE);
|
2007-12-01 15:45:25 +00:00
|
|
|
}
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2016-04-21 08:26:31 +00:00
|
|
|
if (!ctl->connname)
|
2019-10-18 15:24:02 +00:00
|
|
|
ctl->connname = g_strdup(getenv("VIRSH_DEFAULT_CONNECT_URI"));
|
2016-04-21 08:26:31 +00:00
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
if (!ctl->imode) {
|
2006-03-15 12:13:25 +00:00
|
|
|
ret = vshCommandRun(ctl, ctl->cmd);
|
2005-12-01 16:35:42 +00:00
|
|
|
} else {
|
2005-12-08 10:23:34 +00:00
|
|
|
/* interactive mode */
|
|
|
|
if (!ctl->quiet) {
|
2006-05-22 14:38:33 +00:00
|
|
|
vshPrint(ctl,
|
2023-03-09 14:54:58 +00:00
|
|
|
_("Welcome to %1$s, the virtualization interactive terminal.\n\n"),
|
2006-03-15 12:13:25 +00:00
|
|
|
progname);
|
2008-01-16 17:13:23 +00:00
|
|
|
vshPrint(ctl, "%s",
|
2006-09-21 15:24:37 +00:00
|
|
|
_("Type: 'help' for help with commands\n"
|
2007-02-07 13:50:18 +00:00
|
|
|
" 'quit' to quit\n\n"));
|
2005-12-08 10:23:34 +00:00
|
|
|
}
|
2010-01-03 14:45:10 +00:00
|
|
|
|
2005-12-08 10:23:34 +00:00
|
|
|
do {
|
2015-06-15 16:53:58 +00:00
|
|
|
const char *prompt = virshCtl.readonly ? VIRSH_PROMPT_RO
|
|
|
|
: VIRSH_PROMPT_RW;
|
2006-03-15 12:13:25 +00:00
|
|
|
ctl->cmdstr =
|
2007-12-06 16:36:21 +00:00
|
|
|
vshReadline(ctl, prompt);
|
2006-03-15 12:13:25 +00:00
|
|
|
if (ctl->cmdstr == NULL)
|
|
|
|
break; /* EOF */
|
2005-12-08 10:23:34 +00:00
|
|
|
if (*ctl->cmdstr) {
|
2020-09-03 08:02:52 +00:00
|
|
|
vshReadlineHistoryAdd(ctl->cmdstr);
|
|
|
|
|
2021-01-26 08:51:27 +00:00
|
|
|
if (vshCommandStringParse(ctl, ctl->cmdstr, NULL, 0))
|
2005-12-08 10:23:34 +00:00
|
|
|
vshCommandRun(ctl, ctl->cmd);
|
|
|
|
}
|
2010-01-03 16:13:27 +00:00
|
|
|
VIR_FREE(ctl->cmdstr);
|
2006-03-15 12:13:25 +00:00
|
|
|
} while (ctl->imode);
|
2005-12-08 10:23:34 +00:00
|
|
|
|
2006-03-15 12:13:25 +00:00
|
|
|
if (ctl->cmdstr == NULL)
|
|
|
|
fputc('\n', stdout); /* line break after alone prompt */
|
2005-12-08 10:23:34 +00:00
|
|
|
}
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2015-06-15 16:53:58 +00:00
|
|
|
virshDeinit(ctl);
|
2005-12-08 10:23:34 +00:00
|
|
|
exit(ret ? EXIT_SUCCESS : EXIT_FAILURE);
|
2005-11-10 16:12:31 +00:00
|
|
|
}
|