Перейти к содержанию

REST API документация

SpaceVM предоставляет JSON REST интерфейс, к которому можно обращаться напрямую.

Ресурсо-ориентированный подход

В API используется ресурсо-ориентированный подход. Ниже описаны принципы, которые действуют для всех API SpaceVM:

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

В REST для каждого ресурса определен свой уникальный URL, который формируется по схеме:

http(s)://<адрес контроллера>/<категория ресурса>/<идентификатор ресурса>

Пример запроса узла

GET http://<адрес контроллера>/api/nodes/cdf10fc6-57f8-436c-a031-78ba3ba1ae40

Как видно из примера, URL ресурсов идентифицируется связкой "категория ресурса и идентификатор ресурса".

Набор методов REST

GET

Пример запроса узлов

GET http(s)://<адрес контроллера>/api/nodes/

PUT

Пример изменения статуса сервиса ballooning узла

PUT http(s)://<адрес контроллера>/api/nodes/94450c3e-b452-46b0-af4a-f688c726f054/ballooning/

{
"ballooning": true
}

POST

Пример выключения ВМ

POST http(s)://<адрес контроллера>/api/domains/f348f0d8-e26a-4063-8019-6929b51ca57d/shutdown/

{
"force": true
}

Пример запросов через curl к API

Сначала необходимо получить ключ интеграции.

Get new VM id

