Infrastructure

GLPI — Renommer des entités en masse via MariaDB

Comment identifier et corriger en masse des occurrences d'un label obsolète dans GLPI via des requêtes MariaDB directes, sur deux instances Docker simultanément.

Table des matières

Après une réorganisation interne, plusieurs labels dans GLPI doivent être renommés — entités, lieux, catégories, etc. Plutôt que de tout modifier manuellement dans l’interface, voici comment procéder via MariaDB directement sur des instances Docker.

Contexte

Deux instances GLPI tournent en Docker avec des bases MariaDB distinctes. L’objectif : renommer un label (ANCIEN) en NOUVEAU dans toutes les tables concernées, sans toucher aux comptes utilisateurs.

Audit préalable — identifier toutes les occurrences

Avant de modifier quoi que ce soit, un audit complet sur toutes les tables susceptibles de contenir le label :

docker exec glpi-db mysql -u root -p'PASS' glpidb -e "
SELECT 'glpi_entities'      as tbl, id, name FROM glpi_entities      WHERE name LIKE '%ANCIEN%' OR completename LIKE '%ANCIEN%'
UNION ALL
SELECT 'glpi_locations',    id, name FROM glpi_locations    WHERE name LIKE '%ANCIEN%' OR completename LIKE '%ANCIEN%'
UNION ALL
SELECT 'glpi_groups',       id, name FROM glpi_groups       WHERE name LIKE '%ANCIEN%' OR completename LIKE '%ANCIEN%'
UNION ALL
SELECT 'glpi_itilcategories', id, name FROM glpi_itilcategories WHERE name LIKE '%ANCIEN%' OR completename LIKE '%ANCIEN%'
UNION ALL
SELECT 'glpi_profiles',     id, name FROM glpi_profiles     WHERE name LIKE '%ANCIEN%'
UNION ALL
SELECT 'glpi_rules',        id, name FROM glpi_rules        WHERE name LIKE '%ANCIEN%'
UNION ALL
SELECT 'glpi_knowbaseitems', id, name FROM glpi_knowbaseitems WHERE name LIKE '%ANCIEN%'
UNION ALL
SELECT 'glpi_computers',    id, name FROM glpi_computers    WHERE name LIKE '%ANCIEN%'
"
Éviter les faux positifs

Les noms de machines réels (ex: LRFANCIENXX) ne doivent pas être renommés — ils correspondent à des hostnames réseau. Filtrez par table et par contexte, pas en UPDATE global aveugle.

Sauvegarde avant modification

# Toujours sauvegarder avant toute modification directe en base
docker exec glpi-db mysqldump -u root -p'PASS' glpidb \
  > ~/glpidb_avant_renommage_$(date +%Y%m%d).sql

# Vérifier la sauvegarde
ls -lh ~/glpidb_avant_renommage_*.sql

Modification — entités et lieux

docker exec -it glpi-db mysql -u root -p'PASS' glpidb
-- Renommer dans les entités (name ET completename)
UPDATE glpi_entities SET
  name         = REPLACE(name,         'ANCIEN', 'NOUVEAU'),
  completename = REPLACE(completename, 'ANCIEN', 'NOUVEAU')
WHERE name LIKE '%ANCIEN%' OR completename LIKE '%ANCIEN%';

-- Renommer dans les lieux
UPDATE glpi_locations SET
  name         = REPLACE(name,         'ANCIEN', 'NOUVEAU'),
  completename = REPLACE(completename, 'ANCIEN', 'NOUVEAU')
WHERE name LIKE '%ANCIEN%' OR completename LIKE '%ANCIEN%';

-- Vérification immédiate
SELECT id, name, completename FROM glpi_entities WHERE name LIKE '%NOUVEAU%';
SELECT id, name FROM glpi_locations WHERE name LIKE '%NOUVEAU%';

Problème rencontré — completename des lieux enfants

Après le premier renommage, l’entité racine était correcte mais les lieux enfants conservaient encore l’ancien label dans leur completename :

AVANT : Bâtiment A > Salle ANCIEN > Bureau 12
APRÈS (partiel) : Bâtiment A > Salle NOUVEAU > Bureau 12  ← name OK
                  Bâtiment A > Salle ANCIEN > Bureau 12   ← completename pas mis à jour !

Fix :

-- Corriger le completename des enfants
UPDATE glpi_locations
SET completename = REPLACE(completename, 'ANCIEN', 'NOUVEAU')
WHERE completename LIKE '%ANCIEN%';

-- Vérifier qu'il ne reste aucune occurrence
SELECT COUNT(*) as reste
FROM glpi_locations
WHERE completename LIKE '%ANCIEN%';
-- Attendu : 0

Reconstruction de l’arbre (si nécessaire)

Sur certaines versions de GLPI, la commande CLI de reconstruction de l’arbre n’existe pas :

# Cette commande n'existe PAS sur GLPI 10/11
docker exec glpi-app php bin/console glpi:database:fix_item_tree --itemtype=Entity
# → "Command not defined"

Vérification SQL directe à la place :

-- Vérifier qu'il n'y a pas de sous-entités orphelines
SELECT id, name, completename, entities_id
FROM glpi_entities
WHERE entities_id = <ID_ENTITE_RENOMMEE>;
-- Si Empty set : pas d'enfants, rien à propager

Script réutilisable pour deux instances

#!/bin/bash
# rename_glpi_label.sh — Renommer un label sur N instances GLPI Docker

ANCIEN="$1"
NOUVEAU="$2"
PASS="VOTRE_PASS_MARIADB"

for DB_CONTAINER in glpi-db-instance1 glpi-db-instance2; do
  DB_NAME=$(docker exec "$DB_CONTAINER" \
    mysql -u root -p"$PASS" -e "SHOW DATABASES;" 2>/dev/null | grep glpi | head -1)

  echo "=== $DB_CONTAINER ($DB_NAME) ==="

  # Backup
  docker exec "$DB_CONTAINER" mysqldump -u root -p"$PASS" "$DB_NAME" \
    > "/tmp/${DB_CONTAINER}_backup_$(date +%Y%m%d_%H%M).sql"

  # Update
  docker exec "$DB_CONTAINER" mysql -u root -p"$PASS" "$DB_NAME" -e "
    UPDATE glpi_entities SET
      name = REPLACE(name, '$ANCIEN', '$NOUVEAU'),
      completename = REPLACE(completename, '$ANCIEN', '$NOUVEAU')
    WHERE name LIKE '%${ANCIEN}%' OR completename LIKE '%${ANCIEN}%';

    UPDATE glpi_locations SET
      name = REPLACE(name, '$ANCIEN', '$NOUVEAU'),
      completename = REPLACE(completename, '$ANCIEN', '$NOUVEAU')
    WHERE name LIKE '%${ANCIEN}%' OR completename LIKE '%${ANCIEN}%';
  "

  echo "Done."
done
chmod +x rename_glpi_label.sh
./rename_glpi_label.sh ANCIEN NOUVEAU

Vérification finale dans l’interface

Après les modifications SQL, vérifiez dans GLPI :

  • Administration → Entités → le nouveau label est affiché
  • Parc → (un asset quelconque) → le lieu affiche le nouveau label
  • Les tickets existants référencent correctement le nouveau label
Pas de cache à vider

GLPI lit directement le completename depuis la base à chaque affichage — pas de cache applicatif à invalider après un UPDATE SQL.

Comments