Merge "Convert request schema (flavors)"
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 203b653..57c07d1 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -355,6 +355,22 @@
return secgroup
+ def rebuild_server(self, server, client=None, image=None,
+ preserve_ephemeral=False, wait=True,
+ rebuild_kwargs=None):
+ if client is None:
+ client = self.compute_client
+ if image is None:
+ image = CONF.compute.image_ref
+ rebuild_kwargs = rebuild_kwargs or {}
+
+ LOG.debug("Rebuilding server (name: %s, image: %s, preserve eph: %s)",
+ server.name, image, preserve_ephemeral)
+ server.rebuild(image, preserve_ephemeral=preserve_ephemeral,
+ **rebuild_kwargs)
+ if wait:
+ self.status_timeout(client.servers, server.id, 'ACTIVE')
+
def create_server(self, client=None, name=None, image=None, flavor=None,
wait_on_boot=True, wait_on_delete=True,
create_kwargs={}):
diff --git a/tempest/scenario/test_baremetal_basic_ops.py b/tempest/scenario/test_baremetal_basic_ops.py
index f197c15..9ad6bc4 100644
--- a/tempest/scenario/test_baremetal_basic_ops.py
+++ b/tempest/scenario/test_baremetal_basic_ops.py
@@ -23,7 +23,7 @@
LOG = logging.getLogger(__name__)
-class BaremetalBasicOpsPXESSH(manager.BaremetalScenarioTest):
+class BaremetalBasicOps(manager.BaremetalScenarioTest):
"""
This smoke test tests the pxe_ssh Ironic driver. It follows this basic
set of operations:
@@ -35,10 +35,76 @@
* Verifies SSH connectivity using created keypair via fixed IP
* Associates a floating ip
* Verifies SSH connectivity using created keypair via floating IP
+ * Verifies instance rebuild with ephemeral partition preservation
* Deletes instance
* Monitors the associated Ironic node for power and
expected state transitions
"""
+ def rebuild_instance(self, preserve_ephemeral=False):
+ self.rebuild_server(self.instance,
+ preserve_ephemeral=preserve_ephemeral,
+ wait=False)
+
+ node = self.get_node(instance_id=self.instance.id)
+ self.instance = self.compute_client.servers.get(self.instance.id)
+
+ self.addCleanup_with_wait(self.compute_client.servers,
+ self.instance.id,
+ cleanup_callable=self.delete_wrapper,
+ cleanup_args=[self.instance])
+
+ # We should remain on the same node
+ self.assertEqual(self.node.uuid, node.uuid)
+ self.node = node
+
+ self.status_timeout(self.compute_client.servers, self.instance.id,
+ 'REBUILD')
+ self.status_timeout(self.compute_client.servers, self.instance.id,
+ 'ACTIVE')
+
+ def create_remote_file(self, client, filename):
+ """Create a file on the remote client connection.
+
+ After creating the file, force a filesystem sync. Otherwise,
+ if we issue a rebuild too quickly, the file may not exist.
+ """
+ client.exec_command('sudo touch ' + filename)
+ client.exec_command('sync')
+
+ def verify_partition(self, client, label, mount, gib_size):
+ """Verify a labeled partition's mount point and size."""
+ LOG.info("Looking for partition %s mounted on %s" % (label, mount))
+
+ # Validate we have a device with the given partition label
+ cmd = "/sbin/blkid | grep '%s' | cut -d':' -f1" % label
+ device = client.exec_command(cmd).rstrip('\n')
+ LOG.debug("Partition device is %s" % device)
+ self.assertNotEqual('', device)
+
+ # Validate the mount point for the device
+ cmd = "mount | grep '%s' | cut -d' ' -f3" % device
+ actual_mount = client.exec_command(cmd).rstrip('\n')
+ LOG.debug("Partition mount point is %s" % actual_mount)
+ self.assertEqual(actual_mount, mount)
+
+ # Validate the partition size matches what we expect
+ numbers = '0123456789'
+ devnum = device.replace('/dev/', '')
+ cmd = "cat /sys/block/%s/%s/size" % (devnum.rstrip(numbers), devnum)
+ num_bytes = client.exec_command(cmd).rstrip('\n')
+ num_bytes = int(num_bytes) * 512
+ actual_gib_size = num_bytes / (1024 * 1024 * 1024)
+ LOG.debug("Partition size is %d GiB" % actual_gib_size)
+ self.assertEqual(actual_gib_size, gib_size)
+
+ def get_flavor_ephemeral_size(self):
+ """Returns size of the ephemeral partition in GiB."""
+ f_id = self.instance.flavor['id']
+ ephemeral = self.compute_client.flavors.get(f_id).ephemeral
+ if ephemeral != 'N/A':
+ return int(ephemeral)
+ return None
+
def add_floating_ip(self):
floating_ip = self.compute_client.floating_ips.create()
self.instance.add_floating_ip(floating_ip)
@@ -53,10 +119,32 @@
@test.services('baremetal', 'compute', 'image', 'network')
def test_baremetal_server_ops(self):
+ test_filename = '/mnt/rebuild_test.txt'
self.add_keypair()
self.boot_instance()
self.validate_ports()
self.verify_connectivity()
floating_ip = self.add_floating_ip()
self.verify_connectivity(ip=floating_ip)
+
+ vm_client = self.get_remote_client(self.instance)
+
+ # We expect the ephemeral partition to be mounted on /mnt and to have
+ # the same size as our flavor definition.
+ eph_size = self.get_flavor_ephemeral_size()
+ self.assertIsNotNone(eph_size)
+ self.verify_partition(vm_client, 'ephemeral0', '/mnt', eph_size)
+
+ # Create the test file
+ self.create_remote_file(vm_client, test_filename)
+
+ # Rebuild and preserve the ephemeral partition
+ self.rebuild_instance(True)
+ self.verify_connectivity()
+
+ # Check that we maintained our data
+ vm_client = self.get_remote_client(self.instance)
+ self.verify_partition(vm_client, 'ephemeral0', '/mnt', eph_size)
+ vm_client.exec_command('ls ' + test_filename)
+
self.terminate_instance()