Автоматизация управления массивами HPE: PowerShell, Python и REST API в HPE OneView | AdminWiki
Timeweb Cloud — сервера, Kubernetes, S3, Terraform. Лучшие цены IaaS.
Попробовать

Автоматизация управления массивами HPE: PowerShell, Python и REST API в HPE OneView

12 мая 2026 16 мин. чтения
Содержание статьи

Ручное управление массивами хранения через графический интерфейс HPE OneView отнимает часы рабочего времени и создает риск человеческих ошибок. Автоматизация через REST API решает эту проблему. Используя Python или PowerShell, вы превращаете повторяющиеся операции в выполняемые скрипты, которые работают быстрее и надежнее. Эта статья предоставляет проверенные на практике шаблоны кода для аутентификации, создания томов, сбора отчетов и интеграции с системами мониторинга. Вы сможете внедрить эти решения в свои процессы уже сегодня.

Зачем автоматизировать управление HPE хранилищами? От рутины к IaC

Администраторы тратят до 30% рабочего времени на рутинные операции с системами хранения. Эти задачи повторяются еженедельно или ежемесячно, но выполняются вручную через веб-интерфейс. Автоматизация через API сокращает время выполнения с часов до минут и исключает ошибки конфигурации. Подход Infrastructure as Code (IaC) применяет принципы разработки программного обеспечения к управлению инфраструктурой: конфигурации хранятся в репозитории, изменения отслеживаются, а развертывание выполняется скриптами.

Типичные ручные операции, которые отнимают время

Ежедневный мониторинг состояния массивов через GUI требует последовательного входа в каждый интерфейс управления. Проверка статуса дисков, температуры контроллеров и состояния репликации занимает 15-20 минут для небольшой инфраструктуры из 3-5 массивов. Создание 50 томов для нового проекта вручную занимает 2-3 часа: нужно задать имя, размер, выбрать пул, подтвердить операцию для каждого тома отдельно. Формирование ежемесячного отчета по использованию емкости требует экспорта данных из разных разделов OneView и их объединения в электронной таблице. Настройка репликации между двумя сайтами включает 10-15 шагов в интерфейсе, которые легко пропустить или выполнить в неправильном порядке.

HPE OneView и REST API: ваш шлюз к автоматизации

HPE OneView служит единой точкой управления для конвергентной инфраструктуры HPE, объединяя серверы, хранилища и сети. Помимо графического интерфейса, платформа предоставляет REST API версии 3000 и выше. Этот API позволяет внешним системам и скриптам выполнять все операции управления программно. Через API доступны ресурсы для работы с storage systems (массивами), storage pools (пулами), volumes (томами) и alerts (оповещениями). Каждый запрос требует аутентификации с получением session ID, который действует 24 часа. API возвращает данные в формате JSON, что упрощает их обработку в скриптах.

Настройка окружения и первое подключение к API

Прежде чем писать скрипты, подготовьте среду выполнения и установите связь с HPE OneView. Вам потребуются учетные данные администратора OneView, сетевой доступ к его IP-адресу на порту 443, а также Python 3.8+ или PowerShell 5.1+. Для тестовых сред можно временно отключить проверку SSL-сертификатов, но в рабочих окружениях используйте валидные сертификаты.

Подготовка: Python с requests и PowerShell

Установите Python с официального сайта python.org, выбрав версию 3.8 или новее. После установки откройте командную строку и выполните команду pip install requests для добавления библиотеки HTTP-запросов. PowerShell обычно предустановлен в Windows 10 и 11. Проверьте версию командой $PSVersionTable.PSVersion - она должна быть 5.1 или выше. Для написания и отладки скриптов используйте VS Code с расширениями Python и PowerShell.

Шаблон скрипта для аутентификации в HPE OneView (Python и PowerShell)

Этот базовый скрипт выполняет аутентификацию и возвращает session token для последующих запросов. Сохраните учетные данные в переменных окружения, а не в коде скрипта.

Python скрипт:

import requests
import os
import warnings

