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