2
0
mirror of https://github.com/xcat2/xcat-core.git synced 2025-06-15 10:50:28 +00:00

Add snmp_scan method for switchdiscover command

This commit is contained in:
Casandra Qiu
2016-03-24 21:22:58 -04:00
parent 74d35a6b3d
commit 4488c24a30
4 changed files with 191 additions and 84 deletions

View File

@ -5,7 +5,7 @@ Use switchdiscover command to discover the switches that are attached to the nei
switchdiscover [noderange|--range ip_ranges][-s scan_methods][-r|-x|-z][-w]
where the scan_methods can be **nmap** . The default is **nmap**. (**nmap** comes from most os distribution.)
where the scan_methods can be **nmap**, **snmp", or **lldp** . The default is **nmap**. (**nmap** comes from most os distribution.)
To discover switches over the IP range 10.4.25.0/24 and 192.168.0.0/24, use the following command: ::

View File

@ -29,6 +29,8 @@ To view all the switches defined in the xCAT databasee use \ **lsdef -w "nodetyp
For lldp method, please make sure that lldpd package is installed and lldpd is running on the xCAT management node. lldpd comes from xcat-dep packge or you can get it from http://vincentbernat.github.io/lldpd/installation.html.
For snmp method, please make sure that snmpwalk command is installed and snmp is enabled for switches. To install snmpwalk, "yum install net-snmp-utils" for redhat and sles, "apt-get install snmp" for Ubuntu.
*******
OPTIONS
@ -60,6 +62,8 @@ OPTIONS
Specify one or more IP ranges. Each can be an ip address (10.1.2.3) or an ip range (10.1.2.0/24). If the range is huge, for example, 192.168.1.1/8, the switch discover may take a very long time to scan. So the range should be exactly specified.
For nmap scan method, it accepts multiple formats. For example, 192.168.1.1/24, 40-41.1-2.3-4.1-100.
For snmp scan method, it accepts multiple formats. For example: 192.168.1.1/24, 1.2-3.4.5, 1.2.3-4.5, 1.2.3.4-5
If the range is not specified, the command scans all the subnets that the active network interfaces (eth0, eth1) are on where this command is issued.
@ -74,7 +78,7 @@ OPTIONS
\ **-s**\
It is a comma separated list of methods for switch discovery.
The possible switch scan methods are: lldp and nmap. The default is nmap.
The possible switch scan methods are: lldp, nmap or snmp. The default is nmap.

View File

@ -16,12 +16,14 @@ B<switchdiscover> [I<noderange> | B<--range> I<ip_ranges>] B<[-V] [-w][-r|-x|-z]
=head1 DESCRIPTION
The switchdiscover command scans the subnets and discovers all the swithches on the subnets. The command takes a list of subnets as input. The default subnets are the ones that the xCAT management node is on. It uses nmap command to discover the switches. However, you can specify other discovery methods such as lldp with B<-s> flag. You can write the discovered switches into xCAT database with B<-w> flag. This command supports may output formats such as xml(B<-x>), raw(B<-r>) and stanza(B<-z>) in addition to the default format.
The switchdiscover command scans the subnets and discovers all the swithches on the subnets. The command takes a list of subnets as input. The default subnets are the ones that the xCAT management node is on. It uses nmap command as default to discover the switches. However, you can specify other discovery methods such as lldp or snmp with B<-s> flag. You can write the discovered switches into xCAT database with B<-w> flag. This command supports may output formats such as xml(B<-x>), raw(B<-r>) and stanza(B<-z>) in addition to the default format.
To view all the switches defined in the xCAT databasee use B<lsdef -w "nodetype=switch"> command.
For lldp method, please make sure that lldpd package is installed and lldpd is running on the xCAT management node. lldpd comes from xcat-dep packge or you can get it from http://vincentbernat.github.io/lldpd/installation.html.
For snmp method, please make sure that snmpwalk command is installed and snmp is enabled for switches. To install snmpwalk, "yum install net-snmp-utils" for redhat and sles, "apt-get install snmp" for Ubuntu.
=head1 OPTIONS
@ -46,7 +48,9 @@ Display usage message.
Specify one or more IP ranges. Each can be an ip address (10.1.2.3) or an ip range (10.1.2.0/24). If the range is huge, for example, 192.168.1.1/8, the switch discover may take a very long time to scan. So the range should be exactly specified.
For nmap scan method, it accepts multiple formats. For example, 192.168.1.1/24, 40-41.1-2.3-4.1-100.
For nmap scan method, it accepts multiple formats. For example: 192.168.1.1/24, 40-41.1-2.3-4.1-100.
For snmp scan method, it accepts multiple formats. For example: 192.168.1.1/24, 1.2-3.4.5, 1.2.3-4.5, 1.2.3.4-5
If the range is not specified, the command scans all the subnets that the active network interfaces (eth0, eth1) are on where this command is issued.
@ -57,7 +61,7 @@ Display Raw responses.
=item B<-s>
It is a comma separated list of methods for switch discovery.
The possible switch scan methods are: lldp and nmap. The default is nmap.
The possible switch scan methods are: lldp, nmap or snmp. The default is nmap.
=item B<-v|--version>

