github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/api/controller/controller.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package controller
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	"github.com/juju/loggo"
     9  	"github.com/juju/names"
    10  
    11  	"github.com/juju/juju/api"
    12  	"github.com/juju/juju/api/base"
    13  	"github.com/juju/juju/apiserver/params"
    14  )
    15  
    16  var logger = loggo.GetLogger("juju.api.controller")
    17  
    18  // Client provides methods that the Juju client command uses to interact
    19  // with the Juju controller.
    20  type Client struct {
    21  	base.ClientFacade
    22  	facade base.FacadeCaller
    23  }
    24  
    25  // NewClient creates a new `Client` based on an existing authenticated API
    26  // connection.
    27  func NewClient(st base.APICallCloser) *Client {
    28  	frontend, backend := base.NewClientFacade(st, "Controller")
    29  	return &Client{ClientFacade: frontend, facade: backend}
    30  }
    31  
    32  // AllModels allows controller administrators to get the list of all the
    33  // models in the controller.
    34  func (c *Client) AllModels() ([]base.UserModel, error) {
    35  	var models params.UserModelList
    36  	err := c.facade.FacadeCall("AllModels", nil, &models)
    37  	if err != nil {
    38  		return nil, errors.Trace(err)
    39  	}
    40  	result := make([]base.UserModel, len(models.UserModels))
    41  	for i, model := range models.UserModels {
    42  		owner, err := names.ParseUserTag(model.OwnerTag)
    43  		if err != nil {
    44  			return nil, errors.Annotatef(err, "OwnerTag %q at position %d", model.OwnerTag, i)
    45  		}
    46  		result[i] = base.UserModel{
    47  			Name:           model.Name,
    48  			UUID:           model.UUID,
    49  			Owner:          owner.Canonical(),
    50  			LastConnection: model.LastConnection,
    51  		}
    52  	}
    53  	return result, nil
    54  }
    55  
    56  // ModelConfig returns all model settings for the
    57  // controller model.
    58  func (c *Client) ModelConfig() (map[string]interface{}, error) {
    59  	result := params.ModelConfigResults{}
    60  	err := c.facade.FacadeCall("ModelConfig", nil, &result)
    61  	return result.Config, err
    62  }
    63  
    64  // DestroyController puts the controller model into a "dying" state,
    65  // and removes all non-manager machine instances. Underlying DestroyModel
    66  // calls will fail if there are any manually-provisioned non-manager machines
    67  // in state.
    68  func (c *Client) DestroyController(destroyModels bool) error {
    69  	args := params.DestroyControllerArgs{
    70  		DestroyModels: destroyModels,
    71  	}
    72  	return c.facade.FacadeCall("DestroyController", args, nil)
    73  }
    74  
    75  // ListBlockedModels returns a list of all models within the controller
    76  // which have at least one block in place.
    77  func (c *Client) ListBlockedModels() ([]params.ModelBlockInfo, error) {
    78  	result := params.ModelBlockInfoList{}
    79  	err := c.facade.FacadeCall("ListBlockedModels", nil, &result)
    80  	return result.Models, err
    81  }
    82  
    83  // RemoveBlocks removes all the blocks in the controller.
    84  func (c *Client) RemoveBlocks() error {
    85  	args := params.RemoveBlocksArgs{All: true}
    86  	return c.facade.FacadeCall("RemoveBlocks", args, nil)
    87  }
    88  
    89  // WatchAllModels returns an AllWatcher, from which you can request
    90  // the Next collection of Deltas (for all models).
    91  func (c *Client) WatchAllModels() (*api.AllWatcher, error) {
    92  	info := new(api.WatchAll)
    93  	if err := c.facade.FacadeCall("WatchAllModels", nil, info); err != nil {
    94  		return nil, err
    95  	}
    96  	return api.NewAllModelWatcher(c.facade.RawAPICaller(), &info.AllWatcherId), nil
    97  }
    98  
    99  // ModelStatus returns a status summary for each model tag passed in.
   100  func (c *Client) ModelStatus(tags ...names.ModelTag) ([]base.ModelStatus, error) {
   101  	result := params.ModelStatusResults{}
   102  	models := make([]params.Entity, len(tags))
   103  	for i, tag := range tags {
   104  		models[i] = params.Entity{Tag: tag.String()}
   105  	}
   106  	req := params.Entities{
   107  		Entities: models,
   108  	}
   109  	if err := c.facade.FacadeCall("ModelStatus", req, &result); err != nil {
   110  		return nil, err
   111  	}
   112  
   113  	results := make([]base.ModelStatus, len(result.Results))
   114  	for i, r := range result.Results {
   115  		model, err := names.ParseModelTag(r.ModelTag)
   116  		if err != nil {
   117  			return nil, errors.Annotatef(err, "ModelTag %q at position %d", r.ModelTag, i)
   118  		}
   119  		owner, err := names.ParseUserTag(r.OwnerTag)
   120  		if err != nil {
   121  			return nil, errors.Annotatef(err, "OwnerTag %q at position %d", r.OwnerTag, i)
   122  		}
   123  
   124  		results[i] = base.ModelStatus{
   125  			UUID:               model.Id(),
   126  			Life:               r.Life,
   127  			Owner:              owner.Canonical(),
   128  			HostedMachineCount: r.HostedMachineCount,
   129  			ServiceCount:       r.ServiceCount,
   130  		}
   131  
   132  	}
   133  	return results, nil
   134  }
   135  
   136  // ModelMigrationSpec holds the details required to start the
   137  // migration of a single model.
   138  type ModelMigrationSpec struct {
   139  	ModelUUID            string
   140  	TargetControllerUUID string
   141  	TargetAddrs          []string
   142  	TargetCACert         string
   143  	TargetUser           string
   144  	TargetPassword       string
   145  }
   146  
   147  // Validate performs sanity checks on the migration configuration it
   148  // holds.
   149  func (s *ModelMigrationSpec) Validate() error {
   150  	if !names.IsValidModel(s.ModelUUID) {
   151  		return errors.NotValidf("model UUID")
   152  	}
   153  	if !names.IsValidModel(s.TargetControllerUUID) {
   154  		return errors.NotValidf("controller UUID")
   155  	}
   156  	if len(s.TargetAddrs) < 1 {
   157  		return errors.NotValidf("empty target API addresses")
   158  	}
   159  	if s.TargetCACert == "" {
   160  		return errors.NotValidf("empty target CA cert")
   161  	}
   162  	if !names.IsValidUser(s.TargetUser) {
   163  		return errors.NotValidf("target user")
   164  	}
   165  	if s.TargetPassword == "" {
   166  		return errors.NotValidf("empty target password")
   167  	}
   168  	return nil
   169  }
   170  
   171  // InitiateModelMigration attempts to start a migration for the
   172  // specified model, returning the migration's ID.
   173  //
   174  // The API server supports starting multiple migrations in one request
   175  // but we don't need that at the client side yet (and may never) so
   176  // this call just supports starting one migration at a time.
   177  func (c *Client) InitiateModelMigration(spec ModelMigrationSpec) (string, error) {
   178  	if err := spec.Validate(); err != nil {
   179  		return "", errors.Trace(err)
   180  	}
   181  	args := params.InitiateModelMigrationArgs{
   182  		Specs: []params.ModelMigrationSpec{{
   183  			ModelTag: names.NewModelTag(spec.ModelUUID).String(),
   184  			TargetInfo: params.ModelMigrationTargetInfo{
   185  				ControllerTag: names.NewModelTag(spec.TargetControllerUUID).String(),
   186  				Addrs:         spec.TargetAddrs,
   187  				CACert:        spec.TargetCACert,
   188  				AuthTag:       names.NewUserTag(spec.TargetUser).String(),
   189  				Password:      spec.TargetPassword,
   190  			},
   191  		}},
   192  	}
   193  	response := params.InitiateModelMigrationResults{}
   194  	if err := c.facade.FacadeCall("InitiateModelMigration", args, &response); err != nil {
   195  		return "", errors.Trace(err)
   196  	}
   197  	if len(response.Results) != 1 {
   198  		return "", errors.New("unexpected number of results returned")
   199  	}
   200  	result := response.Results[0]
   201  	if result.Error != nil {
   202  		return "", errors.Trace(result.Error)
   203  	}
   204  	return result.Id, nil
   205  }