]> git.proxmox.com Git - pmg-api.git/blame - PMG/ClusterConfig.pm
pmgconfig: split command into smaller parts
[pmg-api.git] / PMG / ClusterConfig.pm
CommitLineData
9f67f5b3
DM
1package PMG::ClusterConfig::Base;
2
3use strict;
4use warnings;
5use Data::Dumper;
6
7use PVE::Tools;
8use PVE::JSONSchema qw(get_standard_option);
9use PVE::SectionConfig;
10
11use base qw(PVE::SectionConfig);
12
13my $defaultData = {
14 propertyList => {
15 type => { description => "Cluster node type." },
16 cid => {
17 description => "Cluster Node ID.",
18 type => 'integer',
19 minimum => 1,
20 },
21 },
22};
23
24sub private {
25 return $defaultData;
26}
27
28sub parse_section_header {
29 my ($class, $line) = @_;
30
31 if ($line =~ m/^(node|master):\s*(\d+)\s*$/) {
32 my ($type, $sectionId) = ($1, $2);
33 my $errmsg = undef; # set if you want to skip whole section
34 my $config = {}; # to return additional attributes
35 return ($type, $sectionId, $errmsg, $config);
36 }
37 return undef;
38}
39
40
41package PMG::ClusterConfig::Node;
42
43use strict;
44use warnings;
45
46use base qw(PMG::ClusterConfig::Base);
47
48sub type {
49 return 'node';
50}
51sub properties {
52 return {
53 ip => {
54 description => "IP address.",
55 type => 'string', format => 'address',
56 },
57 name => {
58 description => "Node name.",
59 type => 'string', format =>'pve-node',
60 },
61 hostrsapubkey => {
62 description => "Public SSH RSA key for the host.",
63 type => 'string',
64 },
65 rootrsapubkey => {
66 description => "Public SSH RSA key for the root user.",
67 type => 'string',
68 },
69 };
70}
71
72sub options {
73 return {
74 ip => { fixed => 1 },
75 name => { fixed => 1 },
76 hostrsapubkey => {},
77 rootrsapubkey => {},
78 };
79}
80
81package PMG::ClusterConfig::Master;
82
83use strict;
84use warnings;
85
86use base qw(PMG::ClusterConfig::Base);
87
88sub type {
89 return 'master';
90}
91
92sub properties {
93 return {
94 maxcid => {
95 description => "Maximum used cluster node ID (used internally, do not modify).",
96 type => 'integer',
97 minimum => 1,
98 },
99 };
100}
101
102sub options {
103 return {
104 maxcid => { fixed => 1 },
105 ip => { fixed => 1 },
106 name => { fixed => 1 },
107 hostrsapubkey => {},
108 rootrsapubkey => {},
109 };
110}
111
112package PMG::ClusterConfig;
113
114use strict;
115use warnings;
116use Data::Dumper;
117
118use PVE::SafeSyslog;
119use PVE::Tools;
120use PVE::INotify;
121
122use PMG::Utils;
123
124PMG::ClusterConfig::Node->register;
125PMG::ClusterConfig::Master->register;
126PMG::ClusterConfig::Base->init();
127
128
129sub new {
130 my ($type) = @_;
131
132 my $class = ref($type) || $type;
133
134 my $cfg = PVE::INotify::read_file("cluster.conf");
135
136 return bless $cfg, $class;
137}
138
139sub write {
140 my ($self) = @_;
141
142 PVE::INotify::write_file("cluster.conf", $self);
143}
144
145my $lockfile = "/var/lock/pmgcluster.lck";
146
147sub lock_config {
148 my ($code, $errmsg) = @_;
149
150 my $p = PVE::Tools::lock_file($lockfile, undef, $code);
151 if (my $err = $@) {
152 $errmsg ? die "$errmsg: $err" : die $err;
153 }
154}
155
156sub read_cluster_conf {
157 my ($filename, $fh) = @_;
158
159 local $/ = undef; # slurp mode
160
161 my $raw = defined($fh) ? <$fh> : undef;
162
163 my $cinfo = PMG::ClusterConfig::Base->parse_config($filename, $raw);
9f67f5b3
DM
164
165 my $localname = PVE::INotify::nodename();
166 my $localip = PMG::Utils::lookup_node_ip($localname);
167
168 $cinfo->{remnodes} = [];
169 $cinfo->{configport}->{0} = 83;
170 $cinfo->{dbport}->{0} = 5432;
171
172 $cinfo->{local} = {
173 cid => 0,
174 ip => $localip,
175 name => $localname,
176 };
177
178 my $maxcid = 0;
179 my $names_hash = {};
180
181 my $errprefix = "unable to parse $filename";
182
183 foreach my $cid (keys %{$cinfo->{ids}}) {
184 my $d = $cinfo->{ids}->{$cid};
185
186 die "$errprefix: duplicate use of name '$d->{name}'\n" if $names_hash->{$d->{name}};
187 $names_hash->{$d->{name}} = 1;
188
189 $d->{cid} = $cid;
190 $maxcid = $cid > $maxcid ? $cid : $maxcid;
191 $maxcid = $d->{maxcid} if defined($d->{maxcid}) && $d->{maxcid} > $maxcid;
192 $cinfo->{master} = $d if $d->{type} eq 'master';
193 $cinfo->{'local'} = $d if $d->{name} eq $localname;
194 }
195
196 if ($maxcid) {
197 die "$errprefix: cluster without master node\n"
198 if !defined($cinfo->{master});
199 $cinfo->{master}->{maxcid} = $maxcid;
200 }
201
202 my $ind = 0;
203 foreach my $cid (sort keys %{$cinfo->{ids}}) {
204 if ($cinfo->{'local'}->{cid} == $cid) { # local CID
205 $cinfo->{configport}->{$cid} = 83;
206 $cinfo->{dbport}->{$cid} = 5432;
207 } else {
208 my $portid = $ind++;
209 $cinfo->{configport}->{$cid} = 50000 + $portid;
210 $cinfo->{dbport}->{$cid} = 50100 + $portid;
cf07e7c3 211 push @{$cinfo->{remnodes}}, $cid;
9f67f5b3
DM
212 }
213 }
214
215 return $cinfo;
216}
217
218sub write_cluster_conf {
219 my ($filename, $fh, $cfg) = @_;
220
221 my $raw = PMG::ClusterConfig::Base->write_config($filename, $cfg);
222
223 PVE::Tools::safe_print($filename, $fh, $raw);
224}
225
226PVE::INotify::register_file('cluster.conf', "/etc/proxmox/cluster.conf",
227 \&read_cluster_conf,
228 \&write_cluster_conf,
229 undef,
230 always_call_parser => 1);
231
2321;