github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/apiserver/facades/agent/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  // NewRebootAPI creates a new server-side RebootAPI facade.
    34  func NewRebootAPI(st *state.State, resources facade.Resources, auth facade.Authorizer) (*RebootAPI, error) {
    35  	if !auth.AuthMachineAgent() {
    36  		return nil, common.ErrPerm
    37  	}
    38  
    39  	tag, ok := auth.GetAuthTag().(names.MachineTag)
    40  	if !ok {
    41  		return nil, errors.Errorf("Expected names.MachineTag, got %T", auth.GetAuthTag())
    42  	}
    43  	machine, err := st.Machine(tag.Id())
    44  	if err != nil {
    45  		return nil, errors.Trace(err)
    46  	}
    47  
    48  	canAccess := func() (common.AuthFunc, error) {
    49  		return auth.AuthOwner, nil
    50  	}
    51  
    52  	return &RebootAPI{
    53  		RebootActionGetter: common.NewRebootActionGetter(st, canAccess),
    54  		RebootRequester:    common.NewRebootRequester(st, canAccess),
    55  		RebootFlagClearer:  common.NewRebootFlagClearer(st, canAccess),
    56  		st:                 st,
    57  		machine:            machine,
    58  		resources:          resources,
    59  		auth:               auth,
    60  	}, nil
    61  }
    62  
    63  // WatchForRebootEvent starts a watcher to track if there is a new
    64  // reboot request on the machines ID or any of its parents (in case we are a container).
    65  func (r *RebootAPI) WatchForRebootEvent() (params.NotifyWatchResult, error) {
    66  	err := common.ErrPerm
    67  	var watch state.NotifyWatcher
    68  	var result params.NotifyWatchResult
    69  
    70  	if r.auth.AuthOwner(r.machine.Tag()) {
    71  		watch = r.machine.WatchForRebootEvent()
    72  		err = nil
    73  		// Consume the initial event. Technically, API
    74  		// calls to Watch 'transmit' the initial event
    75  		// in the Watch response. But NotifyWatchers
    76  		// have no state to transmit.
    77  		if _, ok := <-watch.Changes(); ok {
    78  			result.NotifyWatcherId = r.resources.Register(watch)
    79  		} else {
    80  			err = watcher.EnsureErr(watch)
    81  		}
    82  	}
    83  	result.Error = common.ServerError(err)
    84  	return result, nil
    85  }