Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions package/confd/confd.mk
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ endif
define CONFD_INSTALL_EXTRA
for fn in confd.conf crond.conf resolvconf.conf; do \
cp $(CONFD_PKGDIR)/$$fn $(FINIT_D)/available/; \
done
for fn in confd.conf resolvconf.conf; do \
ln -sf ../available/$$fn $(FINIT_D)/enabled/$$fn; \
done
cp $(CONFD_PKGDIR)/tmpfiles.conf $(TARGET_DIR)/etc/tmpfiles.d/confd.conf
Expand Down
65 changes: 48 additions & 17 deletions src/confd/src/schedule.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
#include "core.h"

#define XPATH_BASE "/ietf-system:system/infix-schedule:schedules"
#define CRONTAB_FILE "/var/spool/cron/crontabs/admin"
#define CRONTAB_DIR "/var/spool/cron/crontabs"
#define CRONTAB_FILE CRONTAB_DIR "/admin"
#define CRONTAB_NEXT CRONTAB_DIR "/admin.next"

/* Features register a consumer to run a command on a schedule. */
static const struct cron_consumer **consumers;
Expand Down Expand Up @@ -176,11 +178,13 @@ static void build_cron_expr(struct lyd_node *recurrence, char *expr, size_t sz)
snprintf(expr, sz, "%s %s %s %s %s", min, hr, dom, mon, dow);
}

static void reload_crond(void)
static void crond_apply(int active)
{
char *args[] = { "pkill", "-HUP", "crond", NULL };

runbg(args, 0);
if (active) {
finit_enable("crond");
} else {
finit_disable("crond");
}
Comment thread
mattiaswal marked this conversation as resolved.
}

/*
Expand Down Expand Up @@ -217,21 +221,23 @@ static int schedule_to_cron(struct lyd_node *config, const char *name,
}

/*
* Rebuild the crontab from every registered consumer. Each consumer points
* at a feature container holding a schedule-ref; we resolve that to cron
* fields and emit one line running the consumer's own command.
* Generate the next crontab from every registered consumer. Each consumer
* points at a feature container holding a schedule-ref; we resolve that to
* cron fields and emit one line running the consumer's own command. Written
* to CRONTAB_NEXT, promoted in SR_EV_DONE. Returns the active job count;
* CRONTAB_NEXT is removed when there are none, so DONE knows to stop crond.
*/
static void apply_schedules(struct lyd_node *config)
static int gen_schedules(struct lyd_node *config)
{
int count = 0;
FILE *fp;
size_t i;

makepath("/var/spool/cron/crontabs");
fp = fopen(CRONTAB_FILE, "w");
makepath(CRONTAB_DIR);
fp = fopen(CRONTAB_NEXT, "w");
if (!fp) {
ERROR("schedule: failed to open %s", CRONTAB_FILE);
return;
ERROR("schedule: failed to open %s", CRONTAB_NEXT);
return -1;
}
fprintf(fp, "# Managed by infix-schedule\n");

Expand Down Expand Up @@ -267,16 +273,41 @@ static void apply_schedules(struct lyd_node *config)

out:
fclose(fp);
reload_crond();
NOTE("schedule: %d active job(s) written to crontab", count);
if (!count)
(void)remove(CRONTAB_NEXT);

return count;
}

int schedule_change(sr_session_ctx_t *session, struct lyd_node *config,
struct lyd_node *diff, sr_event_t event, struct confd *confd)
{
if (event != SR_EV_DONE && event != SR_EV_ENABLED)
if (diff && !lydx_get_xpathf(diff, XPATH_BASE))
return SR_ERR_OK;

apply_schedules(config);
switch (event) {
case SR_EV_ENABLED: /* first time, on register */
case SR_EV_CHANGE: /* regular change */
gen_schedules(config);
break;

case SR_EV_ABORT: /* user abort, or another plugin failed */
(void)remove(CRONTAB_NEXT);
break;

case SR_EV_DONE:
if (fexist(CRONTAB_NEXT)) {
(void)rename(CRONTAB_NEXT, CRONTAB_FILE);
crond_apply(1);
} else {
(void)remove(CRONTAB_FILE);
crond_apply(0);
}
break;

default:
break;
}

return SR_ERR_OK;
}