github.com/mwhudson/juju@v0.0.0-20160512215208-90ff01f3497f/provider/maas/maas_test.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package maas
     5  
     6  import (
     7  	"bytes"
     8  	"encoding/json"
     9  	"fmt"
    10  	"net"
    11  	"path/filepath"
    12  	"strconv"
    13  	"time"
    14  
    15  	"github.com/juju/gomaasapi"
    16  	jc "github.com/juju/testing/checkers"
    17  	"github.com/juju/utils"
    18  	"github.com/juju/utils/arch"
    19  	"github.com/juju/utils/series"
    20  	"github.com/juju/utils/set"
    21  	gc "gopkg.in/check.v1"
    22  
    23  	"github.com/juju/juju/environs/config"
    24  	sstesting "github.com/juju/juju/environs/simplestreams/testing"
    25  	envtesting "github.com/juju/juju/environs/testing"
    26  	envtools "github.com/juju/juju/environs/tools"
    27  	"github.com/juju/juju/feature"
    28  	"github.com/juju/juju/instance"
    29  	"github.com/juju/juju/juju"
    30  	"github.com/juju/juju/network"
    31  	coretesting "github.com/juju/juju/testing"
    32  	jujuversion "github.com/juju/juju/version"
    33  )
    34  
    35  const maas2VersionResponse = `{"version": "unknown", "subversion": "", "capabilities": ["networks-management", "static-ipaddresses", "ipv6-deployment-ubuntu", "devices-management", "storage-deployment-ubuntu", "network-deployment-ubuntu"]}`
    36  
    37  type baseProviderSuite struct {
    38  	coretesting.FakeJujuXDGDataHomeSuite
    39  	envtesting.ToolsFixture
    40  }
    41  
    42  func (suite *baseProviderSuite) setupFakeTools(c *gc.C) {
    43  	suite.PatchValue(&juju.JujuPublicKey, sstesting.SignedMetadataPublicKey)
    44  	storageDir := c.MkDir()
    45  	toolsDir := filepath.Join(storageDir, "tools")
    46  	suite.PatchValue(&envtools.DefaultBaseURL, utils.MakeFileURL(toolsDir))
    47  	suite.UploadFakeToolsToDirectory(c, storageDir, "released", "released")
    48  }
    49  
    50  func (s *baseProviderSuite) SetUpSuite(c *gc.C) {
    51  	s.FakeJujuXDGDataHomeSuite.SetUpSuite(c)
    52  	restoreTimeouts := envtesting.PatchAttemptStrategies(&shortAttempt)
    53  	restoreFinishBootstrap := envtesting.DisableFinishBootstrap()
    54  	s.AddCleanup(func(*gc.C) {
    55  		restoreFinishBootstrap()
    56  		restoreTimeouts()
    57  	})
    58  	s.PatchValue(&nodeDeploymentTimeout, func(*maasEnviron) time.Duration {
    59  		return coretesting.ShortWait
    60  	})
    61  }
    62  
    63  func (s *baseProviderSuite) SetUpTest(c *gc.C) {
    64  	s.FakeJujuXDGDataHomeSuite.SetUpTest(c)
    65  	s.ToolsFixture.SetUpTest(c)
    66  	s.PatchValue(&jujuversion.Current, coretesting.FakeVersionNumber)
    67  	s.PatchValue(&arch.HostArch, func() string { return arch.AMD64 })
    68  	s.PatchValue(&series.HostSeries, func() string { return series.LatestLts() })
    69  	s.SetFeatureFlags(feature.AddressAllocation)
    70  }
    71  
    72  func (s *baseProviderSuite) TearDownTest(c *gc.C) {
    73  	s.ToolsFixture.TearDownTest(c)
    74  	s.FakeJujuXDGDataHomeSuite.TearDownTest(c)
    75  }
    76  
    77  func (s *baseProviderSuite) TearDownSuite(c *gc.C) {
    78  	s.FakeJujuXDGDataHomeSuite.TearDownSuite(c)
    79  }
    80  
    81  type providerSuite struct {
    82  	baseProviderSuite
    83  	testMAASObject *gomaasapi.TestMAASObject
    84  }
    85  
    86  func spaceJSON(space gomaasapi.CreateSpace) *bytes.Buffer {
    87  	var out bytes.Buffer
    88  	err := json.NewEncoder(&out).Encode(space)
    89  	if err != nil {
    90  		panic(err)
    91  	}
    92  	return &out
    93  }
    94  
    95  const exampleAgentName = "dfb69555-0bc4-4d1f-85f2-4ee390974984"
    96  
    97  func (s *providerSuite) SetUpSuite(c *gc.C) {
    98  	s.baseProviderSuite.SetUpSuite(c)
    99  	s.testMAASObject = gomaasapi.NewTestMAAS("1.0")
   100  }
   101  
   102  func (s *providerSuite) SetUpTest(c *gc.C) {
   103  	s.baseProviderSuite.SetUpTest(c)
   104  	mockCapabilities := func(client *gomaasapi.MAASObject) (set.Strings, error) {
   105  		return set.NewStrings("network-deployment-ubuntu"), nil
   106  	}
   107  	mockGetController := func(maasServer, apiKey string) (gomaasapi.Controller, error) {
   108  		return nil, gomaasapi.NewUnsupportedVersionError("oops")
   109  	}
   110  	s.PatchValue(&GetCapabilities, mockCapabilities)
   111  	s.PatchValue(&GetMAAS2Controller, mockGetController)
   112  	// Creating a space ensures that the spaces endpoint won't 404.
   113  	s.testMAASObject.TestServer.NewSpace(spaceJSON(gomaasapi.CreateSpace{Name: "space-0"}))
   114  }
   115  
   116  func (s *providerSuite) TearDownTest(c *gc.C) {
   117  	s.baseProviderSuite.TearDownTest(c)
   118  	s.testMAASObject.TestServer.Clear()
   119  }
   120  
   121  func (s *providerSuite) TearDownSuite(c *gc.C) {
   122  	s.baseProviderSuite.TearDownSuite(c)
   123  	s.testMAASObject.Close()
   124  }
   125  
   126  var maasEnvAttrs = coretesting.Attrs{
   127  	"name":            "test env",
   128  	"type":            "maas",
   129  	"maas-oauth":      "a:b:c",
   130  	"maas-agent-name": exampleAgentName,
   131  }
   132  
   133  // makeEnviron creates a functional maasEnviron for a test.
   134  func (suite *providerSuite) makeEnviron() *maasEnviron {
   135  	testAttrs := coretesting.Attrs{}
   136  	for k, v := range maasEnvAttrs {
   137  		testAttrs[k] = v
   138  	}
   139  	testAttrs["maas-server"] = suite.testMAASObject.TestServer.URL
   140  	attrs := coretesting.FakeConfig().Merge(testAttrs)
   141  	cfg, err := config.New(config.NoDefaults, attrs)
   142  	if err != nil {
   143  		panic(err)
   144  	}
   145  	env, err := NewEnviron(cfg)
   146  	if err != nil {
   147  		panic(err)
   148  	}
   149  	return env
   150  }
   151  
   152  func (suite *providerSuite) addNode(jsonText string) instance.Id {
   153  	node := suite.testMAASObject.TestServer.NewNode(jsonText)
   154  	resourceURI, _ := node.GetField("resource_uri")
   155  	return instance.Id(resourceURI)
   156  }
   157  
   158  func (suite *providerSuite) getInstance(systemId string) *maas1Instance {
   159  	input := fmt.Sprintf(`{"system_id": %q}`, systemId)
   160  	node := suite.testMAASObject.TestServer.NewNode(input)
   161  	statusGetter := func(instance.Id) (string, string) {
   162  		return "unknown", "FAKE"
   163  	}
   164  	return &maas1Instance{&node, nil, statusGetter}
   165  }
   166  
   167  func (suite *providerSuite) getNetwork(name string, id int, vlanTag int) *gomaasapi.MAASObject {
   168  	var vlan string
   169  	if vlanTag == 0 {
   170  		vlan = "null"
   171  	} else {
   172  		vlan = fmt.Sprintf("%d", vlanTag)
   173  	}
   174  	var input string
   175  	input = fmt.Sprintf(`{"name": %q, "ip":"192.168.%d.1", "netmask": "255.255.255.0",`+
   176  		`"vlan_tag": %s, "description": "%s_%d_%d" }`, name, id, vlan, name, id, vlanTag)
   177  	network := suite.testMAASObject.TestServer.NewNetwork(input)
   178  	return &network
   179  }
   180  
   181  func createSubnetInfo(subnetID, spaceID, ipRange uint) network.SubnetInfo {
   182  	return network.SubnetInfo{
   183  		CIDR:              fmt.Sprintf("192.168.%d.0/24", ipRange),
   184  		ProviderId:        network.Id(strconv.Itoa(int(subnetID))),
   185  		AllocatableIPLow:  net.ParseIP(fmt.Sprintf("192.168.%d.139", ipRange)).To4(),
   186  		AllocatableIPHigh: net.ParseIP(fmt.Sprintf("192.168.%d.255", ipRange)).To4(),
   187  		SpaceProviderId:   network.Id(fmt.Sprintf("%d", spaceID)),
   188  	}
   189  }
   190  
   191  func createSubnet(ipRange, spaceAndNICID uint) gomaasapi.CreateSubnet {
   192  	space := fmt.Sprintf("space-%d", spaceAndNICID)
   193  	return createSubnetWithSpace(ipRange, spaceAndNICID, space)
   194  }
   195  
   196  func createSubnetWithSpace(ipRange, NICID uint, space string) gomaasapi.CreateSubnet {
   197  	var s gomaasapi.CreateSubnet
   198  	s.DNSServers = []string{"192.168.1.2"}
   199  	s.Name = fmt.Sprintf("maas-eth%d", NICID)
   200  	s.Space = space
   201  	s.GatewayIP = fmt.Sprintf("192.168.%v.1", ipRange)
   202  	s.CIDR = fmt.Sprintf("192.168.%v.0/24", ipRange)
   203  	return s
   204  }
   205  
   206  func (suite *providerSuite) addSubnet(c *gc.C, ipRange, spaceAndNICID uint, systemID string) uint {
   207  	space := fmt.Sprintf("space-%d", spaceAndNICID)
   208  	return suite.addSubnetWithSpace(c, ipRange, spaceAndNICID, space, systemID)
   209  }
   210  
   211  func (suite *providerSuite) addSubnetWithSpace(c *gc.C, ipRange, NICID uint, space string, systemID string) uint {
   212  	out := bytes.Buffer{}
   213  	err := json.NewEncoder(&out).Encode(createSubnetWithSpace(ipRange, NICID, space))
   214  	c.Assert(err, jc.ErrorIsNil)
   215  	subnet := suite.testMAASObject.TestServer.NewSubnet(&out)
   216  	c.Assert(err, jc.ErrorIsNil)
   217  
   218  	other := gomaasapi.AddressRange{}
   219  	other.Start = fmt.Sprintf("192.168.%d.139", ipRange)
   220  	other.End = fmt.Sprintf("192.168.%d.149", ipRange)
   221  	other.Purpose = []string{"not-the-dynamic-range"}
   222  	suite.testMAASObject.TestServer.AddFixedAddressRange(subnet.ID, other)
   223  
   224  	ar := gomaasapi.AddressRange{}
   225  	ar.Start = fmt.Sprintf("192.168.%d.10", ipRange)
   226  	ar.End = fmt.Sprintf("192.168.%d.138", ipRange)
   227  	ar.Purpose = []string{"something", "dynamic-range"}
   228  	suite.testMAASObject.TestServer.AddFixedAddressRange(subnet.ID, ar)
   229  	if systemID != "" {
   230  		var nni gomaasapi.NodeNetworkInterface
   231  		nni.Name = subnet.Name
   232  		nni.Links = append(nni.Links, gomaasapi.NetworkLink{
   233  			ID:     uint(1),
   234  			Mode:   "auto",
   235  			Subnet: subnet,
   236  		})
   237  		suite.testMAASObject.TestServer.SetNodeNetworkLink(systemID, nni)
   238  	}
   239  	return subnet.ID
   240  }