1 |
95b003ff
|
Origo
|
#!/usr/bin/perl -U
|
2 |
|
|
|
3 |
|
|
# All rights reserved and Copyright (c) 2020 Origo Systems ApS.
|
4 |
|
|
# This file is provided with no warranty, and is subject to the terms and conditions defined in the license file LICENSE.md.
|
5 |
|
|
# The license file is part of this source code package and its content is also available at:
|
6 |
|
|
# https://www.origo.io/info/stabiledocs/licensing/stabile-open-source-license
|
7 |
|
|
|
8 |
|
|
package Stabile::Pressurecontrol;
|
9 |
|
|
|
10 |
|
|
use Config::Simple;
|
11 |
|
|
use ConfigReader::Simple; # Needed for parsing Apache config
|
12 |
|
|
use Data::UUID;
|
13 |
|
|
use LWP::Simple;
|
14 |
|
|
use Digest::SHA qw(sha512_base64 sha512_hex);
|
15 |
|
|
use Data::Dumper;
|
16 |
|
|
use JSON;
|
17 |
|
|
use Tie::DBI;
|
18 |
|
|
use Proc::Daemon;
|
19 |
|
|
use Proc::ProcessTable;
|
20 |
|
|
use HTTP::Daemon;
|
21 |
|
|
use URI::Escape qw(uri_escape uri_unescape);
|
22 |
|
|
use Error qw(:try);
|
23 |
|
|
# use sigtrap 'handler' => \&TERMINATE, 'QUIT', 'INT', 'TERM', 'KILL', 'STOP';
|
24 |
|
|
use sigtrap 'handler' => \&HUP, 'HUP';
|
25 |
|
|
|
26 |
|
|
my $running = 1;
|
27 |
|
|
my $naptime = 90; # seconds
|
28 |
|
|
$user = 'irigo';
|
29 |
|
|
|
30 |
|
|
my $argv = shift if $ARGV[0];
|
31 |
|
|
my $debug = 1 if ($argv eq 'debug');
|
32 |
|
|
my $cfg = new Config::Simple("/etc/stabile/config.cfg");
|
33 |
|
|
my $nodecfg = new Config::Simple("/etc/stabile/nodeconfig.cfg");
|
34 |
|
|
|
35 |
|
|
my $uuid = $cfg->param('ENGINEID') || '';
|
36 |
|
|
my $dbiuser = $cfg->param('DBI_USER') || "irigo";
|
37 |
|
|
my $dbipasswd = $cfg->param('DBI_PASSWD') || "";
|
38 |
|
|
my $engineuser = $cfg->param('ENGINEUSER') || "";
|
39 |
|
|
my @spoolpaths = $cfg->param('STORAGE_POOLS_LOCAL_PATHS');
|
40 |
|
|
my $downloadmasters = $cfg->param('DOWNLOAD_MASTERS');
|
41 |
|
|
|
42 |
|
|
my $valve_readlimit = $cfg->param('VALVE_READ_LIMIT'); # e.g. 125829120 = 120 * 1024 * 1024 = 120 MB / s
|
43 |
|
|
my $valve_writelimit = $cfg->param('VALVE_WRITE_LIMIT');
|
44 |
|
|
my $valve_iopsreadlimit = $cfg->param('VALVE_IOPS_READ_LIMIT'); # e.g. 1000 IOPS
|
45 |
|
|
my $valve_iopswritelimit = $cfg->param('VALVE_IOPS_WRITE_LIMIT');
|
46 |
|
|
|
47 |
|
|
my $vm_readlimit = $nodecfg->param('VM_READ_LIMIT'); # e.g. 125829120 = 120 * 1024 * 1024 = 120 MB / s
|
48 |
|
|
my $vm_writelimit = $nodecfg->param('VM_WRITE_LIMIT');
|
49 |
|
|
my $vm_iopsreadlimit = $nodecfg->param('VM_IOPS_READ_LIMIT'); # e.g. 1000 IOPS
|
50 |
|
|
my $vm_iopswritelimit = $nodecfg->param('VM_IOPS_WRITE_LIMIT');
|
51 |
|
|
my $identity = $nodecfg->param('IDENTITY');
|
52 |
|
|
|
53 |
|
|
my $stabile_upgrade = $cfg->param('UPGRADE');
|
54 |
|
|
my $datanic = $cfg->param('ENGINE_DATA_NIC');
|
55 |
|
|
|
56 |
|
|
my $basedir = "/var/www/stabile";
|
57 |
|
|
$basedir = `cat /etc/stabile/basedir` if -e "/etc/stabile/basedir";
|
58 |
|
|
chomp $basedir;
|
59 |
2a63870a
|
Christian Orellana
|
my $baseurl;
|
60 |
|
|
if (-e "/etc/stabile/baseurl") {
|
61 |
|
|
$baseurl = `cat /etc/stabile/baseurl`;
|
62 |
|
|
chomp $baseurl;
|
63 |
|
|
} else {
|
64 |
|
|
my $hostname = `hostname`; chomp $hostname;
|
65 |
|
|
chomp $hostname;
|
66 |
|
|
$baseurl = "https://$hostname/stabile";
|
67 |
|
|
}
|
68 |
95b003ff
|
Origo
|
|
69 |
|
|
unless (checkDB()) {
|
70 |
|
|
die "Unable to connect to db...\n";
|
71 |
|
|
}
|
72 |
|
|
|
73 |
|
|
require "$basedir/cgi/Stabile.pm";
|
74 |
|
|
|
75 |
|
|
if ($stabile_upgrade) {
|
76 |
|
|
print "Steamgine upgrade requested. Hang on...\n";
|
77 |
|
|
$cfg->delete('UPGRADE');
|
78 |
|
|
$cfg->save();
|
79 |
|
|
`apt-get update`;
|
80 |
|
|
if (`hostname` =~ /orellana/) {# Don't upgrade devel server
|
81 |
|
|
print "Not upgrading development source server...";
|
82 |
|
|
`echo "Not upgrading development source server..." >> /tmp/stabile.upgrade.log`
|
83 |
|
|
} else {
|
84 |
|
|
`echo "upgrading" > /tmp/stabile.upgrading`; # This file makes sure postinst does not kill pressurecontrol
|
85 |
|
|
`echo "Steamgine upgrade requested. Hang on..." >> /tmp/stabile.upgrade.log`;
|
86 |
|
|
print `DEBCONF_DEBUG=developer apt-get -q -y --force-yes --no-install-recommends install stabile 2>&1 | tee -a /tmp/stabile.upgrade.log`;
|
87 |
|
|
unlink '/tmp/stabile.upgrading';
|
88 |
|
|
exit;
|
89 |
|
|
}
|
90 |
|
|
}
|
91 |
|
|
|
92 |
|
|
# Make webmin inaccessible from 10.0.0.0
|
93 |
|
|
print `/sbin/iptables -D INPUT -p udp --destination-port 10000 -s 10.0.0.0/255.0.0.0 -j DROP 2>/dev/null`;
|
94 |
|
|
print `/sbin/iptables -A INPUT -p udp --destination-port 10000 -s 10.0.0.0/255.0.0.0 -j DROP`;
|
95 |
|
|
print `/sbin/iptables -D INPUT -p tcp --destination-port 10000 -s 10.0.0.0/255.0.0.0 -j DROP 2>/dev/null`;
|
96 |
|
|
print `/sbin/iptables -A INPUT -p tcp --destination-port 10000 -s 10.0.0.0/255.0.0.0 -j DROP`;
|
97 |
d24d9a01
|
hq
|
# Make netserver (netperf) inaccessible outside of 10.0.0.0
|
98 |
|
|
print `/sbin/iptables -D INPUT -p udp --destination-port 12865 ! -s 10.0.0.0/255.0.0.0 -j DROP 2>/dev/null`;
|
99 |
|
|
print `/sbin/iptables -A INPUT -p udp --destination-port 12865 ! -s 10.0.0.0/255.0.0.0 -j DROP`;
|
100 |
|
|
print `/sbin/iptables -D INPUT -p tcp --destination-port 12865 ! -s 10.0.0.0/255.0.0.0 -j DROP 2>/dev/null`;
|
101 |
|
|
print `/sbin/iptables -A INPUT -p tcp --destination-port 12865 ! -s 10.0.0.0/255.0.0.0 -j DROP`;
|
102 |
95b003ff
|
Origo
|
# Make ugly exception for virtual instances running in Stabile
|
103 |
|
|
if (-e "/tmp/internalip") {
|
104 |
|
|
my $internalip = `cat /tmp/internalip`; chomp $internalip;
|
105 |
|
|
print `/sbin/iptables -D INPUT -p tcp --destination-port 10000 -s $internalip/24 -j ACCEPT 2>/dev/null`;
|
106 |
|
|
print `/sbin/iptables -I INPUT -p tcp --destination-port 10000 -s $internalip/24 -j ACCEPT`;
|
107 |
|
|
}
|
108 |
|
|
# Don't route packets to pistons
|
109 |
|
|
print `/sbin/iptables -D FORWARD -i $datanic+ -o $datanic+ -d 10.0.0.0/24 -j DROP`;
|
110 |
|
|
print `/sbin/iptables -A FORWARD -i $datanic+ -o $datanic+ -d 10.0.0.0/24 -j DROP`;
|
111 |
104449f5
|
Origo
|
# Masquerade
|
112 |
|
|
my $masq = `/sbin/iptables -L -n -t nat`;
|
113 |
|
|
unless ($masq =~ "MASQUERADE.+all.+--.+0\.0\.0\.0/0") {
|
114 |
|
|
`/sbin/iptables --table nat --append POSTROUTING --out-interface $datanic -s 10.0.0.0/8 -j MASQUERADE`;
|
115 |
|
|
}
|
116 |
95b003ff
|
Origo
|
# Make sure webmin conf is readable
|
117 |
|
|
`chmod 644 /etc/webmin/miniserv.conf`;
|
118 |
|
|
# Make sure log is readable and writable
|
119 |
|
|
`touch /var/log/stabile/steam.log`;
|
120 |
|
|
`chown www-data:www-data /var/log/stabile/steam.log`;
|
121 |
|
|
`chmod 664 /var/log/stabile/steam.log`;
|
122 |
|
|
# Make sure ui_update can remove files from /tmp
|
123 |
|
|
`chmod -t /tmp`;
|
124 |
|
|
# Copy customized guacamole index file
|
125 |
|
|
if (-e "/usr/share/stabile/guacamole-index.html" && !(`grep stabile /var/lib/tomcat8/webapps/guacamole/index.html`)) {
|
126 |
|
|
`cp /usr/share/stabile/guacamole-index.html /var/lib/tomcat8/webapps/guacamole/index.html`;
|
127 |
|
|
`systemctl restart tomcat8`;
|
128 |
|
|
}
|
129 |
|
|
# Handle strange error on node when reading sudoers file
|
130 |
|
|
#system("perl -pi -e 's/(Defaults.*)/Defaults:irigo !requiretty/' /mnt/stabile/tftp/bionic/casper/filesystem.dir/etc/sudoers.d/stabile");
|
131 |
|
|
|
132 |
|
|
print "Mounting storage pools\n";
|
133 |
|
|
mountPaths();
|
134 |
|
|
|
135 |
|
|
print "Checking quotas\n";
|
136 |
|
|
foreach my $sp (@spoolpaths) {
|
137 |
d24d9a01
|
hq
|
`quotacheck -c "$sp"` if (-e "$sp");
|
138 |
95b003ff
|
Origo
|
}
|
139 |
|
|
|
140 |
|
|
if (-d "/sys/fs/cgroup") {
|
141 |
27512919
|
Origo
|
print "Setting cgroups limits\n";
|
142 |
|
|
my @files = ("/etc/stabile/cgconfig.conf");
|
143 |
d24d9a01
|
hq
|
push @files, "/etc/cgconfig.conf" if (-s "/etc/cgconfig.conf");
|
144 |
27512919
|
Origo
|
foreach my $file (@files) {
|
145 |
|
|
open (FILE, "< $file") || die "problem opening $file\n";
|
146 |
|
|
my @lines = <FILE>;
|
147 |
|
|
close FILE;
|
148 |
|
|
chomp @lines;
|
149 |
|
|
my $group;
|
150 |
|
|
my @newlines;
|
151 |
|
|
for my $line (@lines) {
|
152 |
|
|
$group = $1 if ($line =~ /^group (\S+) \{/ );
|
153 |
|
|
if ($group eq 'stabile') {
|
154 |
|
|
$line =~ s/(blkio.throttle.read_bps_device = "\d+:\d+).*/$1 $valve_readlimit";/;
|
155 |
|
|
$line =~ s/(blkio.throttle.write_bps_device = "\d+:\d+).*/$1 $valve_writelimit";/;
|
156 |
|
|
$line =~ s/(blkio.throttle.read_iops_device = "\d+:\d+).*/$1 $valve_iopsreadlimit";/;
|
157 |
|
|
$line =~ s/(blkio.throttle.write_iops_device = "\d+:\d+).*/$1 $valve_iopswritelimit";/;
|
158 |
|
|
} elsif ($group eq 'stabilevm') {
|
159 |
|
|
$line =~ s/(blkio.throttle.read_bps_device = "\d+:\d+).*/$1 $vm_readlimit";/;
|
160 |
|
|
$line =~ s/(blkio.throttle.write_bps_device = "\d+:\d+).*/$1 $vm_writelimit";/;
|
161 |
|
|
$line =~ s/(blkio.throttle.read_iops_device = "\d+:\d+).*/$1 $vm_iopsreadlimit";/;
|
162 |
|
|
$line =~ s/(blkio.throttle.write_iops_device = "\d+:\d+).*/$1 $vm_iopswritelimit";/;
|
163 |
|
|
}
|
164 |
|
|
push @newlines, $line;
|
165 |
95b003ff
|
Origo
|
}
|
166 |
27512919
|
Origo
|
open (FILE, "> $file") || die "problem opening $file\n";
|
167 |
|
|
print FILE join("\n", @newlines);
|
168 |
|
|
close (FILE);
|
169 |
95b003ff
|
Origo
|
}
|
170 |
27512919
|
Origo
|
# `cgconfigparser -l /etc/stabile/cgconfig.conf -l /etc/cgconfig.conf`;
|
171 |
|
|
my $cmd = "cgconfigparser " . join(" ", map { '-l ' . $_ } @files);
|
172 |
|
|
`$cmd`;
|
173 |
95b003ff
|
Origo
|
} else {
|
174 |
|
|
print "cgroups are not enabled!\n";
|
175 |
|
|
}
|
176 |
|
|
|
177 |
|
|
if ($uuid && !ref $uuid) {
|
178 |
|
|
;
|
179 |
|
|
} else {
|
180 |
|
|
my $ug = new Data::UUID;
|
181 |
|
|
$uuid = $ug->create_str();
|
182 |
|
|
$cfg->param('ENGINEID', $uuid);
|
183 |
|
|
$cfg->save();
|
184 |
|
|
$main::syslogit->('pressurecontrol', 'info', "Generated new UUID: $uuid");
|
185 |
|
|
}
|
186 |
|
|
|
187 |
|
|
if ($uuid) {
|
188 |
|
|
$main::syslogit->('pressurecontrol', 'info', "Starting pressurecontrol on engine: $uuid");
|
189 |
|
|
} else {
|
190 |
|
|
$main::syslogit->('pressurecontrol', 'info', "Unable to get engine id...");
|
191 |
|
|
die "Unable to get engine id...\n";
|
192 |
|
|
}
|
193 |
|
|
|
194 |
|
|
my $tktcfg_file = "/etc/apache2/conf-available/auth_tkt_cgi.conf";
|
195 |
|
|
my $tktcfg = ConfigReader::Simple->new($tktcfg_file, [qw(TKTAuthSecret)]);
|
196 |
|
|
my $tktkey = $tktcfg->get('TKTAuthSecret') || '';
|
197 |
|
|
|
198 |
|
|
unless ($tktkey) {
|
199 |
|
|
$main::syslogit->('pressurecontrol', 'info', "Unable to get engine tktkey...");
|
200 |
|
|
die "Unable to get engine tktkey...\n";
|
201 |
|
|
}
|
202 |
|
|
|
203 |
|
|
my $browser = LWP::UserAgent->new;
|
204 |
|
|
$browser->timeout(15);
|
205 |
|
|
$browser->agent('pressurecontrol/1.0b');
|
206 |
|
|
$browser->protocols_allowed( [ 'http','https'] );
|
207 |
|
|
|
208 |
|
|
my %postreq;
|
209 |
|
|
$postreq->{'engineid'} = $uuid;
|
210 |
|
|
$postreq->{'enginetkthash'} = sha512_hex($tktkey);
|
211 |
|
|
|
212 |
|
|
my $linked = $cfg->param('ENGINE_LINKED');
|
213 |
48fcda6b
|
Origo
|
my $pullconfigs = $cfg->param('PULL_CONFIGS');
|
214 |
95b003ff
|
Origo
|
print "Engine is marked as linked\n" if ($linked);
|
215 |
|
|
my $content;
|
216 |
|
|
if ($linked) {
|
217 |
|
|
print "Checking linking with Stabile Registry\n";
|
218 |
|
|
$content = $browser->post("https://www.origo.io/irigo/engine.cgi?action=lookup", $postreq)->content();
|
219 |
|
|
$linked = ($content =~ /(.*is linked.*)/i);
|
220 |
|
|
} else {
|
221 |
|
|
print "This engine is not marked as linked to Stabile Registry\n";
|
222 |
|
|
}
|
223 |
|
|
|
224 |
|
|
if ($content =~ /(.*linked.*)/i) {
|
225 |
|
|
print $1,"\n";
|
226 |
|
|
} else {
|
227 |
|
|
print "Linking could not be verified - check your configuration and/or your Internet connection\n";
|
228 |
|
|
print $content;
|
229 |
|
|
}
|
230 |
|
|
$main::syslogit->('pressurecontrol', 'info', "This engine is " . ($linked?'':'not') . " linked to Stabile Registry.");
|
231 |
|
|
|
232 |
|
|
# If linked, get config parameters from origo.io
|
233 |
|
|
$cfg->param('ENGINE_LINKED', 0+$linked);
|
234 |
|
|
if ($linked) {
|
235 |
|
|
my %cfgkeys = filterCfgParams();
|
236 |
|
|
my %enginekeys = %{$cfgkeys{'engine'}};
|
237 |
|
|
my %pistonkeys = %{$cfgkeys{'piston'}};
|
238 |
|
|
|
239 |
|
|
unless (tie %idreg,'Tie::DBI', {
|
240 |
|
|
db=>'mysql:steamregister',
|
241 |
|
|
table=>'nodeidentities',
|
242 |
|
|
key=>'identity',
|
243 |
|
|
autocommit=>0,
|
244 |
|
|
CLOBBER=>3,
|
245 |
|
|
user=>$dbiuser,
|
246 |
|
|
password=>$dbipasswd}) {throw Error::Simple("Register could not be accessed")};
|
247 |
|
|
|
248 |
|
|
my %nodeconfigs;
|
249 |
|
|
# Build hash of known node config files
|
250 |
|
|
foreach my $valref (values %idreg) {
|
251 |
|
|
my $nodeconfigfile = $valref->{'path'} . "/casper/filesystem.dir/etc/stabile/nodeconfig.cfg";
|
252 |
|
|
next if ($nodeconfigs{$nodeconfigfile}); # Node identities may share basedir and node config file
|
253 |
|
|
$nodeconfigfile = $valref->{'path'} . "/live/filesystem.dir/etc/stabile/nodeconfig.cfg" unless (-e $nodeconfigfile); # support old naming
|
254 |
|
|
if (-e $nodeconfigfile) {
|
255 |
|
|
my $nodecfg = new Config::Simple($nodeconfigfile);
|
256 |
|
|
$nodeconfigs{$nodeconfigfile} = $nodecfg;
|
257 |
|
|
}
|
258 |
|
|
}
|
259 |
|
|
my $defaultpath = $idreg{'default'}->{'path'} . "/casper/filesystem.dir/etc/stabile/nodeconfig.cfg";
|
260 |
|
|
untie %idreg;
|
261 |
|
|
my @nodecfgkeys = keys %nodeconfigs;
|
262 |
|
|
|
263 |
|
|
foreach my $line (split /\n/, $content) { # This is where we get ENGINENAME and ENGINEOWNER and write them to config
|
264 |
|
|
next if ($line=~ /(.*is linked.*)/i || !$line);
|
265 |
|
|
if ($line =~ /(\S+): ?(.*)/) {
|
266 |
|
|
my $k = $1;
|
267 |
|
|
my $v = $2; # Value received from origo.io
|
268 |
|
|
if ($enginekeys{$k}) {
|
269 |
|
|
my @vals = $cfg->param($k); my $val = join(", ", @vals);
|
270 |
|
|
if ($val ne $v) {
|
271 |
d24d9a01
|
hq
|
if (($pullconfigs || $k eq 'ENGINEUSER') && $k ne 'ENGINEID' && $k ne 'ENGINE_LINKED') {
|
272 |
d3d1a2d4
|
Origo
|
print "Received modified config: $line\n";
|
273 |
|
|
$cfg->param($k, $v);
|
274 |
|
|
}
|
275 |
95b003ff
|
Origo
|
} else {
|
276 |
|
|
#print "Unmodified config line received: $line, $val[0]\n";
|
277 |
|
|
}
|
278 |
|
|
} elsif ($pistonkeys{$k}) {
|
279 |
|
|
foreach my $cfgkey (@nodecfgkeys) {
|
280 |
|
|
# my @vals = $nodecfg->param($k); my $val = join(", ", @vals);
|
281 |
|
|
my @vals = $nodeconfigs{$cfgkey}->param($k); my $val = join(", ", @vals);
|
282 |
|
|
if ($val ne $v) {
|
283 |
|
|
# Different node types may require different interface specifications
|
284 |
|
|
# maintained manually
|
285 |
|
|
if (($k eq 'ADMIN_NIC' || $k eq 'DATA_NIC') && $cfgkey ne $defaultpath) {
|
286 |
|
|
print "Not changing NIC on non-default nodeidentity $cfgkey: $line\n";
|
287 |
6fdc8676
|
hq
|
} elsif ($pullconfigs) {
|
288 |
95b003ff
|
Origo
|
print "Received modified node config ($cfgkey): $line\n";
|
289 |
6fdc8676
|
hq
|
$nodeconfigs{$cfgkey}->param($k, $v);
|
290 |
95b003ff
|
Origo
|
if ($k =~ /READ_LIMIT|WRITE_LIMIT/) {
|
291 |
|
|
print `echo /nodes/reloadall | stash`;
|
292 |
|
|
}
|
293 |
|
|
}
|
294 |
|
|
}
|
295 |
|
|
}
|
296 |
|
|
}
|
297 |
|
|
}
|
298 |
|
|
}
|
299 |
48fcda6b
|
Origo
|
foreach my $nodecfg (values %nodeconfigs) {$nodecfg->save() if ($pullconfigs)};
|
300 |
95b003ff
|
Origo
|
} else {
|
301 |
|
|
$postreq = {};
|
302 |
|
|
}
|
303 |
|
|
$cfg->save();
|
304 |
|
|
|
305 |
|
|
if ($downloadmasters) {
|
306 |
|
|
downloadMasters();
|
307 |
|
|
} else {
|
308 |
|
|
print "Not downloading masters from origo.io, because DOWNLOAD_MASTERS not set in config.\n"
|
309 |
|
|
}
|
310 |
|
|
|
311 |
|
|
print "Starting pressurecontrol on engine: $uuid\n";
|
312 |
|
|
|
313 |
|
|
my $pid = fork();
|
314 |
|
|
|
315 |
|
|
if ($pid) {
|
316 |
|
|
my $pid2 = fork();
|
317 |
|
|
if ($pid2) {
|
318 |
|
|
my $amtdone;
|
319 |
|
|
$amtdone = 1 if ($debug); # Don't wait for this when debugging
|
320 |
|
|
if ($uuid) {
|
321 |
|
|
my $tktname = substr($uuid, 0, 8);
|
322 |
|
|
my $cookiebase;
|
323 |
|
|
$cookiebase = `cat /etc/stabile/cookiebase` if -e "/etc/stabile/cookiebase";
|
324 |
|
|
chomp $cookiebase;
|
325 |
|
|
|
326 |
|
|
my $apachecfg = '/etc/apache2/sites-available/stabile-ssl';
|
327 |
|
|
$apachecfg = '/etc/apache2/conf.d/stabile-ssl.conf' if -e ('/etc/apache2/conf.d/stabile-ssl.conf');
|
328 |
|
|
$apachecfg = '/etc/apache2/conf-available/stabile-ssl.conf' if -e ('/etc/apache2/conf-available/stabile-ssl.conf');
|
329 |
48fcda6b
|
Origo
|
$apachecfg = '/etc/apache2/sites-available/stabile-ssl.conf' if -e ('/etc/apache2/sites-available/stabile-ssl.conf');
|
330 |
95b003ff
|
Origo
|
system("perl -pi -e 's/(.*TKTAuthCookieName.*\\n)//' $apachecfg");
|
331 |
|
|
system("perl -pi -e 's/(.*TKTAuthDomain.*\\n)//' $apachecfg");
|
332 |
|
|
if ($cookiebase) {
|
333 |
|
|
system("perl -pi -e 's/(.*TKTAuthLoginURL.*)/\$1\\n TKTAuthCookieName auth_$tktname\\n TKTAuthDomain $cookiebase/' $apachecfg");
|
334 |
|
|
} else {
|
335 |
|
|
system("perl -pi -e 's/(.*TKTAuthLoginURL.*)/\$1\\n TKTAuthCookieName auth_$tktname/' $apachecfg");
|
336 |
|
|
}
|
337 |
|
|
|
338 |
|
|
system("perl -pi -e 's/(.*TKTAuthCookieName.*\\n)//' $tktcfg_file");
|
339 |
|
|
system("perl -pi -e 's/(^<Directory \\\/var\\\/www\\\/.*auth>.*)/\$1\\n TKTAuthCookieName auth_$tktname/' $tktcfg_file");
|
340 |
|
|
|
341 |
|
|
}
|
342 |
|
|
print `systemctl restart apache2`;
|
343 |
|
|
my $reportbackup = 0;
|
344 |
|
|
my $command = 'fullstatsb';
|
345 |
|
|
# Main loop
|
346 |
|
|
while ($running) {
|
347 |
|
|
$cfg = new Config::Simple("/etc/stabile/config.cfg");
|
348 |
|
|
my $dl = $cfg->param('DOWNLOAD_MASTERS');
|
349 |
|
|
# Monitor changes in downloadmasters - only download if changed - periodic check is done below
|
350 |
2a63870a
|
Christian Orellana
|
if ((!$downloadmasters && $dl) || $dl==2) { # 2 is force one-shot download
|
351 |
95b003ff
|
Origo
|
print "Now downloading master images...\n";
|
352 |
2a63870a
|
Christian Orellana
|
my $mastersavailable = downloadMasters();
|
353 |
|
|
if ($dl==2) {
|
354 |
|
|
$cfg->param('DOWNLOAD_MASTERS',1 );
|
355 |
|
|
$cfg->save();
|
356 |
|
|
$main::updateUI->({tab=>"nodes", user=>'irigo', type=>"message", message=>"No new or updated masters available"}) unless ($mastersavailable);
|
357 |
|
|
}
|
358 |
95b003ff
|
Origo
|
} else {
|
359 |
|
|
print "Not downloading master images right now...\n";
|
360 |
|
|
}
|
361 |
|
|
$downloadmasters = $dl;
|
362 |
|
|
|
363 |
|
|
# Remove dangling up_update processes and pipes. New pipes get created by ui_update cgi's that are active
|
364 |
|
|
print "Cleaning up ui_update tasks and named pipes\n";
|
365 |
|
|
print `/bin/rm /tmp/*.tasks 2>/dev/null; /usr/bin/pkill -f "/bin/cat < /tmp/.*tasks"`;
|
366 |
|
|
`/usr/bin/pkill -f "/usr/bin/tee /tmp"`; # Kill hanging ui updates
|
367 |
|
|
|
368 |
|
|
# my $statsjson = `echo /nodes/$command | stash 2>>/dev/null`;
|
369 |
|
|
my $statsjson = `REMOTE_USER=irigo $basedir/cgi/nodes.cgi -c -a $command`;
|
370 |
|
|
|
371 |
|
|
if ($linked) {
|
372 |
|
|
print "Reporting status to Stabile Registry ($command)\n";
|
373 |
|
|
$postreq->{'POSTDATA'} = $statsjson;
|
374 |
|
|
# print $statsjson;
|
375 |
|
|
my $res = $browser->post("https://www.origo.io/irigo/engine.cgi?action=status", $postreq)->content();
|
376 |
|
|
my $ok = ($res =~ /OK: (.*)/i);
|
377 |
|
|
print $res;
|
378 |
|
|
}
|
379 |
|
|
|
380 |
|
|
$reportbackup++;
|
381 |
|
|
if ($reportbackup > 100) {
|
382 |
|
|
$command = 'fullstatsb';
|
383 |
|
|
downloadMasters();
|
384 |
|
|
$reportbackup = 0;
|
385 |
|
|
} else {
|
386 |
|
|
$command = 'fullstats';
|
387 |
|
|
}
|
388 |
|
|
|
389 |
d970352a
|
hq
|
print &pretty_time.": ".`REMOTE_USER=irigo $basedir/cgi/nodes.cgi -a updateregister -f`;
|
390 |
|
|
print &pretty_time.": ".`REMOTE_USER=irigo $basedir/cgi/servers.cgi -a updateregister -f`;
|
391 |
|
|
print &pretty_time.": ".`REMOTE_USER=irigo $basedir/cgi/images.cgi -a updateregister -f`;
|
392 |
95b003ff
|
Origo
|
unless ($amtdone) {
|
393 |
|
|
print "Updating AMT info\n";
|
394 |
|
|
print &pretty_time.": ".`REMOTE_USER=irigo $basedir/cgi/nodes.cgi -a updateamtinfo`;
|
395 |
|
|
$amtdone = 1;
|
396 |
|
|
}
|
397 |
|
|
print &pretty_time.": ".`/usr/local/bin/steamExec releaseolddhcpleases`;
|
398 |
|
|
|
399 |
|
|
sleep $naptime;
|
400 |
|
|
}
|
401 |
|
|
} else {
|
402 |
|
|
print "Registering Gearman worker\n";
|
403 |
|
|
use Storable qw(freeze thaw);
|
404 |
|
|
use Gearman::Worker;
|
405 |
|
|
use List::Util qw( sum );
|
406 |
|
|
my $worker = Gearman::Worker->new;
|
407 |
|
|
$worker->job_servers('127.0.0.1:4730');
|
408 |
|
|
$worker->register_function(steamexec =>
|
409 |
|
|
sub {
|
410 |
|
|
my %args = %{ thaw($_[0]->arg) };
|
411 |
|
|
my $tktuser = $args{tktuser};
|
412 |
|
|
my $user = $args{user};
|
413 |
|
|
my $target = $args{target};
|
414 |
|
|
my $package = $args{package};
|
415 |
|
|
my $uargs;
|
416 |
|
|
my $res = "No result";
|
417 |
|
|
if ($args{args}) {
|
418 |
|
|
if (ref $args{args}) { # not a string
|
419 |
|
|
$uargs = uri_escape( JSON->new->allow_nonref->encode ( $args{args} ));
|
420 |
|
|
} else { # assume a string
|
421 |
|
|
$uargs = uri_escape($args{args});
|
422 |
|
|
}
|
423 |
|
|
}
|
424 |
|
|
if ($args{action}) {
|
425 |
|
|
if ($package =~ /systems|servers|images|networks|nodes|users/) {
|
426 |
|
|
my $action = 'gear_' . $args{action};
|
427 |
|
|
my $cmd = qq|REMOTE_USER=$tktuser $basedir/cgi/$package.cgi -v -s $user -a $action|;
|
428 |
|
|
$cmd .= qq| -t "$target"| if ($target);
|
429 |
|
|
$cmd .= qq| -g "$uargs"| if ($uargs);
|
430 |
|
|
print "Executing $cmd\n";
|
431 |
|
|
$res = `$cmd`;
|
432 |
|
|
print "-> $res\n" if ($debug);
|
433 |
|
|
} else {
|
434 |
|
|
print "Not executing $args{action}, $package\n";
|
435 |
|
|
}
|
436 |
|
|
}
|
437 |
|
|
$res;
|
438 |
|
|
});
|
439 |
|
|
$worker->register_function(restart_apache =>
|
440 |
|
|
sub {
|
441 |
|
|
`pkill -HUP apache2`;
|
442 |
|
|
});
|
443 |
|
|
$worker->register_function(sum => sub { sum @{ thaw($_[0]->arg) } });
|
444 |
|
|
$worker->work while ($running);
|
445 |
|
|
}
|
446 |
|
|
} else {
|
447 |
|
|
my $d = HTTP::Daemon->new(
|
448 |
|
|
LocalAddr => '127.0.0.1', # remove this to listen from other machines
|
449 |
|
|
# (i.e. open-relay... be careful of spammers!)
|
450 |
|
|
LocalPort => 8082,
|
451 |
|
|
ReuseAddr => 1
|
452 |
|
|
) || die "Local port not available";
|
453 |
|
|
print "Starting managementlink proxy on:", $d->url, "\n";
|
454 |
|
|
|
455 |
|
|
# Avoid leaving zombies
|
456 |
|
|
$SIG{CHLD} = 'IGNORE';
|
457 |
|
|
# Avoid dying from browser cancel
|
458 |
|
|
$SIG{PIPE} = 'IGNORE';
|
459 |
|
|
|
460 |
|
|
my %networks;
|
461 |
|
|
print "Configuring networking and loading network tables\n";
|
462 |
|
|
eval {`/bin/echo 1 > /proc/sys/net/ipv4/ip_forward`; 1;} or do {print "Unable to enable nat'ing: $@\n";};
|
463 |
|
|
|
464 |
|
|
$content = `REMOTE_USER=irigo $basedir/cgi/networks.cgi -a jsonlist -f`;
|
465 |
|
|
my $nets = from_json($content);
|
466 |
|
|
foreach my $net (@$nets) {
|
467 |
|
|
$networks{$net->{uuid}} = $net;
|
468 |
|
|
};
|
469 |
|
|
fork(); fork(); fork(); # 2^3 = 8 processes
|
470 |
|
|
|
471 |
|
|
my $dbrowser = LWP::UserAgent->new;
|
472 |
6fdc8676
|
hq
|
$dbrowser->timeout(60);
|
473 |
95b003ff
|
Origo
|
$dbrowser->agent('pressurecontrol/1.0b');
|
474 |
|
|
$dbrowser->protocols_allowed( [ 'http','https'] );
|
475 |
|
|
|
476 |
|
|
while (my $c = $d->accept) {
|
477 |
|
|
while (my $request = $c->get_request) {
|
478 |
|
|
my $uri = $request->uri->as_string;
|
479 |
|
|
my $host = $c->sockhost;
|
480 |
|
|
my $response;
|
481 |
|
|
if ($uri =~ /^\/\/(https?:\/\/?)?(\S{36})(:\d+)?(.*)/) {
|
482 |
48fcda6b
|
Origo
|
my $prot = $1||'http://';
|
483 |
95b003ff
|
Origo
|
my $networkuuid = $2;
|
484 |
48fcda6b
|
Origo
|
my $uriport = $3;
|
485 |
95b003ff
|
Origo
|
my $uripath = $4;
|
486 |
48fcda6b
|
Origo
|
$prot = "$prot/" unless ($prot =~ /\/\//);
|
487 |
|
|
my $geturi = $prot . "$networkuuid$uriport$uripath";
|
488 |
95b003ff
|
Origo
|
$host = $2 if ($uripath =~ /(\?|\&)host=(.+)\&/ || $uripath =~ /(\?|\&)host=(.+)/);
|
489 |
|
|
my $user = $request->header('STEAM_USER');
|
490 |
|
|
my $networkuser = $networks{$networkuuid}->{'user'};
|
491 |
|
|
if (!$networkuser) { # If not found, we look up ip etc. in the DB
|
492 |
|
|
print "Loading $networkuuid ($uri, $user) from db\n";
|
493 |
|
|
$content = `REMOTE_USER=$user $basedir/cgi/networks.cgi -a list -u $networkuuid`;
|
494 |
|
|
print "Got: $content\n";
|
495 |
|
|
my $net = from_json($content);
|
496 |
|
|
if (ref $net eq 'HASH') {
|
497 |
|
|
$intip = $net->{'internalip'};
|
498 |
|
|
$extip = $net->{'externalip'};
|
499 |
|
|
$ip = $intip;
|
500 |
|
|
$ip = $extip if (!$ip || $ip eq '--');
|
501 |
|
|
$networkuser = $net->{'user'};
|
502 |
|
|
|
503 |
|
|
$networks{$networkuuid}->{'internalip'} = $intip;
|
504 |
|
|
$networks{$networkuuid}->{'externalip'} = $extip;
|
505 |
|
|
$networks{$networkuuid}->{'user'} = $networkuser;
|
506 |
|
|
}
|
507 |
|
|
}
|
508 |
|
|
$user = validateUser($user, $networkuser); # Set $user to $networkuser if validated
|
509 |
|
|
if ($user) {
|
510 |
6fdc8676
|
hq
|
my $baseuri = "$baseurl/pipe/$networkuuid$uriport/";
|
511 |
|
|
my $steamhost = $request->header('STEAM_HOST');
|
512 |
|
|
$baseuri = "https://$steamhost/stabile/pipe/$networkuuid$uriport/" if ($steamhost);
|
513 |
95b003ff
|
Origo
|
my $extip = $networks{$networkuuid}->{'externalip'};
|
514 |
|
|
my $intip = $networks{$networkuuid}->{'internalip'};
|
515 |
|
|
my $ip = $intip;
|
516 |
|
|
$ip = $extip if (!$ip || $ip eq '--');
|
517 |
|
|
if ($ip && $networkuser && $networkuser eq $user) {
|
518 |
|
|
$geturi =~ s/$networkuuid/$ip/;
|
519 |
|
|
#$geturi .= '/' unless ($geturi =~ /\/$/);
|
520 |
991e7f1b
|
hq
|
print "Getting $networkuuid: $geturi ($uri)\n" if ($debug);
|
521 |
95b003ff
|
Origo
|
$request->uri($geturi);
|
522 |
|
|
$request->remove_header( 'Referer' );
|
523 |
|
|
$request->header('Host' => $host) if ($host);
|
524 |
|
|
if ($uri =~ /:4200\/\?$/) { # shellinaboxd
|
525 |
|
|
$dbrowser->timeout(120);
|
526 |
|
|
$response = $dbrowser->simple_request( $request );
|
527 |
6fdc8676
|
hq
|
$dbrowser->timeout(60);
|
528 |
95b003ff
|
Origo
|
} else {
|
529 |
|
|
$response = $dbrowser->simple_request( $request );
|
530 |
|
|
}
|
531 |
|
|
|
532 |
|
|
# Do a lot of proxy text translations in order to fix things up a bit in the browser
|
533 |
6fdc8676
|
hq
|
#my $link = $response->header('Link');
|
534 |
|
|
#$link =~ s/<\/(\w)/<$baseuri$1/gi;
|
535 |
|
|
#$response->header('Link', $link);
|
536 |
95b003ff
|
Origo
|
|
537 |
|
|
my $loc = $response->header('Location');
|
538 |
|
|
if ($loc && $loc =~ /^https?:\/\/.+\/(.+)\//) {
|
539 |
|
|
$response->header('Location', "$baseuri/$1/");
|
540 |
|
|
}
|
541 |
|
|
${$response->content_ref} =~ s/\{internalip\}/$ip/gi;
|
542 |
|
|
${$response->content_ref} =~ s/\{externalip\}/$extip/gi;
|
543 |
48fcda6b
|
Origo
|
# \w is included to avoid matching url's starting with //, which should be left alone
|
544 |
6fdc8676
|
hq
|
# ${$response->content_ref} =~ s/(href|src|action|value)=('|")\/(\w)/$1=$2$baseuri$3/gi;
|
545 |
95b003ff
|
Origo
|
# This is purely to fixup javascript in Wordpress install.php
|
546 |
|
|
${$response->content_ref} =~ s/\\\/home/../;
|
547 |
6fdc8676
|
hq
|
# This is to fix css links in Wordpress install
|
548 |
89cb0977
|
hq
|
${$response->content_ref} =~ s/'\/home\/wp-includes/'$baseuri\/home\/wp-includes/g;
|
549 |
|
|
${$response->content_ref} =~ s/'\/home\/wp-admin/'$baseuri\/home\/wp-admin/g;
|
550 |
95b003ff
|
Origo
|
# This is purely to fixup image path in Thirdlane PBX UI
|
551 |
|
|
# ${$response->content_ref} =~ s/\.\.\/\.\.\/\.\.\//..\/..\//;
|
552 |
|
|
|
553 |
|
|
|
554 |
|
|
${$response->content_ref} =~ s/(load\()('|")\//$1$2$baseuri/gi;
|
555 |
6fdc8676
|
hq
|
$response->push_header( 'X-Via' => "1.1 $baseuri" );
|
556 |
95b003ff
|
Origo
|
$response->push_header( 'X-BaseUri' => "1.1 $baseuri" );
|
557 |
|
|
$response->remove_header( 'Content-Security-Policy');
|
558 |
d24d9a01
|
hq
|
$response->push_header( 'Content-Security-Policy' => "script-src 'self' 'unsafe-inline' 'unsafe-eval' https://ajax.googleapis.com https://code.jquery.com https://ajax.microsoft.com https://cdn.jsdelivr.net; style-src 'self' 'unsafe-inline' 'unsafe-eval' https://fonts.googleapis.com https://ajax.googleapis.com https://code.jquery.com" );
|
559 |
95b003ff
|
Origo
|
$c->send_response( $response );
|
560 |
991e7f1b
|
hq
|
print "Got: $geturi\n" if ($debug);
|
561 |
95b003ff
|
Origo
|
} else {
|
562 |
|
|
my $msg = "Not found: $networkuuid, $ip, $networkuser, " . $user;
|
563 |
|
|
# $c->send_status_line('200', $msg);
|
564 |
|
|
$c->send_status_line('404', $msg);
|
565 |
|
|
$c->send_header('X-Via', "1.1 $geturi");
|
566 |
|
|
print "$msg\n";
|
567 |
|
|
#last;
|
568 |
|
|
# $c->send_error(404);
|
569 |
|
|
}
|
570 |
|
|
} else {
|
571 |
|
|
$c->send_error(RC_FORBIDDEN);
|
572 |
|
|
}
|
573 |
|
|
} else {
|
574 |
|
|
my $msg = "Forbidden - not allowing: $uri";
|
575 |
|
|
$c->send_status_line('404', $msg); #403
|
576 |
|
|
$c->send_header('X-Via', "1.1 $uri");
|
577 |
|
|
#$c->send_error(RC_FORBIDDEN, $msg);
|
578 |
|
|
#$main::syslogit->($stackuser, 'info', $msg);
|
579 |
|
|
print "$msg\n";
|
580 |
|
|
#last;
|
581 |
|
|
}
|
582 |
|
|
}
|
583 |
|
|
$c->close;
|
584 |
|
|
undef($c);
|
585 |
|
|
}
|
586 |
|
|
}
|
587 |
|
|
|
588 |
|
|
print "Done\n";
|
589 |
|
|
exit;
|
590 |
|
|
|
591 |
|
|
sub lookupProcess {
|
592 |
|
|
my $process = shift;
|
593 |
|
|
my $match;
|
594 |
|
|
my $t = new Proc::ProcessTable;
|
595 |
|
|
foreach $p ( @{$t->table} ){
|
596 |
|
|
my $pcmd = $p->cmndline;
|
597 |
|
|
if ($pcmd =~ /$process/) {
|
598 |
|
|
$match = $p->pid;
|
599 |
|
|
last;
|
600 |
|
|
}
|
601 |
|
|
}
|
602 |
|
|
return $match;
|
603 |
|
|
}
|
604 |
|
|
|
605 |
|
|
sub validateUser {
|
606 |
|
|
my ($vuser, $account) = @_;
|
607 |
|
|
|
608 |
|
|
unless (tie %userreg,'Tie::DBI', {
|
609 |
|
|
db=>'mysql:steamregister',
|
610 |
|
|
table=>'users',
|
611 |
|
|
key=>'username',
|
612 |
|
|
autocommit=>0,
|
613 |
|
|
CLOBBER=>1,
|
614 |
|
|
user=>$dbiuser,
|
615 |
|
|
password=>$dbipasswd}) {return};
|
616 |
|
|
|
617 |
|
|
my $dbuser = $userreg{$vuser}->{'username'};
|
618 |
|
|
unless ($dbuser) {untie %userreg; $vuser = '';};
|
619 |
|
|
|
620 |
|
|
$privileges = $userreg{$vuser}->{'privileges'};
|
621 |
|
|
if (index($privileges,"d")!=-1) {$vuser = ''}; # disabled user
|
622 |
|
|
|
623 |
|
|
if ($account && $vuser && $account ne $vuser) {
|
624 |
|
|
my %ahash;
|
625 |
|
|
my @accounts = split(/,\s*/, $userreg{$vuser}->{'accounts'});
|
626 |
|
|
my @accountsprivs = split(/,\s*/, $userreg{$vuser}->{'accountsprivileges'});
|
627 |
|
|
for my $i (0 .. $#accounts)
|
628 |
|
|
{ $ahash{$accounts[$i]} = $accountsprivs[$i] || 'r'; }
|
629 |
|
|
|
630 |
|
|
if ($ahash{$account}) {
|
631 |
|
|
my $privileges = $ahash{$account};
|
632 |
|
|
if ($userreg{$account}->{'username'} && index($privileges,"d")==-1){
|
633 |
|
|
$vuser = $account;
|
634 |
|
|
} else {
|
635 |
|
|
$vuser = '';
|
636 |
|
|
}
|
637 |
|
|
} else {
|
638 |
|
|
$vuser = '';
|
639 |
|
|
}
|
640 |
|
|
}
|
641 |
|
|
|
642 |
|
|
untie %userreg;
|
643 |
|
|
return $vuser;
|
644 |
|
|
}
|
645 |
|
|
|
646 |
|
|
sub checkDB {
|
647 |
|
|
my $dbOK = 0;
|
648 |
|
|
eval {
|
649 |
|
|
if (tie %userreg,'Tie::DBI', {
|
650 |
|
|
db=>'mysql:steamregister',
|
651 |
|
|
table=>'users',
|
652 |
|
|
key=>'username',
|
653 |
|
|
autocommit=>0,
|
654 |
|
|
CLOBBER=>1,
|
655 |
|
|
user=>$dbiuser,
|
656 |
|
|
password=>$dbipasswd}) {
|
657 |
|
|
untie %userreg;
|
658 |
|
|
print "Database looks OK\n";
|
659 |
|
|
$dbOK = 1;
|
660 |
|
|
}
|
661 |
|
|
};
|
662 |
|
|
unless ($dbOK) {
|
663 |
|
|
eval {
|
664 |
|
|
print "Creating initial DB...\n";
|
665 |
|
|
`/var/lib/dpkg/info/stabile.postinst createdb`;
|
666 |
|
|
if (tie %userreg, 'Tie::DBI', {
|
667 |
|
|
db => 'mysql:steamregister',
|
668 |
|
|
table => 'users',
|
669 |
|
|
key => 'username',
|
670 |
|
|
autocommit => 0,
|
671 |
|
|
CLOBBER => 1,
|
672 |
|
|
user => $dbiuser,
|
673 |
|
|
password => $dbipasswd }) {
|
674 |
|
|
untie %userreg;
|
675 |
|
|
$dbOK = 1;
|
676 |
|
|
`systemctl restart tomcat8`; # This looks like a first run, restart tomcat to load our auth
|
677 |
|
|
}
|
678 |
|
|
};
|
679 |
|
|
}
|
680 |
|
|
return $dbOK;
|
681 |
|
|
}
|
682 |
|
|
|
683 |
|
|
sub pretty_time {
|
684 |
|
|
my $current_time = time;
|
685 |
|
|
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($current_time);
|
686 |
|
|
# my $year += 1900;
|
687 |
|
|
my $month = substr("0" . ($mon+1), -2);
|
688 |
|
|
my $pretty_time = sprintf "%4d-%02d-%02d@%02d:%02d:%02d",$year+1900,$mon+1,$mday,$hour,$min,$sec;
|
689 |
|
|
return $pretty_time;
|
690 |
|
|
}
|
691 |
|
|
|
692 |
|
|
# Pick out config file parameters from general hash
|
693 |
|
|
sub filterCfgParams {
|
694 |
|
|
my $paramsref = shift;
|
695 |
|
|
my %params = %{$paramsref};
|
696 |
|
|
|
697 |
|
|
my @engineparams = qw(
|
698 |
|
|
EXTERNAL_IP_RANGE_START
|
699 |
|
|
EXTERNAL_IP_RANGE_END
|
700 |
|
|
VLAN_RANGE_START
|
701 |
|
|
VLAN_RANGE_END
|
702 |
|
|
EXTERNAL_SUBNET_SIZE
|
703 |
|
|
PROXY_IP
|
704 |
|
|
PROXY_SUBNET_SIZE
|
705 |
|
|
PROXY_GW
|
706 |
|
|
PROXY_NIC
|
707 |
|
|
PROXY_IP_RANGE_START
|
708 |
|
|
PROXY_IP_RANGE_END
|
709 |
|
|
RDIFF-BACKUP_ENABLED
|
710 |
|
|
RDIFF-BACKUP_USERS
|
711 |
|
|
ENGINE_DATA_NIC
|
712 |
|
|
EXTERNAL_NIC
|
713 |
|
|
EXTERNAL_IP_QUOTA
|
714 |
|
|
MEMORY_QUOTA
|
715 |
|
|
VCPU_QUOTA
|
716 |
|
|
STORAGE_QUOTA
|
717 |
|
|
RX_QUOTA
|
718 |
|
|
TX_QUOTA
|
719 |
|
|
STORAGE_POOLS_RDIFF-BACKUP_ENABLED
|
720 |
|
|
STORAGE_POOLS_ADDRESS_PATHS
|
721 |
|
|
STORAGE_POOLS_LOCAL_PATHS
|
722 |
|
|
STORAGE_POOLS_NAMES
|
723 |
|
|
STORAGE_POOLS_MOUNTABLE
|
724 |
|
|
STORAGE_POOLS_DEFAULTS
|
725 |
|
|
STORAGE_BACKUPDIR
|
726 |
|
|
DBI_USER
|
727 |
|
|
DBI_PASSWD
|
728 |
|
|
CPU_OVERCOMMISION
|
729 |
|
|
DO_DNS
|
730 |
|
|
DO_XMPP
|
731 |
|
|
SHOW_COST
|
732 |
|
|
ENGINEID
|
733 |
|
|
ENGINENAME
|
734 |
|
|
ENGINEUSER
|
735 |
|
|
DOWNLOAD_MASTERS
|
736 |
|
|
NODE_STORAGE_OVERCOMMISSION
|
737 |
|
|
NODESTORAGE_QUOTA
|
738 |
|
|
CURRENCY
|
739 |
|
|
EXTERNALIP_PRICE
|
740 |
|
|
NODESTORAGE_PRICE
|
741 |
|
|
STORAGE_PRICE
|
742 |
|
|
MEMORY_PRICE
|
743 |
|
|
VCPU_PRICE
|
744 |
|
|
VALVE_READ_LIMIT
|
745 |
|
|
VALVE_WRITE_LIMIT
|
746 |
|
|
VALVE_IOPS_READ_LIMIT
|
747 |
|
|
VALVE_IOPS_WRITE_LIMIT
|
748 |
|
|
);
|
749 |
|
|
my @pistonparams = qw(
|
750 |
|
|
ADMIN_SERVER_ADDRESS
|
751 |
|
|
STORAGE_SERVERS_ADDRESS_PATHS
|
752 |
|
|
STORAGE_SERVERS_LOCAL_PATHS
|
753 |
|
|
ADMIN_NIC
|
754 |
|
|
DATA_NIC
|
755 |
|
|
INITIALIZE_LOCAL_DISK
|
756 |
|
|
VM_READ_LIMIT
|
757 |
|
|
VM_WRITE_LIMIT
|
758 |
|
|
VM_IOPS_READ_LIMIT
|
759 |
|
|
VM_IOPS_WRITE_LIMIT
|
760 |
|
|
PISTON_READ_LIMIT
|
761 |
|
|
PISTON_WRITE_LIMIT
|
762 |
|
|
PISTON_IOPS_READ_LIMIT
|
763 |
|
|
PISTON_IOPS_WRITE_LIMIT
|
764 |
|
|
);
|
765 |
|
|
|
766 |
|
|
my %cfghash;
|
767 |
|
|
if ($paramsref) {
|
768 |
|
|
foreach my $param (@engineparams) {
|
769 |
|
|
$cfghash{$param} = $params{$param} if (defined $params{$param});
|
770 |
|
|
}
|
771 |
|
|
foreach my $param (@pistonparams) {
|
772 |
|
|
$cfghash{$param} = $params{$param} if (defined $params{$param});
|
773 |
|
|
}
|
774 |
|
|
} else {
|
775 |
|
|
my %enginehash; @enginehash{@engineparams} = (1) x @engineparams;
|
776 |
|
|
my %pistonhash; @pistonhash{@pistonparams} = (1) x @pistonparams;
|
777 |
|
|
|
778 |
|
|
$cfghash{engine} = \%enginehash;
|
779 |
|
|
$cfghash{piston} = \%pistonhash;
|
780 |
|
|
}
|
781 |
|
|
return %cfghash;
|
782 |
|
|
}
|
783 |
|
|
|
784 |
|
|
sub mountPaths {
|
785 |
|
|
my @tenderlist = $cfg->param('STORAGE_POOLS_ADDRESS_PATHS');
|
786 |
|
|
my @tenderpathslist = $cfg->param('STORAGE_POOLS_LOCAL_PATHS');
|
787 |
|
|
|
788 |
|
|
my $mounts = `cat /proc/mounts`;
|
789 |
|
|
for (my $i=0; $i<= scalar @tenderpathslist; $i++) {
|
790 |
|
|
my $path = $tenderpathslist[$i];
|
791 |
|
|
my $host = $tenderlist[$i];
|
792 |
|
|
next unless ($path && $host);
|
793 |
|
|
# Directory / mount point must exist
|
794 |
|
|
if (!(-d $path)) {
|
795 |
|
|
print "Creating storage pool $path ($host)\n";
|
796 |
|
|
mkdir "$path" or {print ("Error $path could not be created\n")};
|
797 |
|
|
} else {
|
798 |
|
|
print "Storage pool exists: $path ($host)\n";
|
799 |
|
|
};
|
800 |
|
|
unless ($host eq 'local' || $mounts =~ m/$path/i) {
|
801 |
|
|
$main::syslogit->('pressurecontrol', 'info', "Mounting $path from $host");
|
802 |
|
|
eval {print `mount -o intr,noatime,nfsvers=3 $host $path`; 1;} or do {print $@;};
|
803 |
|
|
}
|
804 |
|
|
}
|
805 |
|
|
# Allow user irigo to receive snapshots from nodes
|
806 |
|
|
print `zfs allow irigo create,mount,snapshot,receive,mountpoint,compression,sharenfs,userprop stabile-backups` if (`zfslist` =~ /stabile-backups/);
|
807 |
|
|
}
|
808 |
|
|
|
809 |
|
|
sub downloadMasters {
|
810 |
|
|
print "Looking for available masters at Stabile Registry...\n";
|
811 |
|
|
# Reload config in case storage setup changed
|
812 |
|
|
$cfg = new Config::Simple("/etc/stabile/config.cfg");
|
813 |
|
|
@spoolpaths = $cfg->param('STORAGE_POOLS_LOCAL_PATHS');
|
814 |
2a63870a
|
Christian Orellana
|
my @dlmasters;
|
815 |
95b003ff
|
Origo
|
|
816 |
|
|
unless (tie %imagereg,'Tie::DBI', { # Needed for ValidateItem
|
817 |
|
|
db=>'mysql:steamregister',
|
818 |
|
|
table=>'images',
|
819 |
|
|
key=>'path',
|
820 |
|
|
autocommit=>0,
|
821 |
|
|
CLOBBER=>3,
|
822 |
|
|
user=>$dbiuser,
|
823 |
|
|
password=>$dbipasswd}) {print "Image register could not be accessed\n"; exit 0;};
|
824 |
|
|
|
825 |
|
|
$content = $browser->post("https://www.origo.io/irigo/engine.cgi?action=liststackmasters", $postreq)->content();
|
826 |
|
|
my $stacks = {};
|
827 |
|
|
if ($content =~ /^{/) {
|
828 |
|
|
$stacks = from_json($content);
|
829 |
|
|
print Dumper($stacks) if ($debug);
|
830 |
|
|
}
|
831 |
|
|
my @cmds;
|
832 |
|
|
foreach my $stackuser (keys %$stacks) {
|
833 |
|
|
my $ustacks = $stacks->{$stackuser};
|
834 |
2a63870a
|
Christian Orellana
|
my @downloadalerts;
|
835 |
95b003ff
|
Origo
|
foreach my $stack (@$ustacks) {
|
836 |
|
|
my $fname = $stack->{'filename'};
|
837 |
|
|
my $name = $stack->{'name'};
|
838 |
|
|
my $managementlink = $stack->{'managementlink'};
|
839 |
|
|
my $upgradelink = $stack->{'upgradelink'};
|
840 |
|
|
my $terminallink = $stack->{'terminallink'};
|
841 |
|
|
my $fname2 = $stack->{'image2'};
|
842 |
|
|
my $name2 = $stack->{'name2'};
|
843 |
|
|
my $version = $stack->{'version'};
|
844 |
|
|
my $current = $stack->{'current'};
|
845 |
|
|
my $appid = $stack->{'appid'};
|
846 |
|
|
my $suser = $stack->{'user'};
|
847 |
|
|
my $fsize = $stack->{'size'};
|
848 |
|
|
my $vsize = $stack->{'virtualsize'};
|
849 |
|
|
my $fsize2 = $stack->{'size2'};
|
850 |
|
|
my $frealsize = $stack->{'realsize'};
|
851 |
2a63870a
|
Christian Orellana
|
my $frealsize2 = $stack->{'realsize2'};
|
852 |
95b003ff
|
Origo
|
my $imgurl = "$stack->{'url'}?auth_tkt=$stack->{'tkt'}";
|
853 |
|
|
my $imgurl2;
|
854 |
|
|
my $match;
|
855 |
|
|
my $match2;
|
856 |
|
|
my $lsize;
|
857 |
|
|
my $lrealsize;
|
858 |
|
|
my $lsize2;
|
859 |
|
|
my $lrealsize2;
|
860 |
|
|
my $f;
|
861 |
|
|
my $f2;
|
862 |
|
|
foreach my $sp (@spoolpaths) {
|
863 |
|
|
$f = "$sp/$stackuser/$fname";
|
864 |
|
|
if (-e $f) {
|
865 |
|
|
my @stat = stat($f);
|
866 |
|
|
$lsize = $stat[7];
|
867 |
|
|
$lrealsize = $stat[12] * 512;
|
868 |
|
|
$match = 1;
|
869 |
|
|
last;
|
870 |
|
|
}
|
871 |
|
|
}
|
872 |
|
|
my $msg;
|
873 |
|
|
my $cmd;
|
874 |
|
|
my $img = $imagereg{$f};
|
875 |
|
|
if ($match && $imagereg{$f} && ($imagereg{$f}->{'version'} ge $version || $lsize == $fsize) ) {
|
876 |
|
|
$msg = "Image $fname ($version) found in $f [$fsize bytes]. Updating: $name, $suser. ";
|
877 |
|
|
$imagereg{$f}->{'status'} = 'unused' if ($imagereg{$f}->{'status'} eq 'downloading');
|
878 |
|
|
$imagereg{$f}->{'version'} = $version unless ($imagereg{$f}->{'version'} eq $version);
|
879 |
|
|
} else {
|
880 |
|
|
if (!$current) {
|
881 |
|
|
$msg = "Image $fname is not latest version, not downloading. ";
|
882 |
d24d9a01
|
hq
|
} elsif (lookupProcess($fname)) { # Check if image is already being downloaded
|
883 |
|
|
$msg = "Image $fname is already being downloaded. ";
|
884 |
|
|
} elsif (-s $f) { # Check if image exists
|
885 |
|
|
$msg = "Image $fname already exists but with a different size than in registry - please remove or correct. ";
|
886 |
|
|
} else {
|
887 |
95b003ff
|
Origo
|
$f = "$spoolpaths[0]/$stackuser/$fname";
|
888 |
|
|
print `echo "status=downloading" > "$f.meta"`;
|
889 |
|
|
$msg = "Image $fname not found. Downloading $fsize bytes to $f ($stack->{url})... ";
|
890 |
|
|
my $msize = int($fsize /1024/1024);
|
891 |
|
|
my $uimsg = qq|Now downloading $name ($msize) MB)|;
|
892 |
2a63870a
|
Christian Orellana
|
push @downloadalerts, {tab=>"nodes", user=>'irigo', type=>"message", message=>$uimsg, download=>$f, name=>$name, size=>$frealsize};
|
893 |
|
|
push @dlmasters, $name;
|
894 |
d24d9a01
|
hq
|
# $main::updateUI->({tab=>"nodes", user=>'irigo', type=>"message", message=>$uimsg}); # notify user
|
895 |
95b003ff
|
Origo
|
$cmd = qq|wget --no-check-certificate --no-verbose --tries=4 -a /mnt/stabile/images/stacks-xfer.log -O "$f" $imgurl|;
|
896 |
|
|
$cmd .= qq|; rm "$f.meta"; steamExec updateimagestatus "$f" installable $vsize; steamExec updatebackingfile "$f"|;
|
897 |
|
|
}
|
898 |
|
|
}
|
899 |
|
|
|
900 |
|
|
if ($imagereg{$f}) {
|
901 |
|
|
$imagereg{$f}->{'name'} = $name if ($name);
|
902 |
|
|
$imagereg{$f}->{'managementlink'} = $managementlink;
|
903 |
|
|
$imagereg{$f}->{'upgradelink'} = $upgradelink;
|
904 |
|
|
$imagereg{$f}->{'terminallink'} = $terminallink;
|
905 |
|
|
$imagereg{$f}->{'version'} = $version;
|
906 |
|
|
$imagereg{$f}->{'appid'} = $appid;
|
907 |
|
|
} else {
|
908 |
|
|
if ($name && $current) {
|
909 |
|
|
my $ug = new Data::UUID;
|
910 |
|
|
my $newuuid = $ug->create_str();
|
911 |
|
|
$imagereg{$f} = {
|
912 |
|
|
uuid=>$newuuid,
|
913 |
|
|
user=>$stackuser,
|
914 |
|
|
name=>$name,
|
915 |
64c667ea
|
hq
|
type=>'qcow2',
|
916 |
95b003ff
|
Origo
|
managementlink=>$managementlink,
|
917 |
|
|
upgradelink=>$upgradelink,
|
918 |
|
|
terminallink=>$terminallink,
|
919 |
|
|
version=>$version,
|
920 |
|
|
virtualsize=>$virtualsize,
|
921 |
|
|
appid=>$appid
|
922 |
|
|
}
|
923 |
|
|
}
|
924 |
|
|
}
|
925 |
d24d9a01
|
hq
|
if ($imagereg{$f} && $f =~ /\.master\.qcow2$/) {
|
926 |
95b003ff
|
Origo
|
$imagereg{$f}->{'installable'} = 'true';
|
927 |
64c667ea
|
hq
|
$imagereg{$f}->{'type'} = 'qcow2';
|
928 |
95b003ff
|
Origo
|
# Check for old versions and remove installable flag in order to not confuse matters
|
929 |
|
|
if ($appid) {
|
930 |
|
|
foreach my $imgref (values %imagereg) {
|
931 |
|
|
if (
|
932 |
|
|
$imgref->{'path'} =~ /\.master\.qcow2$/
|
933 |
|
|
&& $imgref->{'appid'} eq $appid
|
934 |
|
|
&& $imgref->{'path'} ne $f
|
935 |
|
|
&& $imgref->{'version'} lt $img->{'version'}
|
936 |
|
|
) {
|
937 |
|
|
my $imgversion = $imgref->{'version'} || '1.0';
|
938 |
|
|
print "Removing installable flag from old version: $imgref->{path} ($imgref->{'version'} < $img->{'version'})\n";
|
939 |
|
|
$imgref->{'installable'} = 'false';
|
940 |
|
|
$imgref->{'name'} .= " ($imgversion)" unless ($imgref->{'name'} =~ /$imgversion/ );
|
941 |
|
|
}
|
942 |
|
|
}
|
943 |
|
|
}
|
944 |
|
|
}
|
945 |
|
|
|
946 |
|
|
my $cmd2;
|
947 |
|
|
if ($fname2) { # This app also has a data image
|
948 |
|
|
foreach $sp (@spoolpaths) {
|
949 |
|
|
$f2 = "$sp/$stackuser/$fname2";
|
950 |
|
|
if (-e $f2) {
|
951 |
|
|
my @stat = stat($f2);
|
952 |
|
|
$lsize2 = $stat[7];
|
953 |
|
|
$lrealsize2 = $stat[12] * 512;
|
954 |
|
|
$match2 = 1;
|
955 |
|
|
last;
|
956 |
|
|
}
|
957 |
|
|
}
|
958 |
|
|
$imgurl2 = "$stack->{'url2'}?auth_tkt=$stack->{'tkt'}";
|
959 |
|
|
|
960 |
|
|
# if ($match2 && $lsize2 >= $fsize2) {
|
961 |
|
|
if ($match2 && $imagereg{$f2} && ($imagereg{$f2}->{'version'} ge $version || $lsize2 == $fsize2) ) {
|
962 |
|
|
$msg .= "Image2 $fname2 found in $f2 [$fsize2 bytes]. Updating: $name2 ";
|
963 |
|
|
$imagereg{$f2}->{'status'} = 'unused' if ($imagereg{$f2}->{'status'} eq 'downloading');
|
964 |
|
|
} else {
|
965 |
|
|
if (!lookupProcess($fname2)) { # Check if image is already being downloaded
|
966 |
|
|
$f2 = "$spoolpaths[0]/$stackuser/$fname2";
|
967 |
|
|
print `echo "status=downloading" > "$f2.meta"`;
|
968 |
|
|
$msg .= "Image2 $fname2 not found. Downloading $fsize2 bytes to $f2... ";
|
969 |
|
|
my $msize = int($fsize2 /1024/1024);
|
970 |
|
|
my $uimsg = qq|Now downloading $name2 ($msize) MB)|;
|
971 |
2a63870a
|
Christian Orellana
|
push @downloadalerts, {tab=>"nodes", user=>'irigo', type=>"message", message=>$uimsg, download=>$f2, name=>$name2, size=>$frealsize2};
|
972 |
|
|
push @dlmasters, $name;
|
973 |
95b003ff
|
Origo
|
$cmd2 = qq|wget --no-check-certificate --no-verbose --tries=4 -a /mnt/stabile/images/stacks-xfer.log -O "$f2" $imgurl2|;
|
974 |
|
|
$cmd2 .= qq|; rm "$f2.meta"; steamExec updateimagestatus "$f2" downloaded $fsize2; steamExec updatebackingfile "$f2"|;
|
975 |
|
|
} else {
|
976 |
|
|
$msg .= "Image $fname is already being downloaded. ";
|
977 |
|
|
}
|
978 |
|
|
}
|
979 |
|
|
|
980 |
|
|
if ($imagereg{$f2}) {
|
981 |
|
|
$imagereg{$f2}->{'name'} = $name2 if ($name2);
|
982 |
|
|
$imagereg{$f2}->{'version'} = $version;
|
983 |
|
|
$imagereg{$f2}->{'appid'} = $appid;
|
984 |
|
|
} else {
|
985 |
|
|
if ($name2) {
|
986 |
|
|
my $ug = new Data::UUID;
|
987 |
|
|
my $newuuid = $ug->create_str();
|
988 |
|
|
$imagereg{$f2} = {
|
989 |
|
|
uuid=>$newuuid,
|
990 |
|
|
user=>$stackuser,
|
991 |
|
|
name=>$name2,
|
992 |
|
|
version=>$version,
|
993 |
64c667ea
|
hq
|
type=>'qcow2',
|
994 |
95b003ff
|
Origo
|
appid=>$appid
|
995 |
|
|
}
|
996 |
|
|
}
|
997 |
|
|
}
|
998 |
|
|
}
|
999 |
|
|
# Update data image information
|
1000 |
d24d9a01
|
hq
|
$imagereg{$f}->{'image2'} = $f2 if ($imagereg{$f});
|
1001 |
95b003ff
|
Origo
|
tied(%imagereg)->commit;
|
1002 |
|
|
push @cmds, $cmd if ($cmd);
|
1003 |
|
|
push @cmds, $cmd2 if ($cmd2);
|
1004 |
|
|
print "$msg\n" if ($msg);
|
1005 |
2a63870a
|
Christian Orellana
|
$main::updateUI->(@downloadalerts) if (@downloadalerts); # notify user
|
1006 |
95b003ff
|
Origo
|
$main::syslogit->($stackuser, 'info', $msg) if ($msg && ($cmd || $cmd2));
|
1007 |
|
|
}
|
1008 |
|
|
}
|
1009 |
|
|
untie %imagereg;
|
1010 |
|
|
undef %imagereg;
|
1011 |
|
|
foreach my $cmd (@cmds) {
|
1012 |
|
|
#print "$cmd\n";
|
1013 |
|
|
#system("sh $cmd &");
|
1014 |
|
|
my $daemon = Proc::Daemon->new(
|
1015 |
|
|
work_dir => '/usr/local/bin',
|
1016 |
|
|
exec_command => $cmd
|
1017 |
|
|
) or do {$msg = "Error downloading $fname $@";};
|
1018 |
|
|
my $pid = $daemon->Init() or do {$msg = "Error downloading $fname $@";};
|
1019 |
|
|
}
|
1020 |
2a63870a
|
Christian Orellana
|
return @dlmasters;
|
1021 |
95b003ff
|
Origo
|
}
|
1022 |
|
|
|
1023 |
|
|
sub TERMINATE {
|
1024 |
|
|
print "Terminating\n" if ($running);
|
1025 |
|
|
$running = 0;
|
1026 |
|
|
}
|
1027 |
|
|
|
1028 |
|
|
sub HUP {
|
1029 |
|
|
} |