github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/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="disk" 44 KNAME="sda2" SIZE="1024" LABEL="boot" UUID="" TYPE="disk" 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="disk" 47 EOF`) 48 49 devices, err := diskmanager.ListBlockDevices() 50 c.Assert(err, jc.ErrorIsNil) 51 c.Assert(devices, jc.DeepEquals, []storage.BlockDevice{{ 52 DeviceName: "sda", 53 Size: 228936, 54 }, { 55 DeviceName: "sda1", 56 Size: 243, 57 UUID: "7a62bd85-a350-4c09-8944-5b99bf2080c6", 58 MountPoint: "/tmp", 59 }, { 60 DeviceName: "sda2", 61 Size: 0, // truncated 62 Label: "boot", 63 }, { 64 DeviceName: "sdb", 65 Size: 30533, 66 InUse: true, 67 }, { 68 DeviceName: "sdb1", 69 Size: 30532, 70 Label: "media", 71 UUID: "2c1c701d-f2ce-43a4-b345-33e2e39f9503", 72 FilesystemType: "ext4", 73 }}) 74 } 75 76 func (s *ListBlockDevicesSuite) TestListBlockDevicesBusAddress(c *gc.C) { 77 // If ID_BUS is scsi, then we should get a 78 // BusAddress value. 79 s.testListBlockDevicesExtended(c, ` 80 DEVPATH=/a/b/c/d/1:2:3:4/block/sda 81 ID_BUS=scsi 82 `, storage.BlockDevice{BusAddress: "scsi@1:2.3.4"}) 83 } 84 85 func (s *ListBlockDevicesSuite) TestListBlockDevicesHardwareId(c *gc.C) { 86 // If ID_BUS and ID_SERIAL are both present, we 87 // should get a HardwareId value. 88 s.testListBlockDevicesExtended(c, ` 89 ID_BUS=ata 90 ID_SERIAL=0980978987987 91 `, storage.BlockDevice{HardwareId: "ata-0980978987987"}) 92 } 93 94 func (s *ListBlockDevicesSuite) TestListBlockDevicesDeviceLinks(c *gc.C) { 95 // Values from DEVLINKS should be split by space, and entered into 96 // DeviceLinks verbatim. 97 s.testListBlockDevicesExtended(c, ` 98 DEVLINKS=/dev/disk/by-id/abc /dev/disk/by-id/def 99 `, storage.BlockDevice{ 100 DeviceLinks: []string{"/dev/disk/by-id/abc", "/dev/disk/by-id/def"}, 101 }) 102 } 103 104 func (s *ListBlockDevicesSuite) TestListBlockDevicesAll(c *gc.C) { 105 s.testListBlockDevicesExtended(c, ` 106 DEVPATH=/a/b/c/d/1:2:3:4/block/sda 107 ID_BUS=scsi 108 ID_SERIAL=0980978987987 109 `, storage.BlockDevice{BusAddress: "scsi@1:2.3.4", HardwareId: "scsi-0980978987987"}) 110 } 111 112 func (s *ListBlockDevicesSuite) TestListBlockDevicesUnexpectedDevpathFormat(c *gc.C) { 113 // If DEVPATH's format doesn't match what we expect, then we should 114 // just not get the BusAddress value. 115 s.testListBlockDevicesExtended(c, ` 116 DEVPATH=/a/b/c/d/x:y:z:zy/block/sda 117 ID_BUS=ata 118 ID_SERIAL=0980978987987 119 `, storage.BlockDevice{HardwareId: "ata-0980978987987"}) 120 } 121 122 func (s *ListBlockDevicesSuite) TestListBlockDevicesUnexpectedPropertyFormat(c *gc.C) { 123 // If udevadm outputs in an unexpected format, we won't error; 124 // we only error if some catastrophic error occurs while reading 125 // from the udevadm command's stdout. 126 s.testListBlockDevicesExtended(c, "nonsense", storage.BlockDevice{}) 127 } 128 129 func (s *ListBlockDevicesSuite) testListBlockDevicesExtended( 130 c *gc.C, 131 udevadmInfo string, 132 expect storage.BlockDevice, 133 ) { 134 testing.PatchExecutable(c, s, "lsblk", `#!/bin/bash --norc 135 cat <<EOF 136 KNAME="sda" SIZE="240057409536" LABEL="" UUID="" TYPE="disk" 137 EOF`) 138 testing.PatchExecutable(c, s, "udevadm", `#!/bin/bash --norc 139 cat <<EOF 140 `+strings.TrimSpace(udevadmInfo)+` 141 EOF`) 142 143 expect.DeviceName = "sda" 144 expect.Size = 228936 145 146 devices, err := diskmanager.ListBlockDevices() 147 c.Assert(err, jc.ErrorIsNil) 148 c.Assert(devices, jc.DeepEquals, []storage.BlockDevice{expect}) 149 } 150 151 func (s *ListBlockDevicesSuite) TestListBlockDevicesLsblkError(c *gc.C) { 152 testing.PatchExecutableThrowError(c, s, "lsblk", 123) 153 devices, err := diskmanager.ListBlockDevices() 154 c.Assert(err, gc.ErrorMatches, "cannot list block devices: lsblk failed: exit status 123") 155 c.Assert(devices, gc.IsNil) 156 } 157 158 func (s *ListBlockDevicesSuite) TestListBlockDevicesBlockDeviceInUseError(c *gc.C) { 159 s.PatchValue(diskmanager.BlockDeviceInUse, func(dev storage.BlockDevice) (bool, error) { 160 return false, errors.New("badness") 161 }) 162 testing.PatchExecutable(c, s, "lsblk", `#!/bin/bash --norc 163 cat <<EOF 164 KNAME="sda" SIZE="240057409536" LABEL="" UUID="" TYPE="disk" 165 EOF`) 166 167 // If the in-use check errors, the block device will be marked "in use" 168 // to prevent it from being used, but no error will be returned. 169 devices, err := diskmanager.ListBlockDevices() 170 c.Assert(err, jc.ErrorIsNil) 171 c.Assert(devices, jc.DeepEquals, []storage.BlockDevice{{ 172 DeviceName: "sda", 173 Size: 228936, 174 InUse: true, 175 }}) 176 } 177 178 func (s *ListBlockDevicesSuite) TestListBlockDevicesLsblkBadOutput(c *gc.C) { 179 // Extra key/value pairs should be ignored; invalid sizes should 180 // be logged and ignored (Size will be set to zero). 181 testing.PatchExecutable(c, s, "lsblk", `#!/bin/bash --norc 182 cat <<EOF 183 KNAME="sda" SIZE="eleventy" LABEL="" UUID="" TYPE="disk" 184 KNAME="sdb" SIZE="1048576" LABEL="" UUID="" BOB="DOBBS" TYPE="disk" 185 EOF`) 186 187 devices, err := diskmanager.ListBlockDevices() 188 c.Assert(err, jc.ErrorIsNil) 189 c.Assert(devices, jc.DeepEquals, []storage.BlockDevice{{ 190 DeviceName: "sda", 191 Size: 0, 192 }, { 193 DeviceName: "sdb", 194 Size: 1, 195 }}) 196 } 197 198 func (s *ListBlockDevicesSuite) TestListBlockDevicesDeviceNotExist(c *gc.C) { 199 s.PatchValue(diskmanager.BlockDeviceInUse, func(dev storage.BlockDevice) (bool, error) { 200 return false, os.ErrNotExist 201 }) 202 testing.PatchExecutable(c, s, "lsblk", `#!/bin/bash --norc 203 cat <<EOF 204 KNAME="sda" SIZE="240057409536" LABEL="" UUID="" TYPE="disk" 205 KNAME="sdb" SIZE="32017047552" LABEL="" UUID="" TYPE="disk" 206 EOF`) 207 208 devices, err := diskmanager.ListBlockDevices() 209 c.Assert(err, jc.ErrorIsNil) 210 c.Assert(devices, gc.HasLen, 0) 211 } 212 213 func (s *ListBlockDevicesSuite) TestListBlockDevicesDeviceFiltering(c *gc.C) { 214 testing.PatchExecutable(c, s, "lsblk", `#!/bin/bash --norc 215 cat <<EOF 216 KNAME="sda" SIZE="240057409536" LABEL="" UUID="" TYPE="disk" 217 KNAME="sda1" SIZE="254803968" LABEL="" UUID="" TYPE="part" 218 KNAME="loop0" SIZE="254803968" LABEL="" UUID="" TYPE="loop" 219 KNAME="sr0" SIZE="254803968" LABEL="" UUID="" TYPE="rom" 220 KNAME="whatever" SIZE="254803968" LABEL="" UUID="" TYPE="lvm" 221 EOF`) 222 223 devices, err := diskmanager.ListBlockDevices() 224 c.Assert(err, gc.IsNil) 225 c.Assert(devices, jc.DeepEquals, []storage.BlockDevice{{ 226 DeviceName: "sda", 227 Size: 228936, 228 }, { 229 DeviceName: "loop0", 230 Size: 243, 231 }}) 232 }