mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-27 16:15:23 +00:00
b9d8cadeaa
Change the logic in a way, so that VSH_CMD_FLAG_ALIAS behaves similarly to how VSH_OT_ALIAS for command options, i.e. there is no need for code duplication for the alias and the aliased command structures. Along with that change, switch any existing VSH_CMD_FLAG_ALIAS occurrences to this new format. Also, since this patch introduces a new command structure element, adjust the virsh-self-test test to make sure we won't ever miss to specify the '.alias' member for an aliased command because doing that would lead to an internal error. Signed-off-by: Erik Skultety <eskultet@redhat.com>
576 lines
22 KiB
C
576 lines
22 KiB
C
/*
|
|
* vsh.h: common data to be used by clients to exercise the libvirt API
|
|
*
|
|
* Copyright (C) 2005, 2007-2015 Red Hat, Inc.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library. If not, see
|
|
* <http://www.gnu.org/licenses/>.
|
|
*
|
|
* Daniel Veillard <veillard@redhat.com>
|
|
* Karel Zak <kzak@redhat.com>
|
|
* Daniel P. Berrange <berrange@redhat.com>
|
|
*/
|
|
|
|
#ifndef VSH_H
|
|
# define VSH_H
|
|
|
|
# include <stdio.h>
|
|
# include <stdlib.h>
|
|
# include <string.h>
|
|
# include <stdarg.h>
|
|
# include <unistd.h>
|
|
# include <sys/stat.h>
|
|
# include <termios.h>
|
|
|
|
# include "internal.h"
|
|
# include "virerror.h"
|
|
# include "virthread.h"
|
|
|
|
# define VIR_FROM_THIS VIR_FROM_NONE
|
|
|
|
# define GETTIMEOFDAY(T) gettimeofday(T, NULL)
|
|
# define VSH_MAX_XML_FILE (10*1024*1024)
|
|
# define VSH_MATCH(FLAG) (flags & (FLAG))
|
|
|
|
/**
|
|
* The log configuration
|
|
*/
|
|
# define MSG_BUFFER 4096
|
|
# define DIR_MODE (S_IWUSR | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) /* 0755 */
|
|
# define FILE_MODE (S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH) /* 0644 */
|
|
# define LOCK_MODE (S_IWUSR | S_IRUSR) /* 0600 */
|
|
# define LVL_DEBUG "DEBUG"
|
|
# define LVL_INFO "INFO"
|
|
# define LVL_NOTICE "NOTICE"
|
|
# define LVL_WARNING "WARNING"
|
|
# define LVL_ERROR "ERROR"
|
|
|
|
/**
|
|
* vshErrorLevel:
|
|
*
|
|
* Indicates the level of a log message
|
|
*/
|
|
typedef enum {
|
|
VSH_ERR_DEBUG = 0,
|
|
VSH_ERR_INFO,
|
|
VSH_ERR_NOTICE,
|
|
VSH_ERR_WARNING,
|
|
VSH_ERR_ERROR
|
|
} vshErrorLevel;
|
|
|
|
# define VSH_DEBUG_DEFAULT VSH_ERR_ERROR
|
|
|
|
/*
|
|
* virsh command line grammar:
|
|
*
|
|
* command_line = <command>\n | <command>; <command>; ...
|
|
*
|
|
* command = <keyword> <option> [--] <data>
|
|
*
|
|
* option = <bool_option> | <int_option> | <string_option>
|
|
* data = <string>
|
|
*
|
|
* bool_option = --optionname
|
|
* int_option = --optionname <number> | --optionname=<number>
|
|
* string_option = --optionname <string> | --optionname=<string>
|
|
*
|
|
* keyword = [a-zA-Z][a-zA-Z-]*
|
|
* number = [0-9]+
|
|
* string = ('[^']*'|"([^\\"]|\\.)*"|([^ \t\n\\'"]|\\.))+
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* vshCmdOptType - command option type
|
|
*/
|
|
typedef enum {
|
|
VSH_OT_BOOL, /* optional boolean option */
|
|
VSH_OT_STRING, /* optional string option */
|
|
VSH_OT_INT, /* optional or mandatory int option */
|
|
VSH_OT_DATA, /* string data (as non-option) */
|
|
VSH_OT_ARGV, /* remaining arguments */
|
|
VSH_OT_ALIAS, /* alternate spelling for a later argument */
|
|
} vshCmdOptType;
|
|
|
|
/*
|
|
* Command Option Flags
|
|
*/
|
|
enum {
|
|
VSH_OFLAG_NONE = 0, /* without flags */
|
|
VSH_OFLAG_REQ = (1 << 0), /* option required */
|
|
VSH_OFLAG_EMPTY_OK = (1 << 1), /* empty string option allowed */
|
|
VSH_OFLAG_REQ_OPT = (1 << 2), /* --optionname required */
|
|
};
|
|
|
|
/* forward declarations */
|
|
typedef struct _vshClientHooks vshClientHooks;
|
|
typedef struct _vshCmd vshCmd;
|
|
typedef struct _vshCmdDef vshCmdDef;
|
|
typedef struct _vshCmdGrp vshCmdGrp;
|
|
typedef struct _vshCmdInfo vshCmdInfo;
|
|
typedef struct _vshCmdOpt vshCmdOpt;
|
|
typedef struct _vshCmdOptDef vshCmdOptDef;
|
|
typedef struct _vshControl vshControl;
|
|
|
|
typedef char **(*vshCompleter)(void *opaque, unsigned int flags);
|
|
|
|
/*
|
|
* vshCmdInfo -- name/value pair for information about command
|
|
*
|
|
* Commands should have at least the following names:
|
|
* "help" - short description of command
|
|
* "desc" - description of command, or empty string
|
|
*/
|
|
struct _vshCmdInfo {
|
|
const char *name; /* name of information, or NULL for list end */
|
|
const char *data; /* non-NULL information */
|
|
};
|
|
|
|
/*
|
|
* vshCmdOptDef - command option definition
|
|
*/
|
|
struct _vshCmdOptDef {
|
|
const char *name; /* the name of option, or NULL for list end */
|
|
vshCmdOptType type; /* option type */
|
|
unsigned int flags; /* flags */
|
|
const char *help; /* non-NULL help string; or for VSH_OT_ALIAS
|
|
* the name of a later public option */
|
|
vshCompleter completer; /* option completer */
|
|
unsigned int completer_flags; /* option completer flags */
|
|
};
|
|
|
|
/*
|
|
* vshCmdOpt - command options
|
|
*
|
|
* After parsing a command, all arguments to the command have been
|
|
* collected into a list of these objects.
|
|
*/
|
|
struct _vshCmdOpt {
|
|
const vshCmdOptDef *def; /* non-NULL pointer to option definition */
|
|
char *data; /* allocated data, or NULL for bool option */
|
|
vshCmdOpt *next;
|
|
};
|
|
|
|
/*
|
|
* Command Usage Flags
|
|
*/
|
|
enum {
|
|
VSH_CMD_FLAG_NOCONNECT = (1 << 0), /* no prior connection needed */
|
|
VSH_CMD_FLAG_ALIAS = (1 << 1), /* command is an alias */
|
|
};
|
|
|
|
/*
|
|
* vshCmdDef - command definition
|
|
*/
|
|
struct _vshCmdDef {
|
|
const char *name; /* name of command, or NULL for list end */
|
|
bool (*handler) (vshControl *, const vshCmd *); /* command handler */
|
|
const vshCmdOptDef *opts; /* definition of command options */
|
|
const vshCmdInfo *info; /* details about command */
|
|
unsigned int flags; /* bitwise OR of VSH_CMD_FLAG */
|
|
const char *alias; /* name of the aliased command */
|
|
};
|
|
|
|
/*
|
|
* vshCmd - parsed command
|
|
*/
|
|
struct _vshCmd {
|
|
const vshCmdDef *def; /* command definition */
|
|
vshCmdOpt *opts; /* list of command arguments */
|
|
vshCmd *next; /* next command */
|
|
};
|
|
|
|
/*
|
|
* vshControl
|
|
*/
|
|
struct _vshControl {
|
|
const char *name; /* hardcoded name of the binary that cannot
|
|
* be changed without recompilation compared
|
|
* to program name */
|
|
const char *env_prefix; /* hardcoded environment variable prefix */
|
|
char *connname; /* connection name */
|
|
char *progname; /* program name */
|
|
vshCmd *cmd; /* the current command */
|
|
char *cmdstr; /* string with command */
|
|
bool imode; /* interactive mode? */
|
|
bool quiet; /* quiet mode */
|
|
bool timing; /* print timing info? */
|
|
int debug; /* print debug messages? */
|
|
char *logfile; /* log file name */
|
|
int log_fd; /* log file descriptor */
|
|
char *historydir; /* readline history directory name */
|
|
char *historyfile; /* readline history file name */
|
|
virThread eventLoop;
|
|
virMutex lock;
|
|
bool eventLoopStarted;
|
|
bool quit;
|
|
int eventPipe[2]; /* Write-to-self pipe to end waiting for an
|
|
* event to occur */
|
|
int eventTimerId; /* id of event loop timeout registration */
|
|
|
|
int keepalive_interval; /* Client keepalive interval */
|
|
int keepalive_count; /* Client keepalive count */
|
|
|
|
# ifndef WIN32
|
|
struct termios termattr; /* settings of the tty terminal */
|
|
# endif
|
|
bool istty; /* is the terminal a tty */
|
|
|
|
const vshClientHooks *hooks;/* mandatory client specific hooks */
|
|
void *privData; /* client specific data */
|
|
};
|
|
|
|
typedef void *
|
|
(*vshConnectionHook)(vshControl *ctl);
|
|
|
|
struct _vshClientHooks {
|
|
vshConnectionHook connHandler;
|
|
};
|
|
|
|
struct _vshCmdGrp {
|
|
const char *name; /* name of group, or NULL for list end */
|
|
const char *keyword; /* help keyword */
|
|
const vshCmdDef *commands;
|
|
};
|
|
|
|
void vshError(vshControl *ctl, const char *format, ...)
|
|
ATTRIBUTE_FMT_PRINTF(2, 3);
|
|
void vshOpenLogFile(vshControl *ctl);
|
|
void vshOutputLogFile(vshControl *ctl, int log_level, const char *format,
|
|
va_list ap)
|
|
ATTRIBUTE_FMT_PRINTF(3, 0);
|
|
void vshCloseLogFile(vshControl *ctl);
|
|
|
|
const char *vshCmddefGetInfo(const vshCmdDef *cmd, const char *info);
|
|
const vshCmdDef *vshCmddefSearch(const char *cmdname);
|
|
bool vshCmddefHelp(vshControl *ctl, const char *name);
|
|
const vshCmdGrp *vshCmdGrpSearch(const char *grpname);
|
|
bool vshCmdGrpHelp(vshControl *ctl, const char *name);
|
|
|
|
int vshCommandOptInt(vshControl *ctl, const vshCmd *cmd,
|
|
const char *name, int *value)
|
|
ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK;
|
|
int vshCommandOptUInt(vshControl *ctl, const vshCmd *cmd,
|
|
const char *name, unsigned int *value)
|
|
ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK;
|
|
int vshCommandOptUIntWrap(vshControl *ctl, const vshCmd *cmd,
|
|
const char *name, unsigned int *value)
|
|
ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK;
|
|
int vshCommandOptUL(vshControl *ctl, const vshCmd *cmd,
|
|
const char *name, unsigned long *value)
|
|
ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK;
|
|
int vshCommandOptULWrap(vshControl *ctl, const vshCmd *cmd,
|
|
const char *name, unsigned long *value)
|
|
ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK;
|
|
int vshCommandOptStringQuiet(vshControl *ctl, const vshCmd *cmd,
|
|
const char *name, const char **value)
|
|
ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK;
|
|
int vshCommandOptStringReq(vshControl *ctl, const vshCmd *cmd,
|
|
const char *name, const char **value)
|
|
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
|
|
ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK;
|
|
int vshCommandOptLongLong(vshControl *ctl, const vshCmd *cmd,
|
|
const char *name, long long *value)
|
|
ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK;
|
|
int vshCommandOptULongLong(vshControl *ctl, const vshCmd *cmd,
|
|
const char *name, unsigned long long *value)
|
|
ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK;
|
|
int vshCommandOptULongLongWrap(vshControl *ctl, const vshCmd *cmd,
|
|
const char *name, unsigned long long *value)
|
|
ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK;
|
|
int vshCommandOptScaledInt(vshControl *ctl, const vshCmd *cmd,
|
|
const char *name, unsigned long long *value,
|
|
int scale, unsigned long long max)
|
|
ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK;
|
|
int vshBlockJobOptionBandwidth(vshControl *ctl,
|
|
const vshCmd *cmd,
|
|
bool bytes,
|
|
unsigned long *bandwidth);
|
|
bool vshCommandOptBool(const vshCmd *cmd, const char *name);
|
|
bool vshCommandRun(vshControl *ctl, const vshCmd *cmd);
|
|
bool vshCommandStringParse(vshControl *ctl, char *cmdstr);
|
|
|
|
const vshCmdOpt *vshCommandOptArgv(vshControl *ctl, const vshCmd *cmd,
|
|
const vshCmdOpt *opt);
|
|
bool vshCommandArgvParse(vshControl *ctl, int nargs, char **argv);
|
|
int vshCommandOptTimeoutToMs(vshControl *ctl, const vshCmd *cmd, int *timeout);
|
|
|
|
void vshPrint(vshControl *ctl, const char *format, ...)
|
|
ATTRIBUTE_FMT_PRINTF(2, 3);
|
|
void vshPrintExtra(vshControl *ctl, const char *format, ...)
|
|
ATTRIBUTE_FMT_PRINTF(2, 3);
|
|
bool vshInit(vshControl *ctl, const vshCmdGrp *groups, const vshCmdDef *set);
|
|
bool vshInitReload(vshControl *ctl);
|
|
void vshDeinit(vshControl *ctl);
|
|
void vshDebug(vshControl *ctl, int level, const char *format, ...)
|
|
ATTRIBUTE_FMT_PRINTF(3, 4);
|
|
|
|
/* User visible sort, so we want locale-specific case comparison. */
|
|
# define vshStrcasecmp(S1, S2) strcasecmp(S1, S2)
|
|
int vshNameSorter(const void *a, const void *b);
|
|
|
|
virTypedParameterPtr vshFindTypedParamByName(const char *name,
|
|
virTypedParameterPtr list,
|
|
int count);
|
|
char *vshGetTypedParamValue(vshControl *ctl, virTypedParameterPtr item)
|
|
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
|
|
|
|
double vshPrettyCapacity(unsigned long long val, const char **unit);
|
|
int vshStringToArray(const char *str, char ***array);
|
|
|
|
/* Given an index, return either the name of that device (non-NULL) or
|
|
* of its parent (NULL if a root). */
|
|
typedef const char * (*vshTreeLookup)(int devid, bool parent, void *opaque);
|
|
int vshTreePrint(vshControl *ctl, vshTreeLookup lookup, void *opaque,
|
|
int num_devices, int devid);
|
|
|
|
/* error handling */
|
|
extern virErrorPtr last_error;
|
|
void vshErrorHandler(void *opaque, virErrorPtr error);
|
|
void vshReportError(vshControl *ctl);
|
|
void vshResetLibvirtError(void);
|
|
void vshSaveLibvirtError(void);
|
|
|
|
/* file handling */
|
|
char *vshEditWriteToTempFile(vshControl *ctl, const char *doc);
|
|
int vshEditFile(vshControl *ctl, const char *filename);
|
|
char *vshEditReadBackFile(vshControl *ctl, const char *filename);
|
|
int vshAskReedit(vshControl *ctl, const char *msg, bool relax_avail);
|
|
|
|
/* terminal modifications */
|
|
bool vshTTYIsInterruptCharacter(vshControl *ctl, const char chr);
|
|
int vshTTYDisableInterrupt(vshControl *ctl);
|
|
int vshTTYRestore(vshControl *ctl);
|
|
int vshTTYMakeRaw(vshControl *ctl, bool report_errors);
|
|
bool vshTTYAvailable(vshControl *ctl);
|
|
|
|
/* waiting for events */
|
|
enum {
|
|
VSH_EVENT_INTERRUPT,
|
|
VSH_EVENT_TIMEOUT,
|
|
VSH_EVENT_DONE,
|
|
};
|
|
void vshEventCleanup(vshControl *ctl);
|
|
void vshEventDone(vshControl *ctl);
|
|
void vshEventLoop(void *opaque);
|
|
int vshEventStart(vshControl *ctl, int timeout_ms);
|
|
void vshEventTimeout(int timer, void *opaque);
|
|
int vshEventWait(vshControl *ctl);
|
|
|
|
/* generic commands */
|
|
extern const vshCmdOptDef opts_help[];
|
|
extern const vshCmdInfo info_help[];
|
|
extern const vshCmdOptDef opts_cd[];
|
|
extern const vshCmdInfo info_cd[];
|
|
extern const vshCmdOptDef opts_echo[];
|
|
extern const vshCmdInfo info_echo[];
|
|
extern const vshCmdInfo info_pwd[];
|
|
extern const vshCmdInfo info_quit[];
|
|
extern const vshCmdInfo info_selftest[];
|
|
|
|
bool cmdHelp(vshControl *ctl, const vshCmd *cmd);
|
|
bool cmdCd(vshControl *ctl, const vshCmd *cmd);
|
|
bool cmdEcho(vshControl *ctl, const vshCmd *cmd);
|
|
bool cmdPwd(vshControl *ctl, const vshCmd *cmd);
|
|
bool cmdQuit(vshControl *ctl, const vshCmd *cmd);
|
|
bool cmdSelfTest(vshControl *ctl, const vshCmd *cmd);
|
|
|
|
# define VSH_CMD_CD \
|
|
{ \
|
|
.name = "cd", \
|
|
.handler = cmdCd, \
|
|
.opts = opts_cd, \
|
|
.info = info_cd, \
|
|
.flags = VSH_CMD_FLAG_NOCONNECT \
|
|
}
|
|
|
|
# define VSH_CMD_ECHO \
|
|
{ \
|
|
.name = "echo", \
|
|
.handler = cmdEcho, \
|
|
.opts = opts_echo, \
|
|
.info = info_echo, \
|
|
.flags = VSH_CMD_FLAG_NOCONNECT \
|
|
}
|
|
|
|
# define VSH_CMD_EXIT \
|
|
{ \
|
|
.name = "exit", \
|
|
.handler = cmdQuit, \
|
|
.opts = NULL, \
|
|
.info = info_quit, \
|
|
.flags = VSH_CMD_FLAG_NOCONNECT \
|
|
}
|
|
|
|
# define VSH_CMD_HELP \
|
|
{ \
|
|
.name = "help", \
|
|
.handler = cmdHelp, \
|
|
.opts = opts_help, \
|
|
.info = info_help, \
|
|
.flags = VSH_CMD_FLAG_NOCONNECT \
|
|
}
|
|
|
|
# define VSH_CMD_PWD \
|
|
{ \
|
|
.name = "pwd", \
|
|
.handler = cmdPwd, \
|
|
.opts = NULL, \
|
|
.info = info_pwd, \
|
|
.flags = VSH_CMD_FLAG_NOCONNECT \
|
|
}
|
|
|
|
# define VSH_CMD_QUIT \
|
|
{ \
|
|
.name = "quit", \
|
|
.handler = cmdQuit, \
|
|
.opts = NULL, \
|
|
.info = info_quit, \
|
|
.flags = VSH_CMD_FLAG_NOCONNECT \
|
|
}
|
|
|
|
# define VSH_CMD_SELF_TEST \
|
|
{ \
|
|
.name = "self-test", \
|
|
.handler = cmdSelfTest, \
|
|
.opts = NULL, \
|
|
.info = info_selftest, \
|
|
.flags = VSH_CMD_FLAG_NOCONNECT | VSH_CMD_FLAG_ALIAS, \
|
|
.alias = "self-test" \
|
|
}
|
|
|
|
|
|
/* readline */
|
|
char * vshReadline(vshControl *ctl, const char *prompt);
|
|
|
|
/* allocation wrappers */
|
|
void *_vshMalloc(vshControl *ctl, size_t sz, const char *filename, int line);
|
|
# define vshMalloc(_ctl, _sz) _vshMalloc(_ctl, _sz, __FILE__, __LINE__)
|
|
|
|
void *_vshCalloc(vshControl *ctl, size_t nmemb, size_t sz,
|
|
const char *filename, int line);
|
|
# define vshCalloc(_ctl, _nmemb, _sz) \
|
|
_vshCalloc(_ctl, _nmemb, _sz, __FILE__, __LINE__)
|
|
|
|
char *_vshStrdup(vshControl *ctl, const char *s, const char *filename,
|
|
int line);
|
|
# define vshStrdup(_ctl, _s) _vshStrdup(_ctl, _s, __FILE__, __LINE__)
|
|
|
|
/* Macros to help dealing with mutually exclusive options. */
|
|
|
|
/* VSH_EXCLUSIVE_OPTIONS_EXPR:
|
|
*
|
|
* @NAME1: String containing the name of the option.
|
|
* @EXPR1: Expression to validate the variable (boolean variable)
|
|
* @NAME2: String containing the name of the option.
|
|
* @EXPR2: Expression to validate the variable (boolean variable)
|
|
*
|
|
* Reject mutually exclusive command options in virsh. Use the
|
|
* provided expression to check the variables.
|
|
*
|
|
* This helper does an early return and therefore it has to be called
|
|
* before anything that would require cleanup.
|
|
*/
|
|
# define VSH_EXCLUSIVE_OPTIONS_EXPR(NAME1, EXPR1, NAME2, EXPR2) \
|
|
if ((EXPR1) && (EXPR2)) { \
|
|
vshError(ctl, _("Options --%s and --%s are mutually exclusive"), \
|
|
NAME1, NAME2); \
|
|
return false; \
|
|
}
|
|
|
|
/* VSH_EXCLUSIVE_OPTIONS:
|
|
*
|
|
* @NAME1: String containing the name of the option.
|
|
* @NAME2: String containing the name of the option.
|
|
*
|
|
* Reject mutually exclusive command options in virsh. Use the
|
|
* vshCommandOptBool call to request them.
|
|
*
|
|
* This helper does an early return and therefore it has to be called
|
|
* before anything that would require cleanup.
|
|
*/
|
|
# define VSH_EXCLUSIVE_OPTIONS(NAME1, NAME2) \
|
|
VSH_EXCLUSIVE_OPTIONS_EXPR(NAME1, vshCommandOptBool(cmd, NAME1), \
|
|
NAME2, vshCommandOptBool(cmd, NAME2))
|
|
|
|
/* VSH_EXCLUSIVE_OPTIONS_VAR:
|
|
*
|
|
* @VARNAME1: Boolean variable containing the value of the option of same name
|
|
* @VARNAME2: Boolean variable containing the value of the option of same name
|
|
*
|
|
* Reject mutually exclusive command options in virsh. Check in variables that
|
|
* contain the value and have same name as the option.
|
|
*
|
|
* This helper does an early return and therefore it has to be called
|
|
* before anything that would require cleanup.
|
|
*/
|
|
# define VSH_EXCLUSIVE_OPTIONS_VAR(VARNAME1, VARNAME2) \
|
|
VSH_EXCLUSIVE_OPTIONS_EXPR(#VARNAME1, VARNAME1, #VARNAME2, VARNAME2)
|
|
|
|
/* Macros to help dealing with required options. */
|
|
|
|
/* VSH_REQUIRE_OPTION_EXPR:
|
|
*
|
|
* @NAME1: String containing the name of the option.
|
|
* @EXPR1: Expression to validate the variable (boolean variable).
|
|
* @NAME2: String containing the name of required option.
|
|
* @EXPR2: Expression to validate the variable (boolean variable).
|
|
*
|
|
* Check if required command options in virsh was set. Use the
|
|
* provided expression to check the variables.
|
|
*
|
|
* This helper does an early return and therefore it has to be called
|
|
* before anything that would require cleanup.
|
|
*/
|
|
# define VSH_REQUIRE_OPTION_EXPR(NAME1, EXPR1, NAME2, EXPR2) \
|
|
do { \
|
|
if ((EXPR1) && !(EXPR2)) { \
|
|
vshError(ctl, _("Option --%s is required by option --%s"), \
|
|
NAME2, NAME1); \
|
|
return false; \
|
|
} \
|
|
} while (0)
|
|
|
|
/* VSH_REQUIRE_OPTION:
|
|
*
|
|
* @NAME1: String containing the name of the option.
|
|
* @NAME2: String containing the name of required option.
|
|
*
|
|
* Check if required command options in virsh was set. Use the
|
|
* vshCommandOptBool call to request them.
|
|
*
|
|
* This helper does an early return and therefore it has to be called
|
|
* before anything that would require cleanup.
|
|
*/
|
|
# define VSH_REQUIRE_OPTION(NAME1, NAME2) \
|
|
VSH_REQUIRE_OPTION_EXPR(NAME1, vshCommandOptBool(cmd, NAME1), \
|
|
NAME2, vshCommandOptBool(cmd, NAME2))
|
|
|
|
/* VSH_REQUIRE_OPTION_VAR:
|
|
*
|
|
* @VARNAME1: Boolean variable containing the value of the option of same name.
|
|
* @VARNAME2: Boolean variable containing the value of required option of
|
|
* same name.
|
|
*
|
|
* Check if required command options in virsh was set. Check in variables
|
|
* that contain the value and have same name as the option.
|
|
*
|
|
* This helper does an early return and therefore it has to be called
|
|
* before anything that would require cleanup.
|
|
*/
|
|
# define VSH_REQUIRE_OPTION_VAR(VARNAME1, VARNAME2) \
|
|
VSH_REQUIRE_OPTION_EXPR(#VARNAME1, VARNAME1, #VARNAME2, VARNAME2)
|
|
|
|
#endif /* VSH_H */
|