image

Всем привет!

За последние годы мы привыкли что можно и нужно все мониторить, множество инструментов начиная от простых логов, заканчивая Zabbix и все можно связать. Microsoft в свою очередь тоже дала нам отличный инструмент WinRM, с помощью которого мы можем отслеживать состояние операционных систем и не только. Но как всегда есть ложка дегтя, собственно об «обходе» этой ложки дегтя и пойдет речь.

Как выше было сказано, мы имеем все необходимые инструменты для мониторинга IT структуры, но так сложилось что мы не имеем «автоматизированный» инструмент для мониторинга состояния Intel raid массивов в Windows core. Обращаю Ваше внимание на то, что речь идет об обычном «желтом железе».

Все мы знаем что есть софт от Intel, rapid и matrix storage, но к сожалению на стандартном Windows core он не работает, также есть утилита raidcfg32, она работает в режиме командной строки, умеет обслуживать в ручном режиме и показывать статус, тоже в ручном режиме. Думаю Америку не для кого не открыл.

Постоянно в ручном режиме проверять состояние raid или ждать выхода из строя сервера виртуализации не самый лучший выбор.

Для реализации коварного плана по автоматизации мониторинга Intel raid мы используем
основные инструменты:

  • Powershell
  • EventLog
  • Raidcfg32.exe
  • Вспомогательные:
  • WinRM
  • Rsyslog
  • LogAnalyzer

Первым делом нужно установить драйвер для raid контроллера:
cmd.exe pnputil.exe -i -a [путь до *.inf]

Копируем raidcfg32.exe в c:\raidcfg32\

Проверяем корректно ли установлен драйвер:
cmd.exe C:\raidcfg32\raidcfg32.exe /stv

Если получаем состояние raid и дисков, то все ок.

Создаем источник в журнале application:

*Дальше все выполняется в powershell

New-EventLog -Source "RAID" -LogName "Application"

Выполняем запрос состояния raid, удаляем кавычки для упрощения парсинга, подключаем содержимое файла.

c:\RAIDCFG32\RAIDCFG32.exe /stv > c:\RAIDCFG32\raidcfgStatus.txt
Get-Content "c:\RAIDCFG32\raidcfgStatus.txt" | ForEach-Object {$_ -replace ('"'),' '} > c:\RAIDCFG32\raidstatus.txt
$1 = Get-Content c:\RAIDCFG32\raidstatus.txt
$2 = "$1"

Ищем ключевые слова, если одно из слов ниже будет найдено, то в файле errorRAID.txt появится значение true, это будет говорить о наличии ошибки, если совпадений не найдено, то будет записано значение false.

$2 -match "failed" > c:\RAIDCFG32\errorRAID.txt
$2 -match "disabled" >> c:\RAIDCFG32\errorRAID.txt
$2 -match "degraded" >> c:\RAIDCFG32\errorRAID.txt
$2 -match "rebuild" >> c:\RAIDCFG32\errorRAID.txt
$2 -match "updating" >> c:\RAIDCFG32\errorRAID.txt
$2 -match "critical" >> c:\RAIDCFG32\errorRAID.txt

Подключаем файл с записаными true и false, ищем в файле true, если true найдено то заменяем его на Error, заменяем false на Information.

Записывам результат в EntryType.txt

$3 = Get-Content c:\RAIDCFG32\errorRAID.txt
$4 = "$3"
$5 = $4 -match "true"
$6 = "$5"
$7 = $6 -replace "true", "Error" > c:\RAIDCFG32\EntryType.txt
$8 = $6 -replace "false", "Information" >> c:\RAIDCFG32\EntryType.txt

Подключаем содержимое файла EntryType.txt и удаляем в нем False, тем самым выводим корректный -EntryType что в свою очередь и является «Уровнем» сообщения.

Записываем в EventLog сообщение, где в случае если будут найдены ключевые слова, уровень сообщения будет Error, если не будут найдены, то Information.

$9 = Get-Content c:\RAIDCFG32\EntryType.txt
$10 = "$9"
$11 = $10 -replace "False"
Write-EventLog -LogName Application -Source "RAID" -EventID 9999 -EntryType "$11" -Message "$1"
exit