VM_ID=$(curl -s -f -S -H "Content-Type: application/json" \
                    -H "Authorization: jwt ${TOKEN}" \
                    http://${VEIL_ADDRESS}/api/domains/?name=${VM_NAME} | jq -r .results[].id)

Clone VM from template

TASK_ID=$(curl -s -f -S -H "Content-Type: application/json" \
                    -H "Authorization: jwt ${TOKEN}" \
                    -d "{\\"node\\":\\"${VEIL_NODE_ID}\\", \\"verbose_name\\":\\"${VM_NAME}\\", \\"datapool\\":\\"${VEIL_DATAPOOL_ID}\\"}" \
                    http://${VEIL_ADDRESS}/api/domains/${TEMPLATE_ID}/clone/?async=1 | jq -r ._task.id)

Waiting for VM creation

until [ "$TASK_STATUS" == "SUCCESS" ]
                  do
                    sleep 10
                    TASK_STATUS=$(curl -s -f -S -H "Content-Type: application/json" \
                    -H "Authorization: jwt ${TOKEN}" \
                    http://${VEIL_ADDRESS}/api/tasks/${TASK_ID}/ | jq -r .status)
                    TASK_PROGRESS=$(curl -s -f -S -H "Content-Type: application/json" \
                    -H "Authorization: jwt ${TOKEN}" \
                    http://${VEIL_ADDRESS}/api/tasks/${TASK_ID}/ | jq -r .progress)
                    echo "Task status is: $TASK_STATUS, progress: $TASK_PROGRESS %"
                  done

Convert template to VM

curl -s -f -S -XPUT -H "Content-Type: application/json" \
                    -H "Authorization: jwt ${TOKEN}" \
                    -d "{\\"template\\":\\"false\\"}" \
                    http://${VEIL_ADDRESS}/api/domains/${VM_ID}/template/  

Add authorized key

curl -s -f -S -XPOST -H "Content-Type: application/json" \
                    -H "Authorization: jwt ${TOKEN}" \
                    -d "{\\"create_user\\":false, \\"ssh_user\\":\\"${VM_USERNAME}\\", \\"ssh_key\\":\\"${PUBLIC_KEY}\\"}" \
                    http://${VEIL_ADDRESS}/api/domains/${VM_ID}/ssh-inject/  

Start VM

curl -s -f -S -XPOST -H "Content-Type: application/json" \
                    -H "Authorization: jwt ${TOKEN}" \
                    http://${VEIL_ADDRESS}/api/domains/${VM_ID}/start/

Get VM ip address

VM_IP=$(curl -s -f -S -H "Content-Type: application/json" \
                    -H "Authorization: jwt ${TOKEN}" \
                    http://${VEIL_ADDRESS}/api/domains/?name=${VM_NAME} | jq -r .results[].guest_utils.ipv4[0])  

Backup VM

TASK_ID=$(curl -s -f -S -XPOST -H "Content-Type: application/json" \
                    -H "Authorization: jwt ${TOKEN}" \
                    -d "{\\"domain\\":\\"$VM_ID\\", \\"datapool\\":\\"${VEIL_DATAPOOL_ID}\\", \\"compress\\":true, \\"limit_days\\":1}" \
                    http://${VEIL_ADDRESS}/api/domains/backup/?async=1 | jq -r ._task.id)  

Remove VM

curl -s -f -S -H "Content-Type: application/json" \
                    -H "Authorization: jwt ${TOKEN}" \
                    -d "{\\"full\\":\\"true\\"}" \
                    http://${VEIL_ADDRESS}/api/domains/${VM_ID}/remove/

Пагинация

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

Чтобы получить нужную страницу с результатами, в запросе следует передать параметры:

  • limit - количество результатов на странице. Доступные значения: от 0 до 100. Значение по умолчанию: 100.

  • offset - сдвиг результатов относительно 0. Доступные значения: от 0 до общего количества элементов.

Пример запроса 100 событий со сдвигом 200

GET http(s)://<адрес контроллера>/api/events/?limit=100&offset=200

Обработка ошибок

Если операция завершилась успешно, сервер возвращает клиенту статус OK. Если в ходе выполнения операции возникла ошибка, сервер возвращает сообщение с описанием ошибки.

Список возможных ошибок

HTTP-код Описание ошибки
400 Клиент некорректно указал параметры запроса.
401 Нет прав или ошибка аутентификации.
403 Нет прав или ошибка аутентификации.
404 Запрашиваемый ресурс не найден.
405 Метод не разрешен
500 Ошибка сервера при обработке запроса.
503 Недоступность SMTP сервера.

Описание отчетов об ошибках

Структура отчетов всех ошибок представляет собой JSON с двумя фиксированными (code, msg_key) и одним динамическим ключами.

code - используется для автоматической обработки ошибок и представляет собой номер или 'invalid', если не задан.

msg_key - содержит имя динамического ключа ошибки. Используется для прямого доступа к сообщению ошибки.

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

  1. различные общие ошибки, возникающие во время работы системы (detail);

  2. ошибки данных, введенных пользователем в форму, но не относящиеся к определенным полям (non_field_errors);

  3. ошибки данных, введенных пользователем в поля форм (ключом является имя поля).

Сообщения ошибок первой категории (1) отображаются в верхнем правом углу главного окна интерфейса. Пример структуры (ключ detail):

{
    "errors": [
        {
            "detail": "Запрашиваемое количество процессоров (2) для виртуальной машины должно быть меньше или равно максимальному количеству процессоров (1).",
            "code": "invalid"
            "msg_key": "detail",
        }
    ]
}

Сообщения ошибок второй категории (2) отображаются в нижней части окна формы, в котором были введены неверные данные. Пример структуры (ключ non_field_errors):

{
    "errors": [
        {
            "non_field_errors": "Тип пула данных Базовый локальный пул данных узла 192.168.20.120 (fb283687-555e-411b-aa74-a5edd1930c48) должен быть одним из следующих: lvm, thin_lvm, shared_lvm."
            "code": "invalid"
            "msg_key": "non_field_errors"
        }
    ]
}

Сообщения ошибок третьей категории (3) отображаются непосредственно под полем, в котором были введены неверные данные. Пример (ключ username):

{
    "errors": [
        {
            "username": "Это поле обязательно.",
            "code": "required",
            "msg_key": "username"
        }
    ]
}

Работа с операциями

Все операции, изменяющие состояние ресурса, имеют асинхронную сигнатуру (добавляется ?async=1 в конце запроса). При вызове таких операций сервер возвращает объект data_with_entity или объект data_without_entity. Используйте эти объекты, чтобы отслеживать статус операций.

Многие операции поддерживают механизм идемпотентности. Это означает, что при многократном вызове одной и той же операции сервер выполнит эту операцию один раз. Ниже в разделе Идемпотентность показано, как работает механизм идемпотентности, а также приведены примеры его использования.

Объекты ответы от задач data_with_entity и data_without_entity

Каждая операция, которая запускает задачу (просмотр осуществляется в журнале задач), приводит к созданию объекта Задачи. Этот объект содержит информацию об операции: статус, идентификатор, время вызова и т. д.

data_with_entity - словарь с ключом _task, где значением является объект задачи, и ключом _entity, где значением является объект сущности.

data_without_entity - словарь с ключом _task и значением объекта задачи.

Идемпотентность

Space VM поддерживает механизм идемпотентности. Идемпотентная операция — это операция, которая при многократном вызове возвращает один и тот же результат.

По умолчанию некоторые операции в API не являются идемпотентными. Например, операции, которые изменяют состояние ресурсов. Для обеспечения их идемпотентности в теле запросов необходимо передавать ключ idempotency_key. В теле следует указать uuid-строку — ее необходимо сформировать самостоятельно. У каждой операции должен быть свой uuid.

Примечание

Обратите внимание, что следует использовать UUID версии 4.

Когда сервис получит запрос с ключом idempotency_key в теле, он проверит, была ли ранее создана задача с таким uuid. Если операция была создана, сервер вернет объект data_with_entity или data_without_entity с текущим статусом этой операции. Если операции с таким uuid не найдено, сервис начнет ее выполнение.

Примеры

На примерах ниже показано, как использовать механизм идемпотентности при работе с API SpaceVM.

Пример запуска ВМ

Например, вы отправили запрос на запуск виртуальной машины:

  POST http(s)://<адрес контроллера>/api/domains/f348f0d8-e26a-4063-8019-6929b51ca57d/start/

  {
  "force": true,
  "idempotency_key": "c1700de3-b8cb-4d8a-9990-e4ebf052e9aa"  
  }

Если снова отправить этот запрос c тем же idempotency_key, сервер не будет выполнять повторный запуск машины. Вместо этого сервер вернет объект ВМ.

Пример гонки

Данный пример демонстрирует ситуацию, в которой возникает состояние гонки.

Пусть с одного клиента был отправлен запрос на остановку запущенной виртуальной машины. Ключ idempotency_key при этом не указан.

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

В это время другой клиент заново запускает эту виртуальную машину (например, через Web-интерфейс).

Но когда у первого клиента появится доступ к интернету, он повторно отправит запрос на остановку машины. Так как ключ idempotency_key не используется, виртуальная машина, которая необходима второму клиенту, будет остановлена.

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

Swagger

Swagger.yaml доступен по url http://{controller or node ip}/api/schema/.

Swagger-ui доступен по url http://{controller or node ip}/api/schema/swagger-ui/.

Swagger-redoc доступен по url http://{controller or node ip}/api/schema/redoc/.

Описание API контроллера

Описание API узла