Вступление от HP: эта публикация написана одним из наших заказчиков, который по долгу службы пожелал остаться анонимным. Все совпадения имён и айпишников считать случайными. Попробовать сделать то же самое можно в любое время в нашем демо-центре в Москве — желающих просим писать в комментарии.

Приветствую. Меня зовут Эдуард, и я системный администратор в небольшой компании, которая аутсорсит администрирование ИТ-инфраструктуры. Кхм… Уже похоже на клуб анонимных кого-то с проблемами? Ну да ладно, одна интересная проблема у нас действительно была, а сегодня мы расскажем, как мы с ней столкнулись, и как случайно её решили.


Для начала немного предыстории. Все же помнят, как весело было админить удалённое железо раньше, лет 5-8 назад? Пишем заявку инженерам в ДЦ, ждём, когда они подключат KVM, настраиваем BIOS/CMOS, выставляем загрузку по сети, ставим систему (это хорошо, если кто-то добрый уже написал генератор preseed/kickstart-файлов, и в ДЦ есть DHCP/PXE сервер). А потом у нас на всех серверах появился ipmi (ну со временем). Ох, как мы радовались первое время!

ipmitool -U user -P password power up -H XXX
ipmitool -U user -P password password bootdev pxe -H XXX
ipmitool -U user -P password power reset -H XXX

И сервер уже вроде бы ставит ОС. Остаётся только наблюдать за этим в консоли, если скучно. Огорчало только то, что BIOS всё равно приходилось обновлять руками и настраивать (ну там HT/VT-d включить, хотя бы). В итоге все серверы были настроены по-разному, в зависимости от того, в каком квартале их ставили. Ну вы же понимаете, что серверы всегда ставил самый младший админ.

Когда мы находили что-то критичное – мы шли и руками переключали настройки. Бардак, да и только. Но вообще всё это нас устраивало до того, как с нами случилась история, о которой я сегодня и буду рассказывать.

Стоит упомянуть, что часть клиентов мы размещаем прямо на своём железе (точнее на виртуалках на этом железе, которое рулится через <зачеркнуто печатью с большими буквами NDA>). Ну чтобы вам было легче представить – наша система сильно похожа на OpenStack. И вот, в один прекрасный день, к нам пришел заказчик и попросил «на его железе сделать систему для управления виртуальными машинами в приватном облаке». Мы обрадовались, начали ему показывать своё решение (уже после подписания контракта и ТЗ), ему всё понравилось. Всё понравилось, менеджеры уже открывают шампанское (а надо сказать, что контракт по нашим меркам был очень неплохой). И тут клиент показывает пальцем в пункт ТЗ и спрашивает – «а с этим как?». Сидят админы и недоуменно смотрят в этот пункт – «новые серверы должны автоматически добавляться в облако после инвентаризации, установки в стои?ку и подключения сети-питания». Мы начали показывать – вот смотрите, мы записываем сервер сюда (1c), добавляем его mac-адрес вот сюда (самописная web-морда для управления dhcp-сервером и pxe), запускаем скрипт, сервер загружается по сети, система ставится (мы с облегчением выдохнули, поняв, что хотя бы система ставится сама), потом мы ловим сервер при перезагрузке, усиленно жмем клавишу Del… В общем, представитель клиента посмотрел на это, почесал затылок, походил по переговорке, собрался с мыслями и произнес: «Да где ж тут автоматически? Вот даваи?те выкинем все?, кроме 1С, все? равно туда бухгалтеры сервер вносить будут, а не я, и того места, куда вы mac-адрес записывали». Ну и вскоре после этого ушел, добавив, что надеется на то, что задачу мы всё же решим.

Потом мы, как обычно, ТЗ решили прочитать. Нашли там всякие интересные пункты, которые мы (ну те, кто делал задачу, а не те, кто ТЗ подписывал и пересказывал его нам) увидели впервые. Например, мониторинг температуры в обход ОС, мониторинг потребления электричества, автоматическая настройка BIOS… Начали размышлять. Сначала склонялись к мысли, что ipmitool всё это может. Потом представили, как всё это будет выглядеть. Подумали про то, как обновлять настройки, про мониторинг датчиков… В общем, разошлись на выходные с задачей «изучить весь гугл на предмет альтернатив ipmi, которые могут».

Приходим в понедельник, все грустные, злые. А один админ сидит и улыбается. Логичным было пристать к нему с расспросами на тему того, зачем он читает ithappens, когда у нас такая беда. Как оказалось, радовался он по поводу того, что читал не ithappens, а Redfish server management spec v 1.0 (читать здесь). Почитали все вместе вслух, злиться перестали. Redfish оказался именно тем, что нам нужно. Взяли менеджера, заставили его обзванивать всех производителей серверов, чтобы найти железку, в которой Redfish реализован. Приходят через час и смеется, показывает пальцем на коробку у входа и говорит «все?, я нашел». Собственно, коробка оказалась коробкой от HP Proliant Gen9. Сервер мы нашли, вернули в лабораторию (и кто вообще догадался новенький неизученный сервер сразу в ДЦ везти…) и приступили к знакомству с HP REST API (которая и является реализацией Redfish в серверах HP).

