e8d31a0b80
We don't need to have the vim headers in each source files. We can set it in our vimrc file instead. Also if set incorrectly, gate (pep8 check) will catch the mistakes. More discussions: http://lists.openstack.org/pipermail/openstack-dev/2013-October/017353.html Change-Id: I43703e2289212389c7841f44691ae7849ed1f505 Closes-Bug: #1229324
409 lines
18 KiB
Python
409 lines
18 KiB
Python
# Copyright 2012 OpenStack Foundation
|
|
# All Rights Reserved.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
import time
|
|
|
|
import testtools
|
|
|
|
from tempest.api.compute import base
|
|
from tempest.common.utils import data_utils
|
|
from tempest.common.utils.linux.remote_client import RemoteClient
|
|
from tempest import config
|
|
from tempest import exceptions
|
|
from tempest.test import attr
|
|
from tempest.test import skip_because
|
|
|
|
CONF = config.CONF
|
|
|
|
|
|
class ServerActionsV3TestJSON(base.BaseV3ComputeTest):
|
|
_interface = 'json'
|
|
resize_available = CONF.compute_feature_enabled.resize
|
|
run_ssh = CONF.compute.run_ssh
|
|
|
|
def setUp(self):
|
|
# NOTE(afazekas): Normally we use the same server with all test cases,
|
|
# but if it has an issue, we build a new one
|
|
super(ServerActionsV3TestJSON, self).setUp()
|
|
# Check if the server is in a clean state after test
|
|
try:
|
|
self.client.wait_for_server_status(self.server_id, 'ACTIVE')
|
|
except Exception:
|
|
# Rebuild server if something happened to it during a test
|
|
self.__class__.server_id = self.rebuild_server(self.server_id)
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
super(ServerActionsV3TestJSON, cls).setUpClass()
|
|
cls.client = cls.servers_client
|
|
cls.server_id = cls.rebuild_server(None)
|
|
|
|
@testtools.skipUnless(CONF.compute_feature_enabled.change_password,
|
|
'Change password not available.')
|
|
@attr(type='gate')
|
|
def test_change_server_password(self):
|
|
# The server's password should be set to the provided password
|
|
new_password = 'Newpass1234'
|
|
resp, body = self.client.change_password(self.server_id, new_password)
|
|
self.assertEqual(202, resp.status)
|
|
self.client.wait_for_server_status(self.server_id, 'ACTIVE')
|
|
|
|
if self.run_ssh:
|
|
# Verify that the user can authenticate with the new password
|
|
resp, server = self.client.get_server(self.server_id)
|
|
linux_client = RemoteClient(server, self.ssh_user, new_password)
|
|
linux_client.validate_authentication()
|
|
|
|
@attr(type='smoke')
|
|
def test_reboot_server_hard(self):
|
|
# The server should be power cycled
|
|
if self.run_ssh:
|
|
# Get the time the server was last rebooted,
|
|
resp, server = self.client.get_server(self.server_id)
|
|
linux_client = RemoteClient(server, self.ssh_user, self.password)
|
|
boot_time = linux_client.get_boot_time()
|
|
|
|
resp, body = self.client.reboot(self.server_id, 'HARD')
|
|
self.assertEqual(202, resp.status)
|
|
self.client.wait_for_server_status(self.server_id, 'ACTIVE')
|
|
|
|
if self.run_ssh:
|
|
# Log in and verify the boot time has changed
|
|
linux_client = RemoteClient(server, self.ssh_user, self.password)
|
|
new_boot_time = linux_client.get_boot_time()
|
|
self.assertGreater(new_boot_time, boot_time)
|
|
|
|
@skip_because(bug="1014647")
|
|
@attr(type='smoke')
|
|
def test_reboot_server_soft(self):
|
|
# The server should be signaled to reboot gracefully
|
|
if self.run_ssh:
|
|
# Get the time the server was last rebooted,
|
|
resp, server = self.client.get_server(self.server_id)
|
|
linux_client = RemoteClient(server, self.ssh_user, self.password)
|
|
boot_time = linux_client.get_boot_time()
|
|
|
|
resp, body = self.client.reboot(self.server_id, 'SOFT')
|
|
self.assertEqual(202, resp.status)
|
|
self.client.wait_for_server_status(self.server_id, 'ACTIVE')
|
|
|
|
if self.run_ssh:
|
|
# Log in and verify the boot time has changed
|
|
linux_client = RemoteClient(server, self.ssh_user, self.password)
|
|
new_boot_time = linux_client.get_boot_time()
|
|
self.assertGreater(new_boot_time, boot_time)
|
|
|
|
@attr(type='smoke')
|
|
def test_rebuild_server(self):
|
|
# The server should be rebuilt using the provided image and data
|
|
meta = {'rebuild': 'server'}
|
|
new_name = data_utils.rand_name('server')
|
|
password = 'rebuildPassw0rd'
|
|
resp, rebuilt_server = self.client.rebuild(self.server_id,
|
|
self.image_ref_alt,
|
|
name=new_name,
|
|
metadata=meta,
|
|
admin_password=password)
|
|
self.addCleanup(self.client.rebuild, self.server_id, self.image_ref)
|
|
|
|
# Verify the properties in the initial response are correct
|
|
self.assertEqual(self.server_id, rebuilt_server['id'])
|
|
rebuilt_image_id = rebuilt_server['image']['id']
|
|
self.assertTrue(self.image_ref_alt.endswith(rebuilt_image_id))
|
|
self.assertEqual(self.flavor_ref, rebuilt_server['flavor']['id'])
|
|
|
|
# Verify the server properties after the rebuild completes
|
|
self.client.wait_for_server_status(rebuilt_server['id'], 'ACTIVE')
|
|
resp, server = self.client.get_server(rebuilt_server['id'])
|
|
rebuilt_image_id = server['image']['id']
|
|
self.assertTrue(self.image_ref_alt.endswith(rebuilt_image_id))
|
|
self.assertEqual(new_name, server['name'])
|
|
|
|
if self.run_ssh:
|
|
# Verify that the user can authenticate with the provided password
|
|
linux_client = RemoteClient(server, self.ssh_user, password)
|
|
linux_client.validate_authentication()
|
|
|
|
@attr(type='gate')
|
|
def test_rebuild_server_in_stop_state(self):
|
|
# The server in stop state should be rebuilt using the provided
|
|
# image and remain in SHUTOFF state
|
|
resp, server = self.client.get_server(self.server_id)
|
|
old_image = server['image']['id']
|
|
new_image = self.image_ref_alt \
|
|
if old_image == self.image_ref else self.image_ref
|
|
resp, server = self.client.stop(self.server_id)
|
|
self.assertEqual(202, resp.status)
|
|
self.client.wait_for_server_status(self.server_id, 'SHUTOFF')
|
|
self.addCleanup(self.client.start, self.server_id)
|
|
resp, rebuilt_server = self.client.rebuild(self.server_id, new_image)
|
|
self.addCleanup(self.client.wait_for_server_status, self.server_id,
|
|
'SHUTOFF')
|
|
self.addCleanup(self.client.rebuild, self.server_id, old_image)
|
|
|
|
# Verify the properties in the initial response are correct
|
|
self.assertEqual(self.server_id, rebuilt_server['id'])
|
|
rebuilt_image_id = rebuilt_server['image']['id']
|
|
self.assertEqual(new_image, rebuilt_image_id)
|
|
self.assertEqual(self.flavor_ref, rebuilt_server['flavor']['id'])
|
|
|
|
# Verify the server properties after the rebuild completes
|
|
self.client.wait_for_server_status(rebuilt_server['id'], 'SHUTOFF')
|
|
resp, server = self.client.get_server(rebuilt_server['id'])
|
|
rebuilt_image_id = server['image']['id']
|
|
self.assertEqual(new_image, rebuilt_image_id)
|
|
|
|
def _detect_server_image_flavor(self, server_id):
|
|
# Detects the current server image flavor ref.
|
|
resp, server = self.client.get_server(server_id)
|
|
current_flavor = server['flavor']['id']
|
|
new_flavor_ref = self.flavor_ref_alt \
|
|
if current_flavor == self.flavor_ref else self.flavor_ref
|
|
return current_flavor, new_flavor_ref
|
|
|
|
@testtools.skipIf(not resize_available, 'Resize not available.')
|
|
@attr(type='smoke')
|
|
def test_resize_server_confirm(self):
|
|
# The server's RAM and disk space should be modified to that of
|
|
# the provided flavor
|
|
|
|
previous_flavor_ref, new_flavor_ref = \
|
|
self._detect_server_image_flavor(self.server_id)
|
|
|
|
resp, server = self.client.resize(self.server_id, new_flavor_ref)
|
|
self.assertEqual(202, resp.status)
|
|
self.client.wait_for_server_status(self.server_id, 'VERIFY_RESIZE')
|
|
|
|
self.client.confirm_resize(self.server_id)
|
|
self.client.wait_for_server_status(self.server_id, 'ACTIVE')
|
|
|
|
resp, server = self.client.get_server(self.server_id)
|
|
self.assertEqual(new_flavor_ref, server['flavor']['id'])
|
|
|
|
@testtools.skipIf(not resize_available, 'Resize not available.')
|
|
@attr(type='gate')
|
|
def test_resize_server_revert(self):
|
|
# The server's RAM and disk space should return to its original
|
|
# values after a resize is reverted
|
|
|
|
previous_flavor_ref, new_flavor_ref = \
|
|
self._detect_server_image_flavor(self.server_id)
|
|
|
|
resp, server = self.client.resize(self.server_id, new_flavor_ref)
|
|
self.assertEqual(202, resp.status)
|
|
self.client.wait_for_server_status(self.server_id, 'VERIFY_RESIZE')
|
|
|
|
self.client.revert_resize(self.server_id)
|
|
self.client.wait_for_server_status(self.server_id, 'ACTIVE')
|
|
|
|
# Need to poll for the id change until lp#924371 is fixed
|
|
resp, server = self.client.get_server(self.server_id)
|
|
start = int(time.time())
|
|
|
|
while server['flavor']['id'] != previous_flavor_ref:
|
|
time.sleep(self.build_interval)
|
|
resp, server = self.client.get_server(self.server_id)
|
|
|
|
if int(time.time()) - start >= self.build_timeout:
|
|
message = 'Server %s failed to revert resize within the \
|
|
required time (%s s).' % (self.server_id, self.build_timeout)
|
|
raise exceptions.TimeoutException(message)
|
|
|
|
@attr(type='gate')
|
|
def test_create_backup(self):
|
|
# Positive test:create backup successfully and rotate backups correctly
|
|
# create the first and the second backup
|
|
backup1 = data_utils.rand_name('backup')
|
|
resp, _ = self.servers_client.create_backup(self.server_id,
|
|
'daily',
|
|
2,
|
|
backup1)
|
|
oldest_backup_exist = True
|
|
|
|
# the oldest one should be deleted automatically in this test
|
|
def _clean_oldest_backup(oldest_backup):
|
|
if oldest_backup_exist:
|
|
self.images_client.delete_image(oldest_backup)
|
|
|
|
image1_id = data_utils.parse_image_id(resp['location'])
|
|
self.addCleanup(_clean_oldest_backup, image1_id)
|
|
self.assertEqual(202, resp.status)
|
|
self.images_client.wait_for_image_status(image1_id, 'active')
|
|
|
|
backup2 = data_utils.rand_name('backup')
|
|
self.servers_client.wait_for_server_status(self.server_id, 'ACTIVE')
|
|
resp, _ = self.servers_client.create_backup(self.server_id,
|
|
'daily',
|
|
2,
|
|
backup2)
|
|
image2_id = data_utils.parse_image_id(resp['location'])
|
|
self.addCleanup(self.images_client.delete_image, image2_id)
|
|
self.assertEqual(202, resp.status)
|
|
self.images_client.wait_for_image_status(image2_id, 'active')
|
|
|
|
# verify they have been created
|
|
properties = {
|
|
'image_type': 'backup',
|
|
'backup_type': "daily",
|
|
'instance_uuid': self.server_id,
|
|
}
|
|
resp, image_list = self.images_client.image_list_detail(
|
|
properties,
|
|
sort_key='created_at',
|
|
sort_dir='asc')
|
|
self.assertEqual(200, resp.status)
|
|
self.assertEqual(2, len(image_list))
|
|
self.assertEqual((backup1, backup2),
|
|
(image_list[0]['name'], image_list[1]['name']))
|
|
|
|
# create the third one, due to the rotation is 2,
|
|
# the first one will be deleted
|
|
backup3 = data_utils.rand_name('backup')
|
|
self.servers_client.wait_for_server_status(self.server_id, 'ACTIVE')
|
|
resp, _ = self.servers_client.create_backup(self.server_id,
|
|
'daily',
|
|
2,
|
|
backup3)
|
|
image3_id = data_utils.parse_image_id(resp['location'])
|
|
self.addCleanup(self.images_client.delete_image, image3_id)
|
|
self.assertEqual(202, resp.status)
|
|
# the first back up should be deleted
|
|
self.images_client.wait_for_resource_deletion(image1_id)
|
|
oldest_backup_exist = False
|
|
resp, image_list = self.images_client.image_list_detail(
|
|
properties,
|
|
sort_key='created_at',
|
|
sort_dir='asc')
|
|
self.assertEqual(200, resp.status)
|
|
self.assertEqual(2, len(image_list))
|
|
self.assertEqual((backup2, backup3),
|
|
(image_list[0]['name'], image_list[1]['name']))
|
|
|
|
def _get_output(self):
|
|
resp, output = self.servers_client.get_console_output(
|
|
self.server_id, 10)
|
|
self.assertEqual(200, resp.status)
|
|
self.assertTrue(output, "Console output was empty.")
|
|
lines = len(output.split('\n'))
|
|
self.assertEqual(lines, 10)
|
|
|
|
@attr(type='gate')
|
|
def test_get_console_output(self):
|
|
# Positive test:Should be able to GET the console output
|
|
# for a given server_id and number of lines
|
|
|
|
# This reboot is necessary for outputting some console log after
|
|
# creating a instance backup. If a instance backup, the console
|
|
# log file is truncated and we cannot get any console log through
|
|
# "console-log" API.
|
|
# The detail is https://bugs.launchpad.net/nova/+bug/1251920
|
|
resp, body = self.servers_client.reboot(self.server_id, 'HARD')
|
|
self.assertEqual(202, resp.status)
|
|
self.servers_client.wait_for_server_status(self.server_id, 'ACTIVE')
|
|
|
|
self.wait_for(self._get_output)
|
|
|
|
@attr(type='gate')
|
|
def test_get_console_output_server_id_in_shutoff_status(self):
|
|
# Positive test:Should be able to GET the console output
|
|
# for a given server_id in SHUTOFF status
|
|
|
|
# NOTE: SHUTOFF is irregular status. To avoid test instability,
|
|
# one server is created only for this test without using
|
|
# the server that was created in setupClass.
|
|
resp, server = self.create_test_server(wait_until='ACTIVE')
|
|
temp_server_id = server['id']
|
|
|
|
resp, server = self.servers_client.stop(temp_server_id)
|
|
self.assertEqual(202, resp.status)
|
|
self.servers_client.wait_for_server_status(temp_server_id, 'SHUTOFF')
|
|
|
|
self.wait_for(self._get_output)
|
|
|
|
@attr(type='gate')
|
|
def test_pause_unpause_server(self):
|
|
resp, server = self.client.pause_server(self.server_id)
|
|
self.assertEqual(202, resp.status)
|
|
self.client.wait_for_server_status(self.server_id, 'PAUSED')
|
|
resp, server = self.client.unpause_server(self.server_id)
|
|
self.assertEqual(202, resp.status)
|
|
self.client.wait_for_server_status(self.server_id, 'ACTIVE')
|
|
|
|
@attr(type='gate')
|
|
def test_suspend_resume_server(self):
|
|
resp, server = self.client.suspend_server(self.server_id)
|
|
self.assertEqual(202, resp.status)
|
|
self.client.wait_for_server_status(self.server_id, 'SUSPENDED')
|
|
resp, server = self.client.resume_server(self.server_id)
|
|
self.assertEqual(202, resp.status)
|
|
self.client.wait_for_server_status(self.server_id, 'ACTIVE')
|
|
|
|
@attr(type='gate')
|
|
def test_shelve_unshelve_server(self):
|
|
resp, server = self.client.shelve_server(self.server_id)
|
|
self.assertEqual(202, resp.status)
|
|
|
|
offload_time = self.config.compute.shelved_offload_time
|
|
if offload_time >= 0:
|
|
self.client.wait_for_server_status(self.server_id,
|
|
'SHELVED_OFFLOADED',
|
|
extra_timeout=offload_time)
|
|
else:
|
|
self.client.wait_for_server_status(self.server_id,
|
|
'SHELVED')
|
|
|
|
resp, server = self.client.get_server(self.server_id)
|
|
image_name = server['name'] + '-shelved'
|
|
resp, images = self.images_client.image_list(name=image_name)
|
|
self.assertEqual(1, len(images))
|
|
self.assertEqual(image_name, images[0]['name'])
|
|
|
|
resp, server = self.client.unshelve_server(self.server_id)
|
|
self.assertEqual(202, resp.status)
|
|
self.client.wait_for_server_status(self.server_id, 'ACTIVE')
|
|
|
|
@attr(type='gate')
|
|
def test_stop_start_server(self):
|
|
resp, server = self.servers_client.stop(self.server_id)
|
|
self.assertEqual(202, resp.status)
|
|
self.servers_client.wait_for_server_status(self.server_id, 'SHUTOFF')
|
|
resp, server = self.servers_client.start(self.server_id)
|
|
self.assertEqual(202, resp.status)
|
|
self.servers_client.wait_for_server_status(self.server_id, 'ACTIVE')
|
|
|
|
@attr(type='gate')
|
|
def test_lock_unlock_server(self):
|
|
# Lock the server,try server stop(exceptions throw),unlock it and retry
|
|
resp, server = self.servers_client.lock_server(self.server_id)
|
|
self.assertEqual(202, resp.status)
|
|
resp, server = self.servers_client.get_server(self.server_id)
|
|
self.assertEqual(200, resp.status)
|
|
self.assertEqual(server['status'], 'ACTIVE')
|
|
# Locked server is not allowed to be stopped by non-admin user
|
|
self.assertRaises(exceptions.Conflict,
|
|
self.servers_client.stop, self.server_id)
|
|
resp, server = self.servers_client.unlock_server(self.server_id)
|
|
self.assertEqual(202, resp.status)
|
|
resp, server = self.servers_client.stop(self.server_id)
|
|
self.assertEqual(202, resp.status)
|
|
self.servers_client.wait_for_server_status(self.server_id, 'SHUTOFF')
|
|
resp, server = self.servers_client.start(self.server_id)
|
|
self.assertEqual(202, resp.status)
|
|
self.servers_client.wait_for_server_status(self.server_id, 'ACTIVE')
|
|
|
|
|
|
class ServerActionsV3TestXML(ServerActionsV3TestJSON):
|
|
_interface = 'xml'
|