github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/provider/vsphere/upgrades.go (about)

     1  // Copyright 2017 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package vsphere
     5  
     6  import (
     7  	"path"
     8  
     9  	"github.com/juju/errors"
    10  	"github.com/vmware/govmomi/vim25/types"
    11  
    12  	"github.com/juju/juju/environs"
    13  	"github.com/juju/juju/environs/context"
    14  	"github.com/juju/juju/environs/tags"
    15  )
    16  
    17  // UpgradeOperations is part of the upgrades.OperationSource interface.
    18  func (env *environ) UpgradeOperations(ctx context.ProviderCallContext, args environs.UpgradeOperationsParams) []environs.UpgradeOperation {
    19  	return []environs.UpgradeOperation{{
    20  		providerVersion1,
    21  		[]environs.UpgradeStep{
    22  			extraConfigUpgradeStep{env, args.ControllerUUID},
    23  			modelFoldersUpgradeStep{env, args.ControllerUUID},
    24  		},
    25  	}}
    26  }
    27  
    28  // extraConfigUpgradeStep moves top-level VMs into a model-specific
    29  // VM folder.
    30  type extraConfigUpgradeStep struct {
    31  	env            *environ
    32  	controllerUUID string
    33  }
    34  
    35  // Description is part of the environs.UpgradeStep interface.
    36  func (extraConfigUpgradeStep) Description() string {
    37  	return "Update ExtraConfig properties with standard Juju tags"
    38  }
    39  
    40  // Run is part of the environs.UpgradeStep interface.
    41  func (step extraConfigUpgradeStep) Run(ctx context.ProviderCallContext) error {
    42  	const (
    43  		legacyControllerTag   = "juju_controller_uuid_key"
    44  		legacyIsControllerTag = "juju_is_controller_key"
    45  	)
    46  	return step.env.withSession(ctx, func(env *sessionEnviron) error {
    47  		vms, err := env.client.VirtualMachines(env.ctx, env.namespace.Prefix()+"*")
    48  		if err != nil || len(vms) == 0 {
    49  			HandleCredentialError(err, ctx)
    50  			return err
    51  		}
    52  		for _, vm := range vms {
    53  			update := false
    54  			isController := false
    55  			for _, opt := range vm.Config.ExtraConfig {
    56  				value := opt.GetOptionValue()
    57  				switch value.Key {
    58  				case legacyControllerTag:
    59  					update = true
    60  				case legacyIsControllerTag:
    61  					isController = true
    62  				}
    63  			}
    64  			if !update {
    65  				continue
    66  			}
    67  			metadata := map[string]string{
    68  				tags.JujuController: step.controllerUUID,
    69  				tags.JujuModel:      env.Config().UUID(),
    70  			}
    71  			if isController {
    72  				metadata[tags.JujuIsController] = "true"
    73  			}
    74  			if err := env.client.UpdateVirtualMachineExtraConfig(
    75  				env.ctx, vm, metadata,
    76  			); err != nil {
    77  				HandleCredentialError(err, ctx)
    78  				return errors.Annotatef(err, "updating VM %s", vm.Name)
    79  			}
    80  		}
    81  		return nil
    82  	})
    83  }
    84  
    85  // modelFoldersUpgradeStep moves top-level VMs into a model-specific
    86  // VM folder.
    87  type modelFoldersUpgradeStep struct {
    88  	env            *environ
    89  	controllerUUID string
    90  }
    91  
    92  // Description is part of the environs.UpgradeStep interface.
    93  func (modelFoldersUpgradeStep) Description() string {
    94  	return "Move VMs into controller/model folders"
    95  }
    96  
    97  // Run is part of the environs.UpgradeStep interface.
    98  func (step modelFoldersUpgradeStep) Run(ctx context.ProviderCallContext) error {
    99  	return step.env.withSession(ctx, func(env *sessionEnviron) error {
   100  		// We must create the folder even if there are no VMs in the model.
   101  		modelFolderPath := path.Join(
   102  			controllerFolderName(step.controllerUUID),
   103  			env.modelFolderName(),
   104  		)
   105  		if _, err := env.client.EnsureVMFolder(env.ctx, modelFolderPath); err != nil {
   106  			HandleCredentialError(err, ctx)
   107  			return errors.Annotate(err, "creating model folder")
   108  		}
   109  
   110  		// List all instances at the top level with the model UUID,
   111  		// and move them into the folder.
   112  		vms, err := env.client.VirtualMachines(env.ctx, env.namespace.Prefix()+"*")
   113  		if err != nil || len(vms) == 0 {
   114  			HandleCredentialError(err, ctx)
   115  			return err
   116  		}
   117  		refs := make([]types.ManagedObjectReference, len(vms))
   118  		for i, vm := range vms {
   119  			logger.Debugf("moving VM %q into %q", vm.Name, modelFolderPath)
   120  			refs[i] = vm.Reference()
   121  		}
   122  		if err := env.client.MoveVMsInto(env.ctx, modelFolderPath, refs...); err != nil {
   123  			HandleCredentialError(err, ctx)
   124  			return errors.Annotate(err, "moving VMs into model folder")
   125  		}
   126  		return nil
   127  	})
   128  }