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

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package migrationtarget
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	"github.com/juju/names"
     9  
    10  	"github.com/juju/juju/apiserver/common"
    11  	"github.com/juju/juju/apiserver/params"
    12  	"github.com/juju/juju/migration"
    13  	"github.com/juju/juju/state"
    14  )
    15  
    16  func init() {
    17  	common.RegisterStandardFacade("MigrationTarget", 1, NewAPI)
    18  }
    19  
    20  // API implements the API required for the model migration
    21  // master worker when communicating with the target controller.
    22  type API struct {
    23  	state      *state.State
    24  	authorizer common.Authorizer
    25  	resources  *common.Resources
    26  }
    27  
    28  // NewAPI returns a new API.
    29  func NewAPI(
    30  	st *state.State,
    31  	resources *common.Resources,
    32  	authorizer common.Authorizer,
    33  ) (*API, error) {
    34  	if err := checkAuth(authorizer, st); err != nil {
    35  		return nil, errors.Trace(err)
    36  	}
    37  	return &API{
    38  		state:      st,
    39  		authorizer: authorizer,
    40  		resources:  resources,
    41  	}, nil
    42  }
    43  
    44  func checkAuth(authorizer common.Authorizer, st *state.State) error {
    45  	if !authorizer.AuthClient() {
    46  		return errors.Trace(common.ErrPerm)
    47  	}
    48  
    49  	// Type assertion is fine because AuthClient is true.
    50  	apiUser := authorizer.GetAuthTag().(names.UserTag)
    51  	if isAdmin, err := st.IsControllerAdministrator(apiUser); err != nil {
    52  		return errors.Trace(err)
    53  	} else if !isAdmin {
    54  		// The entire facade is only accessible to controller administrators.
    55  		return errors.Trace(common.ErrPerm)
    56  	}
    57  	return nil
    58  }
    59  
    60  // Import takes a serialized Juju model, deserializes it, and
    61  // recreates it in the receiving controller.
    62  func (api *API) Import(serialized params.SerializedModel) error {
    63  	_, st, err := migration.ImportModel(api.state, serialized.Bytes)
    64  	if err != nil {
    65  		return err
    66  	}
    67  	defer st.Close()
    68  	// TODO(mjs) - post import checks
    69  	return err
    70  }
    71  
    72  func (api *API) getModel(args params.ModelArgs) (*state.Model, error) {
    73  	tag, err := names.ParseModelTag(args.ModelTag)
    74  	if err != nil {
    75  		return nil, errors.Trace(err)
    76  	}
    77  	model, err := api.state.GetModel(tag)
    78  	if err != nil {
    79  		return nil, errors.Trace(err)
    80  	}
    81  	if model.MigrationMode() != state.MigrationModeImporting {
    82  		return nil, errors.New("migration mode for the model is not importing")
    83  	}
    84  	return model, nil
    85  }
    86  
    87  // Abort removes the specified model from the database. It is an error to
    88  // attempt to Abort a model that has a migration mode other than importing.
    89  func (api *API) Abort(args params.ModelArgs) error {
    90  	model, err := api.getModel(args)
    91  	if err != nil {
    92  		return errors.Trace(err)
    93  	}
    94  
    95  	st, err := api.state.ForModel(model.ModelTag())
    96  	if err != nil {
    97  		return errors.Trace(err)
    98  	}
    99  	defer st.Close()
   100  
   101  	return st.RemoveImportingModelDocs()
   102  }
   103  
   104  // Activate sets the migration mode of the model to "active". It is an error to
   105  // attempt to Abort a model that has a migration mode other than importing.
   106  func (api *API) Activate(args params.ModelArgs) error {
   107  	model, err := api.getModel(args)
   108  	if err != nil {
   109  		return errors.Trace(err)
   110  	}
   111  
   112  	return model.SetMigrationMode(state.MigrationModeActive)
   113  }