Так как мы админы (это потом уже нам дали питониста и он нам всё написал и сделал красивый web-интерфейс), то первым делом мы сели писать sh-ники, которые будут делать то, что нам нужно. Конечно, мы бы не советовали ходить в Rest API консольным curl-ом и генерировать JSON через echo (ну или хотя бы потом не показывайте никому это), но вот поделиться примерами взаимодействия с HP ProLiant REST API будем рады (тем более, что сами представители HP нас об этом и попросили).

Возможностей там полно на самом деле, в документации 2 сотни страниц списка объектов и краткого их описания. Мы первым делом пытались выполнить свои основные задачи, как proof-of-concept. Конечно, часть из них можно делать и через IPMI, но мы решили использовать один инструмент, именно API.

Первым делом (ну хорошо, вторым, после подключения сервера в стойке и после того, как HP iLO получит IP-адрес), прописываем все настройки BIOS:

# echo '{"AcpiRootBridgePxm":"Enabled","AcpiRtcSupport":"Disabled","AcpiSlit":"Enabled","AdjSecPrefetch":"Enabled","AdminEmail":"","AdminName":"","AdminOtherInfo":"","AdminPassword":"","AdminPhone":"","AdvancedMemProtection":"AdvancedEcc","AsrStatus":"Enabled","AsrTimeoutMinutes":"10","AssetTagProtection":"Unlocked","AttributeRegistry":"HpBiosAttributeRegistryP86.1.1.0","AutoPowerOn":"RestoreLastState","BootMode":"LegacyBios","BootOrderPolicy":"RetryIndefinitely","ChannelInterleaving":"Enabled","CollabPowerControl":"Enabled","ConsistentDevNaming":"LomsOnly","CustomPostMessage":"","DcuIpPrefetcher":"Enabled","DcuStreamPrefetcher":"Enabled","Description":"This is the Platform/BIOS Configuration (RBSU) Current Settings","Dhcpv4":"Enabled","DynamicPowerCapping":"Auto","DynamicPowerResponse":"Fast","EmbNicEnable":"Enabled","EmbSata1Enable":"Enabled","EmbSata2Enable":"Enabled","EmbVideoConnection":"Auto","EmbeddedDiagnostics":"Enabled","EmbeddedDiagsMode":"Auto","EmbeddedSata":"Raid","EmbeddedUefiShell":"Enabled","EmsConsole":"Disabled","EnergyPerfBias":"BalancedPerf","EraseUserDefaults":"No","ExtendedAmbientTemp":"Disabled","ExtendedMemTest":"Disabled","F11BootMenu":"Enabled","FanFailPolicy":"Shutdown","FanInstallReq":"EnableMessaging","HwPrefetcher":"Enabled","IntelDmiLinkFreq":"Auto","IntelPerfMonitoring":"Disabled","IntelProcVtd":"Enabled","IntelQpiFreq":"Auto","IntelQpiPowerManagement":"Enabled","IntelTxt":"Disabled","IntelligentProvisioning":"Enabled","Ipv4Address":"0.0.0.0","Ipv4Gateway":"0.0.0.0","Ipv4PrimaryDNS":"0.0.0.0","Ipv4SecondaryDNS":"0.0.0.0","Ipv4SubnetMask":"0.0.0.0","MaxMemBusFreqMHz":"Auto","MaxPcieSpeed":"MaxSupported","MemFastTraining":"Enabled","MinProcIdlePkgState":"C6Retention","MinProcIdlePower":"C6","MixedPowerSupplyReportngi":"Enabled","Modified":"2015-02-12T20:16:59+00:00","Name":"BIOS Current Settings","NetworkBootRetry":"Enabled","NicBoot1":"NetworkBoot","NicBoot2":"Disabled","NmiDebugButton":"Enabled","NodeInterleaving":"Disabled","OldAdminPassword":"","OldPowerOnPassword":"","PciBusPadding":"Enabled","PostF1Prompt":"Delayed20Sec","PowerButton":"Enabled","PowerOnDelay":"None","PowerOnLogo":"Enabled","PowerOnPassword":"","PowerProfile":"BalancedPowerPerf","PowerRegulator":"DynamicPowerSavings","PreBootNetwork":"EmbNic","ProcCoreDisable":0,"ProcHyperthreading":"Enabled","ProcNoExecute":"Enabled","ProcTurbo":"Enabled","ProcVirtualization":"Disabled","ProcX2Apic":"Enabled","ProductId":"777424-AA1","QpiBandwidthOpt":"Balanced","QpiSnoopConfig":"Standard","RedundantPowerSupply":"BalancedMode","RemovableFlashBootSeq":"ExternalKeysFirst","RestoreDefaults":"No","RestoreManufacturingDefaults":"No","RomSelection":"CurrentRom","SataSecureErase":"Disabled","SaveUserDefaults":"No","SecureBoot":"Disabled","SerialConsoleBaudRate":"115200","SerialConsoleEmulation":"Vt100Plus","SerialConsolePort":"Auto","SerialNumber":"8CW4340081","ServerAssetTag":"","ServerName":"","ServerOtherInfo":"","ServerPrimaryOs":"","ServiceEmail":"","ServiceName":"","ServiceOtherInfo":"","ServicePhone":"","SettingsResult":{"ETag":"","Messages":[{"MessageArgs":[],"MessageID":"Base.1.0:Success"}],"Time":""},"Sriov":"Enabled","ThermalConfig":"OptimalCooling","ThermalShutdown":"Enabled","TimeZone":"Utc0","TpmBinding":"Disabled","TpmOperation":"Disable","TpmState":"NotPresent","TpmType":"NoTpm","TpmVisibility":"Visible","Type":"HpBios.1.0.0","UefiOptimizedBoot":"Enabled","UefiPxeBoot":"Auto","UefiShellBootOrder":"Disabled","UefiShellStartup":"Disabled","UefiShellStartupLocation":"AttachedMedia","UefiShellStartupUri":"","UrlBootFile":"","Usb3Mode":"Auto","UsbBoot":"Enabled","UsbControl":"UsbEnabled","UtilityLang":"English","VideoOptions":"BothVideoEnabled","VirtualInstallDisk":"Disabled","VirtualSerialPort":"Com2Irq3","WakeOnLan":"Enabled","links":{"BaseConfigs":{"href":"/rest/v1/systems/1/bios/BaseConfigs"},"Boot":{"href":"/rest/v1/systems/1/bios/Boot"},"Mappings":{"href":"/rest/v1/systems/1/bios/Mappings"},"Settings":{"href":"/rest/v1/systems/1/bios/Settings"}}}' | curl -v -k -X PATCH https://Administrator:Password@192.168.2.250/rest/v1/systems/1/Bios/Settings -H "Content-Type: application/json" --data-binary @- ; echo


