Организации и местоположения в GLPI: полное руководство

Техническое руководство по организациям и местоположениям в GLPI: разница между разделением данных и картой физического пространства, как GLPI хранит дерево (glpi_entities, sons_cache, is_recursive), диагностический SQL и практические ловушки, которые проявляются только в среде с несколькими организациями.

В этой статьеРазделов: 7

Организации и местоположения в GLPI выглядят как одно и то же «дерево», но решают противоположные задачи: организация разделяет данные и права; местоположение — лишь физическая привязка. Путать их или проектировать иерархию организаций после того, как данные уже внесены, — источник переделок, которые стоят дней работы. Это руководство показывает, как GLPI хранит эти деревья в базе, даёт пошаговый план проектирования структуры и описывает ловушки, которые проявляются только при сопровождении сред с несколькими организациями.

Организация, местоположение и группа: кто за что отвечает

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

МеханизмРазделяет права?Иерархический?Что начинает видеть пользовательТипичное применение
ОрганизацияДа (данные и доступ)ДаТолько данные своей организацииФилиал, клиент MSP, изолированный отдел
МестоположениеНетДаНичего не меняется — это лишь физическая меткаЗдание, этаж, помещение, стойка, дата-центр
ГруппаЧастично (заявки)ДаЗаявки, назначенные своей группеКоманда поддержки, squad, дежурство

Практическое правило: организация — это граница конфиденциальности, местоположение — физическая карта актива, группа — очередь работы. Если вопрос звучит как «кто может это видеть», ответ почти всегда — организация; местоположение никогда ничего ни от кого не скрывает.

Как GLPI хранит дерево организаций

Экран Администрирование > Организации — это оболочка над таблицей glpi_entities. Каждая строка указывает на родителя через столбец entities_id, хранит полный путь в completename и глубину в level. Два незаметных столбца — sons_cache и ancestors_cache — хранят предвычисленное дерево в сериализованном виде; именно из них читают фильтры видимости, а не из рекурсивного JOIN во время запроса.

-- Arvore de entidades: pai, nivel e caminho completo
SELECT e.id,
       e.name         AS entidade,
       e.completename AS caminho,
       e.level        AS nivel,
       pai.name       AS entidade_pai
FROM   glpi_entities e
LEFT   JOIN glpi_entities pai ON pai.id = e.entities_id
ORDER  BY e.completename;

completename («Matriz > TI > Suporte») — это то, что отображается в селекторах и отчётах; level ускоряет запросы видимости. Запомните эти два имени: по completename вы проверяете дерево, а по level GLPI определяет область видимости, не сканируя всю таблицу.

Наследование: что спускается к дочерним (и что нет)

Дочерняя организация не наследует данные родительской автоматически — она наследует конфигурацию, помеченную как рекурсивная. Категории, SLA, бизнес-правила, шаблоны уведомлений и местоположения несут пару (entities_id, is_recursive): чтобы действовать во всём дереве, объект должен находиться в корневой организации (entities_id = 0) с is_recursive = 1. Категория, созданная внутри дочерней организации, остаётся привязанной к ней, и соседние организации её не видят.

-- Categorias ITIL que NAO estao compartilhadas para toda a arvore
-- (um item global correto tem entities_id = 0 e is_recursive = 1)
SELECT id, name, entities_id, is_recursive
FROM   glpi_itilcategories
WHERE  NOT (entities_id = 0 AND is_recursive = 1);

Типичная ошибка — завести категорию ITIL «только для этого клиента», а потом обнаружить, что половина операции её не видит. При сопровождении мы выполняем эту проверку перед любым go-live с несколькими организациями: объект, который должен быть глобальным, но не находится в (0, рекурсивно), — это баг, ждущий первой заявки.

Пошагово: спроектируйте структуру до данных

  1. Перечислите реальные границы конфиденциальности (кто НЕ должен видеть что). Каждая жёсткая граница становится организацией; всё остальное — местоположение или группа.
  2. Нарисуйте дерево на бумаге максимум с тремя уровнями. Глубина взимает плату в каждом селекторе и отчёте.
  3. Создавайте организации через интерфейс, сверху вниз, — никогда через SQL (см. ловушки).
  4. Настройте в корне то, что является общим (категории, SLA, уведомления), отметив is_recursive; в дочернюю организацию опускайте только то, что относится исключительно к ней.
  5. Только после этого заводите пользователей, активы и заявки. Перемещать данные между организациями потом дорого, и это тянет за собой вложения.

Местоположения: физическая иерархия и поле, о котором все забывают

Таблица glpi_locations иерархична за счёт собственного locations_id (родитель), но каждое местоположение также принадлежит организации (entities_id) и имеет is_recursive. Местоположение, созданное внутри дочерней организации, не появляется в других организациях, если оно не рекурсивное, — тот же механизм, что и у категорий. А значение 0 в locations_id не равно null: это сигнальное значение «нет местоположения».

-- Computadores sem localizacao definida, por entidade
SELECT e.completename AS entidade,
       COUNT(*)       AS sem_localizacao
