blob: 9fc147a723ca85464ee0477787c3a731572fc466 [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
Daryl Wallecked8bef32011-12-05 23:02:08 -060030
Daryl Walleckc7251962012-03-12 17:26:54 -050031
Attila Fazekas19044d52013-02-16 07:35:06 +010032class ServerActionsTestJSON(base.BaseComputeTest):
33 _interface = 'json'
Daryl Walleck587385b2012-03-03 13:00:26 -060034 resize_available = tempest.config.TempestConfig().compute.resize_available
Daryl Walleck98e66dd2012-06-21 04:58:39 -050035 run_ssh = tempest.config.TempestConfig().compute.run_ssh
Daryl Wallecked8bef32011-12-05 23:02:08 -060036
Attila Fazekas19044d52013-02-16 07:35:06 +010037 def setUp(self):
Attila Fazekasf7f34f92013-08-01 17:01:44 +020038 # NOTE(afazekas): Normally we use the same server with all test cases,
Attila Fazekas45c3fbc2013-02-24 16:39:52 +010039 # but if it has an issue, we build a new one
Attila Fazekas19044d52013-02-16 07:35:06 +010040 super(ServerActionsTestJSON, self).setUp()
41 # Check if the server is in a clean state after test
42 try:
43 self.client.wait_for_server_status(self.server_id, 'ACTIVE')
afazekas14025cd2013-03-13 23:42:17 +010044 except Exception:
Attila Fazekas19044d52013-02-16 07:35:06 +010045 # Rebuild server if something happened to it during a test
46 self.rebuild_servers()
47
48 @classmethod
49 def setUpClass(cls):
50 super(ServerActionsTestJSON, cls).setUpClass()
51 cls.client = cls.servers_client
52 cls.rebuild_servers()
53
ivan-zhu1feeb382013-01-24 10:14:39 +080054 @testtools.skipUnless(compute.CHANGE_PASSWORD_AVAILABLE,
55 'Change password not available.')
Giampaolo Lauriae9c77022013-05-22 01:23:58 -040056 @attr(type='gate')
Daryl Wallecked8bef32011-12-05 23:02:08 -060057 def test_change_server_password(self):
Sean Dague4dd2c0b2013-01-03 17:50:28 -050058 # The server's password should be set to the provided password
Daryl Walleck98e66dd2012-06-21 04:58:39 -050059 new_password = 'Newpass1234'
60 resp, body = self.client.change_password(self.server_id, new_password)
Daryl Wallecked8bef32011-12-05 23:02:08 -060061 self.assertEqual(202, resp.status)
Brian Waldon3bde07f2011-12-13 15:11:22 -050062 self.client.wait_for_server_status(self.server_id, 'ACTIVE')
Daryl Wallecked8bef32011-12-05 23:02:08 -060063
Daryl Walleck98e66dd2012-06-21 04:58:39 -050064 if self.run_ssh:
65 # Verify that the user can authenticate with the new password
66 resp, server = self.client.get_server(self.server_id)
67 linux_client = RemoteClient(server, self.ssh_user, new_password)
68 self.assertTrue(linux_client.can_authenticate())
69
Daryl Wallecked8bef32011-12-05 23:02:08 -060070 @attr(type='smoke')
71 def test_reboot_server_hard(self):
Sean Dague4dd2c0b2013-01-03 17:50:28 -050072 # The server should be power cycled
Daryl Walleck98e66dd2012-06-21 04:58:39 -050073 if self.run_ssh:
74 # Get the time the server was last rebooted,
Daryl Walleck98e66dd2012-06-21 04:58:39 -050075 resp, server = self.client.get_server(self.server_id)
76 linux_client = RemoteClient(server, self.ssh_user, self.password)
77 boot_time = linux_client.get_boot_time()
Daryl Walleck98e66dd2012-06-21 04:58:39 -050078
Brian Waldon3bde07f2011-12-13 15:11:22 -050079 resp, body = self.client.reboot(self.server_id, 'HARD')
Daryl Wallecked8bef32011-12-05 23:02:08 -060080 self.assertEqual(202, resp.status)
Brian Waldon3bde07f2011-12-13 15:11:22 -050081 self.client.wait_for_server_status(self.server_id, 'ACTIVE')
Daryl Wallecked8bef32011-12-05 23:02:08 -060082
Daryl Walleck98e66dd2012-06-21 04:58:39 -050083 if self.run_ssh:
84 # Log in and verify the boot time has changed
85 linux_client = RemoteClient(server, self.ssh_user, self.password)
86 new_boot_time = linux_client.get_boot_time()
87 self.assertGreater(new_boot_time, boot_time)
88
Giulio Fidente6cc3ade2013-08-23 17:21:03 +020089 @testtools.skip('Skipped until the Bug #1014647 is resolved.')
Giampaolo Lauriae9c77022013-05-22 01:23:58 -040090 @attr(type='smoke')
Daryl Wallecked8bef32011-12-05 23:02:08 -060091 def test_reboot_server_soft(self):
Sean Dague4dd2c0b2013-01-03 17:50:28 -050092 # The server should be signaled to reboot gracefully
Daryl Walleck98e66dd2012-06-21 04:58:39 -050093 if self.run_ssh:
94 # Get the time the server was last rebooted,
Daryl Walleck98e66dd2012-06-21 04:58:39 -050095 resp, server = self.client.get_server(self.server_id)
96 linux_client = RemoteClient(server, self.ssh_user, self.password)
97 boot_time = linux_client.get_boot_time()
Daryl Walleck98e66dd2012-06-21 04:58:39 -050098
Brian Waldon3bde07f2011-12-13 15:11:22 -050099 resp, body = self.client.reboot(self.server_id, 'SOFT')
Daryl Wallecked8bef32011-12-05 23:02:08 -0600100 self.assertEqual(202, resp.status)
Brian Waldon3bde07f2011-12-13 15:11:22 -0500101 self.client.wait_for_server_status(self.server_id, 'ACTIVE')
Daryl Wallecked8bef32011-12-05 23:02:08 -0600102
Daryl Walleck98e66dd2012-06-21 04:58:39 -0500103 if self.run_ssh:
104 # Log in and verify the boot time has changed
105 linux_client = RemoteClient(server, self.ssh_user, self.password)
106 new_boot_time = linux_client.get_boot_time()
107 self.assertGreater(new_boot_time, boot_time)
108
Daryl Wallecked8bef32011-12-05 23:02:08 -0600109 @attr(type='smoke')
110 def test_rebuild_server(self):
Sean Dague4dd2c0b2013-01-03 17:50:28 -0500111 # The server should be rebuilt using the provided image and data
Daryl Wallecked8bef32011-12-05 23:02:08 -0600112 meta = {'rebuild': 'server'}
Brian Waldon738cd632011-12-12 18:45:09 -0500113 new_name = rand_name('server')
Daryl Wallecked8bef32011-12-05 23:02:08 -0600114 file_contents = 'Test server rebuild.'
Mahesh Panchaksharaiah21599a92013-07-03 15:28:58 +0530115 personality = [{'path': 'rebuild.txt',
Daryl Wallecked8bef32011-12-05 23:02:08 -0600116 'contents': base64.b64encode(file_contents)}]
Daryl Walleck98e66dd2012-06-21 04:58:39 -0500117 password = 'rebuildPassw0rd'
Brian Waldon3bde07f2011-12-13 15:11:22 -0500118 resp, rebuilt_server = self.client.rebuild(self.server_id,
Daryl Wallecked8bef32011-12-05 23:02:08 -0600119 self.image_ref_alt,
Brian Waldon738cd632011-12-12 18:45:09 -0500120 name=new_name, meta=meta,
Daryl Wallecked8bef32011-12-05 23:02:08 -0600121 personality=personality,
Daryl Walleck98e66dd2012-06-21 04:58:39 -0500122 adminPass=password)
Daryl Wallecked8bef32011-12-05 23:02:08 -0600123
Attila Fazekasf7f34f92013-08-01 17:01:44 +0200124 # Verify the properties in the initial response are correct
Brian Waldon3bde07f2011-12-13 15:11:22 -0500125 self.assertEqual(self.server_id, rebuilt_server['id'])
Eoghan Glynn57c1a3d2012-03-01 16:50:29 -0500126 rebuilt_image_id = rebuilt_server['image']['id']
127 self.assertTrue(self.image_ref_alt.endswith(rebuilt_image_id))
Matthew Treinish39e48ef2012-12-21 13:36:15 -0500128 self.assertEqual(self.flavor_ref, int(rebuilt_server['flavor']['id']))
Daryl Wallecked8bef32011-12-05 23:02:08 -0600129
Attila Fazekasf7f34f92013-08-01 17:01:44 +0200130 # Verify the server properties after the rebuild completes
Daryl Wallecked8bef32011-12-05 23:02:08 -0600131 self.client.wait_for_server_status(rebuilt_server['id'], 'ACTIVE')
132 resp, server = self.client.get_server(rebuilt_server['id'])
Eoghan Glynn57c1a3d2012-03-01 16:50:29 -0500133 rebuilt_image_id = rebuilt_server['image']['id']
134 self.assertTrue(self.image_ref_alt.endswith(rebuilt_image_id))
Brian Waldon738cd632011-12-12 18:45:09 -0500135 self.assertEqual(new_name, rebuilt_server['name'])
Daryl Wallecked8bef32011-12-05 23:02:08 -0600136
Daryl Walleck98e66dd2012-06-21 04:58:39 -0500137 if self.run_ssh:
138 # Verify that the user can authenticate with the provided password
139 linux_client = RemoteClient(server, self.ssh_user, password)
140 self.assertTrue(linux_client.can_authenticate())
141
Tiago Mello52d8fda2013-02-12 12:10:30 -0500142 def _detect_server_image_flavor(self, server_id):
143 # Detects the current server image flavor ref.
144 resp, server = self.client.get_server(self.server_id)
145 current_flavor = server['flavor']['id']
146 new_flavor_ref = self.flavor_ref_alt \
147 if int(current_flavor) == self.flavor_ref else self.flavor_ref
148 return int(current_flavor), int(new_flavor_ref)
149
ivan-zhu1feeb382013-01-24 10:14:39 +0800150 @testtools.skipIf(not resize_available, 'Resize not available.')
Giampaolo Lauriae9c77022013-05-22 01:23:58 -0400151 @attr(type='smoke')
Daryl Wallecked8bef32011-12-05 23:02:08 -0600152 def test_resize_server_confirm(self):
Sean Dague4dd2c0b2013-01-03 17:50:28 -0500153 # The server's RAM and disk space should be modified to that of
154 # the provided flavor
Daryl Wallecked8bef32011-12-05 23:02:08 -0600155
Tiago Mello52d8fda2013-02-12 12:10:30 -0500156 previous_flavor_ref, new_flavor_ref = \
157 self._detect_server_image_flavor(self.server_id)
158
159 resp, server = self.client.resize(self.server_id, new_flavor_ref)
Daryl Wallecked8bef32011-12-05 23:02:08 -0600160 self.assertEqual(202, resp.status)
Brian Waldon3bde07f2011-12-13 15:11:22 -0500161 self.client.wait_for_server_status(self.server_id, 'VERIFY_RESIZE')
Daryl Wallecked8bef32011-12-05 23:02:08 -0600162
Brian Waldon3bde07f2011-12-13 15:11:22 -0500163 self.client.confirm_resize(self.server_id)
164 self.client.wait_for_server_status(self.server_id, 'ACTIVE')
Daryl Wallecked8bef32011-12-05 23:02:08 -0600165
Brian Waldon3bde07f2011-12-13 15:11:22 -0500166 resp, server = self.client.get_server(self.server_id)
Tiago Mello52d8fda2013-02-12 12:10:30 -0500167 self.assertEqual(new_flavor_ref, int(server['flavor']['id']))
Daryl Wallecked8bef32011-12-05 23:02:08 -0600168
ivan-zhu1feeb382013-01-24 10:14:39 +0800169 @testtools.skipIf(not resize_available, 'Resize not available.')
Giulio Fidenteba3985a2013-05-29 01:46:36 +0200170 @attr(type='gate')
Daryl Wallecked8bef32011-12-05 23:02:08 -0600171 def test_resize_server_revert(self):
Sean Dague4dd2c0b2013-01-03 17:50:28 -0500172 # The server's RAM and disk space should return to its original
173 # values after a resize is reverted
Daryl Wallecked8bef32011-12-05 23:02:08 -0600174
Tiago Mello52d8fda2013-02-12 12:10:30 -0500175 previous_flavor_ref, new_flavor_ref = \
176 self._detect_server_image_flavor(self.server_id)
177
178 resp, server = self.client.resize(self.server_id, new_flavor_ref)
Daryl Wallecked8bef32011-12-05 23:02:08 -0600179 self.assertEqual(202, resp.status)
Brian Waldon3bde07f2011-12-13 15:11:22 -0500180 self.client.wait_for_server_status(self.server_id, 'VERIFY_RESIZE')
Daryl Wallecked8bef32011-12-05 23:02:08 -0600181
Brian Waldon3bde07f2011-12-13 15:11:22 -0500182 self.client.revert_resize(self.server_id)
183 self.client.wait_for_server_status(self.server_id, 'ACTIVE')
Daryl Wallecked8bef32011-12-05 23:02:08 -0600184
Daryl Walleckb43ce8a2012-02-26 19:14:25 -0600185 # Need to poll for the id change until lp#924371 is fixed
Brian Waldon3bde07f2011-12-13 15:11:22 -0500186 resp, server = self.client.get_server(self.server_id)
Daryl Walleckb43ce8a2012-02-26 19:14:25 -0600187 start = int(time.time())
188
Tiago Mello52d8fda2013-02-12 12:10:30 -0500189 while int(server['flavor']['id']) != previous_flavor_ref:
Daryl Walleckb43ce8a2012-02-26 19:14:25 -0600190 time.sleep(self.build_interval)
191 resp, server = self.client.get_server(self.server_id)
192
193 if int(time.time()) - start >= self.build_timeout:
194 message = 'Server %s failed to revert resize within the \
195 required time (%s s).' % (self.server_id, self.build_timeout)
196 raise exceptions.TimeoutException(message)
sapan-konaf1e3f002011-12-22 23:18:44 +0530197
Giampaolo Lauriae9c77022013-05-22 01:23:58 -0400198 @attr(type=['negative', 'gate'])
Joe Gordonddf39272012-09-13 15:04:55 -0700199 def test_reboot_nonexistent_server_soft(self):
Sean Dague4dd2c0b2013-01-03 17:50:28 -0500200 # Negative Test: The server reboot on non existent server should return
201 # an error
David Kranz5a23d862012-02-14 09:48:55 -0500202 self.assertRaises(exceptions.NotFound, self.client.reboot, 999, 'SOFT')
sapan-konaf1e3f002011-12-22 23:18:44 +0530203
Giampaolo Lauriae9c77022013-05-22 01:23:58 -0400204 @attr(type=['negative', 'gate'])
Joe Gordonddf39272012-09-13 15:04:55 -0700205 def test_rebuild_nonexistent_server(self):
Sean Dague4dd2c0b2013-01-03 17:50:28 -0500206 # Negative test: The server rebuild for a non existing server
207 # should not be allowed
sapan-konaf1e3f002011-12-22 23:18:44 +0530208 meta = {'rebuild': 'server'}
209 new_name = rand_name('server')
210 file_contents = 'Test server rebuild.'
211 personality = [{'path': '/etc/rebuild.txt',
212 'contents': base64.b64encode(file_contents)}]
Attila Fazekas45c3fbc2013-02-24 16:39:52 +0100213 self.assertRaises(exceptions.NotFound,
214 self.client.rebuild,
215 999, self.image_ref_alt,
216 name=new_name, meta=meta,
217 personality=personality,
218 adminPass='rebuild')
219
Giulio Fidenteba3985a2013-05-29 01:46:36 +0200220 @attr(type='gate')
Attila Fazekas45c3fbc2013-02-24 16:39:52 +0100221 def test_get_console_output(self):
222 # Positive test:Should be able to GET the console output
223 # for a given server_id and number of lines
224 def get_output():
225 resp, output = self.servers_client.get_console_output(
226 self.server_id, 10)
227 self.assertEqual(200, resp.status)
Ionuț Arțărișia767b522013-08-21 18:09:26 +0200228 self.assertTrue(output, "Console output was empty.")
Attila Fazekas45c3fbc2013-02-24 16:39:52 +0100229 lines = len(output.split('\n'))
230 self.assertEqual(lines, 10)
231 self.wait_for(get_output)
232
Giampaolo Lauriae9c77022013-05-22 01:23:58 -0400233 @attr(type=['negative', 'gate'])
Attila Fazekas45c3fbc2013-02-24 16:39:52 +0100234 def test_get_console_output_invalid_server_id(self):
235 # Negative test: Should not be able to get the console output
236 # for an invalid server_id
237 self.assertRaises(exceptions.NotFound,
238 self.servers_client.get_console_output,
239 '!@#$%^&*()', 10)
240
Giulio Fidente6cc3ade2013-08-23 17:21:03 +0200241 @testtools.skip('Skipped until the Bug #1014683 is resolved.')
Giulio Fidenteba3985a2013-05-29 01:46:36 +0200242 @attr(type='gate')
Attila Fazekas45c3fbc2013-02-24 16:39:52 +0100243 def test_get_console_output_server_id_in_reboot_status(self):
244 # Positive test:Should be able to GET the console output
245 # for a given server_id in reboot status
246 resp, output = self.servers_client.reboot(self.server_id, 'SOFT')
247 self.servers_client.wait_for_server_status(self.server_id,
248 'REBOOT')
249 resp, output = self.servers_client.get_console_output(self.server_id,
250 10)
251 self.assertEqual(200, resp.status)
Ionuț Arțăriși7f7d4522013-08-21 11:47:47 +0200252 self.assertIsNotNone(output)
Attila Fazekas45c3fbc2013-02-24 16:39:52 +0100253 lines = len(output.split('\n'))
254 self.assertEqual(lines, 10)
Dan Smithbc3bd242012-08-14 09:48:48 -0700255
Prem Karat6631f802013-07-04 12:07:33 +0530256 @attr(type='gate')
257 def test_pause_unpause_server(self):
258 resp, server = self.client.pause_server(self.server_id)
259 self.assertEqual(202, resp.status)
260 self.client.wait_for_server_status(self.server_id, 'PAUSED')
261 resp, server = self.client.unpause_server(self.server_id)
262 self.assertEqual(202, resp.status)
263 self.client.wait_for_server_status(self.server_id, 'ACTIVE')
264
265 @attr(type='gate')
266 def test_suspend_resume_server(self):
267 resp, server = self.client.suspend_server(self.server_id)
268 self.assertEqual(202, resp.status)
269 self.client.wait_for_server_status(self.server_id, 'SUSPENDED')
270 resp, server = self.client.resume_server(self.server_id)
271 self.assertEqual(202, resp.status)
272 self.client.wait_for_server_status(self.server_id, 'ACTIVE')
273
Andrea Frittolib05be602013-02-13 17:38:58 +0000274 @classmethod
275 def rebuild_servers(cls):
276 # Destroy any existing server and creates a new one
277 cls.clear_servers()
Sean Dague22897e12013-02-25 17:54:09 -0500278 resp, server = cls.create_server(wait_until='ACTIVE')
Andrea Frittolib05be602013-02-13 17:38:58 +0000279 cls.server_id = server['id']
280 cls.password = server['adminPass']
Andrea Frittolib05be602013-02-13 17:38:58 +0000281
Anju Tiwariaf98d222013-08-05 15:19:50 +0530282 @attr(type='gate')
283 def test_stop_start_server(self):
284 resp, server = self.servers_client.stop(self.server_id)
285 self.assertEqual(202, resp.status)
286 self.servers_client.wait_for_server_status(self.server_id, 'SHUTOFF')
287 resp, server = self.servers_client.start(self.server_id)
288 self.assertEqual(202, resp.status)
289 self.servers_client.wait_for_server_status(self.server_id, 'ACTIVE')
290
Zhu Zhu9643e512013-09-23 09:13:07 -0500291 @attr(type='gate')
292 def test_lock_unlock_server(self):
293 # Lock the server,try server stop(exceptions throw),unlock it and retry
294 resp, server = self.servers_client.lock_server(self.server_id)
295 self.assertEqual(202, resp.status)
296 resp, server = self.servers_client.get_server(self.server_id)
297 self.assertEqual(200, resp.status)
298 self.assertEqual(server['status'], 'ACTIVE')
299 # Locked server is not allowed to be stopped by non-admin user
300 self.assertRaises(exceptions.BadRequest,
301 self.servers_client.stop, self.server_id)
302 resp, server = self.servers_client.unlock_server(self.server_id)
303 self.assertEqual(202, resp.status)
304 resp, server = self.servers_client.stop(self.server_id)
305 self.assertEqual(202, resp.status)
306 self.servers_client.wait_for_server_status(self.server_id, 'SHUTOFF')
307 resp, server = self.servers_client.start(self.server_id)
308 self.assertEqual(202, resp.status)
309 self.servers_client.wait_for_server_status(self.server_id, 'ACTIVE')
310
Dan Smithbc3bd242012-08-14 09:48:48 -0700311
Attila Fazekas19044d52013-02-16 07:35:06 +0100312class ServerActionsTestXML(ServerActionsTestJSON):
313 _interface = 'xml'