Dynamically manage service states based on user defined conditions

Old event system has been replaced with a more generic condition
concept. The idea is that finit plugins may provide arbitrary
conditions that services may specify as dependencies that they require
to run.

In order to accomodate this, the service management has been
redesigned to use a state machine.
This commit is contained in:
Tobias Waldekranz
2016-01-05 15:01:58 +01:00
parent 7a3408c173
commit 2232aea0f7
17 changed files with 879 additions and 736 deletions
+1 -1
View File
@@ -8,7 +8,7 @@ LDFLAGS += -shared
ifneq ($(STATIC), 1)
PLUGINS ?= initctl.so alsa-utils.so bootmisc.so dbus.so hwclock.so \
resolvconf.so urandom.so x11-common.so tty.so time.so \
netlink.so
netlink.so pidfile.so
DEPS := $(PLUGINS:.so=.d)
endif
+18 -15
View File
@@ -16,6 +16,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <arpa/inet.h>
#include <errno.h>
#include <net/if.h> /* IFNAMSIZ */
#include <sys/socket.h>
@@ -25,7 +26,7 @@
#include <unistd.h>
#include "../finit.h"
#include "../event.h"
#include "../cond.h"
#include "../helpers.h"
#include "../plugin.h"
@@ -86,13 +87,10 @@ static void nl_route(struct nlmsghdr *nlmsg)
}
if ((!dst && !mask) && (gw || idx)) {
char msg[MAX_ARG_LEN];
if (nlmsg->nlmsg_type == RTM_DELROUTE)
snprintf(msg, sizeof(msg), "GW:DN");
cond_clear("net/gw");
else
snprintf(msg, sizeof(msg), "GW:UP");
event_dispatch(msg);
cond_set("net/gw");
}
}
@@ -123,19 +121,24 @@ static void nl_link(struct nlmsghdr *nlmsg)
* New interface has appearad, or interface flags has changed.
* Check ifi_flags here to see if the interface is UP/DOWN
*/
if (i->ifi_change & IFF_UP)
snprintf(msg, sizeof(msg), "IF%s:%s",
(i->ifi_flags & IFF_UP) ? "UP" : "DN",
ifname);
else
snprintf(msg, sizeof(msg), "IFADD:%s", ifname);
event_dispatch(msg);
if (i->ifi_change & IFF_UP) {
snprintf(msg, sizeof(msg), "net/%s/up", ifname);
if (i->ifi_flags & IFF_UP)
cond_set(msg);
else
cond_clear(msg);
} else {
snprintf(msg, sizeof(msg), "net/%s/exist", ifname);
cond_set(msg);
}
break;
case RTM_DELLINK:
/* NOTE: Interface has dissapeared, not link down ... */
snprintf(msg, sizeof(msg), "IFDEL:%s", ifname);
event_dispatch(msg);
snprintf(msg, sizeof(msg), "net/%s/exist", ifname);
cond_clear(msg);
break;
case RTM_NEWADDR:
+121
View File
@@ -0,0 +1,121 @@
#include <limits.h>
#include <paths.h>
#include <sys/inotify.h>
#include "../finit.h"
#include "../cond.h"
#include "../helpers.h"
#include "../plugin.h"
struct context {
int fd;
int wd;
};
static void pidfile_callback(void *UNUSED(arg), int fd, int UNUSED(events))
{
static char ev_buf[8 *(sizeof(struct inotify_event) + NAME_MAX + 1)];
static char cond[MAX_ARG_LEN];
struct inotify_event *ev;
ssize_t sz, len;
char *basename;
svc_t *svc;
sz = read(fd, ev_buf, sizeof(ev_buf));
if (sz <= 0) {
_pe("invalid inotify event\n");
return;
}
for (ev = (void *)ev_buf; sz > sizeof(*ev);
len = sizeof(*ev) + ev->len, ev = (void *)ev + len, sz -= len) {
/* ev = (void *)(ev + 1) + ev->len, sz -= sizeof(*ev) + ev->len) { */
if (!ev->mask || !strstr(ev->name, ".pid"))
continue;
basename = strtok(ev->name, ".");
svc = svc_find_by_nameid(basename, 1);
if (!svc)
continue;
/* TODO FIXME XXX WKZ check that pid is controlled by finit */
_d("%s: match %s", basename, svc->cmd);
snprintf(cond, sizeof(cond), "svc%s", svc->cmd);
if (ev->mask & (IN_CREATE | IN_ATTRIB))
cond_set(cond);
else if (ev->mask & IN_DELETE)
cond_clear(cond);
}
}
static void pidfile_reconf(void *_null)
{
static char name[MAX_ARG_LEN];
svc_t *svc;
(void)(_null);
for (svc = svc_iterator(1); svc; svc = svc_iterator(0)) {
if (svc->state == SVC_RUNNING_STATE && !svc_is_changed(svc)) {
snprintf(name, MAX_ARG_LEN, "svc%s", svc->cmd);
cond_set_path(cond_path(name), COND_ON);
}
}
}
static void pidfile_init (void *arg)
{
struct context *ctx = arg;
ctx->wd = inotify_add_watch(ctx->fd, _PATH_VARRUN,
IN_CREATE | IN_ATTRIB | IN_DELETE);
if (ctx->wd < 0) {
_pe("inotify_add_watch()");
close(ctx->fd);
return;
}
_d("pidfile monitor active");
}
static struct context pidfile_ctx;
static plugin_t plugin = {
.hook[HOOK_BASEFS_UP] = { .arg = &pidfile_ctx, .cb = pidfile_init },
.hook[HOOK_SVC_RECONF] = { .cb = pidfile_reconf },
.io = {
.cb = pidfile_callback,
.flags = PLUGIN_IO_READ,
},
};
PLUGIN_INIT(plugin_init)
{
pidfile_ctx.fd = inotify_init();
if (pidfile_ctx.fd < 0) {
_pe("inotify_init()");
return;
}
plugin.io.fd = pidfile_ctx.fd;
plugin_register(&plugin);
}
PLUGIN_EXIT(plugin_exit)
{
inotify_rm_watch(pidfile_ctx.fd, pidfile_ctx.wd);
close(pidfile_ctx.fd);
plugin_unregister(&plugin);
}
/**
* Local Variables:
* version-control: t
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
*/