From efb2a9b5a40953de0d3f67a1e9499a5676244e10 Mon Sep 17 00:00:00 2001 From: jbjohnso Date: Mon, 30 Aug 2010 21:01:35 +0000 Subject: [PATCH] -Working clonevm for both directiors for kvm git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@7314 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd --- xCAT-server/lib/xcat/plugins/kvm.pm | 113 +++++++++++++++++++++------- 1 file changed, 86 insertions(+), 27 deletions(-) diff --git a/xCAT-server/lib/xcat/plugins/kvm.pm b/xCAT-server/lib/xcat/plugins/kvm.pm index 31de0081f..739a7a4e3 100644 --- a/xCAT-server/lib/xcat/plugins/kvm.pm +++ b/xCAT-server/lib/xcat/plugins/kvm.pm @@ -151,7 +151,6 @@ sub get_storage_pool_by_url { #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"); - print "$checkhost eq $host and $checkpath eq $path\n"; #) { #TODO: check name resolution to see if they match really even if not strictly the same 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; } @@ -1455,8 +1454,7 @@ sub promote_vm_to_master { return; } my $parsedxml = $parser->parse_string($xml); - my $tmpnod = $parsedxml->findnodes('/domain/uuid')->[0]; #get rid of the VM specific uuid - $tmpnod->parentNode->removeChild($tmpnod); + my $tmpnod = $parsedxml->findnodes('/domain/uuid/text()')->[0]->setData("none"); #get rid of the VM specific uuid $target =~ /^(.*)\/([^\/]*)\z/; my $directory=$1; @@ -1555,6 +1553,7 @@ sub promote_vm_to_master { $mastertabentry->{$_}=$confdata->{vm}->{$node}->[0]->{$_}; } } + $mastertabentry->{storage}=$directory; $mastertabentry->{vintage}=localtime; $mastertabentry->{originator}=$requester; $updatetable->{vmmaster}->{$mastername}=$mastertabentry; @@ -1585,7 +1584,6 @@ sub clonevm { } sub clone_vm_from_master { -=cut my %args = @_; my $base=$args{base}; my $vmmastertab=xCAT::Table->new('vmmaster',-create=>0); @@ -1603,33 +1601,94 @@ sub clone_vm_from_master { return; } my $newnodexml = $parser->parse_string($kvmmasteref->{xml}); - if ($masterref->{nics} and $masterref->{nics} ne $confdata->{vm}->{$node}->[0]->{nics}) { - $confdata->{vm}->{$node}->[0]->{nics}=$masterref->{nics}; - $updatetable->{vm}->{$node}->{nics}=$masterref->{nics}; + $newnodexml->findnodes("/domain/name/text()")->[0]->setData($node); #set name correctly + 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); + #ok, now the fun part, storage... + my $disk; + my $url; + if ($confdata->{vm}->{$node}->[0]->{storage}) { + unless ($confdata->{vm}->{$node}->[0]->{storage} =~ /^nfs:/) { + die "not implemented"; + } + $url = $confdata->{vm}->{$node}->[0]->{storage}; + } else { + $url = $masteref->{storage}; + $updatetable->{vm}->{$node}->{storage}=$url; } - - $confdata->{vm}->{$node}->[0]->{nics}=$masteref->{nics}; + if ($masteref->{storagemodel} and not $confdata->{vm}->{$node}->[0]->{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 $srcfilename = $disk->findnodes("./source")->[0]->getAttribute("file"); + my $filename = $srcfilename; + $filename =~ s/^.*$mastername/$node/; + $filename =~ m!\.([^\.]*)\z!; + my $format=$1; + my $newbasexml="$filename0$srcfilename"; + my $newvol = $destinationpool->create_volume($newbasexml); + my $newfilename=$newvol->get_path(); + $disk->findnodes("./source")->[0]->setAttribute("file"=>$newfilename); + } + my $textxml=$newnodexml->toString(); + $updatetable->{kvm_nodedata}->{$node}->{xml}=$textxml; } - sub build_nicstruct { - if ($confdata->{vm}->{$node}->[0]->{nics}) { -...... - my $parsedxml = $parser->parse_string($xml); - my $tmpnod = $parsedxml->findnodes('/domain/uuid')->[0]; #get rid of the VM specific uuid - $tmpnod->parentNode->removeChild($tmpnod); - - $target =~ /^(.*)\/([^\/]*)\z/; - my $directory=$1; - my $mastername=$2; - - $tmpnod = $parsedxml->findnodes('/domain/name/text()')->[0]; - $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"=>''); } +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}; + } + 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}; + } + 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}; + } else { + @nics = ('virbr0'); + } + 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); + return; + } + my $nicstruct; + 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); + } + my $nic; + my $deviceroot=$newnodexml->findnodes("/domain/devices")->[0]; + foreach $nic (@nics) { #need more xml to throw at it.. + my $type = 'e1000'; #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 + if ($confdata->{vm}->{$node}->[0]->{nicmodel}) { + $type = $confdata->{vm}->{$node}->[0]->{nicmodel}; + } + if ($nic =~ /=/) { + ($nic,$type) = split /=/,$nic,2; + } + my $xmlsnippet = ""; + my $chunk = $parser->parse_balanced_chunk($xmlsnippet); + $deviceroot->appendChild($chunk); } -=cut - } sub mkvm { shift; #Throuw away first argument @@ -2107,7 +2166,7 @@ sub process_request { $callback->({error=>"Can't find ".join(",",keys %orphans),errorcode=>[1]}); return; } - } elsif ($command eq "mkvm") { #must adopt to create + } 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;