github.com/mhilton/juju-juju@v0.0.0-20150901100907-a94dd2c73455/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.SameContents, []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) TestListBlockDevicesAll(c *gc.C) { 95 s.testListBlockDevicesExtended(c, ` 96 DEVPATH=/a/b/c/d/1:2:3:4/block/sda 97 ID_BUS=scsi 98 ID_SERIAL=0980978987987 99 `, storage.BlockDevice{BusAddress: "scsi@1:2.3.4", HardwareId: "scsi-0980978987987"}) 100 } 101 102 func (s *ListBlockDevicesSuite) TestListBlockDevicesUnexpectedDevpathFormat(c *gc.C) { 103 // If DEVPATH's format doesn't match what we expect, then we should 104 // just not get the BusAddress value. 105 s.testListBlockDevicesExtended(c, ` 106 DEVPATH=/a/b/c/d/x:y:z:zy/block/sda 107 ID_BUS=ata 108 ID_SERIAL=0980978987987 109 `, storage.BlockDevice{HardwareId: "ata-0980978987987"}) 110 } 111 112 func (s *ListBlockDevicesSuite) TestListBlockDevicesUnexpectedPropertyFormat(c *gc.C) { 113 // If udevadm outputs in an unexpected format, we won't error; 114 // we only error if some catastrophic error occurs while reading 115 // from the udevadm command's stdout. 116 s.testListBlockDevicesExtended(c, "nonsense", storage.BlockDevice{}) 117 } 118 119 func (s *ListBlockDevicesSuite) testListBlockDevicesExtended( 120 c *gc.C, 121 udevadmInfo string, 122 expect storage.BlockDevice, 123 ) { 124 testing.PatchExecutable(c, s, "lsblk", `#!/bin/bash --norc 125 cat <<EOF 126 KNAME="sda" SIZE="240057409536" LABEL="" UUID="" TYPE="disk" 127 EOF`) 128 testing.PatchExecutable(c, s, "udevadm", `#!/bin/bash --norc 129 cat <<EOF 130 `+strings.TrimSpace(udevadmInfo)+` 131 EOF`) 132 133 expect.DeviceName = "sda" 134 expect.Size = 228936 135 136 devices, err := diskmanager.ListBlockDevices() 137 c.Assert(err, jc.ErrorIsNil) 138 c.Assert(devices, jc.DeepEquals, []storage.BlockDevice{expect}) 139 } 140 141 func (s *ListBlockDevicesSuite) TestListBlockDevicesLsblkError(c *gc.C) { 142 testing.PatchExecutableThrowError(c, s, "lsblk", 123) 143 devices, err := diskmanager.ListBlockDevices() 144 c.Assert(err, gc.ErrorMatches, "cannot list block devices: lsblk failed: exit status 123") 145 c.Assert(devices, gc.IsNil) 146 } 147 148 func (s *ListBlockDevicesSuite) TestListBlockDevicesBlockDeviceInUseError(c *gc.C) { 149 s.PatchValue(diskmanager.BlockDeviceInUse, func(dev storage.BlockDevice) (bool, error) { 150 return false, errors.New("badness") 151 }) 152 testing.PatchExecutable(c, s, "lsblk", `#!/bin/bash --norc 153 cat <<EOF 154 KNAME="sda" SIZE="240057409536" LABEL="" UUID="" TYPE="disk" 155 EOF`) 156 157 // If the in-use check errors, the block device will be marked "in use" 158 // to prevent it from being used, but no error will be returned. 159 devices, err := diskmanager.ListBlockDevices() 160 c.Assert(err, jc.ErrorIsNil) 161 c.Assert(devices, jc.SameContents, []storage.BlockDevice{{ 162 DeviceName: "sda", 163 Size: 228936, 164 InUse: true, 165 }}) 166 } 167 168 func (s *ListBlockDevicesSuite) TestListBlockDevicesLsblkBadOutput(c *gc.C) { 169 // Extra key/value pairs should be ignored; invalid sizes should 170 // be logged and ignored (Size will be set to zero). 171 testing.PatchExecutable(c, s, "lsblk", `#!/bin/bash --norc 172 cat <<EOF 173 KNAME="sda" SIZE="eleventy" LABEL="" UUID="" TYPE="disk" 174 KNAME="sdb" SIZE="1048576" LABEL="" UUID="" BOB="DOBBS" TYPE="disk" 175 EOF`) 176 177 devices, err := diskmanager.ListBlockDevices() 178 c.Assert(err, jc.ErrorIsNil) 179 c.Assert(devices, jc.SameContents, []storage.BlockDevice{{ 180 DeviceName: "sda", 181 Size: 0, 182 }, { 183 DeviceName: "sdb", 184 Size: 1, 185 }}) 186 } 187 188 func (s *ListBlockDevicesSuite) TestListBlockDevicesDeviceNotExist(c *gc.C) { 189 s.PatchValue(diskmanager.BlockDeviceInUse, func(dev storage.BlockDevice) (bool, error) { 190 return false, os.ErrNotExist 191 }) 192 testing.PatchExecutable(c, s, "lsblk", `#!/bin/bash --norc 193 cat <<EOF 194 KNAME="sda" SIZE="240057409536" LABEL="" UUID="" TYPE="disk" 195 KNAME="sdb" SIZE="32017047552" LABEL="" UUID="" TYPE="disk" 196 EOF`) 197 198 devices, err := diskmanager.ListBlockDevices() 199 c.Assert(err, jc.ErrorIsNil) 200 c.Assert(devices, gc.HasLen, 0) 201 } 202 203 func (s *ListBlockDevicesSuite) TestListBlockDevicesDeviceFiltering(c *gc.C) { 204 testing.PatchExecutable(c, s, "lsblk", `#!/bin/bash --norc 205 cat <<EOF 206 KNAME="sda" SIZE="240057409536" LABEL="" UUID="" TYPE="disk" 207 KNAME="sda1" SIZE="254803968" LABEL="" UUID="" TYPE="part" 208 KNAME="loop0" SIZE="254803968" LABEL="" UUID="" TYPE="loop" 209 KNAME="sr0" SIZE="254803968" LABEL="" UUID="" TYPE="rom" 210 KNAME="whatever" SIZE="254803968" LABEL="" UUID="" TYPE="lvm" 211 EOF`) 212 213 devices, err := diskmanager.ListBlockDevices() 214 c.Assert(err, gc.IsNil) 215 c.Assert(devices, jc.SameContents, []storage.BlockDevice{{ 216 DeviceName: "sda", 217 Size: 228936, 218 }, { 219 DeviceName: "loop0", 220 Size: 243, 221 }}) 222 }