github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/provider/maas/volumes_test.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package maas
     5  
     6  import (
     7  	"github.com/juju/gomaasapi"
     8  	jc "github.com/juju/testing/checkers"
     9  	gc "gopkg.in/check.v1"
    10  	"gopkg.in/juju/names.v2"
    11  
    12  	"github.com/juju/juju/constraints"
    13  	"github.com/juju/juju/instance"
    14  	"github.com/juju/juju/storage"
    15  	"github.com/juju/juju/testing"
    16  )
    17  
    18  type volumeSuite struct {
    19  	providerSuite
    20  }
    21  
    22  var _ = gc.Suite(&volumeSuite{})
    23  
    24  func (s *volumeSuite) TestBuildMAASVolumeParametersNoVolumes(c *gc.C) {
    25  	vInfo, err := buildMAASVolumeParameters(nil, constraints.Value{})
    26  	c.Assert(err, jc.ErrorIsNil)
    27  	c.Assert(vInfo, gc.HasLen, 0)
    28  }
    29  
    30  func (s *volumeSuite) TestBuildMAASVolumeParametersJustRootDisk(c *gc.C) {
    31  	var cons constraints.Value
    32  	rootSize := uint64(20000)
    33  	cons.RootDisk = &rootSize
    34  	vInfo, err := buildMAASVolumeParameters(nil, cons)
    35  	c.Assert(err, jc.ErrorIsNil)
    36  	c.Assert(vInfo, jc.DeepEquals, []volumeInfo{
    37  		{"root", 20, nil},
    38  	})
    39  }
    40  
    41  func (s *volumeSuite) TestBuildMAASVolumeParametersNoTags(c *gc.C) {
    42  	vInfo, err := buildMAASVolumeParameters([]storage.VolumeParams{
    43  		{Tag: names.NewVolumeTag("1"), Size: 2000000},
    44  	}, constraints.Value{})
    45  	c.Assert(err, jc.ErrorIsNil)
    46  	c.Assert(vInfo, jc.DeepEquals, []volumeInfo{
    47  		{"root", 0, nil}, //root disk
    48  		{"1", 1954, nil},
    49  	})
    50  }
    51  
    52  func (s *volumeSuite) TestBuildMAASVolumeParametersWithRootDisk(c *gc.C) {
    53  	var cons constraints.Value
    54  	rootSize := uint64(20000)
    55  	cons.RootDisk = &rootSize
    56  	vInfo, err := buildMAASVolumeParameters([]storage.VolumeParams{
    57  		{Tag: names.NewVolumeTag("1"), Size: 2000000},
    58  	}, cons)
    59  	c.Assert(err, jc.ErrorIsNil)
    60  	c.Assert(vInfo, jc.DeepEquals, []volumeInfo{
    61  		{"root", 20, nil}, //root disk
    62  		{"1", 1954, nil},
    63  	})
    64  }
    65  
    66  func (s *volumeSuite) TestBuildMAASVolumeParametersWithTags(c *gc.C) {
    67  	vInfo, err := buildMAASVolumeParameters([]storage.VolumeParams{
    68  		{Tag: names.NewVolumeTag("1"), Size: 2000000, Attributes: map[string]interface{}{"tags": "tag1,tag2"}},
    69  	}, constraints.Value{})
    70  	c.Assert(err, jc.ErrorIsNil)
    71  	c.Assert(vInfo, jc.DeepEquals, []volumeInfo{
    72  		{"root", 0, nil}, //root disk
    73  		{"1", 1954, []string{"tag1", "tag2"}},
    74  	})
    75  }
    76  
    77  func (s *volumeSuite) TestInstanceVolumesMAAS2(c *gc.C) {
    78  	instance := maas2Instance{
    79  		machine: &fakeMachine{},
    80  		constraintMatches: gomaasapi.ConstraintMatches{
    81  			Storage: map[string][]gomaasapi.BlockDevice{
    82  				"root": {&fakeBlockDevice{name: "sda", path: "/dev/disk/by-dname/sda", size: 250059350016}},
    83  				"1":    {&fakeBlockDevice{name: "sdb", path: "/dev/disk/by-dname/sdb", size: 500059350016}},
    84  				"2": {
    85  					&fakeBlockDevice{name: "sdc", path: "/dev/disk/by-dname/sdc", size: 250362438230},
    86  					&fakeBlockDevice{name: "sdf", path: "/dev/disk/by-dname/sdf", size: 280362438231},
    87  				},
    88  				"3": {&fakeBlockDevice{name: "sdd", path: "/dev/disk/by-dname/sdd", size: 250362438230}},
    89  				"4": {&fakeBlockDevice{name: "sde", path: "/dev/disk/by-dname/sde", size: 250362438230}},
    90  			},
    91  		},
    92  	}
    93  	mTag := names.NewMachineTag("1")
    94  	volumes, attachments, err := instance.volumes(mTag, []names.VolumeTag{
    95  		names.NewVolumeTag("1"),
    96  		names.NewVolumeTag("2"),
    97  	})
    98  	c.Assert(err, jc.ErrorIsNil)
    99  	// Expect 3 volumes - root volume is ignored.
   100  	c.Assert(volumes, gc.HasLen, 3)
   101  	c.Assert(attachments, gc.HasLen, 3)
   102  	c.Check(volumes, jc.SameContents, []storage.Volume{{
   103  		names.NewVolumeTag("1"),
   104  		storage.VolumeInfo{
   105  			VolumeId:   "volume-1",
   106  			Size:       476893,
   107  			Persistent: false,
   108  		},
   109  	}, {
   110  		names.NewVolumeTag("2"),
   111  		storage.VolumeInfo{
   112  			VolumeId:   "volume-2",
   113  			Size:       238764,
   114  			Persistent: false,
   115  		},
   116  	}, {
   117  		names.NewVolumeTag("2"),
   118  		storage.VolumeInfo{
   119  			VolumeId:   "volume-2",
   120  			Size:       267374,
   121  			Persistent: false,
   122  		},
   123  	}})
   124  	c.Assert(attachments, jc.SameContents, []storage.VolumeAttachment{{
   125  		names.NewVolumeTag("1"),
   126  		mTag,
   127  		storage.VolumeAttachmentInfo{
   128  			DeviceLink: "/dev/disk/by-dname/sdb",
   129  			ReadOnly:   false,
   130  		},
   131  	}, {
   132  		names.NewVolumeTag("2"),
   133  		mTag,
   134  		storage.VolumeAttachmentInfo{
   135  			DeviceLink: "/dev/disk/by-dname/sdc",
   136  			ReadOnly:   false,
   137  		},
   138  	}, {
   139  		names.NewVolumeTag("2"),
   140  		mTag,
   141  		storage.VolumeAttachmentInfo{
   142  			DeviceLink: "/dev/disk/by-dname/sdf",
   143  			ReadOnly:   false,
   144  		},
   145  	}})
   146  }
   147  
   148  func (s *volumeSuite) TestInstanceVolumes(c *gc.C) {
   149  	obj := s.testMAASObject.TestServer.NewNode(validVolumeJson)
   150  	statusGetter := func(instance.Id) (string, string) {
   151  		return "unknown", "FAKE"
   152  	}
   153  
   154  	instance := maas1Instance{&obj, nil, statusGetter}
   155  	mTag := names.NewMachineTag("1")
   156  	volumes, attachments, err := instance.volumes(mTag, []names.VolumeTag{
   157  		names.NewVolumeTag("1"),
   158  		names.NewVolumeTag("2"),
   159  	})
   160  	c.Assert(err, jc.ErrorIsNil)
   161  	// Expect 2 volumes - root volume is ignored.
   162  	c.Assert(volumes, gc.HasLen, 2)
   163  	c.Assert(attachments, gc.HasLen, 2)
   164  	c.Check(volumes, jc.DeepEquals, []storage.Volume{
   165  		{
   166  			// This volume has no id_path.
   167  			names.NewVolumeTag("1"),
   168  			storage.VolumeInfo{
   169  				HardwareId: "",
   170  				VolumeId:   "volume-1",
   171  				Size:       476893,
   172  				Persistent: false,
   173  			},
   174  		},
   175  		{
   176  			names.NewVolumeTag("2"),
   177  			storage.VolumeInfo{
   178  				HardwareId: "id_for_sdc",
   179  				VolumeId:   "volume-2",
   180  				Size:       238764,
   181  				Persistent: false,
   182  			},
   183  		},
   184  	})
   185  	c.Assert(attachments, jc.DeepEquals, []storage.VolumeAttachment{
   186  		{
   187  			names.NewVolumeTag("1"),
   188  			mTag,
   189  			storage.VolumeAttachmentInfo{
   190  				DeviceName: "sdb",
   191  				ReadOnly:   false,
   192  			},
   193  		},
   194  		// Device name not set because there's a hardware id in the volume.
   195  		{
   196  			names.NewVolumeTag("2"),
   197  			mTag,
   198  			storage.VolumeAttachmentInfo{
   199  				DeviceName: "",
   200  				ReadOnly:   false,
   201  			},
   202  		},
   203  	})
   204  }
   205  
   206  func (s *volumeSuite) TestInstanceVolumesOldMass(c *gc.C) {
   207  	obj := s.testMAASObject.TestServer.NewNode(`{"system_id": "node0"}`)
   208  	statusGetter := func(instance.Id) (string, string) {
   209  		// status, substatus or status info.
   210  		return "provisioning", "substatus"
   211  	}
   212  
   213  	instance := maas1Instance{&obj, nil, statusGetter}
   214  	volumes, attachments, err := instance.volumes(names.NewMachineTag("1"), []names.VolumeTag{
   215  		names.NewVolumeTag("1"),
   216  		names.NewVolumeTag("2"),
   217  	})
   218  	c.Assert(err, jc.ErrorIsNil)
   219  	c.Assert(volumes, gc.HasLen, 0)
   220  	c.Assert(attachments, gc.HasLen, 0)
   221  }
   222  
   223  var validVolumeJson = `
   224  {
   225      "system_id": "node0",
   226      "physicalblockdevice_set": [
   227          {
   228              "name": "sda",
   229              "tags": [
   230                  "ssd",
   231                  "sata"
   232              ],
   233              "id": 1,
   234              "id_path": "/dev/disk/by-id/id_for_sda",
   235              "path": "/dev/sda",
   236              "model": "Samsung_SSD_850_EVO_250GB",
   237              "block_size": 4096,
   238              "serial": "S21NNSAFC38075L",
   239              "size": 250059350016
   240          },
   241          {
   242              "name": "sdb",
   243              "tags": [
   244                  "ssd",
   245                  "sata"
   246              ],
   247              "id": 2,
   248              "path": "/dev/sdb",
   249              "model": "Samsung_SSD_850_EVO_500GB",
   250              "block_size": 4096,
   251              "serial": "S21NNSAFC38076L",
   252              "size": 500059350016
   253          },
   254          {
   255              "name": "sdb",
   256              "tags": [
   257                  "ssd",
   258                  "sata"
   259              ],
   260              "id": 3,
   261              "id_path": "/dev/disk/by-id/id_for_sdc",
   262              "path": "/dev/sdc",
   263              "model": "Samsung_SSD_850_EVO_250GB",
   264              "block_size": 4096,
   265              "serial": "S21NNSAFC38999L",
   266              "size": 250362438230
   267          },
   268          {
   269              "name": "sdd",
   270              "tags": [
   271                  "ssd",
   272                  "sata"
   273              ],
   274              "id": 4,
   275              "id_path": "/dev/disk/by-id/id_for_sdd",
   276              "path": "/dev/sdd",
   277              "model": "Samsung_SSD_850_EVO_250GB",
   278              "block_size": 4096,
   279              "serial": "S21NNSAFC386666L",
   280              "size": 250362438230
   281          },
   282          {
   283              "name": "sde",
   284              "tags": [
   285                  "ssd",
   286                  "sata"
   287              ],
   288              "id": 666,
   289              "id_path": "/dev/disk/by-id/id_for_sde",
   290              "path": "/dev/sde",
   291              "model": "Samsung_SSD_850_EVO_250GB",
   292              "block_size": 4096,
   293              "serial": "S21NNSAFC388888L",
   294              "size": 250362438230
   295          }
   296      ],
   297      "constraint_map": {
   298          "1": "root",
   299          "2": "1",
   300          "3": "2",
   301          "4": "3"
   302      }
   303  }
   304  `[1:]
   305  
   306  type storageProviderSuite struct {
   307  	testing.BaseSuite
   308  }
   309  
   310  var _ = gc.Suite(&storageProviderSuite{})
   311  
   312  func (*storageProviderSuite) TestValidateConfigTags(c *gc.C) {
   313  	p := maasStorageProvider{}
   314  	validate := func(tags interface{}) {
   315  		cfg, err := storage.NewConfig("foo", maasStorageProviderType, map[string]interface{}{
   316  			"tags": tags,
   317  		})
   318  		c.Assert(err, jc.ErrorIsNil)
   319  		err = p.ValidateConfig(cfg)
   320  		c.Assert(err, jc.ErrorIsNil)
   321  	}
   322  	validate("singular")
   323  	validate("mul,ti,ple")
   324  	validate(" leading, spaces")
   325  	validate("trailing ,spaces ")
   326  	validate(" and,everything, in ,  between ")
   327  }
   328  
   329  func (*storageProviderSuite) TestValidateConfigInvalidConfig(c *gc.C) {
   330  	p := maasStorageProvider{}
   331  	cfg, err := storage.NewConfig("foo", maasStorageProviderType, map[string]interface{}{
   332  		"tags": "white space",
   333  	})
   334  	c.Assert(err, jc.ErrorIsNil)
   335  	err = p.ValidateConfig(cfg)
   336  	c.Assert(err, gc.ErrorMatches, `tags may not contain whitespace: "white space"`)
   337  }
   338  
   339  func (*storageProviderSuite) TestValidateConfigUnknownAttribute(c *gc.C) {
   340  	p := maasStorageProvider{}
   341  	cfg, err := storage.NewConfig("foo", maasStorageProviderType, map[string]interface{}{
   342  		"unknown": "config",
   343  	})
   344  	c.Assert(err, jc.ErrorIsNil)
   345  	err = p.ValidateConfig(cfg)
   346  	c.Assert(err, jc.ErrorIsNil) // unknown attributes are ignored
   347  }
   348  
   349  func (s *storageProviderSuite) TestSupports(c *gc.C) {
   350  	p := maasStorageProvider{}
   351  	c.Assert(p.Supports(storage.StorageKindBlock), jc.IsTrue)
   352  	c.Assert(p.Supports(storage.StorageKindFilesystem), jc.IsFalse)
   353  }
   354  
   355  func (s *storageProviderSuite) TestScope(c *gc.C) {
   356  	p := maasStorageProvider{}
   357  	c.Assert(p.Scope(), gc.Equals, storage.ScopeEnviron)
   358  }