25.02.2015

Скрипт для выявления порта свитча по маку

Имеем сеть с кучей управляемых свитчей, подключенных к одному корневому и друг к другу с включенным STP. Необходимо найти порт, к которому подключено устройство с известным нам MAC-адресом. Бегать по web-интерфейсам свитчей крайне напряжно, если маков больше 5.
Я использую систему мониторинга The Dude, которая умеет обходить устройства по SNMP и вываливать необходимую инфу в csv. Поэтому с каждого свитча сливаем в csv таблицу FDB. Получаем подобное:
Flag,MAC,Port,Status
,00:03:0F:18:F1:6A,D-Link DGS-3120-48TC R3.10.B01 Port 43 on Unit 1 (43),learned
,00:0B:82:3E:27:C6,D-Link DGS-3120-48TC R3.10.B01 Port 2 on Unit 1 (2),learned
,00:0B:82:3E:27:C9,D-Link DGS-3120-48TC R3.10.B01 Port 10 on Unit 2 (74),learned
,00:0C:29:BD:81:53,D-Link DGS-3120-48TC R3.10.B01 Port 5 on Unit 1 (5),learned
,00:11:BE:00:0F:34,D-Link DGS-3120-48TC R3.10.B01 Port 13 on Unit 1 (13),learned

У меня один корневой свитч (его FDB я обозвал FDB21.csv) и несколько коммутаторов на уровне доступа (все остальные .csv). Я знаю к каким портам корневого подключены остальные коммутаторы. Писал на PowerShell, так как считаю его довольно удобным и мощным и хочу научиться использовать его. Собственно скрипт:

$path = "d:\scripts\FDB\"
$rootDB = "FDB21.csv"
$sport = ("D-Link DGS-3120-48TC R3.10.B01 Port 1 on Unit 1 (1)", "D-Link DGS-3120-48TC R3.10.B01 Port 2 on Unit 1 (2)", "D-Link DGS-3120-48TC R3.10.B01 Port 5 on Unit 1 (1)", "D-Link DGS-3120-48TC R3.10.B01 Port 12 on Unit 1 (12)", "D-Link DGS-3120-48TC R3.10.B01 Port 13 on Unit 1 (13)", "D-Link DGS-3120-48TC R3.10.B01 Port 14 on Unit 1 (14)", "D-Link DGS-3120-48TC R3.10.B01 Port 43 on Unit 1 (43)", "D-Link DGS-3120-48TC R3.10.B01 Port 44 on Unit 1 (44)", "D-Link DGS-3120-48TC R3.10.B01 Port 1 on Unit 2 (65)", "D-Link DGS-3120-48TC R3.10.B01 Port 2 on Unit 2 (66)", "D-Link DGS-3120-48TC R3.10.B01 Port 10 on Unit 2 (74)", "D-Link DGS-3120-48TC R3.10.B01 Port 43 on Unit 2 (107)")
$swDB = ("FDB42.csv", "FDB44.csv", "FDB61.csv", "FDB52.csv", "FDB51.csv", "FDB12.csv", "FDB33.csv", "FDB32.csv", "FDB41.csv", "FDB43.csv", "FDB11.csv", "FDB34.csv")

function findinarr ($array, $value) {
    for ($i=0; $i -lt $array.count;$i++) { 
        if($array[$i] -eq $value){$i}
    }
}

$dataRoot = Import-CSV -path $path$rootDB | Select-Object MAC, Port
$mac = Read-Host "Enter MAC"
foreach ($S in $dataRoot)
{
if ($mac -eq $s.mac)
{
$portRoot = $s.port
}
}

$A = findinarr $sport $portRoot

$datasw = Import-CSV -path $path$swDB[$A] | Select-Object MAC, Port
foreach ($S in $datasw)
{
if ($mac -eq $s.mac)
{
$port = $s.port
}
}
Write-Host $mac on $port

Разбор по строкам:
$path = "d:\scripts\FDB\" - указываем путь к папке с .csv

$rootDB = "FDB21.csv" - FDB с корневого коммутатора. По нему ищем с самого начала и на основе найденного порта переходим к следующему коммутатору.

$sport - строковый массив из названий портов в csv.

$swDB - массив из названий файлов, содержащих информацию о соответствии MAC-порт. Массивы sport и swDB должны иметь однозначное соответствие! В моем случае к Port 1 on Unit 1 подключен коммутатор sw42, следовательно, если нашли MAC на первом порту первого юнита, то дальше будем искать в файле FDB42.csv, где находится база sw42. И так далее.

function findinarr позаимствована у Вадима Поданса, который в свою очередь позаимствовал её у Василия Гусева. Это матерые пауэршэльщики, советую почитать их блоги. Функция находит индекс искомого элемента в массиве.

В переменную $dataRoot считываем csv с корневого коммутатора. Причем забираем только параметры MAC и Port - остальные нас не интересуют.

$mac = Read-Host "Enter MAC" - вводим искомый мак.

foreach ($S in $dataRoot) - ищем в массиве MAC-Port наш MAC-адрес. Если находим, то запоминаем порт.

$A = findinarr $sport $portRoot - ищем индекс найденного порта в массиве sport.

$datasw = Import-CSV -path $path$swDB[$A] | Select-Object MAC, Port - полученный в предыдущем шаге индекс подставляем в swDB и находим в нем имя следующего обрабатываемого файла. Этот файл считываем в переменную datasw, которую далее обрабатываем точно так же, как и dataRoot.


Не претендую на правильность скрипта, но у меня оно работает. Написал за неполный рабочий день будучи полнейшим нулем в PowerShell и 0,1 в программировании. Теперь нужно избавиться от csv и прикрутить опрос свитчей по SNMP прямо из скрипта.

Комментариев нет:

Отправить комментарий