diff --git a/perl-xCAT/xCAT/Schema.pm b/perl-xCAT/xCAT/Schema.pm index fc6e18c55..5c84c9d1b 100644 --- a/perl-xCAT/xCAT/Schema.pm +++ b/perl-xCAT/xCAT/Schema.pm @@ -425,7 +425,7 @@ mpa => { }, }, networks => { - cols => [qw(netname net mask mgtifname gateway dhcpserver tftpserver nameservers ntpservers logservers dynamicrange nodehostname ddnsdomain comments disable)], + cols => [qw(netname net mask mgtifname gateway dhcpserver tftpserver nameservers ntpservers logservers dynamicrange nodehostname ddnsdomain vlanid comments disable)], keys => [qw(net mask)], table_desc => 'Describes the networks in the cluster and info necessary to set up nodes on that network.', descriptions => { @@ -441,7 +441,8 @@ networks => { logservers => 'The log servers for this network. Used in creating the DHCP network definition. Assumed to be the DHCP server if not set.', dynamicrange => 'The IP address range used by DHCP to assign dynamic IP addresses for requests on this network. This should not overlap with entities expected to be configured with static host declarations, i.e. anything ever expected to be a node with an address registered in the mac table.', nodehostname => 'A regular expression used to specify node name to network-specific hostname. i.e. "/\z/-secondary/" would mean that the hostname of "n1" would be n1-secondary on this network. By default, the nodename is assumed to equal the hostname, followed by nodename-interfacename.', - ddnsdomain => 'A domain to be combined with nodename to construct FQDN for DDNS updates induced by DHCP. This is not passed down to the client as "domain"', + ddnsdomain => 'A domain to be combined with nodename to construct FQDN for DDNS updates induced by DHCP. This is not passed down to the client as "domain"', + vlanid => 'The vlan ID if this network is within a vlan.', comments => 'Any user-written notes.', disable => "Set to 'yes' or '1' to comment out this row.", }, @@ -2067,6 +2068,10 @@ push(@{$defspec{node}->{'attrs'}}, @nodeattrs); {attr_name => 'dynamicrange', tabentry => 'networks.dynamicrange', access_tabentry => 'networks.netname=attr:netname', + }, + {attr_name => 'vlanid', + tabentry => 'networks.vlanid', + access_tabentry => 'networks.netname=attr:netname', }, {attr_name => 'usercomment', tabentry => 'networks.comments', diff --git a/xCAT-server/lib/perl/xCAT/Postage.pm b/xCAT-server/lib/perl/xCAT/Postage.pm index 638967207..542f225d2 100644 --- a/xCAT-server/lib/perl/xCAT/Postage.pm +++ b/xCAT-server/lib/perl/xCAT/Postage.pm @@ -334,6 +334,81 @@ sub makescript push @scriptd, "export MACADDRESS\n"; } + #get vlan related items + my $vlan; + my $swtab = xCAT::Table->new("switch", -create => 0); + if ($swtab) { + my $tmp = $swtab->getNodeAttribs($node, ['vlan']); + if (defined($tmp) && ($tmp) && $tmp->{vlan}) + { + $vlan = $tmp->{vlan}; + push @scriptd, "VLANID='" . $vlan . "'\n"; + push @scriptd, "export VLANID\n"; + } else { + my $vmtab = xCAT::Table->new("vm", -create => 0); + if ($vmtab) { + my $tmp1 = $vmtab->getNodeAttribs($node, ['nics']); + if (defined($tmp1) && ($tmp1) && $tmp1->{nics}) + { + push @scriptd, "VMNODE='YES'\n"; + push @scriptd, "export VMNODE\n"; + + my @nics=split(',', $tmp1->{nics}); + foreach my $nic (@nics) { + if ($nic =~ /^vl([\d]+)$/) { + $vlan = $1; + push @scriptd, "VLANID='" . $vlan . "'\n"; + push @scriptd, "export VLANID\n"; + last; + } + } + } + } + } + + if ($vlan) { + my $nwtab=xCAT::Table->new("networks", -create =>0); + if ($nwtab) { + my $sent = $nwtab->getAttribs({vlanid=>"$vlan"},'net','mask'); + my $subnet; + my $netmask; + if ($sent and ($sent->{net})) { + $subnet=$sent->{net}; + $netmask=$sent->{mask}; + } + if (($subnet) && ($netmask)) { + my $hoststab = xCAT::Table->new("hosts", -create => 0); + if ($hoststab) { + my $tmp = $hoststab->getNodeAttribs($node, ['otherinterfaces']); + if (defined($tmp) && ($tmp) && $tmp->{otherinterfaces}) + { + my $otherinterfaces = $tmp->{otherinterfaces}; + my @itf_pairs=split(/,/, $otherinterfaces); + foreach (@itf_pairs) { + my ($name,$ip)=split(/:/, $_); + if(xCAT::NetworkUtils->ishostinsubnet($ip, $netmask, $subnet)) { + if ($name =~ /^-/ ) { + $name = $node.$name; + } + push @scriptd, "VLANHOSTNAME='" . $name . "'\n"; + push @scriptd, "export VLANHOSTNAME\n"; + push @scriptd, "VLANIP='" . $ip . "'\n"; + push @scriptd, "export VLANIP\n"; + push @scriptd, "VLANSUBNET='" . $subnet . "'\n"; + push @scriptd, "export VLANSUBNET\n"; + push @scriptd, "VLANNETMASK='" . $netmask . "'\n"; + push @scriptd, "export VLANNETMASK\n"; + last; + } + } + } + } + } + } + } + } + + #get monitoring server and other configuration data for monitoring setup on nodes my %mon_conf = xCAT_monitoring::monitorctrl->getNodeConfData($node); foreach (keys(%mon_conf)) diff --git a/xCAT-server/lib/xcat/plugins/bind.pm b/xCAT-server/lib/xcat/plugins/bind.pm index d5483bba6..c19164f53 100755 --- a/xCAT-server/lib/xcat/plugins/bind.pm +++ b/xCAT-server/lib/xcat/plugins/bind.pm @@ -125,7 +125,7 @@ sub process_request my $rsp = {}; $rsp->{data}->[0] = "Could not create $DBDir.\n"; xCAT::MsgUtils->message("E", $rsp, $callback, 1); - exit 1; + return 1; } } @@ -448,7 +448,7 @@ sub process_request my $rsp = {}; $rsp->{data}->[0] = "Setup of DNS complete."; xCAT::MsgUtils->message("I", $rsp, $callback); - exit 0; + return 0; } # diff --git a/xCAT-server/lib/xcat/plugins/kvm.pm b/xCAT-server/lib/xcat/plugins/kvm.pm index e7d686ea9..36a615e80 100644 --- a/xCAT-server/lib/xcat/plugins/kvm.pm +++ b/xCAT-server/lib/xcat/plugins/kvm.pm @@ -238,12 +238,14 @@ sub get_filepath_by_url { #at the end of the day, the libvirt storage api gives 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 my $poolobj = get_storage_pool_by_url($url); unless ($poolobj) { die "Could not get storage pool for $url"; } $poolobj->refresh(); #if volumes change on nfs storage, libvirt is too dumb to notice 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) { @@ -375,6 +377,7 @@ sub build_oshash { } sub build_diskstruct { + print "build_diskstruct called\n"; my $cdloc=shift; my @returns=(); my $currdev; @@ -875,9 +878,48 @@ sub xhrm_satisfy { if ($confdata->{vm}->{$node}->[0]->{nics}) { @nics = split /,/,$confdata->{vm}->{$node}->[0]->{nics}; } + + $rc |=system("scp $::XCATROOT/share/xcat/scripts/xHRM $hyp:/usr/bin"); + foreach (@nics) { s/=.*//; #this code cares not about the model of virtual nic - $rc |=system("ssh $hyp xHRM bridgeprereq $_"); + my $nic=$_; + my $vlanip; + my $netmask; + my $subnet; + if ($nic =~ /^vl([\d]+)$/) { + my $vlan=$1; + my $nwtab=xCAT::Table->new("networks", -create =>0); + if ($nwtab) { + my $sent = $nwtab->getAttribs({vlanid=>"$vlan"},'net','mask'); + if ($sent and ($sent->{net})) { + $subnet=$sent->{net}; + $netmask=$sent->{mask}; + } + if (($subnet) && ($netmask)) { + my $hoststab = xCAT::Table->new("hosts", -create => 0); + if ($hoststab) { + my $tmp = $hoststab->getNodeAttribs($hyp, ['otherinterfaces']); + if (defined($tmp) && ($tmp) && $tmp->{otherinterfaces}) + { + my $otherinterfaces = $tmp->{otherinterfaces}; + my @itf_pairs=split(/,/, $otherinterfaces); + foreach (@itf_pairs) { + my ($name,$vip)=split(/:/, $_); + if(xCAT::NetworkUtils->ishostinsubnet($vip, $netmask, $subnet)) { + $vlanip=$vip; + last; + } + } + } + } + } + } + } + + #print "nic=$nic\n"; + $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 @@ -938,6 +980,7 @@ sub makedom { sub createstorage { #svn rev 6638 held the older vintage of createstorage + #print "createstorage called\n"; my $filename=shift; my $mastername=shift; my $size=shift; @@ -979,7 +1022,7 @@ sub createstorage { if ($filename =~ /^nfs:/ or $filename =~ /^dir:/) { #libvirt storage pool to be used for this my @sizes = split /,/,$size; foreach (@sizes) { - get_filepath_by_url(url=>$filename,dev=>$prefix.shift(@suffixes),create=>$_); + get_filepath_by_url(url=>$filename,dev=>$prefix.shift(@suffixes),create=>$_, force=>$force); } }else{ oldCreateStorage($filename, $mastername, $size, $cfginfo, $force); @@ -1861,6 +1904,7 @@ sub mkvm { return 1,"mkvm management of block device storage not implemented"; } } + #print "force=$force\n"; if ($mastername or $disksize) { my @return= createstorage($diskname,$mastername,$disksize,$confdata->{vm}->{$node}->[0],$force); unless ($confdata->{kvmnodedata}->{$node} and $confdata->{kvmnodedata}->{$node}->[0] and $confdata->{kvmnodedata}->{$node}->[0]->{xml}) { diff --git a/xCAT-server/share/xcat/scripts/xHRM b/xCAT-server/share/xcat/scripts/xHRM index 72d7ef9c8..a0165e8ea 100755 --- a/xCAT-server/share/xcat/scripts/xHRM +++ b/xCAT-server/share/xcat/scripts/xHRM @@ -1,131 +1,206 @@ #!/bin/bash #written in bash for fewest prerequisites function get_def_interface { - #gethostbyname on `hostname` would be helpful, but since we - #are in bash, the best alternative is to use ping to get at it - #don't want to grep in /etc/hosts or presume DNS - #we are, however, presuming ipv4 for the moment - retval=$(ping -c 1 `hostname`|head -n 1|cut -d\( -f 2|cut -d\) -f 1) - if [ -z "$retval" -o "127.0.0.1" = "$retval" ]; then #ok, that didn't pan out, now we grab the first address that looks sane - retval=`ifconfig|grep inet" " |grep -v addr:127.0.0.1|grep -v 'addr:169.254'|head -n 1|cut -d: -f 2|cut -d' ' -f 1` - fi - if [ -z "$retval" ]; then - echo "ERROR: Unable to reasonably guess the 'default' interface" >&2 - exit 1 - fi - iface=`ifconfig|grep -v inet6|egrep '(Link|inet)'|grep -B1 'addr:'$retval |head -n 1|awk '{print $1}'` - if [ -z "$iface" ]; then - echo "ERROR: Unable to reasonably guess the default interface" >&2 - exit 1 - fi - if brctl show | grep ^$iface >& /dev/null; then # - OIFS=$IFS - IFS=$'\n' + #gethostbyname on `hostname` would be helpful, but since we + #are in bash, the best alternative is to use ping to get at it + #don't want to grep in /etc/hosts or presume DNS + #we are, however, presuming ipv4 for the moment + retval=$(ping -c 1 `hostname`|head -n 1|cut -d\( -f 2|cut -d\) -f 1) + if [ -z "$retval" -o "127.0.0.1" = "$retval" ]; then #ok, that didn't pan out, now we grab the first address that looks sane + retval=`ifconfig|grep inet" " |grep -v addr:127.0.0.1|grep -v 'addr:169.254'|head -n 1|cut -d: -f 2|cut -d' ' -f 1` + fi + if [ -z "$retval" ]; then + echo "ERROR: Unable to reasonably guess the 'default' interface" >&2 + exit 1 + fi + iface=`ifconfig|grep -v inet6|egrep '(Link|inet)'|grep -B1 'addr:'$retval |head -n 1|awk '{print $1}'` + if [ -z "$iface" ]; then + echo "ERROR: Unable to reasonably guess the default interface" >&2 + exit 1 + fi + if brctl show | grep ^$iface >& /dev/null; then # + OIFS=$IFS + IFS=$'\n' + INMATCH=0 + for brline in $(brctl show); do + if [ $(expr match "$brline" $iface) == $(expr length $iface) ]; then + INMATCH=1 + elif [ $(expr match "$brline" " ") != 1 ]; then INMATCH=0 - for brline in $(brctl show); do - if [ $(expr match "$brline" $iface) == $(expr length $iface) ]; then - INMATCH=1 - elif [ $(expr match "$brline" " ") != 1 ]; then - INMATCH=0 - fi - if [ "$INMATCH" == 1 ]; then - if ! ethtool -i `echo $brline|awk '{print $NF}'`|grep "driver: tun" >& /dev/null; then - iface=`echo $brline|awk '{print $NF}'` - echo "$iface" - IFS=$OFIS - return - fi - fi - done - else - echo "$iface" - fi + fi + if [ "$INMATCH" == 1 ]; then + if ! ethtool -i `echo $brline|awk '{print $NF}'`|grep "driver: tun" >& /dev/null; then + iface=`echo $brline|awk '{print $NF}'` + echo "$iface" + IFS=$OFIS + return + fi + fi + done + else + echo "$iface" + fi } if [ "storageprereq" = "$1" ]; then - MOUNTURI="$2" - DIRNAME=`echo $MOUNTURI|sed -e 's!nfs://!nfs_!'` - MOUNTPATH=`echo $DIRNAME|sed -e 's!nfs_!!'|sed -e 's!/!:/!'` - if mount|grep $MOUNTPATH > /dev/null; then - exit 0; - fi - mkdir -p /var/lib/xcat/vmnt/$DIRNAME - mount $MOUNTPATH /var/lib/xcat/vmnt/$DIRNAME + MOUNTURI="$2" + DIRNAME=`echo $MOUNTURI|sed -e 's!nfs://!nfs_!'` + MOUNTPATH=`echo $DIRNAME|sed -e 's!nfs_!!'|sed -e 's!/!:/!'` + if mount|grep $MOUNTPATH > /dev/null; then + exit 0; + fi + mkdir -p /var/lib/xcat/vmnt/$DIRNAME + mount $MOUNTPATH /var/lib/xcat/vmnt/$DIRNAME elif [ "bridgeprereq" = "$1" ]; then - NETDESC="$2" - if [ -z "$NETDESC" ]; then - echo "Incorrect usage" - exit 1 - fi - if echo "$NETDESC"|grep ':'> /dev/null; then - PORTS=`echo "$NETDESC"|cut -d: -f 1` - BNAME=`echo "$NETDESC"|cut -d: -f 2` - else - BNAME=$NETDESC - fi - if brctl showstp "$BNAME" > /dev/null; then - echo "$BNAME" - exit 0 - fi - #Still here, that means we must build a bridge - if [ -z "$PORTS" ]; then #No ports specified, default to whatever looks up - PORTS=$(get_def_interface) - fi - if [ -z "$PORTS" ]; then #This has been checked many times before in theory, check again just in case - exit 1 - fi - #For now, we only support bridge name==network name. This precludes - #the config of the same vlan number on multiple fabrics, but - #will cover that flexibility later if demanded (with 4k vlan ids, - #I think it would be unwise to reuse them as it could confuse anyway) - if echo "$PORTS"|grep '&'; then #we have bonding... fun to be had - #To be slack, going to just support one bond for now.. - modprobe bonding miimon=100 mode=4 - PORTS=`echo $PORTS |sed -e 's/&/ /'` - ip link set bond0 up - for p in $PORTS; do - #TODO: we are only going to manage the default - #route for now - saveroutes=`ip route | grep default| grep "dev $p"|grep via|sed -e 's/dev .*//'` - #TODO: support inet6+inet and aliases, probably messing with IFS to do so - saveip=`ip addr show dev $p scope global|grep inet|sed -e 's/inet.//'|sed -e 's/[^ ]*$//'` - if [ ! -z "$saveip" ]; then - ip addr add dev bond0 $saveip - fi - ifenslave bond0 $p - if [ ! -z "$saveroutes" ]; then - ip route add $saveroutes - fi - done - PORTS=bond0 - fi - if echo "$BNAME"|egrep '^vl(an)?[0123456789]' > /dev/null; then - TNAME=${BNAME##vl} - TNAME=${TNAME##an} - #We have a vlan... more fun - modprobe 8021q - vconfig add $PORTS $TNAME - vconfig set_flag $PORTS.$TNAME 2 1 #Turn on GVRP where supported - ip link set $PORTS.$TNAME up - PORTS=$PORTS.$TNAME - fi - #Now, $PORTS is 'the' physical device to participate in a bridge - #TODO: we are only going to manage the default - #route for now - brctl addbr $BNAME - brctl setfd $BNAME 0 #fast forwarding - ip link set $BNAME up - saveroutes=`ip route | grep default| grep "dev $PORTS"|grep via|sed -e 's/dev .*//'` - #TODO: support inet6+inet and aliases, probably messing with IFS to do so - saveip=`ip addr show dev $PORTS scope global|grep inet|sed -e 's/inet.//'|sed -e 's/[^ ]*$//'` - if [ ! -z "$saveip" ]; then - ip addr add dev $BNAME $saveip - fi - brctl addif $BNAME $PORTS - if [ ! -z "$saveip" ]; then - ip addr del dev $PORTS $saveip - fi - if [ ! -z "$saveroutes" ]; then + NETDESC="$2" + if [ -z "$NETDESC" ]; then + echo "Incorrect usage" + exit 1 + fi + if echo "$NETDESC"|grep ':'> /dev/null; then + PORTS=`echo "$NETDESC"|cut -d: -f 1` + BNAME=`echo "$NETDESC"|cut -d: -f 2` + else + BNAME=$NETDESC + fi + if brctl showstp "$BNAME" > /dev/null; then + echo "$BNAME" + exit 0 + fi + #Still here, that means we must build a bridge + if [ -z "$PORTS" ]; then #No ports specified, default to whatever looks up + PORTS=$(get_def_interface) + fi + if [ -z "$PORTS" ]; then #This has been checked many times before in theory, check again just in case + exit 1 + fi + #For now, we only support bridge name==network name. This precludes + #the config of the same vlan number on multiple fabrics, but + #will cover that flexibility later if demanded (with 4k vlan ids, + #I think it would be unwise to reuse them as it could confuse anyway) + if echo "$PORTS"|grep '&'; then #we have bonding... fun to be had + #To be slack, going to just support one bond for now.. + modprobe bonding miimon=100 mode=4 + PORTS=`echo $PORTS |sed -e 's/&/ /'` + ip link set bond0 up + for p in $PORTS; do + #TODO: we are only going to manage the default + #route for now + saveroutes=`ip route | grep default| grep "dev $p"|grep via|sed -e 's/dev .*//'` + #TODO: support inet6+inet and aliases, probably messing with IFS to do so + saveip=`ip addr show dev $p scope global|grep inet|sed -e 's/inet.//'|sed -e 's/[^ ]*$//'` + if [ ! -z "$saveip" ]; then + ip addr add dev bond0 $saveip + fi + ifenslave bond0 $p + if [ ! -z "$saveroutes" ]; then ip route add $saveroutes + fi + done + PORTS=bond0 + fi + if echo "$BNAME"|egrep '^vl(an)?[0123456789]' > /dev/null; then + vlan="yes" + TNAME=${BNAME##vl} + TNAME=${TNAME##an} + #We have a vlan... more fun + modprobe 8021q + vconfig add $PORTS $TNAME + vconfig set_flag $PORTS.$TNAME 2 1 #Turn on GVRP where supported + ip link set $PORTS.$TNAME up + PORTS=$PORTS.$TNAME + fi + #Now, $PORTS is 'the' physical device to participate in a bridge + #TODO: we are only going to manage the default + #route for now + brctl addbr $BNAME + brctl setfd $BNAME 0 #fast forwarding + ip link set $BNAME up + saveroutes=`ip route | grep default| grep "dev $PORTS"|grep via|sed -e 's/dev .*//'` + #TODO: support inet6+inet and aliases, probably messing with IFS to do so + saveip=`ip addr show dev $PORTS scope global|grep inet|sed -e 's/inet.//'|sed -e 's/[^ ]*$//'` + if [ ! -z "$saveip" ]; then + ip addr add dev $BNAME $saveip + else + if [ ! -z "$3" ]; then + ip addr add dev $BNAME $3 fi + fi + brctl addif $BNAME $PORTS + if [ ! -z "$saveip" ]; then + ip addr del dev $PORTS $saveip + fi + if [ ! -z "$saveroutes" ]; then + ip route add $saveroutes + fi + + #now save the settings into the config files so that they will be persistent among reboots + if [[ $OSVER = sles* ]] || [[ $OSVER = suse* ]] || [[ -f /etc/SuSE-release ]]; then + nwdir="/etc/sysconfig/network" + isSLES=1 + else + nwdir="/etc/sysconfig/network-scripts" + fi + + #write into the network configuration file + if [[ $isSLES -eq 1 ]]; then + cat >$nwdir/ifcfg-$PORTS <> $nwdir/ifcfg-$PORTS + fi + if [ ! -z "$vlan" ]; then + echo "VLAN='yes'" >> $nwdir/ifcfg-$PORTS + fi + cat >$nwdir/ifcfg-$BNAME <> $nwdir/ifcfg-$BNAME + if [ ! -z "$4" ]; then + echo "NETMASK='$4'" >> $nwdir/ifcfg-$BNAME + fi + else + echo "BOOTPROTO=dhcp" >> $nwdir/ifcfg-$BNAME + fi + else + cat >$nwdir/ifcfg-$PORTS <> $nwdir/ifcfg-$PORTS + fi + if [ ! -z "$vlan" ]; then + echo "VLAN=yes" >> $nwdir/ifcfg-$PORTS + fi + cat >$nwdir/ifcfg-$BNAME <> $nwdir/ifcfg-$BNAME + if [ ! -z "$4" ]; then + echo "NETMASK=$4" >> $nwdir/ifcfg-$BNAME + fi + else + echo "BOOTPROTO=dhcp" >> $nwdir/ifcfg-$BNAME + fi + fi + + ifup $BNAME fi #END bridge config. + \ No newline at end of file