# Отключение предупреждений о SSL только для тестовых сред
warnings.filterwarnings('ignore')

# Параметры подключения
oneview_ip = os.getenv('ONEVIEW_IP', '192.168.1.100')
username = os.getenv('ONEVIEW_USER', 'administrator')
password = os.getenv('ONEVIEW_PASS')

# URL для аутентификации
auth_url = f"https://{oneview_ip}/rest/login-sessions"

# Тело запроса
auth_data = {
    "userName": username,
    "password": password,
    "authLoginDomain": "Local"
}

# Заголовки запроса
headers = {
    "Content-Type": "application/json",
    "X-API-Version": "3000"
}

# Отправка запроса
try:
    response = requests.post(auth_url, 
                           json=auth_data, 
                           headers=headers, 
                           verify=False)  # verify=True для рабочих сред
    response.raise_for_status()
    
    # Извлечение session ID
    session_id = response.json().get('sessionID')
    print(f"Успешная аутентификация. Session ID: {session_id[:20]}...")
    
    # Заголовки для последующих запросов
    auth_headers = {
        "Content-Type": "application/json",
        "X-API-Version": "3000",
        "auth": session_id
    }
    
except requests.exceptions.RequestException as e:
    print(f"Ошибка подключения: {e}")

PowerShell скрипт:

# Параметры подключения
$oneviewIP = $env:ONEVIEW_IP ?? "192.168.1.100"
$username = $env:ONEVIEW_USER ?? "administrator"
$password = $env:ONEVIEW_PASS

# Отключение проверки SSL (только для тестов)
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}

# URL для аутентификации
$authUrl = "https://${oneviewIP}/rest/login-sessions"

# Тело запроса
$authBody = @{
    userName = $username
    password = $password
    authLoginDomain = "Local"
} | ConvertTo-Json

# Заголовки запроса
$headers = @{
    "Content-Type" = "application/json"
    "X-API-Version" = "3000"
}

try {
    # Отправка запроса
    $response = Invoke-RestMethod -Uri $authUrl \
                                 -Method Post \
                                 -Body $authBody \
                                 -Headers $headers \
                                 -SkipCertificateCheck
    
    # Извлечение session ID
    $sessionID = $response.sessionID
    Write-Host "Успешная аутентификация. Session ID: $($sessionID.Substring(0,20))..."
    
    # Заголовки для последующих запросов
    $authHeaders = @{
        "Content-Type" = "application/json"
        "X-API-Version" = "3000"
        "auth" = $sessionID
    }
} catch {
    Write-Host "Ошибка подключения: $($_.Exception.Message)"
}

Автоматизация основных операций: готовые скрипты

После настройки аутентификации вы можете автоматизировать конкретные задачи управления хранилищами. Эти скрипты используют session token, полученный на предыдущем этапе, и выполняют операции через REST API. Каждый скрипт включает обработку ошибок и логирование результатов.

Создание тома (LUN) по шаблону на Python

Этот скрипт создает новый том в указанном пуле хранилищ. Он находит storage system и storage pool по имени, затем отправляет POST-запрос с параметрами тома.

def create_volume(oneview_ip, auth_headers, volume_name, size_gb, pool_name):
    """Создание тома в HPE OneView"""
    
    # 1. Поиск storage system
    systems_url = f"https://{oneview_ip}/rest/storage-systems"
    systems_response = requests.get(systems_url, headers=auth_headers, verify=False)
    
    if systems_response.status_code != 200:
        print(f"Ошибка получения списка систем: {systems_response.status_code}")
        return None
    
    systems = systems_response.json()['members']
    if not systems:
        print("Не найдены storage systems")
        return None
    
    # Используем первую найденную систему
    system_uri = systems[0]['uri']
    
    # 2. Поиск storage pool
    pools_url = f"https://{oneview_ip}/rest/storage-pools"
    pools_response = requests.get(pools_url, headers=auth_headers, verify=False)
    
    target_pool = None
    for pool in pools_response.json()['members']:
        if pool['name'] == pool_name:
            target_pool = pool
            break
    
    if not target_pool:
        print(f"Пул {pool_name} не найден")
        return None
    
    # 3. Формирование запроса на создание тома
    volume_url = f"https://{oneview_ip}/rest/storage-volumes"
    
    volume_data = {
        "name": volume_name,
        "description": f"Создан автоматически через API",
        "storageSystemUri": system_uri,
        "provisioningType": "Thin",  # Thin или Thick
        "provisionedCapacityBytes": size_gb * 1024 * 1024 * 1024,
        "isShareable": True,
        "storagePoolUri": target_pool['uri']
    }
    
    # 4. Отправка запроса
    create_response = requests.post(volume_url, 
                                  json=volume_data, 
                                  headers=auth_headers, 
                                  verify=False)
    
    if create_response.status_code == 202:
        task_uri = create_response.headers.get('Location')
        print(f"Задача создания тома запущена. Task URI: {task_uri}")
        return task_uri
    else:
        print(f"Ошибка создания тома: {create_response.status_code}")
        print(create_response.text)
        return None

# Пример использования
if __name__ == "__main__":
    # Используем заголовки из предыдущего скрипта аутентификации
    volume_task = create_volume(
        oneview_ip="192.168.1.100",
        auth_headers=auth_headers,  # Заголовки с session ID
        volume_name="DB_Data_Volume_01",
        size_gb=500,
        pool_name="SSD_Pool_01"
    )

PowerShell-скрипт для массового создания томов из CSV-файла

Для создания десятков томов подготовьте CSV-файл с колонками Name, SizeGB и PoolName. Этот скрипт читает файл и создает тома для каждой строки.

# Массовое создание томов из CSV
$csvPath = "C:\Scripts\volumes_to_create.csv"
$logPath = "C:\Scripts\volume_creation_log_$(Get-Date -Format 'yyyyMMdd').txt"

# Чтение CSV файла
$volumes = Import-Csv -Path $csvPath

# Функция создания одного тома
function Create-OneViewVolume {
    param($VolumeName, $SizeGB, $PoolName)
    
    $volumeBody = @{
        name = $VolumeName
        description = "Created from CSV batch $(Get-Date)"
        provisioningType = "Thin"
        provisionedCapacityBytes = [int64]($SizeGB * 1GB)
        isShareable = $true
        storagePoolUri = $poolUri  # Нужно получить URI пула
    } | ConvertTo-Json
    
    $volumeUrl = "https://$oneviewIP/rest/storage-volumes"
    
    try {
        $response = Invoke-RestMethod -Uri $volumeUrl \
                                    -Method Post \
                                    -Body $volumeBody \
                                    -Headers $authHeaders \
                                    -SkipCertificateCheck
        
        $result = @{
            Name = $VolumeName
            Status = "Success"
            TaskURI = $response.taskUri
            Timestamp = Get-Date
        }
    } catch {
        $result = @{
            Name = $VolumeName
            Status = "Failed"
            Error = $_.Exception.Message
            Timestamp = Get-Date
        }
    }
    
    return $result
}

# Обработка каждой строки CSV
$results = @()
foreach ($volume in $volumes) {
    $result = Create-OneViewVolume -VolumeName $volume.Name \
                                  -SizeGB $volume.SizeGB \
                                  -PoolName $volume.PoolName
    
    $results += $result
    
    # Логирование
    $logEntry = "$(Get-Date) - $($volume.Name): $($result.Status)"
    if ($result.Error) {
        $logEntry += " - Error: $($result.Error)"
    }
    Add-Content -Path $logPath -Value $logEntry
    
    # Пауза между созданиями (1 секунда)
    Start-Sleep -Seconds 1
}

# Вывод сводки
$successCount = ($results | Where-Object { $_.Status -eq "Success" }).Count
Write-Host "Создано томов: $successCount из $($volumes.Count)"

Сбор данных для отчетов: состояние массивов и использование пулов

