ZhiQiang Fan | 39f9722 | 2013-09-20 04:49:44 +0800 | [diff] [blame] | 1 | # Copyright 2012 OpenStack Foundation |
Mate Lakat | 99ee914 | 2012-09-14 12:34:46 +0100 | [diff] [blame] | 2 | # All Rights Reserved. |
| 3 | # |
| 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may |
| 5 | # not use this file except in compliance with the License. You may obtain |
| 6 | # a copy of the License at |
| 7 | # |
| 8 | # http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | # |
| 10 | # Unless required by applicable law or agreed to in writing, software |
| 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| 13 | # License for the specific language governing permissions and limitations |
| 14 | # under the License. |
| 15 | |
Mate Lakat | 99ee914 | 2012-09-14 12:34:46 +0100 | [diff] [blame] | 16 | |
ivan-zhu | 1feeb38 | 2013-01-24 10:14:39 +0800 | [diff] [blame] | 17 | import testtools |
Matthew Treinish | a83a16e | 2012-12-07 13:44:02 -0500 | [diff] [blame] | 18 | |
Sean Dague | 1937d09 | 2013-05-17 16:36:38 -0400 | [diff] [blame] | 19 | from tempest.api.compute import base |
Ken'ichi Ohmichi | 0eb153c | 2015-07-13 02:18:25 +0000 | [diff] [blame] | 20 | from tempest.common import waiters |
Mate Lakat | 99ee914 | 2012-09-14 12:34:46 +0100 | [diff] [blame] | 21 | from tempest import config |
Yuiko Takada | e9999d6 | 2014-03-06 09:22:54 +0000 | [diff] [blame] | 22 | from tempest import test |
Mate Lakat | 99ee914 | 2012-09-14 12:34:46 +0100 | [diff] [blame] | 23 | |
Matthew Treinish | b0a78fc | 2014-01-29 16:49:12 +0000 | [diff] [blame] | 24 | CONF = config.CONF |
| 25 | |
Mate Lakat | 99ee914 | 2012-09-14 12:34:46 +0100 | [diff] [blame] | 26 | |
ivan-zhu | f2b0050 | 2013-10-18 10:06:52 +0800 | [diff] [blame] | 27 | class LiveBlockMigrationTestJSON(base.BaseV2ComputeAdminTest): |
Mate Lakat | 0ccf0eb | 2013-03-28 12:00:52 +0000 | [diff] [blame] | 28 | _host_key = 'OS-EXT-SRV-ATTR:host' |
Mate Lakat | 99ee914 | 2012-09-14 12:34:46 +0100 | [diff] [blame] | 29 | |
Mate Lakat | 99ee914 | 2012-09-14 12:34:46 +0100 | [diff] [blame] | 30 | @classmethod |
Timofey Durakov | ad7aea5 | 2015-10-12 13:37:44 +0300 | [diff] [blame] | 31 | def skip_checks(cls): |
| 32 | super(LiveBlockMigrationTestJSON, cls).skip_checks() |
| 33 | |
| 34 | if not CONF.compute_feature_enabled.live_migration: |
| 35 | skip_msg = ("%s skipped as live-migration is " |
| 36 | "not available" % cls.__name__) |
| 37 | raise cls.skipException(skip_msg) |
Jordan Pittier | f60c100 | 2015-11-16 11:24:09 +0100 | [diff] [blame] | 38 | if CONF.compute.min_compute_nodes < 2: |
Timofey Durakov | 7a04e91 | 2015-11-17 17:37:53 +0300 | [diff] [blame] | 39 | raise cls.skipException( |
Timofey Durakov | ad7aea5 | 2015-10-12 13:37:44 +0300 | [diff] [blame] | 40 | "Less than 2 compute nodes, skipping migration test.") |
| 41 | |
| 42 | @classmethod |
Rohan Kanade | 60b7309 | 2015-02-04 17:58:19 +0530 | [diff] [blame] | 43 | def setup_clients(cls): |
| 44 | super(LiveBlockMigrationTestJSON, cls).setup_clients() |
Attila Fazekas | 8e99b99 | 2013-02-24 09:53:23 +0100 | [diff] [blame] | 45 | cls.admin_hosts_client = cls.os_adm.hosts_client |
| 46 | cls.admin_servers_client = cls.os_adm.servers_client |
ghanshyam | bed8276 | 2015-07-21 16:03:11 +0900 | [diff] [blame] | 47 | cls.admin_migration_client = cls.os_adm.migrations_client |
Mate Lakat | 99ee914 | 2012-09-14 12:34:46 +0100 | [diff] [blame] | 48 | |
Timofey Durakov | ad7aea5 | 2015-10-12 13:37:44 +0300 | [diff] [blame] | 49 | @classmethod |
| 50 | def _get_compute_hostnames(cls): |
| 51 | body = cls.admin_hosts_client.list_hosts()['hosts'] |
Mate Lakat | 99ee914 | 2012-09-14 12:34:46 +0100 | [diff] [blame] | 52 | return [ |
| 53 | host_record['host_name'] |
| 54 | for host_record in body |
| 55 | if host_record['service'] == 'compute' |
| 56 | ] |
| 57 | |
| 58 | def _get_server_details(self, server_id): |
ghanshyam | 0f82525 | 2015-08-25 16:02:50 +0900 | [diff] [blame] | 59 | body = self.admin_servers_client.show_server(server_id)['server'] |
Mate Lakat | 99ee914 | 2012-09-14 12:34:46 +0100 | [diff] [blame] | 60 | return body |
| 61 | |
| 62 | def _get_host_for_server(self, server_id): |
Mate Lakat | 0ccf0eb | 2013-03-28 12:00:52 +0000 | [diff] [blame] | 63 | return self._get_server_details(server_id)[self._host_key] |
Mate Lakat | 99ee914 | 2012-09-14 12:34:46 +0100 | [diff] [blame] | 64 | |
Timofey Durakov | f358a7e | 2015-10-05 13:06:51 +0300 | [diff] [blame] | 65 | def _migrate_server_to(self, server_id, dest_host, volume_backed): |
| 66 | block_migration = (CONF.compute_feature_enabled. |
| 67 | block_migration_for_live_migration and |
| 68 | not volume_backed) |
David Kranz | ae99b9a | 2015-02-16 13:37:01 -0500 | [diff] [blame] | 69 | body = self.admin_servers_client.live_migrate_server( |
Timofey Durakov | f358a7e | 2015-10-05 13:06:51 +0300 | [diff] [blame] | 70 | server_id, host=dest_host, block_migration=block_migration, |
Ken'ichi Ohmichi | 86f5893 | 2015-08-18 04:16:15 +0000 | [diff] [blame] | 71 | disk_over_commit=False) |
Mate Lakat | 99ee914 | 2012-09-14 12:34:46 +0100 | [diff] [blame] | 72 | return body |
| 73 | |
| 74 | def _get_host_other_than(self, host): |
| 75 | for target_host in self._get_compute_hostnames(): |
| 76 | if host != target_host: |
| 77 | return target_host |
| 78 | |
Mate Lakat | 99ee914 | 2012-09-14 12:34:46 +0100 | [diff] [blame] | 79 | def _get_server_status(self, server_id): |
| 80 | return self._get_server_details(server_id)['status'] |
| 81 | |
Bob Ball | c078be9 | 2013-04-09 14:25:00 +0100 | [diff] [blame] | 82 | def _volume_clean_up(self, server_id, volume_id): |
John Warren | 6177c9e | 2015-08-19 20:00:17 +0000 | [diff] [blame] | 83 | body = self.volumes_client.show_volume(volume_id)['volume'] |
Bob Ball | c078be9 | 2013-04-09 14:25:00 +0100 | [diff] [blame] | 84 | if body['status'] == 'in-use': |
| 85 | self.servers_client.detach_volume(server_id, volume_id) |
| 86 | self.volumes_client.wait_for_volume_status(volume_id, 'available') |
| 87 | self.volumes_client.delete_volume(volume_id) |
| 88 | |
Joe Gordon | 8843f0f | 2015-03-17 15:07:34 -0700 | [diff] [blame] | 89 | def _test_live_migration(self, state='ACTIVE', volume_backed=False): |
| 90 | """Tests live migration between two hosts. |
Matt Riedemann | bb9f704 | 2015-03-03 08:53:11 -0800 | [diff] [blame] | 91 | |
| 92 | Requires CONF.compute_feature_enabled.live_migration to be True. |
| 93 | |
| 94 | :param state: The vm_state the migrated server should be in before and |
| 95 | after the live migration. Supported values are 'ACTIVE' |
| 96 | and 'PAUSED'. |
Joe Gordon | 8843f0f | 2015-03-17 15:07:34 -0700 | [diff] [blame] | 97 | :param volume_backed: If the instance is volume backed or not. If |
| 98 | volume_backed, *block* migration is not used. |
Matt Riedemann | bb9f704 | 2015-03-03 08:53:11 -0800 | [diff] [blame] | 99 | """ |
Timofey Durakov | f358a7e | 2015-10-05 13:06:51 +0300 | [diff] [blame] | 100 | # Live migrate an instance to another host |
Jordan Pittier | 599a356 | 2016-01-08 17:38:14 +0100 | [diff] [blame] | 101 | server_id = self.create_test_server(wait_until="ACTIVE", |
| 102 | volume_backed=volume_backed)['id'] |
Mate Lakat | 99ee914 | 2012-09-14 12:34:46 +0100 | [diff] [blame] | 103 | actual_host = self._get_host_for_server(server_id) |
Mate Lakat | 99ee914 | 2012-09-14 12:34:46 +0100 | [diff] [blame] | 104 | target_host = self._get_host_other_than(actual_host) |
Matt Riedemann | bb9f704 | 2015-03-03 08:53:11 -0800 | [diff] [blame] | 105 | |
| 106 | if state == 'PAUSED': |
| 107 | self.admin_servers_client.pause_server(server_id) |
Ken'ichi Ohmichi | 0eb153c | 2015-07-13 02:18:25 +0000 | [diff] [blame] | 108 | waiters.wait_for_server_status(self.admin_servers_client, |
| 109 | server_id, state) |
Matt Riedemann | bb9f704 | 2015-03-03 08:53:11 -0800 | [diff] [blame] | 110 | |
Timofey Durakov | f358a7e | 2015-10-05 13:06:51 +0300 | [diff] [blame] | 111 | self._migrate_server_to(server_id, target_host, volume_backed) |
Ken'ichi Ohmichi | 0eb153c | 2015-07-13 02:18:25 +0000 | [diff] [blame] | 112 | waiters.wait_for_server_status(self.servers_client, server_id, state) |
ghanshyam | 8a59949 | 2015-08-24 15:55:59 +0900 | [diff] [blame] | 113 | migration_list = (self.admin_migration_client.list_migrations() |
| 114 | ['migrations']) |
ghanshyam | bed8276 | 2015-07-21 16:03:11 +0900 | [diff] [blame] | 115 | |
| 116 | msg = ("Live Migration failed. Migrations list for Instance " |
| 117 | "%s: [" % server_id) |
| 118 | for live_migration in migration_list: |
| 119 | if (live_migration['instance_uuid'] == server_id): |
| 120 | msg += "\n%s" % live_migration |
| 121 | msg += "]" |
| 122 | self.assertEqual(target_host, self._get_host_for_server(server_id), |
| 123 | msg) |
Mate Lakat | 99ee914 | 2012-09-14 12:34:46 +0100 | [diff] [blame] | 124 | |
Matt Riedemann | bb9f704 | 2015-03-03 08:53:11 -0800 | [diff] [blame] | 125 | @test.idempotent_id('1dce86b8-eb04-4c03-a9d8-9c1dc3ee0c7b') |
Matt Riedemann | bb9f704 | 2015-03-03 08:53:11 -0800 | [diff] [blame] | 126 | def test_live_block_migration(self): |
Joe Gordon | 8843f0f | 2015-03-17 15:07:34 -0700 | [diff] [blame] | 127 | self._test_live_migration() |
Matt Riedemann | bb9f704 | 2015-03-03 08:53:11 -0800 | [diff] [blame] | 128 | |
| 129 | @test.idempotent_id('1e107f21-61b2-4988-8f22-b196e938ab88') |
Matt Riedemann | bb9f704 | 2015-03-03 08:53:11 -0800 | [diff] [blame] | 130 | @testtools.skipUnless(CONF.compute_feature_enabled.pause, |
| 131 | 'Pause is not available.') |
| 132 | @testtools.skipUnless(CONF.compute_feature_enabled |
| 133 | .live_migrate_paused_instances, |
| 134 | 'Live migration of paused instances is not ' |
| 135 | 'available.') |
| 136 | def test_live_block_migration_paused(self): |
Joe Gordon | 8843f0f | 2015-03-17 15:07:34 -0700 | [diff] [blame] | 137 | self._test_live_migration(state='PAUSED') |
| 138 | |
| 139 | @test.idempotent_id('5071cf17-3004-4257-ae61-73a84e28badd') |
Joe Gordon | 8843f0f | 2015-03-17 15:07:34 -0700 | [diff] [blame] | 140 | @test.services('volume') |
| 141 | def test_volume_backed_live_migration(self): |
| 142 | self._test_live_migration(volume_backed=True) |
Matt Riedemann | bb9f704 | 2015-03-03 08:53:11 -0800 | [diff] [blame] | 143 | |
Chris Hoge | 7579c1a | 2015-02-26 14:12:15 -0800 | [diff] [blame] | 144 | @test.idempotent_id('e19c0cc6-6720-4ed8-be83-b6603ed5c812') |
Timofey Durakov | ad7aea5 | 2015-10-12 13:37:44 +0300 | [diff] [blame] | 145 | @testtools.skipIf(not CONF.compute_feature_enabled. |
Matthew Treinish | d5c9602 | 2013-10-17 21:51:23 +0000 | [diff] [blame] | 146 | block_migration_for_live_migration, |
Bob Ball | c078be9 | 2013-04-09 14:25:00 +0100 | [diff] [blame] | 147 | 'Block Live migration not available') |
Matthew Treinish | d5c9602 | 2013-10-17 21:51:23 +0000 | [diff] [blame] | 148 | @testtools.skipIf(not CONF.compute_feature_enabled. |
| 149 | block_migrate_cinder_iscsi, |
Bob Ball | c078be9 | 2013-04-09 14:25:00 +0100 | [diff] [blame] | 150 | 'Block Live migration not configured for iSCSI') |
| 151 | def test_iscsi_volume(self): |
Jordan Pittier | 599a356 | 2016-01-08 17:38:14 +0100 | [diff] [blame] | 152 | server_id = self.create_test_server(wait_until="ACTIVE")['id'] |
Bob Ball | c078be9 | 2013-04-09 14:25:00 +0100 | [diff] [blame] | 153 | actual_host = self._get_host_for_server(server_id) |
| 154 | target_host = self._get_host_other_than(actual_host) |
| 155 | |
John Warren | 6177c9e | 2015-08-19 20:00:17 +0000 | [diff] [blame] | 156 | volume = self.volumes_client.create_volume( |
| 157 | display_name='test')['volume'] |
Bob Ball | c078be9 | 2013-04-09 14:25:00 +0100 | [diff] [blame] | 158 | |
| 159 | self.volumes_client.wait_for_volume_status(volume['id'], |
| 160 | 'available') |
| 161 | self.addCleanup(self._volume_clean_up, server_id, volume['id']) |
| 162 | |
| 163 | # Attach the volume to the server |
Ken'ichi Ohmichi | dfc88de | 2015-08-13 05:12:20 +0000 | [diff] [blame] | 164 | self.servers_client.attach_volume(server_id, volumeId=volume['id'], |
Bob Ball | c078be9 | 2013-04-09 14:25:00 +0100 | [diff] [blame] | 165 | device='/dev/xvdb') |
| 166 | self.volumes_client.wait_for_volume_status(volume['id'], 'in-use') |
| 167 | |
| 168 | self._migrate_server_to(server_id, target_host) |
Ken'ichi Ohmichi | 0eb153c | 2015-07-13 02:18:25 +0000 | [diff] [blame] | 169 | waiters.wait_for_server_status(self.servers_client, |
| 170 | server_id, 'ACTIVE') |
Chang Bo Guo | fc77e93 | 2013-09-16 17:38:26 -0700 | [diff] [blame] | 171 | self.assertEqual(target_host, self._get_host_for_server(server_id)) |