-
Notifications
You must be signed in to change notification settings - Fork 0
1.12b Step | SetupDataDir
Creates Odoo's filestore (
data_dir) reversibly. It lives insrc/steps/setup_data_dir.rs. Born in R6 to close A-R5-3, and with it a new rule: ownership of the directory and ownership of the data are two different questions, and removing requires a yes to both.
The data_dir written into odoo<N>.conf by
1.12 GenerateConfig is <odoo_home>/.local/share/Odoo — inside
/opt/odoo, which is the odoo user's $HOME. That is where Odoo writes the filestore: the actual
files of the records' attachments.
While no step created it, that directory came into existence by itself on Odoo's first start. And
/opt/odoo, when the installer finds it already there, is Preexisting: never touched, rightly so.
Result, measured by integration.yml's Ubuntu job: after a complete rollback, /opt/odoo/.local was
still there.
An artifact born with nobody recording it cannot be undone. It is not a hole in an undo: it is an
artifact outside the model. Here it is created by a step, with its own PreState, and becomes removable
by the only route this project allows — because the snapshot says we created it.
| Phase | Behaviour |
|---|---|
| snapshot | does the data_dir already exist? → Preexisting. Otherwise record the highest level missing on the way down from odoo_home (usually .local) and read from the Context whether the database is ours |
| run |
Preexisting → no-op. Otherwise mkdir -p as the odoo user (the service has to be able to write there) → CreatedByUs
|
| undo | removes the recorded level — but only if CreatedByUs and the database was ours |
struct DataDirSnapshot {
prestate: PreState, // is the directory ours?
created_root: Option<PathBuf>, // the highest level we created
db_was_ours: bool, // is the data inside ours?
}created_root is what makes the undo surgical: if the customer already had /opt/odoo/.local (with
other things in it), the highest missing level is .local/share, and their .local is not touched. We
do not remove the branch, we remove exactly the piece we grafted on.
A filestore is not a cache: it is the on-disk half of the application data. If the database was
Preexisting — a customer database with the same name, which
1.8 CreateDatabase protects from the dropdb — then its filestore
contains real attachments. We created the directory; the data inside is not ours.
So the undo requires two conditions, and one false is enough to stop it:
undo acts ⟺ prestate == CreatedByUs ∧ db_was_ours
(the directory is ours) (the data is ours)
It is the anti-drop rule applied to the data's other half: same protection, same reason.
The verdict arrives through the Context::db_created_by_us channel, which CreateDatabase publishes in
its own snapshot. This step comes later in the sequence, so by its snapshot the value is there —
and it is copied into the persisted snapshot.
That is not redundancy. The invok rollback command rebuilds the Context from the persisted
configuration, where that flag defaults to false: without a local copy the undo would never know it
may act, and the filestore would stay behind as a leftover. With the flag inverted the worse thing would
happen — a customer's data removed by mistake. As with the database, the verdict is re-read, not
re-derived.
The undo recursively deletes a path that comes from disk. A corrupted state, or one written by
another installation, must not become a disaster elsewhere: before acting, created_root must be a
strict descendant of odoo_home. Outside that (or equal to odoo_home) the undo logs and removes
nothing. Better a leftover to remove by hand.
The step comes after create-database, so its undo runs before the dropdb (reverse order). If the
dropdb failed — it is best-effort — a database of ours would be left without its filestore.
That is unavoidable: the snapshot must run after CreateDatabase's in order to know whose the
database is, and that fixes its position in the sequence. The case is a database we are throwing away
anyway, and a failed dropdb already ends up in the leftovers report at the end of the rollback.
- The
data_dirpath lives in one place,generate_config::data_dir: two identicalformat!s in two files would be the premise of a rollback cleaning the wrong directory. -
dry_run: neithermkdirnorrm -rf, only logs. - Tests (
tests/setup_data_dir.rs): the two ownership axes separately, a pre-existing.localleft untouched, a pre-existing filestore ignored entirely, the database verdict surviving the round trip through disk, the perimeter guard with hostile paths, and an inert dry-run. The step is also intests/rehydrate.rs'sCHAIN, so it goes through the equivalence check between the live undo and the rehydrated one.
Start here
Key concepts
References
For developers
Technical detail — how it works inside
Steps:
- 1.1 PrepareOptRoot
- 1.2 CreateOdooUser
- 1.3 SetupLogDir
- 1.3b SetupCacheDir
- 1.4 AptPackages (delta)
- 1.5 InstallWkhtmltopdf
- 1.6 SetupPostgres
- 1.7 CreateDbRole
- 1.8 CreateDatabase
- 1.9 CloneOdooRepo
- 1.10 CreateVirtualenv
- 1.11 InstallPythonRequirements
- 1.12 GenerateConfig
- 1.12b SetupDataDir
- 1.13 InitializeOdooDatabase
- 1.14 SetupSystemd
- 1.15 Nginx (6 sub-steps)
- 1.16 WriteControlScript + PatchBashrc
Cross-cutting: