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