mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge tag 'qga-pull-2024-07-23' of https://github.com/kostyanf14/qemu into staging
qga-pull-2024-07-23 # -----BEGIN PGP SIGNATURE----- # # iQIzBAABCAAdFiEEwsLBCepDxjwUI+uE711egWG6hOcFAmafUs0ACgkQ711egWG6 # hOffwQ/+PMFMOq3jwV11Na0GnrFHT0SLlcxNWYGQjE0Q/nwuYWMTKdo2iB9rVC7T # qxaT6PLtTZPgRsJudJ5kkvLFw88Nr6BuWl31tCVeALUO7C0oTg/oRDfYVeH4/jfG # PS5TiM6ie27SvI5lhGZhd9sRAy8N6NGgT6Fh+pS2tVVfftcfVYKVmnzgtvk314A+ # MpeW8ukVruSW+9G+suXaE750g/drZJAoepC5pW1HXdHE+IuzXNdMWZqwMqBZSM5T # X8VcLvMjFrFrfLOP2el6mloriw67aJyKe9Uwsp548HdXfZKrLCmaR7cZK5zKVQDK # Rzolyuw19wNNi0TZAwmP+MBioDiIHcM4nNhVDCHIVCbXzQHa4BhAr/cr8uucyfM5 # hdCWmaTl4Tksk4q4ooHurDWshV26QNRbLRD1Vx1Rhrwz42MmU2VG13PsSWqLj00I # fj1LzhQOmr26cewgayIL7ODwHDXiwKi+6lKS1OyTjXXubucScgxSyTNC785T6Rvk # T58KAnBRD3vDhE7Dn/4KdRClRFY+7R2/jcHdFnA4vfvOVV8ZXp/m0O0wfLEikH6/ # dGDDVBLNG5gqV477++0wdqkYFq6MmON3PH/EA6rgZYc4At5kS+HFNASBvnFRYMGf # dgtyj8jV5uoffqYOqyXxClP6eTgV1EZ0/wKZ8uJipivB7azjnkE= # =xzjT # -----END PGP SIGNATURE----- # gpg: Signature made Tue 23 Jul 2024 04:50:53 PM AEST # gpg: using RSA key C2C2C109EA43C63C1423EB84EF5D5E8161BA84E7 # gpg: Good signature from "Kostiantyn Kostiuk (Upstream PR sign) <kkostiuk@redhat.com>" [unknown] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: C2C2 C109 EA43 C63C 1423 EB84 EF5D 5E81 61BA 84E7 * tag 'qga-pull-2024-07-23' of https://github.com/kostyanf14/qemu: (25 commits) qga/linux: Add new api 'guest-network-get-route' guest-agent: document allow-rpcs in config file section qga/commands-posix: Make ga_wait_child() return boolean qga: centralize logic for disabling/enabling commands qga: allow configuration file path via the cli qga: remove pointless 'blockrpcs_key' variable qga: move declare of QGAConfig struct to top of file qga: don't disable fsfreeze commands if vss_init fails qga: conditionalize schema for commands not supported on other UNIX qga: conditionalize schema for commands requiring utmpx qga: conditionalize schema for commands requiring libudev qga: conditionalize schema for commands requiring fstrim qga: conditionalize schema for commands requiring fsfreeze qga: conditionalize schema for commands only supported on Windows qga: conditionalize schema for commands requiring linux/win32 qga: conditionalize schema for commands requiring getifaddrs qga: conditionalize schema for commands unsupported on non-Linux POSIX qga: conditionalize schema for commands unsupported on Windows qga: move CONFIG_FSFREEZE/TRIM to be meson defined options qga: move linux memory block command impls to commands-linux.c ... Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
@@ -28,11 +28,30 @@ configuration options on the command line. For the same key, the last
|
||||
option wins, but the lists accumulate (see below for configuration
|
||||
file format).
|
||||
|
||||
If an allowed RPCs list is defined in the configuration, then all
|
||||
RPCs will be blocked by default, except for the allowed list.
|
||||
|
||||
If a blocked RPCs list is defined in the configuration, then all
|
||||
RPCs will be allowed by default, except for the blocked list.
|
||||
|
||||
If both allowed and blocked RPCs lists are defined in the configuration,
|
||||
then all RPCs will be blocked by default, then the allowed list will
|
||||
be applied, followed by the blocked list.
|
||||
|
||||
While filesystems are frozen, all except for a designated safe set
|
||||
of RPCs will blocked, regardless of what the general configuration
|
||||
declares.
|
||||
|
||||
Options
|
||||
-------
|
||||
|
||||
.. program:: qemu-ga
|
||||
|
||||
.. option:: -c, --config=PATH
|
||||
|
||||
Configuration file path (the default is |CONFDIR|\ ``/qemu-ga.conf``,
|
||||
unless overriden by the QGA_CONF environment variable)
|
||||
|
||||
.. option:: -m, --method=METHOD
|
||||
|
||||
Transport method: one of ``unix-listen``, ``virtio-serial``, or
|
||||
@@ -131,6 +150,7 @@ fsfreeze-hook string
|
||||
statedir string
|
||||
verbose boolean
|
||||
block-rpcs string list
|
||||
allow-rpcs string list
|
||||
============= ===========
|
||||
|
||||
See also
|
||||
|
||||
+16
@@ -2187,6 +2187,19 @@ have_virtfs_proxy_helper = get_option('virtfs_proxy_helper') \
|
||||
.require(libcap_ng.found(), error_message: 'the virtfs proxy helper requires libcap-ng') \
|
||||
.allowed()
|
||||
|
||||
qga_fsfreeze = false
|
||||
qga_fstrim = false
|
||||
if host_os == 'linux'
|
||||
if cc.has_header_symbol('linux/fs.h', 'FIFREEZE')
|
||||
qga_fsfreeze = true
|
||||
endif
|
||||
if cc.has_header_symbol('linux/fs.h', 'FITRIM')
|
||||
qga_fstrim = true
|
||||
endif
|
||||
elif host_os == 'freebsd' and cc.has_header_symbol('ufs/ffs/fs.h', 'UFSSUSPEND')
|
||||
qga_fsfreeze = true
|
||||
endif
|
||||
|
||||
if get_option('block_drv_ro_whitelist') == ''
|
||||
config_host_data.set('CONFIG_BDRV_RO_WHITELIST', '')
|
||||
else
|
||||
@@ -2263,6 +2276,7 @@ config_host_data.set('CONFIG_ATTR', libattr.found())
|
||||
config_host_data.set('CONFIG_BDRV_WHITELIST_TOOLS', get_option('block_drv_whitelist_in_tools'))
|
||||
config_host_data.set('CONFIG_BRLAPI', brlapi.found())
|
||||
config_host_data.set('CONFIG_BSD', host_os in bsd_oses)
|
||||
config_host_data.set('CONFIG_FREEBSD', host_os == 'freebsd')
|
||||
config_host_data.set('CONFIG_CAPSTONE', capstone.found())
|
||||
config_host_data.set('CONFIG_COCOA', cocoa.found())
|
||||
config_host_data.set('CONFIG_DARWIN', host_os == 'darwin')
|
||||
@@ -2423,6 +2437,8 @@ config_host_data.set('CONFIG_DEBUG_TCG', get_option('debug_tcg'))
|
||||
config_host_data.set('CONFIG_DEBUG_REMAP', get_option('debug_remap'))
|
||||
config_host_data.set('CONFIG_QOM_CAST_DEBUG', get_option('qom_cast_debug'))
|
||||
config_host_data.set('CONFIG_REPLICATION', get_option('replication').allowed())
|
||||
config_host_data.set('CONFIG_FSFREEZE', qga_fsfreeze)
|
||||
config_host_data.set('CONFIG_FSTRIM', qga_fstrim)
|
||||
|
||||
# has_header
|
||||
config_host_data.set('CONFIG_EPOLL', cc.has_header('sys/epoll.h'))
|
||||
|
||||
@@ -149,30 +149,6 @@ int qmp_guest_fsfreeze_do_thaw(Error **errp)
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
GuestFilesystemInfoList *qmp_guest_get_fsinfo(Error **errp)
|
||||
{
|
||||
error_setg(errp, QERR_UNSUPPORTED);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GuestDiskInfoList *qmp_guest_get_disks(Error **errp)
|
||||
{
|
||||
error_setg(errp, QERR_UNSUPPORTED);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GuestDiskStatsInfoList *qmp_guest_get_diskstats(Error **errp)
|
||||
{
|
||||
error_setg(errp, QERR_UNSUPPORTED);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GuestCpuStatsList *qmp_guest_get_cpustats(Error **errp)
|
||||
{
|
||||
error_setg(errp, QERR_UNSUPPORTED);
|
||||
return NULL;
|
||||
}
|
||||
#endif /* CONFIG_FSFREEZE */
|
||||
|
||||
#ifdef HAVE_GETIFADDRS
|
||||
|
||||
@@ -15,19 +15,10 @@
|
||||
|
||||
#if defined(__linux__)
|
||||
#include <linux/fs.h>
|
||||
#ifdef FIFREEZE
|
||||
#define CONFIG_FSFREEZE
|
||||
#endif
|
||||
#ifdef FITRIM
|
||||
#define CONFIG_FSTRIM
|
||||
#endif
|
||||
#endif /* __linux__ */
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <ufs/ffs/fs.h>
|
||||
#ifdef UFSSUSPEND
|
||||
#define CONFIG_FSFREEZE
|
||||
#endif
|
||||
#endif /* __FreeBSD__ */
|
||||
|
||||
#if defined(CONFIG_FSFREEZE) || defined(CONFIG_FSTRIM)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+5
-2022
File diff suppressed because it is too large
Load Diff
+3
-75
@@ -1203,7 +1203,7 @@ GuestFilesystemInfoList *qmp_guest_get_fsinfo(Error **errp)
|
||||
GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **errp)
|
||||
{
|
||||
if (!vss_initialized()) {
|
||||
error_setg(errp, QERR_UNSUPPORTED);
|
||||
error_setg(errp, "fsfreeze not possible as VSS failed to initialize");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1231,7 +1231,7 @@ int64_t qmp_guest_fsfreeze_freeze_list(bool has_mountpoints,
|
||||
Error *local_err = NULL;
|
||||
|
||||
if (!vss_initialized()) {
|
||||
error_setg(errp, QERR_UNSUPPORTED);
|
||||
error_setg(errp, "fsfreeze not possible as VSS failed to initialize");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1266,7 +1266,7 @@ int64_t qmp_guest_fsfreeze_thaw(Error **errp)
|
||||
int i;
|
||||
|
||||
if (!vss_initialized()) {
|
||||
error_setg(errp, QERR_UNSUPPORTED);
|
||||
error_setg(errp, "fsfreeze not possible as VSS failed to initialize");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1494,11 +1494,6 @@ out:
|
||||
}
|
||||
}
|
||||
|
||||
void qmp_guest_suspend_hybrid(Error **errp)
|
||||
{
|
||||
error_setg(errp, QERR_UNSUPPORTED);
|
||||
}
|
||||
|
||||
static IP_ADAPTER_ADDRESSES *guest_get_adapters_addresses(Error **errp)
|
||||
{
|
||||
IP_ADAPTER_ADDRESSES *adptr_addrs = NULL;
|
||||
@@ -1862,12 +1857,6 @@ GuestLogicalProcessorList *qmp_guest_get_vcpus(Error **errp)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int64_t qmp_guest_set_vcpus(GuestLogicalProcessorList *vcpus, Error **errp)
|
||||
{
|
||||
error_setg(errp, QERR_UNSUPPORTED);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static gchar *
|
||||
get_net_error_message(gint error)
|
||||
{
|
||||
@@ -1969,55 +1958,6 @@ done:
|
||||
g_free(rawpasswddata);
|
||||
}
|
||||
|
||||
GuestMemoryBlockList *qmp_guest_get_memory_blocks(Error **errp)
|
||||
{
|
||||
error_setg(errp, QERR_UNSUPPORTED);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GuestMemoryBlockResponseList *
|
||||
qmp_guest_set_memory_blocks(GuestMemoryBlockList *mem_blks, Error **errp)
|
||||
{
|
||||
error_setg(errp, QERR_UNSUPPORTED);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GuestMemoryBlockInfo *qmp_guest_get_memory_block_info(Error **errp)
|
||||
{
|
||||
error_setg(errp, QERR_UNSUPPORTED);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* add unsupported commands to the list of blocked RPCs */
|
||||
GList *ga_command_init_blockedrpcs(GList *blockedrpcs)
|
||||
{
|
||||
const char *list_unsupported[] = {
|
||||
"guest-suspend-hybrid",
|
||||
"guest-set-vcpus",
|
||||
"guest-get-memory-blocks", "guest-set-memory-blocks",
|
||||
"guest-get-memory-block-size", "guest-get-memory-block-info",
|
||||
NULL};
|
||||
char **p = (char **)list_unsupported;
|
||||
|
||||
while (*p) {
|
||||
blockedrpcs = g_list_append(blockedrpcs, g_strdup(*p++));
|
||||
}
|
||||
|
||||
if (!vss_init(true)) {
|
||||
g_debug("vss_init failed, vss commands are going to be disabled");
|
||||
const char *list[] = {
|
||||
"guest-get-fsinfo", "guest-fsfreeze-status",
|
||||
"guest-fsfreeze-freeze", "guest-fsfreeze-thaw", NULL};
|
||||
p = (char **)list;
|
||||
|
||||
while (*p) {
|
||||
blockedrpcs = g_list_append(blockedrpcs, g_strdup(*p++));
|
||||
}
|
||||
}
|
||||
|
||||
return blockedrpcs;
|
||||
}
|
||||
|
||||
/* register init/cleanup routines for stateful command groups */
|
||||
void ga_command_state_init(GAState *s, GACommandState *cs)
|
||||
{
|
||||
@@ -2505,15 +2445,3 @@ char *qga_get_host_name(Error **errp)
|
||||
|
||||
return g_utf16_to_utf8(tmp, size, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
GuestDiskStatsInfoList *qmp_guest_get_diskstats(Error **errp)
|
||||
{
|
||||
error_setg(errp, QERR_UNSUPPORTED);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GuestCpuStatsList *qmp_guest_get_cpustats(Error **errp)
|
||||
{
|
||||
error_setg(errp, QERR_UNSUPPORTED);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+117
-107
@@ -70,6 +70,28 @@ typedef struct GAPersistentState {
|
||||
|
||||
typedef struct GAConfig GAConfig;
|
||||
|
||||
struct GAConfig {
|
||||
char *channel_path;
|
||||
char *method;
|
||||
char *log_filepath;
|
||||
char *pid_filepath;
|
||||
#ifdef CONFIG_FSFREEZE
|
||||
char *fsfreeze_hook;
|
||||
#endif
|
||||
char *state_dir;
|
||||
#ifdef _WIN32
|
||||
const char *service;
|
||||
#endif
|
||||
gchar *bliststr; /* blockedrpcs may point to this string */
|
||||
gchar *aliststr; /* allowedrpcs may point to this string */
|
||||
GList *blockedrpcs;
|
||||
GList *allowedrpcs;
|
||||
int daemonize;
|
||||
GLogLevelFlags log_level;
|
||||
int dumpconf;
|
||||
bool retry_path;
|
||||
};
|
||||
|
||||
struct GAState {
|
||||
JSONMessageParser parser;
|
||||
GMainLoop *main_loop;
|
||||
@@ -226,12 +248,16 @@ static void usage(const char *cmd)
|
||||
#ifdef CONFIG_FSFREEZE
|
||||
g_autofree char *fsfreeze_hook = get_relocated_path(QGA_FSFREEZE_HOOK_DEFAULT);
|
||||
#endif
|
||||
g_autofree char *conf_path = get_relocated_path(QGA_CONF_DEFAULT);
|
||||
|
||||
printf(
|
||||
"Usage: %s [-m <method> -p <path>] [<options>]\n"
|
||||
"QEMU Guest Agent " QEMU_FULL_VERSION "\n"
|
||||
QEMU_COPYRIGHT "\n"
|
||||
"\n"
|
||||
" -c, --config=PATH configuration file path (default is\n"
|
||||
" %s/qemu-ga.conf\n"
|
||||
" unless overriden by the QGA_CONF environment variable)\n"
|
||||
" -m, --method transport method: one of unix-listen, virtio-serial,\n"
|
||||
" isa-serial, or vsock-listen (virtio-serial is the default)\n"
|
||||
" -p, --path device/socket path (the default for virtio-serial is:\n"
|
||||
@@ -272,8 +298,8 @@ QEMU_COPYRIGHT "\n"
|
||||
" plug/unplug, etc.)\n"
|
||||
" -h, --help display this help and exit\n"
|
||||
"\n"
|
||||
QEMU_HELP_BOTTOM "\n"
|
||||
, cmd, QGA_VIRTIO_PATH_DEFAULT, QGA_SERIAL_PATH_DEFAULT,
|
||||
QEMU_HELP_BOTTOM "\n",
|
||||
cmd, conf_path, QGA_VIRTIO_PATH_DEFAULT, QGA_SERIAL_PATH_DEFAULT,
|
||||
dfl_pathnames.pidfile,
|
||||
#ifdef CONFIG_FSFREEZE
|
||||
fsfreeze_hook,
|
||||
@@ -397,58 +423,77 @@ static gint ga_strcmp(gconstpointer str1, gconstpointer str2)
|
||||
return strcmp(str1, str2);
|
||||
}
|
||||
|
||||
/* disable commands that aren't safe for fsfreeze */
|
||||
static void ga_disable_not_allowed_freeze(const QmpCommand *cmd, void *opaque)
|
||||
static bool ga_command_is_allowed(const QmpCommand *cmd, GAState *state)
|
||||
{
|
||||
bool allowed = false;
|
||||
int i = 0;
|
||||
GAConfig *config = state->config;
|
||||
const char *name = qmp_command_name(cmd);
|
||||
/* Fallback policy is allow everything */
|
||||
bool allowed = true;
|
||||
|
||||
while (ga_freeze_allowlist[i] != NULL) {
|
||||
if (strcmp(name, ga_freeze_allowlist[i]) == 0) {
|
||||
if (config->allowedrpcs) {
|
||||
/*
|
||||
* If an allow-list is given, this changes the fallback
|
||||
* policy to deny everything
|
||||
*/
|
||||
allowed = false;
|
||||
|
||||
if (g_list_find_custom(config->allowedrpcs, name, ga_strcmp) != NULL) {
|
||||
allowed = true;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (!allowed) {
|
||||
g_debug("disabling command: %s", name);
|
||||
qmp_disable_command(&ga_commands, name, "the agent is in frozen state");
|
||||
|
||||
/*
|
||||
* If both allowedrpcs and blockedrpcs are set, the blocked
|
||||
* list will take priority
|
||||
*/
|
||||
if (config->blockedrpcs) {
|
||||
if (g_list_find_custom(config->blockedrpcs, name, ga_strcmp) != NULL) {
|
||||
allowed = false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If frozen, this filtering must take priority over
|
||||
* absolutely everything
|
||||
*/
|
||||
if (state->frozen) {
|
||||
allowed = false;
|
||||
|
||||
while (ga_freeze_allowlist[i] != NULL) {
|
||||
if (strcmp(name, ga_freeze_allowlist[i]) == 0) {
|
||||
allowed = true;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
return allowed;
|
||||
}
|
||||
|
||||
/* [re-]enable all commands, except those explicitly blocked by user */
|
||||
static void ga_enable_non_blocked(const QmpCommand *cmd, void *opaque)
|
||||
static void ga_apply_command_filters_iter(const QmpCommand *cmd, void *opaque)
|
||||
{
|
||||
GAState *s = opaque;
|
||||
GList *blockedrpcs = s->blockedrpcs;
|
||||
GList *allowedrpcs = s->allowedrpcs;
|
||||
GAState *state = opaque;
|
||||
bool want = ga_command_is_allowed(cmd, state);
|
||||
bool have = qmp_command_is_enabled(cmd);
|
||||
const char *name = qmp_command_name(cmd);
|
||||
|
||||
if (g_list_find_custom(blockedrpcs, name, ga_strcmp) == NULL) {
|
||||
if (qmp_command_is_enabled(cmd)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (allowedrpcs &&
|
||||
g_list_find_custom(allowedrpcs, name, ga_strcmp) == NULL) {
|
||||
return;
|
||||
}
|
||||
if (want == have) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (have) {
|
||||
g_debug("disabling command: %s", name);
|
||||
qmp_disable_command(&ga_commands, name, "the command is not allowed");
|
||||
} else {
|
||||
g_debug("enabling command: %s", name);
|
||||
qmp_enable_command(&ga_commands, name);
|
||||
}
|
||||
}
|
||||
|
||||
/* disable commands that aren't allowed */
|
||||
static void ga_disable_not_allowed(const QmpCommand *cmd, void *opaque)
|
||||
static void ga_apply_command_filters(GAState *state)
|
||||
{
|
||||
GList *allowedrpcs = opaque;
|
||||
const char *name = qmp_command_name(cmd);
|
||||
|
||||
if (g_list_find_custom(allowedrpcs, name, ga_strcmp) == NULL) {
|
||||
g_debug("disabling command: %s", name);
|
||||
qmp_disable_command(&ga_commands, name, "the command is not allowed");
|
||||
}
|
||||
qmp_for_each_command(&ga_commands, ga_apply_command_filters_iter, state);
|
||||
}
|
||||
|
||||
static bool ga_create_file(const char *path)
|
||||
@@ -483,15 +528,14 @@ void ga_set_frozen(GAState *s)
|
||||
if (ga_is_frozen(s)) {
|
||||
return;
|
||||
}
|
||||
/* disable all forbidden (for frozen state) commands */
|
||||
qmp_for_each_command(&ga_commands, ga_disable_not_allowed_freeze, NULL);
|
||||
g_warning("disabling logging due to filesystem freeze");
|
||||
ga_disable_logging(s);
|
||||
s->frozen = true;
|
||||
if (!ga_create_file(s->state_filepath_isfrozen)) {
|
||||
g_warning("unable to create %s, fsfreeze may not function properly",
|
||||
s->state_filepath_isfrozen);
|
||||
}
|
||||
ga_apply_command_filters(s);
|
||||
ga_disable_logging(s);
|
||||
}
|
||||
|
||||
void ga_unset_frozen(GAState *s)
|
||||
@@ -523,12 +567,12 @@ void ga_unset_frozen(GAState *s)
|
||||
}
|
||||
|
||||
/* enable all disabled, non-blocked and allowed commands */
|
||||
qmp_for_each_command(&ga_commands, ga_enable_non_blocked, s);
|
||||
s->frozen = false;
|
||||
if (!ga_delete_file(s->state_filepath_isfrozen)) {
|
||||
g_warning("unable to delete %s, fsfreeze may not function properly",
|
||||
s->state_filepath_isfrozen);
|
||||
}
|
||||
ga_apply_command_filters(s);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_FSFREEZE
|
||||
@@ -996,38 +1040,14 @@ static GList *split_list(const gchar *str, const gchar *delim)
|
||||
return list;
|
||||
}
|
||||
|
||||
struct GAConfig {
|
||||
char *channel_path;
|
||||
char *method;
|
||||
char *log_filepath;
|
||||
char *pid_filepath;
|
||||
#ifdef CONFIG_FSFREEZE
|
||||
char *fsfreeze_hook;
|
||||
#endif
|
||||
char *state_dir;
|
||||
#ifdef _WIN32
|
||||
const char *service;
|
||||
#endif
|
||||
gchar *bliststr; /* blockedrpcs may point to this string */
|
||||
gchar *aliststr; /* allowedrpcs may point to this string */
|
||||
GList *blockedrpcs;
|
||||
GList *allowedrpcs;
|
||||
int daemonize;
|
||||
GLogLevelFlags log_level;
|
||||
int dumpconf;
|
||||
bool retry_path;
|
||||
};
|
||||
|
||||
static void config_load(GAConfig *config)
|
||||
static void config_load(GAConfig *config, const char *confpath, bool required)
|
||||
{
|
||||
GError *gerr = NULL;
|
||||
GKeyFile *keyfile;
|
||||
g_autofree char *conf = g_strdup(g_getenv("QGA_CONF")) ?: get_relocated_path(QGA_CONF_DEFAULT);
|
||||
const gchar *blockrpcs_key = "block-rpcs";
|
||||
|
||||
/* read system config */
|
||||
keyfile = g_key_file_new();
|
||||
if (!g_key_file_load_from_file(keyfile, conf, 0, &gerr)) {
|
||||
if (!g_key_file_load_from_file(keyfile, confpath, 0, &gerr)) {
|
||||
goto end;
|
||||
}
|
||||
if (g_key_file_has_key(keyfile, "general", "daemon", NULL)) {
|
||||
@@ -1071,9 +1091,9 @@ static void config_load(GAConfig *config)
|
||||
g_key_file_get_boolean(keyfile, "general", "retry-path", &gerr);
|
||||
}
|
||||
|
||||
if (g_key_file_has_key(keyfile, "general", blockrpcs_key, NULL)) {
|
||||
if (g_key_file_has_key(keyfile, "general", "block-rpcs", NULL)) {
|
||||
config->bliststr =
|
||||
g_key_file_get_string(keyfile, "general", blockrpcs_key, &gerr);
|
||||
g_key_file_get_string(keyfile, "general", "block-rpcs", &gerr);
|
||||
config->blockedrpcs = g_list_concat(config->blockedrpcs,
|
||||
split_list(config->bliststr, ","));
|
||||
}
|
||||
@@ -1084,19 +1104,12 @@ static void config_load(GAConfig *config)
|
||||
split_list(config->aliststr, ","));
|
||||
}
|
||||
|
||||
if (g_key_file_has_key(keyfile, "general", blockrpcs_key, NULL) &&
|
||||
g_key_file_has_key(keyfile, "general", "allow-rpcs", NULL)) {
|
||||
g_critical("wrong config, using 'block-rpcs' and 'allow-rpcs' keys at"
|
||||
" the same time is not allowed");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
end:
|
||||
g_key_file_free(keyfile);
|
||||
if (gerr &&
|
||||
!(gerr->domain == G_FILE_ERROR && gerr->code == G_FILE_ERROR_NOENT)) {
|
||||
if (gerr && (required ||
|
||||
!(gerr->domain == G_FILE_ERROR && gerr->code == G_FILE_ERROR_NOENT))) {
|
||||
g_critical("error loading configuration from path: %s, %s",
|
||||
conf, gerr->message);
|
||||
confpath, gerr->message);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
g_clear_error(&gerr);
|
||||
@@ -1168,12 +1181,12 @@ static void config_dump(GAConfig *config)
|
||||
|
||||
static void config_parse(GAConfig *config, int argc, char **argv)
|
||||
{
|
||||
const char *sopt = "hVvdm:p:l:f:F::b:a:s:t:Dr";
|
||||
const char *sopt = "hVvdc:m:p:l:f:F::b:a:s:t:Dr";
|
||||
int opt_ind = 0, ch;
|
||||
bool block_rpcs = false, allow_rpcs = false;
|
||||
const struct option lopt[] = {
|
||||
{ "help", 0, NULL, 'h' },
|
||||
{ "version", 0, NULL, 'V' },
|
||||
{ "config", 1, NULL, 'c' },
|
||||
{ "dump-conf", 0, NULL, 'D' },
|
||||
{ "logfile", 1, NULL, 'l' },
|
||||
{ "pidfile", 1, NULL, 'f' },
|
||||
@@ -1193,6 +1206,26 @@ static void config_parse(GAConfig *config, int argc, char **argv)
|
||||
{ "retry-path", 0, NULL, 'r' },
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
g_autofree char *confpath = g_strdup(g_getenv("QGA_CONF")) ?:
|
||||
get_relocated_path(QGA_CONF_DEFAULT);
|
||||
bool confrequired = false;
|
||||
|
||||
while ((ch = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) {
|
||||
switch (ch) {
|
||||
case 'c':
|
||||
g_free(confpath);
|
||||
confpath = g_strdup(optarg);
|
||||
confrequired = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
config_load(config, confpath, confrequired);
|
||||
|
||||
/* Reset for second pass */
|
||||
optind = 1;
|
||||
|
||||
while ((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) {
|
||||
switch (ch) {
|
||||
@@ -1245,7 +1278,6 @@ static void config_parse(GAConfig *config, int argc, char **argv)
|
||||
}
|
||||
config->blockedrpcs = g_list_concat(config->blockedrpcs,
|
||||
split_list(optarg, ","));
|
||||
block_rpcs = true;
|
||||
break;
|
||||
}
|
||||
case 'a': {
|
||||
@@ -1255,7 +1287,6 @@ static void config_parse(GAConfig *config, int argc, char **argv)
|
||||
}
|
||||
config->allowedrpcs = g_list_concat(config->allowedrpcs,
|
||||
split_list(optarg, ","));
|
||||
allow_rpcs = true;
|
||||
break;
|
||||
}
|
||||
#ifdef _WIN32
|
||||
@@ -1296,12 +1327,6 @@ static void config_parse(GAConfig *config, int argc, char **argv)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
if (block_rpcs && allow_rpcs) {
|
||||
g_critical("wrong commandline, using --block-rpcs and --allow-rpcs at the"
|
||||
" same time is not allowed");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
static void config_free(GAConfig *config)
|
||||
@@ -1395,6 +1420,10 @@ static GAState *initialize_agent(GAConfig *config, int socket_activation)
|
||||
" '%s': %s", config->state_dir, strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!vss_init(true)) {
|
||||
g_debug("vss_init failed, vss commands will not function");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ga_is_frozen(s)) {
|
||||
@@ -1408,7 +1437,6 @@ static GAState *initialize_agent(GAConfig *config, int socket_activation)
|
||||
s->deferred_options.log_filepath = config->log_filepath;
|
||||
}
|
||||
ga_disable_logging(s);
|
||||
qmp_for_each_command(&ga_commands, ga_disable_not_allowed_freeze, NULL);
|
||||
} else {
|
||||
if (config->daemonize) {
|
||||
become_daemon(config->pid_filepath);
|
||||
@@ -1432,25 +1460,6 @@ static GAState *initialize_agent(GAConfig *config, int socket_activation)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (config->allowedrpcs) {
|
||||
qmp_for_each_command(&ga_commands, ga_disable_not_allowed, config->allowedrpcs);
|
||||
s->allowedrpcs = config->allowedrpcs;
|
||||
}
|
||||
|
||||
/*
|
||||
* Some commands can be blocked due to system limitation.
|
||||
* Initialize blockedrpcs list even if allowedrpcs specified.
|
||||
*/
|
||||
config->blockedrpcs = ga_command_init_blockedrpcs(config->blockedrpcs);
|
||||
if (config->blockedrpcs) {
|
||||
GList *l = config->blockedrpcs;
|
||||
s->blockedrpcs = config->blockedrpcs;
|
||||
do {
|
||||
g_debug("disabling command: %s", (char *)l->data);
|
||||
qmp_disable_command(&ga_commands, l->data, NULL);
|
||||
l = g_list_next(l);
|
||||
} while (l);
|
||||
}
|
||||
s->command_state = ga_command_state_new();
|
||||
ga_command_state_init(s, s->command_state);
|
||||
ga_command_state_init_all(s->command_state);
|
||||
@@ -1476,6 +1485,8 @@ static GAState *initialize_agent(GAConfig *config, int socket_activation)
|
||||
}
|
||||
#endif
|
||||
|
||||
ga_apply_command_filters(s);
|
||||
|
||||
ga_state = s;
|
||||
return s;
|
||||
}
|
||||
@@ -1579,7 +1590,6 @@ int main(int argc, char **argv)
|
||||
qga_qmp_init_marshal(&ga_commands);
|
||||
|
||||
init_dfl_pathnames();
|
||||
config_load(config);
|
||||
config_parse(config, argc, argv);
|
||||
|
||||
if (config->pid_filepath == NULL) {
|
||||
|
||||
+175
-51
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user