Сбор значения энергопотребления устройства
После формирования структуры проекта можно перейти к наполнению логикой операции по сбору значений энергопотребления устройства.
В данном разделе описана логика сбора информации в рамках этой системной операции.
Обзор операции
Данная операция отвечает за сбор данных энергопотребления целевого устройства по протоколу Redfish.
Для реализации операции, RPC будет иметь следующую сигнатуру:
rpc CollectPowerUsage(CollectBmcPowerUsageRequest) returns (CollectBmcPowerUsageResponse)
На вход модуль получает следующий запрос в формате Protocol buffers:
Тип CollectBmcPowerUsageRequest:
-
device:-
Тип параметра:
DeviceContent - Описание: Данные об устройстве.
-
Тип параметра:
-
metric_templates:-
Тип параметра:
repeated SystemMetricTemplate - Описание: Список шаблонов по сбору метрик.
-
Тип параметра:
Тип DeviceContent:
-
device_id:-
Тип параметра:
string - Описание: Идентификатор устройства.
-
Тип параметра:
-
model_name:-
Тип параметра:
string - Описание: Модель устройства.
-
Тип параметра:
-
vendor_name:-
Тип параметра:
string - Описание: Вендор устройства.
-
Тип параметра:
-
connectors:-
Тип параметра:
repeated DeviceConnector - Описание: Список интерфейсов подключения к устройству.
-
Тип параметра:
Тип DeviceConnector:
-
device_network_id:-
Тип параметра:
string - Описание: Идентификатор сетевого интерфейса устройства.
-
Тип параметра:
-
address:-
Тип параметра:
string - Описание: Адрес подключения (ip/fqdn).
-
Тип параметра:
-
mac:-
Тип параметра:
string - Описание: MAC-адрес устройства.
-
Тип параметра:
-
credentials:-
Тип параметра:
repeated Credential - Описание: Список данных подключения к устройству.
-
Тип параметра:
Тип Credential:
-
protocol:-
Тип параметра:
ConnectorProtocol - Описание: Протокол подключения.
-
Тип параметра:
-
login:-
Тип параметра:
string - Описание: Логин для подключения.
-
Тип параметра:
-
password:-
Тип параметра:
string - Описание: Пароль для подключения.
-
Тип параметра:
-
port:-
Тип параметра:
int32 - Описание: Порт подключения.
-
Тип параметра:
-
cipher:-
Тип параметра:
int32 - Описание: Шифрование (только для IPMI).
-
Тип параметра:
-
version:-
Тип параметра:
int32 - Описание: Версия протокола (только для SNMP).
-
Тип параметра:
-
community:-
Тип параметра:
string - Описание: Community слово (только для SNMP).
-
Тип параметра:
-
security_name:-
Тип параметра:
string - Описание: Security name (только для SNMP).
-
Тип параметра:
-
context:-
Тип параметра:
string - Описание: Контекст подключения (только для SNMP).
-
Тип параметра:
-
auth_protocol:-
Тип параметра:
string - Описание: Auth protocol (только для SNMP).
-
Тип параметра:
-
auth_key:-
Тип параметра:
string - Описание: Auth key (только для SNMP).
-
Тип параметра:
-
private_protocol:-
Тип параметра:
string - Описание: Private protocol (только для SNMP).
-
Тип параметра:
-
private_key:-
Тип параметра:
string - Описание: Private key (только для SNMP).
-
Тип параметра:
-
security_level:-
Тип параметра:
string - Описание: Уровень безопасности.
-
Тип параметра:
Тип SystemMetricTemplate:
-
system_metric_template_id:-
Тип параметра:
string - Описание: Идентификатор шаблона системной метрики.
-
Тип параметра:
-
template:-
Тип параметра:
string - Описание: Шаблон для сбора данных системной метрики (путь к данным).
-
Тип параметра:
-
system_metric:-
Тип параметра:
SystemMetric - Описание: Тип системной метрики.
-
Тип параметра:
Перечисление SystemMetric:
-
SYSTEM_METRIC_POWER_UNSPECIFIED:- Описание: Инвалид.
-
SYSTEM_METRIC_POWER_STATE:- Описание: Метрика текущего состояния питания.
-
SYSTEM_METRIC_BOOT_GET:- Описание: Метрика получения текущего загрузочного носителя.
-
SYSTEM_METRIC_MODEL:- Описание: Метрика получения модели устройства.
-
SYSTEM_METRIC_VENDOR:- Описание: Метрика получения вендора.
-
SYSTEM_METRIC_SERVER_LED:- Описание: Метрика получения текущего значения LED сервера.
-
SYSTEM_METRIC_POWER_USAGE:- Описание: Метрика получения текущего энергопотребления.
-
SYSTEM_METRIC_FIRMWARE_BOOT_SOURCE_GET:- Описание: Метрика получения текущего режима загрузки BIOS/UEFI.
-
SYSTEM_METRIC_SERIAL_NUMBER:- Описание: Метрика получения серийного номера устройства.
-
SYSTEM_METRIC_BIOS_VERSION:- Описание: Метрика получения текущей версии прошивки BIOS/UEFI.
-
SYSTEM_METRIC_BMC_VERSION:- Описание: Метрика получения текущей версии прошивки BMC.
-
SYSTEM_METRIC_OPERATION_SYSTEM:- Описание: Метрика получения текущей операционной системы.
-
SYSTEM_METRIC_HOSTINFO:- Описание: Метрика получения текущей информации о хостах оборудования.
-
SYSTEM_METRIC_PROCESSOR:- Описание: Метрика получения текущей информации о процессорах устройства.
-
SYSTEM_METRIC_DEVICE_TEMPERATURE:- Описание: Метрика получения текущей информации о температуре устройства.
Структура Credential является общей для реализации операции сбора значений энергопотребления по разным протоколам, поэтому может содержать большее количество полей, чем поддерживает модуль расширения.
Для корректной работы сбора данных, устройство должно иметь хотя бы одно действительное подключение с протоколом Redfish (поле protocol списка credentials со значением CONNECTOR_PROTOCOL_REDFISH), остальные устройства модуль должен игнорировать.
Пример данных запроса:
{
"device": {
"device_id": "test",
"connectors": [
{
"address": "192.168.1.55",
"credentials": [
{
"login": "root",
"password": "1qaz@WSX",
"port": 443,
"protocol": "CONNECTOR_PROTOCOL_REDFISH"
}
]
}
]
}
}
В качестве cообщения-ответа в RPC используется модель:
Тип CollectBmcPowerUsageResponse:
-
usage:-
Тип параметра:
DevicePowerUsage - Описание: Перечень собранных данных энергопотребления с устройства.
-
Тип параметра:
Тип DevicePowerUsage:
-
device_identity:-
Тип параметра:
DeviceDataIdentity - Описание: Описание источника сбора данных.
-
Тип параметра:
-
total_usage:-
Тип параметра:
google.protobuf.DoubleValue - Описание: Текущее значение энергопотребления сервера в ваттах.
-
Тип параметра:
-
consumers:-
Тип параметра:
DevicePowerConsumer - Описание: Потребители устройства.
-
Тип параметра:
Тип DeviceDataIdentity:
-
device_id:-
Тип параметра:
string - Описание: Идентификатор устройства.
-
Тип параметра:
-
source:-
Тип параметра:
ServiceSource - Описание: Идентификатор rpc, с которого были собраны данные.
-
Тип параметра:
Перечисление ServiceSource:
-
SERVICE_SOURCE_UNSPECIFIED:- Описание: Невалидное значение.
-
SERVICE_SOURCE_BMC_MANAGER:- Описание: Реализация управления и сбора с BMC.
-
SERVICE_SOURCE_LINUX_MANAGER:- Описание: Реализация управления и сбора с linux-хостов.
-
SERVICE_SOURCE_WINDOWS_MANAGER:- Описание: Реализация управления и сбора с windows-хостов.
-
SERVICE_SOURCE_HYPERVISOR_MANAGER:- Описание: Реализация управления и сбора с гипервизоров.
-
SERVICE_SOURCE_TEMPLATE_MANAGER:- Описание: Реализация шаблонного мониторинга.
Тип DevicePowerConsumer:
-
consumer_usage:-
Тип параметра:
double - Описание: Значение энергопотребления в ваттах.
-
Тип параметра:
-
consumer_name:-
Тип параметра:
string - Описание: Имя БП.
-
Тип параметра:
-
health:-
Тип параметра:
PowerSupplyHealth - Описание: Статус устройства.
-
Тип параметра:
-
state:-
Тип параметра:
PowerSupplyState - Описание: Состояние устройства.
-
Тип параметра:
-
line_input_voltage:-
Тип параметра:
google.protobuf.DoubleValue - Описание: Входное напряжение на линии.
-
Тип параметра:
-
capacity_watts:-
Тип параметра:
google.protobuf.DoubleValue - Описание: Максимальная выдаваемая мощность
-
Тип параметра:
-
power_supply_type:-
Тип параметра:
PowerSupplyType - Описание: Тип источника питания.
-
Тип параметра:
-
firmware_version:-
Тип параметра:
string - Описание: Версия прошивки.
-
Тип параметра:
-
serial_number:-
Тип параметра:
string - Описание: Серийный номер блока питания.
-
Тип параметра:
-
part_number:-
Тип параметра:
string - Описание: Номер партии.
-
Тип параметра:
-
model:-
Тип параметра:
string - Описание: Модель БП, если есть.
-
Тип параметра:
-
vendor:-
Тип параметра:
string - Описание: Название производителя.
-
Тип параметра:
Перечисление PowerSupplyType:
-
POWER_SUPPLY_TYPE_UNSPECIFIED:- Описание: Невалидное значение.
-
POWER_SUPPLY_TYPE_UNKNOWN:- Описание: Неизвестно.
-
POWER_SUPPLY_TYPE_AC:- Описание: Источник питания переменного тока (AC).
-
POWER_SUPPLY_TYPE_DC:- Описание: Источник питания постоянного тока (DC).
-
POWER_SUPPLY_TYPE_AC_OR_DC:- Описание: Источник питания поддерживает как постоянный, так и переменный ток.
-
POWER_SUPPLY_TYPE_UNKNOWN:- Описание: Тип источника питания не может быть определен.
Перечисление PowerSupplyHealth:
-
POWER_SUPPLY_HEALTH_UNSPECIFIED:- Описание: Невалидное значение.
-
POWER_SUPPLY_HEALTH_UNKNOWN:- Описание: Неизвестно.
-
POWER_SUPPLY_HEALTH_OK:- Описание: Здоров.
-
POWER_SUPPLY_HEALTH_WARNING:- Описание: Предупреждение.
-
POWER_SUPPLY_HEALTH_CRITICAL:- Описание: Критическое состояние.
Перечисление PowerSupplyState:
-
POWER_SUPPLY_STATE_UNSPECIFIED:- Описание: Невалидное значение.
-
POWER_SUPPLY_STATE_UNKNOWN:- Описание: Неизвестно.
-
POWER_SUPPLY_STATE_ABSENT:- Описание: Эта функция или ресурс либо отсутствуют, либо обнаружены.
-
POWER_SUPPLY_STATE_DEFERRING:- Описание: Элемент не обрабатывает никаких команд, а ставит в очередь новые запросы.
-
POWER_SUPPLY_STATE_DISABLED:- Описание: Эта функция или ресурс отключены.
-
POWER_SUPPLY_STATE_ENABLED:- Описание: Эта функция или ресурс включена.
-
POWER_SUPPLY_STATE_IN_TEST:- Описание: Эта функция или ресурс проходит тестирование или собирает информацию для отладки.
-
POWER_SUPPLY_STATE_QUALIFIED:- Описание: Качество элемента находится в пределах допустимого диапазона эксплуатаци.
-
POWER_SUPPLY_STATE_QUIESCED:- Описание: Элемент включен, но обрабатывает только ограниченный набор команд.
-
POWER_SUPPLY_STATE_STAND_BY_OFFLINE:- Описание: Эта функция или ресурс включена, но ожидает внешнего действия для ее активации.
-
POWER_SUPPLY_STATE_STAND_BY_SPARE:- Описание: Эта функция или ресурс является частью набора резервирования и ожидает переключения при сбое или другого внешнего действия для ее активации.
-
POWER_SUPPLY_STATE_STARTING:- Описание: Эта функция или ресурс запускается.
-
POWER_SUPPLY_STATE_UNAVAILABLE_OFFLINE:- Описание: Эта функция или ресурс присутствует, но не может быть использован.
-
POWER_SUPPLY_STATE_UPDATING:- Описание: Элемент обновляется и может быть недоступен или ухудшен.
С полной структурой данных вы можете ознакомиться в протофайлах.
Пример реализации
Реализация операции будет производиться на устройстве от производителя Huawei со следующими характеристикам:
- Название ОС:
- - Версия:
- - Процессор:
Intel(R) Xeon(R) Silver 4208 CPU @ 2.10GHz x 2 - Объем памяти дисков:
- - Суммарно установлено памяти (ОЗУ):
24 GB - Количество плашек ОЗУ:
3
Для реализации сбора данных необходимо иметь возможность подключения к удаленному хосту по протоколу Redfish, для этого необходимо сформировать набор данных подключения.
Изучив документацию с официального сайта производителя Huawei становится понятно каким образом хранятся данные по Redfish.
URI домашней страницы службы Redfish (другое название корневой адрес службы) можно получить с помощью следующего URI: https://<IP-адрес:порт>/redfish/v1
Для получения данных по энергопотреблению использоваться содержимое страницы Chassis/1/Power, а итоговый адрес получения данных буде выглядит так - https://<IP-адрес:порт>/redfish/v1/Chassis/1/Power
С этой содержимого этой страницы будет интересовать значения полей списка PowerSupplies или PowerControl
Подробнее по ссылке:
Процесс сбора данных энергопотребления, который состоит из получения содержимого страницы:
private async Task<PowerConsumerInfo?> GetRedfishPowerConsumers(Credential creds, string address)
{
string payloadHeader = $"authorization:Basic {Convert.ToBase64String(Encoding.UTF8.GetBytes(creds.Login + ':' + creds.Password))}";
ImmutableArray<string> chassisMembers = await GetMembers("/redfish/v1/Chassis/", payloadHeader, address, creds.Port);
PowerConsumerInfo? powerConsumerInfo = new()
{
Consumers = [],
};
foreach (string chassis in chassisMembers)
{
if (string.IsNullOrWhiteSpace(chassis))
{
continue;
}
string powerChassis = chassis + (chassis.EndsWith('/') ? "Power/" : "/Power/");
string? powerRaw = await TryGetJsonPage(powerChassis, payloadHeader, address, creds.Port);
if (string.IsNullOrWhiteSpace(powerRaw))
{
continue;
}
try
{
List<DevicePowerConsumer>? consumers = ProcessPowerStatus(powerRaw);
if (consumers is not null)
{
powerConsumerInfo.Consumers.AddRange(consumers);
}
}
catch (Exception ex)
{
Console.WriteLine("Ex while try get powerConsumers from device {0} {1}", address, ex);
}
}
if (powerConsumerInfo.Consumers is not null)
{
powerConsumerInfo.TotalUsage = powerConsumerInfo.Consumers.Sum(c => c.ConsumerUsage);
}
return powerConsumerInfo;
}
Процесс отправки запроса получения содержимого страницы:
private static async Task<string?> TryGetJsonPage(string path, string authHeader, string ip, int port)
{
try
{
string uri = (port == 80 || port / 100 == 50 ? "http" : "https") + "://" + ip + ':' + port + path;
HttpRequestMessage httpRequestMessage = new()
{
RequestUri = new(uri),
};
string[] headers = authHeader.Split(':', 2);
if (headers.Length == 2)
{
httpRequestMessage.Headers.Add(headers[0], headers[1]);
}
HttpClient httpClient = new(new HttpClientHandler()
{
ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true,
AllowAutoRedirect = false,
})
{
Timeout = TimeSpan.FromSeconds(100)
};
using HttpResponseMessage httpResponseMessage = await httpClient.SendAsync(httpRequestMessage);
string result = await httpResponseMessage.Content.ReadAsStringAsync();
if (httpResponseMessage.IsSuccessStatusCode)
{
return result;
}
}
catch
{
return null;
}
return null;
}
Процесс парсинга данных:
public List<DevicePowerConsumer>? ProcessPowerStatus(string powerRaw)
{
List<DevicePowerConsumer> retData = [];
try
{
PowerStatusResponse? parsedObject = JsonConvert.DeserializeObject<PowerStatusResponse>(powerRaw);
if (parsedObject == null)
{
return retData;
}
int pcl = parsedObject.PowerControl != null ? parsedObject.PowerControl.Count : 0;
int psl = parsedObject.PowerSupplies != null ? parsedObject.PowerSupplies.Count : 0;
int threshold = pcl >= psl ? pcl : psl;
for (int a = 0; a < threshold; a++)
{
PowerSupply curControl = parsedObject.PowerControl != null && parsedObject.PowerControl.Count > a ? parsedObject.PowerControl[a] : new PowerSupply();
PowerSupply curSupply = parsedObject.PowerSupplies != null && parsedObject.PowerSupplies.Count > a ? parsedObject.PowerSupplies[a] : new PowerSupply();
retData.Add(BuildState(curControl, curSupply));
}
}
catch (Exception ex)
{
Console.WriteLine("Exception while parse power usage {0}", ex);
}
return retData;
}
Пример готового проекта расположен в папке project