Introduction
Ce système automatise la migration complète de tous les Shared Drives d'un compte Google Workspace (Compte A) vers un autre compte Google Workspace (Compte B), sans interruption de service et avec une reprise sur erreur.
La migration est orchestrée via n8n, exécutée par un agent rclone déployé sur le VPS, et suivie via Google Sheets comme base de données de progression.
Architecture globale
Composants
/transfer, /status, /check, /scan. Lance rclone en arrière-plan et persiste les jobs sur disque.Rapport (1 ligne par drive) et Transfert_Detail (1 ligne par fichier/dossier).rclone copyto pour les fichiers individuels et rclone copy pour les dossiers. Authentification OAuth2 par compte.WF-0 · Créer les drives de destination
Exécuté une seule fois avant la migration. Lit la liste des Shared Drives du Compte A depuis le Rapport et crée leur équivalent vide dans le Compte B.
WF-A · Scanner les Shared Drives
Pour chaque drive dont le statut est À TRANSFÉRER, appelle POST /scan sur rclone_agent (qui exécute rclone lsjson sur le drive source, profondeur max 2). Chaque élément retourné est inséré dans Transfert_Detail avec le statut EN ATTENTE.
Colonnes générées dans Transfert_Detail
| Colonne | Description | Exemple |
|---|---|---|
Clé | Identifiant unique NomDrive|Chemin | MonDrive|Digital/logo.png |
Chemin | Chemin relatif dans le drive | Digital/logo.png |
Type | fichier ou dossier | fichier |
ID source | ID du Shared Drive source | 0AH… |
ID destination | ID du Shared Drive destination | 0AC… |
Statut | EN ATTENTE au départ | EN ATTENTE |
WF-B · Orchestrateur
Le cœur du système. S'exécute toutes les 5 minutes et lance 3 chaînes en parallèle à chaque tick.
Chaîne A — Polling des jobs actifs
Pour chaque ligne avec statut EN COURS, interroge GET /status/{job_id}. Si le job est terminé (SUCCESS ou ERROR), met à jour le statut dans le Sheet.
Chaîne B — Consolidation du Rapport
Vérifie si tous les éléments d'un drive sont TRANSFÉRÉ. Si oui, marque le drive comme DÉJÀ TRANSFÉRÉ dans l'onglet Rapport. Si des erreurs persistent, marque ERREUR PARTIELLE.
Chaîne C — Lancement des transferts
Calcule le nombre de slots disponibles (MAX_PARALLEL = 4 − jobs EN COURS). Lance les prochains éléments EN ATTENTE jusqu'à remplir les slots. Chaque lancement appelle POST /transfer et reçoit un job_id en retour.
rclone copyto pour les fichiers individuels (préserve le nom exact) et rclone copy pour les dossiers. Sans cette distinction, rclone interprète la destination d'un fichier comme un répertoire → erreur "is a file not a directory".
WF-C · Vérification des erreurs
Workflow de maintenance exécuté manuellement après WF-B pour corriger les faux positifs. Une erreur rclone ne signifie pas toujours que le fichier est absent de la destination.
La vérification est directe : /check utilise rclone lsf sur le drive destination pour chercher le fichier. Si lsf le trouve → le fichier est bien présent → faux positif. Le statut passe à TRANSFÉRÉ.
Cycle de vie d'un fichier
| Statut | Signification | Prochaine action |
|---|---|---|
| EN ATTENTE | Scanné, en attente de slot | WF-B chaîne C le lance |
| EN COURS | Job rclone en cours d'exécution | WF-B chaîne A poll toutes les 5 min |
| TRANSFÉRÉ | Copie confirmée | WF-B chaîne B consolide le drive |
| ERREUR | rclone a retourné un code ≠ 0 | WF-C vérifie l'existence réelle |
Google Sheets — Structure des données
Onglet Rapport
Un enregistrement par Shared Drive. Vue consolidée de la progression.
| Colonne | Description |
|---|---|
Nom du drive | Clé de correspondance (upsert) |
Statut | À TRANSFÉRER / DÉJÀ TRANSFÉRÉ / ERREUR PARTIELLE |
ID source | ID Shared Drive Compte A |
ID destination | ID Shared Drive Compte B (rempli par WF-0) |
Date analyse | Date de dernière mise à jour |
Onglet Transfert_Detail
Un enregistrement par fichier ou dossier scanné. C'est la table principale de la migration.
| Colonne | Description |
|---|---|
Clé | Identifiant unique NomDrive|Chemin — utilisé pour les upserts |
Nom Drive | Nom du drive parent |
Chemin | Chemin relatif dans le drive (ex: Design/logo.png) |
Type | fichier ou dossier |
Statut | EN ATTENTE / EN COURS / TRANSFÉRÉ / ERREUR |
Taille (Mo) | Taille en Mo (vide pour les dossiers) |
ID source | ID du Shared Drive source |
ID destination | ID du Shared Drive destination |
Début | Horodatage de démarrage du transfert |
Fin | Horodatage de fin |
Job ID | ID court du job rclone_agent (ex: 9e3c6661) |
rclone_agent — API Reference
Agent HTTP Python minimal hébergé sur le VPS, accessible depuis les containers Docker via http://host.docker.internal:3001. Authentification Bearer token.
Endpoints
GET /health
Vérifie l'état de l'agent et le nombre de jobs en cours.
{ "status": "ok", "total_jobs": 155, "running": 0 }
POST /transfer
Lance un transfert rclone en arrière-plan. Retourne immédiatement un job_id.
// Body
{ "src_drive_id": "0AH...", "dst_drive_id": "0AC...", "path": "Design/logo.png", "type": "fichier" }
// Response 202
{ "job_id": "9e3c6661", "log_file": "/home/sidy/scripts/logs/transfer_9e3c6661.log" }
type est "fichier", l'agent utilise rclone copyto qui préserve le nom exact du fichier destination. Pour "dossier", rclone copy est utilisé (copie le contenu du dossier).
GET /status/:job_id
Interroge l'état d'un job. Retourne RUNNING, SUCCESS ou ERROR.
{ "job_id": "9e3c6661", "status": "SUCCESS", "exit_code": 0,
"started_at": "2026-03-26T05:55:17", "finished_at": "2026-03-26T05:55:28",
"log_tail": "..." }
POST /check
Vérifie si un fichier ou dossier existe dans le drive destination (utilisé par WF-C).
// Body
{ "dst_drive_id": "0AC...", "path": "Design/logo.png", "type": "fichier" }
// Response
{ "exists": true, "path": "Design/logo.png", "type": "fichier" }
POST /scan
Scanne un Shared Drive source et retourne la liste des éléments (via rclone lsjson profondeur 2).
// Body
{ "drive_id": "0AH...", "max_depth": 2 }
// Response
{ "items": [ { "Path": "Design/logo.png", "IsDir": false, "Size": 54321 }, ... ], "count": 42 }
Infrastructure
| Service | Image / Stack | URL |
|---|---|---|
| Reverse proxy | Traefik latest | :80/:443 → HTTPS auto |
| n8n | n8nio/n8n | n8n.levell.cloud |
| rclone_agent | Python 3 systemd | host:3001 |
| Monitoring Beszel | Docker | VPS metrics |
| Transfer Monitor | nginx:alpine | suivi.levell.cloud |