func addMachineForUnit(st *state.State, unit *state.Unit, placement *instance.Placement, networks []string) (*state.Machine, error) { unitCons, err := unit.Constraints() if err != nil { return nil, err } var containerType instance.ContainerType var mid, placementDirective string // Extract container type and parent from container placement directives. if containerType, err = instance.ParseContainerType(placement.Scope); err == nil { mid = placement.Directive } else { switch placement.Scope { case st.EnvironUUID(): placementDirective = placement.Directive case instance.MachineScope: mid = placement.Directive default: return nil, errors.Errorf("invalid environment UUID %q", placement.Scope) } } // Create any new machine marked as dirty so that // nothing else will grab it before we assign the unit to it. // If a container is to be used, create it. if containerType != "" { template := state.MachineTemplate{ Series: unit.Series(), Jobs: []state.MachineJob{state.JobHostUnits}, Dirty: true, Constraints: *unitCons, RequestedNetworks: networks, } return st.AddMachineInsideMachine(template, mid, containerType) } // If a placement directive is to be used, do that here. if placementDirective != "" { template := state.MachineTemplate{ Series: unit.Series(), Jobs: []state.MachineJob{state.JobHostUnits}, Dirty: true, Constraints: *unitCons, RequestedNetworks: networks, Placement: placementDirective, } return st.AddOneMachine(template) } // Otherwise use an existing machine. return st.Machine(mid) }