2015-10-12 17:07:21 +02:00
|
|
|
/*
|
|
|
|
* virt-admin.c: a shell to exercise the libvirt admin API
|
|
|
|
*
|
|
|
|
* Copyright (C) 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/>.
|
|
|
|
* Authors:
|
|
|
|
* Erik Skultety <eskultet@redhat.com>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
#include "virt-admin.h"
|
|
|
|
|
|
|
|
#include <errno.h>
|
|
|
|
#include <getopt.h>
|
|
|
|
#include <locale.h>
|
|
|
|
|
|
|
|
#if WITH_READLINE
|
|
|
|
# include <readline/readline.h>
|
|
|
|
# include <readline/history.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "configmake.h"
|
|
|
|
#include "internal.h"
|
|
|
|
#include "viralloc.h"
|
|
|
|
#include "virerror.h"
|
|
|
|
#include "virfile.h"
|
|
|
|
#include "virstring.h"
|
|
|
|
#include "virthread.h"
|
|
|
|
|
|
|
|
/* Gnulib doesn't guarantee SA_SIGINFO support. */
|
|
|
|
#ifndef SA_SIGINFO
|
|
|
|
# define SA_SIGINFO 0
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define VIRT_ADMIN_PROMPT "virt-admin # "
|
|
|
|
|
|
|
|
static char *progname;
|
|
|
|
|
|
|
|
static const vshCmdGrp cmdGroups[];
|
|
|
|
static const vshClientHooks hooks;
|
|
|
|
|
2015-10-12 17:10:57 +02:00
|
|
|
/*
|
|
|
|
* vshAdmCatchDisconnect:
|
|
|
|
*
|
|
|
|
* We get here when the connection was closed. Unlike virsh, we do not save
|
admin: Rename virAdmConnect to virAdmDaemon
virAdmConnect was named after virConnect, but after some discussions,
most of the APIs called will be working with remote daemon and starting
them virAdmDaemon will make more sense. Only possibly controversal name
is CloseCallback (de)registration, and connecting to the daemon (which
will still be Open/Close), but even this makes sense if one thinks about
the daemon being opened and closed, e.g. as file, etc.
This way all the APIs working with the daemon will start with
virAdmDaemon prefix, they will accept virAdmDaemonPtr as first parameter
and that will better suit with other namings as well (virDomain*,
virAdmServer*, etc.).
Because in virt-admin, the connection name does not refer to a struct
that would have a connect in its name, also adjust 'connname' in
clients. And because it is not used anywhere in the vsh code, move it
from there into each client.
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
2015-11-25 16:59:30 +01:00
|
|
|
* the fact that the event was raised, sice there is virAdmDaemonIsAlive to
|
2015-10-12 17:10:57 +02:00
|
|
|
* check if the communication channel has not been closed by remote party.
|
|
|
|
*/
|
|
|
|
static void
|
admin: Rename virAdmConnect to virAdmDaemon
virAdmConnect was named after virConnect, but after some discussions,
most of the APIs called will be working with remote daemon and starting
them virAdmDaemon will make more sense. Only possibly controversal name
is CloseCallback (de)registration, and connecting to the daemon (which
will still be Open/Close), but even this makes sense if one thinks about
the daemon being opened and closed, e.g. as file, etc.
This way all the APIs working with the daemon will start with
virAdmDaemon prefix, they will accept virAdmDaemonPtr as first parameter
and that will better suit with other namings as well (virDomain*,
virAdmServer*, etc.).
Because in virt-admin, the connection name does not refer to a struct
that would have a connect in its name, also adjust 'connname' in
clients. And because it is not used anywhere in the vsh code, move it
from there into each client.
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
2015-11-25 16:59:30 +01:00
|
|
|
vshAdmCatchDisconnect(virAdmDaemonPtr dmn ATTRIBUTE_UNUSED,
|
2015-10-12 17:10:57 +02:00
|
|
|
int reason,
|
|
|
|
void *opaque)
|
|
|
|
{
|
|
|
|
vshControl *ctl = opaque;
|
|
|
|
const char *str = "unknown reason";
|
|
|
|
virErrorPtr error;
|
|
|
|
char *uri = NULL;
|
|
|
|
|
|
|
|
if (reason == VIR_CONNECT_CLOSE_REASON_CLIENT)
|
|
|
|
return;
|
|
|
|
|
|
|
|
error = virSaveLastError();
|
admin: Rename virAdmConnect to virAdmDaemon
virAdmConnect was named after virConnect, but after some discussions,
most of the APIs called will be working with remote daemon and starting
them virAdmDaemon will make more sense. Only possibly controversal name
is CloseCallback (de)registration, and connecting to the daemon (which
will still be Open/Close), but even this makes sense if one thinks about
the daemon being opened and closed, e.g. as file, etc.
This way all the APIs working with the daemon will start with
virAdmDaemon prefix, they will accept virAdmDaemonPtr as first parameter
and that will better suit with other namings as well (virDomain*,
virAdmServer*, etc.).
Because in virt-admin, the connection name does not refer to a struct
that would have a connect in its name, also adjust 'connname' in
clients. And because it is not used anywhere in the vsh code, move it
from there into each client.
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
2015-11-25 16:59:30 +01:00
|
|
|
uri = virAdmDaemonGetURI(dmn);
|
2015-10-12 17:10:57 +02:00
|
|
|
|
|
|
|
switch ((virConnectCloseReason) reason) {
|
|
|
|
case VIR_CONNECT_CLOSE_REASON_ERROR:
|
|
|
|
str = N_("Disconnected from %s due to I/O error");
|
|
|
|
break;
|
|
|
|
case VIR_CONNECT_CLOSE_REASON_EOF:
|
|
|
|
str = N_("Disconnected from %s due to end of file");
|
|
|
|
break;
|
|
|
|
case VIR_CONNECT_CLOSE_REASON_KEEPALIVE:
|
|
|
|
str = N_("Disconnected from %s due to keepalive timeout");
|
|
|
|
break;
|
|
|
|
/* coverity[dead_error_condition] */
|
|
|
|
case VIR_CONNECT_CLOSE_REASON_CLIENT:
|
|
|
|
case VIR_CONNECT_CLOSE_REASON_LAST:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
vshError(ctl, _(str), NULLSTR(uri));
|
|
|
|
|
|
|
|
if (error) {
|
|
|
|
virSetError(error);
|
|
|
|
virFreeError(error);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-12 17:07:21 +02:00
|
|
|
static int
|
admin: Rename virAdmConnect to virAdmDaemon
virAdmConnect was named after virConnect, but after some discussions,
most of the APIs called will be working with remote daemon and starting
them virAdmDaemon will make more sense. Only possibly controversal name
is CloseCallback (de)registration, and connecting to the daemon (which
will still be Open/Close), but even this makes sense if one thinks about
the daemon being opened and closed, e.g. as file, etc.
This way all the APIs working with the daemon will start with
virAdmDaemon prefix, they will accept virAdmDaemonPtr as first parameter
and that will better suit with other namings as well (virDomain*,
virAdmServer*, etc.).
Because in virt-admin, the connection name does not refer to a struct
that would have a connect in its name, also adjust 'connname' in
clients. And because it is not used anywhere in the vsh code, move it
from there into each client.
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
2015-11-25 16:59:30 +01:00
|
|
|
vshAdmDaemon(vshControl *ctl, unsigned int flags)
|
2015-10-12 17:07:21 +02:00
|
|
|
{
|
|
|
|
vshAdmControlPtr priv = ctl->privData;
|
|
|
|
|
admin: Rename virAdmConnect to virAdmDaemon
virAdmConnect was named after virConnect, but after some discussions,
most of the APIs called will be working with remote daemon and starting
them virAdmDaemon will make more sense. Only possibly controversal name
is CloseCallback (de)registration, and connecting to the daemon (which
will still be Open/Close), but even this makes sense if one thinks about
the daemon being opened and closed, e.g. as file, etc.
This way all the APIs working with the daemon will start with
virAdmDaemon prefix, they will accept virAdmDaemonPtr as first parameter
and that will better suit with other namings as well (virDomain*,
virAdmServer*, etc.).
Because in virt-admin, the connection name does not refer to a struct
that would have a connect in its name, also adjust 'connname' in
clients. And because it is not used anywhere in the vsh code, move it
from there into each client.
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
2015-11-25 16:59:30 +01:00
|
|
|
priv->dmn = virAdmDaemonOpen(priv->name, flags);
|
2015-10-12 17:07:21 +02:00
|
|
|
|
admin: Rename virAdmConnect to virAdmDaemon
virAdmConnect was named after virConnect, but after some discussions,
most of the APIs called will be working with remote daemon and starting
them virAdmDaemon will make more sense. Only possibly controversal name
is CloseCallback (de)registration, and connecting to the daemon (which
will still be Open/Close), but even this makes sense if one thinks about
the daemon being opened and closed, e.g. as file, etc.
This way all the APIs working with the daemon will start with
virAdmDaemon prefix, they will accept virAdmDaemonPtr as first parameter
and that will better suit with other namings as well (virDomain*,
virAdmServer*, etc.).
Because in virt-admin, the connection name does not refer to a struct
that would have a connect in its name, also adjust 'connname' in
clients. And because it is not used anywhere in the vsh code, move it
from there into each client.
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
2015-11-25 16:59:30 +01:00
|
|
|
if (!priv->dmn) {
|
2015-10-12 17:07:21 +02:00
|
|
|
if (priv->wantReconnect)
|
|
|
|
vshError(ctl, "%s", _("Failed to reconnect to the admin server"));
|
|
|
|
else
|
|
|
|
vshError(ctl, "%s", _("Failed to connect to the admin server"));
|
|
|
|
return -1;
|
|
|
|
} else {
|
admin: Rename virAdmConnect to virAdmDaemon
virAdmConnect was named after virConnect, but after some discussions,
most of the APIs called will be working with remote daemon and starting
them virAdmDaemon will make more sense. Only possibly controversal name
is CloseCallback (de)registration, and connecting to the daemon (which
will still be Open/Close), but even this makes sense if one thinks about
the daemon being opened and closed, e.g. as file, etc.
This way all the APIs working with the daemon will start with
virAdmDaemon prefix, they will accept virAdmDaemonPtr as first parameter
and that will better suit with other namings as well (virDomain*,
virAdmServer*, etc.).
Because in virt-admin, the connection name does not refer to a struct
that would have a connect in its name, also adjust 'connname' in
clients. And because it is not used anywhere in the vsh code, move it
from there into each client.
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
2015-11-25 16:59:30 +01:00
|
|
|
if (virAdmDaemonRegisterCloseCallback(priv->dmn, vshAdmCatchDisconnect,
|
|
|
|
NULL, NULL) < 0)
|
2015-10-12 17:10:57 +02:00
|
|
|
vshError(ctl, "%s", _("Unable to register disconnect callback"));
|
|
|
|
|
2015-10-12 17:07:21 +02:00
|
|
|
if (priv->wantReconnect)
|
|
|
|
vshPrint(ctl, "%s\n", _("Reconnected to the admin server"));
|
|
|
|
else
|
|
|
|
vshPrint(ctl, "%s\n", _("Connected to the admin server"));
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
vshAdmDisconnect(vshControl *ctl)
|
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
vshAdmControlPtr priv = ctl->privData;
|
|
|
|
|
admin: Rename virAdmConnect to virAdmDaemon
virAdmConnect was named after virConnect, but after some discussions,
most of the APIs called will be working with remote daemon and starting
them virAdmDaemon will make more sense. Only possibly controversal name
is CloseCallback (de)registration, and connecting to the daemon (which
will still be Open/Close), but even this makes sense if one thinks about
the daemon being opened and closed, e.g. as file, etc.
This way all the APIs working with the daemon will start with
virAdmDaemon prefix, they will accept virAdmDaemonPtr as first parameter
and that will better suit with other namings as well (virDomain*,
virAdmServer*, etc.).
Because in virt-admin, the connection name does not refer to a struct
that would have a connect in its name, also adjust 'connname' in
clients. And because it is not used anywhere in the vsh code, move it
from there into each client.
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
2015-11-25 16:59:30 +01:00
|
|
|
if (!priv->dmn)
|
2015-10-12 17:07:21 +02:00
|
|
|
return ret;
|
|
|
|
|
admin: Rename virAdmConnect to virAdmDaemon
virAdmConnect was named after virConnect, but after some discussions,
most of the APIs called will be working with remote daemon and starting
them virAdmDaemon will make more sense. Only possibly controversal name
is CloseCallback (de)registration, and connecting to the daemon (which
will still be Open/Close), but even this makes sense if one thinks about
the daemon being opened and closed, e.g. as file, etc.
This way all the APIs working with the daemon will start with
virAdmDaemon prefix, they will accept virAdmDaemonPtr as first parameter
and that will better suit with other namings as well (virDomain*,
virAdmServer*, etc.).
Because in virt-admin, the connection name does not refer to a struct
that would have a connect in its name, also adjust 'connname' in
clients. And because it is not used anywhere in the vsh code, move it
from there into each client.
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
2015-11-25 16:59:30 +01:00
|
|
|
virAdmDaemonUnregisterCloseCallback(priv->dmn, vshAdmCatchDisconnect);
|
|
|
|
ret = virAdmDaemonClose(priv->dmn);
|
2015-10-12 17:07:21 +02:00
|
|
|
if (ret < 0)
|
|
|
|
vshError(ctl, "%s", _("Failed to disconnect from the admin server"));
|
|
|
|
else if (ret > 0)
|
|
|
|
vshError(ctl, "%s", _("One or more references were leaked after "
|
|
|
|
"disconnect from the hypervisor"));
|
admin: Rename virAdmConnect to virAdmDaemon
virAdmConnect was named after virConnect, but after some discussions,
most of the APIs called will be working with remote daemon and starting
them virAdmDaemon will make more sense. Only possibly controversal name
is CloseCallback (de)registration, and connecting to the daemon (which
will still be Open/Close), but even this makes sense if one thinks about
the daemon being opened and closed, e.g. as file, etc.
This way all the APIs working with the daemon will start with
virAdmDaemon prefix, they will accept virAdmDaemonPtr as first parameter
and that will better suit with other namings as well (virDomain*,
virAdmServer*, etc.).
Because in virt-admin, the connection name does not refer to a struct
that would have a connect in its name, also adjust 'connname' in
clients. And because it is not used anywhere in the vsh code, move it
from there into each client.
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
2015-11-25 16:59:30 +01:00
|
|
|
priv->dmn = NULL;
|
2015-10-12 17:07:21 +02:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* vshAdmReconnect:
|
|
|
|
*
|
|
|
|
* Reconnect to a daemon's admin server
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
vshAdmReconnect(vshControl *ctl)
|
|
|
|
{
|
|
|
|
vshAdmControlPtr priv = ctl->privData;
|
admin: Rename virAdmConnect to virAdmDaemon
virAdmConnect was named after virConnect, but after some discussions,
most of the APIs called will be working with remote daemon and starting
them virAdmDaemon will make more sense. Only possibly controversal name
is CloseCallback (de)registration, and connecting to the daemon (which
will still be Open/Close), but even this makes sense if one thinks about
the daemon being opened and closed, e.g. as file, etc.
This way all the APIs working with the daemon will start with
virAdmDaemon prefix, they will accept virAdmDaemonPtr as first parameter
and that will better suit with other namings as well (virDomain*,
virAdmServer*, etc.).
Because in virt-admin, the connection name does not refer to a struct
that would have a connect in its name, also adjust 'connname' in
clients. And because it is not used anywhere in the vsh code, move it
from there into each client.
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
2015-11-25 16:59:30 +01:00
|
|
|
if (priv->dmn)
|
2015-10-12 17:07:21 +02:00
|
|
|
priv->wantReconnect = true;
|
|
|
|
|
|
|
|
vshAdmDisconnect(ctl);
|
admin: Rename virAdmConnect to virAdmDaemon
virAdmConnect was named after virConnect, but after some discussions,
most of the APIs called will be working with remote daemon and starting
them virAdmDaemon will make more sense. Only possibly controversal name
is CloseCallback (de)registration, and connecting to the daemon (which
will still be Open/Close), but even this makes sense if one thinks about
the daemon being opened and closed, e.g. as file, etc.
This way all the APIs working with the daemon will start with
virAdmDaemon prefix, they will accept virAdmDaemonPtr as first parameter
and that will better suit with other namings as well (virDomain*,
virAdmServer*, etc.).
Because in virt-admin, the connection name does not refer to a struct
that would have a connect in its name, also adjust 'connname' in
clients. And because it is not used anywhere in the vsh code, move it
from there into each client.
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
2015-11-25 16:59:30 +01:00
|
|
|
vshAdmDaemon(ctl, 0);
|
2015-10-12 17:07:21 +02:00
|
|
|
|
|
|
|
priv->wantReconnect = false;
|
|
|
|
}
|
|
|
|
|
2015-10-12 16:07:52 +02:00
|
|
|
/*
|
|
|
|
* 'uri' command
|
|
|
|
*/
|
|
|
|
|
|
|
|
static const vshCmdInfo info_uri[] = {
|
|
|
|
{.name = "help",
|
|
|
|
.data = N_("print the admin server URI")
|
|
|
|
},
|
|
|
|
{.name = "desc",
|
|
|
|
.data = ""
|
|
|
|
},
|
|
|
|
{.name = NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static bool
|
|
|
|
cmdURI(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
char *uri;
|
|
|
|
vshAdmControlPtr priv = ctl->privData;
|
|
|
|
|
admin: Rename virAdmConnect to virAdmDaemon
virAdmConnect was named after virConnect, but after some discussions,
most of the APIs called will be working with remote daemon and starting
them virAdmDaemon will make more sense. Only possibly controversal name
is CloseCallback (de)registration, and connecting to the daemon (which
will still be Open/Close), but even this makes sense if one thinks about
the daemon being opened and closed, e.g. as file, etc.
This way all the APIs working with the daemon will start with
virAdmDaemon prefix, they will accept virAdmDaemonPtr as first parameter
and that will better suit with other namings as well (virDomain*,
virAdmServer*, etc.).
Because in virt-admin, the connection name does not refer to a struct
that would have a connect in its name, also adjust 'connname' in
clients. And because it is not used anywhere in the vsh code, move it
from there into each client.
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
2015-11-25 16:59:30 +01:00
|
|
|
uri = virAdmDaemonGetURI(priv->dmn);
|
2015-10-12 16:07:52 +02:00
|
|
|
if (!uri) {
|
|
|
|
vshError(ctl, "%s", _("failed to get URI"));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
vshPrint(ctl, "%s\n", uri);
|
|
|
|
VIR_FREE(uri);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-10-05 17:17:51 +02:00
|
|
|
/*
|
|
|
|
* "version" command
|
|
|
|
*/
|
|
|
|
|
|
|
|
static const vshCmdInfo info_version[] = {
|
|
|
|
{.name = "help",
|
|
|
|
.data = N_("show version")
|
|
|
|
},
|
|
|
|
{.name = "desc",
|
|
|
|
.data = N_("Display the system and also the daemon version information.")
|
|
|
|
},
|
|
|
|
{.name = NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static bool
|
|
|
|
cmdVersion(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
unsigned long libVersion;
|
|
|
|
unsigned long long includeVersion;
|
|
|
|
unsigned long long daemonVersion;
|
|
|
|
int ret;
|
|
|
|
unsigned int major;
|
|
|
|
unsigned int minor;
|
|
|
|
unsigned int rel;
|
|
|
|
vshAdmControlPtr priv = ctl->privData;
|
|
|
|
|
|
|
|
includeVersion = LIBVIR_VERSION_NUMBER;
|
|
|
|
major = includeVersion / 1000000;
|
|
|
|
includeVersion %= 1000000;
|
|
|
|
minor = includeVersion / 1000;
|
|
|
|
rel = includeVersion % 1000;
|
|
|
|
vshPrint(ctl, _("Compiled against library: libvirt %d.%d.%d\n"),
|
|
|
|
major, minor, rel);
|
|
|
|
|
|
|
|
ret = virGetVersion(&libVersion, NULL, NULL);
|
|
|
|
if (ret < 0) {
|
|
|
|
vshError(ctl, "%s", _("failed to get the library version"));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
major = libVersion / 1000000;
|
|
|
|
libVersion %= 1000000;
|
|
|
|
minor = libVersion / 1000;
|
|
|
|
rel = libVersion % 1000;
|
|
|
|
vshPrint(ctl, _("Using library: libvirt %d.%d.%d\n"),
|
|
|
|
major, minor, rel);
|
|
|
|
|
admin: Rename virAdmConnect to virAdmDaemon
virAdmConnect was named after virConnect, but after some discussions,
most of the APIs called will be working with remote daemon and starting
them virAdmDaemon will make more sense. Only possibly controversal name
is CloseCallback (de)registration, and connecting to the daemon (which
will still be Open/Close), but even this makes sense if one thinks about
the daemon being opened and closed, e.g. as file, etc.
This way all the APIs working with the daemon will start with
virAdmDaemon prefix, they will accept virAdmDaemonPtr as first parameter
and that will better suit with other namings as well (virDomain*,
virAdmServer*, etc.).
Because in virt-admin, the connection name does not refer to a struct
that would have a connect in its name, also adjust 'connname' in
clients. And because it is not used anywhere in the vsh code, move it
from there into each client.
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
2015-11-25 16:59:30 +01:00
|
|
|
ret = virAdmDaemonGetVersion(priv->dmn, &daemonVersion);
|
2015-10-05 17:17:51 +02:00
|
|
|
if (ret < 0) {
|
|
|
|
vshError(ctl, "%s", _("failed to get the daemon version"));
|
|
|
|
} else {
|
|
|
|
major = daemonVersion / 1000000;
|
|
|
|
daemonVersion %= 1000000;
|
|
|
|
minor = daemonVersion / 1000;
|
|
|
|
rel = daemonVersion % 1000;
|
|
|
|
vshPrint(ctl, _("Running against daemon: %d.%d.%d\n"),
|
|
|
|
major, minor, rel);
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-10-12 16:07:52 +02:00
|
|
|
|
2015-10-12 17:07:21 +02:00
|
|
|
/* ---------------
|
|
|
|
* Command Connect
|
|
|
|
* ---------------
|
|
|
|
*/
|
|
|
|
|
|
|
|
static const vshCmdOptDef opts_connect[] = {
|
|
|
|
{.name = "name",
|
|
|
|
.type = VSH_OT_STRING,
|
|
|
|
.flags = VSH_OFLAG_EMPTY_OK,
|
|
|
|
.help = N_("daemon's admin server connection URI")
|
|
|
|
},
|
|
|
|
{.name = NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static const vshCmdInfo info_connect[] = {
|
|
|
|
{.name = "help",
|
|
|
|
.data = N_("connect to daemon's admin server")
|
|
|
|
},
|
|
|
|
{.name = "desc",
|
|
|
|
.data = N_("Connect to a daemon's administrating server.")
|
|
|
|
},
|
|
|
|
{.name = NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static bool
|
|
|
|
cmdConnect(vshControl *ctl, const vshCmd *cmd)
|
|
|
|
{
|
|
|
|
const char *name = NULL;
|
|
|
|
vshAdmControlPtr priv = ctl->privData;
|
|
|
|
|
|
|
|
if (vshCommandOptStringReq(ctl, cmd, "name", &name) < 0)
|
|
|
|
return false;
|
|
|
|
|
admin: Rename virAdmConnect to virAdmDaemon
virAdmConnect was named after virConnect, but after some discussions,
most of the APIs called will be working with remote daemon and starting
them virAdmDaemon will make more sense. Only possibly controversal name
is CloseCallback (de)registration, and connecting to the daemon (which
will still be Open/Close), but even this makes sense if one thinks about
the daemon being opened and closed, e.g. as file, etc.
This way all the APIs working with the daemon will start with
virAdmDaemon prefix, they will accept virAdmDaemonPtr as first parameter
and that will better suit with other namings as well (virDomain*,
virAdmServer*, etc.).
Because in virt-admin, the connection name does not refer to a struct
that would have a connect in its name, also adjust 'connname' in
clients. And because it is not used anywhere in the vsh code, move it
from there into each client.
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
2015-11-25 16:59:30 +01:00
|
|
|
VIR_FREE(priv->name);
|
|
|
|
priv->name = vshStrdup(ctl, name);
|
2015-10-12 17:07:21 +02:00
|
|
|
|
|
|
|
vshAdmReconnect(ctl);
|
|
|
|
|
admin: Rename virAdmConnect to virAdmDaemon
virAdmConnect was named after virConnect, but after some discussions,
most of the APIs called will be working with remote daemon and starting
them virAdmDaemon will make more sense. Only possibly controversal name
is CloseCallback (de)registration, and connecting to the daemon (which
will still be Open/Close), but even this makes sense if one thinks about
the daemon being opened and closed, e.g. as file, etc.
This way all the APIs working with the daemon will start with
virAdmDaemon prefix, they will accept virAdmDaemonPtr as first parameter
and that will better suit with other namings as well (virDomain*,
virAdmServer*, etc.).
Because in virt-admin, the connection name does not refer to a struct
that would have a connect in its name, also adjust 'connname' in
clients. And because it is not used anywhere in the vsh code, move it
from there into each client.
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
2015-11-25 16:59:30 +01:00
|
|
|
return !!priv->dmn;
|
2015-10-12 17:07:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void *
|
admin: Rename virAdmConnect to virAdmDaemon
virAdmConnect was named after virConnect, but after some discussions,
most of the APIs called will be working with remote daemon and starting
them virAdmDaemon will make more sense. Only possibly controversal name
is CloseCallback (de)registration, and connecting to the daemon (which
will still be Open/Close), but even this makes sense if one thinks about
the daemon being opened and closed, e.g. as file, etc.
This way all the APIs working with the daemon will start with
virAdmDaemon prefix, they will accept virAdmDaemonPtr as first parameter
and that will better suit with other namings as well (virDomain*,
virAdmServer*, etc.).
Because in virt-admin, the connection name does not refer to a struct
that would have a connect in its name, also adjust 'connname' in
clients. And because it is not used anywhere in the vsh code, move it
from there into each client.
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
2015-11-25 16:59:30 +01:00
|
|
|
vshAdmDaemonionHandler(vshControl *ctl)
|
2015-10-12 17:07:21 +02:00
|
|
|
{
|
|
|
|
vshAdmControlPtr priv = ctl->privData;
|
|
|
|
|
admin: Rename virAdmConnect to virAdmDaemon
virAdmConnect was named after virConnect, but after some discussions,
most of the APIs called will be working with remote daemon and starting
them virAdmDaemon will make more sense. Only possibly controversal name
is CloseCallback (de)registration, and connecting to the daemon (which
will still be Open/Close), but even this makes sense if one thinks about
the daemon being opened and closed, e.g. as file, etc.
This way all the APIs working with the daemon will start with
virAdmDaemon prefix, they will accept virAdmDaemonPtr as first parameter
and that will better suit with other namings as well (virDomain*,
virAdmServer*, etc.).
Because in virt-admin, the connection name does not refer to a struct
that would have a connect in its name, also adjust 'connname' in
clients. And because it is not used anywhere in the vsh code, move it
from there into each client.
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
2015-11-25 16:59:30 +01:00
|
|
|
if (!virAdmDaemonIsAlive(priv->dmn))
|
2015-10-12 17:07:21 +02:00
|
|
|
vshAdmReconnect(ctl);
|
|
|
|
|
admin: Rename virAdmConnect to virAdmDaemon
virAdmConnect was named after virConnect, but after some discussions,
most of the APIs called will be working with remote daemon and starting
them virAdmDaemon will make more sense. Only possibly controversal name
is CloseCallback (de)registration, and connecting to the daemon (which
will still be Open/Close), but even this makes sense if one thinks about
the daemon being opened and closed, e.g. as file, etc.
This way all the APIs working with the daemon will start with
virAdmDaemon prefix, they will accept virAdmDaemonPtr as first parameter
and that will better suit with other namings as well (virDomain*,
virAdmServer*, etc.).
Because in virt-admin, the connection name does not refer to a struct
that would have a connect in its name, also adjust 'connname' in
clients. And because it is not used anywhere in the vsh code, move it
from there into each client.
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
2015-11-25 16:59:30 +01:00
|
|
|
if (!virAdmDaemonIsAlive(priv->dmn)) {
|
2015-10-12 17:07:21 +02:00
|
|
|
vshError(ctl, "%s", _("no valid connection"));
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
admin: Rename virAdmConnect to virAdmDaemon
virAdmConnect was named after virConnect, but after some discussions,
most of the APIs called will be working with remote daemon and starting
them virAdmDaemon will make more sense. Only possibly controversal name
is CloseCallback (de)registration, and connecting to the daemon (which
will still be Open/Close), but even this makes sense if one thinks about
the daemon being opened and closed, e.g. as file, etc.
This way all the APIs working with the daemon will start with
virAdmDaemon prefix, they will accept virAdmDaemonPtr as first parameter
and that will better suit with other namings as well (virDomain*,
virAdmServer*, etc.).
Because in virt-admin, the connection name does not refer to a struct
that would have a connect in its name, also adjust 'connname' in
clients. And because it is not used anywhere in the vsh code, move it
from there into each client.
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
2015-11-25 16:59:30 +01:00
|
|
|
return priv->dmn;
|
2015-10-12 17:07:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Initialize connection.
|
|
|
|
*/
|
|
|
|
static bool
|
|
|
|
vshAdmInit(vshControl *ctl)
|
|
|
|
{
|
|
|
|
vshAdmControlPtr priv = ctl->privData;
|
|
|
|
|
|
|
|
/* Since we have the commandline arguments parsed, we need to
|
|
|
|
* reload our initial settings to make debugging and readline
|
|
|
|
* work properly */
|
|
|
|
vshInitReload(ctl);
|
|
|
|
|
admin: Rename virAdmConnect to virAdmDaemon
virAdmConnect was named after virConnect, but after some discussions,
most of the APIs called will be working with remote daemon and starting
them virAdmDaemon will make more sense. Only possibly controversal name
is CloseCallback (de)registration, and connecting to the daemon (which
will still be Open/Close), but even this makes sense if one thinks about
the daemon being opened and closed, e.g. as file, etc.
This way all the APIs working with the daemon will start with
virAdmDaemon prefix, they will accept virAdmDaemonPtr as first parameter
and that will better suit with other namings as well (virDomain*,
virAdmServer*, etc.).
Because in virt-admin, the connection name does not refer to a struct
that would have a connect in its name, also adjust 'connname' in
clients. And because it is not used anywhere in the vsh code, move it
from there into each client.
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
2015-11-25 16:59:30 +01:00
|
|
|
if (priv->dmn)
|
2015-10-12 17:07:21 +02:00
|
|
|
return false;
|
|
|
|
|
|
|
|
/* set up the library error handler */
|
|
|
|
virSetErrorFunc(NULL, vshErrorHandler);
|
|
|
|
|
|
|
|
if (virEventRegisterDefaultImpl() < 0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (virThreadCreate(&ctl->eventLoop, true, vshEventLoop, ctl) < 0)
|
|
|
|
return false;
|
|
|
|
ctl->eventLoopStarted = true;
|
|
|
|
|
admin: Rename virAdmConnect to virAdmDaemon
virAdmConnect was named after virConnect, but after some discussions,
most of the APIs called will be working with remote daemon and starting
them virAdmDaemon will make more sense. Only possibly controversal name
is CloseCallback (de)registration, and connecting to the daemon (which
will still be Open/Close), but even this makes sense if one thinks about
the daemon being opened and closed, e.g. as file, etc.
This way all the APIs working with the daemon will start with
virAdmDaemon prefix, they will accept virAdmDaemonPtr as first parameter
and that will better suit with other namings as well (virDomain*,
virAdmServer*, etc.).
Because in virt-admin, the connection name does not refer to a struct
that would have a connect in its name, also adjust 'connname' in
clients. And because it is not used anywhere in the vsh code, move it
from there into each client.
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
2015-11-25 16:59:30 +01:00
|
|
|
if (priv->name) {
|
2015-10-12 17:07:21 +02:00
|
|
|
vshAdmReconnect(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).
|
|
|
|
*/
|
admin: Rename virAdmConnect to virAdmDaemon
virAdmConnect was named after virConnect, but after some discussions,
most of the APIs called will be working with remote daemon and starting
them virAdmDaemon will make more sense. Only possibly controversal name
is CloseCallback (de)registration, and connecting to the daemon (which
will still be Open/Close), but even this makes sense if one thinks about
the daemon being opened and closed, e.g. as file, etc.
This way all the APIs working with the daemon will start with
virAdmDaemon prefix, they will accept virAdmDaemonPtr as first parameter
and that will better suit with other namings as well (virDomain*,
virAdmServer*, etc.).
Because in virt-admin, the connection name does not refer to a struct
that would have a connect in its name, also adjust 'connname' in
clients. And because it is not used anywhere in the vsh code, move it
from there into each client.
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
2015-11-25 16:59:30 +01:00
|
|
|
if (!priv->dmn) {
|
2015-10-12 17:07:21 +02:00
|
|
|
vshReportError(ctl);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
vshAdmDeinitTimer(int timer ATTRIBUTE_UNUSED, void *opaque ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
/* nothing to be done here */
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Deinitialize virt-admin
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
vshAdmDeinit(vshControl *ctl)
|
|
|
|
{
|
|
|
|
vshAdmControlPtr priv = ctl->privData;
|
|
|
|
|
|
|
|
vshDeinit(ctl);
|
admin: Rename virAdmConnect to virAdmDaemon
virAdmConnect was named after virConnect, but after some discussions,
most of the APIs called will be working with remote daemon and starting
them virAdmDaemon will make more sense. Only possibly controversal name
is CloseCallback (de)registration, and connecting to the daemon (which
will still be Open/Close), but even this makes sense if one thinks about
the daemon being opened and closed, e.g. as file, etc.
This way all the APIs working with the daemon will start with
virAdmDaemon prefix, they will accept virAdmDaemonPtr as first parameter
and that will better suit with other namings as well (virDomain*,
virAdmServer*, etc.).
Because in virt-admin, the connection name does not refer to a struct
that would have a connect in its name, also adjust 'connname' in
clients. And because it is not used anywhere in the vsh code, move it
from there into each client.
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
2015-11-25 16:59:30 +01:00
|
|
|
VIR_FREE(priv->name);
|
2015-10-12 17:07:21 +02:00
|
|
|
|
admin: Rename virAdmConnect to virAdmDaemon
virAdmConnect was named after virConnect, but after some discussions,
most of the APIs called will be working with remote daemon and starting
them virAdmDaemon will make more sense. Only possibly controversal name
is CloseCallback (de)registration, and connecting to the daemon (which
will still be Open/Close), but even this makes sense if one thinks about
the daemon being opened and closed, e.g. as file, etc.
This way all the APIs working with the daemon will start with
virAdmDaemon prefix, they will accept virAdmDaemonPtr as first parameter
and that will better suit with other namings as well (virDomain*,
virAdmServer*, etc.).
Because in virt-admin, the connection name does not refer to a struct
that would have a connect in its name, also adjust 'connname' in
clients. And because it is not used anywhere in the vsh code, move it
from there into each client.
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
2015-11-25 16:59:30 +01:00
|
|
|
if (priv->dmn)
|
2015-10-12 17:07:21 +02:00
|
|
|
vshAdmDisconnect(ctl);
|
|
|
|
|
|
|
|
virResetLastError();
|
|
|
|
|
|
|
|
if (ctl->eventLoopStarted) {
|
|
|
|
int timer;
|
|
|
|
|
|
|
|
virMutexLock(&ctl->lock);
|
|
|
|
ctl->quit = true;
|
|
|
|
/* HACK: Add a dummy timeout to break event loop */
|
|
|
|
timer = virEventAddTimeout(0, vshAdmDeinitTimer, NULL, NULL);
|
|
|
|
virMutexUnlock(&ctl->lock);
|
|
|
|
|
|
|
|
virThreadJoin(&ctl->eventLoop);
|
|
|
|
|
|
|
|
if (timer != -1)
|
|
|
|
virEventRemoveTimeout(timer);
|
|
|
|
|
|
|
|
ctl->eventLoopStarted = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
virMutexDestroy(&ctl->lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Print usage
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
vshAdmUsage(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 daemon admin connection URI\n"
|
|
|
|
" -d | --debug=NUM debug level [0-4]\n"
|
|
|
|
" -h | --help this help\n"
|
|
|
|
" -l | --log=FILE output logging to file\n"
|
|
|
|
" -q | --quiet quiet mode\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
|
|
|
|
vshAdmShowVersion(vshControl *ctl ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
/* FIXME - list a copyright blurb, as in GNU programs? */
|
|
|
|
vshPrint(ctl, _("Virt-admin 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:"));
|
|
|
|
#ifdef WITH_LIBVIRTD
|
|
|
|
vshPrint(ctl, " Daemon");
|
|
|
|
#endif
|
|
|
|
#ifdef ENABLE_DEBUG
|
|
|
|
vshPrint(ctl, " Debug");
|
|
|
|
#endif
|
|
|
|
#if WITH_READLINE
|
|
|
|
vshPrint(ctl, " Readline");
|
|
|
|
#endif
|
|
|
|
vshPrint(ctl, "\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool
|
|
|
|
vshAdmParseArgv(vshControl *ctl, int argc, char **argv)
|
|
|
|
{
|
|
|
|
int arg, debug;
|
|
|
|
size_t i;
|
|
|
|
int longindex = -1;
|
admin: Rename virAdmConnect to virAdmDaemon
virAdmConnect was named after virConnect, but after some discussions,
most of the APIs called will be working with remote daemon and starting
them virAdmDaemon will make more sense. Only possibly controversal name
is CloseCallback (de)registration, and connecting to the daemon (which
will still be Open/Close), but even this makes sense if one thinks about
the daemon being opened and closed, e.g. as file, etc.
This way all the APIs working with the daemon will start with
virAdmDaemon prefix, they will accept virAdmDaemonPtr as first parameter
and that will better suit with other namings as well (virDomain*,
virAdmServer*, etc.).
Because in virt-admin, the connection name does not refer to a struct
that would have a connect in its name, also adjust 'connname' in
clients. And because it is not used anywhere in the vsh code, move it
from there into each client.
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
2015-11-25 16:59:30 +01:00
|
|
|
vshAdmControlPtr priv = ctl->privData;
|
2015-10-12 17:07:21 +02:00
|
|
|
struct option opt[] = {
|
|
|
|
{"connect", required_argument, NULL, 'c'},
|
|
|
|
{"debug", required_argument, NULL, 'd'},
|
|
|
|
{"help", no_argument, NULL, 'h'},
|
|
|
|
{"log", required_argument, NULL, 'l'},
|
|
|
|
{"quiet", no_argument, NULL, 'q'},
|
|
|
|
{"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 virt-admin options. */
|
|
|
|
while ((arg = getopt_long(argc, argv, "+:c:d:hl:qvV", opt, &longindex)) != -1) {
|
|
|
|
switch (arg) {
|
|
|
|
case 'c':
|
admin: Rename virAdmConnect to virAdmDaemon
virAdmConnect was named after virConnect, but after some discussions,
most of the APIs called will be working with remote daemon and starting
them virAdmDaemon will make more sense. Only possibly controversal name
is CloseCallback (de)registration, and connecting to the daemon (which
will still be Open/Close), but even this makes sense if one thinks about
the daemon being opened and closed, e.g. as file, etc.
This way all the APIs working with the daemon will start with
virAdmDaemon prefix, they will accept virAdmDaemonPtr as first parameter
and that will better suit with other namings as well (virDomain*,
virAdmServer*, etc.).
Because in virt-admin, the connection name does not refer to a struct
that would have a connect in its name, also adjust 'connname' in
clients. And because it is not used anywhere in the vsh code, move it
from there into each client.
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
2015-11-25 16:59:30 +01:00
|
|
|
VIR_FREE(priv->name);
|
|
|
|
priv->name = vshStrdup(ctl, optarg);
|
2015-10-12 17:07:21 +02:00
|
|
|
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 'h':
|
|
|
|
vshAdmUsage();
|
|
|
|
exit(EXIT_SUCCESS);
|
|
|
|
break;
|
|
|
|
case 'l':
|
|
|
|
vshCloseLogFile(ctl);
|
|
|
|
ctl->logfile = vshStrdup(ctl, optarg);
|
|
|
|
vshOpenLogFile(ctl);
|
|
|
|
break;
|
|
|
|
case 'q':
|
|
|
|
ctl->quiet = true;
|
|
|
|
break;
|
|
|
|
case 'v':
|
|
|
|
if (STRNEQ_NULLABLE(optarg, "long")) {
|
|
|
|
puts(VERSION);
|
|
|
|
exit(EXIT_SUCCESS);
|
|
|
|
}
|
|
|
|
/* fall through */
|
|
|
|
case 'V':
|
|
|
|
vshAdmShowVersion(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) {
|
|
|
|
ctl->imode = true;
|
|
|
|
} else {
|
|
|
|
/* 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 vshAdmCmds[] = {
|
|
|
|
VSH_CMD_CD,
|
|
|
|
VSH_CMD_ECHO,
|
|
|
|
VSH_CMD_EXIT,
|
|
|
|
VSH_CMD_HELP,
|
|
|
|
VSH_CMD_PWD,
|
|
|
|
VSH_CMD_QUIT,
|
2015-10-12 16:07:52 +02:00
|
|
|
{.name = "uri",
|
|
|
|
.handler = cmdURI,
|
|
|
|
.opts = NULL,
|
|
|
|
.info = info_uri,
|
|
|
|
.flags = 0
|
|
|
|
},
|
2015-10-05 17:17:51 +02:00
|
|
|
{.name = "version",
|
|
|
|
.handler = cmdVersion,
|
|
|
|
.opts = NULL,
|
|
|
|
.info = info_version,
|
|
|
|
.flags = 0
|
|
|
|
},
|
2015-10-12 17:07:21 +02:00
|
|
|
{.name = "connect",
|
|
|
|
.handler = cmdConnect,
|
|
|
|
.opts = opts_connect,
|
|
|
|
.info = info_connect,
|
|
|
|
.flags = VSH_CMD_FLAG_NOCONNECT
|
|
|
|
},
|
|
|
|
{.name = NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static const vshCmdGrp cmdGroups[] = {
|
|
|
|
{"Virt-admin itself", "virt-admin", vshAdmCmds},
|
|
|
|
{NULL, NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static const vshClientHooks hooks = {
|
admin: Rename virAdmConnect to virAdmDaemon
virAdmConnect was named after virConnect, but after some discussions,
most of the APIs called will be working with remote daemon and starting
them virAdmDaemon will make more sense. Only possibly controversal name
is CloseCallback (de)registration, and connecting to the daemon (which
will still be Open/Close), but even this makes sense if one thinks about
the daemon being opened and closed, e.g. as file, etc.
This way all the APIs working with the daemon will start with
virAdmDaemon prefix, they will accept virAdmDaemonPtr as first parameter
and that will better suit with other namings as well (virDomain*,
virAdmServer*, etc.).
Because in virt-admin, the connection name does not refer to a struct
that would have a connect in its name, also adjust 'connname' in
clients. And because it is not used anywhere in the vsh code, move it
from there into each client.
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
2015-11-25 16:59:30 +01:00
|
|
|
.connHandler = vshAdmDaemonionHandler
|
2015-10-12 17:07:21 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
int
|
|
|
|
main(int argc, char **argv)
|
|
|
|
{
|
|
|
|
vshControl _ctl, *ctl = &_ctl;
|
|
|
|
vshAdmControl virtAdminCtl;
|
|
|
|
const char *defaultConn;
|
|
|
|
bool ret = true;
|
|
|
|
|
|
|
|
memset(ctl, 0, sizeof(vshControl));
|
|
|
|
memset(&virtAdminCtl, 0, sizeof(vshAdmControl));
|
|
|
|
ctl->name = "virt-admin"; /* hardcoded name of the binary */
|
|
|
|
ctl->log_fd = -1; /* Initialize log file descriptor */
|
|
|
|
ctl->debug = VSH_DEBUG_DEFAULT;
|
|
|
|
ctl->hooks = &hooks;
|
|
|
|
|
|
|
|
ctl->eventPipe[0] = -1;
|
|
|
|
ctl->eventPipe[1] = -1;
|
|
|
|
ctl->privData = &virtAdminCtl;
|
|
|
|
|
|
|
|
if (!(progname = strrchr(argv[0], '/')))
|
|
|
|
progname = argv[0];
|
|
|
|
else
|
|
|
|
progname++;
|
|
|
|
ctl->progname = progname;
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
virFileActivateDirOverride(argv[0]);
|
|
|
|
|
|
|
|
if ((defaultConn = virGetEnvBlockSUID("LIBVIRT_DEFAULT_ADMIN_URI")))
|
admin: Rename virAdmConnect to virAdmDaemon
virAdmConnect was named after virConnect, but after some discussions,
most of the APIs called will be working with remote daemon and starting
them virAdmDaemon will make more sense. Only possibly controversal name
is CloseCallback (de)registration, and connecting to the daemon (which
will still be Open/Close), but even this makes sense if one thinks about
the daemon being opened and closed, e.g. as file, etc.
This way all the APIs working with the daemon will start with
virAdmDaemon prefix, they will accept virAdmDaemonPtr as first parameter
and that will better suit with other namings as well (virDomain*,
virAdmServer*, etc.).
Because in virt-admin, the connection name does not refer to a struct
that would have a connect in its name, also adjust 'connname' in
clients. And because it is not used anywhere in the vsh code, move it
from there into each client.
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
2015-11-25 16:59:30 +01:00
|
|
|
virtAdminCtl.name = vshStrdup(ctl, defaultConn);
|
2015-10-12 17:07:21 +02:00
|
|
|
|
|
|
|
if (!vshInit(ctl, cmdGroups, NULL))
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
|
|
|
|
if (!vshAdmParseArgv(ctl, argc, argv) ||
|
|
|
|
!vshAdmInit(ctl)) {
|
|
|
|
vshAdmDeinit(ctl);
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!ctl->imode) {
|
|
|
|
ret = vshCommandRun(ctl, ctl->cmd);
|
|
|
|
} else {
|
|
|
|
/* interactive mode */
|
|
|
|
if (!ctl->quiet) {
|
|
|
|
vshPrint(ctl,
|
|
|
|
_("Welcome to %s, the administrating virtualization "
|
|
|
|
"interactive terminal.\n\n"),
|
|
|
|
progname);
|
|
|
|
vshPrint(ctl, "%s",
|
|
|
|
_("Type: 'help' for help with commands\n"
|
|
|
|
" 'quit' to quit\n\n"));
|
|
|
|
}
|
|
|
|
|
|
|
|
do {
|
|
|
|
ctl->cmdstr = vshReadline(ctl, VIRT_ADMIN_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 */
|
|
|
|
}
|
|
|
|
|
|
|
|
vshAdmDeinit(ctl);
|
|
|
|
exit(ret ? EXIT_SUCCESS : EXIT_FAILURE);
|
|
|
|
}
|