diff --git a/tempest/scenario/test_stamp_pattern.py b/tempest/scenario/test_stamp_pattern.py new file mode 100644 index 0000000000..89beb15d5f --- /dev/null +++ b/tempest/scenario/test_stamp_pattern.py @@ -0,0 +1,247 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2013 NEC Corporation +# All Rights Reserved. +# +# 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. + +from cinderclient import exceptions +from tempest.common import log as logging +from tempest.common.utils.data_utils import rand_name +from tempest.common.utils.linux.remote_client import RemoteClient +from tempest.scenario import manager +import time + +LOG = logging.getLogger(__name__) + + +class TestStampPattern(manager.OfficialClientTest): + """ + This test is for snapshotting an instance/volume and attaching the volume + created from snapshot to the instance booted from snapshot. + The following is the scenario outline: + 1. Boot an instance "instance1" + 2. Create a volume "volume1" + 3. Attach volume1 to instance1 + 4. Create a filesystem on volume1 + 5. Mount volume1 + 6. Create a file which timestamp is written in volume1 + 7. Unmount volume1 + 8. Detach volume1 from instance1 + 9. Get a snapshot "snapshot_from_volume" of volume1 + 10. Get a snapshot "snapshot_from_instance" of instance1 + 11. Boot an instance "instance2" from snapshot_from_instance + 12. Create a volume "volume2" from snapshot_from_volume + 13. Attach volume2 to instance2 + 14. Check the existence of a file which created at 6. in volume2 + """ + + def _wait_for_server_status(self, server, status): + self.status_timeout(self.compute_client.servers, + server.id, + status) + + def _wait_for_image_status(self, image_id, status): + self.status_timeout(self.image_client.images, image_id, status) + + def _wait_for_volume_snapshot_status(self, volume_snapshot, status): + self.status_timeout(self.volume_client.volume_snapshots, + volume_snapshot.id, status) + + def _boot_image(self, image_id): + name = rand_name('scenario-server-') + client = self.compute_client + flavor_id = self.config.compute.flavor_ref + LOG.debug("name:%s, image:%s" % (name, image_id)) + server = client.servers.create(name=name, + image=image_id, + flavor=flavor_id, + key_name=self.keypair.name) + self.addCleanup(self.compute_client.servers.delete, server) + self.assertEqual(name, server.name) + self._wait_for_server_status(server, 'ACTIVE') + server = client.servers.get(server) # getting network information + LOG.debug("server:%s" % server) + return server + + def _add_keypair(self): + name = rand_name('scenario-keypair-') + self.keypair = self.compute_client.keypairs.create(name=name) + self.addCleanup(self.compute_client.keypairs.delete, self.keypair) + self.assertEqual(name, self.keypair.name) + + def _create_floating_ip(self): + floating_ip = self.compute_client.floating_ips.create() + self.addCleanup(floating_ip.delete) + return floating_ip + + def _add_floating_ip(self, server, floating_ip): + server.add_floating_ip(floating_ip) + + def _create_security_group_rule(self): + sgs = self.compute_client.security_groups.list() + for sg in sgs: + if sg.name == 'default': + secgroup = sg + + ruleset = { + # ssh + 'ip_protocol': 'tcp', + 'from_port': 22, + 'to_port': 22, + 'cidr': '0.0.0.0/0', + 'group_id': None + } + sg_rule = self.compute_client.security_group_rules.create(secgroup.id, + **ruleset) + self.addCleanup(self.compute_client.security_group_rules.delete, + sg_rule.id) + + def _ssh_to_server(self, server_or_ip): + if isinstance(server_or_ip, basestring): + ip = server_or_ip + else: + network_name_for_ssh = self.config.compute.network_for_ssh + ip = server_or_ip.networks[network_name_for_ssh][0] + username = self.config.scenario.ssh_user + linux_client = RemoteClient(ip, + username, + pkey=self.keypair.private_key) + + return linux_client.ssh_client + + def _create_image(self, server): + snapshot_name = rand_name('scenario-snapshot-') + create_image_client = self.compute_client.servers.create_image + image_id = create_image_client(server, snapshot_name) + self.addCleanup(self.image_client.images.delete, image_id) + self._wait_for_server_status(server, 'ACTIVE') + self._wait_for_image_status(image_id, 'active') + snapshot_image = self.image_client.images.get(image_id) + self.assertEquals(snapshot_name, snapshot_image.name) + return image_id + + def _create_volume_snapshot(self, volume): + snapshot_name = rand_name('scenario-snapshot-') + volume_snapshots = self.volume_client.volume_snapshots + snapshot = volume_snapshots.create( + volume.id, display_name=snapshot_name) + + def cleaner(): + volume_snapshots.delete(snapshot) + try: + while volume_snapshots.get(snapshot.id): + time.sleep(1) + except exceptions.NotFound: + pass + self.addCleanup(cleaner) + self._wait_for_volume_status(volume, 'available') + self._wait_for_volume_snapshot_status(snapshot, 'available') + self.assertEquals(snapshot_name, snapshot.display_name) + return snapshot + + def _wait_for_volume_status(self, volume, status): + self.status_timeout( + self.volume_client.volumes, volume.id, status) + + def _create_volume(self, snapshot_id=None): + name = rand_name('scenario-volume-') + LOG.debug("volume display-name:%s" % name) + volume = self.volume_client.volumes.create(size=1, + display_name=name, + snapshot_id=snapshot_id) + LOG.debug("volume created:%s" % volume.display_name) + + def cleaner(): + self._wait_for_volume_status(volume, 'available') + self.volume_client.volumes.delete(volume) + self.addCleanup(cleaner) + self._wait_for_volume_status(volume, 'available') + self.assertEqual(name, volume.display_name) + return volume + + def _attach_volume(self, server, volume): + attach_volume_client = self.compute_client.volumes.create_server_volume + attached_volume = attach_volume_client(server.id, + volume.id, + '/dev/vdb') + self.assertEqual(volume.id, attached_volume.id) + self._wait_for_volume_status(attached_volume, 'in-use') + + def _detach_volume(self, server, volume): + detach_volume_client = self.compute_client.volumes.delete_server_volume + detach_volume_client(server.id, volume.id) + self._wait_for_volume_status(volume, 'available') + + def _create_timestamp(self, server_or_ip): + ssh_client = self._ssh_to_server(server_or_ip) + ssh_client.exec_command('sudo /usr/sbin/mkfs.ext4 /dev/vdb') + ssh_client.exec_command('sudo mount /dev/vdb /mnt') + ssh_client.exec_command('sudo sh -c "date > /mnt/timestamp;sync"') + self.timestamp = ssh_client.exec_command('sudo cat /mnt/timestamp') + ssh_client.exec_command('sudo umount /mnt') + + def _check_timestamp(self, server_or_ip): + ssh_client = self._ssh_to_server(server_or_ip) + ssh_client.exec_command('sudo mount /dev/vdb /mnt') + got_timestamp = ssh_client.exec_command('sudo cat /mnt/timestamp') + self.assertEqual(self.timestamp, got_timestamp) + + def test_stamp_pattern(self): + # prepare for booting a instance + self._add_keypair() + self._create_security_group_rule() + + # boot an instance and create a timestamp file in it + volume = self._create_volume() + server = self._boot_image(self.config.compute.image_ref) + + # create and add floating IP to server1 + if self.config.compute.use_floatingip_for_ssh: + floating_ip_for_server = self._create_floating_ip() + self._add_floating_ip(server, floating_ip_for_server) + ip_for_server = floating_ip_for_server.ip + else: + ip_for_server = server + + self._attach_volume(server, volume) + self._create_timestamp(ip_for_server) + self._detach_volume(server, volume) + + # snapshot the volume + volume_snapshot = self._create_volume_snapshot(volume) + + # snapshot the instance + snapshot_image_id = self._create_image(server) + + # create second volume from the snapshot(volume2) + volume_from_snapshot = self._create_volume( + snapshot_id=volume_snapshot.id) + + # boot second instance from the snapshot(instance2) + server_from_snapshot = self._boot_image(snapshot_image_id) + + # create and add floating IP to server_from_snapshot + if self.config.compute.use_floatingip_for_ssh: + floating_ip_for_snapshot = self._create_floating_ip() + self._add_floating_ip(server_from_snapshot, + floating_ip_for_snapshot) + ip_for_snapshot = floating_ip_for_snapshot.ip + else: + ip_for_snapshot = server_from_snapshot + + # attach volume2 to instance2 + self._attach_volume(server_from_snapshot, volume_from_snapshot) + + # check the existence of the timestamp file in the volume2 + self._check_timestamp(ip_for_snapshot)