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  }