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  }