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