+ # Make sure that the newly added node has links compatible with the
+ # rest of the cluster. To start, extract all links that currently
+ # exist. Check any node, all have the same links here (because of
+ # verify_conf above).
+ my $node_options = (values %$nodelist)[0];
+ my $cluster_links = {};
+ foreach my $opt (keys %$node_options) {
+ my ($linktype, $linkid) = PVE::Corosync::parse_link_entry($opt);
+ next if !defined($linktype);
+ $cluster_links->{$linkid} = $node_options->{$opt};
+ }
+
+ # in case no fallback IP was passed, but instead only a single link,
+ # treat it as fallback to allow link-IDs to be matched automatically
+ # FIXME: remove in 8.0 or when joining an old node not supporting
+ # new_node_ip becomes infeasible otherwise
+ my $legacy_fallback = 0;
+ if (!$param->{new_node_ip} && scalar(%$links) == 1) {
+ my $passed_link_id = (keys %$links)[0];
+ my $passed_link = delete $links->{$passed_link_id};
+ $param->{new_node_ip} = $passed_link->{address};
+ $legacy_fallback = 1;
+ }
+
+ if (scalar(%$links)) {
+ # verify specified links exist and none are missing
+ for my $linknum (0..PVE::Corosync::MAX_LINK_INDEX) {
+ my $have_cluster_link = defined($cluster_links->{$linknum});
+ my $have_new_link = defined($links->{$linknum});
+
+ die "corosync: link $linknum exists in cluster config but wasn't specified for new node\n"
+ if $have_cluster_link && !$have_new_link;
+ die "corosync: link $linknum specified for new node doesn't exist in cluster config\n"
+ if !$have_cluster_link && $have_new_link;
+ }
+ } else {
+ # when called without any link parameters, fall back to
+ # new_node_ip, if all existing nodes only have a single link too
+ die "no links and no fallback ip (new_node_ip) given, cannot join cluster\n"
+ if !$param->{new_node_ip};
+
+ my $cluster_link_count = scalar(%$cluster_links);
+ if ($cluster_link_count == 1) {
+ my $linknum = (keys %$cluster_links)[0];
+ $links->{$linknum} = { address => $param->{new_node_ip} };
+ } else {
+ die "cluster has $cluster_link_count links, but only 1 given"
+ if $legacy_fallback;
+ die "no links given but multiple links found on other nodes,"
+ . " fallback only supported on single-link clusters\n";
+ }
+ }
+