xcat-core/perl-xCAT/xCAT/VMCommon.pm

116 lines
3.9 KiB
Perl

package xCAT::VMCommon;
use Socket;
use strict;
#Functions common to virtualization management (KVM, Xen, VMware)
sub grab_table_data{ #grab table data relevent to VM guest nodes
my $noderange=shift;
my $cfghash = shift;
my $callback=shift;
my $vmtab = xCAT::Table->new("vm");
my $hmtab = xCAT::Table->new("nodehm");
my $nttab = xCAT::Table->new("nodetype");
my $sitetab = xCAT::Table->new("site");
$cfghash->{site}->{genmacprefix} = xCAT::Utils->get_site_attribute('genmacprefix');
if ($hmtab) {
$cfghash->{nodehm} = $hmtab->getNodesAttribs($noderange,['serialspeed']);
}
if ($nttab) {
$cfghash->{nodetype} = $nttab->getNodesAttribs($noderange,['os','arch']); #allow us to guess RTC config
}
unless ($vmtab) {
$callback->({data=>["Cannot open vm table"]});
return;
}
$cfghash->{vm} = $vmtab->getNodesAttribs($noderange,['node','host','migrationdest','cfgstore','storage','memory','cpus','nics','bootorder','virtflags']);
my $mactab = xCAT::Table->new("mac",-create=>1);
my $nrtab= xCAT::Table->new("noderes",-create=>1);
$cfghash->{mac} = $mactab->getAllNodeAttribs(['mac'],1);
my $macs;
my $mac;
foreach (keys %{$cfghash->{mac}}) {
$macs=$cfghash->{mac}->{$_}->[0]->{mac};
foreach $mac (split /\|/,$macs) {
$mac =~ s/\!.*//;
$cfghash->{usedmacs}->{lc($mac)}=1;
}
}
}
sub getMacAddresses {
my $tablecfg = shift;
my $node = shift;
my $count = shift;
my $mactab = xCAT::Table->new("mac",-create=>1);
my $macdata = $tablecfg->{mac}->{$node}->[0]->{mac};
unless ($macdata) { $macdata ="" }
my @macs;
my $macaddr;
foreach $macaddr (split /\|/,$macdata) {
$macaddr =~ s/\!.*//;
push @macs,lc($macaddr);
}
$count-=scalar(@macs);
my $updatesneeded=0;
if ($count > 0) {
$updatesneeded = 1;
}
while ($count > 0) { #still need more, autogen
$macaddr = "";
while (not $macaddr) {
$macaddr = lc(genMac($node,$tablecfg->{site}->{genmacprefix}));
if ($tablecfg->{usedmacs}->{$macaddr}) {
$macaddr = "";
}
}
$count--;
$tablecfg->{usedmacs}->{$macaddr} = 1;
if (not $macdata) {
$macdata = $macaddr;
} else {
$macdata .= "|".$macaddr;
}
push @macs,$macaddr;
}
if ($updatesneeded) {
my $mactab = xCAT::Table->new('mac',-create=>1);
$mactab->setNodeAttribs($node,{mac=>$macdata});
$tablecfg->{dhcpneeded}->{$node}=1; #at our leisure, this dhcp binding should be updated
}
return @macs;
# $cfghash->{usedmacs}-{lc{$mac}};
}
sub genMac { #Generates a mac address for a node, does NOT assure uniqueness, calling code needs to do that
my $node=shift;
my $prefix = shift;
srand(); #Re-seed the rng. I haven't been able to reproduce it, but duplicate macs were somehow making it
if ($prefix) { #Specific prefix requested, honor it
my $tail = int(rand(0xffffff)); #With only 24 bits of space, use random bits;
$tail = sprintf("%06x",$tail);
$tail =~ s/(..)(..)(..)/:$1:$2:$3/;
return $prefix.$tail;
}
my $allbutmult = 0xfeff; # to & with a number to ensure multicast bit is *not* set
my $locallyadministered = 0x200; # to | with the 16 MSBs to indicate a local mac
my $leading = int(rand(0xffff));
$leading = $leading & $allbutmult;
$leading = $leading | $locallyadministered;
#If this nodename is a resolvable name, we'll use that for the other 32 bits
my $low32;
my $n;
if ($n = inet_aton($node)) {
$low32= unpack("N",$n);
}
unless ($low32) { #If that failed, just do 32 psuedo-random bits
$low32 = int(rand(0xffffffff));
}
my $mac;
$mac = sprintf("%04x%08x",$leading,$low32);
$mac =~s/(..)(..)(..)(..)(..)(..)/$1:$2:$3:$4:$5:$6/;
return $mac;
}
1;