Skip to content

1.12b Step | SetupDataDir

Omisen edited this page Jul 29, 2026 · 3 revisions

Crea il filestore di Odoo (data_dir) in modo reversibile. Vive in src/steps/setup_data_dir.rs. Nato in R6 per chiudere A-R5-3, e con esso una regola nuova: proprietà della directory e proprietà dei dati sono due domande diverse, e per rimuovere serve rispondere sì a entrambe.


Il problema: un artefatto che nasceva senza padrone

Il data_dir scritto in odoo<N>.conf da 1.12 GenerateConfig è <odoo_home>/.local/share/Odoo — dentro /opt/odoo, che è l'$HOME dell'utente odoo. Lì Odoo scrive il filestore: i file veri degli allegati dei record.

Finché nessuno step lo creava, quella directory nasceva da sola al primo avvio di Odoo. E /opt/odoo, se l'installer la trova già esistente, è Preexisting: non la tocca mai, giustamente. Risultato misurato dal job Ubuntu di integration.yml: dopo un rollback completo, /opt/odoo/.local restava lì.

Un artefatto che nasce senza che nessuno lo registri non è annullabile. Non è un buco nell'undo: è un artefatto fuori dal modello. Qui viene creato da uno step, con il suo PreState, e diventa rimovibile per la sola strada che il progetto ammette — perché risulta dallo snapshot che l'abbiamo creato noi.


Il ciclo

Fase Comportamento
snapshot il data_dir esiste già? → Preexisting. Altrimenti registra il livello più alto che manca scendendo da odoo_home (di norma .local) e legge dal Context se il database è nostro
run Preexisting → no-op. Altrimenti mkdir -p come utente odoo (il servizio deve poterci scrivere) → CreatedByUs
undo rimuove il livello registrato — ma solo se CreatedByUs e il database era nostro
struct DataDirSnapshot {
    prestate: PreState,                  // la directory è nostra?
    created_root: Option<PathBuf>,       // il livello più alto che abbiamo creato
    db_was_ours: bool,                   // i dati dentro sono nostri?
}

created_root è ciò che rende l'undo chirurgico: se il cliente aveva già /opt/odoo/.local (ci teneva altro), il livello più alto mancante è .local/share, e la sua .local non viene toccata. Non si rimuove il ramo, si rimuove esattamente il pezzo che abbiamo innestato.


La protezione: il filestore segue il destino del database

Un filestore non è una cache: è la metà su disco dei dati applicativi. Se il database era Preexisting — un DB del cliente con lo stesso nome, che 1.8 CreateDatabase protegge dal dropdb — allora il suo filestore contiene allegati veri. La directory l'abbiamo creata noi; i dati dentro no.

Perciò l'undo richiede due condizioni, e ne basta una falsa per fermarlo:

undo agisce  ⟺  prestate == CreatedByUs   ∧   db_was_ours
                (la directory è nostra)       (i dati sono nostri)

È l'anti-drop applicato all'altra metà dei dati: stessa protezione, stesso motivo.

Perché db_was_ours è persistito e non riletto dal Context

Il verdetto arriva dal canale Context::db_created_by_us, che CreateDatabase pubblica nel proprio snapshot. Questo step sta dopo nella sequenza, quindi al suo snapshot il valore c'è — e viene copiato nello snapshot persistito.

Non è ridondanza. Il comando odoo-installer rollback ricostruisce il Context dalla configurazione persistita, dove quel flag vale false di default: senza copia locale, l'undo non saprebbe mai di poter agire e il filestore resterebbe un residuo. Con il flag invertito succederebbe il peggio — quello di un cliente rimosso per errore. Come per il database, il verdetto si rilegge, non si rideduce.


La rete sul rm -rf

L'undo cancella ricorsivamente un path che arriva dal disco. Uno stato corrotto, o scritto da un'altra installazione, non deve diventare un disastro altrove: prima di agire, created_root deve essere un discendente stretto di odoo_home. Fuori da lì (o uguale a odoo_home) l'undo logga e non rimuove nulla. Meglio un residuo da rimuovere a mano.


Ordine dell'undo, dichiarato

Lo step sta dopo create-database, quindi il suo undo gira prima del dropdb (ordine inverso). Se il dropdb fallisse — è best-effort — resterebbe un database nostro senza filestore.

Non è evitabile: lo snapshot deve girare dopo quello di CreateDatabase per sapere di chi è il database, e questo fissa la posizione nella sequenza. Il caso è comunque quello di un DB che stiamo buttando via, e un dropdb fallito finisce già nel report dei residui di fine rollback.


Note di design

  • Il path del data_dir vive in un solo posto, generate_config::data_dir: due format! identici in due file sarebbero la premessa di un rollback che pulisce la directory sbagliata.
  • dry_run: né mkdirrm -rf, solo log.
  • Test (tests/setup_data_dir.rs): i due assi di proprietà separatamente, .local preesistente non toccata, filestore preesistente ignorato del tutto, il verdetto sul DB che attraversa il disco, la guardia sul perimetro con path ostili, e il dry-run inerte. Lo step è anche nella CHAIN di tests/rehydrate.rs, quindi passa dalla verifica di equivalenza fra undo live e undo reidratato.

Clone this wiki locally