From 32d760ad5e23cb759106438d4a58e5ada4b52517 Mon Sep 17 00:00:00 2001 From: Christophe Varoqui Date: Wed, 4 Feb 2026 11:52:12 +0100 Subject: [PATCH 01/14] Fix a stack in actor.FQDN() Permission errors accessing node.conf during kw dereference can lead to actor.fqdn() to return nil, and thus FQDN() to stack on fqdn().String(). Test fqdn() result and return "" if nil. panic: runtime error: invalid memory address or nil pointer dereference [recovered] panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x16c8f9f] goroutine 1 [running]: main.main.func1() /home/cvaroqui/dev/om3/cmd/om/main.go:23 +0xbf panic({0x20ab6e0?, 0x4477890?}) /home/cvaroqui/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.24.0.linux-amd64/src/runtime/panic.go:787 +0x132 github.com/opensvc/om3/v3/core/object.(*core).FQDN(0x20f1f60?) /home/cvaroqui/dev/om3/core/object/core_config.go:87 +0x1f github.com/opensvc/om3/v3/core/object.(*core).Dereference(0xc0002e86c0, {0xc00013527f, 0x4}) /home/cvaroqui/dev/om3/core/object/core_config.go:313 +0x1e5 github.com/opensvc/om3/v3/core/xconfig.T.dereferenceWellKnown({{0xc00027b840, 0x1e}, {{0x7ffc488c10f0, 0x8}, {0x230ebbc, 0x4}, {0x230e04b, 0x3}}, {0x37f3850, 0xc0002e86c0}, ...}, ...) /home/cvaroqui/dev/om3/core/xconfig/main.go:1335 +0x402 github.com/opensvc/om3/v3/core/xconfig.T.dereference({{0xc00027b840, 0x1e}, {{0x7ffc488c10f0, 0x8}, {0x230ebbc, 0x4}, {0x230e04b, 0x3}}, {0x37f3850, 0xc0002e86c0}, ...}, ...) /home/cvaroqui/dev/om3/core/xconfig/main.go:1197 +0x4d4 github.com/opensvc/om3/v3/core/xconfig.(*T).replaceReferences.func1({0xc00013527e, 0x6}) /home/cvaroqui/dev/om3/core/xconfig/main.go:951 +0x225 regexp.(*Regexp).ReplaceAllStringFunc.func1({0xc000487430, 0x5, 0x8}, {0xc000487420?, 0xc00066ba68?, 0x0?}) /home/cvaroqui/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.24.0.linux-amd64/src/regexp/regexp.go:598 +0x85 regexp.(*Regexp).replaceAll(0xc000244000, {0x0, 0x0, 0x0}, {0xc000135279, 0x10}, 0x2, 0xc00066bb30) /home/cvaroqui/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.24.0.linux-amd64/src/regexp/regexp.go:636 +0x3e3 regexp.(*Regexp).ReplaceAllStringFunc(0x0?, {0xc000135279?, 0x0?}, 0x0?) /home/cvaroqui/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.24.0.linux-amd64/src/regexp/regexp.go:597 +0x4b github.com/opensvc/om3/v3/core/xconfig.(*T).replaceReferences(0x0?, {0xc000135279?, 0x231229e?}, {0xc000487be8?, 0x231ad4b?}, {0x0?, 0x1?}, 0x0?, 0x0?) /home/cvaroqui/dev/om3/core/xconfig/main.go:950 +0xac github.com/opensvc/om3/v3/core/xconfig.(*T).evalDescopeStringAs(_, {{_, _}, {_, _}}, {{0x0, 0x0}, {0x231229e, 0x6}, {0x231ad4b, ...}, ...}, ...) /home/cvaroqui/dev/om3/core/xconfig/main.go:912 +0xf6 github.com/opensvc/om3/v3/core/xconfig.(*T).evalStringAs(_, {{_, _}, {_, _}}, {{0x0, 0x0}, {0x231229e, 0x6}, {0x231ad4b, ...}, ...}, ...) /home/cvaroqui/dev/om3/core/xconfig/main.go:866 +0x1fe github.com/opensvc/om3/v3/core/xconfig.(*T).EvalKeywordAs(_, {{_, _}, {_, _}}, {{0x0, 0x0}, {0x231229e, 0x6}, {0x231ad4b, ...}, ...}, ...) /home/cvaroqui/dev/om3/core/xconfig/main.go:840 +0x15b github.com/opensvc/om3/v3/core/object.(*actor).configureResource(0xc0002e86c0, {0x3811430, 0xc0002ed088}, {0xc000487be8, 0x5}) /home/cvaroqui/dev/om3/core/object/actor.go:468 +0x42d github.com/opensvc/om3/v3/core/object.(*actor).ConfigureResources(0xc0002e86c0) /home/cvaroqui/dev/om3/core/object/actor.go:301 +0x67a github.com/opensvc/om3/v3/core/object.(*actor).Resources(0xc0002e86c0) /home/cvaroqui/dev/om3/core/object/actor.go:252 +0x3b github.com/opensvc/om3/v3/core/object.listResources(...) /home/cvaroqui/dev/om3/core/object/actor.go:218 github.com/opensvc/om3/v3/core/object.(*actor).Schedules(0xc0002e86c0) /home/cvaroqui/dev/om3/core/object/actor_print_schedule.go:71 +0x3a9 github.com/opensvc/om3/v3/core/omcmd.(*CmdObjectScheduleList).extractLocal(0xc0002d30e0?, {0x7ffc488c10f0, 0x8}) /home/cvaroqui/dev/om3/core/omcmd/object_schedule_list.go:63 +0x1f7 github.com/opensvc/om3/v3/core/omcmd.(*CmdObjectScheduleList).extract(0xc0002d30e0, {0x7ffc488c10f0, 0x8}, 0x8?) /home/cvaroqui/dev/om3/core/omcmd/object_schedule_list.go:36 +0x8e github.com/opensvc/om3/v3/core/omcmd.(*CmdObjectScheduleList).Run(0xc0002d30e0, {0x230e04b?, 0x0?}) /home/cvaroqui/dev/om3/core/omcmd/object_schedule_list.go:142 +0x88 github.com/opensvc/om3/v3/core/om.newCmdObjectScheduleList.func1(0xc000505208?, {0x230ec78?, 0x4?, 0x230eb70?}) /home/cvaroqui/dev/om3/core/om/factory.go:2289 +0x1f github.com/spf13/cobra.(*Command).execute(0xc000505208, {0xc000702460, 0x2, 0x2}) /home/cvaroqui/go/pkg/mod/github.com/spf13/cobra@v1.9.1/command.go:1015 +0xa94 github.com/spf13/cobra.(*Command).ExecuteC(0x44ad9c0) /home/cvaroqui/go/pkg/mod/github.com/spf13/cobra@v1.9.1/command.go:1148 +0x40c github.com/spf13/cobra.(*Command).Execute(...) /home/cvaroqui/go/pkg/mod/github.com/spf13/cobra@v1.9.1/command.go:1071 github.com/opensvc/om3/v3/core/om.ExecuteArgs({0xc00003e150, 0x3, 0x3}) /home/cvaroqui/dev/om3/core/om/root.go:215 +0x52 github.com/opensvc/om3/v3/core/om.Execute() /home/cvaroqui/dev/om3/core/om/root.go:155 +0x45 main.main() /home/cvaroqui/dev/om3/cmd/om/main.go:29 +0x4a --- core/object/core_config.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/core/object/core_config.go b/core/object/core_config.go index 3faed22b1..549265134 100644 --- a/core/object/core_config.go +++ b/core/object/core_config.go @@ -84,7 +84,11 @@ func (t *core) Orchestrate() string { } func (t *core) FQDN() string { - return t.fqdn().String() + if fqdn := t.fqdn(); fqdn != nil { + return fqdn.String() + } else { + return "" + } } func (t *core) Domain() string { From dc034383ac3b896475445a088bde2b696f53cc61 Mon Sep 17 00:00:00 2001 From: Christophe Varoqui Date: Wed, 4 Feb 2026 15:25:09 +0100 Subject: [PATCH 02/14] Update the pool capabilities kw documentation document more caps. --- .../text/kw/node/pool.virtual.capabilities | 32 +++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/core/object/text/kw/node/pool.virtual.capabilities b/core/object/text/kw/node/pool.virtual.capabilities index 2d6b3bd94..3bb4fe4ee 100644 --- a/core/object/text/kw/node/pool.virtual.capabilities +++ b/core/object/text/kw/node/pool.virtual.capabilities @@ -2,9 +2,37 @@ The capabilities exposed by the virtual pool. Supported capabilities: -* `shared` +* `blk` + The pool can satisfy the `format=false` requirement. + +* `file` + The pool can satisfy the `format=true` requirement. + +* `move` + The pool volumes can host data for resources proposing live migration (e.g. container.kvm). + * `roo` + Read-Only from One node. + The pool can satisfy the `access=roo` requirement. + * `rox` + Read-Only from Many nodes. + The pool can satisfy the `access=rox` requirement. + * `rwo` + Read-Write from One node. + The pool can satisfy the `access=rwo` requirement. + * `rwx` -* `blk` + Read-Write from Many nodes. + The pool can satisfy the `access=rwx` requirement. + +* `shared` + The same technical object is used on all nodes. + +* `snap` + The volume can be snapshotted. + +* `volatile` + The pool can satisfy the `volatile=true` requirement. + From c0045ee7da69b6d12f48d385acabeddf7feda11c Mon Sep 17 00:00:00 2001 From: Christophe Varoqui Date: Wed, 4 Feb 2026 15:38:22 +0100 Subject: [PATCH 03/14] Fix shm pool lookup error With [volume#1] type=shm size=10m the pool lookup would discard the shm pool with a error like: [shm] not persistent capable The pool lookup is too strict and expects: [volume#1] type = shm size = 10m volatile = true This expectation breaks backward compat. So accept that explicetly asking for the shm pool implies volatile. --- core/pool/lookup.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/pool/lookup.go b/core/pool/lookup.go index 93f398177..b19900f28 100644 --- a/core/pool/lookup.go +++ b/core/pool/lookup.go @@ -110,7 +110,7 @@ func (t Lookup) Do(ctx context.Context) (Pooler, error) { cause = append(cause, fmt.Sprintf("[%s] not volatile capable", p.Name())) continue } - if t.Volatile == false && HasCapability(p, CapVolatile) { + if t.Volatile == false && HasCapability(p, CapVolatile) && t.Type != "shm" { cause = append(cause, fmt.Sprintf("[%s] not persistent capable", p.Name())) continue } From b6685397d77df633b26a6ec572a552c228276725 Mon Sep 17 00:00:00 2001 From: Christophe Varoqui Date: Wed, 4 Feb 2026 15:59:25 +0100 Subject: [PATCH 04/14] Mention ips_per_node to mask_per_node in the CHANGELOG --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 13eb48490..27f06fab9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -628,3 +628,6 @@ Where the password is the value of the `þassword` key in `system/sec/relay-v3`. * Flush iptables rules created by om2. om3 now configures the firewall using nft only. +* Change `ips_per_node` to `mask_per_node`. The former was inadequate for large subnets (ipv6). For example, `ips_per_node=18446744073709551616` is easier expressed as `mask_per_node=64`. Backward compatibility is maintained for this release. + + From 431f36aa624181b914ee272e0d65afda1894a60f Mon Sep 17 00:00:00 2001 From: Christophe Varoqui Date: Thu, 5 Feb 2026 15:26:34 +0100 Subject: [PATCH 05/14] Remove unused driver groups The following driver were dropped as abstracting igw configuration using opensvc keywords is no longer supported: GroupCertificate | GroupExpose | GroupRoute | GroupVhost This abstraction caused lots of igw features to be masked, and forced us to follow igw syntax changes. --- core/driver/group.go | 78 +++++++++++++++++++------------------------- 1 file changed, 33 insertions(+), 45 deletions(-) diff --git a/core/driver/group.go b/core/driver/group.go index bd4a94f6d..d6ad13920 100644 --- a/core/driver/group.go +++ b/core/driver/group.go @@ -19,10 +19,6 @@ const ( GroupApp GroupSync GroupTask - GroupCertificate - GroupExpose - GroupRoute - GroupVhost GroupPool GroupNetwork GroupHeartbeat @@ -33,51 +29,43 @@ const ( ) var ( - resourceGroups = GroupIP | GroupVolume | GroupDisk | GroupFS | GroupShare | GroupContainer | GroupApp | GroupSync | GroupTask | GroupCertificate | GroupExpose | GroupRoute | GroupVhost + resourceGroups = GroupIP | GroupVolume | GroupDisk | GroupFS | GroupShare | GroupContainer | GroupApp | GroupSync | GroupTask toGroupID = map[string]Group{ - "ip": GroupIP, - "volume": GroupVolume, - "disk": GroupDisk, - "fs": GroupFS, - "share": GroupShare, - "container": GroupContainer, - "app": GroupApp, - "sync": GroupSync, - "task": GroupTask, - "certificate": GroupCertificate, - "expose": GroupExpose, - "route": GroupRoute, - "vhost": GroupVhost, - "pool": GroupPool, - "network": GroupNetwork, - "hb": GroupHeartbeat, - "array": GroupArray, - "switch": GroupSwitch, - "stonith": GroupStonith, - "backup": GroupBackup, + "ip": GroupIP, + "volume": GroupVolume, + "disk": GroupDisk, + "fs": GroupFS, + "share": GroupShare, + "container": GroupContainer, + "app": GroupApp, + "sync": GroupSync, + "task": GroupTask, + "pool": GroupPool, + "network": GroupNetwork, + "hb": GroupHeartbeat, + "array": GroupArray, + "switch": GroupSwitch, + "stonith": GroupStonith, + "backup": GroupBackup, } toGroupString = map[Group]string{ - GroupIP: "ip", - GroupVolume: "volume", - GroupDisk: "disk", - GroupFS: "fs", - GroupShare: "share", - GroupContainer: "container", - GroupApp: "app", - GroupSync: "sync", - GroupTask: "task", - GroupCertificate: "certificate", - GroupExpose: "expose", - GroupRoute: "route", - GroupVhost: "vhost", - GroupPool: "pool", - GroupNetwork: "network", - GroupHeartbeat: "hb", - GroupArray: "array", - GroupSwitch: "switch", - GroupStonith: "stonith", - GroupBackup: "backup", + GroupIP: "ip", + GroupVolume: "volume", + GroupDisk: "disk", + GroupFS: "fs", + GroupShare: "share", + GroupContainer: "container", + GroupApp: "app", + GroupSync: "sync", + GroupTask: "task", + GroupPool: "pool", + GroupNetwork: "network", + GroupHeartbeat: "hb", + GroupArray: "array", + GroupSwitch: "switch", + GroupStonith: "stonith", + GroupBackup: "backup", } ) From 90a9b0ead8d6ad63bff5c573d9cfe3fccf6a6137 Mon Sep 17 00:00:00 2001 From: Christophe Varoqui Date: Thu, 5 Feb 2026 15:29:57 +0100 Subject: [PATCH 06/14] Remove one unused interface declaration --- core/object/interfaces.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/core/object/interfaces.go b/core/object/interfaces.go index d85d755c5..9935a6950 100644 --- a/core/object/interfaces.go +++ b/core/object/interfaces.go @@ -5,7 +5,6 @@ import ( "github.com/opensvc/om3/v3/core/keyop" "github.com/opensvc/om3/v3/core/rawconfig" - "github.com/opensvc/om3/v3/core/schedule" "github.com/opensvc/om3/v3/core/xconfig" "github.com/opensvc/om3/v3/util/key" ) @@ -31,8 +30,4 @@ type ( Update(context.Context, []string, []key.T, []keyop.T) error Unset(context.Context, ...key.T) error } - - scheduler interface { - Schedules() schedule.Table - } ) From 58216e540b67a88edb47607f0d4dd4a2d94006b4 Mon Sep 17 00:00:00 2001 From: Christophe Varoqui Date: Thu, 5 Feb 2026 15:33:01 +0100 Subject: [PATCH 07/14] Store the resource configuration error in resource.T MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Misconfigured resources are now listed by Actor.Resources() * The functions passed to resourceset.T.Do() now have to decide if they skip a misconfigured resource: * Actor.FreshStatus don't skip them, but format a "undef" resource.Status with a status log reporting the configuration error. * Abort() skips silently * Action() skips with a warn log Example: $ om tstencap instance status -r tstencap up warn └ instances └ eggplant up warn idle started └ resources ├ ip#4 ...../.. undef │ error: configuration does not exist: key 'dev' not found (all scopes tried) ├ fs#0 .M...... up tmpfs none@/srv/tstencap.root.svc.homepool1/tmp ├ container#1 ...../.. up docker alpine └ subset#app:g1 └ app#2 ..D../.. n/a forking app.forking $ om tstencap instance start go build -o bin/om ./cmd/om/ 15:22:27.138 INF tstencap: >>> do start [./bin/om tstencap instance start] (origin user, sid daea11fd-8cf4-4821-8349-fa5e1fa130d8) 15:22:27.177 WRN tstencap: ip#4: skip resource with configuration error: configuration does not exist: key 'dev' not found (all scopes tried) 15:22:27.189 INF tstencap: fs#0: none already mounted on /srv/tstencap.root.svc.homepool1/tmp 15:22:27.205 INF tstencap: container#1: container start tstencap.container.1: already started 15:22:27.378 INF tstencap: <<< done start [./bin/om tstencap instance start] in 240.156022ms, instance status is now up, with warnings --- core/object/actor.go | 19 +++++++++++------- core/object/actor_push_resinfo.go | 3 +++ core/object/actor_status.go | 8 ++++++++ core/object/core_action.go | 7 +++++++ core/omcmd/object_schedule_list.go | 9 ++++----- core/resource/resource.go | 32 ++++++++++++++++++++++++------ core/resourceset/resourceset.go | 27 ++++++++++--------------- 7 files changed, 70 insertions(+), 35 deletions(-) diff --git a/core/object/actor.go b/core/object/actor.go index 2f6c3c567..940562198 100644 --- a/core/object/actor.go +++ b/core/object/actor.go @@ -271,7 +271,7 @@ func (t *actor) ConfigureResources() { } driverGroup := rid.DriverGroup() if driverGroup == driver.GroupUnknown { - t.log.Attr("rid", k).Tracef("unknown driver group in rid %s", k) + t.log.Tracef("unknown driver group in rid %s", k) continue } typeKey := key.New(k, "type") @@ -306,30 +306,35 @@ func (t *actor) ConfigureResources() { } postponed[o.RID] = append(postponed[o.RID], r) default: - t.log.Attr("rid", k).Errorf("configure resource %s: %s", k, err) + r.SetConfigured(err) + t.log.Tracef("resource %s configuration error: %s", k, err) + t._resources = append(t._resources, r) } continue } dur := time.Now().Sub(rBegin) - t.log.Attr("rid", k).Attr("duration", dur).Tracef("resource %s configured in %s", k, dur) + t.log.Tracef("resource %s configured in %s", k, dur) t._resources = append(t._resources, r) } for _, resources := range postponed { for _, r := range resources { rBegin := time.Now() + k := r.RID() if err := t.ReconfigureResource(r); err != nil { - t.log.Attr("rid", r.RID()).Errorf("configure postponed resource %s: %s", r.RID(), err) + r.SetConfigured(err) + t.log.Tracef("postponed resource %s configuration error: %s", k, err) + t._resources = append(t._resources, r) continue } dur := time.Now().Sub(rBegin) - t.log.Attr("rid", r.RID()).Attr("duration", dur).Tracef("postponed resource %s configured in %s", r.RID(), dur) + t.log.Tracef("postponed resource %s configured in %s", k, dur) t._resources = append(t._resources, r) } } t.resources = t._resources t._resources = nil dur := time.Now().Sub(begin) - t.log.Attr("duration", dur).Tracef("all resources configured in %s", dur) + t.log.Tracef("%d resources configured in %s", len(t.resources), dur) return } @@ -339,6 +344,7 @@ func (t *actor) ReconfigureResource(r resource.Driver) error { func (t *actor) configureResource(r resource.Driver, rid string) error { r.SetRID(rid) + r.SetObject(t) m := r.Manifest() getDNS := func() ([]string, error) { n, err := t.Node() @@ -482,7 +488,6 @@ func (t *actor) configureResource(r resource.Driver, rid string) error { } } } - r.SetObject(t) r.SetPG(t.pgConfig(rid)) if i, ok := r.(resource.Configurer); ok { if err := i.Configure(); err != nil { diff --git a/core/object/actor_push_resinfo.go b/core/object/actor_push_resinfo.go index badc3ed49..ba293836e 100644 --- a/core/object/actor_push_resinfo.go +++ b/core/object/actor_push_resinfo.go @@ -95,6 +95,9 @@ func (t *actor) masterResInfo(ctx context.Context) ([]resource.Info, error) { resourceLister := resourceselector.FromContext(ctx, t) barrier := actioncontext.To(ctx) err := t.ResourceSets().Do(ctx, resourceLister, barrier, "resinfo", func(ctx context.Context, r resource.Driver) error { + if !r.IsConfigured() { + return nil + } info, err := resource.GetInfo(ctx, r) if err != nil { return err diff --git a/core/object/actor_status.go b/core/object/actor_status.go index 1fe598d44..69e4249b1 100644 --- a/core/object/actor_status.go +++ b/core/object/actor_status.go @@ -226,6 +226,14 @@ func (t *actor) resourceStatusEval(ctx context.Context, data *instance.Status, m return nil } + if err := r.GetConfigurationError(); err != nil { + log := resource.NewStatusLog() + log.Error("%s", err) + resourceStatus.Log = log.Entries() + data.Resources[r.RID()] = resourceStatus + return nil + } + if monitoredOnly && !r.IsMonitored() { resourceStatus = data.Resources[r.RID()] sb.Post(r.RID(), resourceStatus.Status, false) diff --git a/core/object/core_action.go b/core/object/core_action.go index dbd624517..e8ba4a7d0 100644 --- a/core/object/core_action.go +++ b/core/object/core_action.go @@ -306,6 +306,9 @@ func (t *actor) abortStartDrivers(ctx context.Context, resources resource.Driver q := make(chan bool, len(resources)) var wg sync.WaitGroup for _, r := range resources { + if !r.IsConfigured() { + return nil + } if v, err := t.isEncapNodeMatchingResource(r); err != nil { return err } else if !v { @@ -626,6 +629,10 @@ func (t *actor) action(ctx context.Context, fn resourceset.DoFunc) error { progressWrap := func(fn resourceset.DoFunc) resourceset.DoFunc { return func(ctx context.Context, r resource.Driver) error { + if !r.IsConfigured() { + r.Log().Warnf("skip resource with configuration error: %s", r.GetConfigurationError()) + return nil + } if v, err := t.isEncapNodeMatchingResource(r); err != nil { return err } else if !v { diff --git a/core/omcmd/object_schedule_list.go b/core/omcmd/object_schedule_list.go index 84db6ab3c..4a4175667 100644 --- a/core/omcmd/object_schedule_list.go +++ b/core/omcmd/object_schedule_list.go @@ -51,9 +51,11 @@ func (t *CmdObjectScheduleList) extractLocal(selector string) (api.ScheduleList, if err != nil { return data, err } + var errs error for _, p := range paths { obj, err := object.New(p) if err != nil { + errs = errors.Join(errs, err) continue } i, ok := obj.(scheduler) @@ -84,7 +86,7 @@ func (t *CmdObjectScheduleList) extractLocal(selector string) (api.ScheduleList, data.Items = append(data.Items, item) } } - return data, nil + return data, errs } func (t *CmdObjectScheduleList) extractFromDaemons(selector string, c *client.T) (api.ScheduleList, error) { @@ -140,9 +142,6 @@ func (t *CmdObjectScheduleList) Run(kind string) error { return err } data, err := t.extract(mergedSelector, c) - if err != nil { - return err - } output.Renderer{ DefaultOutput: "tab=OBJECT:meta.object,NODE:meta.node,ACTION:data.action,KEY:data.key,LAST_RUN_AT:data.last_run_at,NEXT_RUN_AT:data.next_run_at,SCHEDULE:data.schedule", Output: t.Output, @@ -150,5 +149,5 @@ func (t *CmdObjectScheduleList) Run(kind string) error { Data: data, Colorize: rawconfig.Colorize, }.Print() - return nil + return err } diff --git a/core/resource/resource.go b/core/resource/resource.go index 515909248..294c7afce 100644 --- a/core/resource/resource.go +++ b/core/resource/resource.go @@ -67,12 +67,14 @@ type ( // common ApplyPGChain(context.Context) error + GetConfigurationError() error GetObject() any GetPG() *pg.Config GetPGID() string GetRestartDelay() time.Duration ID() *resourceid.T IsActionDisabled() bool + IsConfigured() bool IsDisabled() bool IsEncap() bool IsMonitored() bool @@ -83,6 +85,7 @@ type ( IsStandby() bool IsStopped() bool IsStatusDisabled() bool + SetConfigured(error) // Label returns a formatted short description of the Resource Label(context.Context) string @@ -149,11 +152,12 @@ type ( EnableProvision bool EnableUnprovision bool - statusLog StatusLog - log plog.Logger - object any - objectDriver ObjectDriver - pg *pg.Config + configurationError error + statusLog StatusLog + log plog.Logger + object any + objectDriver ObjectDriver + pg *pg.Config } // devReservabler is an interface implemented by resource drivers that want the core resource @@ -363,7 +367,7 @@ func (t *T) IsOptional() bool { // IsEncap returns true if the resource definition contains encap=true. func (t *T) IsEncap() bool { - return t.Encap || t.Tags.Has("encap") + return t.Encap || t.MatchTag("encap") } // IsDisabled returns true if the resource definition contains disable=true. @@ -414,6 +418,18 @@ func (t *T) IsActionDisabled() bool { return t.MatchTag("noaction") } +func (t *T) IsConfigured() bool { + return t.configurationError == nil +} + +func (t *T) GetConfigurationError() error { + return t.configurationError +} + +func (t *T) SetConfigured(err error) { + t.configurationError = err +} + // RestartCount returns the value of the Restart field func (t *T) RestartCount() int { return t.Restart @@ -1120,6 +1136,10 @@ func stop(ctx context.Context, r Driver) error { func EvalStatus(ctx context.Context, r Driver) status.T { r.StatusLog().Reset() s := status.NotApplicable + if err := r.GetConfigurationError(); err != nil { + r.StatusLog().Error("%s", err) + return s + } var tags []string if r.IsActionDisabled() { tags = append(tags, "actions disabled") diff --git a/core/resourceset/resourceset.go b/core/resourceset/resourceset.go index ec8202358..6bbeadede 100644 --- a/core/resourceset/resourceset.go +++ b/core/resourceset/resourceset.go @@ -305,29 +305,22 @@ func (t T) doSerial(ctx context.Context, l ResourceLister, resources resource.Dr if pgMgr != nil { pgMgr.Register(r.GetPG()) } - var err error - c := make(chan error, 1) - if err = l.ReconfigureResource(r); err == nil { - c <- fn(ctx, r) - } - select { - case <-ctx.Done(): - err = fmt.Errorf("timeout") - case err = <-c: + if err := l.ReconfigureResource(r); err != nil { + r.SetConfigured(err) } - switch { - case err == nil: + err := fn(ctx, r) + if err == nil { continue - case errors.Is(err, resource.ErrBarrier): + } + if errors.Is(err, resource.ErrBarrier) { // linkWrap executed resourceset.L.Do again with a fn that can return ErrBarrier return true, nil - case r.IsOptional(): + } + if r.IsOptional() { r.Log().Warnf("error from optional resource: %s", err) - continue - default: - r.Log().Errorf("%s", err) - return hasHitBarrier, fmt.Errorf("%s: %w", rid, err) } + r.Log().Errorf("%s", err) + return hasHitBarrier, fmt.Errorf("%s: %w", rid, err) } return hasHitBarrier, nil } From 9c998b87b87ba9b01ac69bab5860b1dee8d24259 Mon Sep 17 00:00:00 2001 From: Christophe Varoqui Date: Thu, 5 Feb 2026 19:22:21 +0100 Subject: [PATCH 08/14] Make instance.ResourceMonitorRestart a pointer So resources that don't support restarts, like tasks, do not clutter the memory and their json representation. --- core/instance/config.go | 2 +- core/instance/monitor.go | 24 +++++++++++++------ core/instance/monitor_test.go | 6 ++--- core/instance/status.go | 4 +++- daemon/imon/main_cmd.go | 8 ++++--- daemon/imon/orchestration_resource_restart.go | 4 ++++ 6 files changed, 33 insertions(+), 15 deletions(-) diff --git a/core/instance/config.go b/core/instance/config.go index fb8201d84..5011391ae 100644 --- a/core/instance/config.go +++ b/core/instance/config.go @@ -63,7 +63,7 @@ type ( IsDisabled bool `json:"is_disabled"` IsMonitored bool `json:"is_monitored"` IsStandby bool `json:"is_standby"` - Restart int `json:"restart"` + Restart int `json:"restart,omitempty"` RestartDelay *time.Duration `json:"restart_delay"` } SubsetConfig struct { diff --git a/core/instance/monitor.go b/core/instance/monitor.go index b3abf2458..84296f58a 100644 --- a/core/instance/monitor.go +++ b/core/instance/monitor.go @@ -10,7 +10,6 @@ import ( "github.com/google/uuid" "github.com/opensvc/om3/v3/core/status" - "github.com/opensvc/om3/v3/util/xmap" ) type ( @@ -72,11 +71,11 @@ type ( // ResourceMonitor describes the restart states maintained by the daemon // for an object instance. ResourceMonitor struct { - Restart ResourceMonitorRestart `json:"restart"` + Restart *ResourceMonitorRestart `json:"restart,omitempty"` } ResourceMonitorRestart struct { - Remaining int `json:"remaining"` - LastAt time.Time `json:"last_at"` + Remaining int `json:"remaining,omitempty"` + LastAt time.Time `json:"last_at,omitempty"` } MonitorState int @@ -219,7 +218,16 @@ func (m ResourceMonitors) Get(rid string) *ResourceMonitor { } func (m ResourceMonitors) DeepCopy() ResourceMonitors { - return xmap.Copy(m) + c := make(ResourceMonitors) + for k, v := range m { + v2 := ResourceMonitor{} + if v.Restart != nil { + r2 := *v.Restart + v2.Restart = &r2 + } + c[k] = v2 + } + return c } func (mon Monitor) DeepCopy() *Monitor { @@ -244,9 +252,11 @@ func (mon Monitor) DeepCopy() *Monitor { } func (t ResourceMonitor) Unstructured() map[string]any { - return map[string]any{ - "restart": t.Restart.Unstructured(), + m := map[string]any{} + if t.Restart != nil { + m["restart"] = t.Restart.Unstructured() } + return m } func (t ResourceMonitorRestart) Unstructured() map[string]any { diff --git a/core/instance/monitor_test.go b/core/instance/monitor_test.go index ed045b752..d61d52168 100644 --- a/core/instance/monitor_test.go +++ b/core/instance/monitor_test.go @@ -36,7 +36,7 @@ func Test_Monitor_Unmarshal(t *testing.T) { StateUpdatedAt: t0, Resources: ResourceMonitors{ "fs#1": ResourceMonitor{ - Restart: ResourceMonitorRestart{ + Restart: &ResourceMonitorRestart{ Remaining: 1, LastAt: time.Date(2020, time.March, 4, 16, 33, 23, 167003830, time.UTC), }, @@ -62,8 +62,8 @@ func Test_Monitor_DeepCopy(t *testing.T) { LocalExpectUpdatedAt: time.Now(), GlobalExpectUpdatedAt: time.Now(), Resources: ResourceMonitors{ - "a": ResourceMonitor{Restart: ResourceMonitorRestart{Remaining: 1, LastAt: time.Now()}}, - "b": ResourceMonitor{Restart: ResourceMonitorRestart{Remaining: 8, LastAt: time.Now()}}, + "a": ResourceMonitor{Restart: &ResourceMonitorRestart{Remaining: 1, LastAt: time.Now()}}, + "b": ResourceMonitor{Restart: &ResourceMonitorRestart{Remaining: 8, LastAt: time.Now()}}, }, } mon2 := *mon1.DeepCopy() diff --git a/core/instance/status.go b/core/instance/status.go index e2f6300b4..20cceaf45 100644 --- a/core/instance/status.go +++ b/core/instance/status.go @@ -138,7 +138,9 @@ func ResourceFlagsString(rid string, mon Monitor, status Status, rstatus resourc restartFlag := func() string { retries := 0 if rmon := mon.Resources.Get(rid); rmon != nil { - retries = rmon.Restart.Remaining + if rmon.Restart != nil { + retries = rmon.Restart.Remaining + } } s := rstatus.RestartFlag(retries) if s == "." { diff --git a/daemon/imon/main_cmd.go b/daemon/imon/main_cmd.go index 2827b0636..da554ce90 100644 --- a/daemon/imon/main_cmd.go +++ b/daemon/imon/main_cmd.go @@ -1145,11 +1145,13 @@ func (t *Manager) initResourceMonitor() { m := make(instance.ResourceMonitors, 0) for rid, rcfg := range t.instConfig.Resources { - m[rid] = instance.ResourceMonitor{ - Restart: instance.ResourceMonitorRestart{ + resourceMonitor := instance.ResourceMonitor{} + if rcfg.Restart > 0 { + resourceMonitor.Restart = &instance.ResourceMonitorRestart{ Remaining: rcfg.Restart, - }, + } } + m[rid] = resourceMonitor if rcfg.IsMonitored && hasMonitorActionNone { t.orchestrationResource(rcfg.IsStandby).log.Infof("rid %s is monitored, but monitor action is none", rid) } diff --git a/daemon/imon/orchestration_resource_restart.go b/daemon/imon/orchestration_resource_restart.go index 5ebd88d6b..b05f0db14 100644 --- a/daemon/imon/orchestration_resource_restart.go +++ b/daemon/imon/orchestration_resource_restart.go @@ -480,6 +480,10 @@ func (t *Manager) orchestrateResourcePlan(rid string, rcfg *instance.ResourceCon err = fmt.Errorf("orchestrate resource plan called with nil resource config") return } + if rmon.Restart == nil { + // Resource not supporting restarts, e.g. task + return + } or := t.orchestrationResource(rcfg.IsStandby) From 63a02f995f2ccc1a14e55ae978f2387d1a5a9361 Mon Sep 17 00:00:00 2001 From: Christophe Varoqui Date: Fri, 6 Feb 2026 16:17:55 +0100 Subject: [PATCH 09/14] Re-add a context timeout test in the doSerial() loop Add don't reformat the context.Context.Err() error. --- core/resourceset/resourceset.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/core/resourceset/resourceset.go b/core/resourceset/resourceset.go index 6bbeadede..e1b16d702 100644 --- a/core/resourceset/resourceset.go +++ b/core/resourceset/resourceset.go @@ -223,7 +223,7 @@ func (t T) doParallel(ctx context.Context, l ResourceLister, resources resource. } select { case <-ctx.Done(): - err = fmt.Errorf("timeout") + err = ctx.Err() case err = <-c: } q <- result{ @@ -292,6 +292,12 @@ func (t T) doSerial(ctx context.Context, l ResourceLister, resources resource.Dr hasHitBarrier := false selectedResources := l.Resources() for _, r := range resources { + select { + case <-ctx.Done(): + return hasHitBarrier, ctx.Err() + default: + // pass + } if hasHitBarrier { break } From d7e0d412db2fc13140b1aa4723be3811d6292769 Mon Sep 17 00:00:00 2001 From: Christophe Varoqui Date: Fri, 6 Feb 2026 16:31:36 +0100 Subject: [PATCH 10/14] Split resource.Restart out of resource.T Every resource type implementing the starter interface must now embed explicitely resource.Restart. --- core/instance/config.go | 14 +- core/instance/monitor.go | 51 +-- core/instance/states_render.go | 2 +- core/instance/status.go | 14 +- core/manifest/dbkeywords.go | 4 +- core/resource/info.go | 19 +- core/resource/resource.go | 43 +-- core/tui/instance.go | 2 +- daemon/api/api.yaml | 6 - daemon/api/codegen_client_gen.go | 2 +- daemon/api/codegen_server_gen.go | 544 ++++++++++++++-------------- daemon/api/codegen_type_gen.go | 2 +- daemon/imon/main_cmd.go | 2 +- drivers/resapp/base.go | 1 + drivers/rescontainerkvm/main.go | 1 + drivers/rescontainerlxc/main.go | 1 + drivers/rescontainerocibase/main.go | 1 + drivers/rescontainervbox/main.go | 1 + drivers/resdisk/main.go | 1 + drivers/resfsdir/main.go | 1 + drivers/resfsflag/main.go | 1 + drivers/resfshost/main.go | 1 + drivers/resfszfs/main.go | 1 + drivers/resipcni/main.go | 1 + drivers/resiphost/main.go | 1 + drivers/resipnetns/main.go | 1 + drivers/resiproute/main.go | 1 + drivers/ressharenfs/main.go | 1 + drivers/ressyncsymsrdfs/main.go | 1 + drivers/resvol/main.go | 1 + 30 files changed, 372 insertions(+), 350 deletions(-) diff --git a/core/instance/config.go b/core/instance/config.go index 5011391ae..013f09c50 100644 --- a/core/instance/config.go +++ b/core/instance/config.go @@ -64,7 +64,7 @@ type ( IsMonitored bool `json:"is_monitored"` IsStandby bool `json:"is_standby"` Restart int `json:"restart,omitempty"` - RestartDelay *time.Duration `json:"restart_delay"` + RestartDelay *time.Duration `json:"restart_delay,omitempty"` } SubsetConfig struct { Parallel bool `json:"parallel,omitempty"` @@ -172,11 +172,13 @@ func (t Config) Unstructured() map[string]any { func (t ResourceConfig) Unstructured() map[string]any { m := map[string]any{ - "is_disabled": t.IsDisabled, - "is_monitored": t.IsMonitored, - "is_standby": t.IsStandby, - "restart": t.Restart, - "restart_delay": t.RestartDelay, + "is_disabled": t.IsDisabled, + "is_monitored": t.IsMonitored, + "is_standby": t.IsStandby, + "restart": t.Restart, + } + if t.RestartDelay != nil { + m["restart_delay"] = t.RestartDelay } return m } diff --git a/core/instance/monitor.go b/core/instance/monitor.go index 84296f58a..e7682e476 100644 --- a/core/instance/monitor.go +++ b/core/instance/monitor.go @@ -199,12 +199,20 @@ func (t *MonitorGlobalExpect) UnmarshalText(b []byte) error { } } -func (rmon *ResourceMonitor) DecRestartRemaining() { - if rmon.Restart.Remaining > 0 { - rmon.Restart.Remaining -= 1 +func (m *ResourceMonitor) DecRestartRemaining() { + if m.Restart.Remaining > 0 { + m.Restart.Remaining -= 1 } } +func (t *ResourceMonitor) Unstructured() map[string]any { + m := map[string]any{} + if t.Restart != nil { + m["restart"] = t.Restart.Unstructured() + } + return m +} + func (m ResourceMonitors) Set(rid string, rmon ResourceMonitor) { m[rid] = rmon } @@ -220,16 +228,21 @@ func (m ResourceMonitors) Get(rid string) *ResourceMonitor { func (m ResourceMonitors) DeepCopy() ResourceMonitors { c := make(ResourceMonitors) for k, v := range m { - v2 := ResourceMonitor{} - if v.Restart != nil { - r2 := *v.Restart - v2.Restart = &r2 + c[k] = ResourceMonitor{ + Restart: v.Restart.DeepCopy(), } - c[k] = v2 } return c } +func (t ResourceMonitors) Unstructured() map[string]map[string]any { + m := make(map[string]map[string]any) + for k, v := range t { + m[k] = v.Unstructured() + } + return m +} + func (mon Monitor) DeepCopy() *Monitor { v := mon v.Resources = v.Resources.DeepCopy() @@ -251,15 +264,17 @@ func (mon Monitor) DeepCopy() *Monitor { return &v } -func (t ResourceMonitor) Unstructured() map[string]any { - m := map[string]any{} - if t.Restart != nil { - m["restart"] = t.Restart.Unstructured() +func (t *ResourceMonitorRestart) DeepCopy() *ResourceMonitorRestart { + if t == nil { + return nil + } + return &ResourceMonitorRestart{ + Remaining: t.Remaining, + LastAt: t.LastAt, } - return m } -func (t ResourceMonitorRestart) Unstructured() map[string]any { +func (t *ResourceMonitorRestart) Unstructured() map[string]any { return map[string]any{ "remaining": t.Remaining, "last_at": t.LastAt, @@ -296,14 +311,6 @@ func (t Monitor) Unstructured() map[string]any { return m } -func (t ResourceMonitors) Unstructured() map[string]map[string]any { - m := make(map[string]map[string]any) - for k, v := range t { - m[k] = v.Unstructured() - } - return m -} - func (t MonitorUpdate) String() string { s := fmt.Sprintf("CandidateOrchestrationID=%s", t.CandidateOrchestrationID) if t.State != nil { diff --git a/core/instance/states_render.go b/core/instance/states_render.go index 024e570a3..2ce75a47a 100644 --- a/core/instance/states_render.go +++ b/core/instance/states_render.go @@ -88,7 +88,7 @@ func (t States) LoadTreeNode(head *tree.Node) { lastSubset = r.Subset } doResource := func(n *tree.Node, r resource.Status) *tree.Column { - flags := ResourceFlagsString(r.ResourceID.Name, t.Monitor, t.Status, r) + flags := ResourceFlagsString(r.ResourceID.Name, t, r) n.AddColumn().AddText(r.ResourceID.Name) n.AddColumn().AddText(flags) n.AddColumn().AddText(colorstatus.Sprint(r.Status, rawconfig.Colorize)) diff --git a/core/instance/status.go b/core/instance/status.go index 20cceaf45..22bba3ddb 100644 --- a/core/instance/status.go +++ b/core/instance/status.go @@ -127,9 +127,9 @@ func (a ResourceOrder) Less(i, j int) bool { // P Provisioned // S Standby // Restart remaining, + More than 9 remaining, X UserStopped -func ResourceFlagsString(rid string, mon Monitor, status Status, rstatus resource.Status) string { +func ResourceFlagsString(rid string, states States, rstatus resource.Status) string { runningFlag := func() string { - if status.Running.Has(rid) { + if states.Status.Running.Has(rid) { return "R" } else { return "." @@ -137,16 +137,20 @@ func ResourceFlagsString(rid string, mon Monitor, status Status, rstatus resourc } restartFlag := func() string { retries := 0 - if rmon := mon.Resources.Get(rid); rmon != nil { + restart := 0 + if rcfg := states.Config.Resources.Get(rid); rcfg != nil { + restart = rcfg.Restart + } + if rmon := states.Monitor.Resources.Get(rid); rmon != nil { if rmon.Restart != nil { retries = rmon.Restart.Remaining } } - s := rstatus.RestartFlag(retries) + s := rstatus.RestartFlag(restart, retries) if s == "." { return s } - if mon.LocalExpect != MonitorLocalExpectStarted || status.IsFrozen() { + if states.Monitor.LocalExpect != MonitorLocalExpectStarted || states.Status.IsFrozen() { s = rawconfig.Colorize.Secondary(s) } return s diff --git a/core/manifest/dbkeywords.go b/core/manifest/dbkeywords.go index 1c6c7cd8a..5ce1fb425 100644 --- a/core/manifest/dbkeywords.go +++ b/core/manifest/dbkeywords.go @@ -206,7 +206,7 @@ var ( } KWRestart = keywords.Keyword{ - Attr: "Restart", + Attr: "Restart.Count", Default: "0", Converter: "int", Option: "restart", @@ -215,7 +215,7 @@ var ( } KWRestartDelay = keywords.Keyword{ - Attr: "RestartDelay", + Attr: "Restart.Delay", Converter: "duration", Default: "500ms", Option: "restart_delay", diff --git a/core/resource/info.go b/core/resource/info.go index f0cbad6a5..ef8bfae88 100644 --- a/core/resource/info.go +++ b/core/resource/info.go @@ -28,6 +28,10 @@ type ( infoer interface { Info(context.Context) (InfoKeys, error) } + + restarter interface { + GetRestart() Restart + } ) func GetInfo(ctx context.Context, r Driver) (Info, error) { @@ -62,16 +66,15 @@ func GetInfo(ctx context.Context, r Driver) (Info, error) { Key: "encap", Value: fmt.Sprint(r.IsEncap()), }, - { - Key: "restart", - Value: fmt.Sprint(r.RestartCount()), - }, - { - Key: "restart_delay", - Value: fmt.Sprint(r.GetRestartDelay()), - }, }, } + if i, ok := r.(restarter); ok { + restart := i.GetRestart() + info.Keys = append(info.Keys, + InfoKey{"restart_count", fmt.Sprint(restart.Count)}, + InfoKey{"restart_delay", fmt.Sprint(restart.Delay)}, + ) + } i, ok := r.(infoer) if !ok { return info, nil diff --git a/core/resource/resource.go b/core/resource/resource.go index 294c7afce..68bc3ece5 100644 --- a/core/resource/resource.go +++ b/core/resource/resource.go @@ -71,7 +71,6 @@ type ( GetObject() any GetPG() *pg.Config GetPGID() string - GetRestartDelay() time.Duration ID() *resourceid.T IsActionDisabled() bool IsConfigured() bool @@ -96,7 +95,6 @@ type ( MatchSubset(string) bool MatchTag(string) bool Requires(string) *resourcereqs.T - RestartCount() int RID() string RSubset() string SetObject(any) @@ -109,6 +107,14 @@ type ( VarDir() string } + Restart struct { + // Count is how many times imon should try to restart before giving up. + Count int + + // Delay is the duration between 2 restarts. + Delay *time.Duration + } + // T is the resource type, embedded in each drivers type T struct { Driver @@ -120,8 +126,6 @@ type ( Standby bool Shared bool Encap bool - Restart int - RestartDelay *time.Duration Tags *set.Set BlockingPreStart string BlockingPreStop string @@ -218,9 +222,6 @@ type ( // collect site-wide about this resource. Info map[string]any `json:"info,omitempty"` - // Restart is the number of restart to be tried before giving up. - Restart int `json:"restart,omitempty"` - // Tags is a set of words attached to the resource. Tags TagSet `json:"tags,omitempty"` @@ -280,6 +281,14 @@ var ( ErrBarrier = errors.New("barrier hit") ) +func (t *Restart) GetRestart() Restart { + return *t +} + +func (t *Restart) SetRestart(n *Restart) { + t = n +} + // IsMonitoredFlag returns a one character representation of the IsMonitored state. func (t *Status) IsMonitoredFlag() string { if t.IsMonitored { @@ -297,11 +306,11 @@ func (t *Status) IsDisabledFlag() string { } // RestartFlag returns a one character representation of the Restart state. -func (t *Status) RestartFlag(retries int) string { +func (t *Status) RestartFlag(restart, retries int) string { switch { case t.IsStopped: return "X" - case t.Restart <= 0: + case restart <= 0: return "." case retries <= 0: return "0" @@ -430,19 +439,6 @@ func (t *T) SetConfigured(err error) { t.configurationError = err } -// RestartCount returns the value of the Restart field -func (t *T) RestartCount() int { - return t.Restart -} - -// GetRestartDelay returns the duration between 2 restarts -func (t *T) GetRestartDelay() time.Duration { - if t.RestartDelay == nil { - return 500 * time.Millisecond - } - return *t.RestartDelay -} - // RSubset returns the resource subset name func (t *T) RSubset() string { return t.Subset @@ -607,6 +603,7 @@ func (t *T) trigger(ctx context.Context, s string) error { command.WithName(cmdArgs[0]), command.WithVarArgs(cmdArgs[1:]...), command.WithLogger(&t.log), + command.WithEnv(append(os.Environ(), "OPENSVC_RID="+t.RID())), command.WithStdoutLogLevel(zerolog.InfoLevel), command.WithStderrLogLevel(zerolog.ErrorLevel)) return cmd.Run() @@ -1257,7 +1254,6 @@ func GetStatus(ctx context.Context, r Driver) Status { IsStopped: r.IsStopped(), IsMonitored: r.IsMonitored(), - Restart: r.RestartCount(), IsOptional: r.IsOptional(), IsStandby: r.IsStandby(), IsDisabled: r.IsDisabled(), @@ -1404,7 +1400,6 @@ func (t *Status) Unstructured() map[string]any { "disable": t.IsDisabled, "optional": t.IsOptional, "encap": t.IsEncap, - "restart": t.Restart, "standby": t.IsStandby, "stopped": t.IsStopped, } diff --git a/core/tui/instance.go b/core/tui/instance.go index 8893499f9..411763c68 100644 --- a/core/tui/instance.go +++ b/core/tui/instance.go @@ -249,7 +249,7 @@ func (t *App) updateInstanceView() { return tview.NewTableCell(s).SetSelectable(false) } cellFlags := func(rid string, resourceStatus resource.Status, instanceState instance.States) *tview.TableCell { - s := instance.ResourceFlagsString(rid, instanceState.Monitor, instanceState.Status, resourceStatus) + s := instance.ResourceFlagsString(rid, instanceState, resourceStatus) s = tview.TranslateANSI(s) return tview.NewTableCell(s).SetSelectable(false) } diff --git a/daemon/api/api.yaml b/daemon/api/api.yaml index 9783e6847..0e8e6ad19 100644 --- a/daemon/api/api.yaml +++ b/daemon/api/api.yaml @@ -7066,7 +7066,6 @@ components: - is_monitored - is_standby - restart - - restart_delay properties: is_disabled: type: boolean @@ -7208,8 +7207,6 @@ components: x-go-type-import: path: github.com/opensvc/om3/v3/core/instance type: object - required: - - restart properties: restart: $ref: '#/components/schemas/ResourceMonitorRestart' @@ -7253,7 +7250,6 @@ components: - monitor - optional - provisioned - - restart - standby - status - subset @@ -7291,8 +7287,6 @@ components: Errors in optional resource don't stop a state transition action provisioned: $ref: '#/components/schemas/ResourceProvisionStatus' - restart: - type: integer standby: type: boolean description: | diff --git a/daemon/api/codegen_client_gen.go b/daemon/api/codegen_client_gen.go index 197a5ac3c..55bdb943e 100644 --- a/daemon/api/codegen_client_gen.go +++ b/daemon/api/codegen_client_gen.go @@ -1,6 +1,6 @@ // Package api provides primitives to interact with the openapi HTTP API. // -// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.5.1 DO NOT EDIT. +// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.5.0 DO NOT EDIT. package api import ( diff --git a/daemon/api/codegen_server_gen.go b/daemon/api/codegen_server_gen.go index a84d60f46..4cab0c0ff 100644 --- a/daemon/api/codegen_server_gen.go +++ b/daemon/api/codegen_server_gen.go @@ -1,6 +1,6 @@ // Package api provides primitives to interact with the openapi HTTP API. // -// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.5.1 DO NOT EDIT. +// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.5.0 DO NOT EDIT. package api import ( @@ -6230,281 +6230,281 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "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", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/daemon/api/codegen_type_gen.go b/daemon/api/codegen_type_gen.go index b4fd94ae6..d3b968601 100644 --- a/daemon/api/codegen_type_gen.go +++ b/daemon/api/codegen_type_gen.go @@ -1,6 +1,6 @@ // Package api provides primitives to interact with the openapi HTTP API. // -// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.5.1 DO NOT EDIT. +// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.5.0 DO NOT EDIT. package api import ( diff --git a/daemon/imon/main_cmd.go b/daemon/imon/main_cmd.go index da554ce90..80525aceb 100644 --- a/daemon/imon/main_cmd.go +++ b/daemon/imon/main_cmd.go @@ -1150,8 +1150,8 @@ func (t *Manager) initResourceMonitor() { resourceMonitor.Restart = &instance.ResourceMonitorRestart{ Remaining: rcfg.Restart, } + m[rid] = resourceMonitor } - m[rid] = resourceMonitor if rcfg.IsMonitored && hasMonitorActionNone { t.orchestrationResource(rcfg.IsStandby).log.Infof("rid %s is monitored, but monitor action is none", rid) } diff --git a/drivers/resapp/base.go b/drivers/resapp/base.go index 2e24bbedd..933252170 100644 --- a/drivers/resapp/base.go +++ b/drivers/resapp/base.go @@ -16,6 +16,7 @@ import ( // BaseT is the app base driver structure type BaseT struct { resource.T + resource.Restart RetCodes string `json:"retcodes"` Path naming.Path `json:"path"` Nodes []string `json:"nodes"` diff --git a/drivers/rescontainerkvm/main.go b/drivers/rescontainerkvm/main.go index 85869aaaf..fd9ba733e 100644 --- a/drivers/rescontainerkvm/main.go +++ b/drivers/rescontainerkvm/main.go @@ -53,6 +53,7 @@ const ( type ( T struct { resource.T + resource.Restart resource.SSH resource.SCSIPersistentReservation Path naming.Path `json:"path"` diff --git a/drivers/rescontainerlxc/main.go b/drivers/rescontainerlxc/main.go index 59ee2d6b0..cc70c8b15 100644 --- a/drivers/rescontainerlxc/main.go +++ b/drivers/rescontainerlxc/main.go @@ -55,6 +55,7 @@ var _ resource.Encaper = (*T)(nil) type ( T struct { resource.T + resource.Restart resource.SSH resource.SCSIPersistentReservation Path naming.Path `json:"path"` diff --git a/drivers/rescontainerocibase/main.go b/drivers/rescontainerocibase/main.go index a92116f57..79239b109 100644 --- a/drivers/rescontainerocibase/main.go +++ b/drivers/rescontainerocibase/main.go @@ -46,6 +46,7 @@ import ( type ( BT struct { resource.T + resource.Restart resource.SCSIPersistentReservation ObjectDomain string `json:"object_domain"` PG pg.Config `json:"pg"` diff --git a/drivers/rescontainervbox/main.go b/drivers/rescontainervbox/main.go index 97aeae0e7..8265a96b5 100644 --- a/drivers/rescontainervbox/main.go +++ b/drivers/rescontainervbox/main.go @@ -40,6 +40,7 @@ import ( type ( T struct { resource.T + resource.Restart resource.SSH resource.SCSIPersistentReservation Path naming.Path `json:"path"` diff --git a/drivers/resdisk/main.go b/drivers/resdisk/main.go index 260e88304..ee057590a 100644 --- a/drivers/resdisk/main.go +++ b/drivers/resdisk/main.go @@ -11,6 +11,7 @@ import ( type ( T struct { resource.T + resource.Restart resource.SCSIPersistentReservation PromoteRW bool } diff --git a/drivers/resfsdir/main.go b/drivers/resfsdir/main.go index 5788a2e22..db35b1e66 100644 --- a/drivers/resfsdir/main.go +++ b/drivers/resfsdir/main.go @@ -21,6 +21,7 @@ const ( type ( T struct { resource.T + resource.Restart Path string `json:"path"` User *user.User `json:"user"` Group *user.Group `json:"group"` diff --git a/drivers/resfsflag/main.go b/drivers/resfsflag/main.go index 256b38d96..9d5c86cd3 100644 --- a/drivers/resfsflag/main.go +++ b/drivers/resfsflag/main.go @@ -22,6 +22,7 @@ import ( // T is the driver structure. type T struct { resource.T + resource.Restart resource.SSH Path naming.Path `json:"path"` Nodes []string `json:"nodes"` diff --git a/drivers/resfshost/main.go b/drivers/resfshost/main.go index 7b8a17182..787436b0f 100644 --- a/drivers/resfshost/main.go +++ b/drivers/resfshost/main.go @@ -31,6 +31,7 @@ import ( type ( T struct { resource.T + resource.Restart resource.SCSIPersistentReservation Path naming.Path MountPoint string `json:"mnt"` diff --git a/drivers/resfszfs/main.go b/drivers/resfszfs/main.go index 1cfeb8d7f..8a4e7b66b 100644 --- a/drivers/resfszfs/main.go +++ b/drivers/resfszfs/main.go @@ -30,6 +30,7 @@ import ( type ( T struct { resource.T + resource.Restart MountPoint string `json:"mnt"` Device string `json:"dev"` MountOptions string `json:"mnt_opt"` diff --git a/drivers/resipcni/main.go b/drivers/resipcni/main.go index 8766b3a6c..50e120997 100644 --- a/drivers/resipcni/main.go +++ b/drivers/resipcni/main.go @@ -36,6 +36,7 @@ import ( type ( T struct { resource.T + resource.Restart Path naming.Path DNS []string diff --git a/drivers/resiphost/main.go b/drivers/resiphost/main.go index 36266b717..d3c4da8c6 100644 --- a/drivers/resiphost/main.go +++ b/drivers/resiphost/main.go @@ -30,6 +30,7 @@ const ( type ( T struct { resource.T + resource.Restart Path naming.Path ObjectFQDN string diff --git a/drivers/resipnetns/main.go b/drivers/resipnetns/main.go index c1e10eb14..b5e62a5d4 100644 --- a/drivers/resipnetns/main.go +++ b/drivers/resipnetns/main.go @@ -38,6 +38,7 @@ const ( type ( T struct { resource.T + resource.Restart Path naming.Path ObjectFQDN string diff --git a/drivers/resiproute/main.go b/drivers/resiproute/main.go index ceaa6226b..aac2544ce 100644 --- a/drivers/resiproute/main.go +++ b/drivers/resiproute/main.go @@ -14,6 +14,7 @@ type T struct { NetNS string `json:"netns"` Dev string `json:"dev"` resource.T + resource.Restart } // New allocates a new driver diff --git a/drivers/ressharenfs/main.go b/drivers/ressharenfs/main.go index 2c0d92c45..55e94ae65 100644 --- a/drivers/ressharenfs/main.go +++ b/drivers/ressharenfs/main.go @@ -14,6 +14,7 @@ import ( // T is the driver structure. type T struct { resource.T + resource.Restart SharePath string `json:"path"` ShareOpts string `json:"opts"` diff --git a/drivers/ressyncsymsrdfs/main.go b/drivers/ressyncsymsrdfs/main.go index af03f7667..7eacf6381 100644 --- a/drivers/ressyncsymsrdfs/main.go +++ b/drivers/ressyncsymsrdfs/main.go @@ -33,6 +33,7 @@ import ( type ( T struct { ressync.T + resource.Restart SymDG string SymID string RDFG int diff --git a/drivers/resvol/main.go b/drivers/resvol/main.go index b29a6ecbd..2a3f66963 100644 --- a/drivers/resvol/main.go +++ b/drivers/resvol/main.go @@ -52,6 +52,7 @@ import ( type ( T struct { resource.T + resource.Restart datarecv.DataRecv Name string `json:"name"` Access string `json:"access"` From 1bbeee3fa716f665552c74355d4b91de90d5e5d7 Mon Sep 17 00:00:00 2001 From: Christophe Varoqui Date: Fri, 6 Feb 2026 16:46:04 +0100 Subject: [PATCH 11/14] Nicer resource configuration error get/set interface Replace: * IsConfigured() bool * SetConfigured(error) * GetConfigurationError() error With a nicer: * GetConfigurationError() error * SetConfigurationError(error) --- core/object/actor.go | 4 ++-- core/object/actor_push_resinfo.go | 2 +- core/object/core_action.go | 6 +++--- core/resource/resource.go | 12 ++++-------- core/resourceset/resourceset.go | 2 +- 5 files changed, 11 insertions(+), 15 deletions(-) diff --git a/core/object/actor.go b/core/object/actor.go index 940562198..58415ecf3 100644 --- a/core/object/actor.go +++ b/core/object/actor.go @@ -306,7 +306,7 @@ func (t *actor) ConfigureResources() { } postponed[o.RID] = append(postponed[o.RID], r) default: - r.SetConfigured(err) + r.SetConfigurationError(err) t.log.Tracef("resource %s configuration error: %s", k, err) t._resources = append(t._resources, r) } @@ -321,7 +321,7 @@ func (t *actor) ConfigureResources() { rBegin := time.Now() k := r.RID() if err := t.ReconfigureResource(r); err != nil { - r.SetConfigured(err) + r.SetConfigurationError(err) t.log.Tracef("postponed resource %s configuration error: %s", k, err) t._resources = append(t._resources, r) continue diff --git a/core/object/actor_push_resinfo.go b/core/object/actor_push_resinfo.go index ba293836e..e19e3ddcd 100644 --- a/core/object/actor_push_resinfo.go +++ b/core/object/actor_push_resinfo.go @@ -95,7 +95,7 @@ func (t *actor) masterResInfo(ctx context.Context) ([]resource.Info, error) { resourceLister := resourceselector.FromContext(ctx, t) barrier := actioncontext.To(ctx) err := t.ResourceSets().Do(ctx, resourceLister, barrier, "resinfo", func(ctx context.Context, r resource.Driver) error { - if !r.IsConfigured() { + if r.GetConfigurationError() != nil { return nil } info, err := resource.GetInfo(ctx, r) diff --git a/core/object/core_action.go b/core/object/core_action.go index e8ba4a7d0..8b103c81f 100644 --- a/core/object/core_action.go +++ b/core/object/core_action.go @@ -306,7 +306,7 @@ func (t *actor) abortStartDrivers(ctx context.Context, resources resource.Driver q := make(chan bool, len(resources)) var wg sync.WaitGroup for _, r := range resources { - if !r.IsConfigured() { + if r.GetConfigurationError() != nil { return nil } if v, err := t.isEncapNodeMatchingResource(r); err != nil { @@ -629,8 +629,8 @@ func (t *actor) action(ctx context.Context, fn resourceset.DoFunc) error { progressWrap := func(fn resourceset.DoFunc) resourceset.DoFunc { return func(ctx context.Context, r resource.Driver) error { - if !r.IsConfigured() { - r.Log().Warnf("skip resource with configuration error: %s", r.GetConfigurationError()) + if err := r.GetConfigurationError(); err != nil { + r.Log().Warnf("skip resource with configuration error: %s", err) return nil } if v, err := t.isEncapNodeMatchingResource(r); err != nil { diff --git a/core/resource/resource.go b/core/resource/resource.go index 68bc3ece5..e25e28852 100644 --- a/core/resource/resource.go +++ b/core/resource/resource.go @@ -67,13 +67,11 @@ type ( // common ApplyPGChain(context.Context) error - GetConfigurationError() error GetObject() any GetPG() *pg.Config GetPGID() string ID() *resourceid.T IsActionDisabled() bool - IsConfigured() bool IsDisabled() bool IsEncap() bool IsMonitored() bool @@ -84,7 +82,9 @@ type ( IsStandby() bool IsStopped() bool IsStatusDisabled() bool - SetConfigured(error) + + GetConfigurationError() error + SetConfigurationError(error) // Label returns a formatted short description of the Resource Label(context.Context) string @@ -427,15 +427,11 @@ func (t *T) IsActionDisabled() bool { return t.MatchTag("noaction") } -func (t *T) IsConfigured() bool { - return t.configurationError == nil -} - func (t *T) GetConfigurationError() error { return t.configurationError } -func (t *T) SetConfigured(err error) { +func (t *T) SetConfigurationError(err error) { t.configurationError = err } diff --git a/core/resourceset/resourceset.go b/core/resourceset/resourceset.go index e1b16d702..b6054add7 100644 --- a/core/resourceset/resourceset.go +++ b/core/resourceset/resourceset.go @@ -312,7 +312,7 @@ func (t T) doSerial(ctx context.Context, l ResourceLister, resources resource.Dr pgMgr.Register(r.GetPG()) } if err := l.ReconfigureResource(r); err != nil { - r.SetConfigured(err) + r.SetConfigurationError(err) } err := fn(ctx, r) if err == nil { From e3dd9f6b64796a319e64300c5dd384003e106ea3 Mon Sep 17 00:00:00 2001 From: Christophe Varoqui Date: Fri, 6 Feb 2026 17:10:49 +0100 Subject: [PATCH 12/14] Fix a go test in core/instance/ --- core/instance/instance_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/core/instance/instance_test.go b/core/instance/instance_test.go index 319444eb1..fe3f6fd42 100644 --- a/core/instance/instance_test.go +++ b/core/instance/instance_test.go @@ -71,7 +71,6 @@ func Test_Status_Unmarshal(t *testing.T) { Mtime: time.Date(2022, time.November, 28, 21, 46, 25, 849702075, time.UTC), State: provisioned.False, }, - Restart: 2, }, }, } From a0d732cb83bf19e676c0d370c7a6c60fd6e44416 Mon Sep 17 00:00:00 2001 From: Christophe Varoqui Date: Fri, 6 Feb 2026 19:34:31 +0100 Subject: [PATCH 13/14] Fix renderers accessing *ActorConfig fields without checking nil This caused "status -m" and "status -r" exit 2 errors in the daemon logs. --- core/instance/states_render.go | 8 +++++--- core/instance/status.go | 4 ++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/core/instance/states_render.go b/core/instance/states_render.go index 2ce75a47a..b32a73aa7 100644 --- a/core/instance/states_render.go +++ b/core/instance/states_render.go @@ -78,9 +78,11 @@ func (t States) LoadTreeNode(head *tree.Node) { subsetNode.AddColumn() subsetNode.AddColumn() parallel := "" - if subset, ok := t.Config.Subsets[resourceSetName]; ok { - if subset.Parallel { - parallel = "//" + if t.Config.ActorConfig != nil { + if subset, ok := t.Config.Subsets[resourceSetName]; ok { + if subset.Parallel { + parallel = "//" + } } } subsetNode.AddColumn().AddText(parallel) diff --git a/core/instance/status.go b/core/instance/status.go index 22bba3ddb..df19862b4 100644 --- a/core/instance/status.go +++ b/core/instance/status.go @@ -136,6 +136,10 @@ func ResourceFlagsString(rid string, states States, rstatus resource.Status) str } } restartFlag := func() string { + if states.Config.ActorConfig == nil { + // only actors have the Resources field + return "." + } retries := 0 restart := 0 if rcfg := states.Config.Resources.Get(rid); rcfg != nil { From ed14bea951f7456043f3f04dd5ce86081bf2ac81 Mon Sep 17 00:00:00 2001 From: Christophe Varoqui Date: Fri, 6 Feb 2026 19:36:03 +0100 Subject: [PATCH 14/14] Fix the monitor action no longer executed no-restart resources Broken by the the "ResourceMonitor as a pointer" patch. --- daemon/imon/orchestration_resource_restart.go | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/daemon/imon/orchestration_resource_restart.go b/daemon/imon/orchestration_resource_restart.go index b05f0db14..82910261a 100644 --- a/daemon/imon/orchestration_resource_restart.go +++ b/daemon/imon/orchestration_resource_restart.go @@ -268,9 +268,6 @@ func (t *Manager) orchestrateResourceRestart() { continue } rmon := t.state.Resources.Get(rid) - if rmon == nil { - continue - } needRestart, needMonitorAction, err := t.orchestrateResourcePlan(rid, rcfg, rmon, rstat, started) if err != nil { t.log.Errorf("orchestrate resource plan for resource %s: %s", rid, err) @@ -476,13 +473,6 @@ func (t *Manager) orchestrateResourcePlan(rid string, rcfg *instance.ResourceCon if rcfg == nil { err = fmt.Errorf("orchestrate resource plan called with nil resource monitor") return - } else if rmon == nil { - err = fmt.Errorf("orchestrate resource plan called with nil resource config") - return - } - if rmon.Restart == nil { - // Resource not supporting restarts, e.g. task - return } or := t.orchestrationResource(rcfg.IsStandby) @@ -494,6 +484,9 @@ func (t *Manager) orchestrateResourcePlan(rid string, rcfg *instance.ResourceCon } resetRemaining := func(rid string, reason string) { + if rmon == nil || rmon.Restart == nil { + return + } if rmon.Restart.Remaining != rcfg.Restart { or.log.Infof("rid %s %s: reset restart count to config value (%d -> %d)", rid, reason, rmon.Restart.Remaining, rcfg.Restart) rmon.Restart.Remaining = rcfg.Restart @@ -525,7 +518,12 @@ func (t *Manager) orchestrateResourcePlan(rid string, rcfg *instance.ResourceCon case t.monitorActionCalled(): or.log.Tracef("planFor rid %s skipped: monitor action has been already called", rid) case rcfg.IsStandby || started: - if rmon.Restart.Remaining == 0 && rcfg.IsMonitored { + if rmon == nil || rmon.Restart == nil { + if rcfg.IsMonitored { + or.log.Infof("rid %s status %s, no restart configured: need monitor action", rid, rStatus.Status) + needMonitorAction = true + } + } else if rmon.Restart.Remaining == 0 && rcfg.IsMonitored { or.log.Infof("rid %s status %s, restart remaining %d out of %d: need monitor action", rid, rStatus.Status, rmon.Restart.Remaining, rcfg.Restart) needMonitorAction = true } else if rmon.Restart.Remaining > 0 {