Научимся управлять питанием. Ребут «по кнопке»:

# echo '{"Action":"Reset","ResetType":"ForceRestart"}' | curl -v -k -X POST https://Administrator:Password@192.168.2.250/rest/v1/systems/1 -H "Content-Type: application/json" --data-binary @- ; echo

«Выдёргиваем кабель из розетки»:

# echo '{"Action":"Reset","ResetType":"ForceOff"}' | curl -v -k -X POST https://Administrator:Password@192.168.2.250/rest/v1/systems/1 -H "Content-Type: application/json" --data-binary @- ; echo

Включаем сервер:

# echo '{"Action":"Reset","ResetType":"On"}' | curl -v -k -X POST https://Administrator:Password@192.168.2.250/rest/v1/systems/1 -H "Content-Type: application/json" --data-binary @- ; echo

Отправляем инженера «нажать кнопку питания»:

# echo '{"Action":"Reset","ResetType":"PushPowerButton"}' | curl -v -k -X POST https://Administrator:D3BFF4AE@192.168.2.250/rest/v1/systems/1 -H "Content-Type: application/json" --data-binary @- ; echo

Спросим у сервера, кто он такой:

# curl -v -k -X GET https://Administrator:Password@192.168.2.250/rest/v1 -H "Content-Type: application/json"

{"Name":"HP RESTful Root Service","Oem":{"Hp":{"Manager":[{"DefaultLanguage":"en","FQDN":"ILO8CW4340081.","HostName":"ILO8CW4340081","Languages":[{"Language":"en","TranslationName":"English","Version":"2.02"}],"ManagerFirmwareVersion":"2.02","ManagerType":"iLO 4"}],"Sessions":{"CertCommonName":"ILO8CW4340081","KerberosEnabled":false,"LDAPAuthLicenced":false,"LDAPEnabled":false,"LocalLoginEnabled":true,"LoginFailureDelay":0,"LoginHint":{"Hint":"POST to /Sessions to login using the following JSON object:","HintPOSTData":{"Password":"password","UserName":"username"}},"SecurityOverride":true,"ServerName":""},"Type":"HpiLOServiceExt.0.9.5","links":{"Providers":{"href":"/rest/v1/Providers"}}}},"ServiceVersion":"0.9.5","Time":"2015-05-06T18:01:55Z","Type":"ServiceRoot.0.9.5","links":{"AccountService":{"href":"/rest/v1/AccountService"},"Chassis":{"href":"/rest/v1/Chassis"},"Managers":{"href":"/rest/v1/Managers"},"Registries":{"href":"/rest/v1/Registries"},"Schemas":{"href":"/rest/v1/Schemas"},"Sessions":{"href":"/rest/v1/Sessions"},"Systems":{"href":"/rest/v1/Systems"},"self":{"href":"/rest/v1/root"}}}

