Changes the namespace from storm to tempest, as well as adding addition tests and improvements

* Changed namespace from storm to tempest
* Added absolute limits service and server personality file tests
* Optimized run time for image metadata tests
* Added additional assertions for create server and rebuild server tests
* Removed any SSH verification until further decisions are made

Change-Id: I5bebd29be382c9404914c7314302670ae09627fc
This commit is contained in:
Daryl Walleck 2011-12-05 23:02:08 -06:00
parent 7f75763f54
commit ed8bef3a03
32 changed files with 443 additions and 330 deletions

View File

@ -1,8 +1,8 @@
To run: To run:
-rename the /etc/storm.conf.sample file to storm.conf -rename the /etc/tempest.conf.sample file to tempest.conf
-Set the fields in the file to values relevant to your system -Set the fields in the file to values relevant to your system
-Set the "authentication" value (basic or keystone_v2 currently supported) -Set the "authentication" value (basic or keystone_v2 currently supported)
-from the root directory of the project, run "nosetests storm/tests" to -from the root directory of the project, run "nosetests tempest/tests" to
run all tests run all tests
TODO: TODO:

View File

@ -1,158 +0,0 @@
from nose.plugins.attrib import attr
from storm import openstack
from storm.common.utils.data_utils import rand_name
import storm.config
import unittest2 as unittest
class ImagesMetadataTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.os = openstack.Manager()
cls.servers_client = cls.os.servers_client
cls.client = cls.os.images_client
cls.config = cls.os.config
cls.image_ref = cls.config.env.image_ref
cls.flavor_ref = cls.config.env.flavor_ref
cls.ssh_timeout = cls.config.nova.ssh_timeout
name = rand_name('server')
resp, cls.server = cls.servers_client.create_server(name,
cls.image_ref,
cls.flavor_ref)
#Wait for the server to become active
cls.servers_client.wait_for_server_status(cls.server['id'], 'ACTIVE')
#Create an image from the server
name = rand_name('image')
cls.meta = {'key1': 'value1', 'key2': 'value2'}
resp, body = cls.client.create_image(cls.server['id'], name, cls.meta)
image_ref = resp['location']
temp = image_ref.rsplit('/')
image_id = temp[len(temp) - 1]
cls.client.wait_for_image_resp_code(image_id, 200)
cls.client.wait_for_image_status(image_id, 'ACTIVE')
resp, cls.image = cls.client.get_image(image_id)
@classmethod
def tearDownClass(cls):
cls.servers_client.delete_server(cls.server['id'])
cls.client.delete_image(cls.image['id'])
def _parse_image_id(self, image_ref):
temp = image_ref.rsplit('/')
return len(temp) - 1
def test_list_image_metadata(self):
"""All metadata key/value pairs for an image should be returned"""
resp, metadata = self.client.list_image_metadata(self.image['id'])
self.assertEqual('value1', metadata['key1'])
self.assertEqual('value2', metadata['key2'])
def test_set_image_metadata(self):
"""The metadata for the image should match the new values"""
meta = {'meta1': 'data1'}
name = rand_name('server')
resp, server = self.servers_client.create_server(name, self.image_ref,
self.flavor_ref)
self.servers_client.wait_for_server_status(server['id'], 'ACTIVE')
name = rand_name('image')
resp, body = self.client.create_image(server['id'], name, meta)
image_id = self._parse_image_id(resp['location'])
self.client.wait_for_image_resp_code(image_id, 200)
self.client.wait_for_image_status(image_id, 'ACTIVE')
resp, image = self.client.get_image(image_id)
meta = {'meta2': 'data2', 'meta3': 'data3'}
resp, body = self.client.set_image_metadata(image['id'], meta)
resp, metadata = self.client.list_image_metadata(image['id'])
self.assertEqual('data2', metadata['meta2'])
self.assertEqual('data3', metadata['meta3'])
self.assertTrue('meta1' not in metadata)
self.servers_client.delete_server(server['id'])
self.client.delete_image(image['id'])
def test_update_image_metadata(self):
"""The metadata for the image should match the updated values"""
meta = {'key1': 'value1', 'key2': 'value2'}
name = rand_name('server')
resp, server = self.servers_client.create_server(name, self.image_ref,
self.flavor_ref)
self.servers_client.wait_for_server_status(server['id'], 'ACTIVE')
name = rand_name('image')
resp, body = self.client.create_image(server['id'], name, meta)
image_id = self._parse_image_id(resp['location'])
self.client.wait_for_image_resp_code(image_id, 200)
self.client.wait_for_image_status(image_id, 'ACTIVE')
resp, image = self.client.get_image(image_id)
meta = {'key1': 'alt1', 'key2': 'alt2'}
resp, metadata = self.client.update_image_metadata(image['id'], meta)
resp, metadata = self.client.list_image_metadata(image['id'])
self.assertEqual('alt1', metadata['key1'])
self.assertEqual('alt2', metadata['key2'])
self.servers_client.delete_server(server['id'])
self.client.delete_image(image['id'])
def test_get_image_metadata_item(self):
"""The value for a specic metadata key should be returned"""
resp, meta = self.client.get_image_metadata_item(self.image['id'],
'key2')
self.assertTrue('value2', meta['key2'])
def test_set_image_metadata_item(self):
"""
The value provided for the given meta item should be set for the image
"""
meta = {'nova': 'server'}
name = rand_name('server')
resp, server = self.servers_client.create_server(name, self.image_ref,
self.flavor_ref)
self.servers_client.wait_for_server_status(server['id'], 'ACTIVE')
name = rand_name('image')
resp, body = self.client.create_image(server['id'], name, meta)
image_id = self._parse_image_id(resp['location'])
self.client.wait_for_image_resp_code(image_id, 200)
self.client.wait_for_image_status(image_id, 'ACTIVE')
resp, image = self.client.get_image(image_id)
meta = {'nova': 'alt'}
resp, body = self.client.set_image_metadata_item(image['id'],
'nova', meta)
resp, metadata = self.client.list_image_metadata(image['id'])
self.assertEqual('alt', metadata['nova'])
self.servers_client.delete_server(server['id'])
self.client.delete_image(image['id'])
def test_delete_image_metadata_item(self):
"""The metadata value/key pair should be deleted from the image"""
meta = {'delkey': 'delvalue'}
name = rand_name('server')
resp, server = self.servers_client.create_server(name, self.image_ref,
self.flavor_ref)
self.servers_client.wait_for_server_status(server['id'], 'ACTIVE')
name = rand_name('image')
resp, body = self.client.create_image(server['id'], name, meta)
image_id = self._parse_image_id(resp['location'])
self.client.wait_for_image_resp_code(image_id, 200)
self.client.wait_for_image_status(image_id, 'ACTIVE')
resp, image = self.client.get_image(image_id)
resp, body = self.client.delete_image_metadata_item(image['id'],
'delkey')
resp, metadata = self.client.list_image_metadata(image['id'])
self.assertTrue('delkey' not in metadata)
self.servers_client.delete_server(server['id'])
self.client.delete_image(image['id'])

