Pull to refresh

API виртуальных машин и REST

Reading time 3 min
Views 2.2K
trivia: REST и виртуальные машины не совместимы.

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

Итак,
тезис 1: REST хорошо, *-RPC (например, XML-RPC, JSON-RPC) — плохо.
тезис 2: Т.к. REST хорошо, его нужно использовать для управления виртуальными машинами (в частности, в облаке).

На первый взгляд так и есть. Например, если мы хотим поменять атрибут (допустим, атрибут «загрузочный диск») для виртуальной машины, то мы пишем:

PUT .../vm333/disk1/bootable
enable=true
PUT .../vm333/disk1/bootable
enable=false

Или даже так:
POST /vm/333/disk1/bootable
DELETE /vm333/disk1/bootable

Если мы хотим создать диск, мы говорим POST /vm333/disk2 и передаём атрибуты (вроде размера или хранилища).

Однако, это хорошо только до того момента, пока наша инфраструктура напоминает записи в БД.

А теперь простой вопрос: как в REST будет выглядеть команда перезагрузки виртуальной машины? Ведь состояние машины не меняется, как была running, так и остаётся. Очевидно, что перезагрузка не идемпотентный вызов, то есть мы должны говорить POST. Но 'POST что и куда?'. Заметим, даже shutdown/start вполне себе укладываются в POST power-state'а. Но вот ребут — который нарушает логику «имманентности» состояния объекта в БД и приводит нас в жестокий императивный мир — увы, не укладываются. Аналогичные проблемы будут при операции 'install' (запуск установки OS).
Причина тут куда более глубокая, чем просто «не очень хорошо получается». Извините за слово «онтология», но эта причина — онтологическая.

Суть проблемы

Объекты в облаке (да и вообще, в хозяйстве по управлению серверами) — не строчки в БД. Они живут своей жизнью, и то, что видно в нашей БД (к которой мы и пытаемся приделать REST-интерфейс) — лишь отображение этой жизни.

Часть атрибутов в БД — это авторитетные значения. Например, если мы сказали, что эта машина называется 'foobar', то она именно так и называется. И мнение негров не доставляет шерифу удовольствия. Однако, например, рассмотрим состояние 'running'. Ведь это не «атрибут» БД по управлению виртуальной машиной. Это _её_, её ЛИЧНОЕ состояние. Как она захочет, так и будет. Захочет падать при старте — и вы не сможете никакими силами её через запись атрибута power-state в значение 'running' сделать 'running'. Аналогично с многими другими вопросами: мы можем сказать «сделай себе 32 Мб памяти», но виртуальная машина может посмотреть на память занятую ядром в 48Мб и сказать «спасибо, не надо» — и остановиться на 64Мб. Мы записали атрибут «32 мб», а там «64Мб». И самое что ужасное, это не ситуация «не смогла поставить», отказ в транзакции. Это «что смогла, то сделала». Было 128Мб, сказали сделать 32, стало 64. Да ещё и с задержкой — сначала 96Мб, потом 82, и только через минут 20 — 64. Более того, если мы совсем напряжёмся и таки заставим машину (точнее, машина «не подумает головой»), то мы вместо 32Мб получим power-state=crashed. Вместо ожидаемых 32Мб. Нонсенс. Не база данных, а порнография какая-то.

Причина в том, что наша БД, в которую мы пишем — не есть база данных. Это наши авторитетные значения (про которые виртуальная машина ни сном ни духом, типа своего названия и номера — и тут это настоящая БД без малейшего сомнения), это наши ограничения для машины (которые машина может попытаться обойти, но у неё не получится, тоже БД) и это наши пожелания, которые машина может попытаться исполнить, но у неё может не получиться или получиться не до конца.

Таким образом мы видим противоречие по сути отношений между REST-идеологией отношений с послушной БД и реальным миром.

RPC спасёт мир?

В этом случае куда более разумным выглядит императивный подход — использование любого рода RPC, в котором мы «вызываем» удалённые (императивные) функции и передаём им аргументы.

В этом случае «начали менять одно, получилось другое» выглядит куда более логично. Особенно, если мы вместо vm.set_memory() будем делать vm.send_desired_mem(). Первая команда может сделать ахинею, вторая — никогда. Сказали передать число, передали. А что там дальше будет зависит уже от VM. В этом случае мы решаем онтологическую проблему — признаём у управляемых объектов право на самостоятельность (где можем — разрешаем/запрещаем, где не можем — фиксируем фактическое состояние).

Но RPC справедливо ругают, ибо оно тяжёлое, неудобное и заставляет думать о предметной области, вместо комфортного созерцания отношений в БД.

В этом месте красивый рассказ обрывается и слово предоставляется комментирующим.
Tags:
Hubs:
+20
Comments 44
Comments Comments 44

Articles