github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/cmd/juju/commands/migrate.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package commands 5 6 import ( 7 "github.com/juju/cmd" 8 "github.com/juju/errors" 9 10 "github.com/juju/juju/api/controller" 11 "github.com/juju/juju/cmd/modelcmd" 12 ) 13 14 func newMigrateCommand() cmd.Command { 15 return modelcmd.WrapController(&migrateCommand{}) 16 } 17 18 // migrateCommand initiates a model migration. 19 type migrateCommand struct { 20 modelcmd.ControllerCommandBase 21 api migrateAPI 22 23 model string 24 targetController string 25 } 26 27 type migrateAPI interface { 28 InitiateModelMigration(spec controller.ModelMigrationSpec) (string, error) 29 } 30 31 const migrateDoc = ` 32 migrate begins the migration of a model from its current controller to 33 a new controller. This is useful for load balancing when a controller 34 is too busy, or as a way to upgrade a model's controller to a newer 35 Juju version. Once complete, the model's machine and and unit agents 36 will be connected to the new controller. The model will no longer be 37 available at the source controller. 38 39 Note that only hosted models can be migrated. Controller models can 40 not be migrated. 41 42 If the migration fails for some reason, the model be returned to its 43 original state with the model being managed by the original 44 controller. 45 46 In order to start a migration, the target controller must be in the 47 juju client's local configuration cache. See the juju "login" command 48 for details of how to do this. 49 50 This command only starts a model migration - it does not wait for its 51 completion. The progress of a migration can be tracked using the 52 "status" command and by consulting the logs. 53 54 See Also: 55 juju help login 56 juju help controllers 57 juju help status 58 ` 59 60 // Info implements cmd.Command. 61 func (c *migrateCommand) Info() *cmd.Info { 62 return &cmd.Info{ 63 Name: "migrate", 64 Args: "<model-name> <target-controller-name>", 65 Purpose: "migrate a hosted model to another controller", 66 Doc: migrateDoc, 67 } 68 } 69 70 // Init implements cmd.Command. 71 func (c *migrateCommand) Init(args []string) error { 72 if len(args) < 1 { 73 return errors.New("model not specified") 74 } 75 if len(args) < 2 { 76 return errors.New("target controller not specified") 77 } 78 if len(args) > 2 { 79 return errors.New("too many arguments specified") 80 } 81 82 c.model = args[0] 83 c.targetController = args[1] 84 return nil 85 } 86 87 func (c *migrateCommand) getMigrationSpec() (*controller.ModelMigrationSpec, error) { 88 store := c.ClientStore() 89 90 modelInfo, err := store.ModelByName(c.ControllerName(), c.AccountName(), c.model) 91 if err != nil { 92 return nil, err 93 } 94 95 controllerName, err := modelcmd.ResolveControllerName(store, c.targetController) 96 if err != nil { 97 return nil, err 98 } 99 100 controllerInfo, err := store.ControllerByName(controllerName) 101 if err != nil { 102 return nil, err 103 } 104 105 accountName, err := store.CurrentAccount(controllerName) 106 if err != nil { 107 return nil, err 108 } 109 110 accountInfo, err := store.AccountByName(controllerName, accountName) 111 if err != nil { 112 return nil, err 113 } 114 115 return &controller.ModelMigrationSpec{ 116 ModelUUID: modelInfo.ModelUUID, 117 TargetControllerUUID: controllerInfo.ControllerUUID, 118 TargetAddrs: controllerInfo.APIEndpoints, 119 TargetCACert: controllerInfo.CACert, 120 TargetUser: accountInfo.User, 121 TargetPassword: accountInfo.Password, 122 }, nil 123 } 124 125 // Run implements cmd.Command. 126 func (c *migrateCommand) Run(ctx *cmd.Context) error { 127 spec, err := c.getMigrationSpec() 128 if err != nil { 129 return err 130 } 131 api, err := c.getAPI() 132 if err != nil { 133 return err 134 } 135 id, err := api.InitiateModelMigration(*spec) 136 if err != nil { 137 return err 138 } 139 ctx.Infof("Migration started with ID %q", id) 140 return nil 141 } 142 143 func (c *migrateCommand) getAPI() (migrateAPI, error) { 144 if c.api != nil { 145 return c.api, nil 146 } 147 return c.NewControllerAPIClient() 148 }