From: Michal Fox <me@dualfroz.com>
To: pve-devel@lists.proxmox.com
Subject: [PATCH cluster] fix #5794: cluster join: check that the interfaces of the links are up
Date: Sat, 3 Oct 2026 13:16:42 +0000 [thread overview]
Message-ID: <20261003131642.7-1-me@dualfroz.com> (raw)
Before joining a cluster, the IPs of the corosync links are checked to
be configured on the node. An IP on an interface without carrier, for
example with an unplugged cable, still counts as configured, so the
join is started even though corosync cannot reach the other nodes.
The join then fails halfway, and the node stays without quorum until
the link comes up, which looks like a split brain.
Additionally check the operational state of the interface the IP is
configured on and refuse to join if it is not up. Interfaces that
report their state as unknown, like dummy interfaces, are treated as
up. Like the other checks, this can be overridden with 'force'.
Signed-off-by: Michal Fox <me@dualfroz.com>
---
Tested with a script that runs assert_joinable() in a container with a
veth pair: with the peer down, the IP of link0 is on an interface in
state LOWERLAYERDOWN, and the join is refused with "link0: cannot use
IP '10.100.0.29', interface 'veth0' is not up (LOWERLAYERDOWN)". With
the peer up, the check passes. Missing IPs and interfaces that are
administratively down are reported as before. Without the fix, the
join is not refused. The corosync parser and MAC prefix tests pass.
src/PVE/Cluster/Setup.pm | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)
diff --git a/src/PVE/Cluster/Setup.pm b/src/PVE/Cluster/Setup.pm
index 53935dc..6bc8f18 100644
--- a/src/PVE/Cluster/Setup.pm
+++ b/src/PVE/Cluster/Setup.pm
@@ -6,6 +6,7 @@ use warnings;
use Digest::HMAC_SHA1;
use Digest::SHA;
use IO::File;
+use JSON;
use MIME::Base64;
use Net::IP;
use UUID;
@@ -661,8 +662,23 @@ sub assert_joinable {
my $cidr = (Net::IP::ip_is_ipv6($ip)) ? "$ip/128" : "$ip/32";
my $configured_ips = PVE::Network::get_local_ip_from_cidr($cidr);
- $error->("$logid: cannot use IP '$ip', not found on local node!\n")
- if scalar(@$configured_ips) < 1;
+ if (scalar(@$configured_ips) < 1) {
+ $error->("$logid: cannot use IP '$ip', not found on local node!\n");
+ return;
+ }
+
+ # the IP is also listed if the interface has no carrier, but corosync cannot use it then
+ my $addresses = '';
+ PVE::Tools::run_command(
+ ['/sbin/ip', '-json', 'address', 'show', 'to', $cidr, 'up'],
+ outfunc => sub { $addresses .= shift },
+ );
+ for my $iface (decode_json($addresses)->@*) {
+ my $name = $iface->{ifname} or next;
+ my $state = $iface->{operstate} // 'UNKNOWN';
+ next if $state eq 'UP' || $state eq 'UNKNOWN';
+ $error->("$logid: cannot use IP '$ip', interface '$name' is not up ($state)\n");
+ }
};
$check_ip->($local_addr, 'local node address');
--
2.43.0
reply other threads:[~2026-10-03 13:16 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261003131642.7-1-me@dualfroz.com \
--to=me@dualfroz.com \
--cc=pve-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox