// fetchMachines returns a map from top level machine id to machines, where machines[0] is the host // machine and machines[1..n] are any containers (including nested ones). // // If machineIds is non-nil, only machines whose IDs are in the set are returned. func fetchMachines(st *state.State, machineIds *set.Strings) (map[string][]*state.Machine, error) { v := make(map[string][]*state.Machine) machines, err := st.AllMachines() if err != nil { return nil, err } // AllMachines gives us machines sorted by id. for _, m := range machines { if machineIds != nil && !machineIds.Contains(m.Id()) { continue } parentId, ok := m.ParentId() if !ok { // Only top level host machines go directly into the machine map. v[m.Id()] = []*state.Machine{m} } else { topParentId := state.TopParentId(m.Id()) machines, ok := v[topParentId] if !ok { panic(fmt.Errorf("unexpected machine id %q", parentId)) } machines = append(machines, m) v[topParentId] = machines } } return v, nil }
// updateAllMachines finds all machines and resets the stored state address // in each of them. The address does not include the port. func updateAllMachines(st *state.State, stateAddr string) error { machines, err := st.AllMachines() if err != nil { return err } pendingMachineCount := 0 done := make(chan error) for _, machine := range machines { // A newly resumed state server requires no updating, and more // than one state server is not yet support by this plugin. if machine.IsManager() || machine.Life() == state.Dead { continue } pendingMachineCount++ machine := machine go func() { err := runMachineUpdate(machine, setAgentAddressScript(stateAddr)) if err != nil { logger.Errorf("failed to update machine %s: %v", machine, err) } else { progress("updated machine %s", machine) } done <- err }() } err = nil for ; pendingMachineCount > 0; pendingMachineCount-- { if updateErr := <-done; updateErr != nil && err == nil { err = fmt.Errorf("machine update failed") } } return err }
// DestroyEnvironment destroys all services and non-manager machine // instances in the specified environment. This function assumes that all // necessary authentication checks have been done. func DestroyEnvironment(st *state.State, environTag names.EnvironTag) error { var err error if environTag != st.EnvironTag() { if st, err = st.ForEnviron(environTag); err != nil { return errors.Trace(err) } defer st.Close() } check := NewBlockChecker(st) if err = check.DestroyAllowed(); err != nil { return errors.Trace(err) } env, err := st.Environment() if err != nil { return errors.Trace(err) } if err = env.Destroy(); err != nil { return errors.Trace(err) } machines, err := st.AllMachines() if err != nil { return errors.Trace(err) } err = sendMetrics(st) if err != nil { logger.Warningf("failed to send leftover metrics: %v", err) } // We must destroy instances server-side to support JES (Juju Environment // Server), as there's no CLI to fall back on. In that case, we only ever // destroy non-state machines; we leave destroying state servers in non- // hosted environments to the CLI, as otherwise the API server may get cut // off. if err := destroyNonManagerMachines(st, machines); err != nil { return errors.Trace(err) } // If this is not the state server environment, remove all documents from // state associated with the environment. if env.EnvironTag() != env.ServerTag() { return errors.Trace(st.RemoveAllEnvironDocs()) } // Return to the caller. If it's the CLI, it will finish up // by calling the provider's Destroy method, which will // destroy the state servers, any straggler instances, and // other provider-specific resources. return nil }
// The provisioner will remove dead machines once their backing instances are // stopped. For the tests, we remove them directly. func assertAllMachinesDeadAndRemove(c *gc.C, st *state.State) { machines, err := st.AllMachines() c.Assert(err, jc.ErrorIsNil) for _, m := range machines { if m.IsManager() { continue } if _, isContainer := m.ParentId(); isContainer { continue } manual, err := m.IsManual() c.Assert(err, jc.ErrorIsNil) if manual { continue } c.Assert(m.Life(), gc.Equals, state.Dead) c.Assert(m.Remove(), jc.ErrorIsNil) } }
func assertMachineCount(c *gc.C, st *state.State, count int) { otherMachines, err := st.AllMachines() c.Assert(err, jc.ErrorIsNil) c.Assert(otherMachines, gc.HasLen, count) }
func assertMachineCount(c *gc.C, st *state.State, expect int) { ms, err := st.AllMachines() c.Assert(err, jc.ErrorIsNil) c.Assert(ms, gc.HasLen, expect, gc.Commentf("%v", ms)) }