Коротко. Раздел «Ресурсы» в GUI рисует стойку по данным модели, и первым делом читает location.serial у локации типа RACK. Если серийника нет, контроллер падает на charAt of null, страница остаётся пустой — при этом плитка dashboard зелёная, узлы ONLINE, события молчат. Лечится записью серийника стойки в модель и перезапуском samurai, а не переустановкой и не правкой бандла.
Симптом
- Меню «Ресурсы» открывается, но стойка и узлы не отрисованы: пустое поле, иногда белая страница.
- Dashboard при этом живой: плитка кластера зелёная, глобальное здоровье считается, события читаются.
- В списке машин всё на месте: узлы
ONLINE/CONFIGURED, роли назначены. - В
samurai.logповторяется:ERROR [configuration] Cannot read property 'charAt' of nullсо стеком вtachi-service-configuration/configurationService.jsи рядомCould not get GUI version. - Свитч в стойке не рисуется — но это отдельная деталь: если объекта
networkswitchв модели нет, свитч не появится и после починки серийника.
Что проверить первым (read-only)
Модель — по mTLS, сертификаты продукта root-only, поэтому запросы на узле, root.
-
Серийник стойки — главная проверка:
bash sudo curl -sk --cert /opt/ampli/cfg/marvin/ssl/machine.cert \ --key /opt/ampli/cfg/marvin/ssl/machine.key \ https://127.0.0.1:8443/model/location/ \ | jq '.["location"][] | {name, locationtype, serial}'Ожидается: у локацииlocationtype = RACKполеserialнеnull.null— причина найдена. -
Что говорит samurai:
bash sudo grep -c "charAt' of null\|charAt of null" /opt/ampli/var/log/samurai/samurai.log sudo grep -m3 -n 'Could not get GUI version' /opt/ampli/var/log/samurai/samurai.logОжидается 0 совпадений. Счётчик больше нуля подтверждает, что UI падает на чтении свойства, а не на данных о железе. -
Живы ли данные, из которых рисуется стойка:
bash sudo curl -sk --cert /opt/ampli/cfg/marvin/ssl/machine.cert \ --key /opt/ampli/cfg/marvin/ssl/machine.key \ "https://127.0.0.1:8443/model/machine/?fields=name,role,rackunit,status" | jqОжидается: машины с ролью (неnull) и статусомONLINE. Пустой список илиrole=null— другая проблема (модель без ролей), не эта. -
Есть ли свитч в модели — почему стойка может остаться неполной:
bash sudo curl -sk --cert /opt/ampli/cfg/marvin/ssl/machine.cert \ --key /opt/ampli/cfg/marvin/ssl/machine.key \ https://127.0.0.1:8443/model/networkswitch/ | jq 'length'0— свитч не рисуется, это данные, а не дефект UI. -
Отвечает ли endpoint, который дергает UI (на узле,
root):bash sudo curl -sk --cert /opt/ampli/cfg/marvin/ssl/machine.cert \ --key /opt/ampli/cfg/marvin/ssl/machine.key \ https://127.0.0.1:8443/api/resources/machines/hierarchy -w '\nHTTP=%{http_code}\n' | tail -3Ожидается200и JSON с иерархией. Если здесь ошибка, а модель читается — смотреть samurai, а не модель.
Причина
Страница «Ресурсы» рисуется Angular-директивой resourcesRack. Порядок в контроллере:
getRackSummaryById(rack.id)→ список узлов (switches+machines);- по каждому узлу
getNodeDetails→getNodeById; - решается, жёсткая раскладка по юнитам или свободная сортировка (по наличию
rackunit); - узлы раскладываются по типам (
SWITCH,SERVER,STORAGE/COMBINED,ENCLOSURE).
На этом пути UI читает версию GUI и серийник локации — location.serial.charAt(...). Если serial равен
null, вызов падает с TypeError: Cannot read property 'charAt' of null; директива не дорисовывает
разметку, и раздел остаётся пустым. Dashboard использует другие данные, поэтому он и остаётся зелёным:
проблема не в здоровье кластера, а в одном поле модели.
Почему поля не было: серийник стойки — вход очереди установки. При настройке площадки его кладёт
скрипт network_config_s1.py (параметр --rack_serial) в location.serial. В вендорском примере очереди
location.json поле serial у стойки присутствует; в нашей очереди его не было — значит, шаг настройки
локации был пропущен. Продукт при этом не считает это ошибкой установки: install-ng завершается, машины
поднимаются, а дефект проявляется только в UI.
Гипотеза, которая проверяется так же: если serial заполнен, а страница всё равно пуста, смотреть
rackunit — при частично заданных rackunit раскладка идёт «свободной» сортировкой, и часть узлов может
не попасть на картинку. Доказательство — список машин с rackunit и предупреждение в шаблоне про
несовпадение физического положения (актуально для платформ с двумя модулями в корпусе).
Решение (штатное)
-
Взять серийник с железа. Источник —
Chassis Serialведущей ноды (FRU через IPMI), а не документы и не «похожее» значение. Ожидается строка того же формата, что у остальных узлов площадки. -
Снять бэкап документов модели вне каталога продукта —
location.jsonиenvironment.json(каталог вида/home/marvin/model-bak-<дата>/). Бэкап внутри каталога продукта не годится: правки модели и апгрейды его перетирают. -
Записать серийник в локацию стойки — штатный
PUTв модель:bash sudo curl -sk --cert /opt/ampli/cfg/marvin/ssl/machine.cert \ --key /opt/ampli/cfg/marvin/ssl/machine.key \ -X PUT -H 'Content-Type: application/json' \ -d '{"serial":"<RACK_SERIAL>"}' \ https://127.0.0.1:8443/model/location/<RACK_GUID>/Ожидается200. Тело безContent-Type: application/jsonдаёт400— это ошибка запроса, не модели. -
Перезапустить samurai, чтобы сбросить кэш иерархии:
bash sudo /etc/init.d/marvinservices restart samuraiВажно: действиеapplication/<samurai>/action/configure/процесс не перезапускает — нужен именно рестарт службы. -
Открыть GUI → Ресурсы и убедиться, что стойка отрисована, узлы на своих местах.
Если штатный путь недоступен
Не штатно, временная мера. Если серийник получить нельзя (нет доступа к BMC, FRU нечитаем), допустимо записать временное значение, чтобы UI перестал падать, и пометить его как временное в реестре обходов. Такое значение нельзя выдавать за инвентарный номер: оно попадёт в отчёты и в сравнение с железом, поэтому план замены — получить серийник штатно (IPMI/FRU) и перезаписать поле.
Чего не делать: не править бандл samurai (sed по статике) — это слетает при апгрейде и ломает целостность
бандла; не подменять .gz-соседей статики; не переустанавливать кластер из-за пустой страницы.
Проверка
GET /model/location/→ у локацииRACKполеserialнеnullи совпадает сChassis Serial.- В
samurai.log0 новыхcharAt of nullпосле рестарта (считать до/после). GET /api/resources/machines/hierarchy→200и непустая иерархия.- GUI → «Ресурсы»: стойка отрисована, узлы присутствуют, статусы совпадают с моделью.
- Dashboard по-прежнему зелёный; новых событий нет.
Профилактика
- Приёмка по факту, а не по коду возврата: среди проверок —
location.serialнеnull, узлы с ролями, свитч в модели. См. Чек-лист подготовки к установке. - Очередь установки должна нести серийник стойки. Проверять
location.jsonдо прогона, а не после. - Не путать серийники:
Chassis Serial(корпус) иProduct Serial(изделие) — разные поля; для стойки берётся корпусный. - Рестарт samurai — только штатной службой; после правок модели UI читает кэш, и без рестарта можно решить, что правка «не применилась».
- Держать бэкапы модели вне каталога продукта перед любыми
PUT.
Источники и дата
- Quantum, Manage System Settings (ActiveScale 7.3): https://qsupport.quantum.com/kb/flare/Content/ActiveScale/Software/Content/Admin/09_Manage_System_Settings.htm (дата доступа: 2026-11-07).
- Наша практика, обезличено: пустая страница «Ресурсы» на стенде — в
samurai.logcharAt of nullиз-заlocation.serial = null; лечилосьPUTсерийника стойки и рестартом samurai. - Обновлено: 2026-11-07.