diff --git a/perl-xCAT/xCAT/Schema.pm b/perl-xCAT/xCAT/Schema.pm index dedee793e..7c4b22c6d 100644 --- a/perl-xCAT/xCAT/Schema.pm +++ b/perl-xCAT/xCAT/Schema.pm @@ -50,7 +50,7 @@ vm => { 'cfgstore' => 'Optional location for persistant storage separate of emulated hard drives for virtualization solutions that require persistant store to place configuration data', 'memory' => 'Megabytes of memory the VM currently should be set to.', 'cpus' => 'Number of CPUs the node should see.', - 'nics' => 'Network configuration parameters', + 'nics' => 'Network configuration parameters. Of the general form [physnet:]interface[=model],.. Generally, interface describes the vlan entity (default for native, tagged for tagged, vl[number] for a specific vlan. model is the type of device to imitate (i.e. virtio, e1000 (generally default), rtl8139, depending on the virtualization technology. physnet is a virtual switch name or port description that is used for some virtualization technologies to construct virtual switches. hypervisor.netmap can map names to hypervisor specific layouts, or the descriptions described there may be used directly here where possible.', 'bootorder' => 'Boot sequence (i.e. net,hd)', 'clockoffset' => 'Whether to have guest RTC synced to "localtime" or "utc" If not populated, xCAT will guess based on the nodetype.os contents.', 'virtflags' => 'General flags used by the virtualization method. For example, in Xen it could, among other things, specify paravirtualized setup, or direct kernel boot. For a hypervisor/dom0 entry, it is the virtualization method (i.e. "xen")', @@ -60,12 +60,13 @@ vm => { } }, hypervisor => { - cols => [qw(node mgr comments disable)], + cols => [qw(node mgr netmap comments disable)], keys => [qw(node)], table_desc => 'Hypervisor parameters', descriptions => { 'node' => 'The node or static group name', mgr => 'The virtualization specific manager of this hypervisor when applicable', + 'netmap' => 'Optional mapping of useful names to relevant physical ports. For example, 10ge=vmnic_16.0&vmnic_16.1,ge=vmnic1 would be requesting two virtual switches to be created, one called 10ge with vmnic_16.0 and vmnic_16.1 bonded, and another simply connected to vmnic1. Use of this allows abstracting guests from network differences amongst hypervisors', } }, websrv => { diff --git a/xCAT-server/lib/xcat/plugins/esx.pm b/xCAT-server/lib/xcat/plugins/esx.pm index 8e52a7b81..c7c895cc9 100644 --- a/xCAT-server/lib/xcat/plugins/esx.pm +++ b/xCAT-server/lib/xcat/plugins/esx.pm @@ -326,6 +326,11 @@ sub process_request { $hyphash{$hyp}->{nodes}->{$node}=1;# $nodeid; } } + my $hyptab = xCAT::Table->new('hypervisor',create=>0); + if ($hyptab) { + my @hyps = keys %hyphash; + $tablecfg{hypervisor} = $hyptab->getNodesAttribs(\@hyps,['mgr','netmap']); + } #my $children = 0; #my $vmmaxp = 84; @@ -1409,14 +1414,95 @@ sub validate_datacenter_prereqs { -sub validate_vswitch_prereqs { +sub get_switchname_for_portdesc { +#Thisk function will examine all current switches to find or create a switch to match the described requirement my $hyp = shift; - my $switchname = shift; + my $portdesc = shift; + my $description; #actual name to use for the virtual switch + if ($tablecfg{hypervisor}->{$hyp}->[0]->{netmap}) { + foreach (split /,/,$tablecfg{hypervisor}->{$hyp}->[0]->{netmap}) { + if (/^$portdesc=/) { + ($description,$portdesc) = split /=/,$_,2; + last; + } + } + } else { + $description = 'vsw'.$portdesc; + } + unless ($description) { + sendmsg([1,": Invalid format for hypervisor.netmap detected for $hyp"]); + return undef; + } + my %requiredports; + my %portkeys; + foreach (split /&/,$portdesc) { + $requiredports{$_}=1; + } + my $hostview = $hyphash{$hyp}->{hostview}; unless ($hostview) { $hyphash{$hyp}->{hostview} = get_hostview(hypname=>$hyp,conn=>$hyphash{$hyp}->{conn}); #,properties=>['config','configManager']); $hostview = $hyphash{$hyp}->{hostview}; } + foreach (@{$hostview->config->network->pnic}) { + if ($requiredports{$_->device}) { #We establish lookups both ways + $portkeys{$_->key}=$_->device; + delete $requiredports{$_->device}; + } + } + if (keys %requiredports) { + sendmsg([1,":Unable to locate the following nics on $hyp: ".join(',',keys %requiredports)]); + return undef; + } + my $foundmatchswitch; + my $cfgmismatch=0; + my $vswitch; + foreach $vswitch (@{$hostview->config->network->vswitch}) { + $cfgmismatch=0; #new switch, no sign of mismatch + foreach (@{$vswitch->pnic}) { + if ($portkeys{$_}) { + $foundmatchswitch=$vswitch->name; + delete $requiredports{$portkeys{$_}}; + delete $portkeys{$_}; + } else { + $cfgmismatch=1; #If this turns out to have anything, it is bad + } + } + if ($foundmatchswitch) { last; } + } + if ($foundmatchswitch) { + if ($cfgmismatch) { + sendmsg([1,": Aggregation mismatch detected, request nic is aggregated with a nic not requested"]); + return undef; + } + unless (keys %portkeys) { + return $foundmatchswitch; + } + die "TODO: add physical nics to aggregation if requested"; + } else { + return create_vswitch($hyp,$description,values %portkeys); + } + die "impossible occurance"; + return undef; +} +sub create_vswitch { + my $hyp = shift; + my $description = shift; + my @ports = @_; + my $vswitch = HostVirtualSwitchBondBridge->new( + nicDevice=>\@ports + ); + my $vswspec = HostVirtualSwitchSpec->new( + bridge=>$vswitch, + mtu=>9000, + numPorts=>64 + ); + my $hostview = $hyphash{$hyp}->{hostview}; + my $netman=$hyphash{$hyp}->{conn}->get_view(mo_ref=>$hostview->configManager->networkSystem); + $netman->AddVirtualSwitch( + vswitchName=>$description, + spec=>$vswspec + ); } sub validate_network_prereqs { @@ -1448,9 +1534,8 @@ sub validate_network_prereqs { s/=.*//; #TODO specify nic model with =model if (/:/) { s/(.*)://; #TODO: support specifiying physical ports with : - $switchname = $1; + $switchname = get_switchname_for_portdesc($hyp,$1); } - #validate_vswitch_prereqs($switchname); #auto-add my $netname = $_; my $netsys; my $policy = HostNetworkPolicy->new(); @@ -1513,7 +1598,9 @@ sub validate_datastore_prereqs { } foreach $node (@$nodes) { my @storage = split /,/,$tablecfg{vm}->{$node}->[0]->{storage}; - push @storage,$tablecfg{vm}->{$node}->[0]->{cfgstore}; + if ($tablecfg{vm}->{$node}->[0]->{cfgstore}) { + push @storage,$tablecfg{vm}->{$node}->[0]->{cfgstore}; + } foreach (@storage) { s/\/$//; #Strip trailing slash if specified, to align to VMware semantics if (/:\/\//) {