| 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 |
|
|
package Stabile::Servers;
|
| 9 |
|
|
|
| 10 |
|
|
use Error qw(:try);
|
| 11 |
|
|
use Data::UUID;
|
| 12 |
|
|
use Proc::Daemon;
|
| 13 |
|
|
use File::Basename;
|
| 14 |
|
|
use lib dirname (__FILE__);
|
| 15 |
|
|
use File::Basename;
|
| 16 |
a2e0bc7e
|
hq
|
use Config::Simple;
|
| 17 |
95b003ff
|
Origo
|
use lib dirname (__FILE__);
|
| 18 |
|
|
use Stabile;
|
| 19 |
|
|
#use Encode::Escape;
|
| 20 |
|
|
|
| 21 |
|
|
$\ = ''; # Some of the above seems to set this to \n, resulting in every print appending a line feed
|
| 22 |
|
|
|
| 23 |
|
|
$cpuovercommision = $Stabile::config->get('CPU_OVERCOMMISION') || 1;
|
| 24 |
|
|
$dpolicy = $Stabile::config->get('DISTRIBUTION_POLICY') || 'disperse'; #"disperse" or "pack"
|
| 25 |
|
|
$amtpasswd = $Stabile::config->get('AMT_PASSWD') || "";
|
| 26 |
|
|
$brutalsleep = $Stabile::config->get('BRUTAL_SLEEP') || "";
|
| 27 |
|
|
$sshcmd = $sshcmd || $Stabile::sshcmd;
|
| 28 |
|
|
|
| 29 |
|
|
my %ahash; # A hash of accounts and associated privileges current user has access to
|
| 30 |
|
|
|
| 31 |
|
|
#my %options=();
|
| 32 |
|
|
#Getopt::Std::getopts("a:hfu:m:k:", \%options); # -a action -h help -f full-list (all users) -u uuid -m match pattern -k keywords
|
| 33 |
|
|
|
| 34 |
|
|
try {
|
| 35 |
|
|
Init(); # Perform various initalization tasks
|
| 36 |
|
|
process() if ($package);
|
| 37 |
|
|
|
| 38 |
|
|
if ($action || %params) {
|
| 39 |
|
|
untie %register;
|
| 40 |
|
|
untie %networkreg;
|
| 41 |
|
|
untie %nodereg;
|
| 42 |
|
|
untie %xmlreg;
|
| 43 |
|
|
}
|
| 44 |
|
|
|
| 45 |
|
|
} catch Error with {
|
| 46 |
|
|
my $ex = shift;
|
| 47 |
|
|
print $Stabile::q->header('text/html', '500 Internal Server Error') unless ($console);
|
| 48 |
|
|
if ($ex->{-text}) {
|
| 49 |
|
|
print "Got error: ", $ex->{-text}, " on line ", $ex->{-line}, "\n";
|
| 50 |
|
|
} else {
|
| 51 |
|
|
print "Status=ERROR\n";
|
| 52 |
|
|
}
|
| 53 |
|
|
} finally {
|
| 54 |
|
|
};
|
| 55 |
|
|
|
| 56 |
|
|
1;
|
| 57 |
|
|
|
| 58 |
|
|
sub getObj {
|
| 59 |
|
|
my %h = %{@_[0]};
|
| 60 |
|
|
$console = 1 if $h{"console"};
|
| 61 |
|
|
$api = 1 if $h{"api"};
|
| 62 |
|
|
my $uuid = $h{"uuid"};
|
| 63 |
|
|
$uuid = $curuuid if ($uuid eq 'this');
|
| 64 |
|
|
my $obj;
|
| 65 |
c899e439
|
Origo
|
$action = $action || $h{'action'};
|
| 66 |
|
|
|
| 67 |
6372a66e
|
hq
|
if ($h{'action'} eq 'destroy' || $action eq 'destroy' || $action eq 'destroyuserservers' || $action eq 'attach' || $action eq 'detach' || $action =~ /changepassword|sshaccess/) {
|
| 68 |
95b003ff
|
Origo
|
$obj = \%h;
|
| 69 |
|
|
return $obj;
|
| 70 |
|
|
}
|
| 71 |
|
|
|
| 72 |
|
|
# Allow specifying nicmac1 instead of uuid if known
|
| 73 |
|
|
if (!$uuid) {
|
| 74 |
|
|
$uuid = nicmac1ToUuid($h{"nicmac1"});
|
| 75 |
|
|
}
|
| 76 |
|
|
my $status = 'new';
|
| 77 |
|
|
$status = $register{$uuid}->{'status'} if ($register{$uuid});
|
| 78 |
|
|
|
| 79 |
|
|
my $objaction = lc $h{"action"};
|
| 80 |
|
|
$objaction = "" if ($status eq "new");
|
| 81 |
|
|
|
| 82 |
|
|
if ((!$uuid) && $status eq 'new') {
|
| 83 |
|
|
my $ug = new Data::UUID;
|
| 84 |
|
|
$uuid = $ug->create_str();
|
| 85 |
|
|
if ($uripath =~ /servers(\.cgi)?\/(.+)/) {
|
| 86 |
|
|
my $huuid = $2;
|
| 87 |
|
|
if ($ug->to_string($ug->from_string($huuid)) eq $huuid) { # Check for valid uuid
|
| 88 |
|
|
$uuid = $huuid;
|
| 89 |
|
|
}
|
| 90 |
|
|
}
|
| 91 |
|
|
};
|
| 92 |
|
|
unless ($uuid && length $uuid == 36) {
|
| 93 |
|
|
$posterror .= "Status=Error Invalid uuid.\n";
|
| 94 |
|
|
return;
|
| 95 |
|
|
}
|
| 96 |
|
|
|
| 97 |
|
|
my $dbobj = $register{$uuid} || {};
|
| 98 |
|
|
|
| 99 |
|
|
my $name = $h{"name"} || $dbobj->{'name'};
|
| 100 |
|
|
utf8::decode($name);
|
| 101 |
|
|
my $memory = $h{"memory"} || $dbobj->{'memory'};
|
| 102 |
|
|
my $vcpu = $h{"vcpu"} || $dbobj->{'vcpu'};
|
| 103 |
|
|
my $boot = $h{"boot"} || $dbobj->{'boot'};
|
| 104 |
04c16f26
|
hq
|
my $loader = $h{"loader"} || $dbobj->{'loader'};
|
| 105 |
95b003ff
|
Origo
|
my $image = $h{"image"} || $dbobj->{'image'};
|
| 106 |
|
|
my $imagename = $h{"imagename"} || $dbobj->{'imagename'};
|
| 107 |
|
|
if ($image && $image ne '--' && !($image =~ /^\//)) { # Image is registered by uuid - we find the path
|
| 108 |
|
|
unless ( tie(%imagereg2,'Tie::DBI', Hash::Merge::merge({table=>'images', CLOBBER=>1}, $Stabile::dbopts)) ) {$posterror = "Unable to access image uuid register"; return;};
|
| 109 |
|
|
$image = $imagereg2{$image}->{'path'};
|
| 110 |
|
|
$imagename = $imagereg2{$image}->{'name'};
|
| 111 |
|
|
untie %imagereg2;
|
| 112 |
|
|
return unless ($image);
|
| 113 |
|
|
}
|
| 114 |
|
|
my $image2 = $h{"image2"} || $dbobj->{'image2'};
|
| 115 |
|
|
my $image3 = $h{"image3"} || $dbobj->{'image3'};
|
| 116 |
|
|
my $image4 = $h{"image4"} || $dbobj->{'image4'};
|
| 117 |
|
|
my $image2name = $h{"image2name"} || $dbobj->{'image2name'};
|
| 118 |
|
|
my $image3name = $h{"image3name"} || $dbobj->{'image3name'};
|
| 119 |
|
|
my $image4name = $h{"image4name"} || $dbobj->{'image4name'};
|
| 120 |
|
|
if ($image2 && $image2 ne '--' && !($image2 =~ /^\//)) { # Image2 is registered by uuid - we find the path
|
| 121 |
|
|
unless ( tie(%imagereg2,'Tie::DBI', Hash::Merge::merge({table=>'images', CLOBBER=>1}, $Stabile::dbopts)) ) {$postreply = "Unable to access image uuid register"; return $postreply;};
|
| 122 |
|
|
$image2 = $imagereg2{$image2}->{'path'};
|
| 123 |
|
|
$image2name = $imagereg2{$image2}->{'name'};
|
| 124 |
|
|
untie %imagereg2;
|
| 125 |
|
|
}
|
| 126 |
|
|
my $diskbus = $h{"diskbus"} || $dbobj->{'diskbus'};
|
| 127 |
|
|
my $diskdev = "vda";
|
| 128 |
|
|
my $diskdev2 = "vdb";
|
| 129 |
|
|
my $diskdev3 = "vdc";
|
| 130 |
|
|
my $diskdev4 = "vdd";
|
| 131 |
|
|
if ($diskbus eq "ide") {$diskdev = "hda"; $diskdev2 = "hdb"; $diskdev3 = "hdc"; $diskdev4 = "hdd"};
|
| 132 |
|
|
my $cdrom = $h{"cdrom"} || $dbobj->{'cdrom'};
|
| 133 |
04c16f26
|
hq
|
if ($cdrom && $cdrom ne '--' && !($cdrom =~ /^\//) && $cdrom ne 'virtio') {
|
| 134 |
95b003ff
|
Origo
|
unless ( tie(%imagereg2,'Tie::DBI', Hash::Merge::merge({table=>'images', CLOBBER=>1}, $Stabile::dbopts)) ) {$postreply = "Unable to access image uuid register"; return $postreply;};
|
| 135 |
|
|
$cdrom = $imagereg2{$cdrom}->{'path'};
|
| 136 |
|
|
untie %imagereg2;
|
| 137 |
|
|
}
|
| 138 |
|
|
|
| 139 |
|
|
my $networkuuid1 = $h{"networkuuid1"} || $dbobj->{'networkuuid1'};
|
| 140 |
|
|
if ($h{"networkuuid1"} eq "0") {$networkuuid1 = "0"}; #Stupid perl... :-)
|
| 141 |
|
|
my $networkid1 = $h{"networkid1"} || $dbobj->{'networkid1'};
|
| 142 |
|
|
my $networkname1 = $h{"networkname1"} || $dbobj->{'networkname1'};
|
| 143 |
|
|
my $nicmodel1 = $h{"nicmodel1"} || $dbobj->{'nicmodel1'};
|
| 144 |
|
|
my $nicmac1 = $h{"nicmac1"} || $dbobj->{'nicmac1'};
|
| 145 |
|
|
if (!$nicmac1 || $nicmac1 eq "--") {$nicmac1 = randomMac();}
|
| 146 |
|
|
|
| 147 |
|
|
my $networkuuid2 = $h{"networkuuid2"} || $dbobj->{'networkuuid2'};
|
| 148 |
|
|
if ($h{"networkuuid2"} eq "0") {$networkuuid2 = "0"};
|
| 149 |
|
|
my $networkid2 = $h{"networkid2"} || $dbobj->{'networkid2'};
|
| 150 |
|
|
my $networkname2 = $h{"networkname2"} || $dbobj->{'networkname2'};
|
| 151 |
|
|
my $nicmac2 = $h{"nicmac2"} || $dbobj->{'nicmac2'};
|
| 152 |
|
|
if (!$nicmac2 || $nicmac2 eq "--") {$nicmac2 = randomMac();}
|
| 153 |
|
|
|
| 154 |
|
|
my $networkuuid3 = $h{"networkuuid3"} || $dbobj->{'networkuuid3'};
|
| 155 |
|
|
if ($h{"networkuuid3"} eq "0") {$networkuuid3 = "0"};
|
| 156 |
|
|
my $networkid3 = $h{"networkid3"} || $dbobj->{'networkid3'};
|
| 157 |
|
|
my $networkname3 = $h{"networkname3"} || $dbobj->{'networkname3'};
|
| 158 |
|
|
my $nicmac3 = $h{"nicmac3"} || $dbobj->{'nicmac3'};
|
| 159 |
|
|
if (!$nicmac3 || $nicmac3 eq "--") {$nicmac3 = randomMac();}
|
| 160 |
|
|
|
| 161 |
|
|
my $action = $h{"action"};
|
| 162 |
|
|
my $notes = $h{"notes"};
|
| 163 |
|
|
$notes = $dbobj->{'notes'} if (!$notes || $notes eq '--');
|
| 164 |
|
|
my $reguser = $dbobj->{'user'};
|
| 165 |
|
|
my $autostart = ($h{"autostart"} ."") || $dbobj->{'autostart'};
|
| 166 |
|
|
if ($autostart && $autostart ne "false") {$autostart = "true";}
|
| 167 |
|
|
my $locktonode = ($h{"locktonode"} ."") || $dbobj->{'locktonode'};
|
| 168 |
|
|
if ($locktonode && $locktonode ne "false") {$locktonode = "true";}
|
| 169 |
|
|
my $mac;
|
| 170 |
d3805c61
|
hq
|
$mac = $dbobj->{'mac'} unless ($objaction eq 'start' || $objaction eq 'move' || $objaction eq 'stormove');
|
| 171 |
95b003ff
|
Origo
|
$mac = $h{"mac"} if ($isadmin && $h{"mac"});
|
| 172 |
|
|
my $domuser = $h{"user"} || $user; # Set if user is trying to move server to another account
|
| 173 |
|
|
|
| 174 |
|
|
# Sanity checks
|
| 175 |
|
|
if (
|
| 176 |
|
|
($name && length $name > 255)
|
| 177 |
|
|
|| ($networkuuid1<0)
|
| 178 |
|
|
|| ($networkuuid2<0)
|
| 179 |
|
|
|| ($networkuuid3<0)
|
| 180 |
|
|
|| ($networkuuid1>1 && length $networkuuid1 != 36)
|
| 181 |
|
|
|| ($networkuuid2>1 && length $networkuuid2 != 36)
|
| 182 |
|
|
|| ($networkuuid3>1 && length $networkuuid3 != 36)
|
| 183 |
|
|
|| ($image && length $image > 255)
|
| 184 |
|
|
|| ($imagename && length $imagename > 255)
|
| 185 |
|
|
|| ($image2 && length $image2 > 255)
|
| 186 |
|
|
|| ($image3 && length $image3 > 255)
|
| 187 |
|
|
|| ($image4 && length $image4 > 255)
|
| 188 |
|
|
|| ($image2name && length $image2name > 255)
|
| 189 |
|
|
|| ($image3name && length $image3name > 255)
|
| 190 |
|
|
|| ($image4name && length $image4name > 255)
|
| 191 |
|
|
|| ($cdrom && length $cdrom > 255)
|
| 192 |
a439a9c4
|
hq
|
|| ($memory && ($memory<64 || $memory >1024*64))
|
| 193 |
95b003ff
|
Origo
|
) {
|
| 194 |
a439a9c4
|
hq
|
$postreply .= "Status=ERROR Invalid server data: $name\n";
|
| 195 |
95b003ff
|
Origo
|
return 0;
|
| 196 |
|
|
}
|
| 197 |
|
|
|
| 198 |
|
|
# Security check
|
| 199 |
2a63870a
|
Christian Orellana
|
if ($status eq 'new' && (($action && $action ne '--' && $action ne 'save') || !$image || $image eq '--')) {
|
| 200 |
|
|
$postreply .= "Status=ERROR Bad server data: $name\n";
|
| 201 |
|
|
$postmsg = "Bad server data";
|
| 202 |
95b003ff
|
Origo
|
return 0;
|
| 203 |
|
|
}
|
| 204 |
|
|
if (!$reguser && $status ne 'new'
|
| 205 |
|
|
&& !($name && $memory && $vcpu && $boot && $image && $diskbus && $networkuuid1 && $nicmodel1)) {
|
| 206 |
|
|
$posterror .= "Status=ERROR Insufficient data: $name\n";
|
| 207 |
|
|
return 0;
|
| 208 |
|
|
}
|
| 209 |
|
|
if (!$isadmin) {
|
| 210 |
|
|
if (($networkuuid1>1 && $networkreg{$networkuuid1}->{'user'} ne $user)
|
| 211 |
|
|
|| ($networkuuid2>1 && $networkreg{$networkuuid2}->{'user'} ne $user)
|
| 212 |
|
|
|| ($networkuuid3>1 && $networkreg{$networkuuid3}->{'user'} ne $user)
|
| 213 |
|
|
)
|
| 214 |
|
|
{
|
| 215 |
|
|
$postreply .= "Status=ERROR No privileges: $networkname1 $networkname2\n";
|
| 216 |
|
|
return 0;
|
| 217 |
|
|
}
|
| 218 |
91a21c75
|
hq
|
if ( ($reguser && ($user ne $reguser) && $action ) || ($reguser && $status eq "new"))
|
| 219 |
95b003ff
|
Origo
|
{
|
| 220 |
|
|
$postreply .= "Status=ERROR No privileges: $name\n";
|
| 221 |
|
|
return 0;
|
| 222 |
|
|
}
|
| 223 |
|
|
if (!($image =~ /\/$user\//)
|
| 224 |
|
|
|| ($image2 && $image2 ne "--" && !($image2 =~ /\/$user\//))
|
| 225 |
|
|
|| ($image3 && $image3 ne "--" && !($image3 =~ /\/$user\//))
|
| 226 |
|
|
|| ($image4 && $image4 ne "--" && !($image4 =~ /\/$user\//))
|
| 227 |
|
|
)
|
| 228 |
|
|
{
|
| 229 |
|
|
$postreply .= "Status=ERROR No image privileges: $name\n";
|
| 230 |
|
|
return 0;
|
| 231 |
|
|
}
|
| 232 |
|
|
}
|
| 233 |
|
|
|
| 234 |
|
|
# No action - regular save of domain properties
|
| 235 |
04c16f26
|
hq
|
$cdrom = '--' if ($cdrom eq 'virtio' && $action ne 'mountcd');
|
| 236 |
95b003ff
|
Origo
|
|
| 237 |
|
|
$obj = {
|
| 238 |
|
|
uuid => $uuid,
|
| 239 |
|
|
status => $status,
|
| 240 |
|
|
name => $name,
|
| 241 |
|
|
memory => $memory,
|
| 242 |
|
|
vcpu => $vcpu,
|
| 243 |
|
|
image => $image,
|
| 244 |
|
|
imagename => $imagename,
|
| 245 |
|
|
image2 => $image2,
|
| 246 |
|
|
image2name => $image2name,
|
| 247 |
|
|
image3 => $image3,
|
| 248 |
|
|
image3name => $image3name,
|
| 249 |
|
|
image4 => $image4,
|
| 250 |
|
|
image4name => $image4name,
|
| 251 |
|
|
diskbus => $diskbus,
|
| 252 |
|
|
cdrom => $cdrom,
|
| 253 |
|
|
boot => $boot,
|
| 254 |
04c16f26
|
hq
|
loader=> $loader,
|
| 255 |
95b003ff
|
Origo
|
networkuuid1 => $networkuuid1,
|
| 256 |
|
|
networkid1 => $networkid1,
|
| 257 |
|
|
networkname1 => $networkname1,
|
| 258 |
|
|
nicmodel1 => $nicmodel1,
|
| 259 |
|
|
nicmac1 => $nicmac1,
|
| 260 |
|
|
networkuuid2 => $networkuuid2,
|
| 261 |
|
|
networkid2 => $networkid2,
|
| 262 |
|
|
networkname2 => $networkname2,
|
| 263 |
|
|
nicmac2 => $nicmac2,
|
| 264 |
|
|
networkuuid3 => $networkuuid3,
|
| 265 |
|
|
networkid3 => $networkid3,
|
| 266 |
|
|
networkname3 => $networkname3,
|
| 267 |
|
|
nicmac3 => $nicmac3,
|
| 268 |
|
|
notes => $notes,
|
| 269 |
|
|
autostart => $autostart,
|
| 270 |
|
|
locktonode => $locktonode,
|
| 271 |
|
|
mac => $mac,
|
| 272 |
|
|
user => $domuser
|
| 273 |
|
|
};
|
| 274 |
|
|
return $obj;
|
| 275 |
|
|
}
|
| 276 |
|
|
|
| 277 |
|
|
sub Init {
|
| 278 |
|
|
# Tie database tables to hashes
|
| 279 |
|
|
unless ( tie(%register,'Tie::DBI', Hash::Merge::merge({table=>'domains'}, $Stabile::dbopts)) ) {return "Unable to access image register"};
|
| 280 |
|
|
unless ( tie(%networkreg,'Tie::DBI', Hash::Merge::merge({table=>'networks'}, $Stabile::dbopts)) ) {return "Unable to access network register"};
|
| 281 |
|
|
unless ( tie(%nodereg,'Tie::DBI', Hash::Merge::merge({table=>'nodes', key=>'mac'}, $Stabile::dbopts)) ) {return "Unable to access nodes register"};
|
| 282 |
|
|
unless ( tie(%xmlreg,'Tie::DBI', Hash::Merge::merge({table=>'domainxml'}, $Stabile::dbopts)) ) {return "Unable to access domainxml register"};
|
| 283 |
|
|
|
| 284 |
|
|
# simplify globals initialized in Stabile.pm
|
| 285 |
|
|
$tktuser = $tktuser || $Stabile::tktuser;
|
| 286 |
|
|
$user = $user || $Stabile::user;
|
| 287 |
|
|
$isadmin = $isadmin || $Stabile::isadmin;
|
| 288 |
|
|
$privileges = $privileges || $Stabile::privileges;
|
| 289 |
|
|
|
| 290 |
|
|
# Create aliases of functions
|
| 291 |
|
|
*header = \&CGI::header;
|
| 292 |
|
|
*to_json = \&JSON::to_json;
|
| 293 |
|
|
|
| 294 |
|
|
*Showautostart = \&Autostartall;
|
| 295 |
d3805c61
|
hq
|
*Stormove = \&Move;
|
| 296 |
95b003ff
|
Origo
|
|
| 297 |
|
|
*do_save = \&Save;
|
| 298 |
|
|
*do_tablelist = \&do_list;
|
| 299 |
|
|
*do_jsonlist = \&do_list;
|
| 300 |
|
|
*do_showautostart = \&action;
|
| 301 |
|
|
*do_autostartall = \&privileged_action;
|
| 302 |
|
|
*do_help = \&action;
|
| 303 |
|
|
|
| 304 |
|
|
*do_start = \&privileged_action;
|
| 305 |
|
|
*do_destroy = \&action;
|
| 306 |
|
|
*do_shutdown = \&action;
|
| 307 |
|
|
*do_suspend = \&action;
|
| 308 |
|
|
*do_resume = \&action;
|
| 309 |
|
|
*do_remove = \&privileged_action;
|
| 310 |
|
|
*do_move = \&action;
|
| 311 |
d3805c61
|
hq
|
*do_abort = \&action;
|
| 312 |
|
|
*do_stormove = \&action;
|
| 313 |
95b003ff
|
Origo
|
*do_mountcd = \&action;
|
| 314 |
c899e439
|
Origo
|
*do_changepassword = \&privileged_action;
|
| 315 |
|
|
*do_sshaccess = \&privileged_action;
|
| 316 |
95b003ff
|
Origo
|
|
| 317 |
|
|
*do_gear_start = \&do_gear_action;
|
| 318 |
|
|
*do_gear_autostart = \&do_gear_action;
|
| 319 |
|
|
*do_gear_showautostart = \&do_gear_action;
|
| 320 |
|
|
*do_gear_autostartall = \&do_gear_action;
|
| 321 |
|
|
*do_gear_remove = \&do_gear_action;
|
| 322 |
c899e439
|
Origo
|
*do_gear_changepassword = \&do_gear_action;
|
| 323 |
|
|
*do_gear_sshaccess = \&do_gear_action;
|
| 324 |
95b003ff
|
Origo
|
|
| 325 |
|
|
}
|
| 326 |
|
|
|
| 327 |
|
|
sub do_list {
|
| 328 |
|
|
my ($uuid, $action) = @_;
|
| 329 |
|
|
if ($help) {
|
| 330 |
|
|
return <<END
|
| 331 |
|
|
GET:uuid:
|
| 332 |
|
|
List servers current user has access to.
|
| 333 |
|
|
END
|
| 334 |
|
|
}
|
| 335 |
|
|
|
| 336 |
|
|
my $res;
|
| 337 |
|
|
my $filter;
|
| 338 |
|
|
my $statusfilter;
|
| 339 |
|
|
my $uuidfilter;
|
| 340 |
|
|
my $curserv = $register{$curuuid};
|
| 341 |
|
|
if ($curuuid && ($isadmin || $curserv->{'user'} eq $user) && $uripath =~ /servers(\.cgi)?\/(\?|)(this)/) {
|
| 342 |
|
|
$uuidfilter = $curuuid;
|
| 343 |
|
|
} elsif ($uripath =~ /servers(\.cgi)?\/(\?|)(name|status)/) {
|
| 344 |
|
|
$filter = $3 if ($uripath =~ /servers(\.cgi)?\/\??name(:|=)(.+)/);
|
| 345 |
|
|
$filter = $1 if ($filter =~ /(.*)\*$/);
|
| 346 |
|
|
$statusfilter = $4 if ($uripath =~ /servers(\.cgi)?\/\??(.+ AND )?status(:|=)(\w+)/);
|
| 347 |
|
|
} elsif ($uripath =~ /servers(\.cgi)?\/(\w{8}-\w{4}-\w{4}-\w{4}-\w{12})/) {
|
| 348 |
|
|
$uuidfilter = $2;
|
| 349 |
|
|
}
|
| 350 |
|
|
$filter = $1 if ($filter =~ /(.*)\*/);
|
| 351 |
|
|
|
| 352 |
|
|
my $sysuuid;
|
| 353 |
|
|
if ($params{'system'}) {
|
| 354 |
|
|
$sysuuid = $params{'system'};
|
| 355 |
|
|
$sysuuid = $cursysuuid || $curuuid if ($params{'system'} eq 'this');
|
| 356 |
|
|
}
|
| 357 |
|
|
my @curregvalues;
|
| 358 |
|
|
my @regkeys;
|
| 359 |
|
|
if ($fulllist && $isadmin) {
|
| 360 |
|
|
@regkeys = keys %register;
|
| 361 |
|
|
} elsif ($uuidfilter && $isadmin) {
|
| 362 |
|
|
@regkeys = (tied %register)->select_where("uuid = '$uuidfilter'");
|
| 363 |
|
|
} elsif ($sysuuid) {
|
| 364 |
|
|
@regkeys = (tied %register)->select_where("system = '$sysuuid' OR uuid = '$sysuuid'");
|
| 365 |
|
|
} else {
|
| 366 |
|
|
@regkeys = (tied %register)->select_where("user = '$user'");
|
| 367 |
|
|
}
|
| 368 |
|
|
|
| 369 |
|
|
unless (tie(%sysreg,'Tie::DBI', Hash::Merge::merge({table=>'systems'}, $Stabile::dbopts)) ) {$res .= qq|{"status": "Error": "message": "Unable to access systems register"}|; return $res;};
|
| 370 |
|
|
unless (tie(%imagereg,'Tie::DBI', Hash::Merge::merge({table=>'images', key=>'path'}, $Stabile::dbopts)) ) {$res .= qq|{"status": "Error": "message": "Unable to access images register"}|; return $res;};
|
| 371 |
|
|
|
| 372 |
|
|
foreach my $k (@regkeys) {
|
| 373 |
|
|
$valref = $register{$k};
|
| 374 |
|
|
# Only include VM's belonging to current user (or all users if specified and user is admin)
|
| 375 |
|
|
if ($user eq $valref->{'user'} || $fulllist || ($uuidfilter && $isadmin)) {
|
| 376 |
|
|
next unless (!$sysuuid || $valref->{'system'} eq $sysuuid || $valref->{'uuid'} eq $sysuuid);
|
| 377 |
|
|
|
| 378 |
|
|
my $validatedref = validateItem($valref);
|
| 379 |
|
|
my %val = %{$validatedref}; # Deference and assign to new ass array, effectively cloning object
|
| 380 |
|
|
$val{'memory'} += 0;
|
| 381 |
|
|
$val{'vcpu'} += 0;
|
| 382 |
|
|
$val{'nodetype'} = 'parent';
|
| 383 |
|
|
$val{'internalip'} = $networkreg{$val{'networkuuid1'}}->{'internalip'};
|
| 384 |
|
|
$val{'self'} = 1 if ($curuuid && $curuuid eq $val{'uuid'});
|
| 385 |
|
|
if ($action eq 'treelist') {
|
| 386 |
|
|
if ($val{'system'} && $val{'system'} ne '') {
|
| 387 |
|
|
my $sysuuid = $val{'system'};
|
| 388 |
|
|
my $sysname = $sysreg{$sysuuid}->{'name'};
|
| 389 |
|
|
if (!$sysname) {
|
| 390 |
|
|
$sysname = $1 if ($sysname =~ /(.+)\..*/);
|
| 391 |
|
|
$sysname = $val{'name'};
|
| 392 |
|
|
$sysname =~ s/server/System/i;
|
| 393 |
|
|
}
|
| 394 |
|
|
$sysreg{$sysuuid} = {
|
| 395 |
|
|
uuid => $sysuuid,
|
| 396 |
|
|
name => $sysname,
|
| 397 |
|
|
user => 'irigo'
|
| 398 |
|
|
};
|
| 399 |
|
|
|
| 400 |
|
|
my %pval = %{$sysreg{$sysuuid}};
|
| 401 |
|
|
$pval{'nodetype'} = 'parent';
|
| 402 |
|
|
$pval{'status'} = '--';
|
| 403 |
|
|
$val{'nodetype'} = 'child';
|
| 404 |
|
|
|
| 405 |
|
|
my @children;
|
| 406 |
|
|
push @children,\%val;
|
| 407 |
|
|
$pval{'children'} = \@children;
|
| 408 |
|
|
push @curregvalues,\%pval;
|
| 409 |
|
|
} else {
|
| 410 |
|
|
push @curregvalues,\%val;
|
| 411 |
|
|
}
|
| 412 |
|
|
} elsif ($filter || $statusfilter || $uuidfilter) { # List filtered servers
|
| 413 |
|
|
my $fmatch;
|
| 414 |
|
|
my $smatch;
|
| 415 |
|
|
my $umatch;
|
| 416 |
|
|
$fmatch = 1 if (!$filter || $val{'name'}=~/$filter/i);
|
| 417 |
|
|
$smatch = 1 if (!$statusfilter || $statusfilter eq 'all'
|
| 418 |
|
|
|| $statusfilter eq $val{'status'}
|
| 419 |
|
|
);
|
| 420 |
|
|
$umatch = 1 if ($val{'uuid'} eq $uuidfilter);
|
| 421 |
|
|
if ($fmatch && $smatch && !$uuidfilter) {
|
| 422 |
|
|
push @curregvalues,\%val;
|
| 423 |
|
|
} elsif ($umatch) {
|
| 424 |
|
|
push @curregvalues,\%val;
|
| 425 |
|
|
last;
|
| 426 |
|
|
}
|
| 427 |
|
|
} else {
|
| 428 |
|
|
push @curregvalues,\%val;
|
| 429 |
|
|
}
|
| 430 |
|
|
}
|
| 431 |
|
|
}
|
| 432 |
|
|
tied(%sysreg)->commit;
|
| 433 |
|
|
untie(%sysreg);
|
| 434 |
|
|
untie %imagereg;
|
| 435 |
|
|
@curregvalues = (sort {$a->{'status'} cmp $b->{'status'}} @curregvalues); # Sort by status
|
| 436 |
|
|
|
| 437 |
|
|
# Sort @curregvalues
|
| 438 |
2a63870a
|
Christian Orellana
|
@curregvalues = (sort {$b->{'name'} <=> $a->{'name'}} @curregvalues); # Always sort by name first
|
| 439 |
95b003ff
|
Origo
|
my $sort = 'status';
|
| 440 |
|
|
$sort = $2 if ($uripath =~ /sort\((\+|\-)(\S+)\)/);
|
| 441 |
|
|
my $reverse;
|
| 442 |
|
|
$reverse = 1 if ($1 eq '-');
|
| 443 |
|
|
if ($reverse) { # sort reverse
|
| 444 |
|
|
if ($sort =~ /memory|vcpu/) {
|
| 445 |
|
|
@curregvalues = (sort {$b->{$sort} <=> $a->{$sort}} @curregvalues); # Sort as number
|
| 446 |
|
|
} else {
|
| 447 |
|
|
@curregvalues = (sort {$b->{$sort} cmp $a->{$sort}} @curregvalues); # Sort as string
|
| 448 |
|
|
}
|
| 449 |
|
|
} else {
|
| 450 |
|
|
if ($sort =~ /memory|vcpu/) {
|
| 451 |
|
|
@curregvalues = (sort {$a->{$sort} <=> $b->{$sort}} @curregvalues); # Sort as number
|
| 452 |
|
|
} else {
|
| 453 |
|
|
@curregvalues = (sort {$a->{$sort} cmp $b->{$sort}} @curregvalues); # Sort as string
|
| 454 |
|
|
}
|
| 455 |
|
|
}
|
| 456 |
|
|
|
| 457 |
|
|
if ($action eq 'tablelist') {
|
| 458 |
|
|
my $t2;
|
| 459 |
|
|
|
| 460 |
|
|
if ($isadmin) {
|
| 461 |
|
|
$t2 = Text::SimpleTable->new(36,20,20,10,10,12,7);
|
| 462 |
|
|
$t2->row('uuid', 'name', 'imagename', 'memory', 'user', 'mac', 'status');
|
| 463 |
|
|
} else {
|
| 464 |
|
|
$t2 = Text::SimpleTable->new(36,20,20,10,10,7);
|
| 465 |
|
|
$t2->row('uuid', 'name', 'imagename', 'memory', 'user', 'status');
|
| 466 |
|
|
}
|
| 467 |
|
|
$t2->hr;
|
| 468 |
|
|
my $pattern = $options{m};
|
| 469 |
|
|
foreach $rowref (@curregvalues){
|
| 470 |
|
|
if ($pattern) {
|
| 471 |
|
|
my $rowtext = $rowref->{'uuid'} . " " . $rowref->{'name'} . " " . $rowref->{'imagename'} . " " . $rowref->{'memory'}
|
| 472 |
|
|
. " " . $rowref->{'user'} . " " . $rowref->{'status'};
|
| 473 |
|
|
$rowtext .= " " . $rowref->{'mac'} if ($isadmin);
|
| 474 |
|
|
next unless ($rowtext =~ /$pattern/i);
|
| 475 |
|
|
}
|
| 476 |
|
|
if ($isadmin) {
|
| 477 |
|
|
$t2->row($rowref->{'uuid'}, $rowref->{'name'}, $rowref->{'imagename'}, $rowref->{'memory'},
|
| 478 |
|
|
$rowref->{'user'}, $rowref->{'mac'}, $rowref->{'status'});
|
| 479 |
|
|
} else {
|
| 480 |
|
|
$t2->row($rowref->{'uuid'}, $rowref->{'name'}, $rowref->{'imagename'}, $rowref->{'memory'},
|
| 481 |
|
|
$rowref->{'user'}, $rowref->{'status'});
|
| 482 |
|
|
}
|
| 483 |
|
|
}
|
| 484 |
|
|
$res .= $t2->draw;
|
| 485 |
|
|
} elsif ($console) {
|
| 486 |
|
|
$res .= Dumper(\@curregvalues);
|
| 487 |
|
|
} else {
|
| 488 |
|
|
my $json_text;
|
| 489 |
|
|
if ($uuidfilter && @curregvalues) {
|
| 490 |
|
|
$json_text = to_json($curregvalues[0], {pretty => 1});
|
| 491 |
|
|
} else {
|
| 492 |
|
|
$json_text = to_json(\@curregvalues, {pretty => 1});
|
| 493 |
|
|
}
|
| 494 |
|
|
|
| 495 |
|
|
$json_text =~ s/\x/ /g;
|
| 496 |
|
|
$json_text =~ s/\"\"/"--"/g;
|
| 497 |
c899e439
|
Origo
|
$json_text =~ s/null/"--"/g;
|
| 498 |
04c16f26
|
hq
|
$json_text =~ s/"autostart"\s?:\s?"true"/"autostart": true/g;
|
| 499 |
|
|
$json_text =~ s/"autostart"\s?:\s?"--"/"autostart": false/g;
|
| 500 |
|
|
$json_text =~ s/"locktonode"\s?:\s?"true"/"locktonode": true/g;
|
| 501 |
|
|
$json_text =~ s/"locktonode"\s?:\s?"--"/"locktonode": false/g;
|
| 502 |
|
|
$json_text =~ s/"loader"\s?:\s?"--"/"loader": "bios"/g;
|
| 503 |
95b003ff
|
Origo
|
if ($action eq 'jsonlist' || $action eq 'list' || !$action) {
|
| 504 |
|
|
$res .= $json_text;
|
| 505 |
|
|
} else {
|
| 506 |
|
|
$res .= qq|{"action": "$action", "identifier": "uuid", "label": "uuid", "items" : $json_text}|;
|
| 507 |
|
|
}
|
| 508 |
|
|
}
|
| 509 |
|
|
return $res;
|
| 510 |
|
|
}
|
| 511 |
|
|
|
| 512 |
|
|
sub do_uuidshow {
|
| 513 |
|
|
my ($uuid, $action) = @_;
|
| 514 |
|
|
if ($help) {
|
| 515 |
|
|
return <<END
|
| 516 |
|
|
GET:uuid:
|
| 517 |
|
|
Simple action for showing a single server.
|
| 518 |
|
|
END
|
| 519 |
|
|
}
|
| 520 |
|
|
my $res;
|
| 521 |
|
|
$res .= $Stabile::q->header('text/plain') unless $console;
|
| 522 |
|
|
my $u = $uuid || $options{u};
|
| 523 |
|
|
if ($u || $u eq '0') {
|
| 524 |
|
|
foreach my $uuid (keys %register) {
|
| 525 |
|
|
if (($register{$uuid}->{'user'} eq $user || $register{$uuid}->{'user'} eq 'common' || $isadmin)
|
| 526 |
|
|
&& $uuid =~ /^$u/) {
|
| 527 |
|
|
my %hash = %{$register{$uuid}};
|
| 528 |
|
|
delete $hash{'action'};
|
| 529 |
|
|
my $dump = Dumper(\%hash);
|
| 530 |
|
|
$dump =~ s/undef/"--"/g;
|
| 531 |
|
|
$res .= $dump;
|
| 532 |
|
|
last;
|
| 533 |
|
|
}
|
| 534 |
|
|
}
|
| 535 |
|
|
}
|
| 536 |
|
|
return $res;
|
| 537 |
|
|
}
|
| 538 |
|
|
|
| 539 |
|
|
sub do_uuidlookup {
|
| 540 |
|
|
if ($help) {
|
| 541 |
|
|
return <<END
|
| 542 |
|
|
GET:uuid:
|
| 543 |
|
|
Simple action for looking up a uuid or part of a uuid and returning the complete uuid.
|
| 544 |
|
|
END
|
| 545 |
|
|
}
|
| 546 |
|
|
my $res;
|
| 547 |
|
|
$res .= header('text/plain') unless $console;
|
| 548 |
|
|
my $u = $options{u};
|
| 549 |
|
|
$u = $curuuid unless ($u || $u eq '0');
|
| 550 |
|
|
my $ruuid;
|
| 551 |
|
|
if ($u || $u eq '0') {
|
| 552 |
|
|
my $match;
|
| 553 |
|
|
foreach my $uuid (keys %register) {
|
| 554 |
|
|
if ($uuid =~ /^$u/) {
|
| 555 |
|
|
$ruuid = $uuid if ($register{$uuid}->{'user'} eq $user || index($privileges,"a")!=-1);
|
| 556 |
|
|
$match = 1;
|
| 557 |
|
|
last;
|
| 558 |
|
|
}
|
| 559 |
|
|
}
|
| 560 |
|
|
if (!$match && $isadmin) { # If no match and user is admin, do comprehensive lookup
|
| 561 |
|
|
foreach my $uuid (keys %register) {
|
| 562 |
|
|
if ($uuid =~ /^$u/ || $register{$uuid}->{'name'} =~ /^$u/) {
|
| 563 |
|
|
$ruuid = $uuid;
|
| 564 |
|
|
last;
|
| 565 |
|
|
}
|
| 566 |
|
|
}
|
| 567 |
|
|
}
|
| 568 |
|
|
}
|
| 569 |
|
|
$res .= "$ruuid\n" if ($ruuid);
|
| 570 |
|
|
return $res;
|
| 571 |
|
|
}
|
| 572 |
|
|
|
| 573 |
|
|
sub do_destroyuserservers {
|
| 574 |
6372a66e
|
hq
|
my ($uuid, $action, $obj) = @_;
|
| 575 |
95b003ff
|
Origo
|
if ($help) {
|
| 576 |
|
|
return <<END
|
| 577 |
6372a66e
|
hq
|
GET:username:
|
| 578 |
95b003ff
|
Origo
|
Simple action for destroying all servers belonging to a user
|
| 579 |
|
|
END
|
| 580 |
|
|
}
|
| 581 |
6372a66e
|
hq
|
$username = $obj->{username};
|
| 582 |
95b003ff
|
Origo
|
my $res;
|
| 583 |
|
|
$res .= $Stabile::q->header('text/plain') unless $console;
|
| 584 |
6372a66e
|
hq
|
|
| 585 |
|
|
destroyUserServers($username);
|
| 586 |
95b003ff
|
Origo
|
$res .= $postreply;
|
| 587 |
|
|
return $res;
|
| 588 |
|
|
}
|
| 589 |
|
|
|
| 590 |
|
|
sub do_removeuserservers {
|
| 591 |
|
|
if ($help) {
|
| 592 |
|
|
return <<END
|
| 593 |
|
|
GET::
|
| 594 |
|
|
Simple action for removing all servers belonging to a user
|
| 595 |
|
|
END
|
| 596 |
|
|
}
|
| 597 |
|
|
my $res;
|
| 598 |
|
|
$res .= $Stabile::q->header('text/plain') unless $console;
|
| 599 |
|
|
removeUserServers($user);
|
| 600 |
|
|
$res .= $postreply;
|
| 601 |
|
|
return $res;
|
| 602 |
|
|
}
|
| 603 |
|
|
|
| 604 |
|
|
sub do_getappid {
|
| 605 |
|
|
my ($uuid, $action) = @_;
|
| 606 |
|
|
if ($help) {
|
| 607 |
|
|
return <<END
|
| 608 |
|
|
GET:uuid:
|
| 609 |
|
|
Simple action for getting the app id
|
| 610 |
|
|
END
|
| 611 |
|
|
}
|
| 612 |
|
|
my $res;
|
| 613 |
|
|
$res .= $Stabile::q->header('text/plain') unless $console;
|
| 614 |
|
|
$uuid = $uuid || $options{u};
|
| 615 |
|
|
$uuid = $curuuid unless ($uuid);
|
| 616 |
|
|
if ($uuid && $register{$uuid}) {
|
| 617 |
|
|
unless ( tie(%imagereg,'Tie::DBI', Hash::Merge::merge({table=>'images', key=>'path'}, $Stabile::dbopts)) ) {return "Unable to access image register"};
|
| 618 |
|
|
$res .= "appid: ". $imagereg{$register{$uuid}->{image}}->{appid}, "\n";
|
| 619 |
|
|
untie %imagereg;
|
| 620 |
|
|
}
|
| 621 |
|
|
return $res;
|
| 622 |
|
|
}
|
| 623 |
|
|
|
| 624 |
|
|
sub do_setrunning {
|
| 625 |
|
|
my ($uuid, $action) = @_;
|
| 626 |
|
|
if ($help) {
|
| 627 |
|
|
return <<END
|
| 628 |
|
|
GET:uuid:
|
| 629 |
|
|
Simple action for setting status back to running after e.g. an upgrade
|
| 630 |
|
|
END
|
| 631 |
|
|
}
|
| 632 |
|
|
my $res;
|
| 633 |
|
|
$res .= $Stabile::q->header('text/plain') unless $console;
|
| 634 |
|
|
$uuid = $uuid || $options{u};
|
| 635 |
|
|
$uuid = $curuuid unless ($uuid);
|
| 636 |
|
|
if ($uuid && $register{$uuid}) {
|
| 637 |
|
|
$register{$uuid}->{'status'} = 'running';
|
| 638 |
|
|
$main::updateUI->({ tab => 'servers',
|
| 639 |
|
|
user => $user,
|
| 640 |
|
|
uuid => $uuid,
|
| 641 |
|
|
status => 'running' })
|
| 642 |
|
|
|
| 643 |
|
|
};
|
| 644 |
|
|
$res .= "Status=OK Set status of $register{$uuid}->{'name'} to running\n";
|
| 645 |
|
|
return $res;
|
| 646 |
|
|
}
|
| 647 |
|
|
|
| 648 |
|
|
sub do_getappinfo {
|
| 649 |
|
|
my ($uuid, $action) = @_;
|
| 650 |
|
|
if ($help) {
|
| 651 |
|
|
return <<END
|
| 652 |
|
|
GET:uuid:
|
| 653 |
|
|
Simple action for getting the apps basic info
|
| 654 |
|
|
END
|
| 655 |
|
|
}
|
| 656 |
|
|
my $res;
|
| 657 |
|
|
$res .= $Stabile::q->header('application/json') unless $console;
|
| 658 |
|
|
$uuid = $uuid || $options{u};
|
| 659 |
|
|
$uuid = $curuuid unless ($uuid);
|
| 660 |
|
|
my %appinfo;
|
| 661 |
|
|
if ($uuid && $register{$uuid}) {
|
| 662 |
|
|
unless ( tie(%imagereg,'Tie::DBI', Hash::Merge::merge({table=>'images', key=>'path'}, $Stabile::dbopts)) ) {return "Unable to access image register"};
|
| 663 |
|
|
$appinfo{'appid'} = $imagereg{$register{$uuid}->{image}}->{appid} || '';
|
| 664 |
|
|
$appinfo{'managementlink'} = $imagereg{$register{$uuid}->{image}}->{managementlink} || '';
|
| 665 |
|
|
$appinfo{'managementlink'} =~ s/{uuid}/$register{$uuid}->{networkuuid1}/;
|
| 666 |
|
|
|
| 667 |
|
|
my $termlink = $imagereg{$register{$uuid}->{image}}->{terminallink} || '';
|
| 668 |
|
|
$termlink =~ s/{uuid}/$register{$uuid}->{networkuuid1}/;
|
| 669 |
|
|
my $burl = $baseurl;
|
| 670 |
|
|
$burl = $1 if ($termlink =~ /\/stabile/ && $baseurl =~ /(.+)\/stabile/); # Unpretty, but works for now
|
| 671 |
6fdc8676
|
hq
|
# $termlink = $1 if ($termlink =~ /\/(.+)/);
|
| 672 |
|
|
# $termlink = "$burl/$termlink" unless ($termlink =~ /^http/ || !$termlink); # || $termlink =~ /^\//
|
| 673 |
95b003ff
|
Origo
|
$appinfo{'terminallink'} = $termlink;
|
| 674 |
|
|
|
| 675 |
|
|
$appinfo{'upgradelink'} = $imagereg{$register{$uuid}->{image}}->{upgradelink} || '';
|
| 676 |
|
|
$appinfo{'upgradelink'} =~ s/{uuid}/$register{$uuid}->{networkuuid1}/;
|
| 677 |
|
|
$appinfo{'version'} = $imagereg{$register{$uuid}->{image}}->{version} || '';
|
| 678 |
|
|
$appinfo{'status'} = $register{$uuid}->{status} || '';
|
| 679 |
|
|
$appinfo{'name'} = $register{$uuid}->{name} || '';
|
| 680 |
d3d1a2d4
|
Origo
|
$appinfo{'system'} = $register{$uuid}->{system} || '';
|
| 681 |
|
|
|
| 682 |
|
|
if ($appinfo{'system'}) {
|
| 683 |
|
|
unless (tie(%sysreg,'Tie::DBI', Hash::Merge::merge({table=>'systems'}, $Stabile::dbopts)) ) {$res .= qq|{"status": "Error": "message": "Unable to access systems register"}|; return $res;};
|
| 684 |
|
|
$appinfo{'systemname'} = $sysreg{$appinfo{'system'}}->{name} || '';
|
| 685 |
|
|
untie(%sysreg);
|
| 686 |
|
|
} else {
|
| 687 |
|
|
$appinfo{'systemname'} = $appinfo{'name'};
|
| 688 |
|
|
}
|
| 689 |
|
|
|
| 690 |
95b003ff
|
Origo
|
|
| 691 |
|
|
if ($appinfo{'appid'}) {
|
| 692 |
|
|
my @regkeys = (tied %imagereg)->select_where("appid = '$appinfo{appid}'");
|
| 693 |
|
|
foreach my $k (@regkeys) {
|
| 694 |
|
|
my $imgref = $imagereg{$k};
|
| 695 |
|
|
if ($imgref->{'path'} =~ /\.master\.qcow2$/ && $imgref->{'appid'} eq $appinfo{'appid'}
|
| 696 |
|
|
&& $imgref->{'installable'} && $imgref->{'installable'} ne 'false'
|
| 697 |
|
|
) {
|
| 698 |
|
|
if ($imgref->{'version'} > $appinfo{'currentversion'}) {
|
| 699 |
|
|
$appinfo{'currentversion'} = $imgref->{'version'};
|
| 700 |
|
|
$appinfo{'appname'} = $imgref->{'name'};
|
| 701 |
|
|
}
|
| 702 |
|
|
}
|
| 703 |
|
|
}
|
| 704 |
|
|
}
|
| 705 |
|
|
|
| 706 |
|
|
untie %imagereg;
|
| 707 |
|
|
}
|
| 708 |
|
|
$appinfo{'appstoreurl'} = $appstoreurl;
|
| 709 |
|
|
$appinfo{'dnsdomain'} = ($enginelinked)?$dnsdomain:'';
|
| 710 |
6fdc8676
|
hq
|
$appinfo{'dnssubdomain'} = ($enginelinked)?substr($engineid, 0, 8):'';
|
| 711 |
95b003ff
|
Origo
|
$appinfo{'uuid'} = $uuid;
|
| 712 |
|
|
$appinfo{'user'} = $user;
|
| 713 |
|
|
$appinfo{'remoteip'} = $remoteip;
|
| 714 |
|
|
$res .= to_json(\%appinfo, { pretty => 1 });
|
| 715 |
|
|
return $res;
|
| 716 |
|
|
}
|
| 717 |
|
|
|
| 718 |
|
|
sub do_removeserver {
|
| 719 |
|
|
if ($help) {
|
| 720 |
|
|
return <<END
|
| 721 |
|
|
GET:uuid:
|
| 722 |
|
|
Simple action for destroying and removing a single server
|
| 723 |
|
|
END
|
| 724 |
|
|
}
|
| 725 |
|
|
my $res;
|
| 726 |
|
|
$res .= $Stabile::q->header('text/plain') unless $console;
|
| 727 |
|
|
if ($curuuid) {
|
| 728 |
|
|
removeUserServers($user, $curuuid, 1);
|
| 729 |
|
|
}
|
| 730 |
|
|
else {
|
| 731 |
|
|
$postreply .= "Status=Error Unable to uninstall\n";
|
| 732 |
|
|
}
|
| 733 |
|
|
$res .= $postreply;
|
| 734 |
|
|
return $res;
|
| 735 |
|
|
}
|
| 736 |
|
|
|
| 737 |
|
|
sub do_updateregister {
|
| 738 |
|
|
if ($help) {
|
| 739 |
|
|
return <<END
|
| 740 |
|
|
GET::
|
| 741 |
|
|
Update server register
|
| 742 |
|
|
END
|
| 743 |
|
|
}
|
| 744 |
|
|
my $res;
|
| 745 |
|
|
$res .= $Stabile::q->header('text/plain') unless $console;
|
| 746 |
|
|
return unless $isadmin;
|
| 747 |
|
|
updateRegister();
|
| 748 |
|
|
$res .= "Status=OK Updated server registry for all users\n";
|
| 749 |
|
|
return $res;
|
| 750 |
|
|
}
|
| 751 |
|
|
|
| 752 |
|
|
sub Autostartall {
|
| 753 |
|
|
my ($uuid, $action) = @_;
|
| 754 |
|
|
if ($help) {
|
| 755 |
|
|
return <<END
|
| 756 |
|
|
GET::
|
| 757 |
|
|
Start all servers marked for autostart. When called as showautostart only shows which would be started.
|
| 758 |
|
|
END
|
| 759 |
|
|
}
|
| 760 |
|
|
my $res;
|
| 761 |
|
|
$res .= $Stabile::q->header('text/plain') unless $console;
|
| 762 |
|
|
my $mes;
|
| 763 |
|
|
return $res if ($isreadonly);
|
| 764 |
|
|
|
| 765 |
|
|
# Wait for all pistons to be online
|
| 766 |
|
|
my $nodedown;
|
| 767 |
|
|
my $nodecount;
|
| 768 |
f222b89c
|
hq
|
for (my $i = 0; $i < 20; $i++) {
|
| 769 |
95b003ff
|
Origo
|
$nodedown = 0;
|
| 770 |
|
|
foreach my $node (values %nodereg) {
|
| 771 |
|
|
if ($node->{'status'} ne 'running' && $node->{'status'} ne 'maintenance') {
|
| 772 |
|
|
$nodedown = 1;
|
| 773 |
|
|
}
|
| 774 |
|
|
else {
|
| 775 |
|
|
$nodecount++ unless ($node->{'status'} eq 'maintenance');
|
| 776 |
|
|
}
|
| 777 |
|
|
}
|
| 778 |
|
|
if ($nodedown) {
|
| 779 |
|
|
# Wait and see if nodes come online
|
| 780 |
|
|
$mes = "Waiting for nodes...(" . (10 - $i) . ")\n";
|
| 781 |
|
|
print $mes if ($console);
|
| 782 |
|
|
$res .= $mes;
|
| 783 |
f222b89c
|
hq
|
sleep 10;
|
| 784 |
95b003ff
|
Origo
|
}
|
| 785 |
|
|
else {
|
| 786 |
|
|
last;
|
| 787 |
|
|
}
|
| 788 |
|
|
}
|
| 789 |
|
|
|
| 790 |
a2e0bc7e
|
hq
|
$mes = "$nodecount nodes ready - autostarting servers...\n";
|
| 791 |
f222b89c
|
hq
|
$main::syslogit->("irigo", "info", "$nodecount nodes ready - autostarting servers...");
|
| 792 |
|
|
|
| 793 |
a2e0bc7e
|
hq
|
print $mes if ($console);
|
| 794 |
|
|
$res .= $mes;
|
| 795 |
95b003ff
|
Origo
|
if (!%nodereg || $nodedown || !$nodecount) {
|
| 796 |
a2e0bc7e
|
hq
|
$mes = "Only autostarting servers on local node - not all nodes ready!\n";
|
| 797 |
95b003ff
|
Origo
|
print $mes if ($console);
|
| 798 |
|
|
$res .= $mes;
|
| 799 |
|
|
}
|
| 800 |
a2e0bc7e
|
hq
|
if ($action eq "showautostart") {
|
| 801 |
|
|
$mes = "Only showing which servers would be starting!\n";
|
| 802 |
95b003ff
|
Origo
|
print $mes if ($console);
|
| 803 |
|
|
$res .= $mes;
|
| 804 |
a2e0bc7e
|
hq
|
}
|
| 805 |
95b003ff
|
Origo
|
|
| 806 |
a2e0bc7e
|
hq
|
$Stabile::Networks::user = $user;
|
| 807 |
|
|
require "$Stabile::basedir/cgi/networks.cgi";
|
| 808 |
|
|
$Stabile::Networks::console = 1;
|
| 809 |
|
|
|
| 810 |
|
|
foreach my $dom (values %register) {
|
| 811 |
|
|
if ($nodedown) { # Only start local servers
|
| 812 |
|
|
unless ($dom->{mac} && $nodereg{$dom->{mac}}->{identity} eq 'local_kvm') {
|
| 813 |
|
|
$mes = "Skipping non-local domain $dom->{name}, $dom->{status}\n";
|
| 814 |
|
|
print $mes if ($console);
|
| 815 |
|
|
$res .= $mes;
|
| 816 |
|
|
next;
|
| 817 |
|
|
}
|
| 818 |
|
|
}
|
| 819 |
|
|
if ($dom->{'autostart'} eq '1' || $dom->{'autostart'} eq 'true') {
|
| 820 |
|
|
$res .= "Checking if $dom->{'name'} ($dom->{'user'}, $dom->{'uuid'}) should be started\n";
|
| 821 |
|
|
my $networkstatus1 = $networkreg{$dom->{'networkuuid1'}}->{status};
|
| 822 |
|
|
my $networkstatus2 = ($networkreg{$dom->{'networkuuid2'}})?$networkreg{$dom->{'networkuuid2'}}->{status}:'';
|
| 823 |
|
|
my $networkstatus3 = ($networkreg{$dom->{'networkuuid3'}})?$networkreg{$dom->{'networkuuid3'}}->{status}:'';
|
| 824 |
|
|
my @dnets;
|
| 825 |
|
|
push @dnets, $dom->{'networkuuid1'} if ($dom->{'networkuuid1'} && $dom->{'networkuuid1'} ne '--' && $networkstatus1 ne 'up');
|
| 826 |
|
|
push @dnets, $dom->{'networkuuid2'} if ($dom->{'networkuuid2'} && $dom->{'networkuuid2'} ne '--' && $networkstatus2 ne 'up');
|
| 827 |
|
|
push @dnets, $dom->{'networkuuid3'} if ($dom->{'networkuuid3'} && $dom->{'networkuuid3'} ne '--' && $networkstatus3 ne 'up');
|
| 828 |
|
|
my $i;
|
| 829 |
|
|
for ($i=0; $i<5; $i++) { # wait for status newer than 10 secs
|
| 830 |
|
|
validateItem($dom);
|
| 831 |
|
|
last if (time() - $dom->{timestamp} < 10);
|
| 832 |
|
|
$mes = "Waiting for newer timestamp, current is " . (time() - $dom->{timestamp}) . " old\n";
|
| 833 |
|
|
print $mes if ($console);
|
| 834 |
|
|
$res .= $mes;
|
| 835 |
|
|
sleep 2;
|
| 836 |
|
|
}
|
| 837 |
|
|
if (
|
| 838 |
|
|
$dom->{'status'} eq 'shutoff' || $dom->{'status'} eq 'inactive'
|
| 839 |
|
|
) {
|
| 840 |
|
|
if ($action eq "showautostart") { # Dry run
|
| 841 |
|
|
$mes = "Starting $dom->{'name'} ($dom->{'user'}, $dom->{'uuid'})\n";
|
| 842 |
95b003ff
|
Origo
|
print $mes if ($console);
|
| 843 |
|
|
$res .= $mes;
|
| 844 |
|
|
}
|
| 845 |
a2e0bc7e
|
hq
|
else {
|
| 846 |
|
|
$mes = "Starting $dom->{'name'} ($dom->{'user'}, $dom->{'uuid'})\n";
|
| 847 |
|
|
print $mes if ($console);
|
| 848 |
|
|
$res .= $mes;
|
| 849 |
|
|
$postreply = Start($dom->{'uuid'});
|
| 850 |
|
|
print $postreply if ($console);
|
| 851 |
|
|
$res .= $postreply;
|
| 852 |
|
|
# $mes = `REMOTE_USER=$dom->{'user'} $base/cgi/servers.cgi -a start -u $dom->{'uuid'}`;
|
| 853 |
|
|
print $mes if ($console);
|
| 854 |
|
|
$res .= $mes;
|
| 855 |
|
|
sleep 1;
|
| 856 |
|
|
}
|
| 857 |
|
|
}
|
| 858 |
|
|
elsif (@dnets) {
|
| 859 |
|
|
if ($action eq "showautostart") { # Dry run
|
| 860 |
|
|
foreach my $networkuuid (@dnets) {
|
| 861 |
|
|
$mes = "Would bring network $networkreg{$networkuuid}->{name} up for $dom->{'name'} ($dom->{'user'}, $dom->{'uuid'})\n";
|
| 862 |
95b003ff
|
Origo
|
print $mes if ($console);
|
| 863 |
|
|
$res .= $mes;
|
| 864 |
|
|
}
|
| 865 |
a2e0bc7e
|
hq
|
}
|
| 866 |
|
|
else {
|
| 867 |
|
|
foreach my $networkuuid (@dnets) {
|
| 868 |
|
|
$mes = "Bringing network $networkreg{$networkuuid}->{name} up for $dom->{'name'} ($dom->{'user'}, $dom->{'uuid'})\n";
|
| 869 |
95b003ff
|
Origo
|
print $mes if ($console);
|
| 870 |
|
|
$res .= $mes;
|
| 871 |
a2e0bc7e
|
hq
|
$mes = Stabile::Networks::Activate($networkuuid, 'activate');
|
| 872 |
48fcda6b
|
Origo
|
print $mes if ($console);
|
| 873 |
|
|
$res .= $mes;
|
| 874 |
95b003ff
|
Origo
|
sleep 1;
|
| 875 |
|
|
}
|
| 876 |
|
|
}
|
| 877 |
|
|
}
|
| 878 |
a2e0bc7e
|
hq
|
} else {
|
| 879 |
|
|
$res .= "Not marked for autostart ($dom->{'autostart'}): $dom->{'name'} ($dom->{'user'}, $dom->{'uuid'})\n";
|
| 880 |
|
|
validateItem($dom);
|
| 881 |
95b003ff
|
Origo
|
}
|
| 882 |
|
|
}
|
| 883 |
|
|
return $res;
|
| 884 |
|
|
}
|
| 885 |
|
|
|
| 886 |
|
|
sub do_listnodeavailability {
|
| 887 |
|
|
if ($help) {
|
| 888 |
|
|
return <<END
|
| 889 |
|
|
GET::
|
| 890 |
|
|
Utility call - only informational. Shows availability of nodes for starting servers.
|
| 891 |
|
|
END
|
| 892 |
|
|
}
|
| 893 |
|
|
my $res;
|
| 894 |
|
|
$res .= $Stabile::q->header('application/json') unless ($console);
|
| 895 |
|
|
my ($temp1, $temp2, $temp3, $temp4, $ahashref) = locateTargetNode();
|
| 896 |
|
|
my @avalues = values %$ahashref;
|
| 897 |
|
|
my @sorted_values = (sort {$b->{'index'} <=> $a->{'index'}} @avalues);
|
| 898 |
|
|
$res .= to_json(\@sorted_values, { pretty => 1 });
|
| 899 |
|
|
return $res;
|
| 900 |
|
|
}
|
| 901 |
|
|
|
| 902 |
|
|
sub do_listbillingdata {
|
| 903 |
|
|
if ($help) {
|
| 904 |
|
|
return <<END
|
| 905 |
|
|
GET::
|
| 906 |
|
|
List current billing data.
|
| 907 |
|
|
END
|
| 908 |
|
|
}
|
| 909 |
|
|
my $res;
|
| 910 |
|
|
$res .= $Stabile::q->header('application/json') unless ($console);
|
| 911 |
|
|
my $buser = URI::Escape::uri_unescape($params{'user'}) || $user;
|
| 912 |
|
|
my %b;
|
| 913 |
|
|
my @bmonths;
|
| 914 |
|
|
if ($isadmin || $buser eq $user) {
|
| 915 |
|
|
my $bmonth = URI::Escape::uri_unescape($params{'month'}) || $month;
|
| 916 |
|
|
my $byear = URI::Escape::uri_unescape($params{'year'}) || $year;
|
| 917 |
|
|
if ($bmonth eq "all") {
|
| 918 |
|
|
@bmonths = ("01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12");
|
| 919 |
|
|
}
|
| 920 |
|
|
else {
|
| 921 |
|
|
@bmonths = ($bmonth);
|
| 922 |
|
|
}
|
| 923 |
|
|
|
| 924 |
|
|
unless ( tie(%billingreg,'Tie::DBI', Hash::Merge::merge({table=>'billing_domains', key=>'usernodetime'}, $Stabile::dbopts)) ) {return "Unable to access billing register"};
|
| 925 |
|
|
|
| 926 |
|
|
my @nkeys = keys %nodereg;
|
| 927 |
|
|
foreach my $bm (@bmonths) {
|
| 928 |
|
|
my $vcpuavg = 0;
|
| 929 |
|
|
my $memoryavg = 0;
|
| 930 |
|
|
foreach my $nmac (@nkeys) {
|
| 931 |
|
|
$vcpuavg += $billingreg{"$buser-$nmac-$byear-$bm"}->{'vcpuavg'};
|
| 932 |
|
|
$memoryavg += $billingreg{"$buser-$nmac-$byear-$bm"}->{'memoryavg'};
|
| 933 |
|
|
}
|
| 934 |
|
|
$b{"$buser-$byear-$bm"} = {
|
| 935 |
|
|
id => "$buser-$byear-$bm",
|
| 936 |
|
|
vcpuavg => $vcpuavg,
|
| 937 |
|
|
memoryavg => $memoryavg,
|
| 938 |
|
|
month => $bm + 0,
|
| 939 |
|
|
year => $byear + 0
|
| 940 |
|
|
}
|
| 941 |
|
|
}
|
| 942 |
|
|
untie %billingreg;
|
| 943 |
|
|
}
|
| 944 |
|
|
my @bvalues = values %b;
|
| 945 |
|
|
$res .= "{\"identifier\": \"id\", \"label\": \"id\", \"items\":" . to_json(\@bvalues) . "}";
|
| 946 |
|
|
return $res;
|
| 947 |
|
|
}
|
| 948 |
|
|
|
| 949 |
|
|
# Print list of available actions on objects
|
| 950 |
|
|
sub do_plainhelp {
|
| 951 |
|
|
my $res;
|
| 952 |
|
|
$res .= $Stabile::q->header('text/plain') unless $console;
|
| 953 |
|
|
$res .= <<END
|
| 954 |
|
|
new [name="name"]
|
| 955 |
|
|
* start: Starts a server
|
| 956 |
|
|
* destroy: Destroys a server, i.e. terminates the VM, equivalent of turning the power off a physical computer
|
| 957 |
|
|
* shutdown: Asks the operating system of a server to shut down via ACPI
|
| 958 |
|
|
* suspend: Suspends the VM, effectively putting the server to sleep
|
| 959 |
|
|
* resume: Resumes a suspended VM, effectively waking the server from sleep
|
| 960 |
|
|
* move [mac="mac"]: Moves a server to specified node. If no node is specified, moves to other node with highest availability
|
| 961 |
|
|
index
|
| 962 |
|
|
* delete: Deletes a server. Image and network are not deleted, only information about the server. Server cannot be
|
| 963 |
|
|
runing
|
| 964 |
|
|
* mountcd [cdrom="path"]: Mounts a cd rom
|
| 965 |
|
|
END
|
| 966 |
|
|
;
|
| 967 |
|
|
return $res;
|
| 968 |
|
|
}
|
| 969 |
|
|
|
| 970 |
|
|
# Helper function
|
| 971 |
|
|
sub recurse($) {
|
| 972 |
|
|
my($path) = @_;
|
| 973 |
|
|
my @files;
|
| 974 |
|
|
## append a trailing / if it's not there
|
| 975 |
|
|
$path .= '/' if($path !~ /\/$/);
|
| 976 |
|
|
## loop through the files contained in the directory
|
| 977 |
|
|
for my $eachFile (glob($path.'*')) {
|
| 978 |
|
|
## if the file is a directory
|
| 979 |
|
|
if( -d $eachFile) {
|
| 980 |
|
|
## pass the directory to the routine ( recursion )
|
| 981 |
|
|
push(@files,recurse($eachFile));
|
| 982 |
|
|
} else {
|
| 983 |
|
|
push(@files,$eachFile);
|
| 984 |
|
|
}
|
| 985 |
|
|
}
|
| 986 |
|
|
return @files;
|
| 987 |
|
|
}
|
| 988 |
|
|
|
| 989 |
|
|
sub Start {
|
| 990 |
|
|
my ($uuid, $action, $obj) = @_;
|
| 991 |
|
|
$dmac = $obj->{mac};
|
| 992 |
|
|
$buildsystem = $obj->{buildsystem};
|
| 993 |
|
|
$uistatus = $obj->{uistatus};
|
| 994 |
|
|
if ($help) {
|
| 995 |
|
|
return <<END
|
| 996 |
|
|
GET:uuid,mac:
|
| 997 |
|
|
Start a server. Supply mac for starting on specific node.
|
| 998 |
|
|
END
|
| 999 |
|
|
}
|
| 1000 |
|
|
$dmac = $dmac || $params{'mac'};
|
| 1001 |
|
|
return "Status=ERROR No uuid\n" unless ($register{$uuid});
|
| 1002 |
|
|
my $serv = $register{$uuid};
|
| 1003 |
|
|
$postreply = '' if ($buildsystem);
|
| 1004 |
|
|
|
| 1005 |
|
|
my $name = $serv->{'name'};
|
| 1006 |
|
|
utf8::decode($name);
|
| 1007 |
|
|
my $image = $serv->{'image'};
|
| 1008 |
|
|
my $image2 = $serv->{'image2'};
|
| 1009 |
|
|
my $image3 = $serv->{'image3'};
|
| 1010 |
|
|
my $image4 = $serv->{'image4'};
|
| 1011 |
|
|
my $memory = $serv->{'memory'};
|
| 1012 |
|
|
my $vcpu = $serv->{'vcpu'};
|
| 1013 |
|
|
my $vgpu = $serv->{'vgpu'};
|
| 1014 |
|
|
my $dbstatus = $serv->{'status'};
|
| 1015 |
|
|
my $mac = $serv->{'mac'};
|
| 1016 |
|
|
my $macname = $serv->{'macname'};
|
| 1017 |
|
|
my $networkuuid1 = $serv->{'networkuuid1'};
|
| 1018 |
|
|
my $networkuuid2 = $serv->{'networkuuid2'};
|
| 1019 |
|
|
my $networkuuid3 = $serv->{'networkuuid3'};
|
| 1020 |
|
|
my $nicmodel1 = $serv->{'nicmodel1'};
|
| 1021 |
|
|
my $nicmac1 = $serv->{'nicmac1'};
|
| 1022 |
|
|
my $nicmac2 = $serv->{'nicmac2'};
|
| 1023 |
|
|
my $nicmac3 = $serv->{'nicmac3'};
|
| 1024 |
|
|
my $boot = $serv->{'boot'};
|
| 1025 |
04c16f26
|
hq
|
my $loader = $serv->{'loader'};
|
| 1026 |
95b003ff
|
Origo
|
my $diskbus = $serv->{'diskbus'};
|
| 1027 |
|
|
my $cdrom = $serv->{'cdrom'};
|
| 1028 |
|
|
my $diskdev = "vda";
|
| 1029 |
|
|
my $diskdev2 = "vdb";
|
| 1030 |
|
|
my $diskdev3 = "vdc";
|
| 1031 |
|
|
my $diskdev4 = "vdd";
|
| 1032 |
|
|
if ($diskbus eq "ide") {$diskdev = "hda"; $diskdev2 = "hdb"; $diskdev3 = "hdc"; $diskdev4 = "hdd"};
|
| 1033 |
|
|
|
| 1034 |
|
|
my $mem = $memory * 1024;
|
| 1035 |
|
|
|
| 1036 |
|
|
unless ( tie(%imagereg,'Tie::DBI', Hash::Merge::merge({table=>'images', key=>'path'}, $Stabile::dbopts)) ) {return "Unable to access image register"};
|
| 1037 |
|
|
|
| 1038 |
|
|
my $img = $imagereg{$image};
|
| 1039 |
|
|
my $imagename = $img->{'name'};
|
| 1040 |
|
|
my $imagestatus = $img->{'status'};
|
| 1041 |
|
|
my $img2 = $imagereg{$image2};
|
| 1042 |
|
|
my $image2status = $img2->{'status'};
|
| 1043 |
|
|
my $img3 = $imagereg{$image3};
|
| 1044 |
|
|
my $image3status = $img3->{'status'};
|
| 1045 |
|
|
my $img4 = $imagereg{$image4};
|
| 1046 |
|
|
my $image4status = $img4->{'status'};
|
| 1047 |
|
|
|
| 1048 |
|
|
if (!$imagereg{$image}) {
|
| 1049 |
|
|
$postreply .= "Status=Error Image $image not found - please select a new image for your server, not starting $name\n";
|
| 1050 |
|
|
untie %imagereg;
|
| 1051 |
|
|
return $postreply;
|
| 1052 |
|
|
}
|
| 1053 |
|
|
untie %imagereg;
|
| 1054 |
|
|
|
| 1055 |
|
|
if ($imagestatus ne "used" && $imagestatus ne "cloning") {
|
| 1056 |
|
|
$postreply .= "Status=ERROR Image $imagename $image is $imagestatus, not starting $name\n";
|
| 1057 |
|
|
} elsif ($image2 && $image2 ne '--' && $image2status ne "used" && $image2status ne "cloning") {
|
| 1058 |
|
|
$postreply .= "Status=ERROR Image2 is $image2status, not starting $name\n";
|
| 1059 |
|
|
} elsif ($image3 && $image3 ne '--' && $image3status ne "used" && $image3status ne "cloning") {
|
| 1060 |
|
|
$postreply .= "Status=ERROR Image3 is $image3status, not starting $name\n";
|
| 1061 |
|
|
} elsif ($image4 && $image4 ne '--' && $image4status ne "used" && $image4status ne "cloning") {
|
| 1062 |
|
|
$postreply .= "Status=ERROR Image4 is $image4status, not starting $name\n";
|
| 1063 |
a2e0bc7e
|
hq
|
} elsif (Stabile::Servers::overQuotas($memory,$vcpu)) {
|
| 1064 |
|
|
$main::syslogit->($user, "info", "Over quota ($memory, $vcpu, " . Stabile::Servers::overQuotas($memory,$vcpu) . ") starting a $dbstatus domain: $uuid");
|
| 1065 |
95b003ff
|
Origo
|
$postreply .= "Status=ERROR Over quota - not starting $name\n";
|
| 1066 |
|
|
# Status inactive is typically caused by a movepiston having problems. We should not start inactive servers since
|
| 1067 |
|
|
# they could possibly be running even if movepiston is down. Movepiston on the node should be brought up to update
|
| 1068 |
|
|
# the status, or the node should be removed from the stabile.
|
| 1069 |
|
|
# We now allow to force start of inactive server when dmac is specified
|
| 1070 |
|
|
} elsif ((!$dmac || $dmac eq $mac) && $dbstatus eq 'inactive' && $nodereg{$mac} && ($nodereg{$mac}->{'status'} eq 'inactive' || $nodereg{$mac}->{'status'} eq 'shutdown')) {
|
| 1071 |
|
|
$main::syslogit->($user, "info", "Not starting inactive domain: $uuid (last seen on $mac)");
|
| 1072 |
|
|
$postreply .= "Status=ERROR Not starting $name - Please bring up node $macname\n";
|
| 1073 |
|
|
} elsif ($dbstatus eq 'inactive' || $dbstatus eq 'shutdown' || $dbstatus eq 'shutoff' || $dbstatus eq 'new') {
|
| 1074 |
|
|
unless ($dmac && $isadmin) {
|
| 1075 |
|
|
$dmac = $mac if ($dbstatus eq 'inactive'); # If movepiston crashed while shutting down, allow server to start on same node
|
| 1076 |
|
|
}
|
| 1077 |
|
|
$uistatus = "starting" unless ($uistatus);
|
| 1078 |
|
|
my $hypervisor = getHypervisor($image);
|
| 1079 |
|
|
my ($targetmac, $targetname, $targetip, $port) = locateTargetNode($uuid, $dmac, $mem, $vcpu, $image, $image2 ,$image3, $image4, $hypervisor);
|
| 1080 |
|
|
|
| 1081 |
a2e0bc7e
|
hq
|
# Read limits from nodeconfig
|
| 1082 |
|
|
my $vm_readlimit = '';
|
| 1083 |
|
|
my $vm_writelimit = '';
|
| 1084 |
|
|
my $vm_iopsreadlimit = ''; # e.g. 1000 IOPS
|
| 1085 |
|
|
my $vm_iopswritelimit = '';
|
| 1086 |
|
|
if (-e "/etc/stabile/nodeconfig.cfg") {
|
| 1087 |
|
|
my $nodecfg = new Config::Simple("/etc/stabile/nodeconfig.cfg");
|
| 1088 |
|
|
$vm_readlimit = $nodecfg->param('VM_READ_LIMIT'); # e.g. 125829120 = 120 * 1024 * 1024 = 120 MB / s
|
| 1089 |
|
|
$vm_writelimit = $nodecfg->param('VM_WRITE_LIMIT');
|
| 1090 |
|
|
$vm_iopsreadlimit = $nodecfg->param('VM_IOPS_READ_LIMIT'); # e.g. 1000 IOPS
|
| 1091 |
|
|
$vm_iopswritelimit = $nodecfg->param('VM_IOPS_WRITE_LIMIT');
|
| 1092 |
|
|
}
|
| 1093 |
|
|
|
| 1094 |
95b003ff
|
Origo
|
# Build XML for starting domain
|
| 1095 |
|
|
my $graphics = "vnc";
|
| 1096 |
|
|
$graphics = "rdp" if ($hypervisor eq "vbox");
|
| 1097 |
|
|
my $net1 = $networkreg{$networkuuid1};
|
| 1098 |
|
|
my $networkid1 = $net1->{'id'}; # Get the current vlan id of the network
|
| 1099 |
|
|
my $net2 = $networkreg{$networkuuid2};
|
| 1100 |
|
|
my $networkid2 = $net2->{'id'}; # Get the current vlan id of the network
|
| 1101 |
|
|
my $net3 = $networkreg{$networkuuid2};
|
| 1102 |
|
|
my $networkid3 = $net3->{'id'}; # Get the current vlan id of the network
|
| 1103 |
|
|
my $networkid1ip = $net1->{'internalip'};
|
| 1104 |
|
|
$networkid1ip = $net1->{'externalip'} if ($net1->{'type'} eq 'externalip');
|
| 1105 |
|
|
|
| 1106 |
|
|
my $uname = $name . substr($uuid,0,8); # We don't enforce unique names, so we make them
|
| 1107 |
|
|
$uname =~ s/[^[:ascii:]]/_/g; # Get rid of funny chars - they mess up Guacamole
|
| 1108 |
|
|
$uname =~ s/\W/_/g;
|
| 1109 |
|
|
|
| 1110 |
|
|
my $driver1;
|
| 1111 |
|
|
my $driver2;
|
| 1112 |
|
|
if ($hypervisor eq 'kvm') {
|
| 1113 |
|
|
my $fmt1 = ($image =~ /\.qcow2$/)?'qcow2':'raw';
|
| 1114 |
|
|
my $fmt2 = ($image2 =~ /\.qcow2$/)?'qcow2':'raw';
|
| 1115 |
|
|
my $fmt3 = ($image3 =~ /\.qcow2$/)?'qcow2':'raw';
|
| 1116 |
|
|
my $fmt4 = ($image4 =~ /\.qcow2$/)?'qcow2':'raw';
|
| 1117 |
2a63870a
|
Christian Orellana
|
my $cache1 = ($image =~ /\/node\//)?'default':'writeback';
|
| 1118 |
|
|
my $cache2 = ($image2 =~ /\/node\//)?'default':'writeback';
|
| 1119 |
|
|
my $cache3 = ($image3 =~ /\/node\//)?'default':'writeback';
|
| 1120 |
|
|
my $cache4 = ($image4 =~ /\/node\//)?'default':'writeback';
|
| 1121 |
|
|
$driver1 = "\n <driver name='qemu' type='$fmt1' cache='$cache1'/>";
|
| 1122 |
|
|
$driver2 = "\n <driver name='qemu' type='$fmt2' cache='$cache2'/>";
|
| 1123 |
|
|
$driver3 = "\n <driver name='qemu' type='$fmt3' cache='$cache3'/>";
|
| 1124 |
|
|
$driver4 = "\n <driver name='qemu' type='$fmt4' cache='$cache4'/>";
|
| 1125 |
95b003ff
|
Origo
|
}
|
| 1126 |
|
|
|
| 1127 |
|
|
my $networktype1 = "user";
|
| 1128 |
|
|
my $networksource1 = "default";
|
| 1129 |
|
|
my $networkforward1 = "bridge";
|
| 1130 |
|
|
my $networkisolated1 = "no";
|
| 1131 |
|
|
$networksource1 = "vboxnet0" if ($hypervisor eq "vbox");
|
| 1132 |
|
|
if ($networkid1 eq '0') {
|
| 1133 |
|
|
$networktype1 = "user";
|
| 1134 |
|
|
$networkforward1 = "nat";
|
| 1135 |
f222b89c
|
hq
|
$networkisolated1 = "no"
|
| 1136 |
95b003ff
|
Origo
|
} elsif ($networkid1 == 1) {
|
| 1137 |
|
|
$networktype1 = "network" ;
|
| 1138 |
|
|
$networkforward1 = "nat";
|
| 1139 |
|
|
$networkisolated1 = "yes"
|
| 1140 |
|
|
} elsif ($networkid1 > 1) {
|
| 1141 |
|
|
$networktype1 = "bridge";
|
| 1142 |
|
|
$networksource1 = "br$networkid1";
|
| 1143 |
|
|
}
|
| 1144 |
|
|
my $networktype2 = "user";
|
| 1145 |
|
|
my $networksource2 = "default";
|
| 1146 |
|
|
my $networkforward2 = "bridge";
|
| 1147 |
|
|
my $networkisolated2 = "no";
|
| 1148 |
|
|
$networksource2 = "vboxnet0" if ($hypervisor eq "vbox");
|
| 1149 |
|
|
if ($networkid2 eq '0') {
|
| 1150 |
|
|
$networktype2 = "user";
|
| 1151 |
|
|
$networkforward2 = "nat";
|
| 1152 |
|
|
$networkisolated2 = "yes"
|
| 1153 |
|
|
} elsif ($networkid2 == 1) {
|
| 1154 |
|
|
$networktype2 = "network" ;
|
| 1155 |
|
|
$networkforward2 = "nat";
|
| 1156 |
|
|
$networkisolated2 = "yes"
|
| 1157 |
|
|
} elsif ($networkid2 > 1) {
|
| 1158 |
|
|
$networktype2 = "bridge";
|
| 1159 |
|
|
$networksource2 = "br$networkid2";
|
| 1160 |
|
|
}
|
| 1161 |
|
|
my $networktype3 = "user";
|
| 1162 |
|
|
my $networksource3 = "default";
|
| 1163 |
|
|
my $networkforward3 = "bridge";
|
| 1164 |
|
|
my $networkisolated3 = "no";
|
| 1165 |
|
|
$networksource3 = "vboxnet0" if ($hypervisor eq "vbox");
|
| 1166 |
|
|
if ($networkid3 eq '0') {
|
| 1167 |
|
|
$networktype3 = "user";
|
| 1168 |
|
|
$networkforward3 = "nat";
|
| 1169 |
|
|
$networkisolated3 = "yes"
|
| 1170 |
|
|
} elsif ($networkid3 == 1) {
|
| 1171 |
|
|
$networktype3 = "network" ;
|
| 1172 |
|
|
$networkforward3 = "nat";
|
| 1173 |
|
|
$networkisolated3 = "yes"
|
| 1174 |
|
|
} elsif ($networkid3 > 1) {
|
| 1175 |
|
|
$networktype3 = "bridge";
|
| 1176 |
|
|
$networksource3 = "br$networkid3";
|
| 1177 |
|
|
}
|
| 1178 |
|
|
|
| 1179 |
|
|
my $xml = "<domain type='$hypervisor' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>\n";
|
| 1180 |
|
|
# if ($vgpu && $vgpu ne "--") {
|
| 1181 |
|
|
# $xml .= <<ENDXML2
|
| 1182 |
|
|
# <qemu:commandline>
|
| 1183 |
|
|
# <qemu:arg value='-device'/>
|
| 1184 |
|
|
# <qemu:arg value='vfio-pci,host=01:00.0,x-vga=on'/>
|
| 1185 |
|
|
# <qemu:arg value='-device'/>
|
| 1186 |
|
|
# <qemu:arg value='vfio-pci,host=02:00.0,x-vga=on'/>
|
| 1187 |
|
|
# </qemu:commandline>
|
| 1188 |
|
|
#ENDXML2
|
| 1189 |
|
|
# ;
|
| 1190 |
|
|
# }
|
| 1191 |
|
|
|
| 1192 |
|
|
# <qemu:arg value='-set'/>
|
| 1193 |
|
|
# <qemu:arg value='device.hostdev1.x-vga=on'/>
|
| 1194 |
|
|
# <qemu:arg value='-cpu'/>
|
| 1195 |
|
|
# <qemu:arg value='host,kvm=off'/>
|
| 1196 |
|
|
# <qemu:arg value='-device'/>
|
| 1197 |
|
|
# <qemu:arg value='pci-assign,host=01:00.0,id=hostdev0,configfd=20,bus=pci.0,addr=0x6,x-pci-vendor-id=0x10DE,x-pci-device-id=0x11BA,x-pci-sub-vendor-id=0x10DE,x-pci-sub-device-id=0x0965'/>
|
| 1198 |
|
|
|
| 1199 |
|
|
# <cpu mode='host-model'>
|
| 1200 |
|
|
# <vendor>Intel</vendor>
|
| 1201 |
|
|
# <model>core2duo</model>
|
| 1202 |
|
|
# </cpu>
|
| 1203 |
|
|
|
| 1204 |
|
|
# <loader readonly='yes' type='pflash'>/usr/share/OVMF/OVMF_CODE.fd</loader>
|
| 1205 |
|
|
# <nvram template='/usr/share/OVMF/OVMF_VARS.fd'/>
|
| 1206 |
04c16f26
|
hq
|
my $loader_xml = <<ENDXML
|
| 1207 |
|
|
<bootmenu enable='yes' timeout='200'/>
|
| 1208 |
|
|
<smbios mode='sysinfo'/>
|
| 1209 |
|
|
ENDXML
|
| 1210 |
|
|
;
|
| 1211 |
d3805c61
|
hq
|
if ($loader eq 'uefi') {
|
| 1212 |
|
|
$loader_xml = <<ENDXML
|
| 1213 |
04c16f26
|
hq
|
<loader readonly='yes' secure='no' type='pflash'>/usr/share/ovmf/OVMF.fd</loader>
|
| 1214 |
|
|
<nvram template='/usr/share/OVMF/OVMF_VARS.fd'>/tmp/guest_VARS.fd</nvram>
|
| 1215 |
|
|
ENDXML
|
| 1216 |
|
|
;
|
| 1217 |
d3805c61
|
hq
|
}
|
| 1218 |
|
|
my $iotune_xml = <<ENDXML
|
| 1219 |
|
|
<iotune>
|
| 1220 |
|
|
<read_bytes_sec>$vm_readlimit</read_bytes_sec>
|
| 1221 |
|
|
<write_bytes_sec>$vm_writelimit</write_bytes_sec>
|
| 1222 |
|
|
<read_iops_sec>$vm_iopsreadlimit</read_iops_sec>
|
| 1223 |
|
|
<write_iops_sec>$vm_iopswritelimit</write_iops_sec>
|
| 1224 |
|
|
</iotune>
|
| 1225 |
|
|
ENDXML
|
| 1226 |
|
|
;
|
| 1227 |
|
|
$iotune_xml = '' unless ($enforceiolimits);
|
| 1228 |
95b003ff
|
Origo
|
|
| 1229 |
705b5366
|
hq
|
if ($vgpu && $vgpu ne "--") {
|
| 1230 |
|
|
$xml .= <<ENDXML
|
| 1231 |
95b003ff
|
Origo
|
<cpu mode='host-passthrough'>
|
| 1232 |
|
|
<feature policy='disable' name='hypervisor'/>
|
| 1233 |
|
|
</cpu>
|
| 1234 |
|
|
ENDXML
|
| 1235 |
|
|
;
|
| 1236 |
705b5366
|
hq
|
} else {
|
| 1237 |
|
|
$xml .= <<ENDXML
|
| 1238 |
|
|
<cpu mode='host-model'>
|
| 1239 |
|
|
</cpu>
|
| 1240 |
|
|
ENDXML
|
| 1241 |
|
|
;
|
| 1242 |
95b003ff
|
Origo
|
}
|
| 1243 |
|
|
$xml .= <<ENDXML
|
| 1244 |
|
|
<name>$uname</name>
|
| 1245 |
|
|
<uuid>$uuid</uuid>
|
| 1246 |
|
|
<memory>$mem</memory>
|
| 1247 |
|
|
<vcpu>$vcpu</vcpu>
|
| 1248 |
|
|
<os>
|
| 1249 |
|
|
<type arch='x86_64' machine='pc'>hvm</type>
|
| 1250 |
|
|
<boot dev='$boot'/>
|
| 1251 |
04c16f26
|
hq
|
$loader_xml
|
| 1252 |
95b003ff
|
Origo
|
</os>
|
| 1253 |
|
|
<sysinfo type='smbios'>
|
| 1254 |
|
|
<bios>
|
| 1255 |
|
|
<entry name='vendor'>Origo</entry>
|
| 1256 |
|
|
</bios>
|
| 1257 |
|
|
<system>
|
| 1258 |
|
|
<entry name='manufacturer'>Origo</entry>
|
| 1259 |
|
|
<entry name='sku'>$networkid1ip</entry>
|
| 1260 |
|
|
</system>
|
| 1261 |
|
|
</sysinfo>
|
| 1262 |
|
|
<features>
|
| 1263 |
|
|
ENDXML
|
| 1264 |
|
|
;
|
| 1265 |
|
|
if ($vgpu && $vgpu ne "--") { $xml .= <<ENDXML
|
| 1266 |
|
|
<kvm>
|
| 1267 |
|
|
<hidden state='on'/>
|
| 1268 |
|
|
</kvm>
|
| 1269 |
|
|
ENDXML
|
| 1270 |
|
|
;
|
| 1271 |
|
|
}
|
| 1272 |
|
|
$xml .= <<ENDXML
|
| 1273 |
|
|
<pae/>
|
| 1274 |
|
|
<acpi/>
|
| 1275 |
|
|
<apic/>
|
| 1276 |
|
|
</features>
|
| 1277 |
|
|
<clock offset='localtime'>
|
| 1278 |
|
|
<timer name='rtc' tickpolicy='catchup' track='guest'/>
|
| 1279 |
|
|
<timer name='pit' tickpolicy='delay'/>
|
| 1280 |
|
|
<timer name='hpet' present='no'/>
|
| 1281 |
|
|
</clock>
|
| 1282 |
|
|
<on_poweroff>destroy</on_poweroff>
|
| 1283 |
04c16f26
|
hq
|
<on_reboot>restart</on_reboot>½
|
| 1284 |
95b003ff
|
Origo
|
<on_crash>restart</on_crash>
|
| 1285 |
|
|
<devices>
|
| 1286 |
e837d785
|
hq
|
<sound model='ich6'/>
|
| 1287 |
95b003ff
|
Origo
|
ENDXML
|
| 1288 |
|
|
;
|
| 1289 |
|
|
# if ($vgpu && $vgpu ne "--") {
|
| 1290 |
|
|
# $xml .= <<ENDXML2
|
| 1291 |
|
|
# <hostdev mode='subsystem' type='pci' managed='yes'>
|
| 1292 |
|
|
# <source>
|
| 1293 |
|
|
# <address domain='0x0000' bus='0x01' slot='0x00' function='0x0' multifunction='on'/>
|
| 1294 |
|
|
# </source>
|
| 1295 |
|
|
# </hostdev>
|
| 1296 |
|
|
# <hostdev mode='subsystem' type='pci' managed='yes'>
|
| 1297 |
|
|
# <source>
|
| 1298 |
|
|
# <address domain='0x0000' bus='0x02' slot='0x00' function='0x0' multifunction='on'/>
|
| 1299 |
|
|
# </source>
|
| 1300 |
|
|
# </hostdev>
|
| 1301 |
|
|
#ENDXML2
|
| 1302 |
|
|
#;
|
| 1303 |
|
|
# }
|
| 1304 |
|
|
if ($image && $image ne "" && $image ne "--") {
|
| 1305 |
|
|
$xml .= <<ENDXML2
|
| 1306 |
|
|
<disk type='file' device='disk'>
|
| 1307 |
|
|
<source file='$image'/>$driver1
|
| 1308 |
|
|
<target dev='$diskdev' bus='$diskbus'/>
|
| 1309 |
d3805c61
|
hq
|
$iotune_xml
|
| 1310 |
95b003ff
|
Origo
|
</disk>
|
| 1311 |
|
|
ENDXML2
|
| 1312 |
|
|
;
|
| 1313 |
|
|
};
|
| 1314 |
|
|
|
| 1315 |
|
|
if ($image2 && $image2 ne "" && $image2 ne "--") {
|
| 1316 |
|
|
$xml .= <<ENDXML2
|
| 1317 |
|
|
<disk type='file' device='disk'>$driver2
|
| 1318 |
|
|
<source file='$image2'/>
|
| 1319 |
|
|
<target dev='$diskdev2' bus='$diskbus'/>
|
| 1320 |
d3805c61
|
hq
|
$iotune_xml
|
| 1321 |
95b003ff
|
Origo
|
</disk>
|
| 1322 |
|
|
ENDXML2
|
| 1323 |
|
|
;
|
| 1324 |
|
|
};
|
| 1325 |
|
|
if ($image3 && $image3 ne "" && $image3 ne "--") {
|
| 1326 |
|
|
$xml .= <<ENDXML2
|
| 1327 |
|
|
<disk type='file' device='disk'>$driver3
|
| 1328 |
|
|
<source file='$image3'/>
|
| 1329 |
|
|
<target dev='$diskdev3' bus='$diskbus'/>
|
| 1330 |
d3805c61
|
hq
|
$iotune_xml
|
| 1331 |
95b003ff
|
Origo
|
</disk>
|
| 1332 |
|
|
ENDXML2
|
| 1333 |
|
|
;
|
| 1334 |
|
|
};
|
| 1335 |
|
|
if ($image4 && $image4 ne "" && $image4 ne "--") {
|
| 1336 |
|
|
$xml .= <<ENDXML2
|
| 1337 |
|
|
<disk type='file' device='disk'>$driver4
|
| 1338 |
|
|
<source file='$image4'/>
|
| 1339 |
|
|
<target dev='$diskdev4' bus='$diskbus'/>
|
| 1340 |
d3805c61
|
hq
|
$iotune_xml
|
| 1341 |
95b003ff
|
Origo
|
</disk>
|
| 1342 |
|
|
ENDXML2
|
| 1343 |
|
|
;
|
| 1344 |
|
|
};
|
| 1345 |
|
|
|
| 1346 |
|
|
unless ($image4 && $image4 ne '--' && $diskbus eq 'ide') {
|
| 1347 |
|
|
if ($cdrom && $cdrom ne "" && $cdrom ne "--") {
|
| 1348 |
|
|
$xml .= <<ENDXML3
|
| 1349 |
|
|
<disk type='file' device='cdrom'>
|
| 1350 |
|
|
<source file='$cdrom'/>
|
| 1351 |
|
|
<target dev='hdd' bus='ide'/>
|
| 1352 |
|
|
<readonly/>
|
| 1353 |
|
|
</disk>
|
| 1354 |
|
|
ENDXML3
|
| 1355 |
|
|
;
|
| 1356 |
|
|
} elsif ($hypervisor ne "vbox") {
|
| 1357 |
|
|
$xml .= <<ENDXML3
|
| 1358 |
|
|
<disk type='file' device='cdrom'>
|
| 1359 |
|
|
<target dev='hdd' bus='ide'/>
|
| 1360 |
|
|
<readonly/>
|
| 1361 |
|
|
</disk>
|
| 1362 |
|
|
ENDXML3
|
| 1363 |
|
|
;
|
| 1364 |
|
|
}
|
| 1365 |
|
|
}
|
| 1366 |
|
|
|
| 1367 |
|
|
$xml .= <<ENDXML4
|
| 1368 |
|
|
<interface type='$networktype1'>
|
| 1369 |
|
|
<source $networktype1='$networksource1'/>
|
| 1370 |
|
|
<forward mode='$networkforward1'/>
|
| 1371 |
|
|
<port isolated='$networkisolated1'/>
|
| 1372 |
|
|
<model type='$nicmodel1'/>
|
| 1373 |
|
|
<mac address='$nicmac1'/>
|
| 1374 |
|
|
</interface>
|
| 1375 |
|
|
ENDXML4
|
| 1376 |
|
|
;
|
| 1377 |
|
|
|
| 1378 |
|
|
if (($networkuuid2 && $networkuuid2 ne '--') || $networkuuid2 eq '0') {
|
| 1379 |
|
|
$xml .= <<ENDXML5
|
| 1380 |
|
|
<interface type='$networktype2'>
|
| 1381 |
|
|
<source $networktype2='$networksource2'/>
|
| 1382 |
|
|
<forward mode='$networkforward2'/>
|
| 1383 |
|
|
<port isolated='$networkisolated2'/>
|
| 1384 |
|
|
<model type='$nicmodel1'/>
|
| 1385 |
|
|
<mac address='$nicmac2'/>
|
| 1386 |
|
|
</interface>
|
| 1387 |
|
|
ENDXML5
|
| 1388 |
|
|
;
|
| 1389 |
|
|
}
|
| 1390 |
|
|
if (($networkuuid3 && $networkuuid3 ne '--') || $networkuuid3 eq '0') {
|
| 1391 |
|
|
$xml .= <<ENDXML5
|
| 1392 |
|
|
<interface type='$networktype3'>
|
| 1393 |
|
|
<source $networktype3='$networksource3'/>
|
| 1394 |
|
|
<forward mode='$networkforward3'/>
|
| 1395 |
|
|
<port isolated='$networkisolated3'/>
|
| 1396 |
|
|
<model type='$nicmodel1'/>
|
| 1397 |
|
|
<mac address='$nicmac3'/>
|
| 1398 |
|
|
</interface>
|
| 1399 |
|
|
ENDXML5
|
| 1400 |
|
|
;
|
| 1401 |
|
|
}
|
| 1402 |
|
|
$xml .= <<ENDXML6
|
| 1403 |
|
|
<serial type='pty'>
|
| 1404 |
|
|
<source path='/dev/pts/0'/>
|
| 1405 |
|
|
<target port='0'/>
|
| 1406 |
|
|
</serial>
|
| 1407 |
|
|
<input type='tablet' bus='usb'/>
|
| 1408 |
|
|
<graphics type='$graphics' port='$port'/>
|
| 1409 |
|
|
</devices>
|
| 1410 |
|
|
</domain>
|
| 1411 |
|
|
ENDXML6
|
| 1412 |
|
|
;
|
| 1413 |
|
|
|
| 1414 |
|
|
|
| 1415 |
|
|
# <graphics type='$graphics' port='$port' keymap='en-us'/>
|
| 1416 |
|
|
# <console type='pty' tty='/dev/pts/0'>
|
| 1417 |
|
|
# <source path='/dev/pts/0'/>
|
| 1418 |
|
|
# <target port='0'/>
|
| 1419 |
|
|
# </console>
|
| 1420 |
|
|
# <graphics type='$graphics' port='-1' autoport='yes'/>
|
| 1421 |
|
|
|
| 1422 |
|
|
$xmlreg{$uuid} = {
|
| 1423 |
|
|
xml=>URI::Escape::uri_escape($xml)
|
| 1424 |
|
|
};
|
| 1425 |
|
|
|
| 1426 |
|
|
# Actually ask node to start domain
|
| 1427 |
|
|
if ($targetmac) {
|
| 1428 |
|
|
$register{$uuid}->{'mac'} = $targetmac;
|
| 1429 |
|
|
$register{$uuid}->{'macname'} = $targetname;
|
| 1430 |
|
|
$register{$uuid}->{'macip'} = $targetip;
|
| 1431 |
|
|
|
| 1432 |
|
|
my $tasks = $nodereg{$targetmac}->{'tasks'};
|
| 1433 |
|
|
$tasks .= "START $uuid $user\n";
|
| 1434 |
|
|
$nodereg{$targetmac}->{'tasks'} = $tasks;
|
| 1435 |
|
|
tied(%nodereg)->commit;
|
| 1436 |
|
|
$uiuuid = $uuid;
|
| 1437 |
|
|
$uidisplayip = $targetip;
|
| 1438 |
|
|
$uidisplayport = $port;
|
| 1439 |
|
|
$register{$uuid}->{'status'} = $uistatus;
|
| 1440 |
|
|
$register{$uuid}->{'statustime'} = $current_time;
|
| 1441 |
|
|
tied(%register)->commit;
|
| 1442 |
|
|
|
| 1443 |
|
|
# Activate networks
|
| 1444 |
|
|
require "$Stabile::basedir/cgi/networks.cgi";
|
| 1445 |
|
|
Stabile::Networks::Activate($networkuuid1, 'activate');
|
| 1446 |
|
|
Stabile::Networks::Activate($networkuuid2, 'activate') if ($networkuuid2 && $networkuuid2 ne '--');
|
| 1447 |
|
|
Stabile::Networks::Activate($networkuuid3, 'activate') if ($networkuuid3 && $networkuuid3 ne '--');
|
| 1448 |
|
|
|
| 1449 |
|
|
$main::syslogit->($user, "info", "Marked $name ($uuid) for ". $serv->{'status'} . " on $targetname ($targetmac)");
|
| 1450 |
|
|
$postreply .= "Status=starting OK $uistatus ". $serv->{'name'} . "\n";
|
| 1451 |
|
|
} else {
|
| 1452 |
|
|
$main::syslogit->($user, "info", "Could not find $hypervisor target for creating $uuid ($image)");
|
| 1453 |
|
|
$postreply .= "Status=ERROR problem $uistatus ". $serv->{'name'} . " (unable to locate target node)\n";
|
| 1454 |
|
|
};
|
| 1455 |
|
|
} else {
|
| 1456 |
|
|
$main::syslogit->($user, "info", "Problem $uistatus a $dbstatus domain: $uuid");
|
| 1457 |
|
|
$postreply .= "Status=ERROR problem $uistatus ". $serv->{'name'} . "\n";
|
| 1458 |
|
|
}
|
| 1459 |
|
|
#return ($uiuuid, $uidisplayip, $uidisplayport, $postreply, $targetmac);
|
| 1460 |
|
|
return $postreply;
|
| 1461 |
|
|
}
|
| 1462 |
|
|
|
| 1463 |
|
|
sub do_attach {
|
| 1464 |
|
|
my ($uuid, $action, $obj) = @_;
|
| 1465 |
|
|
if ($help) {
|
| 1466 |
|
|
return <<END
|
| 1467 |
|
|
GET:uuid,image:
|
| 1468 |
|
|
Attaches an image to a server as a disk device. Image must not be in use.
|
| 1469 |
|
|
END
|
| 1470 |
|
|
}
|
| 1471 |
|
|
my $dev = '';
|
| 1472 |
|
|
my $imagenum = 0;
|
| 1473 |
|
|
my $serv = $register{$uuid};
|
| 1474 |
|
|
|
| 1475 |
|
|
if (!$serv->{'uuid'} || ($serv->{'status'} ne 'running' && $serv->{'status'} ne 'paused')) {
|
| 1476 |
|
|
return "Status=Error Server must exist and be running\n";
|
| 1477 |
|
|
}
|
| 1478 |
|
|
my $macip = $serv->{macip};
|
| 1479 |
|
|
my $image = $obj->{image} || $obj->{path};
|
| 1480 |
|
|
if ($image && !($image =~ /^\//)) { # We have a uuid
|
| 1481 |
|
|
unless ( tie(%imagereg2,'Tie::DBI', Hash::Merge::merge({table=>'images', CLOBBER=>1}, $Stabile::dbopts)) ) {return "Status=Error Unable to access images register\n"};
|
| 1482 |
|
|
$image = $imagereg2{$image}->{'path'} if ($imagereg2{$image});
|
| 1483 |
|
|
untie %imagereg2;
|
| 1484 |
|
|
}
|
| 1485 |
|
|
unless (tie(%imagereg,'Tie::DBI', Hash::Merge::merge({table=>'images', key=>'path'}, $Stabile::dbopts)) ) {$postreply .= "Status=Error Unable to access images register\n"; return $postreply;};
|
| 1486 |
|
|
unless ($macip && $imagereg{$image} && $imagereg{$image}->{'user'} eq $user && $serv->{'user'} eq $user) {$postreply .= "Status=Error Invalid image or server\n"; return $postreply;};
|
| 1487 |
|
|
if ($imagereg{$image}->{'status'} ne 'unused') {return "Status=Error Image $image is already in use ($imagereg{$image}->{'status'})\n"};
|
| 1488 |
|
|
|
| 1489 |
|
|
my $cmd = qq|$sshcmd $macip "LIBVIRT_DEFAULT_URI=qemu:///system virsh domblklist $uuid"|;
|
| 1490 |
|
|
my $res = `$cmd`;
|
| 1491 |
|
|
unless ($res =~ /vdb\s+.+/) {$dev = 'vdb'; $imagenum = 2};
|
| 1492 |
|
|
unless ($dev || $res =~ /vdc\s+.+/) {$dev = 'vdc'; $imagenum = 3};
|
| 1493 |
|
|
unless ($dev || $res =~ /vdd\s+.+/) {$dev = 'vdd'; $imagenum = 4};
|
| 1494 |
|
|
if (!$dev) {
|
| 1495 |
|
|
$postreply = "Status=Error No more images can be attached\n";
|
| 1496 |
|
|
} else {
|
| 1497 |
|
|
my $xml = <<END
|
| 1498 |
|
|
<disk type='file' device='disk'>
|
| 1499 |
|
|
<driver type='qcow2' name='qemu' cache='default'/>
|
| 1500 |
|
|
<source file='$image'/>
|
| 1501 |
|
|
<target dev='$dev' bus='virtio'/>
|
| 1502 |
|
|
</disk>
|
| 1503 |
|
|
END
|
| 1504 |
|
|
;
|
| 1505 |
|
|
$cmd = qq|$sshcmd $macip "echo \\"$xml\\" > /tmp/attach-device-$uuid.xml"|;
|
| 1506 |
|
|
$res = `$cmd`;
|
| 1507 |
|
|
$res .= `$sshcmd $macip LIBVIRT_DEFAULT_URI=qemu:///system virsh attach-device $uuid /tmp/attach-device-$uuid.xml`;
|
| 1508 |
|
|
chomp $res;
|
| 1509 |
|
|
if ($res =~ /successfully/) {
|
| 1510 |
|
|
$postreply .= "Status=OK Attaching $image to $dev\n";
|
| 1511 |
|
|
$imagereg{$image}->{'status'} = 'active';
|
| 1512 |
|
|
$imagereg{$image}->{'domains'} = $uuid;
|
| 1513 |
|
|
$imagereg{$image}->{'domainnames'} = $serv->{'name'};
|
| 1514 |
|
|
$serv->{"image$imagenum"} = $image;
|
| 1515 |
|
|
$serv->{"image$imagenum"."name"} = $imagereg{$image}->{'name'};
|
| 1516 |
|
|
$serv->{"image$imagenum"."type"} = 'qcow2';
|
| 1517 |
|
|
} else {
|
| 1518 |
|
|
$postreply .= "Status=Error Unable to attach image $image to $dev ($res)\n";
|
| 1519 |
|
|
}
|
| 1520 |
|
|
}
|
| 1521 |
|
|
untie %imagereg;
|
| 1522 |
|
|
return $postreply;
|
| 1523 |
|
|
}
|
| 1524 |
|
|
|
| 1525 |
|
|
sub do_detach {
|
| 1526 |
|
|
my ($uuid, $action, $obj) = @_;
|
| 1527 |
|
|
if ($help) {
|
| 1528 |
|
|
return <<END
|
| 1529 |
|
|
GET:uuid,image:
|
| 1530 |
|
|
Detaches a disk device and the associated image from a running server. All associated file-systems within the server should be unmounted before detaching, otherwise data loss i very probable. Use with care.
|
| 1531 |
|
|
END
|
| 1532 |
|
|
}
|
| 1533 |
|
|
my $dev = '';
|
| 1534 |
|
|
my $serv = $register{$uuid};
|
| 1535 |
|
|
|
| 1536 |
|
|
if (!$serv->{'uuid'} || ($serv->{'status'} ne 'running' && $serv->{'status'} ne 'paused')) {
|
| 1537 |
|
|
return "Status=Error Server must exist and be running\n";
|
| 1538 |
|
|
}
|
| 1539 |
|
|
my $macip = $serv->{macip};
|
| 1540 |
|
|
|
| 1541 |
|
|
my $image = $obj->{image} || $obj->{path} || $serv->{'image2'};
|
| 1542 |
|
|
if ($image && !($image =~ /^\//)) { # We have a uuid
|
| 1543 |
|
|
unless ( tie(%imagereg2,'Tie::DBI', Hash::Merge::merge({table=>'images', CLOBBER=>1}, $Stabile::dbopts)) ) {return "Unable to access images register"};
|
| 1544 |
|
|
$image = $imagereg2{$image}->{'path'} if ($imagereg2{$image});
|
| 1545 |
|
|
untie %imagereg2;
|
| 1546 |
|
|
}
|
| 1547 |
|
|
unless (tie(%imagereg,'Tie::DBI', Hash::Merge::merge({table=>'images', key=>'path'}, $Stabile::dbopts)) ) {$postreply .= "Status=Error Unable to access images register\n"; return $postreply;};
|
| 1548 |
|
|
unless ($macip && $imagereg{$image} && $imagereg{$image}->{'user'} eq $user && $serv->{'user'} eq $user) {$postreply .= "Status=Error Invalid image or server. Server must have a secondary image attached.\n"; return $postreply;};
|
| 1549 |
|
|
|
| 1550 |
|
|
my $cmd = qq|$sshcmd $macip "LIBVIRT_DEFAULT_URI=qemu:///system virsh domblklist $uuid"|;
|
| 1551 |
|
|
my $res = `$cmd`;
|
| 1552 |
|
|
$dev = $1 if ($res =~ /(vd.)\s+.+$image/);
|
| 1553 |
|
|
if (!$dev) {
|
| 1554 |
|
|
$postreply = qq|Status=Error Image $image, $cmd, is not currently attached\n|;
|
| 1555 |
|
|
} elsif ($dev eq 'vda') {
|
| 1556 |
|
|
$postreply = "Status=Error You cannot detach the primary image\n";
|
| 1557 |
|
|
} else {
|
| 1558 |
|
|
$res = `$sshcmd $macip LIBVIRT_DEFAULT_URI=qemu:///system virsh detach-disk $uuid $dev`;
|
| 1559 |
|
|
chomp $res;
|
| 1560 |
|
|
if ($res =~ /successfully/) {
|
| 1561 |
|
|
$postreply .= "Status=OK Detaching image $image, $imagereg{$image}->{'uuid'} from $dev\n";
|
| 1562 |
|
|
my $imagenum;
|
| 1563 |
|
|
$imagenum = 2 if ($serv->{'image2'} eq $image);
|
| 1564 |
|
|
$imagenum = 3 if ($serv->{'image3'} eq $image);
|
| 1565 |
|
|
$imagenum = 4 if ($serv->{'image4'} eq $image);
|
| 1566 |
|
|
$imagereg{$image}->{'status'} = 'unused';
|
| 1567 |
|
|
$imagereg{$image}->{'domains'} = '';
|
| 1568 |
|
|
$imagereg{$image}->{'domainnames'} = '';
|
| 1569 |
|
|
if ($imagenum) {
|
| 1570 |
|
|
$serv->{"image$imagenum"} = '';
|
| 1571 |
|
|
$serv->{"image$imagenum"."name"} = '';
|
| 1572 |
|
|
$serv->{"image$imagenum"."type"} = '';
|
| 1573 |
|
|
}
|
| 1574 |
|
|
} else {
|
| 1575 |
|
|
$postreply .= "Status=Error Unable to attach image $image to $dev ($res)\n";
|
| 1576 |
|
|
}
|
| 1577 |
|
|
}
|
| 1578 |
|
|
untie %imagereg;
|
| 1579 |
|
|
return $postreply;
|
| 1580 |
|
|
}
|
| 1581 |
|
|
|
| 1582 |
|
|
sub Destroy {
|
| 1583 |
|
|
my ($uuid, $action, $obj) = @_;
|
| 1584 |
|
|
if ($help) {
|
| 1585 |
|
|
return <<END
|
| 1586 |
|
|
GET:uuid,wait:
|
| 1587 |
|
|
Marks a server for halt, i.e. pull the plug if regular shutdown does not work or is not desired. Server and storage is preserved.
|
| 1588 |
|
|
END
|
| 1589 |
|
|
}
|
| 1590 |
|
|
my $uistatus = 'destroying';
|
| 1591 |
|
|
my $name = $register{$uuid}->{'name'};
|
| 1592 |
|
|
my $mac = $register{$uuid}->{'mac'};
|
| 1593 |
|
|
my $macname = $register{$uuid}->{'macname'};
|
| 1594 |
|
|
my $dbstatus = $register{$uuid}->{'status'};
|
| 1595 |
|
|
my $wait = $obj->{'wait'};
|
| 1596 |
|
|
if ($dbstatus eq 'running' or $dbstatus eq 'paused'
|
| 1597 |
|
|
or $dbstatus eq 'shuttingdown' or $dbstatus eq 'starting'
|
| 1598 |
|
|
or $dbstatus eq 'destroying' or $dbstatus eq 'upgrading'
|
| 1599 |
|
|
or $dbstatus eq 'suspending' or $dbstatus eq 'resuming') {
|
| 1600 |
|
|
if ($wait) {
|
| 1601 |
6372a66e
|
hq
|
my $username = $register{$uuid}->{'user'} || $user;
|
| 1602 |
|
|
$username = $user unless ($isadmin);
|
| 1603 |
|
|
$postreply = destroyUserServers($username, 1, $uuid);
|
| 1604 |
95b003ff
|
Origo
|
} else {
|
| 1605 |
6372a66e
|
hq
|
my $node = $nodereg{$mac};
|
| 1606 |
|
|
my $tasks = $node->{'tasks'};
|
| 1607 |
|
|
$node->{'tasks'} = $tasks . "DESTROY $uuid $user\n";
|
| 1608 |
95b003ff
|
Origo
|
tied(%nodereg)->commit;
|
| 1609 |
|
|
$register{$uuid}->{'status'} = $uistatus;
|
| 1610 |
|
|
$register{$uuid}->{'statustime'} = $current_time;
|
| 1611 |
|
|
$uiuuid = $uuid;
|
| 1612 |
|
|
$main::syslogit->($user, "info", "Marked $name ($uuid) for $uistatus on $macname ($mac)");
|
| 1613 |
|
|
$postreply .= "Status=destroying $uistatus ". $register{$uuid}->{'name'} . "\n";
|
| 1614 |
|
|
}
|
| 1615 |
|
|
} else {
|
| 1616 |
|
|
$main::syslogit->($user, "info", "Problem $uistatus a $dbstatus domain: $name ($uuid)");
|
| 1617 |
|
|
$postreply .= "Status=ERROR problem $uistatus $name\n";
|
| 1618 |
|
|
}
|
| 1619 |
|
|
return $postreply;
|
| 1620 |
|
|
}
|
| 1621 |
|
|
|
| 1622 |
|
|
sub getHypervisor {
|
| 1623 |
|
|
my $image = shift;
|
| 1624 |
|
|
# Produce a mapping of image file suffixes to hypervisors
|
| 1625 |
|
|
my %idreg;
|
| 1626 |
|
|
unless ( tie(%idreg,'Tie::DBI', Hash::Merge::merge({table=>'nodeidentities', key=>'identity'}, $Stabile::dbopts)) ) {return "Unable to access nodeidentities register"};
|
| 1627 |
|
|
my @idvalues = values %idreg;
|
| 1628 |
|
|
my %formats;
|
| 1629 |
|
|
foreach my $val (@idvalues) {
|
| 1630 |
|
|
my %h = %$val;
|
| 1631 |
|
|
foreach (split(/,/,$h{'formats'})) {
|
| 1632 |
|
|
$formats{lc $_} = $h{'hypervisor'}
|
| 1633 |
|
|
}
|
| 1634 |
|
|
}
|
| 1635 |
|
|
untie %idreg;
|
| 1636 |
|
|
|
| 1637 |
|
|
# and then determine the hypervisor in question
|
| 1638 |
|
|
my $hypervisor = "vbox";
|
| 1639 |
|
|
my ($pathname, $path, $suffix) = fileparse($image, '\.[^\.]*');
|
| 1640 |
|
|
$suffix = substr $suffix, 1;
|
| 1641 |
|
|
my $hypervisor = $formats{lc $suffix};
|
| 1642 |
|
|
return $hypervisor;
|
| 1643 |
|
|
}
|
| 1644 |
|
|
|
| 1645 |
|
|
sub nicmac1ToUuid {
|
| 1646 |
|
|
my $nicmac1 = shift;
|
| 1647 |
|
|
my $uuid;
|
| 1648 |
|
|
return $uuid unless $nicmac1;
|
| 1649 |
|
|
my @regkeys = (tied %register)->select_where("user = '$user' AND nicmac1 = '$nicmac1");
|
| 1650 |
|
|
foreach my $k (@regkeys) {
|
| 1651 |
|
|
my $val = $register{$k};
|
| 1652 |
|
|
my %h = %$val;
|
| 1653 |
|
|
if (lc $h{'nicmac1'} eq lc $nicmac1 && $user eq $h{'user'}) {
|
| 1654 |
|
|
$uuid = $h{'uuid'};
|
| 1655 |
|
|
last;
|
| 1656 |
|
|
}
|
| 1657 |
|
|
}
|
| 1658 |
|
|
return $uuid;
|
| 1659 |
|
|
}
|
| 1660 |
|
|
|
| 1661 |
|
|
sub randomMac {
|
| 1662 |
|
|
my ( %vendor, $lladdr, $i );
|
| 1663 |
|
|
# $lladdr = '00';
|
| 1664 |
|
|
$lladdr = '52:54:00';# KVM vendor string
|
| 1665 |
|
|
while ( ++$i )
|
| 1666 |
|
|
# { last if $i > 10;
|
| 1667 |
|
|
{ last if $i > 6;
|
| 1668 |
|
|
$lladdr .= ':' if $i % 2;
|
| 1669 |
|
|
$lladdr .= sprintf "%" . ( qw (X x) [int ( rand ( 2 ) ) ] ), int ( rand ( 16 ) );
|
| 1670 |
|
|
}
|
| 1671 |
|
|
return $lladdr;
|
| 1672 |
|
|
}
|
| 1673 |
|
|
|
| 1674 |
|
|
sub overQuotas {
|
| 1675 |
|
|
my $meminc = shift;
|
| 1676 |
|
|
my $vcpuinc = shift;
|
| 1677 |
|
|
my $usedmemory = 0;
|
| 1678 |
|
|
my $usedvcpus = 0;
|
| 1679 |
|
|
my $overquota = 0;
|
| 1680 |
|
|
return $overquota if ($isadmin || $Stabile::userprivileges =~ /a/); # Don't enforce quotas for admins
|
| 1681 |
|
|
|
| 1682 |
a2e0bc7e
|
hq
|
my $memoryquota = $Stabile::usermemoryquota;
|
| 1683 |
|
|
my $vcpuquota = $Stabile::uservcpuquota;
|
| 1684 |
95b003ff
|
Origo
|
|
| 1685 |
|
|
if (!$memoryquota || !$vcpuquota) { # 0 or empty quota means use defaults
|
| 1686 |
|
|
$memoryquota = $memoryquota || $Stabile::config->get('MEMORY_QUOTA');
|
| 1687 |
|
|
$vcpuquota = $vcpuquota || $Stabile::config->get('VCPU_QUOTA');
|
| 1688 |
|
|
}
|
| 1689 |
|
|
|
| 1690 |
|
|
my @regkeys = (tied %register)->select_where("user = '$user'");
|
| 1691 |
|
|
foreach my $k (@regkeys) {
|
| 1692 |
|
|
my $val = $register{$k};
|
| 1693 |
|
|
if ($val->{'user'} eq $user && $val->{'status'} ne "shutoff" &&
|
| 1694 |
|
|
$val->{'status'} ne "inactive" && $val->{'status'} ne "shutdown" ) {
|
| 1695 |
|
|
|
| 1696 |
|
|
$usedmemory += $val->{'memory'};
|
| 1697 |
|
|
$usedvcpus += $val->{'vcpu'};
|
| 1698 |
|
|
}
|
| 1699 |
|
|
}
|
| 1700 |
|
|
$overquota = $usedmemory+$meminc if ($memoryquota!=-1 && $usedmemory+$meminc > $memoryquota); # -1 means no quota
|
| 1701 |
|
|
$overquota = $usedvcpus+$vcpuinc if ($vcpuquota!=-1 && $usedvcpus+$vcpuinc > $vcpuquota);
|
| 1702 |
|
|
return $overquota;
|
| 1703 |
|
|
}
|
| 1704 |
|
|
|
| 1705 |
|
|
sub validateItem {
|
| 1706 |
a2e0bc7e
|
hq
|
unless (%imagereg) {
|
| 1707 |
|
|
unless ( tie(%imagereg,'Tie::DBI', Hash::Merge::merge({table=>'images', key=>'path'}, $Stabile::dbopts)) ) {return "Unable to access images register"};
|
| 1708 |
|
|
}
|
| 1709 |
95b003ff
|
Origo
|
my $valref = shift;
|
| 1710 |
|
|
my $img = $imagereg{$valref->{'image'}};
|
| 1711 |
|
|
my $imagename = $img->{'name'};
|
| 1712 |
|
|
$valref->{'imagename'} = $imagename if ($imagename);
|
| 1713 |
|
|
my $imagetype = $img->{'type'};
|
| 1714 |
|
|
$valref->{'imagetype'} = $imagetype if ($imagetype);
|
| 1715 |
|
|
|
| 1716 |
|
|
# imagex may be registered by uuid instead of path - find the path
|
| 1717 |
|
|
# We now support up to 4 images
|
| 1718 |
|
|
for (my $i=2; $i<=4; $i++) {
|
| 1719 |
|
|
if ($valref->{"image$i"} && $valref->{"image$i"} ne '--' && !($valref->{"image$i"} =~ /^\//)) {
|
| 1720 |
|
|
unless ( tie(%imagereg2,'Tie::DBI', Hash::Merge::merge({table=>'images', CLOBBER=>1}, $Stabile::dbopts)) ) {return "Unable to access images register"};
|
| 1721 |
|
|
$valref->{"image$i"} = $imagereg2{$valref->{"image$i"}}->{'path'};
|
| 1722 |
|
|
untie %imagereg2;
|
| 1723 |
|
|
}
|
| 1724 |
|
|
|
| 1725 |
|
|
my $imgi = $imagereg{$valref->{"image$i"}};
|
| 1726 |
|
|
$valref->{"image$i" . 'name'} = $imgi->{'name'} || $valref->{"image$i" . 'name'};
|
| 1727 |
|
|
$valref->{"image$i" . 'type'} = $imgi->{'type'} || $valref->{"image$i" . 'type'};
|
| 1728 |
|
|
}
|
| 1729 |
|
|
|
| 1730 |
|
|
my $net1 = $networkreg{$valref->{'networkuuid1'}};
|
| 1731 |
|
|
my $networkname1 = $net1->{'name'};
|
| 1732 |
|
|
$valref->{'networkname1'} = $networkname1 if ($networkname1);
|
| 1733 |
|
|
my $net2 = $networkreg{$valref->{'networkuuid2'}};
|
| 1734 |
|
|
my $networkname2 = $net2->{'name'};
|
| 1735 |
|
|
$valref->{'networkname2'} = $networkname2 if ($networkname2);
|
| 1736 |
|
|
my $name = $valref->{'name'};
|
| 1737 |
|
|
$valref->{'name'} = $imagename unless $name;
|
| 1738 |
|
|
|
| 1739 |
a2e0bc7e
|
hq
|
# Make sure we start shutoff servers on the node their image is on
|
| 1740 |
95b003ff
|
Origo
|
if ($valref->{'status'} eq "shutoff" || $valref->{'status'} eq "inactive") {
|
| 1741 |
|
|
my $node = $nodereg{$valref->{'mac'}};
|
| 1742 |
|
|
if ($valref->{'image'} =~ /\/mnt\/stabile\/node\//) {
|
| 1743 |
|
|
$valref->{'mac'} = $img->{'mac'};
|
| 1744 |
|
|
$valref->{'macname'} = $node->{'name'};
|
| 1745 |
|
|
$valref->{'macip'} = $node->{'ip'};
|
| 1746 |
|
|
} elsif ($valref->{'image2'} =~ /\/mnt\/stabile\/node\//) {
|
| 1747 |
|
|
$valref->{'mac'} = $imagereg{$valref->{'image2'}}->{'mac'};
|
| 1748 |
|
|
$valref->{'macname'} = $node->{'name'};
|
| 1749 |
|
|
$valref->{'macip'} = $node->{'ip'};
|
| 1750 |
|
|
} elsif ($valref->{'image3'} =~ /\/mnt\/stabile\/node\//) {
|
| 1751 |
|
|
$valref->{'mac'} = $imagereg{$valref->{'image3'}}->{'mac'};
|
| 1752 |
|
|
$valref->{'macname'} = $node->{'name'};
|
| 1753 |
|
|
$valref->{'macip'} = $node->{'ip'};
|
| 1754 |
|
|
} elsif ($valref->{'image4'} =~ /\/mnt\/stabile\/node\//) {
|
| 1755 |
|
|
$valref->{'mac'} = $imagereg{$valref->{'image4'}}->{'mac'};
|
| 1756 |
|
|
$valref->{'macname'} = $node->{'name'};
|
| 1757 |
|
|
$valref->{'macip'} = $node->{'ip'};
|
| 1758 |
|
|
}
|
| 1759 |
|
|
}
|
| 1760 |
|
|
# Mark domains we have heard from in the last 20 secs as inactive
|
| 1761 |
|
|
my $dbtimestamp = 0;
|
| 1762 |
|
|
$dbtimestamp = $register{$valref->{'uuid'}}->{'timestamp'} if ($register{$valref->{'uuid'}});
|
| 1763 |
|
|
my $timediff = $current_time - $dbtimestamp;
|
| 1764 |
|
|
if ($timediff >= 20) {
|
| 1765 |
|
|
if (! ($valref->{'status'} eq "shutoff"
|
| 1766 |
|
|
|| $valref->{'status'} eq "starting"
|
| 1767 |
|
|
# || $valref->{'status'} eq "shuttingdown"
|
| 1768 |
|
|
# || $valref->{'status'} eq "destroying"
|
| 1769 |
d3805c61
|
hq
|
|| ($valref->{'status'} =~ /moving/ && $timediff<40)
|
| 1770 |
95b003ff
|
Origo
|
)) { # Move has probably failed
|
| 1771 |
|
|
$valref->{'status'} = "inactive";
|
| 1772 |
|
|
$imagereg{$valref->{'image'}}->{'status'} = "used" if ($valref->{'image'} && $imagereg{$valref->{'image'}});
|
| 1773 |
a2e0bc7e
|
hq
|
$imagereg{$valref->{'image2'}}->{'status'} = "used" if ($valref->{'image2'} && $imagereg{$valref->{'image2'}});
|
| 1774 |
95b003ff
|
Origo
|
$imagereg{$valref->{'image3'}}->{'status'} = "used" if ($valref->{'image3'} && $imagereg{$valref->{'image3'}});
|
| 1775 |
|
|
$imagereg{$valref->{'image4'}}->{'status'} = "used" if ($valref->{'image4'} && $imagereg{$valref->{'image4'}});
|
| 1776 |
|
|
}
|
| 1777 |
|
|
};
|
| 1778 |
a2e0bc7e
|
hq
|
# untie %imagereg;
|
| 1779 |
95b003ff
|
Origo
|
return $valref;
|
| 1780 |
|
|
}
|
| 1781 |
|
|
|
| 1782 |
|
|
# Run through all domains and mark domains we have heard from in the last 20 secs as inactive
|
| 1783 |
|
|
sub updateRegister {
|
| 1784 |
|
|
unless ( tie(%userreg,'Tie::DBI', Hash::Merge::merge({table=>'users', key=>'username', CLOBBER=>1}, $Stabile::dbopts)) ) {return "Unable to access user register"};
|
| 1785 |
|
|
unless ( tie(%imagereg,'Tie::DBI', Hash::Merge::merge({table=>'images', key=>'path'}, $Stabile::dbopts)) ) {return "Unable to access images register"};
|
| 1786 |
|
|
|
| 1787 |
|
|
my @regkeys = (tied %register)->select_where("user = '$user'");
|
| 1788 |
|
|
|
| 1789 |
|
|
foreach my $k (@regkeys) {
|
| 1790 |
|
|
my $valref = $register{$k};
|
| 1791 |
|
|
next unless ($userreg{$valref->{'user'}});
|
| 1792 |
|
|
my $dbtimestamp = $valref->{'timestamp'};
|
| 1793 |
|
|
my $dbstatus = $valref->{'status'};
|
| 1794 |
|
|
my $timediff = $current_time - $dbtimestamp;
|
| 1795 |
|
|
my $imgstatus;
|
| 1796 |
|
|
my $domstatus;
|
| 1797 |
|
|
if ($timediff >= 20) {
|
| 1798 |
|
|
if ( $valref->{'status'} eq "shutoff" ) {
|
| 1799 |
|
|
$imgstatus = 'used';
|
| 1800 |
|
|
} elsif (( $valref->{'status'} eq "starting"
|
| 1801 |
|
|
|| $valref->{'status'} eq "shuttingdown"
|
| 1802 |
|
|
) && $timediff>50) {
|
| 1803 |
|
|
$imgstatus = 'used';
|
| 1804 |
|
|
$domstatus = 'inactive';
|
| 1805 |
|
|
} elsif ($valref->{'status'} eq "destroying" || $valref->{'status'} eq "moving") {
|
| 1806 |
|
|
;
|
| 1807 |
|
|
} else {
|
| 1808 |
|
|
$domstatus = 'inactive';
|
| 1809 |
|
|
$imgstatus = 'used';
|
| 1810 |
|
|
}
|
| 1811 |
|
|
$valref->{'status'} = $domstatus if ($domstatus);
|
| 1812 |
|
|
my $image = $valref->{'image'};
|
| 1813 |
|
|
my $image2 = $valref->{'image2'};
|
| 1814 |
|
|
my $image3 = $valref->{'image3'};
|
| 1815 |
|
|
my $image4 = $valref->{'image4'};
|
| 1816 |
|
|
$imagereg{$image}->{'status'} = $imgstatus if ($imgstatus);
|
| 1817 |
|
|
$imagereg{$image2}->{'status'} = $imgstatus if ($image2 && $imgstatus);
|
| 1818 |
|
|
$imagereg{$image3}->{'status'} = $imgstatus if ($image3 && $imgstatus);
|
| 1819 |
|
|
$imagereg{$image4}->{'status'} = $imgstatus if ($image4 && $imgstatus);
|
| 1820 |
|
|
if ($domstatus eq 'inactive ' && $dbstatus ne 'inactive') {
|
| 1821 |
|
|
$main::updateUI->({ tab=>'servers',
|
| 1822 |
|
|
user=>$valref->{'user'},
|
| 1823 |
|
|
uuid=>$valref->{'uuid'},
|
| 1824 |
|
|
sender=>'updateRegister',
|
| 1825 |
|
|
status=>'inactive'})
|
| 1826 |
|
|
}
|
| 1827 |
|
|
};
|
| 1828 |
|
|
|
| 1829 |
|
|
}
|
| 1830 |
|
|
untie %userreg;
|
| 1831 |
|
|
untie %imagereg;
|
| 1832 |
|
|
}
|
| 1833 |
|
|
|
| 1834 |
|
|
|
| 1835 |
|
|
sub locateTargetNode {
|
| 1836 |
d3805c61
|
hq
|
my ($uuid, $dmac, $mem, $vcpu, $image, $image2, $image3, $image4, $hypervisor, $smac, $stormove)= @_;
|
| 1837 |
95b003ff
|
Origo
|
my $targetname;
|
| 1838 |
|
|
my $targetip;
|
| 1839 |
|
|
my $port;
|
| 1840 |
|
|
my $targetnode;
|
| 1841 |
|
|
my $targetindex; # Availability index of located target node
|
| 1842 |
|
|
my %avhash;
|
| 1843 |
|
|
|
| 1844 |
d3805c61
|
hq
|
$dmac = '' unless ($isadmin); # Only allow admins to select specific node
|
| 1845 |
95b003ff
|
Origo
|
my $mnode = $register{$uuid};
|
| 1846 |
d3805c61
|
hq
|
if (!$dmac
|
| 1847 |
95b003ff
|
Origo
|
&& $mnode->{'locktonode'} eq 'true'
|
| 1848 |
|
|
&& $mnode->{'mac'}
|
| 1849 |
|
|
&& $mnode->{'mac'} ne '--'
|
| 1850 |
d3805c61
|
hq
|
) {
|
| 1851 |
|
|
$dmac = $mnode->{'mac'}; # Server is locked to specific node
|
| 1852 |
|
|
}
|
| 1853 |
95b003ff
|
Origo
|
if ($dmac && !$nodereg{$dmac}) {
|
| 1854 |
|
|
$main::syslogit->($user, "info", "The target node $dmac no longer exists, starting $uuid on another node if possible");
|
| 1855 |
|
|
$dmac = '';
|
| 1856 |
|
|
}
|
| 1857 |
d3805c61
|
hq
|
my $imageonnode = ((!$stormove) && ($image =~ /\/mnt\/stabile\/node\//
|
| 1858 |
95b003ff
|
Origo
|
|| $image2 =~ /\/mnt\/stabile\/node\//
|
| 1859 |
|
|
|| $image3 =~ /\/mnt\/stabile\/node\//
|
| 1860 |
|
|
|| $image4 =~ /\/mnt\/stabile\/node\//
|
| 1861 |
d3805c61
|
hq
|
));
|
| 1862 |
95b003ff
|
Origo
|
|
| 1863 |
|
|
foreach $node (values %nodereg) {
|
| 1864 |
|
|
my $nstatus = $node->{'status'};
|
| 1865 |
|
|
my $maintenance = $node->{'maintenance'};
|
| 1866 |
|
|
my $nmac = $node->{'mac'};
|
| 1867 |
|
|
|
| 1868 |
|
|
if (($nstatus eq 'running' || $nstatus eq 'asleep' || $nstatus eq 'maintenance' || $nstatus eq 'waking')
|
| 1869 |
|
|
&& $smac ne $nmac
|
| 1870 |
|
|
&& (( ($node->{'memfree'} > $mem+512*1024)
|
| 1871 |
|
|
&& (($node->{'vmvcpus'} + $vcpu) <= ($cpuovercommision * $node->{'cpucores'} * $node->{'cpucount'})) ) || $action eq 'listnodeavailability')
|
| 1872 |
|
|
) {
|
| 1873 |
|
|
# Determine how available this node is
|
| 1874 |
|
|
# Available memory
|
| 1875 |
|
|
my $memweight = 0.2; # memory weighing factor
|
| 1876 |
|
|
my $memindex = $avhash{$nmac}->{'memindex'} = int(100* $memweight* $node->{'memfree'} / (1024*1024) )/100;
|
| 1877 |
|
|
# Free cores
|
| 1878 |
|
|
my $cpuindex = $avhash{$nmac}->{'cpuindex'} = int(100*($cpuovercommision * $node->{'cpucores'} * $node->{'cpucount'} - $node->{'vmvcpus'} - $node->{'reservedvcpus'}))/100;
|
| 1879 |
|
|
# Asleep - not asleep gives a +3
|
| 1880 |
|
|
my $sleepindex = $avhash{$nmac}->{'sleepindex'} = ($node->{'status'} eq 'asleep' || $node->{'status'} eq 'waking')?'0':'3';
|
| 1881 |
|
|
$avhash{$nmac}->{'vmvcpus'} = $node->{'vmvcpus'};
|
| 1882 |
|
|
# $avhash{$nmac}->{'cpucommision'} = $cpuovercommision * $node->{'cpucores'} * $node->{'cpucount'};
|
| 1883 |
|
|
# $avhash{$nmac}->{'cpureservation'} = $node->{'vmvcpus'} + $node->{'reservedvcpus'};
|
| 1884 |
|
|
$avhash{$nmac}->{'name'} = $node->{'name'};
|
| 1885 |
|
|
$avhash{$nmac}->{'mac'} = $node->{'mac'};
|
| 1886 |
|
|
|
| 1887 |
|
|
my $aindex = $memindex + $cpuindex + $sleepindex;
|
| 1888 |
|
|
# Don't use nodes that are out of memory of cores
|
| 1889 |
|
|
$aindex = 0 if ($memindex <= 0 || $cpuindex <= 0);
|
| 1890 |
|
|
$avhash{$nmac}->{'index'} = $aindex;
|
| 1891 |
|
|
$avhash{$nmac}->{'storfree'} = $node->{'storfree'};
|
| 1892 |
c899e439
|
Origo
|
$avhash{$nmac}->{'memfree'} = $node->{'memfree'};
|
| 1893 |
95b003ff
|
Origo
|
$avhash{$nmac}->{'ip'} = $node->{'ip'};
|
| 1894 |
|
|
$avhash{$nmac}->{'identity'} = $node->{'identity'};
|
| 1895 |
|
|
$avhash{$nmac}->{'status'} = $node->{'status'};
|
| 1896 |
|
|
$avhash{$nmac}->{'maintenance'} = $maintenance;
|
| 1897 |
|
|
$avhash{$nmac}->{'reservedvcpus'} = $node->{'reservedvcpus'};
|
| 1898 |
|
|
my $nodeidentity = $node->{'identity'};
|
| 1899 |
|
|
$nodeidentity = 'kvm' if ($nodeidentity eq 'local_kvm');
|
| 1900 |
|
|
if ($hypervisor eq $nodeidentity) {
|
| 1901 |
|
|
# If image is on node, we must start on same node - registered when moving image
|
| 1902 |
|
|
if ($imageonnode) {
|
| 1903 |
|
|
unless ( tie(%imagereg,'Tie::DBI', Hash::Merge::merge({table=>'images', key=>'path'}, $Stabile::dbopts)) ) {return "Unable to access images register"};
|
| 1904 |
|
|
$dmac = $imagereg{$image}->{'mac'};
|
| 1905 |
|
|
$dmac = $imagereg{$image2}->{'mac'} unless ($dmac);
|
| 1906 |
|
|
$dmac = $imagereg{$image3}->{'mac'} unless ($dmac);
|
| 1907 |
|
|
$dmac = $imagereg{$image4}->{'mac'} unless ($dmac);
|
| 1908 |
|
|
untie %imagereg;
|
| 1909 |
|
|
if (!$dmac) {
|
| 1910 |
|
|
$postreply .= "Status=ERROR Image node not found\n";
|
| 1911 |
|
|
last;
|
| 1912 |
|
|
}
|
| 1913 |
|
|
}
|
| 1914 |
|
|
$dmac = "" if ($dmac eq "--");
|
| 1915 |
a439a9c4
|
hq
|
# If a specific node is asked for, match mac addresses
|
| 1916 |
95b003ff
|
Origo
|
if ($dmac eq $nmac) {
|
| 1917 |
|
|
$targetnode = $node;
|
| 1918 |
|
|
last;
|
| 1919 |
|
|
} elsif (!$dmac && $nstatus ne "maintenance" && !$maintenance) {
|
| 1920 |
|
|
# pack or disperse
|
| 1921 |
|
|
if (!$targetindex) {
|
| 1922 |
|
|
$targetindex = $aindex;
|
| 1923 |
|
|
$targetnode = $node;
|
| 1924 |
|
|
} elsif ($dpolicy eq 'pack') {
|
| 1925 |
|
|
if ($aindex < $targetindex) {
|
| 1926 |
|
|
$targetnode = $node;
|
| 1927 |
|
|
$targetindex = $aindex;
|
| 1928 |
|
|
}
|
| 1929 |
|
|
} else {
|
| 1930 |
|
|
if ($aindex > $targetindex) {
|
| 1931 |
|
|
$targetnode = $node;
|
| 1932 |
|
|
$targetindex = $aindex;
|
| 1933 |
|
|
}
|
| 1934 |
|
|
}
|
| 1935 |
|
|
}
|
| 1936 |
|
|
}
|
| 1937 |
|
|
}
|
| 1938 |
|
|
}
|
| 1939 |
|
|
if ($targetnode && $uuid) {
|
| 1940 |
|
|
if ($targetnode->{'status'} eq 'asleep') {
|
| 1941 |
|
|
my $nmac = $targetnode->{'mac'};
|
| 1942 |
|
|
my $realmac = substr($nmac,0,2).":".substr($nmac,2,2).":".substr($nmac,4,2).":".substr($nmac,6,2).":".substr($nmac,8,2).":".substr($nmac,10,2);
|
| 1943 |
|
|
my $nlogmsg = "Node $nmac marked for wake ";
|
| 1944 |
|
|
if ($brutalsleep && (
|
| 1945 |
|
|
($targetnode->{'amtip'} && $targetnode->{'amtip'} ne '--')
|
| 1946 |
|
|
|| ($targetnode->{'ipmiip'} && $targetnode->{'ipmiip'} ne '--')
|
| 1947 |
|
|
)) {
|
| 1948 |
|
|
my $wakecmd;
|
| 1949 |
|
|
if ($targetnode->{'amtip'} && $targetnode->{'amtip'} ne '--') {
|
| 1950 |
|
|
$wakecmd = "echo 'y' | AMT_PASSWORD='$amtpasswd' /usr/bin/amttool $targetnode->{'amtip'} powerup pxe";
|
| 1951 |
|
|
} else {
|
| 1952 |
|
|
$wakecmd = "ipmitool -I lanplus -H $targetnode->{'ipmiip'} -U ADMIN -P ADMIN power on";
|
| 1953 |
|
|
}
|
| 1954 |
|
|
$nlogmsg .= `$wakecmd`;
|
| 1955 |
|
|
} else {
|
| 1956 |
|
|
my $broadcastip = $targetnode->{'ip'};
|
| 1957 |
|
|
$broadcastip =~ s/\.\d{1,3}$/.255/;
|
| 1958 |
|
|
$nlogmsg .= 'on lan ' . `/usr/bin/wakeonlan -i $broadcastip $realmac`;
|
| 1959 |
|
|
}
|
| 1960 |
|
|
$targetnode->{'status'} = "waking";
|
| 1961 |
|
|
$nlogmsg =~ s/\n/ /g;
|
| 1962 |
|
|
$main::syslogit->($user, "info", $nlogmsg);
|
| 1963 |
|
|
$postreply .= "Status=OK waking $targetnode->{'name'}\n";
|
| 1964 |
|
|
}
|
| 1965 |
|
|
$targetname = $targetnode->{'name'};
|
| 1966 |
|
|
$targetmac = $targetnode->{'mac'};
|
| 1967 |
|
|
$targetip = $targetnode->{'ip'};
|
| 1968 |
|
|
$targetip = $targetnode->{'ip'};
|
| 1969 |
|
|
my $porttaken = 1;
|
| 1970 |
|
|
while ($porttaken) {
|
| 1971 |
|
|
$porttaken = 0;
|
| 1972 |
|
|
$port = $targetnode->{'vms'} + (($hypervisor eq "vbox")?3389:5900);
|
| 1973 |
|
|
$port += int(rand(200));
|
| 1974 |
|
|
my @regkeys = (tied %register)->select_where("port = '$port' AND macip = '$targetip'");
|
| 1975 |
|
|
foreach my $k (@regkeys) {
|
| 1976 |
|
|
$r = $register{$k};
|
| 1977 |
|
|
if ($r->{'port'} eq $port && $r->{'macip'} eq $targetip) {
|
| 1978 |
|
|
$porttaken = 1;
|
| 1979 |
|
|
}
|
| 1980 |
|
|
}
|
| 1981 |
|
|
}
|
| 1982 |
|
|
$targetnode->{'vms'}++;
|
| 1983 |
|
|
$targetnode->{'vmvcpus'} += $vcpu;
|
| 1984 |
|
|
$register{$uuid}->{'port'} = $port;
|
| 1985 |
|
|
# $register{$uuid}->{'mac'} = $targetmac;
|
| 1986 |
|
|
# $register{$uuid}->{'macname'} = $targetname;
|
| 1987 |
|
|
# $register{$uuid}->{'macip'} = $targetip;
|
| 1988 |
|
|
$register{$uuid}->{'display'} = (($hypervisor eq "vbox")?'rdp':'vnc');
|
| 1989 |
|
|
} else {
|
| 1990 |
|
|
my $macstatus;
|
| 1991 |
|
|
$macstatus = $nodereg{$dmac}->{status} if ($nodereg{$dmac});
|
| 1992 |
d3805c61
|
hq
|
$main::syslogit->($user, "info", "Could not find target for $uuid, $dmac, $imageonnode, $mem, $vcpu, $image, $image2,$image3,$image4, $hypervisor, $smac, dmac-status: $macstatus") if ($uuid);
|
| 1993 |
95b003ff
|
Origo
|
}
|
| 1994 |
|
|
return ($targetmac, $targetname, $targetip, $port, \%avhash);
|
| 1995 |
|
|
}
|
| 1996 |
|
|
|
| 1997 |
|
|
sub destroyUserServers {
|
| 1998 |
|
|
my $username = shift;
|
| 1999 |
|
|
my $wait = shift; # Should we wait for servers do die
|
| 2000 |
|
|
my $duuid = shift;
|
| 2001 |
6372a66e
|
hq
|
return unless ($username && ($isadmin || $user eq $username));
|
| 2002 |
95b003ff
|
Origo
|
my @updateList;
|
| 2003 |
|
|
|
| 2004 |
|
|
my @regkeys = (tied %register)->select_where("user = '$username'");
|
| 2005 |
|
|
foreach my $uuid (@regkeys) {
|
| 2006 |
|
|
if ($register{$uuid}->{'user'} eq $username
|
| 2007 |
|
|
&& $register{$uuid}->{'status'} ne 'shutoff'
|
| 2008 |
|
|
&& (!$duuid || $duuid eq $uuid)
|
| 2009 |
|
|
) {
|
| 2010 |
|
|
$postreply .= "Destroying $username server $register{$uuid}->{'name'}, $uuid\n";
|
| 2011 |
|
|
Destroy($uuid);
|
| 2012 |
|
|
push (@updateList,{ tab=>'servers',
|
| 2013 |
|
|
user=>$user,
|
| 2014 |
|
|
uuid=>$duuid,
|
| 2015 |
|
|
status=>'destroying'});
|
| 2016 |
|
|
}
|
| 2017 |
|
|
}
|
| 2018 |
|
|
$main::updateUI->(@updateList) if (@updateList);
|
| 2019 |
|
|
if ($wait) {
|
| 2020 |
|
|
my @regkeys = (tied %register)->select_where("user = '$username'");
|
| 2021 |
|
|
my $activeservers = 1;
|
| 2022 |
|
|
my $i = 0;
|
| 2023 |
6372a66e
|
hq
|
while ($activeservers && $i<30) {
|
| 2024 |
95b003ff
|
Origo
|
$activeservers = 0;
|
| 2025 |
|
|
foreach my $k (@regkeys) {
|
| 2026 |
|
|
my $valref = $register{$k};
|
| 2027 |
|
|
if ($username eq $valref->{'user'}
|
| 2028 |
|
|
&& ($valref->{'status'} ne 'shutoff'
|
| 2029 |
|
|
&& $valref->{'status'} ne 'inactive')
|
| 2030 |
|
|
&& (!$duuid || $duuid eq $valref->{'uuid'})
|
| 2031 |
|
|
) {
|
| 2032 |
|
|
$activeservers = $valref->{'uuid'};
|
| 2033 |
|
|
}
|
| 2034 |
|
|
}
|
| 2035 |
|
|
$i++;
|
| 2036 |
|
|
if ($activeservers) {
|
| 2037 |
|
|
my $res .= "Status=OK Waiting $i for server $register{$activeservers}->{'name'}, $register{$activeservers}->{'status'} to die...\n";
|
| 2038 |
9de5a3f1
|
hq
|
# print $res if ($console);
|
| 2039 |
95b003ff
|
Origo
|
$postreply .= $res;
|
| 2040 |
|
|
sleep 2;
|
| 2041 |
|
|
}
|
| 2042 |
|
|
}
|
| 2043 |
|
|
$postreply .= "Status=OK Servers halted for $username\n" unless ($activeservers);
|
| 2044 |
|
|
}
|
| 2045 |
|
|
return $postreply;
|
| 2046 |
|
|
}
|
| 2047 |
|
|
|
| 2048 |
|
|
sub removeUserServers {
|
| 2049 |
|
|
my $username = shift;
|
| 2050 |
|
|
my $uuid = shift;
|
| 2051 |
|
|
my $destroy = shift; # Should running servers be destroyed before removing
|
| 2052 |
|
|
return unless (($isadmin || $user eq $username) && !$isreadonly);
|
| 2053 |
|
|
$user = $username;
|
| 2054 |
|
|
my @regkeys = (tied %register)->select_where("user = '$username'");
|
| 2055 |
|
|
foreach my $ruuid (@regkeys) {
|
| 2056 |
|
|
next if ($uuid && $ruuid ne $uuid);
|
| 2057 |
|
|
if ($destroy && $register{$ruuid}->{'user'} eq $username && ($register{$ruuid}->{'status'} ne 'shutoff' && $register{$ruuid}->{'status'} ne 'inactive')) {
|
| 2058 |
|
|
destroyUserServers($username, 1, $ruuid);
|
| 2059 |
|
|
}
|
| 2060 |
|
|
|
| 2061 |
|
|
if ($register{$ruuid}->{'user'} eq $username && ($register{$ruuid}->{'status'} eq 'shutoff' || $register{$ruuid}->{'status'} eq 'inactive')) {
|
| 2062 |
|
|
$postreply .= "Removing $username server $register{$ruuid}->{'name'}, $ruuid" . ($console?'':'<br>') . "\n";
|
| 2063 |
|
|
Remove($ruuid);
|
| 2064 |
|
|
}
|
| 2065 |
|
|
}
|
| 2066 |
|
|
}
|
| 2067 |
|
|
|
| 2068 |
|
|
sub Remove {
|
| 2069 |
|
|
my ($uuid, $action) = @_;
|
| 2070 |
|
|
if ($help) {
|
| 2071 |
|
|
return <<END
|
| 2072 |
|
|
DELETE:uuid:
|
| 2073 |
|
|
Removes a server. Server must be shutoff. Does not remove associated images or networks.
|
| 2074 |
|
|
END
|
| 2075 |
|
|
}
|
| 2076 |
|
|
my $reguser = $register{$uuid}->{'user'};
|
| 2077 |
|
|
my $dbstatus = $register{$uuid}->{'status'};
|
| 2078 |
|
|
my $image = $register{$uuid}->{'image'};
|
| 2079 |
|
|
my $image2 = $register{$uuid}->{'image2'};
|
| 2080 |
|
|
my $image3 = $register{$uuid}->{'image3'};
|
| 2081 |
|
|
my $image4 = $register{$uuid}->{'image4'};
|
| 2082 |
|
|
my $name = $register{$uuid}->{'name'};
|
| 2083 |
|
|
$image2 = '' if ($image2 eq '--');
|
| 2084 |
|
|
$image3 = '' if ($image3 eq '--');
|
| 2085 |
|
|
$image4 = '' if ($image4 eq '--');
|
| 2086 |
|
|
|
| 2087 |
|
|
if ($reguser ne $user) {
|
| 2088 |
|
|
$postreply .= "Status=ERROR You cannot delete a vm you don't own\n";
|
| 2089 |
|
|
} elsif ($dbstatus eq 'inactive' || $dbstatus eq 'shutdown' || $dbstatus eq 'shutoff') {
|
| 2090 |
|
|
|
| 2091 |
|
|
# Delete software packages and monitors from register
|
| 2092 |
|
|
$postmsg .= deletePackages($uuid);
|
| 2093 |
|
|
my $sname = $register{$uuid}->{'name'};
|
| 2094 |
|
|
utf8::decode($sname);
|
| 2095 |
48fcda6b
|
Origo
|
$postmsg .= deleteMonitors($uuid)?" deleted monitors for $sname ":'';
|
| 2096 |
95b003ff
|
Origo
|
|
| 2097 |
|
|
delete $register{$uuid};
|
| 2098 |
|
|
delete $xmlreg{$uuid};
|
| 2099 |
|
|
|
| 2100 |
|
|
unless ( tie(%imagereg,'Tie::DBI', Hash::Merge::merge({table=>'images', key=>'path'}, $Stabile::dbopts)) ) {return "Unable to access images register"};
|
| 2101 |
|
|
$imagereg{$image}->{'status'} = "unused" if ($imagereg{$image});
|
| 2102 |
|
|
$imagereg{$image2}->{'status'} = "unused" if ($image2 && $imagereg{$image2});
|
| 2103 |
|
|
$imagereg{$image3}->{'status'} = "unused" if ($image3 && $imagereg{$image3});
|
| 2104 |
|
|
$imagereg{$image4}->{'status'} = "unused" if ($image4 && $imagereg{$image4});
|
| 2105 |
|
|
untie %imagereg;
|
| 2106 |
|
|
|
| 2107 |
|
|
# Delete metrics
|
| 2108 |
|
|
my $metricsdir = "/var/lib/graphite/whisper/domains/$uuid";
|
| 2109 |
|
|
`rm -r $metricsdir` if (-e $metricsdir);
|
| 2110 |
|
|
my $rrdfile = "/var/cache/rrdtool/".$uuid."_highres.rrd";
|
| 2111 |
|
|
`rm $rrdfile` if (-e $rrdfile);
|
| 2112 |
|
|
|
| 2113 |
|
|
$main::syslogit->($user, "info", "Deleted domain $uuid from db");
|
| 2114 |
|
|
utf8::decode($name);
|
| 2115 |
48fcda6b
|
Origo
|
$postmsg .= " deleted server $name";
|
| 2116 |
95b003ff
|
Origo
|
$postreply = "[]";
|
| 2117 |
|
|
sleep 1;
|
| 2118 |
|
|
} else {
|
| 2119 |
|
|
$postreply .= "Status=ERROR Cannot delete a $dbstatus server\n";
|
| 2120 |
|
|
}
|
| 2121 |
|
|
return $postreply;
|
| 2122 |
|
|
}
|
| 2123 |
|
|
|
| 2124 |
|
|
# Delete all monitors belonging to a server
|
| 2125 |
|
|
sub deleteMonitors {
|
| 2126 |
|
|
my ($serveruuid) = @_;
|
| 2127 |
|
|
my $match;
|
| 2128 |
|
|
if ($serveruuid) {
|
| 2129 |
|
|
if ($register{$serveruuid}->{'user'} eq $user || $isadmin) {
|
| 2130 |
|
|
local($^I, @ARGV) = ('.bak', "/etc/mon/mon.cf");
|
| 2131 |
|
|
# undef $/; # This makes <> read in the entire file in one go
|
| 2132 |
|
|
my $uuidmatch;
|
| 2133 |
|
|
while (<>) {
|
| 2134 |
|
|
if (/^watch (\S+)/) {
|
| 2135 |
|
|
if ($1 eq $serveruuid) {$uuidmatch = $serveruuid}
|
| 2136 |
|
|
else {$uuidmatch = ''};
|
| 2137 |
|
|
};
|
| 2138 |
|
|
if ($uuidmatch) {
|
| 2139 |
|
|
$match = 1;
|
| 2140 |
|
|
} else {
|
| 2141 |
|
|
#chomp;
|
| 2142 |
|
|
print unless (/^hostgroup $serveruuid/);
|
| 2143 |
|
|
}
|
| 2144 |
|
|
close ARGV if eof;
|
| 2145 |
|
|
}
|
| 2146 |
|
|
#$/ = "\n";
|
| 2147 |
|
|
}
|
| 2148 |
|
|
unlink glob "/var/log/stabile/*:$serveruuid:*";
|
| 2149 |
|
|
}
|
| 2150 |
|
|
`/usr/bin/moncmd reset keepstate` if ($match);
|
| 2151 |
|
|
return $match;
|
| 2152 |
|
|
}
|
| 2153 |
|
|
|
| 2154 |
|
|
sub deletePackages {
|
| 2155 |
|
|
my ($uuid, $issystem, %packreg) = @_;
|
| 2156 |
|
|
unless ( tie(%packreg,'Tie::DBI', Hash::Merge::merge({table=>'packages', key=>'id'}, $Stabile::dbopts)) ) {return "Unable to access images register"};
|
| 2157 |
|
|
|
| 2158 |
|
|
my @domains;
|
| 2159 |
|
|
if ($issystem) {
|
| 2160 |
|
|
foreach my $valref (values %register) {
|
| 2161 |
|
|
if (($valref->{'system'} eq $uuid || $uuid eq '*')
|
| 2162 |
|
|
&& ($valref->{'user'} eq $user || $fulllist)) {
|
| 2163 |
|
|
push(@domains, $valref->{'uuid'});
|
| 2164 |
|
|
}
|
| 2165 |
|
|
}
|
| 2166 |
|
|
} else { # Allow if domain no longer exists or belongs to user
|
| 2167 |
|
|
push(@domains, $uuid) if (!$register{$uuid} || $register{$uuid}->{'user'} eq $user || $fulllist);
|
| 2168 |
|
|
}
|
| 2169 |
|
|
|
| 2170 |
|
|
foreach my $domuuid (@domains) {
|
| 2171 |
|
|
foreach my $packref (values %packreg) {
|
| 2172 |
|
|
my $id = $packref->{'id'};
|
| 2173 |
|
|
if (substr($id, 0,36) eq $domuuid || ($uuid eq '*' && $packref->{'user'} eq $user)) {
|
| 2174 |
|
|
delete $packreg{$id};
|
| 2175 |
|
|
}
|
| 2176 |
|
|
}
|
| 2177 |
|
|
}
|
| 2178 |
|
|
tied(%packreg)->commit;# if (%packreg);
|
| 2179 |
|
|
if ($issystem) {
|
| 2180 |
|
|
my $sname = $register{$uuid}->{'name'};
|
| 2181 |
|
|
utf8::decode($sname);
|
| 2182 |
|
|
return "Status=OK Cleared packages for $sname\n";
|
| 2183 |
|
|
} elsif ($register{$uuid}) {
|
| 2184 |
|
|
my $sname = $register{$uuid}->{'name'};
|
| 2185 |
|
|
utf8::decode($sname);
|
| 2186 |
|
|
return "Status=OK Cleared packages for $sname\n";
|
| 2187 |
|
|
} else {
|
| 2188 |
|
|
return "Status=OK Cleared packages. System not registered\n";
|
| 2189 |
|
|
}
|
| 2190 |
|
|
}
|
| 2191 |
|
|
|
| 2192 |
|
|
sub Save {
|
| 2193 |
|
|
my ($uuid, $action, $obj) = @_;
|
| 2194 |
|
|
if ($help) {
|
| 2195 |
|
|
return <<END
|
| 2196 |
04c16f26
|
hq
|
POST:uuid, name, user, system, autostart, locktonode, mac, memory, vcpu, boot, loader, diskbus, nicmodel1, vgpu, cdrom, image, image2, image3, image4, networkuuid2, networkuuid3, networkuuid1, nicmac1, nicmac2, nicmac3:
|
| 2197 |
95b003ff
|
Origo
|
To save a servers of networks you either PUT or POST a JSON array to the main endpoint with objects representing the servers with the changes you want.
|
| 2198 |
|
|
Depending on your privileges not all changes are permitted. If you save without specifying a uuid, a new server is created.
|
| 2199 |
|
|
If you pass [user] parameter it is assumed you want to move server to this user's account.
|
| 2200 |
|
|
Supported parameters:
|
| 2201 |
|
|
|
| 2202 |
|
|
uuid: UUID
|
| 2203 |
|
|
name: string
|
| 2204 |
|
|
user: string
|
| 2205 |
48fcda6b
|
Origo
|
system: UUID of stack this server belongs to
|
| 2206 |
95b003ff
|
Origo
|
autostart: true|false
|
| 2207 |
|
|
locktonode: true|false
|
| 2208 |
|
|
mac: MAC address of target node
|
| 2209 |
|
|
|
| 2210 |
|
|
memory: int bytes
|
| 2211 |
|
|
vcpu: int
|
| 2212 |
|
|
boot: hd|cdrom|network
|
| 2213 |
04c16f26
|
hq
|
loader: bios|uefi
|
| 2214 |
95b003ff
|
Origo
|
diskbus: virtio|ide|scsi
|
| 2215 |
|
|
nicmodel1: virtio|rtl8139|ne2k_pci|e1000|i82551|i82557b|i82559er|pcnet
|
| 2216 |
|
|
vgpu: int
|
| 2217 |
|
|
|
| 2218 |
|
|
cdrom: string path
|
| 2219 |
|
|
image: string path
|
| 2220 |
|
|
image2: string path
|
| 2221 |
|
|
image3: string path
|
| 2222 |
|
|
image4: string path
|
| 2223 |
|
|
|
| 2224 |
|
|
networkuuid1: UUID of network connection
|
| 2225 |
|
|
networkuuid2: UUID of network connection
|
| 2226 |
|
|
networkuuid3: UUID of network connection
|
| 2227 |
|
|
|
| 2228 |
|
|
END
|
| 2229 |
|
|
}
|
| 2230 |
|
|
|
| 2231 |
|
|
# notes, opemail, opfullname, opphone, email, fullname, phone, services, recovery, alertemail
|
| 2232 |
|
|
# notes: string
|
| 2233 |
|
|
# opemail: string
|
| 2234 |
|
|
# opfullname: string
|
| 2235 |
|
|
# opphone: string
|
| 2236 |
|
|
# email: string
|
| 2237 |
|
|
# fullname: string
|
| 2238 |
|
|
# phone: string
|
| 2239 |
|
|
# services: string
|
| 2240 |
|
|
# recovery: string
|
| 2241 |
|
|
# alertemail: string
|
| 2242 |
|
|
|
| 2243 |
|
|
my $system = $obj->{system};
|
| 2244 |
|
|
my $newsystem = $obj->{newsystem};
|
| 2245 |
|
|
my $buildsystem = $obj->{buildsystem};
|
| 2246 |
|
|
my $nicmac1 = $obj->{nicmac1};
|
| 2247 |
|
|
$console = $console || $obj->{console};
|
| 2248 |
|
|
|
| 2249 |
|
|
$postmsg = '' if ($buildsystem);
|
| 2250 |
|
|
if (!$uuid && $nicmac1) {
|
| 2251 |
|
|
$uuid = nicmac1ToUuid($nicmac1); # If no uuid try to locate based on mac
|
| 2252 |
|
|
}
|
| 2253 |
|
|
if (!$uuid && $uripath =~ /servers(\.cgi)?\/(.+)/) { # Try to parse uuid out of URI
|
| 2254 |
|
|
my $huuid = $2;
|
| 2255 |
|
|
if ($ug->to_string($ug->from_string($huuid)) eq $huuid) { # Check for valid uuid
|
| 2256 |
|
|
$uuid = $huuid;
|
| 2257 |
|
|
}
|
| 2258 |
|
|
}
|
| 2259 |
|
|
my $regserv = $register{$uuid};
|
| 2260 |
|
|
my $status = $regserv->{'status'} || 'new';
|
| 2261 |
|
|
if ((!$uuid) && $status eq 'new') {
|
| 2262 |
|
|
my $ug = new Data::UUID;
|
| 2263 |
|
|
$uuid = $ug->create_str();
|
| 2264 |
|
|
};
|
| 2265 |
|
|
unless ($uuid && length $uuid == 36){
|
| 2266 |
48fcda6b
|
Origo
|
$postmsg = "Status=Error No valid uuid ($uuid), $obj->{image}";
|
| 2267 |
95b003ff
|
Origo
|
return $postmsg;
|
| 2268 |
|
|
}
|
| 2269 |
|
|
$nicmac1 = $nicmac1 || $regserv->{'nicmac1'};
|
| 2270 |
|
|
my $name = $obj->{name} || $regserv->{'name'};
|
| 2271 |
|
|
my $memory = $obj->{memory} || $regserv->{'memory'};
|
| 2272 |
|
|
my $vcpu = $obj->{vcpu} || $regserv->{'vcpu'};
|
| 2273 |
|
|
my $image = $obj->{image} || $regserv->{'image'};
|
| 2274 |
|
|
my $imagename = $obj->{imagename} || $regserv->{'imagename'};
|
| 2275 |
|
|
my $image2 = $obj->{image2} || $regserv->{'image2'};
|
| 2276 |
|
|
my $image2name = $obj->{image2name} || $regserv->{'image2name'};
|
| 2277 |
|
|
my $image3 = $obj->{image3} || $regserv->{'image3'};
|
| 2278 |
|
|
my $image3name = $obj->{image3name} || $regserv->{'image3name'};
|
| 2279 |
|
|
my $image4 = $obj->{image4} || $regserv->{'image4'};
|
| 2280 |
|
|
my $image4name = $obj->{image4name} || $regserv->{'image4name'};
|
| 2281 |
|
|
my $diskbus = $obj->{diskbus} || $regserv->{'diskbus'};
|
| 2282 |
|
|
my $cdrom = $obj->{cdrom} || $regserv->{'cdrom'};
|
| 2283 |
|
|
my $boot = $obj->{boot} || $regserv->{'boot'};
|
| 2284 |
04c16f26
|
hq
|
my $loader = $obj->{loader} || $regserv->{'loader'};
|
| 2285 |
95b003ff
|
Origo
|
my $networkuuid1 = ($obj->{networkuuid1} || $obj->{networkuuid1} eq '0')?$obj->{networkuuid1}:$regserv->{'networkuuid1'};
|
| 2286 |
|
|
my $networkid1 = $obj->{networkid1} || $regserv->{'networkid1'};
|
| 2287 |
|
|
my $networkname1 = $obj->{networkname1} || $regserv->{'networkname1'};
|
| 2288 |
|
|
my $nicmodel1 = $obj->{nicmodel1} || $regserv->{'nicmodel1'};
|
| 2289 |
|
|
my $networkuuid2 = ($obj->{networkuuid2} || $obj->{networkuuid2} eq '0')?$obj->{networkuuid2}:$regserv->{'networkuuid2'};
|
| 2290 |
|
|
my $networkid2 = $obj->{networkid2} || $regserv->{'networkid2'};
|
| 2291 |
|
|
my $networkname2 = $obj->{networkname2} || $regserv->{'networkname2'};
|
| 2292 |
|
|
my $nicmac2 = $obj->{nicmac2} || $regserv->{'nicmac2'};
|
| 2293 |
|
|
my $networkuuid3 = ($obj->{networkuuid3} || $obj->{networkuuid3} eq '0')?$obj->{networkuuid3}:$regserv->{'networkuuid3'};
|
| 2294 |
|
|
my $networkid3 = $obj->{networkid3} || $regserv->{'networkid3'};
|
| 2295 |
|
|
my $networkname3 = $obj->{networkname3} || $regserv->{'networkname3'};
|
| 2296 |
|
|
my $nicmac3 = $obj->{nicmac3} || $regserv->{'nicmac3'};
|
| 2297 |
|
|
my $notes = $obj->{notes} || $regserv->{'notes'};
|
| 2298 |
|
|
my $autostart = $obj->{autostart} || $regserv->{'autostart'};
|
| 2299 |
|
|
my $locktonode = $obj->{locktonode} || $regserv->{'locktonode'};
|
| 2300 |
|
|
my $mac = $obj->{mac} || $regserv->{'mac'};
|
| 2301 |
|
|
my $created = $regserv->{'created'} || time;
|
| 2302 |
|
|
# Sanity checks
|
| 2303 |
|
|
my $tenderpaths = $Stabile::config->get('STORAGE_POOLS_LOCAL_PATHS') || "/mnt/stabile/images";
|
| 2304 |
|
|
my @tenderpathslist = split(/,\s*/, $tenderpaths);
|
| 2305 |
|
|
|
| 2306 |
|
|
$networkid1 = $networkreg{$networkuuid1}->{'id'};
|
| 2307 |
|
|
my $networktype1 = $networkreg{$networkuuid1}->{'type'};
|
| 2308 |
|
|
my $networktype2;
|
| 2309 |
|
|
if (!$nicmac1 || $nicmac1 eq "--") {$nicmac1 = randomMac();}
|
| 2310 |
|
|
if ($networkuuid2 && $networkuuid2 ne "--") {
|
| 2311 |
|
|
$networkid2 = $networkreg{$networkuuid2}->{'id'};
|
| 2312 |
|
|
$nicmac2 = randomMac() if (!$nicmac2 || $nicmac2 eq "--");
|
| 2313 |
|
|
$networktype2 = $networkreg{$networkuuid2}->{'type'};
|
| 2314 |
|
|
}
|
| 2315 |
|
|
if ($networkuuid3 && $networkuuid3 ne "--") {
|
| 2316 |
|
|
$networkid3 = $networkreg{$networkuuid3}->{'id'};
|
| 2317 |
|
|
$networkname3 = $networkreg{$networkuuid3}->{'name'};
|
| 2318 |
|
|
$nicmac3 = randomMac() if (!$nicmac3 || $nicmac3 eq "--");
|
| 2319 |
|
|
$networktype3 = $networkreg{$networkuuid3}->{'type'};
|
| 2320 |
|
|
}
|
| 2321 |
|
|
|
| 2322 |
|
|
my $imgdup;
|
| 2323 |
|
|
my $netdup;
|
| 2324 |
|
|
my $json_text; # returned if all goes well
|
| 2325 |
|
|
|
| 2326 |
|
|
unless ( tie(%imagereg,'Tie::DBI', Hash::Merge::merge({table=>'images', key=>'path'}, $Stabile::dbopts)) ) {return "Unable to access images register"};
|
| 2327 |
|
|
|
| 2328 |
|
|
if ($networkid1 > 1 && $networkid2 > 1 && $networktype1 ne 'gateway' && $networktype2 ne 'gateway'
|
| 2329 |
|
|
&& $networkuuid1 eq $networkuuid2) {
|
| 2330 |
|
|
$netdup = 1;
|
| 2331 |
|
|
}
|
| 2332 |
|
|
if ($networkid1 > 1 && $networkid3 > 1 && $networktype1 ne 'gateway' && $networktype3 ne 'gateway'
|
| 2333 |
|
|
&& $networkuuid1 eq $networkuuid3) {
|
| 2334 |
|
|
$netdup = 11;
|
| 2335 |
|
|
}
|
| 2336 |
|
|
if ($image eq $image2
|
| 2337 |
|
|
|| $image eq $image3
|
| 2338 |
|
|
|| $image eq $image4
|
| 2339 |
|
|
|| $image2 && $image2 ne '--' && $image2 eq $image3
|
| 2340 |
|
|
|| $image2 && $image2 ne '--' && $image2 eq $image4
|
| 2341 |
|
|
|| $image3 && $image3 ne '--' && $image3 eq $image4
|
| 2342 |
|
|
) {
|
| 2343 |
|
|
$imgdup = 1;
|
| 2344 |
|
|
} elsif ($image =~ m/\.master\.qcow2/
|
| 2345 |
|
|
|| $image2 =~ m/\.master\.qcow2/
|
| 2346 |
|
|
|| $image3 =~ m/\.master\.qcow2/
|
| 2347 |
|
|
|| $image4 =~ m/\.master\.qcow2/
|
| 2348 |
|
|
) {
|
| 2349 |
|
|
$imgdup = 2;
|
| 2350 |
|
|
} else {
|
| 2351 |
|
|
# Check if another server is using image
|
| 2352 |
|
|
my @regkeys = (tied %register)->select_where("user = '$user' OR user = 'common'");
|
| 2353 |
|
|
foreach my $k (@regkeys) {
|
| 2354 |
|
|
my $val = $register{$k};
|
| 2355 |
a2e0bc7e
|
hq
|
if ($val->{'uuid'} ne $uuid) {
|
| 2356 |
95b003ff
|
Origo
|
if (
|
| 2357 |
a2e0bc7e
|
hq
|
$image eq $val->{'image'} || $image eq $val->{'image2'}|| $image eq $val->{'image3'}|| $image eq $val->{'image4'}
|
| 2358 |
95b003ff
|
Origo
|
) {
|
| 2359 |
|
|
$imgdup = 51;
|
| 2360 |
|
|
} elsif ($image2 && $image2 ne "--" &&
|
| 2361 |
a2e0bc7e
|
hq
|
($image2 eq $val->{'image'} || $image2 eq $val->{'image2'} || $image2 eq $val->{'image3'} || $image2 eq $val->{'image4'})
|
| 2362 |
95b003ff
|
Origo
|
) {
|
| 2363 |
|
|
$imgdup = 52;
|
| 2364 |
|
|
} elsif ($image3 && $image3 ne "--" &&
|
| 2365 |
a2e0bc7e
|
hq
|
($image3 eq $val->{'image'} || $image3 eq $val->{'image2'} || $image3 eq $val->{'image3'} || $image3 eq $val->{'image4'})
|
| 2366 |
95b003ff
|
Origo
|
) {
|
| 2367 |
|
|
$imgdup = 53;
|
| 2368 |
|
|
} elsif ($image4 && $image4 ne "--" &&
|
| 2369 |
a2e0bc7e
|
hq
|
($image4 eq $val->{'image'} || $image4 eq $val->{'image2'} || $image4 eq $val->{'image3'} || $image4 eq $val->{'image4'})
|
| 2370 |
95b003ff
|
Origo
|
) {
|
| 2371 |
|
|
$imgdup = 54;
|
| 2372 |
|
|
}
|
| 2373 |
|
|
|
| 2374 |
|
|
if ($networkid1>1) {
|
| 2375 |
|
|
if ($networktype1 ne 'gateway' &&
|
| 2376 |
a2e0bc7e
|
hq
|
($networkuuid1 eq $val->{'networkuuid1'} || $networkuuid1 eq $val->{'networkuuid2'})
|
| 2377 |
95b003ff
|
Origo
|
) {
|
| 2378 |
|
|
$netdup = 51;
|
| 2379 |
|
|
}
|
| 2380 |
|
|
}
|
| 2381 |
|
|
if ($networkid2>1) {
|
| 2382 |
|
|
if ($networktype2 ne 'gateway' && $networkuuid2 && $networkuuid2 ne "--" &&
|
| 2383 |
a2e0bc7e
|
hq
|
($networkuuid2 eq $val->{'networkuuid1'} || $networkuuid2 eq $val->{'networkuuid2'})
|
| 2384 |
95b003ff
|
Origo
|
) {
|
| 2385 |
|
|
$netdup = 52;
|
| 2386 |
|
|
}
|
| 2387 |
|
|
}
|
| 2388 |
|
|
}
|
| 2389 |
|
|
}
|
| 2390 |
|
|
my $legalpath;
|
| 2391 |
|
|
if ($image =~ m/\/mnt\/stabile\/node\/$user/) {
|
| 2392 |
|
|
$legalpath = 1;
|
| 2393 |
|
|
} else {
|
| 2394 |
|
|
foreach my $path (@tenderpathslist) {
|
| 2395 |
|
|
if ($image =~ m/$path\/$user/) {
|
| 2396 |
|
|
$legalpath = 1;
|
| 2397 |
|
|
last;
|
| 2398 |
|
|
}
|
| 2399 |
|
|
}
|
| 2400 |
|
|
}
|
| 2401 |
|
|
$imgdup = 6 unless $legalpath;
|
| 2402 |
|
|
if ($image2 && $image2 ne "--") { # TODO: We should probably check for conflicting nodes for image3 and image 4 too
|
| 2403 |
|
|
if ($image2 =~ m/\/mnt\/stabile\/node\/$user/) {
|
| 2404 |
|
|
if ($image =~ m/\/mnt\/stabile\/node\/$user/) {
|
| 2405 |
|
|
if ($imagereg{$image}->{'mac'} eq $imagereg{$image2}->{'mac'}) {
|
| 2406 |
|
|
$legalpath = 1;
|
| 2407 |
|
|
} else {
|
| 2408 |
|
|
$legalpath = 0; # Images are on two different nodes
|
| 2409 |
|
|
}
|
| 2410 |
|
|
} else {
|
| 2411 |
|
|
$legalpath = 1;
|
| 2412 |
|
|
}
|
| 2413 |
|
|
} else {
|
| 2414 |
|
|
$legalpath = 0;
|
| 2415 |
|
|
foreach my $path (@tenderpathslist) {
|
| 2416 |
|
|
if ($image2 =~ m/$path\/$user/) {
|
| 2417 |
|
|
$legalpath = 1;
|
| 2418 |
|
|
last;
|
| 2419 |
|
|
}
|
| 2420 |
|
|
}
|
| 2421 |
|
|
}
|
| 2422 |
|
|
$imgdup = 7 unless $legalpath;
|
| 2423 |
|
|
}
|
| 2424 |
|
|
}
|
| 2425 |
|
|
|
| 2426 |
|
|
if (!$imgdup && !$netdup) {
|
| 2427 |
|
|
if ($status eq "new") {
|
| 2428 |
|
|
$status = "shutoff";
|
| 2429 |
|
|
$name = $name || 'New Server';
|
| 2430 |
|
|
$memory = $memory || 1024;
|
| 2431 |
|
|
$vcpu = $vcpu || 1;
|
| 2432 |
|
|
$imagename = $imagename || '--';
|
| 2433 |
|
|
$image2 = $image2 || '--';
|
| 2434 |
|
|
$image2name = $image2name || '--';
|
| 2435 |
|
|
$image3 = $image3 || '--';
|
| 2436 |
|
|
$image3name = $image3name || '--';
|
| 2437 |
|
|
$image4 = $image4 || '--';
|
| 2438 |
|
|
$image4name = $image4name || '--';
|
| 2439 |
|
|
$diskbus = $diskbus || 'ide';
|
| 2440 |
|
|
$cdrom = $cdrom || '--';
|
| 2441 |
|
|
$boot = $boot || 'hd';
|
| 2442 |
04c16f26
|
hq
|
$loader = $loader || 'bios';
|
| 2443 |
95b003ff
|
Origo
|
$networkuuid1 = $networkuuid1 || 1;
|
| 2444 |
|
|
$networkid1 = $networkid1 || 1;
|
| 2445 |
|
|
$networkname1 = $networkname1 || '--';
|
| 2446 |
|
|
$nicmodel1 = $nicmodel1 || 'rtl8139';
|
| 2447 |
|
|
$nicmac1 = $nicmac1 || randomMac();
|
| 2448 |
|
|
$networkuuid2 = $networkuuid2 || '--';
|
| 2449 |
|
|
$networkid2 = $networkid2 || '--';
|
| 2450 |
|
|
$networkname2 = $networkname2 || '--';
|
| 2451 |
|
|
$nicmac2 = $nicmac2 || randomMac();
|
| 2452 |
|
|
$networkuuid3 = $networkuuid3 || '--';
|
| 2453 |
|
|
$networkid3 = $networkid3 || '--';
|
| 2454 |
|
|
$networkname3 = $networkname3 || '--';
|
| 2455 |
|
|
$nicmac3 = $nicmac3 || randomMac();
|
| 2456 |
|
|
# $uiuuid = $uuid; # No need to update ui for new server with jsonreststore
|
| 2457 |
8d7785ff
|
Origo
|
$postmsg .= "OK Created new server: $name";
|
| 2458 |
3657de20
|
Origo
|
$postmsg .= ", uuid: $uuid " if ($console);
|
| 2459 |
95b003ff
|
Origo
|
}
|
| 2460 |
|
|
# Update status of images
|
| 2461 |
|
|
my @imgs = ($image, $image2, $image3, $image4);
|
| 2462 |
|
|
my @imgkeys = ('image', 'image2', 'image3', 'image4');
|
| 2463 |
|
|
for (my $i=0; $i<4; $i++) {
|
| 2464 |
|
|
my $img = $imgs[$i];
|
| 2465 |
|
|
my $k = $imgkeys[$i];
|
| 2466 |
|
|
my $regimg = $imagereg{$img};
|
| 2467 |
|
|
# if ($img && $img ne '--' && ($status eq 'new' || $img ne $regserv->{$k})) { # Servers image changed - update image status
|
| 2468 |
|
|
if ($img && $img ne '--') { # Always update image status
|
| 2469 |
|
|
$regimg->{'status'} = 'used' if (
|
| 2470 |
|
|
$regimg->{'status'} eq 'unused'
|
| 2471 |
|
|
# Image cannot be active if server is shutoff
|
| 2472 |
|
|
|| ($regimg->{'status'} eq 'active' && $status eq 'shutoff')
|
| 2473 |
|
|
);
|
| 2474 |
|
|
$regimg->{'domains'} = $uuid;
|
| 2475 |
|
|
$regimg->{'domainnames'} = $name;
|
| 2476 |
|
|
}
|
| 2477 |
|
|
# If image has changed, release the old image
|
| 2478 |
|
|
if ($status ne 'new' && $img ne $regserv->{$k} && $imagereg{$regserv->{$k}}) {
|
| 2479 |
|
|
$imagereg{$regserv->{$k}}->{'status'} = 'unused';
|
| 2480 |
|
|
delete $imagereg{$regserv->{$k}}->{'domains'};
|
| 2481 |
|
|
delete $imagereg{$regserv->{$k}}->{'domainnames'};
|
| 2482 |
|
|
}
|
| 2483 |
|
|
}
|
| 2484 |
|
|
|
| 2485 |
|
|
my $valref = {
|
| 2486 |
|
|
uuid=>$uuid,
|
| 2487 |
|
|
user=>$user,
|
| 2488 |
|
|
name=>$name,
|
| 2489 |
|
|
memory=>$memory,
|
| 2490 |
|
|
vcpu=>$vcpu,
|
| 2491 |
|
|
image=>$image,
|
| 2492 |
|
|
imagename=>$imagename,
|
| 2493 |
|
|
image2=>$image2,
|
| 2494 |
|
|
image2name=>$image2name,
|
| 2495 |
|
|
image3=>$image3,
|
| 2496 |
|
|
image3name=>$image3name,
|
| 2497 |
|
|
image4=>$image4,
|
| 2498 |
|
|
image4name=>$image4name,
|
| 2499 |
|
|
diskbus=>$diskbus,
|
| 2500 |
|
|
cdrom=>$cdrom,
|
| 2501 |
|
|
boot=>$boot,
|
| 2502 |
04c16f26
|
hq
|
loader=>$loader,
|
| 2503 |
95b003ff
|
Origo
|
networkuuid1=>$networkuuid1,
|
| 2504 |
|
|
networkid1=>$networkid1,
|
| 2505 |
|
|
networkname1=>$networkname1,
|
| 2506 |
|
|
nicmodel1=>$nicmodel1,
|
| 2507 |
|
|
nicmac1=>$nicmac1,
|
| 2508 |
|
|
networkuuid2=>$networkuuid2,
|
| 2509 |
|
|
networkid2=>$networkid2,
|
| 2510 |
|
|
networkname2=>$networkname2,
|
| 2511 |
|
|
nicmac2=>$nicmac2,
|
| 2512 |
|
|
networkuuid3=>$networkuuid3,
|
| 2513 |
|
|
networkid3=>$networkid3,
|
| 2514 |
|
|
networkname3=>$networkname3,
|
| 2515 |
|
|
nicmac3=>$nicmac3,
|
| 2516 |
|
|
status=>$status,
|
| 2517 |
|
|
notes=>$notes,
|
| 2518 |
|
|
autostart=>$autostart,
|
| 2519 |
|
|
locktonode=>$locktonode,
|
| 2520 |
|
|
action=>"",
|
| 2521 |
|
|
created=>$created
|
| 2522 |
|
|
};
|
| 2523 |
|
|
$valref->{'system'} = $system if ($system);
|
| 2524 |
|
|
if ($mac && $locktonode eq 'true') {
|
| 2525 |
|
|
$valref->{'mac'} = $mac;
|
| 2526 |
|
|
$valref->{'macip'} = $nodereg{$mac}->{'ip'};
|
| 2527 |
|
|
$valref->{'macname'} = $nodereg{$mac}->{'name'};
|
| 2528 |
|
|
}
|
| 2529 |
|
|
if ($newsystem) {
|
| 2530 |
|
|
my $ug = new Data::UUID;
|
| 2531 |
|
|
$sysuuid = $ug->create_str();
|
| 2532 |
|
|
$valref->{'system'} = $sysuuid;
|
| 2533 |
3657de20
|
Origo
|
$postmsg .= "OK sysuuid: $sysuuid " if ($console);
|
| 2534 |
95b003ff
|
Origo
|
}
|
| 2535 |
|
|
|
| 2536 |
|
|
# Remove domain uuid from old networks. Leave gateways alone - they get updated on next listing
|
| 2537 |
|
|
my $oldnetworkuuid1 = $regserv->{'networkuuid1'};
|
| 2538 |
|
|
if ($oldnetworkuuid1 ne $networkuuid1 && $networkreg{$oldnetworkuuid1}) {
|
| 2539 |
|
|
$networkreg{$oldnetworkuuid1}->{'domains'} =~ s/($uuid)(,?)( ?)//;
|
| 2540 |
|
|
}
|
| 2541 |
|
|
$register{$uuid} = validateItem($valref);
|
| 2542 |
|
|
|
| 2543 |
|
|
if ($networkreg{$networkuuid1}->{'type'} eq 'gateway') {
|
| 2544 |
04c16f26
|
hq
|
# We now remove before adding to support API calls that dont necessarily list afterwards
|
| 2545 |
|
|
$networkreg{$networkuuid1}->{'domains'} =~ s/($uuid)(,?)( ?)//;
|
| 2546 |
95b003ff
|
Origo
|
my $domains = $networkreg{$networkuuid1}->{'domains'};
|
| 2547 |
|
|
$networkreg{$networkuuid1}->{'domains'} = ($domains?"$domains, ":"") . $uuid;
|
| 2548 |
04c16f26
|
hq
|
|
| 2549 |
|
|
$networkreg{$networkuuid1}->{'domainnames'} =~ s/($name)(,?)( ?)//;
|
| 2550 |
95b003ff
|
Origo
|
my $domainnames = $networkreg{$networkuuid1}->{'domainnames'};
|
| 2551 |
|
|
$networkreg{$networkuuid1}->{'domainnames'} = ($domainnames?"$domainnames, ":"") . $name;
|
| 2552 |
|
|
} else {
|
| 2553 |
|
|
$networkreg{$networkuuid1}->{'domains'} = $uuid;
|
| 2554 |
|
|
$networkreg{$networkuuid1}->{'domainnames'} = $name;
|
| 2555 |
|
|
}
|
| 2556 |
|
|
|
| 2557 |
|
|
if ($networkuuid2 && $networkuuid2 ne '--') {
|
| 2558 |
|
|
if ($networkreg{$networkuuid2}->{'type'} eq 'gateway') {
|
| 2559 |
04c16f26
|
hq
|
$networkreg{$networkuuid2}->{'domains'} =~ s/($uuid)(,?)( ?)//;
|
| 2560 |
95b003ff
|
Origo
|
my $domains = $networkreg{$networkuuid2}->{'domains'};
|
| 2561 |
|
|
$networkreg{$networkuuid2}->{'domains'} = ($domains?"$domains, ":"") . $uuid;
|
| 2562 |
04c16f26
|
hq
|
|
| 2563 |
|
|
$networkreg{$networkuuid2}->{'domainnames'} =~ s/($name)(,?)( ?)//;
|
| 2564 |
95b003ff
|
Origo
|
my $domainnames = $networkreg{$networkuuid2}->{'domainnames'};
|
| 2565 |
|
|
$networkreg{$networkuuid2}->{'domainnames'} = ($domainnames?"$domainnames, ":"") . $name;
|
| 2566 |
|
|
} else {
|
| 2567 |
|
|
$networkreg{$networkuuid2}->{'domains'} = $uuid;
|
| 2568 |
|
|
$networkreg{$networkuuid2}->{'domainnames'} = $name;
|
| 2569 |
|
|
}
|
| 2570 |
|
|
}
|
| 2571 |
|
|
|
| 2572 |
|
|
if ($networkuuid3 && $networkuuid3 ne '--') {
|
| 2573 |
|
|
if ($networkreg{$networkuuid3}->{'type'} eq 'gateway') {
|
| 2574 |
|
|
my $domains = $networkreg{$networkuuid3}->{'domains'};
|
| 2575 |
|
|
$networkreg{$networkuuid3}->{'domains'} = ($domains?"$domains, ":"") . $uuid;
|
| 2576 |
|
|
my $domainnames = $networkreg{$networkuuid3}->{'domainnames'};
|
| 2577 |
|
|
$networkreg{$networkuuid3}->{'domainnames'} = ($domainnames?"$domainnames, ":"") . $name;
|
| 2578 |
|
|
} else {
|
| 2579 |
|
|
$networkreg{$networkuuid3}->{'domains'} = $uuid;
|
| 2580 |
|
|
$networkreg{$networkuuid3}->{'domainnames'} = $name;
|
| 2581 |
|
|
}
|
| 2582 |
|
|
}
|
| 2583 |
|
|
my %jitem = %{$register{$uuid}};
|
| 2584 |
|
|
$json_text = to_json(\%jitem, {pretty=>1});
|
| 2585 |
|
|
$json_text =~ s/null/"--"/g;
|
| 2586 |
|
|
$uiuuid = $uuid;
|
| 2587 |
|
|
$uiname = $name;
|
| 2588 |
|
|
|
| 2589 |
|
|
tied(%register)->commit;
|
| 2590 |
|
|
tied(%networkreg)->commit;
|
| 2591 |
a2e0bc7e
|
hq
|
tied(%imagereg)->commit;
|
| 2592 |
95b003ff
|
Origo
|
|
| 2593 |
|
|
} else {
|
| 2594 |
48fcda6b
|
Origo
|
$postmsg .= "ERROR This image ($image) cannot be used ($imgdup) " if ($imgdup);
|
| 2595 |
|
|
$postmsg .= "ERROR This network ($networkname1) cannot be used ($netdup)" if ($netdup);
|
| 2596 |
95b003ff
|
Origo
|
}
|
| 2597 |
|
|
|
| 2598 |
|
|
my $domuser = $obj->{'user'};
|
| 2599 |
|
|
# We were asked to move server to another account
|
| 2600 |
|
|
if ($domuser && $domuser ne '--' && $domuser ne $user) {
|
| 2601 |
|
|
unless ( tie(%userreg,'Tie::DBI', Hash::Merge::merge({table=>'users', key=>'username', CLOBBER=>0}, $Stabile::dbopts)) ) {throw Error::Simple("Stroke=Error User register could not be accessed")};
|
| 2602 |
|
|
if ($status eq 'shutoff' || $status eq 'inactive') {
|
| 2603 |
|
|
unless ( tie(%userreg,'Tie::DBI', Hash::Merge::merge({table=>'users', key=>'username', CLOBBER=>1}, $Stabile::dbopts)) ) {$posterror = "Unable to access user register"; return 0;};
|
| 2604 |
|
|
my @accounts = split(/,\s*/, $userreg{$tktuser}->{'accounts'});
|
| 2605 |
|
|
my @accountsprivs = split(/,\s*/, $userreg{$tktuser}->{'accountsprivileges'});
|
| 2606 |
|
|
%ahash = ($tktuser, $userreg{$tktuser}->{'privileges'}); # Include tktuser in accounts hash
|
| 2607 |
|
|
for my $i (0 .. scalar @accounts)
|
| 2608 |
|
|
{
|
| 2609 |
|
|
next unless $accounts[$i];
|
| 2610 |
|
|
$ahash{$accounts[$i]} = $accountsprivs[$i] || 'r';
|
| 2611 |
|
|
}
|
| 2612 |
|
|
untie %userreg;
|
| 2613 |
|
|
|
| 2614 |
|
|
if (!$isreadonly && $ahash{$domuser} && !($ahash{$domuser} =~ /r/)) { # Check if user is allow to access account
|
| 2615 |
|
|
my $imgdone;
|
| 2616 |
|
|
my $netdone;
|
| 2617 |
|
|
# First move main image
|
| 2618 |
|
|
$Stabile::Images::user = $user;
|
| 2619 |
|
|
require "$Stabile::basedir/cgi/images.cgi";
|
| 2620 |
|
|
$Stabile::Images::console = 1;
|
| 2621 |
|
|
$main::updateUI->({tab=>"servers", user=>$user, message=>"Moving image $imagename to account: $domuser"});
|
| 2622 |
|
|
my $nimage = Stabile::Images::Move($image, $domuser);
|
| 2623 |
48fcda6b
|
Origo
|
chomp $nimage;
|
| 2624 |
95b003ff
|
Origo
|
if ($nimage) {
|
| 2625 |
|
|
$main::syslogit->($user, "info", "Moving $nimage to account: $domuser");
|
| 2626 |
|
|
$register{$uuid}->{'image'} = $nimage;
|
| 2627 |
|
|
$imgdone = 1;
|
| 2628 |
|
|
} else {
|
| 2629 |
|
|
$main::syslogit->($user, "info", "Unable to move image $imagename to account: $domuser");
|
| 2630 |
|
|
}
|
| 2631 |
|
|
# Move other attached images
|
| 2632 |
|
|
my @images = ($image2, $image3, $image4);
|
| 2633 |
|
|
my @imagenames = ($image2name, $image3name, $image4name);
|
| 2634 |
|
|
my @imagekeys = ('image2', 'image3', 'image4');
|
| 2635 |
|
|
for (my $i=0; $i<3; $i++) {
|
| 2636 |
|
|
my $img = $images[$i];
|
| 2637 |
|
|
my $imgname = $imagenames[$i];
|
| 2638 |
|
|
my $imgkey = $imagekeys[$i];
|
| 2639 |
|
|
if ($img && $img ne '--') {
|
| 2640 |
|
|
$main::updateUI->({tab=>"servers", user=>$user, message=>"Moving $imgkey $imgname to account: $domuser"});
|
| 2641 |
|
|
$nimage = Stabile::Images::Move($img, $domuser);
|
| 2642 |
48fcda6b
|
Origo
|
chomp $nimage;
|
| 2643 |
95b003ff
|
Origo
|
if ($nimage) {
|
| 2644 |
|
|
$main::syslogit->($user, "info", "Moving $nimage to account: $domuser");
|
| 2645 |
|
|
$register{$uuid}->{$imgkey} = $nimage;
|
| 2646 |
|
|
} else {
|
| 2647 |
|
|
$main::syslogit->($user, "info", "Unable to move $imagekeys[$i] $img to account: $domuser");
|
| 2648 |
|
|
}
|
| 2649 |
|
|
}
|
| 2650 |
|
|
}
|
| 2651 |
6fdc8676
|
hq
|
# Then move network(s)
|
| 2652 |
95b003ff
|
Origo
|
if ($imgdone) {
|
| 2653 |
|
|
$Stabile::Networks::user = $user;
|
| 2654 |
|
|
require "$Stabile::basedir/cgi/networks.cgi";
|
| 2655 |
|
|
$Stabile::Networks::console = 1;
|
| 2656 |
|
|
my @networks = ($networkuuid1, $networkuuid2, $networkuuid3);
|
| 2657 |
|
|
my @netkeys = ('networkuuid1', 'networkuuid2', 'networkuuid3');
|
| 2658 |
|
|
my @netnamekeys = ('networkname1', 'networkname2', 'networkname3');
|
| 2659 |
|
|
for (my $i=0; $i<scalar @networks; $i++) {
|
| 2660 |
|
|
my $net = $networks[$i];
|
| 2661 |
|
|
my $netkey = $netkeys[$i];
|
| 2662 |
|
|
my $netnamekey = $netnamekeys[$i];
|
| 2663 |
48fcda6b
|
Origo
|
my $regnet = $networkreg{$net};
|
| 2664 |
|
|
my $oldid = $regnet->{'id'};
|
| 2665 |
95b003ff
|
Origo
|
next if ($net eq '' || $net eq '--');
|
| 2666 |
48fcda6b
|
Origo
|
if ($regnet->{'type'} eq 'gateway') {
|
| 2667 |
95b003ff
|
Origo
|
if ($oldid > 1) { # Private gateway
|
| 2668 |
|
|
foreach my $networkvalref (values %networkreg) { # use gateway with same id if it exists
|
| 2669 |
|
|
if ($networkvalref->{'user'} eq $domuser
|
| 2670 |
|
|
&& $networkvalref->{'type'} eq 'gateway'
|
| 2671 |
|
|
&& $networkvalref->{'id'} == $oldid) {
|
| 2672 |
|
|
# We found an existing gateway with same id - use it
|
| 2673 |
|
|
$register{$uuid}->{$netkey} = $networkvalref->{'uuid'};
|
| 2674 |
|
|
$register{$uuid}->{$netnamekey} = $networkvalref->{'name'};
|
| 2675 |
|
|
$netdone = 1;
|
| 2676 |
|
|
$main::updateUI->({tab=>"networks", user=>$user, message=>"Using network $networkvalref->{'name'} from account: $domuser"});
|
| 2677 |
|
|
last;
|
| 2678 |
|
|
}
|
| 2679 |
|
|
}
|
| 2680 |
|
|
if (!($netdone)) {
|
| 2681 |
|
|
# Make a new gateway
|
| 2682 |
|
|
my $ug = new Data::UUID;
|
| 2683 |
|
|
my $newuuid = $ug->create_str();
|
| 2684 |
48fcda6b
|
Origo
|
Stabile::Networks::save($oldid, $newuuid, $regnet->{'name'}, 'new', 'gateway', '', '', $regnet->{'ports'}, 0, $domuser);
|
| 2685 |
95b003ff
|
Origo
|
$register{$uuid}->{$netkey} = $newuuid;
|
| 2686 |
48fcda6b
|
Origo
|
$register{$uuid}->{$netnamekey} = $regnet->{'name'};
|
| 2687 |
95b003ff
|
Origo
|
$netdone = 1;
|
| 2688 |
48fcda6b
|
Origo
|
$main::updateUI->({tab=>"networks", user=>$user, message=>"Created gateway $regnet->{'name'} for account: $domuser"});
|
| 2689 |
|
|
$main::syslogit->($user, "info", "Created gateway $regnet->{'name'} for account: $domuser");
|
| 2690 |
95b003ff
|
Origo
|
}
|
| 2691 |
|
|
} elsif ($oldid==0 || $oldid==1) {
|
| 2692 |
|
|
$netdone = 1; # Use common gateway
|
| 2693 |
48fcda6b
|
Origo
|
$main::updateUI->({tab=>"networks", user=>$user, message=>"Reused network $regnet->{'name'} for account: $domuser"});
|
| 2694 |
95b003ff
|
Origo
|
}
|
| 2695 |
|
|
} else {
|
| 2696 |
|
|
my $newid = Stabile::Networks::getNextId('', $domuser);
|
| 2697 |
|
|
$networkreg{$net}->{'id'} = $newid;
|
| 2698 |
|
|
$networkreg{$net}->{'user'} = $domuser;
|
| 2699 |
6fdc8676
|
hq
|
# if ($regnet->{'type'} eq 'internalip' || $regnet->{'type'} eq 'ipmapping') {
|
| 2700 |
95b003ff
|
Origo
|
# Deactivate network and assign new internal ip
|
| 2701 |
48fcda6b
|
Origo
|
Stabile::Networks::Deactivate($regnet->{'uuid'});
|
| 2702 |
95b003ff
|
Origo
|
$networkreg{$net}->{'internalip'} =
|
| 2703 |
48fcda6b
|
Origo
|
Stabile::Networks::getNextInternalIP('',$regnet->{'uuid'}, $newid, $domuser);
|
| 2704 |
6fdc8676
|
hq
|
# }
|
| 2705 |
95b003ff
|
Origo
|
$netdone = 1;
|
| 2706 |
48fcda6b
|
Origo
|
$main::updateUI->({tab=>"networks", user=>$user, message=>"Moved network $regnet->{'name'} to account: $domuser"});
|
| 2707 |
|
|
$main::syslogit->($user, "info", "Moved network $regnet->{'name'} to account: $domuser");
|
| 2708 |
95b003ff
|
Origo
|
}
|
| 2709 |
|
|
}
|
| 2710 |
|
|
if ($netdone) {
|
| 2711 |
|
|
# Finally move the server
|
| 2712 |
|
|
$register{$uuid}->{'user'} = $domuser;
|
| 2713 |
48fcda6b
|
Origo
|
$postmsg .= "OK Moved server $name to account: $domuser";
|
| 2714 |
95b003ff
|
Origo
|
$main::syslogit->($user, "info", "Moved server $name ($uuid) to account: $domuser");
|
| 2715 |
48fcda6b
|
Origo
|
$main::updateUI->({tab=>"servers", user=>$user, type=>"update"});
|
| 2716 |
95b003ff
|
Origo
|
} else {
|
| 2717 |
48fcda6b
|
Origo
|
$postmsg .= "ERROR Unable to move network to account: $domuser";
|
| 2718 |
95b003ff
|
Origo
|
$main::updateUI->({tab=>"image", user=>$user, message=>"Unable to move network to account: $domuser"});
|
| 2719 |
|
|
}
|
| 2720 |
|
|
} else {
|
| 2721 |
|
|
$main::updateUI->({tab=>"image", user=>$user, message=>"Could not move image to account: $domuser"});
|
| 2722 |
|
|
}
|
| 2723 |
|
|
} else {
|
| 2724 |
48fcda6b
|
Origo
|
$postmsg .= "ERROR No access to move server";
|
| 2725 |
95b003ff
|
Origo
|
}
|
| 2726 |
|
|
} else {
|
| 2727 |
48fcda6b
|
Origo
|
$postmsg .= "Error Unable to move $status server";
|
| 2728 |
95b003ff
|
Origo
|
$main::updateUI->({tab=>"servers", user=>$user, message=>"Please shut down before moving server"});
|
| 2729 |
|
|
}
|
| 2730 |
|
|
untie %userreg;
|
| 2731 |
|
|
}
|
| 2732 |
|
|
|
| 2733 |
|
|
if ($console) {
|
| 2734 |
|
|
$postreply = $postmsg;
|
| 2735 |
|
|
} else {
|
| 2736 |
|
|
$postreply = $json_text || $postmsg;
|
| 2737 |
|
|
}
|
| 2738 |
|
|
return $postreply;
|
| 2739 |
|
|
untie %imagereg;
|
| 2740 |
|
|
}
|
| 2741 |
|
|
|
| 2742 |
|
|
|
| 2743 |
|
|
sub Shutdown {
|
| 2744 |
|
|
my ($uuid, $action, $obj) = @_;
|
| 2745 |
|
|
if ($help) {
|
| 2746 |
|
|
return <<END
|
| 2747 |
|
|
GET:uuid:
|
| 2748 |
|
|
Marks a server for shutdown, i.e. send and ACPI shutdown event to the server. If OS supports ACPI, it begins a shutdown.
|
| 2749 |
|
|
END
|
| 2750 |
|
|
}
|
| 2751 |
|
|
$uistatus = "shuttingdown";
|
| 2752 |
|
|
my $dbstatus = $obj->{status};
|
| 2753 |
|
|
my $mac = $obj->{mac};
|
| 2754 |
|
|
my $macname = $obj->{macname};
|
| 2755 |
|
|
my $name = $obj->{name};
|
| 2756 |
|
|
if ($dbstatus eq 'running') {
|
| 2757 |
|
|
my $tasks;
|
| 2758 |
|
|
$tasks = $nodereg{$mac}->{'tasks'} if ($nodereg{$mac});
|
| 2759 |
|
|
$nodereg{$mac}->{'tasks'} = $tasks . "SHUTDOWN $uuid $user\n";
|
| 2760 |
|
|
tied(%nodereg)->commit;
|
| 2761 |
|
|
$register{$uuid}->{'status'} = $uistatus;
|
| 2762 |
|
|
$register{$uuid}->{'statustime'} = $current_time;
|
| 2763 |
|
|
$uiuuid = $uuid;
|
| 2764 |
|
|
$main::syslogit->($user, "info", "Marked $name ($uuid) for $uistatus by $macname ($mac)");
|
| 2765 |
|
|
$postreply .= "Status=$uistatus OK $uistatus $name\n";
|
| 2766 |
|
|
} else {
|
| 2767 |
|
|
$main::syslogit->($user, "info", "Problem $uistatus a $dbstatus domain: $uuid");
|
| 2768 |
|
|
$postreply .= "Status=ERROR problem $uistatus $name...\n";
|
| 2769 |
|
|
}
|
| 2770 |
|
|
return $postreply;
|
| 2771 |
|
|
}
|
| 2772 |
|
|
|
| 2773 |
|
|
sub Suspend {
|
| 2774 |
|
|
my ($uuid, $action, $obj) = @_;
|
| 2775 |
|
|
if ($help) {
|
| 2776 |
|
|
return <<END
|
| 2777 |
|
|
GET:uuid:
|
| 2778 |
|
|
Marks a server for suspend, i.e. pauses the server. Server must be running
|
| 2779 |
|
|
END
|
| 2780 |
|
|
}
|
| 2781 |
|
|
$uistatus = "suspending";
|
| 2782 |
|
|
my $dbstatus = $obj->{status};
|
| 2783 |
|
|
my $mac = $obj->{mac};
|
| 2784 |
|
|
my $macname = $obj->{macname};
|
| 2785 |
|
|
my $name = $obj->{name};
|
| 2786 |
a2e0bc7e
|
hq
|
my $areply = '';
|
| 2787 |
95b003ff
|
Origo
|
if ($dbstatus eq 'running') {
|
| 2788 |
|
|
my $tasks = $nodereg{$mac}->{'tasks'};
|
| 2789 |
|
|
$nodereg{$mac}->{'tasks'} = $tasks . "SUSPEND $uuid $user\n";
|
| 2790 |
|
|
tied(%nodereg)->commit;
|
| 2791 |
|
|
$register{$uuid}->{'status'} = $uistatus;
|
| 2792 |
|
|
$register{$uuid}->{'statustime'} = $current_time;
|
| 2793 |
|
|
$uiuuid = $uuid;
|
| 2794 |
|
|
$main::syslogit->($user, "info", "Marked $name ($uuid) for $uistatus by $macname ($mac)");
|
| 2795 |
a2e0bc7e
|
hq
|
$areply .= "Status=$uistatus OK $uistatus $name.\n";
|
| 2796 |
95b003ff
|
Origo
|
} else {
|
| 2797 |
|
|
$main::syslogit->($user, "info", "Problem $uistatus a $dbstatus domain: $uuid");
|
| 2798 |
a2e0bc7e
|
hq
|
$areply .= "Status=ERROR problem $uistatus $name.\n";
|
| 2799 |
95b003ff
|
Origo
|
}
|
| 2800 |
a2e0bc7e
|
hq
|
return $areply;
|
| 2801 |
95b003ff
|
Origo
|
}
|
| 2802 |
|
|
|
| 2803 |
|
|
sub Resume {
|
| 2804 |
|
|
my ($uuid, $action, $obj) = @_;
|
| 2805 |
|
|
if ($help) {
|
| 2806 |
|
|
return <<END
|
| 2807 |
|
|
GET:uuid:
|
| 2808 |
|
|
Marks a server for resume running. Server must be paused.
|
| 2809 |
|
|
END
|
| 2810 |
|
|
}
|
| 2811 |
|
|
my $dbstatus = $obj->{status};
|
| 2812 |
|
|
my $mac = $obj->{mac};
|
| 2813 |
|
|
my $macname = $obj->{macname};
|
| 2814 |
|
|
my $name = $obj->{name};
|
| 2815 |
|
|
my $image = $obj->{image};
|
| 2816 |
|
|
my $image2 = $obj->{image2};
|
| 2817 |
|
|
my $image3 = $obj->{image3};
|
| 2818 |
|
|
my $image4 = $obj->{image4};
|
| 2819 |
|
|
unless ( tie(%imagereg,'Tie::DBI', Hash::Merge::merge({table=>'images', key=>'path'}, $Stabile::dbopts)) ) {$posterror = "Unable to access image register"; return;};
|
| 2820 |
|
|
if ($imagereg{$image}->{'status'} ne "paused"
|
| 2821 |
|
|
|| ($image2 && $image2 ne '--' && $imagereg{$image}->{'status'} ne "paused")
|
| 2822 |
|
|
|| ($image3 && $image3 ne '--' && $imagereg{$image3}->{'status'} ne "paused")
|
| 2823 |
|
|
|| ($image4 && $image4 ne '--' && $imagereg{$image4}->{'status'} ne "paused")
|
| 2824 |
|
|
) {
|
| 2825 |
|
|
$postreply .= "Status=ERROR Image $uuid busy ($imagereg{$image}->{'status'}), please wait 30 sec.\n";
|
| 2826 |
|
|
untie %imagereg;
|
| 2827 |
|
|
return $postreply ;
|
| 2828 |
|
|
} else {
|
| 2829 |
|
|
untie %imagereg;
|
| 2830 |
|
|
}
|
| 2831 |
|
|
$uistatus = "resuming";
|
| 2832 |
|
|
if ($dbstatus eq 'paused') {
|
| 2833 |
|
|
my $tasks = $nodereg{$mac}->{'tasks'};
|
| 2834 |
|
|
$nodereg{$mac}->{'tasks'} = $tasks . "RESUME $uuid $user\n";
|
| 2835 |
|
|
tied(%nodereg)->commit;
|
| 2836 |
|
|
$register{$uuid}->{'status'} = $uistatus;
|
| 2837 |
|
|
$register{$uuid}->{'statustime'} = $current_time;
|
| 2838 |
|
|
$uiuuid = $uuid;
|
| 2839 |
|
|
$main::syslogit->($user, "info", "Marked $name ($uuid) for $uistatus by $macname ($mac)");
|
| 2840 |
|
|
$postreply .= "Status=$uistatus OK $uistatus ". $register{$uuid}->{'name'} . "\n";
|
| 2841 |
|
|
} else {
|
| 2842 |
|
|
$main::syslogit->($user, "info", "Problem $uistatus a $dbstatus domain: $uuid");
|
| 2843 |
|
|
$postreply .= "Status=ERROR problem $uistatus ". $register{$uuid}->{'name'} . "\n";
|
| 2844 |
|
|
}
|
| 2845 |
|
|
return $postreply;
|
| 2846 |
|
|
}
|
| 2847 |
|
|
|
| 2848 |
d3805c61
|
hq
|
sub Abort {
|
| 2849 |
|
|
my ($uuid, $action, $obj) = @_;
|
| 2850 |
|
|
if ($help) {
|
| 2851 |
|
|
return <<END
|
| 2852 |
|
|
GET:uuid,mac:
|
| 2853 |
|
|
Aborts an ongoing server move between nodes initiated with move or stormove.
|
| 2854 |
|
|
END
|
| 2855 |
|
|
}
|
| 2856 |
|
|
my $dbstatus = $obj->{status};
|
| 2857 |
|
|
my $dmac = $obj->{mac};
|
| 2858 |
|
|
my $name = $obj->{name};
|
| 2859 |
|
|
if ($isadmin || $register{$uuid}->{user} eq $user) {
|
| 2860 |
|
|
my $tasks = $nodereg{$dmac}->{'tasks'};
|
| 2861 |
|
|
$tasks .= "ABORT $uuid $user\n";
|
| 2862 |
|
|
$nodereg{$dmac}->{'tasks'} = $tasks;
|
| 2863 |
|
|
tied(%nodereg)->commit;
|
| 2864 |
|
|
$postreply = "Status=aborting Aborting move of server $name ($dbstatus) on node $dmac\n";
|
| 2865 |
|
|
} else {
|
| 2866 |
|
|
$postreply = "Status=OK Insufficient privileges\n";
|
| 2867 |
|
|
}
|
| 2868 |
|
|
}
|
| 2869 |
|
|
|
| 2870 |
95b003ff
|
Origo
|
sub Move {
|
| 2871 |
|
|
my ($uuid, $action, $obj) = @_;
|
| 2872 |
|
|
if ($help) {
|
| 2873 |
|
|
return <<END
|
| 2874 |
|
|
GET:uuid,mac:
|
| 2875 |
d3805c61
|
hq
|
Moves a server to a different node (Qemu live migration). Server must be running. When called as stormove, non-shared disks are migrated. This may of course take a lot of time, dependeing on the size of the backing images involved.
|
| 2876 |
95b003ff
|
Origo
|
END
|
| 2877 |
|
|
}
|
| 2878 |
|
|
my $dbstatus = $obj->{status};
|
| 2879 |
|
|
my $dmac = $obj->{mac};
|
| 2880 |
|
|
my $name = $obj->{name};
|
| 2881 |
|
|
my $mem = $obj->{memory};
|
| 2882 |
|
|
my $vcpu = $obj->{vcpu};
|
| 2883 |
|
|
my $image = $obj->{image};
|
| 2884 |
|
|
my $image2 = $obj->{image2};
|
| 2885 |
|
|
my $image3 = $obj->{image3};
|
| 2886 |
|
|
my $image4 = $obj->{image4};
|
| 2887 |
d3805c61
|
hq
|
|
| 2888 |
95b003ff
|
Origo
|
$uistatus = "moving";
|
| 2889 |
|
|
if ($dbstatus eq 'running' && $isadmin) {
|
| 2890 |
|
|
my $hypervisor = getHypervisor($image);
|
| 2891 |
|
|
my $mac = $register{$uuid}->{'mac'};
|
| 2892 |
|
|
$dmac = "" if ($dmac eq "--");
|
| 2893 |
|
|
$mac = "" if ($mac eq "--");
|
| 2894 |
|
|
|
| 2895 |
d3805c61
|
hq
|
if (( $image =~ /\/mnt\/stabile\/node\//
|
| 2896 |
95b003ff
|
Origo
|
|| $image2 =~ /\/mnt\/stabile\/node\//
|
| 2897 |
|
|
|| $image3 =~ /\/mnt\/stabile\/node\//
|
| 2898 |
d3805c61
|
hq
|
|| $image4 =~ /\/mnt\/stabile\/node\// ) && $action ne 'stormove'
|
| 2899 |
95b003ff
|
Origo
|
) {
|
| 2900 |
d3805c61
|
hq
|
$postreply = qq|{"error": 1, "message": "Servers with local storage must be moved with stormove"}|;
|
| 2901 |
|
|
$main::updateUI->({tab=>"servers", user=>$user, message=>"Servers with local storage must be moved with stormove"});
|
| 2902 |
95b003ff
|
Origo
|
} else {
|
| 2903 |
|
|
my ($targetmac, $targetname, $targetip, $port) =
|
| 2904 |
d3805c61
|
hq
|
locateTargetNode($uuid, $dmac, $mem, $vcpu, $image, $image2, $image3, $image4, $hypervisor, $mac, 1);
|
| 2905 |
95b003ff
|
Origo
|
if ($targetmac) {
|
| 2906 |
|
|
my $tasks = $nodereg{$targetmac}->{'tasks'};
|
| 2907 |
d3805c61
|
hq
|
if ($action eq 'stormove') {
|
| 2908 |
|
|
$tasks = $tasks . "RECEIVESTOR $uuid $user\n";
|
| 2909 |
|
|
} else {
|
| 2910 |
|
|
$tasks = $tasks . "RECEIVE $uuid $user\n";
|
| 2911 |
|
|
}
|
| 2912 |
95b003ff
|
Origo
|
# Also update allowed port forwards
|
| 2913 |
|
|
$nodereg{$targetmac}->{'tasks'} = $tasks . "PERMITOPEN $user\n";
|
| 2914 |
|
|
$register{$uuid}->{'status'} = "moving";
|
| 2915 |
|
|
$register{$uuid}->{'statustime'} = $current_time;
|
| 2916 |
|
|
$uiuuid = $uuid;
|
| 2917 |
|
|
$uidisplayip = $targetip;
|
| 2918 |
|
|
$uidisplayport = $port;
|
| 2919 |
|
|
$main::syslogit->($user, "info", "Marked $name ($uuid) for $uistatus to $targetname ($targetmac)");
|
| 2920 |
|
|
$postreply .= "Status=OK $uistatus ". $register{$uuid}->{'name'} . "\n";
|
| 2921 |
|
|
|
| 2922 |
d3805c61
|
hq
|
# Precreate images on destination node
|
| 2923 |
|
|
if ($action eq 'stormove') {
|
| 2924 |
|
|
my $preimages = '';
|
| 2925 |
|
|
$Stabile::Images::user = $user;
|
| 2926 |
|
|
require "$Stabile::basedir/cgi/images.cgi";
|
| 2927 |
|
|
$Stabile::Images::console = 1;
|
| 2928 |
|
|
if ($targetip eq '10.0.0.1') { # Moving from node
|
| 2929 |
|
|
if ($image =~ /\/mnt\/stabile\/node\//) { # Only move to shared storage if not already on shared storage
|
| 2930 |
|
|
my $res = Stabile::Images::Move($image, $user, '0', '', 0, 1);
|
| 2931 |
|
|
$preimages .= " $register{$uuid}->{imagename}";
|
| 2932 |
|
|
}
|
| 2933 |
|
|
if ($image2 =~ /\/mnt\/stabile\/node\//) { # Only move to shared storage if not already on shared storage
|
| 2934 |
|
|
my $res = Stabile::Images::Move($image2, $user, '0', '', 0, 1);
|
| 2935 |
|
|
$preimages .= " $register{$uuid}->{image2name}";
|
| 2936 |
|
|
}
|
| 2937 |
|
|
if ($image3 =~ /\/mnt\/stabile\/node\//) { # Only move to shared storage if not already on shared storage
|
| 2938 |
|
|
my $res = Stabile::Images::Move($image3, $user, '0', '', 0, 1);
|
| 2939 |
|
|
$preimages .= " $register{$uuid}->{image3name}";
|
| 2940 |
|
|
}
|
| 2941 |
|
|
if ($image4 =~ /\/mnt\/stabile\/node\//) { # Only move to shared storage if not already on shared storage
|
| 2942 |
|
|
my $res = Stabile::Images::Move($image4, $user, '0', '', 0, 1);
|
| 2943 |
|
|
$preimages .= " $register{$uuid}->{image4name}";
|
| 2944 |
|
|
}
|
| 2945 |
|
|
} else { # Moving to node or between nodes - always move primary image, also if on shared storage
|
| 2946 |
|
|
my $res = Stabile::Images::Move($image, $user, '-1', $targetmac, 0, 1);
|
| 2947 |
|
|
$preimages .= " $register{$uuid}->{imagename}";
|
| 2948 |
|
|
if ($image2 && $image2 ne '--') {
|
| 2949 |
|
|
# We don't migrate data disks away from shared storage
|
| 2950 |
|
|
unless ($image2 =~ /\/stabile-images\/images\/.*-data\..*\.qcow2/) {
|
| 2951 |
|
|
my $res = Stabile::Images::Move($image2, $user, '-1', $targetmac, 0, 1);
|
| 2952 |
|
|
$preimages .= " $register{$uuid}->{image2name}";
|
| 2953 |
|
|
}
|
| 2954 |
|
|
}
|
| 2955 |
|
|
if ($image3 && $image3 ne '--') {
|
| 2956 |
|
|
unless ($image3 =~ /\/stabile-images\/images\/.*-data\..*\.qcow2/) {
|
| 2957 |
|
|
my $res = Stabile::Images::Move($image3, $user, '-1', $targetmac, 0, 1);
|
| 2958 |
|
|
$preimages .= " $register{$uuid}->{image3name}";
|
| 2959 |
|
|
}
|
| 2960 |
|
|
}
|
| 2961 |
|
|
if ($image4 && $image4 ne '--') {
|
| 2962 |
|
|
unless ($image4 =~ /\/stabile-images\/images\/.*-data\..*\.qcow2/) {
|
| 2963 |
|
|
my $res = Stabile::Images::Move($image4, $user, '-1', $targetmac, 0, 1);
|
| 2964 |
|
|
$preimages .= " $register{$uuid}->{image4name}";
|
| 2965 |
|
|
}
|
| 2966 |
|
|
}
|
| 2967 |
|
|
}
|
| 2968 |
|
|
if ($preimages) {
|
| 2969 |
|
|
$main::syslogit->($user, "info", "Precreating images $preimages on node $targetmac");
|
| 2970 |
|
|
$main::updateUI->({tab=>"servers", user=>$user, message=>"Precreating images $preimages on node $targetmac"});
|
| 2971 |
|
|
}
|
| 2972 |
|
|
}
|
| 2973 |
95b003ff
|
Origo
|
if ($params{'PUTDATA'}) {
|
| 2974 |
|
|
my %jitem = %{$register{$uuid}};
|
| 2975 |
|
|
my $json_text = to_json(\%jitem);
|
| 2976 |
|
|
$json_text =~ s/null/"--"/g;
|
| 2977 |
|
|
$postreply = $json_text;
|
| 2978 |
|
|
}
|
| 2979 |
d3805c61
|
hq
|
# $main::updateUI->({tab=>"servers", user=>$user, status=>'moving', uuid=>$uuid, type=>'update', message=>"Moving $register{$uuid}->{name} to $targetmac"});
|
| 2980 |
95b003ff
|
Origo
|
} else {
|
| 2981 |
|
|
$main::syslogit->($user, "info", "Could not find $hypervisor target for $uistatus $uuid ($image)");
|
| 2982 |
d3805c61
|
hq
|
$main::updateUI->({tab=>"servers", user=>$user, message=>"Could not find target for $uistatus $register{$uuid}->{'name'}"});
|
| 2983 |
95b003ff
|
Origo
|
$postreply = qq|{"error": 1, "message": "Could not find target for $uistatus $register{$uuid}->{'name'}"}|;
|
| 2984 |
|
|
}
|
| 2985 |
|
|
}
|
| 2986 |
|
|
} else {
|
| 2987 |
|
|
$main::syslogit->($user, "info", "Problem moving a $dbstatus domain: $uuid");
|
| 2988 |
d3805c61
|
hq
|
my $serv = $register{$uuid};
|
| 2989 |
|
|
$postreply .= qq|{"error": 1, "message": "ERROR problem moving $serv->{'name'} ($dbstatus)"}|;
|
| 2990 |
95b003ff
|
Origo
|
}
|
| 2991 |
|
|
return $postreply;
|
| 2992 |
|
|
}
|
| 2993 |
|
|
|
| 2994 |
c899e439
|
Origo
|
sub Changepassword {
|
| 2995 |
|
|
my ($uuid, $action, $obj) = @_;
|
| 2996 |
|
|
if ($help) {
|
| 2997 |
|
|
return <<END
|
| 2998 |
|
|
POST:uuid,username,password:
|
| 2999 |
|
|
Attempts to set password for [username] to [password] using guestfish. If no username is specified, user 'stabile' is assumed.
|
| 3000 |
|
|
END
|
| 3001 |
|
|
}
|
| 3002 |
|
|
my $img = $register{$uuid}->{'image'};
|
| 3003 |
|
|
my $username = $obj->{'username'} || 'stabile';
|
| 3004 |
|
|
my $password = $obj->{'password'};
|
| 3005 |
|
|
return "Status=Error Please supply a password\n" unless ($password);
|
| 3006 |
|
|
return "Status=Error Please shut down the server before changing password\n" unless ($register{$uuid} && $register{$uuid}->{'status'} eq 'shutoff');
|
| 3007 |
|
|
return "Status=Error Not allowed\n" unless ($isadmin || $register{$uuid}->{'user'} eq $user);
|
| 3008 |
|
|
|
| 3009 |
|
|
unless (tie(%imagereg,'Tie::DBI', Hash::Merge::merge({table=>'images', key=>'path'}, $Stabile::dbopts)) ) {$res .= qq|{"status": "Error": "message": "Unable to access images register"}|; return $res;};
|
| 3010 |
|
|
my $cmd = qq/guestfish --rw -a $img -i command "bash -c 'echo $username:$password | chpasswd'" 2>\&1/;
|
| 3011 |
|
|
if ($imagereg{$img} && $imagereg{$img}->{'mac'}) {
|
| 3012 |
|
|
my $mac = $imagereg{$img}->{'mac'};
|
| 3013 |
|
|
my $macip = $nodereg{$mac}->{'ip'};
|
| 3014 |
|
|
$cmd = "$sshcmd $macip $cmd";
|
| 3015 |
|
|
}
|
| 3016 |
|
|
my $res = `$cmd`;
|
| 3017 |
|
|
$res = $1 if ($res =~ /guestfish: (.*)/);
|
| 3018 |
|
|
chomp $res;
|
| 3019 |
|
|
return "Status=OK Ran chpasswd for user $username in server $register{$uuid}->{'name'}: $res\n";
|
| 3020 |
|
|
}
|
| 3021 |
|
|
|
| 3022 |
|
|
sub Sshaccess {
|
| 3023 |
|
|
my ($uuid, $action, $obj) = @_;
|
| 3024 |
|
|
if ($help) {
|
| 3025 |
|
|
return <<END
|
| 3026 |
|
|
POST:uuid,address:
|
| 3027 |
|
|
Attempts to change the ip addresses you can access the server over SSH (port 22) from, by adding [address] to /etc/hosts.allow.
|
| 3028 |
|
|
[address] should either be an IP address or a range in CIDR notation. Please note that no validation of [address] is performed.
|
| 3029 |
|
|
END
|
| 3030 |
|
|
}
|
| 3031 |
|
|
my $img = $register{$uuid}->{'image'};
|
| 3032 |
|
|
my $address = $obj->{'address'};
|
| 3033 |
|
|
return "Status=Error Please supply an aaddress\n" unless ($address);
|
| 3034 |
|
|
return "Status=Error Please shut down the server before changing SSH access\n" unless ($register{$uuid} && $register{$uuid}->{'status'} eq 'shutoff');
|
| 3035 |
|
|
return "Status=Error Not allowed\n" unless ($isadmin || $register{$uuid}->{'user'} eq $user);
|
| 3036 |
|
|
|
| 3037 |
|
|
unless (tie(%imagereg,'Tie::DBI', Hash::Merge::merge({table=>'images', key=>'path'}, $Stabile::dbopts)) ) {$res .= qq|{"status": "Error": "message": "Unable to access images register"}|; return $res;};
|
| 3038 |
|
|
|
| 3039 |
|
|
my $isshcmd = '';
|
| 3040 |
|
|
my $cmd = qq[guestfish --rw -a $img -i command "sed -i -re 's|(sshd: .*)#stabile|\\1 $address #stabile|' /etc/hosts.allow"];
|
| 3041 |
|
|
# my $cmd = qq[guestfish --rw -a $img -i command "bash -c 'echo sshd: $address >> /etc/hosts.allow'"];
|
| 3042 |
|
|
if ($imagereg{$img} && $imagereg{$img}->{'mac'}) {
|
| 3043 |
|
|
my $mac = $imagereg{$img}->{'mac'};
|
| 3044 |
|
|
my $macip = $nodereg{$mac}->{'ip'};
|
| 3045 |
|
|
$isshcmd = "$sshcmd $macip ";
|
| 3046 |
|
|
}
|
| 3047 |
|
|
my $res = `$isshcmd$cmd`;
|
| 3048 |
|
|
chomp $res;
|
| 3049 |
|
|
#$cmd = qq[guestfish --rw -a $img -i command "bash -c 'cat /etc/hosts.allow'"];
|
| 3050 |
|
|
#$res .= `$isshcmd$cmd`;
|
| 3051 |
|
|
#chomp $res;
|
| 3052 |
|
|
return "Status=OK Tried to add sshd: $address to /etc/hosts.allow in server $register{$uuid}->{'name'}\n";
|
| 3053 |
|
|
}
|
| 3054 |
|
|
|
| 3055 |
95b003ff
|
Origo
|
sub Mountcd {
|
| 3056 |
|
|
my ($uuid, $action, $obj) = @_;
|
| 3057 |
|
|
if ($help) {
|
| 3058 |
|
|
return <<END
|
| 3059 |
|
|
GET:uuid,cdrom:
|
| 3060 |
|
|
Mounts a cdrom on a server. Server must be running. Mounting the special cdrom named '--' unomunts any currently mounted cdrom.
|
| 3061 |
|
|
END
|
| 3062 |
|
|
}
|
| 3063 |
|
|
my $dbstatus = $obj->{status};
|
| 3064 |
|
|
my $mac = $obj->{mac};
|
| 3065 |
|
|
my $cdrom = $obj->{cdrom};
|
| 3066 |
|
|
unless ($cdrom && $dbstatus eq 'running') {
|
| 3067 |
|
|
$main::updateUI->({tab=>"servers", user=>$user, uuid=>$uuid, type=>'update', message=>"Unable to mount cdrom"});
|
| 3068 |
|
|
$postreply = qq|{"Error": 1, "message": "Problem mounting cdrom on $obj->{name}"}|;
|
| 3069 |
|
|
return;
|
| 3070 |
|
|
}
|
| 3071 |
|
|
my $tasks = $nodereg{$mac}->{'tasks'};
|
| 3072 |
|
|
# $user is in the middle here, because $cdrom may contain spaces...
|
| 3073 |
|
|
$nodereg{$mac}->{'tasks'} = $tasks . "MOUNT $uuid $user \"$cdrom\"\n";
|
| 3074 |
|
|
tied(%nodereg)->commit;
|
| 3075 |
|
|
if ($cdrom eq "--") {
|
| 3076 |
|
|
$postreply = qq|{"OK": 1, "message": "OK unmounting cdrom from $obj->{name}"}|;
|
| 3077 |
|
|
} else {
|
| 3078 |
|
|
$postreply = qq|{"OK": 1, "message": "OK mounting cdrom $cdrom on $obj->{name}"}|;
|
| 3079 |
|
|
}
|
| 3080 |
|
|
$register{$uuid}->{'cdrom'} = $cdrom unless ($cdrom eq 'virtio');
|
| 3081 |
|
|
return $postreply;
|
| 3082 |
|
|
} |