fix race conditions in updating task/recipe/recipeset/job status

Status changes now always happen at the task level, on the first
unfinished task in the recipe, using a conditional UPDATE. This ensures
status changes from beakerd (while scheduling) or the harness (while
running) do not trample over status changes from the UI (for example,
cancelling the job).

The states of the higher-level job components are not updated in the
same transaction anymore. Instead, a new beakerd thread loops over
"dirty" jobs and updates their state. This ensures a consistent view of
the state of the entire job while updating it.

Every task status change causes the job to be marked "dirty", by writing
a new UUID value into the job.dirty_version column. When beakerd updates
the job state it copies this value to the job.clean_version column.
A job is therefore "dirty" when dirty_version != clean_version. This
lets us guarantee that jobs will always eventually reach a consistent
("clean") state, without needing to do costly SELECT FOR UPDATE queries
across the job.

Bug: 807237
Change-Id: I8875c14191072b3c1a1f76e16d4296ef6dbebc30
abort guests which have not started if their host finishes

Bug: 903935
Change-Id: I19973cf5147bce819376cd95a4c145c439f28b8e