View File

@ -30,24 +30,14 @@ my %global_scan_type = (
my %global_switch_type = (
Juniper => "Juniper",
juniper => "Juniper",
Cisco => "Cisco",
BNT => "BNT",
Mellanox => "Mellanox"
);
my %global_OID_model_metrix = (
"enterprises.2636.1.1.1.2.54" => "Juniper",
"enterprises.2636" => "Juniper",
"enterprises.20301.1.18.13" => "(BNT)IBM Flex System Fabric EN4093/EN2092 Scalable Switch",
"enterprises.26543.1.7.1" => "(BNT)IBM Networking Operating System RackSwitch G8000-RS",
"enterprises.26543.1.7.4" => "(BNT)IBM Networking Operating System RackSwitch G8124",
"enterprises.26543.1.7.6" => "(BNT)IBM Networking Operating System RackSwitch G8264",
"enterprises.26543.1.7.7" => "(BNT)IBM Networking Operating System RackSwitch G8052",
"enterprises.26543" => "BNT",
"enterprises.33049.1.1.1.6036" => "IBM Mellanox Switch SX6036",
"enterprises.33049.1.1.1.6512" => "IBM Mellanox Switch SX6512",
"enterprises.33049.2.1" => "IBM Mellanox Switch IB6131",
"enterprises.33049" => "IBM Mellanox Switch"
Mellanox => "Mellanox",
mellanox => "Mellanox",
MLNX => "Mellanox",
MELLAN => "Mellanox",
IBM => "BNT",
);
@ -433,7 +423,7 @@ sub process_request {
if (!$display_done) {
#display header
$format = "%-12s\t%-18s\t%-20.20s\t%-12s";
$format = "%-12s\t%-15s\t%-40.50s\t%-12s";
$header = sprintf $format, "ip", "name","vendor", "mac";
send_msg(\%request, 0, $header);
my $sep = "------------";
@ -712,10 +702,6 @@ sub nmap_scan {
$counter++;
}
my $vendor = $addr->{vendor};
# run snmpwalk command to find vendor
if (!$vendor) {
$vendor = get_vendorinfo($request, $ip);
}
if ($vendor) {
my $search_string = join '|', keys(%global_switch_type);
if ($vendor =~ /($search_string)/) {
@ -818,17 +804,98 @@ sub nmap_scan {
#--------------------------------------------------------------------------------
sub snmp_scan {
my $request = shift;
my $ccmd;
my $switches;
my $counter = 0;
my @iplists = ();
send_msg($request, 0, "Discovering switches using snmp is not supported yet.");
my $switches = {
"AABBCCDDEEFA" =>{name=>"switch1", vendor=>"ibm", ip=>"10.1.2.3"},
"112233445566" =>{name=>"switch2", vendor=>"cisco", ip=>"11.4.5.6"}
};
return 1;
if (-x "/usr/bin/snmpwalk" ){
send_msg($request, 0, "Discovering switches using snmpwalk.....");
} else {
send_msg($request, 0, "snmpwalk is not available, please install snmpwalk command first");
return 1;
}
#################################################
# If --range options, take iprange, if noderange is defined
# us the ip addresses of the nodes. If none is define, use the
# subnets for all the interfaces.
##################################################
my $ranges = get_ip_ranges($request);
#push each ip to ip list (need better code?)
foreach my $ips (@$ranges) {
#process ip address 1.2.3.4-5 format
if ($ips =~ /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\-(\d+)$/) {
my $startip = "$1.$2.$3.$4";
my $endip = "$1.$2.$3.$5";
my $iplist = xCAT::NetworkUtils->get_allips_in_range($startip, $endip, 1);
foreach (@$iplist) {
push (@iplists, $_);
}
}
#process ip address 1.2.3-4.5 format
if ($ips =~ /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\-(\d{1,3})\.(\d{1,3})$/) {
my $beginip = $3;
my $endip = $4;
while ( $beginip <= $endip ) {
my $tip = "$1.$2.$beginip.$5";
push (@iplists, $tip);
$beginip++;
}
}
#process ip address 1.2-3.4.5 format
if ($ips =~ /^(\d{1,3})\.(\d{1,3})\-(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/) {
my $beginip = $2;
my $endip = $3;
while ( $beginip <= $endip ) {
my $tip = "$1.$beginip.$4.$5";
push (@iplists, $tip);
$beginip++;
}
}
#process ip address 1.2.3.4/24 format
if ($ips =~ /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\/(\d+)$/) {
my ($startip, $mask) = split '/', $ips;
$mask = xCAT::NetworkUtils::formatNetmask($mask, 1, 0);
my $endip = xCAT::NetworkUtils->getBroadcast($startip, $mask);
my $iplist = xCAT::NetworkUtils->get_allips_in_range($startip, $endip, 1);
foreach (@$iplist) {
push (@iplists, $_);
}
}
#process single ip address 1.2.3.4
if ($ips =~ /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/) {
push (@iplists, $ips);
}
}
foreach my $ip (@iplists) {
my $vendor = get_snmpvendorinfo($request, $ip);
if ($vendor) {
my $hostname;
my $mac = get_snmpmac($request, $ip);
if (!$mac) {
$mac="nomac_nmap_$counter";
$counter++;
}
$hostname = get_snmphostname($hostname, $ip);
my $stype = get_switchtype($vendor);
$switches->{$mac}->{ip} = $ip;
$switches->{$mac}->{vendor} = $vendor;
$switches->{$mac}->{name} = $hostname;
if (exists($globalopt{verbose})) {
send_msg($request, 0, "found switch: $hostname, $ip, $stype, $vendor");
}
}
}
return $switches;
}
#--------------------------------------------------------------------------------
=head3 get_vendorinfo
=head3 get_snmpvendorinfo
return vendor info from snmpwalk command
Arguments:
ip : IP address passed by the switch after scan
@ -836,24 +903,13 @@ sub snmp_scan {
vendor: vendor info of the switch
=cut
#--------------------------------------------------------------------------------
sub get_vendorinfo {
sub get_snmpvendorinfo {
my $request = shift;
my $ip = shift;
my $snmpwalk_vendor;
if (-x "/usr/bin/snmpwalk" ){
if (exists($globalopt{verbose})) {
send_msg($request, 0, "Discovering switch vendor using snmpwalk.....");
}
} else {
if (exists($globalopt{verbose})) {
send_msg($request, 0, "snmpwalk is not available, please install snmpwalk command for better results");
}
return $snmpwalk_vendor;
}
my $ccmd = "snmpwalk -Os -v1 -c public $ip system | grep enterprises";
my $ccmd = "snmpwalk -Os -v1 -c public $ip sysDescr.0";
if (exists($globalopt{verbose})) {
send_msg($request, 0, "Process command: $ccmd\n");
}
@ -867,28 +923,91 @@ sub get_vendorinfo {
return $snmpwalk_vendor;
}
my ($desc,$oid) = split /: /, $result;
my $key;
my ($desc,$model) = split /: /, $result;
if (exists($globalopt{verbose})) {
send_msg($request, 0, "oid = $oid\n" );
}
my $search_string = join '|', keys(%global_OID_model_metrix);
if ($oid =~ /($search_string)/) {
$key = $1;
$snmpwalk_vendor = $global_OID_model_metrix{$key};
if (exists($globalopt{verbose})) {
send_msg($request, 0, "find vendor = $snmpwalk_vendor from snmpwalk command\n");
}
} else {
if (exists($globalopt{verbose})) {
send_msg($request, 0, "Couldn't find vendor from snmpwalk command\n");
}
send_msg($request, 0, "switch model = $model\n" );
}
return $snmpwalk_vendor;
return $model;
}
#--------------------------------------------------------------------------------
=head3 get_snmpmac
return mac address from snmpwalk command
Arguments:
ip : IP address passed by the switch after scan
Returns:
mac: mac address of the switch
=cut
#--------------------------------------------------------------------------------
sub get_snmpmac {
my $request = shift;
my $ip = shift;
my $mac;
my $ccmd = "snmpwalk -Os -v1 -c public $ip ipNetToMediaPhysAddress | grep $ip";
if (exists($globalopt{verbose})) {
send_msg($request, 0, "Process command: $ccmd\n");
}
my $result = xCAT::Utils->runcmd($ccmd, 0);
if ($::RUNCMD_RC != 0)
{
if (exists($globalopt{verbose})) {
send_msg($request, 1, "Could not process this command: $ccmd" );
}
return $mac;
}
my ($desc,$mac) = split /: /, $result;
if (exists($globalopt{verbose})) {
send_msg($request, 0, "switch mac = $mac\n" );
}
return $mac;
}
#--------------------------------------------------------------------------------
=head3 get_snmphostname
return hostname from snmpwalk command
Arguments:
ip : IP address passed by the switch after scan
Returns:
mac: hostname of the switch
=cut
#--------------------------------------------------------------------------------
sub get_snmphostname {
my $request = shift;
my $ip = shift;
my $hostname;
my $ccmd = "snmpwalk -Os -v1 -c public $ip sysName";
if (exists($globalopt{verbose})) {
send_msg($request, 0, "Process command: $ccmd\n");
}
my $result = xCAT::Utils->runcmd($ccmd, 0);
if ($::RUNCMD_RC != 0)
{
if (exists($globalopt{verbose})) {
send_msg($request, 1, "Could not process this command: $ccmd" );
}
return $hostname;
}
my ($desc,$hostname) = split /: /, $result;
if (exists($globalopt{verbose})) {
send_msg($request, 0, "switch hostname = $hostname\n" );
}
return $hostname;
}
#--------------------------------------------------------------------------------
=head3 get_hostname
return hostname for the switch discovered
@ -897,34 +1016,14 @@ sub get_vendorinfo {
ip : IP address passed by the switch after scan
Returns:
host: hostname of the switch
if host is empty, try to lookup use snmpwalk command or ip address,
otherwise format hostname as switch and ip combination. ex: switch-9-114-5-6
if host is empty, try to lookup use ip address, otherwise format hostname
as switch and ip combination. ex: switch-9-114-5-6
=cut
#--------------------------------------------------------------------------------
sub get_hostname {
my $host = shift;
my $ip = shift;
if ($host) {
return $host;
}
# run snmpwalk to get hostname
my $ccmd = "snmpwalk -Os -v1 -c public $ip system | grep sysName";
if (exists($globalopt{verbose})) {
send_msg($request, 0, "Process command: $ccmd\n");
}
my $result = xCAT::Utils->runcmd($ccmd, 0);
if ($::RUNCMD_RC != 0)
{
if (exists($globalopt{verbose})) {
send_msg($request, 1, "Could not process this command: $ccmd" );
}
}
my ($desc,$host) = split /: /, $result;
if ( !$host ) {
$host = gethostbyaddr( inet_aton($ip), AF_INET );
if ( !$host ) {