tempest/kong/tests/test_server_actions.py

386 lines
14 KiB
Python

import json
import time
from kong import exceptions
from kong import openstack
from kong import tests
from kong.common import ssh
import unittest2 as unittest
class ServerActionsTest(tests.FunctionalTest):
def setUp(self):
super(ServerActionsTest, self).setUp()
self.os = openstack.Manager(self.nova)
self.multi_node = self.nova['multi_node'] == 'yes'
self.image_ref = self.glance['image_id']
self.image_ref_alt = self.glance['image_id_alt']
self.flavor_ref = self.nova['flavor_ref']
self.flavor_ref_alt = self.nova['flavor_ref_alt']
self.ssh_timeout = int(self.nova['ssh_timeout'])
self.build_timeout = int(self.nova['build_timeout'])
self.server_password = 'testpwd'
self.server_name = 'stacktester1'
expected_server = {
'name': self.server_name,
'imageRef': self.image_ref,
'flavorRef': self.flavor_ref,
'adminPass': self.server_password,
}
created_server = self.os.nova.create_server(expected_server)
self.server_id = created_server['id']
self._wait_for_server_status(self.server_id, 'ACTIVE')
server = self.os.nova.get_server(self.server_id)
self.access_ip = server['addresses']['public'][0]['addr']
# Ensure server came up
if self.ssh_timeout:
self._assert_ssh_password()
def tearDown(self):
self.os.nova.delete_server(self.server_id)
def _get_ssh_client(self, password):
return ssh.Client(self.access_ip, 'root', password, self.ssh_timeout)
def _assert_ssh_password(self, password=None):
_password = password or self.server_password
client = self._get_ssh_client(_password)
self.assertTrue(client.test_connection_auth())
def _wait_for_server_status(self, server_id, status):
try:
self.os.nova.wait_for_server_status(server_id, status,
timeout=self.build_timeout)
except exceptions.TimeoutException:
self.fail("Server failed to change status to %s" % status)
def _get_boot_time(self):
"""Return the time the server was started"""
output = self._read_file("/proc/uptime")
uptime = float(output.split().pop(0))
return time.time() - uptime
def _write_file(self, filename, contents, password=None):
command = "echo -n %s > %s" % (contents, filename)
return self._exec_command(command, password)
def _read_file(self, filename, password=None):
command = "cat %s" % filename
return self._exec_command(command, password)
def _exec_command(self, command, password=None):
if password is None:
password = self.server_password
client = self._get_ssh_client(password)
return client.exec_command(command)
def test_reboot_server(self):
"""Reboot a server SOFT and HARD"""
# SSH and get the uptime
if self.ssh_timeout:
initial_time_started = self._get_boot_time()
else:
intitial_time_started = 0
# Make reboot request
post_body = json.dumps({'reboot': {'type': 'SOFT'}})
url = "/servers/%s/action" % self.server_id
response, body = self.os.nova.request('POST', url, body=post_body)
self.assertEqual(response['status'], '202')
# Assert status transition
self._wait_for_server_status(self.server_id, 'REBOOT')
self._wait_for_server_status(self.server_id, 'ACTIVE')
# SSH and verify uptime is less than before
if self.ssh_timeout:
post_reboot_time_started = self._get_boot_time()
self.assertTrue(initial_time_started < post_reboot_time_started)
# SSH and get the uptime for the next reboot
initial_time_started = post_reboot_time_started
# Make reboot request
post_body = json.dumps({'reboot': {'type': 'HARD'}})
url = "/servers/%s/action" % self.server_id
response, body = self.os.nova.request('POST', url, body=post_body)
self.assertEqual(response['status'], '202')
# Assert status transition
# KNOWN-ISSUE 884906
#self._wait_for_server_status(self.server_id, 'HARD_REBOOT')
self._wait_for_server_status(self.server_id, 'REBOOT')
self._wait_for_server_status(self.server_id, 'ACTIVE')
# SSH and verify uptime is less than before
if self.ssh_timeout:
post_reboot_time_started = self._get_boot_time()
self.assertTrue(initial_time_started < post_reboot_time_started)
test_reboot_server.tags = ['nova']
def test_change_password(self):
"""Change root password of a server"""
# Change server password
post_body = json.dumps({'changePassword': {'adminPass': 'test123'}})
url = '/servers/%s/action' % self.server_id
response, body = self.os.nova.request('POST', url, body=post_body)
# Assert status transition
self.assertEqual('202', response['status'])
self._wait_for_server_status(self.server_id, 'PASSWORD')
self._wait_for_server_status(self.server_id, 'ACTIVE')
# SSH into server using new password
if self.ssh_timeout:
self._assert_ssh_password('test123')
test_change_password.tags = ['nova']
def test_rebuild(self):
"""Rebuild a server"""
FILENAME = '/tmp/testfile'
CONTENTS = 'WORDS'
# write file to server
if self.ssh_timeout:
self._write_file(FILENAME, CONTENTS)
self.assertEqual(self._read_file(FILENAME), CONTENTS)
# Make rebuild request
post_body = json.dumps({'rebuild': {'imageRef': self.image_ref_alt}})
url = '/servers/%s/action' % self.server_id
response, body = self.os.nova.request('POST', url, body=post_body)
# check output
self.assertEqual('202', response['status'])
rebuilt_server = json.loads(body)['server']
generated_password = rebuilt_server['adminPass']
# Ensure correct status transition
self._wait_for_server_status(self.server_id, 'REBUILD')
self._wait_for_server_status(self.server_id, 'ACTIVE')
# Treats an issue where we ssh'd in too soon after rebuild
#TODO(bcwaldon): fix the Xen driver so we don't have to sleep here
time.sleep(30)
# Check that the instance's imageRef matches the new imageRef
server = self.os.nova.get_server(self.server_id)
ref_match = self.image_ref_alt == server['image']['links'][0]['href']
id_match = self.image_ref_alt == server['image']['id']
self.assertTrue(ref_match or id_match)
# SSH into the server to ensure it came back up
if self.ssh_timeout:
self._assert_ssh_password(generated_password)
# make sure file is gone
self.assertEqual(self._read_file(FILENAME, generated_password), '')
# test again with a specified password
self._write_file(FILENAME, CONTENTS, generated_password)
_contents = self._read_file(FILENAME, generated_password)
self.assertEqual(_contents, CONTENTS)
specified_password = 'some_password'
# Make rebuild request
post_body = json.dumps({
'rebuild': {
'imageRef': self.image_ref,
'adminPass': specified_password,
}
})
url = '/servers/%s/action' % self.server_id
response, body = self.os.nova.request('POST', url, body=post_body)
# check output
self.assertEqual('202', response['status'])
rebuilt_server = json.loads(body)['server']
self.assertEqual(rebuilt_server['adminPass'], specified_password)
# Ensure correct status transition
self._wait_for_server_status(self.server_id, 'REBUILD')
self._wait_for_server_status(self.server_id, 'ACTIVE')
# Treats an issue where we ssh'd in too soon after rebuild
time.sleep(30)
# Check that the instance's imageRef matches the new imageRef
server = self.os.nova.get_server(self.server_id)
ref_match = self.image_ref == server['image']['links'][0]['href']
id_match = self.image_ref == server['image']['id']
self.assertTrue(ref_match or id_match)
# make sure file is gone
if self.ssh_timeout:
self.assertEqual(self._read_file(FILENAME, specified_password), '')
test_rebuild.tags = ['nova']
def test_resize(self):
"""Resize a server"""
# Make resize request
post_body = json.dumps({'resize': {'flavorRef': self.flavor_ref_alt}})
url = '/servers/%s/action' % self.server_id
response, body = self.os.nova.request('POST', url, body=post_body)
# Wait for status transition
self.assertEqual('202', response['status'])
self._wait_for_server_status(self.server_id, 'VERIFY_RESIZE')
# Ensure API reports new flavor
server = self.os.nova.get_server(self.server_id)
self.assertEqual(self.flavor_ref_alt, server['flavor']['id'])
#SSH into the server to ensure it came back up
if self.ssh_timeout:
self._assert_ssh_password()
# Make confirmResize request
post_body = json.dumps({'confirmResize': 'null'})
url = '/servers/%s/action' % self.server_id
response, body = self.os.nova.request('POST', url, body=post_body)
# Wait for status transition
self.assertEqual('204', response['status'])
self._wait_for_server_status(self.server_id, 'ACTIVE')
# Ensure API still reports new flavor
server = self.os.nova.get_server(self.server_id)
self.assertEqual(self.flavor_ref_alt, server['flavor']['id'])
test_resize.tags = ['nova']
def test_resize_revert(self):
"""Resize a server, then revert"""
# Make resize request
post_body = json.dumps({'resize': {'flavorRef': self.flavor_ref_alt}})
url = '/servers/%s/action' % self.server_id
response, body = self.os.nova.request('POST', url, body=post_body)
# Wait for status transition
self.assertEqual('202', response['status'])
self._wait_for_server_status(self.server_id, 'VERIFY_RESIZE')
# SSH into the server to ensure it came back up
if self.ssh_timeout:
self._assert_ssh_password()
# Ensure API reports new flavor
server = self.os.nova.get_server(self.server_id)
self.assertEqual(self.flavor_ref_alt, server['flavor']['id'])
# Make revertResize request
post_body = json.dumps({'revertResize': 'null'})
url = '/servers/%s/action' % self.server_id
response, body = self.os.nova.request('POST', url, body=post_body)
# Assert status transition
self.assertEqual('202', response['status'])
self._wait_for_server_status(self.server_id, 'ACTIVE')
# Ensure flavor ref was reverted to original
server = self.os.nova.get_server(self.server_id)
self.assertEqual(self.flavor_ref, server['flavor']['id'])
test_resize_revert.tags = ['nova']
class SnapshotTests(tests.FunctionalTest):
def setUp(self):
super(SnapshotTests, self).setUp()
self.os = openstack.Manager(self.nova)
self.image_ref = self.glance['image_id']
self.flavor_ref = self.nova['flavor_ref']
self.ssh_timeout = int(self.nova['ssh_timeout'])
self.build_timeout = int(self.nova['build_timeout'])
self.server_name = 'stacktester1'
expected_server = {
'name': self.server_name,
'imageRef': self.image_ref,
'flavorRef': self.flavor_ref,
}
created_server = self.os.nova.create_server(expected_server)
self.server_id = created_server['id']
def tearDown(self):
self.os.nova.delete_server(self.server_id)
def _wait_for_server_status(self, server_id, status):
try:
self.os.nova.wait_for_server_status(server_id, status,
timeout=self.build_timeout)
except exceptions.TimeoutException:
self.fail("Server failed to change status to %s" % status)
def test_snapshot(self):
"""Create image from an existing server"""
# Wait for server to come up before running this test
self._wait_for_server_status(self.server_id, 'ACTIVE')
# Create snapshot
image_data = {'name': 'testserver_snapshot'}
req_body = json.dumps({'createImage': image_data})
url = '/servers/%s/action' % self.server_id
response, body = self.os.nova.request('POST', url, body=req_body)
self.assertEqual(response['status'], '202')
image_ref = response['location']
snapshot_id = image_ref.rsplit('/', 1)[1]
# Get snapshot and check its attributes
resp, body = self.os.nova.request('GET', '/images/%s' % snapshot_id)
snapshot = json.loads(body)['image']
self.assertEqual(snapshot['name'], image_data['name'])
server_ref = snapshot['server']['links'][0]['href']
self.assertTrue(server_ref.endswith('/%s' % self.server_id))
# Wait for first snapshot to start saving before making second snapshot
self.os.nova.wait_for_image_status(snapshot['id'], 'SAVING')
# Create second snapshot
image_data = {'name': 'testserver_snapshot2'}
req_body = json.dumps({'createImage': image_data})
url = '/servers/%s/action' % self.server_id
response, body = self.os.nova.request('POST', url, body=req_body)
self.assertEqual(response['status'], '409')
# Ensure both snapshots succeed
self.os.nova.wait_for_image_status(snapshot['id'], 'ACTIVE')
# Cleaning up
self.os.nova.request('DELETE', '/images/%s' % snapshot_id)
test_snapshot.tags = ['nova']
def test_snapshot_while_building(self):
"""Ensure inability to snapshot server in BUILD state"""
# Ensure server is in BUILD state
url = '/servers/%s' % self.server_id
response, body = self.os.nova.request('GET', url)
server = json.loads(body)['server']
self.assertEqual(server['status'], 'BUILD', 'Server built too quickly')
# Create snapshot
req_body = json.dumps({'createImage': {'name': 'testserver_snapshot'}})
url = '/servers/%s/action' % self.server_id
response, body = self.os.nova.request('POST', url, body=req_body)
# KNOWN-ISSUE 885232
self.assertEqual(response['status'], '409')
test_snapshot_while_building.tags = ['nova']