2
0
mirror of https://github.com/xcat2/xcat-core.git synced 2025-06-13 01:40:26 +00:00

add support for chvm --detachdev

This commit is contained in:
immarvin
2015-12-21 05:10:22 -05:00
parent 332af17c2b
commit 181fdee0ce
4 changed files with 207 additions and 36 deletions

View File

@ -222,7 +222,7 @@ vm => {
'vncport' => 'Tracks the current VNC display port (currently not meant to be set',
'textconsole' => 'Tracks the Psuedo-TTY that maps to the serial port or console of a VM',
'powerstate' => "This flag is used by xCAT to track the last known power state of the VM.",
'othersettings' => "This allows specifying a semicolon delimited list of key->value pairs to include in a vmx file of VMware or KVM. For partitioning on normal power machines, this option is used to specify the hugepage and/or bsr information, the value is like:'hugepage:1,bsr=2'. For KVM cpu pinning, this option is used to specify the physical cpu set on the host, the value is like:'vcpupin:'0-15,^8' ',Its syntax is a comma separated list and a special markup using '-' and '^' (ex. '0-4', '0-3,^2') can also be allowed, the '-' denotes the range and the '^' denotes exclusive. For KVM memory binding, the value is like:'membind:0', restrict a guest to allocate memory from the specified set of NUMA nodes. For PCI passthrough, the value is like:'devpassthrough:pci_0001_01_00_0,pci_0000_03_00_0',the PCI devices are assigned to a virtual machine, and the virtual machine can use this I/O exclusively,the devices list are a list of PCI device names delimited with comma, the PCI device names can be obtained by running B<virsh nodedev-list> on the host.",
'othersettings' => "This allows specifying a semicolon delimited list of key->value pairs to include in a vmx file of VMware or KVM. For partitioning on normal power machines, this option is used to specify the hugepage and/or bsr information, the value is like:'hugepage:1,bsr=2'. For KVM cpu pinning, this option is used to specify the physical cpu set on the host, the value is like:\"vcpupin:'0-15,^8'\",Its syntax is a comma separated list and a special markup using '-' and '^' (ex. '0-4', '0-3,^2') can also be allowed, the '-' denotes the range and the '^' denotes exclusive. For KVM memory binding, the value is like:'membind:0', restrict a guest to allocate memory from the specified set of NUMA nodes. For PCI passthrough, the value is like:'devpassthrough:pci_0001_01_00_0,pci_0000_03_00_0',the PCI devices are assigned to a virtual machine, and the virtual machine can use this I/O exclusively,the devices list are a list of PCI device names delimited with comma, the PCI device names can be obtained by running B<virsh nodedev-list> on the host.",
'guestostype' => "This allows administrator to specify an identifier for OS to pass through to virtualization stack. Normally this should be ignored as xCAT will translate from nodetype.os rather than requiring this field be used\n",
'beacon' => "This flag is used by xCAT to track the state of the identify LED with respect to the VM.",
'datacenter' => "Optionally specify a datacenter for the VM to exist in (only applicable to VMWare)",

View File

@ -250,9 +250,11 @@ my %usage = (
[add_vmnics=vlan1,vlan2] [add_vmstorage=<N|viosnode:slotid>] [--vios]
chvm <noderange> [del_physlots=drc_index1,drc_index2...]
chvm <noderange> [del_vadapter=slotid]
KVM specific:
chvm <noderange> [--cpupin hostcpuset]
chvm <noderange> [--membind numanodeset]
chvm <noderange> [--devpassthru pcidevice1,pcidevice2... ]
chvm <noderange> [--devdetach pcidevice1,pcidevice2... ]
VMware specific:
chvm <noderange> [-a size][-d disk][-p disk][--resize disk=size][--cpus count][--mem memory]
zVM specific:

View File

@ -29,12 +29,16 @@ B<chvm> I<noderange> [B<vmcpus=min/req/max>] [B<vmmemory=min/req/max>]
[B<del_physlots=drc_index1,drc_index2...>]
[B<del_vadapter=slotid>]
=head2 KVM specific:
B<chvm> I<noderange> [B<--cpupin> I<hostcpuset>]
B<chvm> I<noderange> [B<--membind> I<numanodeset>]
B<chvm> I<noderange> [B<--devpassthru> I<pcidevice>...]
B<chvm> I<noderange> [B<--devdetach> I<pcidevice>...]
=head2 VMware/KVM specific:
@ -125,9 +129,6 @@ For normal power machine:
chvm could be used to modify the resources assigned to partitions. The admin shall specify the attributes with options I<vmcpus>, I<vmmemory>, I<add_physlots>, I<vmothersetting>, I<add_vmnics> and/or I<add_vmstorage>. If nothing specified, nothing will be returned.
=head2 VMware/KVM specific:
The chvm command modifes the vm specified in noderange. Calling with deregister or purge options at the same time as the resize option is not recommended.
=head2 zVM specific:
@ -223,28 +224,6 @@ To delete physical slots which are specified by the I<drc_index1,drc_index2...>.
To delete a virtual adapter specified by the I<slotid>.
=item B<--cpupin hostcpuset>
To pin guest domain virtual CPUs to physical host CPUs specified with I<hostcpuset>.
I<hostcpuset> is a list of physical CPU numbers. Its syntax is a comma separated list and a special
markup using '-' and '^' (ex. '0-4', '0-3,^2') can also be allowed. The '-' denotes the range and
the '^' denotes exclusive.
Note: The expression is sequentially evaluated, so "0-15,^8" is identical to "9-14,0-7,15" but not
identical to "^8,0-15".
=item B<--membind numanodeset>
It is possible to restrict a guest to allocate memory from the specified set of NUMA nodes I<numanodeset>.
If the guest vCPUs are also pinned to a set of cores located on that same set of NUMA nodes, memory
access is local and improves memory access performance.
=item B<--devpassthru pcidevice1,pcidevice2...>
The PCI passthrough gives a guest VM direct access to I/O devices I<pcidevice1,pcidevice2...>.
The PCI devices are assigned to a virtual machine, and the virtual machine can use this I/O exclusively.
The devices list are a list of comma separated PCI device names delimited with comma, the PCI device names can be obtained by running B<virsh nodedev-list> on the host.
=back
@ -276,6 +255,40 @@ Purge the Hard disk. Deregisters and deletes the files. Multiple can be done w
Change the size of the Hard disk. The disk can never be set to less than it's current size. Multiple disks can be resized to I<size> by using comma separated values on the left side of B<=>. The disks are specified by SCSI id. Size defaults to GB.
=back
=head2 KVM specific:
=over 10
=item B<--cpupin hostcpuset>
To pin guest domain virtual CPUs to physical host CPUs specified with I<hostcpuset>.
I<hostcpuset> is a list of physical CPU numbers. Its syntax is a comma separated list and a special
markup using '-' and '^' (ex. '0-4', '0-3,^2') can also be allowed. The '-' denotes the range and
the '^' denotes exclusive.
Note: The expression is sequentially evaluated, so "0-15,^8" is identical to "9-14,0-7,15" but not
identical to "^8,0-15".
=item B<--membind numanodeset>
It is possible to restrict a guest to allocate memory from the specified set of NUMA nodes I<numanodeset>.
If the guest vCPUs are also pinned to a set of cores located on that same set of NUMA nodes, memory
access is local and improves memory access performance.
=item B<--devpassthru pcidevice1,pcidevice2...>
The PCI passthrough gives a guest VM direct access to I/O devices I<pcidevice1,pcidevice2...>.
The PCI devices are assigned to a virtual machine, and the virtual machine can use this I/O exclusively.
The devices list are a list of comma separated PCI device names delimited with comma, the PCI device names can be obtained by running B<virsh nodedev-list> on the host.
=item B<--devdetach pcidevice1,pcidevice2...>
To detaching the PCI devices which are attached to VM guest via PCI passthrough from the VM guest. The devices list are a list of comma separated PCI device names delimited with comma, the PCI device names can be obtained by running B<virsh nodedev-list> on the host.
=back
=head2 zVM specific:

View File

@ -36,7 +36,7 @@ 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
require Sys::Virt;
require Sys::Virt;
if (Sys::Virt->VERSION =~ /^0\.[10]\./) {
die;
}
@ -1711,9 +1711,12 @@ sub chvm {
my $pcpuset;
my $numanodeset;
my $passthrudevices;
my $devicestodetach;
@ARGV=@_;
require Getopt::Long;
GetOptions(
Getopt::Long::Configure("bundling");
Getopt::Long::Configure("no_pass_through");
if (!GetOptions(
"a=s"=>\@addsizes,
"d=s"=>\@derefdisks,
"mem|memory=s"=>\$memory,
@ -1725,7 +1728,14 @@ sub chvm {
"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";
xCAT::MsgUtils->message("E", $rsp, $callback);
return;
};
if (@derefdisks) {
xCAT::SvrUtils::sendmsg([1,"Detach without purge TODO for kvm"],$callback,$node);
return;
@ -2157,6 +2167,9 @@ sub chvm {
unless($devxml){
next;
}
my $devhash=XMLin($devxml);
if(defined $devhash->{capability}->{type} and $devhash->{capability}->{type} =~ /pci/i ){
my %tmphash;
@ -2169,11 +2182,40 @@ sub chvm {
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 <hostdev> 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 {
$dom->attach_device($newxml);
$devobj->dettach(undef,0);
};
if ($@) {
xCAT::SvrUtils::sendmsg([1,"$@"],$callback,$node);
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();
@ -2211,13 +2253,11 @@ sub chvm {
#hostdev existed in guest xml
$hostdevfound=1;
goto PROCESS_HOSTDEV_XML;
goto PROCESS_HOSTDEV_XML_ATTATCH;
}
}
PROCESS_HOSTDEV_XML:
PROCESS_HOSTDEV_XML_ATTATCH:
unless($hostdevfound){
#hostdev does not exist,add into guest xml
my $hostdevnode = $parser->parse_balanced_chunk($newxml);
@ -2232,10 +2272,126 @@ sub chvm {
}
}
}
}
$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;