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:
parent
7f75763f54
commit
ed8bef3a03
|
@ -1,8 +1,8 @@
|
|||
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 "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
|
||||
|
||||
TODO:
|
|
@ -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'])
|
|
@ -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'])
|
|
@ -2,8 +2,8 @@ import json
|
|||
|
||||
import httplib2
|
||||
|
||||
from storm import exceptions
|
||||
import storm.config
|
||||
from tempest import exceptions
|
||||
import tempest.config
|
||||
|
||||
|
||||
class RestClient(object):
|
||||
|
@ -102,4 +102,12 @@ class RestClient(object):
|
|||
body = json.loads(body)
|
||||
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
|
|
@ -120,9 +120,10 @@ class EnvironmentConfig(object):
|
|||
return self.get("authentication", 'keystone')
|
||||
|
||||
|
||||
class StormConfig(object):
|
||||
class TempestConfig(object):
|
||||
"""Provides OpenStack configuration information."""
|
||||
|
||||
|
||||
def __init__(self, conf_dir, conf_file):
|
||||
"""
|
||||
Initialize a configuration from a conf directory and conf file.
|
|
@ -23,3 +23,11 @@ class AuthenticationFailure(Exception):
|
|||
"%(password)s failed.")
|
||||
def __init__(self, **kwargs):
|
||||
self.message = self.msg % kwargs
|
||||
|
||||
|
||||
class OverLimit(Exception):
|
||||
def __init__(self, message):
|
||||
self.message = message
|
||||
|
||||
def __str__(self):
|
||||
return repr(self.message)
|
|
@ -1,10 +1,11 @@
|
|||
import os
|
||||
|
||||
from storm.services.nova.json.images_client import ImagesClient
|
||||
from storm.services.nova.json.flavors_client import FlavorsClient
|
||||
from storm.services.nova.json.servers_client import ServersClient
|
||||
from storm.common.utils import data_utils
|
||||
import storm.config
|
||||
from tempest.services.nova.json.images_client import ImagesClient
|
||||
from tempest.services.nova.json.flavors_client import FlavorsClient
|
||||
from tempest.services.nova.json.servers_client import ServersClient
|
||||
from tempest.services.nova.json.limits_client import LimitsClient
|
||||
from tempest.common.utils import data_utils
|
||||
import tempest.config
|
||||
|
||||
|
||||
class Manager(object):
|
||||
|
@ -48,6 +49,12 @@ class Manager(object):
|
|||
self.config.nova.api_key,
|
||||
self.auth_url,
|
||||
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:
|
||||
#Assuming basic/native authentication
|
||||
self.servers_client = ServersClient(self.config,
|
||||
|
@ -63,3 +70,8 @@ class Manager(object):
|
|||
self.config.nova.auth_url,
|
||||
self.config.nova.api_key,
|
||||
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)
|
|
@ -1,4 +1,4 @@
|
|||
from storm.common import rest_client
|
||||
from tempest.common import rest_client
|
||||
import json
|
||||
import time
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
from storm.common import rest_client
|
||||
from tempest.common import rest_client
|
||||
from tempest import exceptions
|
||||
import json
|
||||
import storm.config
|
||||
import tempest.config
|
||||
import time
|
||||
|
||||
|
||||
|
@ -10,6 +11,7 @@ class ImagesClient(object):
|
|||
self.config = config
|
||||
self.client = rest_client.RestClient(config, username, key,
|
||||
auth_url, tenant_name)
|
||||
|
||||
self.build_interval = self.config.nova.build_interval
|
||||
self.build_timeout = self.config.nova.build_timeout
|
||||
self.headers = {'Content-Type': 'application/json',
|
|
@ -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']
|
|
@ -1,7 +1,7 @@
|
|||
from storm import exceptions
|
||||
from storm.common import rest_client
|
||||
from tempest import exceptions
|
||||
from tempest.common import rest_client
|
||||
import json
|
||||
import storm.config
|
||||
import tempest.config
|
||||
import time
|
||||
|
||||
|
||||
|
@ -11,6 +11,7 @@ class ServersClient(object):
|
|||
self.config = config
|
||||
self.client = rest_client.RestClient(config, username, key,
|
||||
auth_url, tenant_name)
|
||||
|
||||
self.build_interval = self.config.nova.build_interval
|
||||
self.build_timeout = self.config.nova.build_timeout
|
||||
self.headers = {'Content-Type': 'application/json',
|
|
@ -1,6 +1,6 @@
|
|||
from nose.plugins.attrib import attr
|
||||
from storm import openstack
|
||||
import storm.config
|
||||
from tempest import openstack
|
||||
import tempest.config
|
||||
import unittest2 as unittest
|
||||
|
||||
|
|
@ -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)
|
|
@ -1,8 +1,8 @@
|
|||
from nose.plugins.attrib import attr
|
||||
from storm import openstack
|
||||
from storm.common.utils.data_utils import rand_name
|
||||
from tempest import openstack
|
||||
from tempest.common.utils.data_utils import rand_name
|
||||
import unittest2 as unittest
|
||||
import storm.config
|
||||
import tempest.config
|
||||
|
||||
# Some module-level skip conditions
|
||||
create_image_enabled = False
|
||||
|
@ -24,8 +24,9 @@ class ImagesTest(unittest.TestCase):
|
|||
temp = image_ref.rsplit('/')
|
||||
return temp[6]
|
||||
|
||||
@unittest.skipIf(not create_image_enabled,
|
||||
@unittest.skipIf(not imaging_enabled,
|
||||
'Environment unable to create images.')
|
||||
@attr(type='smoke')
|
||||
def test_create_delete_image(self):
|
||||
"""An image for the provided server should be created"""
|
||||
server_name = rand_name('server')
|
||||
|
@ -36,7 +37,8 @@ class ImagesTest(unittest.TestCase):
|
|||
|
||||
#Create a new 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'])
|
||||
self.client.wait_for_image_resp_code(image_id, 200)
|
||||
self.client.wait_for_image_status(image_id, 'ACTIVE')
|
||||
|
@ -44,27 +46,13 @@ class ImagesTest(unittest.TestCase):
|
|||
#Verify the image was created correctly
|
||||
resp, image = self.client.get_image(image_id)
|
||||
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
|
||||
self.client.delete_image(image['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)
|
|
@ -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)
|
|
@ -1,8 +1,8 @@
|
|||
from nose.plugins.attrib import attr
|
||||
from storm import openstack
|
||||
from storm.common.utils.data_utils import rand_name
|
||||
from tempest import openstack
|
||||
from tempest.common.utils.data_utils import rand_name
|
||||
import unittest2 as unittest
|
||||
import storm.config
|
||||
import tempest.config
|
||||
|
||||
|
||||
class ServerDetailsTest(unittest.TestCase):
|
|
@ -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'])
|
|
@ -1,8 +1,8 @@
|
|||
from nose.plugins.attrib import attr
|
||||
from storm import openstack
|
||||
from storm.common.utils.data_utils import rand_name
|
||||
from tempest import openstack
|
||||
from tempest.common.utils.data_utils import rand_name
|
||||
import unittest2 as unittest
|
||||
import storm.config
|
||||
import tempest.config
|
||||
|
||||
|
||||
class ServerMetadataTest(unittest.TestCase):
|
|
@ -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'])
|
|
@ -1,9 +1,9 @@
|
|||
from storm.common import ssh
|
||||
from tempest.common import ssh
|
||||
from nose.plugins.attrib import attr
|
||||
from storm import openstack
|
||||
from storm.common.utils.data_utils import rand_name
|
||||
from tempest import openstack
|
||||
from tempest.common.utils.data_utils import rand_name
|
||||
import base64
|
||||
import storm.config
|
||||
import tempest.config
|
||||
import unittest2 as unittest
|
||||
|
||||
|
||||
|
@ -16,7 +16,6 @@ class ServersTest(unittest.TestCase):
|
|||
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
|
||||
|
||||
@attr(type='smoke')
|
||||
def test_create_delete_server(self):
|
||||
|
@ -34,6 +33,10 @@ class ServersTest(unittest.TestCase):
|
|||
accessIPv4=accessIPv4,
|
||||
accessIPv6=accessIPv6,
|
||||
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
|
||||
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(str(self.flavor_ref), server['flavor']['id'])
|
||||
|
||||
#Teardown
|
||||
self.client.delete_server(self.id)
|
||||
#Delete the server
|
||||
resp, body = self.client.delete_server(server['id'])
|
||||
self.assertEqual(204, resp.status)
|
||||
|
||||
@attr(type='smoke')
|
||||
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
|
||||
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
|
||||
self.client.delete_server(server['id'])
|
||||
|
||||
|
@ -84,7 +80,8 @@ class ServersTest(unittest.TestCase):
|
|||
self.client.wait_for_server_status(server['id'], 'ACTIVE')
|
||||
|
||||
#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')
|
||||
|
||||
#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')
|
||||
|
||||
#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'],
|
||||
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')
|
||||
|
||||
#Verify the access addresses have been updated
|
|
@ -1,11 +1,11 @@
|
|||
import unittest2 as unittest
|
||||
import storm.config
|
||||
import tempest.config
|
||||
import base64
|
||||
from nose.plugins.attrib import attr
|
||||
from storm import openstack
|
||||
from storm.common.utils.data_utils import rand_name
|
||||
from storm.common import ssh
|
||||
from storm import exceptions
|
||||
from tempest import openstack
|
||||
from tempest.common.utils.data_utils import rand_name
|
||||
from tempest.common import ssh
|
||||
from tempest import exceptions
|
||||
|
||||
|
||||
class ServersNegativeTest(unittest.TestCase):
|
Loading…
Reference in New Issue