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