1 |
95b003ff
|
Origo
|
#!/usr/bin/perl
|
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 |
|
|
use LWP::Simple;
|
9 |
|
|
use URI::Escape;
|
10 |
|
|
use POSIX;
|
11 |
|
|
use Sys::Syslog qw( :DEFAULT setlogsock);
|
12 |
|
|
use Sys::Virt;
|
13 |
|
|
use XML::Simple;
|
14 |
|
|
use Socket;
|
15 |
|
|
use File::Copy;
|
16 |
|
|
use Data::Dumper;
|
17 |
|
|
use Time::HiRes qw (usleep ualarm gettimeofday tv_interval);
|
18 |
|
|
use ConfigReader::Simple;
|
19 |
|
|
use Config::Simple;
|
20 |
|
|
use File::Basename;
|
21 |
|
|
use Text::ParseWords;
|
22 |
|
|
use Proc::Daemon;
|
23 |
|
|
use Error qw(:try);
|
24 |
|
|
use Proc::Background;
|
25 |
|
|
use Storable;
|
26 |
|
|
use sigtrap 'handler' => \&TERMINATE, 'QUIT', 'INT', 'TERM', 'KILL', 'STOP';
|
27 |
|
|
|
28 |
|
|
#$SIG{TERM} = TERMINATE;
|
29 |
|
|
#$SIG{KILL} = TERMINATE;
|
30 |
|
|
#$SIG{STOP} = TERMINATE;
|
31 |
|
|
#$SIG{__DIE__} = \&dont_die; # Won't die now
|
32 |
|
|
#$SIG{__WARN__} = \&dont_die; # Won't die now
|
33 |
|
|
|
34 |
|
|
my $cmdline = `cat /proc/cmdline`;
|
35 |
|
|
$cmdline =~ /identity=(\S*)/;
|
36 |
|
|
my $identity = $1;
|
37 |
|
|
|
38 |
|
|
my $cfg = new Config::Simple("/etc/stabile/nodeconfig.cfg");
|
39 |
|
|
# my $config = ConfigReader::Simple->new("/etc/stabile/nodeconfig.cfg",
|
40 |
|
|
# [qw(ADMIN_SERVER_ADDRESS STORAGE_SERVERS_ADDRESS_PATHS STORAGE_SERVERS_LOCAL_PATHS ADMIN_NIC DATA_NIC
|
41 |
|
|
# INITIALIZE_LOCAL_DISK
|
42 |
|
|
# VM_READ_LIMIT VM_WRITE_LIMIT VM_IOPS_READ_LIMIT VM_IOPS_WRITE_LIMIT
|
43 |
|
|
# PISTON_READ_LIMIT PISTON_WRITE_LIMIT PISTON_IOPS_READ_LIMIT PISTON_IOPS_WRITE_LIMIT
|
44 |
|
|
# )]);
|
45 |
|
|
my $mainvalve = $cfg->param('ADMIN_SERVER_ADDRESS');
|
46 |
|
|
my $mainvalvepwd = $cfg->param('ADMIN_SERVER_HTTP_PWD') ||'sunshine';
|
47 |
|
|
|
48 |
|
|
my $cgset; # Have cgroup values been set?
|
49 |
|
|
|
50 |
|
|
my $initdisk = $cfg->param('INITIALIZE_LOCAL_DISK');
|
51 |
|
|
$identity = $identity || $cfg->param('IDENTITY');
|
52 |
|
|
|
53 |
d24d9a01
|
hq
|
my $adminnic = $cfg->param('ADMIN_NIC'); # This is the internal interface used for nfs-roots and for communcating with admin node on 10.0.0.1
|
54 |
|
|
my $datanic = $cfg->param('DATA_NIC'); # This is the external interface used for VM vlans
|
55 |
2a63870a
|
Christian Orellana
|
$adminnic = $datanic if (!$adminnic && $datanic);
|
56 |
|
|
$datanic = $adminnic if (!$datanic && $adminnic);
|
57 |
|
|
|
58 |
|
|
if (!($datanic) || !(`ifconfig | grep flags= | sed -n -e 's/ .*//p'` =~ /^$datanic::/)) { # Make sure device exists
|
59 |
|
|
($adminnic, $datanic) = getNics();
|
60 |
95b003ff
|
Origo
|
}
|
61 |
|
|
|
62 |
|
|
print "Using $adminnic as admin NIC\n";
|
63 |
|
|
print "Using $datanic as data NIC\n";
|
64 |
|
|
|
65 |
2a63870a
|
Christian Orellana
|
if ($identity eq 'local_kvm') {
|
66 |
|
|
`iptables -D INPUT --in-interface $datanic -d 10.0.0.1 -j DROP 2>/dev/null`; # Disallow outside access to virtual internal network
|
67 |
|
|
`iptables -A INPUT --in-interface $datanic -d 10.0.0.1 -j DROP`;
|
68 |
64c667ea
|
hq
|
} else {
|
69 |
|
|
# Make kvm listen for vnc connections on all interfaces - only on compute nodes not directly accessible from outside
|
70 |
|
|
system("perl -pi -e 's/.*vnc_listen = .+/vnc_listen = \"0.0.0.0\"/' /etc/libvirt/qemu.conf") unless (`grep 'vnc_listen = "0.0.0.0"' /etc/libvirt/qemu.conf`);
|
71 |
2a63870a
|
Christian Orellana
|
}
|
72 |
|
|
|
73 |
95b003ff
|
Origo
|
# Make sure data nic is up...
|
74 |
|
|
print `ifconfig $datanic up`;
|
75 |
|
|
|
76 |
|
|
my $resolv = `cat /etc/resolv.conf`;
|
77 |
|
|
if ($resolv =~ /nameserver (\S*)/) {
|
78 |
|
|
$mainvalve = scalar(gethostbyaddr(inet_aton($1), AF_INET)) unless $mainvalve;
|
79 |
|
|
print "Using admin server $mainvalve ($1)\n";
|
80 |
|
|
} elsif ($mainvalve) {
|
81 |
|
|
print "Adding nameserver $mainvalve\n";
|
82 |
|
|
`echo "nameserver $mainvalve" >> /etc/resolv.conf`;
|
83 |
|
|
}
|
84 |
|
|
|
85 |
|
|
my $basedir = "/mnt/stabile/node";
|
86 |
|
|
my %mtimes;
|
87 |
|
|
my %img_sizes;
|
88 |
|
|
my %img_realsizes;
|
89 |
|
|
my %img_virtualsizes;
|
90 |
|
|
my %oldTimes;
|
91 |
|
|
|
92 |
|
|
my $tenders = $cfg->param('STORAGE_SERVERS_ADDRESS_PATHS') || "$mainvalve:/mnt/stabile/images";
|
93 |
27512919
|
Origo
|
my @tenderlist;
|
94 |
|
|
if (ref $tenders eq 'ARRAY') {
|
95 |
|
|
@tenderlist = @{$tenders};
|
96 |
|
|
} else {
|
97 |
|
|
@tenderlist = split(/,\s*/, $tenders);
|
98 |
|
|
}
|
99 |
95b003ff
|
Origo
|
my $tenderpaths = $cfg->param('STORAGE_SERVERS_LOCAL_PATHS') || "/mnt/stabile/images";
|
100 |
27512919
|
Origo
|
my @tenderpathslist;
|
101 |
|
|
if (ref $tenderpaths eq 'ARRAY') {
|
102 |
|
|
@tenderpathslist = @{$tenderpaths};
|
103 |
|
|
} else {
|
104 |
|
|
@tenderpathslist = split(/,\s*/, $tenderpaths);
|
105 |
|
|
}
|
106 |
95b003ff
|
Origo
|
|
107 |
|
|
unless ($mainvalve && $adminnic) {
|
108 |
|
|
print "ADMIN_SERVER_ADDRESS and ADMIN_NIC in /etc/stabile/nodeconfig.cfg should contain valid values\n";
|
109 |
|
|
exit(0);
|
110 |
|
|
}
|
111 |
|
|
|
112 |
|
|
$processes = `ps ax | grep \/usr\/local\/sbin\/movepiston | wc -l`;
|
113 |
|
|
if (!($ARGV[0] =~ /command=(.+)/) && $processes > 3) {
|
114 |
|
|
print "Only one movepiston can be running!\n";
|
115 |
|
|
logit('info', "Only one movepiston can be running!");
|
116 |
|
|
sleep 1;
|
117 |
|
|
exit(0);
|
118 |
|
|
}
|
119 |
|
|
|
120 |
|
|
my $base_url = "http://$mainvalve/stabile/piston/piston.cgi";
|
121 |
|
|
my $stats_url = "http://$mainvalve/stabile/piston/pistonstats.cgi";
|
122 |
|
|
|
123 |
|
|
|
124 |
|
|
my $running = 1;
|
125 |
|
|
my $dostats = 1;
|
126 |
|
|
my $status = "shutdown";
|
127 |
|
|
my $virshemu = 'qemu';
|
128 |
|
|
my $naptime = 5; # time in seconds between piston updates
|
129 |
|
|
my $statsnap = 10; # time in seconds between stats updates - this must be coordinated with values in pistonstats.cgi
|
130 |
|
|
my $stornap = 5; # How often to update storage and local image info
|
131 |
|
|
my $laststatstime = 0;
|
132 |
|
|
my $laststortime = 0;
|
133 |
|
|
#my $laststorfree = 0;
|
134 |
|
|
my $sleepafter = 50*60; # default time to sleep after
|
135 |
|
|
my $drowsiness = 0;
|
136 |
|
|
my %mortuary;
|
137 |
|
|
|
138 |
|
|
if ($identity eq "vbox") {$virshemu = 'vbox'};
|
139 |
|
|
|
140 |
|
|
my @domstates = ("nostate", "running", "blocked", "paused", "shutdown", "shutoff", "crashed");
|
141 |
|
|
|
142 |
|
|
my $browser = LWP::UserAgent->new;
|
143 |
|
|
if ($identity eq 'local_kvm') {
|
144 |
|
|
$browser->local_address("10.0.0.1");
|
145 |
|
|
}
|
146 |
|
|
$browser->agent('movepiston/1.0b');
|
147 |
|
|
$browser->protocols_allowed( [ 'http','https'] );
|
148 |
|
|
$browser->credentials(
|
149 |
|
|
"$mainvalve:80",
|
150 |
|
|
'Services',
|
151 |
|
|
'irigo', $mainvalvepwd
|
152 |
|
|
);
|
153 |
|
|
|
154 |
|
|
my $ifinfo;
|
155 |
|
|
if (`ifconfig $adminnic`) {
|
156 |
|
|
$ifinfo = `ifconfig $adminnic`;
|
157 |
|
|
} else {
|
158 |
|
|
print "NIC $adminnic is not availaible on this node\n";
|
159 |
|
|
die;
|
160 |
|
|
}
|
161 |
|
|
my $mac;
|
162 |
|
|
$mac = $1 if ($ifinfo =~ /HWaddr (\S+)(\s*)\n/);
|
163 |
|
|
$mac = $1 if ($ifinfo =~ /ether (\S+)(\s*)/);
|
164 |
|
|
my $nmac = $mac;
|
165 |
|
|
$nmac =~ tr/://d;
|
166 |
2a63870a
|
Christian Orellana
|
print "Using mac $mac as id for this node\n";
|
167 |
|
|
|
168 |
|
|
if ($identity eq "local_kvm" && $nmac ne $cfg->param('MAC')) {
|
169 |
|
|
$identity = '';
|
170 |
|
|
print "Network interface change detected - rejoining\n";
|
171 |
|
|
}
|
172 |
|
|
|
173 |
|
|
|
174 |
95b003ff
|
Origo
|
my $hostname = $mac;
|
175 |
|
|
$mac = uri_escape($mac);
|
176 |
|
|
$hostname =~ tr/://d;
|
177 |
|
|
$hostname = "piston" . $hostname;
|
178 |
27512919
|
Origo
|
$ifinfo =~ m/inet (\S+) (.*)\n/i;
|
179 |
95b003ff
|
Origo
|
my $ip = $1;
|
180 |
|
|
my $glogentry = "--: nodes: $nmac: running: Bringing up $identity piston...";
|
181 |
|
|
my $command;
|
182 |
|
|
|
183 |
|
|
# Load IPMI modules
|
184 |
|
|
`modprobe ipmi_devintf`;
|
185 |
|
|
my $ipmiip;
|
186 |
d24d9a01
|
hq
|
unless (system("modprobe ipmi_si")) {
|
187 |
95b003ff
|
Origo
|
my $ipmiinfo = `/usr/bin/ipmitool lan print 1`;
|
188 |
|
|
if ($ipmiinfo =~ m/IP Address .+: (.+)\n/i) {
|
189 |
|
|
$ipmiip = $1;
|
190 |
|
|
}
|
191 |
|
|
} else {
|
192 |
|
|
print "IPMI is not available on this node\n";
|
193 |
|
|
}
|
194 |
|
|
|
195 |
d24d9a01
|
hq
|
# Disable offloading to NIC - at least for our mini-ITX boards this prevents crashes
|
196 |
|
|
print `ethtool -K $adminnic gso off gro off tso off`;
|
197 |
|
|
print `ethtool -K $datanic gso off gro off tso off` if ($adminnic ne $datanic);
|
198 |
|
|
|
199 |
95b003ff
|
Origo
|
# Prevent VM's using Libvirt's default network to reach each other + infrastructure
|
200 |
|
|
`modprobe br_netfilter` unless (`lsmod | grep br_netfilter`);
|
201 |
|
|
`echo 1 > /proc/sys/net/bridge/bridge-nf-call-iptables`;
|
202 |
|
|
`iptables -D FORWARD --in-interface virbr0 -d 192.168.0.0/16 -j DROP 2>/dev/null`;
|
203 |
|
|
`iptables -I FORWARD --in-interface virbr0 -d 192.168.0.0/16 -j DROP`;
|
204 |
|
|
`iptables -D FORWARD --in-interface virbr0 -d 10.0.0.0/8 -j DROP 2>/dev/null`;
|
205 |
|
|
`iptables -I FORWARD --in-interface virbr0 -d 10.0.0.0/8 -j DROP`;
|
206 |
|
|
|
207 |
|
|
my $stor;
|
208 |
|
|
my $test;
|
209 |
|
|
$debug;
|
210 |
|
|
$debug = 1 if ($ARGV[0] eq 'debug' || $ARGV[0] eq 'stats' || $ARGV[0] eq 'test' || $ARGV[1] eq 'debug' || $ARGV[1] eq 'stats');
|
211 |
|
|
$dostats = 0 if ($ARGV[0] eq 'nostats' || $ARGV[1] eq 'nostats');
|
212 |
|
|
|
213 |
|
|
my $badstrokes = "/tmp/badstrokes"; # Keeping track of bad, crashing tasks
|
214 |
|
|
my $tombstones = "/tmp/tombstones"; # Keep track of destroyed servers
|
215 |
|
|
|
216 |
|
|
`rm /tmp/movepiston.out` if (-e "/tmp/movepiston.out");
|
217 |
27512919
|
Origo
|
`chmod 666 /dev/zfs` if (-e '/dev/zfs'); # TODO: This should be removed once we upgrade to Bionic and zfs allow is supported
|
218 |
95b003ff
|
Origo
|
|
219 |
|
|
while ($running) {
|
220 |
|
|
if ($ARGV[0] eq 'stop') {
|
221 |
|
|
TERMINATE();
|
222 |
|
|
} elsif ($ARGV[0] =~ /^command=(.+)/) {
|
223 |
|
|
$command = $1;
|
224 |
|
|
if ($command =~ /(backup\..+)/ && -e "/tmp/$1") {
|
225 |
|
|
my $backuptasks = $1;
|
226 |
|
|
# logit('info', "Performing command $command $ARGV[1] $ARGV[2] $ARGV[3] $ARGV[4] $ARGV[5] $ARGV[6]");
|
227 |
|
|
my $lines = `cat /tmp/$backuptasks`;
|
228 |
|
|
chomp $lines;
|
229 |
|
|
unlink("/tmp/$backuptasks");
|
230 |
|
|
my @clines = split /\n/, $lines;
|
231 |
|
|
foreach my $line (@clines) {
|
232 |
|
|
logit('info', "Backing up: $line");
|
233 |
|
|
my @args = shellwords($line);
|
234 |
|
|
backup($args[0], $args[1], $args[2], $args[3], $args[4],$args[5]);
|
235 |
|
|
}
|
236 |
|
|
# backup($ARGV[1], $ARGV[2], $ARGV[3], $ARGV[4], $ARGV[5], $ARGV[6]);
|
237 |
|
|
}
|
238 |
|
|
} elsif ($ARGV[0] eq 'test' && $identity) {
|
239 |
|
|
$test = 1;
|
240 |
|
|
initializeLocalDisk($initdisk) if ($initdisk && $identity ne 'local_kvm');
|
241 |
|
|
updatePistonInfo();
|
242 |
2a63870a
|
Christian Orellana
|
TERMINATE();
|
243 |
95b003ff
|
Origo
|
} elsif ($ARGV[0] eq 'stats' && $identity) {
|
244 |
|
|
$test = 1;
|
245 |
|
|
updatePistonStats();
|
246 |
|
|
$running = 0;
|
247 |
|
|
} elsif ($identity eq "kvm" || $identity eq "local_kvm" || $identity eq "vbox") {
|
248 |
|
|
$status = "running";
|
249 |
|
|
$running = 1;
|
250 |
|
|
if ($identity ne 'local_kvm') {
|
251 |
|
|
if ($initdisk) {
|
252 |
|
|
my $res = initializeLocalDisk($initdisk);
|
253 |
|
|
}
|
254 |
|
|
print `/bin/hostname $hostname`;
|
255 |
|
|
print `/bin/echo "127.0.0.1 localhost\n$ip $hostname" > /etc/hosts`;
|
256 |
|
|
|
257 |
|
|
my $mounts = `cat /proc/mounts`;
|
258 |
|
|
if ($mounts =~ /\mnt\/stabile\/node/) {
|
259 |
|
|
if ($mounts =~ /volgroup1-lvol1/) {
|
260 |
|
|
$stor = 'lvm';
|
261 |
|
|
} elsif ($mounts =~ /stabile-node/) {
|
262 |
|
|
$stor = 'zfs';
|
263 |
|
|
}
|
264 |
|
|
}
|
265 |
|
|
if ($identity eq 'local_kvm') {
|
266 |
|
|
logit('info', "Local kvm - not initializing cgroups");
|
267 |
|
|
} elsif (!$cgset) {
|
268 |
|
|
setCgroups();
|
269 |
|
|
$cgset = 1;
|
270 |
|
|
} else {
|
271 |
|
|
logit('info', "Unable to initialize cgroups!!");
|
272 |
|
|
print "Unable to initialize cgroups!!\n";
|
273 |
|
|
$running = 0;
|
274 |
|
|
}
|
275 |
|
|
# restart rsyslog to pick up new hostname
|
276 |
|
|
print `/sbin/restart rsyslog`;
|
277 |
|
|
print "Setting clock from $mainvalve\n" unless ($debug);
|
278 |
|
|
print `/usr/sbin/ntpdate $mainvalve` unless ($debug);
|
279 |
|
|
print "Known tenders:\n", Dumper(\@tenderlist) if $debug;
|
280 |
|
|
print "Known tender paths:\n", Dumper(\@tenderpathslist) if $debug;
|
281 |
|
|
print "Trying to mount " . (scalar @tenderpathslist) . " tenders\n";
|
282 |
|
|
|
283 |
|
|
for (my $i=0; $i<(scalar @tenderpathslist); $i++) {
|
284 |
|
|
my $path = $tenderpathslist[$i];
|
285 |
|
|
my $host = $tenderlist[$i];
|
286 |
|
|
if ($mounts =~ m/$path /i) {
|
287 |
|
|
print ("$path already mounted\n") if ($debug);
|
288 |
|
|
} elsif ($identity ne 'local_kvm' && $host =~ /10\.0\.0\.1/) {
|
289 |
|
|
print "Mounting $path from $host\n";
|
290 |
|
|
logit('info', "Mounting (1) $path from $host");
|
291 |
|
|
# Directory / mount point must exist
|
292 |
|
|
`mkdir -p "$path"` unless (-e $path);
|
293 |
|
|
# eval {print `mount -o intr,noatime,nfsvers=3 $host $path`; 1;} or do {print $@;};
|
294 |
|
|
eval {print `mount -o hard,intr,nolock,noatime,nfsvers=3,tcp,timeo=1200,rsize=1048600,wsize=1048600,bg $host $path`; 1;} or do {print $@;};
|
295 |
|
|
}
|
296 |
|
|
}
|
297 |
e9af6c24
|
Origo
|
`chmod 777 /mnt/stabile/*`;
|
298 |
95b003ff
|
Origo
|
}
|
299 |
|
|
if ($identity eq "kvm") {
|
300 |
|
|
logit('info', "Bringing up KVM piston $nmac");
|
301 |
|
|
} elsif ($identity eq "local_kvm") {
|
302 |
|
|
logit('info', "Bringing up local KVM piston $nmac");
|
303 |
|
|
} elsif ($identity eq "vbox") {
|
304 |
|
|
logit('info', "Bringing up Virtual Box piston $nmac");
|
305 |
|
|
print `/etc/init.d/vboxdrv start`,"\n";
|
306 |
|
|
}
|
307 |
|
|
|
308 |
|
|
|
309 |
|
|
my $failedtasks;
|
310 |
|
|
if (-e $badstrokes && !(-z $badstrokes)) {
|
311 |
|
|
$failedtasks = `cat $badstrokes`;
|
312 |
|
|
logit('info', "A previous attempt at executing tasks failed:\n$failedtasks");
|
313 |
|
|
print "Trying to execute again.\n";
|
314 |
|
|
updatePistonInfo($failedtasks) if ($failedtasks =~ m/^\S+=(.*)/ig);
|
315 |
|
|
unlink($badstrokes);
|
316 |
|
|
}
|
317 |
|
|
if (-e $tombstones && !(-z $tombstones)) {
|
318 |
|
|
my $hashref = retrieve($tombstones);
|
319 |
|
|
%mortuary = %{$hashref};
|
320 |
|
|
logit('info', "A list of previously destroyed domains was found: " . Dumper(%mortuary));
|
321 |
|
|
}
|
322 |
|
|
while ($running) {
|
323 |
|
|
try {
|
324 |
|
|
$running = updatePistonInfo();
|
325 |
|
|
if ($dostats && (time() > $laststatstime + $statsnap)) {
|
326 |
|
|
# `sync; echo 3 > /proc/sys/vm/drop_caches`; # Clean up
|
327 |
|
|
$laststatstime = time();
|
328 |
|
|
updatePistonStats();
|
329 |
|
|
}
|
330 |
|
|
sleep $naptime;
|
331 |
|
|
drowse();
|
332 |
|
|
} catch Error with {
|
333 |
|
|
my $ex = shift;
|
334 |
|
|
print "Internal Error: $ex\n";
|
335 |
|
|
} finally {
|
336 |
|
|
};
|
337 |
|
|
}
|
338 |
|
|
} elsif ($identity eq "rescue") {
|
339 |
|
|
logit('info', "Bringing up rescue piston");
|
340 |
|
|
$status = "running";
|
341 |
|
|
$running = 1;
|
342 |
|
|
while ($running) {
|
343 |
|
|
sleep $naptime;
|
344 |
|
|
}
|
345 |
|
|
} else {
|
346 |
|
|
logit('info', "No identity: $identity Joining the engine...");
|
347 |
|
|
updateInterfaces();
|
348 |
|
|
$status = "joining";
|
349 |
|
|
my $cpuinfo = `cat /proc/cpuinfo`;
|
350 |
|
|
$cpuinfo =~ m/model name.*:\s*(.*)\n/i;
|
351 |
|
|
my $cpuname = $1;
|
352 |
|
|
$cpuname =~ s/( )+//g;
|
353 |
|
|
$cpuinfo =~ m/cpu family.*:\s*(.*)\n/i;
|
354 |
|
|
my $cpufamily = $1;
|
355 |
|
|
$cpuinfo =~ m/model.*:\s*(.*)\n/i;
|
356 |
|
|
my $cpumodel = $1;
|
357 |
|
|
$cpuinfo =~ m/cpu MHz.*:\s*(.*)\n/i;
|
358 |
|
|
my $cpuspeed = $1;
|
359 |
|
|
my $cpucores = "1";
|
360 |
|
|
if ($cpuinfo =~ m/cpu cores.*:\s*(.+)\n/i) {
|
361 |
|
|
$cpucores = $1;
|
362 |
|
|
} elsif ($cpuinfo =~ m/siblings.*:\s*(.+)\n/i) {
|
363 |
|
|
$cpucores = $1;
|
364 |
|
|
}
|
365 |
|
|
my $cpucount = 0;
|
366 |
|
|
while ($cpuinfo =~ /physical id.*: (.+)\n/gi) {
|
367 |
|
|
if ($1 > $cpucount) {
|
368 |
|
|
$cpucount = $1;
|
369 |
|
|
}
|
370 |
|
|
}
|
371 |
|
|
$cpucount++;
|
372 |
|
|
my $meminfo = `cat /proc/meminfo`;
|
373 |
|
|
$meminfo =~ m/MemTotal:\s*(.*) kB\n/i;
|
374 |
|
|
my $memtotal = $1;
|
375 |
|
|
$meminfo =~ m/MemFree:\s*(.*) kB\n/i;
|
376 |
|
|
my $memfree = $1;
|
377 |
|
|
$meminfo =~ m/Cached:\s*(.*) kB\n/i;
|
378 |
|
|
my $memcached = $1;
|
379 |
|
|
$memfree += $memcached; # or `echo 3 > /proc/sys/vm/drop_caches` to free caches
|
380 |
|
|
|
381 |
|
|
my $logentry = "--: nodes: $nmac: joining: Trying to join";
|
382 |
|
|
my $url = $base_url . "?mac=$mac&ip=$ip&cpucores=$cpucores&cpucount=$cpucount&cpuspeed=$cpuspeed&cpuname=" .
|
383 |
|
|
uri_escape("$cpuname") . "&ipmiip=" . uri_escape($ipmiip) .
|
384 |
|
|
"&cpufamily=$cpufamily&cpumodel=$cpumodel&memtotal=$memtotal&memfree=$memfree&status=joining&logentry=" .
|
385 |
|
|
$logentry;
|
386 |
|
|
|
387 |
|
|
my $assimilated = 0;
|
388 |
|
|
my $i = 0;
|
389 |
|
|
while ($assimilated == 0) {
|
390 |
|
|
my $content = $browser->get($url)->content();
|
391 |
|
|
logit('info', "Waiting for assimilation...");
|
392 |
|
|
if (defined $content) {
|
393 |
|
|
my $assimilation_status = "";
|
394 |
|
|
if ($content =~ /Assimilation=(\S*)(.*)/i) {
|
395 |
|
|
$assimilation_status = $1;
|
396 |
|
|
$assimilation_reason = $2;
|
397 |
|
|
if ($assimilation_status eq "OK") {
|
398 |
|
|
$assimilated = 1;
|
399 |
|
|
} else {
|
400 |
|
|
logit('info', "Assimilation not accepted: $assimilation_status$assimilation_reason");
|
401 |
|
|
sleep 2;
|
402 |
|
|
if ($i>2) {last} else {$i++};
|
403 |
|
|
}
|
404 |
|
|
} else {
|
405 |
|
|
logit('info', "Assimilation answer not received: $content");
|
406 |
|
|
sleep 2;
|
407 |
|
|
if ($i>2) {last} else {$i++};
|
408 |
|
|
}
|
409 |
|
|
} else {
|
410 |
|
|
logit('info', "Couldn't get $url:");
|
411 |
|
|
sleep 2;
|
412 |
|
|
if ($i>2) {last} else {$i++};
|
413 |
|
|
}
|
414 |
|
|
}
|
415 |
|
|
if ($assimilated == 1) {
|
416 |
|
|
if (-e "/etc/stabile/config.cfg") { # We are on valve
|
417 |
|
|
$identity = 'local_kvm';
|
418 |
|
|
} else {
|
419 |
|
|
$identity = 'kvm';
|
420 |
|
|
}
|
421 |
|
|
$cfg->param("IDENTITY", $identity);
|
422 |
2a63870a
|
Christian Orellana
|
$cfg->param("MAC", $nmac);
|
423 |
95b003ff
|
Origo
|
$cfg->save();
|
424 |
|
|
logit('info', "Assimilation completed...");
|
425 |
|
|
}
|
426 |
|
|
}
|
427 |
|
|
}
|
428 |
|
|
1;
|
429 |
|
|
|
430 |
|
|
|
431 |
|
|
sub updatePistonInfo {
|
432 |
|
|
my $failedtasks = shift;
|
433 |
|
|
logit('info', "Updating piston info...") if ($debug);
|
434 |
|
|
$naptime = 5;
|
435 |
|
|
my $pid;
|
436 |
|
|
|
437 |
|
|
my $cpuload = `cat /proc/loadavg`;
|
438 |
|
|
$cpuload =~ m/(\S*) /i;
|
439 |
|
|
$cpuload = $1;
|
440 |
|
|
my $cpucores = "1";
|
441 |
|
|
my $cpuinfo = `cat /proc/cpuinfo`;
|
442 |
|
|
if ($cpuinfo =~ m/cpu cores.*:\s*(.+)\n/i) {
|
443 |
|
|
$cpucores = $1;
|
444 |
|
|
} elsif ($cpuinfo =~ m/siblings.*:\s*(.+)\n/i) {
|
445 |
|
|
$cpucores = $1;
|
446 |
|
|
}
|
447 |
|
|
my $cpucount = 0;
|
448 |
|
|
while ($cpuinfo =~ /physical id.*: (.+)\n/gi) {
|
449 |
|
|
if ($1 > $cpucount) {
|
450 |
|
|
$cpucount = $1;
|
451 |
|
|
}
|
452 |
|
|
}
|
453 |
|
|
$cpucount++;
|
454 |
|
|
my $meminfo = `cat /proc/meminfo`;
|
455 |
|
|
$meminfo =~ m/MemTotal:\s*(.*) kB\n/i;
|
456 |
|
|
my $memtotal = $1;
|
457 |
|
|
$meminfo =~ m/MemFree:\s*(.*) kB\n/i;
|
458 |
|
|
my $memfree = $1;
|
459 |
|
|
$meminfo =~ m/Cached:\s*(.*) kB\n/i;
|
460 |
|
|
my $memcached = $1;
|
461 |
|
|
$memfree += $memcached; # or `echo 3 > /proc/sys/vm/drop_caches` to free caches
|
462 |
|
|
$status = "shutdown" unless ($running || $status eq "asleep");
|
463 |
|
|
|
464 |
|
|
my $nfsroot;
|
465 |
|
|
$nfsroot = uri_escape($1) if ($cmdline =~ m/ nfsroot=(\S+) /);
|
466 |
|
|
my $kernel;
|
467 |
|
|
$kernel = uri_escape($1) if ($cmdline =~ m/BOOT_IMAGE=(\S+) /);
|
468 |
|
|
|
469 |
|
|
# Bring up local interfaces if it has been lost because of S3 sleep
|
470 |
|
|
updateInterfaces();
|
471 |
|
|
|
472 |
d24d9a01
|
hq
|
# piston.cgi gets the ip from the http request
|
473 |
|
|
#my $ipline = `ip -br addr show $adminnic`;
|
474 |
|
|
#chomp $ipline;
|
475 |
|
|
#my $ip;
|
476 |
|
|
#$ip = $1 if ($ipline =~ /\d+\.\d+\.\d+\.\d+\/24/);
|
477 |
|
|
|
478 |
95b003ff
|
Origo
|
# my $virshlist = `virsh -c $virshemu:///system list`;
|
479 |
|
|
logit('info', "Initializing libvirt connection: $virshemu:///system") if ($debug);
|
480 |
|
|
my $vmm = Sys::Virt->new(address => "$virshemu:///system");# unless $vmm;
|
481 |
|
|
logit('info', "Getting dominfo from: $virshemu:///system") if ($debug);
|
482 |
|
|
|
483 |
|
|
# Load domain info into $dinfo
|
484 |
|
|
my $dinfo = dominfo($vmm);
|
485 |
|
|
|
486 |
|
|
# Put node info into $dinfo
|
487 |
|
|
$dinfo->{'status'} = $status;
|
488 |
|
|
$dinfo->{'mac'} = $mac;
|
489 |
d24d9a01
|
hq
|
#$dinfo->{'ip'} = $ip;
|
490 |
95b003ff
|
Origo
|
$dinfo->{'memtotal'} = $memtotal;
|
491 |
|
|
$dinfo->{'memfree'} = $memfree;
|
492 |
|
|
$dinfo->{'identity'} = $identity;
|
493 |
|
|
$dinfo->{'nfsroot'} = $nfsroot;
|
494 |
|
|
$dinfo->{'kernel'} = $kernel;
|
495 |
|
|
$dinfo->{'cpuload'} = $cpuload;
|
496 |
|
|
$dinfo->{'cpucount'} = $cpucount;
|
497 |
|
|
$dinfo->{'cpucores'} = $cpucores;
|
498 |
|
|
$dinfo->{'cpucores'} = $cpucores;
|
499 |
|
|
$dinfo->{'ipmiip'} = uri_escape($ipmiip);
|
500 |
|
|
|
501 |
|
|
# Local storage info
|
502 |
|
|
my $stortotal = "0";
|
503 |
|
|
my $storfree = "0";
|
504 |
|
|
my $esc_path = ($identity eq 'local_kvm')?$tenderpathslist[0]:'/mnt/stabile/node';
|
505 |
|
|
my $storinfo = `df -kl $esc_path`;
|
506 |
e9af6c24
|
Origo
|
if (!($storinfo=~/aufs/) && $storinfo =~ m/\s+(\d+)\s+(\d+)\s+(\d+).+\n/si) {
|
507 |
95b003ff
|
Origo
|
$stortotal = $1;
|
508 |
|
|
$storfree = $3;
|
509 |
|
|
}
|
510 |
|
|
# Load storage info into $dinfo
|
511 |
|
|
print "Getting storage info\n" if ($debug);
|
512 |
|
|
if (time() > $laststortime + $stornap) {
|
513 |
|
|
$laststortime = time();
|
514 |
|
|
|
515 |
|
|
# Local image sizes
|
516 |
|
|
my @thefiles = recurse($basedir);
|
517 |
|
|
my $j = 0;
|
518 |
|
|
foreach my $f (@thefiles) {
|
519 |
|
|
if ($f =~ /(s\d\d\d\.vmdk$)|(-flat\.vmdk$)/) {
|
520 |
|
|
;
|
521 |
|
|
} elsif($f =~ /(\.vmdk$)|(\.img$)|(\.vhd$)|(\.qcow$)|(\.qcow2$)|(\.vdi$)|(\.iso$)/i) {
|
522 |
|
|
$j++;
|
523 |
|
|
my($fname, $dirpath, $suffix) = fileparse($f, (".vmdk", ".img", ".vhd", ".qcow", ".qcow2", ".vdi", ".iso"));
|
524 |
|
|
$dirpath =~ /$basedir\/([^\/]+)/;
|
525 |
|
|
my $user = $1;
|
526 |
|
|
# Deal with sizes
|
527 |
|
|
($newsize, $newrealsize, $newvirtualsize, $newmtime) = getSizes($f, $mtimes{$f});
|
528 |
|
|
if ($newmtime) {
|
529 |
|
|
$mtimes{$f} = $newmtime;
|
530 |
|
|
$img_sizes{$f} = $newsize;
|
531 |
|
|
$img_realsizes{$f} = $newrealsize;
|
532 |
|
|
$img_virtualsizes{$f} = $newvirtualsize;
|
533 |
|
|
}
|
534 |
|
|
$dinfo->{"img$j"} = uri_escape($f);
|
535 |
|
|
$dinfo->{"size$j"} = $img_sizes{$f};
|
536 |
|
|
$dinfo->{"realsize$j"} = $img_realsizes{$f};
|
537 |
|
|
$dinfo->{"virtualsize$j"} = $img_virtualsizes{$f};
|
538 |
|
|
|
539 |
|
|
if (-e "$f.meta" && `grep backingup "$f.meta"` && !(`pgrep "$f.meta"`)) {
|
540 |
|
|
unlink "$f.meta";
|
541 |
|
|
$mes = "Backup aborted ($fname)";
|
542 |
|
|
logit('err', "Backup of $f aborted for user $user");
|
543 |
|
|
my $logentry = "$user: images: $f: unused: $mes";
|
544 |
|
|
|
545 |
|
|
# Update the client UI
|
546 |
|
|
my $url = $base_url . "?mac=$mac&status=updateui&logentry=" . uri_escape($logentry);
|
547 |
|
|
print "Updating image registry: $url\n" if ($debug);
|
548 |
|
|
my $content = $browser->get($url)->content();
|
549 |
|
|
print $content;
|
550 |
|
|
}
|
551 |
|
|
|
552 |
|
|
}
|
553 |
|
|
}
|
554 |
|
|
$dinfo->{"stortotal"} = $stortotal;
|
555 |
|
|
$dinfo->{"storfree"} = $storfree;
|
556 |
|
|
$dinfo->{"stor"} = $stor;
|
557 |
|
|
}
|
558 |
|
|
|
559 |
|
|
if($failedtasks) {
|
560 |
|
|
logit('info', "Not posting node status - we have failed tasks: " . Dumper($dinfo)) if ($debug);
|
561 |
|
|
$content = $failedtasks; # content restored from previous crash was supplied
|
562 |
|
|
$glogentry = "--: nodes: $nmac: $status: Brought up piston with failed tasks...";
|
563 |
|
|
} else {
|
564 |
|
|
$dinfo->{'logentry'} = uri_escape($glogentry) if ($glogentry);
|
565 |
|
|
logit('info', "Posting node status to URL: $base_url: " . Dumper($dinfo)) if ($debug);
|
566 |
|
|
$content = $browser->post($base_url, $dinfo)->content();
|
567 |
|
|
$glogentry = '';
|
568 |
|
|
}
|
569 |
|
|
|
570 |
|
|
if ($test || $debug) {
|
571 |
|
|
print pretty_time(), ": ", $content if ($debug);
|
572 |
|
|
};
|
573 |
|
|
# my $debugline = pretty_time() . ": " . $content;
|
574 |
|
|
# open TEMP3, ">>/tmp/movepiston.out";
|
575 |
|
|
# print TEMP3 $debugline;
|
576 |
|
|
# close TEMP3;
|
577 |
|
|
|
578 |
|
|
my $task_1 = '';
|
579 |
|
|
my $task_2 = '';
|
580 |
|
|
my $task_3 = '';
|
581 |
|
|
|
582 |
|
|
if (defined $content) {
|
583 |
|
|
my @receiveuuids;
|
584 |
|
|
my @clines = split /\n/, $content;
|
585 |
|
|
my @lines;
|
586 |
|
|
foreach my $line (@clines) {
|
587 |
|
|
if ($line =~ m/^\S+=SLEEPAFTER (\d+)/ig) {
|
588 |
|
|
$sleepafter = int($1);
|
589 |
|
|
} elsif ($line =~ m/^\S+=.+/ig) {
|
590 |
|
|
push(@lines, $line);
|
591 |
|
|
}
|
592 |
|
|
}
|
593 |
|
|
while (my $line = shift @lines) {
|
594 |
|
|
$url = $base_url . "?mac=$mac&identity=$identity";
|
595 |
|
|
|
596 |
|
|
my $rcontent = join("\n", @lines);
|
597 |
|
|
`echo "$rcontent" > $badstrokes` if (@lines);
|
598 |
|
|
$line =~ m/^\S+=(.*)/ig;
|
599 |
|
|
@tasks = shellwords($1);
|
600 |
|
|
$task_1 = $tasks[0]; #$1;
|
601 |
|
|
$task_2 = $tasks[1]; #$2;
|
602 |
|
|
$task_3 = $tasks[2]; #$3;
|
603 |
|
|
if ($task_1 eq "REBOOT" && $identity ne 'local_kvm') {
|
604 |
|
|
$status = "reboot";
|
605 |
|
|
my $logentry = "$task_2: nodes: $nmac: $status: Reboot request received - rebooting";
|
606 |
|
|
logit('info', $logentry);
|
607 |
|
|
$url .= "&status=$status&logentry=" . uri_escape($logentry);
|
608 |
|
|
my $newcontent = $browser->get($url)->content();
|
609 |
|
|
print `/sbin/reboot`;
|
610 |
|
|
chop $@; $logentry .= "\n$@" if $@;
|
611 |
|
|
if ($@) {
|
612 |
|
|
chop $@; $logentry .= "\n$@";
|
613 |
|
|
$newcontent = $browser->get($url)->content();
|
614 |
|
|
}
|
615 |
|
|
}
|
616 |
|
|
elsif ($task_1 eq "HALT" && $identity ne 'local_kvm') {
|
617 |
|
|
$status = "shutdown";
|
618 |
|
|
my $logentry = "$task_2: nodes: $nmac: $status: Halt request received - shutting down";
|
619 |
|
|
logit('info', $logentry);
|
620 |
|
|
$url .= "&status=$status&logentry=" . uri_escape($logentry);
|
621 |
|
|
my $newcontent = $browser->get($url)->content();
|
622 |
|
|
sleep 5;
|
623 |
2a63870a
|
Christian Orellana
|
print `systemctl stop movepiston`;
|
624 |
95b003ff
|
Origo
|
`echo 0 > /proc/sys/kernel/hung_task_timeout_secs`;
|
625 |
|
|
print `poweroff`;
|
626 |
|
|
if ($@) {
|
627 |
|
|
chop $@; $logentry .= "\n$@";
|
628 |
|
|
$newcontent = $browser->get($url)->content();
|
629 |
|
|
}
|
630 |
|
|
}
|
631 |
|
|
elsif ($task_1 eq "SLEEP" && $identity ne 'local_kvm') {
|
632 |
|
|
if ($identity eq "kvm") {
|
633 |
|
|
logit('info', "Taking down KVM piston");
|
634 |
|
|
} elsif ($identity eq "vbox") {
|
635 |
|
|
logit('info', "Taking down Virtual Box piston");
|
636 |
|
|
}
|
637 |
|
|
$status = "asleep";
|
638 |
|
|
my $logentry = "$task_2: nodes: $nmac: $status: Sleep request received - putting node to sleep";
|
639 |
|
|
logit('info', $logentry);
|
640 |
|
|
$running = 0;
|
641 |
|
|
$url .= "&status=$status&logentry=" . uri_escape($logentry);
|
642 |
|
|
my $newcontent = $browser->get($url)->content();
|
643 |
|
|
sleep 5;
|
644 |
|
|
# my $meminfo = `cat /proc/acpi/sleep`;
|
645 |
|
|
# my $s3sleep = ($meminfo =~ m/S3/);
|
646 |
|
|
|
647 |
|
|
my $meminfo = `cat /sys/power/state`;
|
648 |
|
|
my $s3sleep = ($meminfo =~ m/mem/);
|
649 |
|
|
|
650 |
|
|
if (0 && $s3sleep) {
|
651 |
|
|
print `/etc/init.d/libvirt-bin stop`,"\n" if ($identity eq "vbox");
|
652 |
|
|
#print `/etc/acpi/sleep.sh`;
|
653 |
|
|
print `/bin/echo -n "mem" > /sys/power/state`;
|
654 |
|
|
} else {
|
655 |
2a63870a
|
Christian Orellana
|
print `systemctl stop movepiston`;
|
656 |
95b003ff
|
Origo
|
`echo 0 > /proc/sys/kernel/hung_task_timeout_secs`;
|
657 |
|
|
print `poweroff`;
|
658 |
|
|
# print `/sbin/shutdown -P now`;
|
659 |
|
|
}
|
660 |
|
|
}
|
661 |
|
|
elsif ($task_1 eq "WAKE" && $identity ne 'local_kvm') {
|
662 |
|
|
$status = "awake";
|
663 |
|
|
my $logentry = "$task_2: nodes: $nmac: $status: Wake request received - now awake";
|
664 |
|
|
logit('info', $logentry);
|
665 |
|
|
$url .= "&status=$status&logentry=" . uri_escape($logentry);
|
666 |
|
|
my $newcontent = $browser->get($url)->content();
|
667 |
|
|
}
|
668 |
|
|
elsif ($task_1 eq "WIPE" && $identity ne 'local_kvm') {
|
669 |
|
|
my $logentry = "$task_2: nodes: $nmac: $status: Wipe request received";
|
670 |
|
|
logit('info', $logentry);
|
671 |
|
|
my $url2 = "$url&status=$status&logentry=" . uri_escape($logentry);
|
672 |
|
|
my $newcontent = $browser->get($url2)->content();
|
673 |
|
|
my $res = initializeLocalDisk($initdisk, 1);
|
674 |
|
|
$logentry = "$task_2: nodes: $nmac: $status: $res";
|
675 |
|
|
logit('info', $logentry);
|
676 |
|
|
$url2 = "$url&status=$status&logentry=" . uri_escape($logentry);
|
677 |
|
|
$newcontent = $browser->get($url2)->content();
|
678 |
|
|
}
|
679 |
|
|
elsif ($task_1 eq "UNJOIN") {
|
680 |
|
|
$status = "unjoin";
|
681 |
|
|
my $logentry = "$task_2: nodes: $nmac: $status: Unjoin request received";
|
682 |
|
|
logit('info', $logentry);
|
683 |
|
|
$url .= "&status=$status&logentry=" . uri_escape($logentry);
|
684 |
|
|
my $newcontent = $browser->get($url)->content();
|
685 |
|
|
print `/sbin/reboot`;
|
686 |
|
|
}
|
687 |
|
|
elsif ($task_1 eq "RELOAD") {
|
688 |
|
|
$status = "reload";
|
689 |
|
|
my $logentry = "$task_2: nodes: $nmac: $status: Reload request received";
|
690 |
|
|
logit('info', $logentry);
|
691 |
|
|
$url .= "&status=$status&logentry=" . uri_escape($logentry);
|
692 |
|
|
my $newcontent = $browser->get($url)->content();
|
693 |
|
|
$running = 0;
|
694 |
|
|
`/bin/systemctl restart movepiston`;
|
695 |
|
|
}
|
696 |
|
|
# Reload cgroups
|
697 |
|
|
elsif ($task_1 eq "CGLOAD") {
|
698 |
|
|
setCgroups();
|
699 |
|
|
$cgset = 1;
|
700 |
|
|
}
|
701 |
|
|
elsif ($task_1 eq "SLEEPAFTER") {
|
702 |
|
|
$sleepafter = int($task_2);
|
703 |
|
|
}
|
704 |
|
|
elsif ($task_1 eq "PERMITOPEN") {
|
705 |
|
|
if ($task_2) {
|
706 |
|
|
my $logentry = "$task_2: servers: : : Permitopen request received - updating allowed ssh forwards";
|
707 |
|
|
logit('info', $logentry);
|
708 |
|
|
# Ask piston.cgi to allow port forwards for user
|
709 |
|
|
my $newurl = $url . "&status=permitopen&user=$task_2";
|
710 |
|
|
my $newcontent = $browser->get($newurl)->content();
|
711 |
|
|
# Clear tasks list
|
712 |
|
|
#$newurl = $url ."&status=$status";
|
713 |
|
|
#$newcontent = $browser->get($newurl)->content();
|
714 |
|
|
}
|
715 |
|
|
}
|
716 |
|
|
elsif ($task_1 eq "DESTROY") {
|
717 |
|
|
$naptime = 1; # Temporarily speed up in order to report back promptly
|
718 |
|
|
# uuid ~ $task_2, user ~ $task_3
|
719 |
|
|
my $logentry = "$task_3: servers: $task_2: destroying: Destroy request received";
|
720 |
|
|
logit('info', $logentry);
|
721 |
|
|
my $dom;
|
722 |
|
|
eval {$dom = $vmm->get_domain_by_uuid($task_2);} or do {print $@;};
|
723 |
|
|
# $dom->destroy();
|
724 |
|
|
my $virshcmd = "virsh -c $virshemu:///system destroy $task_2";
|
725 |
|
|
# status is set to -- to prevent redundant UI update from piston.cgi
|
726 |
|
|
my $nurl = $url . "&status=--&logentry=" . uri_escape($logentry);
|
727 |
|
|
my $newcontent = $browser->get($nurl)->content();
|
728 |
|
|
$mortuary{$task_2} = 'destroying';
|
729 |
|
|
store \%mortuary, $tombstones;
|
730 |
|
|
run_in_bg($virshcmd) if ($dom);
|
731 |
|
|
# status is set to -- to prevent redundant UI update from piston.cgi
|
732 |
|
|
$url .= "&status=--";
|
733 |
|
|
my $newcontent = $browser->get($url)->content();
|
734 |
|
|
}
|
735 |
|
|
elsif ($task_1 eq "SHUTDOWN") {
|
736 |
|
|
$naptime = 1; # Temporarily speed up in order to report back promptly
|
737 |
|
|
my $logentry = "$task_3: servers: $task_2: shuttingdown: Shutdown request received";
|
738 |
|
|
logit('info', $logentry);
|
739 |
|
|
#my $virshcmd = `echo 'qemu-monitor-command --hmp $task_2 "system_powerdown"' | virsh -c $virshemu:///system`;
|
740 |
|
|
#print $virshcmd,"\n";
|
741 |
|
|
#my $virshcmd = "/usr/bin/sudo -u irigo /usr/bin/ssh localhost virsh -c $virshemu:///system shutdown $task_2";
|
742 |
|
|
my $dom;
|
743 |
|
|
eval {$dom = $vmm->get_domain_by_uuid($task_2);} or do {print $@;};
|
744 |
|
|
#$dom->shutdown();
|
745 |
|
|
#sleep 2;
|
746 |
|
|
|
747 |
|
|
my $virshcmd = "virsh -c $virshemu:///system shutdown $task_2";
|
748 |
|
|
my $nurl = $url . "&status=--&logentry=" . uri_escape($logentry);
|
749 |
|
|
my $newcontent = $browser->get($nurl)->content();
|
750 |
|
|
$mortuary{$task_2} = 'shuttingdown';
|
751 |
|
|
store \%mortuary, $tombstones;
|
752 |
|
|
run_in_bg($virshcmd) if ($dom);
|
753 |
|
|
$url .= "&status=--";
|
754 |
|
|
my $newcontent = $browser->get($url)->content();
|
755 |
|
|
}
|
756 |
|
|
elsif ($task_1 eq "SUSPEND") {
|
757 |
|
|
$naptime = 1; # Temporarily speed up in order to report back promptly
|
758 |
|
|
my $logentry = "$task_3: servers: $task_2: suspending: Suspend request received";
|
759 |
|
|
logit('info', $logentry);
|
760 |
|
|
my $virshcmd = "virsh -c $virshemu:///system suspend $task_2";
|
761 |
|
|
run_in_bg($virshcmd);
|
762 |
|
|
$url .= "&status=--&logentry=" . uri_escape($logentry);
|
763 |
|
|
my $newcontent = $browser->get($url)->content();
|
764 |
|
|
}
|
765 |
|
|
elsif ($task_1 eq "RESUME") {
|
766 |
|
|
$naptime = 1; # Temporarily speed up in order to report back promptly
|
767 |
|
|
my $logentry = "$task_3: servers: $task_2: resuming: Resume request received";
|
768 |
|
|
logit('info', $logentry);
|
769 |
|
|
my $virshcmd = "virsh -c $virshemu:///system resume $task_2";
|
770 |
|
|
run_in_bg($virshcmd);
|
771 |
|
|
$url .= "&status=--&logentry=" . uri_escape($logentry);
|
772 |
|
|
my $newcontent = $browser->get($url)->content();
|
773 |
|
|
}
|
774 |
|
|
elsif ($task_1 eq "MOUNT") {
|
775 |
|
|
$naptime = 1; # Temporarily speed up in order to report back promptly
|
776 |
|
|
my $user = $task_3;
|
777 |
|
|
my $cdrom = $tasks[3];
|
778 |
|
|
my $logentry ="$user: servers: $task_2: mounting: Mount request received - $cdrom" .
|
779 |
|
|
($cdrom eq "--"?"unmounting cdrom":"mounting $cdrom");
|
780 |
|
|
logit('info', $logentry);
|
781 |
|
|
if ($cdrom eq "--") {
|
782 |
|
|
$pid = fork();
|
783 |
|
|
unless ($pid) {
|
784 |
|
|
eval {
|
785 |
|
|
if ($identity eq "vbox") {
|
786 |
|
|
my $vboxcmd = qq|VBoxManage storageattach $task_2 --storagectl "IDE Controller" --port 1 --device 0 --type dvddrive --medium emptydrive --forceunmount|;
|
787 |
|
|
print `$virshcmd`,"\n";
|
788 |
|
|
1;
|
789 |
|
|
} else {
|
790 |
|
|
# my $dom = $vmm->get_domain_by_uuid($muuid);
|
791 |
|
|
# $dom->attach_device();
|
792 |
|
|
my $virshcmd = `virsh -c $virshemu:///system attach-device $task_2 $tenderpathslist[0]/ejectcdrom.xml`;
|
793 |
|
|
print `$virshcmd`,"\n";
|
794 |
|
|
1;
|
795 |
|
|
}
|
796 |
|
|
} or do {print $@;};
|
797 |
|
|
}
|
798 |
|
|
} elsif ($cdrom eq "virtio") {
|
799 |
|
|
$pid = fork();
|
800 |
|
|
unless ($pid) {
|
801 |
|
|
eval {
|
802 |
|
|
my $virshcmd = qq|virsh -c $virshemu:///system attach-device $task_2 $tenderpathslist[0]/mountvirtio.xml|;
|
803 |
|
|
print `$virshcmd`,"\n";
|
804 |
|
|
1;
|
805 |
|
|
} or do {print $@;};
|
806 |
|
|
}
|
807 |
|
|
} else {
|
808 |
|
|
$pid = fork();
|
809 |
|
|
unless ($pid) {
|
810 |
|
|
eval {
|
811 |
|
|
if ($identity eq "vbox") {
|
812 |
|
|
my $vboxcmd = qq|VBoxManage storageattach $task_2 --storagectl "IDE Controller" --port 1 --device 0 --type dvddrive --medium "$cdrom" --forceunmount|;
|
813 |
|
|
print `$virshcmd`,"\n";
|
814 |
|
|
1;
|
815 |
|
|
} else {
|
816 |
|
|
# my $dom = $vmm->get_domain_by_uuid($muuid);
|
817 |
|
|
# $dom->attach_disk();
|
818 |
|
|
my $virshcmd = qq{echo 'attach-disk $task_2 "$cdrom" hdd --mode readonly --driver file --type cdrom' | virsh -c $virshemu:///system};
|
819 |
|
|
print `$virshcmd`,"\n";
|
820 |
|
|
1;
|
821 |
|
|
}
|
822 |
|
|
} or do {print $@;};
|
823 |
|
|
}
|
824 |
|
|
}
|
825 |
|
|
chop $@; $logentry .= "\n$@" if $@;
|
826 |
|
|
$url .= "&status=--";
|
827 |
|
|
my $newcontent = $browser->get($url)->content();
|
828 |
|
|
}
|
829 |
|
|
elsif ($task_1 eq "BACKUP") {
|
830 |
|
|
my $user = $task_2;
|
831 |
|
|
my $uistatus = $task_3;
|
832 |
|
|
my $status = $tasks[3];
|
833 |
|
|
my $path = $tasks[4];
|
834 |
|
|
my $backupdir = $tasks[5];
|
835 |
|
|
my $remolder = $tasks[6];
|
836 |
|
|
my $targetdir = "$mainvalve\:\:$backupdir";
|
837 |
|
|
logit("info", "Backup request received $user $uistatus $status \"$path\" \"$targetdir\" $remolder");
|
838 |
|
|
eval {
|
839 |
|
|
#`/usr/local/sbin/movepiston command=backup $user $uistatus $status "$path" "$targetdir" &`;
|
840 |
|
|
|
841 |
|
|
# my $pid = exec(qq{/usr/local/sbin/movepiston command=backup $user $uistatus $status "$path" "$targetdir" &});
|
842 |
|
|
|
843 |
|
|
#my $daemon = Proc::Daemon->new(
|
844 |
|
|
# child_STDOUT => STDOUT,
|
845 |
|
|
# child_STDERR => STDERR,
|
846 |
|
|
# work_dir => '/usr/local/sbin',
|
847 |
|
|
# exec_command => "/usr/local/sbin/movepiston command=backup $user $uistatus $status \"$path\" \"$targetdir\""
|
848 |
|
|
# ) or do {logit("info", "ERROR doing backup of $path $@")};
|
849 |
|
|
#my $pid = $daemon->Init() or do {logit("info", "ERROR performing backup of $path $@")};
|
850 |
|
|
|
851 |
|
|
# Line below is the only variant that does not terminate movepiston - not sure why...
|
852 |
|
|
# my $backupcmd = qq{/usr/local/sbin/movepiston command=backup $user $uistatus $status "$path" "$targetdir" $remolder &};
|
853 |
|
|
# my $pid = system($backupcmd);
|
854 |
|
|
my $backupcmd = qq{$user $uistatus $status "$path" "$targetdir" $remolder};
|
855 |
|
|
my $backuptasks = "backup." . time;
|
856 |
|
|
`echo '$backupcmd' >> /tmp/$backuptasks`;
|
857 |
|
|
sleep 1;
|
858 |
|
|
my $pid = system(qq{/usr/local/sbin/movepiston command=$backuptasks &});
|
859 |
|
|
1;
|
860 |
|
|
} or do {print "Error! ", $@;};
|
861 |
|
|
logit("info", "Backup of \"$path\" running...");
|
862 |
|
|
}
|
863 |
|
|
elsif ($task_1 eq "MOVE") {
|
864 |
|
|
my $vm = $task_2;
|
865 |
|
|
my $targethost = $task_3;
|
866 |
|
|
my $targetmac = $tasks[3];
|
867 |
|
|
my $user = $tasks[4];
|
868 |
|
|
my $logentry = "$nmac: servers: $task_2: moving: Now moving to $targethost...";
|
869 |
|
|
logit('info', $logentry);
|
870 |
|
|
my $newurl = $url . "&status=--&logentry=" . uri_escape($logentry);
|
871 |
|
|
my $newcontent = $browser->get($newurl)->content();
|
872 |
|
|
|
873 |
|
|
if ($identity eq "vbox") {
|
874 |
|
|
changeHosts($targethost, "piston$targetmac") or
|
875 |
|
|
$logentry = "$user: servers: /etc/hosts could not be updated\n".$@."\n"; # probably only needed for KVM but...
|
876 |
|
|
eval {
|
877 |
|
|
my $cmd = "/usr/bin/VBoxManage controlvm $vm teleport --host $targethost --port 6000";
|
878 |
|
|
run_in_bg($cmd);
|
879 |
|
|
1;
|
880 |
|
|
} or do {$logentry = "$user: Servers: " . "\n".$@."\n";};
|
881 |
|
|
} else {
|
882 |
|
|
changeHosts($targethost, "piston$targetmac") or
|
883 |
|
|
$logentry = "$user: servers: /etc/hosts could not be updated\n".$@."\n"; # probably only needed for KVM but...
|
884 |
|
|
my $uriport = 15900 + int(rand(200)); # Choose a random port for live migration
|
885 |
2a63870a
|
Christian Orellana
|
my $cmd = "sudo -u irigo virsh -c qemu:///system migrate --migrateuri tcp://$targethost:$uriport --live --unsafe $vm qemu+ssh://$targethost/system";
|
886 |
95b003ff
|
Origo
|
logit('info', $cmd);
|
887 |
|
|
run_in_bg($cmd);
|
888 |
|
|
}
|
889 |
|
|
#eval { # We do not want the same domain reported in different states from two different nodes
|
890 |
|
|
# my $dom = $vmm->get_domain_by_uuid($vm);
|
891 |
|
|
# if ($dom) {$dom->undefine()};
|
892 |
|
|
# 1;
|
893 |
|
|
#} or do {print $@;};
|
894 |
|
|
}
|
895 |
|
|
elsif ($task_1 eq "RECEIVE") {
|
896 |
|
|
my $uuid = $task_2; my $user = $task_3;
|
897 |
|
|
my $logentry = "$user: servers: $task_2: receiving: Receive domain request received";
|
898 |
|
|
logit('info', $logentry);
|
899 |
|
|
my $mounts = `cat /proc/mounts`;
|
900 |
|
|
for (my $i=0; $i<=$#tenderpathslist; $i++
|
901 |
|
|
)
|
902 |
|
|
{
|
903 |
|
|
my $path = $tenderpathslist[$i];
|
904 |
|
|
my $host = $tenderlist[$i];
|
905 |
|
|
# Directory / mount point must exist
|
906 |
|
|
unless (-d $path) {
|
907 |
|
|
mkdir "$path" or {print ("Error $path could not be created\n")};
|
908 |
|
|
};
|
909 |
|
|
unless ($mounts =~ m/$path/i || ($identity eq 'local_kvm' && $host =~ /10\.0\.0\.1/)) {
|
910 |
|
|
logit('info', "Mounting (2) $path from $host");
|
911 |
|
|
eval {print `mount -o intr,noatime,nfsvers=3 $host $path`; 1;} or do {print $@;};
|
912 |
|
|
}
|
913 |
|
|
}
|
914 |
|
|
|
915 |
|
|
my $xml = $browser->get($base_url . "?status=listxml&uuid=$uuid&mac=$mac")->content();
|
916 |
|
|
if ($xml =~ /<domain /i) {
|
917 |
|
|
print "Adding $uuid to move list\n" if ($debug);
|
918 |
|
|
push (@receiveuuids, $uuid);
|
919 |
|
|
eval { # Undefine domain in case it has been running here before
|
920 |
|
|
my $dom = $vmm->get_domain_by_uuid($task_2);
|
921 |
|
|
if ($dom) {$dom->undefine()};
|
922 |
|
|
1;
|
923 |
|
|
} or do {print $@;};
|
924 |
|
|
logit('info', "Defining $task_2");
|
925 |
|
|
# print $xml if ($debug);
|
926 |
|
|
|
927 |
|
|
# Add bridge interfaces
|
928 |
|
|
eval {print `modprobe 8021q`; 1;} or do {print $@;};
|
929 |
|
|
eval {print `ifconfig $datanic up`; 1;} or do {print $@;};
|
930 |
|
|
if ($xml =~ /<interface type=\'bridge\'/i
|
931 |
|
|
)
|
932 |
|
|
{
|
933 |
|
|
my $char = "<source bridge=";
|
934 |
|
|
my $offset = 0;
|
935 |
|
|
my $result = index($xml, $char, $offset);
|
936 |
|
|
while ($result != -1) {
|
937 |
|
|
my $br = substr($xml, $result+18, 5);
|
938 |
|
|
if ($br =~ /(\d+)/) {
|
939 |
|
|
$br = $1;
|
940 |
|
|
$logentry .= " - bringing up bridge br $br on $datanic";
|
941 |
|
|
eval {print `vconfig add $datanic $br`; 1;} or do {print $@;};
|
942 |
|
|
eval {print `brctl addbr br$br`; 1;} or do {print $@;};
|
943 |
|
|
eval {print `brctl stp br$br on`; 1;} or do {print $@;};
|
944 |
|
|
eval {print `brctl addif br$br $datanic.$br`; 1;} or do {print $@;};
|
945 |
|
|
eval {print `ifconfig $datanic.$br up`; 1;} or do {print $@;};
|
946 |
|
|
eval {print `ifconfig br$br up`; 1;} or do {print $@;};
|
947 |
|
|
}
|
948 |
|
|
$offset = $result + 1;
|
949 |
|
|
$result = index($xml, $char, $offset);
|
950 |
|
|
}
|
951 |
|
|
}
|
952 |
|
|
|
953 |
|
|
chop $@; $logentry .= "\n$br : $@" if $@;
|
954 |
|
|
if ($identity eq "vbox") { # vbox domains need to be defined on the receiving end
|
955 |
|
|
eval {
|
956 |
|
|
my $dom = $vmm->define_domain($xml);
|
957 |
|
|
logit ('info', "Defined: " + $dom);
|
958 |
|
|
1;
|
959 |
|
|
} or do {print $@;};
|
960 |
|
|
if ($@) {chop $@; $logentry .= "\n$@";}
|
961 |
|
|
# $logentry .= $dom;
|
962 |
|
|
my $res;
|
963 |
|
|
eval {$res = `/usr/bin/VBoxManage modifyvm $task_2 --teleporter on --teleporterport 6000`; 1;} or
|
964 |
|
|
do {$logentry .= "\n$user: servers: ".$res."\n".$@;};
|
965 |
|
|
eval {$res = `/usr/bin/VBoxManage startvm $task_2 --type vrdp`; 1;} or
|
966 |
|
|
do {$logentry .= "\n$user: servers: ".$res."\n".$@;};
|
967 |
|
|
} else {
|
968 |
|
|
;
|
969 |
|
|
}
|
970 |
|
|
} else {
|
971 |
|
|
$logentry .= "\n$user: servers: Invalid domain xml...";
|
972 |
|
|
}
|
973 |
|
|
}
|
974 |
|
|
elsif ($task_1 eq "BCLONE") {
|
975 |
|
|
my $user = $task_3;
|
976 |
|
|
my $image = uri_unescape($task_2);
|
977 |
|
|
my $logentry = "$user: images: $image: cloning: Clone request received";
|
978 |
|
|
logit('info', $logentry);
|
979 |
|
|
my $master = $browser->get($base_url . "?status=listimagemaster&image=$task_2")->content();
|
980 |
|
|
if ($master) {
|
981 |
|
|
$master = uri_unescape($master);
|
982 |
|
|
$logentry = "Cloning $image from $master ";
|
983 |
|
|
$image =~ /(.+)\/.*/;
|
984 |
|
|
my $dir = $1;
|
985 |
6fdc8676
|
hq
|
unless (-e $dir) {
|
986 |
|
|
`/bin/mkdir -p "$dir"`;
|
987 |
|
|
`chmod 777 "$dir"`;
|
988 |
|
|
}
|
989 |
95b003ff
|
Origo
|
my $cmd = qq|/usr/bin/qemu-img create -f qcow2 -b "$master" "$image"|;
|
990 |
|
|
$logentry .= `$cmd`;
|
991 |
|
|
$logentry =~ tr/\n/ /;
|
992 |
|
|
logit('info', $logentry);
|
993 |
|
|
} else {
|
994 |
|
|
logit('info', "Master for $image not found $master");
|
995 |
|
|
}
|
996 |
|
|
}
|
997 |
|
|
elsif ($task_1 eq "DROWSE") {
|
998 |
|
|
drowse('', 1);
|
999 |
|
|
}
|
1000 |
|
|
elsif ($task_1 eq "REMOVE") {
|
1001 |
|
|
my $user = $task_3;
|
1002 |
|
|
my $image = uri_unescape($task_2);
|
1003 |
|
|
my $logentry = "$user: images: $image: removing: Remove image request received";
|
1004 |
|
|
logit('info', $logentry);
|
1005 |
|
|
$logengry = "Removed image $image " . unlink($image);
|
1006 |
|
|
logit('info', $logentry);
|
1007 |
|
|
}
|
1008 |
|
|
elsif ($task_1 eq "PREMOVE") { # preserve backup
|
1009 |
|
|
my $user = $task_3;
|
1010 |
|
|
my $image = uri_unescape($task_2);
|
1011 |
|
|
my $logentry = "$user: images: $image: removing: Premove image request received";
|
1012 |
|
|
logit('info', $logentry);
|
1013 |
|
|
$logengry = "Removed image $image (preserved) " . `mv "$image" "$image.bak"`;
|
1014 |
|
|
logit('info', $logentry);
|
1015 |
|
|
}
|
1016 |
|
|
elsif ($task_1 eq "START") {
|
1017 |
|
|
$naptime = 1; # Temporarily speed up in order to report back promptly
|
1018 |
|
|
my $user = $task_3;
|
1019 |
|
|
my $logentry = "$user: servers: $task_2: starting: Start request received";
|
1020 |
|
|
logit('info', $logentry);
|
1021 |
|
|
|
1022 |
|
|
my $mounts = `cat /proc/mounts`;
|
1023 |
|
|
for (my $i=0; $i<=$#tenderpathslist; $i++
|
1024 |
|
|
)
|
1025 |
|
|
{
|
1026 |
|
|
my $path = $tenderpathslist[$i];
|
1027 |
|
|
my $host = $tenderlist[$i];
|
1028 |
|
|
# Directory / mount point must exist
|
1029 |
|
|
unless (-d $path) {
|
1030 |
|
|
mkdir "$path" or {print ("Error $path could not be created\n")};
|
1031 |
|
|
};
|
1032 |
|
|
if ($mounts =~ m/$path /i || ($identity eq 'local_kvm' && $host =~ /10\.0\.0\.1/)) {
|
1033 |
|
|
print ("$path already mounted\n") if ($debug);
|
1034 |
|
|
} else {
|
1035 |
|
|
logit('info', "Mounting (3) $path from $host");
|
1036 |
|
|
eval {print `mount -o intr,noatime,nfsvers=3 $host $path`; 1;} or do {print $@;};
|
1037 |
|
|
}
|
1038 |
|
|
}
|
1039 |
|
|
my $xml = $browser->get($base_url . "?status=listxml&uuid=$task_2&mac=$mac")->content();
|
1040 |
|
|
if ($xml =~ /<domain /i) {
|
1041 |
|
|
logit('info', "Creating $task_2");
|
1042 |
|
|
unless ($identity eq "local_kvm") {
|
1043 |
|
|
# Add bridge interfaces
|
1044 |
|
|
eval {print `modprobe 8021q`; 1;} or do {print $@;};
|
1045 |
|
|
eval {print `ifconfig $datanic up`; 1;} or do {print $@;};
|
1046 |
|
|
if ($xml =~ /<interface type=\'bridge\'/i) {
|
1047 |
|
|
my $char = "<source bridge=";
|
1048 |
|
|
my $offset = 0;
|
1049 |
|
|
my $result = index($xml, $char, $offset);
|
1050 |
|
|
while ($result != -1) {
|
1051 |
|
|
my $br = substr($xml, $result+18, 5);
|
1052 |
|
|
if ($br =~ /(\d+)/) {
|
1053 |
|
|
$br = $1;
|
1054 |
|
|
$logentry .= " - bringing up bridge br$br on $datanic ";
|
1055 |
|
|
eval {print `vconfig add $datanic $br`; 1;} or do {print $@;};
|
1056 |
|
|
eval {print `brctl addbr br$br`; 1;} or do {print $@;};
|
1057 |
|
|
eval {print `brctl stp br$br on`; 1;} or do {print $@;};
|
1058 |
|
|
eval {print `brctl addif br$br $datanic.$br`; 1;} or do {print $@;};
|
1059 |
|
|
eval {print `ifconfig $datanic.$br up`; 1;} or do {print $@;};
|
1060 |
|
|
eval {print `ifconfig br$br up`; 1;} or do {print $@;};
|
1061 |
|
|
}
|
1062 |
|
|
print $logentry if ($debug);
|
1063 |
|
|
$offset = $result + 1;
|
1064 |
|
|
$result = index($xml, $char, $offset);
|
1065 |
|
|
}
|
1066 |
|
|
}
|
1067 |
|
|
chop $@; $logentry .= " -- $br : $@" if $@;
|
1068 |
|
|
}
|
1069 |
|
|
|
1070 |
|
|
eval {
|
1071 |
|
|
my $domid = `virsh -c $virshemu:///system domid $task_2`;
|
1072 |
|
|
my $virshcmd = "virsh -c $virshemu:///system undefine $domid";
|
1073 |
|
|
print `$virshcmd` if ($domid);
|
1074 |
|
|
1;
|
1075 |
|
|
} or do {
|
1076 |
|
|
;# print $@;
|
1077 |
|
|
};
|
1078 |
|
|
|
1079 |
|
|
if ($xml=~/<source file=\'(.+)\'/i
|
1080 |
|
|
&& -s $1)
|
1081 |
|
|
{
|
1082 |
|
|
eval {
|
1083 |
|
|
if ($xml =~ /<hostdev /i) {
|
1084 |
|
|
# `modprobe pci_stub`;
|
1085 |
|
|
# `echo "10de 1b81" > /sys/bus/pci/drivers/pci-stub/new_id`;
|
1086 |
|
|
# `echo "0000:01:00.0" > /sys/bus/pci/devices/0000:01:00.0/driver/unbind; echo "0000:01:00.0" > /sys/bus/pci/drivers/pci-stub/bind`;
|
1087 |
|
|
# `echo "0000:02:00.0" > /sys/bus/pci/devices/0000:02:00.0/driver/unbind; echo "0000:02:00.0" > /sys/bus/pci/drivers/pci-stub/bind`;
|
1088 |
|
|
# `echo 1 > /sys/bus/pci/devices/0000:01:00.1/remove`;
|
1089 |
|
|
# `echo 1 > /sys/bus/pci/devices/0000:02:00.1/remove`;
|
1090 |
|
|
|
1091 |
|
|
# `echo "0000:01:00.1" > /sys/bus/pci/devices/0000:01:00.1/driver/unbind; echo "0000:01:00.1" > /sys/bus/pci/drivers/pci-stub/bind`;
|
1092 |
|
|
# `echo "0000:02:00.1" > /sys/bus/pci/devices/0000:02:00.1/driver/unbind; echo "0000:02:00.1" > /sys/bus/pci/drivers/pci-stub/bind`;
|
1093 |
|
|
}
|
1094 |
|
|
print "Defining domain from:\n$xml\n" if ($debug);
|
1095 |
|
|
print `echo "$xml" > /tmp/$task_2.xml`;
|
1096 |
|
|
my $virshcmd = "virsh -c $virshemu:///system create /tmp/$task_2.xml";
|
1097 |
|
|
run_in_bg( $virshcmd );
|
1098 |
|
|
logit ('info', "Created: $task_2");
|
1099 |
|
|
$logentry .= " - Created: $task_2" ;
|
1100 |
|
|
1;
|
1101 |
|
|
} or do {print "Error: " . $@;};
|
1102 |
|
|
if ($@) {
|
1103 |
|
|
chop $@; $logentry .= "\n$@";
|
1104 |
|
|
# $returntasks = uri_escape("START $task_2 $user"); # START did not succeed - return it to try again
|
1105 |
|
|
}
|
1106 |
|
|
} else {
|
1107 |
|
|
logit ('info', "Image $1 not found creating: $task_2");
|
1108 |
|
|
$logentry .= " - Image $1 not found creating: $task_2" ;
|
1109 |
|
|
}
|
1110 |
|
|
} else {
|
1111 |
|
|
$logentry .= " - $user: servers: Invalid domain xml...";
|
1112 |
|
|
}
|
1113 |
|
|
my $rtasks = $returntasks?"returntasks=$returntasks":'';
|
1114 |
|
|
my $newurl = $url . "&status=--&logentry=". uri_escape($logentry) . $rtasks;
|
1115 |
|
|
my $newcontent = $browser->get($newurl)->content();
|
1116 |
|
|
} elsif ($task_1 ne "OK") {
|
1117 |
|
|
my $logentry = "--: --: Info not accepted: $task_1 - $task_2 - $task_3";
|
1118 |
|
|
logit('debug', $logentry);
|
1119 |
|
|
}
|
1120 |
|
|
}
|
1121 |
|
|
if (@receiveuuids) {
|
1122 |
|
|
$url .= "&receive=" . uri_escape(join(',', @receiveuuids)) . "&status=--";
|
1123 |
|
|
logit('info', "Asking to send me: " . join(',', @receiveuuids) . " $url ") if ($debug);
|
1124 |
|
|
my $newcontent = $browser->get($url)->content();
|
1125 |
|
|
}
|
1126 |
|
|
} else {
|
1127 |
|
|
logit('info', "Couldn't get: $url");
|
1128 |
|
|
}
|
1129 |
|
|
if ($pid) {return "";}
|
1130 |
|
|
else {return $running;}
|
1131 |
|
|
}
|
1132 |
|
|
|
1133 |
|
|
sub logit {
|
1134 |
|
|
my ($priority, $msg) = @_;
|
1135 |
|
|
if ($priority =~ /info|err/ || $debug) {print pretty_time(), ": ", $priority, ": ", $msg, "\n"};
|
1136 |
|
|
|
1137 |
|
|
setlogsock('unix');
|
1138 |
|
|
# Log the PID and to CONSole if there's a problem. Use facility 'user'.
|
1139 |
|
|
openlog(basename($0), 'pid,cons', 'user');
|
1140 |
|
|
syslog($priority, "$nmac: $msg");
|
1141 |
|
|
closelog();
|
1142 |
|
|
}
|
1143 |
|
|
|
1144 |
|
|
sub dominfo {
|
1145 |
|
|
my $vmm = shift;
|
1146 |
|
|
my $domreq = ();
|
1147 |
|
|
$domreq->{'dominfo'} = 1;
|
1148 |
|
|
my @domains = $vmm->list_domains();
|
1149 |
|
|
my %activedoms;
|
1150 |
|
|
my $i = 0;
|
1151 |
|
|
if (!$cgset) {
|
1152 |
|
|
setCgroups();
|
1153 |
|
|
$cgset = 1;
|
1154 |
|
|
}
|
1155 |
|
|
|
1156 |
|
|
print "Looking at " . scalar @domains . " domains\n" if ($debug);
|
1157 |
|
|
foreach my $dom (@domains) {
|
1158 |
|
|
eval {
|
1159 |
|
|
my $xml = $dom->get_xml_description();
|
1160 |
|
|
my $domxml = XMLin($xml);
|
1161 |
|
|
my $display = $domxml->{devices}->{graphics}->{type};
|
1162 |
|
|
my $port = $domxml->{devices}->{graphics}->{port};
|
1163 |
|
|
my $domstate = $domstates[$dom->get_info->{ 'state' }];
|
1164 |
|
|
my $domuuid = $dom->get_uuid_string;
|
1165 |
|
|
$i++;
|
1166 |
|
|
$activedoms{$domuuid} = $domstate;
|
1167 |
|
|
# $dominfo .= "&dom$i=$domuuid&domstate$i=$domstate&domdisplay$i=" . $display . "&domport$i=" . $port;
|
1168 |
|
|
$domreq->{"dom$i"} = $domuuid;
|
1169 |
|
|
$domreq->{"domstate$i"} = $domstate;
|
1170 |
|
|
$domreq->{"domdisplay$i"} = $display;
|
1171 |
|
|
$domreq->{"domport$i"} = $port;
|
1172 |
|
|
|
1173 |
|
|
if (-e "/tmp/$domuuid.xml") {
|
1174 |
|
|
unlink "/tmp/$domuuid.xml";
|
1175 |
|
|
}
|
1176 |
|
|
|
1177 |
|
|
# If cgroups are enabled, put in values
|
1178 |
|
|
# We put in values in /mnt/cgroup/libvirt/qemu/ instead of for individual domains
|
1179 |
|
|
# if (-d '/mnt/' && -e '/proc/cgroups') {
|
1180 |
|
|
# if ($xml=~/<name>(.+)<\/name>/) {
|
1181 |
|
|
# my $domname = $1;
|
1182 |
|
|
# if (-e "/tmp/$domuuid.xml" && -d "/mnt/cgroup/libvirt/qemu/$domname/") {
|
1183 |
|
|
# logit('info', "Setting cgroups limits $readlimit/$writelimit, $iopsreadlimit/$iopswritelimit for $domuuid ($domname)");
|
1184 |
|
|
# `echo "8:0 $readlimit" > "/mnt/cgroup/libvirt/qemu/$domname/blkio.throttle.read_bps_device"`;
|
1185 |
|
|
# `echo "8:0 $writelimit" > "/mnt/cgroup/libvirt/qemu/$domname/blkio.throttle.write_bps_device"`;
|
1186 |
|
|
# `echo "8:0 $iopsreadlimit" > "/mnt/cgroup/libvirt/qemu/$domname/blkio.throttle.read_iops_device"`;
|
1187 |
|
|
# `echo "8:0 $iopswritelimit" > "/mnt/cgroup/libvirt/qemu/$domname/blkio.throttle.write_iops_device"`;
|
1188 |
|
|
# unlink "/tmp/$domuuid.xml";
|
1189 |
|
|
# }
|
1190 |
|
|
# } else {
|
1191 |
|
|
# logit('info', "Not setting cgroup limits for " . $dom->get_name() ) if ($debug);
|
1192 |
|
|
# }
|
1193 |
|
|
# }
|
1194 |
|
|
1;
|
1195 |
|
|
} or do {print $@;};
|
1196 |
|
|
|
1197 |
|
|
}
|
1198 |
|
|
@domains = $vmm->list_defined_domains();
|
1199 |
|
|
print "Looking at " . scalar @domains . " defined domains\n" if ($debug);
|
1200 |
|
|
foreach my $dom (@domains) {
|
1201 |
|
|
eval {
|
1202 |
|
|
my $domstate = $domstates[$dom->get_info->{ 'state' }];
|
1203 |
|
|
my $domuuid = $dom->get_uuid_string;
|
1204 |
|
|
if ($domstate ne "running") {
|
1205 |
|
|
$i++;
|
1206 |
|
|
$activedoms{$domuuid} = $domstate;
|
1207 |
|
|
$domreq->{"dom$i"} = $domuuid;
|
1208 |
|
|
$domreq->{"domstate$i"} = $domstate;
|
1209 |
|
|
}
|
1210 |
|
|
eval {
|
1211 |
|
|
if ($domstate eq "shutoff") {$dom->undefine()};
|
1212 |
|
|
1;
|
1213 |
|
|
} or do {print $@;};
|
1214 |
|
|
} or do {print $@;};
|
1215 |
|
|
}
|
1216 |
|
|
foreach my $domuuid (keys %mortuary) {
|
1217 |
|
|
unless ($activedoms{$domuuid}) {
|
1218 |
|
|
$i++;
|
1219 |
|
|
$domreq->{"dom$i"} = $domuuid;
|
1220 |
|
|
$domreq->{"domstate$i"} = 'shutoff';
|
1221 |
|
|
delete $mortuary{$domuuid};
|
1222 |
|
|
}
|
1223 |
|
|
}
|
1224 |
|
|
if (%mortuary) {
|
1225 |
|
|
store \%mortuary, $tombstones;
|
1226 |
|
|
} else {
|
1227 |
|
|
`> $tombstones` if (-e $tombstones && !(-z $tombstones));
|
1228 |
|
|
}
|
1229 |
|
|
return $domreq;
|
1230 |
|
|
}
|
1231 |
|
|
|
1232 |
|
|
sub drowse {
|
1233 |
|
|
my $vmm = shift;
|
1234 |
|
|
$vmm = Sys::Virt->new(address => "$virshemu:///system") unless $vmm;
|
1235 |
|
|
my $drowsenow = shift;
|
1236 |
|
|
|
1237 |
|
|
my @domains = $vmm->list_domains();
|
1238 |
|
|
my $i = 0;
|
1239 |
|
|
foreach my $dom (@domains) {
|
1240 |
|
|
if ($domstates[$dom->get_info->{ 'state' }] eq "running" || $domstates[$dom->get_info->{ 'state' }] eq "paused") {
|
1241 |
|
|
$i++;
|
1242 |
|
|
last;
|
1243 |
|
|
}
|
1244 |
|
|
}
|
1245 |
|
|
if ($i==0) {$drowsiness += $naptime} else {$drowsiness = 0};
|
1246 |
|
|
if (($sleepafter > 0 && $drowsiness > $sleepafter) || $drowsenow) {
|
1247 |
|
|
if ($identity eq "vbox") {
|
1248 |
|
|
logit('info', "Taking down Virtual Box piston");
|
1249 |
|
|
print `/etc/init.d/vboxdrv stop`,"\n";
|
1250 |
|
|
} else {
|
1251 |
|
|
logit('info', "Taking down KVM piston");
|
1252 |
|
|
print `/etc/init.d/kvm stop`,"\n";
|
1253 |
|
|
}
|
1254 |
|
|
$status = "drowsing";
|
1255 |
|
|
my $logentry = "--: nodes: $mac: $status: Feeling drowsy ($drowsiness > $sleepafter) - putting node to sleep";
|
1256 |
|
|
logit('info', $logentry);
|
1257 |
|
|
$running = 0;
|
1258 |
|
|
|
1259 |
|
|
my $meminfo = `cat /proc/meminfo`;
|
1260 |
|
|
$meminfo =~ m/MemTotal:\s*(.*) kB\n/i;
|
1261 |
|
|
my $memtotal = $1;
|
1262 |
|
|
$meminfo =~ m/MemFree:\s*(.*) kB\n/i;
|
1263 |
|
|
my $memfree = $1;
|
1264 |
|
|
|
1265 |
|
|
my $url = $base_url . "?mac=" . uri_escape($mac);
|
1266 |
|
|
$url .= "&status=$status&logentry=" . uri_escape($logentry) ."&memtotal=$memtotal&memfree=$memfree&identity=$identity";
|
1267 |
|
|
`umount -a`;
|
1268 |
|
|
my $newcontent = $browser->get($url)->content();
|
1269 |
|
|
my @clines = split /\n/, $newcontent;
|
1270 |
|
|
foreach my $line (@clines) {
|
1271 |
|
|
if ($line =~ m/^\S+=SWEETDREAMS/ig) {
|
1272 |
|
|
print "Awating power off...\n";
|
1273 |
|
|
return;
|
1274 |
|
|
}
|
1275 |
|
|
}
|
1276 |
|
|
|
1277 |
|
|
$meminfo = `cat /proc/acpi/sleep`;
|
1278 |
|
|
my $s3sleep = ($meminfo =~ m/S3/);
|
1279 |
|
|
if ($s3sleep) {
|
1280 |
|
|
print `/etc/init.d/libvirt-bin stop`,"\n" if ($identity eq "vbox");
|
1281 |
|
|
print `/etc/acpi/sleep.sh`;
|
1282 |
|
|
} else {
|
1283 |
2a63870a
|
Christian Orellana
|
print `systemctl stop movepiston`;
|
1284 |
95b003ff
|
Origo
|
`echo 0 > /proc/sys/kernel/hung_task_timeout_secs`;
|
1285 |
|
|
print `poweroff`;
|
1286 |
|
|
# print `/sbin/shutdown -P +1`;
|
1287 |
|
|
}
|
1288 |
|
|
};
|
1289 |
|
|
}
|
1290 |
|
|
|
1291 |
|
|
sub changeHosts {
|
1292 |
|
|
my $hosts = "/etc/hosts";
|
1293 |
|
|
my $targetip = $_[0];
|
1294 |
|
|
my $targetname = $_[1];
|
1295 |
|
|
return 0 unless ($targetip && $targetname);
|
1296 |
|
|
copy($hosts, "$hosts.bak") or return 0;
|
1297 |
|
|
|
1298 |
|
|
my $newfile = "";
|
1299 |
|
|
my $match;
|
1300 |
|
|
open (FILE, $hosts);
|
1301 |
|
|
while (<FILE>) {
|
1302 |
|
|
chomp;
|
1303 |
|
|
my $line = $_;
|
1304 |
|
|
$newfile .= "$line\n" unless ($line =~ /^$targetip/);
|
1305 |
|
|
}
|
1306 |
|
|
$newfile .= "$targetip $targetname";
|
1307 |
|
|
close (FILE);
|
1308 |
|
|
open( FILE, ">$hosts" ) or return 0;
|
1309 |
|
|
print FILE $newfile;
|
1310 |
|
|
close(FILE);
|
1311 |
|
|
return "$hosts updated\n";
|
1312 |
|
|
}
|
1313 |
|
|
|
1314 |
|
|
sub pretty_time {
|
1315 |
|
|
my $current_time = time;
|
1316 |
|
|
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($current_time);
|
1317 |
|
|
my $pretty_time = sprintf "%4d-%02d-%02d@%02d:%02d:%02d",$year+1900,$mon+1,$mday,$hour,$min,$sec;
|
1318 |
|
|
return $pretty_time;
|
1319 |
|
|
}
|
1320 |
|
|
|
1321 |
|
|
sub recurse {
|
1322 |
|
|
my($path) = shift; # @_;
|
1323 |
|
|
my @files;
|
1324 |
|
|
## append a trailing / if it's not there
|
1325 |
|
|
$path .= '/' if($path !~ /\/$/);
|
1326 |
|
|
## loop through the files contained in the directory
|
1327 |
|
|
for my $eachFile (glob($path.'*')) {
|
1328 |
|
|
## if the file is a directory
|
1329 |
|
|
if( -d $eachFile) {
|
1330 |
|
|
## pass the directory to the routine ( recursion )
|
1331 |
|
|
push(@files,recurse($eachFile));
|
1332 |
|
|
} else {
|
1333 |
|
|
push(@files,$eachFile);
|
1334 |
|
|
}
|
1335 |
|
|
}
|
1336 |
|
|
return @files;
|
1337 |
|
|
}
|
1338 |
|
|
|
1339 |
|
|
sub getSizes {
|
1340 |
|
|
my $f = shift;
|
1341 |
|
|
my $lmtime = shift;
|
1342 |
|
|
|
1343 |
|
|
#print "$f :";
|
1344 |
|
|
my @stat = stat($f);
|
1345 |
|
|
my $size = $stat[7];
|
1346 |
|
|
my $realsize = $stat[12] * 512;
|
1347 |
|
|
my $virtualsize = $size;
|
1348 |
|
|
my $mtime = $stat[9];
|
1349 |
|
|
# Only fire up qemu-img etc. if image has been modified
|
1350 |
|
|
#print " $lmtime : $mtime\n";
|
1351 |
|
|
if ($mtime ne $lmtime) {
|
1352 |
|
|
my($fname, $dirpath, $suffix) = fileparse($f, (".vmdk", ".img", ".vhd", ".qcow", ".qcow2", ".vdi", ".iso"));
|
1353 |
|
|
# Special handling of vmdk's
|
1354 |
|
|
if ($suffix eq ".vmdk") {
|
1355 |
3657de20
|
Origo
|
my $qinfo = `/usr/bin/qemu-img info --force-share "$f"`;
|
1356 |
95b003ff
|
Origo
|
$qinfo =~ /virtual size:.*\((.+) bytes\)/g;
|
1357 |
|
|
$virtualsize = int($1);
|
1358 |
|
|
if ( -s ($dirpath . $fname . "-flat" . $suffix)) {
|
1359 |
|
|
my @fstatus = stat($dirpath . $fname . "-flat" . $suffix);
|
1360 |
|
|
my $fsize = $fstatus[7];
|
1361 |
|
|
my $frealsize = $fstatus[12] * 512;
|
1362 |
|
|
$size += $fsize;
|
1363 |
|
|
$virtualsize += $fsize;
|
1364 |
|
|
$realsize += $frealsize;
|
1365 |
|
|
}
|
1366 |
|
|
my $i = 1;
|
1367 |
|
|
while (@fstatus = stat($dirpath . $fname . "-s00$i" . $suffix)) {
|
1368 |
|
|
$fsize = $fstatus[7];
|
1369 |
|
|
$frealsize = $fstatus[12] * 512;
|
1370 |
|
|
$size += $fsize;
|
1371 |
|
|
$virtualsize += $fsize;
|
1372 |
|
|
$realsize += $frealsize;
|
1373 |
|
|
$i++;
|
1374 |
|
|
}
|
1375 |
|
|
# Get virtual size of qcow2 auto-grow volumes
|
1376 |
|
|
} elsif ($suffix eq ".qcow2") {
|
1377 |
3657de20
|
Origo
|
my $qinfo = `/usr/bin/qemu-img info --force-share "$f"`;
|
1378 |
95b003ff
|
Origo
|
$qinfo =~ /virtual size:.*\((.+) bytes\)/g;
|
1379 |
|
|
$virtualsize = int($1);
|
1380 |
|
|
# Get virtual size of vdi auto-grow volumes
|
1381 |
|
|
} elsif ($suffix eq ".vdi") {
|
1382 |
|
|
my $qinfo = `/usr/bin/VBoxManage showhdinfo "$f"`;
|
1383 |
|
|
$qinfo =~ /Logical size:\s*(\d+) MBytes/g;
|
1384 |
|
|
$virtualsize = int($1) * 1024 * 1024;
|
1385 |
|
|
}
|
1386 |
|
|
# Actual used blocks times block size on disk, i.e. $realsize may be bigger than the
|
1387 |
|
|
# logical size of the image file $virtualsize and the logical provisioned size of the disk $virtualsize
|
1388 |
|
|
# in order to minimize confusion, we set $realsize to $size if this is the case
|
1389 |
|
|
$realsize = $size if ($realsize > $size);
|
1390 |
|
|
return ($size, $realsize, $virtualsize, $mtime);
|
1391 |
|
|
} else {
|
1392 |
|
|
return 0;
|
1393 |
|
|
}
|
1394 |
|
|
|
1395 |
|
|
}
|
1396 |
|
|
|
1397 |
|
|
sub updatePistonStats {
|
1398 |
|
|
my $vmm = shift;
|
1399 |
|
|
logit('info', "Updating domain statistics...") if $debug == 1;
|
1400 |
|
|
|
1401 |
|
|
# Connect to libvirt...
|
1402 |
|
|
$vmm = Sys::Virt->new(address => "$virshemu:///system") unless $vmm;
|
1403 |
|
|
my @domains = $vmm->list_domains();
|
1404 |
|
|
my $postreq = ();
|
1405 |
|
|
my $i = 0;
|
1406 |
|
|
# Loop through all local domains...
|
1407 |
|
|
foreach my $dom (@domains) {
|
1408 |
|
|
$i++;
|
1409 |
|
|
print "\tProcessing '",$dom->get_name(),"' [",$dom->get_uuid_string(),"]...\n" if $debug;
|
1410 |
|
|
# my ($timestamp_seconds, $timestamp_microseconds_decimals) = gettimeofday();
|
1411 |
|
|
my $timestamp_useconds = Time::HiRes::time();
|
1412 |
|
|
my $timestamp_seconds = floor($timestamp_useconds);
|
1413 |
|
|
my $uuid = $dom->get_uuid_string();
|
1414 |
|
|
$postreq->{"$i.uuid"} = $uuid;
|
1415 |
|
|
# $postreq->{"$i.timestamp"} = sprintf("%.0f%06.0f", $timestamp_seconds, $timestamp_microseconds_decimals);
|
1416 |
|
|
$postreq->{"$i.timestamp"} = $timestamp_seconds;
|
1417 |
|
|
|
1418 |
|
|
# Fetch basic node/domain information (cpu, memory, cputime etc)...
|
1419 |
|
|
my $dom_info = $dom->get_info();
|
1420 |
|
|
while (my($key, $value) = each(%$dom_info)) {
|
1421 |
|
|
$postreq->{"$i.domain.$key"} = $value;
|
1422 |
|
|
};
|
1423 |
|
|
|
1424 |
|
|
my $t2 = $timestamp_useconds;
|
1425 |
|
|
my $t1 = $oldTimes{$uuid}->{timestamp_useconds};
|
1426 |
|
|
my $c2 = $dom_info->{cpuTime};
|
1427 |
|
|
my $c1 = $oldTimes{$uuid}->{cpuTime};
|
1428 |
|
|
my $delta = $t2-$t1;
|
1429 |
|
|
|
1430 |
|
|
if ($t1 && $c2>$c1) { # Work across reboots
|
1431 |
|
|
$postreq->{"$i.domain.cpuLoad"} = sprintf("%.4f", (($c2 - $c1)/1000000000) / $delta );
|
1432 |
|
|
$postreq->{"$i.delta"} = floor($delta);
|
1433 |
|
|
}
|
1434 |
|
|
$oldTimes{$uuid}->{cpuTime} = $dom_info->{cpuTime};
|
1435 |
|
|
$oldTimes{$uuid}->{timestamp_useconds} = $timestamp_useconds;
|
1436 |
|
|
$oldTimes{$uuid}->{timestamp} = $timestamp_seconds;
|
1437 |
|
|
# Fetch the xml description of the specific domain...
|
1438 |
|
|
my $domxml = XMLin($dom->get_xml_description());
|
1439 |
|
|
|
1440 |
|
|
# Process block devices...
|
1441 |
|
|
my @devices;
|
1442 |
|
|
# Collect statistics for several block devices...
|
1443 |
|
|
if (ref($domxml->{devices}->{disk}) eq 'ARRAY') {@devices = @{$domxml->{devices}->{disk}};}
|
1444 |
|
|
# Collect statistics for a single block device...
|
1445 |
|
|
else {push @devices, $domxml->{devices}->{disk};}
|
1446 |
|
|
|
1447 |
|
|
my $wr2;
|
1448 |
|
|
my $wr1 = $oldTimes{$uuid}->{"wr_kbytes_s"};
|
1449 |
|
|
my $rd2;
|
1450 |
|
|
my $rd1 = $oldTimes{$uuid}->{"rd_kbytes_s"};
|
1451 |
|
|
foreach my $device (@devices) {
|
1452 |
|
|
if ($device->{device} eq 'disk') {
|
1453 |
|
|
my $blockdev = $device->{target}->{dev};
|
1454 |
|
|
eval {
|
1455 |
|
|
my $blockstats = $dom->block_stats($blockdev);
|
1456 |
|
|
while (my($key, $value) = each(%$blockstats)) {
|
1457 |
|
|
$postreq->{"$i.blk.$blockdev.$key"} = $value;
|
1458 |
|
|
# $postreq->{"$i.blk.hd.$key"} += $value; # We report collected traffic under hd
|
1459 |
|
|
$wr2 += $value if ($key eq 'wr_bytes');
|
1460 |
|
|
$rd2 += $value if ($key eq 'rd_bytes');
|
1461 |
|
|
}
|
1462 |
|
|
};
|
1463 |
|
|
|
1464 |
|
|
print("\tFailed while requesting block device statistics for $blockdev, skipping...") if $@;
|
1465 |
|
|
}
|
1466 |
|
|
}
|
1467 |
|
|
$postreq->{"$i.blk.hd.wr_bytes"} = $wr2;
|
1468 |
|
|
$postreq->{"$i.blk.hd.rd_bytes"} = $rd2;
|
1469 |
|
|
if ($t1 && $c2>$c1) {
|
1470 |
|
|
$postreq->{"$i.blk.hd.wr_kbytes_s"} = sprintf("%.2f", (($wr2 - $wr1)/1024) / $delta );
|
1471 |
|
|
$postreq->{"$i.blk.hd.rd_kbytes_s"} = sprintf("%.2f", (($rd2 - $rd1)/1024) / $delta );
|
1472 |
|
|
$postreq->{"$i.blk.hd.wr_kbytes_s"} = 0 if ($postreq->{"$i.blk.hd.wr_kbytes_s"} eq '0.00');
|
1473 |
|
|
$postreq->{"$i.blk.hd.rd_kbytes_s"} = 0 if ($postreq->{"$i.blk.hd.rd_kbytes_s"} eq '0.00');
|
1474 |
|
|
}
|
1475 |
|
|
$oldTimes{$uuid}->{wr_kbytes_s} = $wr2;
|
1476 |
|
|
$oldTimes{$uuid}->{rd_kbytes_s} = $rd2;
|
1477 |
|
|
|
1478 |
|
|
# Collect statistics for network interfaces...
|
1479 |
|
|
my @netdevices;
|
1480 |
|
|
if (ref($domxml->{devices}->{interface}) eq 'ARRAY') {@netdevices = @{$domxml->{devices}->{interface}};}
|
1481 |
|
|
else {push @netdevices, $domxml->{devices}->{interface};}
|
1482 |
|
|
|
1483 |
|
|
my $rx2;
|
1484 |
|
|
my $rx1 = $oldTimes{$uuid}->{"rx_kbytes_s"};
|
1485 |
|
|
my $tx2;
|
1486 |
|
|
my $tx1 = $oldTimes{$uuid}->{"tx_kbytes_s"};
|
1487 |
|
|
foreach my $device (@netdevices) {
|
1488 |
|
|
my $interface = $device->{target}->{dev};
|
1489 |
|
|
if ($interface) {
|
1490 |
|
|
eval {
|
1491 |
|
|
my $ifstats = $dom->interface_stats($interface);
|
1492 |
|
|
while (my($key, $value) = each(%$ifstats)) {
|
1493 |
|
|
$postreq->{"$i.if.$interface.$key"} = $value;
|
1494 |
|
|
$postreq->{"$i.if.vnet.$key"} += $value; # We report collected traffic under vnet
|
1495 |
|
|
$rx2 += $value if ($key eq 'rx_bytes');
|
1496 |
|
|
$tx2 += $value if ($key eq 'tx_bytes');
|
1497 |
|
|
}
|
1498 |
|
|
};
|
1499 |
|
|
print("\tFailed while requesting interface statistics ('"+$@+"'), skipping...") if $@;
|
1500 |
|
|
}
|
1501 |
|
|
}
|
1502 |
|
|
if ($t1 && $c2>$c1) {
|
1503 |
|
|
$postreq->{"$i.if.vnet.rx_kbytes_s"} = sprintf("%.2f", (($rx2 - $rx1)/1024) / $delta );
|
1504 |
|
|
$postreq->{"$i.if.vnet.tx_kbytes_s"} = sprintf("%.2f", (($tx2 - $tx1)/1024) / $delta );
|
1505 |
|
|
$postreq->{"$i.if.vnet.rx_kbytes_s"} = 0 if ($postreq->{"$i.if.vnet.rx_kbytes_s"} eq '0.00');
|
1506 |
|
|
$postreq->{"$i.if.vnet.tx_kbytes_s"} = 0 if ($postreq->{"$i.if.vnet.tx_kbytes_s"} eq '0.00');
|
1507 |
|
|
}
|
1508 |
|
|
$oldTimes{$uuid}->{rx_kbytes_s} = $rx2;
|
1509 |
|
|
$oldTimes{$uuid}->{tx_kbytes_s} = $tx2;
|
1510 |
|
|
}
|
1511 |
|
|
if ($postreq) {
|
1512 |
|
|
# POST request to admin server...
|
1513 |
|
|
logit('info', "Posting stats to: $stats_url") if $debug;
|
1514 |
|
|
print("POSTREQ:\n".Dumper($postreq)) if $debug;
|
1515 |
|
|
$content = $browser->post($stats_url, $postreq)->content();
|
1516 |
|
|
print "$content\n" if $debug;
|
1517 |
|
|
}
|
1518 |
|
|
}
|
1519 |
|
|
|
1520 |
|
|
sub backup {
|
1521 |
|
|
my $user = $_[0];
|
1522 |
|
|
my $uistatus = $_[1];
|
1523 |
|
|
my $status =$_[2];
|
1524 |
|
|
my $path = $_[3];
|
1525 |
|
|
my $targetdir = $_[4];
|
1526 |
|
|
my $remolder = $_[5];
|
1527 |
|
|
my $pool = "/mnt/stabile/node";
|
1528 |
|
|
my $image;
|
1529 |
|
|
my $subdir; # 1 level of subdirs supported
|
1530 |
|
|
my $res;
|
1531 |
|
|
return 0 unless ($path && $targetdir && $user);
|
1532 |
|
|
# $image is the image to back up (including potential subdir), $pool the source dir (storage pool) and $targetdir the target dir (general backup dir)
|
1533 |
|
|
|
1534 |
|
|
#mkdir "$targetdir/$user" unless -d "$targetdir/$user"; # Create the target dirs which will contain the backup
|
1535 |
|
|
$path =~ /\/$user\/(.+)/;
|
1536 |
|
|
my $imagepath = $1;
|
1537 |
|
|
if ($path =~ /\/$user\/(.+)\/(.+)/) {
|
1538 |
|
|
$subdir = $1;
|
1539 |
|
|
$image = $2;
|
1540 |
|
|
} else {
|
1541 |
|
|
$path =~ /\/$user\/(.+)/;
|
1542 |
|
|
$image = $1;
|
1543 |
|
|
}
|
1544 |
|
|
if ($subdir) { # Creation of $targetdir/$user is done when user logs in
|
1545 |
|
|
#mkdir "$targetdir/$user/$subdir" unless -d "$targetdir/$user/$subdir";
|
1546 |
|
|
#mkdir "$targetdir/$user/$subdir/$image" unless -d "$targetdir/$user/$subdir/$image";
|
1547 |
|
|
my $dironly = $1 if ($targetdir =~ /.+::(.+)/);
|
1548 |
|
|
eval {$res .= `/usr/bin/sudo -u irigo /usr/bin/ssh $mainvalve mkdir "$dironly/$user/$subdir"`; 1;}
|
1549 |
|
|
} else { # Image subdir is created by rdiff-backup
|
1550 |
|
|
#mkdir "$targetdir/$user/$image" unless -d "$targetdir/$user/$image";
|
1551 |
|
|
}
|
1552 |
|
|
$res .= `/bin/echo $status > "$pool/$user/$imagepath.meta"`;
|
1553 |
|
|
|
1554 |
|
|
if (-d "/mnt/$user-$image") {
|
1555 |
|
|
$res .= "Image is already being backed up";
|
1556 |
|
|
} else {
|
1557 |
|
|
my $snapname;
|
1558 |
|
|
my $snappath;
|
1559 |
|
|
my $snapsrcdir;
|
1560 |
|
|
if ($status eq "lbackingup") { # Do a local lvm snapshot before backing up
|
1561 |
|
|
$res .= `/sbin/modprobe dm-snapshot`; # Make sure we can make lvm snapshots
|
1562 |
|
|
$snapname = "$user-$image";
|
1563 |
|
|
$snapname =~ tr/ /-/; #No spaces allowed in snapshot names...
|
1564 |
|
|
$snapname =~ tr/@/+/; #No spaces allowed in snapshot names...
|
1565 |
|
|
$snappath = "/mnt/$snapname"; # The path to mount our snapshot on
|
1566 |
|
|
mkdir $snappath;
|
1567 |
|
|
|
1568 |
|
|
my $q = `/bin/cat /proc/mounts | grep $pool`; # Find the lvm volume mounted on /mnt/images
|
1569 |
|
|
$q =~ /\/dev\/mapper\/(\S+)-(\S+) $pool .+/;
|
1570 |
|
|
my $lvolgroup = $1;
|
1571 |
|
|
my $lvol = $2;
|
1572 |
|
|
|
1573 |
|
|
$res .= `/sbin/lvcreate -L1024M -s -n $snapname /dev/$lvolgroup/$lvol`; # Take a snapshot
|
1574 |
|
|
$res .= changeFstab($snapname, $pool); # Change fstab to allow mount
|
1575 |
|
|
$res .= `/bin/mount "$snappath"`; # Mount the snapshot
|
1576 |
|
|
$snapsrcdir = "$snappath/$user"; # Change source dir to our new snapshot
|
1577 |
|
|
} else {
|
1578 |
|
|
$snapsrcdir = "$pool/$user";
|
1579 |
|
|
}
|
1580 |
|
|
|
1581 |
|
|
# Do the backup
|
1582 |
|
|
eval {$res .= `/usr/bin/sudo -u irigo /usr/bin/rdiff-backup --print-statistics --include "$snapsrcdir/$imagepath" --exclude '**' "$snapsrcdir" "$targetdir/$user/$imagepath"`; 1;}
|
1583 |
|
|
or do {$res .= "Problem executing backup";};
|
1584 |
|
|
if ($remolder) {
|
1585 |
|
|
eval {$res .= `/usr/bin/sudo -u irigo /usr/bin/rdiff-backup --print-statistics --force --remove-older-than $remolder "$targetdir/$user/$imagepath"`; 1;}
|
1586 |
|
|
or do {$res .= "Problem cleaning up old backups";};
|
1587 |
|
|
}
|
1588 |
|
|
$res .= qq{/usr/bin/sudo -u irigo /usr/bin/rdiff-backup --print-statistics --include "$snapsrcdir/$imagepath" --exclude '**' "$snapsrcdir" "$targetdir/$user/$imagepath"};
|
1589 |
|
|
# Clean up
|
1590 |
|
|
if ($status eq "lbackingup") {
|
1591 |
|
|
$res .= `/bin/umount "$snappath"`;
|
1592 |
|
|
$res .= changeFstab($snapname, $pool, 1);
|
1593 |
|
|
$res .= `/bin/rm -r "$snappath"` unless (-d "$snappath/$user");
|
1594 |
|
|
$res .= `/sbin/lvremove -f /dev/$lvolgroup/$snapname`;
|
1595 |
|
|
}
|
1596 |
|
|
logit("info", "Backed up $snapsrcdir/$imagepath to $targetdir/$user/$imagepath");
|
1597 |
|
|
}
|
1598 |
|
|
unlink "$pool/$user/$imagepath.meta";
|
1599 |
|
|
print "$res\n" if ($debug);
|
1600 |
|
|
|
1601 |
|
|
|
1602 |
|
|
my $mes = "";
|
1603 |
|
|
if ($res =~ /TotalDestinationSizeChange (\d+)(.+\))/) {
|
1604 |
|
|
if ($1 eq "0") {
|
1605 |
|
|
$mes = "No changes to back up ($imagepath)";
|
1606 |
|
|
} else {
|
1607 |
|
|
$mes = "Backed up $1$2 ($imagepath)";
|
1608 |
|
|
}
|
1609 |
|
|
} elsif ($res =~ /(Image is already being backed up)/) {
|
1610 |
|
|
$mes = "$1 ($imagepath)";
|
1611 |
|
|
} else {
|
1612 |
|
|
my $hres = $res;
|
1613 |
|
|
$hres =~ s/\n/<br>/g;
|
1614 |
|
|
$hres =~ s/\"/\\"/g;
|
1615 |
|
|
$mes = "Backup failed ($imagepath)";
|
1616 |
|
|
logit('err', "Backup of $imagepath failed - $hres");
|
1617 |
|
|
}
|
1618 |
|
|
my $logentry = "$user: images: $path: $status: $mes";
|
1619 |
|
|
|
1620 |
|
|
# Update the client UI
|
1621 |
|
|
my $url = $base_url . "?mac=$mac&status=updateui&logentry=" . uri_escape($logentry);
|
1622 |
|
|
$content = $browser->get($url);
|
1623 |
|
|
}
|
1624 |
|
|
|
1625 |
|
|
sub changeFstab {
|
1626 |
|
|
my $image = $_[0];
|
1627 |
|
|
my $pool = $_[1];
|
1628 |
|
|
my $remove = 1 if $_[2];
|
1629 |
|
|
return 0 unless ($image);
|
1630 |
|
|
return 0 unless (index($image, " ")==-1);
|
1631 |
|
|
copy($fstab, "$fstab.steam.bak") or return 0;
|
1632 |
|
|
|
1633 |
|
|
my $q = `/bin/cat /proc/mounts | grep $pool`; # Find the lvm volume mounted on /mnt/images
|
1634 |
|
|
$q =~ /\/dev\/mapper\/(\S+)-(\S+) $pool .+/;
|
1635 |
|
|
my $lvolgroup = $1;
|
1636 |
|
|
my $lvol = $2;
|
1637 |
|
|
|
1638 |
|
|
my $newfile = "";
|
1639 |
|
|
my $match;
|
1640 |
|
|
open (FILE, $fstab);
|
1641 |
|
|
while (<FILE>) {
|
1642 |
|
|
chomp;
|
1643 |
|
|
my $line = $_;
|
1644 |
|
|
if ($line =~ /^\/dev\/$lvolgroup\/$image/) {
|
1645 |
|
|
$newfile .= "$line\n" unless ($remove);
|
1646 |
|
|
$match = 1;
|
1647 |
|
|
} else {
|
1648 |
|
|
$newfile .= "$line\n";
|
1649 |
|
|
}
|
1650 |
|
|
}
|
1651 |
|
|
$newfile .= "/dev/$lvolgroup/$image /mnt/$image ext3 users,ro 0 0\n" unless ($match || $remove);
|
1652 |
|
|
close (FILE);
|
1653 |
|
|
open( FILE, ">$fstab" );
|
1654 |
|
|
print FILE $newfile;
|
1655 |
|
|
close(FILE);
|
1656 |
|
|
return "fstab updated $remove\n";
|
1657 |
|
|
}
|
1658 |
|
|
|
1659 |
|
|
sub initializeLocalDisk {
|
1660 |
|
|
my $initld = shift;
|
1661 |
|
|
my $force = shift;
|
1662 |
|
|
my $res;
|
1663 |
2a63870a
|
Christian Orellana
|
if ((-e "/dev/sda" || -e "/dev/vda" || -e "/dev/nvme0n1") && -e '/sbin/sfdisk') {
|
1664 |
95b003ff
|
Origo
|
my $dev = "sda";
|
1665 |
|
|
$dev = "vda" if (-e "/dev/vda");
|
1666 |
|
|
my $part = $dev . "1";
|
1667 |
2a63870a
|
Christian Orellana
|
if (-e "/dev/nvme0n1") {
|
1668 |
|
|
$dev = "nvme0n1";
|
1669 |
|
|
$part = $dev . "p1";
|
1670 |
|
|
}
|
1671 |
|
|
|
1672 |
95b003ff
|
Origo
|
`chmod 666 /dev/zfs` if (-e '/dev/zfs'); # TODO: This should be removed once we upgrade to Bionic and zfs allow is supported
|
1673 |
|
|
my $partinfo = `/sbin/sfdisk -q -d /dev/$dev`;
|
1674 |
|
|
my $zlist = `zpool list`;
|
1675 |
|
|
|
1676 |
|
|
if (!$force) {
|
1677 |
|
|
my $mounts = `/bin/cat /proc/mounts`;
|
1678 |
|
|
if ($mounts =~ /volgroup1-lvol1/ || $mounts =~ /\mnt\/stabile\/node/) {
|
1679 |
|
|
$res = "Local disk is already mounted.";
|
1680 |
|
|
print "$res\n";
|
1681 |
|
|
return $res;
|
1682 |
|
|
} else {
|
1683 |
|
|
if (( $partinfo =~ /\/dev\/$part.+size=.*(\d+),/i && $1>0 ) || $zlist =~ /stabile-node/) {
|
1684 |
|
|
$res = "Local disk is already partitioned. Trying to mount.";
|
1685 |
|
|
if ($initld eq 'zfs') {
|
1686 |
|
|
$res .= " ZFS specified.";
|
1687 |
|
|
`zpool import stabile-node`;
|
1688 |
|
|
`zfs mount stabile-node/node`;
|
1689 |
|
|
} else {
|
1690 |
|
|
$res .= " LVM specified.";
|
1691 |
|
|
`/bin/mount /dev/volgroup1/lvol1 /mnt/stabile/node`;
|
1692 |
|
|
}
|
1693 |
|
|
print "$res\n";
|
1694 |
|
|
}
|
1695 |
|
|
`/bin/chmod 777 /mnt/stabile/node`;
|
1696 |
|
|
return $res;
|
1697 |
|
|
}
|
1698 |
|
|
}
|
1699 |
|
|
|
1700 |
|
|
if ($force) {
|
1701 |
|
|
if (`ls -l /mnt/stabile/node/*/*.qcow2`) {
|
1702 |
|
|
$res = "Node storage dir not empty";
|
1703 |
|
|
print "$res\n";
|
1704 |
|
|
return $res;
|
1705 |
|
|
}
|
1706 |
|
|
print `umount /mnt/stabile/node`;
|
1707 |
|
|
print `umount /stabile-node`;
|
1708 |
|
|
my $mounts = `cat /proc/mounts`;
|
1709 |
|
|
if ($mounts =~ /stabile-node/ || $mounts =~ /\/mnt\/stabile\/node/) {
|
1710 |
|
|
$res = "Unable to unmount node storage\n";
|
1711 |
|
|
print "$res\n";
|
1712 |
|
|
return $res;
|
1713 |
|
|
}
|
1714 |
|
|
print `zpool destroy stabile-node`;
|
1715 |
|
|
print `vgremove -f volgroup1`;
|
1716 |
|
|
}
|
1717 |
|
|
if ($initld eq 'zfs') { # ZFS was specified
|
1718 |
|
|
$res = "Initializing local disk with ZFS...";
|
1719 |
|
|
print "$res\n";
|
1720 |
|
|
print `rmdir /mnt/stabile/node` if (-e "/mnt/stabile/node" && !(`ls /mnt/stabile/node`));
|
1721 |
|
|
print `parted -s /dev/$dev mklabel GPT`;
|
1722 |
|
|
print `zpool create stabile-node /dev/$dev`;
|
1723 |
|
|
print `zfs create stabile-node/node`;
|
1724 |
|
|
print `zfs set mountpoint=/mnt/stabile/node stabile-node/node`;
|
1725 |
|
|
print `zfs set atime=off stabile-node/node`;
|
1726 |
|
|
} else { # Assume LVM
|
1727 |
|
|
$res = "Initializing local disk with LVM...";
|
1728 |
|
|
print "$res\n";
|
1729 |
|
|
`/sbin/sfdisk -d /dev/$dev > /root/$dev-partition-sectors.save`;
|
1730 |
|
|
`sfdisk /dev/$dev << EOF\n;\nEOF`;
|
1731 |
|
|
`/sbin/vgcreate -f volgroup1 /dev/$part`;
|
1732 |
|
|
`/sbin/vgchange -a y volgroup1`;
|
1733 |
|
|
my $totalpe =`/sbin/vgdisplay volgroup1 | grep "Total PE"`;
|
1734 |
|
|
$totalpe =~ /Total PE\s+(\d+)/;
|
1735 |
|
|
my $size = $1 -2000;
|
1736 |
|
|
`/sbin/lvcreate -l $size volgroup1 -n lvol1`;
|
1737 |
|
|
`/sbin/mkfs.ext3 /dev/volgroup1/lvol1`;
|
1738 |
|
|
`/bin/mount /dev/volgroup1/lvol1 /mnt/stabile/node`;
|
1739 |
|
|
}
|
1740 |
3657de20
|
Origo
|
`/bin/chmod 777 /mnt/stabile/node`;
|
1741 |
95b003ff
|
Origo
|
my $lsistatus = `/usr/local/bin/lsi.sh status`;
|
1742 |
|
|
if ($lsistatus =~ /Adapter 0/) {
|
1743 |
|
|
#unless (-e "/etc/cron.hourly/lsicheck.sh") {
|
1744 |
|
|
print "Adding hourly cron check of LSI raid\n";
|
1745 |
|
|
my $alertemail = `cat /etc/stabile/nodeconfig.cfg | grep ALERT_EMAIL | cut -f2 -d "="`;
|
1746 |
|
|
`/bin/echo "#!/bin/bash\n\n/usr/local/bin/lsi.sh checkNemail $alertemail" > /etc/cron.hourly/lsicheck.sh`;
|
1747 |
|
|
$res .= "Adding hourly cron check of LSI raid";
|
1748 |
|
|
print "$res\n";
|
1749 |
|
|
`/bin/echo "#!/bin/bash\n\n/usr/local/bin/lsi.sh status | mail -s \\"$hostname LSI status\\" $alertemail" > /etc/cron.weekly/lsistatus.sh`;
|
1750 |
|
|
#}
|
1751 |
|
|
}
|
1752 |
|
|
} else {
|
1753 |
|
|
$res = "No local disk";
|
1754 |
|
|
print "$res\n";
|
1755 |
|
|
}
|
1756 |
|
|
return $res;
|
1757 |
|
|
}
|
1758 |
|
|
|
1759 |
|
|
sub dont_die {
|
1760 |
|
|
print "We trudge along\n";
|
1761 |
|
|
}
|
1762 |
|
|
|
1763 |
|
|
sub run_in_bg {
|
1764 |
|
|
my ($cmd) = @_;
|
1765 |
|
|
my $proc1 = Proc::Background->new($cmd);
|
1766 |
|
|
}
|
1767 |
|
|
|
1768 |
|
|
sub setCgroups {
|
1769 |
|
|
if (-d "/sys/fs/cgroup") {
|
1770 |
2a63870a
|
Christian Orellana
|
print `cgconfigparser -l /etc/stabile/cgconfig.conf`;
|
1771 |
95b003ff
|
Origo
|
} else {
|
1772 |
|
|
print "cgroups are not enabled!!\n";
|
1773 |
|
|
}
|
1774 |
|
|
}
|
1775 |
|
|
|
1776 |
|
|
sub updateInterfaces {
|
1777 |
|
|
if ($identity eq 'local_kvm' || -e "/etc/stabile/config.cfg") {
|
1778 |
|
|
unless (`ifconfig | grep "inet 10\.0\.0\.1"`) {
|
1779 |
2a63870a
|
Christian Orellana
|
# print "Adding 10.0.0.1 as to $datanic\n";
|
1780 |
|
|
# `ifconfig $datanic:1 10.0.0.1/24 up`;
|
1781 |
|
|
print "Adding 10.0.0.1 as to $adminnic\n";
|
1782 |
|
|
`ifconfig $adminnic:1 10.0.0.1/24 up`;
|
1783 |
95b003ff
|
Origo
|
`steamExec post-wake`;
|
1784 |
|
|
}
|
1785 |
|
|
}
|
1786 |
|
|
}
|
1787 |
|
|
|
1788 |
2a63870a
|
Christian Orellana
|
# Enumerate and return network interfaces
|
1789 |
|
|
sub getNics {
|
1790 |
|
|
my $droute = `ip route show default`;
|
1791 |
d24d9a01
|
hq
|
my $internalnic = $1 if ($droute =~ /default via .+ dev (.+) proto/); # On the node, default route is on the internal network
|
1792 |
|
|
# First get all nics and activate link on ethers - for some reason Ubuntu puts them down if they are not configured with an IP
|
1793 |
|
|
my $niclist = `ifconfig -a | grep flags= | sed -n -e 's/: .*//p'`;
|
1794 |
|
|
foreach my $line (split("\n", $niclist)) {
|
1795 |
|
|
my $nic = $1 if ($line =~ /(\S+)/);
|
1796 |
|
|
if ($nic=~/^en/) {
|
1797 |
|
|
`ifconfig $nic up`;
|
1798 |
|
|
}
|
1799 |
|
|
}
|
1800 |
|
|
sleep 1;
|
1801 |
|
|
# Then list those that are up i.e. have link
|
1802 |
2a63870a
|
Christian Orellana
|
my $niclist = `ifconfig | grep flags= | sed -n -e 's/: .*//p'`;
|
1803 |
|
|
# my $niclist = `netstat -in`;
|
1804 |
|
|
my @nics = ();
|
1805 |
d24d9a01
|
hq
|
push @nics, $internalnic if ($internalnic);
|
1806 |
2a63870a
|
Christian Orellana
|
foreach my $line (split("\n", $niclist)) {
|
1807 |
|
|
my $nic = $1 if ($line =~ /(\S+)/);
|
1808 |
d24d9a01
|
hq
|
if ($nic ne 'lo' && $nic ne $internalnic && !($nic=~/^virbr/) && !($nic=~/^docker/) && !($nic=~/^br/) && !($nic=~/^vnet/) && !($nic=~/^Name/) && !($nic=~/^Kernel/) && !($nic=~/^Iface/) && !($nic=~/(\.|\:)/)) {
|
1809 |
2a63870a
|
Christian Orellana
|
push @nics, $1;
|
1810 |
|
|
}
|
1811 |
|
|
}
|
1812 |
d24d9a01
|
hq
|
$internalnic = $nics[0] unless ($internalnic);
|
1813 |
|
|
my $externalnic = $internalnic;
|
1814 |
|
|
$externalnic = $nics[1] if (scalar @nics > 1);
|
1815 |
|
|
if ($identity eq 'local_kvm') { # local_kvm uses external NIC for vlans and internal NIC for 10.0.0.1
|
1816 |
|
|
return ($externalnic, $internalnic);
|
1817 |
|
|
} else {
|
1818 |
|
|
return ($internalnic, $externalnic);
|
1819 |
|
|
}
|
1820 |
2a63870a
|
Christian Orellana
|
}
|
1821 |
|
|
|
1822 |
95b003ff
|
Origo
|
sub TERMINATE {
|
1823 |
|
|
$running = 0;
|
1824 |
|
|
$status = "shutdown" unless ($status eq "asleep");
|
1825 |
|
|
$glogentry = "--: nodes: $nmac: $status: Shutting down $identity piston...";
|
1826 |
|
|
updatePistonInfo();
|
1827 |
|
|
logit("debug", "Shutting down");
|
1828 |
|
|
if ($identity eq "vbox") {
|
1829 |
|
|
logit('info', "Shutting down Virtual Box piston");
|
1830 |
|
|
print `/etc/init.d/vboxdrv stop`,"\n";
|
1831 |
|
|
} else {
|
1832 |
|
|
logit('info', "Shutting down KVM piston");
|
1833 |
|
|
print `/etc/init.d/kvm stop`,"\n";
|
1834 |
|
|
}
|
1835 |
|
|
##logit("debug", `killall movepiston`);
|
1836 |
|
|
##exit(0);
|
1837 |
|
|
}
|
1838 |
|
|
|
1839 |
|
|
##
|