Boostrapping a model

When you first start looking at the bootstrap process it all seems to be a convoluted mess. However there is method to our madness.

Bootstrapping starts with the CLI command bootstrap. That is found in cmd/juju/bootstrap.go

The first step of bootstrap is to create an Environ instance which is named. This Environ instance has the model configuration (the *config.Config instance). Initially this will check in the default config store, which is $JUJU_HOME/models. This calls through to bootstrap.PrepareForName in environs/open.go. This makes sure that the model configuration contains an admin secret, a CA cert, and a UUID.

It is at this time that the initial .jenv file is written out to $JUJU_DATA/models.

Further checks are then done as part of the bootstrap command:

  • validating the constaints

  • checking to make sure the model is already bootstrapped

The code then moves on to the Bootstrap function defined in environs/bootstrap/bootstrap.go.

bootstrap.Bootstrap starts with sanity checks:

  • setting a package global in the network package for prefer IPv6 (not sanity)

  • there is an admin-secret

  • that there is at least one authorised SSH key

  • that there is a CA Cert and CA Key

  • that the model storage is writable (by writing the bootstrap-init file)

  • finds available agent binaries

    • locate agent binaries available externally (matching constraints)

    • determine which agent binaries can be built and uploaded to make up shortfall in above

    • if the best agent binaries are local, we attempt to upload them

This code then calls into the Bootstrap function on the environ instance (backed by a provider), which returns arch, series, and a finalizer function.

Now things diverge here a little:

  • azure does some initial config around affinity groups and networks, then calls common.Bootstrap.

  • ec2, maas, and openstack all fall through to common.Bootstrap

  • dummy, local and manual all do their own thing

Firstly, common.Bootstrap:

  • creates machine config for the bootstrap machine

  • starts an instance for the bootstrap machine

  • writes the instance id (as yaml) into the the “provider-state” file in environ storage

    • this step will go away soon, or at least become provider specific

The finalizer function is run by bootstrap.Bootstrap after the following is performed:

  • select agent binaries from the previously calculated set based on the architecture and series of the instance that the provider started

  • make sure that the agent binaries are available

  • create the machine config struct for the bootstrap machine

  • set the agent binaries in that structure to the agent binaries bootstrap knows about.

The common finalizer function does the following:

  • updates the machine config with the instance id of the new machine

  • calls environs.FinishMachineConfig

    • populates the machine config with information from the config object

    • checks for CA Cert

    • checks for admin-secret

    • creates a password hash using the password.CompatSalt

    • uses this password hash for both the APIInfo and MongoInfo passwords.

    • creates the controller cert and key

    • strips the admin-secret and server ca-private-key from the config

      • this step is probably not needed any more

  • calls common.FinishBootstrap

    • calls ssh with a custom script that first checks the nonce on the cloud instance

    • calls ConfigureMachine

      • creates cloud init script from the machine config, this includes the call to jujud bootstrap-state.

      • the bootstrap config is passed to jujud as base64 encoded yaml

      • runs said script over ssh

jujud bootstrap-state

  • creates a *config.Config object from the base64 encoded yaml from the command line

  • sets the package global in the network package for prefer IPv6

  • generates and writes out the system SSH identity file

  • generates a (long) shared secret for mongo

  • mongo is then started

  • the database is then initialized (state.Initialize)

  • copies the agent binaries into model storage

    • also clones the agent binaries for each series of the same OS (for the time being at least, while each series’ agent binaries are equivalent)