diff --git a/board/common/rootfs/usr/sbin/container b/board/common/rootfs/usr/sbin/container index a86c34eb..e17a4f53 100755 --- a/board/common/rootfs/usr/sbin/container +++ b/board/common/rootfs/usr/sbin/container @@ -626,20 +626,32 @@ case $cmd in podman stats -i 2 ;; upgrade) + # Start script used to initially create container + script=/var/lib/containers/active/S01-${1}.sh + + # Find container image img=$(podman inspect "$1" | jq -r .[].ImageName) if [ -z "$img" ]; then echo "No such container ($1), or invalid ImageName. Cannot upgrade." exit 1; fi + + # Likely an OCI archive, or local directory, assume user has updated image. if echo "$img" | grep -Eq '^localhost/'; then - # Likely an OCI archive, or local directory, assume user has updated image. - file=$(awk '{s=$NF} END{print s}' "/var/lib/containers/active/${1}.sh") + file=$(awk '{s=$NF} END{print s}' "$script") echo "Upgrading container ${1} with local archive: $file ..." else + printf ">> Stopping ... " podman stop "$1" + printf ">> " podman pull "$img" || (echo "Failed fetching $img, check your network (settings)."; exit 1) fi - "/var/lib/containers/active/${1}.sh" || (echo "Failed recreating container $1"; exit 1) + echo ">> Starting $1 ..." + if ! "$script"; then + echo ">> Failed recreating container $1" + exit 1 + fi + echo ">> Done." ;; volume) cmd=$1 diff --git a/src/confd/src/infix-containers.c b/src/confd/src/infix-containers.c index c11e66cb..320070ef 100644 --- a/src/confd/src/infix-containers.c +++ b/src/confd/src/infix-containers.c @@ -36,8 +36,8 @@ static int add(const char *name, struct lyd_node *cif) /* Stop any running container gracefully so it releases its IP addresses. */ fprintf(fp, "#!/bin/sh\n" - "container stop %s\n" - "container delete %s\n" + "container stop %s >/dev/null\n" /* Silence "not running" on upgrade */ + "container delete %s >/dev/null\n" /* Silence any hashes when deleting */ "container", name, name); LYX_LIST_FOR_EACH(lyd_child(cif), node, "dns") @@ -367,7 +367,10 @@ static void cleanup(sr_session_ctx_t *session, struct confd *confd) continue; /* odd, non-script file? */ *ptr = 0; - if (is_active(session, name)) + if (strncmp(name, "S01-", 4)) + continue; /* odd, not start script? */ + + if (is_active(session, &name[4])) continue; /* Not found in running-config, remove stale cache. */ @@ -421,11 +424,15 @@ void infix_containers_post_hook(sr_session_ctx_t *session, struct confd *confd) strlcpy(name, d->d_name, sizeof(name)); ptr = strstr(name, ".sh"); if (ptr) { + char *nm = NULL; + *ptr = 0; + if (!strncmp(name, "S01-", 4)) + nm = &name[4]; /* New job is already active, no changes, skipping ... */ - if (!is_manual(session, name)) - systemf("initctl -bnq cond set container:%s", name); + if (nm && !is_manual(session, nm)) + systemf("initctl -bnq cond set container:%s", nm); } remove(next); continue; diff --git a/src/execd/execd.c b/src/execd/execd.c index d28ff5cd..03a23f36 100644 --- a/src/execd/execd.c +++ b/src/execd/execd.c @@ -57,7 +57,7 @@ static void run_job(const char *path, char *file, int archive) return; } - dbg("job %s in %s done", file, path); + dbg("job %s in %s done %p, archive: %d", file, path, done, archive); if (done && archive) movefile(cmd, done); else @@ -69,28 +69,43 @@ static void run_job(const char *path, char *file, int archive) * a type '*' just to figure out if a job should be archived in * the done directory. */ -static int check(const char *name, int type, int *archive) +static int should_run(const char *name, int type, int *archive) { if (!name || strlen(name) < 3) - return -1; + return 0; if (isdigit(name[1]) && isdigit(name[2])) { - if (type == '*') - type = name[0]; + if (type == '*') { + switch (name[0]) { + case 'K': + *archive = 0; + return 1; + case 'S': + *archive = 1; + return 1; + default: + errx("unsupported '%s', scripts must start with S or K", name); + return 0; + } + } switch (type) { case 'K': *archive = 0; - return 0; + break; case 'S': *archive = 1; - return 0; - default: break; + default: + return 0; } + + dbg("name:%s type:'%c' archive:%d => run:%d", name, type, *archive, type == name[0]); + return type == name[0]; } - return 1; + errx("unsupported script %s, must follow pattern SNN/KNN", name); + return 0; } static void run_dir(const char *path, int type) @@ -106,15 +121,24 @@ static void run_dir(const char *path, int type) } for (i = 0; i < n; i++) { - if (!check(namelist[i]->d_name, type, &archive)) - run_job(path, namelist[i]->d_name, archive); + struct dirent *d = namelist[i]; - free(namelist[i]); + if (d->d_type == DT_DIR) + continue; + + if (should_run(d->d_name, type, &archive)) + run_job(path, d->d_name, archive); + + free(d); } free(namelist); } +/* + * Call stop/cleanup jobs first, may use same container name or + * resources as replacement container start scripts use. + */ static void run_queue(char *path) { run_dir(path, 'K'); @@ -154,7 +178,7 @@ static void inotify_cb(uev_t *w, void *arg, int _) if (event->mask & (IN_CLOSE_WRITE | IN_ATTRIB | IN_MOVED_TO)) { dbg("Got inotify event %s 0x%04x", name, event->mask); - if (check(name, '*', &archive)) + if (!should_run(name, '*', &archive)) continue; run_job(arg, name, archive);