blob: af58433db6769807206fbb6b8d74da1ab2b3f7a3 [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:
Benny Kopilovd1d58212022-08-19 00:47:44 +030046 self.validation_resources = self.get_class_validation_resources(
Martin Kopec78b960f2022-02-08 17:18:02 +000047 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'],
Benny Kopilovd1d58212022-08-19 00:47:44 +030056 self.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
Benny Kopilovd1d58212022-08-19 00:47:44 +030063 self.validation_resources = self.get_class_validation_resources(
Andrea Frittoli9f416dd2017-08-10 15:38:00 +010064 self.os_primary)
Joseph Lanouxffe09dd2015-03-18 16:45:33 +000065 server = self.create_test_server(
66 validatable=True,
Benny Kopilovd1d58212022-08-19 00:47:44 +030067 validation_resources=self.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
109 newserver = self.create_test_server(
110 validatable=True,
Benny Kopilovd1d58212022-08-19 00:47:44 +0300111 validation_resources=self.validation_resources,
Emily Hugenbruch1315e182016-10-10 17:34:06 -0400112 wait_until='ACTIVE')
zhangyangyangc248f592019-04-24 18:54:52 +0800113 self.addCleanup(self.delete_server, newserver['id'])
Sean Dague4dd2c0b2013-01-03 17:50:28 -0500114 # The server's password should be set to the provided password
Daryl Walleck98e66dd2012-06-21 04:58:39 -0500115 new_password = 'Newpass1234'
Emily Hugenbruch1315e182016-10-10 17:34:06 -0400116 self.client.change_password(newserver['id'], adminPass=new_password)
117 waiters.wait_for_server_status(self.client, newserver['id'], 'ACTIVE')
Daryl Wallecked8bef32011-12-05 23:02:08 -0600118
Joseph Lanouxffe09dd2015-03-18 16:45:33 +0000119 if CONF.validation.run_validation:
Daryl Walleck98e66dd2012-06-21 04:58:39 -0500120 # Verify that the user can authenticate with the new password
Emily Hugenbruch1315e182016-10-10 17:34:06 -0400121 server = self.client.show_server(newserver['id'])['server']
Joseph Lanouxffe09dd2015-03-18 16:45:33 +0000122 linux_client = remote_client.RemoteClient(
Benny Kopilovd1d58212022-08-19 00:47:44 +0300123 self.get_server_ip(server, self.validation_resources),
Joseph Lanouxffe09dd2015-03-18 16:45:33 +0000124 self.ssh_user,
Andrea Frittoli (andreaf)2a70a612016-04-29 16:09:13 -0500125 new_password,
126 server=server,
127 servers_client=self.client)
Attila Fazekasad7ef7d2013-11-20 10:12:53 +0100128 linux_client.validate_authentication()
Daryl Walleck98e66dd2012-06-21 04:58:39 -0500129
Ken'ichi Ohmichi84d7fbc2014-09-30 01:42:33 +0000130 def _test_reboot_server(self, reboot_type):
Joseph Lanouxffe09dd2015-03-18 16:45:33 +0000131 if CONF.validation.run_validation:
Daryl Walleck98e66dd2012-06-21 04:58:39 -0500132 # Get the time the server was last rebooted,
ghanshyam0f825252015-08-25 16:02:50 +0900133 server = self.client.show_server(self.server_id)['server']
Joseph Lanouxffe09dd2015-03-18 16:45:33 +0000134 linux_client = remote_client.RemoteClient(
Benny Kopilovd1d58212022-08-19 00:47:44 +0300135 self.get_server_ip(server, self.validation_resources),
Joseph Lanouxffe09dd2015-03-18 16:45:33 +0000136 self.ssh_user,
137 self.password,
Benny Kopilovd1d58212022-08-19 00:47:44 +0300138 self.validation_resources['keypair']['private_key'],
Andrea Frittoli (andreaf)2a70a612016-04-29 16:09:13 -0500139 server=server,
140 servers_client=self.client)
Daryl Walleck98e66dd2012-06-21 04:58:39 -0500141 boot_time = linux_client.get_boot_time()
Daryl Walleck98e66dd2012-06-21 04:58:39 -0500142
Ken'ichi Ohmichi05ab8562016-07-12 00:06:18 -0700143 # NOTE: This sync is for avoiding the loss of pub key data
144 # in a server
145 linux_client.exec_command("sync")
146
Artom Lifshitzea2b59c2021-08-19 14:34:00 -0400147 self.reboot_server(self.server_id, type=reboot_type)
Daryl Wallecked8bef32011-12-05 23:02:08 -0600148
Joseph Lanouxffe09dd2015-03-18 16:45:33 +0000149 if CONF.validation.run_validation:
Daryl Walleck98e66dd2012-06-21 04:58:39 -0500150 # Log in and verify the boot time has changed
Joseph Lanouxffe09dd2015-03-18 16:45:33 +0000151 linux_client = remote_client.RemoteClient(
Benny Kopilovd1d58212022-08-19 00:47:44 +0300152 self.get_server_ip(server, self.validation_resources),
Joseph Lanouxffe09dd2015-03-18 16:45:33 +0000153 self.ssh_user,
154 self.password,
Benny Kopilovd1d58212022-08-19 00:47:44 +0300155 self.validation_resources['keypair']['private_key'],
Andrea Frittoli (andreaf)2a70a612016-04-29 16:09:13 -0500156 server=server,
157 servers_client=self.client)
Daryl Walleck98e66dd2012-06-21 04:58:39 -0500158 new_boot_time = linux_client.get_boot_time()
Béla Vancsics64862f72016-11-08 09:12:31 +0100159 self.assertGreater(new_boot_time, boot_time,
160 '%s > %s' % (new_boot_time, boot_time))
Daryl Walleck98e66dd2012-06-21 04:58:39 -0500161
Jordan Pittier3b46d272017-04-12 16:17:28 +0200162 @decorators.attr(type='smoke')
Ken'ichi Ohmichi14b0ae12017-01-27 17:18:52 -0800163 @decorators.idempotent_id('2cb1baf6-ac8d-4429-bf0d-ba8a0ba53e32')
Ken'ichi Ohmichi84d7fbc2014-09-30 01:42:33 +0000164 def test_reboot_server_hard(self):
zhufl27f410a2020-08-13 15:27:59 +0800165 """Test hard rebooting server
166
167 The server should be power cycled.
168 """
Ken'ichi Ohmichi84d7fbc2014-09-30 01:42:33 +0000169 self._test_reboot_server('HARD')
170
lianghaofd8d3152017-04-01 15:34:26 +0800171 @decorators.idempotent_id('1d1c9104-1b0a-11e7-a3d4-fa163e65f5ce')
172 def test_remove_server_all_security_groups(self):
zhufl27f410a2020-08-13 15:27:59 +0800173 """Test removing all security groups from server"""
lianghaofd8d3152017-04-01 15:34:26 +0800174 server = self.create_test_server(wait_until='ACTIVE')
175
176 # Remove all Security group
177 self.client.remove_security_group(
178 server['id'], name=server['security_groups'][0]['name'])
179
180 # Verify all Security group
181 server = self.client.show_server(server['id'])['server']
182 self.assertNotIn('security_groups', server)
183
Benny Kopilovd1d58212022-08-19 00:47:44 +0300184 def _rebuild_server_and_check(self, image_ref, server):
185 rebuilt_server = (self.client.rebuild_server(server['id'], image_ref)
ghanshyam0f825252015-08-25 16:02:50 +0900186 ['server'])
Benny Kopilovd1d58212022-08-19 00:47:44 +0300187 if CONF.validation.run_validation:
188 tenant_network = self.get_tenant_network()
189 compute.wait_for_ssh_or_ping(
190 server, self.os_primary, tenant_network,
191 True, self.validation_resources, "SSHABLE", True)
192 else:
Damian Dabrowski5928eeb2022-10-27 16:13:53 +0200193 waiters.wait_for_server_status(self.client, server['id'],
Benny Kopilovd1d58212022-08-19 00:47:44 +0300194 'ACTIVE')
195
Yaroslav Lobankovfb1c3642015-05-13 18:38:47 +0300196 msg = ('Server was not rebuilt to the original image. '
197 'The original image: {0}. The current image: {1}'
198 .format(image_ref, rebuilt_server['image']['id']))
199 self.assertEqual(image_ref, rebuilt_server['image']['id'], msg)
200
zhufl01512d22017-08-03 16:30:23 +0800201 def _test_rebuild_server(self):
Castulo J. Martinez0d1b63f2016-07-08 13:55:57 -0700202 # Get the IPs the server has before rebuilding it
203 original_addresses = (self.client.show_server(self.server_id)['server']
204 ['addresses'])
Sean Dague4dd2c0b2013-01-03 17:50:28 -0500205 # The server should be rebuilt using the provided image and data
Daryl Wallecked8bef32011-12-05 23:02:08 -0600206 meta = {'rebuild': 'server'}
zhuflc6ce5392016-08-17 14:34:37 +0800207 new_name = data_utils.rand_name(self.__class__.__name__ + '-server')
Daryl Walleck98e66dd2012-06-21 04:58:39 -0500208 password = 'rebuildPassw0rd'
ghanshyam0f825252015-08-25 16:02:50 +0900209 rebuilt_server = self.client.rebuild_server(
210 self.server_id,
211 self.image_ref_alt,
212 name=new_name,
213 metadata=meta,
ghanshyam0f825252015-08-25 16:02:50 +0900214 adminPass=password)['server']
Daryl Wallecked8bef32011-12-05 23:02:08 -0600215
Andrea Frittolie8040812015-04-28 14:26:35 +0100216 # If the server was rebuilt on a different image, restore it to the
217 # original image once the test ends
218 if self.image_ref_alt != self.image_ref:
Benny Kopilovd1d58212022-08-19 00:47:44 +0300219 self.addCleanup(self._rebuild_server_and_check, self.image_ref,
220 rebuilt_server)
Andrea Frittolie8040812015-04-28 14:26:35 +0100221
Attila Fazekasf7f34f92013-08-01 17:01:44 +0200222 # Verify the properties in the initial response are correct
Brian Waldon3bde07f2011-12-13 15:11:22 -0500223 self.assertEqual(self.server_id, rebuilt_server['id'])
Eoghan Glynn57c1a3d2012-03-01 16:50:29 -0500224 rebuilt_image_id = rebuilt_server['image']['id']
225 self.assertTrue(self.image_ref_alt.endswith(rebuilt_image_id))
zhuflbcb71172018-03-29 13:49:31 +0800226 self.assert_flavor_equal(self.flavor_ref, rebuilt_server['flavor'])
Daryl Wallecked8bef32011-12-05 23:02:08 -0600227
Attila Fazekasf7f34f92013-08-01 17:01:44 +0200228 # Verify the server properties after the rebuild completes
Ken'ichi Ohmichi0eb153c2015-07-13 02:18:25 +0000229 waiters.wait_for_server_status(self.client,
230 rebuilt_server['id'], 'ACTIVE')
ghanshyam0f825252015-08-25 16:02:50 +0900231 server = self.client.show_server(rebuilt_server['id'])['server']
Zhi Kun Liue5401762013-09-11 20:45:48 +0800232 rebuilt_image_id = server['image']['id']
Eoghan Glynn57c1a3d2012-03-01 16:50:29 -0500233 self.assertTrue(self.image_ref_alt.endswith(rebuilt_image_id))
Zhi Kun Liue5401762013-09-11 20:45:48 +0800234 self.assertEqual(new_name, server['name'])
Castulo J. Martinez0d1b63f2016-07-08 13:55:57 -0700235 self.assertEqual(original_addresses, server['addresses'])
Daryl Wallecked8bef32011-12-05 23:02:08 -0600236
Joseph Lanouxffe09dd2015-03-18 16:45:33 +0000237 if CONF.validation.run_validation:
wangxiyuan878c50e2016-01-04 19:24:17 +0800238 # Authentication is attempted in the following order of priority:
239 # 1.The key passed in, if one was passed in.
240 # 2.Any key we can find through an SSH agent (if allowed).
241 # 3.Any "id_rsa", "id_dsa" or "id_ecdsa" key discoverable in
242 # ~/.ssh/ (if allowed).
243 # 4.Plain username/password auth, if a password was given.
Joseph Lanouxffe09dd2015-03-18 16:45:33 +0000244 linux_client = remote_client.RemoteClient(
Benny Kopilovd1d58212022-08-19 00:47:44 +0300245 self.get_server_ip(rebuilt_server, self.validation_resources),
Weronika Sikorac54a9112019-09-18 13:55:07 +0000246 self.ssh_alt_user,
wangxiyuan878c50e2016-01-04 19:24:17 +0800247 password,
Benny Kopilovd1d58212022-08-19 00:47:44 +0300248 self.validation_resources['keypair']['private_key'],
Andrea Frittoli (andreaf)2a70a612016-04-29 16:09:13 -0500249 server=rebuilt_server,
250 servers_client=self.client)
Attila Fazekasad7ef7d2013-11-20 10:12:53 +0100251 linux_client.validate_authentication()
Daryl Walleck98e66dd2012-06-21 04:58:39 -0500252
zhufl01512d22017-08-03 16:30:23 +0800253 @decorators.idempotent_id('aaa6cdf3-55a7-461a-add9-1c8596b9a07c')
254 def test_rebuild_server(self):
zhufl27f410a2020-08-13 15:27:59 +0800255 """Test rebuilding server
256
257 The server should be rebuilt using the provided image and data.
258 """
zhufl01512d22017-08-03 16:30:23 +0800259 self._test_rebuild_server()
260
Ken'ichi Ohmichi14b0ae12017-01-27 17:18:52 -0800261 @decorators.idempotent_id('30449a88-5aff-4f9b-9866-6ee9b17f906d')
Zhi Kun Liue5401762013-09-11 20:45:48 +0800262 def test_rebuild_server_in_stop_state(self):
zhufl27f410a2020-08-13 15:27:59 +0800263 """Test rebuilding server in stop state
264
265 The server in stop state should be rebuilt using the provided
266 image and remain in SHUTOFF state.
267 """
ghanshyam0f825252015-08-25 16:02:50 +0900268 server = self.client.show_server(self.server_id)['server']
Zhi Kun Liue5401762013-09-11 20:45:48 +0800269 old_image = server['image']['id']
Yaroslav Lobankovfb1c3642015-05-13 18:38:47 +0300270 new_image = (self.image_ref_alt
271 if old_image == self.image_ref else self.image_ref)
Ken'ichi Ohmichib2631082015-08-27 01:31:00 +0000272 self.client.stop_server(self.server_id)
Ken'ichi Ohmichi0eb153c2015-07-13 02:18:25 +0000273 waiters.wait_for_server_status(self.client, self.server_id, 'SHUTOFF')
ghanshyam0f825252015-08-25 16:02:50 +0900274 rebuilt_server = (self.client.rebuild_server(self.server_id, new_image)
275 ['server'])
Yaroslav Lobankovfb1c3642015-05-13 18:38:47 +0300276 # If the server was rebuilt on a different image, restore it to the
277 # original image once the test ends
278 if self.image_ref_alt != self.image_ref:
Benny Kopilovd1d58212022-08-19 00:47:44 +0300279 self.addCleanup(self._rebuild_server_and_check, old_image, server)
Zhi Kun Liue5401762013-09-11 20:45:48 +0800280
281 # Verify the properties in the initial response are correct
282 self.assertEqual(self.server_id, rebuilt_server['id'])
283 rebuilt_image_id = rebuilt_server['image']['id']
284 self.assertEqual(new_image, rebuilt_image_id)
zhuflbcb71172018-03-29 13:49:31 +0800285 self.assert_flavor_equal(self.flavor_ref, rebuilt_server['flavor'])
Zhi Kun Liue5401762013-09-11 20:45:48 +0800286
287 # Verify the server properties after the rebuild completes
Ken'ichi Ohmichi0eb153c2015-07-13 02:18:25 +0000288 waiters.wait_for_server_status(self.client,
289 rebuilt_server['id'], 'SHUTOFF')
ghanshyam0f825252015-08-25 16:02:50 +0900290 server = self.client.show_server(rebuilt_server['id'])['server']
Zhi Kun Liue5401762013-09-11 20:45:48 +0800291 rebuilt_image_id = server['image']['id']
292 self.assertEqual(new_image, rebuilt_image_id)
293
Ken'ichi Ohmichib2631082015-08-27 01:31:00 +0000294 self.client.start_server(self.server_id)
Attila Fazekas305e65b2013-10-29 13:23:07 +0100295
Matt Riedemannb5720532018-09-19 16:02:05 -0400296 # NOTE(mriedem): Marked as slow because while rebuild and volume-backed is
297 # common, we don't actually change the image (you can't with volume-backed
298 # rebuild) so this isn't testing much outside normal rebuild
299 # (and it's slow).
300 @decorators.attr(type='slow')
Ken'ichi Ohmichi14b0ae12017-01-27 17:18:52 -0800301 @decorators.idempotent_id('b68bd8d6-855d-4212-b59b-2e704044dace')
Andrea Frittolicd368412017-08-14 21:37:56 +0100302 @utils.services('volume')
Roman Podoliaka908f9062015-04-21 16:52:20 +0300303 def test_rebuild_server_with_volume_attached(self):
zhufl27f410a2020-08-13 15:27:59 +0800304 """Test rebuilding server with volume attached
305
306 The volume should be attached to the instance after rebuild.
307 """
Roman Podoliaka908f9062015-04-21 16:52:20 +0300308 # create a new volume and attach it to the server
Matt Riedemannf1448f02016-10-01 20:03:16 -0400309 volume = self.create_volume()
Roman Podoliaka908f9062015-04-21 16:52:20 +0300310
Matt Riedemannf1448f02016-10-01 20:03:16 -0400311 server = self.client.show_server(self.server_id)['server']
312 self.attach_volume(server, volume)
Roman Podoliaka908f9062015-04-21 16:52:20 +0300313
314 # run general rebuild test
zhufl01512d22017-08-03 16:30:23 +0800315 self._test_rebuild_server()
Roman Podoliaka908f9062015-04-21 16:52:20 +0300316
317 # make sure the volume is attached to the instance after rebuild
318 vol_after_rebuild = self.volumes_client.show_volume(volume['id'])
319 vol_after_rebuild = vol_after_rebuild['volume']
320 self.assertEqual('in-use', vol_after_rebuild['status'])
321 self.assertEqual(self.server_id,
322 vol_after_rebuild['attachments'][0]['server_id'])
afazekas5d066232019-03-25 18:35:36 +0100323 if CONF.validation.run_validation:
afazekas5d066232019-03-25 18:35:36 +0100324 linux_client = remote_client.RemoteClient(
Benny Kopilovd1d58212022-08-19 00:47:44 +0300325 self.get_server_ip(server, self.validation_resources),
Weronika Sikorac54a9112019-09-18 13:55:07 +0000326 self.ssh_alt_user,
afazekas5d066232019-03-25 18:35:36 +0100327 password=None,
Benny Kopilovd1d58212022-08-19 00:47:44 +0300328 pkey=self.validation_resources['keypair']['private_key'],
afazekas5d066232019-03-25 18:35:36 +0100329 server=server,
330 servers_client=self.client)
331 linux_client.validate_authentication()
Roman Podoliaka908f9062015-04-21 16:52:20 +0300332
Matt Riedemannced8d3c2017-11-01 11:39:11 -0400333 def _test_resize_server_confirm(self, server_id, stop=False):
Sean Dague4dd2c0b2013-01-03 17:50:28 -0500334 # The server's RAM and disk space should be modified to that of
335 # the provided flavor
Daryl Wallecked8bef32011-12-05 23:02:08 -0600336
Matt Riedemann9fd63b82014-04-14 09:33:05 -0700337 if stop:
Matt Riedemannced8d3c2017-11-01 11:39:11 -0400338 self.client.stop_server(server_id)
339 waiters.wait_for_server_status(self.client, server_id,
Ken'ichi Ohmichi0eb153c2015-07-13 02:18:25 +0000340 'SHUTOFF')
Matt Riedemann9fd63b82014-04-14 09:33:05 -0700341
Matt Riedemannced8d3c2017-11-01 11:39:11 -0400342 self.client.resize_server(server_id, self.flavor_ref_alt)
zhufl045d1f52016-08-05 15:06:35 +0800343 # NOTE(jlk): Explicitly delete the server to get a new one for later
344 # tests. Avoids resize down race issues.
Matt Riedemannced8d3c2017-11-01 11:39:11 -0400345 self.addCleanup(self.delete_server, server_id)
346 waiters.wait_for_server_status(self.client, server_id,
Ken'ichi Ohmichi0eb153c2015-07-13 02:18:25 +0000347 'VERIFY_RESIZE')
Daryl Wallecked8bef32011-12-05 23:02:08 -0600348
Matt Riedemannced8d3c2017-11-01 11:39:11 -0400349 self.client.confirm_resize_server(server_id)
Matt Riedemann9fd63b82014-04-14 09:33:05 -0700350 expected_status = 'SHUTOFF' if stop else 'ACTIVE'
Matt Riedemannced8d3c2017-11-01 11:39:11 -0400351 waiters.wait_for_server_status(self.client, server_id,
Ken'ichi Ohmichi0eb153c2015-07-13 02:18:25 +0000352 expected_status)
Daryl Wallecked8bef32011-12-05 23:02:08 -0600353
Matt Riedemannced8d3c2017-11-01 11:39:11 -0400354 server = self.client.show_server(server_id)['server']
zhuflbcb71172018-03-29 13:49:31 +0800355 self.assert_flavor_equal(self.flavor_ref_alt, server['flavor'])
Daryl Wallecked8bef32011-12-05 23:02:08 -0600356
Matt Riedemann9fd63b82014-04-14 09:33:05 -0700357 if stop:
358 # NOTE(mriedem): tearDown requires the server to be started.
Matt Riedemannced8d3c2017-11-01 11:39:11 -0400359 self.client.start_server(server_id)
Matt Riedemann9fd63b82014-04-14 09:33:05 -0700360
Ken'ichi Ohmichi14b0ae12017-01-27 17:18:52 -0800361 @decorators.idempotent_id('1499262a-9328-4eda-9068-db1ac57498d2')
Matt Riedemann9fd63b82014-04-14 09:33:05 -0700362 @testtools.skipUnless(CONF.compute_feature_enabled.resize,
363 'Resize not available.')
Matt Riedemann9fd63b82014-04-14 09:33:05 -0700364 def test_resize_server_confirm(self):
zhufl27f410a2020-08-13 15:27:59 +0800365 """Test resizing server and then confirming"""
Matt Riedemannced8d3c2017-11-01 11:39:11 -0400366 self._test_resize_server_confirm(self.server_id, stop=False)
Matt Riedemann9fd63b82014-04-14 09:33:05 -0700367
Matt Riedemann1df75ee2017-10-30 12:52:51 -0400368 @decorators.idempotent_id('e6c28180-7454-4b59-b188-0257af08a63b')
369 @decorators.related_bug('1728603')
370 @testtools.skipUnless(CONF.compute_feature_enabled.resize,
371 'Resize not available.')
372 @utils.services('volume')
373 def test_resize_volume_backed_server_confirm(self):
zhufl27f410a2020-08-13 15:27:59 +0800374 """Test resizing a volume backed server and then confirming"""
Matt Riedemann1df75ee2017-10-30 12:52:51 -0400375 # We have to create a new server that is volume-backed since the one
376 # from setUp is not volume-backed.
Weronika Sikora9e3cc272020-02-10 10:50:53 +0000377 kwargs = {'volume_backed': True,
378 'wait_until': 'ACTIVE'}
379 if CONF.validation.run_validation:
Weronika Sikora9e3cc272020-02-10 10:50:53 +0000380 kwargs.update({'validatable': True,
Benny Kopilovd1d58212022-08-19 00:47:44 +0300381 'validation_resources': self.validation_resources})
Weronika Sikora9e3cc272020-02-10 10:50:53 +0000382 server = self.create_test_server(**kwargs)
383
Mark Goddardfa30d2f2019-09-02 14:41:02 +0100384 # NOTE(mgoddard): Get detailed server to ensure addresses are present
385 # in fixed IP case.
386 server = self.servers_client.show_server(server['id'])['server']
Weronika Sikora9e3cc272020-02-10 10:50:53 +0000387
Matt Riedemann1df75ee2017-10-30 12:52:51 -0400388 self._test_resize_server_confirm(server['id'])
Weronika Sikora9e3cc272020-02-10 10:50:53 +0000389
Evgeny Antyshevcc400912017-11-16 13:36:14 +0000390 if CONF.compute_feature_enabled.console_output:
391 # Now do something interactive with the guest like get its console
392 # output; we don't actually care about the output,
393 # just that it doesn't raise an error.
394 self.client.get_console_output(server['id'])
395 if CONF.validation.run_validation:
Evgeny Antyshevcc400912017-11-16 13:36:14 +0000396 linux_client = remote_client.RemoteClient(
Benny Kopilovd1d58212022-08-19 00:47:44 +0300397 self.get_server_ip(server, self.validation_resources),
Evgeny Antyshevcc400912017-11-16 13:36:14 +0000398 self.ssh_user,
399 password=None,
Benny Kopilovd1d58212022-08-19 00:47:44 +0300400 pkey=self.validation_resources['keypair']['private_key'],
Evgeny Antyshevcc400912017-11-16 13:36:14 +0000401 server=server,
402 servers_client=self.client)
403 linux_client.validate_authentication()
Matt Riedemann1df75ee2017-10-30 12:52:51 -0400404
Ken'ichi Ohmichi14b0ae12017-01-27 17:18:52 -0800405 @decorators.idempotent_id('138b131d-66df-48c9-a171-64f45eb92962')
Matt Riedemann9fd63b82014-04-14 09:33:05 -0700406 @testtools.skipUnless(CONF.compute_feature_enabled.resize,
407 'Resize not available.')
Matt Riedemann9fd63b82014-04-14 09:33:05 -0700408 def test_resize_server_confirm_from_stopped(self):
zhufl27f410a2020-08-13 15:27:59 +0800409 """Test resizing a stopped server and then confirming"""
Matt Riedemannced8d3c2017-11-01 11:39:11 -0400410 self._test_resize_server_confirm(self.server_id, stop=True)
Matt Riedemann9fd63b82014-04-14 09:33:05 -0700411
Ken'ichi Ohmichi14b0ae12017-01-27 17:18:52 -0800412 @decorators.idempotent_id('c03aab19-adb1-44f5-917d-c419577e9e68')
Matt Riedemann5d1f8b12014-03-24 09:12:53 -0700413 @testtools.skipUnless(CONF.compute_feature_enabled.resize,
414 'Resize not available.')
Daryl Wallecked8bef32011-12-05 23:02:08 -0600415 def test_resize_server_revert(self):
zhufl27f410a2020-08-13 15:27:59 +0800416 """Test resizing server and then reverting
417
418 The server's RAM and disk space should return to its original
419 values after a resize is reverted.
420 """
Daryl Wallecked8bef32011-12-05 23:02:08 -0600421
Ken'ichi Ohmichi5271b0f2015-08-10 07:53:27 +0000422 self.client.resize_server(self.server_id, self.flavor_ref_alt)
zhufl045d1f52016-08-05 15:06:35 +0800423 # NOTE(zhufl): Explicitly delete the server to get a new one for later
424 # tests. Avoids resize down race issues.
425 self.addCleanup(self.delete_server, self.server_id)
Ken'ichi Ohmichi0eb153c2015-07-13 02:18:25 +0000426 waiters.wait_for_server_status(self.client, self.server_id,
427 'VERIFY_RESIZE')
Daryl Wallecked8bef32011-12-05 23:02:08 -0600428
Ken'ichi Ohmichib2631082015-08-27 01:31:00 +0000429 self.client.revert_resize_server(self.server_id)
Ken'ichi Ohmichi0eb153c2015-07-13 02:18:25 +0000430 waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
Daryl Wallecked8bef32011-12-05 23:02:08 -0600431
ghanshyam0f825252015-08-25 16:02:50 +0900432 server = self.client.show_server(self.server_id)['server']
zhuflbcb71172018-03-29 13:49:31 +0800433 self.assert_flavor_equal(self.flavor_ref, server['flavor'])
sapan-konaf1e3f002011-12-22 23:18:44 +0530434
Matt Riedemann01ff7c62017-12-12 10:46:57 -0500435 @decorators.idempotent_id('fbbf075f-a812-4022-bc5c-ccb8047eef12')
ghanshyame027dd32018-07-03 05:44:27 +0000436 @decorators.related_bug('1737599')
Matt Riedemann01ff7c62017-12-12 10:46:57 -0500437 @testtools.skipUnless(CONF.compute_feature_enabled.resize,
438 'Resize not available.')
439 @utils.services('volume')
440 def test_resize_server_revert_with_volume_attached(self):
zhufl27f410a2020-08-13 15:27:59 +0800441 """Test resizing a volume attached server and then reverting
442
443 Tests attaching a volume to a server instance and then resizing
444 the instance. Once the instance is resized, revert the resize which
445 should move the instance and volume attachment back to the original
446 compute host.
447 """
Matt Riedemann01ff7c62017-12-12 10:46:57 -0500448
449 # Create a blank volume and attach it to the server created in setUp.
450 volume = self.create_volume()
451 server = self.client.show_server(self.server_id)['server']
452 self.attach_volume(server, volume)
453 # Now resize the server with the blank volume attached.
454 self.client.resize_server(self.server_id, self.flavor_ref_alt)
455 # Explicitly delete the server to get a new one for later
456 # tests. Avoids resize down race issues.
457 self.addCleanup(self.delete_server, self.server_id)
458 waiters.wait_for_server_status(
459 self.client, self.server_id, 'VERIFY_RESIZE')
460 # Now revert the resize which should move the instance and it's volume
461 # attachment back to the original source compute host.
462 self.client.revert_resize_server(self.server_id)
463 waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
464 # Make sure everything still looks OK.
465 server = self.client.show_server(self.server_id)['server']
zhufl83f524a2019-06-26 17:26:13 +0800466 self.assert_flavor_equal(self.flavor_ref, server['flavor'])
Matt Riedemann01ff7c62017-12-12 10:46:57 -0500467 attached_volumes = server['os-extended-volumes:volumes_attached']
468 self.assertEqual(1, len(attached_volumes))
469 self.assertEqual(volume['id'], attached_volumes[0]['id'])
470
Ken'ichi Ohmichi14b0ae12017-01-27 17:18:52 -0800471 @decorators.idempotent_id('b963d4f1-94b3-4c40-9e97-7b583f46e470')
Adam Gandelmanfbc95ac2014-06-19 17:33:43 -0700472 @testtools.skipUnless(CONF.compute_feature_enabled.snapshot,
473 'Snapshotting not available, backup not possible.')
Andrea Frittolicd368412017-08-14 21:37:56 +0100474 @utils.services('image')
ivan-zhuccc89462013-10-31 16:53:12 +0800475 def test_create_backup(self):
zhufl27f410a2020-08-13 15:27:59 +0800476 """Test creating server backup
477
478 1. create server backup1 with rotation=2, there are 1 backup.
479 2. create server backup2 with rotation=2, there are 2 backups.
480 3. create server backup3, due to the rotation is 2, the first one
481 (backup1) will be deleted, so now there are still 2 backups.
482 """
483
ivan-zhuccc89462013-10-31 16:53:12 +0800484 # create the first and the second backup
Matt Riedemann2aa19d42016-06-06 17:45:41 -0400485
486 # Check if glance v1 is available to determine which client to use. We
487 # prefer glance v1 for the compute API tests since the compute image
488 # API proxy was written for glance v1.
489 if CONF.image_feature_enabled.api_v1:
Jordan Pittier8160d312017-04-18 11:52:23 +0200490 glance_client = self.os_primary.image_client
Matt Riedemann2aa19d42016-06-06 17:45:41 -0400491 elif CONF.image_feature_enabled.api_v2:
Jordan Pittier8160d312017-04-18 11:52:23 +0200492 glance_client = self.os_primary.image_client_v2
Matt Riedemann2aa19d42016-06-06 17:45:41 -0400493 else:
Matthew Treinish4217a702016-10-07 17:27:11 -0400494 raise lib_exc.InvalidConfiguration(
Matt Riedemann2aa19d42016-06-06 17:45:41 -0400495 'Either api_v1 or api_v2 must be True in '
496 '[image-feature-enabled].')
497
Matt Riedemanne699f822014-01-24 08:11:42 -0800498 backup1 = data_utils.rand_name('backup-1')
Ken'ichi Ohmichi32752ff2015-07-13 04:33:23 +0000499 resp = self.client.create_backup(self.server_id,
Ken'ichi Ohmichie6349f32015-12-09 06:47:54 +0000500 backup_type='daily',
501 rotation=2,
zhufl2856ad52018-03-29 11:06:34 +0800502 name=backup1)
ivan-zhuccc89462013-10-31 16:53:12 +0800503 oldest_backup_exist = True
504
505 # the oldest one should be deleted automatically in this test
506 def _clean_oldest_backup(oldest_backup):
507 if oldest_backup_exist:
Ryan Hsu38231092014-06-08 23:12:10 -0700508 try:
Matt Riedemann2aa19d42016-06-06 17:45:41 -0400509 glance_client.delete_image(oldest_backup)
Masayuki Igawabfa07602015-01-20 18:47:17 +0900510 except lib_exc.NotFound:
Ryan Hsu38231092014-06-08 23:12:10 -0700511 pass
512 else:
513 LOG.warning("Deletion of oldest backup %s should not have "
514 "been successful as it should have been "
Jordan Pittier525ec712016-12-07 17:51:26 +0100515 "deleted during rotation.", oldest_backup)
ivan-zhuccc89462013-10-31 16:53:12 +0800516
Felipe Monteiro9ff5c282017-06-21 21:05:07 +0100517 if api_version_utils.compare_version_header_to_response(
zhufl2856ad52018-03-29 11:06:34 +0800518 "OpenStack-API-Version", "compute 2.45", resp.response, "lt"):
Felipe Monteiro9ff5c282017-06-21 21:05:07 +0100519 image1_id = resp['image_id']
520 else:
zhufl2856ad52018-03-29 11:06:34 +0800521 image1_id = data_utils.parse_image_id(resp.response['location'])
ivan-zhuccc89462013-10-31 16:53:12 +0800522 self.addCleanup(_clean_oldest_backup, image1_id)
Matt Riedemann2aa19d42016-06-06 17:45:41 -0400523 waiters.wait_for_image_status(glance_client,
Yaroslav Lobankov2fea4052016-04-19 15:05:57 +0300524 image1_id, 'active')
ivan-zhuccc89462013-10-31 16:53:12 +0800525
Matt Riedemanne699f822014-01-24 08:11:42 -0800526 backup2 = data_utils.rand_name('backup-2')
Ken'ichi Ohmichi32752ff2015-07-13 04:33:23 +0000527 waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
528 resp = self.client.create_backup(self.server_id,
Ken'ichi Ohmichie6349f32015-12-09 06:47:54 +0000529 backup_type='daily',
530 rotation=2,
zhufl2856ad52018-03-29 11:06:34 +0800531 name=backup2)
Felipe Monteiro9ff5c282017-06-21 21:05:07 +0100532 if api_version_utils.compare_version_header_to_response(
zhufl2856ad52018-03-29 11:06:34 +0800533 "OpenStack-API-Version", "compute 2.45", resp.response, "lt"):
Felipe Monteiro9ff5c282017-06-21 21:05:07 +0100534 image2_id = resp['image_id']
535 else:
zhufl2856ad52018-03-29 11:06:34 +0800536 image2_id = data_utils.parse_image_id(resp.response['location'])
Matt Riedemann2aa19d42016-06-06 17:45:41 -0400537 self.addCleanup(glance_client.delete_image, image2_id)
538 waiters.wait_for_image_status(glance_client,
Yaroslav Lobankov2fea4052016-04-19 15:05:57 +0300539 image2_id, 'active')
ivan-zhuccc89462013-10-31 16:53:12 +0800540
541 # verify they have been created
542 properties = {
543 'image_type': 'backup',
544 'backup_type': "daily",
545 'instance_uuid': self.server_id,
546 }
Ken'ichi Ohmichi45d7d422016-06-22 10:03:28 -0700547 params = {
548 'status': 'active',
549 'sort_key': 'created_at',
550 'sort_dir': 'asc'
551 }
Matt Riedemann2aa19d42016-06-06 17:45:41 -0400552 if CONF.image_feature_enabled.api_v1:
Ken'ichi Ohmichie28b2c22016-06-22 10:07:27 -0700553 for key, value in properties.items():
554 params['property-%s' % key] = value
Matt Riedemann2aa19d42016-06-06 17:45:41 -0400555 image_list = glance_client.list_images(
556 detail=True,
557 **params)['images']
558 else:
559 # Additional properties are flattened in glance v2.
Matt Riedemann2aa19d42016-06-06 17:45:41 -0400560 params.update(properties)
561 image_list = glance_client.list_images(params)['images']
562
ivan-zhuccc89462013-10-31 16:53:12 +0800563 self.assertEqual(2, len(image_list))
564 self.assertEqual((backup1, backup2),
565 (image_list[0]['name'], image_list[1]['name']))
566
567 # create the third one, due to the rotation is 2,
568 # the first one will be deleted
Matt Riedemanne699f822014-01-24 08:11:42 -0800569 backup3 = data_utils.rand_name('backup-3')
Ken'ichi Ohmichi32752ff2015-07-13 04:33:23 +0000570 waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
571 resp = self.client.create_backup(self.server_id,
Ken'ichi Ohmichie6349f32015-12-09 06:47:54 +0000572 backup_type='daily',
573 rotation=2,
zhufl2856ad52018-03-29 11:06:34 +0800574 name=backup3)
Felipe Monteiro9ff5c282017-06-21 21:05:07 +0100575 if api_version_utils.compare_version_header_to_response(
zhufl2856ad52018-03-29 11:06:34 +0800576 "OpenStack-API-Version", "compute 2.45", resp.response, "lt"):
Felipe Monteiro9ff5c282017-06-21 21:05:07 +0100577 image3_id = resp['image_id']
578 else:
zhufl2856ad52018-03-29 11:06:34 +0800579 image3_id = data_utils.parse_image_id(resp.response['location'])
Matt Riedemann2aa19d42016-06-06 17:45:41 -0400580 self.addCleanup(glance_client.delete_image, image3_id)
ivan-zhuccc89462013-10-31 16:53:12 +0800581 # the first back up should be deleted
Ken'ichi Ohmichi32752ff2015-07-13 04:33:23 +0000582 waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
Matt Riedemann2aa19d42016-06-06 17:45:41 -0400583 glance_client.wait_for_resource_deletion(image1_id)
ivan-zhuccc89462013-10-31 16:53:12 +0800584 oldest_backup_exist = False
Matt Riedemann2aa19d42016-06-06 17:45:41 -0400585 if CONF.image_feature_enabled.api_v1:
586 image_list = glance_client.list_images(
587 detail=True, **params)['images']
588 else:
589 image_list = glance_client.list_images(params)['images']
Matt Riedemanne699f822014-01-24 08:11:42 -0800590 self.assertEqual(2, len(image_list),
591 'Unexpected number of images for '
592 'v2:test_create_backup; was the oldest backup not '
593 'yet deleted? Image list: %s' %
594 [image['name'] for image in image_list])
ivan-zhuccc89462013-10-31 16:53:12 +0800595 self.assertEqual((backup2, backup3),
596 (image_list[0]['name'], image_list[1]['name']))
597
Ken'ichi Ohmichi547a3062013-12-02 09:30:36 +0900598 def _get_output(self):
Ken'ichi Ohmichi32752ff2015-07-13 04:33:23 +0000599 output = self.client.get_console_output(
zhufl15140ee2018-07-25 16:26:21 +0800600 self.server_id, length=3)['output']
Ken'ichi Ohmichi547a3062013-12-02 09:30:36 +0900601 self.assertTrue(output, "Console output was empty.")
602 lines = len(output.split('\n'))
zhufl15140ee2018-07-25 16:26:21 +0800603 self.assertEqual(lines, 3)
Ken'ichi Ohmichi547a3062013-12-02 09:30:36 +0900604
Ken'ichi Ohmichi14b0ae12017-01-27 17:18:52 -0800605 @decorators.idempotent_id('4b8867e6-fffa-4d54-b1d1-6fdda57be2f3')
Adam Gandelmanc6eefb42014-07-15 16:44:08 -0700606 @testtools.skipUnless(CONF.compute_feature_enabled.console_output,
607 'Console output not supported.')
Attila Fazekas45c3fbc2013-02-24 16:39:52 +0100608 def test_get_console_output(self):
zhufl27f410a2020-08-13 15:27:59 +0800609 """Test getting console output for a server
610
611 Should be able to GET the console output for a given server_id and
612 number of lines.
613 """
Ken'ichi Ohmichi851a1352013-11-26 18:42:52 +0900614
615 # This reboot is necessary for outputting some console log after
Takashi NATSUME6d5a2b42015-09-08 11:27:49 +0900616 # creating an instance backup. If an instance backup, the console
Ken'ichi Ohmichi851a1352013-11-26 18:42:52 +0900617 # log file is truncated and we cannot get any console log through
618 # "console-log" API.
619 # The detail is https://bugs.launchpad.net/nova/+bug/1251920
Artom Lifshitzea2b59c2021-08-19 14:34:00 -0400620 self.reboot_server(self.server_id, type='HARD')
Ken'ichi Ohmichi547a3062013-12-02 09:30:36 +0900621 self.wait_for(self._get_output)
Attila Fazekas45c3fbc2013-02-24 16:39:52 +0100622
Ken'ichi Ohmichi14b0ae12017-01-27 17:18:52 -0800623 @decorators.idempotent_id('89104062-69d8-4b19-a71b-f47b7af093d7')
Adam Gandelmanc6eefb42014-07-15 16:44:08 -0700624 @testtools.skipUnless(CONF.compute_feature_enabled.console_output,
625 'Console output not supported.')
Ken'ichi Ohmichibd5df122014-09-18 08:03:52 +0000626 def test_get_console_output_with_unlimited_size(self):
zhufl27f410a2020-08-13 15:27:59 +0800627 """Test getting server's console output with unlimited size
628
629 The console output lines length should be bigger than the one
630 of test_get_console_output.
631 """
David Kranz0fb14292015-02-11 15:55:20 -0500632 server = self.create_test_server(wait_until='ACTIVE')
Ken'ichi Ohmichibd5df122014-09-18 08:03:52 +0000633
634 def _check_full_length_console_log():
Ken'ichi Ohmichibf4766a2015-12-09 07:48:43 +0000635 output = self.client.get_console_output(server['id'])['output']
Ken'ichi Ohmichibd5df122014-09-18 08:03:52 +0000636 self.assertTrue(output, "Console output was empty.")
637 lines = len(output.split('\n'))
638
639 # NOTE: This test tries to get full length console log, and the
640 # length should be bigger than the one of test_get_console_output.
zhufl15140ee2018-07-25 16:26:21 +0800641 self.assertGreater(lines, 3, "Cannot get enough console log "
642 "length. (lines: %s)" % lines)
Ken'ichi Ohmichibd5df122014-09-18 08:03:52 +0000643
644 self.wait_for(_check_full_length_console_log)
645
Ken'ichi Ohmichi14b0ae12017-01-27 17:18:52 -0800646 @decorators.idempotent_id('5b65d4e7-4ecd-437c-83c0-d6b79d927568')
Ken'ichi Ohmichibd5df122014-09-18 08:03:52 +0000647 @testtools.skipUnless(CONF.compute_feature_enabled.console_output,
648 'Console output not supported.')
Ken'ichi Ohmichi547a3062013-12-02 09:30:36 +0900649 def test_get_console_output_server_id_in_shutoff_status(self):
zhufl27f410a2020-08-13 15:27:59 +0800650 """Test getting console output for a server in SHUTOFF status
651
652 Should be able to GET the console output for a given server_id
653 in SHUTOFF status.
654 """
Ken'ichi Ohmichi547a3062013-12-02 09:30:36 +0900655
656 # NOTE: SHUTOFF is irregular status. To avoid test instability,
657 # one server is created only for this test without using
Ken'ichi Ohmichi4d8ba232017-03-03 18:28:05 -0800658 # the server that was created in setUpClass.
David Kranz0fb14292015-02-11 15:55:20 -0500659 server = self.create_test_server(wait_until='ACTIVE')
Ken'ichi Ohmichi547a3062013-12-02 09:30:36 +0900660 temp_server_id = server['id']
661
Ken'ichi Ohmichib2631082015-08-27 01:31:00 +0000662 self.client.stop_server(temp_server_id)
Ken'ichi Ohmichi32752ff2015-07-13 04:33:23 +0000663 waiters.wait_for_server_status(self.client, temp_server_id, 'SHUTOFF')
Ken'ichi Ohmichi547a3062013-12-02 09:30:36 +0900664 self.wait_for(self._get_output)
Dan Smithbc3bd242012-08-14 09:48:48 -0700665
Ken'ichi Ohmichi14b0ae12017-01-27 17:18:52 -0800666 @decorators.idempotent_id('bd61a9fd-062f-4670-972b-2d6c3e3b9e73')
Matt Riedemann992162e2014-03-24 09:11:06 -0700667 @testtools.skipUnless(CONF.compute_feature_enabled.pause,
668 'Pause is not available.')
Prem Karat6631f802013-07-04 12:07:33 +0530669 def test_pause_unpause_server(self):
zhufl27f410a2020-08-13 15:27:59 +0800670 """Test pausing and unpausing server"""
David Kranzae99b9a2015-02-16 13:37:01 -0500671 self.client.pause_server(self.server_id)
Ken'ichi Ohmichi0eb153c2015-07-13 02:18:25 +0000672 waiters.wait_for_server_status(self.client, self.server_id, 'PAUSED')
David Kranzae99b9a2015-02-16 13:37:01 -0500673 self.client.unpause_server(self.server_id)
Ken'ichi Ohmichi0eb153c2015-07-13 02:18:25 +0000674 waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
Prem Karat6631f802013-07-04 12:07:33 +0530675
Ken'ichi Ohmichi14b0ae12017-01-27 17:18:52 -0800676 @decorators.idempotent_id('0d8ee21e-b749-462d-83da-b85b41c86c7f')
Matt Riedemannf0cf6952014-03-24 09:08:52 -0700677 @testtools.skipUnless(CONF.compute_feature_enabled.suspend,
678 'Suspend is not available.')
Prem Karat6631f802013-07-04 12:07:33 +0530679 def test_suspend_resume_server(self):
zhufl27f410a2020-08-13 15:27:59 +0800680 """Test suspending and resuming server"""
David Kranzae99b9a2015-02-16 13:37:01 -0500681 self.client.suspend_server(self.server_id)
Ken'ichi Ohmichi0eb153c2015-07-13 02:18:25 +0000682 waiters.wait_for_server_status(self.client, self.server_id,
683 'SUSPENDED')
David Kranzae99b9a2015-02-16 13:37:01 -0500684 self.client.resume_server(self.server_id)
Ken'ichi Ohmichi0eb153c2015-07-13 02:18:25 +0000685 waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
Prem Karat6631f802013-07-04 12:07:33 +0530686
Ken'ichi Ohmichi14b0ae12017-01-27 17:18:52 -0800687 @decorators.idempotent_id('77eba8e0-036e-4635-944b-f7a8f3b78dc9')
David Shrewsbury25f666f2014-07-22 12:17:59 -0400688 @testtools.skipUnless(CONF.compute_feature_enabled.shelve,
689 'Shelve is not available.')
Andrea Frittolicd368412017-08-14 21:37:56 +0100690 @utils.services('image')
Ken'ichi Ohmichi39437e22013-10-06 00:21:38 +0900691 def test_shelve_unshelve_server(self):
zhufl27f410a2020-08-13 15:27:59 +0800692 """Test shelving and unshelving server"""
ghanshyam43a40652017-06-27 11:23:27 +0300693 if CONF.image_feature_enabled.api_v2:
694 glance_client = self.os_primary.image_client_v2
695 elif CONF.image_feature_enabled.api_v1:
696 glance_client = self.os_primary.image_client
697 else:
698 raise lib_exc.InvalidConfiguration(
699 'Either api_v1 or api_v2 must be True in '
700 '[image-feature-enabled].')
ghanshyam017b5fe2016-04-15 18:49:26 +0900701 compute.shelve_server(self.client, self.server_id,
702 force_shelve_offload=True)
Ken'ichi Ohmichi17b7f112014-02-20 06:33:49 +0900703
ghanshyam0f825252015-08-25 16:02:50 +0900704 server = self.client.show_server(self.server_id)['server']
Ken'ichi Ohmichi39437e22013-10-06 00:21:38 +0900705 image_name = server['name'] + '-shelved'
706 params = {'name': image_name}
ghanshyam43a40652017-06-27 11:23:27 +0300707 if CONF.image_feature_enabled.api_v2:
708 images = glance_client.list_images(params)['images']
709 elif CONF.image_feature_enabled.api_v1:
710 images = glance_client.list_images(
711 detail=True, **params)['images']
Ken'ichi Ohmichi39437e22013-10-06 00:21:38 +0900712 self.assertEqual(1, len(images))
713 self.assertEqual(image_name, images[0]['name'])
714
René Ribaudbe79b462023-05-10 14:30:10 +0200715 body = self.client.unshelve_server(self.server_id)
716 waiters.wait_for_server_status(
717 self.client,
718 self.server_id,
719 "ACTIVE",
720 request_id=body.response["x-openstack-request-id"],
721 )
ghanshyam43a40652017-06-27 11:23:27 +0300722 glance_client.wait_for_resource_deletion(images[0]['id'])
rsritesh8fdfb1c2017-05-08 11:14:00 +0530723
ghanshyama90ade02018-04-25 08:16:08 +0000724 @decorators.idempotent_id('8cf9f450-a871-42cf-9bef-77eba189c0b0')
725 @decorators.related_bug('1745529')
726 @testtools.skipUnless(CONF.compute_feature_enabled.shelve,
727 'Shelve is not available.')
728 @testtools.skipUnless(CONF.compute_feature_enabled.pause,
729 'Pause is not available.')
730 def test_shelve_paused_server(self):
zhufl27f410a2020-08-13 15:27:59 +0800731 """Test shelving a paused server"""
ghanshyama90ade02018-04-25 08:16:08 +0000732 server = self.create_test_server(wait_until='ACTIVE')
733 self.client.pause_server(server['id'])
734 waiters.wait_for_server_status(self.client, server['id'], 'PAUSED')
735 # Check if Shelve operation is successful on paused server.
736 compute.shelve_server(self.client, server['id'],
737 force_shelve_offload=True)
738
Ken'ichi Ohmichi14b0ae12017-01-27 17:18:52 -0800739 @decorators.idempotent_id('af8eafd4-38a7-4a4b-bdbc-75145a580560')
Anju Tiwariaf98d222013-08-05 15:19:50 +0530740 def test_stop_start_server(self):
zhufl27f410a2020-08-13 15:27:59 +0800741 """Test stopping and starting server"""
Ken'ichi Ohmichib2631082015-08-27 01:31:00 +0000742 self.client.stop_server(self.server_id)
Ken'ichi Ohmichi32752ff2015-07-13 04:33:23 +0000743 waiters.wait_for_server_status(self.client, self.server_id, 'SHUTOFF')
Ken'ichi Ohmichib2631082015-08-27 01:31:00 +0000744 self.client.start_server(self.server_id)
Ken'ichi Ohmichi32752ff2015-07-13 04:33:23 +0000745 waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
Anju Tiwariaf98d222013-08-05 15:19:50 +0530746
Ken'ichi Ohmichi14b0ae12017-01-27 17:18:52 -0800747 @decorators.idempotent_id('80a8094c-211e-440a-ab88-9e59d556c7ee')
Zhu Zhu9643e512013-09-23 09:13:07 -0500748 def test_lock_unlock_server(self):
zhufl27f410a2020-08-13 15:27:59 +0800749 """Test locking and unlocking server
750
751 Lock the server, and trying to stop it will fail because locked
752 server is not allowed to be stopped by non-admin user.
753 Then unlock the server, now the server can be stopped and started.
754 """
Zhu Zhu9643e512013-09-23 09:13:07 -0500755 # Lock the server,try server stop(exceptions throw),unlock it and retry
Ken'ichi Ohmichi32752ff2015-07-13 04:33:23 +0000756 self.client.lock_server(self.server_id)
Viktor Tikkanen3d063df2015-06-26 07:55:11 +0300757 self.addCleanup(self.client.unlock_server, self.server_id)
ghanshyam0f825252015-08-25 16:02:50 +0900758 server = self.client.show_server(self.server_id)['server']
Zhu Zhu9643e512013-09-23 09:13:07 -0500759 self.assertEqual(server['status'], 'ACTIVE')
760 # Locked server is not allowed to be stopped by non-admin user
Masayuki Igawad9388762015-01-20 14:56:42 +0900761 self.assertRaises(lib_exc.Conflict,
Ken'ichi Ohmichib2631082015-08-27 01:31:00 +0000762 self.client.stop_server, self.server_id)
Ken'ichi Ohmichi32752ff2015-07-13 04:33:23 +0000763 self.client.unlock_server(self.server_id)
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 waiters.wait_for_server_status(self.client, self.server_id, 'SHUTOFF')
Ken'ichi Ohmichib2631082015-08-27 01:31:00 +0000766 self.client.start_server(self.server_id)
Ken'ichi Ohmichi32752ff2015-07-13 04:33:23 +0000767 waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
Zhu Zhu9643e512013-09-23 09:13:07 -0500768
Ghanshyam86d1a572014-03-05 10:19:25 +0900769 def _validate_url(self, url):
770 valid_scheme = ['http', 'https']
771 parsed_url = urlparse.urlparse(url)
772 self.assertNotEqual('None', parsed_url.port)
773 self.assertNotEqual('None', parsed_url.hostname)
774 self.assertIn(parsed_url.scheme, valid_scheme)
775
Ken'ichi Ohmichi14b0ae12017-01-27 17:18:52 -0800776 @decorators.idempotent_id('c6bc11bf-592e-4015-9319-1c98dc64daf5')
Ghanshyam86d1a572014-03-05 10:19:25 +0900777 @testtools.skipUnless(CONF.compute_feature_enabled.vnc_console,
778 'VNC Console feature is disabled.')
Ghanshyam86d1a572014-03-05 10:19:25 +0900779 def test_get_vnc_console(self):
zhufl27f410a2020-08-13 15:27:59 +0800780 """Test getting vnc console from a server
781
782 The returned vnc console url should be in valid format.
783 """
Lee Yarwood8a649092019-11-25 08:37:54 +0000784 if self.is_requested_microversion_compatible('2.5'):
785 body = self.client.get_vnc_console(
786 self.server_id, type='novnc')['console']
787 else:
788 body = self.client.get_remote_console(
789 self.server_id, console_type='novnc',
790 protocol='vnc')['remote_console']
791 self.assertEqual('novnc', body['type'])
792 self.assertNotEqual('', body['url'])
793 self._validate_url(body['url'])
Ghanshyam Mann3ee9f212021-12-16 16:55:14 -0600794
795
796class ServersAaction247Test(base.BaseV2ComputeTest):
797 """Test compute server with microversion greater than 2.47
798
799 # NOTE(gmann): This test tests the Server create backup APIs
800 # response schema for 2.47 microversion. No specific assert
801 # or behaviour verification is needed.
802 """
803
804 min_microversion = '2.47'
805
806 @testtools.skipUnless(CONF.compute_feature_enabled.snapshot,
807 'Snapshotting not available, backup not possible.')
808 @utils.services('image')
809 @decorators.idempotent_id('252a4bdd-6366-4dae-9994-8c30aa660f23')
810 def test_create_backup(self):
811 server = self.create_test_server(wait_until='ACTIVE')
812
813 backup1 = data_utils.rand_name('backup-1')
814 # Just check create_back to verify the schema with 2.47
815 self.servers_client.create_backup(server['id'],
816 backup_type='daily',
817 rotation=2,
818 name=backup1)
whoami-rajat768d2532022-02-26 00:16:35 +0530819
820
821class ServerActionsV293TestJSON(base.BaseV2ComputeTest):
822
823 min_microversion = '2.93'
824 volume_min_microversion = '3.68'
825
826 @classmethod
827 def setup_credentials(cls):
828 cls.prepare_instance_network()
829 super(ServerActionsV293TestJSON, cls).setup_credentials()
830
831 @classmethod
832 def resource_setup(cls):
833 super(ServerActionsV293TestJSON, cls).resource_setup()
834 cls.server_id = cls.recreate_server(None, validatable=True)
835
836 @utils.services('volume')
837 @decorators.idempotent_id('6652dab9-ea24-4c93-ab5a-93d79c3041cf')
838 def test_rebuild_volume_backed_server(self):
839 """Test rebuilding a volume backed server"""
840 # We have to create a new server that is volume-backed since the one
841 # from setUp is not volume-backed.
842 kwargs = {'volume_backed': True,
843 'wait_until': 'ACTIVE'}
844 validation_resources = {}
845 if CONF.validation.run_validation:
846 validation_resources = self.get_test_validation_resources(
847 self.os_primary)
848 kwargs.update({'validatable': True,
849 'validation_resources': validation_resources})
850 server = self.create_test_server(**kwargs)
851 server = self.servers_client.show_server(server['id'])['server']
852 self.addCleanup(self.delete_server, server['id'])
853 volume_id = server['os-extended-volumes:volumes_attached'][0]['id']
854 volume_before_rebuild = self.volumes_client.show_volume(volume_id)
855 image_before_rebuild = (
856 volume_before_rebuild['volume']
857 ['volume_image_metadata']['image_id'])
858 # Verify that image inside volume is our initial image before rebuild
859 self.assertEqual(self.image_ref, image_before_rebuild)
860
861 # Authentication is attempted in the following order of priority:
862 # 1.The key passed in, if one was passed in.
863 # 2.Any key we can find through an SSH agent (if allowed).
864 # 3.Any "id_rsa", "id_dsa" or "id_ecdsa" key discoverable in
865 # ~/.ssh/ (if allowed).
866 # 4.Plain username/password auth, if a password was given.
867 linux_client = remote_client.RemoteClient(
868 self.get_server_ip(server, validation_resources),
869 self.ssh_user,
870 password=None,
871 pkey=validation_resources['keypair']['private_key'],
872 server=server,
873 servers_client=self.servers_client)
874 output = linux_client.exec_command('touch test_file')
875 # No output means success
876 self.assertEqual('', output.strip())
877
878 # The server should be rebuilt using the provided image and data
879 meta = {'rebuild': 'server'}
880 new_name = data_utils.rand_name(self.__class__.__name__ + '-server')
881 password = 'rebuildPassw0rd'
882 rebuilt_server = self.servers_client.rebuild_server(
883 server['id'],
884 self.image_ref_alt,
885 name=new_name,
886 metadata=meta,
887 adminPass=password)['server']
888
889 # Verify the properties in the initial response are correct
890 self.assertEqual(server['id'], rebuilt_server['id'])
891 rebuilt_image_id = rebuilt_server['image']
892 # Since it is a volume backed server, image id will remain empty
893 self.assertEqual('', rebuilt_image_id)
894 self.assert_flavor_equal(self.flavor_ref, rebuilt_server['flavor'])
895
896 # Verify the server properties after the rebuild completes
897 waiters.wait_for_server_status(self.servers_client,
898 rebuilt_server['id'], 'ACTIVE')
899 server = self.servers_client.show_server(
900 rebuilt_server['id'])['server']
901 volume_id = server['os-extended-volumes:volumes_attached'][0]['id']
902 volume_after_rebuild = self.volumes_client.show_volume(volume_id)
903 image_after_rebuild = (
904 volume_after_rebuild['volume']
905 ['volume_image_metadata']['image_id'])
906
907 self.assertEqual(new_name, server['name'])
908 # Verify that volume ID remains same before and after rebuild
909 self.assertEqual(volume_before_rebuild['volume']['id'],
910 volume_after_rebuild['volume']['id'])
911 # Verify that image inside volume is our final image after rebuild
912 self.assertEqual(self.image_ref_alt, image_after_rebuild)
913
914 # Authentication is attempted in the following order of priority:
915 # 1.The key passed in, if one was passed in.
916 # 2.Any key we can find through an SSH agent (if allowed).
917 # 3.Any "id_rsa", "id_dsa" or "id_ecdsa" key discoverable in
918 # ~/.ssh/ (if allowed).
919 # 4.Plain username/password auth, if a password was given.
920 linux_client = remote_client.RemoteClient(
921 self.get_server_ip(rebuilt_server, validation_resources),
922 self.ssh_alt_user,
923 password,
924 validation_resources['keypair']['private_key'],
925 server=rebuilt_server,
926 servers_client=self.servers_client)
927 linux_client.validate_authentication()
928 e = self.assertRaises(lib_exc.SSHExecCommandFailed,
929 linux_client.exec_command,
930 'cat test_file')
931 # If we rebuilt the boot volume, then we should not find
932 # the file we touched.
933 self.assertIn('No such file or directory', str(e))