Skip to content

Migrate customer — bring a facility's existing records onto this system

This page is for a facility that already has records: its stocks, its tanks and its own users came from the system it is being moved off, so none of them are created here. Two situations, and they need different pages:

  • A facility already serving here, whose database needs a newer release's schema. That is one step of a short window in which the facility is closed, and it belongs to Upgrade a facility — running the migrations against a facility while its people are working in it is what leaves them using software that does not match its database.
  • A facility still on the old system, moving its records here for the first time. That is the rest of this page.

Where the work happens, and with which account

Everything that touches a facility's records runs from your own machine, across the network to the managed database server: the database is created, the records are loaded into it, its schema is brought up to date and its settings are seeded. The production host is handed one thing at the end of it — the settings files its servers need.

Two things follow, and both are why this page's work is done from your machine: no copy of any facility's records is ever written to the production host's disk, and the database administrator's password — the one credential that can drop every facility — is used here rather than on the host.

The administrator's account is used for exactly two statements per facility: dropping whatever is there from an earlier attempt, and creating the database and the account that will own it. Everything after that is done with the facility's own account, which holds every privilege over that facility's own database and none at all over any other.

What you need first

  • A dump of the facility, and the copy of its old configuration that came with it. scripts/refresh-dumps.sh <facility> pulls both from the live system, backing up the generation it replaces. The dumps hold real researchers' names and addresses, so they stay in db/dumps, which git ignores.
  • The administrator's credentials for the managed cluster, in your environment: ADMIN_DB_HOST, ADMIN_DB_PORT, ADMIN_DB_PASSWORD and ADMIN_DB_SSL_CA, the last being the path to the cluster's CA certificate. The account itself is not configurable.
  • A mysql and mysqldump from MySQL 8, not MariaDB's — see Prepare the hosts.
  • A PI contract row for the facility in PI_CONTRACTS. Seats are a billing figure no settings file records, and a facility with no row silently gets the defaults.

Move the records

scripts/cutover.sh --facilities zri,udemo

Each facility named is taken from nothing to ready in one pass, and reported as it goes. Without --live each is addressed as test-<facility>.<domain-name>, which is what makes a rehearsal harmless: the facility carries on being served from the old system, unreferenced by anything this writes. Add --live when the facility's real address is meant to point here.

The pass starts by dropping what is there, so running it again is how a rehearsal is repeated. A facility that fails is reported and the rest carry on.

What it does to each facility, in order:

  1. Creates the database and the account that owns it, as the administrator, exactly as New customer does. The account is granted its own database and the _bak database beside it, which is what later lets the facility copy itself during an upgrade without any administrator credential.

    An account carried over from an older server cannot log in at all. MySQL 8.4 does not load the mysql_native_password plugin, so every account ZFM uses has to authenticate with caching_sha2_password — the default, and what CREATE USER produces unless told otherwise.

  2. Loads the dump into it, as the facility. The database now holds the old system's schema and its records, the facility's own admin user rows among them.

  3. Records InitialSchema as applied without running it. The schema the dump brought is that migration, so the row goes into the migrations table and migration:run skips it:

    sql INSERT INTO `migrations` (`timestamp`, `name`) VALUES (<InitialSchema timestamp>, '<InitialSchema class name>');

    That row is a claim that the facility's tables already have the shape InitialSchema builds, and the facilities moving onto this system were checked against it: each one taken through the chain and compared with a database the chain built from empty, column by column, index by index, constraint by constraint. They arrive at the same schema.

  4. Runs the rest of the chain against the real rows: the marker model, the backfill that reads the facility's mutations and transgenes forward into it, and everything added since.

  5. Seeds the facility's settings by reading its old configuration forward — the FacilitySettings record in its own database, which Serve a facility describes, and the slim settings file its server starts on. Read what it reports: retired keys are losses on purpose, and anything under NEEDS YOUR ATTENTION wants a decision rather than a nod.
  6. Promotes the facility's owner account: finds the existing owner account, sets its role to super and normalises its display name and initials to ZFM Admin / ZFM, so that one presentation appears in every facility. It never creates a user — if it reports finding none, the dump was not the facility you meant.

Out of the pass comes one file: /tmp/zfm-facility-configs-<date>.tar.gz, mode 0600, holding one settings file per facility. Those files carry each facility's new database password and its signing secret, so the artifact is deleted from both machines once the move it was built for is done.

Put those facilities on the air

Send the artifact and its checksum to the production host, and install them from the release you want those facilities to run:

# on your own machine
scp /tmp/zfm-facility-configs-<date>.tar.gz* <production-host>:/tmp/

# on the production host
cd /tmp
sha256sum -c zfm-facility-configs-<date>.tar.gz.sha256
sudo /srv/zfm/releases/<version>/deploy/install-facilities.sh /tmp/zfm-facility-configs-<date>.tar.gz

For each facility in the artifact this installs its settings where its server reads them, checks that the name in them reaches this host, points the facility at the release the script itself came from, serves its web address, starts and enables its server, and checks it. A facility whose https:// name resolves somewhere else is refused and named, and the rest are installed. A facility already running is restarted onto its new settings, so the first run and the tenth read the same way. It touches no database and holds no database credential.

Am I ready to move on?

sudo /srv/zfm/releases/<version>/deploy/check-facilities.sh --release /srv/zfm/releases/<version>

Every facility you installed should be up, yes, read, ok and reached: its server answering, set to start at boot, its own database reachable, its schema holding exactly the migrations that release carries, and its own web address answering for it.

Then count the rows you moved, against the dump you moved them from. Stocks, tanks and users come across one for one; the facility's genomic features are its old mutations and transgenes read into one table, so their count is the two added together.

Cutover puts this in order with everything else that happens on the day.