Этот Python-скрипт собирает метрики по всем storage systems и pools, затем выводит их в табличном формате или экспортирует в CSV. Для форматирования таблиц используется библиотека pandas.

import pandas as pd
from datetime import datetime

def get_storage_metrics(oneview_ip, auth_headers):
    """Сбор метрик систем хранения"""
    
    metrics = []
    
    # Получение списка storage systems
    systems_url = f"https://{oneview_ip}/rest/storage-systems"
    systems_response = requests.get(systems_url, headers=auth_headers, verify=False)
    
    for system in systems_response.json()['members']:
        # Детальная информация о системе
        system_detail_url = f"https://{oneview_ip}{system['uri']}"
        detail_response = requests.get(system_detail_url, headers=auth_headers, verify=False)
        system_data = detail_response.json()
        
        # Получение информации о пулах для этой системы
        pools_url = f"https://{oneview_ip}/rest/storage-pools"
        pools_response = requests.get(pools_url, headers=auth_headers, verify=False)
        
        for pool in pools_response.json()['members']:
            if pool['storageSystemUri'] == system['uri']:
                # Расчет использования в процентах
                total_bytes = pool['totalCapacity']
                free_bytes = pool['freeCapacity']
                used_bytes = total_bytes - free_bytes
                used_percent = (used_bytes / total_bytes * 100) if total_bytes > 0 else 0
                
                metric = {
                    'system_name': system_data.get('name', 'N/A'),
                    'pool_name': pool.get('name', 'N/A'),
                    'total_tb': round(total_bytes / (1024**4), 2),
                    'used_tb': round(used_bytes / (1024**4), 2),
                    'free_tb': round(free_bytes / (1024**4), 2),
                    'used_percent': round(used_percent, 1),
                    'raid_level': pool.get('raidLevel', 'N/A'),
                    'health_status': pool.get('status', 'N/A'),
                    'timestamp': datetime.now().isoformat()
                }
                metrics.append(metric)
    
    return metrics

# Сбор и вывод метрик
metrics = get_storage_metrics("192.168.1.100", auth_headers)

if metrics:
    # Создание DataFrame
    df = pd.DataFrame(metrics)
    
    # Вывод в консоль
    print("\nМетрики систем хранения:")
    print(df.to_string(index=False))
    
    # Экспорт в CSV
    csv_filename = f"storage_metrics_{datetime.now().strftime('%Y%m%d_%H%M')}.csv"
    df.to_csv(csv_filename, index=False, encoding='utf-8')
    print(f"\nДанные экспортированы в {csv_filename}")
    
    # Проверка критического использования (>85%)
    critical_pools = df[df['used_percent'] > 85]
    if not critical_pools.empty:
        print("\n⚠️  ВНИМАНИЕ: Критическое использование пулов:")
        for _, pool in critical_pools.iterrows():
            print(f"  {pool['pool_name']}: {pool['used_percent']}% заполнено")
else:
    print("Не удалось собрать метрики")

# Интеграция с существующими процессами автоматизации
# Скрипты сбора метрик можно использовать как часть более крупных систем мониторинга.
# Например, в статье Автоматизация инфраструктуры для DevOps и сисадминв: практический гайд (2026) подробно разбираются подходы к построению комплексных пайплайнов мониторинга.

Мониторинг и интеграция с Zabbix и Prometheus

Скрипты сбора данных превращаются в элементы промышленных систем мониторинга. Zabbix использует внешние проверки через скрипты, Prometheus работает через экспортеры, которые предоставляют метрики в специфичном формате. Оба подхода позволяют создавать дашборды и настраивать оповещения при достижении пороговых значений.

Создание пользовательского элемента данных в Zabbix для HPE OneView

Zabbix выполняет внешние скрипты и ожидает числовое значение или текст в ответ. Этот Python-скрипт возвращает свободное место в указанном пуле хранилищ.

#!/usr/bin/env python3
"""Zabbix External Check для HPE OneView"""

import sys
import requests
import os

# Параметры из аргументов командной строки
# Использование: python3 oneview_pool_free.py pool_name
if len(sys.argv) != 2:
    print("Использование: python3 oneview_pool_free.py ")
    sys.exit(1)

