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 <rbtcollins@hp.com>
This commit is contained in:
@@ -40,6 +40,7 @@ from nova import unit
|
|||||||
from nova import utils
|
from nova import utils
|
||||||
from nova.virt.baremetal import baremetal_states
|
from nova.virt.baremetal import baremetal_states
|
||||||
from nova.virt.baremetal import db
|
from nova.virt.baremetal import db
|
||||||
|
from nova.virt.disk import api as disk
|
||||||
|
|
||||||
|
|
||||||
QUEUE = Queue.Queue()
|
QUEUE = Queue.Queue()
|
||||||
@@ -83,14 +84,19 @@ def logout_iscsi(portal_address, portal_port, target_iqn):
|
|||||||
check_exit_code=[0])
|
check_exit_code=[0])
|
||||||
|
|
||||||
|
|
||||||
def make_partitions(dev, root_mb, swap_mb):
|
def make_partitions(dev, root_mb, swap_mb, ephemeral_mb):
|
||||||
"""Create partitions for root and swap on a disk device."""
|
"""Create partitions for root, ephemeral and swap on a disk device."""
|
||||||
# Lead in with 1MB to allow room for the partition table itself, otherwise
|
# 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
|
# the way sfdisk adjusts doesn't shift the partition up to compensate, and
|
||||||
# we lose the space.
|
# we lose the space.
|
||||||
# http://bazaar.launchpad.net/~ubuntu-branches/ubuntu/raring/util-linux/
|
# http://bazaar.launchpad.net/~ubuntu-branches/ubuntu/raring/util-linux/
|
||||||
# raring/view/head:/fdisk/sfdisk.c#L1940
|
# 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,
|
utils.execute('sfdisk', '-uM', dev, process_input=stdin_command,
|
||||||
run_as_root=True,
|
run_as_root=True,
|
||||||
attempts=3,
|
attempts=3,
|
||||||
@@ -125,6 +131,11 @@ def mkswap(dev, label='swap1'):
|
|||||||
check_exit_code=[0])
|
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):
|
def block_uuid(dev):
|
||||||
"""Get UUID of a block device."""
|
"""Get UUID of a block device."""
|
||||||
out, _ = utils.execute('blkid', '-s', 'UUID', '-o', 'value', dev,
|
out, _ = utils.execute('blkid', '-s', 'UUID', '-o', 'value', dev,
|
||||||
@@ -173,15 +184,20 @@ def get_image_mb(image_path):
|
|||||||
return image_mb
|
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."""
|
"""Creates partitions and write an image to the root partition."""
|
||||||
|
if ephemeral_mb:
|
||||||
|
ephemeral_part = "%s-part1" % dev
|
||||||
|
swap_part = "%s-part2" % dev
|
||||||
|
root_part = "%s-part3" % dev
|
||||||
|
else:
|
||||||
root_part = "%s-part1" % dev
|
root_part = "%s-part1" % dev
|
||||||
swap_part = "%s-part2" % dev
|
swap_part = "%s-part2" % dev
|
||||||
|
|
||||||
if not is_block_device(dev):
|
if not is_block_device(dev):
|
||||||
LOG.warn(_("parent device '%s' not found"), dev)
|
LOG.warn(_("parent device '%s' not found"), dev)
|
||||||
return
|
return
|
||||||
make_partitions(dev, root_mb, swap_mb)
|
make_partitions(dev, root_mb, swap_mb, ephemeral_mb)
|
||||||
if not is_block_device(root_part):
|
if not is_block_device(root_part):
|
||||||
LOG.warn(_("root device '%s' not found"), root_part)
|
LOG.warn(_("root device '%s' not found"), root_part)
|
||||||
return
|
return
|
||||||
@@ -190,6 +206,10 @@ def work_on_disk(dev, root_mb, swap_mb, image_path):
|
|||||||
return
|
return
|
||||||
dd(image_path, root_part)
|
dd(image_path, root_part)
|
||||||
mkswap(swap_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:
|
try:
|
||||||
root_uuid = block_uuid(root_part)
|
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,
|
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."""
|
"""All-in-one function to deploy a node."""
|
||||||
dev = get_dev(address, port, iqn, lun)
|
dev = get_dev(address, port, iqn, lun)
|
||||||
image_mb = get_image_mb(image_path)
|
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)
|
discovery(address, port)
|
||||||
login_iscsi(address, port, iqn)
|
login_iscsi(address, port, iqn)
|
||||||
try:
|
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:
|
except processutils.ProcessExecutionError as err:
|
||||||
with excutils.save_and_reraise_exception():
|
with excutils.save_and_reraise_exception():
|
||||||
# Log output if there was a error
|
# Log output if there was a error
|
||||||
@@ -314,6 +335,7 @@ class BareMetalDeploy(object):
|
|||||||
'pxe_config_path': d['pxe_config_path'],
|
'pxe_config_path': d['pxe_config_path'],
|
||||||
'root_mb': int(d['root_mb']),
|
'root_mb': int(d['root_mb']),
|
||||||
'swap_mb': int(d['swap_mb']),
|
'swap_mb': int(d['swap_mb']),
|
||||||
|
'ephemeral_mb': int(d['ephemeral_mb']),
|
||||||
}
|
}
|
||||||
# Restart worker, if needed
|
# Restart worker, if needed
|
||||||
if not self.worker.isAlive():
|
if not self.worker.isAlive():
|
||||||
|
|||||||
@@ -136,22 +136,7 @@ class PhysicalWorkTestCase(test.NoDBTestCase):
|
|||||||
|
|
||||||
self.stubs.Set(time, 'sleep', noop)
|
self.stubs.Set(time, 'sleep', noop)
|
||||||
|
|
||||||
def test_deploy(self):
|
def _deploy_mox(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'
|
|
||||||
|
|
||||||
self.mox.StubOutWithMock(bmdh, 'get_dev')
|
self.mox.StubOutWithMock(bmdh, 'get_dev')
|
||||||
self.mox.StubOutWithMock(bmdh, 'get_image_mb')
|
self.mox.StubOutWithMock(bmdh, 'get_image_mb')
|
||||||
self.mox.StubOutWithMock(bmdh, 'discovery')
|
self.mox.StubOutWithMock(bmdh, 'discovery')
|
||||||
@@ -165,12 +150,30 @@ class PhysicalWorkTestCase(test.NoDBTestCase):
|
|||||||
self.mox.StubOutWithMock(bmdh, 'switch_pxe_config')
|
self.mox.StubOutWithMock(bmdh, 'switch_pxe_config')
|
||||||
self.mox.StubOutWithMock(bmdh, 'notify')
|
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_dev(address, port, iqn, lun).AndReturn(dev)
|
||||||
bmdh.get_image_mb(image_path).AndReturn(1) # < root_mb
|
bmdh.get_image_mb(image_path).AndReturn(1) # < root_mb
|
||||||
bmdh.discovery(address, port)
|
bmdh.discovery(address, port)
|
||||||
bmdh.login_iscsi(address, port, iqn)
|
bmdh.login_iscsi(address, port, iqn)
|
||||||
bmdh.is_block_device(dev).AndReturn(True)
|
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(root_part).AndReturn(True)
|
||||||
bmdh.is_block_device(swap_part).AndReturn(True)
|
bmdh.is_block_device(swap_part).AndReturn(True)
|
||||||
bmdh.dd(image_path, root_part)
|
bmdh.dd(image_path, root_part)
|
||||||
@@ -182,7 +185,50 @@ class PhysicalWorkTestCase(test.NoDBTestCase):
|
|||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
|
|
||||||
bmdh.deploy(address, port, iqn, lun, image_path, pxe_config_path,
|
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()
|
self.mox.VerifyAll()
|
||||||
|
|
||||||
@@ -196,6 +242,7 @@ class PhysicalWorkTestCase(test.NoDBTestCase):
|
|||||||
pxe_config_path = '/tmp/abc/pxeconfig'
|
pxe_config_path = '/tmp/abc/pxeconfig'
|
||||||
root_mb = 128
|
root_mb = 128
|
||||||
swap_mb = 64
|
swap_mb = 64
|
||||||
|
ephemeral_mb = 256
|
||||||
|
|
||||||
dev = '/dev/fake'
|
dev = '/dev/fake'
|
||||||
|
|
||||||
@@ -213,7 +260,7 @@ class PhysicalWorkTestCase(test.NoDBTestCase):
|
|||||||
bmdh.get_image_mb(image_path).AndReturn(1) # < root_mb
|
bmdh.get_image_mb(image_path).AndReturn(1) # < root_mb
|
||||||
bmdh.discovery(address, port)
|
bmdh.discovery(address, port)
|
||||||
bmdh.login_iscsi(address, port, iqn)
|
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)
|
AndRaise(TestException)
|
||||||
bmdh.logout_iscsi(address, port, iqn)
|
bmdh.logout_iscsi(address, port, iqn)
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
@@ -221,7 +268,7 @@ class PhysicalWorkTestCase(test.NoDBTestCase):
|
|||||||
self.assertRaises(TestException,
|
self.assertRaises(TestException,
|
||||||
bmdh.deploy,
|
bmdh.deploy,
|
||||||
address, port, iqn, lun, image_path,
|
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):
|
class SwitchPxeConfigTestCase(test.NoDBTestCase):
|
||||||
|
|||||||
Reference in New Issue
Block a user