github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/api/singular/api.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package singular
     5  
     6  import (
     7  	"time"
     8  
     9  	"github.com/juju/errors"
    10  	"gopkg.in/juju/names.v2"
    11  
    12  	"github.com/juju/juju/api/base"
    13  	"github.com/juju/juju/apiserver/params"
    14  	"github.com/juju/juju/core/lease"
    15  )
    16  
    17  // NewAPI returns a new API client for the Singular facade. It exposes methods
    18  // for claiming and observing administration responsibility for the apiCaller's
    19  // model, on behalf of the supplied controller machine.
    20  func NewAPI(apiCaller base.APICaller, controllerTag names.MachineTag) (*API, error) {
    21  	controllerId := controllerTag.Id()
    22  	if !names.IsValidMachine(controllerId) {
    23  		return nil, errors.NotValidf("controller tag")
    24  	}
    25  	modelTag, ok := apiCaller.ModelTag()
    26  	if !ok {
    27  		return nil, errors.New("cannot use singular API on controller-only connection")
    28  	}
    29  	facadeCaller := base.NewFacadeCaller(apiCaller, "Singular")
    30  	return &API{
    31  		modelTag:      modelTag,
    32  		controllerTag: controllerTag,
    33  		facadeCaller:  facadeCaller,
    34  	}, nil
    35  }
    36  
    37  // API allows controller machines to claim responsibility for; or to wait for
    38  // no other machine to have responsibility for; administration for some model.
    39  type API struct {
    40  	modelTag      names.ModelTag
    41  	controllerTag names.MachineTag
    42  	facadeCaller  base.FacadeCaller
    43  }
    44  
    45  // Claim attempts to claim responsibility for model administration for the
    46  // supplied duration. If the claim is denied, it will return
    47  // lease.ErrClaimDenied.
    48  func (api *API) Claim(duration time.Duration) error {
    49  	args := params.SingularClaims{
    50  		Claims: []params.SingularClaim{{
    51  			ModelTag:      api.modelTag.String(),
    52  			ControllerTag: api.controllerTag.String(),
    53  			Duration:      duration,
    54  		}},
    55  	}
    56  	var results params.ErrorResults
    57  	err := api.facadeCaller.FacadeCall("Claim", args, &results)
    58  	if err != nil {
    59  		return errors.Trace(err)
    60  	}
    61  
    62  	err = results.OneError()
    63  	if err != nil {
    64  		if params.IsCodeLeaseClaimDenied(err) {
    65  			return lease.ErrClaimDenied
    66  		}
    67  		return errors.Trace(err)
    68  	}
    69  	return nil
    70  }
    71  
    72  // Wait blocks until nobody has responsibility for model administration. It
    73  // should probably be doing something watchy rather than blocky, but it's
    74  // following the lease manager implementation underlying the original
    75  // leadership approach and it doesn't seem worth rewriting all that.
    76  func (api *API) Wait() error {
    77  	args := params.Entities{
    78  		Entities: []params.Entity{{
    79  			Tag: api.modelTag.String(),
    80  		}},
    81  	}
    82  	var results params.ErrorResults
    83  	err := api.facadeCaller.FacadeCall("Wait", args, &results)
    84  	if err != nil {
    85  		return errors.Trace(err)
    86  	}
    87  	return results.OneError()
    88  }