target_pool_name = sys.argv[1]

# Конфигурация (лучше хранить в конфигурационном файле Zabbix)
oneview_ip = os.getenv('ONEVIEW_IP', '192.168.1.100')
username = os.getenv('ONEVIEW_USER', 'administrator')
password = os.getenv('ONEVIEW_PASS')

# Аутентификация
auth_url = f"https://{oneview_ip}/rest/login-sessions"
auth_data = {"userName": username, "password": password, "authLoginDomain": "Local"}
headers = {"Content-Type": "application/json", "X-API-Version": "3000"}

try:
    auth_response = requests.post(auth_url, json=auth_data, headers=headers, verify=False)
    auth_response.raise_for_status()
    session_id = auth_response.json().get('sessionID')
    
    auth_headers = {
        "Content-Type": "application/json",
        "X-API-Version": "3000",
        "auth": session_id
    }
    
    # Поиск пула
    pools_url = f"https://{oneview_ip}/rest/storage-pools"
    pools_response = requests.get(pools_url, headers=auth_headers, verify=False)
    
    free_gb = -1  # Значение по умолчанию при ошибке
    
    for pool in pools_response.json()['members']:
        if pool['name'] == target_pool_name:
            free_bytes = pool['freeCapacity']
            free_gb = free_bytes / (1024**3)  # Конвертация в гигабайты
            break
    
    # Zabbix ожидает числовое значение
    print(free_gb)
    
except Exception as e:
    # В случае ошибки возвращаем -1
    print(-1)

В Zabbix настройте внешнюю проверку:

  1. Создайте элемент данных типа "External check"
  2. Укажите команду: python3 /etc/zabbix/externalscripts/oneview_pool_free.py "SSD_Pool_01"
  3. Настройте триггер при значении меньше 100 (ГБ свободно)
  4. Добавьте график для визуализации тренда

Простой Prometheus Exporter на Python

Prometheus экспортер работает как веб-сервер, предоставляя метрики по HTTP. Библиотека prometheus_client упрощает создание метрик и их обновление.

from prometheus_client import start_http_server, Gauge
import time
import threading
import requests

# Создание метрик
storage_pool_free = Gauge('hpestorage_pool_free_bytes', 
                         'Free space in storage pool in bytes',
                         ['pool_name', 'system_name'])
storage_pool_total = Gauge('hpestorage_pool_total_bytes', 
                          'Total space in storage pool in bytes',
                          ['pool_name', 'system_name'])
storage_pool_health = Gauge('hpestorage_pool_health_status', 
                           'Health status of storage pool (0=OK, 1=Warning, 2=Critical)',
                           ['pool_name', 'system_name'])

def update_metrics():
    """Обновление метрик из HPE OneView"""
    while True:
        try:
            # Аутентификация (упрощенный вариант)
            auth_url = "https://192.168.1.100/rest/login-sessions"
            auth_data = {
                "userName": "api_user",
                "password": "secure_password",
                "authLoginDomain": "Local"
            }
            headers = {"Content-Type": "application/json", "X-API-Version": "3000"}
            
            auth_response = requests.post(auth_url, json=auth_data, headers=headers, verify=False)
            session_id = auth_response.json().get('sessionID')
            
            auth_headers = {
                "Content-Type": "application/json",
                "X-API-Version": "3000",
                "auth": session_id
            }
            
            # Получение данных о пулах
            pools_url = "https://192.168.1.100/rest/storage-pools"
            pools_response = requests.get(pools_url, headers=auth_headers, verify=False)
            
            for pool in pools_response.json()['members']:
                pool_name = pool.get('name', 'unknown')
                system_name = pool.get('storageSystemUri', '').split('/')[-1]
                
                # Обновление метрик
                storage_pool_free.labels(pool_name=pool_name, 
                                       system_name=system_name).set(pool['freeCapacity'])
                storage_pool_total.labels(pool_name=pool_name, 
                                        system_name=system_name).set(pool['totalCapacity'])
                
                # Конвертация статуса в числовое значение
                health_status = 0  # OK
                if pool.get('status') == 'Warning':
                    health_status = 1
                elif pool.get('status') == 'Critical':
                    health_status = 2
                
                storage_pool_health.labels(pool_name=pool_name, 
                                         system_name=system_name).set(health_status)
            
        except Exception as e:
            print(f"Ошибка обновления метрик: {e}")
        
        # Обновление каждые 60 секунд
        time.sleep(60)