Сохраняем код в *.ps1

Создаем в планировщике задание на запуск скрипта, я запускаю задание 1 раз в сутки и при каждой загрузке.

Если будет производится сбор логов другой Windows ОС в Eventlog, то на коллекторе логов необходимо создать источник «RAID», пример есть выше.

Мы транспортируем логи в rsyslog через Adison rsyslog для Windows.

На выходе получается вот такая картинка:

image

Скрипт без комментариев
c:\RAIDCFG32\RAIDCFG32.exe /stv > c:\RAIDCFG32\raidcfgStatus.txt
Get-Content "c:\RAIDCFG32\raidcfgStatus.txt" | ForEach-Object {$_ -replace ('"'),' '} > c:\RAIDCFG32\raidstatus.txt
$1 = Get-Content c:\RAIDCFG32\raidstatus.txt
$2 = "$1"
$2 -match "failed" > c:\RAIDCFG32\errorRAID.txt
$2 -match "disabled" >> c:\RAIDCFG32\errorRAID.txt
$2 -match "degraded" >> c:\RAIDCFG32\errorRAID.txt
$2 -match "rebuild" >> c:\RAIDCFG32\errorRAID.txt
$2 -match "updating" >> c:\RAIDCFG32\errorRAID.txt
$2 -match "critical" >> c:\RAIDCFG32\errorRAID.txt
$3 = Get-Content c:\RAIDCFG32\errorRAID.txt
$4 = "$3"
$5 = $4 -match "true"
$6 = "$5"
$7 = $6 -replace "true", "Error" > c:\RAIDCFG32\EntryType.txt
$8 = $6 -replace "false", "Information" >> c:\RAIDCFG32\EntryType.txt
$9 = Get-Content c:\RAIDCFG32\EntryType.txt
$10 = "$9"
$11 = $10 -replace "False"
Write-EventLog -LogName Application -Source "RAID" -EventID 9999 -EntryType "$11" -Message "$1"

Комментарии (5)


  1. AcidVenom
    01.11.2017 18:30
    +1

    Storage Spaces не используете?


  1. VitalKoshalew
    01.11.2017 21:00

    А зачем вы вынесли каталог с исполняемым файлом из-под защищённого Mandatory Integrity Control C:\Program Files (x86) в корень?


  1. yosemity
    02.11.2017 00:45

    Если я правильно понял, то проверка состояния массива раз в сутки — не лучший выбор.


    1. AcidVenom
      02.11.2017 08:36

      Если я правильно понял, ротация лог-файла настроена раз в сутки. А вообще непонятно, почему с работающим Заббиксом люди пилят такие решения. Через LLD, Storage Spaces и PS решается очень быстро

      Заголовок спойлера
      # 2017/03/07 AcidVenom v1
      # Скрипт для обнаружения пулов Storage Spaces (Windows) для Zabbix
      param($1,$2)
      
      # Автообнарежение пулов без Primordial
      # Ключи: discovery 
      if ($1 -eq "discovery") {
      try {
      $items = Get-StoragePool -IsPrimordial $false
      write-host -NoNewline "{"
      write-host -NoNewline "`"data`":["
      
      $n = 0
      foreach ($obj in $items) {
       $n = $n + 1
       $line =  "{`"{#NAME}`":`"" + $obj.FriendlyName + "`", `"{#TYPE}`":`"" + $obj.ResiliencySettingNameDefault + "`", `"{#ID}`":`"" + $obj.UniqueId + "`"}"
       If ($n -lt $items.Count) { $line = "$line,"}
       write-host -NoNewline $line
      }
      
      write-host -NoNewline "]"
      write-host -NoNewline "}"
      
      } 
      catch {exit}
      }
      # Запрос значения от discovery
      # 
      else {
          $obj = (Get-StoragePool -UniqueId "$1").$2
          Write-Host -NoNewline $obj
      }


  1. ol_x
    02.11.2017 08:59

    можно было бы обойтись старым добрым snmp