883cb26642
Change-Id: I4b14079ae47f61fc270d4e0554041f85f2185dbc
386 lines
14 KiB
Python
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']
|