if __name__ == '__main__':
    # Запуск HTTP-сервера на порту 8000
    start_http_server(8000)
    print("Prometheus exporter запущен на порту 8000")
    
    # Запуск потока обновления метрик
    metric_thread = threading.Thread(target=update_metrics)
    metric_thread.daemon = True
    metric_thread.start()
    
    # Основной поток
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        print("\nОстановка экспортера")

# Запустите экспортер как службу или в Docker-контейнере
# docker run -d -p 8000:8000 --name hpe-oneview-exporter ваш-образ

В Prometheus добавьте конфигурацию:

scrape_configs:
  - job_name: 'hpe_oneview'
    static_configs:
      - targets: ['exporter-host:8000']
    scrape_interval: 60s

Реализация сценариев "Infrastructure as Code" для DevOps

Скрипты управления хранилищами становятся частью репозитория инфраструктурного кода. Это позволяет отслеживать изменения, выполнять code review и автоматизировать развертывание через CI/CD пайплайны. Конфигурации хранятся в формате JSON или YAML, что делает их читаемыми и версионируемыми.

Хранение конфигураций хранилищ в Git

Создайте структуру репозитория, которая отделяет скрипты от конфигураций и документации. Это упрощает поддержку и позволяет разным командам работать с кодом.

storage-infrastructure/
├── scripts/
│   ├── python/
│   │   ├── auth.py           # Аутентификация
│   │   ├── create_volume.py  # Создание томов
│   │   └── monitor.py        # Мониторинг
│   └── powershell/
│       ├── Connect-OneView.ps1
│       └── New-StorageVolume.ps1
├── configs/
│   ├── production/
│   │   ├── storage-pools.json
│   │   └── volumes-template.json
│   └── testing/
│       └── test-volumes.json
├── docs/
│   └── API-usage.md
└── .gitignore

Пример конфигурационного файла volumes-template.json:

{
  "volume_configuration": {
    "environment": "production",
    "storage_pool": "SSD_Pool_01",
    "defaults": {
      "provisioning_type": "Thin",
      "is_shareable": true,
      "description_template": "Volume for {purpose} created {timestamp}"
    },
    "volumes": [
      {
        "name": "db_data_primary",
        "size_gb": 1000,
        "purpose": "PostgreSQL primary data"
      },
      {
        "name": "db_wal_primary",
        "size_gb": 200,
        "purpose": "PostgreSQL WAL logs"
      }
    ]
  }
}

Пример: создание тестового окружения по Git-тегу

При создании тега v1.2-test-env в GitLab CI/CD запускается пайплайн, который разворачивает тестовое хранилище. После завершения тестов окружение автоматически удаляется.

# .gitlab-ci.yml
stages:
  - deploy-test-storage
  - cleanup

variables:
  ONEVIEW_IP: "192.168.1.100"
  ONEVIEW_USER: "gitlab_ci_user"
  
deploy-test-volumes:
  stage: deploy-test-storage
  only:
    - tags
  script:
    - python3 -m pip install requests
    - python3 scripts/python/create_test_volumes.py
      --config configs/testing/test-volumes.json
      --tag $CI_COMMIT_TAG
  artifacts:
    paths:
      - deployment_log.txt
    expire_in: 1 week

cleanup-test-volumes:
  stage: cleanup
  only:
    - tags
  when: manual  # Ручной запуск после тестов
  script:
    - python3 scripts/python/delete_test_volumes.py
      --tag $CI_COMMIT_TAG
