Also, update the mocked config to create orphan disks for attach
purposes.
Signed-off-by: Alex Pyrgiotis <[email protected]>
diff --git a/test/py/cmdlib/instance_unittest.py
b/test/py/cmdlib/instance_unittest.py
index 438b228..dea01a1 100644
--- a/test/py/cmdlib/instance_unittest.py
+++ b/test/py/cmdlib/instance_unittest.py
@@ -2245,6 +2245,12 @@ class TestLUInstanceSetParams(CmdlibTestCase):
nics=[(constants.DDM_ADD, -1, {})])
self.ExecOpCode(op)
+ def testAttachNICs(self):
+ msg = "Attach operation is not supported for NICs"
+ op = self.CopyOpCode(self.op,
+ nics=[(constants.DDM_ATTACH, -1, {})])
+ self.ExecOpCodeExpectOpPrereqError(op, msg)
+
def testNoHotplugSupport(self):
op = self.CopyOpCode(self.op,
nics=[(constants.DDM_ADD, -1, {})],
@@ -2387,6 +2393,12 @@ class TestLUInstanceSetParams(CmdlibTestCase):
nics=[(constants.DDM_REMOVE, 0, {})])
self.ExecOpCode(op)
+ def testDetachNICs(self):
+ msg = "Detach operation is not supported for NICs"
+ op = self.CopyOpCode(self.op,
+ nics=[(constants.DDM_DETACH, -1, {})])
+ self.ExecOpCodeExpectOpPrereqError(op, msg)
+
def testHotRemoveNic(self):
inst = self.cfg.AddNewInstance(nics=[self.cfg.CreateNic(),
self.cfg.CreateNic()])
@@ -2435,6 +2447,15 @@ class TestLUInstanceSetParams(CmdlibTestCase):
self.ExecOpCodeExpectException(
op, errors.TypeEnforcementError, "is not a valid size")
+ def testAddDiskUnknownParam(self):
+ op = self.CopyOpCode(self.op,
+ disks=[[constants.DDM_ADD, -1,
+ {
+ "uuid": "mock_uuid_1134"
+ }]])
+ self.ExecOpCodeExpectException(
+ op, errors.TypeEnforcementError, "Unknown parameter 'uuid'")
+
def testAddDiskRunningInstanceNoWaitForSync(self):
op = self.CopyOpCode(self.running_op,
disks=[[constants.DDM_ADD, -1,
@@ -2464,7 +2485,7 @@ class TestLUInstanceSetParams(CmdlibTestCase):
wait_for_sync=False)
self.ExecOpCodeExpectOpPrereqError(
op, "Can't add a disk to an instance with deactivated disks"
- " and --no-wait-for-sync given.")
+ " and --no-wait-for-sync given")
def testAddDiskRunningInstance(self):
op = self.CopyOpCode(self.running_op,
@@ -2506,6 +2527,138 @@ class TestLUInstanceSetParams(CmdlibTestCase):
self.assertTrue(self.rpc.call_blockdev_assemble.called)
self.assertTrue(self.rpc.call_hotplug_device.called)
+ def testAttachDiskWrongParams(self):
+ msg = "Only one argument is permitted in attach op, either name or uuid"
+ op = self.CopyOpCode(self.op,
+ disks=[[constants.DDM_ATTACH, -1,
+ {
+ constants.IDISK_SIZE: 1134
+ }]],
+ )
+ self.ExecOpCodeExpectOpPrereqError(op, msg)
+ op = self.CopyOpCode(self.op,
+ disks=[[constants.DDM_ATTACH, -1,
+ {
+ 'uuid': "1134",
+ constants.IDISK_NAME: "1134",
+ }]],
+ )
+ self.ExecOpCodeExpectOpPrereqError(op, msg)
+ op = self.CopyOpCode(self.op,
+ disks=[[constants.DDM_ATTACH, -1,
+ {
+ 'uuid': "1134",
+ constants.IDISK_SIZE: 1134,
+ }]],
+ )
+ self.ExecOpCodeExpectOpPrereqError(op, msg)
+
+ def testAttachDiskWrongTemplate(self):
+ msg = "Instance has '%s' template while disk has '%s' template" % \
+ (constants.DT_PLAIN, constants.DT_BLOCK)
+ self.cfg.AddOrphanDisk(name="mock_disk_1134", dev_type=constants.DT_BLOCK)
+ op = self.CopyOpCode(self.op,
+ disks=[[constants.DDM_ATTACH, -1,
+ {
+ constants.IDISK_NAME: "mock_disk_1134"
+ }]],
+ )
+ self.ExecOpCodeExpectOpPrereqError(op, msg)
+
+ def testAttachDiskWrongNodes(self):
+ msg = "Disk nodes are \['mock_node_1134'\]"
+
+ self.cfg.AddOrphanDisk(name="mock_disk_1134",
primary_node="mock_node_1134")
+ op = self.CopyOpCode(self.op,
+ disks=[[constants.DDM_ATTACH, -1,
+ {
+ constants.IDISK_NAME: "mock_disk_1134"
+ }]],
+ )
+ self.ExecOpCodeExpectOpPrereqError(op, msg)
+
+ def testAttachDiskRunningInstance(self):
+ self.cfg.AddOrphanDisk(name="mock_disk_1134")
+ self.rpc.call_blockdev_assemble.return_value = \
+ self.RpcResultsBuilder() \
+ .CreateSuccessfulNodeResult(self.master,
+ ("/dev/mocked_path",
+ "/var/run/ganeti/instance-disks/mocked_d",
+ None))
+ op = self.CopyOpCode(self.running_op,
+ disks=[[constants.DDM_ATTACH, -1,
+ {
+ constants.IDISK_NAME: "mock_disk_1134"
+ }]],
+ )
+ self.ExecOpCode(op)
+ self.assertTrue(self.rpc.call_blockdev_assemble.called)
+ self.assertFalse(self.rpc.call_blockdev_shutdown.called)
+
+ def testAttachDiskRunningInstanceNoWaitForSync(self):
+ self.cfg.AddOrphanDisk(name="mock_disk_1134")
+ self.rpc.call_blockdev_assemble.return_value = \
+ self.RpcResultsBuilder() \
+ .CreateSuccessfulNodeResult(self.master,
+ ("/dev/mocked_path",
+ "/var/run/ganeti/instance-disks/mocked_d",
+ None))
+ op = self.CopyOpCode(self.running_op,
+ disks=[[constants.DDM_ATTACH, -1,
+ {
+ constants.IDISK_NAME: "mock_disk_1134"
+ }]],
+ wait_for_sync=False)
+ self.ExecOpCode(op)
+ self.assertTrue(self.rpc.call_blockdev_assemble.called)
+ self.assertFalse(self.rpc.call_blockdev_shutdown.called)
+
+ def testAttachDiskDownInstance(self):
+ self.cfg.AddOrphanDisk(name="mock_disk_1134")
+ op = self.CopyOpCode(self.op,
+ disks=[[constants.DDM_ATTACH, -1,
+ {
+ constants.IDISK_NAME: "mock_disk_1134"
+ }]])
+ self.ExecOpCode(op)
+
+ self.assertTrue(self.rpc.call_blockdev_assemble.called)
+ self.assertTrue(self.rpc.call_blockdev_shutdown.called)
+
+ def testAttachDiskDownInstanceNoWaitForSync(self):
+ self.cfg.AddOrphanDisk(name="mock_disk_1134")
+ op = self.CopyOpCode(self.op,
+ disks=[[constants.DDM_ATTACH, -1,
+ {
+ constants.IDISK_NAME: "mock_disk_1134"
+ }]],
+ wait_for_sync=False)
+ self.ExecOpCodeExpectOpPrereqError(
+ op, "Can't attach a disk to an instance with deactivated disks"
+ " and --no-wait-for-sync given.")
+
+ def testHotAttachDisk(self):
+ self.cfg.AddOrphanDisk(name="mock_disk_1134")
+ self.rpc.call_blockdev_assemble.return_value = \
+ self.RpcResultsBuilder() \
+ .CreateSuccessfulNodeResult(self.master,
+ ("/dev/mocked_path",
+ "/var/run/ganeti/instance-disks/mocked_d",
+ None))
+ op = self.CopyOpCode(self.op,
+ disks=[[constants.DDM_ATTACH, -1,
+ {
+ constants.IDISK_NAME: "mock_disk_1134"
+ }]],
+ hotplug=True)
+ self.rpc.call_hotplug_supported.return_value = \
+ self.RpcResultsBuilder() \
+ .CreateSuccessfulNodeResult(self.master)
+ self.ExecOpCode(op)
+ self.assertTrue(self.rpc.call_hotplug_supported.called)
+ self.assertTrue(self.rpc.call_blockdev_assemble.called)
+ self.assertTrue(self.rpc.call_hotplug_device.called)
+
def testHotRemoveDisk(self):
inst = self.cfg.AddNewInstance(disks=[self.cfg.CreateDisk(),
self.cfg.CreateDisk()])
@@ -2523,6 +2676,64 @@ class TestLUInstanceSetParams(CmdlibTestCase):
self.assertTrue(self.rpc.call_blockdev_shutdown.called)
self.assertTrue(self.rpc.call_blockdev_remove.called)
+ def testHotDetachDisk(self):
+ inst = self.cfg.AddNewInstance(disks=[self.cfg.CreateDisk(),
+ self.cfg.CreateDisk()])
+ op = self.CopyOpCode(self.op,
+ instance_name=inst.name,
+ disks=[[constants.DDM_DETACH, -1,
+ {}]],
+ hotplug=True)
+ self.rpc.call_hotplug_supported.return_value = \
+ self.RpcResultsBuilder() \
+ .CreateSuccessfulNodeResult(self.master)
+ self.ExecOpCode(op)
+ self.assertTrue(self.rpc.call_hotplug_supported.called)
+ self.assertTrue(self.rpc.call_hotplug_device.called)
+ self.assertTrue(self.rpc.call_blockdev_shutdown.called)
+
+ def testAttachDetachDisk(self):
+ """Check if the disks can be attached and detached in sequence.
+
+ Also, check if the operations succeed both with name and uuid.
+ """
+ disk1 = self.cfg.CreateDisk(uuid="mock_uuid_1134")
+ disk2 = self.cfg.CreateDisk(name="mock_name_1134")
+
+ inst = self.cfg.AddNewInstance(disks=[disk1, disk2])
+
+ op = self.CopyOpCode(self.op,
+ instance_name=inst.name,
+ disks=[[constants.DDM_DETACH, "mock_uuid_1134",
+ {}]])
+ self.ExecOpCode(op)
+ self.assertEqual([disk2], self.cfg.GetInstanceDisks(inst.uuid))
+
+ op = self.CopyOpCode(self.op,
+ instance_name=inst.name,
+ disks=[[constants.DDM_ATTACH, 0,
+ {
+ 'uuid': "mock_uuid_1134"
+ }]])
+ self.ExecOpCode(op)
+ self.assertEqual([disk1, disk2], self.cfg.GetInstanceDisks(inst.uuid))
+
+ op = self.CopyOpCode(self.op,
+ instance_name=inst.name,
+ disks=[[constants.DDM_DETACH, "mock_name_1134",
+ {}]])
+ self.ExecOpCode(op)
+ self.assertEqual([disk1], self.cfg.GetInstanceDisks(inst.uuid))
+
+ op = self.CopyOpCode(self.op,
+ instance_name=inst.name,
+ disks=[[constants.DDM_ATTACH, 0,
+ {
+ constants.IDISK_NAME: "mock_name_1134"
+ }]])
+ self.ExecOpCode(op)
+ self.assertEqual([disk2, disk1], self.cfg.GetInstanceDisks(inst.uuid))
+
def testModifyDiskWithSize(self):
op = self.CopyOpCode(self.op,
disks=[[constants.DDM_MODIFY, 0,
diff --git a/test/py/testutils/config_mock.py b/test/py/testutils/config_mock.py
index 62b02e5..d264e84 100644
--- a/test/py/testutils/config_mock.py
+++ b/test/py/testutils/config_mock.py
@@ -345,6 +345,10 @@ class ConfigMock(config.ConfigWriter):
self.AddNetwork(net, None)
return net
+ def AddOrphanDisk(self, **params):
+ disk = self.CreateDisk(**params) # pylint: disable=W0142
+ self._UnlockedAddDisk(disk)
+
def ConnectNetworkToGroup(self, net, group, netparams=None):
"""Connect the given network to the group.
@@ -385,6 +389,7 @@ class ConfigMock(config.ConfigWriter):
dev_type=constants.DT_PLAIN,
logical_id=None,
children=None,
+ nodes=None,
iv_name=None,
size=1024,
mode=constants.DISK_RDWR,
@@ -435,12 +440,20 @@ class ConfigMock(config.ConfigWriter):
meta_child = self.CreateDisk(dev_type=constants.DT_PLAIN,
size=constants.DRBD_META_SIZE)
children = [data_child, meta_child]
+
+ if nodes is None:
+ nodes = [pnode_uuid, snode_uuid]
elif dev_type == constants.DT_PLAIN:
if logical_id is None:
logical_id = ("mockvg", "mock_disk_%d" % disk_id)
+ if nodes is None and primary_node is not None:
+ nodes = [primary_node]
elif dev_type in constants.DTS_FILEBASED:
if logical_id is None:
logical_id = (constants.FD_LOOP, "/file/storage/disk%d" % disk_id)
+ if (nodes is None and primary_node is not None and
+ dev_type == constants.DT_FILE):
+ nodes = [primary_node]
elif dev_type == constants.DT_BLOCK:
if logical_id is None:
logical_id = (constants.BLOCKDEV_DRIVER_MANUAL,
@@ -455,6 +468,8 @@ class ConfigMock(config.ConfigWriter):
raise NotImplementedError
if children is None:
children = []
+ if nodes is None:
+ nodes = []
if iv_name is None:
iv_name = "disk/%d" % instance_disk_index
@@ -463,6 +478,7 @@ class ConfigMock(config.ConfigWriter):
dev_type=dev_type,
logical_id=logical_id,
children=children,
+ nodes=nodes,
iv_name=iv_name,
size=size,
mode=mode,
--
1.7.10.4