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

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package provider_test
     5  
     6  import (
     7  	"errors"
     8  	"runtime"
     9  
    10  	"github.com/juju/names"
    11  	jc "github.com/juju/testing/checkers"
    12  	gc "gopkg.in/check.v1"
    13  
    14  	"github.com/juju/juju/storage"
    15  	"github.com/juju/juju/storage/provider"
    16  	"github.com/juju/juju/testing"
    17  )
    18  
    19  var _ = gc.Suite(&tmpfsSuite{})
    20  
    21  type tmpfsSuite struct {
    22  	testing.BaseSuite
    23  	storageDir string
    24  	commands   *mockRunCommand
    25  }
    26  
    27  func (s *tmpfsSuite) SetUpTest(c *gc.C) {
    28  	if runtime.GOOS == "windows" {
    29  		c.Skip("Tests relevant only on *nix systems")
    30  	}
    31  	s.BaseSuite.SetUpTest(c)
    32  	s.storageDir = c.MkDir()
    33  }
    34  
    35  func (s *tmpfsSuite) TearDownTest(c *gc.C) {
    36  	if s.commands != nil {
    37  		s.commands.assertDrained()
    38  	}
    39  	s.BaseSuite.TearDownTest(c)
    40  }
    41  
    42  func (s *tmpfsSuite) tmpfsProvider(c *gc.C) storage.Provider {
    43  	s.commands = &mockRunCommand{c: c}
    44  	return provider.TmpfsProvider(s.commands.run)
    45  }
    46  
    47  func (s *tmpfsSuite) TestFilesystemSource(c *gc.C) {
    48  	p := s.tmpfsProvider(c)
    49  	cfg, err := storage.NewConfig("name", provider.TmpfsProviderType, map[string]interface{}{})
    50  	c.Assert(err, jc.ErrorIsNil)
    51  	_, err = p.FilesystemSource(nil, cfg)
    52  	c.Assert(err, gc.ErrorMatches, "storage directory not specified")
    53  	cfg, err = storage.NewConfig("name", provider.TmpfsProviderType, map[string]interface{}{
    54  		"storage-dir": c.MkDir(),
    55  	})
    56  	c.Assert(err, jc.ErrorIsNil)
    57  	_, err = p.FilesystemSource(nil, cfg)
    58  	c.Assert(err, jc.ErrorIsNil)
    59  }
    60  
    61  func (s *tmpfsSuite) TestValidateConfig(c *gc.C) {
    62  	p := s.tmpfsProvider(c)
    63  	cfg, err := storage.NewConfig("name", provider.TmpfsProviderType, map[string]interface{}{})
    64  	c.Assert(err, jc.ErrorIsNil)
    65  	err = p.ValidateConfig(cfg)
    66  	// The tmpfs provider does not have any user
    67  	// configuration, so an empty map will pass.
    68  	c.Assert(err, jc.ErrorIsNil)
    69  }
    70  
    71  func (s *tmpfsSuite) TestSupports(c *gc.C) {
    72  	p := s.tmpfsProvider(c)
    73  	c.Assert(p.Supports(storage.StorageKindBlock), jc.IsFalse)
    74  	c.Assert(p.Supports(storage.StorageKindFilesystem), jc.IsTrue)
    75  }
    76  
    77  func (s *tmpfsSuite) TestScope(c *gc.C) {
    78  	p := s.tmpfsProvider(c)
    79  	c.Assert(p.Scope(), gc.Equals, storage.ScopeMachine)
    80  }
    81  
    82  func (s *tmpfsSuite) tmpfsFilesystemSource(c *gc.C) storage.FilesystemSource {
    83  	s.commands = &mockRunCommand{c: c}
    84  	return provider.TmpfsFilesystemSource(
    85  		s.storageDir,
    86  		s.commands.run,
    87  	)
    88  }
    89  
    90  func (s *tmpfsSuite) TestCreateFilesystems(c *gc.C) {
    91  	source := s.tmpfsFilesystemSource(c)
    92  
    93  	results, err := source.CreateFilesystems([]storage.FilesystemParams{{
    94  		Tag:  names.NewFilesystemTag("6"),
    95  		Size: 2,
    96  	}})
    97  	c.Assert(err, jc.ErrorIsNil)
    98  	c.Assert(results, jc.DeepEquals, []storage.CreateFilesystemsResult{{
    99  		Filesystem: &storage.Filesystem{
   100  			Tag: names.NewFilesystemTag("6"),
   101  			FilesystemInfo: storage.FilesystemInfo{
   102  				FilesystemId: "filesystem-6",
   103  				Size:         2,
   104  			},
   105  		},
   106  	}})
   107  }
   108  
   109  func (s *tmpfsSuite) TestCreateFilesystemsHugePages(c *gc.C) {
   110  	source := s.tmpfsFilesystemSource(c)
   111  
   112  	// Set page size to 16MiB.
   113  	s.PatchValue(provider.Getpagesize, func() int { return 16 * 1024 * 1024 })
   114  
   115  	results, err := source.CreateFilesystems([]storage.FilesystemParams{{
   116  		Tag:  names.NewFilesystemTag("1"),
   117  		Size: 17,
   118  	}, {
   119  		Tag:  names.NewFilesystemTag("2"),
   120  		Size: 16,
   121  	}})
   122  	c.Assert(err, jc.ErrorIsNil)
   123  	c.Assert(results, jc.DeepEquals, []storage.CreateFilesystemsResult{{
   124  		Filesystem: &storage.Filesystem{
   125  			Tag: names.NewFilesystemTag("1"),
   126  			FilesystemInfo: storage.FilesystemInfo{
   127  				FilesystemId: "filesystem-1",
   128  				Size:         32,
   129  			},
   130  		},
   131  	}, {
   132  		Filesystem: &storage.Filesystem{
   133  			Tag: names.NewFilesystemTag("2"),
   134  			FilesystemInfo: storage.FilesystemInfo{
   135  				FilesystemId: "filesystem-2",
   136  				Size:         16,
   137  			},
   138  		},
   139  	}})
   140  }
   141  
   142  func (s *tmpfsSuite) TestCreateFilesystemsIsUse(c *gc.C) {
   143  	source := s.tmpfsFilesystemSource(c)
   144  	results, err := source.CreateFilesystems([]storage.FilesystemParams{{
   145  		Tag:  names.NewFilesystemTag("1"),
   146  		Size: 1,
   147  	}, {
   148  		Tag:  names.NewFilesystemTag("1"),
   149  		Size: 2,
   150  	}})
   151  	c.Assert(err, jc.ErrorIsNil)
   152  	c.Assert(results, gc.HasLen, 2)
   153  	c.Assert(results[0].Error, jc.ErrorIsNil)
   154  	c.Assert(results[1].Error, gc.ErrorMatches, "filesystem 1 already exists")
   155  }
   156  
   157  func (s *tmpfsSuite) TestAttachFilesystemsPathNotDir(c *gc.C) {
   158  	source := s.tmpfsFilesystemSource(c)
   159  	_, err := source.CreateFilesystems([]storage.FilesystemParams{{
   160  		Tag:  names.NewFilesystemTag("1"),
   161  		Size: 1,
   162  	}})
   163  	c.Assert(err, jc.ErrorIsNil)
   164  	results, err := source.AttachFilesystems([]storage.FilesystemAttachmentParams{{
   165  		Filesystem: names.NewFilesystemTag("1"),
   166  		Path:       "file",
   167  	}})
   168  	c.Assert(err, jc.ErrorIsNil)
   169  	c.Assert(results[0].Error, gc.ErrorMatches, `path "file" must be a directory`)
   170  }
   171  
   172  func (s *tmpfsSuite) TestAttachFilesystemsAlreadyMounted(c *gc.C) {
   173  	source := s.tmpfsFilesystemSource(c)
   174  	cmd := s.commands.expect("df", "--output=source", "exists")
   175  	cmd.respond("header\nfilesystem-123", nil)
   176  	_, err := source.CreateFilesystems([]storage.FilesystemParams{{
   177  		Tag:  names.NewFilesystemTag("123"),
   178  		Size: 1,
   179  	}})
   180  	c.Assert(err, jc.ErrorIsNil)
   181  	results, err := source.AttachFilesystems([]storage.FilesystemAttachmentParams{{
   182  		Filesystem: names.NewFilesystemTag("123"),
   183  		Path:       "exists",
   184  	}})
   185  	c.Assert(results, jc.DeepEquals, []storage.AttachFilesystemsResult{{
   186  		FilesystemAttachment: &storage.FilesystemAttachment{
   187  			Filesystem: names.NewFilesystemTag("123"),
   188  			FilesystemAttachmentInfo: storage.FilesystemAttachmentInfo{
   189  				Path: "exists",
   190  			},
   191  		},
   192  	}})
   193  }
   194  
   195  func (s *tmpfsSuite) TestAttachFilesystemsMountReadOnly(c *gc.C) {
   196  	source := s.tmpfsFilesystemSource(c)
   197  	_, err := source.CreateFilesystems([]storage.FilesystemParams{{
   198  		Tag:  names.NewFilesystemTag("1"),
   199  		Size: 1024,
   200  	}})
   201  	c.Assert(err, jc.ErrorIsNil)
   202  
   203  	cmd := s.commands.expect("df", "--output=source", "/var/lib/juju/storage/fs/foo")
   204  	cmd.respond("header\nvalue", nil)
   205  	s.commands.expect("mount", "-t", "tmpfs", "filesystem-1", "/var/lib/juju/storage/fs/foo", "-o", "size=1024m,ro")
   206  
   207  	results, err := source.AttachFilesystems([]storage.FilesystemAttachmentParams{{
   208  		Filesystem: names.NewFilesystemTag("1"),
   209  		Path:       "/var/lib/juju/storage/fs/foo",
   210  		AttachmentParams: storage.AttachmentParams{
   211  			Machine:  names.NewMachineTag("2"),
   212  			ReadOnly: true,
   213  		},
   214  	}})
   215  	c.Assert(err, jc.ErrorIsNil)
   216  	c.Assert(results, jc.DeepEquals, []storage.AttachFilesystemsResult{{
   217  		FilesystemAttachment: &storage.FilesystemAttachment{
   218  			Filesystem: names.NewFilesystemTag("1"),
   219  			Machine:    names.NewMachineTag("2"),
   220  			FilesystemAttachmentInfo: storage.FilesystemAttachmentInfo{
   221  				Path:     "/var/lib/juju/storage/fs/foo",
   222  				ReadOnly: true,
   223  			},
   224  		},
   225  	}})
   226  }
   227  
   228  func (s *tmpfsSuite) TestAttachFilesystemsMountFails(c *gc.C) {
   229  	source := s.tmpfsFilesystemSource(c)
   230  	_, err := source.CreateFilesystems([]storage.FilesystemParams{{
   231  		Tag:  names.NewFilesystemTag("1"),
   232  		Size: 1024,
   233  	}})
   234  	c.Assert(err, jc.ErrorIsNil)
   235  
   236  	cmd := s.commands.expect("df", "--output=source", "/var/lib/juju/storage/fs/foo")
   237  	cmd.respond("header\nvalue", nil)
   238  	cmd = s.commands.expect("mount", "-t", "tmpfs", "filesystem-1", "/var/lib/juju/storage/fs/foo", "-o", "size=1024m")
   239  	cmd.respond("", errors.New("mount failed"))
   240  
   241  	results, err := source.AttachFilesystems([]storage.FilesystemAttachmentParams{{
   242  		Filesystem: names.NewFilesystemTag("1"),
   243  		Path:       "/var/lib/juju/storage/fs/foo",
   244  	}})
   245  	c.Assert(err, jc.ErrorIsNil)
   246  	c.Assert(results[0].Error, gc.ErrorMatches, "cannot mount tmpfs: mount failed")
   247  }
   248  
   249  func (s *tmpfsSuite) TestAttachFilesystemsNoPathSpecified(c *gc.C) {
   250  	source := s.tmpfsFilesystemSource(c)
   251  	_, err := source.CreateFilesystems([]storage.FilesystemParams{{
   252  		Tag:  names.NewFilesystemTag("1"),
   253  		Size: 1024,
   254  	}})
   255  	c.Assert(err, jc.ErrorIsNil)
   256  	results, err := source.AttachFilesystems([]storage.FilesystemAttachmentParams{{
   257  		Filesystem: names.NewFilesystemTag("6"),
   258  	}})
   259  	c.Assert(err, jc.ErrorIsNil)
   260  	c.Assert(results[0].Error, gc.ErrorMatches, "filesystem mount point not specified")
   261  }
   262  
   263  func (s *tmpfsSuite) TestAttachFilesystemsNoFilesystem(c *gc.C) {
   264  	source := s.tmpfsFilesystemSource(c)
   265  	results, err := source.AttachFilesystems([]storage.FilesystemAttachmentParams{{
   266  		Filesystem: names.NewFilesystemTag("6"),
   267  		Path:       "/mnt",
   268  	}})
   269  	c.Assert(err, jc.ErrorIsNil)
   270  	c.Assert(results[0].Error, gc.ErrorMatches, "reading filesystem info from disk: open .*/6.info: no such file or directory")
   271  }
   272  
   273  func (s *tmpfsSuite) TestDetachFilesystems(c *gc.C) {
   274  	source := s.tmpfsFilesystemSource(c)
   275  	testDetachFilesystems(c, s.commands, source, true)
   276  }
   277  
   278  func (s *tmpfsSuite) TestDetachFilesystemsUnattached(c *gc.C) {
   279  	source := s.tmpfsFilesystemSource(c)
   280  	testDetachFilesystems(c, s.commands, source, false)
   281  }