Summary
Under HA (force_ha: true, or more than one front end), one-deploy requires one_vip and
unconditionally installs the built-in floating-VIP RAFT hooks. There is no supported way to run
HA without the VIP.
That blocks a legitimate, documented topology: front ends on different subnets, fronted by an
external load balancer. OpenNebula's VIP is an L2 mechanism (ip address add + gratuitous
arping in raft/vip.sh) and cannot migrate across subnets, so a multi-subnet / multi-DC HA
cluster must route to the current leader with an external LB instead. RAFT itself does not need
the VIP — each server is reached at its own <host>:2633.
Request: make one_vip optional so that, when it is omitted, HA still forms but the VIP hooks
are simply not written.
The collection already half-supports this
Three of the code paths that touch one_vip already tolerate it being undefined — so this request
is small and consistent with patterns already in the tree, not a new concept:
- Leader detection —
roles/opennebula/leader/tasks/main.yml already falls back to the first
front end:
{{ one_vip | d(federation.groups.frontend[0]) }}
- ONEGATE endpoint —
roles/opennebula/server/tasks/config.yml already defaults the endpoint
host to the first front end when there is no VIP:
_default: "{{ 'http://' ~ (one_vip | d(_host)) ~ ':5030' }}"
_host: "{{ hostvars[federation.groups.frontend[0]].ansible_host }}"
- VIP-vars integrity — the second assertion in
roles/precheck/pre_reboot/tasks/integrity.yml
("Check if all vip related settings are provided") already permits one_vip, one_vip_cidr and
one_vip_if to be all undefined together.
What actually blocks it (two places)
roles/precheck/pre_reboot/tasks/integrity.yml — the first assertion ("Check if
one_vip/force_ha settings are valid") requires one_vip to be defined whenever HA is in play, so
it cannot be omitted.
roles/opennebula/server/tasks/config.yml — the when: use_ha is true block templates the
raft/vip.sh RAFT_LEADER_HOOK/RAFT_FOLLOWER_HOOK and monitord's MONITOR_ADDRESS from
one_vip / one_vip_if / one_vip_cidr with no guard, so with HA enabled and one_vip omitted
the play fails on the undefined variables.
Proposed change
1. roles/precheck/pre_reboot/tasks/integrity.yml — relax the first assertion so a missing
one_vip is always valid, while still catching a VIP configured without HA:
- name: Check if one_vip/force_ha settings are valid
ansible.builtin.assert:
- that: ((one_vip is defined) and ((_frontend_count | int > 1) or (_force_ha is true)))
- or
- ((one_vip is undefined) and ((_frontend_count | int == 1) and (_force_ha is false)))
- fail_msg: Please either define one_vip in the inventory, add more Front-ends or enable force_ha.
+ # one_vip is optional: HA can run without a floating VIP behind an external
+ # leader-aware load balancer (e.g. multi-subnet front ends, where an L2 VIP
+ # cannot migrate). A VIP still only makes sense with HA, so keep that guard.
+ that: (one_vip is undefined)
+ or
+ ((_frontend_count | int > 1) or (_force_ha is true))
+ fail_msg: one_vip is set but HA is not enabled — add more Front-ends or set force_ha, or omit one_vip.
vars:
_frontend_count: >-
{{ federation.groups.frontend | count }}
_force_ha: >-
{{ force_ha | d(false) | bool }}
2. roles/opennebula/server/tasks/config.yml — guard the VIP-hook / monitord block on a
defined one_vip:
-- when: use_ha is true
+# Only write the vip.sh RAFT hooks + monitord MONITOR_ADDRESS when a VIP exists.
+# Without one_vip, HA still forms (RAFT SERVER config lives in master.yml / slave.yml)
+# and monitord keeps its per-host default.
+- when:
+ - use_ha is true
+ - one_vip is defined
block:
- name: Configure oned (RAFT)
opennebula.deploy.cfgtool:
dest: /etc/one/oned.conf
parser: One
actions:
- put:
path: [RAFT_LEADER_HOOK, COMMAND]
value: '"raft/vip.sh"'
# ... unchanged ...
Why this is safe
- RAFT / HA is not disabled. The consensus
SERVER configuration is written in master.yml /
slave.yml, not in this block — the guarded block only writes the VIP hooks and the monitord
MONITOR_ADDRESS. Skipping it leaves HA fully intact; it just omits the floating IP.
monitord keeps its per-host default MONITOR_ADDRESS when the block is skipped, which is
what you want with no VIP.
- Fully backward compatible. When
one_vip is defined the when: is true and the assertion
passes exactly as before — behaviour is byte-for-byte unchanged for existing VIP deployments.
Evidence
We have run precisely this two-line change on a 3-node RHEL 10 HA front end with no one_vip,
front ends on separate subnets behind an external leader-aware LB:
- HA zone forms and elects a leader.
- Induced-failover recovery measured at ~4.7s election time.
- No
vip.sh hooks and no floating IP present anywhere.
Suggested test
A molecule assertion that, with one_vip undefined and force_ha: true (or >1 front end), the
converge succeeds and onezone show reports a formed zone with an elected leader — i.e. HA without
a VIP.
Environment
- Collection:
opennebula.deploy, release-1.4.1, consumed unmodified apart from evaluating
the change above.
- Target: RHEL 10 front ends on separate subnets, fronted by an external (F5 GTM) leader-aware LB.
Summary
Under HA (
force_ha: true, or more than one front end),one-deployrequiresone_vipandunconditionally installs the built-in floating-VIP RAFT hooks. There is no supported way to run
HA without the VIP.
That blocks a legitimate, documented topology: front ends on different subnets, fronted by an
external load balancer. OpenNebula's VIP is an L2 mechanism (
ip address add+ gratuitousarpinginraft/vip.sh) and cannot migrate across subnets, so a multi-subnet / multi-DC HAcluster must route to the current leader with an external LB instead. RAFT itself does not need
the VIP — each server is reached at its own
<host>:2633.Request: make
one_vipoptional so that, when it is omitted, HA still forms but the VIP hooksare simply not written.
The collection already half-supports this
Three of the code paths that touch
one_vipalready tolerate it being undefined — so this requestis small and consistent with patterns already in the tree, not a new concept:
roles/opennebula/leader/tasks/main.ymlalready falls back to the firstfront end:
{{ one_vip | d(federation.groups.frontend[0]) }}roles/opennebula/server/tasks/config.ymlalready defaults the endpointhost to the first front end when there is no VIP:
roles/precheck/pre_reboot/tasks/integrity.yml("Check if all vip related settings are provided") already permits
one_vip,one_vip_cidrandone_vip_ifto be all undefined together.What actually blocks it (two places)
roles/precheck/pre_reboot/tasks/integrity.yml— the first assertion ("Check ifone_vip/force_ha settings are valid") requires
one_vipto be defined whenever HA is in play, soit cannot be omitted.
roles/opennebula/server/tasks/config.yml— thewhen: use_ha is trueblock templates theraft/vip.shRAFT_LEADER_HOOK/RAFT_FOLLOWER_HOOKandmonitord'sMONITOR_ADDRESSfromone_vip/one_vip_if/one_vip_cidrwith no guard, so with HA enabled andone_vipomittedthe play fails on the undefined variables.
Proposed change
1.
roles/precheck/pre_reboot/tasks/integrity.yml— relax the first assertion so a missingone_vipis always valid, while still catching a VIP configured without HA:2.
roles/opennebula/server/tasks/config.yml— guard the VIP-hook /monitordblock on adefined
one_vip:Why this is safe
SERVERconfiguration is written inmaster.yml/slave.yml, not in this block — the guarded block only writes the VIP hooks and themonitordMONITOR_ADDRESS. Skipping it leaves HA fully intact; it just omits the floating IP.monitordkeeps its per-host defaultMONITOR_ADDRESSwhen the block is skipped, which iswhat you want with no VIP.
one_vipis defined thewhen:is true and the assertionpasses exactly as before — behaviour is byte-for-byte unchanged for existing VIP deployments.
Evidence
We have run precisely this two-line change on a 3-node RHEL 10 HA front end with no
one_vip,front ends on separate subnets behind an external leader-aware LB:
vip.shhooks and no floating IP present anywhere.Suggested test
A molecule assertion that, with
one_vipundefined andforce_ha: true(or >1 front end), theconverge succeeds and
onezone showreports a formed zone with an elected leader — i.e. HA withouta VIP.
Environment
opennebula.deploy,release-1.4.1, consumed unmodified apart from evaluatingthe change above.