Add a virtlogd-admin-sock can serves the admin protocol for the virtlogd daemon and define a virtlogd:///{system,session} URI scheme for connecting to it. Signed-off-by: Daniel P. Berrange <berrange@xxxxxxxxxx> --- src/Makefile.am | 1 + src/libvirt-admin.c | 20 +++-- src/logging/log_daemon.c | 149 +++++++++++++++++++++++++++-------- src/logging/log_daemon_config.c | 3 + src/logging/log_daemon_config.h | 1 + src/logging/test_virtlogd.aug.in | 4 + src/logging/virtlogd-admin.socket.in | 10 +++ src/logging/virtlogd.aug | 1 + src/logging/virtlogd.service.in | 1 + 9 files changed, 149 insertions(+), 41 deletions(-) create mode 100644 src/logging/virtlogd-admin.socket.in diff --git a/src/Makefile.am b/src/Makefile.am index fd8756f10c..828306fd35 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -2672,6 +2672,7 @@ virtlogd_LDFLAGS = \ $(PIE_LDFLAGS) \ $(NULL) virtlogd_LDADD = \ + libvirt_driver_admin.la \ libvirt-net-rpc-server.la \ libvirt-net-rpc.la \ libvirt_util.la \ diff --git a/src/libvirt-admin.c b/src/libvirt-admin.c index 48e6d7fc8a..9d1bff536b 100644 --- a/src/libvirt-admin.c +++ b/src/libvirt-admin.c @@ -38,8 +38,9 @@ #define VIR_FROM_THIS VIR_FROM_ADMIN -#define LIBVIRTD_ADMIN_SOCK_NAME "/libvirt-admin-sock" -#define LIBVIRTD_ADMIN_UNIX_SOCKET LOCALSTATEDIR "/run/libvirt" LIBVIRTD_ADMIN_SOCK_NAME +#define LIBVIRTD_ADMIN_SOCK_NAME "libvirt-admin-sock" +#define VIRTLOGD_ADMIN_SOCK_NAME "virtlogd-admin-sock" + VIR_LOG_INIT("libvirt-admin"); @@ -128,18 +129,25 @@ getSocketPath(virURIPtr uri) } if (!sock_path) { - if (STRNEQ_NULLABLE(uri->scheme, "libvirtd")) { + const char *sockbase = NULL; + if (STREQ_NULLABLE(uri->scheme, "libvirtd")) { + sockbase = LIBVIRTD_ADMIN_SOCK_NAME; + } else if (STREQ_NULLABLE(uri->scheme, "virtlogd")) { + sockbase = VIRTLOGD_ADMIN_SOCK_NAME; + } else { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Unsupported URI scheme '%s'"), NULLSTR(uri->scheme)); goto error; } + if (STREQ_NULLABLE(uri->path, "/system")) { - if (VIR_STRDUP(sock_path, LIBVIRTD_ADMIN_UNIX_SOCKET) < 0) + if (virAsprintf(&sock_path, LOCALSTATEDIR "/run/libvirt/%s", + sockbase) < 0) goto error; } else if (STREQ_NULLABLE(uri->path, "/session")) { - if (!rundir || virAsprintf(&sock_path, "%s%s", rundir, - LIBVIRTD_ADMIN_SOCK_NAME) < 0) + if (!rundir || virAsprintf(&sock_path, "%s/%s", rundir, + sockbase) < 0) goto error; } else { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, diff --git a/src/logging/log_daemon.c b/src/logging/log_daemon.c index 33133af2af..d54d26ab9d 100644 --- a/src/logging/log_daemon.c +++ b/src/logging/log_daemon.c @@ -32,6 +32,7 @@ #include "log_daemon.h" #include "log_daemon_config.h" +#include "admin/admin_server_dispatch.h" #include "virutil.h" #include "virfile.h" #include "virpidfile.h" @@ -137,7 +138,7 @@ static virLogDaemonPtr virLogDaemonNew(virLogDaemonConfigPtr config, bool privileged) { virLogDaemonPtr logd; - virNetServerPtr srv; + virNetServerPtr srv = NULL; if (VIR_ALLOC(logd) < 0) return NULL; @@ -149,6 +150,9 @@ virLogDaemonNew(virLogDaemonConfigPtr config, bool privileged) return NULL; } + if (!(logd->dmn = virNetDaemonNew())) + goto error; + if (!(srv = virNetServerNew("virtlogd", 1, 1, 1, 0, config->max_clients, config->max_clients, -1, 0, @@ -159,8 +163,22 @@ virLogDaemonNew(virLogDaemonConfigPtr config, bool privileged) (void*)(intptr_t)(privileged ? 0x1 : 0x0)))) goto error; - if (!(logd->dmn = virNetDaemonNew()) || - virNetDaemonAddServer(logd->dmn, srv) < 0) + if (virNetDaemonAddServer(logd->dmn, srv) < 0) + goto error; + virObjectUnref(srv); + srv = NULL; + + if (!(srv = virNetServerNew("admin", 1, + 1, 1, 0, config->admin_max_clients, + config->admin_max_clients, -1, 0, + NULL, + remoteAdmClientNew, + remoteAdmClientPreExecRestart, + remoteAdmClientFree, + logd->dmn))) + goto error; + + if (virNetDaemonAddServer(logd->dmn, srv) < 0) goto error; virObjectUnref(srv); srv = NULL; @@ -189,7 +207,7 @@ virLogDaemonGetHandler(virLogDaemonPtr dmn) static virNetServerPtr -virLogDaemonNewServerPostExecRestart(virNetDaemonPtr dmn ATTRIBUTE_UNUSED, +virLogDaemonNewServerPostExecRestart(virNetDaemonPtr dmn, const char *name, virJSONValuePtr object, void *opaque) @@ -202,6 +220,14 @@ virLogDaemonNewServerPostExecRestart(virNetDaemonPtr dmn ATTRIBUTE_UNUSED, virLogDaemonClientPreExecRestart, virLogDaemonClientFree, opaque); + } else if (STREQ(name, "admin")) { + return virNetServerNewPostExecRestart(object, + name, + remoteAdmClientNew, + remoteAdmClientNewPostExecRestart, + remoteAdmClientPreExecRestart, + remoteAdmClientFree, + dmn); } else { virReportError(VIR_ERR_INTERNAL_ERROR, _("Unexpected server name '%s' during restart"), @@ -354,10 +380,12 @@ virLogDaemonForkIntoBackground(const char *argv0) static int virLogDaemonUnixSocketPaths(bool privileged, - char **sockfile) + char **sockfile, + char **adminSockfile) { if (privileged) { - if (VIR_STRDUP(*sockfile, LOCALSTATEDIR "/run/libvirt/virtlogd-sock") < 0) + if (VIR_STRDUP(*sockfile, LOCALSTATEDIR "/run/libvirt/virtlogd-sock") < 0 || + VIR_STRDUP(*adminSockfile, LOCALSTATEDIR "/run/libvirt/virtlogd-admin-sock") < 0) goto error; } else { char *rundir = NULL; @@ -374,7 +402,8 @@ virLogDaemonUnixSocketPaths(bool privileged, } umask(old_umask); - if (virAsprintf(sockfile, "%s/virtlogd-sock", rundir) < 0) { + if (virAsprintf(sockfile, "%s/virtlogd-sock", rundir) < 0 || + virAsprintf(adminSockfile, "%s/virtlogd-admin-sock", rundir) < 0) { VIR_FREE(rundir); goto error; } @@ -485,29 +514,50 @@ virLogDaemonSetupSignals(virNetDaemonPtr dmn) static int -virLogDaemonSetupNetworkingSystemD(virNetServerPtr srv) +virLogDaemonSetupNetworkingSystemD(virNetServerPtr logSrv, virNetServerPtr adminSrv) { - virNetServerServicePtr svc; unsigned int nfds; + size_t i; if ((nfds = virGetListenFDs()) == 0) return 0; - if (nfds > 1) + if (nfds > 2) VIR_DEBUG("Too many (%d) file descriptors from systemd", nfds); - nfds = 1; - /* Systemd passes FDs, starting immediately after stderr, - * so the first FD we'll get is '3'. */ - if (!(svc = virNetServerServiceNewFD(3, 0, + for (i = 0; i < nfds && i < 2; i++) { + virNetServerServicePtr svc; + char *path = virGetUNIXSocketPath(3 + i); + virNetServerPtr srv; + + if (!path) + return -1; + + if (strstr(path, "virtlogd-admin-sock")) { + srv = adminSrv; + } else if (strstr(path, "virtlogd-sock")) { + srv = logSrv; + } else { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unknown UNIX socket %s passed in"), + path); + VIR_FREE(path); + return -1; + } + VIR_FREE(path); + + /* Systemd passes FDs, starting immediately after stderr, + * so the first FD we'll get is '3'. */ + if (!(svc = virNetServerServiceNewFD(3 + i, 0, #if WITH_GNUTLS - NULL, + NULL, #endif - false, 0, 1))) - return -1; + false, 0, 1))) + return -1; - if (virNetServerAddService(srv, svc, NULL) < 0) { - virObjectUnref(svc); - return -1; + if (virNetServerAddService(srv, svc, NULL) < 0) { + virObjectUnref(svc); + return -1; + } } return 1; } @@ -878,8 +928,10 @@ virLogDaemonUsage(const char *argv0, bool privileged) } int main(int argc, char **argv) { - virNetServerPtr srv = NULL; + virNetServerPtr logSrv = NULL; + virNetServerPtr adminSrv = NULL; virNetServerProgramPtr logProgram = NULL; + virNetServerProgramPtr adminProgram = NULL; char *remote_config_file = NULL; int statuswrite = -1; int ret = 1; @@ -889,6 +941,7 @@ int main(int argc, char **argv) { char *pid_file = NULL; int pid_file_fd = -1; char *sock_file = NULL; + char *admin_sock_file = NULL; int timeout = -1; /* -t: Shutdown timeout */ char *state_file = NULL; bool implicit_conf = false; @@ -1016,12 +1069,13 @@ int main(int argc, char **argv) { VIR_DEBUG("Decided on pid file path '%s'", NULLSTR(pid_file)); if (virLogDaemonUnixSocketPaths(privileged, - &sock_file) < 0) { + &sock_file, + &admin_sock_file) < 0) { VIR_ERROR(_("Can't determine socket paths")); exit(EXIT_FAILURE); } - VIR_DEBUG("Decided on socket paths '%s'", - sock_file); + VIR_DEBUG("Decided on socket paths '%s' and '%s'", + sock_file, admin_sock_file); if (virLogDaemonExecRestartStatePath(privileged, &state_file) < 0) { @@ -1098,22 +1152,30 @@ int main(int argc, char **argv) { goto cleanup; } - srv = virNetDaemonGetServer(logDaemon->dmn, "virtlogd"); - if ((rv = virLogDaemonSetupNetworkingSystemD(srv)) < 0) { + logSrv = virNetDaemonGetServer(logDaemon->dmn, "virtlogd"); + adminSrv = virNetDaemonGetServer(logDaemon->dmn, "admin"); + if ((rv = virLogDaemonSetupNetworkingSystemD(logSrv, adminSrv)) < 0) { ret = VIR_LOG_DAEMON_ERR_NETWORK; goto cleanup; } /* Only do this, if systemd did not pass a FD */ - if (rv == 0 && - virLogDaemonSetupNetworkingNative(srv, sock_file) < 0) { - ret = VIR_LOG_DAEMON_ERR_NETWORK; - goto cleanup; + if (rv == 0) { + if (virLogDaemonSetupNetworkingNative(logSrv, sock_file) < 0 || + virLogDaemonSetupNetworkingNative(adminSrv, admin_sock_file) < 0) { + ret = VIR_LOG_DAEMON_ERR_NETWORK; + goto cleanup; + } } - virObjectUnref(srv); + virObjectUnref(logSrv); + virObjectUnref(adminSrv); } - srv = virNetDaemonGetServer(logDaemon->dmn, "virtlogd"); + logSrv = virNetDaemonGetServer(logDaemon->dmn, "virtlogd"); + /* If exec-restarting from old virtlogd, we won't have an + * admin server present */ + if (virNetDaemonHasServer(logDaemon->dmn, "admin")) + adminSrv = virNetDaemonGetServer(logDaemon->dmn, "admin"); if (timeout != -1) { VIR_DEBUG("Registering shutdown timeout %d", timeout); @@ -1133,11 +1195,25 @@ int main(int argc, char **argv) { ret = VIR_LOG_DAEMON_ERR_INIT; goto cleanup; } - if (virNetServerAddProgram(srv, logProgram) < 0) { + if (virNetServerAddProgram(logSrv, logProgram) < 0) { ret = VIR_LOG_DAEMON_ERR_INIT; goto cleanup; } + if (adminSrv != NULL) { + if (!(adminProgram = virNetServerProgramNew(ADMIN_PROGRAM, + ADMIN_PROTOCOL_VERSION, + adminProcs, + adminNProcs))) { + ret = VIR_LOG_DAEMON_ERR_INIT; + goto cleanup; + } + if (virNetServerAddProgram(adminSrv, adminProgram) < 0) { + ret = VIR_LOG_DAEMON_ERR_INIT; + goto cleanup; + } + } + /* Disable error func, now logging is setup */ virSetErrorFunc(NULL, virLogDaemonErrorHandler); @@ -1155,7 +1231,7 @@ int main(int argc, char **argv) { /* Start accepting new clients from network */ - virNetServerUpdateServices(srv, true); + virNetDaemonUpdateServices(logDaemon->dmn, true); virNetDaemonRun(logDaemon->dmn); if (execRestart && @@ -1168,7 +1244,9 @@ int main(int argc, char **argv) { cleanup: virObjectUnref(logProgram); - virObjectUnref(srv); + virObjectUnref(adminProgram); + virObjectUnref(logSrv); + virObjectUnref(adminSrv); virLogDaemonFree(logDaemon); if (statuswrite != -1) { if (ret != 0) { @@ -1184,6 +1262,7 @@ int main(int argc, char **argv) { virPidFileReleasePath(pid_file, pid_file_fd); VIR_FREE(pid_file); VIR_FREE(sock_file); + VIR_FREE(admin_sock_file); VIR_FREE(state_file); VIR_FREE(run_dir); VIR_FREE(remote_config_file); diff --git a/src/logging/log_daemon_config.c b/src/logging/log_daemon_config.c index cf58e6230e..3226b2c484 100644 --- a/src/logging/log_daemon_config.c +++ b/src/logging/log_daemon_config.c @@ -73,6 +73,7 @@ virLogDaemonConfigNew(bool privileged ATTRIBUTE_UNUSED) return NULL; data->max_clients = 1024; + data->admin_max_clients = 5000; data->max_size = 1024 * 1024 * 2; data->max_backups = 3; @@ -103,6 +104,8 @@ virLogDaemonConfigLoadOptions(virLogDaemonConfigPtr data, return -1; if (virConfGetValueUInt(conf, "max_clients", &data->max_clients) < 0) return -1; + if (virConfGetValueUInt(conf, "admin_max_clients", &data->admin_max_clients) < 0) + return -1; if (virConfGetValueSizeT(conf, "max_size", &data->max_size) < 0) return -1; if (virConfGetValueSizeT(conf, "max_backups", &data->max_backups) < 0) diff --git a/src/logging/log_daemon_config.h b/src/logging/log_daemon_config.h index 72d77d5e6f..53101b0610 100644 --- a/src/logging/log_daemon_config.h +++ b/src/logging/log_daemon_config.h @@ -34,6 +34,7 @@ struct _virLogDaemonConfig { char *log_filters; char *log_outputs; unsigned int max_clients; + unsigned int admin_max_clients; size_t max_backups; size_t max_size; diff --git a/src/logging/test_virtlogd.aug.in b/src/logging/test_virtlogd.aug.in index 3e6888fd48..ee3fae5cde 100644 --- a/src/logging/test_virtlogd.aug.in +++ b/src/logging/test_virtlogd.aug.in @@ -2,6 +2,8 @@ module Test_virtlogd = let conf = "log_level = 3 log_filters=\"3:remote 4:event\" log_outputs=\"3:syslog:virtlogd\" +max_clients = 10 +admin_max_clients = 10 max_size = 131072 max_backups = 3 " @@ -10,5 +12,7 @@ max_backups = 3 { "log_level" = "3" } { "log_filters" = "3:remote 4:event" } { "log_outputs" = "3:syslog:virtlogd" } + { "max_clients" = "10" } + { "admin_max_clients" = "10" } { "max_size" = "131072" } { "max_backups" = "3" } diff --git a/src/logging/virtlogd-admin.socket.in b/src/logging/virtlogd-admin.socket.in new file mode 100644 index 0000000000..595e6c4c4b --- /dev/null +++ b/src/logging/virtlogd-admin.socket.in @@ -0,0 +1,10 @@ +[Unit] +Description=Virtual machine log manager socket +Before=libvirtd.service + +[Socket] +ListenStream=@localstatedir@/run/libvirt/virtlogd-admin-sock +Service=virtlogd.service + +[Install] +WantedBy=sockets.target diff --git a/src/logging/virtlogd.aug b/src/logging/virtlogd.aug index 5ed174230d..4fdcba72af 100644 --- a/src/logging/virtlogd.aug +++ b/src/logging/virtlogd.aug @@ -29,6 +29,7 @@ module Virtlogd = | str_entry "log_outputs" | int_entry "log_buffer_size" | int_entry "max_clients" + | int_entry "admin_max_clients" | int_entry "max_size" | int_entry "max_backups" diff --git a/src/logging/virtlogd.service.in b/src/logging/virtlogd.service.in index aa9aa698b5..3d9ae36150 100644 --- a/src/logging/virtlogd.service.in +++ b/src/logging/virtlogd.service.in @@ -1,6 +1,7 @@ [Unit] Description=Virtual machine log manager Requires=virtlogd.socket +Requires=virtlogd-admin.socket Before=libvirtd.service Documentation=man:virtlogd(8) Documentation=https://libvirt.org -- 2.14.3 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list