blob: 0ed73a8f46bfff7d088876c852e2069a1e8f37fa [file] [log] [blame]
ZhiQiang Fan39f97222013-09-20 04:49:44 +08001# Copyright 2012 OpenStack Foundation
Jay Pipes13b479b2012-06-11 14:52:27 -04002# 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
songwenping99d6e002021-01-05 03:07:46 +000016from urllib import parse as urlparse
17
Cady_Chen72014bc2016-11-16 09:43:49 +080018from oslo_log import log as logging
ivan-zhu1feeb382013-01-24 10:14:39 +080019import testtools
Jay Pipes13b479b2012-06-11 14:52:27 -040020
Sean Dague1937d092013-05-17 16:36:38 -040021from tempest.api.compute import base
ghanshyam017b5fe2016-04-15 18:49:26 +090022from tempest.common import compute
Andrea Frittolicd368412017-08-14 21:37:56 +010023from tempest.common import utils
Masayuki Igawa209fd502014-02-17 14:46:43 +090024from tempest.common.utils.linux import remote_client
Ken'ichi Ohmichi0eb153c2015-07-13 02:18:25 +000025from tempest.common import waiters
Sean Dague86bd8422013-12-20 09:56:44 -050026from tempest import config
Felipe Monteiro9ff5c282017-06-21 21:05:07 +010027from tempest.lib.common import api_version_utils
Ken'ichi Ohmichi757833a2017-03-10 10:30:30 -080028from tempest.lib.common.utils import data_utils
Andrea Frittoli (andreaf)db9672e2016-02-23 14:07:24 -050029from tempest.lib import decorators
30from tempest.lib import exceptions as lib_exc
Daryl Wallecked8bef32011-12-05 23:02:08 -060031
Sean Dague86bd8422013-12-20 09:56:44 -050032CONF = config.CONF
33
Ryan Hsu38231092014-06-08 23:12:10 -070034LOG = logging.getLogger(__name__)
35
Daryl Walleckc7251962012-03-12 17:26:54 -050036
ivan-zhuf2b00502013-10-18 10:06:52 +080037class ServerActionsTestJSON(base.BaseV2ComputeTest):
zhufl27f410a2020-08-13 15:27:59 +080038 """Test server actions"""
39
Attila Fazekas19044d52013-02-16 07:35:06 +010040 def setUp(self):
Matt Riedemann2da58592014-06-08 12:46:02 +000041 # NOTE(afazekas): Normally we use the same server with all test cases,
42 # but if it has an issue, we build a new one
Attila Fazekas19044d52013-02-16 07:35:06 +010043 super(ServerActionsTestJSON, self).setUp()
Matt Riedemann2da58592014-06-08 12:46:02 +000044 # Check if the server is in a clean state after test
45 try:
Martin Kopec78b960f2022-02-08 17:18:02 +000046 validation_resources = self.get_class_validation_resources(
47 self.os_primary)
48 # _test_rebuild_server test compares ip address attached to the
49 # server before and after the rebuild, in order to avoid
50 # a situation when a newly created server doesn't have a floating
51 # ip attached at the beginning of the test_rebuild_server let's
52 # make sure right here the floating ip is attached
53 waiters.wait_for_server_floating_ip(
54 self.client,
55 self.client.show_server(self.server_id)['server'],
56 validation_resources['floating_ip'])
Ken'ichi Ohmichi0eb153c2015-07-13 02:18:25 +000057 waiters.wait_for_server_status(self.client,
58 self.server_id, 'ACTIVE')
Viktor Tikkanen1b0ce232015-05-28 10:21:27 +030059 except lib_exc.NotFound:
60 # The server was deleted by previous test, create a new one
Andrea Frittoli9f416dd2017-08-10 15:38:00 +010061 # Use class level validation resources to avoid them being
62 # deleted once a test is over
63 validation_resources = self.get_class_validation_resources(
64 self.os_primary)
Joseph Lanouxffe09dd2015-03-18 16:45:33 +000065 server = self.create_test_server(
66 validatable=True,
Andrea Frittoli9f416dd2017-08-10 15:38:00 +010067 validation_resources=validation_resources,
Artom Lifshitz4fc47f62022-05-05 14:17:27 -040068 wait_until='SSHABLE')
Viktor Tikkanen1b0ce232015-05-28 10:21:27 +030069 self.__class__.server_id = server['id']
Matt Riedemann2da58592014-06-08 12:46:02 +000070 except Exception:
71 # Rebuild server if something happened to it during a test
zhuflba0e5532017-09-13 10:51:07 +080072 self.__class__.server_id = self.recreate_server(
Artom Lifshitz4fc47f62022-05-05 14:17:27 -040073 self.server_id, validatable=True, wait_until='SSHABLE')
Matt Riedemann2da58592014-06-08 12:46:02 +000074
75 def tearDown(self):
Matt Riedemann2da58592014-06-08 12:46:02 +000076 super(ServerActionsTestJSON, self).tearDown()
zhufle913e462018-07-25 17:16:10 +080077 # NOTE(zhufl): Because server_check_teardown will raise Exception
78 # which will prevent other cleanup steps from being executed, so
79 # server_check_teardown should be called after super's tearDown.
80 self.server_check_teardown()
Attila Fazekas305e65b2013-10-29 13:23:07 +010081
Attila Fazekas19044d52013-02-16 07:35:06 +010082 @classmethod
Joseph Lanouxffe09dd2015-03-18 16:45:33 +000083 def setup_credentials(cls):
84 cls.prepare_instance_network()
85 super(ServerActionsTestJSON, cls).setup_credentials()
86
87 @classmethod
Rohan Kanade60b73092015-02-04 17:58:19 +053088 def setup_clients(cls):
89 super(ServerActionsTestJSON, cls).setup_clients()
90 cls.client = cls.servers_client
91
92 @classmethod
Andrea Frittoli50bb80d2014-09-15 12:34:27 +010093 def resource_setup(cls):
Andrea Frittoli50bb80d2014-09-15 12:34:27 +010094 super(ServerActionsTestJSON, cls).resource_setup()
Artom Lifshitz34ea7e92022-05-24 10:48:56 -040095 cls.server_id = cls.recreate_server(None, validatable=True,
96 wait_until='SSHABLE')
Attila Fazekas19044d52013-02-16 07:35:06 +010097
Ken'ichi Ohmichi14b0ae12017-01-27 17:18:52 -080098 @decorators.idempotent_id('6158df09-4b82-4ab3-af6d-29cf36af858d')
Sean Dague86bd8422013-12-20 09:56:44 -050099 @testtools.skipUnless(CONF.compute_feature_enabled.change_password,
ivan-zhu1feeb382013-01-24 10:14:39 +0800100 'Change password not available.')
Daryl Wallecked8bef32011-12-05 23:02:08 -0600101 def test_change_server_password(self):
zhufl27f410a2020-08-13 15:27:59 +0800102 """Test changing server's password
103
104 The server's password should be set to the provided password and
105 the user can authenticate with the new password.
106 """
Emily Hugenbruch1315e182016-10-10 17:34:06 -0400107 # Since this test messes with the password and makes the
108 # server unreachable, it should create its own server
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100109 validation_resources = self.get_test_validation_resources(
110 self.os_primary)
Emily Hugenbruch1315e182016-10-10 17:34:06 -0400111 newserver = self.create_test_server(
112 validatable=True,
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100113 validation_resources=validation_resources,
Emily Hugenbruch1315e182016-10-10 17:34:06 -0400114 wait_until='ACTIVE')
zhangyangyangc248f592019-04-24 18:54:52 +0800115 self.addCleanup(self.delete_server, newserver['id'])
Sean Dague4dd2c0b2013-01-03 17:50:28 -0500116 # The server's password should be set to the provided password
Daryl Walleck98e66dd2012-06-21 04:58:39 -0500117 new_password = 'Newpass1234'
Emily Hugenbruch1315e182016-10-10 17:34:06 -0400118 self.client.change_password(newserver['id'], adminPass=new_password)
119 waiters.wait_for_server_status(self.client, newserver['id'], 'ACTIVE')
Daryl Wallecked8bef32011-12-05 23:02:08 -0600120
Joseph Lanouxffe09dd2015-03-18 16:45:33 +0000121 if CONF.validation.run_validation:
Daryl Walleck98e66dd2012-06-21 04:58:39 -0500122 # Verify that the user can authenticate with the new password
Emily Hugenbruch1315e182016-10-10 17:34:06 -0400123 server = self.client.show_server(newserver['id'])['server']
Joseph Lanouxffe09dd2015-03-18 16:45:33 +0000124 linux_client = remote_client.RemoteClient(
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100125 self.get_server_ip(server, validation_resources),
Joseph Lanouxffe09dd2015-03-18 16:45:33 +0000126 self.ssh_user,
Andrea Frittoli (andreaf)2a70a612016-04-29 16:09:13 -0500127 new_password,
128 server=server,
129 servers_client=self.client)
Attila Fazekasad7ef7d2013-11-20 10:12:53 +0100130 linux_client.validate_authentication()
Daryl Walleck98e66dd2012-06-21 04:58:39 -0500131
Ken'ichi Ohmichi84d7fbc2014-09-30 01:42:33 +0000132 def _test_reboot_server(self, reboot_type):
Joseph Lanouxffe09dd2015-03-18 16:45:33 +0000133 if CONF.validation.run_validation:
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100134 validation_resources = self.get_class_validation_resources(
135 self.os_primary)
Daryl Walleck98e66dd2012-06-21 04:58:39 -0500136 # Get the time the server was last rebooted,
ghanshyam0f825252015-08-25 16:02:50 +0900137 server = self.client.show_server(self.server_id)['server']
Joseph Lanouxffe09dd2015-03-18 16:45:33 +0000138 linux_client = remote_client.RemoteClient(
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100139 self.get_server_ip(server, validation_resources),
Joseph Lanouxffe09dd2015-03-18 16:45:33 +0000140 self.ssh_user,
141 self.password,
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100142 validation_resources['keypair']['private_key'],
Andrea Frittoli (andreaf)2a70a612016-04-29 16:09:13 -0500143 server=server,
144 servers_client=self.client)
Daryl Walleck98e66dd2012-06-21 04:58:39 -0500145 boot_time = linux_client.get_boot_time()
Daryl Walleck98e66dd2012-06-21 04:58:39 -0500146
Ken'ichi Ohmichi05ab8562016-07-12 00:06:18 -0700147 # NOTE: This sync is for avoiding the loss of pub key data
148 # in a server
149 linux_client.exec_command("sync")
150
Artom Lifshitzea2b59c2021-08-19 14:34:00 -0400151 self.reboot_server(self.server_id, type=reboot_type)
Daryl Wallecked8bef32011-12-05 23:02:08 -0600152
Joseph Lanouxffe09dd2015-03-18 16:45:33 +0000153 if CONF.validation.run_validation:
Daryl Walleck98e66dd2012-06-21 04:58:39 -0500154 # Log in and verify the boot time has changed
Joseph Lanouxffe09dd2015-03-18 16:45:33 +0000155 linux_client = remote_client.RemoteClient(
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100156 self.get_server_ip(server, validation_resources),
Joseph Lanouxffe09dd2015-03-18 16:45:33 +0000157 self.ssh_user,
158 self.password,
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100159 validation_resources['keypair']['private_key'],
Andrea Frittoli (andreaf)2a70a612016-04-29 16:09:13 -0500160 server=server,
161 servers_client=self.client)
Daryl Walleck98e66dd2012-06-21 04:58:39 -0500162 new_boot_time = linux_client.get_boot_time()
Béla Vancsics64862f72016-11-08 09:12:31 +0100163 self.assertGreater(new_boot_time, boot_time,
164 '%s > %s' % (new_boot_time, boot_time))
Daryl Walleck98e66dd2012-06-21 04:58:39 -0500165
Jordan Pittier3b46d272017-04-12 16:17:28 +0200166 @decorators.attr(type='smoke')
Ken'ichi Ohmichi14b0ae12017-01-27 17:18:52 -0800167 @decorators.idempotent_id('2cb1baf6-ac8d-4429-bf0d-ba8a0ba53e32')
Ken'ichi Ohmichi84d7fbc2014-09-30 01:42:33 +0000168 def test_reboot_server_hard(self):
zhufl27f410a2020-08-13 15:27:59 +0800169 """Test hard rebooting server
170
171 The server should be power cycled.
172 """
Ken'ichi Ohmichi84d7fbc2014-09-30 01:42:33 +0000173 self._test_reboot_server('HARD')
174
lianghaofd8d3152017-04-01 15:34:26 +0800175 @decorators.idempotent_id('1d1c9104-1b0a-11e7-a3d4-fa163e65f5ce')
176 def test_remove_server_all_security_groups(self):
zhufl27f410a2020-08-13 15:27:59 +0800177 """Test removing all security groups from server"""
lianghaofd8d3152017-04-01 15:34:26 +0800178 server = self.create_test_server(wait_until='ACTIVE')
179
180 # Remove all Security group
181 self.client.remove_security_group(
182 server['id'], name=server['security_groups'][0]['name'])
183
184 # Verify all Security group
185 server = self.client.show_server(server['id'])['server']
186 self.assertNotIn('security_groups', server)
187
Yaroslav Lobankovfb1c3642015-05-13 18:38:47 +0300188 def _rebuild_server_and_check(self, image_ref):
ghanshyam0f825252015-08-25 16:02:50 +0900189 rebuilt_server = (self.client.rebuild_server(self.server_id, image_ref)
190 ['server'])
Ken'ichi Ohmichi0eb153c2015-07-13 02:18:25 +0000191 waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
Yaroslav Lobankovfb1c3642015-05-13 18:38:47 +0300192 msg = ('Server was not rebuilt to the original image. '
193 'The original image: {0}. The current image: {1}'
194 .format(image_ref, rebuilt_server['image']['id']))
195 self.assertEqual(image_ref, rebuilt_server['image']['id'], msg)
196
zhufl01512d22017-08-03 16:30:23 +0800197 def _test_rebuild_server(self):
Castulo J. Martinez0d1b63f2016-07-08 13:55:57 -0700198 # Get the IPs the server has before rebuilding it
199 original_addresses = (self.client.show_server(self.server_id)['server']
200 ['addresses'])
Sean Dague4dd2c0b2013-01-03 17:50:28 -0500201 # The server should be rebuilt using the provided image and data
Daryl Wallecked8bef32011-12-05 23:02:08 -0600202 meta = {'rebuild': 'server'}
zhuflc6ce5392016-08-17 14:34:37 +0800203 new_name = data_utils.rand_name(self.__class__.__name__ + '-server')
Daryl Walleck98e66dd2012-06-21 04:58:39 -0500204 password = 'rebuildPassw0rd'
ghanshyam0f825252015-08-25 16:02:50 +0900205 rebuilt_server = self.client.rebuild_server(
206 self.server_id,
207 self.image_ref_alt,
208 name=new_name,
209 metadata=meta,
ghanshyam0f825252015-08-25 16:02:50 +0900210 adminPass=password)['server']
Daryl Wallecked8bef32011-12-05 23:02:08 -0600211
Andrea Frittolie8040812015-04-28 14:26:35 +0100212 # If the server was rebuilt on a different image, restore it to the
213 # original image once the test ends
214 if self.image_ref_alt != self.image_ref:
Yaroslav Lobankovfb1c3642015-05-13 18:38:47 +0300215 self.addCleanup(self._rebuild_server_and_check, self.image_ref)
Andrea Frittolie8040812015-04-28 14:26:35 +0100216
Attila Fazekasf7f34f92013-08-01 17:01:44 +0200217 # Verify the properties in the initial response are correct
Brian Waldon3bde07f2011-12-13 15:11:22 -0500218 self.assertEqual(self.server_id, rebuilt_server['id'])
Eoghan Glynn57c1a3d2012-03-01 16:50:29 -0500219 rebuilt_image_id = rebuilt_server['image']['id']
220 self.assertTrue(self.image_ref_alt.endswith(rebuilt_image_id))
zhuflbcb71172018-03-29 13:49:31 +0800221 self.assert_flavor_equal(self.flavor_ref, rebuilt_server['flavor'])
Daryl Wallecked8bef32011-12-05 23:02:08 -0600222
Attila Fazekasf7f34f92013-08-01 17:01:44 +0200223 # Verify the server properties after the rebuild completes
Ken'ichi Ohmichi0eb153c2015-07-13 02:18:25 +0000224 waiters.wait_for_server_status(self.client,
225 rebuilt_server['id'], 'ACTIVE')
ghanshyam0f825252015-08-25 16:02:50 +0900226 server = self.client.show_server(rebuilt_server['id'])['server']
Zhi Kun Liue5401762013-09-11 20:45:48 +0800227 rebuilt_image_id = server['image']['id']
Eoghan Glynn57c1a3d2012-03-01 16:50:29 -0500228 self.assertTrue(self.image_ref_alt.endswith(rebuilt_image_id))
Zhi Kun Liue5401762013-09-11 20:45:48 +0800229 self.assertEqual(new_name, server['name'])
Castulo J. Martinez0d1b63f2016-07-08 13:55:57 -0700230 self.assertEqual(original_addresses, server['addresses'])
Daryl Wallecked8bef32011-12-05 23:02:08 -0600231
Joseph Lanouxffe09dd2015-03-18 16:45:33 +0000232 if CONF.validation.run_validation:
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100233 validation_resources = self.get_class_validation_resources(
234 self.os_primary)
wangxiyuan878c50e2016-01-04 19:24:17 +0800235 # Authentication is attempted in the following order of priority:
236 # 1.The key passed in, if one was passed in.
237 # 2.Any key we can find through an SSH agent (if allowed).
238 # 3.Any "id_rsa", "id_dsa" or "id_ecdsa" key discoverable in
239 # ~/.ssh/ (if allowed).
240 # 4.Plain username/password auth, if a password was given.
Joseph Lanouxffe09dd2015-03-18 16:45:33 +0000241 linux_client = remote_client.RemoteClient(
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100242 self.get_server_ip(rebuilt_server, validation_resources),
Weronika Sikorac54a9112019-09-18 13:55:07 +0000243 self.ssh_alt_user,
wangxiyuan878c50e2016-01-04 19:24:17 +0800244 password,
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100245 validation_resources['keypair']['private_key'],
Andrea Frittoli (andreaf)2a70a612016-04-29 16:09:13 -0500246 server=rebuilt_server,
247 servers_client=self.client)
Attila Fazekasad7ef7d2013-11-20 10:12:53 +0100248 linux_client.validate_authentication()
Daryl Walleck98e66dd2012-06-21 04:58:39 -0500249
zhufl01512d22017-08-03 16:30:23 +0800250 @decorators.idempotent_id('aaa6cdf3-55a7-461a-add9-1c8596b9a07c')
251 def test_rebuild_server(self):
zhufl27f410a2020-08-13 15:27:59 +0800252 """Test rebuilding server
253
254 The server should be rebuilt using the provided image and data.
255 """
zhufl01512d22017-08-03 16:30:23 +0800256 self._test_rebuild_server()
257
Ken'ichi Ohmichi14b0ae12017-01-27 17:18:52 -0800258 @decorators.idempotent_id('30449a88-5aff-4f9b-9866-6ee9b17f906d')
Zhi Kun Liue5401762013-09-11 20:45:48 +0800259 def test_rebuild_server_in_stop_state(self):
zhufl27f410a2020-08-13 15:27:59 +0800260 """Test rebuilding server in stop state
261
262 The server in stop state should be rebuilt using the provided
263 image and remain in SHUTOFF state.
264 """
ghanshyam0f825252015-08-25 16:02:50 +0900265 server = self.client.show_server(self.server_id)['server']
Zhi Kun Liue5401762013-09-11 20:45:48 +0800266 old_image = server['image']['id']
Yaroslav Lobankovfb1c3642015-05-13 18:38:47 +0300267 new_image = (self.image_ref_alt
268 if old_image == self.image_ref else self.image_ref)
Ken'ichi Ohmichib2631082015-08-27 01:31:00 +0000269 self.client.stop_server(self.server_id)
Ken'ichi Ohmichi0eb153c2015-07-13 02:18:25 +0000270 waiters.wait_for_server_status(self.client, self.server_id, 'SHUTOFF')
ghanshyam0f825252015-08-25 16:02:50 +0900271 rebuilt_server = (self.client.rebuild_server(self.server_id, new_image)
272 ['server'])
Yaroslav Lobankovfb1c3642015-05-13 18:38:47 +0300273 # If the server was rebuilt on a different image, restore it to the
274 # original image once the test ends
275 if self.image_ref_alt != self.image_ref:
276 self.addCleanup(self._rebuild_server_and_check, old_image)
Zhi Kun Liue5401762013-09-11 20:45:48 +0800277
278 # Verify the properties in the initial response are correct
279 self.assertEqual(self.server_id, rebuilt_server['id'])
280 rebuilt_image_id = rebuilt_server['image']['id']
281 self.assertEqual(new_image, rebuilt_image_id)
zhuflbcb71172018-03-29 13:49:31 +0800282 self.assert_flavor_equal(self.flavor_ref, rebuilt_server['flavor'])
Zhi Kun Liue5401762013-09-11 20:45:48 +0800283
284 # Verify the server properties after the rebuild completes
Ken'ichi Ohmichi0eb153c2015-07-13 02:18:25 +0000285 waiters.wait_for_server_status(self.client,
286 rebuilt_server['id'], 'SHUTOFF')
ghanshyam0f825252015-08-25 16:02:50 +0900287 server = self.client.show_server(rebuilt_server['id'])['server']
Zhi Kun Liue5401762013-09-11 20:45:48 +0800288 rebuilt_image_id = server['image']['id']
289 self.assertEqual(new_image, rebuilt_image_id)
290
Ken'ichi Ohmichib2631082015-08-27 01:31:00 +0000291 self.client.start_server(self.server_id)
Attila Fazekas305e65b2013-10-29 13:23:07 +0100292
Matt Riedemannb5720532018-09-19 16:02:05 -0400293 # NOTE(mriedem): Marked as slow because while rebuild and volume-backed is
294 # common, we don't actually change the image (you can't with volume-backed
295 # rebuild) so this isn't testing much outside normal rebuild
296 # (and it's slow).
297 @decorators.attr(type='slow')
Ken'ichi Ohmichi14b0ae12017-01-27 17:18:52 -0800298 @decorators.idempotent_id('b68bd8d6-855d-4212-b59b-2e704044dace')
Andrea Frittolicd368412017-08-14 21:37:56 +0100299 @utils.services('volume')
Roman Podoliaka908f9062015-04-21 16:52:20 +0300300 def test_rebuild_server_with_volume_attached(self):
zhufl27f410a2020-08-13 15:27:59 +0800301 """Test rebuilding server with volume attached
302
303 The volume should be attached to the instance after rebuild.
304 """
Roman Podoliaka908f9062015-04-21 16:52:20 +0300305 # create a new volume and attach it to the server
Matt Riedemannf1448f02016-10-01 20:03:16 -0400306 volume = self.create_volume()
Roman Podoliaka908f9062015-04-21 16:52:20 +0300307
Matt Riedemannf1448f02016-10-01 20:03:16 -0400308 server = self.client.show_server(self.server_id)['server']
309 self.attach_volume(server, volume)
Roman Podoliaka908f9062015-04-21 16:52:20 +0300310
311 # run general rebuild test
zhufl01512d22017-08-03 16:30:23 +0800312 self._test_rebuild_server()
Roman Podoliaka908f9062015-04-21 16:52:20 +0300313
314 # make sure the volume is attached to the instance after rebuild
315 vol_after_rebuild = self.volumes_client.show_volume(volume['id'])
316 vol_after_rebuild = vol_after_rebuild['volume']
317 self.assertEqual('in-use', vol_after_rebuild['status'])
318 self.assertEqual(self.server_id,
319 vol_after_rebuild['attachments'][0]['server_id'])
afazekas5d066232019-03-25 18:35:36 +0100320 if CONF.validation.run_validation:
321 validation_resources = self.get_class_validation_resources(
322 self.os_primary)
323 linux_client = remote_client.RemoteClient(
324 self.get_server_ip(server, validation_resources),
Weronika Sikorac54a9112019-09-18 13:55:07 +0000325 self.ssh_alt_user,
afazekas5d066232019-03-25 18:35:36 +0100326 password=None,
327 pkey=validation_resources['keypair']['private_key'],
328 server=server,
329 servers_client=self.client)
330 linux_client.validate_authentication()
Roman Podoliaka908f9062015-04-21 16:52:20 +0300331
Matt Riedemannced8d3c2017-11-01 11:39:11 -0400332 def _test_resize_server_confirm(self, server_id, stop=False):
Sean Dague4dd2c0b2013-01-03 17:50:28 -0500333 # The server's RAM and disk space should be modified to that of
334 # the provided flavor
Daryl Wallecked8bef32011-12-05 23:02:08 -0600335
Matt Riedemann9fd63b82014-04-14 09:33:05 -0700336 if stop:
Matt Riedemannced8d3c2017-11-01 11:39:11 -0400337 self.client.stop_server(server_id)
338 waiters.wait_for_server_status(self.client, server_id,
Ken'ichi Ohmichi0eb153c2015-07-13 02:18:25 +0000339 'SHUTOFF')
Matt Riedemann9fd63b82014-04-14 09:33:05 -0700340
Matt Riedemannced8d3c2017-11-01 11:39:11 -0400341 self.client.resize_server(server_id, self.flavor_ref_alt)
zhufl045d1f52016-08-05 15:06:35 +0800342 # NOTE(jlk): Explicitly delete the server to get a new one for later
343 # tests. Avoids resize down race issues.
Matt Riedemannced8d3c2017-11-01 11:39:11 -0400344 self.addCleanup(self.delete_server, server_id)
345 waiters.wait_for_server_status(self.client, server_id,
Ken'ichi Ohmichi0eb153c2015-07-13 02:18:25 +0000346 'VERIFY_RESIZE')
Daryl Wallecked8bef32011-12-05 23:02:08 -0600347
Matt Riedemannced8d3c2017-11-01 11:39:11 -0400348 self.client.confirm_resize_server(server_id)
Matt Riedemann9fd63b82014-04-14 09:33:05 -0700349 expected_status = 'SHUTOFF' if stop else 'ACTIVE'
Matt Riedemannced8d3c2017-11-01 11:39:11 -0400350 waiters.wait_for_server_status(self.client, server_id,
Ken'ichi Ohmichi0eb153c2015-07-13 02:18:25 +0000351 expected_status)
Daryl Wallecked8bef32011-12-05 23:02:08 -0600352
Matt Riedemannced8d3c2017-11-01 11:39:11 -0400353 server = self.client.show_server(server_id)['server']
zhuflbcb71172018-03-29 13:49:31 +0800354 self.assert_flavor_equal(self.flavor_ref_alt, server['flavor'])
Daryl Wallecked8bef32011-12-05 23:02:08 -0600355
Matt Riedemann9fd63b82014-04-14 09:33:05 -0700356 if stop:
357 # NOTE(mriedem): tearDown requires the server to be started.
Matt Riedemannced8d3c2017-11-01 11:39:11 -0400358 self.client.start_server(server_id)
Matt Riedemann9fd63b82014-04-14 09:33:05 -0700359
Ken'ichi Ohmichi14b0ae12017-01-27 17:18:52 -0800360 @decorators.idempotent_id('1499262a-9328-4eda-9068-db1ac57498d2')
Matt Riedemann9fd63b82014-04-14 09:33:05 -0700361 @testtools.skipUnless(CONF.compute_feature_enabled.resize,
362 'Resize not available.')
Matt Riedemann9fd63b82014-04-14 09:33:05 -0700363 def test_resize_server_confirm(self):
zhufl27f410a2020-08-13 15:27:59 +0800364 """Test resizing server and then confirming"""
Matt Riedemannced8d3c2017-11-01 11:39:11 -0400365 self._test_resize_server_confirm(self.server_id, stop=False)
Matt Riedemann9fd63b82014-04-14 09:33:05 -0700366
Matt Riedemann1df75ee2017-10-30 12:52:51 -0400367 @decorators.idempotent_id('e6c28180-7454-4b59-b188-0257af08a63b')
368 @decorators.related_bug('1728603')
369 @testtools.skipUnless(CONF.compute_feature_enabled.resize,
370 'Resize not available.')
371 @utils.services('volume')
372 def test_resize_volume_backed_server_confirm(self):
zhufl27f410a2020-08-13 15:27:59 +0800373 """Test resizing a volume backed server and then confirming"""
Matt Riedemann1df75ee2017-10-30 12:52:51 -0400374 # We have to create a new server that is volume-backed since the one
375 # from setUp is not volume-backed.
Weronika Sikora9e3cc272020-02-10 10:50:53 +0000376 kwargs = {'volume_backed': True,
377 'wait_until': 'ACTIVE'}
378 if CONF.validation.run_validation:
379 validation_resources = self.get_test_validation_resources(
380 self.os_primary)
381 kwargs.update({'validatable': True,
382 'validation_resources': validation_resources})
383 server = self.create_test_server(**kwargs)
384
Mark Goddardfa30d2f2019-09-02 14:41:02 +0100385 # NOTE(mgoddard): Get detailed server to ensure addresses are present
386 # in fixed IP case.
387 server = self.servers_client.show_server(server['id'])['server']
Weronika Sikora9e3cc272020-02-10 10:50:53 +0000388
Matt Riedemann1df75ee2017-10-30 12:52:51 -0400389 self._test_resize_server_confirm(server['id'])
Weronika Sikora9e3cc272020-02-10 10:50:53 +0000390
Evgeny Antyshevcc400912017-11-16 13:36:14 +0000391 if CONF.compute_feature_enabled.console_output:
392 # Now do something interactive with the guest like get its console
393 # output; we don't actually care about the output,
394 # just that it doesn't raise an error.
395 self.client.get_console_output(server['id'])
396 if CONF.validation.run_validation:
Evgeny Antyshevcc400912017-11-16 13:36:14 +0000397 linux_client = remote_client.RemoteClient(
398 self.get_server_ip(server, validation_resources),
399 self.ssh_user,
400 password=None,
401 pkey=validation_resources['keypair']['private_key'],
402 server=server,
403 servers_client=self.client)
404 linux_client.validate_authentication()
Matt Riedemann1df75ee2017-10-30 12:52:51 -0400405
Ken'ichi Ohmichi14b0ae12017-01-27 17:18:52 -0800406 @decorators.idempotent_id('138b131d-66df-48c9-a171-64f45eb92962')
Matt Riedemann9fd63b82014-04-14 09:33:05 -0700407 @testtools.skipUnless(CONF.compute_feature_enabled.resize,
408 'Resize not available.')
Matt Riedemann9fd63b82014-04-14 09:33:05 -0700409 def test_resize_server_confirm_from_stopped(self):
zhufl27f410a2020-08-13 15:27:59 +0800410 """Test resizing a stopped server and then confirming"""
Matt Riedemannced8d3c2017-11-01 11:39:11 -0400411 self._test_resize_server_confirm(self.server_id, stop=True)
Matt Riedemann9fd63b82014-04-14 09:33:05 -0700412
Ken'ichi Ohmichi14b0ae12017-01-27 17:18:52 -0800413 @decorators.idempotent_id('c03aab19-adb1-44f5-917d-c419577e9e68')
Matt Riedemann5d1f8b12014-03-24 09:12:53 -0700414 @testtools.skipUnless(CONF.compute_feature_enabled.resize,
415 'Resize not available.')
Daryl Wallecked8bef32011-12-05 23:02:08 -0600416 def test_resize_server_revert(self):
zhufl27f410a2020-08-13 15:27:59 +0800417 """Test resizing server and then reverting
418
419 The server's RAM and disk space should return to its original
420 values after a resize is reverted.
421 """
Daryl Wallecked8bef32011-12-05 23:02:08 -0600422
Ken'ichi Ohmichi5271b0f2015-08-10 07:53:27 +0000423 self.client.resize_server(self.server_id, self.flavor_ref_alt)
zhufl045d1f52016-08-05 15:06:35 +0800424 # NOTE(zhufl): Explicitly delete the server to get a new one for later
425 # tests. Avoids resize down race issues.
426 self.addCleanup(self.delete_server, self.server_id)
Ken'ichi Ohmichi0eb153c2015-07-13 02:18:25 +0000427 waiters.wait_for_server_status(self.client, self.server_id,
428 'VERIFY_RESIZE')
Daryl Wallecked8bef32011-12-05 23:02:08 -0600429
Ken'ichi Ohmichib2631082015-08-27 01:31:00 +0000430 self.client.revert_resize_server(self.server_id)
Ken'ichi Ohmichi0eb153c2015-07-13 02:18:25 +0000431 waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
Daryl Wallecked8bef32011-12-05 23:02:08 -0600432
ghanshyam0f825252015-08-25 16:02:50 +0900433 server = self.client.show_server(self.server_id)['server']
zhuflbcb71172018-03-29 13:49:31 +0800434 self.assert_flavor_equal(self.flavor_ref, server['flavor'])
sapan-konaf1e3f002011-12-22 23:18:44 +0530435
Matt Riedemann01ff7c62017-12-12 10:46:57 -0500436 @decorators.idempotent_id('fbbf075f-a812-4022-bc5c-ccb8047eef12')
ghanshyame027dd32018-07-03 05:44:27 +0000437 @decorators.related_bug('1737599')
Matt Riedemann01ff7c62017-12-12 10:46:57 -0500438 @testtools.skipUnless(CONF.compute_feature_enabled.resize,
439 'Resize not available.')
440 @utils.services('volume')
441 def test_resize_server_revert_with_volume_attached(self):
zhufl27f410a2020-08-13 15:27:59 +0800442 """Test resizing a volume attached server and then reverting
443
444 Tests attaching a volume to a server instance and then resizing
445 the instance. Once the instance is resized, revert the resize which
446 should move the instance and volume attachment back to the original
447 compute host.
448 """
Matt Riedemann01ff7c62017-12-12 10:46:57 -0500449
450 # Create a blank volume and attach it to the server created in setUp.
451 volume = self.create_volume()
452 server = self.client.show_server(self.server_id)['server']
453 self.attach_volume(server, volume)
454 # Now resize the server with the blank volume attached.
455 self.client.resize_server(self.server_id, self.flavor_ref_alt)
456 # Explicitly delete the server to get a new one for later
457 # tests. Avoids resize down race issues.
458 self.addCleanup(self.delete_server, self.server_id)
459 waiters.wait_for_server_status(
460 self.client, self.server_id, 'VERIFY_RESIZE')
461 # Now revert the resize which should move the instance and it's volume
462 # attachment back to the original source compute host.
463 self.client.revert_resize_server(self.server_id)
464 waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
465 # Make sure everything still looks OK.
466 server = self.client.show_server(self.server_id)['server']
zhufl83f524a2019-06-26 17:26:13 +0800467 self.assert_flavor_equal(self.flavor_ref, server['flavor'])
Matt Riedemann01ff7c62017-12-12 10:46:57 -0500468 attached_volumes = server['os-extended-volumes:volumes_attached']
469 self.assertEqual(1, len(attached_volumes))
470 self.assertEqual(volume['id'], attached_volumes[0]['id'])
471
Ken'ichi Ohmichi14b0ae12017-01-27 17:18:52 -0800472 @decorators.idempotent_id('b963d4f1-94b3-4c40-9e97-7b583f46e470')
Adam Gandelmanfbc95ac2014-06-19 17:33:43 -0700473 @testtools.skipUnless(CONF.compute_feature_enabled.snapshot,
474 'Snapshotting not available, backup not possible.')
Andrea Frittolicd368412017-08-14 21:37:56 +0100475 @utils.services('image')
ivan-zhuccc89462013-10-31 16:53:12 +0800476 def test_create_backup(self):
zhufl27f410a2020-08-13 15:27:59 +0800477 """Test creating server backup
478
479 1. create server backup1 with rotation=2, there are 1 backup.
480 2. create server backup2 with rotation=2, there are 2 backups.
481 3. create server backup3, due to the rotation is 2, the first one
482 (backup1) will be deleted, so now there are still 2 backups.
483 """
484
ivan-zhuccc89462013-10-31 16:53:12 +0800485 # create the first and the second backup
Matt Riedemann2aa19d42016-06-06 17:45:41 -0400486
487 # Check if glance v1 is available to determine which client to use. We
488 # prefer glance v1 for the compute API tests since the compute image
489 # API proxy was written for glance v1.
490 if CONF.image_feature_enabled.api_v1:
Jordan Pittier8160d312017-04-18 11:52:23 +0200491 glance_client = self.os_primary.image_client
Matt Riedemann2aa19d42016-06-06 17:45:41 -0400492 elif CONF.image_feature_enabled.api_v2:
Jordan Pittier8160d312017-04-18 11:52:23 +0200493 glance_client = self.os_primary.image_client_v2
Matt Riedemann2aa19d42016-06-06 17:45:41 -0400494 else:
Matthew Treinish4217a702016-10-07 17:27:11 -0400495 raise lib_exc.InvalidConfiguration(
Matt Riedemann2aa19d42016-06-06 17:45:41 -0400496 'Either api_v1 or api_v2 must be True in '
497 '[image-feature-enabled].')
498
Matt Riedemanne699f822014-01-24 08:11:42 -0800499 backup1 = data_utils.rand_name('backup-1')
Ken'ichi Ohmichi32752ff2015-07-13 04:33:23 +0000500 resp = self.client.create_backup(self.server_id,
Ken'ichi Ohmichie6349f32015-12-09 06:47:54 +0000501 backup_type='daily',
502 rotation=2,
zhufl2856ad52018-03-29 11:06:34 +0800503 name=backup1)
ivan-zhuccc89462013-10-31 16:53:12 +0800504 oldest_backup_exist = True
505
506 # the oldest one should be deleted automatically in this test
507 def _clean_oldest_backup(oldest_backup):
508 if oldest_backup_exist:
Ryan Hsu38231092014-06-08 23:12:10 -0700509 try:
Matt Riedemann2aa19d42016-06-06 17:45:41 -0400510 glance_client.delete_image(oldest_backup)
Masayuki Igawabfa07602015-01-20 18:47:17 +0900511 except lib_exc.NotFound:
Ryan Hsu38231092014-06-08 23:12:10 -0700512 pass
513 else:
514 LOG.warning("Deletion of oldest backup %s should not have "
515 "been successful as it should have been "
Jordan Pittier525ec712016-12-07 17:51:26 +0100516 "deleted during rotation.", oldest_backup)
ivan-zhuccc89462013-10-31 16:53:12 +0800517
Felipe Monteiro9ff5c282017-06-21 21:05:07 +0100518 if api_version_utils.compare_version_header_to_response(
zhufl2856ad52018-03-29 11:06:34 +0800519 "OpenStack-API-Version", "compute 2.45", resp.response, "lt"):
Felipe Monteiro9ff5c282017-06-21 21:05:07 +0100520 image1_id = resp['image_id']
521 else:
zhufl2856ad52018-03-29 11:06:34 +0800522 image1_id = data_utils.parse_image_id(resp.response['location'])
ivan-zhuccc89462013-10-31 16:53:12 +0800523 self.addCleanup(_clean_oldest_backup, image1_id)
Matt Riedemann2aa19d42016-06-06 17:45:41 -0400524 waiters.wait_for_image_status(glance_client,
Yaroslav Lobankov2fea4052016-04-19 15:05:57 +0300525 image1_id, 'active')
ivan-zhuccc89462013-10-31 16:53:12 +0800526
Matt Riedemanne699f822014-01-24 08:11:42 -0800527 backup2 = data_utils.rand_name('backup-2')
Ken'ichi Ohmichi32752ff2015-07-13 04:33:23 +0000528 waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
529 resp = self.client.create_backup(self.server_id,
Ken'ichi Ohmichie6349f32015-12-09 06:47:54 +0000530 backup_type='daily',
531 rotation=2,
zhufl2856ad52018-03-29 11:06:34 +0800532 name=backup2)
Felipe Monteiro9ff5c282017-06-21 21:05:07 +0100533 if api_version_utils.compare_version_header_to_response(
zhufl2856ad52018-03-29 11:06:34 +0800534 "OpenStack-API-Version", "compute 2.45", resp.response, "lt"):
Felipe Monteiro9ff5c282017-06-21 21:05:07 +0100535 image2_id = resp['image_id']
536 else:
zhufl2856ad52018-03-29 11:06:34 +0800537 image2_id = data_utils.parse_image_id(resp.response['location'])
Matt Riedemann2aa19d42016-06-06 17:45:41 -0400538 self.addCleanup(glance_client.delete_image, image2_id)
539 waiters.wait_for_image_status(glance_client,
Yaroslav Lobankov2fea4052016-04-19 15:05:57 +0300540 image2_id, 'active')
ivan-zhuccc89462013-10-31 16:53:12 +0800541
542 # verify they have been created
543 properties = {
544 'image_type': 'backup',
545 'backup_type': "daily",
546 'instance_uuid': self.server_id,
547 }
Ken'ichi Ohmichi45d7d422016-06-22 10:03:28 -0700548 params = {
549 'status': 'active',
550 'sort_key': 'created_at',
551 'sort_dir': 'asc'
552 }
Matt Riedemann2aa19d42016-06-06 17:45:41 -0400553 if CONF.image_feature_enabled.api_v1:
Ken'ichi Ohmichie28b2c22016-06-22 10:07:27 -0700554 for key, value in properties.items():
555 params['property-%s' % key] = value
Matt Riedemann2aa19d42016-06-06 17:45:41 -0400556 image_list = glance_client.list_images(
557 detail=True,
558 **params)['images']
559 else:
560 # Additional properties are flattened in glance v2.
Matt Riedemann2aa19d42016-06-06 17:45:41 -0400561 params.update(properties)
562 image_list = glance_client.list_images(params)['images']
563
ivan-zhuccc89462013-10-31 16:53:12 +0800564 self.assertEqual(2, len(image_list))
565 self.assertEqual((backup1, backup2),
566 (image_list[0]['name'], image_list[1]['name']))
567
568 # create the third one, due to the rotation is 2,
569 # the first one will be deleted
Matt Riedemanne699f822014-01-24 08:11:42 -0800570 backup3 = data_utils.rand_name('backup-3')
Ken'ichi Ohmichi32752ff2015-07-13 04:33:23 +0000571 waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
572 resp = self.client.create_backup(self.server_id,
Ken'ichi Ohmichie6349f32015-12-09 06:47:54 +0000573 backup_type='daily',
574 rotation=2,
zhufl2856ad52018-03-29 11:06:34 +0800575 name=backup3)
Felipe Monteiro9ff5c282017-06-21 21:05:07 +0100576 if api_version_utils.compare_version_header_to_response(
zhufl2856ad52018-03-29 11:06:34 +0800577 "OpenStack-API-Version", "compute 2.45", resp.response, "lt"):
Felipe Monteiro9ff5c282017-06-21 21:05:07 +0100578 image3_id = resp['image_id']
579 else:
zhufl2856ad52018-03-29 11:06:34 +0800580 image3_id = data_utils.parse_image_id(resp.response['location'])
Matt Riedemann2aa19d42016-06-06 17:45:41 -0400581 self.addCleanup(glance_client.delete_image, image3_id)
ivan-zhuccc89462013-10-31 16:53:12 +0800582 # the first back up should be deleted
Ken'ichi Ohmichi32752ff2015-07-13 04:33:23 +0000583 waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
Matt Riedemann2aa19d42016-06-06 17:45:41 -0400584 glance_client.wait_for_resource_deletion(image1_id)
ivan-zhuccc89462013-10-31 16:53:12 +0800585 oldest_backup_exist = False
Matt Riedemann2aa19d42016-06-06 17:45:41 -0400586 if CONF.image_feature_enabled.api_v1:
587 image_list = glance_client.list_images(
588 detail=True, **params)['images']
589 else:
590 image_list = glance_client.list_images(params)['images']
Matt Riedemanne699f822014-01-24 08:11:42 -0800591 self.assertEqual(2, len(image_list),
592 'Unexpected number of images for '
593 'v2:test_create_backup; was the oldest backup not '
594 'yet deleted? Image list: %s' %
595 [image['name'] for image in image_list])
ivan-zhuccc89462013-10-31 16:53:12 +0800596 self.assertEqual((backup2, backup3),
597 (image_list[0]['name'], image_list[1]['name']))
598
Ken'ichi Ohmichi547a3062013-12-02 09:30:36 +0900599 def _get_output(self):
Ken'ichi Ohmichi32752ff2015-07-13 04:33:23 +0000600 output = self.client.get_console_output(
zhufl15140ee2018-07-25 16:26:21 +0800601 self.server_id, length=3)['output']
Ken'ichi Ohmichi547a3062013-12-02 09:30:36 +0900602 self.assertTrue(output, "Console output was empty.")
603 lines = len(output.split('\n'))
zhufl15140ee2018-07-25 16:26:21 +0800604 self.assertEqual(lines, 3)
Ken'ichi Ohmichi547a3062013-12-02 09:30:36 +0900605
Ken'ichi Ohmichi14b0ae12017-01-27 17:18:52 -0800606 @decorators.idempotent_id('4b8867e6-fffa-4d54-b1d1-6fdda57be2f3')
Adam Gandelmanc6eefb42014-07-15 16:44:08 -0700607 @testtools.skipUnless(CONF.compute_feature_enabled.console_output,
608 'Console output not supported.')
Attila Fazekas45c3fbc2013-02-24 16:39:52 +0100609 def test_get_console_output(self):
zhufl27f410a2020-08-13 15:27:59 +0800610 """Test getting console output for a server
611
612 Should be able to GET the console output for a given server_id and
613 number of lines.
614 """
Ken'ichi Ohmichi851a1352013-11-26 18:42:52 +0900615
616 # This reboot is necessary for outputting some console log after
Takashi NATSUME6d5a2b42015-09-08 11:27:49 +0900617 # creating an instance backup. If an instance backup, the console
Ken'ichi Ohmichi851a1352013-11-26 18:42:52 +0900618 # log file is truncated and we cannot get any console log through
619 # "console-log" API.
620 # The detail is https://bugs.launchpad.net/nova/+bug/1251920
Artom Lifshitzea2b59c2021-08-19 14:34:00 -0400621 self.reboot_server(self.server_id, type='HARD')
Ken'ichi Ohmichi547a3062013-12-02 09:30:36 +0900622 self.wait_for(self._get_output)
Attila Fazekas45c3fbc2013-02-24 16:39:52 +0100623
Ken'ichi Ohmichi14b0ae12017-01-27 17:18:52 -0800624 @decorators.idempotent_id('89104062-69d8-4b19-a71b-f47b7af093d7')
Adam Gandelmanc6eefb42014-07-15 16:44:08 -0700625 @testtools.skipUnless(CONF.compute_feature_enabled.console_output,
626 'Console output not supported.')
Ken'ichi Ohmichibd5df122014-09-18 08:03:52 +0000627 def test_get_console_output_with_unlimited_size(self):
zhufl27f410a2020-08-13 15:27:59 +0800628 """Test getting server's console output with unlimited size
629
630 The console output lines length should be bigger than the one
631 of test_get_console_output.
632 """
David Kranz0fb14292015-02-11 15:55:20 -0500633 server = self.create_test_server(wait_until='ACTIVE')
Ken'ichi Ohmichibd5df122014-09-18 08:03:52 +0000634
635 def _check_full_length_console_log():
Ken'ichi Ohmichibf4766a2015-12-09 07:48:43 +0000636 output = self.client.get_console_output(server['id'])['output']
Ken'ichi Ohmichibd5df122014-09-18 08:03:52 +0000637 self.assertTrue(output, "Console output was empty.")
638 lines = len(output.split('\n'))
639
640 # NOTE: This test tries to get full length console log, and the
641 # length should be bigger than the one of test_get_console_output.
zhufl15140ee2018-07-25 16:26:21 +0800642 self.assertGreater(lines, 3, "Cannot get enough console log "
643 "length. (lines: %s)" % lines)
Ken'ichi Ohmichibd5df122014-09-18 08:03:52 +0000644
645 self.wait_for(_check_full_length_console_log)
646
Ken'ichi Ohmichi14b0ae12017-01-27 17:18:52 -0800647 @decorators.idempotent_id('5b65d4e7-4ecd-437c-83c0-d6b79d927568')
Ken'ichi Ohmichibd5df122014-09-18 08:03:52 +0000648 @testtools.skipUnless(CONF.compute_feature_enabled.console_output,
649 'Console output not supported.')
Ken'ichi Ohmichi547a3062013-12-02 09:30:36 +0900650 def test_get_console_output_server_id_in_shutoff_status(self):
zhufl27f410a2020-08-13 15:27:59 +0800651 """Test getting console output for a server in SHUTOFF status
652
653 Should be able to GET the console output for a given server_id
654 in SHUTOFF status.
655 """
Ken'ichi Ohmichi547a3062013-12-02 09:30:36 +0900656
657 # NOTE: SHUTOFF is irregular status. To avoid test instability,
658 # one server is created only for this test without using
Ken'ichi Ohmichi4d8ba232017-03-03 18:28:05 -0800659 # the server that was created in setUpClass.
David Kranz0fb14292015-02-11 15:55:20 -0500660 server = self.create_test_server(wait_until='ACTIVE')
Ken'ichi Ohmichi547a3062013-12-02 09:30:36 +0900661 temp_server_id = server['id']
662
Ken'ichi Ohmichib2631082015-08-27 01:31:00 +0000663 self.client.stop_server(temp_server_id)
Ken'ichi Ohmichi32752ff2015-07-13 04:33:23 +0000664 waiters.wait_for_server_status(self.client, temp_server_id, 'SHUTOFF')
Ken'ichi Ohmichi547a3062013-12-02 09:30:36 +0900665 self.wait_for(self._get_output)
Dan Smithbc3bd242012-08-14 09:48:48 -0700666
Ken'ichi Ohmichi14b0ae12017-01-27 17:18:52 -0800667 @decorators.idempotent_id('bd61a9fd-062f-4670-972b-2d6c3e3b9e73')
Matt Riedemann992162e2014-03-24 09:11:06 -0700668 @testtools.skipUnless(CONF.compute_feature_enabled.pause,
669 'Pause is not available.')
Prem Karat6631f802013-07-04 12:07:33 +0530670 def test_pause_unpause_server(self):
zhufl27f410a2020-08-13 15:27:59 +0800671 """Test pausing and unpausing server"""
David Kranzae99b9a2015-02-16 13:37:01 -0500672 self.client.pause_server(self.server_id)
Ken'ichi Ohmichi0eb153c2015-07-13 02:18:25 +0000673 waiters.wait_for_server_status(self.client, self.server_id, 'PAUSED')
David Kranzae99b9a2015-02-16 13:37:01 -0500674 self.client.unpause_server(self.server_id)
Ken'ichi Ohmichi0eb153c2015-07-13 02:18:25 +0000675 waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
Prem Karat6631f802013-07-04 12:07:33 +0530676
Ken'ichi Ohmichi14b0ae12017-01-27 17:18:52 -0800677 @decorators.idempotent_id('0d8ee21e-b749-462d-83da-b85b41c86c7f')
Matt Riedemannf0cf6952014-03-24 09:08:52 -0700678 @testtools.skipUnless(CONF.compute_feature_enabled.suspend,
679 'Suspend is not available.')
Prem Karat6631f802013-07-04 12:07:33 +0530680 def test_suspend_resume_server(self):
zhufl27f410a2020-08-13 15:27:59 +0800681 """Test suspending and resuming server"""
David Kranzae99b9a2015-02-16 13:37:01 -0500682 self.client.suspend_server(self.server_id)
Ken'ichi Ohmichi0eb153c2015-07-13 02:18:25 +0000683 waiters.wait_for_server_status(self.client, self.server_id,
684 'SUSPENDED')
David Kranzae99b9a2015-02-16 13:37:01 -0500685 self.client.resume_server(self.server_id)
Ken'ichi Ohmichi0eb153c2015-07-13 02:18:25 +0000686 waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
Prem Karat6631f802013-07-04 12:07:33 +0530687
Ken'ichi Ohmichi14b0ae12017-01-27 17:18:52 -0800688 @decorators.idempotent_id('77eba8e0-036e-4635-944b-f7a8f3b78dc9')
David Shrewsbury25f666f2014-07-22 12:17:59 -0400689 @testtools.skipUnless(CONF.compute_feature_enabled.shelve,
690 'Shelve is not available.')
Andrea Frittolicd368412017-08-14 21:37:56 +0100691 @utils.services('image')
Ken'ichi Ohmichi39437e22013-10-06 00:21:38 +0900692 def test_shelve_unshelve_server(self):
zhufl27f410a2020-08-13 15:27:59 +0800693 """Test shelving and unshelving server"""
ghanshyam43a40652017-06-27 11:23:27 +0300694 if CONF.image_feature_enabled.api_v2:
695 glance_client = self.os_primary.image_client_v2
696 elif CONF.image_feature_enabled.api_v1:
697 glance_client = self.os_primary.image_client
698 else:
699 raise lib_exc.InvalidConfiguration(
700 'Either api_v1 or api_v2 must be True in '
701 '[image-feature-enabled].')
ghanshyam017b5fe2016-04-15 18:49:26 +0900702 compute.shelve_server(self.client, self.server_id,
703 force_shelve_offload=True)
Ken'ichi Ohmichi17b7f112014-02-20 06:33:49 +0900704
zhuflaa270032017-11-27 15:26:49 +0800705 def _unshelve_server():
706 server_info = self.client.show_server(self.server_id)['server']
707 if 'SHELVED' in server_info['status']:
708 self.client.unshelve_server(self.server_id)
zhufl8c9d4362018-04-03 15:45:50 +0800709 self.addCleanup(_unshelve_server)
zhuflaa270032017-11-27 15:26:49 +0800710
ghanshyam0f825252015-08-25 16:02:50 +0900711 server = self.client.show_server(self.server_id)['server']
Ken'ichi Ohmichi39437e22013-10-06 00:21:38 +0900712 image_name = server['name'] + '-shelved'
713 params = {'name': image_name}
ghanshyam43a40652017-06-27 11:23:27 +0300714 if CONF.image_feature_enabled.api_v2:
715 images = glance_client.list_images(params)['images']
716 elif CONF.image_feature_enabled.api_v1:
717 images = glance_client.list_images(
718 detail=True, **params)['images']
Ken'ichi Ohmichi39437e22013-10-06 00:21:38 +0900719 self.assertEqual(1, len(images))
720 self.assertEqual(image_name, images[0]['name'])
721
David Kranzae99b9a2015-02-16 13:37:01 -0500722 self.client.unshelve_server(self.server_id)
Ken'ichi Ohmichi0eb153c2015-07-13 02:18:25 +0000723 waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
ghanshyam43a40652017-06-27 11:23:27 +0300724 glance_client.wait_for_resource_deletion(images[0]['id'])
rsritesh8fdfb1c2017-05-08 11:14:00 +0530725
ghanshyama90ade02018-04-25 08:16:08 +0000726 @decorators.idempotent_id('8cf9f450-a871-42cf-9bef-77eba189c0b0')
727 @decorators.related_bug('1745529')
728 @testtools.skipUnless(CONF.compute_feature_enabled.shelve,
729 'Shelve is not available.')
730 @testtools.skipUnless(CONF.compute_feature_enabled.pause,
731 'Pause is not available.')
732 def test_shelve_paused_server(self):
zhufl27f410a2020-08-13 15:27:59 +0800733 """Test shelving a paused server"""
ghanshyama90ade02018-04-25 08:16:08 +0000734 server = self.create_test_server(wait_until='ACTIVE')
735 self.client.pause_server(server['id'])
736 waiters.wait_for_server_status(self.client, server['id'], 'PAUSED')
737 # Check if Shelve operation is successful on paused server.
738 compute.shelve_server(self.client, server['id'],
739 force_shelve_offload=True)
740
Ken'ichi Ohmichi14b0ae12017-01-27 17:18:52 -0800741 @decorators.idempotent_id('af8eafd4-38a7-4a4b-bdbc-75145a580560')
Anju Tiwariaf98d222013-08-05 15:19:50 +0530742 def test_stop_start_server(self):
zhufl27f410a2020-08-13 15:27:59 +0800743 """Test stopping and starting server"""
Ken'ichi Ohmichib2631082015-08-27 01:31:00 +0000744 self.client.stop_server(self.server_id)
Ken'ichi Ohmichi32752ff2015-07-13 04:33:23 +0000745 waiters.wait_for_server_status(self.client, self.server_id, 'SHUTOFF')
Ken'ichi Ohmichib2631082015-08-27 01:31:00 +0000746 self.client.start_server(self.server_id)
Ken'ichi Ohmichi32752ff2015-07-13 04:33:23 +0000747 waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
Anju Tiwariaf98d222013-08-05 15:19:50 +0530748
Ken'ichi Ohmichi14b0ae12017-01-27 17:18:52 -0800749 @decorators.idempotent_id('80a8094c-211e-440a-ab88-9e59d556c7ee')
Zhu Zhu9643e512013-09-23 09:13:07 -0500750 def test_lock_unlock_server(self):
zhufl27f410a2020-08-13 15:27:59 +0800751 """Test locking and unlocking server
752
753 Lock the server, and trying to stop it will fail because locked
754 server is not allowed to be stopped by non-admin user.
755 Then unlock the server, now the server can be stopped and started.
756 """
Zhu Zhu9643e512013-09-23 09:13:07 -0500757 # Lock the server,try server stop(exceptions throw),unlock it and retry
Ken'ichi Ohmichi32752ff2015-07-13 04:33:23 +0000758 self.client.lock_server(self.server_id)
Viktor Tikkanen3d063df2015-06-26 07:55:11 +0300759 self.addCleanup(self.client.unlock_server, self.server_id)
ghanshyam0f825252015-08-25 16:02:50 +0900760 server = self.client.show_server(self.server_id)['server']
Zhu Zhu9643e512013-09-23 09:13:07 -0500761 self.assertEqual(server['status'], 'ACTIVE')
762 # Locked server is not allowed to be stopped by non-admin user
Masayuki Igawad9388762015-01-20 14:56:42 +0900763 self.assertRaises(lib_exc.Conflict,
Ken'ichi Ohmichib2631082015-08-27 01:31:00 +0000764 self.client.stop_server, self.server_id)
Ken'ichi Ohmichi32752ff2015-07-13 04:33:23 +0000765 self.client.unlock_server(self.server_id)
Ken'ichi Ohmichib2631082015-08-27 01:31:00 +0000766 self.client.stop_server(self.server_id)
Ken'ichi Ohmichi32752ff2015-07-13 04:33:23 +0000767 waiters.wait_for_server_status(self.client, self.server_id, 'SHUTOFF')
Ken'ichi Ohmichib2631082015-08-27 01:31:00 +0000768 self.client.start_server(self.server_id)
Ken'ichi Ohmichi32752ff2015-07-13 04:33:23 +0000769 waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
Zhu Zhu9643e512013-09-23 09:13:07 -0500770
Ghanshyam86d1a572014-03-05 10:19:25 +0900771 def _validate_url(self, url):
772 valid_scheme = ['http', 'https']
773 parsed_url = urlparse.urlparse(url)
774 self.assertNotEqual('None', parsed_url.port)
775 self.assertNotEqual('None', parsed_url.hostname)
776 self.assertIn(parsed_url.scheme, valid_scheme)
777
Ken'ichi Ohmichi14b0ae12017-01-27 17:18:52 -0800778 @decorators.idempotent_id('c6bc11bf-592e-4015-9319-1c98dc64daf5')
Ghanshyam86d1a572014-03-05 10:19:25 +0900779 @testtools.skipUnless(CONF.compute_feature_enabled.vnc_console,
780 'VNC Console feature is disabled.')
Ghanshyam86d1a572014-03-05 10:19:25 +0900781 def test_get_vnc_console(self):
zhufl27f410a2020-08-13 15:27:59 +0800782 """Test getting vnc console from a server
783
784 The returned vnc console url should be in valid format.
785 """
Lee Yarwood8a649092019-11-25 08:37:54 +0000786 if self.is_requested_microversion_compatible('2.5'):
787 body = self.client.get_vnc_console(
788 self.server_id, type='novnc')['console']
789 else:
790 body = self.client.get_remote_console(
791 self.server_id, console_type='novnc',
792 protocol='vnc')['remote_console']
793 self.assertEqual('novnc', body['type'])
794 self.assertNotEqual('', body['url'])
795 self._validate_url(body['url'])
Ghanshyam Mann3ee9f212021-12-16 16:55:14 -0600796
797
798class ServersAaction247Test(base.BaseV2ComputeTest):
799 """Test compute server with microversion greater than 2.47
800
801 # NOTE(gmann): This test tests the Server create backup APIs
802 # response schema for 2.47 microversion. No specific assert
803 # or behaviour verification is needed.
804 """
805
806 min_microversion = '2.47'
807
808 @testtools.skipUnless(CONF.compute_feature_enabled.snapshot,
809 'Snapshotting not available, backup not possible.')
810 @utils.services('image')
811 @decorators.idempotent_id('252a4bdd-6366-4dae-9994-8c30aa660f23')
812 def test_create_backup(self):
813 server = self.create_test_server(wait_until='ACTIVE')
814
815 backup1 = data_utils.rand_name('backup-1')
816 # Just check create_back to verify the schema with 2.47
817 self.servers_client.create_backup(server['id'],
818 backup_type='daily',
819 rotation=2,
820 name=backup1)