// EnsureAvailabilitySingle applies a single StateServersSpec specification to the current environment. // Exported so it can be called by the legacy client API in the client package. func EnsureAvailabilitySingle(st *state.State, spec params.StateServersSpec) (params.StateServersChanges, error) { if !st.IsStateServer() { return params.StateServersChanges{}, errors.New("unsupported with hosted environments") } // Check if changes are allowed and the command may proceed. blockChecker := common.NewBlockChecker(st) if err := blockChecker.ChangeAllowed(); err != nil { return params.StateServersChanges{}, errors.Trace(err) } // Validate the environment tag if present. if spec.EnvironTag != "" { tag, err := names.ParseEnvironTag(spec.EnvironTag) if err != nil { return params.StateServersChanges{}, errors.Errorf("invalid environment tag: %v", err) } if _, err := st.FindEntity(tag); err != nil { return params.StateServersChanges{}, err } } series := spec.Series if series == "" { ssi, err := st.StateServerInfo() if err != nil { return params.StateServersChanges{}, err } // We should always have at least one voting machine // If we *really* wanted we could just pick whatever series is // in the majority, but really, if we always copy the value of // the first one, then they'll stay in sync. if len(ssi.VotingMachineIds) == 0 { // Better than a panic()? return params.StateServersChanges{}, fmt.Errorf("internal error, failed to find any voting machines") } templateMachine, err := st.Machine(ssi.VotingMachineIds[0]) if err != nil { return params.StateServersChanges{}, err } series = templateMachine.Series() } changes, err := st.EnsureAvailability(spec.NumStateServers, spec.Constraints, series, spec.Placement) if err != nil { return params.StateServersChanges{}, err } return stateServersChanges(changes), nil }
// NewAPI creates a new instance of the Backups API facade. func NewAPI(st *state.State, resources *common.Resources, authorizer common.Authorizer) (*API, error) { if !authorizer.AuthClient() { return nil, errors.Trace(common.ErrPerm) } // For now, backup operations are only permitted on the controller environment. if !st.IsStateServer() { return nil, errors.New("backups are not supported for hosted environments") } // Get the backup paths. dataDir, err := extractResourceValue(resources, "dataDir") if err != nil { return nil, errors.Trace(err) } logsDir, err := extractResourceValue(resources, "logDir") if err != nil { return nil, errors.Trace(err) } paths := backups.Paths{ DataDir: dataDir, LogsDir: logsDir, } // Build the API. machineID, err := extractResourceValue(resources, "machineID") if err != nil { return nil, errors.Trace(err) } b := API{ st: st, paths: &paths, machineID: machineID, } return &b, nil }