// If requested to pre-populate database from a backup of previous/existing database
// and updates clusterState with DB credentials
func (bkr *Broker) prepopulateDatabaseFromExistingClusterData(existingClusterData *structs.ClusterRecreationData, toInstanceID structs.ClusterID, clusterModel *state.ClusterModel, logger lager.Logger) (err error) {
	if bkr.backups.BaseURI == "" {
		return fmt.Errorf("Failed to copy existing database backup: missing backups.base_uri configuration")
	}
	fromDatabaseBackup := fmt.Sprintf("%s/%s", bkr.backups.BaseURI, existingClusterData.InstanceID)
	toDatabaseBackup := fmt.Sprintf("%s/%s", bkr.backups.BaseURI, toInstanceID)
	err = bkr.callbacks.CopyDatabaseBackup(fromDatabaseBackup, toDatabaseBackup, bkr.logger)
	if err != nil {
		logger.Error("prepopulate-database", err)
		return fmt.Errorf("Failed to copy existing database backup to new database: %s", err.Error())
	}

	return clusterModel.UpdateCredentials(existingClusterData)
}
func (s *Scheduler) StopCluster(clusterModel *state.ClusterModel) error {
	plan, err := s.newPlan(clusterModel, structs.ClusterFeatures{NodeCount: 0})
	if err != nil {
		return err
	}

	s.logger.Info("scheduler.stop-cluster", lager.Data{
		"instance-id": clusterModel.InstanceID(),
		"plan":        plan,
		"steps-count": len(plan.steps()),
		"steps":       plan.stepTypes(),
	})

	return s.executePlan(clusterModel, plan)
}
func (s *Scheduler) RunCluster(clusterModel *state.ClusterModel, features structs.ClusterFeatures) (err error) {
	err = s.VerifyClusterFeatures(features)
	if err != nil {
		return
	}

	plan, err := s.newPlan(clusterModel, features)
	if err != nil {
		return
	}

	s.logger.Info("scheduler.run-cluster", lager.Data{
		"instance-id": clusterModel.InstanceID(),
		"steps-count": len(plan.steps()),
		"steps":       plan.stepTypes(),
		"features":    features,
	})

	return s.executePlan(clusterModel, plan)
}
func (s *Scheduler) executePlan(clusterModel *state.ClusterModel, plan plan) error {
	steps := plan.steps()
	clusterModel.BeginScheduling(len(steps))

	for _, step := range steps {
		clusterModel.SchedulingStepStarted(step.StepType())
		err := step.Perform()
		if err != nil {
			clusterModel.SchedulingError(err)
			return err
		}
		clusterModel.SchedulingStepCompleted()
	}
	return nil
}