github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/apiserver/reboot/reboot.go (about) 1 // Copyright 2014 Cloudbase Solutions SRL 2 // Copyright 2014 Canonical Ltd. 3 // Licensed under the AGPLv3, see LICENCE file for details. 4 5 package reboot 6 7 import ( 8 "github.com/juju/errors" 9 "gopkg.in/juju/names.v2" 10 11 "github.com/juju/juju/apiserver/common" 12 "github.com/juju/juju/apiserver/facade" 13 "github.com/juju/juju/apiserver/params" 14 "github.com/juju/juju/state" 15 "github.com/juju/juju/state/watcher" 16 ) 17 18 // RebootAPI provides access to the Upgrader API facade. 19 type RebootAPI struct { 20 *common.RebootActionGetter 21 // The ability for a machine to reboot itself is not yet used. 22 // It will be used for situations like container support in Windows 23 // Where installing the hyper-v role will require a reboot. 24 *common.RebootRequester 25 *common.RebootFlagClearer 26 27 auth facade.Authorizer 28 st *state.State 29 machine *state.Machine 30 resources facade.Resources 31 } 32 33 func init() { 34 common.RegisterStandardFacade("Reboot", 2, NewRebootAPI) 35 } 36 37 // NewRebootAPI creates a new server-side RebootAPI facade. 38 func NewRebootAPI(st *state.State, resources facade.Resources, auth facade.Authorizer) (*RebootAPI, error) { 39 if !auth.AuthMachineAgent() { 40 return nil, common.ErrPerm 41 } 42 43 tag, ok := auth.GetAuthTag().(names.MachineTag) 44 if !ok { 45 return nil, errors.Errorf("Expected names.MachineTag, got %T", auth.GetAuthTag()) 46 } 47 machine, err := st.Machine(tag.Id()) 48 if err != nil { 49 return nil, errors.Trace(err) 50 } 51 52 canAccess := func() (common.AuthFunc, error) { 53 return auth.AuthOwner, nil 54 } 55 56 return &RebootAPI{ 57 RebootActionGetter: common.NewRebootActionGetter(st, canAccess), 58 RebootRequester: common.NewRebootRequester(st, canAccess), 59 RebootFlagClearer: common.NewRebootFlagClearer(st, canAccess), 60 st: st, 61 machine: machine, 62 resources: resources, 63 auth: auth, 64 }, nil 65 } 66 67 // WatchForRebootEvent starts a watcher to track if there is a new 68 // reboot request on the machines ID or any of its parents (in case we are a container). 69 func (r *RebootAPI) WatchForRebootEvent() (params.NotifyWatchResult, error) { 70 err := common.ErrPerm 71 var watch state.NotifyWatcher 72 var result params.NotifyWatchResult 73 74 if r.auth.AuthOwner(r.machine.Tag()) { 75 watch = r.machine.WatchForRebootEvent() 76 err = nil 77 // Consume the initial event. Technically, API 78 // calls to Watch 'transmit' the initial event 79 // in the Watch response. But NotifyWatchers 80 // have no state to transmit. 81 if _, ok := <-watch.Changes(); ok { 82 result.NotifyWatcherId = r.resources.Register(watch) 83 } else { 84 err = watcher.EnsureErr(watch) 85 } 86 } 87 result.Error = common.ServerError(err) 88 return result, nil 89 }