github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/api/singular/api.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package singular 5 6 import ( 7 "time" 8 9 "github.com/juju/errors" 10 "gopkg.in/juju/names.v2" 11 12 "github.com/juju/juju/api/base" 13 "github.com/juju/juju/apiserver/params" 14 "github.com/juju/juju/core/lease" 15 ) 16 17 // NewAPI returns a new API client for the Singular facade. It exposes methods 18 // for claiming and observing administration responsibility for the apiCaller's 19 // model, on behalf of the supplied controller machine. 20 func NewAPI(apiCaller base.APICaller, controllerTag names.MachineTag) (*API, error) { 21 controllerId := controllerTag.Id() 22 if !names.IsValidMachine(controllerId) { 23 return nil, errors.NotValidf("controller tag") 24 } 25 modelTag, ok := apiCaller.ModelTag() 26 if !ok { 27 return nil, errors.New("cannot use singular API on controller-only connection") 28 } 29 facadeCaller := base.NewFacadeCaller(apiCaller, "Singular") 30 return &API{ 31 modelTag: modelTag, 32 controllerTag: controllerTag, 33 facadeCaller: facadeCaller, 34 }, nil 35 } 36 37 // API allows controller machines to claim responsibility for; or to wait for 38 // no other machine to have responsibility for; administration for some model. 39 type API struct { 40 modelTag names.ModelTag 41 controllerTag names.MachineTag 42 facadeCaller base.FacadeCaller 43 } 44 45 // Claim attempts to claim responsibility for model administration for the 46 // supplied duration. If the claim is denied, it will return 47 // lease.ErrClaimDenied. 48 func (api *API) Claim(duration time.Duration) error { 49 args := params.SingularClaims{ 50 Claims: []params.SingularClaim{{ 51 ModelTag: api.modelTag.String(), 52 ControllerTag: api.controllerTag.String(), 53 Duration: duration, 54 }}, 55 } 56 var results params.ErrorResults 57 err := api.facadeCaller.FacadeCall("Claim", args, &results) 58 if err != nil { 59 return errors.Trace(err) 60 } 61 62 err = results.OneError() 63 if err != nil { 64 if params.IsCodeLeaseClaimDenied(err) { 65 return lease.ErrClaimDenied 66 } 67 return errors.Trace(err) 68 } 69 return nil 70 } 71 72 // Wait blocks until nobody has responsibility for model administration. It 73 // should probably be doing something watchy rather than blocky, but it's 74 // following the lease manager implementation underlying the original 75 // leadership approach and it doesn't seem worth rewriting all that. 76 func (api *API) Wait() error { 77 args := params.Entities{ 78 Entities: []params.Entity{{ 79 Tag: api.modelTag.String(), 80 }}, 81 } 82 var results params.ErrorResults 83 err := api.facadeCaller.FacadeCall("Wait", args, &results) 84 if err != nil { 85 return errors.Trace(err) 86 } 87 return results.OneError() 88 }