summaryrefslogtreecommitdiff
path: root/tempest/scenario/test_stamp_pattern.py
blob: f7653e78ac89aab0fe5c1df08f92565a04b97fb7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# 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.

import time

from oslo_log import log as logging
from tempest_lib.common.utils import data_utils
from tempest_lib import decorators
from tempest_lib import exceptions as lib_exc
import testtools

from tempest import config
from tempest import exceptions
from tempest.scenario import manager
from tempest import test
import tempest.test

CONF = config.CONF

LOG = logging.getLogger(__name__)


class TestStampPattern(manager.ScenarioTest):
    """
    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
    """

    @classmethod
    def skip_checks(cls):
        super(TestStampPattern, cls).skip_checks()
        if not CONF.volume_feature_enabled.snapshot:
            raise cls.skipException("Cinder volume snapshots are disabled")

    def _wait_for_volume_snapshot_status(self, volume_snapshot, status):
        self.snapshots_client.wait_for_snapshot_status(volume_snapshot['id'],
                                                       status)

    def _boot_image(self, image_id):
        security_groups = [{'name': self.security_group['name']}]
        create_kwargs = {
            'key_name': self.keypair['name'],
            'security_groups': security_groups
        }
        return self.create_server(image=image_id, create_kwargs=create_kwargs)

    def _add_keypair(self):
        self.keypair = self.create_keypair()

    def _ssh_to_server(self, server_or_ip):
        return self.get_remote_client(server_or_ip)

    def _create_volume_snapshot(self, volume):
        snapshot_name = data_utils.rand_name('scenario-snapshot-')
        _, snapshot = self.snapshots_client.create_snapshot(
            volume['id'], display_name=snapshot_name)

        def cleaner():
            self.snapshots_client.delete_snapshot(snapshot['id'])
            try:
                while self.snapshots_client.get_snapshot(snapshot['id']):
                    time.sleep(1)
            except lib_exc.NotFound:
                pass
        self.addCleanup(cleaner)
        self._wait_for_volume_status(volume, 'available')
        self.snapshots_client.wait_for_snapshot_status(snapshot['id'],
                                                       'available')
        self.assertEqual(snapshot_name, snapshot['display_name'])
        return snapshot

    def _wait_for_volume_status(self, volume, status):
        self.volumes_client.wait_for_volume_status(volume['id'], status)

    def _create_volume(self, snapshot_id=None):
        return self.create_volume(snapshot_id=snapshot_id)

    def _attach_volume(self, server, volume):
        # TODO(andreaf) we should use device from config instead if vdb
        attached_volume = self.servers_client.attach_volume(
            server['id'], volume['id'], device='/dev/vdb')
        self.assertEqual(volume['id'], attached_volume['id'])
        self._wait_for_volume_status(attached_volume, 'in-use')

    def _detach_volume(self, server, volume):
        self.servers_client.detach_volume(server['id'], volume['id'])
        self._wait_for_volume_status(volume, 'available')

    def _wait_for_volume_available_on_the_system(self, server_or_ip):
        ssh = self.get_remote_client(server_or_ip)

        def _func():
            part = ssh.get_partitions()
            LOG.debug("Partitions:%s" % part)
            return 'vdb' in part

        if not tempest.test.call_until_true(_func,
                                            CONF.compute.build_timeout,
                                            CONF.compute.build_interval):
            raise exceptions.TimeoutException

    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)

    @decorators.skip_because(bug="1205344")
    @test.idempotent_id('10fd234a-515c-41e5-b092-8323060598c5')
    @testtools.skipUnless(CONF.compute_feature_enabled.snapshot,
                          'Snapshotting is not available.')
    @tempest.test.services('compute', 'network', 'volume', 'image')
    def test_stamp_pattern(self):
        # prepare for booting a instance
        self._add_keypair()
        self.security_group = self._create_security_group()

        # boot an instance and create a timestamp file in it
        volume = self._create_volume()
        server = self._boot_image(CONF.compute.image_ref)

        # create and add floating IP to server1
        if CONF.compute.use_floatingip_for_ssh:
            floating_ip_for_server = self.create_floating_ip(server)
            ip_for_server = floating_ip_for_server['ip']
        else:
            ip_for_server = server

        self._attach_volume(server, volume)
        self._wait_for_volume_available_on_the_system(ip_for_server)
        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 = self.create_server_snapshot(server=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 CONF.compute.use_floatingip_for_ssh:
            floating_ip_for_snapshot = self.create_floating_ip(
                server_from_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)
        self._wait_for_volume_available_on_the_system(ip_for_snapshot)

        # check the existence of the timestamp file in the volume2
        self._check_timestamp(ip_for_snapshot)