View File

@ -1,98 +0,0 @@
from nose.plugins.attrib import attr
from storm import openstack
import unittest2 as unittest
import storm.config
from storm.common.utils.data_utils import rand_name
# Some module-level skip conditions
resize_available = False
class ServerActionsTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.os = openstack.Manager()
cls.client = cls.os.servers_client
cls.config = cls.os.config
cls.image_ref = cls.config.env.image_ref
cls.image_ref_alt = cls.config.env.image_ref_alt
cls.flavor_ref = cls.config.env.flavor_ref
cls.flavor_ref_alt = cls.config.env.flavor_ref_alt
resize_available = cls.config.env.resize_available
def setUp(self):
self.name = rand_name('server')
resp, server = self.client.create_server(self.name, self.image_ref,
self.flavor_ref)
self.id = server['id']
self.client.wait_for_server_status(self.id, 'ACTIVE')
def tearDown(self):
self.client.delete_server(self.id)
@attr(type='smoke')
def test_change_server_password(self):
"""The server's password should be set to the provided password"""
resp, body = self.client.change_password(self.id, 'newpass')
self.client.wait_for_server_status(self.id, 'ACTIVE')
#TODO: SSH in to verify the new password works
@attr(type='smoke')
def test_reboot_server_hard(self):
""" The server should be power cycled """
#TODO: Add validation the server has been rebooted
resp, body = self.client.reboot(self.id, 'HARD')
self.client.wait_for_server_status(self.id, 'ACTIVE')
@attr(type='smoke')
def test_reboot_server_soft(self):
"""The server should be signaled to reboot gracefully"""
#TODO: Add validation the server has been rebooted
resp, body = self.client.reboot(self.id, 'SOFT')
self.client.wait_for_server_status(self.id, 'ACTIVE')
@attr(type='smoke')
def test_rebuild_server(self):
"""The server should be rebuilt using the provided image"""
self.client.rebuild(self.id, self.image_ref_alt, name='rebuiltserver')
self.client.wait_for_server_status(self.id, 'ACTIVE')
resp, server = self.client.get_server(self.id)
self.assertEqual(self.image_ref_alt, server['image']['id'])
self.assertEqual('rebuiltserver', server['name'])
@attr(type='smoke')
@unittest.skipIf(not resize_available, 'Resize not available.')
def test_resize_server_confirm(self):
"""
The server's RAM and disk space should be modified to that of
the provided flavor
"""
self.client.resize(self.id, self.flavor_ref_alt)
self.client.wait_for_server_status(self.id, 'VERIFY_RESIZE')
self.client.confirm_resize(self.id)
self.client.wait_for_server_status(self.id, 'ACTIVE')
resp, server = self.client.get_server(self.id)
self.assertEqual(self.flavor_ref_alt, server['flavor']['id'])
@attr(type='smoke')
@unittest.skipIf(not resize_available, 'Resize not available.')
def test_resize_server_revert(self):
"""
The server's RAM and disk space should return to its original
values after a resize is reverted
"""
self.client.resize(self.id, self.flavor_ref_alt)
self.client.wait_for_server_status(id, 'VERIFY_RESIZE')
self.client.revert_resize(self.id)
self.client.wait_for_server_status(id, 'ACTIVE')
resp, server = self.client.get_server(id)
self.assertEqual(self.flavor_ref, server['flavor']['id'])

