github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/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  }