提交 85d45ff0 编写于 作者: D Daniel P. Berrange 提交者: Daniel P. Berrangé

logd: add support for admin protocol in virtlogd

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: NDaniel P. Berrange <berrange@redhat.com>
上级 8aca1410
......@@ -2670,6 +2670,7 @@ virtlogd_LDFLAGS = \
$(PIE_LDFLAGS) \
$(NULL)
virtlogd_LDADD = \
libvirt_driver_admin.la \
libvirt-net-rpc-server.la \
libvirt-net-rpc.la \
libvirt_util.la \
......
......@@ -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,
......
......@@ -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);
......
......@@ -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)
......
......@@ -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;
......
......@@ -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" }
[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
......@@ -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"
......
[Unit]
Description=Virtual machine log manager
Requires=virtlogd.socket
Requires=virtlogd-admin.socket
Before=libvirtd.service
Documentation=man:virtlogd(8)
Documentation=https://libvirt.org
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册