View File

@ -2,8 +2,8 @@ import json
import httplib2 import httplib2
from storm import exceptions from tempest import exceptions
import storm.config import tempest.config
class RestClient(object): class RestClient(object):
@ -102,4 +102,12 @@ class RestClient(object):
body = json.loads(body) body = json.loads(body)
raise exceptions.BadRequest(body['badRequest']['message']) raise exceptions.BadRequest(body['badRequest']['message'])
if resp.status == 413:
body = json.loads(body)
raise exceptions.OverLimit(body['overLimit']['message'])
if resp.status in (500, 501):
body = json.loads(body)
raise exceptions.ComputeFault(body['computeFault']['message'])
return resp, body return resp, body

View File

@ -120,9 +120,10 @@ class EnvironmentConfig(object):
return self.get("authentication", 'keystone') return self.get("authentication", 'keystone')
class StormConfig(object): class TempestConfig(object):
"""Provides OpenStack configuration information.""" """Provides OpenStack configuration information."""
def __init__(self, conf_dir, conf_file): def __init__(self, conf_dir, conf_file):
""" """
Initialize a configuration from a conf directory and conf file. Initialize a configuration from a conf directory and conf file.

View File

@ -16,10 +16,18 @@ class BadRequest(Exception):
def __str__(self): def __str__(self):
return repr(self.message) return repr(self.message)
class AuthenticationFailure(Exception): class AuthenticationFailure(Exception):
msg = ("Authentication with user %(user)s and password " msg = ("Authentication with user %(user)s and password "
"%(password)s failed.") "%(password)s failed.")
def __init__(self, **kwargs): def __init__(self, **kwargs):
self.message = self.msg % kwargs self.message = self.msg % kwargs
class OverLimit(Exception):
def __init__(self, message):
self.message = message
def __str__(self):
return repr(self.message)

View File

@ -1,10 +1,11 @@
import os import os
from storm.services.nova.json.images_client import ImagesClient from tempest.services.nova.json.images_client import ImagesClient
from storm.services.nova.json.flavors_client import FlavorsClient from tempest.services.nova.json.flavors_client import FlavorsClient
from storm.services.nova.json.servers_client import ServersClient from tempest.services.nova.json.servers_client import ServersClient
from storm.common.utils import data_utils from tempest.services.nova.json.limits_client import LimitsClient
import storm.config from tempest.common.utils import data_utils
import tempest.config
class Manager(object): class Manager(object):
@ -48,6 +49,12 @@ class Manager(object):
self.config.nova.api_key, self.config.nova.api_key,
self.auth_url, self.auth_url,
self.config.nova.tenant_name) self.config.nova.tenant_name)
self.limits_client = LimitsClient(self.config,
self.config.nova.username,
self.config.nova.api_key,
self.auth_url,
self.config.nova.tenant_name)
else: else:
#Assuming basic/native authentication #Assuming basic/native authentication
self.servers_client = ServersClient(self.config, self.servers_client = ServersClient(self.config,
@ -63,3 +70,8 @@ class Manager(object):
self.config.nova.auth_url, self.config.nova.auth_url,
self.config.nova.api_key, self.config.nova.api_key,
self.auth_url) self.auth_url)
self.limits_client = LimitsClient(self.config,
self.config.nova.username,
self.config.nova.auth_url,
self.config.nova.api_key,
self.auth_url)

