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