blob: 4a1f8e3142b0428f8b6529b27390f589506bb004 [file] [log] [blame]
Jay Pipes13b479b2012-06-11 14:52:27 -04001# vim: tabstop=4 shiftwidth=4 softtabstop=4
2
ZhiQiang Fan39f97222013-09-20 04:49:44 +08003# Copyright 2012 OpenStack Foundation
Jay Pipes13b479b2012-06-11 14:52:27 -04004# All Rights Reserved.
5#
6# Licensed under the Apache License, Version 2.0 (the "License"); you may
7# not use this file except in compliance with the License. You may obtain
8# a copy of the License at
9#
10# http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15# License for the specific language governing permissions and limitations
16# under the License.
17
Daryl Wallecked8bef32011-12-05 23:02:08 -060018import base64
Daryl Walleckb43ce8a2012-02-26 19:14:25 -060019import time
Brian Waldon738cd632011-12-12 18:45:09 -050020
ivan-zhu1feeb382013-01-24 10:14:39 +080021import testtools
Jay Pipes13b479b2012-06-11 14:52:27 -040022
Sean Dague1937d092013-05-17 16:36:38 -040023from tempest.api import compute
24from tempest.api.compute import base
Jay Pipes13b479b2012-06-11 14:52:27 -040025from tempest.common.utils.data_utils import rand_name
Daryl Walleck98e66dd2012-06-21 04:58:39 -050026from tempest.common.utils.linux.remote_client import RemoteClient
Matthew Treinisha83a16e2012-12-07 13:44:02 -050027import tempest.config
28from tempest import exceptions
Chris Yeoh9465b0b2013-02-09 22:19:15 +103029from tempest.test import attr
Giulio Fidente83181a92013-10-01 06:02:24 +020030from tempest.test import skip_because
Daryl Wallecked8bef32011-12-05 23:02:08 -060031
Daryl Walleckc7251962012-03-12 17:26:54 -050032
ivan-zhuf2b00502013-10-18 10:06:52 +080033class ServerActionsTestJSON(base.BaseV2ComputeTest):
Attila Fazekas19044d52013-02-16 07:35:06 +010034 _interface = 'json'
Matthew Treinishd5c96022013-10-17 21:51:23 +000035 resize_available = tempest.config.TempestConfig().\
36 compute_feature_enabled.resize
Daryl Walleck98e66dd2012-06-21 04:58:39 -050037 run_ssh = tempest.config.TempestConfig().compute.run_ssh
Daryl Wallecked8bef32011-12-05 23:02:08 -060038
Attila Fazekas19044d52013-02-16 07:35:06 +010039 def setUp(self):
Attila Fazekasf7f34f92013-08-01 17:01:44 +020040 # NOTE(afazekas): Normally we use the same server with all test cases,
Attila Fazekas45c3fbc2013-02-24 16:39:52 +010041 # but if it has an issue, we build a new one
Attila Fazekas19044d52013-02-16 07:35:06 +010042 super(ServerActionsTestJSON, self).setUp()
43 # Check if the server is in a clean state after test
44 try:
45 self.client.wait_for_server_status(self.server_id, 'ACTIVE')
afazekas14025cd2013-03-13 23:42:17 +010046 except Exception:
Attila Fazekas19044d52013-02-16 07:35:06 +010047 # Rebuild server if something happened to it during a test
Ken'ichi Ohmichida306502013-10-08 23:44:55 +090048 self.rebuild_server()
Attila Fazekas19044d52013-02-16 07:35:06 +010049
50 @classmethod
51 def setUpClass(cls):
52 super(ServerActionsTestJSON, cls).setUpClass()
53 cls.client = cls.servers_client
Ken'ichi Ohmichida306502013-10-08 23:44:55 +090054 cls.rebuild_server()
Attila Fazekas19044d52013-02-16 07:35:06 +010055
ivan-zhu1feeb382013-01-24 10:14:39 +080056 @testtools.skipUnless(compute.CHANGE_PASSWORD_AVAILABLE,
57 'Change password not available.')
Giampaolo Lauriae9c77022013-05-22 01:23:58 -040058 @attr(type='gate')
Daryl Wallecked8bef32011-12-05 23:02:08 -060059 def test_change_server_password(self):
Sean Dague4dd2c0b2013-01-03 17:50:28 -050060 # The server's password should be set to the provided password
Daryl Walleck98e66dd2012-06-21 04:58:39 -050061 new_password = 'Newpass1234'
62 resp, body = self.client.change_password(self.server_id, new_password)
Daryl Wallecked8bef32011-12-05 23:02:08 -060063 self.assertEqual(202, resp.status)
Brian Waldon3bde07f2011-12-13 15:11:22 -050064 self.client.wait_for_server_status(self.server_id, 'ACTIVE')
Daryl Wallecked8bef32011-12-05 23:02:08 -060065
Daryl Walleck98e66dd2012-06-21 04:58:39 -050066 if self.run_ssh:
67 # Verify that the user can authenticate with the new password
68 resp, server = self.client.get_server(self.server_id)
69 linux_client = RemoteClient(server, self.ssh_user, new_password)
70 self.assertTrue(linux_client.can_authenticate())
71
Daryl Wallecked8bef32011-12-05 23:02:08 -060072 @attr(type='smoke')
73 def test_reboot_server_hard(self):
Sean Dague4dd2c0b2013-01-03 17:50:28 -050074 # The server should be power cycled
Daryl Walleck98e66dd2012-06-21 04:58:39 -050075 if self.run_ssh:
76 # Get the time the server was last rebooted,
Daryl Walleck98e66dd2012-06-21 04:58:39 -050077 resp, server = self.client.get_server(self.server_id)
78 linux_client = RemoteClient(server, self.ssh_user, self.password)
79 boot_time = linux_client.get_boot_time()
Daryl Walleck98e66dd2012-06-21 04:58:39 -050080
Brian Waldon3bde07f2011-12-13 15:11:22 -050081 resp, body = self.client.reboot(self.server_id, 'HARD')
Daryl Wallecked8bef32011-12-05 23:02:08 -060082 self.assertEqual(202, resp.status)
Brian Waldon3bde07f2011-12-13 15:11:22 -050083 self.client.wait_for_server_status(self.server_id, 'ACTIVE')
Daryl Wallecked8bef32011-12-05 23:02:08 -060084
Daryl Walleck98e66dd2012-06-21 04:58:39 -050085 if self.run_ssh:
86 # Log in and verify the boot time has changed
87 linux_client = RemoteClient(server, self.ssh_user, self.password)
88 new_boot_time = linux_client.get_boot_time()
89 self.assertGreater(new_boot_time, boot_time)
90
Giulio Fidente83181a92013-10-01 06:02:24 +020091 @skip_because(bug="1014647")
Giampaolo Lauriae9c77022013-05-22 01:23:58 -040092 @attr(type='smoke')
Daryl Wallecked8bef32011-12-05 23:02:08 -060093 def test_reboot_server_soft(self):
Sean Dague4dd2c0b2013-01-03 17:50:28 -050094 # The server should be signaled to reboot gracefully
Daryl Walleck98e66dd2012-06-21 04:58:39 -050095 if self.run_ssh:
96 # Get the time the server was last rebooted,
Daryl Walleck98e66dd2012-06-21 04:58:39 -050097 resp, server = self.client.get_server(self.server_id)
98 linux_client = RemoteClient(server, self.ssh_user, self.password)
99 boot_time = linux_client.get_boot_time()
Daryl Walleck98e66dd2012-06-21 04:58:39 -0500100
Brian Waldon3bde07f2011-12-13 15:11:22 -0500101 resp, body = self.client.reboot(self.server_id, 'SOFT')
Daryl Wallecked8bef32011-12-05 23:02:08 -0600102 self.assertEqual(202, resp.status)
Brian Waldon3bde07f2011-12-13 15:11:22 -0500103 self.client.wait_for_server_status(self.server_id, 'ACTIVE')
Daryl Wallecked8bef32011-12-05 23:02:08 -0600104
Daryl Walleck98e66dd2012-06-21 04:58:39 -0500105 if self.run_ssh:
106 # Log in and verify the boot time has changed
107 linux_client = RemoteClient(server, self.ssh_user, self.password)
108 new_boot_time = linux_client.get_boot_time()
109 self.assertGreater(new_boot_time, boot_time)
110
Daryl Wallecked8bef32011-12-05 23:02:08 -0600111 @attr(type='smoke')
112 def test_rebuild_server(self):
Sean Dague4dd2c0b2013-01-03 17:50:28 -0500113 # The server should be rebuilt using the provided image and data
Daryl Wallecked8bef32011-12-05 23:02:08 -0600114 meta = {'rebuild': 'server'}
Brian Waldon738cd632011-12-12 18:45:09 -0500115 new_name = rand_name('server')
Daryl Wallecked8bef32011-12-05 23:02:08 -0600116 file_contents = 'Test server rebuild.'
Mahesh Panchaksharaiah21599a92013-07-03 15:28:58 +0530117 personality = [{'path': 'rebuild.txt',
Daryl Wallecked8bef32011-12-05 23:02:08 -0600118 'contents': base64.b64encode(file_contents)}]
Daryl Walleck98e66dd2012-06-21 04:58:39 -0500119 password = 'rebuildPassw0rd'
Brian Waldon3bde07f2011-12-13 15:11:22 -0500120 resp, rebuilt_server = self.client.rebuild(self.server_id,
Daryl Wallecked8bef32011-12-05 23:02:08 -0600121 self.image_ref_alt,
ivan-zhu454b1c52013-09-30 16:40:21 +0800122 name=new_name,
123 metadata=meta,
Daryl Wallecked8bef32011-12-05 23:02:08 -0600124 personality=personality,
Daryl Walleck98e66dd2012-06-21 04:58:39 -0500125 adminPass=password)
Daryl Wallecked8bef32011-12-05 23:02:08 -0600126
Attila Fazekasf7f34f92013-08-01 17:01:44 +0200127 # Verify the properties in the initial response are correct
Brian Waldon3bde07f2011-12-13 15:11:22 -0500128 self.assertEqual(self.server_id, rebuilt_server['id'])
Eoghan Glynn57c1a3d2012-03-01 16:50:29 -0500129 rebuilt_image_id = rebuilt_server['image']['id']
130 self.assertTrue(self.image_ref_alt.endswith(rebuilt_image_id))
Matthew Treinish39e48ef2012-12-21 13:36:15 -0500131 self.assertEqual(self.flavor_ref, int(rebuilt_server['flavor']['id']))
Daryl Wallecked8bef32011-12-05 23:02:08 -0600132
Attila Fazekasf7f34f92013-08-01 17:01:44 +0200133 # Verify the server properties after the rebuild completes
Daryl Wallecked8bef32011-12-05 23:02:08 -0600134 self.client.wait_for_server_status(rebuilt_server['id'], 'ACTIVE')
135 resp, server = self.client.get_server(rebuilt_server['id'])
Eoghan Glynn57c1a3d2012-03-01 16:50:29 -0500136 rebuilt_image_id = rebuilt_server['image']['id']
137 self.assertTrue(self.image_ref_alt.endswith(rebuilt_image_id))
Brian Waldon738cd632011-12-12 18:45:09 -0500138 self.assertEqual(new_name, rebuilt_server['name'])
Daryl Wallecked8bef32011-12-05 23:02:08 -0600139
Daryl Walleck98e66dd2012-06-21 04:58:39 -0500140 if self.run_ssh:
141 # Verify that the user can authenticate with the provided password
142 linux_client = RemoteClient(server, self.ssh_user, password)
143 self.assertTrue(linux_client.can_authenticate())
144
Tiago Mello52d8fda2013-02-12 12:10:30 -0500145 def _detect_server_image_flavor(self, server_id):
146 # Detects the current server image flavor ref.
147 resp, server = self.client.get_server(self.server_id)
148 current_flavor = server['flavor']['id']
149 new_flavor_ref = self.flavor_ref_alt \
150 if int(current_flavor) == self.flavor_ref else self.flavor_ref
151 return int(current_flavor), int(new_flavor_ref)
152
ivan-zhu1feeb382013-01-24 10:14:39 +0800153 @testtools.skipIf(not resize_available, 'Resize not available.')
Giampaolo Lauriae9c77022013-05-22 01:23:58 -0400154 @attr(type='smoke')
Daryl Wallecked8bef32011-12-05 23:02:08 -0600155 def test_resize_server_confirm(self):
Sean Dague4dd2c0b2013-01-03 17:50:28 -0500156 # The server's RAM and disk space should be modified to that of
157 # the provided flavor
Daryl Wallecked8bef32011-12-05 23:02:08 -0600158
Tiago Mello52d8fda2013-02-12 12:10:30 -0500159 previous_flavor_ref, new_flavor_ref = \
160 self._detect_server_image_flavor(self.server_id)
161
162 resp, server = self.client.resize(self.server_id, new_flavor_ref)
Daryl Wallecked8bef32011-12-05 23:02:08 -0600163 self.assertEqual(202, resp.status)
Brian Waldon3bde07f2011-12-13 15:11:22 -0500164 self.client.wait_for_server_status(self.server_id, 'VERIFY_RESIZE')
Daryl Wallecked8bef32011-12-05 23:02:08 -0600165
Brian Waldon3bde07f2011-12-13 15:11:22 -0500166 self.client.confirm_resize(self.server_id)
167 self.client.wait_for_server_status(self.server_id, 'ACTIVE')
Daryl Wallecked8bef32011-12-05 23:02:08 -0600168
Brian Waldon3bde07f2011-12-13 15:11:22 -0500169 resp, server = self.client.get_server(self.server_id)
Tiago Mello52d8fda2013-02-12 12:10:30 -0500170 self.assertEqual(new_flavor_ref, int(server['flavor']['id']))
Daryl Wallecked8bef32011-12-05 23:02:08 -0600171
ivan-zhu1feeb382013-01-24 10:14:39 +0800172 @testtools.skipIf(not resize_available, 'Resize not available.')
Giulio Fidenteba3985a2013-05-29 01:46:36 +0200173 @attr(type='gate')
Daryl Wallecked8bef32011-12-05 23:02:08 -0600174 def test_resize_server_revert(self):
Sean Dague4dd2c0b2013-01-03 17:50:28 -0500175 # The server's RAM and disk space should return to its original
176 # values after a resize is reverted
Daryl Wallecked8bef32011-12-05 23:02:08 -0600177
Tiago Mello52d8fda2013-02-12 12:10:30 -0500178 previous_flavor_ref, new_flavor_ref = \
179 self._detect_server_image_flavor(self.server_id)
180
181 resp, server = self.client.resize(self.server_id, new_flavor_ref)
Daryl Wallecked8bef32011-12-05 23:02:08 -0600182 self.assertEqual(202, resp.status)
Brian Waldon3bde07f2011-12-13 15:11:22 -0500183 self.client.wait_for_server_status(self.server_id, 'VERIFY_RESIZE')
Daryl Wallecked8bef32011-12-05 23:02:08 -0600184
Brian Waldon3bde07f2011-12-13 15:11:22 -0500185 self.client.revert_resize(self.server_id)
186 self.client.wait_for_server_status(self.server_id, 'ACTIVE')
Daryl Wallecked8bef32011-12-05 23:02:08 -0600187
Daryl Walleckb43ce8a2012-02-26 19:14:25 -0600188 # Need to poll for the id change until lp#924371 is fixed
Brian Waldon3bde07f2011-12-13 15:11:22 -0500189 resp, server = self.client.get_server(self.server_id)
Daryl Walleckb43ce8a2012-02-26 19:14:25 -0600190 start = int(time.time())
191
Tiago Mello52d8fda2013-02-12 12:10:30 -0500192 while int(server['flavor']['id']) != previous_flavor_ref:
Daryl Walleckb43ce8a2012-02-26 19:14:25 -0600193 time.sleep(self.build_interval)
194 resp, server = self.client.get_server(self.server_id)
195
196 if int(time.time()) - start >= self.build_timeout:
197 message = 'Server %s failed to revert resize within the \
198 required time (%s s).' % (self.server_id, self.build_timeout)
199 raise exceptions.TimeoutException(message)
sapan-konaf1e3f002011-12-22 23:18:44 +0530200
Giulio Fidenteba3985a2013-05-29 01:46:36 +0200201 @attr(type='gate')
Attila Fazekas45c3fbc2013-02-24 16:39:52 +0100202 def test_get_console_output(self):
203 # Positive test:Should be able to GET the console output
204 # for a given server_id and number of lines
205 def get_output():
206 resp, output = self.servers_client.get_console_output(
207 self.server_id, 10)
208 self.assertEqual(200, resp.status)
Ionuț Arțărișia767b522013-08-21 18:09:26 +0200209 self.assertTrue(output, "Console output was empty.")
Attila Fazekas45c3fbc2013-02-24 16:39:52 +0100210 lines = len(output.split('\n'))
211 self.assertEqual(lines, 10)
212 self.wait_for(get_output)
213
Giulio Fidente83181a92013-10-01 06:02:24 +0200214 @skip_because(bug="1014683")
Giulio Fidenteba3985a2013-05-29 01:46:36 +0200215 @attr(type='gate')
Attila Fazekas45c3fbc2013-02-24 16:39:52 +0100216 def test_get_console_output_server_id_in_reboot_status(self):
217 # Positive test:Should be able to GET the console output
218 # for a given server_id in reboot status
219 resp, output = self.servers_client.reboot(self.server_id, 'SOFT')
220 self.servers_client.wait_for_server_status(self.server_id,
221 'REBOOT')
222 resp, output = self.servers_client.get_console_output(self.server_id,
223 10)
224 self.assertEqual(200, resp.status)
Ionuț Arțăriși7f7d4522013-08-21 11:47:47 +0200225 self.assertIsNotNone(output)
Attila Fazekas45c3fbc2013-02-24 16:39:52 +0100226 lines = len(output.split('\n'))
227 self.assertEqual(lines, 10)
Dan Smithbc3bd242012-08-14 09:48:48 -0700228
Prem Karat6631f802013-07-04 12:07:33 +0530229 @attr(type='gate')
230 def test_pause_unpause_server(self):
231 resp, server = self.client.pause_server(self.server_id)
232 self.assertEqual(202, resp.status)
233 self.client.wait_for_server_status(self.server_id, 'PAUSED')
234 resp, server = self.client.unpause_server(self.server_id)
235 self.assertEqual(202, resp.status)
236 self.client.wait_for_server_status(self.server_id, 'ACTIVE')
237
238 @attr(type='gate')
239 def test_suspend_resume_server(self):
240 resp, server = self.client.suspend_server(self.server_id)
241 self.assertEqual(202, resp.status)
242 self.client.wait_for_server_status(self.server_id, 'SUSPENDED')
243 resp, server = self.client.resume_server(self.server_id)
244 self.assertEqual(202, resp.status)
245 self.client.wait_for_server_status(self.server_id, 'ACTIVE')
246
Anju Tiwariaf98d222013-08-05 15:19:50 +0530247 @attr(type='gate')
Ken'ichi Ohmichi39437e22013-10-06 00:21:38 +0900248 def test_shelve_unshelve_server(self):
249 resp, server = self.client.shelve_server(self.server_id)
250 self.assertEqual(202, resp.status)
251
252 offload_time = self.config.compute.shelved_offload_time
253 if offload_time >= 0:
254 self.client.wait_for_server_status(self.server_id,
255 'SHELVED_OFFLOADED',
256 extra_timeout=offload_time)
257 else:
258 self.client.wait_for_server_status(self.server_id,
259 'SHELVED')
260
261 resp, server = self.client.get_server(self.server_id)
262 image_name = server['name'] + '-shelved'
263 params = {'name': image_name}
264 resp, images = self.images_client.list_images(params)
265 self.assertEqual(1, len(images))
266 self.assertEqual(image_name, images[0]['name'])
267
268 resp, server = self.client.unshelve_server(self.server_id)
269 self.assertEqual(202, resp.status)
270 self.client.wait_for_server_status(self.server_id, 'ACTIVE')
271
272 @attr(type='gate')
Anju Tiwariaf98d222013-08-05 15:19:50 +0530273 def test_stop_start_server(self):
274 resp, server = self.servers_client.stop(self.server_id)
275 self.assertEqual(202, resp.status)
276 self.servers_client.wait_for_server_status(self.server_id, 'SHUTOFF')
277 resp, server = self.servers_client.start(self.server_id)
278 self.assertEqual(202, resp.status)
279 self.servers_client.wait_for_server_status(self.server_id, 'ACTIVE')
280
Zhu Zhu9643e512013-09-23 09:13:07 -0500281 @attr(type='gate')
282 def test_lock_unlock_server(self):
283 # Lock the server,try server stop(exceptions throw),unlock it and retry
284 resp, server = self.servers_client.lock_server(self.server_id)
285 self.assertEqual(202, resp.status)
286 resp, server = self.servers_client.get_server(self.server_id)
287 self.assertEqual(200, resp.status)
288 self.assertEqual(server['status'], 'ACTIVE')
289 # Locked server is not allowed to be stopped by non-admin user
ivan-zhu75a4ac82013-10-31 23:07:05 +0800290 self.assertRaises(exceptions.Conflict,
Zhu Zhu9643e512013-09-23 09:13:07 -0500291 self.servers_client.stop, self.server_id)
292 resp, server = self.servers_client.unlock_server(self.server_id)
293 self.assertEqual(202, resp.status)
294 resp, server = self.servers_client.stop(self.server_id)
295 self.assertEqual(202, resp.status)
296 self.servers_client.wait_for_server_status(self.server_id, 'SHUTOFF')
297 resp, server = self.servers_client.start(self.server_id)
298 self.assertEqual(202, resp.status)
299 self.servers_client.wait_for_server_status(self.server_id, 'ACTIVE')
300
Dan Smithbc3bd242012-08-14 09:48:48 -0700301
Attila Fazekas19044d52013-02-16 07:35:06 +0100302class ServerActionsTestXML(ServerActionsTestJSON):
303 _interface = 'xml'