summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2013-01-22 22:57:17 +0000
committerGerrit Code Review <review@openstack.org>2013-01-22 22:57:17 +0000
commit794b0ffc75b71fa69053a11cff330635b7048451 (patch)
tree0bbd0d2e57a89f721e4d3c4b8aaccf55b4bd036a
parent723987a16f093c18bb2d01f26f82d1ad1512c188 (diff)
parent1f96a67661109eb8aa69b7c693b1c483f241b561 (diff)
downloadnova-794b0ffc75b71fa69053a11cff330635b7048451.tar.gz
nova-794b0ffc75b71fa69053a11cff330635b7048451.tar.xz
nova-794b0ffc75b71fa69053a11cff330635b7048451.zip
Merge "Tests for PXE bare-metal provisioning helper server."
-rwxr-xr-xbin/nova-baremetal-deploy-helper5
-rw-r--r--nova/tests/baremetal/test_nova_baremetal_deploy_helper.py256
2 files changed, 260 insertions, 1 deletions
diff --git a/bin/nova-baremetal-deploy-helper b/bin/nova-baremetal-deploy-helper
index f8a487d37..894a42003 100755
--- a/bin/nova-baremetal-deploy-helper
+++ b/bin/nova-baremetal-deploy-helper
@@ -18,7 +18,10 @@
"""Starter script for Bare-Metal Deployment Service."""
import eventlet
-eventlet.monkey_patch()
+
+# Do not monkey_patch in unittest
+if __name__ == '__main__':
+ eventlet.monkey_patch()
import os
import sys
diff --git a/nova/tests/baremetal/test_nova_baremetal_deploy_helper.py b/nova/tests/baremetal/test_nova_baremetal_deploy_helper.py
new file mode 100644
index 000000000..56c3f953e
--- /dev/null
+++ b/nova/tests/baremetal/test_nova_baremetal_deploy_helper.py
@@ -0,0 +1,256 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright (c) 2012 NTT DOCOMO, INC.
+# Copyright 2011 OpenStack LLC
+# Copyright 2011 Ilya Alekseyev
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import imp
+import os
+import sys
+import tempfile
+import time
+
+from nova import test
+
+from nova.tests.baremetal.db import base as bm_db_base
+
+
+TOPDIR = os.path.normpath(os.path.join(
+ os.path.dirname(os.path.abspath(__file__)),
+ os.pardir,
+ os.pardir,
+ os.pardir))
+BMDH_PATH = os.path.join(TOPDIR, 'bin', 'nova-baremetal-deploy-helper')
+
+sys.dont_write_bytecode = True
+bmdh = imp.load_source('bmdh', BMDH_PATH)
+sys.dont_write_bytecode = False
+
+_PXECONF_DEPLOY = """
+default deploy
+
+label deploy
+kernel deploy_kernel
+append initrd=deploy_ramdisk
+ipappend 3
+
+label boot
+kernel kernel
+append initrd=ramdisk root=${ROOT}
+"""
+
+_PXECONF_BOOT = """
+default boot
+
+label deploy
+kernel deploy_kernel
+append initrd=deploy_ramdisk
+ipappend 3
+
+label boot
+kernel kernel
+append initrd=ramdisk root=UUID=12345678-1234-1234-1234-1234567890abcdef
+"""
+
+
+class WorkerTestCase(bm_db_base.BMDBTestCase):
+ def setUp(self):
+ super(WorkerTestCase, self).setUp()
+ self.worker = bmdh.Worker()
+ # Make tearDown() fast
+ self.worker.queue_timeout = 0.1
+ self.worker.start()
+
+ def tearDown(self):
+ if self.worker.isAlive():
+ self.worker.stop = True
+ self.worker.join(timeout=1)
+ super(WorkerTestCase, self).tearDown()
+
+ def wait_queue_empty(self, timeout):
+ for _ in xrange(int(timeout / 0.1)):
+ if bmdh.QUEUE.empty():
+ break
+ time.sleep(0.1)
+
+ def test_run_calls_deploy(self):
+ """Check all queued requests are passed to deploy()."""
+ history = []
+
+ def fake_deploy(**params):
+ history.append(params)
+
+ self.stubs.Set(bmdh, 'deploy', fake_deploy)
+ params_list = [{'fake1': ''}, {'fake2': ''}, {'fake3': ''}]
+ for (dep_id, params) in enumerate(params_list):
+ bmdh.QUEUE.put((dep_id, params))
+ self.wait_queue_empty(1)
+ self.assertEqual(params_list, history)
+
+ def test_run_with_failing_deploy(self):
+ """Check a worker keeps on running even if deploy() raises
+ an exception.
+ """
+ history = []
+
+ def fake_deploy(**params):
+ history.append(params)
+ # always fail
+ raise Exception('test')
+
+ self.stubs.Set(bmdh, 'deploy', fake_deploy)
+ params_list = [{'fake1': ''}, {'fake2': ''}, {'fake3': ''}]
+ for (dep_id, params) in enumerate(params_list):
+ bmdh.QUEUE.put((dep_id, params))
+ self.wait_queue_empty(1)
+ self.assertEqual(params_list, history)
+
+
+class PhysicalWorkTestCase(test.TestCase):
+ def setUp(self):
+ super(PhysicalWorkTestCase, self).setUp()
+
+ def noop(*args, **kwargs):
+ pass
+
+ 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'
+
+ self.mox.StubOutWithMock(bmdh, 'get_dev')
+ self.mox.StubOutWithMock(bmdh, 'get_image_mb')
+ self.mox.StubOutWithMock(bmdh, 'discovery')
+ self.mox.StubOutWithMock(bmdh, 'login_iscsi')
+ self.mox.StubOutWithMock(bmdh, 'logout_iscsi')
+ self.mox.StubOutWithMock(bmdh, 'make_partitions')
+ self.mox.StubOutWithMock(bmdh, 'is_block_device')
+ self.mox.StubOutWithMock(bmdh, 'dd')
+ self.mox.StubOutWithMock(bmdh, 'mkswap')
+ self.mox.StubOutWithMock(bmdh, 'block_uuid')
+ self.mox.StubOutWithMock(bmdh, 'switch_pxe_config')
+ self.mox.StubOutWithMock(bmdh, 'notify')
+
+ 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.is_block_device(root_part).AndReturn(True)
+ bmdh.is_block_device(swap_part).AndReturn(True)
+ bmdh.dd(image_path, root_part)
+ bmdh.mkswap(swap_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)
+
+ def test_always_logout_iscsi(self):
+ """logout_iscsi() must be called once login_iscsi() is called."""
+ 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'
+
+ self.mox.StubOutWithMock(bmdh, 'get_dev')
+ self.mox.StubOutWithMock(bmdh, 'get_image_mb')
+ self.mox.StubOutWithMock(bmdh, 'discovery')
+ self.mox.StubOutWithMock(bmdh, 'login_iscsi')
+ self.mox.StubOutWithMock(bmdh, 'logout_iscsi')
+ self.mox.StubOutWithMock(bmdh, 'work_on_disk')
+
+ class TestException(Exception):
+ pass
+
+ 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.work_on_disk(dev, root_mb, swap_mb, image_path).\
+ AndRaise(TestException)
+ bmdh.logout_iscsi(address, port, iqn)
+ self.mox.ReplayAll()
+
+ self.assertRaises(TestException,
+ bmdh.deploy,
+ address, port, iqn, lun, image_path,
+ pxe_config_path, root_mb, swap_mb)
+
+
+class SwitchPxeConfigTestCase(test.TestCase):
+ def setUp(self):
+ super(SwitchPxeConfigTestCase, self).setUp()
+ (fd, self.fname) = tempfile.mkstemp()
+ os.write(fd, _PXECONF_DEPLOY)
+ os.close(fd)
+
+ def tearDown(self):
+ os.unlink(self.fname)
+ super(SwitchPxeConfigTestCase, self).tearDown()
+
+ def test_switch_pxe_config(self):
+ bmdh.switch_pxe_config(self.fname,
+ '12345678-1234-1234-1234-1234567890abcdef')
+ with open(self.fname, 'r') as f:
+ pxeconf = f.read()
+ self.assertEqual(pxeconf, _PXECONF_BOOT)
+
+
+class OtherFunctionTestCase(test.TestCase):
+ def test_get_dev(self):
+ expected = '/dev/disk/by-path/ip-1.2.3.4:5678-iscsi-iqn.fake-lun-9'
+ actual = bmdh.get_dev('1.2.3.4', 5678, 'iqn.fake', 9)
+ self.assertEqual(expected, actual)
+
+ def test_get_image_mb(self):
+ mb = 1024 * 1024
+ size = None
+
+ def fake_getsize(path):
+ return size
+
+ self.stubs.Set(os.path, 'getsize', fake_getsize)
+ size = 0
+ self.assertEqual(bmdh.get_image_mb('x'), 0)
+ size = 1
+ self.assertEqual(bmdh.get_image_mb('x'), 1)
+ size = mb
+ self.assertEqual(bmdh.get_image_mb('x'), 1)
+ size = mb + 1
+ self.assertEqual(bmdh.get_image_mb('x'), 2)