PATCH-запросом в эту же ручку можно изменить информацию о сервере внутри iLo.

Спросим MAC-адреса у сервера (да, в итоге мы пошли дальше и DHCP-сервер сам проводил инвентаризацию новых серверов, если находил незнакомый iLO в отдельном VLAN-е – для iLO мы выдавали динамические адрес, а потом уже заводили записи о статических адресах для сетевых карт сервера и интерфейса iLo):

# curl -v -k -X GET https://Administrator:Password@192.168.2.250/rest/v1/systems/1 -H "Content-Type: application/json"

{"AvailableActions":[{"Action":"Reset","Capabilities":[{"AllowableValues":["On","ForceOff","ForceRestart","Nmi","PushPowerButton"],"PropertyName":"ResetType"}]}],"Bios":{"Current":{"VersionString":"P86 v1.30 (09/04/2014)"}},"Boot":{"BootSourceOverrideEnabled":"Disabled","BootSourceOverrideSupported":["None","Floppy","Cd","Hdd","Usb","Utilities","Diags","BiosSetup","Pxe","UefiShell","UefiTarget"],"BootSourceOverrideTarget":"None","UefiTargetBootSourceOverride":"None","UefiTargetBootSourceOverrideSupported":["NIC.LOM.1.1.IPv4","NIC.LOM.1.1.IPv6"]},"Description":"Computer System View","HostCorrelation":{"HostMACAddress":["14:58:d0:d3:20:8e","14:58:d0:d3:20:8f"],"HostName":"","IPAddress":[""]},"IndicatorLED":"Off","Manufacturer":"HP","Memory":{"TotalSystemMemoryGB":32},"Model":"ProLiant DL120 Gen9","Name":"Computer System","Oem":{"Hp":{"AvailableActions":[{"Action":"PowerButton","Capabilities":[{"AllowableValues":["Press","PressAndHold"],"PropertyName":"PushType"},{"AllowableValues":["/Oem/Hp"],"PropertyName":"Target"}]}],"Bios":{"Backup":{"Date":"v1.30 (09/04/2014)","Family":"P86","VersionString":"P86 v1.30 (09/04/2014)"},"Bootblock":{"Date":"","Family":"P86","VersionString":"P86 "},"Current":{"Date":"09/04/2014","Family":"P86","VersionString":"P86 v1.30 (09/04/2014)"},"UefiClass":2},"PowerAllocationLimit":900,"PowerAutoOn":"Restore","PowerOnDelay":"Minimum","PowerRegulatorMode":"Dynamic","PowerRegulatorModesSupported":["OSControl","Dynamic","Max","Min"],"Type":"HpComputerSystemExt.0.10.0","VirtualUUID":null,"links":{"BIOS":{"href":"/rest/v1/systems/1/bios"},"PCIDevices":{"href":"/rest/v1/Systems/1/PCIDevices"},"PCISlots":{"href":"/rest/v1/Systems/1/PCISlots"},"SecureBoot":{"href":"/rest/v1/Systems/1/SecureBoot"}}}},"Power":"Off","Processors":{"Count":1,"ProcessorFamily":"Intel(R) Xeon(R) CPU E5-2660 v3 @ 2.60GHz"},"SKU":"777424-AA1","SerialNumber":"8CW4340081","Status":{"Health":"OK","State":"Disabled"},"SystemType":"Physical","Type":"ComputerSystem.0.9.5","UUID":"34373737-3432-4338-5734-333430303831","links":{"Chassis":[{"href":"/rest/v1/Chassis/1"}],"Manager":[{"href":"/rest/v1/Managers/1"}],"self":{"href":"/rest/v1/Systems/1"}}}

Из предыдущего JSON-а мы вытаскивали также и количество памяти с моделью CPU, потом разработчики сделали интеграцию с 1С, сервер отправлял данные о себе и туда. Здесь же мы определяли и версию BIOS, чтобы ругаться об устаревших (или просто отличающихся по кластеру) версиях.

Ещё через REST API можно снять показания метрик питания (к сожалению, не во всех «уровнях» лицензии iLO):

# curl -v -k -X GET https://Administrator:Password@192.168.2.250/rest/v1/chassis/1/PowerMetrics -H "Content-Type: application/json" 

Ещё мы нашли какую-то жуткую ручку, которая описывает состояние сервера – обороты вентилятора, температуру, состояние разных железок внутри сервера.

# curl -v -k -X GET https://Administrator:Password@192.168.1.235/rest/v1/Chassis/1/ThermalMetrics -H "Content-Type: application/json" 

