add files for xCAT-vlan

This commit is contained in:
linggao 2015-01-27 12:09:37 -05:00
parent b877e034fb
commit 220374b22f
22 changed files with 5748 additions and 0 deletions

5
xCAT-vlan/debian/changelog Executable file
View File

@ -0,0 +1,5 @@
xcat-vlan (2.9-snap201304181624) unstable; urgency=low
* Initial release (Closes: #nnnn) <nnnn is the bug number of your ITP>
-- root <root@unknown> Thu, 18 Apr 2013 15:40:26 +0800

1
xCAT-vlan/debian/compat Executable file
View File

@ -0,0 +1 @@
8

13
xCAT-vlan/debian/control Executable file
View File

@ -0,0 +1,13 @@
Source: xcat-vlan
Section: admin
Priority: extra
Maintainer: root <root@unknown>
Build-Depends: debhelper (>= 8.0.0)
Standards-Version: 3.9.2
#Vcs-Git: git://git.debian.org/collab-maint/xcat-vlan.git
#Vcs-Browser: http://git.debian.org/?p=collab-maint/xcat-vlan.git;a=summary
Package: xcat-vlan
Architecture: all
Depends: xCAT-client
Description: xCAT-vlan provides the xCAT vlan confiuration.

36
xCAT-vlan/debian/copyright Executable file
View File

@ -0,0 +1,36 @@
Format: http://dep.debian.net/deps/dep5
Upstream-Name: xcat-vlan
Source: <url://example.com>
Files: *
Copyright: <years> <put author's name and email here>
<years> <likewise for another author>
License: <special license>
<Put the license of the package here indented by 1 space>
<This follows the format of Description: lines in control file>
.
<Including paragraphs>
# If you want to use GPL v2 or later for the /debian/* files use
# the following clauses, or change it to suit. Delete these two lines
Files: debian/*
Copyright: 2013 root <root@unknown>
License: GPL-2+
This package is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
.
This package is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
.
On Debian systems, the complete text of the GNU General
Public License version 2 can be found in "/usr/share/common-licenses/GPL-2".
# Please also look if there are files or directories which have a
# different copyright/license attached and list them here.

6
xCAT-vlan/debian/dirs Executable file
View File

@ -0,0 +1,6 @@
install/postscripts
opt/xcat/lib/perl/xCAT
opt/xcat/lib/perl/xCAT_plugin
opt/xcat/share/man/man1
opt/xcat/share/doc/man1
opt/xcat/bin

0
xCAT-vlan/debian/docs Executable file
View File

5
xCAT-vlan/debian/install Executable file
View File

@ -0,0 +1,5 @@
xCAT/* opt/xcat/lib/perl/xCAT/
xCAT_plugin/* opt/xcat/lib/perl/xCAT_plugin/
install/postscripts/* install/postscripts/
share/man/man1/* opt/xcat/share/man/man1
share/doc/man1/* opt/xcat/share/doc/man1

1
xCAT-vlan/debian/postinst Executable file
View File

@ -0,0 +1 @@
#!/bin/sh

39
xCAT-vlan/debian/rules Executable file
View File

@ -0,0 +1,39 @@
#!/usr/bin/make -f
# -*- makefile -*-
# Sample debian/rules that uses debhelper.
# This file was originally written by Joey Hess and Craig Small.
# As a special exception, when this file is copied by dh-make into a
# dh-make output file, you may use that output file without restriction.
# This special exception was added by Craig Small in version 0.37 of dh-make.
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
build:
./xpod2man
clean:
dh_testdir
dh_testroot
dh_clean -d
install:
pwd
dh_installdirs
dh_install -X".svn"
chmod 444 debian/xcat-vlan/opt/xcat/share/man/man1/*
chmod 644 debian/xcat-vlan/opt/xcat/share/doc/man1/*
ln -sf ../bin/xcatclientnnr debian/xcat-vlan/opt/xcat/bin/mkvlan
ln -sf ../bin/xcatclientnnr debian/xcat-vlan/opt/xcat/bin/chvla
ln -sf ../bin/xcatclientnnr debian/xcat-vlan/opt/xcat/bin/rmvlan
ln -sf ../bin/xcatclientnnr debian/xcat-vlan/opt/xcat/bin/lsvlan
binary-indep: build install
binary-arch:
dh_compress
dh_installdeb
dh_gencontrol
dh_md5sums
dh_builddeb
binary: binary-indep binary-arch
.PHONY: build clean binary-indep binary-arch binary install configure

View File

@ -0,0 +1,284 @@
#!/bin/sh
#-------------------------------------------------------------------------------------
#
# this script configures the vlan on the node, assuming the vlan is already creaed on the switch.
# configvlan <vlan_id>
# if vlan_is is not specified, all the vlans defined for the
# given node will be configured.
#
#-------------------------------------------------------------------------------------
#if [[ -z "$VLANID" ]] || [[ -z "$VLANHOSTNAME" ]] || [[ -z "$VLANIP" ]]; then
# logger -t xcat "configvlan: please make sure that vlan id, vlan hostname and vlan ip are defined for this node.\nPlease use mkvlan or chvlan command."
# echo "configvlan: please make sure that vlan id, vlan hostname and vlan ip are defined for this node.\nPlease use mkvlan or chvlan command."
# exit 0
#fi
if [[ -z $VLANMAXINDEX ]] || [[ $VLANMAXINDEX -eq 0 ]]; then
logger -t xcat "configvlan: Nothing to do."
echo "configvlan: Nothing to do."
exit 0
fi
if [[ $OSTYPE = linux* ]]; then
if [[ $OSVER = sles* ]] || [[ $OSVER = suse* ]] || [[ -f /etc/SuSE-release ]]; then
nwdir="/etc/sysconfig/network"
isSLES=1
else
nwdir="/etc/sysconfig/network-scripts"
fi
else
logger -t xcat "configvlan: Does not support AIX yet."
echo "configvlan: Does not support AIX yet."
exit 0
fi
keephostname=0
if [ $# -eq 1 ]
then
if [ "$1" = "--keephostname"]
then
keephostname=1
else
# the original logic
if [[ -n "$1" ]]; then
IN_VLAN=$1 #The vlan id to be configured, if not specified, all will be configured on this note.
fi
fi
fi
if [ $# -gt 1 ]
then
if [ "$1" = "--keephostname" ]
then
logger -t xcat "configvlan: Usage: configvlan <vlanid> <--keephostname>. Correct the arguments order."
echo "configvlan: Usage: configvlan <vlanid> <--keephostname>. Correct the arguments order."
exit -1
fi
# the original logic
IN_VLAN=$1 #The vlan id to be configured, if not specified, all will be configured on this note.
if [ "$2" != "--keephostname" ]
then
logger -t xcat "configvlan: Usage: configvlan <vlanid> <--keephostname>. Correct the arguments order."
echo "configvlan: Usage: configvlan <vlanid> <--keephostname>. Correct the arguments order."
exit -1
fi
keephostname=1
fi
index=1
while [ $index -le $VLANMAXINDEX ]; do
nic=""
eval VLANID=\$VLANID_$index
if [[ -n $IN_VLAN ]]; then
if [[ "$VLANID" != "$IN_VLAN" ]]; then
index=$((index+1))
continue
fi
fi
if [[ -z $VMNODE ]]; then #for bare-metal nodes
eval VLANNIC=\$VLANNIC_$index #VLANNIC could be ethx, primary, primary:ethx or empty
#determine if the current is primary network
PMRY=0
if [[ -z $VLANNIC ]] || [[ $VLANNIC = primary* ]]; then
PMRY=1
fi
if [[ $VLANNIC = primary* ]]; then
VLANNIC=${VLANNIC#primary}
fi
if [[ -n $VLANNIC ]]; then
nic=${VLANNIC#:}
fi
else #for KVM nodes
eval VLAN_VMNICPOS=\$VLAN_VMNICPOS_$index #VLAN_VMNICPOS identifies the position of the mac address in mac, the mac has the following format: 01:02:03:04:05:0E!node5|01:02:03:05:0F!node6-eth
PMRY=0
if [[ $index -eq 1 ]]; then
PMRY=1 ##the first one is always primary network
fi
if [[ -z $VLAN_VMNICPOS ]]; then
nic="eth1"
fi
fi
if [[ -z $nic ]]; then #get the nic
if [[ -n $MACADDRESS ]]; then
pos=0
#mac has the following format: 01:02:03:04:05:0E!node5|01:02:03:05:0F!node6-eth1
for x in `echo "$MACADDRESS" | tr "|" "\n"`
do
node=""
mac=""
pos=$((pos+1))
i=`expr index $x !`
if [[ $i -gt 0 ]]; then
node=`echo ${x##*!}`
mac_tmp=`echo ${x%%!*}`
else
mac_tmp=$x
fi
if [[ $pos -eq 1 ]]; then
mac1=$mac_tmp
fi
if [[ -n $VMNODE ]]; then
if [[ $pos -eq $VLAN_VMNICPOS ]]; then
mac=$mac_tmp
break
fi
else
if [[ "$PRIMARYNIC" = "$mac_tmp" ]]; then
mac=$mac_tmp
break
fi
if [[ -z "$PRIMARYNIC" ]] || [[ "$PRIMARYNIC" = "mac" ]]; then
if [[ -z $node ]] || [[ "$node" = "$NODE" ]]; then
mac=$mac_tmp
break
fi
fi
fi
done
if [[ -z $mac ]]; then
if [[ -n $VMNODE ]]; then
mac=$mac1
else
if [[ -z "$PRIMARYNIC" ]] || [[ "$PRIMARYNIC" = "mac" ]]; then
mac=$mac1 #if nothing mathes, take the first mac
else
nic=$PRIMARYNIC #or the primary nic itself is the nic
fi
fi
fi
else
logger -t xcat "configvlan: no mac addresses are defined in the mac table for the node $NODE"
echo "configvlan: no mac addresses are defined in the mac table for the node $NODE"
index=$((index+1))
continue
fi
echo "mac=$mac"
fi
if [[ -z $nic ]]; then
#go to each nic to match the mac address
ret=`ifconfig |grep -i $mac | cut -d' ' -f 1 2>&1`;
if [ $? -eq 0 ]; then
for x in $ret
do
#ignore bridge because bridge and the nic has the same mac address
if [[ $isSLES -eq 1 ]]; then
ret1=`grep -i "TYPE='Bridge'" $nwdir/ifcfg-$x 2>&1`;
else
ret1=`grep -i "TYPE=Bridge" $nwdir/ifcfg-$x 2>&1`;
fi
if [ $? -ne 0 ]; then
nic=$x
break
fi
done
if [ -z $nic ]; then
nic=`echo $ret |head -n1`
fi
else
logger -t xcat "configvlan: The mac address for the network for $NODE is not defined."
echo "configvlan: The mac address for the network for $NODE is not defined."
index=$((index+1))
continue
fi
fi
echo "nic=$nic"
eval VLANID=\$VLANID_$index
eval VLANIP=\$VLANIP_$index
eval VLANNETMASK=\$VLANNETMASK_$index
#write into the network configuration file
if [ -z "$VMNODE" ]; then
newnic="$nic.$VLANID"
else
newnic="$nic"
fi
logger -t xcat "configvlan: configuring vlan $VLANID on $newnic for $NODE..."
echo "configvlan: configuring vlan $VLANID on $newnic for $NODE..."
if [[ $isSLES -eq 1 ]]; then
cat >$nwdir/ifcfg-$newnic <<EOF
DEVICE='$newnic'
BOOTPROTO='none'
IPADDR='$VLANIP'
NETMASK='$VLANNETMASK'
ONBOOT='yes'
EOF
if [ -z "$VMNODE" ]; then
echo "VLAN='yes'" >> $nwdir/ifcfg-$newnic
fi
else
cat >$nwdir/ifcfg-$newnic <<EOF
DEVICE=$newnic
BOOTPROTO=none
IPADDR=$VLANIP
NETMASK=$VLANNETMASK
ONBOOT=yes
EOF
if [ -z "$VMNODE" ]; then
echo "VLAN=yes" >> $nwdir/ifcfg-$newnic
fi
fi
#restart the vlan network
logger -t xcat "configvlan: starting $newnic ..."
echo "configvlan: starting $newnic ..."
ret=`ifdown $newnic boot`
sleep 2
ret=`ifup $newnic boot`
if [ $? -ne 0 ]; then
logger -t xcat "configvlan: $ret"
echo "configvlan: $ret"
index=$((index+1))
continue;
else
logger -t xcat "configvlan: done."
echo "configvlan: done."
fi
#change the hostname only for primary vlan
if [[ $PMRY -eq 1 && $keephostname -eq 0 ]]; then
eval VLANHOSTNAME=\$VLANHOSTNAME_$index
hostname $VLANHOSTNAME
#change the hostname permanently
if [ -f /etc/SuSE-release ]
then
#SLES x
echo $VLANHOSTNAME > /etc/HOSTNAME
else
#RedHat and others
fn="/etc/sysconfig/network"
grep HOSTNAME $fn
if [ $? -eq 0 ]; then
sed -i "s/HOSTNAME.*/HOSTNAME=$VLANHOSTNAME/" $fn
else
echo "HOSTNAME=$VLANHOSTNAME" >> $fn
fi
fi
logger -t xcat "configvlan: Hostname changed to $VLANHOSTNAME for $NODE."
echo "configvlan: Hostname changed to $VLANHOSTNAME for $NODE."
fi
#next
index=$((index+1))
done
exit 0

View File

@ -0,0 +1,231 @@
#!/bin/sh
#-------------------------------------------------------------------------------------
#
# this script deconfigures the vlan on the node.
# deconfigvlan <vlan_id>
# if vlan_is is not specified, all the vlans defined
# for the given node will be deconfigured.
#
#-------------------------------------------------------------------------------------
if [[ -z $VLANMAXINDEX ]] || [[ $VLANMAXINDEX -eq 0 ]]; then
logger -t xcat "deconfigvlan: Nothing to do."
echo "deconfigvlan: Nothing to do."
exit 0
fi
if [[ $OSTYPE = linux* ]]; then
if [[ $OSVER = sles* ]] || [[ $OSVER = suse* ]] || [[ -f /etc/SuSE-release ]]; then
nwdir="/etc/sysconfig/network"
isSLES=1
else
nwdir="/etc/sysconfig/network-scripts"
fi
else
logger -t xcat "deconfigvlan: Does not support AIX yet."
echo "deconfigvlan: Does not support AIX yet."
exit 0
fi
if [[ -n "$1" ]]; then
IN_VLAN=$1 #The vlan id to be deconfigured, if not specified, all will be deconfigured on this note.
fi
index=1
while [ $index -le $VLANMAXINDEX ]; do
nic=""
eval VLANID=\$VLANID_$index
if [[ -n $IN_VLAN ]]; then
if [[ "$VLANID" != "$IN_VLAN" ]]; then
index=$((index+1))
continue
fi
fi
if [[ -z $VMNODE ]]; then #for bare-metal nodes
eval VLANNIC=\$VLANNIC_$index #VLANNIC could be ethx, primary, primary:ethx or empty
#determine if the current is primary network
PMRY=0
if [[ -z $VLANNIC ]] || [[ $VLANNIC = primary* ]]; then
PMRY=1
fi
if [[ $VLANNIC = primary* ]]; then
VLANNIC=${VLANNIC#primary}
fi
if [[ -n $VLANNIC ]]; then
nic=${VLANNIC#:}
fi
else #for KVM nodes
eval VLAN_VMNICPOS=\$VLAN_VMNICPOS_$index #VLAN_VMNICPOS identifies the position of the mac address in mac, the mac has the following format: 01:02:03:04:05:0E!node5|01:02:03:05:0F!node6-eth
PMRY=0
if [[ $index -eq 1 ]]; then
PMRY=1 ##the first one is always primary network
fi
if [[ -z $VLAN_VMNICPOS ]]; then
nic="eth1"
fi
fi
if [[ -z $nic ]]; then #get the nic
if [[ -n $MACADDRESS ]]; then
pos=0
#mac has the following format: 01:02:03:04:05:0E!node5|01:02:03:05:0F!node6-eth1
for x in `echo "$MACADDRESS" | tr "|" "\n"`
do
node=""
mac=""
pos=$((pos+1))
i=`expr index $x !`
if [[ $i -gt 0 ]]; then
node=`echo ${x##*!}`
mac_tmp=`echo ${x%%!*}`
else
mac_tmp=$x
fi
if [[ $pos -eq 1 ]]; then
mac1=$mac_tmp
fi
if [[ -n $VMNODE ]]; then
if [[ $pos -eq $VLAN_VMNICPOS ]]; then
mac=$mac_tmp
break
fi
else
if [[ "$PRIMARYNIC" = "$mac_tmp" ]]; then
mac=$mac_tmp
break
fi
if [[ -z "$PRIMARYNIC" ]] || [[ "$PRIMARYNIC" = "mac" ]]; then
if [[ -z "$node" ]] || [[ "$node" = "$NODE" ]]; then
mac=$mac_tmp
break
fi
fi
fi
done
if [[ -z $mac ]]; then
if [[ -n $VMNODE ]]; then
mac=$mac1
else
if [[ -z "$PRIMARYNIC" ]] || [[ "$PRIMARYNIC" = "mac" ]]; then
mac=$mac1 #if nothing mathes, take the first mac
else
nic=$PRIMARYNIC #or the primary nic itself is the nic
fi
fi
fi
else
logger -t xcat "deconfigvlan: no mac addresses are defined in the mac table for the node $NODE"
echo "deconfigvlan: no mac addresses are defined in the mac table for the node $NODE"
index=$((index+1))
continue
fi
echo "mac=$mac"
fi
if [[ -z $nic ]]; then
#go to each nic to match the mac address
ret=`ifconfig |grep -i $mac | cut -d' ' -f 1 2>&1`;
if [ $? -eq 0 ]; then
for x in $ret
do
#ignore bridge because bridge and the nic has the same mac address
if [[ $isSLES -eq 1 ]]; then
ret1=`grep -i "TYPE='Bridge'" $nwdir/ifcfg-$x 2>&1`;
else
ret1=`grep -i "TYPE=Bridge" $nwdir/ifcfg-$x 2>&1`;
fi
if [ $? -ne 0 ]; then
nic=$x
break
fi
done
if [ -z $nic ]; then
nic=`echo $ret |head -n1`
fi
else
logger -t xcat "deconfigvlan: The mac address for the network for $NODE is not defined."
echo "deconfigvlan: The mac address for the network for $NODE is not defined."
index=$((index+1))
continue
fi
fi
echo "nic=$nic"
eval VLANID=\$VLANID_$index
eval VLANIP=\$VLANIP_$index
eval VLANNETMASK=\$VLANNETMASK_$index
#write into the network configuration file
if [ -z "$VMNODE" ]; then
newnic="$nic.$VLANID"
else
newnic="$nic"
fi
#stop the vlan network
logger -t xcat "dconfigvlan: de-configuring vlan $newnic for $NODE..."
echo "dconfigvlan: de-configuring vlan $newnic for $NODE..."
if [[ -n $newnic ]]; then
ret=`ifdown $newnic 2>&1`
if [ $? -ne 0 ]; then
logger -t xcat "deconfigvlan: stopping $newnic: $ret"
echo "deconfigvlan: stopping $newnic: $ret"
fi
#remove the network conf file for the vlan
ret=`rm $nwdir/ifcfg-$newnic 2>&1`
else
logger -t xcat "deconfigvlan: cannot find the nic that has the vlan."
echo "deconfigvlan: cannot find the nic that has the vlan"
fi
#stop the bridge on the vm hosts,
if [ -f $nwdir/ifcfg-vl$VLANID ]; then
ret=`ifconfig vl$VLANID down 2>&1`
ret=`rm $nwdir/ifcfg-vl$VLANID 2>&1`
ret=`brctl delbr vl$VLANID 2>&1`
fi
if [[ $PMRY -eq 1 ]]; then
logger -t xcat "dconfigvlan: changing the hostname back to $NODE..."
echo "dconfigvlan: changing the hostname back to $NODE..."
#change the hostname
hostname $NODE
#change the hostname permanently
if [ -f /etc/SuSE-release ]
then
#SLES x
echo $NODE > /etc/HOSTNAME
else
#RedHat and others
fn="/etc/sysconfig/network"
grep HOSTNAME $fn
if [ $? -eq 0 ]; then
sed -i "s/HOSTNAME.*/HOSTNAME=$NODE/" $fn
else
echo "HOSTNAME=$NODE" >> $fn
fi
fi
fi
logger -t xcat "deconfigvlan: done."
echo "deconfigvlan: done."
#next
index=$((index+1))
done
exit 0

106
xCAT-vlan/pods/man1/chvlan.1.pod Executable file
View File

@ -0,0 +1,106 @@
=head1 NAME
B<chvlan> - It adds or removes nodes for the vlan.
=head1 SYNOPSIS
B<chvlan> I<vlanid> B<-n>|B<--nodes> I<noderange> [B<-i>|B<--interface> I<nic>]
B<chvlan> I<vlanid> B<-n>|B<--nodes> I<noderange> B<-d>|B<--delete>
B<chvlan> [B<-h>|B<--help>]
B<chvlan> [B<-v>|B<--version>]
=head1 DESCRIPTION
The B<chvlan> command adds nodes to the given vlan. If -d is specified, the nodes will be removed from the vlan.
For added security, the root guard and bpdu guard will be enabled for the ports added to this vlan. However, the guards will not be disabled if the ports are removed from the vlan using chvlan (-d) or rmvlan commands. To disable them, you need to use the switch command line interface. Please refer to the switch command line interface manual to see how to disable the root guard and bpdu guard for a port.
=head1 Parameters
I<vlanid> is a unique vlan number.
=head1 OPTIONS
=over 10
=item B<-n|--nodes> The nodes or groups to be added or removed. It can be stand alone nodes or KVM guests. It takes the noderange format. Please check the man page for noderange for details.
=item B<-i|--interface> (For adding only). The interface name where the vlan will be tagged on. If omitted, the xCAT management network will be assumed. For KVM, it is the interface name on the host.
=item B<-h|--help> Display usage message.
=item B<-v|--version> The Command Version.
=back
=head1 RETURN VALUE
0 The command completed successfully.
1 An error has occurred.
=head1 EXAMPLES
=over 3
=item 1.
To add node1, node2 and node3 to vlan 3.
chvlan 3 -n node1,node2,node3
=item 2.
To add node1, node2 and node3 to vlan 3 using eth1 interface.
chvlan 3 -n node1,node2,node3 -i eth1
=item 3.
TO remove node1, node2 and node3 from vlan 3.
chvlan -n node1,node2,node3 -d
=item 4.
To add KVM guests node1 and node2 to vlan 3
mkdef node1 arch=x86_64 groups=kvm,all installnic=mac primarynic=mac mgt=kvm netboot=pxe nfsserver=10.1.0.204 os=rhels6 profile=compute provmethod=install serialport=0 serialspeed=115200 vmcpus=1 vmhost=x3650n01 vmmemory=512 vmnics=br0 vmstorage=nfs://10.1.0.203/vms
mkdef node2 arch=x86_64 groups=kvm,all installnic=mac primarynic=mac mgt=kvm netboot=pxe nfsserver=10.1.0.204 os=rhels6 profile=compute provmethod=install serialport=0 serialspeed=115200 vmcpus=1 vmhost=x3650n01 vmmemory=512 vmnics=br0 vmstorage=nfs://10.1.0.203/vms
chvlan 3 -n node1,node2
mkvm node1,node2 -s 20G
rpower node1,node2 on
rinstall node1,node2
=item 5.
To remove KVM guests node1 and node2 from vlan 3
chvlan 3 -n node1,node2 -d
rpower node1,node2 off
rmvm node1,node2
=back
=head1 FILES
/opt/xcat/bin/chvlan
=head1 SEE ALSO
L<mkvlan(1)|mkvlan.1>, L<rmvlan(1)|rmvlan.1>, L<lsvlan(1)|lsvlan.1>

View File

@ -0,0 +1,72 @@
=head1 NAME
B<chvlanports> - It adds or removes nodes' switch interfaces for the vlan.
=head1 SYNOPSIS
B<chvlanports> I<vlanid> B<-n>|B<--nodes> I<noderange> B<-i>|B<--interface> I<nic>
B<chvlanports> I<vlanid> B<-n>|B<--nodes> I<noderange> B<-i>|B<--interface> I<nic> B<-d>|B<--delete>
B<chvlanports> [B<-h>|B<--help>]
B<chvlanports> [B<-v>|B<--version>]
=head1 DESCRIPTION
The B<chvlanports> command adds nodes switch interfaces to the given vlan. If -d is specified, the nodes switch interfaces will be removed from the vlan.
This command won't create/remove vlans on switches, it just add node's switch ports into exisitng vlan or remove them from existing vlan on switch. Before calling chvlanports, the nodes switch interfaces should be configured in table switch, and vlan must already existing in switches.
=head1 Parameters
I<vlanid> is a unique vlan number.
=head1 OPTIONS
=over 10
=item B<-n|--nodes> The nodes or groups to be added or removed. It takes the noderange format. Please check the man page for noderange for details.
=item B<-i|--interface> The interface name where the vlan will be tagged on.
=item B<-h|--help> Display usage message.
=item B<-v|--version> The Command Version.
=back
=head1 RETURN VALUE
0 The command completed successfully.
1 An error has occurred.
=head1 EXAMPLES
=over 3
=item 1.
To add node1, node2 and node3 to vlan 3 using eth1 interface.
chvlanports 3 -n node1,node2,node3 -i eth1
=item 2.
TO remove eth1 interface of node1, node2 and node3 from vlan 3.
chvlanports 3 -n node1,node2,node3 -i eth1 -d
=back
=head1 FILES
/opt/xcat/bin/chvlanports
=head1 SEE ALSO
L<mkvlan(1)|mkvlan.1>, L<rmvlan(1)|rmvlan.1>, L<lsvlan(1)|lsvlan.1>, L<chvlan(1)|chvlan.1>

View File

@ -0,0 +1,87 @@
=head1 NAME
B<lsvlan> - It lists the existing vlans for the cluster.
=head1 SYNOPSIS
B<lsvlan>
B<lsvlan> [I<vlanid>]
B<lsvlan> [B<-h>|B<--help>]
B<lsvlan> [B<-v>|B<--version>]
=head1 DESCRIPTION
The B<lsvlan> command lists all the vlans for the cluster. If I<vlanid> is specifined it will list more details about this vlan including the nodes in the vlan.
=head1 Parameters
I<vlanid> is a unique vlan number. If it is omitted, all vlans will be listed.
=head1 OPTIONS
=over 10
=item B<-h|--help> Display usage message.
=item B<-v|--version> Command Version.
=back
=head1 RETURN VALUE
0 The command completed successfully.
1 An error has occurred.
=head1 EXAMPLES
=over 3
=item 1.
To list all the vlans in the cluster
lsvlan
Output is similar to:
vlan 3:
subnet 10.3.0.0
netmask 255.255.0.0
vlan 4:
subnet 10.4.0.0
netmask 255.255.0.0
=item 2.
TO list the details for vlan3
lsvlan 3
Output is similar to:
vlan 3
subnet 10.3.0.0
netmask 255.255.0.0
hostname ip address node vm host
v3n1 10.3.0.1 c68m4hsp06
v3n2 10.3.0.2 x3455n01
v3n3 10.3.0.3 x3650n01
v3n4 10.3.0.4 x3650n01kvm1 x3650n01
v3n5 10.3.0.5 x3650n01kvm2 x3650n01
=back
=head1 FILES
/opt/xcat/bin/lsvlan
=head1 SEE ALSO
L<mkvlan(1)|mkvlan.1>, L<rmvlan(1)|rmvlan.1>, L<chvlan(1)|chvlan.1>

144
xCAT-vlan/pods/man1/mkvlan.1.pod Executable file
View File

@ -0,0 +1,144 @@
=head1 NAME
B<mkvlan> - It takes a list of nodes and create a private tagged vlan for them.
=head1 SYNOPSIS
B<mkvlan> [I<vlanid>] B<-n>|B<--nodes> I<noderange> [B<-t>|B<--net> I<subnet>] [B<-m>|B<--mask> I<netmask>] [B<-p>|B<--prefix> I<hostname_prefix>] [B<-i>|B<--interface> I<nic>]
B<mkvlan> [B<-h>|B<--help>]
B<mkvlan> [B<-v>|B<--version>]
=head1 DESCRIPTION
The B<mkvlan> command takes a list of nodes and move them to a private vlan.
This command will configure the switch to create a new tagged vlan on the given nic. The primary nic will be used if the nic is not specified. The new vlan ID is given by the command. However, if it is omitted, xCAT will automatically generate the new vlan ID by querying all the switches involved and finding out the smallest common number that is not used by any existing vlans. The subnet and the netmask for the vlan will be derived from the value of "vlannets" and "vlanmasks" from the I<site> table if -t and -m are not specified. The following are the default site table entires:
vlannets="|(\d+)|10.($1+0).0.0|";
vlanmask="255.255.0.0";
The vlan network will be entered in the I<networks> table. The nodes will be added to the vlan using the vlan tagging technique. And the new IP addresses and new hostnames will be assigned to the nodes. The -p flag specifies the node hostname prefix for the nodes. If it is not specified, by default, the hostnames for the nodes are having the following format:
v<vlanid>nY where Y is the node number. For example, the hostname for node 5 on vlan 10 is v10n5.
The I<switch.vlan> will be updated with the new vlan id for the node for standaline nodes. For KVM guests, the I<vm.nics> identifies which vlan this node belongs to. For example: vl3 means this node is in vlan 3.
If there are more than one switches involved in the vlan, the ports that connect to the switches need to entered in I<switches.linkports> with the following format:
<port numner>:switch,<port number>:switch....
For example:
"42:switch1,43:switch2"
This command will automatically configure the cross-over ports if the given nodes are on different switches.
For added security, the root guard and bpdu guard will be enabled for the ports in this vlan. However, the guards will not be disabled if the ports are removed from the vlan using chvlan or rmvlan commands. To disable them, you need to use the switch command line interface. Please refer to the switch command line interface manual to see how to disable the root guard and bpdu guard for a port.
=head1 Parameters
I<vlanid> is a unique vlan number. If it is omitted, xCAT will automatically generate the new vlan ID by querying all the switches involved and finding out the smallest common number that is not used by any existing vlans. Use B<lsvlan> to find out the existing vlan ids used by xCAT.
=head1 OPTIONS
=over 10
=item B<-n|--nodes> The nodes or groups to be included in the vlan. It can be stand alone nodes or KVM guests. It takes the noderange format. Please check the man page for noderange for details.
=item B<-t|--net> The subnet for the vlan.
=item B<-m|--mask> The netmask for the vlan
=item B<-p|--prefix> The prefix the the new hostnames for the nodes in the vlan.
=item B<-i|--interface> The interface name where the vlan will be tagged on. If omitted, the xCAT management network will be assumed. For FVM, this is the interface name on the host.
=item B<-h|--help> Display usage message.
=item B<-v|--version> The Command Version.
=back
=head1 RETURN VALUE
0 The command completed successfully.
1 An error has occurred.
=head1 EXAMPLES
To start, the xCAT switches and switches table needs to be filled with switch and port info for the nodes. For example, the swith table will look like this:
#node,switch,port,vlan,interface,comments,disable
"node1","switch1","10",,,,
"node1","switch2","1",,"eth1",,
"node2","switch1","11",,"primary",,
"node2","switch2","2",,"eth1",,
"node3","switch1","12",,"primary:eth0",,
"node3","switch2","3",,"eth1",,
Please note that the interface value for the management (primary) network can be empty, the word "primary" or "primary:ethx". For other networks, the interface attribute must be specified.
The following is an example of the switches table
#switch,snmpversion,username,password,privacy,auth,linkports,sshusername,sshpassword,switchtype,comments,disable
"switch1","3","username","passw0rd",,"sha","48:switch2",,,,,
"switch2","2",,,,,"43:switch1",,,,,
=over 3
=item 1.
To make a private vlan for node1, node2 and node3
mkvlan -n node1,node2,node3
The vlan will be created on eth0 for the nodes.
=item 2.
To make a private vlan for node1, node2 and node3 on eth1,
mkvlan -n node1,node2,node3 -i eth1
=item 3.
TO make a private vlan for node1, node2 with given subnet and netmask.
mkvlan -n node1,node2,node3 -t 10.3.2.0 -m 255.255.255.0
=item 4.
To make a private vlan for KVM guests node1 and node2
chtab key=usexhrm site.vlaue=1
mkdef node1 arch=x86_64 groups=kvm,all installnic=mac primarynic=mac mgt=kvm netboot=pxe nfsserver=10.1.0.204 os=rhels6 profile=compute provmethod=install serialport=0 serialspeed=115200 vmcpus=1 vmhost=x3650n01 vmmemory=512 vmnics=br0 vmstorage=nfs://10.1.0.203/vms
mkdef node2 arch=x86_64 groups=kvm,all installnic=mac primarynic=mac mgt=kvm netboot=pxe nfsserver=10.1.0.204 os=rhels6 profile=compute provmethod=install serialport=0 serialspeed=115200 vmcpus=1 vmhost=x3650n01 vmmemory=512 vmnics=br0 vmstorage=nfs://10.1.0.203/vms
mkvlan -n node1,node2
mkvm node1,node2 -s 20G
rpower node1,node2 on
rinstall node1,node2
=back
=head1 FILES
/opt/xcat/bin/mkvlan
=head1 SEE ALSO
L<chvlan(1)|chvlan.1>, L<rmvlan(1)|rmvlan.1>, L<lsvlan(1)|lsvlan.1>

View File

@ -0,0 +1,62 @@
=head1 NAME
B<rmvlan> - It remves the vlan from the cluster.
=head1 SYNOPSIS
B<rmvlan> I<vlanid>
B<rmvlan> [B<-h>|B<--help>]
B<rmvlan> [B<-v>|B<--version>]
=head1 DESCRIPTION
The B<rmvlan> command removes the given vlan ID from the cluster. It removes the vlan id from all the swithces involved, deconfigures the nodes so that vlan adaptor (tag) will be remved, cleans up /etc/hosts, DNS and database tables for the given vlan.
For added security, the root guard and bpdu guard were enabled for the ports in this vlan by mkvlan and chvlan commands. However, the guards will not be disabled by this command. To disable them, you need to use the switch command line interface. Please refer to the switch command line interface manual to see how to disable the root guard and bpdu guard for a port.
=head1 Parameters
I<vlanid> is a unique vlan number.
=head1 OPTIONS
=over 10
=item B<-h|--help> Display usage message.
=item B<-v|--version> The Command Version.
=back
=head1 RETURN VALUE
0 The command completed successfully.
1 An error has occurred.
=head1 EXAMPLES
=over 3
=item 1.
To remove vlan 3
rmvlan 3
If the nodes are KVM guest then the do the following after the vlan is removed:
rpower node1,node2 off
rmvm node1,node2
=back
=head1 FILES
/opt/xcat/bin/rmvlan
=head1 SEE ALSO
L<mkvlan(1)|mkvlan.1>, L<chvlan(1)|chvlan.1>, L<lsvlan(1)|lsvlan.1>

110
xCAT-vlan/xCAT-vlan.spec Executable file
View File

@ -0,0 +1,110 @@
Summary: Executables and data of the xCAT vlan management project
Name: xCAT-vlan
Version: %(cat Version)
Release: snap%(date +"%Y%m%d%H%M")
Epoch: 4
License: IBM
Group: Applications/System
Source: xCAT-vlan-%{version}.tar.gz
Packager: IBM Corp.
Vendor: IBM Corp.
Distribution: %{?_distribution:%{_distribution}}%{!?_distribution:%{_vendor}}
Prefix: /opt/xcat
BuildRoot: /var/tmp/%{name}-%{version}-%{release}-root
%ifos linux
BuildArch: noarch
%endif
Provides: xCAT-vlan = %{epoch}:%{version}
Requires: xCAT-client
%description
xCAT-vlan provides the xCAT vlan confiuration.
%prep
%setup -q -n xCAT-vlan
%build
# Convert pods to man pages and html pages
./xpod2man
%install
# The install phase puts all of the files in the paths they should be in when the rpm is
# installed on a system. The RPM_BUILD_ROOT is a simulated root file system and usually
# has a value like: /var/tmp/xCAT-vlan-2.0-snap200802270932-root
rm -rf $RPM_BUILD_ROOT
mkdir -p $RPM_BUILD_ROOT/%{prefix}/bin
mkdir -p $RPM_BUILD_ROOT/%{prefix}/lib/perl/xCAT
mkdir -p $RPM_BUILD_ROOT/%{prefix}/lib/perl/xCAT_plugin
mkdir -p $RPM_BUILD_ROOT/install/postscripts
mkdir -p $RPM_BUILD_ROOT/%{prefix}/share/man/man1
mkdir -p $RPM_BUILD_ROOT/%{prefix}/share/doc/man1
set +x
cp xCAT/* $RPM_BUILD_ROOT/%{prefix}/lib/perl/xCAT
cp -R xCAT_plugin/* $RPM_BUILD_ROOT/%{prefix}/lib/perl/xCAT_plugin
cp install/postscripts/* $RPM_BUILD_ROOT/install/postscripts
# These were built dynamically in the build phase
cp share/man/man1/* $RPM_BUILD_ROOT/%{prefix}/share/man/man1
chmod 444 $RPM_BUILD_ROOT/%{prefix}/share/man/man1/*
# These were built dynamically during the build phase
cp share/doc/man1/* $RPM_BUILD_ROOT/%{prefix}/share/doc/man1
chmod 644 $RPM_BUILD_ROOT/%{prefix}/share/doc/man1/*
# These links get made in the RPM_BUILD_ROOT/prefix area
ln -sf ../bin/xcatclientnnr $RPM_BUILD_ROOT/%{prefix}/bin/mkvlan
ln -sf ../bin/xcatclientnnr $RPM_BUILD_ROOT/%{prefix}/bin/chvlan
ln -sf ../bin/xcatclientnnr $RPM_BUILD_ROOT/%{prefix}/bin/rmvlan
ln -sf ../bin/xcatclientnnr $RPM_BUILD_ROOT/%{prefix}/bin/lsvlan
ln -sf ../bin/xcatclientnnr $RPM_BUILD_ROOT/%{prefix}/bin/chvlanports
set -x
%clean
# This step does not happen until *after* the %files packaging below
rm -rf $RPM_BUILD_ROOT
%files
%defattr(-,root,root)
#%doc LICENSE.html
# Just package everything that has been copied into RPM_BUILD_ROOT
%{prefix}
/install/postscripts
%changelog
%post
%ifos linux
if [ -f "/proc/cmdline" ]; then # prevent running it during install into chroot image
if [ -f $RPM_INSTALL_PREFIX0/sbin/xcatd ]; then
/etc/init.d/xcatd reload
fi
fi
%else
#restart the xcatd on if xCAT or xCATsn is installed already
if [ -f $RPM_INSTALL_PREFIX0/sbin/xcatd ]; then
if [ -n "$INUCLIENTS" ] && [ $INUCLIENTS -eq 1 ]; then
#Do nothing in not running system
echo "Do not restartxcatd in not running system"
else
XCATROOT=$RPM_INSTALL_PREFIX0 $RPM_INSTALL_PREFIX0/sbin/restartxcatd -r
fi
fi
%endif
exit 0
%preun

336
xCAT-vlan/xCAT/SwitchHandler.pm Executable file
View File

@ -0,0 +1,336 @@
#!/usr/bin/perl
package xCAT::SwitchHandler;
BEGIN
{
$::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat';
}
use lib "$::XCATROOT/lib/perl";
use strict;
use xCAT::Table;
use xCAT::Utils;
use xCAT::MsgUtils;
use xCAT::MacMap;
use IO::Select;
use IO::Handle;
use Sys::Syslog;
use Data::Dumper;
use POSIX qw/WNOHANG/;
use SNMP;
my $sysDescr='.1.3.6.1.2.1.1.1';
sub new {
my $self = {};
my $proto = shift;
my $class = ref($proto) || $proto;
$self->{switch} = shift;
bless ($self, $class);
return $self;
}
sub fill_sessionparms {
my $self = shift;
my %args = @_;
my $community=$args{community};
$self->{sessionparms}=$args{sessionents};
if ($self->{sessionparms}->{snmpversion}) {
if ($self->{sessionparms}->{snmpversion} =~ /3/) { #clean up to accept things like v3 or ver3 or 3, whatever.
$self->{sessionparms}->{snmpversion}=3;
unless ($self->{sessionparms}->{auth}) {
$self->{sessionparms}->{auth}='md5'; #Default to md5 auth if not specified but using v3
}
} elsif ($self->{sessionparms}->{snmpversion} =~ /2/) {
$self->{sessionparms}->{snmpversion}=2;
} else {
$self->{sessionparms}->{snmpversion}=1; #Default to lowest common denominator, snmpv1
}
}
unless (defined $self->{sessionparms}->{password}) { #if no password set, inherit the community
$self->{sessionparms}->{password}=$community;
}
}
sub setoid {
my $session = shift;
my $oid = shift;
my $offset = shift;
my $value = shift;
my $type = shift;
unless ($type) { $type = 'INTEGER'; }
my $varbind = new SNMP::Varbind([$oid,$offset,$value,$type]);
my $data = $session->set($varbind);
if ($session->{ErrorStr}) { return (1,$session->{ErrorStr}); }
return 0,$varbind;
}
#---------------------------------------------------------
=head3 getsnmpsession
It gets an snmp session appropriate for a switch using the switches table
for guidance on the hows.
Arguments: vlan=> $vid if needed for community string indexing (optional)
=cut
#------------------------------------------------------------
sub getsnmpsession {
my $self = shift;
my $community=shift;
my $vlanid = shift;
my $switch = $self->{switch};
my $session;
my $sessionparams;
if (!$community) { $community="private"; }
$self->{sitetab} = xCAT::Table->new('site');
my $tmp = $self->{sitetab}->getAttribs({key=>'snmpc'},'value');
if ($tmp and $tmp->{value}) { $community = $tmp->{value} }
my $switchestab=xCAT::Table->new('switches',-create=>0);
my $ent = $switchestab->getNodeAttribs($switch, [qw(switch snmpversion username password privacy auth)]);
if ($ent) {
$self->fill_sessionparms(community=>$community, sessionents=>$ent);
}
$sessionparams=$self->{sessionparms};
my $snmpver='1';
if ($sessionparams) {
$snmpver=$sessionparams->{snmpversion};
$community=$sessionparams->{password};
}
if ($snmpver ne '3') {
if ($vlanid) { $community .= '@'.$vlanid; }
$session = new SNMP::Session(
DestHost => $switch,
Version => $snmpver,
Community => $community,
UseNumeric => 1
);
} else { #we have snmp3
my %args= (
DestHost => $switch,
SecName => $sessionparams->{username},
AuthProto => uc($sessionparams->{auth}),
AuthPass => $community,
Version => $snmpver,
SecLevel => 'authNoPriv',
UseNumeric => 1
);
if ($vlanid) { $args{Context}="vlan-".$vlanid; }
if ($sessionparams->{privacy}) {
$args{SecLevel}='authPriv';
$args{PrivProto} = uc($sessionparams->{privacy});
$args{PrivPass} = $community;
$args{Retries} = 4;
$args{Timeout}=1500000;
}
#print "args=" . Dumper(%args) . "\n";
$session = new SNMP::Session(%args);
}
#print "switch=$switch\n";
if (!$session) { return $session;}
#get the the switch brand name
my $tmp = xCAT::MacMap::walkoid($session, "$sysDescr", silentfail=>1);
my $swbrand;
if ($tmp->{0}) {
#print "Desc=" . $tmp->{0} . "\n";
my @switch_plugins=glob("$::XCATROOT/lib/perl/xCAT_plugin/vlan/*.pm");
foreach my $fn (@switch_plugins) {
$fn =~ /.*\/([^\/]*).pm$/;
my $module = $1;
#print "fn=$fn,modele=$module\n";
if ( ! eval { require "$fn" }) {
xCAT::MsgUtils->message("S", "Cannot load module $fn");
next;
} else {
no strict 'refs';
my $filter=${"xCAT_plugin::vlan::".$module."::"}{filter_string}->();
my $descr=$tmp->{0};
if ($descr =~ /$filter/) {
$self->{module}=$module;
#print "found it:$module\n";
last;
}
}
}
}
if (!exists($self->{module})) {
$self->{session}=0;
return 0;
} else {
$self->{session}=$session;
return $session;
}
}
#--------------------------------------------------------------
=head3 get_vlan_ids
It gets the existing vlan IDs for the switch.
Returns: an array containing all the vlan ids for the switch
=cut
#-------------------------------------------------------------
sub get_vlan_ids {
my $self = shift;
my $session=$self->{session};
if (! $self->{session}) {
$session = $self->getsnmpsession();
}
unless ($session) { xCAT::MsgUtils->message("S","Failed to communicate with " . $self->{switch} . " or find a plugin module for the switch."); return; }
no strict 'refs';
return ${"xCAT_plugin::vlan::".$self->{module}."::"}{get_vlan_ids}->($session);
}
#--------------------------------------------------------------
=head3 get_vlanids_for_ports
It returns a hash pointer that contains the vlan id for each given port.
=cut
#-------------------------------------------------------------
sub get_vlanids_for_ports {
my $self = shift;
my @ports=@_;
my $session=$self->{session};
if (! $self->{session}) {
$session = $self->getsnmpsession();
}
unless ($session) { xCAT::MsgUtils->message("S","Failed to communicate with " . $self->{switch} . " or find a plugin module for the switch."); return; }
no strict 'refs';
return ${"xCAT_plugin::vlan::".$self->{module}."::"}{get_vlanids_for_ports}->($session, @ports);
}
#--------------------------------------------------------------
=head3 create_vlan
Creates a new vlan on the switch
Returns an array. (erorcode, errormsg). When errorcode=0, means no error.
=cut
#-------------------------------------------------------------
sub create_vlan {
my $self = shift;
my $vlan_id=shift;
my $vlan_name="xcat_vlan_" . $vlan_id;
#print "create vlan get called.\n";
my $session=$self->{session};
if (! $self->{session}) {
$session = $self->getsnmpsession();
}
#my $session = $self->getsnmpsession();
unless ($session) { xCAT::MsgUtils->message("S","Failed to communicate with " . $self->{switch}. " or find a plugin module for the switch."); return; }
#print Dumper($self->{sessionparms});
no strict 'refs';
return ${"xCAT_plugin::vlan::".$self->{module}."::"}{create_vlan}->($session, $vlan_id);
}
#--------------------------------------------------------------
=head3 add_ports_to_vlan
Adds the given ports to the existing vlan
Returns an array. (erorcode, errormsg). When errorcode=0, means no error.
=cut
#-------------------------------------------------------------
sub add_ports_to_vlan {
my $self = shift;
my $vlan_id=shift;
my $portmode=shift;
my @ports=@_;
#print "vlan=$vlan_id, ports=@ports\n";
my $session=$self->{session};
if (! $self->{session}) {
$session = $self->getsnmpsession();
}
#my $session = $self->getsnmpsession();
unless ($session) { xCAT::MsgUtils->message("S","Failed to communicate with " . $self->{switch}. " or find a plugin module for the switch."); return; }
no strict 'refs';
return ${"xCAT_plugin::vlan::".$self->{module}."::"}{add_ports_to_vlan}->($session, $vlan_id, $portmode, @ports);
}
#-------------------------------------------------------
=head3 add_crossover_ports_to_vlan
It enables the vlan on the cross-over links.
Returns an array. (erorcode, errormsg). When errorcode=0, means no error.
=cut
#-------------------------------------------------------
sub add_crossover_ports_to_vlan {
my $self = shift;
my $vlan_id=shift;
my @switches=@_;
if (@switches == 0) { return (0, ""); }
my $session=$self->{session};
if (! $self->{session}) {
$session = $self->getsnmpsession();
}
#my $session = $self->getsnmpsession();
unless ($session) { xCAT::MsgUtils->message("S","Failed to communicate with " . $self->{switch}. " or find a plugin module for the switch."); return; }
no strict 'refs';
return ${"xCAT_plugin::vlan::".$self->{module}."::"}{add_crossover_ports_to_vlan}->($session, $vlan_id, $self->{switch}, @switches);
}
#--------------------------------------------------------------
=head3 remove_vlan
Remove a vlan from the switch
Returns an array. (erorcode, errormsg). When errorcode=0, means no error.
=cut
#-------------------------------------------------------------
sub remove_vlan {
my $self = shift;
my $vlan_id=shift;
my $session=$self->{session};
if (! $self->{session}) {
$session = $self->getsnmpsession();
}
#my $session = $self->getsnmpsession();
unless ($session) { xCAT::MsgUtils->message("S","Failed to communicate with " . $self->{switch}. " or find a plugin module for the switch."); return; }
no strict 'refs';
return ${"xCAT_plugin::vlan::".$self->{module}."::"}{remove_vlan}->($session, $vlan_id);
}
#--------------------------------------------------------------
=head3 remove_ports_from_vlan
Remove ports from a vlan
Returns an array. (erorcode, errormsg). When errorcode=0, means no error.
=cut
#-------------------------------------------------------------
sub remove_ports_from_vlan {
my $self = shift;
my $vlan_id=shift;
my @ports = @_;
my $session=$self->{session};
if (! $self->{session}) {
$session = $self->getsnmpsession();
}
#my $session = $self->getsnmpsession();
unless ($session) { xCAT::MsgUtils->message("S","Failed to communicate with " . $self->{switch}. " or find a plugin module for the switch."); return; }
no strict 'refs';
return ${"xCAT_plugin::vlan::".$self->{module}."::"}{remove_ports_from_vlan}->($session, $vlan_id, @ports);
}
1;

2754
xCAT-vlan/xCAT_plugin/vlan.pm Executable file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,620 @@
#!/usr/bin/perl
package xCAT_plugin::vlan::BNTSwitch;
BEGIN
{
$::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat';
}
use lib "$::XCATROOT/lib/perl";
use strict;
use xCAT::MacMap;
use xCAT::Table;
use Data::Dumper;
use xCAT::SwitchHandler;
use SNMP;
my $sysDescr='.1.3.6.1.2.1.1.1';
#BNT uses different OIDs for different switch module and versions. The following
#assumes that the FW versions are v6.x.
#G8100 is not supported yet because it uses different method. No hw to test.
my $BNTOID={
'EN4093'=>{
'vlanInfoId'=>'.1.3.6.1.4.1.20301.2.5.2.3.5.1.1.1',
'vlanInfoPorts'=>'.1.3.6.1.4.1.20301.2.5.2.3.5.1.1.7',
'portInfoPhyIfDescr'=>'.1.3.6.1.4.1.20301.2.5.1.3.2.1.1.6',
'vlanNewCfgVlanName'=>'.1.3.6.1.4.1.20301.2.5.2.1.1.3.1.2',
'vlanNewCfgState'=>'.1.3.6.1.4.1.20301.2.5.2.1.1.3.1.4', #2:enable 3:disable
'vlanNewCfgAddPort'=>'.1.3.6.1.4.1.20301.2.5.2.1.1.3.1.5',
'vlanNewCfgRemovePort'=>'.1.3.6.1.4.1.20301.2.5.2.1.1.3.1.6',
'vlanNewCfgDelete'=>'.1.3.6.1.4.1.20301.2.5.2.1.1.3.1.7', #1:other 2:delete
'agPortNewCfgVlanTag'=>'.1.3.6.1.4.1.20301.2.5.1.1.2.3.1.3', #2:tagged 3:untagged
'agPortNewCfgBpduGuard'=>'.1.3.6.1.4.1.20301.2.5.1.1.2.3.1.41', #1:enable 2:disable
'agPortNewCfgStpExtGuard'=>'.1.3.6.1.4.1.20301.2.5.1.1.2.3.1.52',#1:loop, 2:root, 3:none, 0:default
'agApplyConfig'=>'.1.3.6.1.4.1.20301.2.5.1.1.8.2',
'agSaveConfiguration'=> '.1.3.6.1.4.1.20301.2.5.1.1.1.4', #saveActive(2), notSaveActive(3)
'arpInfoDestIp'=>'.1.3.6.1.4.1.20301.2.5.3.3.2.1.1.1',
'arpInfoSrcPort'=>'.1.3.6.1.4.1.20301.2.5.3.3.2.1.1.4',
},
'G8000'=>{
'vlanInfoId'=>'.1.3.6.1.4.1.26543.2.7.1.2.3.5.1.1.1',
'vlanInfoPorts'=>'.1.3.6.1.4.1.26543.2.7.1.2.3.5.1.1.7',
'portInfoPhyIfDescr'=>'.1.3.6.1.4.1.26543.2.7.1.1.3.2.1.1.6',
'vlanNewCfgVlanName'=>'.1.3.6.1.4.1.26543.2.7.1.2.1.1.3.1.2',
'vlanNewCfgState'=>'.1.3.6.1.4.1.26543.2.7.1.2.1.1.3.1.4', #2:enable 3:disable
'vlanNewCfgAddPort'=>'.1.3.6.1.4.1.26543.2.7.1.2.1.1.3.1.5',
'vlanNewCfgRemovePort'=>'.1.3.6.1.4.1.26543.2.7.1.2.1.1.3.1.6',
'vlanNewCfgDelete'=>'.1.3.6.1.4.1.26543.2.7.1.2.1.1.3.1.7', #1:other 2:delete
'agPortNewCfgVlanTag'=>'.1.3.6.1.4.1.26543.2.7.1.1.1.2.3.1.3', #2:tagged 3:untagged
'agPortNewCfgBpduGuard'=>'.1.3.6.1.4.1.26543.2.7.1.1.1.2.3.1.41', #1:enable 2:disable
'agPortNewCfgStpExtGuard'=>'.1.3.6.1.4.1.26543.2.7.1.1.1.2.3.1.52',#1:loop, 2:root, 3:none, 0:default
'agApplyConfig'=>'.1.3.6.1.4.1.26543.2.7.1.1.1.8.2',
'agSaveConfiguration'=> '.1.3.6.1.4.1.26543.2.7.1.1.1.1.4', #saveActive(2), notSaveActive(3)
'arpInfoDestIp'=>'.1.3.6.1.4.1.26543.2.7.1.3.3.2.1.1.1',
'arpInfoSrcPort'=>'.1.3.6.1.4.1.26543.2.7.1.3.3.2.1.1.4',
},
'G8052'=>{
'vlanInfoId'=>'.1.3.6.1.4.1.26543.2.7.7.2.3.5.1.1.1',
'vlanInfoPorts'=>'.1.3.6.1.4.1.26543.2.7.7.2.3.5.1.1.7',
'portInfoPhyIfDescr'=>'.1.3.6.1.4.1.26543.2.7.7.1.3.2.1.1.6',
'vlanNewCfgVlanName'=>'.1.3.6.1.4.1.26543.2.7.7.2.1.1.3.1.2',
'vlanNewCfgState'=>'.1.3.6.1.4.1.26543.2.7.7.2.1.1.3.1.4',
'vlanNewCfgAddPort'=>'.1.3.6.1.4.1.26543.2.7.7.2.1.1.3.1.5',
'vlanNewCfgRemovePort'=>'.1.3.6.1.4.1.26543.2.7.7.2.1.1.3.1.6',
'vlanNewCfgDelete'=>'.1.3.6.1.4.1.26543.2.7.7.2.1.1.3.1.7',
'agPortNewCfgVlanTag'=>'.1.3.6.1.4.1.26543.2.7.7.1.1.2.3.1.3',
'agPortNewCfgBpduGuard'=>'.1.3.6.1.4.1.26543.2.7.7.1.1.2.3.1.41',
'agPortNewCfgStpExtGuard'=>'.1.3.6.1.4.1.26543.2.7.7.1.1.2.3.1.52',
'agApplyConfig'=>'.1.3.6.1.4.1.26543.2.7.7.1.1.8.2',
'agSaveConfiguration'=> '.1.3.6.1.4.1.26543.2.7.7.1.1.1.4', #saveActive(2), notSaveActive(3)
'arpInfoDestIp'=>'.1.3.6.1.4.1.26543.2.7.7.3.3.2.1.1.1',
'arpInfoSrcPort'=>'.1.3.6.1.4.1.26543.2.7.7.3.3.2.1.1.4',
},
'G8124'=>{
'vlanInfoId'=>'.1.3.6.1.4.1.26543.2.7.4.2.3.5.1.1.1',
'vlanInfoPorts'=>'.1.3.6.1.4.1.26543.2.7.4.2.3.5.1.1.7',
'portInfoPhyIfDescr'=>'.1.3.6.1.4.1.26543.2.7.4.1.3.2.1.1.6',
'vlanNewCfgVlanName'=>'.1.3.6.1.4.1.26543.2.7.4.2.1.1.3.1.2',
'vlanNewCfgState'=>'.1.3.6.1.4.1.26543.2.7.4.2.1.1.3.1.4',
'vlanNewCfgAddPort'=>'.1.3.6.1.4.1.26543.2.7.4.2.1.1.3.1.5',
'vlanNewCfgRemovePort'=>'.1.3.6.1.4.1.26543.2.7.4.2.1.1.3.1.6',
'vlanNewCfgDelete'=>'.1.3.6.1.4.1.26543.2.7.4.2.1.1.3.1.7',
'agPortNewCfgVlanTag'=>'.1.3.6.1.4.1.26543.2.7.4.1.1.2.3.1.3',
'agPortNewCfgBpduGuard'=>'.1.3.6.1.4.1.26543.2.7.4.1.1.2.3.1.41',
'agPortNewCfgStpExtGuard'=>'.1.3.6.1.4.1.26543.2.7.4.1.1.2.3.1.52',
'agApplyConfig'=>'.1.3.6.1.4.1.26543.2.7.4.1.1.8.2',
'agSaveConfiguration'=> '.1.3.6.1.4.1.26543.2.7.4.1.1.1.4', #saveActive(2), notSaveActive(3)
'arpInfoDestIp'=>'.1.3.6.1.4.1.26543.2.7.4.3.3.2.1.1.1',
'arpInfoSrcPort'=>'.1.3.6.1.4.1.26543.2.7.4.3.3.2.1.1.4',
},
#this is for G8264 and 8264E
'G8264'=>{
'vlanInfoId'=>'.1.3.6.1.4.1.26543.2.7.6.2.3.5.1.1.1',
'vlanInfoPorts'=>'.1.3.6.1.4.1.26543.2.7.6.2.3.5.1.1.7',
'portInfoPhyIfDescr'=>'.1.3.6.1.4.1.26543.2.7.6.1.3.2.1.1.6',
'vlanNewCfgVlanName'=>'.1.3.6.1.4.1.26543.2.7.6.2.1.1.3.1.2',
'vlanNewCfgState'=>'.1.3.6.1.4.1.26543.2.7.6.2.1.1.3.1.4',
'vlanNewCfgAddPort'=>'.1.3.6.1.4.1.26543.2.7.6.2.1.1.3.1.5',
'vlanNewCfgRemovePort'=>'.1.3.6.1.4.1.26543.2.7.6.2.1.1.3.1.6',
'vlanNewCfgDelete'=>'.1.3.6.1.4.1.26543.2.7.6.2.1.1.3.1.7',
'agPortNewCfgVlanTag'=>'.1.3.6.1.4.1.26543.2.7.6.1.1.2.3.1.3',
'agPortNewCfgBpduGuard'=>'.1.3.6.1.4.1.26543.2.7.6.1.1.2.3.1.41',
'agPortNewCfgStpExtGuard'=>'.1.3.6.1.4.1.26543.2.7.6.1.1.2.3.1.52',
'agApplyConfig'=>'.1.3.6.1.4.1.26543.2.7.6.1.1.8.2',
'agSaveConfiguration'=> '.1.3.6.1.4.1.26543.2.7.6.1.1.1.4', #saveActive(2), notSaveActive(3)
'arpInfoDestIp'=>'.1.3.6.1.4.1.26543.2.7.6.3.3.2.1.1.1',
'arpInfoSrcPort'=>'.1.3.6.1.4.1.26543.2.7.6.3.3.2.1.1.4',
},
};
my %HexConv=( 0=>0x80, 1=>0x40, 2=>0x20, 3=>0x10,
4=>0x08, 5=>0x04, 6=>0x02, 7=>0x01);
#--------------------------------------------------------------
=head3 filter_string
Every switch plugin must implement this subroutine.
The return value will be used comare against the string
from sysDescr value from snmpget. If the latter contains
this string, then this mudule will be used to handle the
requests for vlan configuration.
=cut
#-------------------------------------------------------------
sub filter_string {
return "BNT |Blade Network Technologies|IBM Networking Operating System|EN4093";
}
#--------------------------------------------------------------
=head3 get_vlan_ids
Every switch plugin must implement this subroutine.
It gets the existing vlan IDs for the switch.
Returns: an array containing all the vlan ids for the switch
=cut
#-------------------------------------------------------------
sub get_vlan_ids {
my $session=shift;
my $swmod=getSwitchModule($session);
if (!$swmod) { return ();}
my $vlanmap = xCAT::MacMap::walkoid($session, $BNTOID->{$swmod}->{vlanInfoId}, silentfail=>1);
my %vlanids=();
foreach(keys(%$vlanmap)) {
$vlanids{$_}=1;
}
my @ret=(sort keys(%vlanids));
print "ids=@ret\n";
return @ret;
}
#--------------------------------------------------------------
=head3 get_vlanids_for_ports
Every switch plugin must implement this subroutine.
It returns a hash pointer that contains the vlan id for each given port.
The kay is the port, the vlaue is a pointer to an array.
=cut
#-------------------------------------------------------------
sub get_vlanids_for_ports {
my $session=shift;
my @ports=@_;
my $swmod=getSwitchModule($session);
if (!$swmod) { return;}
my $namemap = xCAT::MacMap::walkoid($session, $BNTOID->{$swmod}->{portInfoPhyIfDescr});
if ($namemap) {
my $ifnamesupport=0;
foreach (keys %{$namemap}) {
if ($namemap->{$_}) {
$ifnamesupport=1;
last;
}
}
unless ($ifnamesupport) {
$namemap=0;
}
}
unless ($namemap) {
return;
}
#print "namemap=" . Dumper($namemap) . "\n";
my $portsvlanmap = xCAT::MacMap::walkoid($session, $BNTOID->{$swmod}->{vlanInfoPorts}, silentfail=>1);
#print "portsvlanmap=" . Dumper($portsvlanmap) . "\n";
foreach my $vid (keys (%$portsvlanmap)) {
my $data=$portsvlanmap->{$vid};
my @a = split(//, $data);
foreach (@a) {
my $num=unpack("C*", $_);
$_= sprintf ("%02x",$num);
}
$portsvlanmap->{$vid}=\@a;
}
my %ret=();
if (defined($portsvlanmap)) {
foreach my $portid (keys %{$namemap}) {
my $switchport = $namemap->{$portid};
foreach my $portname (@ports) {
unless (xCAT::MacMap::namesmatch($portname,$switchport)) {
next;
}
foreach my $vid (keys (%$portsvlanmap)) {
my $data=$portsvlanmap->{$vid};
my $index = int($portid / 8);
my $offset = $portid % 8;
my $num = hex($data->[$index]) & ($HexConv{$offset});
if ($num != 0) {
if (exists($ret{$portname})) {
my $pa=$ret{$portname};
push (@$pa, $vid);
} else {
$ret{$portname}=[$vid];
}
}
}
}
}
}
return \%ret;
}
#--------------------------------------------------------------
=head3 create_vlan
Every switch plugin must implement this subroutine.
Creates a new vlan on the switch
Returns an array. (erorcode, errormsg). When errorcode=0, means no error.
=cut
#-------------------------------------------------------------
sub create_vlan {
my $session=shift;
my $vlan_id=shift;
my $vlan_name="xcat_vlan_" . $vlan_id;
my $swmod=getSwitchModule($session);
if (!$swmod) { return (1, "This BNT switch modeule is not supported.");}
print "BNT $swmod\n";
#name
my @ret= xCAT::SwitchHandler::setoid($session, $BNTOID->{$swmod}->{vlanNewCfgVlanName}, $vlan_id, $vlan_name, 'OCTET');
if ($ret[0] != 0) {
$ret[1]="Set vlanNewCfgVlanName " . $BNTOID->{$swmod}->{vlanNewCfgVlanName} . ".$vlan_id to $vlan_name.\n" . $ret[1];
return @ret;
}
my $tmp = xCAT::MacMap::walkoid($session, $BNTOID->{$swmod}->{vlanNewCfgVlanName});
#print "tmp=" . Dumper($tmp) . "\n";
#change to enable state
my @ret= xCAT::SwitchHandler::setoid($session, $BNTOID->{$swmod}->{vlanNewCfgState}, $vlan_id, 2, 'INTEGER');
if ($ret[0] != 0) {
$ret[1]="Set vlanNewCfgState " . $BNTOID->{$swmod}->{vlanNewCfgState} . ".$vlan_id to 2(enable).\n" . $ret[1];
return @ret;
}
@ret=apply_changes($session, $swmod);
return @ret;
}
#--------------------------------------------------------------
=head3 add_ports_to_vlan
Every switch plugin must implement this subroutine.
Adds the given ports to the existing vlan
Returns an array. (erorcode, errormsg). When errorcode=0, means no error.
=cut
#-------------------------------------------------------------
sub add_ports_to_vlan {
my $session=shift;
my $vlan_id=shift;
# If portmode is set, we'll set the switchport to untagged(access) mode.
my $portmode=shift;
my @ports1=@_;
my $swmod=getSwitchModule($session);
if (!$swmod) { return (1, "This BNT switch modeule is not supported.");}
my $port_vlan_hash=get_vlanids_for_ports($session,@ports1);
#print "port_vlan_hash=" . Dumper($port_vlan_hash) . "\n";
my @ports=();
foreach my $port (keys(%$port_vlan_hash)) {
my $val=$port_vlan_hash->{$port};
my $found=0;
foreach my $tmp_vid (@$val) {
if ($tmp_vid == $vlan_id) {
$found=1;
last;
}
}
if (!$found) {
push(@ports, $port);
}
}
if (@ports==0) { return (0, ""); }
#print "vlan=$vlan_id, ports=@ports\n";
my $namemap = xCAT::MacMap::walkoid($session, $BNTOID->{$swmod}->{portInfoPhyIfDescr});
if ($namemap) {
my $ifnamesupport=0;
foreach (keys %{$namemap}) {
if ($namemap->{$_}) {
$ifnamesupport=1;
last;
}
}
unless ($ifnamesupport) {
$namemap=0;
}
}
unless ($namemap) {
return;
}
#print "namemap=" . Dumper($namemap) . "\n";
foreach my $portid (keys %{$namemap}) {
my $switchport = $namemap->{$portid};
foreach my $portname (@ports) {
unless (xCAT::MacMap::namesmatch($portname,$switchport)) {
next;
}
print "portid=$portid, vlan_id=$vlan_id\n";
if ($portmode){
#change this port to untagged
my @ret= xCAT::SwitchHandler::setoid($session, $BNTOID->{$swmod}->{agPortNewCfgVlanTag}, $portid, 3, 'INTEGER');
if ($ret[0] != 0) {
$ret[1]="Set agPortNewCfgVlanTag " . $BNTOID->{$swmod}->{agPortNewCfgVlanTag} . ".$portid to 3(untagged).\n" . $ret[1];
return @ret;
}
} else{
#change this port to tagged
my @ret= xCAT::SwitchHandler::setoid($session, $BNTOID->{$swmod}->{agPortNewCfgVlanTag}, $portid, 2, 'INTEGER');
if ($ret[0] != 0) {
$ret[1]="Set agPortNewCfgVlanTag " . $BNTOID->{$swmod}->{agPortNewCfgVlanTag} . ".$portid to 2(tagged).\n" . $ret[1];
return @ret;
}
}
#security feature:
if ($::XCATSITEVALS{vlansecurity} eq '1') {
#enable bpdu guard on this port
my @ret= xCAT::SwitchHandler::setoid($session, $BNTOID->{$swmod}->{agPortNewCfgBpduGuard}, $portid, 1, 'INTEGER');
if ($ret[0] != 0) {
$ret[1]="Enable bpdu guard for port $portid. (Set " . $BNTOID->{$swmod}->{agPortNewCfgBpduGuard} . ".$portid to 1.)\n" . $ret[1];
return @ret;
}
#enable root guard on this port
my @ret= xCAT::SwitchHandler::setoid($session, $BNTOID->{$swmod}->{agPortNewCfgStpExtGuard}, $portid, 2, 'INTEGER');
if ($ret[0] != 0) {
$ret[1]="Enable root guard for port $portid. (Set " . $BNTOID->{$swmod}->{agPortNewCfgStpExtGuard} . ".$portid to 2.\n" . $ret[1];
# return @ret; #do not return because it is not supported for some switches yet. A defect will be fixed in BNT.
}
}
#add port in one by one
my @ret= xCAT::SwitchHandler::setoid($session, $BNTOID->{$swmod}->{vlanNewCfgAddPort}, $vlan_id, $portid, 'GAUGE');
if ($ret[0] != 0) {
$ret[1]="Set vlanNewCfgAddPort" . $BNTOID->{$swmod}->{vlanNewCfgAddPort} . ".$vlan_id to $portid.\n" . $ret[1];
return @ret;
}
}
}
my @ret=apply_changes($session, $swmod);
return @ret;
}
#-------------------------------------------------------
=head3 add_crossover_ports_to_vlan
It enables the vlan on the cross-over links.
Returns an array. (erorcode, errormsg). When errorcode=0, means no error.
=cut
#-------------------------------------------------------
sub add_crossover_ports_to_vlan {
my $session=shift;
my $vlan_id=shift;
my $switch=shift;
my @switches=@_;
my @ret=(0, "");
my $msg;
if (@switches == 0 ) { return (0, ""); }
# my $swmod=getSwitchModule($session);
# if (!$swmod) { return (1, "This BNT switch modeule is not supported.");}
#figure out the port numbers that are connecting to the given switches
# my @ips=();
#get the ip address for each switch
# foreach my $switch (@switches) {
# my $ip=xCAT::NetworkUtils->getipaddr($switch);
# if (!$ip) {
# $msg .= "Cannot resolve ip address for switch $switch\n";
# } else {
# push(@ips, $ip);
# }
# }
# my @ports=();
# my $tmp = xCAT::MacMap::walkoid($session, $BNTOID->{$swmod}->{arpInfoDestIp});
# my $tmp1 = xCAT::MacMap::walkoid($session, $BNTOID->{$swmod}->{arpInfoSrcPort});
# print Dumper($tmp);
# print Dumper($tmp1);
# foreach my $tmp_id (keys %{$tmp}) {
# my $tmp_ip=$tmp->{$tmp_id};
# if (grep /^$tmp_ip$/, @ips) {
# my $port=$tmp1->{$tmp_id};
# if ($port) { push(@ports, $port); }
# }
# }
#get the ports that are connects to the switches
my $switchestab=xCAT::Table->new('switches',-create=>0);
my $ent = $switchestab->getNodeAttribs($switch, [qw(switch linkports)]);
if ((!$ent) || (! $ent->{linkports})) { return (0, $msg); }
my %linkports=();
foreach my $item (split(',',$ent->{linkports})) {
my @a=split(':', $item);
if (@a>1) {
$linkports{$a[1]}=$a[0];
}
}
#print Dumper(%linkports);
my @ports=();
foreach my $sw (@switches) {
if (exists($linkports{$sw})) {
push(@ports, $linkports{$sw});
}
}
#print "ports=@ports\n";
#now add the ports to the vlan
if (@ports > 0) {
my ($code, $msg1) = add_ports_to_vlan($session, $vlan_id, @ports);
if ($msg) {
$msg1 = $msg . $msg1;
}
return ($code, $msg1);
}
return (0, $msg);
}
#--------------------------------------------------------------
=head3 remove_vlan
Every switch plugin must implement this subroutine.
Remove a vlan from the switch
Returns an array. (erorcode, errormsg). When errorcode=0, means no error.
=cut
#-------------------------------------------------------------
sub remove_vlan {
my $session=shift;
my $vlan_id=shift;
my $swmod=getSwitchModule($session);
if (!$swmod) { return (1, "This BNT switch modeule is not supported.");}
#set to delete state
my @ret= xCAT::SwitchHandler::setoid($session, $BNTOID->{$swmod}->{vlanNewCfgDelete}, $vlan_id, 2, 'INTEGER');
if ($ret[0] != 0) {
$ret[1]="Set vlanNewCfgDelete " . $BNTOID->{$swmod}->{vlanNewCfgDelete} . ".$vlan_id to 2(delete).\n" . $ret[1];
return @ret;
}
@ret=apply_changes($session, $swmod);
return @ret;
}
#--------------------------------------------------------------
=head3 remove_ports_from_vlan
Every switch plugin must implement this subroutine.
Remove ports from a vlan
Returns an array. (erorcode, errormsg). When errorcode=0, means no error.
=cut
#-------------------------------------------------------------
sub remove_ports_from_vlan {
my $session=shift;
my $vlan_id=shift;
my @ports=@_;
my $swmod=getSwitchModule($session);
if (!$swmod) { return (1, "This BNT switch modeule is not supported.");}
#print "vlan=$vlan_id, ports=@ports\n";
my $namemap = xCAT::MacMap::walkoid($session, $BNTOID->{$swmod}->{portInfoPhyIfDescr});
if ($namemap) {
my $ifnamesupport=0;
foreach (keys %{$namemap}) {
if ($namemap->{$_}) {
$ifnamesupport=1;
last;
}
}
unless ($ifnamesupport) {
$namemap=0;
}
}
unless ($namemap) {
return;
}
#print "namemap=" . Dumper($namemap) . "\n";
foreach my $portid (keys %{$namemap}) {
my $switchport = $namemap->{$portid};
foreach my $portname (@ports) {
unless (xCAT::MacMap::namesmatch($portname,$switchport)) {
next;
}
print "portid=$portid, vlan_id=$vlan_id\n";
#remove port in one by one
my @ret= xCAT::SwitchHandler::setoid($session, $BNTOID->{$swmod}->{vlanNewCfgRemovePort}, $vlan_id, $portid, 'GAUGE');
if ($ret[0] != 0) {
$ret[1]="Set vlanNewCfgRemovePort " . $BNTOID->{$swmod}->{vlanNewCfgRemovePort} . ".$vlan_id to $portid.\n" . $ret[1];
return @ret;
}
}
}
my @ret=apply_changes($session, $swmod);
return @ret;
}
sub apply_changes {
my $session=shift;
my $swmod=shift;
#apply
my @ret= xCAT::SwitchHandler::setoid($session, $BNTOID->{$swmod}->{agApplyConfig}, 0, 1, 'INTEGER');
if ($ret[0] != 0) {
$ret[1]="Set agApplyConfig " . $BNTOID->{$swmod}->{agApplyConfig} . ".0 to 1(apply).\n" . $ret[1];
return @ret;
}
my $state=3;
while ($state == 3) {
my $tmp = xCAT::MacMap::walkoid($session, $BNTOID->{$swmod}->{agApplyConfig});
#print "tmp=" . Dumper($tmp) . "\n";
if ($tmp) {
$state=$tmp->{0};
}
sleep(3);
}
#set apply to idle state
my @ret= xCAT::SwitchHandler::setoid($session, $BNTOID->{$swmod}->{agApplyConfig}, 0, 2, 'INTEGER');
if ($ret[0] != 0) {
$ret[1]="Set agApplyConfig " . $BNTOID->{$swmod}->{agApplyConfig} . ".0 to 2(idle).\n" . $ret[1];
return @ret;
}
if ($state == 5) {
return (1, "Apply configuration failed.\n");
}
#save configurations.
my @ret= xCAT::SwitchHandler::setoid($session, $BNTOID->{$swmod}->{agSaveConfiguration}, 0, 2, 'INTEGER');
if ($ret[0] != 0) {
$ret[1]="Set agSaveConfiguration " . $BNTOID->{$swmod}->{agSaveConfiguration} . ".0 to 2(saveActive).\n" . $ret[1];
return @ret;
}
return @ret;
}
sub getSwitchModule {
my $session=shift;
#get the the switch brand name
my $tmp = xCAT::MacMap::walkoid($session, "$sysDescr", silentfail=>1);
my $swmod;
my $descr=$tmp->{0};
if ($descr) {
if ($descr =~ /G8000/) { return "G8000"; }
if ($descr =~ /G8052/) { return "G8052"; }
if ($descr =~ /G8124/) { return "G8124"; }
if ($descr =~ /G8264/) { return "G8264"; }
if ($descr =~ /EN4093/) { return "EN4093"; }
}
return 0;
}
1;

View File

@ -0,0 +1,623 @@
#!/usr/bin/perl
package xCAT_plugin::vlan::CiscoSwitch;
BEGIN
{
$::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat';
}
use lib "$::XCATROOT/lib/perl";
use strict;
use xCAT::MacMap;
use Data::Dumper;
use xCAT::SwitchHandler;
use SNMP;
#IF-MIB
my $ifName='.1.3.6.1.2.1.31.1.1.1.1';
my $ifDescr='.1.3.6.1.2.1.2.2.1.2';
my $ifOperStatus='.1.3.6.1.2.1.2.2.1.8';
#CISCO-VTP-MIB
my $vtpVlanEditTable='.1.3.6.1.4.1.9.9.46.1.4.2';
my $vtpVlanEditOperation='.1.3.6.1.4.1.9.9.46.1.4.1.1.1';
my $vtpVlanEditBufferOwner='.1.3.6.1.4.1.9.9.46.1.4.1.1.3';
my $vtpVlanEditRowStatus='.1.3.6.1.4.1.9.9.46.1.4.2.1.11.1';
my $vtpVlanEditType='.1.3.6.1.4.1.9.9.46.1.4.2.1.3.1';
my $vtpVlanEditName='.1.3.6.1.4.1.9.9.46.1.4.2.1.4.1';
my $vtpVlanEditDot10Said='.1.3.6.1.4.1.9.9.46.1.4.2.1.6.1';
my $vtpVlanState='.1.3.6.1.4.1.9.9.46.1.3.1.1.2';
my $vlanTrunkPortDynamicStatus='.1.3.6.1.4.1.9.9.46.1.6.1.1.14';
my $vlanTrunkPortDynamicState='.1.3.6.1.4.1.9.9.46.1.6.1.1.13';
my $vlanTrunkPortNativeVlan= '.1.3.6.1.4.1.9.9.46.1.6.1.1.5';
my $vlanTrunkPortVlansEnabled='.1.3.6.1.4.1.9.9.46.1.6.1.1.4';
my $vlanTrunkPortEncapsulationType='.1.3.6.1.4.1.9.9.46.1.6.1.1.3';
#CISCO-VLAN-MEMBERSHIP-MIB
my $vmVlan='.1.3.6.1.4.1.9.9.68.1.2.2.1.2';
my $vmVlanType='.1.3.6.1.4.1.9.9.68.1.2.2.1.1'; #1:static 2:dynamic 3:trunk
#CISCI-STP-EXTENSION-MIB
my $stpxRootGuardConfigEnabled='1.3.6.1.4.1.9.9.82.1.5.1.1.2'; #1:enable 2:disable
my $stpxFastStartPortBpduGuardMode='1.3.6.1.4.1.9.9.82.1.9.3.1.4'; #1:enable 2:disable 3:default
my %HexConv=( 0=>0x80, 1=>0x40, 2=>0x20, 3=>0x10,
4=>0x08, 5=>0x04, 6=>0x02, 7=>0x01);
#--------------------------------------------------------------
=head3 filter_string
Every switch plugin must implement this subroutine.
The return value will be used comare against the string
from sysDescr value from snmpget. If the latter contains
this string, then this mudule will be used to handle the
requests for vlan configuration.
=cut
#-------------------------------------------------------------
sub filter_string {
return "Cisco ";
}
#--------------------------------------------------------------
=head3 get_vlan_ids
Every switch plugin must implement this subroutine.
It gets the existing vlan IDs for the switch.
Returns: an array containing all the vlan ids for the switch
=cut
#-------------------------------------------------------------
sub get_vlan_ids {
my $session=shift;
my $vlanmap = xCAT::MacMap::walkoid($session, "$vtpVlanState.1", silentfail=>1);
my %vlanids=();
foreach(keys(%$vlanmap)) {
$vlanids{$_}=1;
}
my @ret=(sort keys(%vlanids));
print "ids=@ret\n";
return @ret;
}
#--------------------------------------------------------------
=head3 get_vlanids_for_ports
Every switch plugin must implement this subroutine.
It returns a hash pointer that contains the vlan ids for each given port.
The kay is the port, the vlaue is a pointer to an array.
=cut
#-------------------------------------------------------------
sub get_vlanids_for_ports {
my $session=shift;
my @ports=@_;
my $namemap = xCAT::MacMap::walkoid($session, $ifName);
#namemap is the mapping of ifIndex->(human readable name)
if ($namemap) {
my $ifnamesupport=0;
foreach (keys %{$namemap}) {
if ($namemap->{$_}) {
$ifnamesupport=1;
last;
}
}
unless ($ifnamesupport) {
$namemap=0;
}
}
unless ($namemap) { #Failback to ifDescr. ifDescr is close, but not perfect on some switches
$namemap = xCAT::MacMap::walkoid($session,$ifDescr);
}
unless ($namemap) {
return;
}
#print "namemap=" . Dumper($namemap) . "\n";
my $iftovlanmap = xCAT::MacMap::walkoid($session, $vmVlan, silentfail=>1);
#print "iftovlanmap=" . Dumper($iftovlanmap) . "\n";
my $trunktovlanmap = xCAT::MacMap::walkoid($session, $vlanTrunkPortNativeVlan, silentfail=>1); #for trunk ports, we are interested in the native vlan
#print "trunktovlanmap=" . Dumper($trunktovlanmap) . "\n";
my %ret=();
if (defined($iftovlanmap) or defined($trunktovlanmap)) {
foreach my $portid (keys %{$namemap}) {
my $switchport = $namemap->{$portid};
foreach my $portname (@ports) {
unless (xCAT::MacMap::namesmatch($portname,$switchport)) {
next;
}
if (defined $iftovlanmap->{$portid}) {
$ret{$portname}=[$iftovlanmap->{$portid}];
} elsif (defined $trunktovlanmap->{$portid}){
$ret{$portname}=[$trunktovlanmap->{$portid}];
} else {
$ret{$portname}=['NA'];
}
}
}
}
return \%ret;
}
#--------------------------------------------------------------
=head3 create_vlan
Every switch plugin must implement this subroutine.
Creates a new vlan on the switch
Returns an array. (erorcode, errormsg). When errorcode=0, means no error.
=cut
#-------------------------------------------------------------
sub create_vlan {
my $session=shift;
my $vlan_id=shift;
my $vlan_name="xcat_vlan_" . $vlan_id;
print "Cisco\n";
#Verify if the edition is in use by another NMS station or device.
#The edition is not in use if you see this message: no MIB objects contained under subtree:
my $tmp = xCAT::MacMap::walkoid($session,$vtpVlanEditTable);
#print "tmp=" . Dumper($tmp) . "\n";
#Set the vtpVlanEditOperation to the copy state(2). This allows to create the VLAN.
my @ret= xCAT::SwitchHandler::setoid($session, $vtpVlanEditOperation, 1, 2, 'INTEGER');
#if ($ret[0] != 0) { return @ret; }
#set vtpVlanEditBufferOwner in order to makethe current owner of the edit permission visible
my $username="xcat";
my @ret=xCAT::SwitchHandler::setoid($session,$vtpVlanEditBufferOwner, 1, $username, 'OCTET');
if ($ret[0] != 0) {
$ret[1]="Set vtpVlanEditBufferOwner $vtpVlanEditBufferOwner.1 to $username.\n" .$ret[1];
return @ret;
}
#my $tmp = xCAT::MacMap::walkoid($session, $vtpVlanEditOperation);
#print "tmp=" . Dumper($tmp) . "\n";
#my $tmp = xCAT::MacMap::walkoid($session, $vtpVlanEditBufferOwner);
#print "tmp=" . Dumper($tmp) . "\n";
#set vtpVlanEditRowStatus to createAndGo(4)
my @ret= xCAT::SwitchHandler::setoid($session, $vtpVlanEditRowStatus, $vlan_id, 4, 'INTEGER');
if ($ret[0] != 0) {
$ret[1]="Set vtpVlanEditRowStatus $vtpVlanEditRowStatus.$vlan_id to 4.\n" . $ret[1];
return @ret;
}
#set vtpVlanEditType to ethernet (1)
my @ret= xCAT::SwitchHandler::setoid($session,$vtpVlanEditType, $vlan_id, 1, 'INTEGER');
if ($ret[0] != 0) {
$ret[1]="Set vtpVlanEditType $vtpVlanEditType.$vlan_id to 1.\n" . $ret[1];
return @ret;
}
#set vtpVlanEditName to xcat_vlan_#
my @ret= xCAT::SwitchHandler::setoid($session,$vtpVlanEditName, $vlan_id, $vlan_name, 'OCTET');
if ($ret[0] != 0) {
$ret[1]="Set vtpVlanEditName $vtpVlanEditName.$vlan_id to $vlan_name.\n" . $ret[1];
return @ret;
}
#Set the vtpVlanEditDot10Said. This is the VLAN number + 100000 translated to hexadecimal.
my $num=100000 + $vlan_id;
my $hex_num=sprintf("%x", $num);
my @ret= xCAT::SwitchHandler::setoid($session,$vtpVlanEditDot10Said, $vlan_id, $hex_num, 'OCTETHEX');
#if ($ret[0] != 0) {
# $ret[1]="Set vtpVlanEditDot10Said $vtpVlanEditDot10Said.$vlan_id to $hex_num.\n" . $ret[1];
#return @ret;
#}
#apply the changes, set vtpVlanEditOperation.1 to apply (3)
my @ret= xCAT::SwitchHandler::setoid($session, $vtpVlanEditOperation, 1, 3, 'INTEGER');
if ($ret[0] != 0) {
$ret[1]="Set vtpVlanEditOperation $vtpVlanEditOperation.1 to 3.\n" . $ret[1];
return @ret;
}
#release the edition buffer, set vtpVlanEditOperation.1 to release (4)
my @ret= xCAT::SwitchHandler::setoid($session, $vtpVlanEditOperation, 1, 4, 'INTEGER');
if ($ret[0] != 0) {
$ret[1]="Set vtpVlanEditOperation $vtpVlanEditOperation.1 to 4.\n" . $ret[1];
return @ret;
}
return (0, "");
}
#--------------------------------------------------------------
=head3 add_ports_to_vlan
Every switch plugin must implement this subroutine.
Adds the given ports to the existing vlan
Returns an array. (erorcode, errormsg). When errorcode=0, means no error.
=cut
#-------------------------------------------------------------
sub add_ports_to_vlan {
my $session=shift;
my $vlan_id=shift;
# If portmode is set, we'll set the switchport to untagged(access) mode.
my $portmode=shift;
my @ports=@_;
#print "Add ports @ports to vla $vlan_id.\n";
#add ports to the vlan.
if (@ports > 0) {
my $namemap = xCAT::MacMap::walkoid($session,$ifName);
#namemap is the mapping of ifIndex->(human readable name)
if ($namemap) {
my $ifnamesupport=0; #Assume broken ifnamesupport until proven good... (Nortel switch)
foreach (keys %{$namemap}) {
if ($namemap->{$_}) {
$ifnamesupport=1;
last;
}
}
unless ($ifnamesupport) {
$namemap=0;
}
}
unless ($namemap) { #Failback to ifDescr. ifDescr is close, but not perfect on some switches
$namemap = xCAT::MacMap::walkoid($session, $ifDescr);
}
unless ($namemap) {
return;
}
#print "namemap=" . Dumper($namemap) . "\n";
my $trunkportstate = xCAT::MacMap::walkoid($session,$vlanTrunkPortDynamicState);
#print "trunkportstate=" . Dumper($trunkportstate) . "\n";
my $iftovlanmap = xCAT::MacMap::walkoid($session, $vmVlan, silentfail=>1);
#print "iftovlanmap=" . Dumper($iftovlanmap) . "\n";
my $trunktovlanmap = xCAT::MacMap::walkoid($session, $vlanTrunkPortNativeVlan, silentfail=>1);
#print "trunktovlanmap=" . Dumper($trunktovlanmap) . "\n";
#get current vlan type (static, dynamic or trunk)
my $vlantypemap = xCAT::MacMap::walkoid($session, $vmVlanType, silentfail=>1);
#print "vlantypemap=" . Dumper($vlantypemap) . "\n";
foreach my $portid (keys %{$namemap}) {
my $switchport = $namemap->{$portid};
foreach my $portname (@ports) {
unless (xCAT::MacMap::namesmatch($portname,$switchport)) {
next;
}
### set the port to trunk mode
print "portid=$portid\n";
# TODO: need testing in cisco's env for how to set a port as access mode through snmpset?
# Can setting vlanTrunkPortDot1qTunnel or cltcDot1qTunnelMode helps?
if ($trunkportstate->{$portid} != 1) {
my @ret = xCAT::SwitchHandler::setoid($session, $vlanTrunkPortEncapsulationType, $portid, 4, 'INTEGER');
if ($ret[0] != 0) {
$ret[1]="Set vlanTrunkPortEncapsulationType $vlanTrunkPortEncapsulationType.$portid to 4(dot1Q).\n" . $ret[1];
return @ret;
}
my @ret = xCAT::SwitchHandler::setoid($session, $vlanTrunkPortDynamicState, $portid, 1, 'INTEGER');
if ($ret[0] != 0) {
$ret[1]="Set vlanTrunkPortDynamicState $vlanTrunkPortDynamicState.$portid to 1.\n" . $ret[1];
return @ret;
}
}
### set trunk native vlan id
my $native_vlanid=1;
if ((exists($vlantypemap->{$portid})) && ($vlantypemap->{$portid} < 3)) { #the port was set to access mode before
if ((exists($iftovlanmap->{$portid})) && ($iftovlanmap->{$portid} > 0)) {
$native_vlanid=$iftovlanmap->{$portid};
}
} else { #the port is originally set to trunk mode
if ((exists($trunktovlanmap->{$portid})) && ($trunktovlanmap->{$portid} > 0)) {
$native_vlanid=$trunktovlanmap->{$portid};
} elsif ((exists($iftovlanmap->{$portid})) && ($iftovlanmap->{$portid} > 0)) {
$native_vlanid=$iftovlanmap->{$portid};
}
}
print "*** native_vlanid=$native_vlanid\n";
my @ret = xCAT::SwitchHandler::setoid($session, $vlanTrunkPortNativeVlan, $portid, $native_vlanid, 'INTEGER');
if ($ret[0] != 0) {
$ret[1]="Set native vlan for port $portid to $native_vlanid ($vlanTrunkPortNativeVlan.$portid to $native_vlanid).\n" . $ret[1];
return @ret;
}
### allow this vlan on the port
my $data = $session->get([$vlanTrunkPortVlansEnabled, $portid]);
my @a = split(//, $data);
foreach (@a) {
my $num=unpack("C*", $_);
$_= sprintf ("%02x",$num);
}
if ((exists($vlantypemap->{$portid})) && ($vlantypemap->{$portid} < 3)) {
#if originally this port was in access or dynamic mode, only enable original vlan and this tagged vlan
#reset the matrix
#print "***was access mode\n";
foreach (@a) {
$_="00";
}
#add native vlan id in the matrix
my $index = int($native_vlanid / 8);
my $offset = $native_vlanid % 8;
my $num = hex($a[$index]) | $HexConv{$offset};
$a[$index] = sprintf("%02x", $num);
#print "index=$index, offset=$offset\n";
#add current vlan id in the matrix
$index = int($vlan_id / 8);
$offset = $vlan_id % 8;
$num = hex($a[$index]) | $HexConv{$offset};
$a[$index] = sprintf("%02x", $num);
} else {
#if this port was trunk mode before, add this tagged vlan in the matrix
# print "***was trunk mode\n";
my $index = int($vlan_id / 8);
my $offset = $vlan_id % 8;
my $num = hex($a[$index]) | $HexConv{$offset};
$a[$index] = sprintf("%02x", $num);
}
#print "a=@a\n";
foreach (@a) {
$_=hex($_);
$_=pack("C*", $_);
}
my $s = join(//, @a);
my @ret = xCAT::SwitchHandler::setoid($session, $vlanTrunkPortVlansEnabled, $portid, $s, 'OCTET');
#print "**** ret=@ret\n";
if ($ret[0] != 0) {
$ret[1]="Allow vlan on port $portid ($vlanTrunkPortVlansEnabled.$portid=$s).\n" . $ret[1];
return @ret;
}
### security feature
if ($::XCATSITEVALS{vlansecurity} eq '1') {
#set root guard on the port
my @ret = xCAT::SwitchHandler::setoid($session, $stpxRootGuardConfigEnabled, $portname, 1, 'INTEGER');
if ($ret[0] != 0) {
$ret[1]="Set root guard for port $portname to enable ($stpxRootGuardConfigEnabled.$portname=1).\n" . $ret[1];
return @ret;
}
#set bpdu guard on the port
my @ret = xCAT::SwitchHandler::setoid($session, $stpxFastStartPortBpduGuardMode, $portname, 1, 'INTEGER');
if ($ret[0] != 0) {
$ret[1]="Set bpdu guard for port $portname to enalbe ($stpxFastStartPortBpduGuardMode.$portname=1).\n" . $ret[1];
return @ret;
}
}
last;
}
}
}
return (0, "");
}
#-------------------------------------------------------
=head3 add_crossover_ports_to_vlan
It enables the vlan on the cross-over links.
Returns an array. (erorcode, errormsg). When errorcode=0, means no error.
=cut
#-------------------------------------------------------
sub add_crossover_ports_to_vlan {
my $session=shift;
my $vlan_id=shift;
my $switch=shift;
my @switches=@_;
my @ret=(0, "");
my $msg;
if (@switches == 0 ) { return (0, ""); }
#get the ports that are connects to the switches
my $switchestab=xCAT::Table->new('switches',-create=>0);
my $ent = $switchestab->getNodeAttribs($switch, [qw(switch linkports)]);
if ((!$ent) || (! $ent->{linkports})) { return (0, $msg); }
my %linkports=();
foreach my $item (split(',',$ent->{linkports})) {
my @a=split(':', $item);
if (@a>1) {
$linkports{$a[1]}=$a[0];
}
}
#print Dumper(%linkports);
my @ports=();
foreach my $sw (@switches) {
if (exists($linkports{$sw})) {
push(@ports, $linkports{$sw});
}
}
#print "ports=@ports\n";
#now add the ports to the vlan
if (@ports > 0) {
my ($code, $msg1) = add_ports_to_vlan($session, $vlan_id, @ports);
if ($msg) {
$msg1 = $msg . $msg1;
}
return ($code, $msg1);
}
return (0, $msg);
}
#--------------------------------------------------------------
=head3 remove_vlan
Every switch plugin must implement this subroutine.
Remove a vlan from the switch
Returns an array. (erorcode, errormsg). When errorcode=0, means no error.
=cut
#-------------------------------------------------------------
sub remove_vlan {
my $session=shift;
my $vlan_id=shift;
#Verify if the edition is in use by another NMS station or device.
#The edition is not in use if you see this message: no MIB objects contained under subtree:
my $tmp = xCAT::MacMap::walkoid($session,$vtpVlanEditTable);
#print "tmp=" . Dumper($tmp) . "\n";
#Set the vtpVlanEditOperation to the copy state(2). This allows to delete the VLAN.
my @ret= xCAT::SwitchHandler::setoid($session, $vtpVlanEditOperation, 1, 2, 'INTEGER');
if ($ret[0] != 0) {
$ret[1]="Set vtpVlanEditOperation $vtpVlanEditOperation.1 to 3 (copy state).\n" . $ret[1];
return @ret;
}
#set vtpVlanEditBufferOwner in order to makethe current owner of the edit permission visible
my $username="xcat";
my @ret=xCAT::SwitchHandler::setoid($session,$vtpVlanEditBufferOwner, 1, $username, 'OCTET');
if ($ret[0] != 0) {
$ret[1]="Set vtpVlanEditBufferOwner $vtpVlanEditBufferOwner.1 to $username.\n" . $ret[1];
return @ret;
}
#set vtpVlanEditRowStatus to destroy(6)
my @ret= xCAT::SwitchHandler::setoid($session, $vtpVlanEditRowStatus, $vlan_id, 6, 'INTEGER');
if ($ret[0] != 0) {
$ret[1]="Set vtpVlanEditRowStatus $vtpVlanEditRowStatus.$vlan_id to 6 (destroy).\n" . $ret[1];
return @ret;
}
#apply the changes, set vtpVlanEditOperation.1 to apply (3)
my @ret= xCAT::SwitchHandler::setoid($session, $vtpVlanEditOperation, 1, 3, 'INTEGER');
if ($ret[0] != 0) {
$ret[1]="Set $vtpVlanEditOperation.1 to 3 (apply).\n" . $ret[1];
return @ret;
}
#release the edition buffer, set vtpVlanEditOperation.1 to release (4)
my @ret= xCAT::SwitchHandler::setoid($session, $vtpVlanEditOperation, 1, 4, 'INTEGER');
if ($ret[0] != 0) {
$ret[1]="Set vtpVlanEditOperation $vtpVlanEditOperation.1 to 4 (release).\n" . $ret[1];
return @ret;
}
#my $iftovlanmap = xCAT::MacMap::walkoid($session, $vmVlan, silentfail=>1);
#print "iftovlanmap=" . Dumper($iftovlanmap) . "\n";
#foreach (keys(%$iftovlanmap)) {
# if($iftovlanmap->{$_} == $vlan_id) {
#my @ret= xCAT::SwitchHandler::setoid($session, $vmVlan, $_, 1, 'INTEGER');
#if ($ret[0] != 0) {
# $ret[1]="Set $vmVlan.$_ to 1.\n" . $ret[1];
# return @ret;
#}
# }
#}
#my $trunktovlanmap = xCAT::MacMap::walkoid($session, $vlanTrunkPortNativeVlan, silentfail=>1); #for trunk ports, we are interested in the native vlan
#print "trunktovlanmap=" . Dumper($trunktovlanmap) . "\n";
#foreach (keys(%$trunktovlanmap)) {
# if($trunktovlanmap->{$_} == $vlan_id) {
# my @ret= xCAT::SwitchHandler::setoid($session, $vlanTrunkPortNativeVlan, $_, 1, 'INTEGER');
# if ($ret[0] != 0) {
# $ret[1]="Set $vlanTrunkPortNativeVlan.$_ to 1.\n" . $ret[1];
# return @ret;
# }
# }
#}
return (0, "");;
}
#--------------------------------------------------------------
=head3 remove_ports_from_vlan
Every switch plugin must implement this subroutine.
Remove ports from a vlan
Returns an array. (erorcode, errormsg). When errorcode=0, means no error.
=cut
#-------------------------------------------------------------
sub remove_ports_from_vlan {
my $session=shift;
my $vlan_id=shift;
my @ports = @_;
if (@ports > 0) {
my $namemap = xCAT::MacMap::walkoid($session,$ifName);
#namemap is the mapping of ifIndex->(human readable name)
if ($namemap) {
my $ifnamesupport=0;
foreach (keys %{$namemap}) {
if ($namemap->{$_}) {
$ifnamesupport=1;
last;
}
}
unless ($ifnamesupport) {
$namemap=0;
}
}
unless ($namemap) { #Failback to ifDescr. ifDescr is close, but not perfect on some switches
$namemap = xCAT::MacMap::walkoid($session, $ifDescr);
}
unless ($namemap) {
return;
}
#print "namemap=" . Dumper($namemap) . "\n";
foreach my $portid (keys %{$namemap}) {
my $switchport = $namemap->{$portid};
foreach my $portname (@ports) {
unless (xCAT::MacMap::namesmatch($portname,$switchport)) {
next;
}
#remove the vlan id from the vlanTrunkPortVlansEnabled.port matrix
my $data = $session->get([$vlanTrunkPortVlansEnabled, $portid]);
my @a = split(//, $data);
foreach (@a) {
my $num=unpack("C*", $_);
$_= sprintf ("%02x",$num);
}
#print "a=@a\n";
my $index = int($vlan_id / 8);
my $offset = $vlan_id % 8;
my $num = hex($a[$index]) & (~$HexConv{$offset});
$a[$index] = sprintf("%02x", $num);
#print "a=@a\n";
foreach (@a) {
$_=hex($_);
$_=pack("C*", $_);
}
my $s = join(//, @a);
my @ret = xCAT::SwitchHandler::setoid($session, $vlanTrunkPortVlansEnabled, $portid, $s, 'OCTET');
if ($ret[0] != 0) {
$ret[1]="Set vlanTrunkPortVlansEnabled $vlanTrunkPortVlansEnabled.$portid to $s.\n" . $ret[1];
return @ret;
}
last;
}
}
}
return (0, "");;
}
1;

213
xCAT-vlan/xpod2man Executable file
View File

@ -0,0 +1,213 @@
#!/usr/bin/perl
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
# First builds the xCAT summary man page from Synopsis of each man page.
# Then converts all of the pod man pages into html (including links to each other)
# We assume that this script is run in the xCAT-vlan-2.0 dir, so everything is
# done relative to that.
use strict;
#use lib '.';
use Pod::Man;
use Pod::Html;
my $poddir = 'pods';
my $mandir = 'share/man';
my $htmldir = 'share/doc';
my $cachedir = '/tmp';
my @pods = getPodList($poddir);
#foreach (@pods) { print "$_\n"; } exit;
# Build the cmd overview page.
#writesummarypage("$poddir/man1/xcat.1.pod", @pods);
# Build the man page for each pod.
#mkdir($mandir) or die "Error: could not create $mandir.\n";
print "Converting PODs to man pages...\n";
foreach my $podfile (@pods) {
my $manfile = $podfile;
$manfile =~ s/^$poddir/$mandir/; # change the beginning of the path
$manfile =~ s/\.pod$//; # change the ending
my $mdir = $manfile;
$mdir =~ s|/[^/]*$||; # get rid of the basename part
if (system("mkdir -p $mdir")) { die "Error: could not create $mdir.\n"; }
my ($section) = $podfile =~ /\.(\d+)\.pod$/;
convertpod2man($podfile, $manfile, $section);
}
my @dummyPods = createDummyPods($poddir, \@pods);
# Build the html page for each pod.
#mkdir($htmldir) or die "Error: could not create $htmldir.\n";
print "Converting PODs to HTML pages...\n";
# have to clear the cache, because old entries can cause a problem
unlink("$cachedir/pod2htmd.tmp", "$cachedir/pod2htmi.tmp");
foreach my $podfile (@pods) {
my $htmlfile = $podfile;
$htmlfile =~ s/^$poddir/$htmldir/; # change the beginning of the path
$htmlfile =~ s/\.pod$/\.html/; # change the ending
my $hdir = $htmlfile;
$hdir =~ s|/[^/]*$||; # get rid of the basename part
if (system("mkdir -p $hdir")) { die "Error: could not create $hdir.\n"; }
#print "$podfile, $htmlfile, $poddir, $htmldir\n";
convertpod2html($podfile, $htmlfile, $poddir, $htmldir);
}
# Remove the dummy pods
unlink @dummyPods;
rmdir "$poddir/man7";
exit;
# To enable linking between the cmd man pages and the db man pages, need to:
# grep thru the cmd pods searching for references (L<>) to any section 5 man page
# if that pod does not exist, create an empty one that will satisfy pod2html
# keep track of all dummy pods created, so they can be removed later
sub createDummyPods {
my ($poddir, $pods) = @_;
my $cmd = "grep -r -E 'L<.+\\([57]\\)\\|.+\\.[57]>' " . $poddir;
#print "Running cmd: ", $cmd, "\n";
my @lines = `$cmd`;
if ($?) { print "Error running: $cmd\n"; print join('', @lines); }
#my @lines;
#system($cmd);
my @dummyPods;
foreach my $l (@lines) {
#print "$l\n";
my @matches = $l =~ /L<([^\(]+)\(([57])\)\|\1\.[57]>/g; # get all the matches in the line
# The above line should create the array with every other entry being the man page name
# and every other entry is the section # (5 or 7)
my $cmd;
while ($cmd=shift @matches) {
#foreach my $m (@matches) {
my $section = shift @matches;
my $filename = "$poddir/man$section/$cmd.$section.pod";
#print "$filename\n";
if (!(grep /^$filename$/, @$pods) && !(grep /^$filename$/, @dummyPods)) { push @dummyPods, $filename; }
}
}
# Create these empty files
print "Creating empty linked-to files: ", join(', ', @dummyPods), "\n";
mkdir "$poddir/man7";
foreach my $d (@dummyPods) {
if (!open(TMP, ">>$d")) { warn "Could not create dummy pod file $d ($!)\n"; }
else { close TMP; }
}
return @dummyPods;
}
# Recursively get the list of pod man page files.
sub getPodList {
my $poddir = shift;
my @files;
# 1st get toplevel dir listing
opendir(DIR, $poddir) or die "Error: could not read $poddir.\n";
my @topdir = grep !/^\./, readdir(DIR); # /
close(DIR);
# Now go thru each subdir (these are man1, man3, etc.)
foreach my $mandir (@topdir) {
opendir(DIR, "$poddir/$mandir") or die "Error: could not read $poddir/$mandir.\n";
my @dir = grep !/^\./, readdir(DIR); # /
close(DIR);
foreach my $file (@dir) {
push @files, "$poddir/$mandir/$file";
}
}
return sort @files;
}
# Create the xcat man page that gives a summary description of each xcat cmd.
sub writesummarypage {
my $file = shift; # relative path file name of the man page
# the rest of @_ contains the pod files that describe each cmd
open(FILE, ">$file") or die "Error: could not open $file for writing.\n";
print FILE <<'EOS1';
=head1 NAME
B<xcat> - extreme Cluster Administration Tool.
=head1 DESCRIPTION
Extreme Cluster Administration Toolkit (xCAT). xCAT is a scalable distributed computing management
and provisioning tool that provides a unified interface for hardware control, discovery, and
OS diskful/diskfree deployment.
=head1 XCAT DATABASE
All of the cluster configuration information is in the xCAT database. See L<xcatdb(5)|xcatdb.5> for
descriptions of every table in the database.
=head1 XCAT COMMANDS
What follows is a short description of each xCAT command. To get more information about a particular
command, see its man page. Note that the commands are listed in alphabetical order B<within each section>,
i.e. all the commands in section 1, then the commands in section 3, etc.
=over 12
EOS1
# extract the summary for each cmd from its man page
foreach my $manpage (@_) {
my ($sectionnum) = $manpage =~ /\.(\d+)\.pod$/;
# Suck in the whole file, then we will parse it.
open(MANPAGE, "$manpage") or die "Error: could not open $manpage for reading.\n";
my @contents = <MANPAGE>;
my $wholemanpage = join('', @contents);
close(MANPAGE);
# This regex matches: optional space, =head1, space, title, space, cmd, space, description, newline
my ($cmd, $description) = $wholemanpage =~ /^\s*=head1\s+\S+\s+(\S+)\s+(.+?)\n/si;
if (!defined($cmd)) { print "Warning: $manpage is not in a recognized structure. It will be ignored.\n"; next; }
if (!defined($description)) { print "Warning: $manpage does not have a description for $cmd. It will be ignored.\n"; next; }
$cmd =~ s/^.<(.+)>$/$1/; # if the cmd name has pod formatting around it, strip it off
$description =~ s/^-\s*//; # if the description has a leading hypen, strip it off
print FILE "\n=item L<$cmd($sectionnum)|$cmd.$sectionnum>\n\n".$description."\n";
}
# Artificially add the xcattest cmd, because the xCAT-test rpm will add this
print FILE "\n=item L<xcattest(1)|xcattest.1>\n\nRun automated xCAT test cases.\n";
print FILE <<"EOS3";
=back
EOS3
close FILE;
}
# Create the html page for one pod.
sub convertpod2html {
my ($podfile, $htmlfile, $poddir, $htmldir) = @_;
#TODO: use --css=<stylesheet> and --title=<pagetitle> to make the pages look better
pod2html($podfile,
"--outfile=$htmlfile",
"--podpath=man1",
"--podroot=$poddir",
"--htmldir=$htmldir",
"--recurse",
"--cachedir=$cachedir",
);
}
# Create the man page for one pod.
sub convertpod2man {
my ($podfile, $manfile, $section) = @_;
my $parser = Pod::Man->new(section => $section);
$parser->parse_from_file($podfile, $manfile);
}