FROM   glpi_computers c
JOIN   glpi_entities  e ON e.id = c.entities_id
WHERE  c.locations_id = 0   -- 0 = nenhuma (sentinela), nao NULL
  AND  c.is_deleted   = 0
GROUP  BY e.completename
ORDER  BY sem_localizacao DESC;

Инвентаризация без местоположений — тихий паттерн, который взрывается при первом физическом инциденте («в какой стойке это стоит?»). Запрос выше становится индикатором гигиены CMDB, который мы отслеживаем по организациям, а не сюрпризом посреди ночи.

Практические ловушки

Худшая из всех — создавать организацию прямо в базе через SQL. Строка добавляется, но sons_cache и ancestors_cache родителя не пересчитываются, а поскольку фильтры видимости читают из этих кешей, организация становится невидимой для getSonsOf(). Симптом жестокий: организация есть в таблице, видна в SELECT, но пропадает из селекторов и дерева в интерфейсе. Мы на собственном горьком опыте научились никогда не создавать организацию через INSERT: кеши пересчитывает именно создание через экран. Если устаревший импорт уже прошёл через SQL, исправление — открыть и сохранить каждую организацию через интерфейс, чтобы принудительно пересчитать дерево.

  • Считать организацию 0 пустой — корневая организация имеет id = 0, и это ДОПУСТИМЫЙ id. Код и интеграции, проверяющие if (!entities_id), по ошибке отбрасывают корень; в компонентах select2 значение корня — "" (пустая строка), а не "0".
  • Документ, пропадающий при перемещении заявки — вложение (Document_Item) требует, чтобы документ находился в той же организации, что и заявка. Перемещение заявки в другую организацию без документа ломает доступ к вложению.
  • Общее местоположение без рекурсии — создать стойку или помещение в дочерней организации в расчёте, что головная его увидит: без is_recursive каждая организация видит только свои местоположения.
  • Слишком много организаций — каждая организация умножает конфигурацию (категории, SLA, уведомления, назначение профилей по организациям). Десять почти одинаковых организаций стоят в десять раз больше в сопровождении. Если единственное различие между двумя подразделениями — отчёт, используйте группу или местоположение, а не организацию.

Чек-лист организационной структуры

  1. Определите границы конфиденциальности до того, как трогать GLPI; только они становятся организациями.
  2. Ограничьте дерево организаций тремя уровнями глубины.
  3. Создавайте организации через интерфейс, никогда через SQL.
  4. Настраивайте общее в корне с is_recursive = 1; опускайте вниз только исключительное.
  5. Считайте id и locations_id, равные 0, допустимым значением, а не пустым.
  6. Перед каждым go-live запускайте проверки глобальных объектов без общего доступа и активов без местоположения.

Нужно спроектировать (или спасти) структуру с несколькими организациями без переделок либо привязать местоположения к карте? NexTool внедряет и сопровождает среды GLPI с несколькими организациями, проверяя дерево от начала до конца, а модуль Geolocation выводит ваши местоположения на карту. Свяжитесь с нашей командой внедрения и сопровождения.


Проверено командой NexTool Solutions.

Часто задаваемые вопросы

Организация разделяет данные и права: она определяет, кто что видит (заявки, активы, пользователей), и является основой для работы с несколькими клиентами и филиалами. Местоположение — лишь физическая привязка (здание, этаж, помещение, стойка) и ничего ни от кого не скрывает. У организации может быть несколько местоположений; местоположение никогда не управляет доступом.

Потому что таблица glpi_entities хранит предвычисленное дерево в столбцах sons_cache и ancestors_cache, а фильтры видимости читают из этих кешей. Прямой INSERT не пересчитывает кеши, поэтому организация становится невидимой для getSonsOf(): она есть в таблице, видна в SELECT, но пропадает из селекторов и дерева в интерфейсе. Всегда создавайте через экран Администрирование > Организации, который пересчитывает кеши.

Только если код считает 0 пустым значением. Id 0 — это корневая организация, и это ДОПУСТИМОЕ значение. Интеграции, выполняющие if (!entities_id), по ошибке отбрасывают корень. В компонентах select2 значение корня — пустая строка (""), а не "0". Та же логика действует для locations_id = 0, что означает «нет местоположения», а не null.

Объект должен находиться в корневой организации (entities_id = 0) с is_recursive = 1. Именно пара (entities_id, is_recursive) заставляет конфигурацию спускаться к дочерним. Категория, созданная внутри дочерней организации, остаётся привязанной к ней, и соседние организации её не видят. Перед go-live с несколькими организациями выполните SELECT, который выведет глобальные объекты, не находящиеся в (0, рекурсивно).

Нет. Отмечайте is_recursive только тогда, когда местоположение общее для нескольких организаций (например, центральный дата-центр, используемый несколькими филиалами). Местоположение, относящееся к одной организации, остаётся без рекурсии, чтобы не засорять остальные. Без is_recursive каждая организация видит только свои собственные местоположения.

Нужна помощь?