github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/state/blockdevices_test.go (about)

     1  // Copyright 2014 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package state_test
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	"github.com/juju/names/v5"
     9  	jc "github.com/juju/testing/checkers"
    10  	gc "gopkg.in/check.v1"
    11  
    12  	"github.com/juju/juju/state"
    13  	"github.com/juju/juju/state/testing"
    14  )
    15  
    16  type BlockDevicesSuite struct {
    17  	ConnSuite
    18  	machine *state.Machine
    19  }
    20  
    21  var _ = gc.Suite(&BlockDevicesSuite{})
    22  
    23  func (s *BlockDevicesSuite) SetUpTest(c *gc.C) {
    24  	s.ConnSuite.SetUpTest(c)
    25  	var err error
    26  	s.machine, err = s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
    27  	c.Assert(err, jc.ErrorIsNil)
    28  }
    29  
    30  func (s *BlockDevicesSuite) assertBlockDevices(c *gc.C, tag names.MachineTag, expected []state.BlockDeviceInfo) {
    31  	sb, err := state.NewStorageBackend(s.State)
    32  	c.Assert(err, jc.ErrorIsNil)
    33  	info, err := sb.BlockDevices(tag)
    34  	c.Assert(err, jc.ErrorIsNil)
    35  	c.Assert(info, gc.DeepEquals, expected)
    36  }
    37  
    38  func (s *BlockDevicesSuite) TestSetMachineBlockDevices(c *gc.C) {
    39  	sda := state.BlockDeviceInfo{DeviceName: "sda"}
    40  	err := s.machine.SetMachineBlockDevices(sda)
    41  	c.Assert(err, jc.ErrorIsNil)
    42  	s.assertBlockDevices(c, s.machine.MachineTag(), []state.BlockDeviceInfo{sda})
    43  }
    44  
    45  func (s *BlockDevicesSuite) TestSetMachineBlockDevicesReplaces(c *gc.C) {
    46  	sda := state.BlockDeviceInfo{DeviceName: "sda"}
    47  	err := s.machine.SetMachineBlockDevices(sda)
    48  	c.Assert(err, jc.ErrorIsNil)
    49  
    50  	sdb := state.BlockDeviceInfo{DeviceName: "sdb"}
    51  	err = s.machine.SetMachineBlockDevices(sdb)
    52  	c.Assert(err, jc.ErrorIsNil)
    53  	s.assertBlockDevices(c, s.machine.MachineTag(), []state.BlockDeviceInfo{sdb})
    54  }
    55  
    56  func (s *BlockDevicesSuite) TestSetMachineBlockDevicesUpdates(c *gc.C) {
    57  	sda := state.BlockDeviceInfo{DeviceName: "sda"}
    58  	sdb := state.BlockDeviceInfo{DeviceName: "sdb"}
    59  	err := s.machine.SetMachineBlockDevices(sda, sdb)
    60  	c.Assert(err, jc.ErrorIsNil)
    61  	s.assertBlockDevices(c, s.machine.MachineTag(), []state.BlockDeviceInfo{sda, sdb})
    62  
    63  	sdb.Label = "root"
    64  	err = s.machine.SetMachineBlockDevices(sdb)
    65  	c.Assert(err, jc.ErrorIsNil)
    66  	s.assertBlockDevices(c, s.machine.MachineTag(), []state.BlockDeviceInfo{sdb})
    67  
    68  	// If a device is attached, unattached, then attached again,
    69  	// then it gets a new name.
    70  	sdb.Label = "" // Label should be reset.
    71  	sdb.FilesystemType = "ext4"
    72  	err = s.machine.SetMachineBlockDevices(sda, sdb)
    73  	c.Assert(err, jc.ErrorIsNil)
    74  	s.assertBlockDevices(c, s.machine.MachineTag(), []state.BlockDeviceInfo{
    75  		sda,
    76  		sdb,
    77  	})
    78  }
    79  
    80  func (s *BlockDevicesSuite) TestSetMachineBlockDevicesMachineDying(c *gc.C) {
    81  	err := s.machine.Destroy()
    82  	c.Assert(err, jc.ErrorIsNil)
    83  
    84  	sda := state.BlockDeviceInfo{DeviceName: "sda"}
    85  	err = s.machine.SetMachineBlockDevices(sda)
    86  	c.Assert(err, jc.ErrorIsNil)
    87  	s.assertBlockDevices(c, s.machine.MachineTag(), []state.BlockDeviceInfo{sda})
    88  }
    89  
    90  func (s *BlockDevicesSuite) TestSetMachineBlockDevicesUnchanged(c *gc.C) {
    91  	sda := state.BlockDeviceInfo{DeviceName: "sda"}
    92  	err := s.machine.SetMachineBlockDevices(sda)
    93  	c.Assert(err, jc.ErrorIsNil)
    94  	s.assertBlockDevices(c, s.machine.MachineTag(), []state.BlockDeviceInfo{sda})
    95  
    96  	// Setting the same should not change txn-revno.
    97  	docID := state.DocID(s.State, s.machine.Id())
    98  	before, err := state.TxnRevno(s.State, state.BlockDevicesC, docID)
    99  	c.Assert(err, jc.ErrorIsNil)
   100  
   101  	err = s.machine.SetMachineBlockDevices(sda)
   102  	c.Assert(err, jc.ErrorIsNil)
   103  
   104  	after, err := state.TxnRevno(s.State, state.BlockDevicesC, docID)
   105  	c.Assert(err, jc.ErrorIsNil)
   106  	c.Assert(after, gc.Equals, before)
   107  }
   108  
   109  func (s *BlockDevicesSuite) TestSetMachineBlockDevicesConcurrently(c *gc.C) {
   110  	sdaInner := state.BlockDeviceInfo{DeviceName: "sda"}
   111  	defer state.SetBeforeHooks(c, s.State, func() {
   112  		err := s.machine.SetMachineBlockDevices(sdaInner)
   113  		c.Assert(err, jc.ErrorIsNil)
   114  	}).Check()
   115  
   116  	sdaOuter := state.BlockDeviceInfo{
   117  		DeviceName: "sda",
   118  		Label:      "root",
   119  	}
   120  	err := s.machine.SetMachineBlockDevices(sdaOuter)
   121  	c.Assert(err, jc.ErrorIsNil)
   122  
   123  	// the outer call should wipe out the inner one's update.
   124  	s.assertBlockDevices(c, s.machine.MachineTag(), []state.BlockDeviceInfo{
   125  		sdaOuter,
   126  	})
   127  }
   128  
   129  func (s *BlockDevicesSuite) TestSetMachineBlockDevicesEmpty(c *gc.C) {
   130  	sda := state.BlockDeviceInfo{DeviceName: "sda"}
   131  	err := s.machine.SetMachineBlockDevices(sda)
   132  	c.Assert(err, jc.ErrorIsNil)
   133  	s.assertBlockDevices(c, s.machine.MachineTag(), []state.BlockDeviceInfo{sda})
   134  
   135  	err = s.machine.SetMachineBlockDevices()
   136  	c.Assert(err, jc.ErrorIsNil)
   137  	s.assertBlockDevices(c, s.machine.MachineTag(), []state.BlockDeviceInfo{})
   138  }
   139  
   140  func (s *BlockDevicesSuite) TestBlockDevicesMachineRemove(c *gc.C) {
   141  	sda := state.BlockDeviceInfo{DeviceName: "sda"}
   142  	err := s.machine.SetMachineBlockDevices(sda)
   143  	c.Assert(err, jc.ErrorIsNil)
   144  
   145  	err = s.machine.EnsureDead()
   146  	c.Assert(err, jc.ErrorIsNil)
   147  	err = s.machine.Remove()
   148  	c.Assert(err, jc.ErrorIsNil)
   149  
   150  	sb, err := state.NewStorageBackend(s.State)
   151  	c.Assert(err, jc.ErrorIsNil)
   152  	_, err = sb.BlockDevices(s.machine.MachineTag())
   153  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   154  }
   155  
   156  func (s *BlockDevicesSuite) TestWatchBlockDevices(c *gc.C) {
   157  	sda := state.BlockDeviceInfo{DeviceName: "sda"}
   158  	sdb := state.BlockDeviceInfo{DeviceName: "sdb"}
   159  	sdc := state.BlockDeviceInfo{DeviceName: "sdc"}
   160  	err := s.machine.SetMachineBlockDevices(sda, sdb, sdc)
   161  	c.Assert(err, jc.ErrorIsNil)
   162  
   163  	// Start block device watcher.
   164  	sb, err := state.NewStorageBackend(s.State)
   165  	c.Assert(err, jc.ErrorIsNil)
   166  	w := sb.WatchBlockDevices(s.machine.MachineTag())
   167  	defer testing.AssertStop(c, w)
   168  	wc := testing.NewNotifyWatcherC(c, w)
   169  	wc.AssertOneChange()
   170  
   171  	// Setting the same should not trigger the watcher.
   172  	err = s.machine.SetMachineBlockDevices(sdc, sdb, sda)
   173  	c.Assert(err, jc.ErrorIsNil)
   174  	wc.AssertNoChange()
   175  
   176  	// change sdb's label.
   177  	sdb.Label = "fatty"
   178  	err = s.machine.SetMachineBlockDevices(sda, sdb, sdc)
   179  	c.Assert(err, jc.ErrorIsNil)
   180  	wc.AssertOneChange()
   181  
   182  	// change sda's label and sdb's UUID at once.
   183  	sda.Label = "giggly"
   184  	sdb.UUID = "4c062658-6225-4f4b-96f3-debf00b964b4"
   185  	err = s.machine.SetMachineBlockDevices(sda, sdb, sdc)
   186  	c.Assert(err, jc.ErrorIsNil)
   187  	wc.AssertOneChange()
   188  
   189  	// drop sdc.
   190  	err = s.machine.SetMachineBlockDevices(sda, sdb)
   191  	c.Assert(err, jc.ErrorIsNil)
   192  	wc.AssertOneChange()
   193  
   194  	// add sdc again: should get a new name.
   195  	err = s.machine.SetMachineBlockDevices(sda, sdb, sdc)
   196  	c.Assert(err, jc.ErrorIsNil)
   197  	wc.AssertOneChange()
   198  }