{"Fans":[{"CurrentReading":33,"FanName":"Fan 1","Oem":{"Hp":{"Location":"System","Type":"HpServerFan.0.9.5"}},"Status":{"Health":"OK","State":"Enabled"},"Units":"Percent"},{"CurrentReading":33,"FanName":"Fan 2","Oem":{"Hp":{"Location":"System","Type":"HpServerFan.0.9.5"}},"Status":{"Health":"OK","State":"Enabled"},"Units":"Percent"},{"CurrentReading":33,"FanName":"Fan 3","Oem":{"Hp":{"Location":"System","Type":"HpServerFan.0.9.5"}},"Status":{"Health":"OK","State":"Enabled"},"Units":"Percent"},{"CurrentReading":33,"FanName":"Fan 4","Oem":{"Hp":{"Location":"System","Type":"HpServerFan.0.9.5"}},"Status":{"Health":"OK","State":"Enabled"},"Units":"Percent"},{"CurrentReading":33,"FanName":"Fan 5","Oem":{"Hp":{"Location":"System","Type":"HpServerFan.0.9.5"}},"Status":{"Health":"OK","State":"Enabled"},"Units":"Percent"},{"CurrentReading":33,"FanName":"Fan 6","Oem":{"Hp":{"Location":"System","Type":"HpServerFan.0.9.5"}},"Status":{"Health":"OK","State":"Enabled"},"Units":"Percent"}],"Name":"ThermalMetrics","Temperatures":[{"Context":"Ambient","CurrentReading":21,"LowerThresholdCritical":46,"LowerThresholdNonCritical":42,"Name":"01-Inlet Ambient","Oem":{"Hp":{"LocationXmm":11,"LocationYmm":0,"Type":"HpSeaOfSensors.0.9.5"}},"Status":{"Health":"OK","State":"Enabled"},"Units":"Celsius"},{"Context":"CPU","CurrentReading":40,"LowerThresholdCritical":0,"LowerThresholdNonCritical":70,"Name":"02-CPU 1","Oem":{"Hp":{"LocationXmm":7,"LocationYmm":9,"Type":"HpSeaOfSensors.0.9.5"}},"Status":{"Health":"OK","State":"Enabled"},"Units":"Celsius"},{"Context":"CPU","CurrentReading":40,"LowerThresholdCritical":0,"LowerThresholdNonCritical":70,"Name":"03-CPU 2","Oem":{"Hp":{"LocationXmm":12,"LocationYmm":9,"Type":"HpSeaOfSensors.0.9.5"}},"Status":{"Health":"OK","State":"Enabled"},"Units":"Celsius"},{"Context":"GPU","CurrentReading":27,"LowerThresholdCritical":0,"LowerThresholdNonCritical":87,"Name":"04-P1 DIMM 1-2","Oem":{"Hp":{"LocationXmm":10,"LocationYmm":10,"Type":"HpSeaOfSensors.0.9.5"}},"Status":{"Health":"OK","State":"Enabled"},"Units":"Celsius"},{"Context":"GPU","CurrentReading":0,"LowerThresholdCritical":0,"LowerThresholdNonCritical":87,"Name":"05-P1 DIMM 3-4","Oem":{"Hp":{"LocationXmm":5,"LocationYmm":10,"Type":"HpSeaOfSensors.0.9.5"}},"Status":{"State":"Absent"},"Units":"Celsius"},{"Context":"GPU","CurrentReading":28,"LowerThresholdCritical":0,"LowerThresholdNonCritical":87,"Name":"06-P2 DIMM 1-2","Oem":{"Hp":{"LocationXmm":14,"LocationYmm":10,"Type":"HpSeaOfSensors.0.9.5"}},"Status":{"Health":"OK","State":"Enabled"},"Units":"Celsius"},{"Context":"GPU","CurrentReading":0,"LowerThresholdCritical":0,"LowerThresholdNonCritical":87,"Name":"07-P2 DIMM 3-4","Oem":{"Hp":{"LocationXmm":11,"LocationYmm":10,"Type":"HpSeaOfSensors.0.9.5"}},"Status":{"State":"Absent"},"Units":"Celsius"},{"Context":"System Board","CurrentReading":0,"LowerThresholdCritical":0,"LowerThresholdNonCritical":60,"Name":"08-HD Max","Oem":{"Hp":{"LocationXmm":4,"LocationYmm":2,"Type":"HpSeaOfSensors.0.9.5"}},"Status":{"State":"Absent"},"Units":"Celsius"},{"Context":"System Board","CurrentReading":41,"LowerThresholdCritical":0,"LowerThresholdNonCritical":105,"Name":"09-Chipset","Oem":{"Hp":{"LocationXmm":7,"LocationYmm":13,"Type":"HpSeaOfSensors.0.9.5"}},"Status":{"Health":"OK","State":"Enabled"},"Units":"Celsius"},{"Context":"System Board","CurrentReading":40,"LowerThresholdCritical":0,"LowerThresholdNonCritical":0,"Name":"10-P/S 1","Oem":{"Hp":{"LocationXmm":1,"LocationYmm":14,"Type":"HpSeaOfSensors.0.9.5"}},"Status":{"Health":"OK","State":"Enabled"},"Units":"Celsius"},{"Context":"System Board","CurrentReading":0,"LowerThresholdCritical":0,"LowerThresholdNonCritical":0,"Name":"11-P/S 2","Oem":{"Hp":{"LocationXmm":2,"LocationYmm":14,"Type":"HpSeaOfSensors.0.9.5"}},"Status":{"State":"Absent"},"Units":"Celsius"},{"Context":"System Board","CurrentReading":30,"LowerThresholdCritical":120,"LowerThresholdNonCritical":115,"Name":"12-VR P1","Oem":{"Hp":{"LocationXmm":7,"LocationYmm":8,"Type":"HpSeaOfSensors.0.9.5"}},"Status":{"Health":"OK","State":"Enabled"},"Units":"Celsius"},{"Context":"System Board","CurrentReading":30,"LowerThresholdCritical":120,"LowerThresholdNonCritical":115,"Name":"13-VR P2","Oem":{"Hp":{"LocationXmm":12,"LocationYmm":8,"Type":"HpSeaOfSensors.0.9.5"}},"Status":{"Health":"OK","State":"Enabled"},"Units":"Celsius"},{"Context":"System Board","CurrentReading":26,"LowerThresholdCritical":120,"LowerThresholdNonCritical":115,"Name":"14-VR P1 Zone","Oem":{"Hp":{"LocationXmm":7,"LocationYmm":7,"Type":"HpSeaOfSensors.0.9.5"}},"Status":{"Health":"OK","State":"Enabled"},"Units":"Celsius"},{"Context":"System Board","CurrentReading":25,"LowerThresholdCritical":120,"LowerThresholdNonCritical":115,"Name":"15-VR P2 Zone","Oem":{"Hp":{"LocationXmm":12,"LocationYmm":7,"Type":"HpSeaOfSensors.0.9.5"}},"Status":{"Health":"OK","State":"Enabled"},"Units":"Celsius"},{"Context":"System Board","CurrentReading":26,"LowerThresholdCritical":120,"LowerThresholdNonCritical":115,"Name":"16-VR P1 Mem","Oem":{"Hp":{"LocationXmm":8,"LocationYmm":7,"Type":"HpSeaOfSensors.0.9.5"}},"Status":{"Health":"OK","State":"Enabled"},"Units":"Celsius"},{"Context":"System Board","CurrentReading":26,"LowerThresholdCritical":120,"LowerThresholdNonCritical":115,"Name":"17-VR P2 Mem","Oem":{"Hp":{"LocationXmm":13,"LocationYmm":7,"Type":"HpSeaOfSensors.0.9.5"}},"Status":{"Health":"OK","State":"Enabled"},"Units":"Celsius"},{"Context":"System Board","CurrentReading":0,"LowerThresholdCritical":0,"LowerThresholdNonCritical":60,"Name":"18-Storage Batt","Oem":{"Hp":{"LocationXmm":0,"LocationYmm":7,"Type":"HpSeaOfSensors.0.9.5"}},"Status":{"State":"Absent"},"Units":"Celsius"},{"Context":"System Board","CurrentReading":30,"LowerThresholdCritical":85,"LowerThresholdNonCritical":80,"Name":"19-iLO Zone","Oem":{"Hp":{"LocationXmm":12,"LocationYmm":13,"Type":"HpSeaOfSensors.0.9.5"}},"Status":{"Health":"OK","State":"Enabled"},"Units":"Celsius"},{"Context":"System Board","CurrentReading":30,"LowerThresholdCritical":105,"LowerThresholdNonCritical":100,"Name":"20-System Board","Oem":{"Hp":{"LocationXmm":7,"LocationYmm":14,"Type":"HpSeaOfSensors.0.9.5"}},"Status":{"Health":"OK","State":"Enabled"},"Units":"Celsius"},{"Context":"System Board","CurrentReading":28,"LowerThresholdCritical":105,"LowerThresholdNonCritical":100,"Name":"21-System Board","Oem":{"Hp":{"LocationXmm":11,"LocationYmm":13,"Type":"HpSeaOfSensors.0.9.5"}},"Status":{"Health":"OK","State":"Enabled"},"Units":"Celsius"},{"Context":"System Board","CurrentReading":24,"LowerThresholdCritical":127,"LowerThresholdNonCritical":126,"Name":"22-P/S Zone","Oem":{"Hp":{"LocationXmm":4,"LocationYmm":9,"Type":"HpSeaOfSensors.0.9.5"}},"Status":{"Health":"OK","State":"Enabled"},"Units":"Celsius"},{"Context":"System Board","CurrentReading":28,"LowerThresholdCritical":0,"LowerThresholdNonCritical":126,"Name":"23-System Board","Oem":{"Hp":{"LocationXmm":4,"LocationYmm":15,"Type":"HpSeaOfSensors.0.9.5"}},"Status":{"Health":"OK","State":"Enabled"},"Units":"Celsius"},{"Context":"System Board","CurrentReading":29,"LowerThresholdCritical":0,"LowerThresholdNonCritical":126,"Name":"24-System Board","Oem":{"Hp":{"LocationXmm":9,"LocationYmm":15,"Type":"HpSeaOfSensors.0.9.5"}},"Status":{"Health":"OK","State":"Enabled"},"Units":"Celsius"},{"Context":"System Board","CurrentReading":29,"LowerThresholdCritical":0,"LowerThresholdNonCritical":126,"Name":"25-System Board","Oem":{"Hp":{"LocationXmm":10,"LocationYmm":15,"Type":"HpSeaOfSensors.0.9.5"}},"Status":{"Health":"OK","State":"Enabled"},"Units":"Celsius"},{"Context":"Expansion Bay","CurrentReading":0,"LowerThresholdCritical":0,"LowerThresholdNonCritical":100,"Name":"26-PCI 1","Oem":{"Hp":{"LocationXmm":4,"LocationYmm":13,"Type":"HpSeaOfSensors.0.9.5"}},"Status":{"State":"Absent"},"Units":"Celsius"},{"Context":"Expansion Bay","CurrentReading":0,"LowerThresholdCritical":0,"LowerThresholdNonCritical":100,"Name":"27-PCI 2","Oem":{"Hp":{"LocationXmm":10,"LocationYmm":13,"Type":"HpSeaOfSensors.0.9.5"}},"Status":{"State":"Absent"},"Units":"Celsius"},{"Context":"Expansion Bay","CurrentReading":0,"LowerThresholdCritical":0,"LowerThresholdNonCritical":100,"Name":"28-PCI 3","Oem":{"Hp":{"LocationXmm":10,"LocationYmm":13,"Type":"HpSeaOfSensors.0.9.5"}},"Status":{"State":"Absent"},"Units":"Celsius"},{"Context":"Expansion Bay","CurrentReading":26,"LowerThresholdCritical":0,"LowerThresholdNonCritical":126,"Name":"29-PCI 1 Zone","Oem":{"Hp":{"LocationXmm":4,"LocationYmm":15,"Type":"HpSeaOfSensors.0.9.5"}},"Status":{"Health":"OK","State":"Enabled"},"Units":"Celsius"},{"Context":"Expansion Bay","CurrentReading":24,"LowerThresholdCritical":0,"LowerThresholdNonCritical":126,"Name":"30-PCI 2 Zone","Oem":{"Hp":{"LocationXmm":10,"LocationYmm":15,"Type":"HpSeaOfSensors.0.9.5"}},"Status":{"Health":"OK","State":"Enabled"},"Units":"Celsius"},{"Context":"Expansion Bay","CurrentReading":25,"LowerThresholdCritical":0,"LowerThresholdNonCritical":126,"Name":"31-PCI 3 Zone","Oem":{"Hp":{"LocationXmm":10,"LocationYmm":15,"Type":"HpSeaOfSensors.0.9.5"}},"Status":{"Health":"OK","State":"Enabled"},"Units":"Celsius"},{"Context":"Expansion Bay","CurrentReading":0,"LowerThresholdCritical":0,"LowerThresholdNonCritical":100,"Name":"32-LOM Card","Oem":{"Hp":{"LocationXmm":10,"LocationYmm":13,"Type":"HpSeaOfSensors.0.9.5"}},"Status":{"State":"Absent"},"Units":"Celsius"},{"Context":"Expansion Bay","CurrentReading":0,"LowerThresholdCritical":0,"LowerThresholdNonCritical":126,"Name":"33-I/O Board","Oem":{"Hp":{"LocationXmm":10,"LocationYmm":15,"Type":"HpSeaOfSensors.0.9.5"}},"Status":{"State":"Absent"},"Units":"Celsius"},{"Context":"System Board","CurrentReading":0,"LowerThresholdCritical":0,"LowerThresholdNonCritical":100,"Name":"34-LOM","Oem":{"Hp":{"LocationXmm":6,"LocationYmm":14,"Type":"HpSeaOfSensors.0.9.5"}},"Status":{"State":"Absent"},"Units":"Celsius"}],"Type":"ThermalMetrics.0.9.5","links":{"self":{"href":"/rest/v1/Chassis/1/ThermalMetrics"}}}

