]>
git.proxmox.com Git - pve-cluster.git/blob - data/PVE/Corosync.pm
0d2a85f7dda7d31771461a89bf267725049bdfac
8 use Net
::IP
qw(ip_is_ipv6);
12 my $basedir = "/etc/pve";
14 my $conf_array_sections = {
19 # a very simply parser ...
21 my ($filename, $raw) = @_;
25 my $digest = Digest
::SHA
::sha1_hex
(defined($raw) ?
$raw : '');
33 my @tokens = split(/\s/, $raw);
35 my $conf = { 'main' => {} };
38 my $section = $conf->{main
};
40 while (defined(my $token = shift @tokens)) {
41 my $nexttok = $tokens[0];
43 if ($nexttok && ($nexttok eq '{')) {
44 shift @tokens; # skip '{'
46 if ($conf_array_sections->{$token}) {
47 $section->{$token} = [] if !defined($section->{$token});
48 push @{$section->{$token}}, $new_section;
49 } elsif (!defined($section->{$token})) {
50 $section->{$token} = $new_section;
52 die "section '$token' already exists and not marked as array!\n";
54 push @$stack, $section;
55 $section = $new_section;
60 $section = pop @$stack;
61 die "parse error - uncexpected '}'\n" if !$section;
66 die "missing ':' after key '$key'\n" if ! ($key =~ s/:$//);
68 die "parse error - no value for '$key'\n" if !defined($nexttok);
69 my $value = shift @tokens;
71 $section->{$key} = $value;
74 # make working with the config way easier
75 my ($totem, $nodelist) = $conf->{main
}->@{"totem", "nodelist"};
79 $_->{name
} // $_->{ring0_addr
} => $_
80 } @{$nodelist->{node
}}
82 $totem->{interface
} = {
84 $_->{linknumber
} // $_->{ringnumber
} => $_
85 } @{$totem->{interface
}}
88 $conf->{digest
} = $digest;
95 my ($section, $prefix) = @_;
99 foreach my $k (sort keys %$section) {
100 my $v = $section->{$k};
101 if (ref($v) eq 'HASH') {
102 $raw .= $prefix . "$k {\n";
103 $raw .= &$dump_section($v, "$prefix ");
104 $raw .= $prefix . "}\n";
105 $raw .= "\n" if !$prefix; # add extra newline at 1st level only
106 } elsif (ref($v) eq 'ARRAY') {
107 foreach my $child (@$v) {
108 $raw .= $prefix . "$k {\n";
109 $raw .= &$dump_section($child, "$prefix ");
110 $raw .= $prefix . "}\n";
113 die "got undefined value for key '$k'!\n" if !defined($v);
114 $raw .= $prefix . "$k: $v\n";
116 die "unexpected reference in config hash: $k => ". ref($v) ."\n";
124 my ($filename, $conf) = @_;
126 my $c = clone
($conf->{main
}) // die "no main section";
128 # retransform back for easier dumping
129 my $hash_to_array = sub {
131 return [ $hash->@{sort keys %$hash} ];
134 $c->{nodelist
}->{node
} = &$hash_to_array($c->{nodelist
}->{node
});
135 $c->{totem
}->{interface
} = &$hash_to_array($c->{totem
}->{interface
});
137 my $raw = &$dump_section($c, '');
142 # read only - use atomic_write_conf method to write
143 PVE
::Cluster
::cfs_register_file
('corosync.conf', \
&parse_conf
);
145 PVE
::Cluster
::cfs_register_file
('corosync.conf.new', \
&parse_conf
,
148 sub check_conf_exists
{
151 $silent = $silent // 0;
153 my $exists = -f
"$basedir/corosync.conf";
155 warn "Corosync config '$basedir/corosync.conf' does not exist - is this node part of a cluster?\n"
156 if !$silent && !$exists;
161 sub update_nodelist
{
162 my ($conf, $nodelist) = @_;
164 $conf->{main
}->{nodelist
}->{node
} = $nodelist;
166 atomic_write_conf
($conf);
171 return clone
($conf->{main
}->{nodelist
}->{node
});
176 return clone
($conf->{main
}->{totem
});
179 # caller must hold corosync.conf cfs lock if used in read-modify-write cycle
180 sub atomic_write_conf
{
181 my ($conf, $no_increase_version) = @_;
183 if (!$no_increase_version) {
184 die "invalid corosync config: unable to read config version\n"
185 if !defined($conf->{main
}->{totem
}->{config_version
});
186 $conf->{main
}->{totem
}->{config_version
}++;
189 PVE
::Cluster
::cfs_write_file
("corosync.conf.new", $conf);
191 rename("/etc/pve/corosync.conf.new", "/etc/pve/corosync.conf")
192 || die "activating corosync.conf.new failed - $!\n";
195 # for creating a new cluster with the current node
196 # params are those from the API/CLI cluster create call
198 my ($nodename, %param) = @_;
200 my $clustername = $param{clustername
};
201 my $nodeid = $param{nodeid
} || 1;
202 my $votes = $param{votes
} || 1;
204 my $local_ip_address = PVE
::Cluster
::remote_node_ip
($nodename);
206 my $link0 = PVE
::Cluster
::parse_corosync_link
($param{link0
});
207 $link0->{address
} //= $local_ip_address;
211 version
=> 2, # protocol version
213 cluster_name
=> $clustername,
215 ip_version
=> 'ipv4-6',
227 quorum_votes
=> $votes,
228 ring0_addr
=> $link0->{address
},
233 provider
=> 'corosync_votequorum',
241 my $link1 = PVE
::Cluster
::parse_corosync_link
($param{link1
});
243 if ($link1->{address
}) {
244 $conf->{totem
}->{interface
}->{1} = {
247 $conf->{totem
}->{link_mode
} = 'passive';
248 $conf->{nodelist
}->{node
}->{$nodename}->{ring1_addr
} = $link1->{address
};
251 return { main
=> $conf };