From 81d35f36e1dfdc02f55c5be3282d458f66e166a3 Mon Sep 17 00:00:00 2001 From: Joe Gordon Date: Mon, 14 Oct 2013 15:53:59 -0700 Subject: [PATCH] Make baremetal_deploy_helper understand ephemeral disks Teach baremetal_deploy_helper how to run sfdisk with ephemeral disks. baremetal_deploy_helper calls default mkfs on the epheral disk. Change-Id: I92d473c34e9a076f5dbcd54be538410b30b10204 Partial-Bug: #1238311 Co-Authored-By: Robert Collins --- nova/cmd/baremetal_deploy_helper.py | 40 +++++++-- .../test_nova_baremetal_deploy_helper.py | 87 ++++++++++++++----- 2 files changed, 98 insertions(+), 29 deletions(-) diff --git a/nova/cmd/baremetal_deploy_helper.py b/nova/cmd/baremetal_deploy_helper.py index 92d2f31f6abc..33e7114d8b72 100644 --- a/nova/cmd/baremetal_deploy_helper.py +++ b/nova/cmd/baremetal_deploy_helper.py @@ -40,6 +40,7 @@ from nova import unit from nova import utils from nova.virt.baremetal import baremetal_states from nova.virt.baremetal import db +from nova.virt.disk import api as disk QUEUE = Queue.Queue() @@ -83,14 +84,19 @@ def logout_iscsi(portal_address, portal_port, target_iqn): check_exit_code=[0]) -def make_partitions(dev, root_mb, swap_mb): - """Create partitions for root and swap on a disk device.""" +def make_partitions(dev, root_mb, swap_mb, ephemeral_mb): + """Create partitions for root, ephemeral and swap on a disk device.""" # Lead in with 1MB to allow room for the partition table itself, otherwise # the way sfdisk adjusts doesn't shift the partition up to compensate, and # we lose the space. # http://bazaar.launchpad.net/~ubuntu-branches/ubuntu/raring/util-linux/ # raring/view/head:/fdisk/sfdisk.c#L1940 - stdin_command = ('1,%d,83;\n,%d,82;\n0,0;\n0,0;\n' % (root_mb, swap_mb)) + if ephemeral_mb: + stdin_command = ('1,%d,83;\n,%d,82;\n,%d,83;\n0,0;\n' % + (ephemeral_mb, swap_mb, root_mb)) + else: + stdin_command = ('1,%d,83;\n,%d,82;\n0,0;\n0,0;\n' % + (root_mb, swap_mb)) utils.execute('sfdisk', '-uM', dev, process_input=stdin_command, run_as_root=True, attempts=3, @@ -125,6 +131,11 @@ def mkswap(dev, label='swap1'): check_exit_code=[0]) +def mkfs_ephemeral(dev, label="ephemeral0"): + #TODO(jogo) support non-default mkfs options as well + disk.mkfs("default", label, dev) + + def block_uuid(dev): """Get UUID of a block device.""" out, _ = utils.execute('blkid', '-s', 'UUID', '-o', 'value', dev, @@ -173,15 +184,20 @@ def get_image_mb(image_path): return image_mb -def work_on_disk(dev, root_mb, swap_mb, image_path): +def work_on_disk(dev, root_mb, swap_mb, ephemeral_mb, image_path): """Creates partitions and write an image to the root partition.""" - root_part = "%s-part1" % dev - swap_part = "%s-part2" % dev + if ephemeral_mb: + ephemeral_part = "%s-part1" % dev + swap_part = "%s-part2" % dev + root_part = "%s-part3" % dev + else: + root_part = "%s-part1" % dev + swap_part = "%s-part2" % dev if not is_block_device(dev): LOG.warn(_("parent device '%s' not found"), dev) return - make_partitions(dev, root_mb, swap_mb) + make_partitions(dev, root_mb, swap_mb, ephemeral_mb) if not is_block_device(root_part): LOG.warn(_("root device '%s' not found"), root_part) return @@ -190,6 +206,10 @@ def work_on_disk(dev, root_mb, swap_mb, image_path): return dd(image_path, root_part) mkswap(swap_part) + if ephemeral_mb and not is_block_device(ephemeral_part): + LOG.warn(_("ephemeral device '%s' not found"), ephemeral_part) + elif ephemeral_mb: + mkfs_ephemeral(ephemeral_part) try: root_uuid = block_uuid(root_part) @@ -200,7 +220,7 @@ def work_on_disk(dev, root_mb, swap_mb, image_path): def deploy(address, port, iqn, lun, image_path, pxe_config_path, - root_mb, swap_mb): + root_mb, swap_mb, ephemeral_mb): """All-in-one function to deploy a node.""" dev = get_dev(address, port, iqn, lun) image_mb = get_image_mb(image_path) @@ -209,7 +229,8 @@ def deploy(address, port, iqn, lun, image_path, pxe_config_path, discovery(address, port) login_iscsi(address, port, iqn) try: - root_uuid = work_on_disk(dev, root_mb, swap_mb, image_path) + root_uuid = work_on_disk(dev, root_mb, swap_mb, ephemeral_mb, + image_path) except processutils.ProcessExecutionError as err: with excutils.save_and_reraise_exception(): # Log output if there was a error @@ -314,6 +335,7 @@ class BareMetalDeploy(object): 'pxe_config_path': d['pxe_config_path'], 'root_mb': int(d['root_mb']), 'swap_mb': int(d['swap_mb']), + 'ephemeral_mb': int(d['ephemeral_mb']), } # Restart worker, if needed if not self.worker.isAlive(): diff --git a/nova/tests/virt/baremetal/test_nova_baremetal_deploy_helper.py b/nova/tests/virt/baremetal/test_nova_baremetal_deploy_helper.py index c5448b786b5f..8b52ef1ace8e 100644 --- a/nova/tests/virt/baremetal/test_nova_baremetal_deploy_helper.py +++ b/nova/tests/virt/baremetal/test_nova_baremetal_deploy_helper.py @@ -136,22 +136,7 @@ class PhysicalWorkTestCase(test.NoDBTestCase): self.stubs.Set(time, 'sleep', noop) - def test_deploy(self): - """Check loosely all functions are called with right args.""" - address = '127.0.0.1' - port = 3306 - iqn = 'iqn.xyz' - lun = 1 - image_path = '/tmp/xyz/image' - pxe_config_path = '/tmp/abc/pxeconfig' - root_mb = 128 - swap_mb = 64 - - dev = '/dev/fake' - root_part = '/dev/fake-part1' - swap_part = '/dev/fake-part2' - root_uuid = '12345678-1234-1234-12345678-12345678abcdef' - + def _deploy_mox(self): self.mox.StubOutWithMock(bmdh, 'get_dev') self.mox.StubOutWithMock(bmdh, 'get_image_mb') self.mox.StubOutWithMock(bmdh, 'discovery') @@ -165,12 +150,30 @@ class PhysicalWorkTestCase(test.NoDBTestCase): self.mox.StubOutWithMock(bmdh, 'switch_pxe_config') self.mox.StubOutWithMock(bmdh, 'notify') + def test_deploy_no_ephemeral(self): + address = '127.0.0.1' + port = 3306 + iqn = 'iqn.xyz' + lun = 1 + image_path = '/tmp/xyz/image' + pxe_config_path = '/tmp/abc/pxeconfig' + root_mb = 128 + swap_mb = 64 + ephemeral_mb = 0 + + dev = '/dev/fake' + root_part = '/dev/fake-part1' + swap_part = '/dev/fake-part2' + root_uuid = '12345678-1234-1234-12345678-12345678abcdef' + + self._deploy_mox() + bmdh.get_dev(address, port, iqn, lun).AndReturn(dev) bmdh.get_image_mb(image_path).AndReturn(1) # < root_mb bmdh.discovery(address, port) bmdh.login_iscsi(address, port, iqn) bmdh.is_block_device(dev).AndReturn(True) - bmdh.make_partitions(dev, root_mb, swap_mb) + bmdh.make_partitions(dev, root_mb, swap_mb, ephemeral_mb) bmdh.is_block_device(root_part).AndReturn(True) bmdh.is_block_device(swap_part).AndReturn(True) bmdh.dd(image_path, root_part) @@ -182,7 +185,50 @@ class PhysicalWorkTestCase(test.NoDBTestCase): self.mox.ReplayAll() bmdh.deploy(address, port, iqn, lun, image_path, pxe_config_path, - root_mb, swap_mb) + root_mb, swap_mb, ephemeral_mb) + + self.mox.VerifyAll() + + def test_deploy_with_ephemeral(self): + address = '127.0.0.1' + port = 3306 + iqn = 'iqn.xyz' + lun = 1 + image_path = '/tmp/xyz/image' + pxe_config_path = '/tmp/abc/pxeconfig' + root_mb = 128 + swap_mb = 64 + ephemeral_mb = 256 + + dev = '/dev/fake' + ephemeral_part = '/dev/fake-part1' + swap_part = '/dev/fake-part2' + root_part = '/dev/fake-part3' + root_uuid = '12345678-1234-1234-12345678-12345678abcdef' + + self._deploy_mox() + self.mox.StubOutWithMock(bmdh, 'mkfs_ephemeral') + + bmdh.get_dev(address, port, iqn, lun).AndReturn(dev) + bmdh.get_image_mb(image_path).AndReturn(1) # < root_mb + bmdh.discovery(address, port) + bmdh.login_iscsi(address, port, iqn) + bmdh.is_block_device(dev).AndReturn(True) + bmdh.make_partitions(dev, root_mb, swap_mb, ephemeral_mb) + bmdh.is_block_device(root_part).AndReturn(True) + bmdh.is_block_device(swap_part).AndReturn(True) + bmdh.is_block_device(ephemeral_part).AndReturn(True) + bmdh.dd(image_path, root_part) + bmdh.mkswap(swap_part) + bmdh.mkfs_ephemeral(ephemeral_part) + bmdh.block_uuid(root_part).AndReturn(root_uuid) + bmdh.logout_iscsi(address, port, iqn) + bmdh.switch_pxe_config(pxe_config_path, root_uuid) + bmdh.notify(address, 10000) + self.mox.ReplayAll() + + bmdh.deploy(address, port, iqn, lun, image_path, pxe_config_path, + root_mb, swap_mb, ephemeral_mb) self.mox.VerifyAll() @@ -196,6 +242,7 @@ class PhysicalWorkTestCase(test.NoDBTestCase): pxe_config_path = '/tmp/abc/pxeconfig' root_mb = 128 swap_mb = 64 + ephemeral_mb = 256 dev = '/dev/fake' @@ -213,7 +260,7 @@ class PhysicalWorkTestCase(test.NoDBTestCase): bmdh.get_image_mb(image_path).AndReturn(1) # < root_mb bmdh.discovery(address, port) bmdh.login_iscsi(address, port, iqn) - bmdh.work_on_disk(dev, root_mb, swap_mb, image_path).\ + bmdh.work_on_disk(dev, root_mb, swap_mb, ephemeral_mb, image_path).\ AndRaise(TestException) bmdh.logout_iscsi(address, port, iqn) self.mox.ReplayAll() @@ -221,7 +268,7 @@ class PhysicalWorkTestCase(test.NoDBTestCase): self.assertRaises(TestException, bmdh.deploy, address, port, iqn, lun, image_path, - pxe_config_path, root_mb, swap_mb) + pxe_config_path, root_mb, swap_mb, ephemeral_mb) class SwitchPxeConfigTestCase(test.NoDBTestCase):