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