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 }