[VCFA 9.X] Forcer la suppression d'une Content Library
Comment supprimer de force une Content Library de son infrastructure à la suite d’un bug ou d’une mauvaise manipulation côté vCenter ?
Ce post fait suite à un souci que j’ai rencontré sur mon infrastructure VCFA 9 qui, rappelons-le, est depuis cette version un mélange de deux anciens produits VMware : VMware Cloud Director et VMware Aria Automation.
Symptômes
Les symptômes sont les suivants :
- La Content Library apparaît avec le statut
Faileddepuis le tenant client. - Un message indique de contacter l’administrateur.

Plusieurs causes peuvent expliquer ce message :
- Un problème de refresh entre VCFA et vCenter. Dans certains cas, un simple nouveau refresh suffit à résoudre le problème.
- Une Content Library supprimée ou modifiée directement dans vCenter au lieu de passer par VCFA. La synchronisation ne peut alors plus se faire correctement.
Dans mon cas, il s’agissait d’une erreur d’administration : la Content Library avait été supprimée directement depuis vCenter au lieu de VCFA.
Diagnostic côté administrateur
Dans un premier temps, j’ai donc suivi le message d’erreur et je me suis connecté au tenant en tant qu’administrateur.
J’ai alors obtenu le message suivant :
[ 75f3e97 ] Erreur interne du serveur
NotFound (com.vmware.vapi.std.errors.not_found) => {
messages = [
LocalizableMessage (com.vmware.vapi.std.localizable_message) => {
id = com.vmware.vdcs.cls-main.library_not_found,
defaultMessage = Library 3fd not found.,
args = [],
params = ,
localized =
}
],
data = ,
errorType = NOT_FOUND
}

