diff --git a/xCAT-server/lib/xcat/plugins/kvm.pm b/xCAT-server/lib/xcat/plugins/kvm.pm
index ed0e63d2e..009593b08 100755
--- a/xCAT-server/lib/xcat/plugins/kvm.pm
+++ b/xCAT-server/lib/xcat/plugins/kvm.pm
@@ -1,9 +1,10 @@
#!/usr/bin/env perl
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
package xCAT_plugin::kvm;
+
BEGIN
{
- $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat';
+ $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat';
}
use lib "$::XCATROOT/lib/perl";
use xCAT::GlobalDef;
@@ -13,6 +14,7 @@ use xCAT_monitoring::monitorctrl;
use xCAT::Table;
use xCAT::Usage;
use XML::LibXML; #now that we are in the business of modifying xml data, need something capable of preserving more of the XML structure
+
#TODO: convert all uses of XML::Simple to LibXML? Using both seems wasteful in a way..
use XML::Simple qw(XMLout);
use Thread qw(yield);
@@ -24,10 +26,11 @@ use IO::Select;
use xCAT::TableUtils;
use xCAT::ServiceNodeUtils;
use strict;
+
#use warnings;
-my $use_xhrm=0; #xCAT Hypervisor Resource Manager, to satisfy networking and storage prerequisites, default to not using it for the moment
-my $imgfmt='raw'; #use raw format by default
-my $clonemethod='qemu-img'; #use qemu-img command
+my $use_xhrm = 0; #xCAT Hypervisor Resource Manager, to satisfy networking and storage prerequisites, default to not using it for the moment
+my $imgfmt = 'raw'; #use raw format by default
+my $clonemethod = 'qemu-img'; #use qemu-img command
my %vm_comm_pids;
my %offlinehyps;
my %hypstats;
@@ -35,13 +38,15 @@ my %offlinevms;
my $parser;
my @destblacklist;
my $updatetable; #when a function is performing per-node operations, it can queue up a table update by populating parts of this hash
-my $confdata; #a reference to serve as a common pointer betweer VMCommon functions and this plugin
+my $confdata; #a reference to serve as a common pointer betweer VMCommon functions and this plugin
require Sys::Virt;
+
if (Sys::Virt->VERSION =~ /^0\.[10]\./) {
- die;
+ die;
}
use XML::Simple;
-$XML::Simple::PREFERRED_PARSER='XML::Parser';
+$XML::Simple::PREFERRED_PARSER = 'XML::Parser';
+
#use Data::Dumper;
use POSIX "WNOHANG";
use Storable qw(freeze thaw store_fd fd_retrieve);
@@ -53,35 +58,37 @@ use Getopt::Long;
use xCAT::SvrUtils;
my %runningstates;
-my $vmmaxp=64;
+my $vmmaxp = 64;
my $mactab;
my %usedmacs;
-my $status_noop="XXXno-opXXX";
+my $status_noop = "XXXno-opXXX";
my $callback;
-my $requester; #used to track the user
+my $requester; #used to track the user
sub handled_commands {
- return {
- rpower => 'nodehm:power,mgt',
- mkvm => 'nodehm:power,mgt',
- clonevm => 'nodehm:power,mgt',
- chvm => 'nodehm:power,mgt',
- rmvm => 'nodehm:power,mgt',
- rinv => 'nodehm:power,mgt',
- rmigrate => 'nodehm:mgt',
- getcons => 'nodehm:mgt',
- #rvitals => 'nodehm:mgt',
- #rinv => 'nodehm:mgt',
- getrvidparms => 'nodehm:mgt',
- lsvm => 'hypervisor:type',
- rbeacon => 'nodehm:mgt',
- revacuate => 'hypervisor:type',
- vmstatenotify => 'hypervisor:type',
- #rspreset => 'nodehm:mgt',
- #rspconfig => 'nodehm:mgt',
- #rbootseq => 'nodehm:mgt',
- #reventlog => 'nodehm:mgt',
- };
+ return {
+ rpower => 'nodehm:power,mgt',
+ mkvm => 'nodehm:power,mgt',
+ clonevm => 'nodehm:power,mgt',
+ chvm => 'nodehm:power,mgt',
+ rmvm => 'nodehm:power,mgt',
+ rinv => 'nodehm:power,mgt',
+ rmigrate => 'nodehm:mgt',
+ getcons => 'nodehm:mgt',
+
+ #rvitals => 'nodehm:mgt',
+ #rinv => 'nodehm:mgt',
+ getrvidparms => 'nodehm:mgt',
+ lsvm => 'hypervisor:type',
+ rbeacon => 'nodehm:mgt',
+ revacuate => 'hypervisor:type',
+ vmstatenotify => 'hypervisor:type',
+
+ #rspreset => 'nodehm:mgt',
+ #rspconfig => 'nodehm:mgt',
+ #rbootseq => 'nodehm:mgt',
+ #reventlog => 'nodehm:mgt',
+ };
}
my $hypconn;
@@ -93,44 +100,45 @@ my $vmtab;
sub get_path_for_pool {
- my $poolobj =shift;
+ my $poolobj = shift;
my $poolxml = $poolobj->get_xml_description();
my $pooldom = $parser->parse_string($poolxml);
- my @paths = $pooldom->findnodes("/pool/target/path/text()");
+ my @paths = $pooldom->findnodes("/pool/target/path/text()");
if (scalar @paths != 1) {
return undef;
}
return $paths[0]->data;
}
+
sub build_pool_xml {
my $url = shift;
my $pooldesc;
- my $name=$url;
- $name=~ s!nfs://!nfs_!;
- $name=~ s!dir://!dir_!;
- $name=~ s!lvm://!lvm_!;
+ my $name = $url;
+ $name =~ s!nfs://!nfs_!;
+ $name =~ s!dir://!dir_!;
+ $name =~ s!lvm://!lvm_!;
$name =~ s/\//_/g; #though libvirt considers / kosher, sometimes it wants to create a local xml file using name for filename...
- if ($url =~ /^dir:/) { #directory style..
- my $path=$url;
- $path =~ s/dir:\/\///g;
- return "$name$path";
- } elsif ($url =~ /^lvm:\/\//) { #lvm specified
- my $path = $url;
- $path =~ s/^lvm:\/\///;
- $path =~ s/:(.*)\z//;
- my $volumes = $1;
- my $mount = "/dev/$path";
- my $xml = ''.$path.''.$mount.'';
- if ($volumes) {
- $xml .= "";
- my @vols = split /,/,$volumes;
- foreach (@vols) {
- $xml .= '';
- }
- $xml .= "";
- }
- $xml .= "";
- return $xml;
+ if ($url =~ /^dir:/) { #directory style..
+ my $path = $url;
+ $path =~ s/dir:\/\///g;
+ return "$name$path";
+ } elsif ($url =~ /^lvm:\/\//) { #lvm specified
+ my $path = $url;
+ $path =~ s/^lvm:\/\///;
+ $path =~ s/:(.*)\z//;
+ my $volumes = $1;
+ my $mount = "/dev/$path";
+ my $xml = '' . $path . '' . $mount . '';
+ if ($volumes) {
+ $xml .= "";
+ my @vols = split /,/, $volumes;
+ foreach (@vols) {
+ $xml .= '';
+ }
+ $xml .= "";
+ }
+ $xml .= "";
+ return $xml;
}
my $mounthost = shift;
unless ($mounthost) { $mounthost = $hyp; }
@@ -139,158 +147,166 @@ sub build_pool_xml {
$host =~ s/.*:\/\///;
$host =~ s/(\/.*)//;
my $srcpath = $1;
- my $uuid = xCAT::Utils::genUUID(url=>$url);
-#first, we make a pool desc that won't have slashes in them
+ my $uuid = xCAT::Utils::genUUID(url => $url);
+
+ #first, we make a pool desc that won't have slashes in them
$pooldesc = '';
- $pooldesc .= ''.$name.'';
- $pooldesc .= ''.$uuid.'>';
+ $pooldesc .= '' . $name . '';
+ $pooldesc .= '' . $uuid . '>';
$pooldesc .= '';
- $pooldesc .= '';
- $pooldesc .= '';
+ $pooldesc .= '';
+ $pooldesc .= '';
$pooldesc .= '';
- $pooldesc .= '/var/lib/xcat/pools/'.$uuid.'';
- #turns out we can 'define', then 'build', then 'create' on the poolobj instead of 'create', to get mkdir -p like function
- #system("ssh $mounthost mkdir -p /var/lib/xcat/pools/$uuid"); #ok, so not *technically* just building XML, but here is the cheapest
- #place to know uuid... And yes, we must be allowed to ssh in
- #libvirt just isn't capable enough for this sort of usage
+ $pooldesc .= '/var/lib/xcat/pools/' . $uuid . '';
+
+#turns out we can 'define', then 'build', then 'create' on the poolobj instead of 'create', to get mkdir -p like function
+#system("ssh $mounthost mkdir -p /var/lib/xcat/pools/$uuid"); #ok, so not *technically* just building XML, but here is the cheapest
+#place to know uuid... And yes, we must be allowed to ssh in
+#libvirt just isn't capable enough for this sort of usage
return $pooldesc;
}
sub get_storage_pool_by_url {
- my $url = shift;
- my $virtconn = shift;
+ my $url = shift;
+ my $virtconn = shift;
my $mounthost = shift;
unless ($virtconn) { $virtconn = $hypconn; }
my @currpools = $virtconn->list_storage_pools();
- push @currpools,$virtconn->list_defined_storage_pools();
+ push @currpools, $virtconn->list_defined_storage_pools();
my $poolobj;
my $pool;
- my $islvm=0;
+ my $islvm = 0;
+
foreach my $poolo (@currpools) {
$poolobj = $poolo;
$pool = $parser->parse_string($poolobj->get_xml_description()); #XMLin($poolobj->get_xml_description());
if ($url =~ /^nfs:\/\/([^\/]*)(\/.*)$/) { #check the essence of the pool rather than the name
- my $host=$1;
- my $path=$2;
+ my $host = $1;
+ my $path = $2;
unless ($pool->findnodes("/pool")->[0]->getAttribute("type") eq "netfs") {
- $pool=undef;
+ $pool = undef;
next;
}
+
#ok, it is netfs, now check source..
my $checkhost = $pool->findnodes("/pool/source/host")->[0]->getAttribute("name");
my $checkpath = $pool->findnodes("/pool/source/dir")->[0]->getAttribute("path");
if ($checkhost eq $host and $checkpath eq $path) { #TODO: check name resolution to see if they match really even if not strictly the same
last;
}
- } elsif ($url =~ /^dir:\/\/(.*)\z/) { #a directory, simple enough
- my $path = $1;
+ } elsif ($url =~ /^dir:\/\/(.*)\z/) { #a directory, simple enough
+ my $path = $1;
unless ($path =~ /^\//) {
- $path = '/'.$path;
- }
- $path =~ s/\/\z//; #delete trailing / if table specifies, a perfectly understable 'mistake'
- my $checkpath = $pool->findnodes("/pool/target/path/text()")->[0]->data;
- if ($checkpath eq $path) {
- last;
+ $path = '/' . $path;
+ }
+ $path =~ s/\/\z//; #delete trailing / if table specifies, a perfectly understable 'mistake'
+ my $checkpath = $pool->findnodes("/pool/target/path/text()")->[0]->data;
+ if ($checkpath eq $path) {
+ last;
+ }
+ } elsif ($url =~ /^lvm:\/\/([^:]*)/) { #lvm volume group....
+ my $vgname = $1;
+ my $checkname = $pool->findnodes("/pool/name/text()")->[0]->data;
+ if ($checkname eq $vgname) {
+ $islvm = 1;
+ last;
}
- } elsif ($url =~ /^lvm:\/\/([^:]*)/) { #lvm volume group....
- my $vgname = $1;
- my $checkname = $pool->findnodes("/pool/name/text()")->[0]->data;
- if ($checkname eq $vgname) {
- $islvm=1;
- last;
- }
} elsif ($pool->findnodes('/pool/name/text()')->[0]->data eq $url) { #$pool->{name} eq $url) {
last;
}
$pool = undef;
}
- if ($pool) {
- my $inf=$poolobj->get_info();
+ if ($pool) {
+ my $inf = $poolobj->get_info();
if ($inf->{state} == 0) { #Sys::Virt::StoragePool::STATE_INACTIVE) { #if pool is currently inactive, bring it up
unless ($islvm) { $poolobj->build(); } #if lvm and defined, it's almost certainly been built
$poolobj->create();
}
- eval { #we *try* to do this, but various things may interfere.
- #this is basically to make sure the list of contents is up to date
- $poolobj->refresh();
- };
- return $poolobj;
+ eval { #we *try* to do this, but various things may interfere.
+ #this is basically to make sure the list of contents is up to date
+ $poolobj->refresh();
+ };
+ return $poolobj;
}
- $poolobj = $virtconn->define_storage_pool(build_pool_xml($url,$mounthost));
+ $poolobj = $virtconn->define_storage_pool(build_pool_xml($url, $mounthost));
eval { $poolobj->build(); };
- if ($@) {
- my $error = $@;
- unless ($error =~ /vgcreate.*exit status 3/ or $error =~ /pvcreate.*exit status 5/) {
- die $@;
- }
+ if ($@) {
+ my $error = $@;
+ unless ($error =~ /vgcreate.*exit status 3/ or $error =~ /pvcreate.*exit status 5/) {
+ die $@;
+ }
}
$poolobj->create();
eval { #wrap in eval, not likely to fail here, but calling it at all may be superfluous anyway
- $poolobj->refresh();
+ $poolobj->refresh();
};
return $poolobj;
}
sub get_multiple_paths_by_url {
- my %args =@_;
- my $url = $args{url};
- my $node = $args{node};
+ my %args = @_;
+ my $url = $args{url};
+ my $node = $args{node};
my $poolobj = get_storage_pool_by_url($url);
unless ($poolobj) { die "Cound not get storage pool for $url"; }
- eval { #refresh() can 'die' if cloning in progress, accept stale data then
- $poolobj->refresh(); #if volumes change on nfs storage, libvirt is too dumb to notice
+ eval { #refresh() can 'die' if cloning in progress, accept stale data then
+ $poolobj->refresh(); #if volumes change on nfs storage, libvirt is too dumb to notice
};
my @volobjs = $poolobj->list_volumes();
my %paths;
foreach (@volobjs) {
if ($_->get_name() =~ /^$node\.([^\.]*)\.([^\.]*)$/) {
- $paths{$_->get_path()} = {device=>$1,format=>$2};
+ $paths{ $_->get_path() } = { device => $1, format => $2 };
} elsif ($_->get_name() =~ /^$node\.([^\.]*)$/) {
- $paths{$_->get_path()} = {device=>$1,format=>'raw'};
- #this requires any current user of qcow2 to migrate, unfortunate to escape
- #a vulnerability where raw user could write malicious qcow2 to header
- #and use that to get at files on the hypervisor os with escalated privilege
+ $paths{ $_->get_path() } = { device => $1, format => 'raw' };
+
+ #this requires any current user of qcow2 to migrate, unfortunate to escape
+ #a vulnerability where raw user could write malicious qcow2 to header
+ #and use that to get at files on the hypervisor os with escalated privilege
}
}
return \%paths;
}
+
sub get_filepath_by_url { #at the end of the day, the libvirt storage api gives the following capability:
#mount, limited ls, and qemu-img
- #it does not frontend mkdir, and does not abstract away any nitty-gritty detail, you must know:
- #the real mountpoint, and the real full path to storage
- #in addition to this, subdirectories are not allowed, and certain extra metadata must be created
- #not a big fan compared to ssh and run the commands myself, but it's the most straightforward path
- #to avoid ssh for users who dislike that style access
- my %args = @_;
- my $url = $args{url};
- my $dev = $args{dev};
+ #it does not frontend mkdir, and does not abstract away any nitty-gritty detail, you must know:
+ #the real mountpoint, and the real full path to storage
+ #in addition to this, subdirectories are not allowed, and certain extra metadata must be created
+ #not a big fan compared to ssh and run the commands myself, but it's the most straightforward path
+ #to avoid ssh for users who dislike that style access
+ my %args = @_;
+ my $url = $args{url};
+ my $dev = $args{dev};
my $create = $args{create};
- my $force = $args{force};
+ my $force = $args{force};
my $format = $args{format};
my $sparse = 1;
if ($url =~ /^lvm:/) {
- $sparse = 0;
- $format = 'raw';
+ $sparse = 0;
+ $format = 'raw';
}
unless ($format) {
$format = 'qcow2';
}
- #print "url=$url, dev=$dev,create=$create, force=$force, format=$format\n";
- #ok, now that we have the pool, we need the storage volume from the pool for the node/dev
+
+#print "url=$url, dev=$dev,create=$create, force=$force, format=$format\n";
+#ok, now that we have the pool, we need the storage volume from the pool for the node/dev
my $poolobj = get_storage_pool_by_url($url);
unless ($poolobj) { die "Could not get storage pool for $url"; }
eval { #make a refresh attempt non-fatal to fail, since cloning can block it
- $poolobj->refresh(); #if volumes change on nfs storage, libvirt is too dumb to notice
+ $poolobj->refresh(); #if volumes change on nfs storage, libvirt is too dumb to notice
};
- my @volobjs = $poolobj->list_volumes();
- my $desiredname = $node.'.'.$dev.'.'.$format;
+ my @volobjs = $poolobj->list_volumes();
+ my $desiredname = $node . '.' . $dev . '.' . $format;
+
#print "desiredname=$desiredname, volobjs=@volobjs\n";
foreach (@volobjs) {
if ($_->get_name() eq $desiredname) {
if ($create) {
- if ($force) { #must destroy the storage
+ if ($force) { #must destroy the storage
$_->delete();
} else {
die "Path already exists";
@@ -300,32 +316,33 @@ sub get_filepath_by_url { #at the end of the day, the libvirt storage api gives
}
}
}
- if ($create) {
+ if ($create) {
if ($create =~ /^clone=(.*)$/) {
my $src = $1;
- my $fmt='raw';
+ my $fmt = 'raw';
if ($src =~ /\.qcow2$/) {
- $fmt='qcow2';
+ $fmt = 'qcow2';
}
- my $vol = $poolobj->create_volume("".$desiredname."100$src");
- #ok, this is simply hinting, not the real deal, so to speak
- # 1) sys::virt complains if capacity isn't defined. We say '100', knowing full well it will be promptly ignored down the code. This is aggravating
- # and warrants recheck with the RHEL6 stack
- # 2) create_volume with backingStore is how we do the clone from master (i.e. a thin clone, a la qemu-img create)
- # note how backing store is full path, allowing cross-pool clones
- # 3) clone_volume is the way to invoke qemu-img convert (i.e. to 'promote' and flatten a vm image to a standalone duplicate volume
- # incidentally, promote to master will be relatively expensive compared to the converse operation, as expected
- # will have to verify as it is investigated whether this can successfully cross pools (hope so)
- # 4) qemu-img was so much more transparent and easy to figure out than this
- # additionally, when mastering a powered down node, we should rebase the node to be a cow clone of the master it just spawned
+ my $vol = $poolobj->create_volume("" . $desiredname . "100$src");
+
+#ok, this is simply hinting, not the real deal, so to speak
+# 1) sys::virt complains if capacity isn't defined. We say '100', knowing full well it will be promptly ignored down the code. This is aggravating
+# and warrants recheck with the RHEL6 stack
+# 2) create_volume with backingStore is how we do the clone from master (i.e. a thin clone, a la qemu-img create)
+# note how backing store is full path, allowing cross-pool clones
+# 3) clone_volume is the way to invoke qemu-img convert (i.e. to 'promote' and flatten a vm image to a standalone duplicate volume
+# incidentally, promote to master will be relatively expensive compared to the converse operation, as expected
+# will have to verify as it is investigated whether this can successfully cross pools (hope so)
+# 4) qemu-img was so much more transparent and easy to figure out than this
+# additionally, when mastering a powered down node, we should rebase the node to be a cow clone of the master it just spawned
} else {
- my $vol;
- unless ($sparse) { #skip allocation specification for now
- #currently, LV can have reduced allocation, but *cannot* grow.....
- $vol = $poolobj->create_volume("".$desiredname."".getUnits($create,"G",1)."");
- } else {
- $vol = $poolobj->create_volume("".$desiredname."".getUnits($create,"G",1)."0");
- }
+ my $vol;
+ unless ($sparse) { #skip allocation specification for now
+ #currently, LV can have reduced allocation, but *cannot* grow.....
+ $vol = $poolobj->create_volume("" . $desiredname . "" . getUnits($create, "G", 1) . "");
+ } else {
+ $vol = $poolobj->create_volume("" . $desiredname . "" . getUnits($create, "G", 1) . "0");
+ }
if ($vol) { return $vol->get_path(); }
}
} else {
@@ -334,99 +351,103 @@ sub get_filepath_by_url { #at the end of the day, the libvirt storage api gives
}
sub nodesockopen {
- my $node = shift;
- my $port = shift;
- unless ($node) { return 0; }
- my $socket;
- my $addr = gethostbyname($node);
- if (!$addr) {
- xCAT::SvrUtils::sendmsg([1,"Cannot not resolve host $node"], $callback);
+ my $node = shift;
+ my $port = shift;
+ unless ($node) { return 0; }
+ my $socket;
+ my $addr = gethostbyname($node);
+ if (!$addr) {
+ xCAT::SvrUtils::sendmsg([ 1, "Cannot not resolve host $node" ], $callback);
return 0;
- }
- my $sin = sockaddr_in($port,$addr);
- my $proto = getprotobyname('tcp');
- socket($socket,PF_INET,SOCK_STREAM,$proto) || return 0;
- connect($socket,$sin) || return 0;
- return 1;
+ }
+ my $sin = sockaddr_in($port, $addr);
+ my $proto = getprotobyname('tcp');
+ socket($socket, PF_INET, SOCK_STREAM, $proto) || return 0;
+ connect($socket, $sin) || return 0;
+ return 1;
}
-
+
sub waitforack {
- my $sock = shift;
+ my $sock = shift;
my $select = new IO::Select;
$select->add($sock);
my $str;
if ($select->can_read(60)) { # Continue after 10 seconds, even if not acked...
if ($str = <$sock>) {
} else {
- $select->remove($sock); #Block until parent acks data
+ $select->remove($sock); #Block until parent acks data
}
}
}
sub reconfigvm {
- $node=shift;
- my $xml = shift;
- my $domdesc = $parser->parse_string($xml);
+ $node = shift;
+ my $xml = shift;
+ my $domdesc = $parser->parse_string($xml);
my @bootdevs = $domdesc->findnodes("/domain/os/boot");
my $curroffset = $domdesc->findnodes("/domain/clock")->[0]->getAttribute("offset");
my $newoffset;
- my $needfixin=0;
- if (defined ($confdata->{vm}->{$node}->[0]->{clockoffset})) {
+ my $needfixin = 0;
+ if (defined($confdata->{vm}->{$node}->[0]->{clockoffset})) {
+
#If user requested a specific behavior, give it
- $newoffset = $confdata->{vm}->{$node}->[0]->{clockoffset};
+ $newoffset = $confdata->{vm}->{$node}->[0]->{clockoffset};
} else {
+
#Otherwise, only do local time for things that look MS
- if (defined ($confdata->{nodetype}->{$node}->[0]->{os}) and $confdata->{nodetype}->{$node}->[0]->{os} =~ /win.*/) {
- $newoffset = 'localtime';
- } else { #For everyone else, utc is preferred generally
- $newoffset = 'utc';
+ if (defined($confdata->{nodetype}->{$node}->[0]->{os}) and $confdata->{nodetype}->{$node}->[0]->{os} =~ /win.*/) {
+ $newoffset = 'localtime';
+ } else { #For everyone else, utc is preferred generally
+ $newoffset = 'utc';
}
}
if ($curroffset ne $newoffset) {
- $needfixin=1;
- $domdesc->findnodes("/domain/clock")->[0]->setAttribute("offset",$newoffset);
+ $needfixin = 1;
+ $domdesc->findnodes("/domain/clock")->[0]->setAttribute("offset", $newoffset);
}
my @oldbootdevs;
if (defined $confdata->{vm}->{$node}->[0]->{memory}) {
- $needfixin=1;
- $domdesc->findnodes("/domain/memory/text()")->[0]->setData(getUnits($confdata->{vm}->{$node}->[0]->{memory},"M",1024));
- foreach ($domdesc->findnodes("/domain/currentMemory/text()")) {
- $_->setData(getUnits($confdata->{vm}->{$node}->[0]->{memory},"M",1024));
- }
+ $needfixin = 1;
+ $domdesc->findnodes("/domain/memory/text()")->[0]->setData(getUnits($confdata->{vm}->{$node}->[0]->{memory}, "M", 1024));
+ foreach ($domdesc->findnodes("/domain/currentMemory/text()")) {
+ $_->setData(getUnits($confdata->{vm}->{$node}->[0]->{memory}, "M", 1024));
+ }
}
if (defined $confdata->{vm}->{$node}->[0]->{vcpus}) {
- $needfixin=1;
- $domdesc->findnodes("/domain/vcpu/text()")->[0]->setData($confdata->{vm}->{$node}->[0]->{vcpus});
+ $needfixin = 1;
+ $domdesc->findnodes("/domain/vcpu/text()")->[0]->setData($confdata->{vm}->{$node}->[0]->{vcpus});
}
if (defined $confdata->{vm}->{$node}->[0]->{bootorder}) {
- my @expectedorder = split(/[:,]/,$confdata->{vm}->{$node}->[0]->{bootorder});
+ my @expectedorder = split(/[:,]/, $confdata->{vm}->{$node}->[0]->{bootorder});
foreach (@expectedorder) { #this loop will check for changes and fix 'n' and 'net'
my $currdev = shift @bootdevs;
if ("net" eq $_ or "n" eq $_) {
$_ = "network";
}
unless ($currdev and $currdev->getAttribute("dev") eq $_) {
- $needfixin=1;
+ $needfixin = 1;
}
if ($currdev) {
- push @oldbootdevs,$currdev;
+ push @oldbootdevs, $currdev;
}
}
if (scalar(@bootdevs)) {
- $needfixin=1;
- push @oldbootdevs,@bootdevs;
+ $needfixin = 1;
+ push @oldbootdevs, @bootdevs;
}
unless ($needfixin) { return 0; }
- #ok, we need to remove all 'boot' nodes from current xml, and put in new ones in the order we like
+
+#ok, we need to remove all 'boot' nodes from current xml, and put in new ones in the order we like
foreach (@oldbootdevs) {
$_->parentNode->removeChild($_);
}
+
#now to add what we want...
my $osnode = $domdesc->findnodes("/domain/os")->[0];
foreach (@expectedorder) {
- my $fragment = $parser->parse_balanced_chunk('');
+ my $fragment = $parser->parse_balanced_chunk('');
$osnode->appendChild($fragment);
}
}
@@ -437,89 +458,93 @@ sub reconfigvm {
sub build_oshash {
my %rethash;
- $rethash{type}->{content}='hvm';
-
- my $hypcpumodel = $confdata->{$confdata->{vm}->{$node}->[0]->{host}}->{cpumodel};
+ $rethash{type}->{content} = 'hvm';
+
+ my $hypcpumodel = $confdata->{ $confdata->{vm}->{$node}->[0]->{host} }->{cpumodel};
unless (defined($hypcpumodel) and $hypcpumodel eq "ppc64le") {
- $rethash{bios}->{useserial}='yes';
+ $rethash{bios}->{useserial} = 'yes';
}
if (defined $confdata->{vm}->{$node}->[0]->{bootorder}) {
my $bootorder = $confdata->{vm}->{$node}->[0]->{bootorder};
- my @bootdevs = split(/[:,]/,$bootorder);
- my $bootnum = 0;
+ my @bootdevs = split(/[:,]/, $bootorder);
+ my $bootnum = 0;
foreach (@bootdevs) {
if ("net" eq $_ or "n" eq $_) {
- $rethash{boot}->[$bootnum]->{dev}="network";
+ $rethash{boot}->[$bootnum]->{dev} = "network";
} else {
- $rethash{boot}->[$bootnum]->{dev}=$_;
+ $rethash{boot}->[$bootnum]->{dev} = $_;
}
$bootnum++;
}
} else {
- $rethash{boot}->[0]->{dev}='network';
- $rethash{boot}->[1]->{dev}='hd';
+ $rethash{boot}->[0]->{dev} = 'network';
+ $rethash{boot}->[1]->{dev} = 'hd';
}
return \%rethash;
}
sub build_diskstruct {
print "build_diskstruct called\n";
- my $cdloc=shift;
- my @returns=();
+ my $cdloc = shift;
+ my @returns = ();
my $currdev;
- my @suffixes=('a','b','d'..'zzz');
- my $suffidx=0;
+ my @suffixes = ('a', 'b', 'd' .. 'zzz');
+ my $suffidx = 0;
my $storagemodel = $confdata->{vm}->{$node}->[0]->{storagemodel};
- my $cachemethod = "none";
- if ( $confdata->{vm}->{$node}->[0]->{storagecache}) {
+ my $cachemethod = "none";
+ if ($confdata->{vm}->{$node}->[0]->{storagecache}) {
$cachemethod = $confdata->{vm}->{$node}->[0]->{storagecache};
}
if (defined $confdata->{vm}->{$node}->[0]->{storage}) {
- my $disklocs=$confdata->{vm}->{$node}->[0]->{storage};
- my @locations=split /\|/,$disklocs;
+ my $disklocs = $confdata->{vm}->{$node}->[0]->{storage};
+ my @locations = split /\|/, $disklocs;
foreach my $disk (@locations) {
+
#Setting default values of a virtual disk backed by a file at hd*.
my $diskhash;
$disk =~ s/=(.*)//;
my $model = $1;
unless ($model) {
+
#if not defined, model will stay undefined like above
$model = $storagemodel;
- unless ($model) { $model = 'ide'; } #if still not defined, ide
+ unless ($model) { $model = 'ide'; } #if still not defined, ide
}
- my $prefix='hd';
+ my $prefix = 'hd';
if ($model eq 'virtio') {
- $prefix='vd';
+ $prefix = 'vd';
} elsif ($model eq 'scsi') {
- $prefix='sd';
+ $prefix = 'sd';
}
- $diskhash->{type} = 'file';
- $diskhash->{device} = 'disk';
- $diskhash->{target}->{dev} = $prefix.$suffixes[$suffidx];
+ $diskhash->{type} = 'file';
+ $diskhash->{device} = 'disk';
+ $diskhash->{target}->{dev} = $prefix . $suffixes[$suffidx];
$diskhash->{target}->{bus} = $model;
my @disk_parts = split(/,/, $disk);
+
#Find host file and determine if it is a file or a block device.
if (substr($disk_parts[0], 0, 4) eq 'phy:') {
- $diskhash->{type}='block';
+ $diskhash->{type} = 'block';
$diskhash->{source}->{dev} = substr($disk_parts[0], 4);
} elsif ($disk_parts[0] =~ m/^nfs:\/\/(.*)$/ or $disk_parts[0] =~ m/^dir:\/\/(.*)$/ or $disk_parts[0] =~ m/^lvm:\/\/(.*)$/) {
- my %disks = %{get_multiple_paths_by_url(url=>$disk_parts[0],node=>$node)};
+ my %disks = %{ get_multiple_paths_by_url(url => $disk_parts[0], node => $node) };
unless (keys %disks) {
- die "Unable to find any persistent disks at ".$disk_parts[0];
+ die "Unable to find any persistent disks at " . $disk_parts[0];
}
foreach (keys %disks) {
my $tdiskhash;
$tdiskhash->{type};
- $tdiskhash->{device}='disk';
- $tdiskhash->{driver}->{name}='qemu';
- $tdiskhash->{driver}->{type}=$disks{$_}->{format};
- $tdiskhash->{driver}->{cache}=$cachemethod;
- $tdiskhash->{source}->{file}=$_;
- $tdiskhash->{target}->{dev} = $disks{$_}->{device};
+ $tdiskhash->{device} = 'disk';
+ $tdiskhash->{driver}->{name} = 'qemu';
+ $tdiskhash->{driver}->{type} = $disks{$_}->{format};
+ $tdiskhash->{driver}->{cache} = $cachemethod;
+ $tdiskhash->{source}->{file} = $_;
+ $tdiskhash->{target}->{dev} = $disks{$_}->{device};
+
if ($disks{$_} =~ /^vd/) {
$tdiskhash->{target}->{bus} = 'virtio';
} elsif ($disks{$_} =~ /^hd/) {
@@ -527,17 +552,17 @@ sub build_diskstruct {
} elsif ($disks{$_} =~ /^sd/) {
$tdiskhash->{target}->{bus} = 'scsi';
}
- push @returns,$tdiskhash;
+ push @returns, $tdiskhash;
}
- next; #nfs:// skips the other stuff
- #$diskhash->{source}->{file} = get_filepath_by_url(url=>$disk_parts[0],dev=>$diskhash->{target}->{dev}); #"/var/lib/xcat/vmnt/nfs_".$1."/$node/".$diskhash->{target}->{dev};
- } else { #currently, this would be a bare file to slap in as a disk
+ next; #nfs:// skips the other stuff
+ #$diskhash->{source}->{file} = get_filepath_by_url(url=>$disk_parts[0],dev=>$diskhash->{target}->{dev}); #"/var/lib/xcat/vmnt/nfs_".$1."/$node/".$diskhash->{target}->{dev};
+ } else { #currently, this would be a bare file to slap in as a disk
$diskhash->{source}->{file} = $disk_parts[0];
}
- #See if there are any other options. If not, increment suffidx because the already determined device node was used.
- #evidently, we support specificying explicitly how to target the system..
+#See if there are any other options. If not, increment suffidx because the already determined device node was used.
+#evidently, we support specificying explicitly how to target the system..
if (@disk_parts gt 1) {
my @disk_opts = split(/:/, $disk_parts[1]);
if ($disk_opts[0] ne '') {
@@ -546,231 +571,236 @@ sub build_diskstruct {
$suffidx++;
}
if ($disk_opts[1] eq 'cdrom') {
- $diskhash->{device}='cdrom';
+ $diskhash->{device} = 'cdrom';
}
} else {
$suffidx++;
}
- push @returns,$diskhash;
+ push @returns, $diskhash;
}
}
- my $cdprefix='hd';
+ my $cdprefix = 'hd';
+
# device name vd* doesn't work for CDROM, so delete it.
#if ($storagemodel eq 'virtio') {
# $cdprefix='vd';
#} els
if ($storagemodel eq 'scsi') {
- $cdprefix='sd';
+ $cdprefix = 'sd';
}
$suffidx += 1;
if ($cdloc) {
my $cdhash;
- $cdhash->{device}='cdrom';
+ $cdhash->{device} = 'cdrom';
if ($cdloc =~ /^\/dev/) {
- $cdhash->{type}='block';
+ $cdhash->{type} = 'block';
} else {
- $cdhash->{type}='file';
+ $cdhash->{type} = 'file';
}
- $cdhash->{source}->{file}=$cdloc;
+ $cdhash->{source}->{file} = $cdloc;
$cdhash->{readonly};
- $cdhash->{target}->{dev}=$cdprefix.$suffixes[$suffidx];
- push @returns,$cdhash;
+ $cdhash->{target}->{dev} = $cdprefix . $suffixes[$suffidx];
+ push @returns, $cdhash;
} else { #give the VM an empty optical drive, to allow chvm live attach/remove
- my $cdhash;
- $cdhash->{device}='cdrom';
- $cdhash->{type}='file';
- $cdhash->{readonly};
- $cdhash->{target}->{dev}=$cdprefix.$suffixes[$suffidx];
- push @returns,$cdhash;
+ my $cdhash;
+ $cdhash->{device} = 'cdrom';
+ $cdhash->{type} = 'file';
+ $cdhash->{readonly};
+ $cdhash->{target}->{dev} = $cdprefix . $suffixes[$suffidx];
+ push @returns, $cdhash;
}
return \@returns;
}
+
sub getNodeUUID {
my $node = shift;
my $uuid;
if ($confdata->{vpd}->{$node}->[0] and $confdata->{vpd}->{$node}->[0]->{uuid}) {
- $uuid = $confdata->{vpd}->{$node}->[0]->{uuid};
- $uuid =~ s/^(..)(..)(..)(..)-(..)(..)-(..)(..)/$4$3$2$1-$6$5-$8$7/;
+ $uuid = $confdata->{vpd}->{$node}->[0]->{uuid};
+ $uuid =~ s/^(..)(..)(..)(..)-(..)(..)-(..)(..)/$4$3$2$1-$6$5-$8$7/;
return $uuid;
}
if ($confdata->{mac}->{$node}->[0]->{mac}) { #a uuidv1 is possible, generate that for absolute uniqueness guarantee
my $mac = $confdata->{mac}->{$node}->[0]->{mac};
$mac =~ s/\|.*//;
$mac =~ s/!.*//;
- $updatetable->{vpd}->{$node}={uuid=>xCAT::Utils::genUUID(mac=>$mac)};
+ $updatetable->{vpd}->{$node} = { uuid => xCAT::Utils::genUUID(mac => $mac) };
} else {
- $updatetable->{vpd}->{$node}={uuid=>xCAT::Utils::genUUID()};
+ $updatetable->{vpd}->{$node} = { uuid => xCAT::Utils::genUUID() };
}
$uuid = $updatetable->{vpd}->{$node}->{uuid};
$uuid =~ s/^(..)(..)(..)(..)-(..)(..)-(..)(..)/$4$3$2$1-$6$5-$8$7/;
return $uuid;
}
+
sub build_nicstruct {
my $rethash;
my $node = shift;
- my @nics=();
+ my @nics = ();
if ($confdata->{vm}->{$node}->[0]->{nics}) {
- @nics = split /,/,$confdata->{vm}->{$node}->[0]->{nics};
+ @nics = split /,/, $confdata->{vm}->{$node}->[0]->{nics};
}
- my @macs=xCAT::VMCommon::getMacAddresses($confdata,$node,scalar @nics);
+ my @macs = xCAT::VMCommon::getMacAddresses($confdata, $node, scalar @nics);
my @rethashes;
foreach (@macs) {
my $rethash;
my $nic = shift @nics;
my $type = 'virtio'; #better default fake nic than rtl8139, relevant to most
unless ($nic) {
- last; #Don't want to have multiple vnics tied to the same switch
+ last; #Don't want to have multiple vnics tied to the same switch
}
- $nic =~ s/.*://; #the detail of how the bridge was built is of no
- #interest to this segment of code
+ $nic =~ s/.*://; #the detail of how the bridge was built is of no
+ #interest to this segment of code
if ($confdata->{vm}->{$node}->[0]->{nicmodel}) {
$type = $confdata->{vm}->{$node}->[0]->{nicmodel};
}
if ($nic =~ /=/) {
- ($nic,$type) = split /=/,$nic,2;
+ ($nic, $type) = split /=/, $nic, 2;
}
- $rethash->{type}='bridge';
- $rethash->{mac}->{address}=$_;
- $rethash->{source}->{bridge}=$nic;
- $rethash->{model}->{type}=$type;
- push @rethashes,$rethash;
+ $rethash->{type} = 'bridge';
+ $rethash->{mac}->{address} = $_;
+ $rethash->{source}->{bridge} = $nic;
+ $rethash->{model}->{type} = $type;
+ push @rethashes, $rethash;
}
return \@rethashes;
}
+
sub getUnits {
- my $amount = shift;
+ my $amount = shift;
my $defunit = shift;
- my $divisor=shift;
+ my $divisor = shift;
unless ($divisor) {
$divisor = 1;
}
- if ($amount =~ /(\D)$/) { #If unitless, add unit
- $defunit=$1;
+ if ($amount =~ /(\D)$/) { #If unitless, add unit
+ $defunit = $1;
chop $amount;
}
if ($defunit =~ /k/i) {
- return $amount*1024/$divisor;
+ return $amount * 1024 / $divisor;
} elsif ($defunit =~ /m/i) {
- return $amount*1048576/$divisor;
+ return $amount * 1048576 / $divisor;
} elsif ($defunit =~ /g/i) {
- return $amount*1073741824/$divisor;
- }
+ return $amount * 1073741824 / $divisor;
+ }
}
sub build_xmldesc {
- my $node = shift;
- my %args=@_;
- my $cdloc=$args{cd};
- my %xtree=();
- my $hypcpumodel = $confdata->{$confdata->{vm}->{$node}->[0]->{host}}->{cpumodel};
- my $hypcputype = $confdata->{$confdata->{vm}->{$node}->[0]->{host}}->{cputype};
- my $hypcputhreads = $confdata->{$confdata->{vm}->{$node}->[0]->{host}}->{cpu_thread};
+ my $node = shift;
+ my %args = @_;
+ my $cdloc = $args{cd};
+ my %xtree = ();
+ my $hypcpumodel = $confdata->{ $confdata->{vm}->{$node}->[0]->{host} }->{cpumodel};
+ my $hypcputype = $confdata->{ $confdata->{vm}->{$node}->[0]->{host} }->{cputype};
+ my $hypcputhreads = $confdata->{ $confdata->{vm}->{$node}->[0]->{host} }->{cpu_thread};
unless ($hypcputhreads) {
$hypcputhreads = "1";
}
- $xtree{type}='kvm';
- $xtree{name}->{content}=$node;
- $xtree{uuid}->{content}=getNodeUUID($node);
- $xtree{os} = build_oshash();
+ $xtree{type} = 'kvm';
+ $xtree{name}->{content} = $node;
+ $xtree{uuid}->{content} = getNodeUUID($node);
+ $xtree{os} = build_oshash();
if (defined($hypcpumodel) and $hypcpumodel eq "ppc64") {
- $xtree{os}->{type}->{arch} = "ppc64";
+ $xtree{os}->{type}->{arch} = "ppc64";
$xtree{os}->{type}->{machine} = "pseries";
delete $xtree{os}->{bios};
}
if ($args{memory}) {
- $xtree{memory}->{content}=getUnits($args{memory},"M",1024);
+ $xtree{memory}->{content} = getUnits($args{memory}, "M", 1024);
if ($confdata->{vm}->{$node}->[0]->{memory}) {
- $updatetable->{vm}->{$node}->{memory}=$args{memory};
+ $updatetable->{vm}->{$node}->{memory} = $args{memory};
}
} elsif (defined $confdata->{vm}->{$node}->[0]->{memory}) {
- $xtree{memory}->{content}=getUnits($confdata->{vm}->{$node}->[0]->{memory},"M",1024);
+ $xtree{memory}->{content} = getUnits($confdata->{vm}->{$node}->[0]->{memory}, "M", 1024);
} else {
- $xtree{memory}->{content}=524288;
+ $xtree{memory}->{content} = 524288;
}
-
+
my %cpupinhash;
my @passthrudevices;
my $memnumanodes;
- my $advsettings=undef;
+ my $advsettings = undef;
if (defined $confdata->{vm}->{$node}->[0]->{othersettings}) {
- $advsettings=$confdata->{vm}->{$node}->[0]->{othersettings};
+ $advsettings = $confdata->{vm}->{$node}->[0]->{othersettings};
}
-
- #parse the additional settings in attrubute vm.othersettings
- #the settings are semicolon delimited, the format of each setting is:
- #cpu pining: "vcpupin:"
- #pci passthrough: "devpassthrough:,..."
- #memory binding: "membind:"
- if($advsettings){
- my @tmp_array=split ";",$advsettings;
- foreach(@tmp_array){
- if(/vcpupin:['"]?([^:'"]*)['"]?:?['"]?([^:'"]*)['"]?/){
- if($2){
- #this is for cpu pining in the vcpu level,which is not currently supported
- #reserved for future use
- $cpupinhash{$1}=$2;
- }else{
- $cpupinhash{ALL}=$1;
- }
- }
-
- if(/devpassthrough:(.*)/){
- @passthrudevices=split ",",$1;
- }
-
- if(/membind:(.*)/){
- $memnumanodes=$1;
- }
-
+
+ #parse the additional settings in attrubute vm.othersettings
+ #the settings are semicolon delimited, the format of each setting is:
+ #cpu pining: "vcpupin:"
+ #pci passthrough: "devpassthrough:,..."
+ #memory binding: "membind:"
+ if ($advsettings) {
+ my @tmp_array = split ";", $advsettings;
+ foreach (@tmp_array) {
+ if (/vcpupin:['"]?([^:'"]*)['"]?:?['"]?([^:'"]*)['"]?/) {
+ if ($2) {
+
+ #this is for cpu pining in the vcpu level,which is not currently supported
+ #reserved for future use
+ $cpupinhash{$1} = $2;
+ } else {
+ $cpupinhash{ALL} = $1;
+ }
+ }
+
+ if (/devpassthrough:(.*)/) {
+ @passthrudevices = split ",", $1;
+ }
+
+ if (/membind:(.*)/) {
+ $memnumanodes = $1;
+ }
+
}
- }
+ }
#prepare the xml hash for memory binding
- if(defined $memnumanodes){
- my %numatunehash;
- $numatunehash{memory}=[{nodeset=>"$memnumanodes"}];
- $xtree{numatune}=\%numatunehash;
+ if (defined $memnumanodes) {
+ my %numatunehash;
+ $numatunehash{memory} = [ { nodeset => "$memnumanodes" } ];
+ $xtree{numatune} = \%numatunehash;
}
#prepare the xml hash for cpu pining
- if(exists $cpupinhash{ALL}){
- $xtree{vcpu}->{placement}='static';
- $xtree{vcpu}->{cpuset}="$cpupinhash{ALL}";
- $xtree{vcpu}->{cpuset}=~s/\"\'//g;
+ if (exists $cpupinhash{ALL}) {
+ $xtree{vcpu}->{placement} = 'static';
+ $xtree{vcpu}->{cpuset} = "$cpupinhash{ALL}";
+ $xtree{vcpu}->{cpuset} =~ s/\"\'//g;
}
-
+
#prepare the xml hash for pci passthrough
my @prdevarray;
- foreach my $devname(@passthrudevices){
- my $devobj=$hypconn->get_node_device_by_name($devname);
- unless($devobj){
- return -1;
- }
+ foreach my $devname (@passthrudevices) {
+ my $devobj = $hypconn->get_node_device_by_name($devname);
+ unless ($devobj) {
+ return -1;
+ }
- #get the xml description of the pci device
- my $devxml=$devobj->get_xml_description();
- unless($devxml){
- return -1;
- }
-
- my $devhash=XMLin($devxml);
- if(defined $devhash->{capability}->{type} and $devhash->{capability}->{type} =~ /pci/i ){
- my %tmphash;
- $tmphash{mode}='subsystem';
- $tmphash{type}=$devhash->{capability}->{type};
- $tmphash{managed}="yes";
- $tmphash{driver}->{name}="vfio";
- $tmphash{source}->{address}->[0]=\%{$devhash->{'capability'}->{'iommuGroup'}->{'address'}};
- push(@prdevarray,\%tmphash);
-
- }
+ #get the xml description of the pci device
+ my $devxml = $devobj->get_xml_description();
+ unless ($devxml) {
+ return -1;
+ }
+
+ my $devhash = XMLin($devxml);
+ if (defined $devhash->{capability}->{type} and $devhash->{capability}->{type} =~ /pci/i) {
+ my %tmphash;
+ $tmphash{mode} = 'subsystem';
+ $tmphash{type} = $devhash->{capability}->{type};
+ $tmphash{managed} = "yes";
+ $tmphash{driver}->{name} = "vfio";
+ $tmphash{source}->{address}->[0] = \%{ $devhash->{'capability'}->{'iommuGroup'}->{'address'} };
+ push(@prdevarray, \%tmphash);
+
+ }
}
-
- $xtree{devices}->{hostdev}=\@prdevarray;
+
+ $xtree{devices}->{hostdev} = \@prdevarray;
if ($hypcpumodel eq "ppc64" or $hypcpumodel eq "ppc64le") {
@@ -779,101 +809,105 @@ sub build_xmldesc {
$cpuhash{model} = $hypcputype;
}
if ($args{cpus}) {
- $xtree{vcpu}->{content}=$args{cpus} * $hypcputhreads;
- $cpuhash{topology}->{sockets} = 1;
- $cpuhash{topology}->{cores} = $args{cpus};
- $cpuhash{topology}->{threads} = $hypcputhreads;
- $updatetable->{vm}->{$node}->{cpus}=$args{cpus};
+ $xtree{vcpu}->{content} = $args{cpus} * $hypcputhreads;
+ $cpuhash{topology}->{sockets} = 1;
+ $cpuhash{topology}->{cores} = $args{cpus};
+ $cpuhash{topology}->{threads} = $hypcputhreads;
+ $updatetable->{vm}->{$node}->{cpus} = $args{cpus};
} elsif (defined $confdata->{vm}->{$node}->[0]->{cpus}) {
- $xtree{vcpu}->{content}=$confdata->{vm}->{$node}->[0]->{cpus} * $hypcputhreads;
+ $xtree{vcpu}->{content} = $confdata->{vm}->{$node}->[0]->{cpus} * $hypcputhreads;
$cpuhash{topology}->{sockets} = 1;
$cpuhash{topology}->{cores} = $confdata->{vm}->{$node}->[0]->{cpus};
$cpuhash{topology}->{threads} = $hypcputhreads;
} else {
- $xtree{vcpu}->{content}=1 * $hypcputhreads;
+ $xtree{vcpu}->{content} = 1 * $hypcputhreads;
$cpuhash{topology}->{sockets} = 1;
- $cpuhash{topology}->{cores} = 1;
+ $cpuhash{topology}->{cores} = 1;
$cpuhash{topology}->{threads} = $hypcputhreads;
}
$xtree{cpu} = \%cpuhash;
} else {
if ($args{cpus}) {
- $xtree{vcpu}->{content}=$args{cpus};
+ $xtree{vcpu}->{content} = $args{cpus};
if ($confdata->{vm}->{$node}->[0]->{cpus}) {
- $updatetable->{vm}->{$node}->{cpus}=$args{cpus};
+ $updatetable->{vm}->{$node}->{cpus} = $args{cpus};
}
} elsif (defined $confdata->{vm}->{$node}->[0]->{cpus}) {
- $xtree{vcpu}->{content}=$confdata->{vm}->{$node}->[0]->{cpus};
+ $xtree{vcpu}->{content} = $confdata->{vm}->{$node}->[0]->{cpus};
} else {
- $xtree{vcpu}->{content}=1;
+ $xtree{vcpu}->{content} = 1;
}
}
- if (defined ($confdata->{vm}->{$node}->[0]->{clockoffset})) {
+ if (defined($confdata->{vm}->{$node}->[0]->{clockoffset})) {
+
#If user requested a specific behavior, give it
- $xtree{clock}->{offset}=$confdata->{vm}->{$node}->[0]->{clockoffset};
+ $xtree{clock}->{offset} = $confdata->{vm}->{$node}->[0]->{clockoffset};
} else {
+
#Otherwise, only do local time for things that look MS
- if (defined ($confdata->{nodetype}->{$node}->[0]->{os}) and $confdata->{nodetype}->{$node}->[0]->{os} =~ /win.*/) {
- $xtree{clock}->{offset}='localtime';
- } else { #For everyone else, utc is preferred generally
- $xtree{clock}->{offset}='utc';
+ if (defined($confdata->{nodetype}->{$node}->[0]->{os}) and $confdata->{nodetype}->{$node}->[0]->{os} =~ /win.*/) {
+ $xtree{clock}->{offset} = 'localtime';
+ } else { #For everyone else, utc is preferred generally
+ $xtree{clock}->{offset} = 'utc';
}
}
- $xtree{features}->{pae}={};
- $xtree{features}->{acpi}={};
- $xtree{features}->{apic}={};
- $xtree{features}->{content}="\n";
- $xtree{devices}->{disk}=build_diskstruct($cdloc);
- $xtree{devices}->{interface}=build_nicstruct($node);
+ $xtree{features}->{pae} = {};
+ $xtree{features}->{acpi} = {};
+ $xtree{features}->{apic} = {};
+ $xtree{features}->{content} = "\n";
+ $xtree{devices}->{disk} = build_diskstruct($cdloc);
+ $xtree{devices}->{interface} = build_nicstruct($node);
+
#use content to force xml simple to not make model the 'name' of video
- if (defined ($confdata->{vm}->{$node}->[0]->{vidmodel})) {
- my $model = $confdata->{vm}->{$node}->[0]->{vidmodel};
- my $vram = '8192';
- if ($model eq 'qxl') {
- $xtree{devices}->{channel}->{type}='spicevmc';
- $xtree{devices}->{channel}->{target}->{type}='virtio';
- $xtree{devices}->{channel}->{target}->{name}='com.redhat.spice.0';
- $vram = 65536; } #surprise, spice blows up with less vram than this after version 0.6 and up
- $xtree{devices}->{video}= [ { 'content'=>'','model'=> {type=>$model,vram=>$vram}}];
+ if (defined($confdata->{vm}->{$node}->[0]->{vidmodel})) {
+ my $model = $confdata->{vm}->{$node}->[0]->{vidmodel};
+ my $vram = '8192';
+ if ($model eq 'qxl') {
+ $xtree{devices}->{channel}->{type} = 'spicevmc';
+ $xtree{devices}->{channel}->{target}->{type} = 'virtio';
+ $xtree{devices}->{channel}->{target}->{name} = 'com.redhat.spice.0';
+ $vram = 65536; } #surprise, spice blows up with less vram than this after version 0.6 and up
+ $xtree{devices}->{video} = [ { 'content' => '', 'model' => { type => $model, vram => $vram } } ];
} else {
- $xtree{devices}->{video}= [ { 'content'=>'','model'=> {type=>'vga',vram=>8192}}];
+ $xtree{devices}->{video} = [ { 'content' => '', 'model' => { type => 'vga', vram => 8192 } } ];
}
- $xtree{devices}->{input}->{type}='tablet';
- $xtree{devices}->{input}->{bus}='usb';
- if (defined ($confdata->{vm}->{$node}->[0]->{vidproto})) {
- $xtree{devices}->{graphics}->{type}=$confdata->{vm}->{$node}->[0]->{vidproto};
+ $xtree{devices}->{input}->{type} = 'tablet';
+ $xtree{devices}->{input}->{bus} = 'usb';
+ if (defined($confdata->{vm}->{$node}->[0]->{vidproto})) {
+ $xtree{devices}->{graphics}->{type} = $confdata->{vm}->{$node}->[0]->{vidproto};
} else {
- $xtree{devices}->{graphics}->{type}='vnc';
+ $xtree{devices}->{graphics}->{type} = 'vnc';
}
- $xtree{devices}->{graphics}->{autoport}='yes';
- $xtree{devices}->{graphics}->{listen}='0.0.0.0';
+ $xtree{devices}->{graphics}->{autoport} = 'yes';
+ $xtree{devices}->{graphics}->{listen} = '0.0.0.0';
if ($confdata->{vm}->{$node}->[0]->{vidpassword}) {
- $xtree{devices}->{graphics}->{password}=$confdata->{vm}->{$node}->[0]->{vidpassword};
+ $xtree{devices}->{graphics}->{password} = $confdata->{vm}->{$node}->[0]->{vidpassword};
} else {
- $xtree{devices}->{graphics}->{password}=genpassword(20);
+ $xtree{devices}->{graphics}->{password} = genpassword(20);
}
if (defined($hypcpumodel) and $hypcpumodel eq 'ppc64') {
$xtree{devices}->{emulator}->{content} = "/usr/bin/qemu-system-ppc64";
- }
+ }
- $xtree{devices}->{console}->{type}='pty';
- $xtree{devices}->{console}->{target}->{port}='1';
- return XMLout(\%xtree,RootName=>"domain");
+ $xtree{devices}->{console}->{type} = 'pty';
+ $xtree{devices}->{console}->{target}->{port} = '1';
+ return XMLout(\%xtree, RootName => "domain");
}
sub refresh_vm {
my $dom = shift;
- my $newxml=$dom->get_xml_description();
- $updatetable->{kvm_nodedata}->{$node}->{xml}=$newxml;
+ my $newxml = $dom->get_xml_description();
+ $updatetable->{kvm_nodedata}->{$node}->{xml} = $newxml;
$newxml = XMLin($newxml);
- my $vidport=$newxml->{devices}->{graphics}->{port};
- my $vidproto=$newxml->{devices}->{graphics}->{type};
- my $stty=$newxml->{devices}->{console}->{tty};
+ my $vidport = $newxml->{devices}->{graphics}->{port};
+ my $vidproto = $newxml->{devices}->{graphics}->{type};
+ my $stty = $newxml->{devices}->{console}->{tty};
+
#$updatetable->{vm}->{$node}={vncport=>$vncport,textconsole=>$stty};
#$vmtab->setNodeAttribs($node,{vncport=>$vncport,textconsole=>$stty});
- return {vidport=>$vidport,textconsole=>$stty,vidproto=>$vidproto};
+ return { vidport => $vidport, textconsole => $stty, vidproto => $vidproto };
}
sub getcons {
@@ -881,117 +915,122 @@ sub getcons {
my $type = shift();
my $dom;
eval {
- $dom = $hypconn->get_domain_by_name($node);
+ $dom = $hypconn->get_domain_by_name($node);
};
unless ($dom) {
- return 1,"Unable to query running VM";
+ return 1, "Unable to query running VM";
}
- my $consdata=refresh_vm($dom);
- my $hyper=$confdata->{vm}->{$node}->[0]->{host};
+ my $consdata = refresh_vm($dom);
+ my $hyper = $confdata->{vm}->{$node}->[0]->{host};
if ($type eq "text") {
my $serialspeed;
if ($confdata->{nodehm}) {
- $serialspeed=$confdata->{nodehm}->{$node}->[0]->{serialspeed};
+ $serialspeed = $confdata->{nodehm}->{$node}->[0]->{serialspeed};
}
- my $sconsparms = {node=>[{name=>[$node]}]};
- $sconsparms->{node}->[0]->{sshhost}=[$hyper];
- $sconsparms->{node}->[0]->{psuedotty}=[$consdata->{textconsole}];
- $sconsparms->{node}->[0]->{baudrate}=[$serialspeed];
- return (0,$sconsparms);
+ my $sconsparms = { node => [ { name => [$node] } ] };
+ $sconsparms->{node}->[0]->{sshhost} = [$hyper];
+ $sconsparms->{node}->[0]->{psuedotty} = [ $consdata->{textconsole} ];
+ $sconsparms->{node}->[0]->{baudrate} = [$serialspeed];
+ return (0, $sconsparms);
} elsif ($type eq "vid") {
- $consdata->{server}=$hyper;
- my $domxml = $dom->get_xml_description();
- my $parseddom = $parser->parse_string($domxml);
- my ($graphicsnode) = $parseddom->findnodes("//graphics");
- my $tpasswd;
- if ($confdata->{vm}->{$node}->[0]->{vidpassword}) {
- $tpasswd=$confdata->{vm}->{$node}->[0]->{vidpassword};
- $graphicsnode->removeAttribute("passwdValidTo");
- } else {
- $tpasswd=genpassword(16);
- my $validto=POSIX::strftime("%Y-%m-%dT%H:%M:%S",gmtime(time()+60));
- $graphicsnode->setAttribute("passwdValidTo",$validto);
- }
- $graphicsnode->setAttribute("passwd",$tpasswd);
- $dom->update_device($graphicsnode->toString());
- #$dom->update_device("");
- $consdata->{password}=$tpasswd;
- return $consdata;
- #return (0,{$consdata->{vidproto}.'@'.$hyper.":".$consdata->{vidport}); #$consdata->{vncport});
+ $consdata->{server} = $hyper;
+ my $domxml = $dom->get_xml_description();
+ my $parseddom = $parser->parse_string($domxml);
+ my ($graphicsnode) = $parseddom->findnodes("//graphics");
+ my $tpasswd;
+ if ($confdata->{vm}->{$node}->[0]->{vidpassword}) {
+ $tpasswd = $confdata->{vm}->{$node}->[0]->{vidpassword};
+ $graphicsnode->removeAttribute("passwdValidTo");
+ } else {
+ $tpasswd = genpassword(16);
+ my $validto = POSIX::strftime("%Y-%m-%dT%H:%M:%S", gmtime(time() + 60));
+ $graphicsnode->setAttribute("passwdValidTo", $validto);
+ }
+ $graphicsnode->setAttribute("passwd", $tpasswd);
+ $dom->update_device($graphicsnode->toString());
+
+#$dom->update_device("");
+ $consdata->{password} = $tpasswd;
+ return $consdata;
+
+#return (0,{$consdata->{vidproto}.'@'.$hyper.":".$consdata->{vidport}); #$consdata->{vncport});
}
}
+
sub getrvidparms {
- my $node=shift;
- my $location = getcons($node,"vid");
+ my $node = shift;
+ my $location = getcons($node, "vid");
unless (ref $location) {
- return (1,"Error: Unable to determine rvid destination for $node (appears VM is off)");
+ return (1, "Error: Unable to determine rvid destination for $node (appears VM is off)");
}
- my @output = (
- "method: kvm"
- );
+ my @output = (
+ "method: kvm"
+ );
foreach (keys %$location) {
- push @output,$_.":".$location->{$_};
+ push @output, $_ . ":" . $location->{$_};
}
- return 0,@output;
+ return 0, @output;
}
my %cached_noderanges;
+
sub pick_target {
- my $node = shift;
+ my $node = shift;
my $addmemory = shift;
my $target;
- my $mostfreememory=undef;
+ my $mostfreememory = undef;
my $currentfreememory;
- my $candidates= $confdata->{vm}->{$node}->[0]->{migrationdest};
- my $currhyp=$confdata->{vm}->{$node}->[0]->{host};
-#caching strategy is implicit on whether $addmemory is passed.
+ my $candidates = $confdata->{vm}->{$node}->[0]->{migrationdest};
+ my $currhyp = $confdata->{vm}->{$node}->[0]->{host};
+
+ #caching strategy is implicit on whether $addmemory is passed.
unless ($candidates) {
return undef;
}
my @fosterhyps; #noderange is relatively expensive, and generally we only will have a few distinct noderange descriptions to contend with in a mass adoption, so cache eache one for reuse across pick_target() calls
if (defined $cached_noderanges{$candidates}) {
- @fosterhyps = @{$cached_noderanges{$candidates}};
+ @fosterhyps = @{ $cached_noderanges{$candidates} };
} else {
- @fosterhyps = noderange($candidates);
+ @fosterhyps = noderange($candidates);
$cached_noderanges{$candidates} = \@fosterhyps;
}
foreach (@fosterhyps) {
my $targconn;
- my $cand=$_;
- if ($_ eq $currhyp) { next; } #skip current node
- if ($offlinehyps{$_}) { next }; #skip already offlined nodes
+ my $cand = $_;
+ if ($_ eq $currhyp) { next; } #skip current node
+ if ($offlinehyps{$_}) { next }; #skip already offlined nodes
if (grep { "$_" eq $cand } @destblacklist) { next; } #skip blacklisted destinations
if ($addmemory and defined $hypstats{$_}->{freememory}) { #only used cache results when addmemory suggests caching can make sense
- $currentfreememory=$hypstats{$_}->{freememory}
+ $currentfreememory = $hypstats{$_}->{freememory}
} else {
- if (not nodesockopen($_,22)) { $offlinehyps{$_}=1; next; } #skip unusable destinations
- eval { #Sys::Virt has bugs that cause it to die out in weird ways some times, contain it here
- $targconn = Sys::Virt->new(uri=>"qemu+ssh://root@".$_."/system?no_tty=1&netcat=nc");
+ if (not nodesockopen($_, 22)) { $offlinehyps{$_} = 1; next; } #skip unusable destinations
+ eval { #Sys::Virt has bugs that cause it to die out in weird ways some times, contain it here
+ $targconn = Sys::Virt->new(uri => "qemu+ssh://root@" . $_ . "/system?no_tty=1&netcat=nc");
+ };
+ unless ($targconn) {
+ eval { #Sys::Virt has bugs that cause it to die out in weird ways some times, contain it here
+ $targconn = Sys::Virt->new(uri => "qemu+ssh://root@" . $_ . "/system?no_tty=1");
};
- unless ($targconn) {
- eval { #Sys::Virt has bugs that cause it to die out in weird ways some times, contain it here
- $targconn = Sys::Virt->new(uri=>"qemu+ssh://root@".$_."/system?no_tty=1");
- };
- }
- unless ($targconn) { next; } #skip unreachable destinations
- $currentfreememory=$targconn->get_node_info()->{memory};
+ }
+ unless ($targconn) { next; } #skip unreachable destinations
+ $currentfreememory = $targconn->get_node_info()->{memory};
foreach ($targconn->list_domains()) {
if ($_->get_name() eq 'Domain-0') { next; } #Dom0 memory usage is elastic, we are interested in HVM DomU memory, which is inelastic
-
+
$currentfreememory -= $_->get_info()->{memory};
}
- $hypstats{$cand}->{freememory}=$currentfreememory;
+ $hypstats{$cand}->{freememory} = $currentfreememory;
}
if ($addmemory and $addmemory->{$_}) {
$currentfreememory -= $addmemory->{$_};
}
- if (not defined ($mostfreememory)) {
- $mostfreememory=$currentfreememory;
- $target=$_;
+ if (not defined($mostfreememory)) {
+ $mostfreememory = $currentfreememory;
+ $target = $_;
} elsif ($currentfreememory > $mostfreememory) {
- $mostfreememory=$currentfreememory;
- $target=$_;
+ $mostfreememory = $currentfreememory;
+ $target = $_;
}
}
return $target;
@@ -1000,15 +1039,16 @@ sub pick_target {
sub migrate {
$node = shift();
- my @args=@_;
+ my @args = @_;
my $targ;
foreach (@args) {
- if (/^-/) { next; }
- $targ = $_;
+ if (/^-/) { next; }
+ $targ = $_;
}
if ($offlinevms{$node}) {
return power("on");
}
+
#TODO: currently, we completely serialize migration events. Some IO fabrics can facilitate concurrent migrations
#One trivial example is an ethernet port aggregation where a single conversation may likely be unable to utilize all the links
#because traffic is balanced by a mac address hashing algorithim, but talking to several hypervisors would have
@@ -1022,135 +1062,142 @@ sub migrate {
$targ = pick_target($node);
}
unless ($targ) {
- return (1,"Unable to identify a suitable target host for guest $node");
+ return (1, "Unable to identify a suitable target host for guest $node");
}
if ($use_xhrm) {
- xhrm_satisfy($node,$targ);
+ xhrm_satisfy($node, $targ);
}
my $prevhyp;
- my $target = "qemu+ssh://root@".$targ."/system?no_tty=1";
- my $currhyp="qemu+ssh://root@";
+ my $target = "qemu+ssh://root@" . $targ . "/system?no_tty=1";
+ my $currhyp = "qemu+ssh://root@";
if ($confdata->{vm}->{$node}->[0]->{host}) {
- $prevhyp=$confdata->{vm}->{$node}->[0]->{host};
- $currhyp.=$prevhyp;
+ $prevhyp = $confdata->{vm}->{$node}->[0]->{host};
+ $currhyp .= $prevhyp;
} else {
- return (1,"Unable to find current location of $node");
+ return (1, "Unable to find current location of $node");
}
- $currhyp.="/system?no_tty=1";
+ $currhyp .= "/system?no_tty=1";
if ($currhyp eq $target) {
- return (0,"Guest is already on host $targ");
+ return (0, "Guest is already on host $targ");
}
my $srchypconn;
my $desthypconn;
- unless ($offlinehyps{$prevhyp} or nodesockopen($prevhyp,22)) {
- $offlinehyps{$prevhyp}=1;
+ unless ($offlinehyps{$prevhyp} or nodesockopen($prevhyp, 22)) {
+ $offlinehyps{$prevhyp} = 1;
}
- my $srcnetcatadd="&netcat=nc";
+ my $srcnetcatadd = "&netcat=nc";
unless ($offlinehyps{$prevhyp}) {
- eval {#Contain Sys::Virt bugs
- $srchypconn= Sys::Virt->new(uri=>"qemu+ssh://root@".$prevhyp."/system?no_tty=1$srcnetcatadd");
+ eval { #Contain Sys::Virt bugs
+ $srchypconn = Sys::Virt->new(uri => "qemu+ssh://root@" . $prevhyp . "/system?no_tty=1$srcnetcatadd");
};
unless ($srchypconn) {
- $srcnetcatadd="";
- eval {#Contain Sys::Virt bugs
- $srchypconn= Sys::Virt->new(uri=>"qemu+ssh://root@".$prevhyp."/system?no_tty=1");
+ $srcnetcatadd = "";
+ eval { #Contain Sys::Virt bugs
+ $srchypconn = Sys::Virt->new(uri => "qemu+ssh://root@" . $prevhyp . "/system?no_tty=1");
};
}
}
unless ($srchypconn) {
if (grep { $_ eq '-f' } @args) {
- unless ($vmtab) { $vmtab = new xCAT::Table('vm',-create=>1); }
- $vmtab->setNodeAttribs($node,{host=>$targ});
- return (0,"migrated to $targ");
+ unless ($vmtab) { $vmtab = new xCAT::Table('vm', -create => 1); }
+ $vmtab->setNodeAttribs($node, { host => $targ });
+ return (0, "migrated to $targ");
} else {
- return (1,"Unable to reach $prevhyp to perform operation of $node, use nodech to change vm.host if certain of no split-brain possibility exists (or use -f on rmigrate)");
- }
+ return (1, "Unable to reach $prevhyp to perform operation of $node, use nodech to change vm.host if certain of no split-brain possibility exists (or use -f on rmigrate)");
+ }
}
- unless ($offlinehyps{$targ} or nodesockopen($targ,22)) {
- $offlinehyps{$targ}=1;
+ unless ($offlinehyps{$targ} or nodesockopen($targ, 22)) {
+ $offlinehyps{$targ} = 1;
}
- my $destnetcatadd="&netcat=nc";
+ my $destnetcatadd = "&netcat=nc";
unless ($offlinehyps{$targ}) {
- eval {#Contain Sys::Virt bugs
- $desthypconn= Sys::Virt->new(uri=>$target.$destnetcatadd);
+ eval { #Contain Sys::Virt bugs
+ $desthypconn = Sys::Virt->new(uri => $target . $destnetcatadd);
};
unless ($desthypconn) {
- $destnetcatadd="";
- eval {#Contain Sys::Virt bugs
- $desthypconn= Sys::Virt->new(uri=>$target);
+ $destnetcatadd = "";
+ eval { #Contain Sys::Virt bugs
+ $desthypconn = Sys::Virt->new(uri => $target);
};
}
}
unless ($desthypconn) {
- return (1,"Unable to reach $targ to perform operation of $node, destination unusable.");
+ return (1, "Unable to reach $targ to perform operation of $node, destination unusable.");
}
if (defined $confdata->{vm}->{$node}->[0]->{storage} and $confdata->{vm}->{$node}->[0]->{storage} =~ /^nfs:/) {
+
#first, assure master is in place
if ($confdata->{vm}->{$node}->[0]->{master}) {
- my $vmmastertab=xCAT::Table->new('vmmaster',-create=>0);
+ my $vmmastertab = xCAT::Table->new('vmmaster', -create => 0);
my $masterent;
if ($vmmastertab) {
- $masterent=$vmmastertab->getAttribs({name=>$confdata->{vm}->{$node}->[0]->{master}},['storage']);
+ $masterent = $vmmastertab->getAttribs({ name => $confdata->{vm}->{$node}->[0]->{master} }, ['storage']);
}
if ($masterent and $masterent->{storage}) {
- foreach (split /,/,$masterent->{storage}) {
- s/=.*//;
- get_storage_pool_by_url($_,$desthypconn,$targ);
- }
+ foreach (split /,/, $masterent->{storage}) {
+ s/=.*//;
+ get_storage_pool_by_url($_, $desthypconn, $targ);
+ }
}
}
- my $urls = $confdata->{vm}->{$node}->[0]->{storage} and $confdata->{vm}->{$node}->[0]->{storage};
- foreach (split /,/,$urls) {
+ my $urls = $confdata->{vm}->{$node}->[0]->{storage} and $confdata->{vm}->{$node}->[0]->{storage};
+ foreach (split /,/, $urls) {
s/=.*//;
- get_storage_pool_by_url($_,$desthypconn,$targ);
+ get_storage_pool_by_url($_, $desthypconn, $targ);
}
}
- my $sock = IO::Socket::INET->new(Proto=>'udp');
- my $ipa=inet_aton($node);
+ my $sock = IO::Socket::INET->new(Proto => 'udp');
+ my $ipa = inet_aton($node);
my $pa;
if ($ipa) {
- $pa=sockaddr_in(7,$ipa); #UDP echo service, not needed to be actually
+ $pa = sockaddr_in(7, $ipa); #UDP echo service, not needed to be actually
}
+
#serviced, we just want to trigger MAC move in the switch forwarding dbs
my $nomadomain;
- eval {
+ eval {
$nomadomain = $srchypconn->get_domain_by_name($node);
};
unless ($nomadomain) {
- unless ($vmtab) { $vmtab = new xCAT::Table('vm',-create=>1); }
- $vmtab->setNodeAttribs($node,{host=>$targ});
- return (0,"migrated to $targ");
- #return (1,"Unable to find $node on $prevhyp, vm.host may be incorrect or a split-brain condition, such as libvirt forgetting a guest due to restart or bug.");
-
+ unless ($vmtab) { $vmtab = new xCAT::Table('vm', -create => 1); }
+ $vmtab->setNodeAttribs($node, { host => $targ });
+ return (0, "migrated to $targ");
+
+#return (1,"Unable to find $node on $prevhyp, vm.host may be incorrect or a split-brain condition, such as libvirt forgetting a guest due to restart or bug.");
+
}
my $newdom;
my $errstr;
eval {
- $newdom=$nomadomain->migrate($desthypconn,&Sys::Virt::Domain::MIGRATE_LIVE,undef,undef,0);
+ $newdom = $nomadomain->migrate($desthypconn, &Sys::Virt::Domain::MIGRATE_LIVE, undef, undef, 0);
};
if ($@) { $errstr = $@; }
+
#TODO: If it looks like it failed to migrate, ensure the guest exists only in one place
- if ($errstr) {
- return (1,"Failed migration of $node from $prevhyp to $targ: $errstr");
+ if ($errstr) {
+ return (1, "Failed migration of $node from $prevhyp to $targ: $errstr");
}
unless ($newdom) {
- return (1,"Failed migration from $prevhyp to $targ");
+ return (1, "Failed migration from $prevhyp to $targ");
}
if ($ipa) {
- system("arp -d $node"); #Make ethernet fabric take note of change
- send($sock,"dummy",0,$pa); #UDP packet to force forwarding table update in switches, ideally a garp happened, but just in case...
+ system("arp -d $node"); #Make ethernet fabric take note of change
+ send($sock, "dummy", 0, $pa); #UDP packet to force forwarding table update in switches, ideally a garp happened, but just in case...
}
- #BTW, this should all be moot since the underlying kvm seems good about gratuitous traffic, but it shouldn't hurt anything
+
+#BTW, this should all be moot since the underlying kvm seems good about gratuitous traffic, but it shouldn't hurt anything
refresh_vm($newdom);
+
#The migration seems tohave suceeded, but to be sure...
close($sock);
if ($desthypconn->get_domain_by_name($node)) {
+
#$updatetable->{vm}->{$node}->{host} = $targ;
- unless ($vmtab) { $vmtab = new xCAT::Table('vm',-create=>1); }
- $vmtab->setNodeAttribs($node,{host=>$targ});
- return (0,"migrated to $targ");
- } else { #This *should* not be possible
- return (1,"Failed migration from $prevhyp to $targ, despite normal looking run...");
+ unless ($vmtab) { $vmtab = new xCAT::Table('vm', -create => 1); }
+ $vmtab->setNodeAttribs($node, { host => $targ });
+ return (0, "migrated to $targ");
+ } else { #This *should* not be possible
+ return (1, "Failed migration from $prevhyp to $targ, despite normal looking run...");
}
}
@@ -1161,7 +1208,7 @@ sub getpowstate {
if ($dom) {
$vmstat = $dom->get_info;
}
- if ($vmstat and $runningstates{$vmstat->{state}}) {
+ if ($vmstat and $runningstates{ $vmstat->{state} }) {
return "on";
} else {
return "off";
@@ -1169,34 +1216,34 @@ sub getpowstate {
}
sub xhrm_satisfy {
- my $node = shift;
- my $hyp = shift;
- my $rc=0;
- my @nics=();
- my @storage=();
+ my $node = shift;
+ my $hyp = shift;
+ my $rc = 0;
+ my @nics = ();
+ my @storage = ();
if ($confdata->{vm}->{$node}->[0]->{nics}) {
- @nics = split /,/,$confdata->{vm}->{$node}->[0]->{nics};
+ @nics = split /,/, $confdata->{vm}->{$node}->[0]->{nics};
}
-
- $rc |=system("scp $::XCATROOT/share/xcat/scripts/xHRM $hyp:/usr/bin");
+
+ $rc |= system("scp $::XCATROOT/share/xcat/scripts/xHRM $hyp:/usr/bin");
foreach (@nics) {
- s/=.*//; #this code cares not about the model of virtual nic
- my $nic=$_;
+ s/=.*//; #this code cares not about the model of virtual nic
+ my $nic = $_;
my $vlanip;
my $netmask;
my $subnet;
my $vlan;
my $interface;
if ($nic =~ /^vl([\d]+)$/) {
- $vlan=$1;
- my $nwtab=xCAT::Table->new("networks", -create =>0);
+ $vlan = $1;
+ my $nwtab = xCAT::Table->new("networks", -create => 0);
if ($nwtab) {
- my $sent = $nwtab->getAttribs({vlanid=>"$vlan"},'net','mask');
+ my $sent = $nwtab->getAttribs({ vlanid => "$vlan" }, 'net', 'mask');
if ($sent and ($sent->{net})) {
- $subnet=$sent->{net};
- $netmask=$sent->{mask};
- }
+ $subnet = $sent->{net};
+ $netmask = $sent->{mask};
+ }
if (($subnet) && ($netmask)) {
my $hoststab = xCAT::Table->new("hosts", -create => 0);
if ($hoststab) {
@@ -1204,22 +1251,23 @@ sub xhrm_satisfy {
if (defined($tmp) && ($tmp) && $tmp->{otherinterfaces})
{
my $otherinterfaces = $tmp->{otherinterfaces};
- my @itf_pairs=split(/,/, $otherinterfaces);
+ my @itf_pairs = split(/,/, $otherinterfaces);
foreach (@itf_pairs) {
- my ($name,$vip)=split(/:/, $_);
- if(xCAT::NetworkUtils->ishostinsubnet($vip, $netmask, $subnet)) {
- $vlanip=$vip;
+ my ($name, $vip) = split(/:/, $_);
+ if (xCAT::NetworkUtils->ishostinsubnet($vip, $netmask, $subnet)) {
+ $vlanip = $vip;
last;
}
}
}
}
+
#get the vlan ip from nics table
unless ($vlanip) {
my $nicstable = xCAT::Table->new("nics", -create => 0);
if ($nicstable) {
my $tmp = $nicstable->getNodeAttribs($hyp, ['nicips']);
- if ($tmp && $tmp->{nicips}){
+ if ($tmp && $tmp->{nicips}) {
$tmp =~ /vl${vlan}nic!([^,]*)/;
$vlanip = $1;
}
@@ -1229,129 +1277,134 @@ sub xhrm_satisfy {
}
}
- #get the nic that vlan tagged
+ #get the nic that vlan tagged
my $swtab = xCAT::Table->new("switch", -create => 0);
if ($swtab) {
- my $tmp_switch = $swtab->getNodesAttribs([$hyp], ['vlan','interface']);
- if (defined($tmp_switch) && (exists($tmp_switch->{$hyp}))) {
- my $tmp_node_array=$tmp_switch->{$hyp};
+ my $tmp_switch = $swtab->getNodesAttribs([$hyp], [ 'vlan', 'interface' ]);
+ if (defined($tmp_switch) && (exists($tmp_switch->{$hyp}))) {
+ my $tmp_node_array = $tmp_switch->{$hyp};
foreach my $tmp (@$tmp_node_array) {
if (exists($tmp->{vlan})) {
my $vlans = $tmp->{vlan};
- foreach my $vlan_tmp (split(',',$vlans)) {
+ foreach my $vlan_tmp (split(',', $vlans)) {
if ($vlan_tmp == $vlan) {
if (exists($tmp->{interface})) {
- $interface=$tmp->{interface};
+ $interface = $tmp->{interface};
}
- last;
+ last;
}
}
}
}
}
}
-
+
if (($interface) || ($interface =~ /primary/)) {
$interface =~ s/primary(:)?//g;
}
- #print "interface=$interface nic=$nic vlanip=$vlanip netmask=$netmask\n";
+
+ #print "interface=$interface nic=$nic vlanip=$vlanip netmask=$netmask\n";
if ($interface) {
- $rc |=system("ssh $hyp xHRM bridgeprereq $interface:$nic $vlanip $netmask");
+ $rc |= system("ssh $hyp xHRM bridgeprereq $interface:$nic $vlanip $netmask");
} else {
- $rc |=system("ssh $hyp xHRM bridgeprereq $nic $vlanip $netmask");
+ $rc |= system("ssh $hyp xHRM bridgeprereq $nic $vlanip $netmask");
}
- #TODO: surprise! there is relatively undocumented libvirt capability for this...
- #./tests/interfaceschemadata/ will have to do in lieu of documentation..
- #note that RHEL6 is where that party starts
- #of course, they don't have a clean 'migrate from normal interface to bridge' capability
- #consequently, would have to have some init script at least pre-bridge it up..
- #even then, may not be able to intelligently modify the bridge remotely, so may still not be feasible for our use..
- #this is sufficiently hard, punting to 2.6 at least..
+#TODO: surprise! there is relatively undocumented libvirt capability for this...
+#./tests/interfaceschemadata/ will have to do in lieu of documentation..
+#note that RHEL6 is where that party starts
+#of course, they don't have a clean 'migrate from normal interface to bridge' capability
+#consequently, would have to have some init script at least pre-bridge it up..
+#even then, may not be able to intelligently modify the bridge remotely, so may still not be feasible for our use..
+#this is sufficiently hard, punting to 2.6 at least..
}
return $rc;
}
+
sub makedom {
- my $node=shift;
+ my $node = shift;
my $cdloc = shift;
- my $xml = shift;
+ my $xml = shift;
my $dom;
if (not $xml and $confdata->{kvmnodedata}->{$node} and $confdata->{kvmnodedata}->{$node}->[0] and $confdata->{kvmnodedata}->{$node}->[0]->{xml}) {
+
#we do this to trigger storage prereq fixup
if (defined $confdata->{vm}->{$node}->[0]->{storage} and ($confdata->{vm}->{$node}->[0]->{storage} =~ /^nfs:/ or $confdata->{vm}->{$node}->[0]->{storage} =~ /^dir:/ or $confdata->{vm}->{$node}->[0]->{storage} =~ /^lvm:/)) {
if ($confdata->{vm}->{$node}->[0]->{master}) {
- my $vmmastertab=xCAT::Table->new('vmmaster',-create=>0);
+ my $vmmastertab = xCAT::Table->new('vmmaster', -create => 0);
my $masterent;
if ($vmmastertab) {
- $masterent=$vmmastertab->getAttribs({name=>$confdata->{vm}->{$node}->[0]->{master}},['storage']);
+ $masterent = $vmmastertab->getAttribs({ name => $confdata->{vm}->{$node}->[0]->{master} }, ['storage']);
}
if ($masterent and $masterent->{storage}) {
- foreach (split /,/,$masterent->{storage}) {
- s/=.*//;
- get_storage_pool_by_url($_);
- }
+ foreach (split /,/, $masterent->{storage}) {
+ s/=.*//;
+ get_storage_pool_by_url($_);
+ }
}
}
- my $urls = $confdata->{vm}->{$node}->[0]->{storage} and $confdata->{vm}->{$node}->[0]->{storage};
- foreach (split /,/,$urls) {
+ my $urls = $confdata->{vm}->{$node}->[0]->{storage} and $confdata->{vm}->{$node}->[0]->{storage};
+ foreach (split /,/, $urls) {
s/=.*//;
get_storage_pool_by_url($_);
}
}
$xml = $confdata->{kvmnodedata}->{$node}->[0]->{xml};
- my $newxml = reconfigvm($node,$xml);
+ my $newxml = reconfigvm($node, $xml);
if ($newxml) {
- $xml=$newxml;
+ $xml = $newxml;
}
} elsif (not $xml) {
- $xml = build_xmldesc($node,cd=>$cdloc);
+ $xml = build_xmldesc($node, cd => $cdloc);
}
my $parseddom = $parser->parse_string($xml);
my ($graphics) = $parseddom->findnodes("//graphics");
if ($confdata->{vm}->{$node}->[0]->{vidpassword}) {
- $graphics->setAttribute("passwd",$confdata->{vm}->{$node}->[0]->{vidpassword});
+ $graphics->setAttribute("passwd", $confdata->{vm}->{$node}->[0]->{vidpassword});
} else {
- $graphics->setAttribute("passwd",genpassword(20));
+ $graphics->setAttribute("passwd", genpassword(20));
}
- $graphics->setAttribute("listen",'0.0.0.0');
+ $graphics->setAttribute("listen", '0.0.0.0');
$xml = $parseddom->toString();
my $errstr;
- eval {
- if ($::XCATSITEVALS{persistkvmguests}) {
- $dom=$hypconn->define_domain($xml);
- $dom->create()
- } else {
- $dom=$hypconn->create_domain($xml);
- }
+ eval {
+ if ($::XCATSITEVALS{persistkvmguests}) {
+ $dom = $hypconn->define_domain($xml);
+ $dom->create()
+ } else {
+ $dom = $hypconn->create_domain($xml);
+ }
};
if ($@) { $errstr = $@; }
if (ref $errstr) {
- $errstr = ":".$errstr->{message};
+ $errstr = ":" . $errstr->{message};
}
- if ($errstr) { return (undef,$errstr); }
+ if ($errstr) { return (undef, $errstr); }
if ($dom) {
- refresh_vm($dom);
+ refresh_vm($dom);
}
- return $dom,undef;
+ return $dom, undef;
}
sub createstorage {
-#svn rev 6638 held the older vintage of createstorage
+
+ #svn rev 6638 held the older vintage of createstorage
#print "createstorage called\n";
- my $filename=shift;
- my $mastername=shift;
- my $size=shift;
- my $cfginfo = shift;
- my $force = shift;
+ my $filename = shift;
+ my $mastername = shift;
+ my $size = shift;
+ my $cfginfo = shift;
+ my $force = shift;
+
#my $diskstruct = shift;
my $node = $cfginfo->{node};
- my @flags = split /,/,$cfginfo->{virtflags};
+ my @flags = split /,/, $cfginfo->{virtflags};
my $format;
foreach (@flags) {
if (/^imageformat=(.*)\z/) {
- $format=$1;
+ $format = $1;
} elsif (/^clonemethod=(.*)\z/) {
- $clonemethod=$1;
+ $clonemethod = $1;
}
}
if ($cfginfo->{storageformat}) {
@@ -1365,127 +1418,130 @@ sub createstorage {
my $basename;
my $dirname;
if ($mastername and $size) {
- return 1,"Can not specify both a master to clone and size(s)";
+ return 1, "Can not specify both a master to clone and size(s)";
}
- $filename=~s/=(.*)//;
- my $model=$1;
+ $filename =~ s/=(.*)//;
+ my $model = $1;
unless ($model) {
+
#if not defined, model will stay undefined like above
$model = $cfginfo->{storagemodel};
}
- my $prefix='hd';
+ my $prefix = 'hd';
if ($model eq 'scsi') {
- $prefix='sd';
+ $prefix = 'sd';
} elsif ($model eq 'virtio') {
- $prefix='vd';
+ $prefix = 'vd';
}
- my @suffixes=('a','b','d'..'zzz');
+ my @suffixes = ('a', 'b', 'd' .. 'zzz');
if ($filename =~ /^nfs:/ or $filename =~ /^dir:/ or $filename =~ /^lvm:/) { #libvirt storage pool to be used for this
- my @sizes = split /,/,$size;
+ my @sizes = split /,/, $size;
foreach (@sizes) {
- get_filepath_by_url(url=>$filename,dev=>$prefix.shift(@suffixes),create=>$_, force=>$force, format=>$format);
+ get_filepath_by_url(url => $filename, dev => $prefix . shift(@suffixes), create => $_, force => $force, format => $format);
}
- }else{
+ } else {
oldCreateStorage($filename, $mastername, $size, $cfginfo, $force);
- }
- my $masterserver;
- if ($mastername) { #cloning
}
- if ($size) {#new volume
+ my $masterserver;
+ if ($mastername) { #cloning
+ }
+ if ($size) { #new volume
}
}
sub oldCreateStorage {
- my $filename=shift;
- my $mastername=shift;
- my $size=shift;
- my $cfginfo = shift;
- my $force = shift;
- my $node = $cfginfo->{node};
- my @flags = split /,/,$cfginfo->{virtflags};
+ my $filename = shift;
+ my $mastername = shift;
+ my $size = shift;
+ my $cfginfo = shift;
+ my $force = shift;
+ my $node = $cfginfo->{node};
+ my @flags = split /,/, $cfginfo->{virtflags};
foreach (@flags) {
+
if (/^imageformat=(.*)\z/) {
- $imgfmt=$1;
+ $imgfmt = $1;
} elsif (/^clonemethod=(.*)\z/) {
- $clonemethod=$1;
+ $clonemethod = $1;
}
}
my $mountpath;
my $pathappend;
my $storageserver;
+
#for nfs paths and qemu-img, we do the magic locally only for now
my $basename;
my $dirname;
- ($basename,$dirname) = fileparse($filename);
+ ($basename, $dirname) = fileparse($filename);
unless ($storageserver) {
if (-f $filename) {
unless ($force) {
- return 1,"Storage already exists, delete manually or use --force";
+ return 1, "Storage already exists, delete manually or use --force";
}
unlink $filename;
}
}
if ($storageserver and $mastername and $clonemethod eq 'reflink') {
- my $rc=system("ssh $storageserver mkdir -p $dirname");
+ my $rc = system("ssh $storageserver mkdir -p $dirname");
if ($rc) {
- return 1,"Unable to manage storage on remote server $storageserver";
+ return 1, "Unable to manage storage on remote server $storageserver";
}
} elsif ($storageserver) {
my @mounts = `mount`;
my $foundmount;
foreach (@mounts) {
- if (/^$storageserver:$mountpath/) {
- chomp;
- s/^.* on (\S*) type nfs.*$/$1/;
- $dirname = $_;
- mkpath($dirname.$pathappend);
- $foundmount=1;
- last;
- }
+ if (/^$storageserver:$mountpath/) {
+ chomp;
+ s/^.* on (\S*) type nfs.*$/$1/;
+ $dirname = $_;
+ mkpath($dirname . $pathappend);
+ $foundmount = 1;
+ last;
+ }
}
unless ($foundmount) {
- return 1,"qemu-img cloning requires that the management server have the directory $mountpath from $storageserver mounted";
+ return 1, "qemu-img cloning requires that the management server have the directory $mountpath from $storageserver mounted";
}
} else {
mkpath($dirname);
}
if ($mastername and $size) {
- return 1,"Can not specify both a master to clone and a size";
+ return 1, "Can not specify both a master to clone and a size";
}
my $masterserver;
if ($mastername) {
unless ($mastername =~ /^\// or $mastername =~ /^nfs:/) {
- $mastername = $xCAT_plugin::kvm::masterdir.'/'.$mastername;
+ $mastername = $xCAT_plugin::kvm::masterdir . '/' . $mastername;
}
if ($mastername =~ m!nfs://([^/]*)(/.*\z)!) {
- $mastername = $2;
+ $mastername = $2;
$masterserver = $1;
}
if ($masterserver ne $storageserver) {
- return 1,"Not supporting cloning between $masterserver and $storageserver at this time, for now ensure master images and target VM images are on the same server";
+ return 1, "Not supporting cloning between $masterserver and $storageserver at this time, for now ensure master images and target VM images are on the same server";
}
my $rc;
if ($clonemethod eq 'qemu-img') {
my $dirn;
my $filn;
- ($filn,$dirn) = fileparse($filename);
+ ($filn, $dirn) = fileparse($filename);
chdir($dirn);
- $rc=system("qemu-img create -f qcow2 -b $mastername $filename");
+ $rc = system("qemu-img create -f qcow2 -b $mastername $filename");
} elsif ($clonemethod eq 'reflink') {
if ($storageserver) {
- $rc=system("ssh $storageserver cp --reflink $mastername $filename");
+ $rc = system("ssh $storageserver cp --reflink $mastername $filename");
} else {
- $rc=system("cp --reflink $mastername $filename");
+ $rc = system("cp --reflink $mastername $filename");
}
}
if ($rc) {
- return $rc,"Failure creating image $filename from $mastername";
+ return $rc, "Failure creating image $filename from $mastername";
}
}
if ($size) {
- my $rc = system("qemu-img create -f $imgfmt $filename ".getUnits($size,"g",1024));
+ my $rc = system("qemu-img create -f $imgfmt $filename " . getUnits($size, "g", 1024));
if ($rc) {
- return $rc,"Failure creating image $filename of size $size\n";
+ return $rc, "Failure creating image $filename of size $size\n";
}
}
}
@@ -1494,56 +1550,60 @@ sub rinv {
shift;
my $dom;
eval {
- $dom = $hypconn->get_domain_by_name($node);
+ $dom = $hypconn->get_domain_by_name($node);
};
- my $currstate=getpowstate($dom);
+ my $currstate = getpowstate($dom);
my $currxml;
if ($currstate eq 'on') {
- $currxml=$dom->get_xml_description();
+ $currxml = $dom->get_xml_description();
} else {
- $currxml =$confdata->{kvmnodedata}->{$node}->[0]->{xml};
+ $currxml = $confdata->{kvmnodedata}->{$node}->[0]->{xml};
}
unless ($currxml) {
- xCAT::SvrUtils::sendmsg([1,"VM does not appear to exist"], $callback,$node);
+ xCAT::SvrUtils::sendmsg([ 1, "VM does not appear to exist" ], $callback, $node);
return;
}
- my $domain=$parser->parse_string($currxml);
- my $uuid = $domain->findnodes('/domain/uuid')->[0]->to_literal;
+ my $domain = $parser->parse_string($currxml);
+ my $uuid = $domain->findnodes('/domain/uuid')->[0]->to_literal;
$uuid =~ s/^(..)(..)(..)(..)-(..)(..)-(..)(..)/$4$3$2$1-$6$5-$8$7/;
- xCAT::SvrUtils::sendmsg("UUID/GUID: $uuid", $callback,$node);
+ xCAT::SvrUtils::sendmsg("UUID/GUID: $uuid", $callback, $node);
my $cpus = $domain->findnodes('/domain/vcpu')->[0]->to_literal;
- xCAT::SvrUtils::sendmsg("CPUs: $cpus", $callback,$node);
- my $memnode = $domain->findnodes('/domain/currentMemory')->[0];
+ xCAT::SvrUtils::sendmsg("CPUs: $cpus", $callback, $node);
+ my $memnode = $domain->findnodes('/domain/currentMemory')->[0];
my $maxmemnode = $domain->findnodes('/domain/memory')->[0];
+
unless ($memnode) {
$memnode = $maxmemnode;
}
if ($memnode) {
my $mem = $memnode->to_literal;
- $mem=$mem/1024;
- xCAT::SvrUtils::sendmsg("Memory: $mem MB", $callback,$node);
+ $mem = $mem / 1024;
+ xCAT::SvrUtils::sendmsg("Memory: $mem MB", $callback, $node);
}
if ($maxmemnode) {
- my $maxmem = $maxmemnode->to_literal;
- $maxmem=$maxmem/1024;
- xCAT::SvrUtils::sendmsg("Maximum Memory: $maxmem MB", $callback,$node);
-
+ my $maxmem = $maxmemnode->to_literal;
+ $maxmem = $maxmem / 1024;
+ xCAT::SvrUtils::sendmsg("Maximum Memory: $maxmem MB", $callback, $node);
+
}
invstorage($domain, $dom);
invnics($domain);
}
+
sub get_storage_pool_by_volume {
- my $vol = shift;
- my $path=$vol->get_path();
+ my $vol = shift;
+ my $path = $vol->get_path();
return get_storage_pool_by_path($path);
}
+
sub get_storage_pool_by_path {
-#attempts to get pool for a volume, returns false on failure
+
+ #attempts to get pool for a volume, returns false on failure
my $file = shift;
my $pool;
return eval {
my @currpools = $hypconn->list_storage_pools();
- push @currpools,$hypconn->list_defined_storage_pools();
+ push @currpools, $hypconn->list_defined_storage_pools();
foreach $pool (@currpools) {
my $parsedpool = $parser->parse_string($pool->get_xml_description());
my $currpath = $parsedpool->findnodes("/pool/target/path/text()")->[0]->data;
@@ -1552,83 +1612,86 @@ sub get_storage_pool_by_path {
}
}
return undef;
+
# $pool = $hypconn->get_storage_pool_by_uuid($pooluuid);
};
}
sub invstorage {
- my $domain = shift; # the dom obj of XML
- my $dom = shift; # the real domain obj
+ my $domain = shift; # the dom obj of XML
+ my $dom = shift; # the real domain obj
my @disks = $domain->findnodes('/domain/devices/disk');
my $disk;
foreach $disk (@disks) {
my $name = $disk->findnodes('./target')->[0]->getAttribute("dev");
my $xref = "";
- my $addr = $disk->findnodes('./address')->[0];
+ my $addr = $disk->findnodes('./address')->[0];
if ($addr) {
if ($name =~ /^vd/) {
- $xref = " (v".$addr->getAttribute("bus").":".$addr->getAttribute('slot').".".$addr->getAttribute("function").")";
+ $xref = " (v" . $addr->getAttribute("bus") . ":" . $addr->getAttribute('slot') . "." . $addr->getAttribute("function") . ")";
$xref =~ s/0x//g;
} else {
- $xref = " (d".$addr->getAttribute("controller").":".$addr->getAttribute("bus").":".$addr->getAttribute("unit").")";
+ $xref = " (d" . $addr->getAttribute("controller") . ":" . $addr->getAttribute("bus") . ":" . $addr->getAttribute("unit") . ")";
}
}
- my @candidatenodes = $disk->findnodes('./source');
- unless (scalar @candidatenodes) {
- next;
- }
+ my @candidatenodes = $disk->findnodes('./source');
+ unless (scalar @candidatenodes) {
+ next;
+ }
my $file = $candidatenodes[0]->getAttribute('file');
- my $dev = $candidatenodes[0]->getAttribute('dev');
+ my $dev = $candidatenodes[0]->getAttribute('dev');
my $vollocation;
my $size;
my %info;
- if ($file) { # for the volumn is a file in storage poll
- #we'll attempt to map file path to pool name and volume name
- #fallback to just reporting filename if not feasible
- #libvirt lacks a way to lookup a storage pool by path, so we'll only do so if using the 'default' xCAT scheme with uuid in the path
+ if ($file) { # for the volumn is a file in storage poll
+ #we'll attempt to map file path to pool name and volume name
+ #fallback to just reporting filename if not feasible
+ #libvirt lacks a way to lookup a storage pool by path, so we'll only do so if using the 'default' xCAT scheme with uuid in the path
$file =~ m!/([^/]*)/($node\..*)\z!;
- my $volname=$2;
- $vollocation=$file;
+ my $volname = $2;
+ $vollocation = $file;
eval {
- my $pool = get_storage_pool_by_path($file);
+ my $pool = get_storage_pool_by_path($file);
my $poolname = $pool->get_name();
$vollocation = "[$poolname] $volname";
};
+
#at least I get to skip the whole pool mess here
my $vol = $hypconn->get_storage_volume_by_path($file);
if ($vol) {
- %info = %{$vol->get_info()};
+ %info = %{ $vol->get_info() };
}
- } elsif ($dev) { # for the volumn is a block device
+ } elsif ($dev) { # for the volumn is a block device
$vollocation = $dev;
- %info = %{$dom->get_block_info($dev)};
+ %info = %{ $dom->get_block_info($dev) };
}
-
+
if ($info{allocation} and $info{capacity}) {
$size = $info{allocation};
- $size = $size/1048576; #convert to MB
- $size = sprintf("%.3f",$size);
- $size .= "/".($info{capacity}/1048576);
+ $size = $size / 1048576; #convert to MB
+ $size = sprintf("%.3f", $size);
+ $size .= "/" . ($info{capacity} / 1048576);
}
-
+
$callback->({
- node=>{
- name=>$node,
- data=>{
- desc=>"Disk $name$xref",
- contents=>"$size MB @ $vollocation",
- }
- }
+ node => {
+ name => $node,
+ data => {
+ desc => "Disk $name$xref",
+ contents => "$size MB @ $vollocation",
+ }
+ }
});
}
}
+
sub invnics {
- my $domain=shift;
- my @nics = $domain->findnodes('/domain/devices/interface');
+ my $domain = shift;
+ my @nics = $domain->findnodes('/domain/devices/interface');
my $nic;
foreach $nic (@nics) {
- my $mac = $nic->findnodes('./mac')->[0]->getAttribute('address');
+ my $mac = $nic->findnodes('./mac')->[0]->getAttribute('address');
my $addr = $nic->findnodes('./address')->[0];
my $loc;
if ($addr) {
@@ -1638,22 +1701,23 @@ sub invnics {
$slot =~ s/^0x//;
my $function = $addr->getAttribute('function');
$function =~ s/^0x//;
- $loc=" at $bus:$slot.$function";
+ $loc = " at $bus:$slot.$function";
}
$callback->({
- node=>{
- name=>$node,
- data=>{
- desc=>"Network adapter$loc",
- contents=>$mac,
- }
- }
+ node => {
+ name => $node,
+ data => {
+ desc => "Network adapter$loc",
+ contents => $mac,
+ }
+ }
});
}
}
+
sub rmvm {
shift;
- @ARGV=@_;
+ @ARGV = @_;
my $force;
my $purge;
GetOptions(
@@ -1662,42 +1726,43 @@ sub rmvm {
);
my $dom;
eval {
- $dom = $hypconn->get_domain_by_name($node);
+ $dom = $hypconn->get_domain_by_name($node);
};
- my $currstate=getpowstate($dom);
+ my $currstate = getpowstate($dom);
my $currxml;
if ($currstate eq 'on') {
if ($force) {
- $currxml=$dom->get_xml_description();
+ $currxml = $dom->get_xml_description();
$dom->destroy();
} else {
- xCAT::SvrUtils::sendmsg([1,"Cannot rmvm active guest (use -f argument to force)"], $callback,$node);
+ xCAT::SvrUtils::sendmsg([ 1, "Cannot rmvm active guest (use -f argument to force)" ], $callback, $node);
return;
}
} else {
- $currxml =$confdata->{kvmnodedata}->{$node}->[0]->{xml};
+ $currxml = $confdata->{kvmnodedata}->{$node}->[0]->{xml};
}
if ($purge and $currxml) {
- my $deadman = $parser->parse_string($currxml);
+ my $deadman = $parser->parse_string($currxml);
my @purgedisks = $deadman->findnodes("/domain/devices/disk/source");
my $disk;
foreach $disk (@purgedisks) {
- my $disktype = $disk->parentNode()->getAttribute("device");
- if ($disktype eq "cdrom") { next; }
+ my $disktype = $disk->parentNode()->getAttribute("device");
+ if ($disktype eq "cdrom") { next; }
my $file = $disk->getAttribute("file");
- my $vol = $hypconn->get_storage_volume_by_path($file);
+ my $vol = $hypconn->get_storage_volume_by_path($file);
if ($vol) {
$vol->delete();
}
}
}
eval { #try to fetch the domain by name even after it has been destroyed, if it is still there it needs an 'undefine'
- $dom = $hypconn->get_domain_by_name($node);
- $dom->undefine();
+ $dom = $hypconn->get_domain_by_name($node);
+ $dom->undefine();
};
-
- $updatetable->{kvm_nodedata}->{'!*XCATNODESTODELETE*!'}->{$node}=1;
+
+ $updatetable->{kvm_nodedata}->{'!*XCATNODESTODELETE*!'}->{$node} = 1;
}
+
sub chvm {
shift;
my @addsizes;
@@ -1712,54 +1777,55 @@ sub chvm {
my $numanodeset;
my $passthrudevices;
my $devicestodetach;
- @ARGV=@_;
+ @ARGV = @_;
require Getopt::Long;
Getopt::Long::Configure("bundling");
Getopt::Long::Configure("no_pass_through");
+
if (!GetOptions(
- "a=s"=>\@addsizes,
- "d=s"=>\@derefdisks,
- "mem|memory=s"=>\$memory,
- "optical|dvd|cdrom=s"=>\$cdrom,
- "eject"=>\$eject,
- "cpus|cpu=s" => \$cpucount,
- "p=s"=>\@purge,
- "resize=s%" => \%resize,
- "cpupin=s" => \$pcpuset,
- "membind=s" => \$numanodeset,
- "devpassthru=s"=> \$passthrudevices,
- "devdetach=s"=> \$devicestodetach,
- )){
+ "a=s" => \@addsizes,
+ "d=s" => \@derefdisks,
+ "mem|memory=s" => \$memory,
+ "optical|dvd|cdrom=s" => \$cdrom,
+ "eject" => \$eject,
+ "cpus|cpu=s" => \$cpucount,
+ "p=s" => \@purge,
+ "resize=s%" => \%resize,
+ "cpupin=s" => \$pcpuset,
+ "membind=s" => \$numanodeset,
+ "devpassthru=s" => \$passthrudevices,
+ "devdetach=s" => \$devicestodetach,
+ )) {
my $usage_string = xCAT::Usage->getUsage("chvm");
my $rsp;
- push @{$rsp->{data}}, "$usage_string";
+ push @{ $rsp->{data} }, "$usage_string";
xCAT::MsgUtils->message("E", $rsp, $callback);
return;
- };
+ }
if (@derefdisks) {
- xCAT::SvrUtils::sendmsg([1,"Detach without purge TODO for kvm"],$callback,$node);
+ xCAT::SvrUtils::sendmsg([ 1, "Detach without purge TODO for kvm" ], $callback, $node);
return;
}
if (@addsizes and @purge) {
- xCAT::SvrUtils::sendmsg([1,"Currently adding and purging concurrently is not supported"],$callback,$node);
+ xCAT::SvrUtils::sendmsg([ 1, "Currently adding and purging concurrently is not supported" ], $callback, $node);
return;
}
-
- if(defined $pcpuset){
- $pcpuset=~s/["']//g;
- if("###$pcpuset" eq "###" or $pcpuset =~ /[^\d\,\^\-]/ ){
- xCAT::SvrUtils::sendmsg([1,"cpu pining: invalid cpuset"],$callback,$node);
- return;
- }
+
+ if (defined $pcpuset) {
+ $pcpuset =~ s/["']//g;
+ if ("###$pcpuset" eq "###" or $pcpuset =~ /[^\d\,\^\-]/) {
+ xCAT::SvrUtils::sendmsg([ 1, "cpu pining: invalid cpuset" ], $callback, $node);
+ return;
+ }
}
- if(defined $numanodeset){
- $numanodeset=~s/["']//g;
- if("###$numanodeset" eq "###" or $numanodeset =~ /[^\d\,\^\-]/ ){
- xCAT::SvrUtils::sendmsg([1,"memory binding: invalid NUMA nodeset"],$callback,$node);
- return;
- }
+ if (defined $numanodeset) {
+ $numanodeset =~ s/["']//g;
+ if ("###$numanodeset" eq "###" or $numanodeset =~ /[^\d\,\^\-]/) {
+ xCAT::SvrUtils::sendmsg([ 1, "memory binding: invalid NUMA nodeset" ], $callback, $node);
+ return;
+ }
}
my %useddisks;
@@ -1769,119 +1835,124 @@ sub chvm {
};
my $vmxml;
if ($dom) {
- $vmxml=$dom->get_xml_description();
+ $vmxml = $dom->get_xml_description();
} else {
- $vmxml=$confdata->{kvmnodedata}->{$node}->[0]->{xml};
+ $vmxml = $confdata->{kvmnodedata}->{$node}->[0]->{xml};
}
- my $currstate=getpowstate($dom);
+ my $currstate = getpowstate($dom);
if (defined $confdata->{vm}->{$node}->[0]->{storage}) {
my $store;
foreach $store (split /\|/, $confdata->{vm}->{$node}->[0]->{storage}) {
$store =~ s/,.*//;
$store =~ s/=.*//;
if (($store =~ /^nfs:\/\//) || ($store =~ /^dir:\/\//) || ($store =~ /^lvm:/)) {
- my %disks = %{get_multiple_paths_by_url(url=>$store,node=>$node)};
+ my %disks = %{ get_multiple_paths_by_url(url => $store, node => $node) };
foreach (keys %disks) {
- $useddisks{$disks{$_}->{device}}=1;
+ $useddisks{ $disks{$_}->{device} } = 1;
}
}
}
}
- if (@addsizes) { #need to add disks, first identify used devnames
+ if (@addsizes) { #need to add disks, first identify used devnames
my @diskstoadd;
my $location = $confdata->{vm}->{$node}->[0]->{storage};
$location =~ s/.*\|//; #use the rightmost location for making new devices
- $location =~ s/,.*//; #no comma specified parameters are valid
- $location =~ s/=(.*)//; #store model if specified here
+ $location =~ s/,.*//; #no comma specified parameters are valid
+ $location =~ s/=(.*)//; #store model if specified here
my $model = $1;
unless ($model) {
+
#if not defined, model will stay undefined like above
$model = $confdata->{vm}->{$node}->[0]->{storagemodel}
}
- my $prefix='hd';
+ my $prefix = 'hd';
if ($model eq 'scsi') {
- $prefix='sd';
+ $prefix = 'sd';
} elsif ($model eq 'virtio') {
- $prefix='vd';
+ $prefix = 'vd';
}
if ($prefix eq 'hd' and $currstate eq 'on') {
- xCAT::SvrUtils::sendmsg("VM must be powered off to add IDE drives",$callback,$node);
+ xCAT::SvrUtils::sendmsg("VM must be powered off to add IDE drives", $callback, $node);
next;
}
my @suffixes;
- if ($prefix eq 'hd') {
- @suffixes=('a','b','d'..'zzz');
+ if ($prefix eq 'hd') {
+ @suffixes = ('a', 'b', 'd' .. 'zzz');
} else {
- @suffixes=('a'..'zzz');
+ @suffixes = ('a' .. 'zzz');
}
my @newsizes;
foreach (@addsizes) {
- push @newsizes,split /,/,$_;
+ push @newsizes, split /,/, $_;
}
foreach (@newsizes) {
my $dev;
do {
- $dev = $prefix.shift(@suffixes);
+ $dev = $prefix . shift(@suffixes);
} while ($useddisks{$dev});
+
#ok, now I need a volume created to attach
- push @diskstoadd,get_filepath_by_url(url=>$location,dev=>$dev,create=>$_);
+ push @diskstoadd, get_filepath_by_url(url => $location, dev => $dev, create => $_);
}
- #now that the volumes are made, must build xml for each and attempt attach if and only if the VM is live
+
+#now that the volumes are made, must build xml for each and attempt attach if and only if the VM is live
foreach (@diskstoadd) {
my $suffix;
my $format;
if (/^[^\.]*\.([^\.]*)\.([^\.]*)/) {
- $suffix=$1;
- $format=$2;
+ $suffix = $1;
+ $format = $2;
} elsif (/^[^\.]*\.([^\.]*)/) {
- $suffix=$1;
- $format='raw';
+ $suffix = $1;
+ $format = 'raw';
}
if ($confdata->{vm}->{$node}->[0]->{storageformat}) {
$format = $confdata->{vm}->{$node}->[0]->{storageformat};
}
- #when creating a new disk not cloned from anything, disable cache as copy on write content similarity is a lost cause...
+
+#when creating a new disk not cloned from anything, disable cache as copy on write content similarity is a lost cause...
my $cachemode = 'none';
+
#unless user knows better
if ($confdata->{vm}->{$node}->[0]->{storagecache}) {
$cachemode = $confdata->{vm}->{$node}->[0]->{storagecache};
}
my $bus;
if ($suffix =~ /^sd/) {
- $bus='scsi';
+ $bus = 'scsi';
} elsif ($suffix =~ /hd/) {
- $bus='ide';
+ $bus = 'ide';
} elsif ($suffix =~ /vd/) {
- $bus='virtio';
+ $bus = 'virtio';
}
my $xml = "";
- if ($currstate eq 'on') { #attempt live attach
- eval {
- $dom->attach_device($xml);
- };
- if ($@) {
- my $err=$@;
- if ($err =~ /No more available PCI addresses/) {
- xCAT::SvrUtils::sendmsg([1,"Exhausted Virtio limits trying to add $_"],$callback,$node);
- } else {
- xCAT::SvrUtils::sendmsg([1,"Unable to attach $_ because of ".$err],$callback,$node);
+ if ($currstate eq 'on') { #attempt live attach
+ eval {
+ $dom->attach_device($xml);
+ };
+ if ($@) {
+ my $err = $@;
+ if ($err =~ /No more available PCI addresses/) {
+ xCAT::SvrUtils::sendmsg([ 1, "Exhausted Virtio limits trying to add $_" ], $callback, $node);
+ } else {
+ xCAT::SvrUtils::sendmsg([ 1, "Unable to attach $_ because of " . $err ], $callback, $node);
+ }
+ my $file = $_;
+ my $vol = $hypconn->get_storage_volume_by_path($file);
+ if ($vol) {
+ $vol->delete();
+ }
}
- my $file = $_;
- my $vol = $hypconn->get_storage_volume_by_path($file);
- if ($vol) {
- $vol->delete();
- }
- }
- $vmxml=$dom->get_xml_description();
- } elsif ($confdata->{kvmnodedata}->{$node}->[0]->{xml}) {
- $vmxml=$confdata->{kvmnodedata}->{$node}->[0]->{xml};
- my $disknode = $parser->parse_balanced_chunk($xml);
- my $vmdoc = $parser->parse_string($vmxml);
+ $vmxml = $dom->get_xml_description();
+ } elsif ($confdata->{kvmnodedata}->{$node}->[0]->{xml}) {
+ $vmxml = $confdata->{kvmnodedata}->{$node}->[0]->{xml};
+ my $disknode = $parser->parse_balanced_chunk($xml);
+ my $vmdoc = $parser->parse_string($vmxml);
my $devicesnode = $vmdoc->findnodes("/domain/devices")->[0];
$devicesnode->appendChild($disknode);
- $vmxml=$vmdoc->toString();
+ $vmxml = $vmdoc->toString();
}
- $updatetable->{kvm_nodedata}->{$node}->{xml}=$vmxml;
+ $updatetable->{kvm_nodedata}->{$node}->{xml} = $vmxml;
}
} elsif (@purge) {
my $dom;
@@ -1890,30 +1961,32 @@ sub chvm {
};
my $vmxml;
if ($dom) {
- $vmxml=$dom->get_xml_description();
+ $vmxml = $dom->get_xml_description();
} else {
- $vmxml=$confdata->{kvmnodedata}->{$node}->[0]->{xml};
+ $vmxml = $confdata->{kvmnodedata}->{$node}->[0]->{xml};
}
- my $currstate=getpowstate($dom);
- my @disklist=get_disks_by_userspecs(\@purge,$vmxml,'returnmoddedxml');
+ my $currstate = getpowstate($dom);
+ my @disklist = get_disks_by_userspecs(\@purge, $vmxml, 'returnmoddedxml');
my $moddedxml = shift @disklist;
foreach (@disklist) {
- my $devxml=$_->[0];
- my $file=$_->[1];
+ my $devxml = $_->[0];
+ my $file = $_->[1];
$file =~ m!/([^/]*)/($node\..*)\z!;
+
#first, detach the device.
eval {
- if ($currstate eq 'on') {
- $dom->detach_device($devxml);
- $vmxml=$dom->get_xml_description();
- } else {
- $vmxml=$moddedxml;
- }
- $updatetable->{kvm_nodedata}->{$node}->{xml}=$vmxml;
+ if ($currstate eq 'on') {
+ $dom->detach_device($devxml);
+ $vmxml = $dom->get_xml_description();
+ } else {
+ $vmxml = $moddedxml;
+ }
+ $updatetable->{kvm_nodedata}->{$node}->{xml} = $vmxml;
};
if ($@) {
- xCAT::SvrUtils::sendmsg([1,"Unable to remove device"],$callback,$node);
+ xCAT::SvrUtils::sendmsg([ 1, "Unable to remove device" ], $callback, $node);
} else {
+
#if that worked, remove the disk..
my $vol = $hypconn->get_storage_volume_by_path($file);
if ($vol) {
@@ -1922,603 +1995,612 @@ sub chvm {
}
}
- }
+ }
my $newcdxml;
if ($cdrom) {
- my $cdpath;
- if ($cdrom =~ m!://!) {
- my $url = $cdrom;
- $url =~ s!([^/]+)\z!!;
- my $imagename=$1;
- my $poolobj = get_storage_pool_by_url($url);
- unless ($poolobj) { die "Cound not get storage pool for $url"; }
- my $poolxml = $poolobj->get_xml_description(); #yes, I have to XML parse for even this...
- my $parsedpool = $parser->parse_string($poolxml);
- $cdpath = $parsedpool->findnodes("/pool/target/path/text()")->[0]->data;
- $cdpath .= "/".$imagename;
- } else {
- if ($cdrom =~ m!^/dev/!) {
- die "TODO: device pass through if anyone cares";
- } elsif ($cdrom =~ m!^/!) { #full path... I guess
- $cdpath=$cdrom;
- } else {
- die "TODO: relative paths, use client cwd as hint?";
- }
- }
- unless ($cdpath) { die "unable to understand cd path specification"; }
- $newcdxml = "";
+ my $cdpath;
+ if ($cdrom =~ m!://!) {
+ my $url = $cdrom;
+ $url =~ s!([^/]+)\z!!;
+ my $imagename = $1;
+ my $poolobj = get_storage_pool_by_url($url);
+ unless ($poolobj) { die "Cound not get storage pool for $url"; }
+ my $poolxml = $poolobj->get_xml_description(); #yes, I have to XML parse for even this...
+ my $parsedpool = $parser->parse_string($poolxml);
+ $cdpath = $parsedpool->findnodes("/pool/target/path/text()")->[0]->data;
+ $cdpath .= "/" . $imagename;
+ } else {
+ if ($cdrom =~ m!^/dev/!) {
+ die "TODO: device pass through if anyone cares";
+ } elsif ($cdrom =~ m!^/!) { #full path... I guess
+ $cdpath = $cdrom;
+ } else {
+ die "TODO: relative paths, use client cwd as hint?";
+ }
+ }
+ unless ($cdpath) { die "unable to understand cd path specification"; }
+ $newcdxml = "";
} elsif ($eject) {
- $newcdxml = "";
+ $newcdxml = "";
}
if ($newcdxml) {
- if ($currstate eq 'on') {
- $dom->attach_device($newcdxml);
- $vmxml=$dom->get_xml_description();
- } else {
- unless ($vmxml) {
- $vmxml=$confdata->{kvmnodedata}->{$node}->[0]->{xml};
- }
- my $domparsed = $parser->parse_string($vmxml);
- my $candidatenodes=$domparsed->findnodes("//disk[\@device='cdrom']");
- if (scalar (@$candidatenodes) != 1) {
- die "shouldn't be possible, should only have one cdrom";
- }
- my $newcd=$parser->parse_balanced_chunk($newcdxml);
- $candidatenodes->[0]->replaceNode($newcd);
- my $moddedxml=$domparsed->toString;
- if ($moddedxml) {
- $vmxml=$moddedxml;
- }
- }
- if ($vmxml) {
- $updatetable->{kvm_nodedata}->{$node}->{xml}=$vmxml;
- }
+ if ($currstate eq 'on') {
+ $dom->attach_device($newcdxml);
+ $vmxml = $dom->get_xml_description();
+ } else {
+ unless ($vmxml) {
+ $vmxml = $confdata->{kvmnodedata}->{$node}->[0]->{xml};
+ }
+ my $domparsed = $parser->parse_string($vmxml);
+ my $candidatenodes = $domparsed->findnodes("//disk[\@device='cdrom']");
+ if (scalar(@$candidatenodes) != 1) {
+ die "shouldn't be possible, should only have one cdrom";
+ }
+ my $newcd = $parser->parse_balanced_chunk($newcdxml);
+ $candidatenodes->[0]->replaceNode($newcd);
+ my $moddedxml = $domparsed->toString;
+ if ($moddedxml) {
+ $vmxml = $moddedxml;
+ }
+ }
+ if ($vmxml) {
+ $updatetable->{kvm_nodedata}->{$node}->{xml} = $vmxml;
+ }
}
if ($cpucount or $memory) {
if ($currstate eq 'on') {
- if ($cpucount) {xCAT::SvrUtils::sendmsg([1,"Hot add of cpus not supported (VM must be powered down to successfuly change)"],$callback,$node); }
+ if ($cpucount) { xCAT::SvrUtils::sendmsg([ 1, "Hot add of cpus not supported (VM must be powered down to successfuly change)" ], $callback, $node); }
if ($cpucount) {
- #$dom->set_vcpus($cpucount); this didn't work out as well as I hoped..
- #xCAT::SvrUtils::sendmsg([1,"Hot add of cpus not supported"],$callback,$node);
+
+ #$dom->set_vcpus($cpucount); this didn't work out as well as I hoped..
+ #xCAT::SvrUtils::sendmsg([1,"Hot add of cpus not supported"],$callback,$node);
}
if ($memory) {
- eval {
- $dom->set_memory(getUnits($memory,"M",1024));
- };
- if ($@) {
- if ($@ =~ /cannot set memory higher/) {
- xCAT::SvrUtils::sendmsg([1,"Unable to increase memory beyond current capacity (requires VM to be powered down to change)"],$callback,$node);
- }
- } else {
- if ($confdata->{vm}->{$node}->[0]->{memory} and $confdata->{vm}->{$node}->[0]->{memory} != $memory) {
- $updatetable->{vm}->{$node}->{memory}=$memory;
- }
- }
- $vmxml=$dom->get_xml_description();
- if ($vmxml) {
- $updatetable->{kvm_nodedata}->{$node}->{xml}=$vmxml;
- }
+ eval {
+ $dom->set_memory(getUnits($memory, "M", 1024));
+ };
+ if ($@) {
+ if ($@ =~ /cannot set memory higher/) {
+ xCAT::SvrUtils::sendmsg([ 1, "Unable to increase memory beyond current capacity (requires VM to be powered down to change)" ], $callback, $node);
+ }
+ } else {
+ if ($confdata->{vm}->{$node}->[0]->{memory} and $confdata->{vm}->{$node}->[0]->{memory} != $memory) {
+ $updatetable->{vm}->{$node}->{memory} = $memory;
+ }
+ }
+ $vmxml = $dom->get_xml_description();
+ if ($vmxml) {
+ $updatetable->{kvm_nodedata}->{$node}->{xml} = $vmxml;
+ }
}
- } else { #offline xml edits
- my $parsed=$parser->parse_string($vmxml); #TODO: should only do this once, oh well
+ } else { #offline xml edits
+ my $parsed = $parser->parse_string($vmxml); #TODO: should only do this once, oh well
if ($cpucount) {
- my $hypcpumodel = $confdata->{$confdata->{vm}->{$node}->[0]->{host}}->{cpumodel};
+ my $hypcpumodel = $confdata->{ $confdata->{vm}->{$node}->[0]->{host} }->{cpumodel};
if ($hypcpumodel eq "ppc64") {
my $cputhreads = $parsed->findnodes("/domain/cpu/topology")->[0]->getAttribute('threads');
unless ($cputhreads) {
$cputhreads = "1";
}
- $parsed->findnodes("/domain/cpu/topology")->[0]->setAttribute('cores'=>$cpucount);
+ $parsed->findnodes("/domain/cpu/topology")->[0]->setAttribute('cores' => $cpucount);
$cpucount *= $cputhreads;
}
$parsed->findnodes("/domain/vcpu/text()")->[0]->setData($cpucount);
}
if ($memory) {
- $parsed->findnodes("/domain/memory/text()")->[0]->setData(getUnits($memory,"M",1024));
+ $parsed->findnodes("/domain/memory/text()")->[0]->setData(getUnits($memory, "M", 1024));
my @currmem = $parsed->findnodes("/domain/currentMemory/text()");
foreach (@currmem) {
- $_->setData(getUnits($memory,"M",1024));
+ $_->setData(getUnits($memory, "M", 1024));
+ }
+ if ($confdata->{vm}->{$node}->[0]->{memory} and $confdata->{vm}->{$node}->[0]->{memory} != $memory) {
+ $updatetable->{vm}->{$node}->{memory} = $memory;
}
- if ($confdata->{vm}->{$node}->[0]->{memory} and $confdata->{vm}->{$node}->[0]->{memory} != $memory) {
- $updatetable->{vm}->{$node}->{memory}=$memory;
- }
}
- $vmxml=$parsed->toString;
- $updatetable->{kvm_nodedata}->{$node}->{xml}=$vmxml;
+ $vmxml = $parsed->toString;
+ $updatetable->{kvm_nodedata}->{$node}->{xml} = $vmxml;
}
}
- if(defined $pcpuset){
- if ($currstate eq 'on') {
- #get the vcpuinfo of the domain
- my @vcpuinfo;
- eval { @vcpuinfo = $dom->get_vcpu_info(); };
- if ($@) {
- xCAT::SvrUtils::sendmsg([1,"$@"],$callback,$node);
- return;
- }
+ if (defined $pcpuset) {
+ if ($currstate eq 'on') {
- #get the cpuinfo of the host
- my ($totcpus, $onlinemap, $totonline);
- eval { ($totcpus, $onlinemap, $totonline) = $hypconn->get_node_cpu_map(); };
- if ($@) {
- xCAT::SvrUtils::sendmsg([1,"$@"],$callback,$node);
- return;
- }
+ #get the vcpuinfo of the domain
+ my @vcpuinfo;
+ eval { @vcpuinfo = $dom->get_vcpu_info(); };
+ if ($@) {
+ xCAT::SvrUtils::sendmsg([ 1, "$@" ], $callback, $node);
+ return;
+ }
- #convert the cpuset to bitmap,which is required by pin_vcpu()
- my @pcpumaparr=(0) x $totcpus;
- my @cpurange=split ",",$pcpuset;
- foreach my $rangeslice (@cpurange){
- if( $rangeslice =~ /^(\d*)-(\d*)$/ ){
- my ($left,$right)=($1,$2);
- @pcpumaparr[$left .. $right]=(1) x ($right-$left+1);
- }elsif($rangeslice =~ /^\^(\d*)$/){
- if($pcpumaparr[$1]==0){
- xCAT::SvrUtils::sendmsg([1,"\'$rangeslice\' is ignored, please make sure the specified cpu set is correct"],$callback,$node);
- return;
- }else{
- $pcpumaparr[$1]=0;
- }
+ #get the cpuinfo of the host
+ my ($totcpus, $onlinemap, $totonline);
+ eval { ($totcpus, $onlinemap, $totonline) = $hypconn->get_node_cpu_map(); };
+ if ($@) {
+ xCAT::SvrUtils::sendmsg([ 1, "$@" ], $callback, $node);
+ return;
+ }
- }elsif($rangeslice =~ /^(\d*)$/){
- $pcpumaparr[$1]=1;
- }
- }
-
- my $pcpumap=join //,@pcpumaparr;
- my $mask=pack("b*",$pcpumap);
-
- #Pin the virtual CPU given to physical CPUs given
- foreach(@vcpuinfo){
- eval {
- $dom->pin_vcpu($_->{number}, $mask);
- };
- if ($@) {
- xCAT::SvrUtils::sendmsg([1,"$@"],$callback,$node);
- }
- }
+ #convert the cpuset to bitmap,which is required by pin_vcpu()
+ my @pcpumaparr = (0) x $totcpus;
+ my @cpurange = split ",", $pcpuset;
+ foreach my $rangeslice (@cpurange) {
+ if ($rangeslice =~ /^(\d*)-(\d*)$/) {
+ my ($left, $right) = ($1, $2);
+ @pcpumaparr[ $left .. $right ] = (1) x ($right - $left + 1);
+ } elsif ($rangeslice =~ /^\^(\d*)$/) {
+ if ($pcpumaparr[$1] == 0) {
+ xCAT::SvrUtils::sendmsg([ 1, "\'$rangeslice\' is ignored, please make sure the specified cpu set is correct" ], $callback, $node);
+ return;
+ } else {
+ $pcpumaparr[$1] = 0;
+ }
- $vmxml=$dom->get_xml_description();
- my $parsed=$parser->parse_string($vmxml);
- my $ref=$parsed->findnodes("/domain/vcpu");
- $ref->[0]->removeAttribute("cpuset");
- $vmxml=$parsed->toString;
- if ($vmxml) {
- $updatetable->{kvm_nodedata}->{$node}->{xml}=$vmxml;
- }
- }else{
- my $parsed=$parser->parse_string($vmxml);
- my $ref=$parsed->findnodes("/domain/vcpu");
- $ref->[0]->setAttribute("cpuset",$pcpuset);
-
- #for virtual CPUs which have the vcpupin specified,
- # the cpuset specified by/domain/vcpu/cpuset will be ignored
- my $ref=$parsed->findnodes("/domain");
- my $cputuneref=$parsed->findnodes("/domain/cputune");
- $cputuneref->[0]->parentNode->removeChild($cputuneref->[0]);
- $vmxml=$parsed->toString;
- $updatetable->{kvm_nodedata}->{$node}->{xml}=$vmxml;
- }
- }
-
- if(defined $numanodeset){
- if ($currstate eq 'on') {
- eval {
- my %tmphash=(Sys::Virt::Domain->NUMA_NODESET => "$numanodeset");
- $dom->set_numa_parameters(\%tmphash);
- };
- if ($@) {
- xCAT::SvrUtils::sendmsg([1,"$@"],$callback,$node);
- return;
- }
- $vmxml=$dom->get_xml_description();
- if ($vmxml) {
- $updatetable->{kvm_nodedata}->{$node}->{xml}=$vmxml;
- }
- }else{
- my %numatunehash;
- $numatunehash{memory}=[{nodeset=>"$numanodeset"}];
- my $numatunexml=XMLout(\%numatunehash,RootName=>"numatune");
-
-
- my $parsed=$parser->parse_string($vmxml);
- my $numatuneref=$parsed->findnodes("/domain/numatune");
-
- if($numatuneref)
- {
- #/domain/numatune exist,modify the numatune/nodeset
- my $ref=$parsed->findnodes("/domain/numatune/memory");
- $ref->[0]->setAttribute("nodeset",$numanodeset);
- }else{
- #/domain/numatune does not exist,create one
- my $ref=$parsed->findnodes("/domain");
- my $numatunenode = $parser->parse_balanced_chunk($numatunexml);
- $ref->[0]->appendChild($numatunenode);
- }
- $vmxml=$parsed->toString;
- $updatetable->{kvm_nodedata}->{$node}->{xml}=$vmxml;
- }
- }
-
-
-
- $passthrudevices=~s/["']//g;
- if(defined $passthrudevices){
- my @prdevarr=split ",",$passthrudevices;
- unless(scalar @prdevarr){
- xCAT::SvrUtils::sendmsg([1,"device passthrough: no device specified"],$callback,$node);
- return;
- }
-
- foreach my $devname (@prdevarr){
- my $devobj;
- eval {
- $devobj=$hypconn->get_node_device_by_name($devname);
- };
- if ($@) {
- xCAT::SvrUtils::sendmsg([1,"$@"],$callback,$node);
- next;
- }
-
- my $devxml=$devobj->get_xml_description();
- unless($devxml){
- next;
- }
-
-
-
- my $devhash=XMLin($devxml);
- if(defined $devhash->{capability}->{type} and $devhash->{capability}->{type} =~ /pci/i ){
- my %tmphash;
- $tmphash{mode}='subsystem';
- $tmphash{type}=$devhash->{capability}->{type};
- $tmphash{managed}="yes";
- $tmphash{driver}->{name}="vfio";
- $tmphash{source}->{address}->[0]=\%{$devhash->{'capability'}->{'iommuGroup'}->{'address'}};
-
- my $newxml=XMLout(\%tmphash,RootName=>"hostdev");
-
- if ($currstate eq 'on') {
- #for a running KVM guest, first unbind the device from the existing driver,
- #reset the device, and bind it
- #If the description of a PCI device includes the attribute managed='yes',
- #and the hypervisor driver supports it, then the device is in managed mode, and attempts to
- #use that passthrough device in an active guest will automatically behave as if nodedev-detach
- #(guest start, device hot-plug) and nodedev-reattach (guest stop, device hot-unplug)
- #were called at the right points.
- #in case the hypervisor driver does not support managed mode, do this explicitly here
- eval {
- $devobj->dettach(undef,0);
- };
- if ($@) {
- xCAT::SvrUtils::sendmsg([0,"detaching $devname from host:$@"],$callback,$node);
- }
-
- eval {
- $devobj->reset();
- };
- if ($@) {
- xCAT::SvrUtils::sendmsg([0,"resetting $devname:$@"],$callback,$node);
- }
-
- my $flag=0;
- if($dom->is_persistent()){
- $flag=&Sys::Virt::Domain::DEVICE_MODIFY_LIVE|&Sys::Virt::Domain::DEVICE_MODIFY_CONFIG;
- }else{
- $flag=&Sys::Virt::Domain::DEVICE_MODIFY_LIVE;
- }
-
- eval {
- $dom->attach_device($newxml,$flag);
- };
- if ($@) {
- xCAT::SvrUtils::sendmsg([1,"attaching device to guest:$@"],$callback,$node);
- next;
- }else{
- $vmxml=$dom->get_xml_description();
- if ($vmxml) {
- $updatetable->{kvm_nodedata}->{$node}->{xml}=$vmxml;
- }
- xCAT::SvrUtils::sendmsg([0,"passthrough: $devname attached to guest successfully "],$callback,$node);
- }
-
- }else{
-
- my $hostdevfound;
- $hostdevfound=0;
- my $parsed=$parser->parse_string($vmxml);
- my $ref=$parsed->findnodes("/domain/devices");
-
- my @hostdevlist=$ref->[0]->findnodes("./hostdev");
- #check whether the hostdev existed in guest xml
- foreach my $hostdevref (@hostdevlist){
- my $devaddrref=$hostdevref->findnodes("./source/address");
-
- my $domain=$devaddrref->[0]->getAttribute("domain");
- my $bus=$devaddrref->[0]->getAttribute("bus");
- my $slot=$devaddrref->[0]->getAttribute("slot");
- my $function=$devaddrref->[0]->getAttribute("function");
-
- my $curdevaddr=\%{$devhash->{'capability'}->{'iommuGroup'}->{'address'}};
-
-
-
- if(("$curdevaddr->{domain}" eq "$domain") and
- ("$curdevaddr->{bus}" eq "$bus") and
- ("$curdevaddr->{slot}" eq "$slot") and
- ("$curdevaddr->{function}" eq "$function")){
-
- #hostdev existed in guest xml
- $hostdevfound=1;
- goto PROCESS_HOSTDEV_XML_ATTATCH;
- }
- }
-
- PROCESS_HOSTDEV_XML_ATTATCH:
- unless($hostdevfound){
- #hostdev does not exist,add into guest xml
- my $hostdevnode = $parser->parse_balanced_chunk($newxml);
- $ref->[0]->appendChild($hostdevnode);
- $vmxml=$parsed->toString;
- $updatetable->{kvm_nodedata}->{$node}->{xml}=$vmxml;
-
- }
-
-
- }
- }
-
- }
- }
-
- $devicestodetach=~s/["']//g;
- if(defined $devicestodetach){
- my @devarr=split ",",$devicestodetach;
- unless(scalar @devarr){
- xCAT::SvrUtils::sendmsg([1,"device detaching: no device specified"],$callback,$node);
- return;
- }
-
- foreach my $devname (@devarr){
- my $devobj;
- eval {
- $devobj=$hypconn->get_node_device_by_name($devname);
- };
- if ($@) {
- xCAT::SvrUtils::sendmsg([1,"$@"],$callback,$node);
- next;
- }
-
-
- my $devxml=$devobj->get_xml_description();
- unless($devxml){
- next;
- }
-
- my $devhash=XMLin($devxml);
- if(defined $devhash->{capability}->{type} and $devhash->{capability}->{type} =~ /pci/i ){
- my %tmphash;
- $tmphash{mode}='subsystem';
- $tmphash{type}=$devhash->{capability}->{type};
- $tmphash{managed}="yes";
- $tmphash{driver}->{name}="vfio";
- $tmphash{source}->{address}->[0]=\%{$devhash->{'capability'}->{'iommuGroup'}->{'address'}};
-
- my $newxml=XMLout(\%tmphash,RootName=>"hostdev");
- if ($currstate eq 'on') {
- my $flag=0;
- if($dom->is_persistent()){
- $flag=&Sys::Virt::Domain::DEVICE_MODIFY_LIVE|&Sys::Virt::Domain::DEVICE_MODIFY_CONFIG;
- }else{
- $flag=&Sys::Virt::Domain::DEVICE_MODIFY_LIVE;
- }
- eval {
- $dom->detach_device($newxml,$flag);
- };
- if ($@) {
- xCAT::SvrUtils::sendmsg([1,"detaching device from guest:$@"],$callback,$node);
- next;
- }else{
- $vmxml=$dom->get_xml_description();
- if ($vmxml) {
- $updatetable->{kvm_nodedata}->{$node}->{xml}=$vmxml;
- }
-
- eval {
- $devobj->reattach();
- };
- if ($@) {
- xCAT::SvrUtils::sendmsg([0,"reattaching device to host:$@"],$callback,$node);
- }
-
- xCAT::SvrUtils::sendmsg([0,"devdetach: $devname detached from guest successfully "],$callback,$node);
- }
-
- }else{
-
- my $hostdevfound;
- $hostdevfound=0;
- my $hostdevobj;
- my $parsed=$parser->parse_string($vmxml);
- my $ref=$parsed->findnodes("/domain/devices");
-
- my @hostdevlist=$ref->[0]->findnodes("./hostdev");
- #check whether the hostdev existed in guest xml
- foreach my $hostdevref (@hostdevlist){
- my $devaddrref=$hostdevref->findnodes("./source/address");
-
- my $domain=$devaddrref->[0]->getAttribute("domain");
- my $bus=$devaddrref->[0]->getAttribute("bus");
- my $slot=$devaddrref->[0]->getAttribute("slot");
- my $function=$devaddrref->[0]->getAttribute("function");
-
- my $curdevaddr=\%{$devhash->{'capability'}->{'iommuGroup'}->{'address'}};
-
-
- if(("$curdevaddr->{domain}" eq "$domain") and
- ("$curdevaddr->{bus}" eq "$bus") and
- ("$curdevaddr->{slot}" eq "$slot") and
- ("$curdevaddr->{function}" eq "$function")){
-
- #hostdev existed in guest xml
- $hostdevfound=1;
- $hostdevobj=$hostdevref;
- goto PROCESS_HOSTDEV_XML_DETATCH;
- }
- }
-
-
-
- PROCESS_HOSTDEV_XML_DETATCH:
- if($hostdevfound){
- #hostdev exist,remove it from guest xml
- my $hostdevnode = $parser->parse_balanced_chunk($newxml);
- $hostdevobj->parentNode()->removeChild($hostdevobj);
- $vmxml=$parsed->toString;
- $updatetable->{kvm_nodedata}->{$node}->{xml}=$vmxml;
- xCAT::SvrUtils::sendmsg([0,"devdetach: $devname detached from guest $node successfully "],$callback,$node);
-
- }else{
- xCAT::SvrUtils::sendmsg([1,"device detaching: the specified device $devname is not attached to $node yet"],$callback,$node);
- return;
+ } elsif ($rangeslice =~ /^(\d*)$/) {
+ $pcpumaparr[$1] = 1;
}
}
- }
- }
+ my $pcpumap = join //, @pcpumaparr;
+ my $mask = pack("b*", $pcpumap);
+
+ #Pin the virtual CPU given to physical CPUs given
+ foreach (@vcpuinfo) {
+ eval {
+ $dom->pin_vcpu($_->{number}, $mask);
+ };
+ if ($@) {
+ xCAT::SvrUtils::sendmsg([ 1, "$@" ], $callback, $node);
+ }
+ }
+
+ $vmxml = $dom->get_xml_description();
+ my $parsed = $parser->parse_string($vmxml);
+ my $ref = $parsed->findnodes("/domain/vcpu");
+ $ref->[0]->removeAttribute("cpuset");
+ $vmxml = $parsed->toString;
+ if ($vmxml) {
+ $updatetable->{kvm_nodedata}->{$node}->{xml} = $vmxml;
+ }
+ } else {
+ my $parsed = $parser->parse_string($vmxml);
+ my $ref = $parsed->findnodes("/domain/vcpu");
+ $ref->[0]->setAttribute("cpuset", $pcpuset);
+
+ #for virtual CPUs which have the vcpupin specified,
+ # the cpuset specified by/domain/vcpu/cpuset will be ignored
+ my $ref = $parsed->findnodes("/domain");
+ my $cputuneref = $parsed->findnodes("/domain/cputune");
+ $cputuneref->[0]->parentNode->removeChild($cputuneref->[0]);
+ $vmxml = $parsed->toString;
+ $updatetable->{kvm_nodedata}->{$node}->{xml} = $vmxml;
+ }
+ }
+
+ if (defined $numanodeset) {
+ if ($currstate eq 'on') {
+ eval {
+ my %tmphash = (Sys::Virt::Domain->NUMA_NODESET => "$numanodeset");
+ $dom->set_numa_parameters(\%tmphash);
+ };
+ if ($@) {
+ xCAT::SvrUtils::sendmsg([ 1, "$@" ], $callback, $node);
+ return;
+ }
+ $vmxml = $dom->get_xml_description();
+ if ($vmxml) {
+ $updatetable->{kvm_nodedata}->{$node}->{xml} = $vmxml;
+ }
+ } else {
+ my %numatunehash;
+ $numatunehash{memory} = [ { nodeset => "$numanodeset" } ];
+ my $numatunexml = XMLout(\%numatunehash, RootName => "numatune");
+
+
+ my $parsed = $parser->parse_string($vmxml);
+ my $numatuneref = $parsed->findnodes("/domain/numatune");
+
+ if ($numatuneref)
+ {
+ #/domain/numatune exist,modify the numatune/nodeset
+ my $ref = $parsed->findnodes("/domain/numatune/memory");
+ $ref->[0]->setAttribute("nodeset", $numanodeset);
+ } else {
+
+ #/domain/numatune does not exist,create one
+ my $ref = $parsed->findnodes("/domain");
+ my $numatunenode = $parser->parse_balanced_chunk($numatunexml);
+ $ref->[0]->appendChild($numatunenode);
+ }
+ $vmxml = $parsed->toString;
+ $updatetable->{kvm_nodedata}->{$node}->{xml} = $vmxml;
+ }
+ }
+
+
+
+ $passthrudevices =~ s/["']//g;
+ if (defined $passthrudevices) {
+ my @prdevarr = split ",", $passthrudevices;
+ unless (scalar @prdevarr) {
+ xCAT::SvrUtils::sendmsg([ 1, "device passthrough: no device specified" ], $callback, $node);
+ return;
+ }
+
+ foreach my $devname (@prdevarr) {
+ my $devobj;
+ eval {
+ $devobj = $hypconn->get_node_device_by_name($devname);
+ };
+ if ($@) {
+ xCAT::SvrUtils::sendmsg([ 1, "$@" ], $callback, $node);
+ next;
+ }
+
+ my $devxml = $devobj->get_xml_description();
+ unless ($devxml) {
+ next;
+ }
+
+
+
+ my $devhash = XMLin($devxml);
+ if (defined $devhash->{capability}->{type} and $devhash->{capability}->{type} =~ /pci/i) {
+ my %tmphash;
+ $tmphash{mode} = 'subsystem';
+ $tmphash{type} = $devhash->{capability}->{type};
+ $tmphash{managed} = "yes";
+ $tmphash{driver}->{name} = "vfio";
+ $tmphash{source}->{address}->[0] = \%{ $devhash->{'capability'}->{'iommuGroup'}->{'address'} };
+
+ my $newxml = XMLout(\%tmphash, RootName => "hostdev");
+
+ if ($currstate eq 'on') {
+
+#for a running KVM guest, first unbind the device from the existing driver,
+#reset the device, and bind it
+#If the description of a PCI device includes the attribute managed='yes',
+#and the hypervisor driver supports it, then the device is in managed mode, and attempts to
+#use that passthrough device in an active guest will automatically behave as if nodedev-detach
+#(guest start, device hot-plug) and nodedev-reattach (guest stop, device hot-unplug)
+#were called at the right points.
+#in case the hypervisor driver does not support managed mode, do this explicitly here
+ eval {
+ $devobj->dettach(undef, 0);
+ };
+ if ($@) {
+ xCAT::SvrUtils::sendmsg([ 0, "detaching $devname from host:$@" ], $callback, $node);
+ }
+
+ eval {
+ $devobj->reset();
+ };
+ if ($@) {
+ xCAT::SvrUtils::sendmsg([ 0, "resetting $devname:$@" ], $callback, $node);
+ }
+
+ my $flag = 0;
+ if ($dom->is_persistent()) {
+ $flag = &Sys::Virt::Domain::DEVICE_MODIFY_LIVE | &Sys::Virt::Domain::DEVICE_MODIFY_CONFIG;
+ } else {
+ $flag = &Sys::Virt::Domain::DEVICE_MODIFY_LIVE;
+ }
+
+ eval {
+ $dom->attach_device($newxml, $flag);
+ };
+ if ($@) {
+ xCAT::SvrUtils::sendmsg([ 1, "attaching device to guest:$@" ], $callback, $node);
+ next;
+ } else {
+ $vmxml = $dom->get_xml_description();
+ if ($vmxml) {
+ $updatetable->{kvm_nodedata}->{$node}->{xml} = $vmxml;
+ }
+ xCAT::SvrUtils::sendmsg([ 0, "passthrough: $devname attached to guest successfully " ], $callback, $node);
+ }
+
+ } else {
+
+ my $hostdevfound;
+ $hostdevfound = 0;
+ my $parsed = $parser->parse_string($vmxml);
+ my $ref = $parsed->findnodes("/domain/devices");
+
+ my @hostdevlist = $ref->[0]->findnodes("./hostdev");
+
+ #check whether the hostdev existed in guest xml
+ foreach my $hostdevref (@hostdevlist) {
+ my $devaddrref = $hostdevref->findnodes("./source/address");
+
+ my $domain = $devaddrref->[0]->getAttribute("domain");
+ my $bus = $devaddrref->[0]->getAttribute("bus");
+ my $slot = $devaddrref->[0]->getAttribute("slot");
+ my $function = $devaddrref->[0]->getAttribute("function");
+
+ my $curdevaddr = \%{ $devhash->{'capability'}->{'iommuGroup'}->{'address'} };
+
+
+
+ if (("$curdevaddr->{domain}" eq "$domain") and
+ ("$curdevaddr->{bus}" eq "$bus") and
+ ("$curdevaddr->{slot}" eq "$slot") and
+ ("$curdevaddr->{function}" eq "$function")) {
+
+ #hostdev existed in guest xml
+ $hostdevfound = 1;
+ goto PROCESS_HOSTDEV_XML_ATTATCH;
+ }
+ }
+
+ PROCESS_HOSTDEV_XML_ATTATCH:
+ unless ($hostdevfound) {
+
+ #hostdev does not exist,add into guest xml
+ my $hostdevnode = $parser->parse_balanced_chunk($newxml);
+ $ref->[0]->appendChild($hostdevnode);
+ $vmxml = $parsed->toString;
+ $updatetable->{kvm_nodedata}->{$node}->{xml} = $vmxml;
+
+ }
+
+
+ }
+ }
+
+ }
+ }
+
+ $devicestodetach =~ s/["']//g;
+ if (defined $devicestodetach) {
+ my @devarr = split ",", $devicestodetach;
+ unless (scalar @devarr) {
+ xCAT::SvrUtils::sendmsg([ 1, "device detaching: no device specified" ], $callback, $node);
+ return;
+ }
+
+ foreach my $devname (@devarr) {
+ my $devobj;
+ eval {
+ $devobj = $hypconn->get_node_device_by_name($devname);
+ };
+ if ($@) {
+ xCAT::SvrUtils::sendmsg([ 1, "$@" ], $callback, $node);
+ next;
+ }
+
+
+ my $devxml = $devobj->get_xml_description();
+ unless ($devxml) {
+ next;
+ }
+
+ my $devhash = XMLin($devxml);
+ if (defined $devhash->{capability}->{type} and $devhash->{capability}->{type} =~ /pci/i) {
+ my %tmphash;
+ $tmphash{mode} = 'subsystem';
+ $tmphash{type} = $devhash->{capability}->{type};
+ $tmphash{managed} = "yes";
+ $tmphash{driver}->{name} = "vfio";
+ $tmphash{source}->{address}->[0] = \%{ $devhash->{'capability'}->{'iommuGroup'}->{'address'} };
+
+ my $newxml = XMLout(\%tmphash, RootName => "hostdev");
+ if ($currstate eq 'on') {
+ my $flag = 0;
+ if ($dom->is_persistent()) {
+ $flag = &Sys::Virt::Domain::DEVICE_MODIFY_LIVE | &Sys::Virt::Domain::DEVICE_MODIFY_CONFIG;
+ } else {
+ $flag = &Sys::Virt::Domain::DEVICE_MODIFY_LIVE;
+ }
+ eval {
+ $dom->detach_device($newxml, $flag);
+ };
+ if ($@) {
+ xCAT::SvrUtils::sendmsg([ 1, "detaching device from guest:$@" ], $callback, $node);
+ next;
+ } else {
+ $vmxml = $dom->get_xml_description();
+ if ($vmxml) {
+ $updatetable->{kvm_nodedata}->{$node}->{xml} = $vmxml;
+ }
+
+ eval {
+ $devobj->reattach();
+ };
+ if ($@) {
+ xCAT::SvrUtils::sendmsg([ 0, "reattaching device to host:$@" ], $callback, $node);
+ }
+
+ xCAT::SvrUtils::sendmsg([ 0, "devdetach: $devname detached from guest successfully " ], $callback, $node);
+ }
+
+ } else {
+
+ my $hostdevfound;
+ $hostdevfound = 0;
+ my $hostdevobj;
+ my $parsed = $parser->parse_string($vmxml);
+ my $ref = $parsed->findnodes("/domain/devices");
+
+ my @hostdevlist = $ref->[0]->findnodes("./hostdev");
+
+ #check whether the hostdev existed in guest xml
+ foreach my $hostdevref (@hostdevlist) {
+ my $devaddrref = $hostdevref->findnodes("./source/address");
+
+ my $domain = $devaddrref->[0]->getAttribute("domain");
+ my $bus = $devaddrref->[0]->getAttribute("bus");
+ my $slot = $devaddrref->[0]->getAttribute("slot");
+ my $function = $devaddrref->[0]->getAttribute("function");
+
+ my $curdevaddr = \%{ $devhash->{'capability'}->{'iommuGroup'}->{'address'} };
+
+
+ if (("$curdevaddr->{domain}" eq "$domain") and
+ ("$curdevaddr->{bus}" eq "$bus") and
+ ("$curdevaddr->{slot}" eq "$slot") and
+ ("$curdevaddr->{function}" eq "$function")) {
+
+ #hostdev existed in guest xml
+ $hostdevfound = 1;
+ $hostdevobj = $hostdevref;
+ goto PROCESS_HOSTDEV_XML_DETATCH;
+ }
+ }
+
+
+
+ PROCESS_HOSTDEV_XML_DETATCH:
+ if ($hostdevfound) {
+
+ #hostdev exist,remove it from guest xml
+ my $hostdevnode = $parser->parse_balanced_chunk($newxml);
+ $hostdevobj->parentNode()->removeChild($hostdevobj);
+ $vmxml = $parsed->toString;
+ $updatetable->{kvm_nodedata}->{$node}->{xml} = $vmxml;
+ xCAT::SvrUtils::sendmsg([ 0, "devdetach: $devname detached from guest $node successfully " ], $callback, $node);
+
+ } else {
+ xCAT::SvrUtils::sendmsg([ 1, "device detaching: the specified device $devname is not attached to $node yet" ], $callback, $node);
+ return;
+ }
+ }
+
+ }
+ }
}
}
sub get_disks_by_userspecs {
- my $specs = shift;
- my $xml = shift;
- my $returnmoddedxml=shift;
- my $struct = XMLin($xml,forcearray=>1);
- my $dominf = $parser->parse_string($xml);
- my @disknodes = $dominf->findnodes('/domain/devices/disk');
+ my $specs = shift;
+ my $xml = shift;
+ my $returnmoddedxml = shift;
+ my $struct = XMLin($xml, forcearray => 1);
+ my $dominf = $parser->parse_string($xml);
+ my @disknodes = $dominf->findnodes('/domain/devices/disk');
my @returnxmls;
foreach my $spec (@$specs) {
my $disknode;
foreach $disknode (@disknodes) {
if ($spec =~ /^.d./) { #vda, hdb, sdc, etc, match be equality to target->{dev}
if ($disknode->findnodes('./target')->[0]->getAttribute("dev") eq $spec) {
- push @returnxmls,[$disknode->toString(),$disknode->findnodes('./source')->[0]->getAttribute('file')];
- if ($returnmoddedxml) {
+ push @returnxmls, [ $disknode->toString(), $disknode->findnodes('./source')->[0]->getAttribute('file') ];
+ if ($returnmoddedxml) {
$disknode->parentNode->removeChild($disknode);
}
}
- } elsif ($spec =~ /^d(.*)/) { #delete by scsi unit number..
- my $loc=$1;
+ } elsif ($spec =~ /^d(.*)/) { #delete by scsi unit number..
+ my $loc = $1;
my $addr = $disknode->findnodes('./address')->[0];
- if ($loc =~ /:/) { #controller, bus, unit
+ if ($loc =~ /:/) { #controller, bus, unit
my $controller;
my $bus;
my $unit;
- ($controller,$bus,$unit) = split /:/,$loc;
+ ($controller, $bus, $unit) = split /:/, $loc;
if (hex($addr->getAttribute('controller')) == hex($controller) and ($addr->getAttribute('bus')) == hex($bus) and ($addr->getAttribute('unit')) == hex($unit)) {
- push @returnxmls,[$disknode->toString(),$disknode->findnodes('./source')->[0]->getAttribute('file')];
- if ($returnmoddedxml) {
+ push @returnxmls, [ $disknode->toString(), $disknode->findnodes('./source')->[0]->getAttribute('file') ];
+ if ($returnmoddedxml) {
$disknode->parentNode->removeChild($disknode);
}
}
-
+
} else { #match just on unit number, not helpful on ide as much generally, but whatever
if (hex($addr->getAttribute('unit')) == hex($loc)) {
- push @returnxmls,[$disknode->toString(),$disknode->findnodes('./source')->[0]->getAttribute('file')];
- if ($returnmoddedxml) {
+ push @returnxmls, [ $disknode->toString(), $disknode->findnodes('./source')->[0]->getAttribute('file') ];
+ if ($returnmoddedxml) {
$disknode->parentNode->removeChild($disknode);
}
}
}
- } elsif ($spec =~ /^v(.*)/) { #virtio pci selector
- my $slot=$1;
- $slot =~ s/^(.*)://; #remove pci bus number (not used for now)
- my $bus=$1;
+ } elsif ($spec =~ /^v(.*)/) { #virtio pci selector
+ my $slot = $1;
+ $slot =~ s/^(.*)://; #remove pci bus number (not used for now)
+ my $bus = $1;
$slot =~ s/\.0$//;
- my $addr=$disknode->findnodes('./address')->[0];
+ my $addr = $disknode->findnodes('./address')->[0];
if (hex($addr->getAttribute('slot')) == hex($slot) and hex($addr->getAttribute('bus') == hex($bus))) {
- push @returnxmls,[$disknode->toString(),$disknode->findnodes('./source')->[0]->getAttribute('file')];
- if ($returnmoddedxml) {
+ push @returnxmls, [ $disknode->toString(), $disknode->findnodes('./source')->[0]->getAttribute('file') ];
+ if ($returnmoddedxml) {
$disknode->parentNode->removeChild($disknode);
}
}
- } #other formats TBD
+ } #other formats TBD
}
}
- if ($returnmoddedxml) {#there are list entries to delete
- unshift @returnxmls,$dominf->toString();
+ if ($returnmoddedxml) { #there are list entries to delete
+ unshift @returnxmls, $dominf->toString();
}
return @returnxmls;
}
sub promote_vm_to_master {
- my %args=@_;
- my $target=$args{target};
- my $force=$args{force};
- my $detach=$args{detach};
- if ($target !~ m!://!) { #if not a url, use same place as source
+ my %args = @_;
+ my $target = $args{target};
+ my $force = $args{force};
+ my $detach = $args{detach};
+ if ($target !~ m!://!) { #if not a url, use same place as source
my $sourcedir = $confdata->{vm}->{$node}->[0]->{storage};
$sourcedir =~ s/=.*//;
$sourcedir =~ s/,.*//;
$sourcedir =~ s!/\z!!;
- $target = $sourcedir."/".$target;
+ $target = $sourcedir . "/" . $target;
}
unless ($target =~ /^nfs:\/\//) {
- xCAT::SvrUtils::sendmsg([1,"KVM plugin only has nfs://// support for cloning at this moment"], $callback,$node);
+ xCAT::SvrUtils::sendmsg([ 1, "KVM plugin only has nfs://// support for cloning at this moment" ], $callback, $node);
return;
}
my $dom;
eval {
- $dom = $hypconn->get_domain_by_name($node);
+ $dom = $hypconn->get_domain_by_name($node);
};
if ($dom and not $force) {
- xCAT::SvrUtils::sendmsg([1,"VM shut be shut down before attempting to clone (-f to copy unclean disks)"], $callback,$node);
+ xCAT::SvrUtils::sendmsg([ 1, "VM shut be shut down before attempting to clone (-f to copy unclean disks)" ], $callback, $node);
return;
}
my $xml;
if ($dom) {
- $xml = $dom->get_xml_description();
- $detach=1; #can't rebase if vm is on
+ $xml = $dom->get_xml_description();
+ $detach = 1; #can't rebase if vm is on
} else {
$xml = $confdata->{kvmnodedata}->{$node}->[0]->{xml};
}
unless ($xml) {
- xCAT::SvrUtils::sendmsg([1,"VM must be created before it can be cloned"], $callback,$node);
+ xCAT::SvrUtils::sendmsg([ 1, "VM must be created before it can be cloned" ], $callback, $node);
return;
}
my $parsedxml = $parser->parse_string($xml);
- my($tmpnod) = $parsedxml->findnodes('/domain/uuid/text()');
+ my ($tmpnod) = $parsedxml->findnodes('/domain/uuid/text()');
if ($tmpnod) {
- $tmpnod->setData("none"); #get rid of the VM specific uuid
+ $tmpnod->setData("none"); #get rid of the VM specific uuid
}
$target =~ m!^(.*)/([^/]*)\z!;
- my $directory=$1;
- my $mastername=$2;
+ my $directory = $1;
+ my $mastername = $2;
($tmpnod) = $parsedxml->findnodes('/domain/name/text()');
if ($tmpnod) {
$tmpnod->setData($mastername); #name the xml whatever the master name is to be
}
- foreach ($parsedxml->findnodes("/domain/devices/interface/mac")) { #clear all mac addresses
- if ($_->hasAttribute("address")) { $_->setAttribute("address"=>''); }
+ foreach ($parsedxml->findnodes("/domain/devices/interface/mac")) { #clear all mac addresses
+ if ($_->hasAttribute("address")) { $_->setAttribute("address" => ''); }
}
my $poolobj = get_storage_pool_by_url($directory);
unless ($poolobj) {
- xCAT::SvrUtils::sendmsg([1,"Unable to reach $directory from hypervisor"], $callback,$node);
+ xCAT::SvrUtils::sendmsg([ 1, "Unable to reach $directory from hypervisor" ], $callback, $node);
return;
}
- #arguments validated, on with our lives
+
+#arguments validated, on with our lives
#firrder of business, calculate all the image names to be created and ensure none will conflict.
my @disks = $parsedxml->findnodes('/domain/devices/disk/source');
my %volclonemap;
foreach (@disks) {
my $filename = $_->getAttribute('file');
- my $volname = $filename;
- $volname =~ s!.*/!!; #perl is greedy by default
+ my $volname = $filename;
+ $volname =~ s!.*/!!; #perl is greedy by default
$volname =~ s/^$node/$mastername/;
my $novol;
eval { #use two evals, there is a chance the pool has a task blocking refresh like long-running clone.... libvirt should do better IMO, oh well
@@ -2528,7 +2610,7 @@ sub promote_vm_to_master {
$novol = $poolobj->get_volume_by_name($volname);
};
if ($novol) {
- xCAT::SvrUtils::sendmsg([1,"$volname already exists in target storage pool"], $callback,$node);
+ xCAT::SvrUtils::sendmsg([ 1, "$volname already exists in target storage pool" ], $callback, $node);
return;
}
my $sourcevol;
@@ -2536,131 +2618,133 @@ sub promote_vm_to_master {
$sourcevol = $hypconn->get_storage_volume_by_path($filename);
};
unless ($sourcevol) {
- xCAT::SvrUtils::sendmsg([1,"Unable to access $filename to clone"], $callback,$node);
+ xCAT::SvrUtils::sendmsg([ 1, "Unable to access $filename to clone" ], $callback, $node);
return;
}
- $volclonemap{$filename}=[$sourcevol,$volname];
+ $volclonemap{$filename} = [ $sourcevol, $volname ];
$filename = get_path_for_pool($poolobj);
$filename =~ s!/\z!!;
- $filename .= '/'.$volname;
- $_->setAttribute(file=>$filename);
+ $filename .= '/' . $volname;
+ $_->setAttribute(file => $filename);
}
foreach (keys %volclonemap) {
my $sourcevol = $volclonemap{$_}->[0];
- my $targname = $volclonemap{$_}->[1];
+ my $targname = $volclonemap{$_}->[1];
my $format;
$targname =~ /([^\.]*)$/;
- $format=$1;
+ $format = $1;
my $newvol;
- my %sourceinfo = %{$sourcevol->get_info()};
- my $targxml = "$targname".$sourceinfo{capacity}."";
- xCAT::SvrUtils::sendmsg("Cloning ".$sourcevol->get_name()." (currently is ".($sourceinfo{allocation}/1048576)." MB and has a capacity of ".($sourceinfo{capacity}/1048576)."MB)",$callback,$node);
+ my %sourceinfo = %{ $sourcevol->get_info() };
+ my $targxml = "$targname" . $sourceinfo{capacity} . "";
+ xCAT::SvrUtils::sendmsg("Cloning " . $sourcevol->get_name() . " (currently is " . ($sourceinfo{allocation} / 1048576) . " MB and has a capacity of " . ($sourceinfo{capacity} / 1048576) . "MB)", $callback, $node);
eval {
- $newvol =$poolobj->clone_volume($targxml,$sourcevol);
+ $newvol = $poolobj->clone_volume($targxml, $sourcevol);
};
if ($newvol) {
- %sourceinfo = %{$newvol->get_info()};
- xCAT::SvrUtils::sendmsg("Cloning of ".$sourcevol->get_name()." complete (clone uses ".($sourceinfo{allocation}/1048576)." for a disk size of ".($sourceinfo{capacity}/1048576)."MB)",$callback,$node);
+ %sourceinfo = %{ $newvol->get_info() };
+ xCAT::SvrUtils::sendmsg("Cloning of " . $sourcevol->get_name() . " complete (clone uses " . ($sourceinfo{allocation} / 1048576) . " for a disk size of " . ($sourceinfo{capacity} / 1048576) . "MB)", $callback, $node);
unless ($detach) {
my $rebasepath = $sourcevol->get_path();
my $rebasename = $sourcevol->get_name();
my $rebasepool = get_storage_pool_by_volume($sourcevol);
unless ($rebasepool) {
- xCAT::SvrUtils::sendmsg([1,"Skipping rebase of $rebasename, unable to find correct storage pool"],$callback,$node);
+ xCAT::SvrUtils::sendmsg([ 1, "Skipping rebase of $rebasename, unable to find correct storage pool" ], $callback, $node);
next;
}
- xCAT::SvrUtils::sendmsg("Rebasing $rebasename from master",$callback,$node);
+ xCAT::SvrUtils::sendmsg("Rebasing $rebasename from master", $callback, $node);
$sourcevol->delete();
- my $newbasexml="$rebasename".$sourceinfo{capacity}."".$newvol->get_path()."";
+ my $newbasexml = "$rebasename" . $sourceinfo{capacity} . "" . $newvol->get_path() . "";
my $newbasevol;
eval {
$newbasevol = $rebasepool->create_volume($newbasexml);
};
if ($newbasevol) {
- xCAT::SvrUtils::sendmsg("Rebased $rebasename from master",$callback,$node);
+ xCAT::SvrUtils::sendmsg("Rebased $rebasename from master", $callback, $node);
} else {
- xCAT::SvrUtils::sendmsg([1,"Critical failure, rebasing process failed halfway through, source VM trashed"],$callback,$node);
+ xCAT::SvrUtils::sendmsg([ 1, "Critical failure, rebasing process failed halfway through, source VM trashed" ], $callback, $node);
}
}
} else {
- xCAT::SvrUtils::sendmsg([1,"Cloning of ".$sourcevol->get_name()." failed due to ". $@],$callback,$node);
+ xCAT::SvrUtils::sendmsg([ 1, "Cloning of " . $sourcevol->get_name() . " failed due to " . $@ ], $callback, $node);
return;
}
}
- my $mastertabentry={};
+ my $mastertabentry = {};
foreach (qw/os arch profile/) {
- if (defined ($confdata->{nodetype}->{$node}->[0]->{$_})) {
- $mastertabentry->{$_}=$confdata->{nodetype}->{$node}->[0]->{$_};
+ if (defined($confdata->{nodetype}->{$node}->[0]->{$_})) {
+ $mastertabentry->{$_} = $confdata->{nodetype}->{$node}->[0]->{$_};
}
}
foreach (qw/storagemodel nics/) {
- if (defined ($confdata->{vm}->{$node}->[0]->{$_})) {
- $mastertabentry->{$_}=$confdata->{vm}->{$node}->[0]->{$_};
+ if (defined($confdata->{vm}->{$node}->[0]->{$_})) {
+ $mastertabentry->{$_} = $confdata->{vm}->{$node}->[0]->{$_};
}
}
- $mastertabentry->{storage}=$directory;
- $mastertabentry->{vintage}=localtime;
- $mastertabentry->{originator}=$requester;
+ $mastertabentry->{storage} = $directory;
+ $mastertabentry->{vintage} = localtime;
+ $mastertabentry->{originator} = $requester;
unless ($detach) {
- $updatetable->{vm}->{$node}->{master}=$mastername;
+ $updatetable->{vm}->{$node}->{master} = $mastername;
}
- $updatetable->{vmmaster}->{$mastername}=$mastertabentry;
+ $updatetable->{vmmaster}->{$mastername} = $mastertabentry;
$updatetable->{kvm_masterdata}->{$mastername}->{xml} = $parsedxml->toString();
}
+
sub clonevm {
- shift; #throw away node
- @ARGV=@_;
+ shift; #throw away node
+ @ARGV = @_;
my $target;
my $base;
my $detach;
my $force;
GetOptions(
- 'f' => \$force,
+ 'f' => \$force,
'b=s' => \$base,
't=s' => \$target,
- 'd' => \$detach,
+ 'd' => \$detach,
);
if ($base and $target) {
- xCAT::SvrUtils::sendmsg([1,"Cannot specify both base (-b) and target (-t)"], $callback,$node);
+ xCAT::SvrUtils::sendmsg([ 1, "Cannot specify both base (-b) and target (-t)" ], $callback, $node);
return;
}
- if ($target) { #we need to take a single vm and create a master out of it
- return promote_vm_to_master(target=>$target,force=>$force,detach=>$detach);
+ if ($target) { #we need to take a single vm and create a master out of it
+ return promote_vm_to_master(target => $target, force => $force, detach => $detach);
} elsif ($base) {
- return clone_vm_from_master(base=>$base,detach=>$detach);
+ return clone_vm_from_master(base => $base, detach => $detach);
}
}
sub clone_vm_from_master {
- my %args = @_;
- my $base=$args{base};
- my $detach=$args{detach};
- my $vmmastertab=xCAT::Table->new('vmmaster',-create=>0);
- my $kvmmastertab = xCAT::Table->new('kvm_masterdata',-create=>0);
+ my %args = @_;
+ my $base = $args{base};
+ my $detach = $args{detach};
+ my $vmmastertab = xCAT::Table->new('vmmaster', -create => 0);
+ my $kvmmastertab = xCAT::Table->new('kvm_masterdata', -create => 0);
unless ($vmmastertab and $kvmmastertab) {
- xCAT::SvrUtils::sendmsg([1,"No KVM master images in tables"], $callback,$node);
+ xCAT::SvrUtils::sendmsg([ 1, "No KVM master images in tables" ], $callback, $node);
return;
}
- my $mastername=$base;
- $mastername=~s!.*/!!; #shouldn't be needed, as storage is in there, but just in case
- my $masteref=$vmmastertab->getAttribs({name=>$mastername},[qw/os arch profile storage storagemodel nics/]);
- my $kvmmasteref=$kvmmastertab->getAttribs({name=>$mastername},['xml']);
+ my $mastername = $base;
+ $mastername =~ s!.*/!!; #shouldn't be needed, as storage is in there, but just in case
+ my $masteref = $vmmastertab->getAttribs({ name => $mastername }, [qw/os arch profile storage storagemodel nics/]);
+ my $kvmmasteref = $kvmmastertab->getAttribs({ name => $mastername }, ['xml']);
unless ($masteref and $kvmmasteref) {
- xCAT::SvrUtils::sendmsg([1,"KVM master $mastername not found in tables"], $callback,$node);
+ xCAT::SvrUtils::sendmsg([ 1, "KVM master $mastername not found in tables" ], $callback, $node);
return;
}
my $newnodexml = $parser->parse_string($kvmmasteref->{xml});
$newnodexml->findnodes("/domain/name/text()")->[0]->setData($node); #set name correctly
- my $uuid=getNodeUUID($node);
+ my $uuid = getNodeUUID($node);
$newnodexml->findnodes("/domain/uuid/text()")->[0]->setData($uuid); #put in correct uuid
- #set up mac addresses and such right...
- fixup_clone_network(mastername=>$mastername,mastertableentry=>$masteref,kvmmastertableentry=>$kvmmasteref,xmlinprogress=>$newnodexml);
+ #set up mac addresses and such right...
+ fixup_clone_network(mastername => $mastername, mastertableentry => $masteref, kvmmastertableentry => $kvmmasteref, xmlinprogress => $newnodexml);
+
#ok, now the fun part, storage...
my $disk;
if ($masteref->{storage}) {
- foreach (split /,/,$masteref->{storage}) {
- s/=.*//;
- get_storage_pool_by_url($_);
+ foreach (split /,/, $masteref->{storage}) {
+ s/=.*//;
+ get_storage_pool_by_url($_);
}
}
my $url;
@@ -2671,259 +2755,265 @@ sub clone_vm_from_master {
$url = $confdata->{vm}->{$node}->[0]->{storage};
} else {
$url = $masteref->{storage};
- $updatetable->{vm}->{$node}->{storage}=$url;
+ $updatetable->{vm}->{$node}->{storage} = $url;
}
if ($masteref->{storagemodel} and not $confdata->{vm}->{$node}->[0]->{storagemodel}) {
- $updatetable->{vm}->{$node}->{storagemodel}=$masteref->{storagemodel};
+ $updatetable->{vm}->{$node}->{storagemodel} = $masteref->{storagemodel};
}
$url =~ s/,.*//;
my $destinationpool = get_storage_pool_by_url($url);
foreach $disk ($newnodexml->findnodes("/domain/devices/disk")) {
- my ($source) = ($disk->findnodes("./source"));
- unless ($source) { next; } #most likely an empty cdrom
+ my ($source) = ($disk->findnodes("./source"));
+ unless ($source) { next; } #most likely an empty cdrom
my $srcfilename = $source->getAttribute("file");
- my $filename = $srcfilename;
+ my $filename = $srcfilename;
$filename =~ s/^.*$mastername/$node/;
$filename =~ m!\.([^\.]*)\z!;
- my $format=$1;
+ my $format = $1;
my $newvol;
+
if ($detach) {
- my $sourcevol = $hypconn->get_storage_volume_by_path($srcfilename);
- my %sourceinfo = %{$sourcevol->get_info()};
- my $targxml = "$filename".$sourceinfo{capacity}."";
- xCAT::SvrUtils::sendmsg("Cloning ".$sourcevol->get_name()." (currently is ".($sourceinfo{allocation}/1048576)." MB and has a capacity of ".($sourceinfo{capacity}/1048576)."MB)",$callback,$node);
+ my $sourcevol = $hypconn->get_storage_volume_by_path($srcfilename);
+ my %sourceinfo = %{ $sourcevol->get_info() };
+ my $targxml = "$filename" . $sourceinfo{capacity} . "";
+ xCAT::SvrUtils::sendmsg("Cloning " . $sourcevol->get_name() . " (currently is " . ($sourceinfo{allocation} / 1048576) . " MB and has a capacity of " . ($sourceinfo{capacity} / 1048576) . "MB)", $callback, $node);
eval {
- $newvol =$destinationpool->clone_volume($targxml,$sourcevol);
+ $newvol = $destinationpool->clone_volume($targxml, $sourcevol);
};
- if ($@) {
- if ($@ =~ /already exists/) {
- return 1,"Storage creation request conflicts with existing file(s)";
- } else {
- return 1,"Unknown issue $@";
- }
- }
+ if ($@) {
+ if ($@ =~ /already exists/) {
+ return 1, "Storage creation request conflicts with existing file(s)";
+ } else {
+ return 1, "Unknown issue $@";
+ }
+ }
} else {
- my $sourcevol = $hypconn->get_storage_volume_by_path($srcfilename);
- my %sourceinfo = %{$sourcevol->get_info()};
- my $newbasexml="$filename".$sourceinfo{capacity}."$srcfilename";
- eval {
- $newvol = $destinationpool->create_volume($newbasexml);
- };
- if ($@) {
- if ($@ =~ /already in use/) {
- return 1,"Storage creation request conflicts with existing file(s)";
- } else {
- return 1,"Unknown issue $@";
- }
- }
- $updatetable->{vm}->{$node}->{master}=$mastername;
+ my $sourcevol = $hypconn->get_storage_volume_by_path($srcfilename);
+ my %sourceinfo = %{ $sourcevol->get_info() };
+ my $newbasexml = "$filename" . $sourceinfo{capacity} . "$srcfilename";
+ eval {
+ $newvol = $destinationpool->create_volume($newbasexml);
+ };
+ if ($@) {
+ if ($@ =~ /already in use/) {
+ return 1, "Storage creation request conflicts with existing file(s)";
+ } else {
+ return 1, "Unknown issue $@";
+ }
+ }
+ $updatetable->{vm}->{$node}->{master} = $mastername;
}
- my $newfilename=$newvol->get_path();
- $disk->findnodes("./source")->[0]->setAttribute("file"=>$newfilename);
- if (not $detach) { #if we are a copied image, enable writethrough cache in order to reduce trips out to disk
- #but if the format is not qcow2, still leave it at 'none'
- my $type = $disk->findnodes("./driver")->[0]->getAttribute("type");
- if ($type eq "qcow2") { $disk->findnodes("./driver")->[0]->setAttribute("cache"=>"writethrough"); }
- }
-
+ my $newfilename = $newvol->get_path();
+ $disk->findnodes("./source")->[0]->setAttribute("file" => $newfilename);
+ if (not $detach) { #if we are a copied image, enable writethrough cache in order to reduce trips out to disk
+ #but if the format is not qcow2, still leave it at 'none'
+ my $type = $disk->findnodes("./driver")->[0]->getAttribute("type");
+ if ($type eq "qcow2") { $disk->findnodes("./driver")->[0]->setAttribute("cache" => "writethrough"); }
+ }
+
}
- my $textxml=$newnodexml->toString();
- $updatetable->{kvm_nodedata}->{$node}->{xml}=$textxml;
+ my $textxml = $newnodexml->toString();
+ $updatetable->{kvm_nodedata}->{$node}->{xml} = $textxml;
}
sub fixup_clone_network {
- my %args = @_;
- my $newnodexml = $args{xmlinprogress};
- my $mastername=$args{mastername};
- my $masteref=$args{mastertableentry};
- my $kvmmasteref=$args{kvmmastertableentry};
- unless (ref ($confdata->{vm}->{$node})) {
- $confdata->{vm}->{$node}=[{nics=>$masteref->{nics}}];
- $updatetable->{vm}->{$node}->{nics}=$masteref->{nics};
+ my %args = @_;
+ my $newnodexml = $args{xmlinprogress};
+ my $mastername = $args{mastername};
+ my $masteref = $args{mastertableentry};
+ my $kvmmasteref = $args{kvmmastertableentry};
+ unless (ref($confdata->{vm}->{$node})) {
+ $confdata->{vm}->{$node} = [ { nics => $masteref->{nics} } ];
+ $updatetable->{vm}->{$node}->{nics} = $masteref->{nics};
}
unless ($confdata->{vm}->{$node}->[0]->{nics}) { #if no nic configuration yet, take the one stored in the master
- $confdata->{vm}->{$node}->[0]->{nics}=$masteref->{nics};
- $updatetable->{vm}->{$node}->{nics}=$masteref->{nics};
+ $confdata->{vm}->{$node}->[0]->{nics} = $masteref->{nics};
+ $updatetable->{vm}->{$node}->{nics} = $masteref->{nics};
}
my @nics;
if ($confdata->{vm}->{$node}->[0]->{nics}) { #could still be empty if it came from master that way
- @nics = split /,/,$confdata->{vm}->{$node}->[0]->{nics};
+ @nics = split /,/, $confdata->{vm}->{$node}->[0]->{nics};
}
my @nicsinmaster = $newnodexml->findnodes("/domain/devices/interface");
if (scalar @nicsinmaster > scalar @nics) { #we don't have enough places to attach nics to..
- xCAT::SvrUtils::sendmsg([1,"KVM master $mastername has ".scalar @nicsinmaster." but this vm only has ".scalar @nics." defined"], $callback,$node);
+ xCAT::SvrUtils::sendmsg([ 1, "KVM master $mastername has " . scalar @nicsinmaster . " but this vm only has " . scalar @nics . " defined" ], $callback, $node);
return;
}
my $nicstruct;
- my @macs=xCAT::VMCommon::getMacAddresses($confdata,$node,scalar @nics);
+ my @macs = xCAT::VMCommon::getMacAddresses($confdata, $node, scalar @nics);
foreach $nicstruct (@nicsinmaster) {
my $bridge = shift @nics;
$bridge =~ s/.*://;
$bridge =~ s/=.*//;
- $nicstruct->findnodes("./mac")->[0]->setAttribute("address"=>shift @macs);
- $nicstruct->findnodes("./source")->[0]->setAttribute("bridge"=>$bridge);
+ $nicstruct->findnodes("./mac")->[0]->setAttribute("address" => shift @macs);
+ $nicstruct->findnodes("./source")->[0]->setAttribute("bridge" => $bridge);
}
my $nic;
- my $deviceroot=$newnodexml->findnodes("/domain/devices")->[0];
- foreach $nic (@nics) { #need more xml to throw at it..
+ my $deviceroot = $newnodexml->findnodes("/domain/devices")->[0];
+ foreach $nic (@nics) { #need more xml to throw at it..
my $type = 'virtio'; #better default fake nic than rtl8139, relevant to most
- $nic =~ s/.*://; #the detail of how the bridge was built is of no
- #interest to this segment of code
+ $nic =~ s/.*://; #the detail of how the bridge was built is of no
+ #interest to this segment of code
if ($confdata->{vm}->{$node}->[0]->{nicmodel}) {
$type = $confdata->{vm}->{$node}->[0]->{nicmodel};
}
if ($nic =~ /=/) {
- ($nic,$type) = split /=/,$nic,2;
+ ($nic, $type) = split /=/, $nic, 2;
}
- my $xmlsnippet = "";
+ my $xmlsnippet = "";
my $chunk = $parser->parse_balanced_chunk($xmlsnippet);
$deviceroot->appendChild($chunk);
}
}
+
sub mkvm {
- shift; #Throuw away first argument
- @ARGV=@_;
- my $disksize;
- my $mastername;
- my $force=0;
- require Getopt::Long;
- my $memory;
- my $cpucount;
- GetOptions(
- 'master|m=s'=>\$mastername,
- 'size|s=s'=>\$disksize,
- "mem=s"=>\$memory,
- "cpus=s" => \$cpucount,
- 'force|f'=>\$force
- );
- if (defined $confdata->{vm}->{$node}->[0]->{storage}) {
- my $diskname=$confdata->{vm}->{$node}->[0]->{storage};
- if ($diskname =~ /^phy:/) { #in this case, mkvm should have no argumens
+ shift; #Throuw away first argument
+ @ARGV = @_;
+ my $disksize;
+ my $mastername;
+ my $force = 0;
+ require Getopt::Long;
+ my $memory;
+ my $cpucount;
+ GetOptions(
+ 'master|m=s' => \$mastername,
+ 'size|s=s' => \$disksize,
+ "mem=s" => \$memory,
+ "cpus=s" => \$cpucount,
+ 'force|f' => \$force
+ );
+ if (defined $confdata->{vm}->{$node}->[0]->{storage}) {
+ my $diskname = $confdata->{vm}->{$node}->[0]->{storage};
+ if ($diskname =~ /^phy:/) { #in this case, mkvm should have no argumens
+ if ($mastername or $disksize) {
+ return 1, "mkvm management of block device storage not implemented";
+ }
+ }
+
+ #print "force=$force\n";
+ my @return;
if ($mastername or $disksize) {
- return 1,"mkvm management of block device storage not implemented";
+ eval {
+ @return = createstorage($diskname, $mastername, $disksize, $confdata->{vm}->{$node}->[0], $force);
+ };
+ if ($@) {
+ if ($@ =~ /ath already exists/) {
+ return 1, "Storage creation request conflicts with existing file(s)";
+ } else {
+ return 1, "Unknown issue $@";
+ }
+ }
+
+ unless ($confdata->{kvmnodedata}->{$node} and $confdata->{kvmnodedata}->{$node}->[0] and $confdata->{kvmnodedata}->{$node}->[0]->{xml}) {
+ my $xml;
+ $xml = build_xmldesc($node, cpus => $cpucount, memory => $memory);
+ $updatetable->{kvm_nodedata}->{$node}->{xml} = $xml;
+ }
+ }
+ my $xml;
+ if ($confdata->{kvmnodedata}->{$node} and $confdata->{kvmnodedata}->{$node}->[0] and $confdata->{kvmnodedata}->{$node}->[0]->{xml}) {
+ $xml = $confdata->{kvmnodedata}->{$node}->[0]->{xml};
+ } else { # ($confdata->{kvmnodedata}->{$node} and $confdata->{kvmnodedata}->{$node}->[0] and $confdata->{kvmnodedata}->{$node}->[0]->{xml}) {
+ $xml = build_xmldesc($node, cpus => $cpucount, memory => $memory);
+ $updatetable->{kvm_nodedata}->{$node}->{xml} = $xml;
+ }
+ if ($::XCATSITEVALS{persistkvmguests}) {
+ $hypconn->define_domain($xml);
+ }
+ return @return;
+ } else {
+ if ($mastername or $disksize) {
+ return 1, "Requested initialization of storage, but vm.storage has no value for node";
}
}
- #print "force=$force\n";
- my @return;
- if ($mastername or $disksize) {
- eval {
- @return = createstorage($diskname,$mastername,$disksize,$confdata->{vm}->{$node}->[0],$force);
- };
- if ($@) {
- if ($@ =~ /ath already exists/) {
- return 1,"Storage creation request conflicts with existing file(s)";
- } else {
- return 1,"Unknown issue $@";
- }
- }
-
- unless ($confdata->{kvmnodedata}->{$node} and $confdata->{kvmnodedata}->{$node}->[0] and $confdata->{kvmnodedata}->{$node}->[0]->{xml}) {
- my $xml;
- $xml = build_xmldesc($node,cpus=>$cpucount,memory=>$memory);
- $updatetable->{kvm_nodedata}->{$node}->{xml}=$xml;
- }
- }
- my $xml;
- if ($confdata->{kvmnodedata}->{$node} and $confdata->{kvmnodedata}->{$node}->[0] and $confdata->{kvmnodedata}->{$node}->[0]->{xml}) {
- $xml = $confdata->{kvmnodedata}->{$node}->[0]->{xml};
- } else { # ($confdata->{kvmnodedata}->{$node} and $confdata->{kvmnodedata}->{$node}->[0] and $confdata->{kvmnodedata}->{$node}->[0]->{xml}) {
- $xml = build_xmldesc($node,cpus=>$cpucount,memory=>$memory);
- $updatetable->{kvm_nodedata}->{$node}->{xml}=$xml;
- }
- if ($::XCATSITEVALS{persistkvmguests}) {
- $hypconn->define_domain($xml);
- }
- return @return;
- } else {
- if ($mastername or $disksize) {
- return 1,"Requested initialization of storage, but vm.storage has no value for node";
- }
- }
}
+
sub power {
- @ARGV=@_;
+ @ARGV = @_;
require Getopt::Long;
my $cdloc;
- GetOptions('cdrom|iso|c|i=s'=>\$cdloc);
+ GetOptions('cdrom|iso|c|i=s' => \$cdloc);
my $subcommand = shift @ARGV;
my $retstring;
my $dom;
eval {
- $dom = $hypconn->get_domain_by_name($node);
+ $dom = $hypconn->get_domain_by_name($node);
};
if ($subcommand eq "boot") {
- my $currstate=getpowstate($dom);
- $retstring=$currstate." ";
+ my $currstate = getpowstate($dom);
+ $retstring = $currstate . " ";
if ($currstate eq "off") {
- $subcommand="on";
+ $subcommand = "on";
} elsif ($currstate eq "on") {
- $subcommand="reset";
+ $subcommand = "reset";
}
}
my $errstr;
if ($subcommand eq 'on') {
unless ($dom) {
if ($use_xhrm) {
- if (xhrm_satisfy($node,$hyp)) {
- return (1,"Failure satisfying networking and storage requirements on $hyp for $node");
- }
+ if (xhrm_satisfy($node, $hyp)) {
+ return (1, "Failure satisfying networking and storage requirements on $hyp for $node");
+ }
}
+
#TODO: here, storage validation is not necessarily performed, consequently, must explicitly do storage validation
#this worked before I started doing the offline xml store because every rpower on tried to rebuild
- ($dom,$errstr) = makedom($node,$cdloc);
- if ($errstr) { return (1,$errstr); }
+ ($dom, $errstr) = makedom($node, $cdloc);
+ if ($errstr) { return (1, $errstr); }
} elsif (not $dom->is_active()) {
- $dom->create();
+ $dom->create();
} else {
- $retstring .= "$status_noop";
+ $retstring .= "$status_noop";
}
} elsif ($subcommand eq 'off') {
if ($dom) {
- my $newxml=$dom->get_xml_description();
- $updatetable->{kvm_nodedata}->{$node}->{xml}=$newxml;
- if ($dom->is_active()) {
- $dom->destroy();
- }
+ my $newxml = $dom->get_xml_description();
+ $updatetable->{kvm_nodedata}->{$node}->{xml} = $newxml;
+ if ($dom->is_active()) {
+ $dom->destroy();
+ }
undef $dom;
} else { $retstring .= "$status_noop"; }
} elsif ($subcommand eq 'softoff') {
if ($dom) {
- my $newxml=$dom->get_xml_description();
- $updatetable->{kvm_nodedata}->{$node}->{xml}=$newxml;
+ my $newxml = $dom->get_xml_description();
+ $updatetable->{kvm_nodedata}->{$node}->{xml} = $newxml;
$dom->shutdown();
- } else { $retstring .= "$status_noop"; }
+ } else { $retstring .= "$status_noop"; }
} elsif ($subcommand eq 'reset') {
if ($dom && $dom->is_active()) {
- my $oldxml=$dom->get_xml_description();
- my $newxml=reconfigvm($node,$oldxml);
- #This *was* to be clever, but libvirt doesn't even frontend the capability, great...
- unless ($newxml) { $newxml=$oldxml; } #TODO: remove this when the 'else' line can be sanely filled out
- if ($newxml) { #need to destroy and repower..
- $updatetable->{kvm_nodedata}->{$node}->{xml}=$newxml;
- my $persist = $dom->is_persistent();
+ my $oldxml = $dom->get_xml_description();
+ my $newxml = reconfigvm($node, $oldxml);
+
+#This *was* to be clever, but libvirt doesn't even frontend the capability, great...
+ unless ($newxml) { $newxml = $oldxml; } #TODO: remove this when the 'else' line can be sanely filled out
+ if ($newxml) { #need to destroy and repower..
+ $updatetable->{kvm_nodedata}->{$node}->{xml} = $newxml;
+ my $persist = $dom->is_persistent();
$dom->destroy();
- if ($persist) { $dom->undefine(); }
+ if ($persist) { $dom->undefine(); }
undef $dom;
if ($use_xhrm) {
- xhrm_satisfy($node,$hyp);
+ xhrm_satisfy($node, $hyp);
}
- ($dom,$errstr) = makedom($node,$cdloc,$newxml);
- if ($errstr) { return (1,$errstr); }
+ ($dom, $errstr) = makedom($node, $cdloc, $newxml);
+ if ($errstr) { return (1, $errstr); }
} else { #no changes, just restart the domain TODO when possible, stupid lack of feature...
}
- $retstring.="reset";
- } else { $retstring .= "$status_noop"; }
- } else {
+ $retstring .= "reset";
+ } else { $retstring .= "$status_noop"; }
+ } else {
unless ($subcommand =~ /^stat/) {
- return (1,"Unsupported power directive '$subcommand'");
+ return (1, "Unsupported power directive '$subcommand'");
}
}
unless ($retstring =~ /reset/) {
- $retstring=$retstring.getpowstate($dom);
+ $retstring = $retstring . getpowstate($dom);
}
- return (0,$retstring);
+ return (0, $retstring);
}
sub lsvm {
@@ -2931,39 +3021,40 @@ sub lsvm {
my @doms = $hypconn->list_domains();
my @vms;
foreach (@doms) {
- push @vms,$_->get_name();
+ push @vms, $_->get_name();
}
- return (0,@vms);
+ return (0, @vms);
}
sub guestcmd {
- $hyp = shift;
- $node = shift;
- my $command = shift;
- my @args = @_;
- my $error;
- if ($command eq "rpower") {
- return power(@args);
- } elsif ($command eq "mkvm") {
- return mkvm($node,@args);
- } elsif ($command eq "clonevm") {
- return clonevm($node,@args);
- } elsif ($command eq "chvm") {
- return chvm($node,@args);
- } elsif ($command eq "rmvm") {
- return rmvm($node,@args);
- } elsif ($command eq "rinv") {
- return rinv($node,@args);
- } elsif ($command eq "rmigrate") {
- return migrate($node,@args);
- } elsif ($command eq "getrvidparms") {
- return getrvidparms($node,@args);
- } elsif ($command eq "getcons") {
- return getcons($node,@args);
- } elsif ($command eq "lsvm") {
- return lsvm($node,@args);
- }
+ $hyp = shift;
+ $node = shift;
+ my $command = shift;
+ my @args = @_;
+ my $error;
+ if ($command eq "rpower") {
+ return power(@args);
+ } elsif ($command eq "mkvm") {
+ return mkvm($node, @args);
+ } elsif ($command eq "clonevm") {
+ return clonevm($node, @args);
+ } elsif ($command eq "chvm") {
+ return chvm($node, @args);
+ } elsif ($command eq "rmvm") {
+ return rmvm($node, @args);
+ } elsif ($command eq "rinv") {
+ return rinv($node, @args);
+ } elsif ($command eq "rmigrate") {
+ return migrate($node, @args);
+ } elsif ($command eq "getrvidparms") {
+ return getrvidparms($node, @args);
+ } elsif ($command eq "getcons") {
+ return getcons($node, @args);
+ } elsif ($command eq "lsvm") {
+ return lsvm($node, @args);
+ }
+
=cut
} elsif ($command eq "rvitals") {
return vitals(@args);
@@ -2986,631 +3077,648 @@ sub guestcmd {
}
=cut
- return (1,"$command not a supported command by kvm method");
+
+ return (1, "$command not a supported command by kvm method");
}
-sub preprocess_request {
- my $request = shift;
- if ($request->{_xcatpreprocessed}->[0] == 1) { return [$request]; }
- my $callback=shift;
- my @requests;
+sub preprocess_request {
+ my $request = shift;
+ if ($request->{_xcatpreprocessed}->[0] == 1) { return [$request]; }
+ my $callback = shift;
+ my @requests;
- my $noderange = $request->{node}; #Should be arrayref
- my $command = $request->{command}->[0];
- my $extrargs = $request->{arg};
- my @exargs=($request->{arg});
- if (ref($extrargs)) {
- @exargs=@$extrargs;
- }
+ my $noderange = $request->{node}; #Should be arrayref
+ my $command = $request->{command}->[0];
+ my $extrargs = $request->{arg};
+ my @exargs = ($request->{arg});
+ if (ref($extrargs)) {
+ @exargs = @$extrargs;
+ }
- my $usage_string=xCAT::Usage->parseCommand($command, @exargs);
- if ($usage_string) {
- $callback->({data=>$usage_string});
- $request = {};
- return;
- }
+ my $usage_string = xCAT::Usage->parseCommand($command, @exargs);
+ if ($usage_string) {
+ $callback->({ data => $usage_string });
+ $request = {};
+ return;
+ }
- if (!$noderange) {
- $usage_string=xCAT::Usage->getUsage($command);
- $callback->({data=>$usage_string});
- $request = {};
- return;
- }
-
- #print "noderange=@$noderange\n";
+ if (!$noderange) {
+ $usage_string = xCAT::Usage->getUsage($command);
+ $callback->({ data => $usage_string });
+ $request = {};
+ return;
+ }
- # find service nodes for requested nodes
- # build an individual request for each service node
- my $service = "xcat";
- my $sn = xCAT::ServiceNodeUtils->get_ServiceNode($noderange, $service, "MN");
+ #print "noderange=@$noderange\n";
- # build each request for each service node
+ # find service nodes for requested nodes
+ # build an individual request for each service node
+ my $service = "xcat";
+ my $sn = xCAT::ServiceNodeUtils->get_ServiceNode($noderange, $service, "MN");
- foreach my $snkey (keys %$sn)
- {
- #print "snkey=$snkey\n";
- my $reqcopy = {%$request};
- $reqcopy->{node} = $sn->{$snkey};
- $reqcopy->{'_xcatdest'} = $snkey;
- $reqcopy->{_xcatpreprocessed}->[0] = 1;
- push @requests, $reqcopy;
- }
- return \@requests;
+ # build each request for each service node
+
+ foreach my $snkey (keys %$sn)
+ {
+ #print "snkey=$snkey\n";
+ my $reqcopy = {%$request};
+ $reqcopy->{node} = $sn->{$snkey};
+ $reqcopy->{'_xcatdest'} = $snkey;
+ $reqcopy->{_xcatpreprocessed}->[0] = 1;
+ push @requests, $reqcopy;
+ }
+ return \@requests;
}
-
-
+
+
sub adopt {
- my $orphash = shift;
- my $hyphash = shift;
+ my $orphash = shift;
+ my $hyphash = shift;
my %addmemory = ();
my $node;
my $target;
my $vmupdates;
foreach $node (keys %{$orphash}) {
- $target=pick_target($node,\%addmemory);
+ $target = pick_target($node, \%addmemory);
unless ($target) {
next;
}
if ($confdata->{vm}->{$node}->[0]->{memory}) {
- $addmemory{$target}+=getUnits($confdata->{vm}->{$node}->[0]->{memory},"M",1024);
+ $addmemory{$target} += getUnits($confdata->{vm}->{$node}->[0]->{memory}, "M", 1024);
} else {
- $addmemory{$target}+=getUnits("4096","M",1024);
+ $addmemory{$target} += getUnits("4096", "M", 1024);
}
- $hyphash{$target}->{nodes}->{$node}=1;
+ $hyphash{$target}->{nodes}->{$node} = 1;
delete $orphash->{$node};
- $vmupdates->{$node}->{host}=$target;
+ $vmupdates->{$node}->{host} = $target;
}
- unless ($vmtab) { $vmtab = new xCAT::Table('vm',-create=>1); }
+ unless ($vmtab) { $vmtab = new xCAT::Table('vm', -create => 1); }
$vmtab->setNodesAttribs($vmupdates);
if (keys %{$orphash}) {
return 0;
- } else {
+ } else {
return 1;
}
}
-sub process_request {
- $SIG{INT} = $SIG{TERM} = sub {
- foreach (keys %vm_comm_pids) {
- kill 2, $_;
- }
- exit 0;
- };
- unless ($parser) {
- $parser = XML::LibXML->new();
- }
- %offlinehyps=();
- %hypstats=();
- %offlinevms=();
- my $request = shift;
- if ($request->{_xcat_authname}->[0]) {
- $requester=$request->{_xcat_authname}->[0];
- }
- $callback = shift;
- require Sys::Virt;
- if ( xCAT::Utils::version_cmp(Sys::Virt->VERSION, "0.2.0") < 0 ) {
- die;
- }
- require Sys::Virt::Domain;
- %runningstates = (&Sys::Virt::Domain::STATE_NOSTATE=>1,&Sys::Virt::Domain::STATE_RUNNING=>1,&Sys::Virt::Domain::STATE_BLOCKED=>1);
-
- $doreq = shift;
- my $level = shift;
- my $noderange = $request->{node};
- my $command = $request->{command}->[0];
- my @exargs;
- unless ($command) {
- return; #Empty request
- }
- if (ref($request->{arg})) {
- @exargs = @{$request->{arg}};
- } else {
- @exargs = ($request->{arg});
- }
- my $forcemode = 0;
- my %orphans=();
- if ($command eq 'vmstatenotify') {
- unless ($vmtab) { $vmtab = new xCAT::Table('vm',-create=>1); }
- my $state = $exargs[0];
- if ($state eq 'vmoff') {
- $vmtab->setNodeAttribs($exargs[1],{powerstate=>'off'});
- return;
- } elsif ($state eq 'vmon') {
- $vmtab->setNodeAttribs($exargs[1],{powerstate=>'on'});
- return;
- } elsif ($state eq 'hypshutdown') { #turn this into an evacuate
- my $nodelisttab = xCAT::Table->new('nodelist');
- my $appstatus = $nodelisttab->getNodeAttribs($noderange->[0],['appstatus']);
- my @apps =split /,/,$appstatus->{'appstatus'};
- my @newapps;
- foreach (@apps) {
- if ($_ eq 'virtualization') { next; }
- push @newapps,$_;
- }
- $nodelisttab->setNodeAttribs($noderange->[0],{appstatus=>join(',',@newapps)});
- $command="revacuate";
- @exargs=();
- } elsif ($state eq 'hypstartup') { #if starting up, check for nodes on this hypervisor and start them up
- my $nodelisttab = xCAT::Table->new('nodelist');
- my $appstatus = $nodelisttab->getNodeAttribs($noderange->[0],['appstatus']);
- my @apps =split /,/,$appstatus->{appstatus};
- unless (grep {$_ eq 'virtualization'} @apps) {
- push @apps,'virtualization';
- $nodelisttab->setNodeAttribs($noderange->[0],{appstatus=>join(',',@apps)});
- }
- my @tents = $vmtab->getAttribs({host=>$noderange->[0],power=>'on'},['node']);
- $noderange=[];
- foreach (@tents) {
- push @$noderange,noderange($_->{node});
- }
- $command="rpower";
- @exargs=("on");
- }
-
- }
- if ($command eq 'revacuate') {
- my $newnoderange;
- if (grep { $_ eq '-f' } @exargs) {
- $forcemode=1;
- }
- foreach (@$noderange) {
- my $hyp = $_; #I used $_ too much here... sorry
- $hypconn=undef;
- push @destblacklist,$_;
- if ((not $offlinehyps{$_}) and nodesockopen($_,22)) {
- eval { #Contain bugs that won't be in $@
- $hypconn= Sys::Virt->new(uri=>"qemu+ssh://root@".$_."/system?no_tty=1&netcat=nc");
- };
- unless ($hypconn) { #retry for socat
- eval { #Contain bugs that won't be in $@
- $hypconn= Sys::Virt->new(uri=>"qemu+ssh://root@".$_."/system?no_tty=1");
- };
- }
+sub process_request {
+ $SIG{INT} = $SIG{TERM} = sub {
+ foreach (keys %vm_comm_pids) {
+ kill 2, $_;
}
- unless ($hypconn) {
- $offlinehyps{$hyp}=1;
- if ($forcemode) { #forcemode indicates the hypervisor is probably already dead, and to clear vm.host of all the nodes, and adopt the ones that are supposed to be 'on', power them on
- unless ($vmtab) { $vmtab = new xCAT::Table('vm',-create=>0); }
- unless ($vmtab) { next; }
- my @vents = $vmtab->getAttribs({host=>$hyp},['node','powerstate']);
- my $vent;
- my $nodestozap;
- foreach $vent (@vents) {
- my @nodes = noderange($vent->{node});
- if ($vent->{powerstate} eq 'on') {
- foreach (@nodes) {
- $offlinevms{$_}=1;
- $orphans{$_}=1;
- push @$newnoderange,$_;
- }
- }
- push @$nodestozap,@nodes;
- }
- $vmtab->setNodesAttribs($nodestozap,{host=>'|^.*$||'});
- } else {
- $callback->({node=>[{name=>[$_],error=>["Cannot communicate via libvirt to node"]}]});
- }
- next;
- }
- if ($hypconn) {
- foreach ($hypconn->list_domains()) {
- my $guestname = $_->get_name();
- if ($guestname eq 'Domain-0') {
- next;
- }
- push @$newnoderange,$guestname;
- }
- }
- }
- $hypconn=undef;
- $noderange = $newnoderange;
- $command = 'rmigrate';
- }
+ exit 0;
+ };
+ unless ($parser) {
+ $parser = XML::LibXML->new();
+ }
+ %offlinehyps = ();
+ %hypstats = ();
+ %offlinevms = ();
+ my $request = shift;
+ if ($request->{_xcat_authname}->[0]) {
+ $requester = $request->{_xcat_authname}->[0];
+ }
+ $callback = shift;
+ require Sys::Virt;
+ if (xCAT::Utils::version_cmp(Sys::Virt->VERSION, "0.2.0") < 0) {
+ die;
+ }
+ require Sys::Virt::Domain;
+ %runningstates = (&Sys::Virt::Domain::STATE_NOSTATE => 1, &Sys::Virt::Domain::STATE_RUNNING => 1, &Sys::Virt::Domain::STATE_BLOCKED => 1);
- if ($::XCATSITEVALS{usexhrm}) { $use_xhrm=1; }
- $vmtab = xCAT::Table->new("vm");
- $confdata={};
- unless ($command eq 'lsvm') {
- xCAT::VMCommon::grab_table_data($noderange,$confdata,$callback);
- my $kvmdatatab = xCAT::Table->new("kvm_nodedata",-create=>0); #grab any pertinent pre-existing xml
- if ($kvmdatatab) {
- $confdata->{kvmnodedata} = $kvmdatatab->getNodesAttribs($noderange,[qw/xml/]);
- } else {
- $confdata->{kvmnodedata} = {};
- }
- }
- if ($command eq 'mkvm' or ($command eq 'clonevm' and (grep { "$_" eq '-b' } @exargs)) or ($command eq 'rpower' and (grep { "$_" eq "on" or $_ eq "boot" or $_ eq "reset" } @exargs))) {
- xCAT::VMCommon::requestMacAddresses($confdata,$noderange);
- my @dhcpnodes;
- foreach (keys %{$confdata->{dhcpneeded}}) {
- push @dhcpnodes,$_;
- delete $confdata->{dhcpneeded}->{$_};
- }
- unless ($::XCATSITEVALS{'dhcpsetup'} and ($::XCATSITEVALS{'dhcpsetup'} =~ /^n/i or $::XCATSITEVALS{'dhcpsetup'} =~ /^d/i or $::XCATSITEVALS{'dhcpsetup'} eq '0')) {
- $doreq->({command=>['makedhcp'],node=>\@dhcpnodes});
- }
- }
-
- if ($command eq 'revacuate' or $command eq 'rmigrate') {
- $vmmaxp=1; #for now throttle concurrent migrations, requires more sophisticated heuristics to ensure sanity
- } else {
- my $tmp;
- if ($::XCATSITEVALS{vmmaxp}) { $vmmaxp=$::XCATSITEVALS{vmmaxp}; }
- }
-
- my $children = 0;
- $SIG{CHLD} = sub { my $cpid; while (($cpid = waitpid(-1, WNOHANG)) > 0) { if ($vm_comm_pids{$cpid}) { delete $vm_comm_pids{$cpid}; $children--; } } };
- my $inputs = new IO::Select;;
- my $sub_fds = new IO::Select;
- %hyphash=();
- if ($command eq 'lsvm') { #command intended for hypervisors, not guests
- foreach(@$noderange) { $hyphash{$_}->{nodes}->{$_}=1; }
- } else {
- foreach (keys %{$confdata->{vm}}) {
- if ($confdata->{vm}->{$_}->[0]->{host}) {
- $hyphash{$confdata->{vm}->{$_}->[0]->{host}}->{nodes}->{$_}=1;
- } else {
- $orphans{$_}=1;
- }
- }
- }
- if (keys %orphans) {
- if ($command eq "rpower") {
- if (grep /^on$/,@exargs or grep /^boot$/,@exargs) {
- unless (adopt(\%orphans,\%hyphash)) {
- $callback->({error=>"Can't find ".join(",",keys %orphans),errorcode=>[1]});
- return 1;
- }
- } else {
- foreach (keys %orphans) {
- $callback->({node=>[{name=>[$_],data=>[{contents=>['off']}]}]});
- }
- }
- } elsif ($command eq "rmigrate") {
- if ($forcemode) {
- unless (adopt(\%orphans,\%hyphash)) {
- $callback->({error=>"Can't find ".join(",",keys %orphans),errorcode=>[1]});
- return 1;
- }
- } else {
- $callback->({error=>"Can't find ".join(",",keys %orphans),errorcode=>[1]});
+ $doreq = shift;
+ my $level = shift;
+ my $noderange = $request->{node};
+ my $command = $request->{command}->[0];
+ my @exargs;
+ unless ($command) {
+ return; #Empty request
+ }
+ if (ref($request->{arg})) {
+ @exargs = @{ $request->{arg} };
+ } else {
+ @exargs = ($request->{arg});
+ }
+ my $forcemode = 0;
+ my %orphans = ();
+ if ($command eq 'vmstatenotify') {
+ unless ($vmtab) { $vmtab = new xCAT::Table('vm', -create => 1); }
+ my $state = $exargs[0];
+ if ($state eq 'vmoff') {
+ $vmtab->setNodeAttribs($exargs[1], { powerstate => 'off' });
return;
- }
- } elsif ($command eq "mkvm" or $command eq "clonevm") { #must adopt to create
- unless (adopt(\%orphans,\%hyphash)) {
- $callback->({error=>"Can't find ".join(",",keys %orphans),errorcode=>[1]});
+ } elsif ($state eq 'vmon') {
+ $vmtab->setNodeAttribs($exargs[1], { powerstate => 'on' });
+ return;
+ } elsif ($state eq 'hypshutdown') { #turn this into an evacuate
+ my $nodelisttab = xCAT::Table->new('nodelist');
+ my $appstatus = $nodelisttab->getNodeAttribs($noderange->[0], ['appstatus']);
+ my @apps = split /,/, $appstatus->{'appstatus'};
+ my @newapps;
+ foreach (@apps) {
+ if ($_ eq 'virtualization') { next; }
+ push @newapps, $_;
+ }
+ $nodelisttab->setNodeAttribs($noderange->[0], { appstatus => join(',', @newapps) });
+ $command = "revacuate";
+ @exargs = ();
+ } elsif ($state eq 'hypstartup') { #if starting up, check for nodes on this hypervisor and start them up
+ my $nodelisttab = xCAT::Table->new('nodelist');
+ my $appstatus = $nodelisttab->getNodeAttribs($noderange->[0], ['appstatus']);
+ my @apps = split /,/, $appstatus->{appstatus};
+ unless (grep { $_ eq 'virtualization' } @apps) {
+ push @apps, 'virtualization';
+ $nodelisttab->setNodeAttribs($noderange->[0], { appstatus => join(',', @apps) });
+ }
+ my @tents = $vmtab->getAttribs({ host => $noderange->[0], power => 'on' }, ['node']);
+ $noderange = [];
+ foreach (@tents) {
+ push @$noderange, noderange($_->{node});
+ }
+ $command = "rpower";
+ @exargs = ("on");
+ }
+
+ }
+ if ($command eq 'revacuate') {
+ my $newnoderange;
+ if (grep { $_ eq '-f' } @exargs) {
+ $forcemode = 1;
+ }
+ foreach (@$noderange) {
+ my $hyp = $_; #I used $_ too much here... sorry
+ $hypconn = undef;
+ push @destblacklist, $_;
+ if ((not $offlinehyps{$_}) and nodesockopen($_, 22)) {
+ eval { #Contain bugs that won't be in $@
+ $hypconn = Sys::Virt->new(uri => "qemu+ssh://root@" . $_ . "/system?no_tty=1&netcat=nc");
+ };
+ unless ($hypconn) { #retry for socat
+ eval { #Contain bugs that won't be in $@
+ $hypconn = Sys::Virt->new(uri => "qemu+ssh://root@" . $_ . "/system?no_tty=1");
+ };
+ }
+ }
+ unless ($hypconn) {
+ $offlinehyps{$hyp} = 1;
+ if ($forcemode) { #forcemode indicates the hypervisor is probably already dead, and to clear vm.host of all the nodes, and adopt the ones that are supposed to be 'on', power them on
+ unless ($vmtab) { $vmtab = new xCAT::Table('vm', -create => 0); }
+ unless ($vmtab) { next; }
+ my @vents = $vmtab->getAttribs({ host => $hyp }, [ 'node', 'powerstate' ]);
+ my $vent;
+ my $nodestozap;
+ foreach $vent (@vents) {
+ my @nodes = noderange($vent->{node});
+ if ($vent->{powerstate} eq 'on') {
+ foreach (@nodes) {
+ $offlinevms{$_} = 1;
+ $orphans{$_} = 1;
+ push @$newnoderange, $_;
+ }
+ }
+ push @$nodestozap, @nodes;
+ }
+ $vmtab->setNodesAttribs($nodestozap, { host => '|^.*$||' });
+ } else {
+ $callback->({ node => [ { name => [$_], error => ["Cannot communicate via libvirt to node"] } ] });
+ }
+ next;
+ }
+ if ($hypconn) {
+ foreach ($hypconn->list_domains()) {
+ my $guestname = $_->get_name();
+ if ($guestname eq 'Domain-0') {
+ next;
+ }
+ push @$newnoderange, $guestname;
+ }
+ }
+ }
+ $hypconn = undef;
+ $noderange = $newnoderange;
+ $command = 'rmigrate';
+ }
+
+ if ($::XCATSITEVALS{usexhrm}) { $use_xhrm = 1; }
+ $vmtab = xCAT::Table->new("vm");
+ $confdata = {};
+ unless ($command eq 'lsvm') {
+ xCAT::VMCommon::grab_table_data($noderange, $confdata, $callback);
+ my $kvmdatatab = xCAT::Table->new("kvm_nodedata", -create => 0); #grab any pertinent pre-existing xml
+ if ($kvmdatatab) {
+ $confdata->{kvmnodedata} = $kvmdatatab->getNodesAttribs($noderange, [qw/xml/]);
+ } else {
+ $confdata->{kvmnodedata} = {};
+ }
+ }
+ if ($command eq 'mkvm' or ($command eq 'clonevm' and (grep { "$_" eq '-b' } @exargs)) or ($command eq 'rpower' and (grep { "$_" eq "on" or $_ eq "boot" or $_ eq "reset" } @exargs))) {
+ xCAT::VMCommon::requestMacAddresses($confdata, $noderange);
+ my @dhcpnodes;
+ foreach (keys %{ $confdata->{dhcpneeded} }) {
+ push @dhcpnodes, $_;
+ delete $confdata->{dhcpneeded}->{$_};
+ }
+ unless ($::XCATSITEVALS{'dhcpsetup'} and ($::XCATSITEVALS{'dhcpsetup'} =~ /^n/i or $::XCATSITEVALS{'dhcpsetup'} =~ /^d/i or $::XCATSITEVALS{'dhcpsetup'} eq '0')) {
+ $doreq->({ command => ['makedhcp'], node => \@dhcpnodes });
+ }
+ }
+
+ if ($command eq 'revacuate' or $command eq 'rmigrate') {
+ $vmmaxp = 1; #for now throttle concurrent migrations, requires more sophisticated heuristics to ensure sanity
+ } else {
+ my $tmp;
+ if ($::XCATSITEVALS{vmmaxp}) { $vmmaxp = $::XCATSITEVALS{vmmaxp}; }
+ }
+
+ my $children = 0;
+ $SIG{CHLD} = sub { my $cpid; while (($cpid = waitpid(-1, WNOHANG)) > 0) { if ($vm_comm_pids{$cpid}) { delete $vm_comm_pids{$cpid}; $children--; } } };
+ my $inputs = new IO::Select;
+ my $sub_fds = new IO::Select;
+ %hyphash = ();
+ if ($command eq 'lsvm') { #command intended for hypervisors, not guests
+ foreach (@$noderange) { $hyphash{$_}->{nodes}->{$_} = 1; }
+ } else {
+ foreach (keys %{ $confdata->{vm} }) {
+ if ($confdata->{vm}->{$_}->[0]->{host}) {
+ $hyphash{ $confdata->{vm}->{$_}->[0]->{host} }->{nodes}->{$_} = 1;
+ } else {
+ $orphans{$_} = 1;
+ }
+ }
+ }
+ if (keys %orphans) {
+ if ($command eq "rpower") {
+ if (grep /^on$/, @exargs or grep /^boot$/, @exargs) {
+ unless (adopt(\%orphans, \%hyphash)) {
+ $callback->({ error => "Can't find " . join(",", keys %orphans), errorcode => [1] });
+ return 1;
+ }
+ } else {
+ foreach (keys %orphans) {
+ $callback->({ node => [ { name => [$_], data => [ { contents => ['off'] } ] } ] });
+ }
+ }
+ } elsif ($command eq "rmigrate") {
+ if ($forcemode) {
+ unless (adopt(\%orphans, \%hyphash)) {
+ $callback->({ error => "Can't find " . join(",", keys %orphans), errorcode => [1] });
+ return 1;
+ }
+ } else {
+ $callback->({ error => "Can't find " . join(",", keys %orphans), errorcode => [1] });
+ return;
+ }
+ } elsif ($command eq "mkvm" or $command eq "clonevm") { #must adopt to create
+ unless (adopt(\%orphans, \%hyphash)) {
+ $callback->({ error => "Can't find " . join(",", keys %orphans), errorcode => [1] });
return 1;
- }
- #mkvm used to be able to happen devoid of any hypervisor, make a fake hypervisor entry to allow this to occur
- #commenting that out for now
+ }
+
+#mkvm used to be able to happen devoid of any hypervisor, make a fake hypervisor entry to allow this to occur
+#commenting that out for now
# foreach (keys %orphans) {
# $hyphash{'!@!XCATDUMMYHYPERVISOR!@!'}->{nodes}->{$_}=1;
# }
- } else {
- $callback->({error=>"Can't find ".join(",",keys %orphans),errorcode=>[1]});
- return;
- }
- }
- if ($command eq "rbeacon") {
- my %req=();
- $req{command}=['rbeacon'];
- $req{arg}=\@exargs;
- $req{node}=[keys %hyphash];
- $doreq->(\%req,$callback);
- return;
- }
-
- #get new node status
- my %oldnodestatus=(); #saves the old node status
- my @allerrornodes=();
- my $check=0;
- my $global_check=1;
- if ($::XCATSITEVALS{nodestatus} =~ /0|n|N/) { $global_check=0; }
-
-
- if ($command eq 'rpower') {
- my $subcommand=$exargs[0];
- if (($global_check) && ($subcommand ne 'stat') && ($subcommand ne 'status')) {
- $check=1;
- my @allnodes=@$noderange;
-
- #save the old status
- my $nodelisttab = xCAT::Table->new('nodelist');
- if ($nodelisttab) {
- my $tabdata = $nodelisttab->getNodesAttribs(\@allnodes, ['node', 'status']);
- foreach my $node (@allnodes)
- {
- my $tmp1 = $tabdata->{$node}->[0];
- if ($tmp1) {
- if ($tmp1->{status}) { $oldnodestatus{$node}=$tmp1->{status}; }
- else { $oldnodestatus{$node}=""; }
- }
- }
- }
- #print "oldstatus:" . Dumper(\%oldnodestatus);
-
- #set the new status to the nodelist.status
- my %newnodestatus=();
- my $newstat;
- if (($subcommand eq 'off') || ($subcommand eq 'softoff')) {
- my $newstat=$::STATUS_POWERING_OFF;
- $newnodestatus{$newstat}=\@allnodes;
- } else {
- #get the current nodeset stat
- if (@allnodes>0) {
- my $nsh={};
- my ($ret, $msg)=xCAT::SvrUtils->getNodesetStates(\@allnodes, $nsh);
- if (!$ret) {
- foreach (keys %$nsh) {
- my $newstat=xCAT_monitoring::monitorctrl->getNodeStatusFromNodesetState($_, "rpower");
- $newnodestatus{$newstat}=$nsh->{$_};
- }
- } else {
- $callback->({data=>$msg});
- }
+ } else {
+ $callback->({ error => "Can't find " . join(",", keys %orphans), errorcode => [1] });
+ return;
}
- }
- #donot update node provision status (installing or netbooting) here
- xCAT::Utils->filter_nostatusupdate(\%newnodestatus);
- #print "newstatus" . Dumper(\%newnodestatus);
- xCAT_monitoring::monitorctrl::setNodeStatusAttributes(\%newnodestatus, 1);
}
- }
-
- if ($::XCATSITEVALS{masterimgdir}) { $xCAT_plugin::kvm::masterdir=$::XCATSITEVALS{masterimgdir} }
-
-
-
- foreach $hyp (sort (keys %hyphash)) {
- while ($children > $vmmaxp) {
- my $handlednodes={};
- forward_data($callback,$sub_fds,$handlednodes);
- #update the node status to the nodelist.status table
- if ($check) {
- updateNodeStatus($handlednodes, \@allerrornodes);
- }
+ if ($command eq "rbeacon") {
+ my %req = ();
+ $req{command} = ['rbeacon'];
+ $req{arg} = \@exargs;
+ $req{node} = [ keys %hyphash ];
+ $doreq->(\%req, $callback);
+ return;
}
- $children++;
- my $cfd;
- my $pfd;
- socketpair($pfd, $cfd,AF_UNIX,SOCK_STREAM,PF_UNSPEC) or die "socketpair: $!";
- $cfd->autoflush(1);
- $pfd->autoflush(1);
- my $cpid = xCAT::Utils->xfork;
- unless (defined($cpid)) { die "Fork error"; }
- unless ($cpid) {
- close($cfd);
- dohyp($pfd,$hyp,$command,-args=>\@exargs);
- exit(0);
+
+ #get new node status
+ my %oldnodestatus = (); #saves the old node status
+ my @allerrornodes = ();
+ my $check = 0;
+ my $global_check = 1;
+ if ($::XCATSITEVALS{nodestatus} =~ /0|n|N/) { $global_check = 0; }
+
+
+ if ($command eq 'rpower') {
+ my $subcommand = $exargs[0];
+ if (($global_check) && ($subcommand ne 'stat') && ($subcommand ne 'status')) {
+ $check = 1;
+ my @allnodes = @$noderange;
+
+ #save the old status
+ my $nodelisttab = xCAT::Table->new('nodelist');
+ if ($nodelisttab) {
+ my $tabdata = $nodelisttab->getNodesAttribs(\@allnodes, [ 'node', 'status' ]);
+ foreach my $node (@allnodes)
+ {
+ my $tmp1 = $tabdata->{$node}->[0];
+ if ($tmp1) {
+ if ($tmp1->{status}) { $oldnodestatus{$node} = $tmp1->{status}; }
+ else { $oldnodestatus{$node} = ""; }
+ }
+ }
+ }
+
+ #print "oldstatus:" . Dumper(\%oldnodestatus);
+
+ #set the new status to the nodelist.status
+ my %newnodestatus = ();
+ my $newstat;
+ if (($subcommand eq 'off') || ($subcommand eq 'softoff')) {
+ my $newstat = $::STATUS_POWERING_OFF;
+ $newnodestatus{$newstat} = \@allnodes;
+ } else {
+
+ #get the current nodeset stat
+ if (@allnodes > 0) {
+ my $nsh = {};
+ my ($ret, $msg) = xCAT::SvrUtils->getNodesetStates(\@allnodes, $nsh);
+ if (!$ret) {
+ foreach (keys %$nsh) {
+ my $newstat = xCAT_monitoring::monitorctrl->getNodeStatusFromNodesetState($_, "rpower");
+ $newnodestatus{$newstat} = $nsh->{$_};
+ }
+ } else {
+ $callback->({ data => $msg });
+ }
+ }
+ }
+
+ #donot update node provision status (installing or netbooting) here
+ xCAT::Utils->filter_nostatusupdate(\%newnodestatus);
+
+ #print "newstatus" . Dumper(\%newnodestatus);
+ xCAT_monitoring::monitorctrl::setNodeStatusAttributes(\%newnodestatus, 1);
+ }
}
- $vm_comm_pids{$cpid} = 1;
- close ($pfd);
- $sub_fds->add($cfd);
- }
- while ($sub_fds->count > 0) { # or $children > 0) { #if count is zero, even if we have live children, we can't possibly get data from them
- my $handlednodes={};
- forward_data($callback,$sub_fds,$handlednodes);
- #update the node status to the nodelist.status table
+
+ if ($::XCATSITEVALS{masterimgdir}) { $xCAT_plugin::kvm::masterdir = $::XCATSITEVALS{masterimgdir} }
+
+
+
+ foreach $hyp (sort (keys %hyphash)) {
+ while ($children > $vmmaxp) {
+ my $handlednodes = {};
+ forward_data($callback, $sub_fds, $handlednodes);
+
+ #update the node status to the nodelist.status table
+ if ($check) {
+ updateNodeStatus($handlednodes, \@allerrornodes);
+ }
+ }
+ $children++;
+ my $cfd;
+ my $pfd;
+ socketpair($pfd, $cfd, AF_UNIX, SOCK_STREAM, PF_UNSPEC) or die "socketpair: $!";
+ $cfd->autoflush(1);
+ $pfd->autoflush(1);
+ my $cpid = xCAT::Utils->xfork;
+ unless (defined($cpid)) { die "Fork error"; }
+
+ unless ($cpid) {
+ close($cfd);
+ dohyp($pfd, $hyp, $command, -args => \@exargs);
+ exit(0);
+ }
+ $vm_comm_pids{$cpid} = 1;
+ close($pfd);
+ $sub_fds->add($cfd);
+ }
+ while ($sub_fds->count > 0) { # or $children > 0) { #if count is zero, even if we have live children, we can't possibly get data from them
+ my $handlednodes = {};
+ forward_data($callback, $sub_fds, $handlednodes);
+
+ #update the node status to the nodelist.status table
+ if ($check) {
+ updateNodeStatus($handlednodes, \@allerrornodes);
+ }
+ }
+
+#while (wait() > -1) { } #keep around just in case we find the absolute need to wait for children to be gone
+
+ #Make sure they get drained, this probably is overkill but shouldn't hurt
+ #my $rc=1;
+ #while ( $rc>0 ) {
+ # my $handlednodes={};
+ # $rc=forward_data($callback,$sub_fds,$handlednodes);
+ # #update the node status to the nodelist.status table
+ # if ($check) {
+ # updateNodeStatus($handlednodes, \@allerrornodes);
+ # }
+ #}
+
if ($check) {
- updateNodeStatus($handlednodes, \@allerrornodes);
+
+ #print "allerrornodes=@allerrornodes\n";
+ #revert the status back for there is no-op for the nodes
+ my %old = ();
+ foreach my $node (@allerrornodes) {
+ my $stat = $oldnodestatus{$node};
+ if (exists($old{$stat})) {
+ my $pa = $old{$stat};
+ push(@$pa, $node);
+ }
+ else {
+ $old{$stat} = [$node];
+ }
+ }
+ xCAT_monitoring::monitorctrl::setNodeStatusAttributes(\%old, 1);
}
- }
- #while (wait() > -1) { } #keep around just in case we find the absolute need to wait for children to be gone
-
- #Make sure they get drained, this probably is overkill but shouldn't hurt
- #my $rc=1;
- #while ( $rc>0 ) {
- # my $handlednodes={};
- # $rc=forward_data($callback,$sub_fds,$handlednodes);
- # #update the node status to the nodelist.status table
- # if ($check) {
- # updateNodeStatus($handlednodes, \@allerrornodes);
- # }
- #}
-
- if ($check) {
- #print "allerrornodes=@allerrornodes\n";
- #revert the status back for there is no-op for the nodes
- my %old=();
- foreach my $node (@allerrornodes) {
- my $stat=$oldnodestatus{$node};
- if (exists($old{$stat})) {
- my $pa=$old{$stat};
- push(@$pa, $node);
- }
- else {
- $old{$stat}=[$node];
- }
- }
- xCAT_monitoring::monitorctrl::setNodeStatusAttributes(\%old, 1);
- }
}
sub updateNodeStatus {
- my $handlednodes=shift;
- my $allerrornodes=shift;
- foreach my $node (keys(%$handlednodes)) {
- if ($handlednodes->{$node} == -1) { push(@$allerrornodes, $node); }
- }
+ my $handlednodes = shift;
+ my $allerrornodes = shift;
+ foreach my $node (keys(%$handlednodes)) {
+ if ($handlednodes->{$node} == -1) { push(@$allerrornodes, $node); }
+ }
}
sub forward_data {
- my $callback = shift;
- my $fds = shift;
- my $errornodes=shift;
- my @ready_fds = $fds->can_read(1);
- my $rfh;
- my $rc = @ready_fds;
- foreach $rfh (@ready_fds) {
- my $data;
- my $responses;
- eval {
- $responses = fd_retrieve($rfh);
- };
- if ($@ and $@ =~ /^Magic number checking on storable file/) { #this most likely means we ran over the end of available input
- $fds->remove($rfh);
- close($rfh);
- } else {
- eval { print $rfh "ACK\n"; }; #ignore failures to send inter-process ack
- foreach (@$responses) {
- #save the nodes that has errors and the ones that has no-op for use by the node status monitoring
- my $no_op=0;
- if ($_->{node}->[0]->{errorcode}) { $no_op=1; }
- else {
- my $text=$_->{node}->[0]->{data}->[0]->{contents}->[0];
- #print "data:$text\n";
- if (($text) && ($text =~ /$status_noop/)) {
- $no_op=1;
- #remove the symbols that meant for use by node status
- $_->{node}->[0]->{data}->[0]->{contents}->[0] =~ s/$status_noop//;
- }
- }
- #print "data:". $_->{node}->[0]->{data}->[0]->{contents}->[0] . "\n";
- if ($no_op) {
- if ($errornodes) { $errornodes->{$_->{node}->[0]->{name}->[0]}=-1; }
- } else {
- if ($errornodes) { $errornodes->{$_->{node}->[0]->{name}->[0]}=1; }
- }
- $callback->($_);
- }
+ my $callback = shift;
+ my $fds = shift;
+ my $errornodes = shift;
+ my @ready_fds = $fds->can_read(1);
+ my $rfh;
+ my $rc = @ready_fds;
+ foreach $rfh (@ready_fds) {
+ my $data;
+ my $responses;
+ eval {
+ $responses = fd_retrieve($rfh);
+ };
+ if ($@ and $@ =~ /^Magic number checking on storable file/) { #this most likely means we ran over the end of available input
+ $fds->remove($rfh);
+ close($rfh);
+ } else {
+ eval { print $rfh "ACK\n"; }; #ignore failures to send inter-process ack
+ foreach (@$responses) {
+
+#save the nodes that has errors and the ones that has no-op for use by the node status monitoring
+ my $no_op = 0;
+ if ($_->{node}->[0]->{errorcode}) { $no_op = 1; }
+ else {
+ my $text = $_->{node}->[0]->{data}->[0]->{contents}->[0];
+
+ #print "data:$text\n";
+ if (($text) && ($text =~ /$status_noop/)) {
+ $no_op = 1;
+
+ #remove the symbols that meant for use by node status
+ $_->{node}->[0]->{data}->[0]->{contents}->[0] =~ s/$status_noop//;
+ }
+ }
+
+ #print "data:". $_->{node}->[0]->{data}->[0]->{contents}->[0] . "\n";
+ if ($no_op) {
+ if ($errornodes) { $errornodes->{ $_->{node}->[0]->{name}->[0] } = -1; }
+ } else {
+ if ($errornodes) { $errornodes->{ $_->{node}->[0]->{name}->[0] } = 1; }
+ }
+ $callback->($_);
+ }
+ }
}
- }
- yield(); #Try to avoid useless iterations as much as possible
- return $rc;
+ yield(); #Try to avoid useless iterations as much as possible
+ return $rc;
}
sub dohyp {
- my $out = shift;
- $hyp = shift;
- my $command=shift;
- my %namedargs=@_;
- my @exargs=@{$namedargs{-args}};
- my $node;
- my $args = \@exargs;
- #$vmtab = xCAT::Table->new("vm");
- $vmtab = undef;
- unless ($offlinehyps{$hyp} or ($hyp eq '!@!XCATDUMMYHYPERVISOR!@!') or nodesockopen($hyp,22)) {
- $offlinehyps{$hyp}=1;
- }
+ my $out = shift;
+ $hyp = shift;
+ my $command = shift;
+ my %namedargs = @_;
+ my @exargs = @{ $namedargs{-args} };
+ my $node;
+ my $args = \@exargs;
-
- eval { #Contain Sys::Virt bugs that make $@ useless
- if ($hyp eq '!@!XCATDUMMYHYPERVISOR!@!') { #Fake connection for commands that have a fake hypervisor key
- $hypconn = 1;
- } elsif (not $offlinehyps{$hyp}) {
- $hypconn= Sys::Virt->new(uri=>"qemu+ssh://root@".$hyp."/system?no_tty=1&netcat=nc");
- }
- };
- unless ($hypconn or $offlinehyps{$hyp}) {
- eval { #Contain Sys::Virt bugs that make $@ useless
- $hypconn= Sys::Virt->new(uri=>"qemu+ssh://root@".$hyp."/system?no_tty=1");
- };
- }
- unless ($hypconn) {
- my %err=(node=>[]);
- foreach (keys %{$hyphash{$hyp}->{nodes}}) {
- push (@{$err{node}},{name=>[$_],error=>["Cannot communicate via libvirt to $hyp"],errorcode=>[1]});
- }
- store_fd([\%err],$out);
- yield();
- waitforack($out);
- %err=(node=>[]);
- if ($command eq 'rmigrate' and grep { $_ eq '-f' } @$args) {
- foreach (keys %{$hyphash{$hyp}->{nodes}}) {
- push (@{$err{node}},{name=>[$_],error=>["Forcibly relocating VM from $hyp"],errorcode=>[1]});
- }
- store_fd([\%err],$out);
- } else {
- return 1,"General error establishing libvirt communication";
- }
- }
- if (($command eq 'mkvm' or $command eq 'chvm') and $hypconn) {
- my $nodeinfo = $hypconn->get_node_info();
- if (exists($nodeinfo->{model})) {
- $confdata->{$hyp}->{cpumodel} = $nodeinfo->{model};
- if ($nodeinfo->{model} eq "ppc64") {
- my $sysinfo = $hypconn->get_sysinfo();
- if ($sysinfo) {
- my $syshash = XMLin($sysinfo);
- my $processor_content = $syshash->{processor}->[0]->{entry}->{type}->{content};
- if ($processor_content =~ /POWER8/i) {
- $confdata->{$hyp}->{cputype} = "power8";
- $confdata->{$hyp}->{cpu_thread} = "8";
- } elsif ($processor_content =~ /POWER7/i) {
- $confdata->{$hyp}->{cputype} = "power7";
- $confdata->{$hyp}->{cpu_thread} = "4";
- } elsif ($processor_content =~ /POWER6/i) {
- $confdata->{$hyp}->{cputype} = "power6";
- $confdata->{$hyp}->{cpu_thread} = "2";
- }
- }
- }
- }
- }
-
- foreach $node (sort (keys %{$hyphash{$hyp}->{nodes}})) {
- if ($confdata->{$hyp}->{cpumodel} and $confdata->{$hyp}->{cpumodel} =~ /ppc64/i) {
- $confdata->{vm}->{$node}->[0]->{storagemodel} = "scsi";
- }
- if ($confdata->{$hyp}->{cpu_thread}) {
- $confdata->{vm}->{$node}->[0]->{cpu_thread} = $confdata->{$hyp}->{cpu_thread};
- }
- if ($confdata->{$hyp}->{cputype}) {
- $confdata->{vm}->{$node}->[0]->{cputype} = $confdata->{$hyp}->{cputype};
+ #$vmtab = xCAT::Table->new("vm");
+ $vmtab = undef;
+ unless ($offlinehyps{$hyp} or ($hyp eq '!@!XCATDUMMYHYPERVISOR!@!') or nodesockopen($hyp, 22)) {
+ $offlinehyps{$hyp} = 1;
}
- my ($rc,@output) = guestcmd($hyp,$node,$command,@$args);
- foreach(@output) {
- my %output;
- if (ref($_)) {
- store_fd([$_],$out);
- yield();
- waitforack($out);
- next;
- }
-
- (my $desc,my $text) = split (/:/,$_,2);
- unless ($text) {
- $text=$desc;
- } else {
- $desc =~ s/^\s+//;
- $desc =~ s/\s+$//;
- if ($desc) {
- $output{node}->[0]->{data}->[0]->{desc}->[0]=$desc;
+ eval { #Contain Sys::Virt bugs that make $@ useless
+ if ($hyp eq '!@!XCATDUMMYHYPERVISOR!@!') { #Fake connection for commands that have a fake hypervisor key
+ $hypconn = 1;
+ } elsif (not $offlinehyps{$hyp}) {
+ $hypconn = Sys::Virt->new(uri => "qemu+ssh://root@" . $hyp . "/system?no_tty=1&netcat=nc");
}
- }
- $text =~ s/^\s+//;
- $text =~ s/\s+$//;
- $output{node}->[0]->{errorcode} = $rc;
- $output{node}->[0]->{name}->[0]=$node;
- if ($rc == 0) {
- $output{node}->[0]->{data}->[0]->{contents}->[0]=$text;
- } else {
- $output{node}->[0]->{error} = $text;
- }
- store_fd([\%output],$out);
- yield();
- waitforack($out);
+ };
+ unless ($hypconn or $offlinehyps{$hyp}) {
+ eval { #Contain Sys::Virt bugs that make $@ useless
+ $hypconn = Sys::Virt->new(uri => "qemu+ssh://root@" . $hyp . "/system?no_tty=1");
+ };
}
- yield();
- }
- foreach (keys %$updatetable) {
- my $tabhandle = xCAT::Table->new($_,-create=>1);
- my $updates = $updatetable->{$_};
- if ($updates->{'!*XCATNODESTODELETE*!'}) {
- my @delkeys;
- foreach (keys %{$updates->{'!*XCATNODESTODELETE*!'}}) {
- if ($_) { push @delkeys, {node=>$_}; }
- }
- if (@delkeys) { $tabhandle->delEntries(\@delkeys); }
- delete $updates->{'!*XCATNODESTODELETE*!'};
- }
- $tabhandle->setNodesAttribs($updatetable->{$_});
- }
- #my $msgtoparent=freeze(\@outhashes); # = XMLout(\%output,RootName => 'xcatresponse');
- #print $out $msgtoparent; #$node.": $_\n";
+ unless ($hypconn) {
+ my %err = (node => []);
+ foreach (keys %{ $hyphash{$hyp}->{nodes} }) {
+ push(@{ $err{node} }, { name => [$_], error => ["Cannot communicate via libvirt to $hyp"], errorcode => [1] });
+ }
+ store_fd([ \%err ], $out);
+ yield();
+ waitforack($out);
+ %err = (node => []);
+ if ($command eq 'rmigrate' and grep { $_ eq '-f' } @$args) {
+ foreach (keys %{ $hyphash{$hyp}->{nodes} }) {
+ push(@{ $err{node} }, { name => [$_], error => ["Forcibly relocating VM from $hyp"], errorcode => [1] });
+ }
+ store_fd([ \%err ], $out);
+ } else {
+ return 1, "General error establishing libvirt communication";
+ }
+ }
+ if (($command eq 'mkvm' or $command eq 'chvm') and $hypconn) {
+ my $nodeinfo = $hypconn->get_node_info();
+ if (exists($nodeinfo->{model})) {
+ $confdata->{$hyp}->{cpumodel} = $nodeinfo->{model};
+ if ($nodeinfo->{model} eq "ppc64") {
+ my $sysinfo = $hypconn->get_sysinfo();
+ if ($sysinfo) {
+ my $syshash = XMLin($sysinfo);
+ my $processor_content = $syshash->{processor}->[0]->{entry}->{type}->{content};
+ if ($processor_content =~ /POWER8/i) {
+ $confdata->{$hyp}->{cputype} = "power8";
+ $confdata->{$hyp}->{cpu_thread} = "8";
+ } elsif ($processor_content =~ /POWER7/i) {
+ $confdata->{$hyp}->{cputype} = "power7";
+ $confdata->{$hyp}->{cpu_thread} = "4";
+ } elsif ($processor_content =~ /POWER6/i) {
+ $confdata->{$hyp}->{cputype} = "power6";
+ $confdata->{$hyp}->{cpu_thread} = "2";
+ }
+ }
+ }
+ }
+ }
+
+ foreach $node (sort (keys %{ $hyphash{$hyp}->{nodes} })) {
+ if ($confdata->{$hyp}->{cpumodel} and $confdata->{$hyp}->{cpumodel} =~ /ppc64/i) {
+ $confdata->{vm}->{$node}->[0]->{storagemodel} = "scsi";
+ }
+ if ($confdata->{$hyp}->{cpu_thread}) {
+ $confdata->{vm}->{$node}->[0]->{cpu_thread} = $confdata->{$hyp}->{cpu_thread};
+ }
+ if ($confdata->{$hyp}->{cputype}) {
+ $confdata->{vm}->{$node}->[0]->{cputype} = $confdata->{$hyp}->{cputype};
+ }
+
+ my ($rc, @output) = guestcmd($hyp, $node, $command, @$args);
+
+ foreach (@output) {
+ my %output;
+ if (ref($_)) {
+ store_fd([$_], $out);
+ yield();
+ waitforack($out);
+ next;
+ }
+
+ (my $desc, my $text) = split(/:/, $_, 2);
+ unless ($text) {
+ $text = $desc;
+ } else {
+ $desc =~ s/^\s+//;
+ $desc =~ s/\s+$//;
+ if ($desc) {
+ $output{node}->[0]->{data}->[0]->{desc}->[0] = $desc;
+ }
+ }
+ $text =~ s/^\s+//;
+ $text =~ s/\s+$//;
+ $output{node}->[0]->{errorcode} = $rc;
+ $output{node}->[0]->{name}->[0] = $node;
+ if ($rc == 0) {
+ $output{node}->[0]->{data}->[0]->{contents}->[0] = $text;
+ } else {
+ $output{node}->[0]->{error} = $text;
+ }
+ store_fd([ \%output ], $out);
+ yield();
+ waitforack($out);
+ }
+ yield();
+ }
+ foreach (keys %$updatetable) {
+ my $tabhandle = xCAT::Table->new($_, -create => 1);
+ my $updates = $updatetable->{$_};
+ if ($updates->{'!*XCATNODESTODELETE*!'}) {
+ my @delkeys;
+ foreach (keys %{ $updates->{'!*XCATNODESTODELETE*!'} }) {
+ if ($_) { push @delkeys, { node => $_ }; }
+ }
+ if (@delkeys) { $tabhandle->delEntries(\@delkeys); }
+ delete $updates->{'!*XCATNODESTODELETE*!'};
+ }
+ $tabhandle->setNodesAttribs($updatetable->{$_});
+ }
+
+#my $msgtoparent=freeze(\@outhashes); # = XMLout(\%output,RootName => 'xcatresponse');
+#print $out $msgtoparent; #$node.": $_\n";
}
-
+
1;