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 }