github.com/altoros/juju-vmware@v0.0.0-20150312064031-f19ae857ccca/worker/diskformatter/diskformatter_test.go (about) 1 // Copyright 2014 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package diskformatter_test 5 6 import ( 7 "errors" 8 "time" 9 10 "github.com/juju/names" 11 gc "gopkg.in/check.v1" 12 13 "github.com/juju/juju/api/watcher" 14 "github.com/juju/juju/apiserver/params" 15 "github.com/juju/juju/storage" 16 coretesting "github.com/juju/juju/testing" 17 "github.com/juju/juju/worker/diskformatter" 18 "github.com/juju/testing" 19 ) 20 21 var _ = gc.Suite(&DiskFormatterWorkerSuite{}) 22 23 type DiskFormatterWorkerSuite struct { 24 coretesting.BaseSuite 25 } 26 27 func (s *DiskFormatterWorkerSuite) TestWorker(c *gc.C) { 28 ids := []string{ 29 "0", "1", "2", "3", "4", "5", 30 } 31 32 blockDeviceResults := []params.BlockDeviceResult{{ 33 Result: storage.BlockDevice{ 34 Name: "0", 35 DeviceName: "sda", 36 Label: "dev0-label", 37 UUID: "9aade75c-6528-4acf-ab69-258b8dc51798", 38 }, 39 }, { 40 Result: storage.BlockDevice{ 41 Name: "1", 42 DeviceName: "sdb", 43 UUID: "edc2348a-a2bc-4b15-b7f3-cb951b3489ad", 44 FilesystemType: "btrfs", 45 }, 46 }, { 47 Result: storage.BlockDevice{ 48 Name: "2", 49 DeviceName: "sdc", 50 }, 51 }, { 52 Result: storage.BlockDevice{ 53 Name: "3", 54 DeviceName: "sdd", 55 }, 56 }, { 57 Result: storage.BlockDevice{ 58 Name: "4", 59 DeviceName: "sde", 60 }, 61 }, { 62 Error: ¶ms.Error{ 63 Code: params.CodeNotFound, 64 Message: "block device 5 not found", 65 }, 66 }} 67 68 blockDeviceStorageInstanceResults := []params.StorageInstanceResult{{ 69 Result: storage.StorageInstance{ 70 Id: "needs-a-filesystem", 71 Kind: storage.StorageKindFilesystem, 72 }, 73 }, { 74 Result: storage.StorageInstance{ 75 Id: "already-has-a-filesystem", 76 Kind: storage.StorageKindFilesystem, 77 }, 78 }, { 79 Result: storage.StorageInstance{ 80 Id: "doesnt-need-a-filesystem", 81 Kind: storage.StorageKindBlock, 82 }, 83 }, { 84 Error: ¶ms.Error{ 85 Code: params.CodeNotAssigned, 86 Message: "3 is not assigned to a storage instance", 87 }, 88 }} 89 90 accessor := &mockBlockDeviceAccessor{ 91 changes: make(chan []string), 92 blockDevices: func(tags []names.DiskTag) (params.BlockDeviceResults, error) { 93 expect := make([]names.DiskTag, len(ids)) 94 for i, id := range ids { 95 expect[i] = names.NewDiskTag(id) 96 } 97 c.Assert(tags, gc.DeepEquals, expect) 98 return params.BlockDeviceResults{blockDeviceResults}, nil 99 }, 100 blockDeviceStorageInstances: func(tags []names.DiskTag) (params.StorageInstanceResults, error) { 101 expect := make([]names.DiskTag, 0, len(blockDeviceResults)) 102 for i, result := range blockDeviceResults { 103 if result.Error != nil { 104 continue 105 } 106 expect = append(expect, names.NewDiskTag(ids[i])) 107 } 108 c.Assert(tags, gc.DeepEquals, expect) 109 return params.StorageInstanceResults{blockDeviceStorageInstanceResults}, nil 110 }, 111 } 112 113 testing.PatchExecutableAsEchoArgs(c, s, "mkfs.ext4") 114 115 w := diskformatter.NewWorker(accessor) 116 accessor.changes <- ids 117 done := make(chan struct{}) 118 go func() { 119 w.Kill() 120 w.Wait() 121 close(done) 122 }() 123 124 select { 125 case <-done: 126 testing.AssertEchoArgs(c, "mkfs.ext4", "/dev/disk/by-label/dev0-label") 127 case <-time.After(coretesting.LongWait): 128 c.Fatalf("timed out waiting for diskformatter to update") 129 } 130 } 131 132 func (s *DiskFormatterWorkerSuite) TestMakeDefaultFilesystem(c *gc.C) { 133 accessor := &mockBlockDeviceAccessor{ 134 blockDevices: func([]names.DiskTag) (params.BlockDeviceResults, error) { 135 return params.BlockDeviceResults{[]params.BlockDeviceResult{{ 136 Result: storage.BlockDevice{ 137 Name: "0", 138 DeviceName: "sda", 139 Label: "dev0-label", 140 UUID: "9aade75c-6528-4acf-ab69-258b8dc51798", 141 }, 142 }}}, nil 143 }, 144 blockDeviceStorageInstances: func(tags []names.DiskTag) (params.StorageInstanceResults, error) { 145 return params.StorageInstanceResults{[]params.StorageInstanceResult{{ 146 Result: storage.StorageInstance{ 147 Id: "needs-a-filesystem", 148 Kind: storage.StorageKindFilesystem, 149 }, 150 }}}, nil 151 }, 152 } 153 154 testing.PatchExecutableAsEchoArgs(c, s, "mkfs.ext4") 155 formatter := diskformatter.NewDiskFormatter(accessor) 156 err := formatter.Handle([]string{"0"}) 157 c.Assert(err, gc.IsNil) 158 testing.AssertEchoArgs(c, "mkfs.ext4", "/dev/disk/by-label/dev0-label") 159 } 160 161 func (s *DiskFormatterWorkerSuite) TestBlockDeviceError(c *gc.C) { 162 accessor := &mockBlockDeviceAccessor{ 163 blockDevices: func(tags []names.DiskTag) (params.BlockDeviceResults, error) { 164 return params.BlockDeviceResults{}, errors.New("BlockDevice failed") 165 }, 166 } 167 formatter := diskformatter.NewDiskFormatter(accessor) 168 err := formatter.Handle([]string{"0"}) 169 c.Assert(err, gc.ErrorMatches, "cannot get block devices: BlockDevice failed") 170 } 171 172 func (s *DiskFormatterWorkerSuite) TestBlockDeviceStorageInstanceError(c *gc.C) { 173 accessor := &mockBlockDeviceAccessor{ 174 blockDevices: func([]names.DiskTag) (params.BlockDeviceResults, error) { 175 return params.BlockDeviceResults{[]params.BlockDeviceResult{{ 176 Result: storage.BlockDevice{Name: "0", DeviceName: "sda"}, 177 }}}, nil 178 }, 179 blockDeviceStorageInstances: func(tags []names.DiskTag) (params.StorageInstanceResults, error) { 180 return params.StorageInstanceResults{}, errors.New("BlockDeviceStorageInstance failed") 181 }, 182 } 183 formatter := diskformatter.NewDiskFormatter(accessor) 184 err := formatter.Handle([]string{"0"}) 185 c.Assert(err, gc.ErrorMatches, "cannot get assigned storage instances: BlockDeviceStorageInstance failed") 186 } 187 188 func (s *DiskFormatterWorkerSuite) TestCannotMakeFilesystem(c *gc.C) { 189 accessor := &mockBlockDeviceAccessor{ 190 blockDevices: func(tags []names.DiskTag) (params.BlockDeviceResults, error) { 191 return params.BlockDeviceResults{[]params.BlockDeviceResult{{ 192 Result: storage.BlockDevice{Name: "0", DeviceName: "sda"}, 193 }}}, nil 194 }, 195 blockDeviceStorageInstances: func(tags []names.DiskTag) (params.StorageInstanceResults, error) { 196 return params.StorageInstanceResults{[]params.StorageInstanceResult{{ 197 Result: storage.StorageInstance{ 198 Id: "needs-a-filesystem", 199 Kind: storage.StorageKindFilesystem, 200 }, 201 }}}, nil 202 }, 203 } 204 // Failure to create a filesystem should not cause the handler to error. 205 testing.PatchExecutableThrowError(c, s, "mkfs.ext4", 1) 206 formatter := diskformatter.NewDiskFormatter(accessor) 207 err := formatter.Handle([]string{"0"}) 208 c.Assert(err, gc.IsNil) 209 } 210 211 type mockBlockDeviceAccessor struct { 212 changes chan []string 213 blockDevices func([]names.DiskTag) (params.BlockDeviceResults, error) 214 blockDeviceStorageInstances func([]names.DiskTag) (params.StorageInstanceResults, error) 215 } 216 217 func (m *mockBlockDeviceAccessor) Changes() <-chan []string { 218 return m.changes 219 } 220 221 func (m *mockBlockDeviceAccessor) Stop() error { 222 return nil 223 } 224 225 func (m *mockBlockDeviceAccessor) Err() error { 226 return nil 227 } 228 229 func (m *mockBlockDeviceAccessor) WatchBlockDevices() (watcher.StringsWatcher, error) { 230 return m, nil 231 } 232 233 func (m *mockBlockDeviceAccessor) BlockDevices(tags []names.DiskTag) (params.BlockDeviceResults, error) { 234 return m.blockDevices(tags) 235 } 236 237 func (m *mockBlockDeviceAccessor) BlockDeviceStorageInstances(tags []names.DiskTag) (params.StorageInstanceResults, error) { 238 return m.blockDeviceStorageInstances(tags) 239 }