github.com/mhilton/juju-juju@v0.0.0-20150901100907-a94dd2c73455/provider/vsphere/environ_broker_test.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 // +build !gccgo 5 6 package vsphere_test 7 8 import ( 9 jc "github.com/juju/testing/checkers" 10 gc "gopkg.in/check.v1" 11 12 "github.com/juju/errors" 13 "github.com/juju/govmomi/vim25/methods" 14 "github.com/juju/govmomi/vim25/soap" 15 "github.com/juju/govmomi/vim25/types" 16 17 "github.com/juju/juju/cloudconfig/instancecfg" 18 "github.com/juju/juju/constraints" 19 "github.com/juju/juju/environs" 20 "github.com/juju/juju/environs/config" 21 "github.com/juju/juju/environs/imagemetadata" 22 "github.com/juju/juju/instance" 23 "github.com/juju/juju/juju/arch" 24 "github.com/juju/juju/provider/common" 25 "github.com/juju/juju/provider/vsphere" 26 "github.com/juju/juju/tools" 27 "github.com/juju/juju/version" 28 ) 29 30 type environBrokerSuite struct { 31 vsphere.BaseSuite 32 } 33 34 var _ = gc.Suite(&environBrokerSuite{}) 35 36 func (s *environBrokerSuite) SetUpTest(c *gc.C) { 37 s.BaseSuite.SetUpTest(c) 38 } 39 40 func (s *environBrokerSuite) PrepareStartInstanceFakes(c *gc.C) { 41 // Prevent falling over to the public datasource. 42 s.BaseSuite.PatchValue(&imagemetadata.DefaultBaseURL, "") 43 44 client := vsphere.ExposeEnvFakeClient(s.Env) 45 client.SetPropertyProxyHandler("FakeDatacenter", vsphere.RetrieveDatacenterProperties) 46 s.FakeInstances(client) 47 s.FakeAvailabilityZones(client, "z1") 48 s.FakeAvailabilityZones(client, "z1") 49 s.FakeAvailabilityZones(client, "z1") 50 s.FakeCreateInstance(client, s.ServerUrl, c) 51 } 52 53 func (s *environBrokerSuite) CreateStartInstanceArgs(c *gc.C) environs.StartInstanceParams { 54 tools := []*tools.Tools{{ 55 Version: version.Binary{Arch: arch.AMD64, Series: "trusty"}, 56 URL: "https://example.org", 57 }} 58 59 cons := constraints.Value{} 60 61 instanceConfig, err := instancecfg.NewBootstrapInstanceConfig(cons, "trusty") 62 c.Assert(err, jc.ErrorIsNil) 63 64 instanceConfig.Tools = tools[0] 65 instanceConfig.AuthorizedKeys = s.Config.AuthorizedKeys() 66 67 return environs.StartInstanceParams{ 68 InstanceConfig: instanceConfig, 69 Tools: tools, 70 Constraints: cons, 71 } 72 } 73 74 func (s *environBrokerSuite) TestStartInstance(c *gc.C) { 75 s.PrepareStartInstanceFakes(c) 76 startInstArgs := s.CreateStartInstanceArgs(c) 77 _, err := s.Env.StartInstance(startInstArgs) 78 79 c.Assert(err, jc.ErrorIsNil) 80 } 81 82 func (s *environBrokerSuite) TestStartInstanceWithNetworks(c *gc.C) { 83 s.PrepareStartInstanceFakes(c) 84 startInstArgs := s.CreateStartInstanceArgs(c) 85 startInstArgs.InstanceConfig.Networks = []string{"someNetwork"} 86 _, err := s.Env.StartInstance(startInstArgs) 87 88 c.Assert(err, gc.ErrorMatches, "starting instances with networks is not supported yet") 89 } 90 91 func (s *environBrokerSuite) TestStartInstanceWithUnsupportedConstraints(c *gc.C) { 92 s.PrepareStartInstanceFakes(c) 93 startInstArgs := s.CreateStartInstanceArgs(c) 94 startInstArgs.Tools[0].Version.Arch = "someArch" 95 _, err := s.Env.StartInstance(startInstArgs) 96 97 c.Assert(err, gc.ErrorMatches, "no matching images found for given constraints: .*") 98 } 99 100 // if tools for multiple architectures are avaliable, provider should filter tools by arch of the selected image 101 func (s *environBrokerSuite) TestStartInstanceFilterToolByArch(c *gc.C) { 102 s.PrepareStartInstanceFakes(c) 103 startInstArgs := s.CreateStartInstanceArgs(c) 104 tools := []*tools.Tools{{ 105 Version: version.Binary{Arch: arch.I386, Series: "trusty"}, 106 URL: "https://example.org", 107 }, { 108 Version: version.Binary{Arch: arch.AMD64, Series: "trusty"}, 109 URL: "https://example.org", 110 }} 111 //setting tools to I386, but provider should update them to AMD64, because our fake simplestream server return only AMD 64 image 112 startInstArgs.Tools = tools 113 startInstArgs.InstanceConfig.Tools = tools[0] 114 res, err := s.Env.StartInstance(startInstArgs) 115 116 c.Assert(err, jc.ErrorIsNil) 117 c.Assert(*res.Hardware.Arch, gc.Equals, arch.AMD64) 118 c.Assert(startInstArgs.InstanceConfig.Tools.Version.Arch, gc.Equals, arch.AMD64) 119 } 120 121 func (s *environBrokerSuite) TestStartInstanceDefaultConstraintsApplied(c *gc.C) { 122 s.PrepareStartInstanceFakes(c) 123 startInstArgs := s.CreateStartInstanceArgs(c) 124 res, err := s.Env.StartInstance(startInstArgs) 125 126 c.Assert(err, jc.ErrorIsNil) 127 c.Assert(*res.Hardware.CpuCores, gc.Equals, vsphere.DefaultCpuCores) 128 c.Assert(*res.Hardware.CpuPower, gc.Equals, vsphere.DefaultCpuPower) 129 c.Assert(*res.Hardware.Mem, gc.Equals, vsphere.DefaultMemMb) 130 c.Assert(*res.Hardware.RootDisk, gc.Equals, common.MinRootDiskSizeGiB*1024) 131 } 132 133 func (s *environBrokerSuite) TestStartInstanceCustomConstraintsApplied(c *gc.C) { 134 s.PrepareStartInstanceFakes(c) 135 startInstArgs := s.CreateStartInstanceArgs(c) 136 cpuCores := uint64(4) 137 startInstArgs.Constraints.CpuCores = &cpuCores 138 cpuPower := uint64(2001) 139 startInstArgs.Constraints.CpuPower = &cpuPower 140 mem := uint64(2002) 141 startInstArgs.Constraints.Mem = &mem 142 rootDisk := uint64(10003) 143 startInstArgs.Constraints.RootDisk = &rootDisk 144 res, err := s.Env.StartInstance(startInstArgs) 145 146 c.Assert(err, jc.ErrorIsNil) 147 c.Assert(*res.Hardware.CpuCores, gc.Equals, cpuCores) 148 c.Assert(*res.Hardware.CpuPower, gc.Equals, cpuPower) 149 c.Assert(*res.Hardware.Mem, gc.Equals, mem) 150 c.Assert(*res.Hardware.RootDisk, gc.Equals, rootDisk) 151 152 } 153 154 func (s *environBrokerSuite) TestStartInstanceCallsFinishMachineConfig(c *gc.C) { 155 s.PrepareStartInstanceFakes(c) 156 startInstArgs := s.CreateStartInstanceArgs(c) 157 s.PatchValue(&vsphere.FinishInstanceConfig, func(mcfg *instancecfg.InstanceConfig, cfg *config.Config) (err error) { 158 return errors.New("FinishMachineConfig called") 159 }) 160 _, err := s.Env.StartInstance(startInstArgs) 161 c.Assert(err, gc.ErrorMatches, "FinishMachineConfig called") 162 } 163 164 func (s *environBrokerSuite) TestStartInstanceDefaultDiskSizeIsUsedForSmallConstraintValue(c *gc.C) { 165 s.PrepareStartInstanceFakes(c) 166 startInstArgs := s.CreateStartInstanceArgs(c) 167 rootDisk := uint64(1000) 168 startInstArgs.Constraints.RootDisk = &rootDisk 169 res, err := s.Env.StartInstance(startInstArgs) 170 c.Assert(err, jc.ErrorIsNil) 171 c.Assert(*res.Hardware.RootDisk, gc.Equals, common.MinRootDiskSizeGiB*1024) 172 } 173 174 func (s *environBrokerSuite) TestStartInstanceInvalidPlacement(c *gc.C) { 175 s.PrepareStartInstanceFakes(c) 176 startInstArgs := s.CreateStartInstanceArgs(c) 177 startInstArgs.Placement = "someInvalidPlacement" 178 _, err := s.Env.StartInstance(startInstArgs) 179 c.Assert(err, gc.ErrorMatches, "unknown placement directive: .*") 180 } 181 182 func (s *environBrokerSuite) TestStartInstanceSelectZone(c *gc.C) { 183 client := vsphere.ExposeEnvFakeClient(s.Env) 184 s.FakeAvailabilityZones(client, "z1", "z2") 185 s.FakeAvailabilityZones(client, "z1", "z2") 186 s.FakeCreateInstance(client, s.ServerUrl, c) 187 startInstArgs := s.CreateStartInstanceArgs(c) 188 startInstArgs.Placement = "zone=z2" 189 _, err := s.Env.StartInstance(startInstArgs) 190 c.Assert(err, jc.ErrorIsNil) 191 } 192 193 func (s *environBrokerSuite) TestStartInstanceCallsAvailabilityZoneAllocations(c *gc.C) { 194 s.PrepareStartInstanceFakes(c) 195 startInstArgs := s.CreateStartInstanceArgs(c) 196 startInstArgs.DistributionGroup = func() ([]instance.Id, error) { 197 return []instance.Id{instance.Id("someId")}, nil 198 } 199 s.PatchValue(&vsphere.AvailabilityZoneAllocations, func(env common.ZonedEnviron, group []instance.Id) ([]common.AvailabilityZoneInstances, error) { 200 c.Assert(len(group), gc.Equals, 1) 201 c.Assert(string(group[0]), gc.Equals, "someId") 202 return nil, errors.New("AvailabilityZoneAllocations called") 203 }) 204 _, err := s.Env.StartInstance(startInstArgs) 205 c.Assert(err, gc.ErrorMatches, "AvailabilityZoneAllocations called") 206 } 207 208 func (s *environBrokerSuite) TestStartInstanceTriesToCreateInstanceInAllAvailabilityZones(c *gc.C) { 209 client := vsphere.ExposeEnvFakeClient(s.Env) 210 client.SetPropertyProxyHandler("FakeDatacenter", vsphere.RetrieveDatacenterProperties) 211 s.FakeInstances(client) 212 s.FakeAvailabilityZones(client, "z1", "z2") 213 s.FakeAvailabilityZones(client, "z1", "z2") 214 s.FakeAvailabilityZones(client, "z1", "z2") 215 client.SetPropertyProxyHandler("FakeDatacenter", vsphere.RetrieveDatacenterProperties) 216 client.SetProxyHandler("CreateImportSpec", func(req, res soap.HasFault) { 217 resBody := res.(*methods.CreateImportSpecBody) 218 resBody.Res = &types.CreateImportSpecResponse{ 219 Returnval: types.OvfCreateImportSpecResult{ 220 Error: []types.LocalizedMethodFault{{ 221 LocalizedMessage: "Error zone 1", 222 }}, 223 }, 224 } 225 }) 226 s.FakeAvailabilityZones(client, "z1", "z2") 227 client.SetPropertyProxyHandler("FakeDatacenter", vsphere.RetrieveDatacenterProperties) 228 client.SetProxyHandler("CreateImportSpec", func(req, res soap.HasFault) { 229 resBody := res.(*methods.CreateImportSpecBody) 230 resBody.Res = &types.CreateImportSpecResponse{ 231 Returnval: types.OvfCreateImportSpecResult{ 232 Error: []types.LocalizedMethodFault{{ 233 LocalizedMessage: "Error zone 2", 234 }}, 235 }, 236 } 237 }) 238 startInstArgs := s.CreateStartInstanceArgs(c) 239 _, err := s.Env.StartInstance(startInstArgs) 240 c.Assert(err, gc.ErrorMatches, "Can't create instance in any of availability zones, last error: Failed to import OVA file: Error zone 2") 241 }