А ещё нашли объект, который говорит о состоянии сервера в целом (ОК/fail) и чем он сейчас занимается (в нашем примере он загружался):

# curl -v -k -X  GET https://Administrator:Password@192.168.1.235/rest/v1/Chassis/1 -H "Content-Type: application/json" 

...
"Status":{"Health":"OK","State":"Starting"}
...

В общем, sh-ник мы в итоге написали и отдали его разработчику. Он над нами посмеялся, мы его за это поругали, пригрозили рута отобрать… Но зато он потом написал модуль в наше облачко, который умеет добавлять и управлять серверами через Redfish (и HP REST API, соответственно). Ну а заказ мы в итоге выполнили.

Наверное, пора закругляться. Расскажем про тех, кто играл главные роли во всей это истории.

  • Конечно же, самую главную роль мы отведём серверу ProLiant DL60 Gen9;
  • Ещё хотелось бы сказать спасибо утилите hprest, strace-дамп которой помог понять нам, с какой стороны вообще к этой коробке подступиться из консоли;
  • Документация по HP Restfull API;
  • Python-ProLiant-SDK, который мы сразу не нашли, но который помог сделать production-решение поверх REST API;
  • Описание спецификации DMTF.org Redfish — как утверждает HP, во многом основанной на разработках собственных REST API для HP ProLiant
  • И, конечно же, компания HP, которая первой запустила в продажу серверы, поддерживающие Redfish, за что мы им и благодарны.

