Lifecycles
==========
In juju, certain fundamental state entities have "lifecycles". These entities
are:
* Machines
* Units
* Applications
* Relations
...and there are only 3 possible states for the above things:
* Alive (An entity is Alive when it is first created.)
* Dying (An entity becomes Dying when the user indicates that it should be
destroyed, and remains so while there are impediments to its removal.)
* Dead (an entity becomes Dead when there are no further impediments to
its removal; at this point it may be removed from the database at any time.
Some entities may become Dead and are removed as a single operation, and
are hence never directly observed to be "Dead", but should still be so
considered.)
There are two fundamental truths in this system:
* All such things start existence Alive.
* No such thing can ever change to an earlier state.
Beyond the above rules, lifecycle shifts occur at different times for different
kinds of entities.
Machines
--------
* Like everything else, a machine starts out Alive. `juju bootstrap` aside,
the user interface does not allow for direct creation of machines, but
`juju deploy` and `juju add-unit` may create machines as a consequence of
unit creation.
* If a machine has the JobManageModel job, it cannot become Dying or Dead.
Other jobs do not affect the lifecycle directly.
* If a machine has the JobHostUnits job, principal units can be assigned to it
while it is Alive.
* While principal units are assigned to a machine, its lifecycle cannot change
and `juju remove-machine` will fail.
* When no principal units are assigned, `juju remove-machine` will set the
machine to Dying. (Future plans: allow a machine to become Dying when it
has principal units, so long as they are not Alive. For now it's extra
complexity with little direct benefit.)
* When a machine has containers, `juju remove-machine` will fail, unless force
is used. However `juju destroy-controller` or `juju destroy-model` allows a
machine to move to dying with containers.
* Once a machine has been set to Dying, the corresponding Machine Agent (MA)
is responsible for setting it to Dead. A dying machine cannot transition to
dead if there are containers. (Future plans: when Dying units are
assigned, wait for them to become Dead and remove them completely before
making the machine Dead; not an issue now because the machine can't yet
become Dying with units assigned.)
* Once a machine has been set to Dead, the agent for some other machine (with
JobManageModel) will release the underlying instance back to the provider
and remove the machine entity from state. (Future uncertainty: should the
provisioner provision an instance for a Dying machine? At the moment, no,
because a Dying machine can't have any units in the first place; in the
future, er, maybe, because those Dying units may be attached to persistent
storage and should thus be allowed to continue to shut down cleanly as they
would usually do. Maybe.)
Units
-----
* A principal unit can be created directly with `juju deploy` or
`juju add-unit`.
* While a principal unit is Alive, it can be assigned to a machine.
* While a principal unit is Alive, it can enter the scopes of Alive
relations, which may cause the creation of subordinate units; so,
indirectly, `juju add-relation` can also cause the creation of units.
* A unit can become Dying at any time, but may not become Dead while any unit
subordinate to it exists, or while the unit is in scope for any relation.
* A principal unit can become Dying in one of two ways:
* `juju remove-unit` (This doesn't work on subordinates; see below.)
* `juju remove-application` (This does work on subordinates, but happens
indirectly in either case: the Unit Agents (UAs) for each unit of an
application set their corresponding units to Dying when they detect their
application Dying; this is because we try to assume 100k-scale and we can't
use mgo/txn to do a bulk update of 100k units: that makes for a txn
with at least 100k operations, and that's just crazy.)
* A subordinate must also become Dying when either:
* its principal becomes Dying, via `juju remove-unit`; or
* the last Alive relation between its application and its principal's
application is no longer Alive. This may come about via `juju remove-relation`.
* When any unit is Dying, its UA is responsible for removing impediments to
the unit becoming Dead, and then making it so. To do so, the UA must:
* Depart from all its relations in an orderly fashion.
* Wait for all its subordinates to become Dead, and remove them from state.
* Set its unit to Dead.
* As just noted, when a subordinate unit is Dead, it is removed from state by
its principal's UA; the relationship is the same as that of a principal unit
to its assigned machine agent, and of a machine to the JobManageModel
machine agent.
Applications
--------
* Applications are created with `juju deploy`. Applications with duplicate names
are not allowed (units and machine with duplicate names are not possible:
their identifiers are assigned by juju).
* Unlike units and machines, applications have no corresponding agent.
* In addition, applications become Dead and are removed from the database in a
single atomic operation.
* When an application is Alive, units may be added to it, and relations can be
added using the application's endpoints.
* An applications can be destroyed at any time, via `juju remove-application`.
This causes all the units to become Dying, as discussed above, and will also
cause all relations in which the application is participating to become Dying
or be removed.
* If a removed application has no units, and all its relations are eligible
for immediate removal, then the application will also be removed immediately
rather than being set to Dying.
* If no associated relations exist, the application is removed by the MA which
removes the last unit of that application from state.
* If no units of the application remain, but its relations still exist, the
responsibility for removing the application falls to the last UA to leave scope
for that relation. (Yes, this is a UA for a unit of a totally different
application.)
Relations
---------
* A relation is created with `juju add-relation`. No two relations with the
same canonical name can exist. (The canonical relation name form is
"