// DestroyMachinesWithParams removes the given set of machines, the semantics of which
// is determined by the force and keep parameters.
// TODO(wallyworld) - for Juju 3.0, this should be the preferred api to use.
544803
func (client *Client) DestroyMachinesWithParams(force, keep bool, maxWait *time.Duration, machines ...string) ([]params.DestroyMachineResult, error) {
	args := params.DestroyMachinesParams{
		Force:       force,
		Keep:        keep,
		MachineTags: make([]string, 0, len(machines)),
	}
	if client.BestAPIVersion() > 5 {
		args.MaxWait = maxWait
	}
	allResults := make([]params.DestroyMachineResult, len(machines))
	index := make([]int, 0, len(machines))
	for i, machineId := range machines {
		if !names.IsValidMachine(machineId) {
			allResults[i].Error = &params.Error{
				Message: errors.NotValidf("machine ID %q", machineId).Error(),
			}
			continue
		}
		index = append(index, i)
		args.MachineTags = append(args.MachineTags, names.NewMachineTag(machineId).String())
	}
	if len(args.MachineTags) > 0 {
		var result params.DestroyMachineResults
		if err := client.facade.FacadeCall("DestroyMachineWithParams", args, &result); err != nil {
			return nil, errors.Trace(err)
		}
		if n := len(result.Results); n != len(args.MachineTags) {
			return nil, errors.Errorf("expected %d result(s), got %d", len(args.MachineTags), n)
		}
		for i, result := range result.Results {
			allResults[index[i]] = result
		}
	}
	return allResults, nil
}
914125
func (st *State) cleanupDyingMachine(machineId string, cleanupArgs []bson.Raw) error {
	var force bool
	switch n := len(cleanupArgs); n {
	case 0:
		// Old cleanups have no args, so follow the old behaviour.
	case 1:
		if err := cleanupArgs[0].Unmarshal(&force); err != nil {
			return errors.Annotate(err, "unmarshalling cleanup arg 'force'")
		}
	default:
		return errors.Errorf("expected 0-1 arguments, got %d", n)
	}
	machine, err := st.Machine(machineId)
	if errors.IsNotFound(err) {
		return nil
	} else if err != nil {
		return err
	}
	return cleanupDyingMachineResources(machine, force)
}
1002636
func ProvisionMachine(args manual.ProvisionMachineArgs) (machineId string, err error) {
	defer func() {
		if machineId != "" && err != nil {
			logger.Errorf("provisioning failed, removing machine %v: %v", machineId, err)
			if cleanupErr := args.Client.ForceDestroyMachines(machineId); cleanupErr != nil {
				logger.Errorf("error cleaning up machine: %s", cleanupErr)
			}
			machineId = ""
		}
	}()

	if err = InitAdministratorUser(&args); err != nil {
		return "", errors.Annotatef(err,
			"Cannot provision machine because no WinRM http/https standard listener is enabled for user %q, on host %q",
			args.User, args.Host)
	}

	machineParams, err := gatherMachineParams(args.Host, args.WinRM.Client)
	if err != nil {
		return "", err
	}

	machineId, err = manual.RecordMachineInState(args.Client, *machineParams)
	if err != nil {
		return "", err
	}

	provisioningScript, err := args.Client.ProvisioningScript(params.ProvisioningScriptParams{
		MachineId:              machineId,
		Nonce:                  machineParams.Nonce,
		DisablePackageCommands: true,
	})

	if err != nil {
		return "", err
	}

	// Finally, provision the machine agent.
	err = runProvisionScript(provisioningScript, args.WinRM.Client, args.Stdout, args.Stderr)
	if err != nil {
		return "", err
	}

	logger.Infof("Provisioned machine %v", machineId)
	return machineId, nil
}
215832
func (mm *MachineManagerAPI) DestroyMachineWithParams(args params.DestroyMachinesParams) (params.DestroyMachineResults, error) {
	entities := params.Entities{Entities: make([]params.Entity, len(args.MachineTags))}
	for i, tag := range args.MachineTags {
		entities.Entities[i].Tag = tag
	}
	return mm.destroyMachine(entities, args.Force, args.Keep, common.MaxWait(args.MaxWait))
}
562803
func (fw *Firewaller) flushMachine(machined *machineData) error {
	want, err := fw.gatherIngressRules(machined)
	if err != nil {
		return errors.Trace(err)
	}
	toOpen, toClose := diffRanges(machined.ingressRules, want)
	machined.ingressRules = want
	if fw.globalMode {
		return fw.flushGlobalPorts(toOpen, toClose)
	}
	return fw.flushInstancePorts(machined, toOpen, toClose)
}
679137
func (s *VirtualMachineService) NewDestroyVirtualMachineParams(id string) *DestroyVirtualMachineParams {
	p := &DestroyVirtualMachineParams{}
	p.p = make(map[string]interface{})
	p.p["id"] = id
	return p
}
217297
func (api *APIBase) DestroyUnit(args params.DestroyUnitsParams) (params.DestroyUnitResults, error) {
	if api.modelType == state.ModelTypeCAAS {
		return params.DestroyUnitResults{}, errors.NotSupportedf("removing units on a non-container model")
	}
	if err := api.checkCanWrite(); err != nil {
		return params.DestroyUnitResults{}, errors.Trace(err)
	}
	if err := api.check.RemoveAllowed(); err != nil {
		return params.DestroyUnitResults{}, errors.Trace(err)
	}
	destroyUnit := func(arg params.DestroyUnitParams) (*params.DestroyUnitInfo, error) {
		unitTag, err := names.ParseUnitTag(arg.UnitTag)
		if err != nil {
			return nil, errors.Trace(err)
		}
		name := unitTag.Id()
		unit, err := api.backend.Unit(name)
		if errors.IsNotFound(err) {
			return nil, errors.Errorf("unit %q does not exist", name)
		} else if err != nil {
			return nil, errors.Trace(err)
		}
		if !unit.IsPrincipal() {
			return nil, errors.Errorf("unit %q is a subordinate", name)
		}
		var info params.DestroyUnitInfo
		storage, err := storagecommon.UnitStorage(api.storageAccess, unit.UnitTag())
		if err != nil {
			return nil, errors.Trace(err)
		}

		if arg.DestroyStorage {
			for _, s := range storage {
				info.DestroyedStorage = append(
					info.DestroyedStorage,
					params.Entity{Tag: s.StorageTag().String()},
				)
			}
		} else {
			info.DestroyedStorage, info.DetachedStorage, err = storagecommon.ClassifyDetachedStorage(
				api.storageAccess.VolumeAccess(), api.storageAccess.FilesystemAccess(), storage,
			)
			if err != nil {
				return nil, errors.Trace(err)
			}
		}
		op := unit.DestroyOperation()
		op.DestroyStorage = arg.DestroyStorage
		op.Force = arg.Force
		if arg.Force {
			op.MaxWait = common.MaxWait(arg.MaxWait)
		}
		if err := api.backend.ApplyOperation(op); err != nil {
			return nil, errors.Trace(err)
		}
		// TODO (anastasiamac 2019-03-29) we want to return errors and info when forced..
		//  maybe always, so that we can report how many errors we are getting/got.
		// At the moment, this only returns the intent not the actual result.
		// However, there is a provision for this functionality for the near-future: destroy operation itself
		// contains Errors that have been encountered during its application.
		logger.Warningf("operational errors destroying unit %v: %v", unit.Name(), op.Errors)
		return &info, nil
	}
	results := make([]params.DestroyUnitResult, len(args.Units))
	for i, entity := range args.Units {
		info, err := destroyUnit(entity)
		if err != nil {
			results[i].Error = common.ServerError(err)
			continue
		}
		results[i].Info = info
	}
	return params.DestroyUnitResults{results}, nil
}
1076748
func (c *CloudAPI) DeleteAllMachineMetadata(machineID string) error {
	machine, err := c.GetMachine(machineID)
	if err != nil {
		return err
	}

	for k := range machine.Metadata {
		delete(machine.Metadata, k)
	}
	return nil
}
393243
func (st *State) cleanupMachinesForDyingModel(cleanupArgs []bson.Raw) (err error) {
	var args DestroyModelParams
	switch n := len(cleanupArgs); n {
	case 0:
	// Old cleanups have no args, so follow the old behaviour.
	case 1:
		if err := cleanupArgs[0].Unmarshal(&args); err != nil {
			return errors.Annotate(err, "unmarshalling cleanup 'destroy model' args")
		}
	default:
		return errors.Errorf("expected 0-1 arguments, got %d", n)
	}
	// This won't miss machines, because a Dying model cannot have
	// machines added to it. But we do have to remove the machines themselves
	// via individual transactions, because they could be in any state at all.
	machines, err := st.AllMachines()
	if err != nil {
		return errors.Trace(err)
	}
	force := args.Force != nil && *args.Force
	for _, m := range machines {
		if m.IsManager() {
			continue
		}
		if _, isContainer := m.ParentId(); isContainer {
			continue
		}
		manual, err := m.IsManual()
		if err != nil {
			// TODO (force 2019-4-24) we should not break out here but continue with other machines.
			return errors.Trace(err)
		}
		if manual {
			// Manually added machines should never be force-
			// destroyed automatically. That should be a user-
			// driven decision, since it may leak applications
			// and resources on the machine. If something is
			// stuck, then the user can still force-destroy
			// the manual machines.
			if err := m.Destroy(); err != nil {
				// Since we cannot delete a manual machine, we cannot proceed with model destruction even if it is forced.
				// TODO (force 2019-4-24) However, we should not break out here but continue with other machines.
				return errors.Trace(errors.Annotatef(err, "could not destroy manual machine %v", m.Id()))
			}
			return nil
		}
		// TODO (force 2019-04-26) Should this always be ForceDestroy or only when
		// 'destroy-model --force' is specified?...
		if err := m.ForceDestroy(args.MaxWait); err != nil {
			err = errors.Annotatef(err, "while destroying machine %v is", m.Id())
			// TODO (force 2019-4-24) we should not break out here but continue with other machines.
			if !force {
				return errors.Trace(err)
			}
			logger.Warningf("%v", err)
		}
	}
	return nil
}
456645
func (m *ModelManagerAPI) DestroyModels(args params.DestroyModelsParams) (params.ErrorResults, error) {
	results := params.ErrorResults{
		Results: make([]params.ErrorResult, len(args.Models)),
	}

	destroyModel := func(modelUUID string, destroyStorage, force *bool, maxWait *time.Duration) error {
		st, releaseSt, err := m.state.GetBackend(modelUUID)
		if err != nil {
			return errors.Trace(err)
		}
		defer releaseSt()

		model, err := st.Model()
		if err != nil {
			return errors.Trace(err)
		}
		if !m.isAdmin {
			hasAdmin, err := m.authorizer.HasPermission(permission.AdminAccess, model.ModelTag())
			if err != nil {
				return errors.Trace(err)
			}
			if !hasAdmin {
				return errors.Trace(common.ErrPerm)
			}
		}

		return errors.Trace(common.DestroyModel(st, destroyStorage, force, maxWait))
	}

	for i, arg := range args.Models {
		tag, err := names.ParseModelTag(arg.ModelTag)
		if err != nil {
			results.Results[i].Error = common.ServerError(err)
			continue
		}
		if err := destroyModel(tag.Id(), arg.DestroyStorage, arg.Force, arg.MaxWait); err != nil {
			results.Results[i].Error = common.ServerError(err)
			continue
		}
	}
	return results, nil
}
600286
func (api *API) AllMachineRemovals() ([]names.MachineTag, error) {
	var results params.EntitiesResults
	args := wrapEntities(api.modelTag)
	err := api.facade.FacadeCall("AllMachineRemovals", &args, &results)
	if err != nil {
		return nil, errors.Trace(err)
	}
	if len(results.Results) != 1 {
		return nil, errors.Errorf("expected one result, got %d", len(results.Results))
	}
	result := results.Results[0]
	if result.Error != nil {
		return nil, errors.Trace(result.Error)
	}
	machines := make([]names.MachineTag, len(result.Entities))
	for i, entity := range result.Entities {
		tag, err := names.ParseMachineTag(entity.Tag)
		if err != nil {
			return nil, errors.Trace(err)
		}
		machines[i] = tag
	}
	return machines, nil
}
1061995
func (c *CloudAPI) DeleteMachine(machineID string) error {
	if err := c.ProcessFunctionHook(c, machineID); err != nil {
		return err
	}

	for i, machine := range c.machines {
		if machine.Id == machineID {
			if machine.State == "stopped" {
				c.machines = append(c.machines[:i], c.machines[i+1:]...)
				return nil
			}

			return fmt.Errorf("Cannot Delete machine %s, machine is not stopped.", machineID)
		}
	}

	return fmt.Errorf("Machine %s not found", machineID)
}
1280461
func (st *State) AllMachines() ([]*Machine, error) {
	machinesCollection, closer := st.db().GetCollection(machinesC)
	defer closer()
	return st.allMachines(machinesCollection)
}
635566
func (a *StorageAPIv3) Destroy(args params.Entities) (params.ErrorResults, error) {
	v4Args := params.RemoveStorage{
		Storage: make([]params.RemoveStorageInstance, len(args.Entities)),
	}
	for i, arg := range args.Entities {
		v4Args.Storage[i] = params.RemoveStorageInstance{
			Tag: arg.Tag,
			// The v3 behaviour was to detach the storage
			// at the same time as marking the storage Dying.
			DestroyAttachments: true,
			DestroyStorage:     true,
		}
	}
	return a.remove(v4Args)
}
915920
func (st stateShim) AllMachines() ([]Machine, error) {
	machines, err := st.State.AllMachines()
	if err != nil {
		return nil, errors.Trace(err)
	}
	result := make([]Machine, len(machines))
	for i, m := range machines {
		result[i] = m
	}
	return result, nil
}
1219541
func jujuMachineFilter() *nova.Filter {
	filter := nova.NewFilter()
	filter.Set(nova.FilterServer, "juju-.*")
	return filter
}
100221
func (m *MachinesClient) Destroy(ctx context.Context, machineID *identity.ID) error {
	return m.client.RoundTrip(ctx, "DELETE", "/machines/"+machineID.String(), nil, nil, nil)
}