mirror of
https://dev.lirent.ru/Vatrog/vm-automation-signaling.git
synced 2026-06-26 04:36:37 +03:00
vmsig: management daemon, runtime endpoint lifecycle, roster, discovery, in-tree drivers, packaging
- core: runtime attach/detach of a per-endpoint adapter trio (runtime-safe add_adapter + vmsig_core_detach_endpoint, deferred reap) - roster: VMSIG_EV_ROSTER + CAP_ROSTER, retained per-endpoint and replayed to late subscribers - discovery: inotify trigger dir, vmid/endpoint slot allocator, host probe; vmsigd daemon with config + per-uid admission - input driver and vgpu perception built in-tree; vgpu perception as a separate library - memctx: own the supplied ro_fd (closed at detach) - deb packaging: install rules, systemd unit, tmpfiles, default config
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
/* test_dynep.c — runtime hot-plug of a VM endpoint (WS1): a discovery-style consumer
|
||||
* attaches an adapter trio, then detaches it and re-attaches it on the SAME endpoint
|
||||
* while the loop is running. Proves:
|
||||
* - vmsig_core_add_adapter works AFTER vmsig_core_run started (from a loop-thread cb);
|
||||
* - vmsig_core_detach_endpoint tears the trio down (deferred reap) and bumps the epoch,
|
||||
* broadcasting MEMCTX_INVALIDATED so a holder settles;
|
||||
* - re-attaching the same endpoint publishes MEMCTX at the strictly-higher epoch.
|
||||
* All driven from the holder callbacks, which run on the loop thread (single-threaded
|
||||
* with the pumps), so attach/detach are issued mid-loop exactly as discovery will. */
|
||||
#define _GNU_SOURCE
|
||||
#include "vmsig.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
static int g_fail = 0;
|
||||
#define CHECK(cond, msg) do { \
|
||||
if (!(cond)) { printf(" FAIL: %s\n", (msg)); g_fail = 1; } \
|
||||
} while (0)
|
||||
|
||||
typedef struct {
|
||||
vmsig_core* core;
|
||||
uint32_t ep;
|
||||
int memctx; /* MEMCTX received */
|
||||
int invalidated; /* MEMCTX_INVALIDATED received */
|
||||
uint32_t last_epoch; /* epoch of the last MEMCTX */
|
||||
int phase; /* 0: pre-detach, 1: detached, 2: reattached */
|
||||
int ticks; /* vmhost watchdog ticks (failsafe) */
|
||||
} dyn;
|
||||
|
||||
/* Re-attach the trio (vmhost watchdog + memctx) on the same endpoint, mid-loop, from the
|
||||
* INVALIDATED delivery — exactly the discovery "file reappeared" path. */
|
||||
static void reattach_trio(dyn* d) {
|
||||
vmsig_core_add_adapter(d->core, vmsig_vmhost_ops(), NULL, d->ep);
|
||||
vmsig_core_add_adapter(d->core, vmsig_memctx_ops(), NULL, d->ep);
|
||||
}
|
||||
|
||||
static int dyn_on_ev(void* u, const vmsig_event* ev) {
|
||||
dyn* d = u;
|
||||
if (ev->kind == VMSIG_EV_VM_LIFECYCLE) d->ticks++;
|
||||
else if (ev->kind == VMSIG_EV_MEMCTX_INVALIDATED) {
|
||||
d->invalidated++;
|
||||
if (d->phase == 1) { d->phase = 2; reattach_trio(d); }
|
||||
}
|
||||
if (d->ticks > 60) vmsig_core_stop(d->core); /* failsafe */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dyn_on_memctx(void* u, const vmsig_event* ev, int fd) {
|
||||
dyn* d = u;
|
||||
const vmsig_memctx* m = (const vmsig_memctx*)ev->inln;
|
||||
(void)fd; /* core closes the borrowed RO-fd after this call */
|
||||
d->memctx++;
|
||||
d->last_epoch = m->epoch;
|
||||
if (d->phase == 0 && m->epoch == 0) {
|
||||
d->phase = 1;
|
||||
vmsig_core_detach_endpoint(d->core, d->ep); /* deferred reap -> bump -> INVALIDATED */
|
||||
} else if (d->phase == 2 && m->epoch >= 1) {
|
||||
vmsig_core_stop(d->core); /* re-attached context observed: done */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void test_dynep(void) {
|
||||
printf("test_dynep\n");
|
||||
vmsig_ctx* ctx = vmsig_ctx_new();
|
||||
vmsig_core* core = vmsig_core_new(ctx);
|
||||
|
||||
dyn d; memset(&d, 0, sizeof d);
|
||||
d.core = core; d.ep = 0;
|
||||
|
||||
vmsig_inproc_cfg cfg; memset(&cfg, 0, sizeof cfg);
|
||||
cfg.on_event = dyn_on_ev; cfg.on_memctx = dyn_on_memctx; cfg.user = &d;
|
||||
void* ctl = vmsig_inproc_control_new(&cfg);
|
||||
|
||||
vmsig_grant g; memset(&g, 0, sizeof g);
|
||||
g.principal = 1; g.endpoint_mask = 1ull << 0; g.source_mask = 0xFFFFFFFFu;
|
||||
g.cap_mask = VMSIG_CAP_MEMCTX | VMSIG_CAP_OBSERVE;
|
||||
vmsig_core_add_control(core, vmsig_inproc_control_ops(), ctl, &g);
|
||||
|
||||
/* initial trio on ep0, pre-run (vmhost watchdog ticks the loop + memctx publishes). */
|
||||
CHECK(vmsig_core_add_adapter(core, vmsig_vmhost_ops(), NULL, 0) >= 0, "add vmhost ep0");
|
||||
CHECK(vmsig_core_add_adapter(core, vmsig_memctx_ops(), NULL, 0) >= 0, "add memctx ep0");
|
||||
|
||||
vmsig_core_run(core);
|
||||
|
||||
CHECK(d.memctx >= 2, "MEMCTX received before AND after re-attach");
|
||||
CHECK(d.invalidated >= 1, "MEMCTX_INVALIDATED delivered on detach");
|
||||
CHECK(d.last_epoch >= 1, "epoch advanced across detach/re-attach");
|
||||
CHECK(d.phase == 2, "reached the re-attached phase");
|
||||
|
||||
vmsig_core_free(core);
|
||||
vmsig_ctx_free(ctx);
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
test_dynep();
|
||||
printf("dynep tests: %s\n", g_fail ? "FAIL" : "PASS");
|
||||
return g_fail ? 1 : 0;
|
||||
}
|
||||
Reference in New Issue
Block a user