Автоматизированная настройка СХД АЭРОДИСК с помощью REST API

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Привет, Хабр.

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

В рейтинге наиболее популярных «хотелок» – интеграция системы хранения данных с внешними отечественными или opensource продуктами: системы мониторинга, системы управления и планирования ёмкостей или сложные автоматизированные метрокластеры с классическим набором серверов приложений, СУБД и систем виртуализации. Решив, что краткого упоминания о REST API в системах хранения данных АЭРОДИСК явно недостаточно, в этой статье мы расскажем о том, как автоматизировать создание классических репликации, конфигурации метрокластера и управлять переключением сайтов с использованием REST API и Python. А послушать про это можно будет на вебинаре «ОколоИТ», который пройдёт 12 марта  в 15:00 – регистрируйтесь по ссылке.

Немного матчасти

Прежде чем перейти к непосредственной разработке скриптов для автоматизированной настройки СХД через REST API, залезем под капот СХД АЭРОДИСК в части работы API.

При разработке API доступного конечному пользователю продукта, очень важно применять такие же принципы, как и при разработке качественного Front-End интерфейса, а именно учитывать пользовательский опыт и понимать, насколько удобно будет использовать тот или иной метод, рассчитывая на то, что использовать его будет скорее всего не команда разработки, а системный администратор заказчика. Немаловажным является качественное документирование API и возможных параметров при вызове методов. Для документирования REST API мы активно используем автодокументирование кода, написанного по спецификации OpenAPI с помощью известного пакета с открытым исходным кодом Swagger. Это позволяет одновременно получить качественный код, тест-кейсы под него и инструмент визуализации выполнения запросов (обычно в рамках обучения или отладки) с помощью Swagger UI. Естественно, это не отменяет необходимость написания технической документации для конечного пользователя с более подробным набором инструкций и примеров, но даже не имея под рукой никаких документов от вендора, можно довольно быстро разобраться с REST API, используя Swagger.

Приступим

Как знают администраторы СХД АЭРОДИСК, все управление нашим дисковым массивом выполняется через браузер: добавив в строке браузера “/api/docs/”, вы попадете как раз в управление СХД с помощью REST API и Swagger.

Названия разделов поделены согласно функциям дискового массива:

  • Authentication – авторизация пользователей, после авторизации будут доступны все остальные REST API запросы к СХД;

  • DDP – управление DDP группами, создание и удаление пулов, томов, снимков данных;

  • RDG – управление RDG группами, создание и удаление пулов, томов, снимков данных;

  • Disk – получение информации об установленных в СХД дисках;

  • Network – управление сетью, vlan, vip;

  • FC – управление Fibre Channel таргетами, группами, маппингами томов;

  • iSCSI – управление iSCSI таргетами, группами, маппингами томов;

  • Consistency group – управление группами консистентности;

  • Rrepl – управление удаленной репликацией и метрокластером, создание репликационных пар, управление переключением.

Авторизация

После авторизации пользователя становятся доступными все разделы по управлению СХД. При использовании Swagger UI возможно составить и отправить REST запрос, получить и проанализировать ответ СХД, а также использовать автоматически сгенерированный запрос curl, который уже можно использовать в своих скриптах.

Авторизация - обычно первая сложность, которую приходится побороть начинающему пользователю REST API. Для авторизации применяется endpoint http://IP_адрес/api/auth/token, куда c помощью POST запроса отправляются данные о пользователе и пароле. В ответе же в формате JSON приходит специальный токен, который можно использовать для авторизации при выполнении других команд. Токен действует в течение 1 часа, после этого времени необходимо его перегенерировать. Приведем пример получения токена авторизации с помощью curl:

curl -X 'POST' \
  'http://192.168.11.30/api/auth/token' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'grant_type=&username=admin&password=Bac12345&scope=&client_id=&client_secret='

