Коротко. Установка ActiveScale состоит из трёх независимых процессов с тремя разными маркерами: marvin_install пишет /tmp/marvin_initialize.rc и удаляет себя, install-ng пишет /tmp/.unattended_install_finished с кодом внутри, а задачи живут в состоянии SUCCESS/FAILURE/QUEUED. Код возврата 0 не доказывает результат: часть фаз при неверном входе завершается нулём, ничего не меняя.
1. Почему «EXIT=0» ничего не значит
install-ng устроен так, что main() вызывает фазы; каждая фаза при «мягкой» ошибке логирует
её и возвращает управление. Процесс всегда заканчивает работу через mark_and_exit(rc): пишет
строку кода в маркер и выходит. Функция _error даёт rc=1, штатное завершение — rc=0.
Беда в том, что rc=0 покрывает два разных исхода:
| Исход | Код | Как выглядит дальше |
|---|---|---|
| Фаза выполнила работу | 0 |
объекты в модели появились, гейты проходят |
| Фаза «прошла мимо» (неверный вход, пустая группа политики, лишний флаг) | 0 |
снаружи зелёное, внутри пусто |
Классический пример: -AST без группы политики в dssconfig.yml завершается rc=0, колонка
создаётся пустой, и только следующий -C падает 500 at least one S3 connection is required.
Если смотреть на код первого прогона, всё «хорошо».
Отсюда правило: код возврата — это признак «процесс закончился», а не «работа сделана». Результат подтверждают гейты из статьи о приёмке и проверки ниже.
2. Три маркера установки
2.1 marvin_install (stage 2, initialize)
/usr/bin/marvin_install запускается вручную и сам:
- вызывает initialize.py, затем initialize_marvin.py;
- разворачивает mongodb, marvinweb, marvintaskmgr;
- создаёт /home/marvin/initial_environment.json;
- переносит upgrade-архив в /home/marvin;
- удаляет себя и пишет /tmp/marvin_initialize.rc.
Признаки завершения (все вместе, а не по одному):
ls -l /usr/bin/marvin_install # файла нет — скрипт самоудалился
cat /tmp/marvin_initialize.rc # код возврата initialize
tail -n 20 /opt/ampli/var/log/marvin/deploy.log # в конце — Done
ls -l /home/marvin/initial_environment.json # файл создан
Сервис marvin_install.service продукт не регистрирует — это задумка, а не поломка. Если
запускать через самодельный юнит, не делайте его Type=forking: сломается таймаут.
2.2 install-ng (stage 3)
Единственный надёжный маркер — файл /tmp/.unattended_install_finished. Внутри — строка кода
возврата. Строки DONE_RC в выводе нет, сколько бы её ни искали в логах.
cat /tmp/.unattended_install_finished
Перед каждым повторным прогоном маркер удаляют: rm -f /tmp/.unattended_install_finished.
Иначе старый файл с 0 будет выглядеть как успех нового прогона, которого ещё нет.
2.3 Задачи продукта
Пока идёт установка, часть работы живёт в задачах (taskmgr). Их состояния читаются в GUI
(раздел задач) или через Model API. Практические значения:
| Состояние | Смысл |
|---|---|
SUCCESS |
задача дошла до конца |
FAILURE |
задача упала; смотреть taskmgr/playbooks.log |
QUEUED |
задача ждёт; при падении фазы остаётся висеть |
NOTCONFIGURED |
приложение/узел не сконфигурирован |
Если фаза упала, узел остаётся NOTCONFIGURED, упавшее приложение — тоже NOTCONFIGURED,
остальные подзадачи — QUEUED. Это не «зависло», а остановленный конвейер.
3. pgrep и ложные «жив»
Проверка «процесс жив» ломается на самой себе:
pgrep -f install-ng.py # матчит вашу же строку запуска → ложное «жив»
pgrep -f "[i]nstall-ng.py" # скобки исключают сам pgrep и вашу команду
pgrep -af install-ng.py # покажет, что именно нашлось
pgrep -f ищет по полной командной строке, а вы только что эту строку и набрали. Поэтому в
скриптах и в ручных проверках используют [i]nstall-ng.py: шаблон [i] совпадает с буквой i
в чужой командной строке, но не с текстом самого шаблона.
Второй ложный «жив» — процесс-сирота после обрыва SSH. Маркер при этом не появился, лог не
двигается. Проверка: pgrep -af install-ng.py плюс stat -c %y /opt/ampli/var/log/marvin/install.log
— если mtime не меняется минутами, процесс не работает, а висит.
4. HTTP-коды как маркеры
Часть состояний продукта читается только кодом ответа. Ниже — те, что действительно различают «работает» и «не работает».
| Код | Где | Что значит |
|---|---|---|
307 + Server: Quantum-ActiveScale |
http://127.0.0.1/ (443) |
S3-фронт жив; редирект штатный |
200 |
/model/... на 8443 под root |
Model API отвечает |
000 |
8443 без sudo |
не предъявлен клиентский сертификат, а не «API лёг» |
400 |
пустой GET на 8180 |
iamd жив, ждёт корректный запрос |
200 быстрее 50 мс |
/federated/_status/ |
федерация здорова |
30000 мс / таймаут |
/federated/_status/ |
pymongo topology-hang: порт/конфиг федерации, не «умерла БД» |
404 |
/federated/_status/ |
локация не отрендерена: федеративная БД не создавалась |
400 |
PUT в модель |
нет заголовка Content-Type: application/json |
500 |
-C / политика |
пустая колонка или неверный category политики |
501 |
Tape Connector по 443 |
запрос ушёл не туда (URL без порта → фронт S3) |
403 |
S3-клиент | подпись/часы (SigV4), а не права |
507 |
S3 PUT | политика не влезает в число блоксторов (w+s > N) |
Логика простая: сначала код, потом смысл. 403 при зелёном GUI — это почти всегда часы, а
507 при свободных дисках — политика, а не ёмкость.
5. Коды полевого health-check
Наш скрипт быстрой проверки узла (as-field-health.sh, только чтение, около 30 секунд на узел)
возвращает:
0— ни одногоFAIL;1— есть хотя бы одинFAIL.
[warn] сам по себе прогон не валит: это повод посмотреть, но не поломка. Так сделано намеренно:
иначе скрипт краснел бы на известных ложных тревогах и им перестали бы пользоваться.
6. Ловушки маркеров
- Старый маркер не удалён. Файл
/tmp/.unattended_install_finishedс прошлого прогона даёт «готово» через секунду после старта. Удалять до запуска. - Пустой
install.logпосле полуночи. Это logrotate: смотретьinstall.log.YYYY_*иtaskmgr/playbooks.log, а не делать вывод «лог не пишется». - Код
0у фазы, которая ничего не сделала. Сверять не код, а объекты в модели и гейты. - Маркер без процесса. Файл мог остаться от оборванного прогона; проверять
pgrepи mtime лога одновременно. - «Задача
QUEUED» ≠ «задача идёт». После падения фазы очередь стоит; смотретьtaskmgr/playbooks.logнаTASK [...],PLAY RECAP,failed=.
7. Чек-лист «завершилось ли»
pgrep -f "[i]nstall-ng.py"→ пусто (процесса нет).cat /tmp/.unattended_install_finished→ код есть, и он ожидаемый./opt/ampli/var/log/marvin/install.log→ последняя запись соответствует концу фазы, нет_error./federated/_status/→200быстрее 50 мс.pgrep -c mongod→ по числу кластеров на каждой ноде.- Приложения →
NOTCONFIGURED= 0. - S3 PUT/GET → round-trip, GUI без пустот, новых
CRITICALв событиях нет.
Только после этих семи пунктов прогон считается завершённым.
8. Источники
- Software Documentation Center (7.3) (дата доступа 2026-11-07)
- Наша практика (обезличено): прогоны stage 0–3 на 3-нодных стендах, разбор ложных «жив» и маркеров завершения.