L’erreur est ici plutôt claire : VCFA ne retrouve plus la Content Library côté vCenter.
Première tentative : passer par l’API
Pour nettoyer la configuration côté VCFA, mon premier réflexe a été de tenter de passer par l’API du Provider.
Malheureusement, celle-ci refuse l’opération, car la Content Library se trouve dans un état qui ne lui convient pas.
Je vais donc devoir passer directement par la base de données PostgreSQL de mon instance VCFA.
Deuxième tentative : passer par la base de données
⚠️ Attention : les étapes suivantes peuvent avoir un impact important sur votre infrastructure.
Soyez conscients des risques avant d’effectuer des modifications directement dans la base de données.
Une petite snapshot ou un backup avant de commencer ne fait jamais de mal !
Connexion SSH à un nœud VCFA
La première étape consiste à se connecter en SSH sur l’un des nœuds VCFA avec l’utilisateur vmware-system-user et le mot de passe défini lors du déploiement.
Dans mon cas, j’utilise PuTTY :
login as: vmware-system-user
Pre-authentication banner message from server:
| Welcome to Photon 5.0 (\m) - Kernel \r (\l)
End of banner message from server
Keyboard-interactive authentication prompts from server:
| Password:
End of keyboard-interactive prompts from server
Last login: Tue Aug 4 13:29:13 2026 from 10.7.50.188
vmware-system-user@vcfalab-ddza2 [ ~ ]$
Passage en root
Il faut ensuite élever ses privilèges afin de passer en root avec la commande suivante :
sudo -s
Ce qui donne :
vmware-system-user@vcfalab-ddza2 [ ~ ]$ sudo -s
root [ /home/vmware-system-user ]#
Configuration de kubectl
Nous devons ensuite exporter le fichier de configuration Kubernetes afin de pouvoir utiliser kubectl :
export KUBECONFIG=/etc/kubernetes/admin.conf
Dans mon cas :
root [ /home/vmware-system-user ]# export KUBECONFIG=/etc/kubernetes/admin.conf
Recherche du pod PostgreSQL
Une fois cela fait, nous pouvons lister les pods afin de trouver les pods PostgreSQL qui nous intéressent :
kubectl get pods -n prelude | grep -I postgres
La commande retourne dans mon environnement :
root [ /home/vmware-system-user ]# kubectl get pods -n prelude | grep -I postgres
vcfapostgres-0 2/2 Running 3 (75d ago) 130d
vcfapostgres-1 2/2 Running 3 (75d ago) 130d
vcfapostgres-2 2/2 Running 4 (72d ago) 130d
vcfapostgres-pooler-qs7b9558c-mcq2c 1/1 Running 1 (75d ago) 130d
vcfapostgres-pooler-qs7b9558c-r6xts 1/1 Running 2 130d
Dans notre cas, le pod qui nous intéresse est le premier : vcfapostgres-0.
Nous allons donc nous connecter directement à l’intérieur de celui-ci :
kubectl -n prelude -it exec vcfapostgres-0 -- bash
Ce qui donne :
root [ /home/vmware-system-user ]# kubectl -n prelude -it exec vcfapostgres-0 -- bash
Defaulted container "postgres" out of: postgres, metrics-exporter
This container is managed by runit, when stopping/starting services use sv
Examples:
sv stop cron
sv restart patroni
Current status: (sv status /etc/service/*)
run: /etc/service/cron: (pid 34) 6480061s
run: /etc/service/etcd: (pid 33) 6480061s
run: /etc/service/patroni: (pid 30) 6480061s
run: /etc/service/pgbouncer: (pid 32) 6480061s
run: /etc/service/pgqd: (pid 31) 6480061s
root [ /home/postgres ]#
Passage sur l’utilisateur PostgreSQL
Une fois à l’intérieur du conteneur, nous devons basculer sur l’utilisateur postgres :
su - postgres
Ce qui donne :
root [ /home/postgres ]# su - postgres
postgres@vcfapostgres-0 [ ~ ]$
Connexion à PostgreSQL
Nous pouvons maintenant lancer le client psql :
psql
Dans mon environnement :
postgres@vcfapostgres-0 [ ~ ]$ psql
psql (16.10, server 14.19)
Type "help" for help.
postgres=#
Connexion à la base tenantmanager
Nous allons tout d’abord activer l’Expanded Display de psql, ce qui rendra les résultats beaucoup plus lisibles :
\x
Puis nous nous connectons à la base de données tenantmanager :
\c tenantmanager
Ce qui donne :
postgres=# \x
Expanded display is on.
postgres=# \c tenantmanager
psql (16.10, server 14.19)
You are now connected to database "tenantmanager" as user "postgres".
tenantmanager=#
Recherche de la Content Library en erreur
Une fois connectés à la base tenantmanager, nous allons lister les différentes Content Libraries présentes dans la table catalog :
SELECT * FROM catalog;
Dans mon cas, la requête retourne notamment les deux entrées suivantes :
-[ RECORD 1 ]---------------+--------------------------------------------------------------------------------------------------
id | 21eadd65-fdb0-4867-a774-ea9980dd0b7f
name | Test-toto
description |
user_id | XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
org_id | XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
shared_count | 0
date_created | 2026-08-11 13:26:26.032
version_number | 1
is_published_external | f
upload_access | f
delete_access | f
library_publish_url |
password |
subscription_location |
subscription_password |
subscription_local_copy | f
subscribed_to_ext_feeds | f
domain_name |
deleted | f
is_cache_enabled | f
preserve_identity_info_flag | f
org_publishing_level | NONE
distributed_catalog_id |
distributed_catalog_name |
bound_access_level |
on_delete_action |
is_vcf_image_library | t
is_provider_content_library | f
auto_attach | t
status | READY
-[ RECORD 2 ]---------------+--------------------------------------------------------------------------------------------------
id | 72d61656-e867-4b9f-a363-265370b64fd2
name | Test-titi
description |
user_id | XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
org_id | XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
shared_count | 0
date_created | 2026-08-11 13:26:40.495
version_number | 1
is_published_external | f
upload_access | f
delete_access | f
library_publish_url |
password |
subscription_location |
subscription_password |
subscription_local_copy | f
subscribed_to_ext_feeds | f
domain_name |
deleted | f
is_cache_enabled | f
preserve_identity_info_flag | f
org_publishing_level | NONE
distributed_catalog_id |
distributed_catalog_name |
bound_access_level |
on_delete_action |
is_vcf_image_library | t
is_provider_content_library | f
auto_attach | t
status | NOT_READY
tenantmanager=#
Nous retrouvons donc bien nos deux Content Libraries :
Test-toto, avec le statutREADYTest-titi, avec le statutNOT_READY
C’est donc Test-titi qui nous intéresse.
Son ID est le suivant :
72d61656-e867-4b9f-a363-265370b64fd2
Suppression de l’entrée dans la base
Nous pouvons maintenant construire la requête SQL permettant de supprimer cette entrée de la table catalog :
DELETE FROM catalog
WHERE id = '72d61656-e867-4b9f-a363-265370b64fd2';
La suppression est bien prise en compte :
tenantmanager=# DELETE FROM catalog WHERE id = '72d61656-e867-4b9f-a363-265370b64fd2';
DELETE 1
tenantmanager=#
Et voilà ! La Content Library a bien été supprimée du tenant VCFA.
⚠️ À noter
Cette procédure s’applique uniquement aux Content Libraries côté tenant et non aux Content Libraries côté Provider.
Elle n’effectue également aucun nettoyage côté vCenter. Il vous appartient donc de vérifier l’état des objets correspondants dans vCenter et d’effectuer le nettoyage nécessaire.