Ответом на эту команду будет возвращен JSON c токеном (Response Body):

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhZG1pbiIsImV4cCI6NDkyMjczMzMzM30.Xe5poHQdIUJ_8yAlWfT_yHVVEgjhnmpLJa4NjmAN4pA",
  "token_type": "bearer"
}

Далее можно использовать авторизационный токен, например, при получении информации о DDP пуле DDP1:

curl -X 'GET' \
  'http://192.168.11.30/api/ddp/pool?name=DDP1' \
  -H 'accept: application/json' \
  -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhZG1pbiIsImV4cCI6NDkyMjczMzMzM30.Xe5poHQdIUJ_8yAlWfT_yHVVEgjhnmpLJa4NjmAN4pA'

Ответом на эту команду будет JSON c информацией о пуле DDP1:

[
  {
    "name": "DDP1",
    "fullSize": 7681507065856,
    "sizeAvailable": 7670761259008,
    "dataDisksQty": 2,
    "cacheDisksQty": 0,
    "hotSpare": true,
    "blockSize": 4194304,
    "uuid": "wOCgyZ-oDio-HOLV-cR01-S7jj-TxZF-80G2ij",
    "state": "UP",
    "health": "ONLINE",
    "lunQty": 0,
    "alua": false,
    "missingDisks": 0,
    "disksInfo": [
      {
        "wwn": "35000c500a189620b",
        "free": 3835380629504,
        "diskType": "data"
      },
      {
        "wwn": "35000c500a189625b",
        "free": 3835380629504,
        "diskType": "data"
      }
    ],
    "thinStorage": false
  }
]

Метрокластер и репликация

Метрокластер – технология, позволяющая обеспечить доступность данных с помощью разнесения СХД на несколько площадок в пределах города или района и использовании репликации данных между ними. Основное отличие метрокластера от классической репликации – это автоматизация обработки отказов оборудования при обеспечении потребителей актуальными данными. Подробно о метрокластере и сценариях отказа мы рассказывали в одном из наших постов на Хабре и даже проводили демонстрацию на вебинаре «ОколоИТ». Здесь же поговорим о той подготовительной работе, которую необходимо провести при начальном развертывании метрокластера и как её можно автоматизировать с помощью REST API.

Подробные инструкции о настройке метрокластера приведены в руководстве администратора СХД, поэтому перечислим тут лишь основные необходимые шаги:

  • создание группы (RDG или DDP);

  • создание томов;

  • создание IP ресурсов для репликации и метрокластера;

  • создание репликационных связей;

  • создание маппингов томов;

  • управление переключением сайта (Primary/Secondary).

Естественно все шаги можно делать из GUI, но для двух массивов и, например, 20 томов это займет достаточно много времени даже у опытного системного администратора.

Приведем пример создания всей инфраструктуры метрокластера через REST API и Python.  Ниже приведем шаги и листинги Python скриптов, при этом конфигурационные файлы и импортируемые модули приложим отдельными файлами.

Шаг 1 - создадим по два DDP пула на двух СХД (скрипт запускается два раза с разными настройками целевой СХД в конфигурационном файле config.conf):

import json
from pages_methods.base_methods import *
from pages_methods.DDP import *

ddp_post_create_pool = {
    'name_pool': "DDP1",
    'qty_disks': 4
    'is_alua': 0,
    'block_size': 4194304,
    'is_hotspare': 0,
    'max_recovery_rate': 50000}

name_pool = ddp_post_create_pool.get("name_pool")
qty_disks = ddp_post_create_pool.get("qty_disks")
is_alua = ddp_post_create_pool.get("is_alua")
block_size = ddp_post_create_pool.get("block_size")
is_hotspare = ddp_post_create_pool.get("is_hotspare")
max_recovery_rate = ddp_post_create_pool.get("max_recovery_rate")

disks = BaseApp.get_wwn_disks (4, "SSD")
print (disks)
Ddp_Methods.post_create_pool(name_pool, is_alua, block_size, is_hotspare, max_recovery_rate, qty_disks)