# create_test_volumes.py
import json
import sys
import requests
from datetime import datetime

def create_test_volumes(config_path, tag):
    """Создание тестовых томов на основе конфигурации"""
    
    with open(config_path, 'r') as f:
        config = json.load(f)
    
    # Аутентификация
    session_id = authenticate()
    
    created_volumes = []
    
    for volume_spec in config['volumes']:
        volume_name = f"test_{tag}_{volume_spec['name']}"
        
        volume_data = {
            "name": volume_name,
            "size_gb": volume_spec['size_gb'],
            "pool_name": config['storage_pool'],
            "description": f"Test volume for {tag}. {volume_spec.get('purpose', '')}"
        }
        
        # Используем функцию создания тома из предыдущих примеров
        task_uri = create_volume(
            oneview_ip=config['oneview_ip'],
            auth_headers={"auth": session_id},
            **volume_data
        )
        
        if task_uri:
            created_volumes.append({
                "name": volume_name,
                "task_uri": task_uri,
                "created_at": datetime.now().isoformat()
            })
    
    # Сохранение информации о созданных томах
    with open(f"test_volumes_{tag}.json", 'w') as f:
        json.dump({"tag": tag, "volumes": created_volumes}, f, indent=2)
    
    print(f"Создано {len(created_volumes)} тестовых томов для тега {tag}")

if __name__ == "__main__":
    if len(sys.argv) != 5:
        print("Использование: python3 create_test_volumes.py --config  --tag ")
        sys.exit(1)
    
    config_path = sys.argv[2]
    tag = sys.argv[4]
    
    create_test_volumes(config_path, tag)

Этот подход интегрирует управление хранилищами в DevOps-практики. Как и в статье Автоматизация резервного копирования и восстановления: практические скрипты Python и Bash для DevOps-инженеров, ключевой принцип - автоматизация критически важных операций инфраструктуры.

Безопасность, обработка ошибок и лучшие практики

Работа с API управления инфраструктурой требует особого внимания к безопасности и надежности. Скрипты должны корректно обрабатывать ошибки, не оставлять задачи в подвешенном состоянии и минимизировать риски при компрометации учетных данных.

Безопасная работа с учетными данными и правами в OneView

Создайте в HPE OneView отдельную учетную запись для API-доступа с минимально необходимыми привилегиями. Назначьте роль "Storage administrator" или создайте кастомную роль, которая разрешает только операции с томами. Никогда не храните пароли в скриптах или репозиториях. Используйте переменные окружения, которые устанавливаются при запуске скрипта, или системы управления секретами.

Пример использования переменных окружения:

# Установка переменных в Linux/Mac
export ONEVIEW_IP="192.168.1.100"
export ONEVIEW_USER="api_service_account"
export ONEVIEW_PASS="$(cat /secrets/oneview-api.pass)"

# В скрипте Python
import os
ip = os.environ.get('ONEVIEW_IP')
user = os.environ.get('ONEVIEW_USER')
password = os.environ.get('ONEVIEW_PASS')

# В PowerShell
$env:ONEVIEW_IP = "192.168.1.100"
$env:ONEVIEW_USER = "api_service_account"
$env:ONEVIEW_PASS = Get-Content -Path "C:\Secrets\oneview-api.pass" -Raw

Для рабочих сред рассмотрите использование аппаратных ключей или сертификатов для аутентификации, если HPE OneView поддерживает эти методы. Регулярно обновляйте пароли учетных записей API и отслеживайте их использование через журналы аудита OneView.

Надежные скрипты: обработка ошибок и логирование

Каждый скрипт должен проверять коды ответа HTTP и корректно обрабатывать ошибки. Используйте структурированное логирование для записи всех операций и их результатов.

import logging
import sys
from logging.handlers import RotatingFileHandler

