// Start implements Machine. func (m *machine) Start(args StartArgs) error { params := NewURLParams() params.MaybeAdd("user_data", args.UserData) params.MaybeAdd("distro_series", args.DistroSeries) params.MaybeAdd("hwe_kernel", args.Kernel) params.MaybeAdd("comment", args.Comment) result, err := m.controller.post(m.resourceURI, "deploy", params.Values) if err != nil { if svrErr, ok := errors.Cause(err).(ServerError); ok { switch svrErr.StatusCode { case http.StatusNotFound, http.StatusConflict: return errors.Wrap(err, NewBadRequestError(svrErr.BodyMessage)) case http.StatusForbidden: return errors.Wrap(err, NewPermissionError(svrErr.BodyMessage)) case http.StatusServiceUnavailable: return errors.Wrap(err, NewCannotCompleteError(svrErr.BodyMessage)) } } return NewUnexpectedError(err) } machine, err := readMachine(m.controller.apiVersion, result) if err != nil { return errors.Trace(err) } m.updateFrom(machine) return nil }
func translateControllerError(store jujuclient.ClientStore, err error) error { if !errors.IsNotFound(err) { return err } controllers, err2 := store.AllControllers() if err2 != nil { return err2 } if len(controllers) == 0 { return errors.Wrap(err, ErrNoControllersDefined) } return errors.Wrap(err, ErrNoCurrentController) }
// Delete implements File. func (f *file) Delete() error { err := f.controller.delete(f.resourceURI) if err != nil { if svrErr, ok := errors.Cause(err).(ServerError); ok { switch svrErr.StatusCode { case http.StatusNotFound: return errors.Wrap(err, NewNoMatchError(svrErr.BodyMessage)) case http.StatusForbidden: return errors.Wrap(err, NewPermissionError(svrErr.BodyMessage)) } } return NewUnexpectedError(err) } return nil }
// validateModelUUID is the common validator for the various // apiserver components that need to check for a valid model // UUID. An empty modelUUID means that the connection has come in at // the root of the URL space and refers to the controller // model. // // It returns the validated model UUID. func validateModelUUID(args validateArgs) (string, error) { ssState := args.statePool.SystemState() if args.modelUUID == "" { // We allow the modelUUID to be empty so that: // TODO: server a limited API at the root (empty modelUUID) // just the user manager and model manager are able to accept // requests that don't require a modelUUID, like add-model. if args.strict { return "", errors.Trace(common.UnknownModelError(args.modelUUID)) } return ssState.ModelUUID(), nil } if args.modelUUID == ssState.ModelUUID() { return args.modelUUID, nil } if args.controllerModelOnly { return "", errors.Unauthorizedf("requested model %q is not the controller model", args.modelUUID) } if !names.IsValidModel(args.modelUUID) { return "", errors.Trace(common.UnknownModelError(args.modelUUID)) } modelTag := names.NewModelTag(args.modelUUID) if _, err := ssState.GetModel(modelTag); err != nil { return "", errors.Wrap(err, common.UnknownModelError(args.modelUUID)) } return args.modelUUID, nil }
// validateModelUUID is the common validator for the various // apiserver components that need to check for a valid model // UUID. An empty modelUUID means that the connection has come in at // the root of the URL space and refers to the controller // model. // // It returns the validated model UUID. func validateModelUUID(args validateArgs) (string, error) { ssState := args.statePool.SystemState() if args.modelUUID == "" { // We allow the modelUUID to be empty for 2 cases // 1) Compatibility with older clients // 2) TODO: server a limited API at the root (empty modelUUID) // with just the user manager and model manager // if the connection comes over a sufficiently up to date // login command. if args.strict { return "", errors.Trace(common.UnknownModelError(args.modelUUID)) } logger.Debugf("validate model uuid: empty modelUUID") return ssState.ModelUUID(), nil } if args.modelUUID == ssState.ModelUUID() { logger.Debugf("validate model uuid: controller model - %s", args.modelUUID) return args.modelUUID, nil } if args.controllerModelOnly { return "", errors.Unauthorizedf("requested model %q is not the controller model", args.modelUUID) } if !names.IsValidModel(args.modelUUID) { return "", errors.Trace(common.UnknownModelError(args.modelUUID)) } modelTag := names.NewModelTag(args.modelUUID) if _, err := ssState.GetModel(modelTag); err != nil { return "", errors.Wrap(err, common.UnknownModelError(args.modelUUID)) } logger.Debugf("validate model uuid: %s", args.modelUUID) return args.modelUUID, nil }
// Devices implements Controller. func (c *controller) CreateDevice(args CreateDeviceArgs) (Device, error) { // There must be at least one mac address. if len(args.MACAddresses) == 0 { return nil, NewBadRequestError("at least one MAC address must be specified") } params := NewURLParams() params.MaybeAdd("hostname", args.Hostname) params.MaybeAdd("domain", args.Domain) params.MaybeAddMany("mac_addresses", args.MACAddresses) params.MaybeAdd("parent", args.Parent) result, err := c.post("devices", "", params.Values) if err != nil { if svrErr, ok := errors.Cause(err).(ServerError); ok { if svrErr.StatusCode == http.StatusBadRequest { return nil, errors.Wrap(err, NewBadRequestError(svrErr.BodyMessage)) } } // Translate http errors. return nil, NewUnexpectedError(err) } device, err := readDevice(c.apiVersion, result) if err != nil { return nil, errors.Trace(err) } device.controller = c return device, nil }
// AddUser adds a user. func (api *UserManagerAPI) AddUser(args params.AddUsers) (params.AddUserResults, error) { result := params.AddUserResults{ Results: make([]params.AddUserResult, len(args.Users)), } if err := api.check.ChangeAllowed(); err != nil { return result, errors.Trace(err) } if len(args.Users) == 0 { return result, nil } loggedInUser, err := api.getLoggedInUser() if err != nil { return result, errors.Wrap(err, common.ErrPerm) } // TODO(thumper): PERMISSIONS Change this permission check when we have // real permissions. For now, only the owner of the initial environment is // able to add users. if err := api.permissionCheck(loggedInUser); err != nil { return result, errors.Trace(err) } for i, arg := range args.Users { user, err := api.state.AddUser(arg.Username, arg.DisplayName, arg.Password, loggedInUser.Id()) if err != nil { err = errors.Annotate(err, "failed to create user") result.Results[i].Error = common.ServerError(err) } else { result.Results[i].Tag = user.Tag().String() } } return result, nil }
func versionInitSystem(ser string) (string, error) { seriesos, err := series.GetOSFromSeries(ser) if err != nil { notFound := errors.NotFoundf("init system for series %q", ser) return "", errors.Wrap(err, notFound) } switch seriesos { case os.Windows: return InitSystemWindows, nil case os.Ubuntu: switch ser { case "precise", "quantal", "raring", "saucy", "trusty", "utopic": return InitSystemUpstart, nil default: // vivid and later if featureflag.Enabled(feature.LegacyUpstart) { return InitSystemUpstart, nil } return InitSystemSystemd, nil } case os.CentOS: return InitSystemSystemd, nil } return "", errors.NotFoundf("unknown os %q (from series %q), init system", seriesos, ser) }
func createContainer( lxcContainer golxc.Container, directory string, networkConfig *container.NetworkConfig, extraCreateArgs, templateParams []string, caCert []byte, ) error { // Generate initial lxc.conf with networking settings. netConfig := generateNetworkConfig(networkConfig) configPath := filepath.Join(directory, "lxc.conf") if err := ioutil.WriteFile(configPath, []byte(netConfig), 0644); err != nil { return errors.Annotatef(err, "failed to write container config %q", configPath) } logger.Tracef("wrote initial config %q for container %q", configPath, lxcContainer.Name()) var err error var execEnv []string = nil var closer func() if caCert != nil { execEnv, closer, err = wgetEnvironment(caCert) if err != nil { return errors.Annotatef(err, "failed to get environment for wget execution") } defer closer() } // Create the container. logger.Debugf("creating lxc container %q", lxcContainer.Name()) logger.Debugf("lxc-create template params: %v", templateParams) if err := lxcContainer.Create(configPath, defaultTemplate, extraCreateArgs, templateParams, execEnv); err != nil { return errors.Wrap(err, instance.NewRetryableCreationError("lxc container creation failed: "+lxcContainer.Name())) } return nil }
func (*functionSuite) TestWrapOfNil(c *gc.C) { detailed := errors.New("detailed") err := errors.Wrap(nil, detailed) //err nilWrapTest c.Assert(err.Error(), gc.Equals, "detailed") c.Assert(errors.Cause(err), gc.Equals, detailed) c.Assert(errors.Details(err), jc.Contains, tagToLocation["nilWrapTest"].String()) }
// Call will repeatedly execute the Func until either the function returns no // error, the retry count is exceeded or the stop channel is closed. func Call(args CallArgs) error { err := args.Validate() if err != nil { return errors.Trace(err) } for i := 1; args.Attempts < 0 || i <= args.Attempts; i++ { err = args.Func() if err == nil { return nil } if args.IsFatalError != nil && args.IsFatalError(err) { return errors.Trace(err) } if args.NotifyFunc != nil { args.NotifyFunc(err, i) } if i == args.Attempts && args.Attempts > 0 { break // don't wait before returning the error } // Wait for the delay, and retry select { case <-args.Clock.After(args.Delay): case <-args.Stop: return RetryStopped } args.Delay = ScaleDuration(args.Delay, args.MaxDelay, args.BackoffFactor) } return errors.Wrap(err, &AttemptsExceeded{err}) }
// validateEnvironUUID is the common validator for the various // apiserver components that need to check for a valid environment // UUID. An empty envUUID means that the connection has come in at // the root of the URL space and refers to the state server // environment. // // It returns the validated environment UUID. func validateEnvironUUID(args validateArgs) (string, error) { ssState := args.statePool.SystemState() if args.envUUID == "" { // We allow the environUUID to be empty for 2 cases // 1) Compatibility with older clients // 2) TODO: server a limited API at the root (empty envUUID) // with just the user manager and environment manager // if the connection comes over a sufficiently up to date // login command. if args.strict { return "", errors.Trace(common.UnknownEnvironmentError(args.envUUID)) } logger.Debugf("validate env uuid: empty envUUID") return ssState.EnvironUUID(), nil } if args.envUUID == ssState.EnvironUUID() { logger.Debugf("validate env uuid: state server environment - %s", args.envUUID) return args.envUUID, nil } if args.stateServerEnvOnly { return "", errors.Unauthorizedf("requested environment %q is not the state server environment", args.envUUID) } if !names.IsValidEnvironment(args.envUUID) { return "", errors.Trace(common.UnknownEnvironmentError(args.envUUID)) } envTag := names.NewEnvironTag(args.envUUID) if _, err := ssState.GetEnvironment(envTag); err != nil { return "", errors.Wrap(err, common.UnknownEnvironmentError(args.envUUID)) } logger.Debugf("validate env uuid: %s", args.envUUID) return args.envUUID, nil }
// finalizeAction passes back the final status of an Action hook to state. // It wraps any errors which occurred in normal behavior of the Action run; // only errors passed in unhandledErr will be returned. func (ctx *HookContext) finalizeAction(err, unhandledErr error) error { // TODO (binary132): synchronize with gsamfira's reboot logic message := ctx.actionData.ResultsMessage results := ctx.actionData.ResultsMap tag := ctx.actionData.Tag status := params.ActionCompleted if ctx.actionData.Failed { status = params.ActionFailed } // If we had an action error, we'll simply encapsulate it in the response // and discard the error state. Actions should not error the uniter. if err != nil { message = err.Error() if IsMissingHookError(err) { message = fmt.Sprintf("action not implemented on unit %q", ctx.unitName) } status = params.ActionFailed } callErr := ctx.state.ActionFinish(tag, status, results, message) if callErr != nil { unhandledErr = errors.Wrap(unhandledErr, callErr) } return unhandledErr }
// checkCreds validates the entities credentials in the current environment. // If the entity is a user, and lookForEnvUser is true, an env user must exist // for the environment. In the case of a user logging in to the server, but // not an environment, there is no env user needed. While we have the env // user, if we do have it, update the last login time. func checkCreds(st *state.State, req params.LoginRequest, lookForEnvUser bool) (state.Entity, *time.Time, error) { tag, err := names.ParseTag(req.AuthTag) if err != nil { return nil, nil, err } entity, err := st.FindEntity(tag) if errors.IsNotFound(err) { // We return the same error when an entity does not exist as for a bad // password, so that we don't allow unauthenticated users to find // information about existing entities. logger.Debugf("entity %q not found", tag) return nil, nil, common.ErrBadCreds } if err != nil { return nil, nil, errors.Trace(err) } authenticator, err := authentication.FindEntityAuthenticator(entity) if err != nil { return nil, nil, err } if err = authenticator.Authenticate(entity, req.Credentials, req.Nonce); err != nil { logger.Debugf("bad credentials") return nil, nil, err } // For user logins, update the last login time. // NOTE: this code path is only for local users. When we support remote // user logins with bearer tokens, we will need to make sure that we also // update the last connection times for the environment users there. var lastLogin *time.Time if user, ok := entity.(*state.User); ok { userLastLogin, err := user.LastLogin() if err != nil && !state.IsNeverLoggedInError(err) { return nil, nil, errors.Trace(err) } if lookForEnvUser { envUser, err := st.EnvironmentUser(user.UserTag()) if err != nil { return nil, nil, errors.Wrap(err, common.ErrBadCreds) } // The last connection for the environment takes precedence over // the local user last login time. userLastLogin, err = envUser.LastConnection() if err != nil && !state.IsNeverConnectedError(err) { return nil, nil, errors.Trace(err) } envUser.UpdateLastConnection() } // Only update the user's last login time if it is a successful // login, meaning that if we are logging into an environment, make // sure that there is an environment user in that environment for // this user. user.UpdateLastLogin() lastLogin = &userLastLogin } return entity, lastLogin, nil }
// Next implements plan.Plan Next interface. func (r *SelectFinalPlan) Next(ctx context.Context) (row *plan.Row, err error) { // push a new rowStackItem into RowStack pushRowStack(ctx, r.SelectList.ResultFields, r.SelectList.FromFields) row, err = r.Src.Next(ctx) // pop the rowStackItem if errPop := popRowStack(ctx); errPop != nil { return nil, errors.Wrap(err, errPop) } if row == nil || err != nil { return nil, errors.Trace(err) } // we should not output hidden fields to client. row.Data = row.Data[:r.HiddenFieldOffset] for i, o := range row.Data { switch v := o.(type) { case bool: // Convert bool field to int if v { row.Data[i] = uint8(1) } else { row.Data[i] = uint8(0) } } } if !r.infered { setResultFieldInfo(r.ResultFields[0:r.HiddenFieldOffset], row.Data) r.infered = true } return }
func (s *ProvisionerSuite) TestProvisionerSucceedStartInstanceWithInjectedWrappedRetryableCreationError(c *gc.C) { // Set the retry delay to 0, and retry count to 1 to keep tests short s.PatchValue(provisioner.RetryStrategyDelay, 0*time.Second) s.PatchValue(provisioner.RetryStrategyCount, 1) // create the error injection channel errorInjectionChannel := make(chan error, 1) c.Assert(errorInjectionChannel, gc.NotNil) p := s.newEnvironProvisioner(c) defer stop(c, p) // patch the dummy provider error injection channel cleanup := dummy.PatchTransientErrorInjectionChannel(errorInjectionChannel) defer cleanup() // send the error message once // - instance creation should succeed retryableError := errors.Wrap(errors.New(""), instance.NewRetryableCreationError("container failed to start and was destroyed")) errorInjectionChannel <- retryableError m, err := s.addMachine() c.Assert(err, jc.ErrorIsNil) s.checkStartInstanceNoSecureConnection(c, m) }
func (s *syncer) Complete() error { err := s.bulker.Submit() if err != nil { return errors.Wrap(err, canal.ErrHandleInterrupted) } return nil }
func (*functionSuite) TestCause(c *gc.C) { c.Assert(errors.Cause(nil), gc.IsNil) c.Assert(errors.Cause(someErr), gc.Equals, someErr) fmtErr := fmt.Errorf("simple") c.Assert(errors.Cause(fmtErr), gc.Equals, fmtErr) err := errors.Wrap(someErr, fmtErr) c.Assert(errors.Cause(err), gc.Equals, fmtErr) err = errors.Annotate(err, "annotated") c.Assert(errors.Cause(err), gc.Equals, fmtErr) err = errors.Maskf(err, "maksed") c.Assert(errors.Cause(err), gc.Equals, err) // Look for a file that we know isn't there. dir := c.MkDir() _, err = os.Stat(filepath.Join(dir, "not-there")) c.Assert(os.IsNotExist(err), jc.IsTrue) err = errors.Annotatef(err, "wrap it") // Now the error itself isn't a 'IsNotExist'. c.Assert(os.IsNotExist(err), jc.IsFalse) // However if we use the Check method, it is. c.Assert(os.IsNotExist(errors.Cause(err)), jc.IsTrue) }
func (api *UserManagerAPI) enableUserImpl(args params.Entities, action string, method func(*state.User) error) (params.ErrorResults, error) { result := params.ErrorResults{ Results: make([]params.ErrorResult, len(args.Entities)), } if len(args.Entities) == 0 { return result, nil } loggedInUser, err := api.getLoggedInUser() if err != nil { return result, errors.Wrap(err, common.ErrPerm) } // TODO(thumper): PERMISSIONS Change this permission check when we have // real permissions. For now, only the owner of the initial environment is // able to add users. if err := api.permissionCheck(loggedInUser); err != nil { return result, errors.Trace(err) } for i, arg := range args.Entities { user, err := api.getUser(arg.Tag) if err != nil { result.Results[i].Error = common.ServerError(err) continue } err = method(user) if err != nil { result.Results[i].Error = common.ServerError(errors.Errorf("failed to %s user: %s", action, err)) } } return result, nil }
// SendMetrics will send any unsent metrics // over the MetricSender interface in batches // no larger than batchSize. func SendMetrics(st *state.State, sender MetricSender, batchSize int) error { metricsManager, err := st.MetricsManager() if err != nil { return errors.Trace(err) } sent := 0 for { metrics, err := st.MetricsToSend(batchSize) if err != nil { return errors.Trace(err) } lenM := len(metrics) if lenM == 0 { if sent == 0 { logger.Infof("nothing to send") } else { logger.Infof("done sending") } break } wireData := make([]*wireformat.MetricBatch, lenM) for i, m := range metrics { wireData[i] = ToWire(m) } response, err := sender.Send(wireData) if err != nil { logger.Errorf("%+v", err) if incErr := metricsManager.IncrementConsecutiveErrors(); incErr != nil { logger.Errorf("failed to increment error count %v", incErr) return errors.Trace(errors.Wrap(err, incErr)) } return errors.Trace(err) } if response != nil { // TODO (mattyw) We are currently ignoring errors during response handling. handleResponse(metricsManager, st, *response) // TODO(fwereade): 2016-03-17 lp:1558657 if err := metricsManager.SetLastSuccessfulSend(time.Now()); err != nil { err = errors.Annotate(err, "failed to set successful send time") logger.Warningf("%v", err) return errors.Trace(err) } } sent += lenM } unsent, err := st.CountOfUnsentMetrics() if err != nil { return errors.Trace(err) } sentStored, err := st.CountOfSentMetrics() if err != nil { return errors.Trace(err) } logger.Infof("metrics collection summary: sent:%d unsent:%d (%d sent metrics stored)", sent, unsent, sentStored) return nil }
func (f *file) readFromServer() ([]byte, error) { // If the content is available, it is base64 encoded, so args := make(url.Values) args.Add("filename", f.filename) bytes, err := f.controller._getRaw("files", "get", args) if err != nil { if svrErr, ok := errors.Cause(err).(ServerError); ok { switch svrErr.StatusCode { case http.StatusNotFound: return nil, errors.Wrap(err, NewNoMatchError(svrErr.BodyMessage)) case http.StatusForbidden: return nil, errors.Wrap(err, NewPermissionError(svrErr.BodyMessage)) } } return nil, NewUnexpectedError(err) } return bytes, nil }
func (*functionSuite) TestWrap(c *gc.C) { first := errors.New("first") //err wrapFirst detailed := errors.New("detailed") err := errors.Wrap(first, detailed) //err wrapTest c.Assert(err.Error(), gc.Equals, "detailed") c.Assert(errors.Cause(err), gc.Equals, detailed) c.Assert(errors.Details(err), jc.Contains, tagToLocation["wrapFirst"].String()) c.Assert(errors.Details(err), jc.Contains, tagToLocation["wrapTest"].String()) }
func (m *model) validateStorage(allMachineIDs, allApplications, allUnits set.Strings) error { appsAndUnits := allApplications.Union(allUnits) allStorage := set.NewStrings() for i, storage := range m.Storages_.Storages_ { if err := storage.Validate(); err != nil { return errors.Annotatef(err, "storage[%d]", i) } allStorage.Add(storage.Tag().Id()) owner, err := storage.Owner() if err != nil { return errors.Wrap(err, errors.NotValidf("storage[%d] owner (%s)", i, owner)) } ownerID := owner.Id() if !appsAndUnits.Contains(ownerID) { return errors.NotValidf("storage[%d] owner (%s)", i, ownerID) } for _, unit := range storage.Attachments() { if !allUnits.Contains(unit.Id()) { return errors.NotValidf("storage[%d] attachment referencing unknown unit %q", i, unit) } } } allVolumes := set.NewStrings() for i, volume := range m.Volumes_.Volumes_ { if err := volume.Validate(); err != nil { return errors.Annotatef(err, "volume[%d]", i) } allVolumes.Add(volume.Tag().Id()) if storeID := volume.Storage().Id(); storeID != "" && !allStorage.Contains(storeID) { return errors.NotValidf("volume[%d] referencing unknown storage %q", i, storeID) } for j, attachment := range volume.Attachments() { if machineID := attachment.Machine().Id(); !allMachineIDs.Contains(machineID) { return errors.NotValidf("volume[%d].attachment[%d] referencing unknown machine %q", i, j, machineID) } } } for i, filesystem := range m.Filesystems_.Filesystems_ { if err := filesystem.Validate(); err != nil { return errors.Annotatef(err, "filesystem[%d]", i) } if storeID := filesystem.Storage().Id(); storeID != "" && !allStorage.Contains(storeID) { return errors.NotValidf("filesystem[%d] referencing unknown storage %q", i, storeID) } if volID := filesystem.Volume().Id(); volID != "" && !allVolumes.Contains(volID) { return errors.NotValidf("filesystem[%d] referencing unknown volume %q", i, volID) } for j, attachment := range filesystem.Attachments() { if machineID := attachment.Machine().Id(); !allMachineIDs.Contains(machineID) { return errors.NotValidf("filesystem[%d].attachment[%d] referencing unknown machine %q", i, j, machineID) } } } return nil }
// Call will repeatedly execute the Func until either the function returns no // error, the retry count is exceeded or the stop channel is closed. func Call(args CallArgs) error { err := args.Validate() if err != nil { return errors.Trace(err) } start := args.Clock.Now() for i := 1; args.Attempts <= 0 || i <= args.Attempts; i++ { err = args.Func() if err == nil { return nil } if args.IsFatalError != nil && args.IsFatalError(err) { return errors.Trace(err) } if args.NotifyFunc != nil { args.NotifyFunc(err, i) } if i == args.Attempts && args.Attempts > 0 { break // don't wait before returning the error } if args.BackoffFunc != nil { delay := args.BackoffFunc(args.Delay, i) if delay > args.MaxDelay && args.MaxDelay > 0 { delay = args.MaxDelay } args.Delay = delay } elapsedTime := args.Clock.Now().Sub(start) if args.MaxDuration > 0 && (elapsedTime+args.Delay) > args.MaxDuration { return errors.Wrap(err, &durationExceeded{err}) } // Wait for the delay, and retry select { case <-args.Clock.After(args.Delay): case <-args.Stop: return errors.Wrap(err, &retryStopped{err}) } } return errors.Wrap(err, &attemptsExceeded{err}) }
func (api *UserManagerAPI) getUser(tag string) (*state.User, error) { userTag, err := names.ParseUserTag(tag) if err != nil { return nil, errors.Trace(err) } user, err := api.state.User(userTag) if err != nil { return nil, errors.Wrap(err, common.ErrPerm) } return user, nil }
func (c *controller) checkCreds() error { if _, err := c.getOp("users", "whoami"); err != nil { if svrErr, ok := errors.Cause(err).(ServerError); ok { if svrErr.StatusCode == http.StatusUnauthorized { return errors.Wrap(err, NewPermissionError(svrErr.BodyMessage)) } } return NewUnexpectedError(err) } return nil }
// ReleaseMachines implements Controller. // // Release multiple machines at once. Returns // - BadRequestError if any of the machines cannot be found // - PermissionError if the user does not have permission to release any of the machines // - CannotCompleteError if any of the machines could not be released due to their current state func (c *controller) ReleaseMachines(args ReleaseMachinesArgs) error { params := NewURLParams() params.MaybeAddMany("machines", args.SystemIDs) params.MaybeAdd("comment", args.Comment) _, err := c.post("machines", "release", params.Values) if err != nil { if svrErr, ok := errors.Cause(err).(ServerError); ok { switch svrErr.StatusCode { case http.StatusBadRequest: return errors.Wrap(err, NewBadRequestError(svrErr.BodyMessage)) case http.StatusForbidden: return errors.Wrap(err, NewPermissionError(svrErr.BodyMessage)) case http.StatusConflict: return errors.Wrap(err, NewCannotCompleteError(svrErr.BodyMessage)) } } return NewUnexpectedError(err) } return nil }
// Validate implements Storage. func (s *storage) Validate() error { if s.ID_ == "" { return errors.NotValidf("storage missing id") } if s.Owner_ == "" { return errors.NotValidf("storage %q missing owner", s.ID_) } // Also check that the owner and attachments are valid. if _, err := s.Owner(); err != nil { return errors.Wrap(err, errors.NotValidf("storage %q invalid owner", s.ID_)) } return nil }
// ClaimLeadership is part of the Claimer interface. func (m *Manager) ClaimLeadership(sid, uid string, duration time.Duration) error { _, err := m.leaseMgr.ClaimLease(leadershipNamespace(sid), uid, duration) if err != nil { if errors.Cause(err) == lease.LeaseClaimDeniedErr { err = errors.Wrap(err, ErrClaimDenied) } else { err = errors.Annotate(err, "unable to make a leadership claim") } } return err }
// CreateInterface implements Device. func (d *device) CreateInterface(args CreateInterfaceArgs) (Interface, error) { if err := args.Validate(); err != nil { return nil, errors.Trace(err) } params := NewURLParams() params.Values.Add("name", args.Name) params.Values.Add("mac_address", args.MACAddress) params.Values.Add("vlan", fmt.Sprint(args.VLAN.ID())) params.MaybeAdd("tags", strings.Join(args.Tags, ",")) params.MaybeAddInt("mtu", args.MTU) params.MaybeAddBool("accept_ra", args.AcceptRA) params.MaybeAddBool("autoconf", args.Autoconf) result, err := d.controller.post(d.interfacesURI(), "create_physical", params.Values) if err != nil { if svrErr, ok := errors.Cause(err).(ServerError); ok { switch svrErr.StatusCode { case http.StatusNotFound, http.StatusConflict: return nil, errors.Wrap(err, NewBadRequestError(svrErr.BodyMessage)) case http.StatusForbidden: return nil, errors.Wrap(err, NewPermissionError(svrErr.BodyMessage)) case http.StatusServiceUnavailable: return nil, errors.Wrap(err, NewCannotCompleteError(svrErr.BodyMessage)) } } return nil, NewUnexpectedError(err) } iface, err := readInterface(d.controller.apiVersion, result) if err != nil { return nil, errors.Trace(err) } iface.controller = d.controller // TODO: add to the interfaces for the device when the interfaces are returned. // lp:bug 1567213. return iface, nil }