ddp_post_create_pool = {
    'name_pool': "DDP2",
    'qty_disks': 4,
    'is_alua': 0,
    'block_size': 4194304,
    'is_hotspare': 0,
    'max_recovery_rate': 50000}

name_pool = ddp_post_create_pool.get("name_pool")
qty_disks = ddp_post_create_pool.get("qty_disks")
is_alua = ddp_post_create_pool.get("is_alua")
block_size = ddp_post_create_pool.get("block_size")
is_hotspare = ddp_post_create_pool.get("is_hotspare")
max_recovery_rate = ddp_post_create_pool.get("max_recovery_rate")

disks = BaseApp.get_wwn_disks (4, "SSD")
print (disks)
Ddp_Methods.post_create_pool(name_pool, is_alua, block_size, is_hotspare, max_recovery_rate, qty_disks)

После выполнения скрипта можем видеть, что создались два пула на СХД1 и СХД2:

Шаг 2 - создадим по 22 тома на двух СХД:

for i in range (121,132): Ddp_Methods.post_create_lun("DDP2", "RAID-10", 300000000000, f'VOL{i}', "", 0, 0, 0)
for i in range (101,112): Ddp_Methods.post_create_lun("DDP1", "RAID-10", 300000000000, f'VOL{i}', "", 0, 0, 0)

Шаг 3 - создадим репликационные IP ресурсы (адреса) на каждой СХД:

СХД 1:

for i in range (101,112): Network_Methods.post_create_vip("ens11f1", "ens11f1", f'192.168.100.{i}', "255.255.255.0", "DDP1", "repl", None)
for i in range (121,132): Network_Methods.post_create_vip("ens11f1", "ens11f1", f'192.168.100.{i}', "255.255.255.0", "DDP2", "repl", None)

СХД2 – не забываем поменять адрес СХД в файле config:

for i in range (151,162): Network_Methods.post_create_vip("ens11f1", "ens11f1", f'192.168.100.{i}', "255.255.255.0", "DDP1", "repl", None)
for i in range (171,182): Network_Methods.post_create_vip("ens11f1", "ens11f1", f'192.168.100.{i}', "255.255.255.0", "DDP2", "repl", None)

Шаг 4 - создадим репликационные связи между томами для каждого из томов:

for i in range (101,112):   
  payload = {
  "name": f'rpl1ddp{i}',
  "protocol": "C",
  "local_node": {
    "pool_type": "DDP",
    "pool_name": "DDP1",
    "lun_name": f'VOL{i}',
    "vip": f'192.168.100.{i}'
  },
  "remote_nodes": [
    {
    "pool_type": "DDP",
    "pool_name": "DDP1",
    "lun_name": f'VOL{i}',
      "vip": f'192.168.100.{i+50}'
    }
  ]}
  print(payload)
  url = f'{URL}/rrepl/node'
  resp = requests.post(url, data=dumps(payload), headers=HEADERS)
  print (resp.text)

for i in range (121,132):   
  payload = {
  "name": f'rpl2ddp{i}',
  "protocol": "C",
  "local_node": {
    "pool_type": "DDP",
    "pool_name": "DDP2",
    "lun_name": f'VOL{i}',
    "vip": f'192.168.100.{i}'
  },
  "remote_nodes": [
    {
    "pool_type": "DDP",
    "pool_name": "DDP2",
    "lun_name": f'VOL{i}',
      "vip": f'192.168.100.{i+50}'
    }
  ]}
  print(payload)
  url = f'{URL}/rrepl/node'
  resp = requests.post(url, data=dumps(payload), headers=HEADERS)
  print (resp.text)

Шаг 5 - создадим VIP метрокластера (адреса для iSCSI порталов метрокластера).

Для большей наглядности сделаем это в графическом интерфейсе СХД. Естественно, можно сделать это через знакомый нам уже endpoint /api/network/vip.

Шаг 6 - сконфигурируем метрокластер и арбитр в интерфейсе.