View File

@ -1,4 +1,4 @@
from storm.common import rest_client from tempest.common import rest_client
import json import json
import time import time

View File

@ -1,6 +1,7 @@
from storm.common import rest_client from tempest.common import rest_client
from tempest import exceptions
import json import json
import storm.config import tempest.config
import time import time
@ -10,6 +11,7 @@ class ImagesClient(object):
self.config = config self.config = config
self.client = rest_client.RestClient(config, username, key, self.client = rest_client.RestClient(config, username, key,
auth_url, tenant_name) auth_url, tenant_name)
self.build_interval = self.config.nova.build_interval self.build_interval = self.config.nova.build_interval
self.build_timeout = self.config.nova.build_timeout self.build_timeout = self.config.nova.build_timeout
self.headers = {'Content-Type': 'application/json', self.headers = {'Content-Type': 'application/json',

View File

@ -0,0 +1,26 @@
import json
from tempest.common import rest_client
class LimitsClient(object):
def __init__(self, username, key, auth_url, tenant_name=None):
self.client = rest_client.RestClient(config, username, key,
auth_url, tenant_name)
def get_limits(self):
resp, body = self.client.get("limits")
body = json.loads(body)
return resp, body['limits']
def get_max_server_meta(self):
resp, limits_dict = self.get_limits()
return resp, limits_dict['absolute']['maxServerMeta']
def get_personality_file_limit(self):
resp, limits_dict = self.get_limits()
return resp, limits_dict['absolute']['maxPersonality']
def get_personality_size_limit(self):
resp, limits_dict = self.get_limits()
return resp, limits_dict['absolute']['maxPersonalitySize']

View File

@ -1,7 +1,7 @@
from storm import exceptions from tempest import exceptions
from storm.common import rest_client from tempest.common import rest_client
import json import json
import storm.config import tempest.config
import time import time
@ -11,6 +11,7 @@ class ServersClient(object):
self.config = config self.config = config
self.client = rest_client.RestClient(config, username, key, self.client = rest_client.RestClient(config, username, key,
auth_url, tenant_name) auth_url, tenant_name)
self.build_interval = self.config.nova.build_interval self.build_interval = self.config.nova.build_interval
self.build_timeout = self.config.nova.build_timeout self.build_timeout = self.config.nova.build_timeout
self.headers = {'Content-Type': 'application/json', self.headers = {'Content-Type': 'application/json',

View File

@ -1,6 +1,6 @@
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
from storm import openstack from tempest import openstack
import storm.config import tempest.config
import unittest2 as unittest import unittest2 as unittest

View File

@ -0,0 +1,107 @@
from nose.plugins.attrib import attr
from tempest import openstack
from tempest.common.utils.data_utils import rand_name
import tempest.config
import unittest2 as unittest
class ImagesMetadataTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.os = openstack.Manager()
cls.servers_client = cls.os.servers_client
cls.client = cls.os.images_client
cls.config = cls.os.config
cls.image_ref = cls.config.env.image_ref
cls.flavor_ref = cls.config.env.flavor_ref
cls.ssh_timeout = cls.config.nova.ssh_timeout
name = rand_name('server')
resp, cls.server = cls.servers_client.create_server(name,
cls.image_ref,
cls.flavor_ref)
#Wait for the server to become active
cls.servers_client.wait_for_server_status(cls.server['id'], 'ACTIVE')
@classmethod
def tearDownClass(cls):
cls.servers_client.delete_server(cls.server['id'])
def setUp(self):
meta = {'key1': 'value1', 'key2': 'value2'}
name = rand_name('image')
resp, body = self.client.create_image(self.server['id'], name, meta)
image_ref = resp['location']
temp = image_ref.rsplit('/')
image_id = temp[6]
self.client.wait_for_image_resp_code(image_id, 200)
self.client.wait_for_image_status(image_id, 'ACTIVE')
resp, self.image = self.client.get_image(image_id)
def tearDown(self):
self.client.delete_image(self.image['id'])
def _parse_image_id(self, image_ref):
temp = image_ref.rsplit('/')
return len(temp) - 1
def test_list_image_metadata(self):
"""All metadata key/value pairs for an image should be returned"""
resp, metadata = self.client.list_image_metadata(self.image['id'])
self.assertEqual('value1', metadata['key1'])
self.assertEqual('value2', metadata['key2'])
def test_set_image_metadata(self):
"""The metadata for the image should match the new values"""
meta = {'meta1': 'data1'}
name = rand_name('image')
resp, body = self.client.create_image(self.server['id'], name, meta)
image_id = self._parse_image_id(resp['location'])
self.client.wait_for_image_resp_code(image_id, 200)
self.client.wait_for_image_status(image_id, 'ACTIVE')
resp, image = self.client.get_image(image_id)
meta = {'meta2': 'data2', 'meta3': 'data3'}
resp, body = self.client.set_image_metadata(image['id'], meta)
resp, metadata = self.client.list_image_metadata(image['id'])
self.assertEqual('data2', metadata['meta2'])
self.assertEqual('data3', metadata['meta3'])
self.assertTrue('key1' not in metadata)
self.servers_client.delete_server(server['id'])
self.client.delete_image(image['id'])
def test_update_image_metadata(self):
"""The metadata for the image should match the updated values"""
meta = {'key1': 'alt1', 'key2': 'alt2'}
resp, metadata = self.client.update_image_metadata(self.image['id'], meta)
resp, metadata = self.client.list_image_metadata(self.image['id'])
self.assertEqual('alt1', metadata['key1'])
self.assertEqual('alt2', metadata['key2'])
def test_get_image_metadata_item(self):
"""The value for a specic metadata key should be returned"""
resp, meta = self.client.get_image_metadata_item(self.image['id'],
'key2')
self.assertTrue('value2', meta['key2'])
def test_set_image_metadata_item(self):
"""
The value provided for the given meta item should be set for the image
"""
meta = {'key1': 'alt'}
resp, body = self.client.set_image_metadata_item(self.image['id'],
'key1', meta)
resp, metadata = self.client.list_image_metadata(self.image['id'])
self.assertEqual('alt', metadata['key1'])
def test_delete_image_metadata_item(self):
"""The metadata value/key pair should be deleted from the image"""
resp, body = self.client.delete_image_metadata_item(self.image['id'],
'key1')
resp, metadata = self.client.list_image_metadata(self.image['id'])
self.assertTrue('key1' not in metadata)

View File

@ -1,8 +1,8 @@
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
from storm import openstack from tempest import openstack
from storm.common.utils.data_utils import rand_name from tempest.common.utils.data_utils import rand_name
import unittest2 as unittest import unittest2 as unittest
import storm.config import tempest.config
# Some module-level skip conditions # Some module-level skip conditions
create_image_enabled = False create_image_enabled = False
@ -24,8 +24,9 @@ class ImagesTest(unittest.TestCase):
temp = image_ref.rsplit('/') temp = image_ref.rsplit('/')
return temp[6] return temp[6]
@unittest.skipIf(not create_image_enabled, @unittest.skipIf(not imaging_enabled,
'Environment unable to create images.') 'Environment unable to create images.')
@attr(type='smoke')
def test_create_delete_image(self): def test_create_delete_image(self):
"""An image for the provided server should be created""" """An image for the provided server should be created"""
server_name = rand_name('server') server_name = rand_name('server')
@ -36,7 +37,8 @@ class ImagesTest(unittest.TestCase):
#Create a new image #Create a new image
name = rand_name('image') name = rand_name('image')
resp, body = self.client.create_image(server['id'], name) meta = {'image_type': 'test'}
resp, body = self.client.create_image(server['id'], name, meta)
image_id = self._parse_image_id(resp['location']) image_id = self._parse_image_id(resp['location'])
self.client.wait_for_image_resp_code(image_id, 200) self.client.wait_for_image_resp_code(image_id, 200)
self.client.wait_for_image_status(image_id, 'ACTIVE') self.client.wait_for_image_status(image_id, 'ACTIVE')
@ -44,27 +46,13 @@ class ImagesTest(unittest.TestCase):
#Verify the image was created correctly #Verify the image was created correctly
resp, image = self.client.get_image(image_id) resp, image = self.client.get_image(image_id)
self.assertEqual(name, image['name']) self.assertEqual(name, image['name'])
self.assertEqual('test', image['metadata']['image_type'])
#Verify minRAM and minDisk values are the same as the original image
resp, original_image = self.client.get_image(self.image_ref)
self.assertEqual(original_image['minRam'], image['minRam'])
self.assertEqual(original_image['minDisk'], image['minDisk'])
#Teardown #Teardown
self.client.delete_image(image['id']) self.client.delete_image(image['id'])
self.servers_client.delete_server(server['id']) self.servers_client.delete_server(server['id'])
@attr(type='smoke')
def test_get_image(self):
"""Returns the correct details for a single image"""
resp, image = self.client.get_image(self.image_ref)
self.assertEqual(self.image_ref, image['id'])
@attr(type='smoke')
def test_list_images(self):
"""The list of all images should contain the image flavor"""
resp, images = self.client.list_images()
found = any([i for i in images if i['id'] == self.image_ref])
self.assertTrue(found)
@attr(type='smoke')
def test_list_images_with_detail(self):
"""Detailed list of all images should contain the expected image"""
resp, images = self.client.list_images_with_detail()
found = any([i for i in images if i['id'] == self.image_ref])
self.assertTrue(found)

View File

@ -0,0 +1,37 @@
from nose.plugins.attrib import attr
from tempest import openstack
from tempest.common.utils.data_utils import rand_name
import unittest2 as unittest
import tempest.config
class ListImagesTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.os = openstack.Manager()
cls.client = cls.os.images_client
cls.servers_client = cls.os.servers_client
cls.config = cls.os.config
cls.image_ref = cls.config.env.image_ref
cls.flavor_ref = cls.config.env.flavor_ref
@attr(type='smoke')
def test_get_image(self):
"""Returns the correct details for a single image"""
resp, image = self.client.get_image(self.image_ref)
self.assertEqual(self.image_ref, image['id'])
@attr(type='smoke')
def test_list_images(self):
"""The list of all images should contain the image"""
resp, images = self.client.list_images()
found = any([i for i in images if i['id'] == self.image_ref])
self.assertTrue(found)
@attr(type='smoke')
def test_list_images_with_detail(self):
"""Detailed list of all images should contain the expected image"""
resp, images = self.client.list_images_with_detail()
found = any([i for i in images if i['id'] == self.image_ref])
self.assertTrue(found)

View File

@ -1,8 +1,8 @@
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
from storm import openstack from tempest import openstack
from storm.common.utils.data_utils import rand_name from tempest.common.utils.data_utils import rand_name
import unittest2 as unittest import unittest2 as unittest
import storm.config import tempest.config
class ServerDetailsTest(unittest.TestCase): class ServerDetailsTest(unittest.TestCase):

View File

@ -0,0 +1,113 @@
from nose.plugins.attrib import attr
from tempest import openstack
from tempest.common.utils.data_utils import rand_name
import unittest2 as unittest
import tempest.config
import base64
class ServerActionsTest(unittest.TestCase):
resize_available = tempest.config.TempestConfig().env.resize_available
@classmethod
def setUpClass(cls):
cls.os = openstack.Manager()
cls.client = cls.os.servers_client
cls.config = cls.os.config
cls.image_ref = cls.config.env.image_ref
cls.image_ref_alt = cls.config.env.image_ref_alt
cls.flavor_ref = cls.config.env.flavor_ref
cls.flavor_ref_alt = cls.config.env.flavor_ref_alt
def setUp(self):
self.name = rand_name('server')
resp, self.server = self.client.create_server(self.name,
self.image_ref,
self.flavor_ref)
self.client.wait_for_server_status(self.server['id'], 'ACTIVE')
def tearDown(self):
self.client.delete_server(self.id)
@attr(type='smoke')
def test_change_server_password(self):
"""The server's password should be set to the provided password"""
resp, body = self.client.change_password(self.server['id'], 'newpass')
self.assertEqual(202, resp.status)
self.client.wait_for_server_status(self.server['id'], 'ACTIVE')
@attr(type='smoke')
def test_reboot_server_hard(self):
""" The server should be power cycled """
resp, body = self.client.reboot(self.server['id'], 'HARD')
self.assertEqual(202, resp.status)
self.client.wait_for_server_status(self.server['id'], 'ACTIVE')
@attr(type='smoke')
def test_reboot_server_soft(self):
"""The server should be signaled to reboot gracefully"""
resp, body = self.client.reboot(self.server['id'], 'SOFT')
self.assertEqual(202, resp.status)
self.client.wait_for_server_status(self.server['id'], 'ACTIVE')
@attr(type='smoke')
def test_rebuild_server(self):
""" The server should be rebuilt using the provided image and data """
meta = {'rebuild': 'server'}
name = rand_name('server')
file_contents = 'Test server rebuild.'
personality = [{'path': '/etc/rebuild.txt',
'contents': base64.b64encode(file_contents)}]
resp, rebuilt_server = self.client.rebuild(self.server['id'],
self.image_ref_alt,
name=name, meta=meta,
personality=personality,
adminPass='rebuild')
#Verify the properties in the initial response are correct
self.assertEqual(self.server['id'], rebuilt_server['id'])
self.assertEqual(self.image_ref_alt, rebuilt_server['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'])
self.assertEqual(self.image_ref_alt, rebuilt_server['image']['id'])
self.assertEqual('rebuiltserver', rebuilt_server['name'])
@attr(type='smoke')
@unittest.skipIf(not resize_available, 'Resize not available.')
def test_resize_server_confirm(self):
"""
The server's RAM and disk space should be modified to that of
the provided flavor
"""
resp, server = self.client.resize(self.id, self.flavor_ref_alt)
self.assertEqual(202, resp.status)
self.client.wait_for_server_status(self.id, 'VERIFY_RESIZE')
self.client.confirm_resize(self.id)
self.client.wait_for_server_status(self.id, 'ACTIVE')
resp, server = self.client.get_server(self.id)
self.assertEqual(self.flavor_ref_alt, server['flavor']['id'])
@attr(type='smoke')
@unittest.skipIf(not resize_available, 'Resize not available.')
def test_resize_server_revert(self):
"""
The server's RAM and disk space should return to its original
values after a resize is reverted
"""
resp, server = self.client.resize(self.id, self.flavor_ref_alt)
self.assertEqual(202, resp.status)
self.client.wait_for_server_status(id, 'VERIFY_RESIZE')
self.client.revert_resize(self.id)
self.client.wait_for_server_status(id, 'ACTIVE')
resp, server = self.client.get_server(id)
self.assertEqual(self.flavor_ref, server['flavor']['id'])

View File

@ -1,8 +1,8 @@
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
from storm import openstack from tempest import openstack
from storm.common.utils.data_utils import rand_name from tempest.common.utils.data_utils import rand_name
import unittest2 as unittest import unittest2 as unittest
import storm.config import tempest.config
class ServerMetadataTest(unittest.TestCase): class ServerMetadataTest(unittest.TestCase):

View File

@ -0,0 +1,67 @@
from nose.plugins.attrib import attr
from tempest import openstack
from tempest import exceptions
from tempest.common.utils.data_utils import rand_name
import base64
import tempest.config
import unittest2 as unittest
class ServerPersonalityTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.os = openstack.Manager()
cls.client = cls.os.servers_client
cls.config = cls.config = cls.os.config
cls.image_ref = cls.config.env.image_ref
cls.flavor_ref = cls.config.env.flavor_ref
cls.user_client = cls.os.limits_client
def test_personality_files_exceed_limit(self):
"""
Server creation should fail if greater than the maximum allowed
number of files are injected into the server.
"""
name = rand_name('server')
file_contents = 'This is a test file.'
personality = []
resp, max_file_limit = self.user_client.get_personality_file_limit()
for i in range(0, max_file_limit + 1):
path = 'etc/test' + str(i) + '.txt'
personality.append({'path': path,
'contents': base64.b64encode(file_contents)})
try:
resp, resp_body = self.client.create_server(name, self.image_ref,
self.flavor_ref,
personality=personality)
except exceptions.OverLimit:
pass
else:
self.fail('This request did not fail as expected')
@attr(type='positive')
def test_can_create_server_with_max_number_personality_files(self):
"""
Server should be created successfully if maximum allowed number of
files is injected into the server during creation.
"""
name = rand_name('server')
file_contents = 'This is a test file.'
resp, max_file_limit = self.user_client.get_personality_file_limit()
self.assertEqual(200, resp.status)
personality = []
for i in range(0, max_file_limit):
path = 'etc/test' + str(i) + '.txt'
personality.append({'path': path,
'contents': base64.b64encode(file_contents)})
resp, server = self.client.create_server(name, self.image_ref,
self.flavor_ref,
personality=personality)
self.assertEqual('202', resp['status'])
#Teardown
self.client.delete_server(server['id'])

View File

@ -1,9 +1,9 @@
from storm.common import ssh from tempest.common import ssh
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
from storm import openstack from tempest import openstack
from storm.common.utils.data_utils import rand_name from tempest.common.utils.data_utils import rand_name
import base64 import base64
import storm.config import tempest.config
import unittest2 as unittest import unittest2 as unittest
@ -16,7 +16,6 @@ class ServersTest(unittest.TestCase):
cls.config = cls.os.config cls.config = cls.os.config
cls.image_ref = cls.config.env.image_ref cls.image_ref = cls.config.env.image_ref
cls.flavor_ref = cls.config.env.flavor_ref cls.flavor_ref = cls.config.env.flavor_ref
cls.ssh_timeout = cls.config.nova.ssh_timeout
@attr(type='smoke') @attr(type='smoke')
def test_create_delete_server(self): def test_create_delete_server(self):
@ -34,6 +33,10 @@ class ServersTest(unittest.TestCase):
accessIPv4=accessIPv4, accessIPv4=accessIPv4,
accessIPv6=accessIPv6, accessIPv6=accessIPv6,
personality=personality) personality=personality)
#Check the initial response
self.assertEqual(202, resp.status)
self.assertTrue(server['id'] is not None)
self.assertTrue(server['adminPass'] is not None)
#Wait for the server to become active #Wait for the server to become active
self.client.wait_for_server_status(server['id'], 'ACTIVE') self.client.wait_for_server_status(server['id'], 'ACTIVE')
@ -46,8 +49,9 @@ class ServersTest(unittest.TestCase):
self.assertEqual(self.image_ref, server['image']['id']) self.assertEqual(self.image_ref, server['image']['id'])
self.assertEqual(str(self.flavor_ref), server['flavor']['id']) self.assertEqual(str(self.flavor_ref), server['flavor']['id'])
#Teardown #Delete the server
self.client.delete_server(self.id) resp, body = self.client.delete_server(server['id'])
self.assertEqual(204, resp.status)
@attr(type='smoke') @attr(type='smoke')
def test_create_server_with_admin_password(self): def test_create_server_with_admin_password(self):
@ -64,14 +68,6 @@ class ServersTest(unittest.TestCase):
#Verify the password is set correctly in the response #Verify the password is set correctly in the response
self.assertEqual('testpassword', server['adminPass']) self.assertEqual('testpassword', server['adminPass'])
#SSH into the server using the set password
self.client.wait_for_server_status(server['id'], 'ACTIVE')
resp, addresses = self.client.list_addresses(server['id'])
ip = addresses['public'][0]['addr']
client = ssh.Client(ip, 'root', 'testpassword', self.ssh_timeout)
self.assertTrue(client.test_connection_auth())
#Teardown #Teardown
self.client.delete_server(server['id']) self.client.delete_server(server['id'])
@ -84,7 +80,8 @@ class ServersTest(unittest.TestCase):
self.client.wait_for_server_status(server['id'], 'ACTIVE') self.client.wait_for_server_status(server['id'], 'ACTIVE')
#Update the server with a new name #Update the server with a new name
self.client.update_server(server['id'], name='newname') resp, server = self.client.update_server(server['id'], name='newname')
self.assertEquals(200, resp.status)
self.client.wait_for_server_status(server['id'], 'ACTIVE') self.client.wait_for_server_status(server['id'], 'ACTIVE')
#Verify the name of the server has changed #Verify the name of the server has changed
@ -105,8 +102,10 @@ class ServersTest(unittest.TestCase):
self.client.wait_for_server_status(server['id'], 'ACTIVE') self.client.wait_for_server_status(server['id'], 'ACTIVE')
#Update the IPv4 and IPv6 access addresses #Update the IPv4 and IPv6 access addresses
self.client.update_server(server['id'], accessIPv4='1.1.1.1', resp, body = self.client.update_server(server['id'],
accessIPv6='::babe:2.2.2.2') accessIPv4='1.1.1.1',
accessIPv6='::babe:2.2.2.2')
self.assertEqual(200, resp.status)
self.client.wait_for_server_status(server['id'], 'ACTIVE') self.client.wait_for_server_status(server['id'], 'ACTIVE')
#Verify the access addresses have been updated #Verify the access addresses have been updated

View File

@ -1,11 +1,11 @@
import unittest2 as unittest import unittest2 as unittest
import storm.config import tempest.config
import base64 import base64
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
from storm import openstack from tempest import openstack
from storm.common.utils.data_utils import rand_name from tempest.common.utils.data_utils import rand_name
from storm.common import ssh from tempest.common import ssh
from storm import exceptions from tempest import exceptions
class ServersNegativeTest(unittest.TestCase): class ServersNegativeTest(unittest.TestCase):