Спасибо за внимание!

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


  1. ildarz
    16.10.2015 15:42
    +1

    Я, наверное, в истории чего-то не понял, но, если у автора истории железо HP-шное, что помешало ему изначально прочитать iLO scripting guide, а не рыть интернет в поисках «альтернатив IPMI»? Или это история на тему «были сервера не-HP, потом мы открыли для себя HP, и наступило счастье»? :))


    1. evg_krsk
      16.10.2015 17:47
      +1

      Сначала контракт подписали, потом почитали, потом нашли, на чем делать. Всё как обычно.


  1. stychos
    16.10.2015 16:47

    Быстро прогресс идёт — всего пару (упс, уже десяток) лет назад для меня и wakeonlan оказался чудом и спасением, а теперь уже можно JSON'ами c железом общаться.


  1. fortyseven
    16.10.2015 21:15
    +1

    Просто оставлю это тут wiki.openstack.org/wiki/Ironic


    1. Tigger
      17.10.2015 15:34

      Ironic — это вещь очень хорошая, конечно — но это другое. Ironic'у нужны прослойки над «голым железом» — IPMI, например. И вот HP REST API — это идеальная прослойка:

      а) функциональность не устапает собственным проприетарным технолгиям HP
      б) в перспективе 3-5 лет уже все другие серверные вендоры (кроме самых гордых) тоже стандартизируются на Redfish. И тогда Ironic и другие подобные средства сильно выиграют в мультивендорных окружениях.


  1. blind_oracle
    16.10.2015 23:31
    +1

    К слову, народные железки Supermicro тоже поддерживают красную рыбу, но толку там не очень много, судя по всему. Настройки биоса через REST оно менять не умеет…


  1. kumbr_87
    17.10.2015 13:14

    Еще есть модуль для администрирования HP через Powershell, плюс еще можно поставить пак для администрирования корзин, настроить подключение к ним и также администрировать через PowerShell как сами корзины так и лезвия.


  1. BasilioCat
    19.10.2015 09:02

    Тоже был весьма удивлен тем, что утилита HP conrep (сохраняет и загружает настройки биоса) работает через /dev/ipmi0, а то я уж было собрался пароль на биос сбросить...
    Впрочем авторам этого увлекательного рассказа вполне хватило бы и проверенных средств для реалиции требований заказчика
    — все сервера втыкаются в сеть, ILO порты в отдельный коммутатор с DHCP
    — периодически запускается задача обнаружения новых IPMI адресов в сети
    — с найденных серверов получают MAC адрес первой сетевухи
    тут надо заметить, что получить мак-адреса можно даже с веб-интерфейса через curl для каких-нибудь кривых Etegro, а у Dell они отдаются и через freeipmi — ipmi-oem dell get-system-info mac-addresses
    — вносят MAC в DHCP, загружают сервер по PXE
    — прописывают настройки BIOS из ОС, а также конфигурируют RAID контроллеры, если их еще кто-то использует
    — ставят любимую ОС


    1. Tigger
      19.10.2015 11:00

      Конечно все это можно делать многими существующими средствами. Но согласитесь, что с открытыми API это выглядит гораздо красивее? И опять же — когда в будущем и другие вендоры поддержат это начинание с REST API, огромная масса вспомогательных утилит просто отомрет за ненадобностью.


      1. BasilioCat
        19.10.2015 11:37

        Когда все откажутся от использования раид-контроллеров, ну или к ним тоже приделают REST, тогда этап конфигурирования железа из ОС можно будет смело выкидывать. Да и vendor-lock никуда не девается даже в рамках стандарта IPMI