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 }