mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 05:35:25 +00:00
virt-admin: Introduce first working skeleton
This patch introduces virt-admin client which is based on virsh client, but had to reimplement several methods to meet virt-admin specific needs or remove unnecessary virsh specific logic.
This commit is contained in:
parent
b32f715d5b
commit
6409578790
1
.gitignore
vendored
1
.gitignore
vendored
@ -183,6 +183,7 @@
|
||||
/tools/virt-login-shell
|
||||
/tools/virsh
|
||||
/tools/virsh-*-edit.c
|
||||
/tools/virt-admin
|
||||
/tools/virt-*-validate
|
||||
/tools/virt-sanlock-cleanup
|
||||
/tools/wireshark/src/plugin.c
|
||||
|
@ -276,6 +276,7 @@ tools/virsh-pool.c
|
||||
tools/virsh-secret.c
|
||||
tools/virsh-snapshot.c
|
||||
tools/virsh-volume.c
|
||||
tools/virt-admin.c
|
||||
tools/virt-host-validate-common.c
|
||||
tools/virt-host-validate-lxc.c
|
||||
tools/virt-host-validate-qemu.c
|
||||
|
@ -1,4 +1,4 @@
|
||||
## Copyright (C) 2005-2014 Red Hat, Inc.
|
||||
## Copyright (C) 2005-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
|
||||
@ -63,7 +63,7 @@ confdir = $(sysconfdir)/libvirt
|
||||
conf_DATA =
|
||||
|
||||
bin_SCRIPTS = virt-xml-validate virt-pki-validate
|
||||
bin_PROGRAMS = virsh virt-host-validate
|
||||
bin_PROGRAMS = virsh virt-host-validate virt-admin
|
||||
libexec_SCRIPTS = libvirt-guests.sh
|
||||
|
||||
if WITH_SANLOCK
|
||||
@ -230,6 +230,28 @@ virsh_CFLAGS = \
|
||||
$(PIE_CFLAGS) \
|
||||
$(COVERAGE_CFLAGS) \
|
||||
$(LIBXML_CFLAGS)
|
||||
|
||||
virt_admin_SOURCES = \
|
||||
virt-admin.c virt-admin.h \
|
||||
$(NULL)
|
||||
|
||||
virt_admin_LDFLAGS = \
|
||||
$(AM_LDFLAGS) \
|
||||
$(COVERAGE_LDFLAGS) \
|
||||
$(STATIC_BINARIES) \
|
||||
$(PIE_LDFLAGS) \
|
||||
$(NULL)
|
||||
virt_admin_LDADD = \
|
||||
../src/libvirt-admin.la \
|
||||
libvirt_shell.la \
|
||||
$(LIBXML_LIBS) \
|
||||
$(NULL)
|
||||
virt_admin_CFLAGS = \
|
||||
$(WARN_CFLAGS) \
|
||||
$(PIE_CFLAGS) \
|
||||
$(COVERAGE_CFLAGS) \
|
||||
$(LIBXML_CFLAGS) \
|
||||
$(READLINE_CFLAGS)
|
||||
BUILT_SOURCES =
|
||||
|
||||
if WITH_WIN_ICON
|
||||
|
546
tools/virt-admin.c
Normal file
546
tools/virt-admin.c
Normal file
@ -0,0 +1,546 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
static int
|
||||
vshAdmConnect(vshControl *ctl, unsigned int flags)
|
||||
{
|
||||
vshAdmControlPtr priv = ctl->privData;
|
||||
|
||||
priv->conn = virAdmConnectOpen(ctl->connname, flags);
|
||||
|
||||
if (!priv->conn) {
|
||||
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 {
|
||||
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;
|
||||
|
||||
if (!priv->conn)
|
||||
return ret;
|
||||
|
||||
ret = virAdmConnectClose(priv->conn);
|
||||
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"));
|
||||
priv->conn = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* vshAdmReconnect:
|
||||
*
|
||||
* Reconnect to a daemon's admin server
|
||||
*
|
||||
*/
|
||||
static void
|
||||
vshAdmReconnect(vshControl *ctl)
|
||||
{
|
||||
vshAdmControlPtr priv = ctl->privData;
|
||||
if (priv->conn)
|
||||
priv->wantReconnect = true;
|
||||
|
||||
vshAdmDisconnect(ctl);
|
||||
vshAdmConnect(ctl, 0);
|
||||
|
||||
priv->wantReconnect = false;
|
||||
}
|
||||
|
||||
/* ---------------
|
||||
* 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;
|
||||
|
||||
VIR_FREE(ctl->connname);
|
||||
ctl->connname = vshStrdup(ctl, name);
|
||||
|
||||
vshAdmReconnect(ctl);
|
||||
|
||||
return !!priv->conn;
|
||||
}
|
||||
|
||||
static void *
|
||||
vshAdmConnectionHandler(vshControl *ctl)
|
||||
{
|
||||
vshAdmControlPtr priv = ctl->privData;
|
||||
|
||||
if (!priv->conn)
|
||||
vshAdmReconnect(ctl);
|
||||
|
||||
if (!priv->conn) {
|
||||
vshError(ctl, "%s", _("no valid connection"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return priv->conn;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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);
|
||||
|
||||
if (priv->conn)
|
||||
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;
|
||||
|
||||
if (ctl->connname) {
|
||||
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).
|
||||
*/
|
||||
if (!priv->conn) {
|
||||
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);
|
||||
VIR_FREE(ctl->connname);
|
||||
|
||||
if (priv->conn)
|
||||
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;
|
||||
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':
|
||||
VIR_FREE(ctl->connname);
|
||||
ctl->connname = vshStrdup(ctl, optarg);
|
||||
break;
|
||||
case 'd':
|
||||
if (virStrToLong_i(optarg, NULL, 10, &debug) < 0) {
|
||||
vshError(ctl, _("option %s takes a numeric argument"),
|
||||
longindex == -1 ? "-d" : "--debug");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (debug < VSH_ERR_DEBUG || debug > VSH_ERR_ERROR)
|
||||
vshError(ctl, _("ignoring debug level %d out of range [%d-%d]"),
|
||||
debug, VSH_ERR_DEBUG, VSH_ERR_ERROR);
|
||||
else
|
||||
ctl->debug = debug;
|
||||
break;
|
||||
case '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,
|
||||
{.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 = {
|
||||
.connHandler = vshAdmConnectionHandler
|
||||
};
|
||||
|
||||
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")))
|
||||
ctl->connname = vshStrdup(ctl, defaultConn);
|
||||
|
||||
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);
|
||||
}
|
46
tools/virt-admin.h
Normal file
46
tools/virt-admin.h
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* virt-admin.h: 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/>.
|
||||
*
|
||||
* Erik Skultety <eskultet@redhat.com>
|
||||
*/
|
||||
|
||||
#ifndef VIRT_ADMIN_H
|
||||
# define VIRT_ADMIN_H
|
||||
|
||||
# include "internal.h"
|
||||
# include "vsh.h"
|
||||
|
||||
# define VIR_FROM_THIS VIR_FROM_NONE
|
||||
|
||||
/*
|
||||
* Command group types
|
||||
*/
|
||||
|
||||
typedef struct _vshAdmControl vshAdmControl;
|
||||
typedef vshAdmControl *vshAdmControlPtr;
|
||||
|
||||
/*
|
||||
* adminControl
|
||||
*/
|
||||
struct _vshAdmControl {
|
||||
virAdmConnectPtr conn; /* connection to a daemon's admin server */
|
||||
bool wantReconnect;
|
||||
};
|
||||
|
||||
#endif /* VIRT_ADMIN_H */
|
Loading…
Reference in New Issue
Block a user