common code for vlan configuration

git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@8888 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
This commit is contained in:
linggao 2011-02-18 20:01:39 +00:00
parent 5caf25f106
commit 05364d326b
5 changed files with 325 additions and 126 deletions

View File

@ -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',

View File

@ -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))

View File

@ -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;
}
#

View File

@ -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}) {

View File

@ -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 <<EOF
DEVICE='$PORTS'
ONBOOT='yes'
BRIDGE='$BNAME'
EOF
mac=`ip addr show dev $PORTS scope global|grep link|sed -e 's/link\/ether//'|sed -e 's/brd.*$//'|sed -e 's/[ ]*//'`
if [ ! -z "$mac" ]; then
echo "HWADDR='$mac'" >> $nwdir/ifcfg-$PORTS
fi
if [ ! -z "$vlan" ]; then
echo "VLAN='yes'" >> $nwdir/ifcfg-$PORTS
fi
cat >$nwdir/ifcfg-$BNAME <<EOF
DEVICE='$BNAME'
TYPE='Bridge'
ONBOOT='yes'
PEERDNS='yes'
DELAY='0'
EOF
if [ ! -z "$3" ]; then
echo "IPADDR='$3'" >> $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 <<EOF
DEVICE=$PORTS
ONBOOT=yes
BRIDGE=$BNAME
EOF
mac=`ip addr show dev $PORTS scope global|grep link|sed -e 's/link\/ether//'|sed -e 's/brd.*$//'|sed -e 's/[ ]*//'`
if [ ! -z "$mac" ]; then
echo "HWADDR=$mac" >> $nwdir/ifcfg-$PORTS
fi
if [ ! -z "$vlan" ]; then
echo "VLAN=yes" >> $nwdir/ifcfg-$PORTS
fi
cat >$nwdir/ifcfg-$BNAME <<EOF
DEVICE=$BNAME
TYPE=Bridge
ONBOOT=yes
PEERDNS=yes
DELAY=0
EOF
if [ ! -z "$3" ]; then
echo "IPADDR=$3" >> $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.