Введем IP адреса арбитра и второй СХД:

Шаг 7 - подключим репликационные пары СХД1 к метрокластеру:

for i in range (101,112):   
  payload = {
  "node_ip": f'192.168.100.{i}',
  "name": f'rpl1ddp{i}',
  "metro_ip": "192.168.11.23",
  "metro_mask": 24
  }
  print(payload)
  url = f'{URL}/rrepl/node~connect_metro'
  resp = requests.post(url, data=dumps(payload), headers=HEADERS)
  print (resp.text)
for i in range (121,132):   
  payload = {
  "node_ip": f'192.168.100.{i}',
  "name": f'rpl2ddp{i}',
  "metro_ip": "192.168.11.24",
  "metro_mask": 24
  }
  print(payload)
  url = f'{URL}/rrepl/node~connect_metro'
  resp = requests.post(url, data=dumps(payload), headers=HEADERS)
  print (resp.text)

Для подключения СХД2 к метрокластеру, необходимо отключить VIP метрокластера на СХД1, сконфигурировать арбитр и связь со вторым СХД и, аналогично предыдущему шагу, выполнить скрипт подключения к метрокластеру каждой репликационной пары.

Шаг 8 - подключим репликационные пары СХД2 к метрокластеру:

for i in range (101,112):   
    payload = {
    "node_ip": f'192.168.100.{i+50}',
    "name": f'rpl1ddp{i}',
    "metro_ip": "192.168.9.23",
    "metro_mask": 24
    }
    print(payload)
    url = f'{URL}/rrepl/node~connect_metro'
    resp = requests.post(url, data=dumps(payload), headers=HEADERS)
    print (resp.text)
for i in range (121,132):   
    payload = {
    "node_ip": f'192.168.100.{i+50}',
    "name": f'rpl2ddp{i}',
    "metro_ip": "192.168.9.24",
    "metro_mask": 24
    }
    print(payload)
    url = f'{URL}/rrepl/node~connect_metro'
    resp = requests.post(url, data=dumps(payload), headers=HEADERS)
    print (resp.text)

Далее можно презентовать тома с каждого дискового массива для хостов и пользоваться отказоустойчивым сервисом по хранению данных.

При возникновении необходимости переключить направление репликации метрокластера можно воспользоваться графическим интерфейсом, либо также использовать REST API Post запрос /api/rrepl/node~set_primary.

Подводим итоги

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

Если вас заинтересовали возможности API АЭРОДИСК и вы хотите попробовать использовать REST для управления СХД, все примеры для работы и документация доступна на нашем портале docs.aerodisk.ru.

Чтобы узнать больше про REST API записывайтесь на наш вебинар «ОколоИТ» 12 марта. На нём мы покажем, как пользоваться REST API, попробуем что-нибудь сломать и, естественно, починить в СХД АЭРОДИСК без перерыва сервиса с помощью технологий метрокластера

Источник: https://habr.com/ru/companies/aerodisk/articles/798475/


Интересные статьи

Интересные статьи

Когда дело доходит до обработки ошибок, основной стратегией является прекращение всех вычислений после обнаружения первой погрешности. Обычно это достигается за счет использования исключений. Хотя это...
Вероятно, все уже слышали о Stable Diffusion - модели, способной создавать фотореалистичные изображения на основе текста. Благодаря библиотеке diffusers от HuggingFace, использование этой модели очень...
Кадр из мультфильма «Смешарики: 132 серия (Пылесос)» При проведении различной ad-hoc аналитики или же создания интеграций между DS решением и внешними системами очень часто приходится использовать ...
В прошлой статье я писал про свои ML-модели для оценки отдельных компаний, но вопрос формирования итогового портфеля совсем не затрагивал. В этом посте хочу рассказать...
Бывает так, что приходится сталкиваться с задачами, к решению которых ты вроде бы и не готов, а получить результат надо здесь и сейчас. Знакомо, да? Добро пожаловать в ми...