github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/worker/diskmanager/lsblk_test.go (about) 1 // Copyright 2014 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 // +build linux 5 6 package diskmanager_test 7 8 import ( 9 "errors" 10 "os" 11 "strings" 12 13 "github.com/juju/testing" 14 jc "github.com/juju/testing/checkers" 15 gc "gopkg.in/check.v1" 16 17 "github.com/juju/juju/storage" 18 coretesting "github.com/juju/juju/testing" 19 "github.com/juju/juju/worker/diskmanager" 20 ) 21 22 var _ = gc.Suite(&ListBlockDevicesSuite{}) 23 24 type ListBlockDevicesSuite struct { 25 coretesting.BaseSuite 26 } 27 28 func (s *ListBlockDevicesSuite) SetUpTest(c *gc.C) { 29 s.BaseSuite.SetUpTest(c) 30 s.PatchValue(diskmanager.BlockDeviceInUse, func(storage.BlockDevice) (bool, error) { 31 return false, nil 32 }) 33 testing.PatchExecutable(c, s, "udevadm", `#!/bin/bash --norc`) 34 } 35 36 func (s *ListBlockDevicesSuite) TestListBlockDevices(c *gc.C) { 37 s.PatchValue(diskmanager.BlockDeviceInUse, func(dev storage.BlockDevice) (bool, error) { 38 return dev.DeviceName == "sdb", nil 39 }) 40 testing.PatchExecutable(c, s, "lsblk", `#!/bin/bash --norc 41 cat <<EOF 42 KNAME="sda" SIZE="240057409536" LABEL="" UUID="" TYPE="disk" 43 KNAME="sda1" SIZE="254803968" LABEL="" UUID="7a62bd85-a350-4c09-8944-5b99bf2080c6" MOUNTPOINT="/tmp" TYPE="part" 44 KNAME="sda2" SIZE="1024" LABEL="boot" UUID="" TYPE="part" 45 KNAME="sdb" SIZE="32017047552" LABEL="" UUID="" TYPE="disk" 46 KNAME="sdb1" SIZE="32015122432" LABEL="media" UUID="2c1c701d-f2ce-43a4-b345-33e2e39f9503" FSTYPE="ext4" TYPE="part" 47 KNAME="fd0" SIZE="1024" TYPE="disk" MAJ:MIN="2:0" 48 KNAME="fd1" SIZE="1024" TYPE="disk" MAJ:MIN="2:1" 49 EOF`) 50 51 devices, err := diskmanager.ListBlockDevices() 52 c.Assert(err, jc.ErrorIsNil) 53 c.Assert(devices, jc.DeepEquals, []storage.BlockDevice{{ 54 DeviceName: "sda", 55 Size: 228936, 56 }, { 57 DeviceName: "sda1", 58 Size: 243, 59 UUID: "7a62bd85-a350-4c09-8944-5b99bf2080c6", 60 MountPoint: "/tmp", 61 }, { 62 DeviceName: "sda2", 63 Size: 0, // truncated 64 Label: "boot", 65 }, { 66 DeviceName: "sdb", 67 Size: 30533, 68 InUse: true, 69 }, { 70 DeviceName: "sdb1", 71 Size: 30532, 72 Label: "media", 73 UUID: "2c1c701d-f2ce-43a4-b345-33e2e39f9503", 74 FilesystemType: "ext4", 75 }}) 76 } 77 78 func (s *ListBlockDevicesSuite) TestListBlockDevicesWWN(c *gc.C) { 79 // If ID_WWN is found, then we should get 80 // a WWN value. 81 s.testListBlockDevicesExtended(c, ` 82 ID_WWN=foo 83 `, storage.BlockDevice{WWN: "foo"}) 84 } 85 86 func (s *ListBlockDevicesSuite) TestListBlockDevicesExtendedWWN(c *gc.C) { 87 // If ID_WWN_WITH_EXTENSION is found, then we should use that 88 // in preference to the ID_WWN value. 89 s.testListBlockDevicesExtended(c, ` 90 ID_WWN_WITH_EXTENSION=foobar 91 ID_WWN=foo 92 `, storage.BlockDevice{WWN: "foobar"}) 93 } 94 95 func (s *ListBlockDevicesSuite) TestListBlockDevicesBusAddress(c *gc.C) { 96 // If ID_BUS is scsi, then we should get a 97 // BusAddress value. 98 s.testListBlockDevicesExtended(c, ` 99 DEVPATH=/a/b/c/d/1:2:3:4/block/sda 100 ID_BUS=scsi 101 `, storage.BlockDevice{BusAddress: "scsi@1:2.3.4"}) 102 } 103 104 func (s *ListBlockDevicesSuite) TestListBlockDevicesHardwareId(c *gc.C) { 105 // If ID_BUS and ID_SERIAL are both present, we 106 // should get a HardwareId value. 107 s.testListBlockDevicesExtended(c, ` 108 ID_BUS=ata 109 ID_SERIAL=0980978987987 110 `, storage.BlockDevice{HardwareId: "ata-0980978987987"}) 111 } 112 113 func (s *ListBlockDevicesSuite) TestListBlockDevicesDeviceLinks(c *gc.C) { 114 // Values from DEVLINKS should be split by space, and entered into 115 // DeviceLinks verbatim. 116 s.testListBlockDevicesExtended(c, ` 117 DEVLINKS=/dev/disk/by-id/abc /dev/disk/by-id/def 118 `, storage.BlockDevice{ 119 DeviceLinks: []string{"/dev/disk/by-id/abc", "/dev/disk/by-id/def"}, 120 }) 121 } 122 123 func (s *ListBlockDevicesSuite) TestListBlockDevicesAll(c *gc.C) { 124 s.testListBlockDevicesExtended(c, ` 125 DEVPATH=/a/b/c/d/1:2:3:4/block/sda 126 ID_BUS=scsi 127 ID_SERIAL=0980978987987 128 `, storage.BlockDevice{BusAddress: "scsi@1:2.3.4", HardwareId: "scsi-0980978987987"}) 129 } 130 131 func (s *ListBlockDevicesSuite) TestListBlockDevicesUnexpectedDevpathFormat(c *gc.C) { 132 // If DEVPATH's format doesn't match what we expect, then we should 133 // just not get the BusAddress value. 134 s.testListBlockDevicesExtended(c, ` 135 DEVPATH=/a/b/c/d/x:y:z:zy/block/sda 136 ID_BUS=ata 137 ID_SERIAL=0980978987987 138 `, storage.BlockDevice{HardwareId: "ata-0980978987987"}) 139 } 140 141 func (s *ListBlockDevicesSuite) TestListBlockDevicesUnexpectedPropertyFormat(c *gc.C) { 142 // If udevadm outputs in an unexpected format, we won't error; 143 // we only error if some catastrophic error occurs while reading 144 // from the udevadm command's stdout. 145 s.testListBlockDevicesExtended(c, "nonsense", storage.BlockDevice{}) 146 } 147 148 func (s *ListBlockDevicesSuite) testListBlockDevicesExtended( 149 c *gc.C, 150 udevadmInfo string, 151 expect storage.BlockDevice, 152 ) { 153 testing.PatchExecutable(c, s, "lsblk", `#!/bin/bash --norc 154 cat <<EOF 155 KNAME="sda" SIZE="240057409536" LABEL="" UUID="" TYPE="disk" 156 EOF`) 157 testing.PatchExecutable(c, s, "udevadm", `#!/bin/bash --norc 158 cat <<EOF 159 `+strings.TrimSpace(udevadmInfo)+` 160 EOF`) 161 162 expect.DeviceName = "sda" 163 expect.Size = 228936 164 165 devices, err := diskmanager.ListBlockDevices() 166 c.Assert(err, jc.ErrorIsNil) 167 c.Assert(devices, jc.DeepEquals, []storage.BlockDevice{expect}) 168 } 169 170 func (s *ListBlockDevicesSuite) TestListBlockDevicesLsblkError(c *gc.C) { 171 testing.PatchExecutableThrowError(c, s, "lsblk", 123) 172 devices, err := diskmanager.ListBlockDevices() 173 c.Assert(err, gc.ErrorMatches, "cannot list block devices: lsblk failed: exit status 123") 174 c.Assert(devices, gc.IsNil) 175 } 176 177 func (s *ListBlockDevicesSuite) TestListBlockDevicesBlockDeviceInUseError(c *gc.C) { 178 s.PatchValue(diskmanager.BlockDeviceInUse, func(dev storage.BlockDevice) (bool, error) { 179 return false, errors.New("badness") 180 }) 181 testing.PatchExecutable(c, s, "lsblk", `#!/bin/bash --norc 182 cat <<EOF 183 KNAME="sda" SIZE="240057409536" LABEL="" UUID="" TYPE="disk" 184 EOF`) 185 186 // If the in-use check errors, the block device will be marked "in use" 187 // to prevent it from being used, but no error will be returned. 188 devices, err := diskmanager.ListBlockDevices() 189 c.Assert(err, jc.ErrorIsNil) 190 c.Assert(devices, jc.DeepEquals, []storage.BlockDevice{{ 191 DeviceName: "sda", 192 Size: 228936, 193 InUse: true, 194 }}) 195 } 196 197 func (s *ListBlockDevicesSuite) TestListBlockDevicesLsblkBadOutput(c *gc.C) { 198 // Extra key/value pairs should be ignored; invalid sizes should 199 // be logged and ignored (Size will be set to zero). 200 testing.PatchExecutable(c, s, "lsblk", `#!/bin/bash --norc 201 cat <<EOF 202 KNAME="sda" SIZE="eleventy" LABEL="" UUID="" TYPE="disk" 203 KNAME="sdb" SIZE="1048576" LABEL="" UUID="" BOB="DOBBS" TYPE="disk" 204 EOF`) 205 206 devices, err := diskmanager.ListBlockDevices() 207 c.Assert(err, jc.ErrorIsNil) 208 c.Assert(devices, jc.DeepEquals, []storage.BlockDevice{{ 209 DeviceName: "sda", 210 Size: 0, 211 }, { 212 DeviceName: "sdb", 213 Size: 1, 214 }}) 215 } 216 217 func (s *ListBlockDevicesSuite) TestListBlockDevicesDeviceNotExist(c *gc.C) { 218 s.PatchValue(diskmanager.BlockDeviceInUse, func(dev storage.BlockDevice) (bool, error) { 219 return false, os.ErrNotExist 220 }) 221 testing.PatchExecutable(c, s, "lsblk", `#!/bin/bash --norc 222 cat <<EOF 223 KNAME="sda" SIZE="240057409536" LABEL="" UUID="" TYPE="disk" 224 KNAME="sdb" SIZE="32017047552" LABEL="" UUID="" TYPE="disk" 225 EOF`) 226 227 devices, err := diskmanager.ListBlockDevices() 228 c.Assert(err, jc.ErrorIsNil) 229 c.Assert(devices, gc.HasLen, 0) 230 } 231 232 func (s *ListBlockDevicesSuite) TestListBlockDevicesDeviceFiltering(c *gc.C) { 233 testing.PatchExecutable(c, s, "lsblk", `#!/bin/bash --norc 234 cat <<EOF 235 KNAME="sda" SIZE="240057409536" LABEL="" UUID="" TYPE="disk" 236 KNAME="sda1" SIZE="254803968" LABEL="" UUID="" TYPE="part" 237 KNAME="loop0" SIZE="254803968" LABEL="" UUID="" TYPE="loop" 238 KNAME="sr0" SIZE="254803968" LABEL="" UUID="" TYPE="rom" 239 KNAME="whatever" SIZE="254803968" LABEL="" UUID="" TYPE="lvm" 240 EOF`) 241 242 devices, err := diskmanager.ListBlockDevices() 243 c.Assert(err, gc.IsNil) 244 c.Assert(devices, jc.DeepEquals, []storage.BlockDevice{{ 245 DeviceName: "sda", 246 Size: 228936, 247 }, { 248 DeviceName: "sda1", 249 Size: 243, 250 }, { 251 DeviceName: "loop0", 252 Size: 243, 253 }}) 254 }