// updateControllerMachines updates the peergrouper's current list of
// controller machines, as well as starting and stopping trackers for
// them as they are added and removed.
346054
func (w *pgWorker) updateControllerMachines() (bool, error) {
	info, err := w.config.State.ControllerInfo()
	if err != nil {
		return false, fmt.Errorf("cannot get controller info: %v", err)
	}

	logger.Debugf("controller machines in state: %#v", info.MachineIds)
	changed := false

	// Stop machine goroutines that no longer correspond to controller
	// machines.
	for _, m := range w.machineTrackers {
		if !inStrings(m.Id(), info.MachineIds) {
			worker.Stop(m)
			delete(w.machineTrackers, m.Id())
			changed = true
		}
	}

	// Start machines with no watcher
	for _, id := range info.MachineIds {
		stm, err := w.config.State.Machine(id)
		if err != nil {
			if errors.IsNotFound(err) {
				// If the machine isn't found, it must have been
				// removed and will soon enough be removed
				// from the controller list. This will probably
				// never happen, but we'll code defensively anyway.
				logger.Warningf("machine %q from controller list not found", id)
				continue
			}
			return false, fmt.Errorf("cannot get machine %q: %v", id, err)
		}
		if _, ok := w.machineTrackers[id]; ok {
			continue
		}
		logger.Debugf("found new machine %q", id)

		// Don't add the machine unless it is "Started"
		machineStatus, err := stm.Status()
		if err != nil {
			return false, errors.Annotatef(err, "cannot get status for machine %q", id)
		}
		// A machine in status Error or Stopped might still be properly running the controller. We still want to treat
		// it as an active machine, even if we're trying to tear it down.
		if machineStatus.Status != status.Pending {
			logger.Debugf("machine %q has started, adding it to peergrouper list", id)
			tracker, err := newMachineTracker(stm, w.machineChanges)
			if err != nil {
				return false, errors.Trace(err)
			}
			if err := w.catacomb.Add(tracker); err != nil {
				return false, errors.Trace(err)
			}
			w.machineTrackers[id] = tracker
			changed = true
		} else {
			logger.Debugf("machine %q not ready: %v", id, machineStatus.Status)
		}

	}
	return changed, nil
}
1222765
func (api *API) CheckMachines(args params.ModelArgs) (params.ErrorResults, error) {
	tag, err := names.ParseModelTag(args.ModelTag)
	if err != nil {
		return params.ErrorResults{}, errors.Trace(err)
	}
	st, err := api.pool.Get(tag.Id())
	if err != nil {
		return params.ErrorResults{}, errors.Trace(err)
	}
	defer st.Release()

	return credentialcommon.ValidateExistingModelCredential(
		credentialcommon.NewPersistentBackend(st.State),
		api.callContext,
	)
}
1348457
func (c *Controller) updateModel(ch ModelChange) {
	c.ensureModel(ch.ModelUUID).setDetails(ch)
}
294134
func (c *registerCommand) updateController(
	ctx *cmd.Context,
	store jujuclient.ClientStore,
	controllerName string,
	controllerDetails jujuclient.ControllerDetails,
	accountDetails jujuclient.AccountDetails,
) error {
	// Check that the same controller isn't already stored, so that we
	// can avoid needlessly asking for a controller name in that case.
	all, err := store.AllControllers()
	if err != nil {
		return errors.Trace(err)
	}
	for name, ctl := range all {
		if ctl.ControllerUUID == controllerDetails.ControllerUUID {
			var buf bytes.Buffer
			if err := alreadyRegisteredMessageT.Execute(
				&buf,
				map[string]interface{}{
					"ControllerName": name,
					"UserName":       accountDetails.User,
				},
			); err != nil {
				return err
			}
			ctx.Warningf(buf.String())
			return errors.Errorf("controller is already registered as %q", name)
		}
	}
	if err := store.AddController(controllerName, controllerDetails); err != nil {
		return errors.Trace(err)
	}
	if err := store.UpdateAccount(controllerName, accountDetails); err != nil {
		return errors.Annotatef(err, "cannot update account information: %v", err)
	}
	return nil
}
530298
func (s *precheckShim) AllMachines() ([]PrecheckMachine, error) {
	machines, err := s.State.AllMachines()
	if err != nil {
		return nil, errors.Trace(err)
	}
	out := make([]PrecheckMachine, 0, len(machines))
	for _, machine := range machines {
		out = append(out, machine)
	}
	return out, nil
}
40994
func updateMachine(c context.Context, m *crimson.Machine, mask *field_mask.FieldMask) (*crimson.Machine, error) {
	if err := validateMachineForUpdate(m, mask); err != nil {
		return nil, err
	}
	stmt := squirrel.Update("machines")
	for _, path := range mask.Paths {
		switch path {
		case "platform":
			stmt = stmt.Set("platform_id", squirrel.Expr("(SELECT id FROM platforms WHERE name = ?)", m.Platform))
		case "rack":
			stmt = stmt.Set("rack_id", squirrel.Expr("(SELECT id FROM racks WHERE name = ?)", m.Rack))
		case "state":
			stmt = stmt.Set("state", m.State)
		case "description":
			stmt = stmt.Set("description", m.Description)
		case "asset_tag":
			stmt = stmt.Set("asset_tag", m.AssetTag)
		case "service_tag":
			stmt = stmt.Set("service_tag", m.ServiceTag)
		case "deployment_ticket":
			stmt = stmt.Set("deployment_ticket", m.DeploymentTicket)
		case "drac_password":
			stmt = stmt.Set("drac_password", m.DracPassword)
		}
	}
	stmt = stmt.Where("name = ?", m.Name)
	query, args, err := stmt.ToSql()
	if err != nil {
		return nil, errors.Annotate(err, "failed to generate statement").Err()
	}

	tx, err := database.Begin(c)
	if err != nil {
		return nil, errors.Annotate(err, "failed to begin transaction").Err()
	}
	defer tx.MaybeRollback(c)

	_, err = tx.ExecContext(c, query, args...)
	if err != nil {
		switch e, ok := err.(*mysql.MySQLError); {
		case !ok:
			// Type assertion failed.
		case e.Number == mysqlerr.ER_BAD_NULL_ERROR && strings.Contains(e.Message, "'platform_id'"):
			// e.g. "Error 1048: Column 'platform_id' cannot be null".
			return nil, status.Errorf(codes.NotFound, "platform %q does not exist", m.Platform)
		case e.Number == mysqlerr.ER_BAD_NULL_ERROR && strings.Contains(e.Message, "'rack_id'"):
			// e.g. "Error 1048: Column 'rack_id' cannot be null".
			return nil, status.Errorf(codes.NotFound, "rack %q does not exist", m.Rack)
		}
		return nil, errors.Annotate(err, "failed to update machine").Err()
	}
	// The number of rows affected cannot distinguish between zero because the machine didn't exist
	// and zero because the row already matched, so skip looking at the number of rows affected.

	machines, err := listMachines(c, tx, &crimson.ListMachinesRequest{
		Names: []string{m.Name},
	})
	switch {
	case err != nil:
		return nil, errors.Annotate(err, "failed to fetch updated machine").Err()
	case len(machines) == 0:
		return nil, status.Errorf(codes.NotFound, "machine %q does not exist", m.Name)
	}

	if err := tx.Commit(); err != nil {
		return nil, errors.Annotate(err, "failed to commit transaction").Err()
	}
	return machines[0], nil
}
1103
func (client *Client) DestroyMachines(machines ...string) ([]params.DestroyMachineResult, error) {
	return client.destroyMachines("DestroyMachine", machines)
}
643692
func ValidateReplicationControllerStatusUpdate(controller, oldController *core.ReplicationController) field.ErrorList {
	allErrs := ValidateObjectMetaUpdate(&controller.ObjectMeta, &oldController.ObjectMeta, field.NewPath("metadata"))
	allErrs = append(allErrs, ValidateReplicationControllerStatus(controller.Status, field.NewPath("status"))...)
	return allErrs
}
270866
func (m *API) CompleteMachineRemovals(machines params.Entities) error {
	machineIDs, err := collectMachineIDs(machines)
	if err != nil {
		return errors.Trace(err)
	}
	return m.backend.CompleteMachineRemovals(machineIDs...)
}
155826
func (a *AAgent) AllMachineStates() (states []MachineState, err error) {
	states = []MachineState{}

	a.Lock()
	defer a.Unlock()

	for _, m := range a.machines {
		state := MachineState{
			Name:                 m.machine.Name(),
			Version:              m.machine.Version(),
			Path:                 m.machine.Directory(),
			ID:                   m.machine.InstanceID(),
			State:                m.machine.State(),
			StartTimeUTC:         m.machine.StartTime().Unix(),
			AvailableTransitions: m.machine.AvailableTransitions(),
		}

		states = append(states, state)
	}

	return states, nil
}
22379
func (m *API) AllMachineRemovals(models params.Entities) params.EntitiesResults {
	results := make([]params.EntitiesResult, len(models.Entities))
	for i, entity := range models.Entities {
		entities, err := m.allRemovalsForTag(entity.Tag)
		results[i].Entities = entities
		results[i].Error = common.ServerError(err)
	}
	return params.EntitiesResults{Results: results}
}
1093732
func watchMachinesLoop(context updaterContext, machinesWatcher watcher.StringsWatcher) (err error) {
	p := &updater{
		context:     context,
		machines:    make(map[names.MachineTag]chan struct{}),
		machineDead: make(chan machine),
	}
	defer func() {
		// TODO(fwereade): is this a home-grown sync.WaitGroup or something?
		// strongly suspect these machine goroutines could be managed rather
		// less opaquely if we made them all workers.
		for len(p.machines) > 0 {
			delete(p.machines, (<-p.machineDead).Tag())
		}
	}()
	for {
		select {
		case <-p.context.dying():
			return p.context.errDying()
		case ids, ok := <-machinesWatcher.Changes():
			if !ok {
				return errors.New("machines watcher closed")
			}
			tags := make([]names.MachineTag, len(ids))
			for i := range ids {
				tags[i] = names.NewMachineTag(ids[i])
			}
			if err := p.startMachines(tags); err != nil {
				return err
			}
		case m := <-p.machineDead:
			delete(p.machines, m.Tag())
		}
	}
}
324040
func (info *UpgradeInfo) SetControllerDone(machineId string) error {
	assertSanity, err := checkUpgradeInfoSanity(info.st, machineId,
		info.doc.PreviousVersion, info.doc.TargetVersion)
	if err != nil {
		return errors.Trace(err)
	}

	buildTxn := func(attempt int) ([]txn.Op, error) {
		doc, err := currentUpgradeInfoDoc(info.st)
		if errors.IsNotFound(err) {
			return nil, jujutxn.ErrNoOperations
		} else if err != nil {
			return nil, errors.Trace(err)
		}
		switch doc.Status {
		case UpgradePending, UpgradeRunning:
			return nil, errors.New("upgrade has not yet run")
		}

		controllersDone := set.NewStrings(doc.ControllersDone...)
		if controllersDone.Contains(machineId) {
			return nil, jujutxn.ErrNoOperations
		}
		controllersDone.Add(machineId)

		controllersReady := set.NewStrings(doc.ControllersReady...)
		controllersNotDone := controllersReady.Difference(controllersDone)
		if controllersNotDone.IsEmpty() {
			// This is the last controller. Archive the current
			// upgradeInfo document.
			doc.ControllersDone = controllersDone.SortedValues()

			ops := info.makeArchiveOps(doc, UpgradeComplete)
			extraOps, err := upgradeStatusHistoryAndOps(info.st, UpgradeComplete, info.st.clock().Now())
			if err != nil {
				return nil, errors.Trace(err)
			}
			if len(extraOps) > 0 {
				ops = append(ops, extraOps...)
			}

			return ops, nil
		}

		return []txn.Op{{
			C:  upgradeInfoC,
			Id: currentUpgradeId,
			// This is not the last controller, but we need to be
			// sure it still isn't when we run this.
			Assert: append(assertSanity, bson.D{{
				"controllersDone", bson.D{{"$nin", controllersNotDone.Values()}},
			}}...),
			Update: bson.D{{"$addToSet", bson.D{{"controllersDone", machineId}}}},
		}}, nil
	}
	err = info.st.db().Run(buildTxn)
	return errors.Annotate(err, "cannot complete upgrade")
}
626563
func ValidateReplicationControllerUpdate(controller, oldController *api.ReplicationController) validation.ErrorList {
	allErrs := validation.ErrorList{}
	allErrs = append(allErrs, ValidateObjectMetaUpdate(&controller.ObjectMeta, &oldController.ObjectMeta, validation.NewFieldPath("metadata"))...)
	allErrs = append(allErrs, ValidateReplicationControllerSpec(&controller.Spec, validation.NewFieldPath("spec"))...)
	return allErrs
}
820201
func (*Service) UpdateMachine(c context.Context, req *crimson.UpdateMachineRequest) (*crimson.Machine, error) {
	return updateMachine(c, req.Machine, req.UpdateMask)
}
500510
func (c *Client) CountMachines() (int, error) {
	var resp int
	req := request{
		method: client.HEAD,
		url:    apiMachines,
		resp:   &resp,
	}
	if _, err := c.sendRequest(req); err != nil {
		return -1, errors.Newf(err, "failed to get count of machines")
	}
	return resp, nil
}
693005
func controllerMachineIds(st *state.State, m *state.Machine) ([]string, error) {
	info, err := st.ControllerInfo()
	if err != nil {
		return nil, err
	}
	result := set.NewStrings(info.MachineIds...)
	result.Remove(m.Id())
	return result.SortedValues(), nil
}