github.com/altoros/juju-vmware@v0.0.0-20150312064031-f19ae857ccca/provider/vmware/environ_broker.go (about)

     1  // Copyright 2014 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package vmware
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	"github.com/vmware/govmomi/vim25/mo"
     9  
    10  	coreCloudinit "github.com/juju/juju/cloudinit"
    11  	"github.com/juju/juju/environs"
    12  	"github.com/juju/juju/environs/cloudinit"
    13  	"github.com/juju/juju/instance"
    14  	"github.com/juju/juju/provider/common"
    15  	"github.com/juju/juju/state/multiwatcher"
    16  	"github.com/juju/juju/tools"
    17  	"github.com/juju/utils"
    18  )
    19  
    20  func isStateServer(mcfg *cloudinit.MachineConfig) bool {
    21  	return multiwatcher.AnyJobNeedsState(mcfg.Jobs...)
    22  }
    23  
    24  // StartInstance implements environs.InstanceBroker.
    25  func (env *environ) StartInstance(args environs.StartInstanceParams) (*environs.StartInstanceResult, error) {
    26  	env = env.getSnapshot()
    27  
    28  	if args.MachineConfig.HasNetworks() {
    29  		return nil, errors.New("starting instances with networks is not supported yet")
    30  	}
    31  
    32  	img, err := findImageMetadata(env, args)
    33  	if err != nil {
    34  		return nil, errors.Trace(err)
    35  	}
    36  	if err := env.finishMachineConfig(args, img); err != nil {
    37  		return nil, errors.Trace(err)
    38  	}
    39  
    40  	raw, hwc, err := newRawInstance(env, args, img)
    41  	if err != nil {
    42  		return nil, errors.Trace(err)
    43  	}
    44  
    45  	logger.Infof("started instance %q", raw.Name)
    46  	inst := newInstance(raw, env)
    47  
    48  	result := environs.StartInstanceResult{
    49  		Instance: inst,
    50  		Hardware: hwc,
    51  	}
    52  	return &result, nil
    53  }
    54  
    55  var newRawInstance = func(env *environ, args environs.StartInstanceParams, img *OvfFileMetadata) (*mo.VirtualMachine, *instance.HardwareCharacteristics, error) {
    56  	return env.newRawInstance(args, img)
    57  }
    58  
    59  // finishMachineConfig updates args.MachineConfig in place. Setting up
    60  // the API, StateServing, and SSHkeys information.
    61  func (env *environ) finishMachineConfig(args environs.StartInstanceParams, img *OvfFileMetadata) error {
    62  	envTools, err := args.Tools.Match(tools.Filter{Arch: img.Arch})
    63  	if err != nil {
    64  		return err
    65  	}
    66  
    67  	args.MachineConfig.Tools = envTools[0]
    68  	return environs.FinishMachineConfig(args.MachineConfig, env.Config())
    69  }
    70  
    71  // newRawInstance is where the new physical instance is actually
    72  // provisioned, relative to the provided args and spec. Info for that
    73  // low-level instance is returned.
    74  func (env *environ) newRawInstance(args environs.StartInstanceParams, img *OvfFileMetadata) (*mo.VirtualMachine, *instance.HardwareCharacteristics, error) {
    75  	machineID := common.MachineFullName(env, args.MachineConfig.MachineId)
    76  
    77  	config := coreCloudinit.New()
    78  	config.SetAptUpdate(true)
    79  	config.SetAptUpgrade(true)
    80  	config.AddPackage("open-vm-tools")
    81  	userData, err := environs.ComposeUserData(args.MachineConfig, config)
    82  	if err != nil {
    83  		return nil, nil, errors.Annotate(err, "cannot make user data")
    84  	}
    85  	userData, err = utils.Gunzip(userData)
    86  	if err != nil {
    87  		return nil, nil, errors.Trace(err)
    88  	}
    89  	logger.Debugf("Vmware user data; %d bytes", len(userData))
    90  
    91  	rootDisk := common.MinRootDiskSizeMB
    92  	if args.Constraints.RootDisk != nil && *args.Constraints.RootDisk > rootDisk {
    93  		rootDisk = *args.Constraints.RootDisk
    94  	}
    95  	cpuCores := uint64(2)
    96  	if args.Constraints.CpuCores != nil {
    97  		cpuCores = *args.Constraints.CpuCores
    98  	}
    99  	cpuPower := uint64(2000)
   100  	if args.Constraints.CpuPower != nil {
   101  		cpuPower = *args.Constraints.CpuPower
   102  	}
   103  	mem := uint64(2000)
   104  	if args.Constraints.Mem != nil {
   105  		mem = *args.Constraints.Mem
   106  	}
   107  
   108  	hwc := &instance.HardwareCharacteristics{
   109  		Arch:     &img.Arch,
   110  		Mem:      &mem,
   111  		CpuCores: &cpuCores,
   112  		CpuPower: &cpuPower,
   113  		RootDisk: &rootDisk,
   114  	}
   115  	inst, err := env.client.CreateInstance(machineID, hwc, img, userData, args.MachineConfig.AuthorizedKeys, isStateServer(args.MachineConfig))
   116  	return inst, hwc, err
   117  }
   118  
   119  // AllInstances implements environs.InstanceBroker.
   120  func (env *environ) AllInstances() ([]instance.Instance, error) {
   121  	instances, err := getInstances(env)
   122  	return instances, errors.Trace(err)
   123  }
   124  
   125  // StopInstances implements environs.InstanceBroker.
   126  func (env *environ) StopInstances(instances ...instance.Id) error {
   127  	env = env.getSnapshot()
   128  
   129  	var ids []string
   130  	for _, id := range instances {
   131  		ids = append(ids, string(id))
   132  	}
   133  
   134  	err := env.client.RemoveInstances(ids...)
   135  	return errors.Trace(err)
   136  }