# Настройка логирования
def setup_logging(log_file='oneview_automation.log'):
    logger = logging.getLogger('hpe_oneview')
    logger.setLevel(logging.INFO)
    
    # Форматтер
    formatter = logging.Formatter(
        '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
    )
    
    # Файловый обработчик с ротацией
    file_handler = RotatingFileHandler(
        log_file, maxBytes=10*1024*1024, backupCount=5
    )
    file_handler.setFormatter(formatter)
    logger.addHandler(file_handler)
    
    # Консольный обработчик
    console_handler = logging.StreamHandler(sys.stdout)
    console_handler.setFormatter(formatter)
    logger.addHandler(console_handler)
    
    return logger

# Использование в функциях
def create_volume_with_logging(oneview_ip, auth_headers, volume_name, size_gb, pool_name):
    logger = logging.getLogger('hpe_oneview')
    
    try:
        logger.info(f"Начало создания тома: {volume_name}, размер: {size_gb}GB")
        
        # Вызов функции создания тома
        task_uri = create_volume(oneview_ip, auth_headers, volume_name, size_gb, pool_name)
        
        if task_uri:
            logger.info(f"Том {volume_name} создан. Task URI: {task_uri}")
            
            # Мониторинг выполнения задачи
            task_completed = monitor_task(oneview_ip, auth_headers, task_uri)
            
            if task_completed:
                logger.info(f"Задача создания тома {volume_name} завершена успешно")
                return True
            else:
                logger.error(f"Задача создания тома {volume_name} завершилась с ошибкой")
                return False
        else:
            logger.error(f"Не удалось запустить создание тома {volume_name}")
            return False
            
    except requests.exceptions.Timeout:
        logger.error(f"Таймаут при создании тома {volume_name}")
        return False
    except requests.exceptions.ConnectionError:
        logger.error(f"Ошибка подключения при создании тома {volume_name}")
        return False
    except Exception as e:
        logger.error(f"Неожиданная ошибка при создании тома {volume_name}: {e}")
        return False

# Функция мониторинга задачи
def monitor_task(oneview_ip, auth_headers, task_uri, timeout_seconds=300):
    """Ожидание завершения задачи"""
    import time
    
    start_time = time.time()
    logger = logging.getLogger('hpe_oneview')
    
    while time.time() - start_time < timeout_seconds:
        try:
            task_response = requests.get(f"https://{oneview_ip}{task_uri}", 
                                       headers=auth_headers, verify=False)
            
            if task_response.status_code == 200:
                task_data = task_response.json()
                task_state = task_data.get('taskState', 'Unknown')
                
                if task_state == 'Completed':
                    logger.info(f"Задача {task_uri} завершена успешно")
                    return True
                elif task_state == 'Error':
                    task_error = task_data.get('taskErrors', [{}])[0].get('message', 'No error details')
                    logger.error(f"Задача {task_uri} завершилась с ошибкой: {task_error}")
                    return False
                # Задача все еще выполняется
                time.sleep(5)
            else:
                logger.warning(f"Ошибка получения статуса задачи {task_uri}: {task_response.status_code}")
                time.sleep(10)
                
        except Exception as e:
            logger.error(f"Ошибка при мониторинге задачи {task_uri}: {e}")
            time.sleep(10)
    
    logger.error(f"Таймаут мониторинга задачи {task_uri}")
    return False

Эти практики обеспечивают надежную работу скриптов в production-средах. Они также помогают быстро диагностировать проблемы при их возникновении. Для комплексного подхода к управлению инфраструктурой изучите Базу знаний IT в 2026: как систематизировать экспертизу и сократить простой команды, где описаны методологии организации работы с инфраструктурным кодом.

Автоматизация управления массивами HPE через REST API превращает рутинные операции в выполняемые программы. Вы начинаете с простых скриптов аутентификации, затем добавляете функции для создания томов и сбора отчетов, после чего интегрируете их в системы мониторинга и CI/CD пайплайны. Каждый шаг приносит конкретную выгоду: экономию времени, снижение ошибок, лучшую наблюдаемость. Используйте готовые примеры из этой статьи как основу для своих решений, адаптируя их под требования вашей инфраструктуры.

Поделиться:
Сохранить гайд? В закладки браузера