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  }