Updates tests to run in other configurations.
* Changes the reddwarf.conf.test flag so "use_nova_server_volume" is turned off, as it should be, and fixes a resulting fake mode bug. * Fixes tests to not check for volume when "reddwarf_main_instance_has_volume" is specified in the test config. * Changes poll_until to reuse Reddwarf implementation instead of rewriting it just for the tests. * Adds tests to confirm its possible to log into a real MySQL instance. These are only run for "real mode" in a VM or other environment, but it's necessary that they live here. * Changes the "get_address" method of the InstanceTestInfo object to get pulled from the test config (necessary when hitting other environments). * Fixes some bugs in guest agent models. * Deleted the pagination test. It can't run very quickly in the tox fake mode, so there's no point in keeping it here (it still exists in Reddwarf-Integration). Change-Id: I2835762c4180e1ca594b27194564b8f993aa4066 Fixes: bug #1085188
This commit is contained in:
parent
46de3f0ad1
commit
bec9bc586a
@ -80,7 +80,7 @@ agent_call_low_timeout = 5
|
||||
agent_call_high_timeout = 100
|
||||
|
||||
server_delete_time_out=10
|
||||
use_nova_server_volume = True
|
||||
use_nova_server_volume = False
|
||||
|
||||
# ============ notifer queue kombu connection options ========================
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
"report_directory":"rdli-test-report",
|
||||
"start_services": false,
|
||||
|
||||
|
||||
"simulate_events":true,
|
||||
"test_mgmt":false,
|
||||
"use_local_ovz":false,
|
||||
"use_venv":false,
|
||||
|
@ -16,7 +16,7 @@ import logging
|
||||
from datetime import datetime
|
||||
from datetime import timedelta
|
||||
|
||||
from reddwarf import db
|
||||
from reddwarf.db import get_db_api
|
||||
from reddwarf.common import config
|
||||
from reddwarf.common import exception
|
||||
from reddwarf.common import utils
|
||||
@ -55,7 +55,7 @@ class AgentHeartBeat(dbmodels.DatabaseModelBase):
|
||||
self['updated_at'] = utils.utcnow()
|
||||
LOG.debug(_("Saving %s: %s") %
|
||||
(self.__class__.__name__, self.__dict__))
|
||||
return db.db_api.save(self)
|
||||
return get_db_api().save(self)
|
||||
|
||||
@staticmethod
|
||||
def is_active(agent):
|
||||
|
@ -39,6 +39,29 @@ FAKE = test_config.values['fake_mode']
|
||||
|
||||
|
||||
@test(depends_on_groups=[GROUP_START],
|
||||
groups=[tests.INSTANCES, "dbaas.guest.mysql"],
|
||||
enabled=not test_config.values['fake_mode'])
|
||||
class TestMysqlAccess(object):
|
||||
"""
|
||||
Make sure that MySQL server was secured.
|
||||
"""
|
||||
|
||||
@time_out(60 * 2)
|
||||
@test
|
||||
def test_mysql_admin(self):
|
||||
"""Ensure we aren't allowed access with os_admin and wrong password."""
|
||||
assert_mysql_connection_fails("os_admin", "asdfd-asdf234",
|
||||
instance_info.get_address())
|
||||
|
||||
@test
|
||||
def test_mysql_root(self):
|
||||
"""Ensure we aren't allowed access with root and wrong password."""
|
||||
assert_mysql_connection_fails("root", "dsfgnear",
|
||||
instance_info.get_address())
|
||||
|
||||
|
||||
@test(depends_on_groups=[GROUP_START],
|
||||
depends_on_classes=[TestMysqlAccess],
|
||||
groups=[tests.DBAAS_API, GROUP, tests.INSTANCES])
|
||||
class TestDatabases(object):
|
||||
"""
|
||||
|
@ -97,10 +97,7 @@ class InstanceTestInfo(object):
|
||||
def get_address(self):
|
||||
result = self.dbaas_admin.mgmt.instances.show(self.id)
|
||||
addresses = result.server['addresses']
|
||||
if "infranet" in addresses:
|
||||
address = addresses['infranet'][0]
|
||||
else:
|
||||
address = addresses['private'][0]
|
||||
address = addresses[test_config.visible_address_group][0]
|
||||
return address['addr']
|
||||
|
||||
def get_local_id(self):
|
||||
@ -445,7 +442,7 @@ class WaitForGuestInstallationToFinish(object):
|
||||
Wait until the Guest is finished installing. It takes quite a while...
|
||||
"""
|
||||
|
||||
@test(groups=['lemon'])
|
||||
@test
|
||||
@time_out(60 * 16)
|
||||
def test_instance_created(self):
|
||||
# This version just checks the REST API status.
|
||||
@ -715,7 +712,7 @@ class CheckDiagnosticsAfterTests(object):
|
||||
class DeleteInstance(object):
|
||||
""" Delete the created instance """
|
||||
|
||||
@time_out(3)
|
||||
@time_out(3 * 60)
|
||||
@test(runs_after_groups=[GROUP_START, GROUP_TEST, tests.INSTANCES])
|
||||
def test_delete(self):
|
||||
if do_not_delete_instance():
|
||||
|
@ -313,6 +313,8 @@ class StopTests(RebootTestBase):
|
||||
Confirms the get call behaves appropriately while an instance is
|
||||
down.
|
||||
"""
|
||||
if not CONFIG.reddwarf_main_instance_has_volume:
|
||||
raise SkipTest("Not testing volumes.")
|
||||
instance = self.dbaas.instances.get(self.instance_id)
|
||||
with TypeCheck("instance", instance) as check:
|
||||
check.has_field("volume", dict)
|
||||
@ -322,8 +324,7 @@ class StopTests(RebootTestBase):
|
||||
check.true(isinstance(instance.volume.get('used', None), float))
|
||||
|
||||
@test(depends_on=[test_set_up],
|
||||
runs_after=[test_instance_get_shows_volume_info_while_mysql_is_down],
|
||||
groups=['donut'])
|
||||
runs_after=[test_instance_get_shows_volume_info_while_mysql_is_down])
|
||||
def test_successful_restart_when_in_shutdown_state(self):
|
||||
"""Restart MySQL via the REST API successfully when MySQL is down."""
|
||||
self.successful_restart()
|
||||
@ -486,7 +487,8 @@ def resize_should_not_delete_users():
|
||||
|
||||
|
||||
@test(depends_on_classes=[ResizeInstanceTest], depends_on=[create_user],
|
||||
groups=[GROUP, tests.INSTANCES])
|
||||
groups=[GROUP, tests.INSTANCES],
|
||||
enabled=CONFIG.reddwarf_main_instance_has_volume)
|
||||
class ResizeInstanceVolume(object):
|
||||
""" Resize the volume of the instance """
|
||||
|
||||
|
@ -1,227 +0,0 @@
|
||||
from proboscis.decorators import time_out
|
||||
from proboscis import after_class
|
||||
from proboscis import before_class
|
||||
from proboscis import test
|
||||
from proboscis.asserts import assert_equal
|
||||
from proboscis.asserts import assert_false
|
||||
from proboscis.asserts import assert_is
|
||||
from proboscis.asserts import assert_is_not
|
||||
from proboscis.asserts import assert_is_none
|
||||
from proboscis.asserts import assert_not_equal
|
||||
from proboscis.asserts import assert_raises
|
||||
from proboscis.asserts import assert_true
|
||||
from proboscis.asserts import Check
|
||||
from proboscis.asserts import fail
|
||||
import time
|
||||
|
||||
from reddwarfclient import exceptions
|
||||
from reddwarf.tests import util
|
||||
from reddwarf.tests.util import create_dbaas_client
|
||||
from reddwarf.tests.util import test_config
|
||||
from reddwarf.tests.util.users import Requirements
|
||||
|
||||
|
||||
class TestBase(object):
|
||||
|
||||
def set_up(self):
|
||||
"""Create a ton of instances."""
|
||||
reqs = Requirements(is_admin=False)
|
||||
self.user = test_config.users.find_user(reqs)
|
||||
self.dbaas = create_dbaas_client(self.user)
|
||||
|
||||
def delete_instances(self):
|
||||
chunk = 0
|
||||
while True:
|
||||
chunk += 1
|
||||
attempts = 0
|
||||
instances = self.dbaas.instances.list()
|
||||
if len(instances) == 0:
|
||||
break
|
||||
# Sit around and try to delete this chunk.
|
||||
while True:
|
||||
instance_results = []
|
||||
attempts += 1
|
||||
deleted_count = 0
|
||||
for instance in instances:
|
||||
try:
|
||||
instance.delete()
|
||||
result = "[w]"
|
||||
except exceptions.UnprocessableEntity:
|
||||
result = "[W]"
|
||||
except exceptions.NotFound:
|
||||
result = "[O]"
|
||||
deleted_count += 1
|
||||
except Exception:
|
||||
result = "[X]"
|
||||
instance_results.append(result)
|
||||
print("Chunk %d, attempt %d : %s"
|
||||
% (chunk, attempts, ",".join(instance_results)))
|
||||
if deleted_count == len(instances):
|
||||
break
|
||||
time.sleep(0.2)
|
||||
|
||||
def create_instances(self):
|
||||
self.ids = []
|
||||
for index in range(self.max):
|
||||
name = "multi-%03d" % index
|
||||
result = self.dbaas.instances.create(name, 1,
|
||||
{'size': 1}, [], [])
|
||||
self.ids.append(result.id)
|
||||
# Sort the list of IDs in order, so we can confirm the lists pagination
|
||||
# returns is also sorted correctly.
|
||||
self.ids.sort()
|
||||
|
||||
@staticmethod
|
||||
def assert_instances_sorted_by_ids(instances):
|
||||
# Assert that the strings are always increasing.
|
||||
last_id = ""
|
||||
for instance in instances:
|
||||
assert_true(last_id < instance.id)
|
||||
|
||||
def print_list(self, instances):
|
||||
print("Length = %d" % len(instances))
|
||||
print(",".join([instance.id for instance in instances]))
|
||||
|
||||
def test_pagination(self, requested_limit, requested_marker,
|
||||
expected_length, expected_marker, expected_last_item):
|
||||
instances = self.dbaas.instances.list(limit=requested_limit,
|
||||
marker=requested_marker)
|
||||
marker = instances.next
|
||||
|
||||
self.print_list(instances)
|
||||
|
||||
# Better get as many as we asked for.
|
||||
assert_equal(len(instances), expected_length)
|
||||
# The last one should be roughly this one in the list.
|
||||
assert_equal(instances[-1].id, expected_last_item)
|
||||
# Because limit < count, the marker must be something.
|
||||
if expected_marker:
|
||||
assert_is_not(marker, None)
|
||||
assert_equal(marker, expected_marker)
|
||||
else:
|
||||
assert_is_none(marker)
|
||||
self.assert_instances_sorted_by_ids(instances)
|
||||
|
||||
|
||||
@test(runs_after_groups=["dbaas.guest.shutdown"],
|
||||
groups=['dbaas.api.instances.pagination'])
|
||||
class SimpleCreateAndDestroy(TestBase):
|
||||
"""
|
||||
It turns out a big part of guaranteeing pagination works is to make sure
|
||||
we can create a big batch of instances and delete them without problems.
|
||||
Even in fake mode though its worth it to check this is the case.
|
||||
"""
|
||||
|
||||
max = 5
|
||||
|
||||
@before_class
|
||||
def set_up(self):
|
||||
"""Create a ton of instances."""
|
||||
super(SimpleCreateAndDestroy, self).set_up()
|
||||
self.delete_instances()
|
||||
|
||||
@test
|
||||
def spin_up(self):
|
||||
self.create_instances()
|
||||
|
||||
@after_class(always_run=True)
|
||||
def tear_down(self):
|
||||
self.delete_instances()
|
||||
|
||||
|
||||
@test(runs_after_groups=["dbaas.guest.shutdown"],
|
||||
groups=['dbaas.api.instances.pagination'])
|
||||
class InstancePagination50(TestBase):
|
||||
|
||||
max = 50
|
||||
|
||||
@before_class
|
||||
def set_up(self):
|
||||
"""Create a ton of instances."""
|
||||
super(InstancePagination50, self).set_up()
|
||||
self.delete_instances()
|
||||
self.create_instances()
|
||||
|
||||
@after_class(always_run=True)
|
||||
def tear_down(self):
|
||||
"""Tear down all instances."""
|
||||
self.delete_instances()
|
||||
|
||||
@test
|
||||
def pagination_short(self):
|
||||
self.test_pagination(requested_limit=10, requested_marker=None,
|
||||
expected_length=10, expected_marker=self.ids[9],
|
||||
expected_last_item=self.ids[9])
|
||||
|
||||
@test
|
||||
def pagination_default(self):
|
||||
self.test_pagination(requested_limit=None, requested_marker=None,
|
||||
expected_length=20, expected_marker=self.ids[19],
|
||||
expected_last_item=self.ids[19])
|
||||
|
||||
@test
|
||||
def pagination_full(self):
|
||||
self.test_pagination(requested_limit=50, requested_marker=None,
|
||||
expected_length=20, expected_marker=self.ids[19],
|
||||
expected_last_item=self.ids[19])
|
||||
|
||||
|
||||
@test(runs_after_groups=["dbaas.guest.shutdown"],
|
||||
groups=['dbaas.api.instances.pagination'])
|
||||
class InstancePagination20(TestBase):
|
||||
|
||||
max = 20
|
||||
|
||||
@before_class
|
||||
def set_up(self):
|
||||
"""Create a ton of instances."""
|
||||
super(InstancePagination20, self).set_up()
|
||||
self.delete_instances()
|
||||
self.create_instances()
|
||||
|
||||
@after_class(always_run=True)
|
||||
def tear_down(self):
|
||||
"""Tear down all instances."""
|
||||
self.delete_instances()
|
||||
|
||||
@test
|
||||
def pagination_short(self):
|
||||
self.test_pagination(requested_limit=10, requested_marker=None,
|
||||
expected_length=10, expected_marker=self.ids[9],
|
||||
expected_last_item=self.ids[9])
|
||||
|
||||
@test
|
||||
def pagination_default(self):
|
||||
self.test_pagination(requested_limit=None, requested_marker=None,
|
||||
expected_length=20, expected_marker=None,
|
||||
expected_last_item=self.ids[19])
|
||||
|
||||
@test
|
||||
def pagination_full(self):
|
||||
self.test_pagination(requested_limit=20, requested_marker=None,
|
||||
expected_length=20, expected_marker=None,
|
||||
expected_last_item=self.ids[19])
|
||||
|
||||
@test
|
||||
def pagination_overkill(self):
|
||||
self.test_pagination(requested_limit=30, requested_marker=None,
|
||||
expected_length=20, expected_marker=None,
|
||||
expected_last_item=self.ids[19])
|
||||
|
||||
@test
|
||||
def pagination_last_half(self):
|
||||
self.test_pagination(requested_limit=10, requested_marker=self.ids[9],
|
||||
expected_length=10, expected_marker=None,
|
||||
expected_last_item=self.ids[19])
|
||||
|
||||
@test
|
||||
def pagination_third_quarter(self):
|
||||
self.test_pagination(requested_limit=5, requested_marker=self.ids[9],
|
||||
expected_length=5, expected_marker=self.ids[14],
|
||||
expected_last_item=self.ids[14])
|
||||
|
||||
@test
|
||||
def pagination_fourth_quarter(self):
|
||||
self.test_pagination(requested_limit=20, requested_marker=self.ids[14],
|
||||
expected_length=5, expected_marker=None,
|
||||
expected_last_item=self.ids[19])
|
@ -95,7 +95,7 @@ def mgmt_instance_get():
|
||||
instance.has_field('tenant_id', basestring)
|
||||
instance.has_field('updated', basestring)
|
||||
# Can be None if no volume is given on this instance.
|
||||
if CONFIG.values['reddwarf_main_instance_has_volume']:
|
||||
if CONFIG.reddwarf_main_instance_has_volume:
|
||||
instance.has_field('volume', dict, volume_check)
|
||||
else:
|
||||
instance.has_field('volume', None)
|
||||
@ -110,13 +110,14 @@ def mgmt_instance_get():
|
||||
server.has_element("name", basestring)
|
||||
server.has_element("status", basestring)
|
||||
server.has_element("tenant_id", basestring)
|
||||
with CollectionCheck("volume", api_instance.volume) as volume:
|
||||
volume.has_element("attachments", list)
|
||||
volume.has_element("availability_zone", basestring)
|
||||
volume.has_element("created_at", (basestring, None))
|
||||
volume.has_element("id", basestring)
|
||||
volume.has_element("size", int)
|
||||
volume.has_element("status", basestring)
|
||||
if CONFIG.reddwarf_main_instance_has_volume:
|
||||
with CollectionCheck("volume", api_instance.volume) as volume:
|
||||
volume.has_element("attachments", list)
|
||||
volume.has_element("availability_zone", basestring)
|
||||
volume.has_element("created_at", (basestring, None))
|
||||
volume.has_element("id", basestring)
|
||||
volume.has_element("size", int)
|
||||
volume.has_element("status", basestring)
|
||||
|
||||
|
||||
@test(groups=["fake." + GROUP])
|
||||
@ -130,8 +131,11 @@ class WhenMgmtInstanceGetIsCalledButServerIsNotReady(object):
|
||||
self.client = create_client(is_admin=True)
|
||||
self.mgmt = self.client.management
|
||||
# Fake nova will fail a server ending with 'test_SERVER_ERROR'."
|
||||
# Fake volume will fail if the size is 13.
|
||||
# TODO(tim.simpson): This would be a lot nicer looking if we used a
|
||||
# traditional mock framework.
|
||||
response = self.client.instances.create('test_SERVER_ERROR', 1,
|
||||
{'size': 1}, [])
|
||||
{'size': 13}, [])
|
||||
poll_until(lambda: self.client.instances.get(response.id),
|
||||
lambda instance: instance.status == 'ERROR',
|
||||
time_out=10)
|
||||
|
@ -34,6 +34,7 @@ from reddwarf.tests.api.instances import GROUP_START
|
||||
from reddwarf.tests.api.instances import instance_info
|
||||
from reddwarf.tests import util
|
||||
from reddwarf.tests.util import test_config
|
||||
from reddwarf.tests.api.databases import TestMysqlAccess
|
||||
|
||||
|
||||
GROUP = "dbaas.api.root"
|
||||
@ -45,7 +46,7 @@ def log_in_as_root(root_password):
|
||||
return con
|
||||
|
||||
|
||||
@test(depends_on_groups=[GROUP_START],
|
||||
@test(depends_on_classes=[TestMysqlAccess],
|
||||
runs_after=[TestUsers],
|
||||
groups=[tests.DBAAS_API, GROUP, tests.INSTANCES])
|
||||
class TestRoot(object):
|
||||
|
@ -35,13 +35,13 @@ from reddwarf.tests.api.instances import GROUP_START
|
||||
from reddwarf.tests.api.instances import instance_info
|
||||
from reddwarf.tests import util
|
||||
from reddwarf.tests.util import test_config
|
||||
|
||||
from reddwarf.tests.api.databases import TestMysqlAccess
|
||||
|
||||
GROUP = "dbaas.api.users"
|
||||
FAKE = test_config.values['fake_mode']
|
||||
|
||||
|
||||
@test(depends_on_groups=[GROUP_START],
|
||||
@test(depends_on_classes=[TestMysqlAccess],
|
||||
groups=[tests.DBAAS_API, GROUP, tests.INSTANCES],
|
||||
runs_after=[TestDatabases])
|
||||
class TestUsers(object):
|
||||
|
@ -78,6 +78,7 @@ class TestConfig(object):
|
||||
"in_proc_server": True,
|
||||
"report_directory": os.environ.get("REPORT_DIRECTORY", None),
|
||||
"sleep_mode": "simulated",
|
||||
"simulate_events": False,
|
||||
}
|
||||
self._frozen_values = FrozenDict(self._values)
|
||||
self._users = None
|
||||
|
@ -445,6 +445,8 @@ class FakeVolumes(object):
|
||||
self.db[id] = volume
|
||||
if size == 9:
|
||||
volume.schedule_status("error", 2)
|
||||
elif size == 13:
|
||||
raise Exception("No volume for you!")
|
||||
else:
|
||||
volume.schedule_status("available", 2)
|
||||
LOG.info("FAKE_VOLUMES_DB : %s" % FAKE_VOLUMES_DB)
|
||||
|
@ -26,16 +26,14 @@
|
||||
.. moduleauthor:: Tim Simpson <tim.simpson@rackspace.com>
|
||||
"""
|
||||
|
||||
# This emulates the old way we did things, which was to load the config
|
||||
# as a module.
|
||||
# TODO(tim.simpson): Change all references from "test_config" to CONFIG.
|
||||
from reddwarf.tests.config import CONFIG as test_config
|
||||
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
|
||||
from reddwarf.tests.config import CONFIG as test_config
|
||||
|
||||
|
||||
try:
|
||||
from eventlet import event
|
||||
from eventlet import greenthread
|
||||
@ -57,9 +55,10 @@ from proboscis.asserts import ASSERTION_ERROR
|
||||
from proboscis import SkipTest
|
||||
from reddwarfclient import Dbaas
|
||||
from reddwarfclient.client import ReddwarfHTTPClient
|
||||
from reddwarf.tests.util import test_config
|
||||
from reddwarf.tests.util import test_config as CONFIG
|
||||
from reddwarf.tests.util.client import TestClient as TestClient
|
||||
from reddwarf.tests.util.users import Requirements
|
||||
from reddwarf.common.exception import PollTimeOut
|
||||
|
||||
|
||||
WHITE_BOX = test_config.white_box
|
||||
@ -179,7 +178,7 @@ def create_nova_client(user, service_type=None):
|
||||
service_type = test_config.nova_client['nova_service_type']
|
||||
openstack = Client(user.auth_user, user.auth_key,
|
||||
user.tenant, test_config.nova_client['auth_url'],
|
||||
service_type=service_type)
|
||||
service_type=service_type, no_cache=True)
|
||||
openstack.authenticate()
|
||||
return TestClient(openstack)
|
||||
|
||||
@ -196,31 +195,30 @@ def string_in_list(str, substr_list):
|
||||
return any([str.find(x) >= 0 for x in substr_list])
|
||||
|
||||
|
||||
class PollTimeOut(RuntimeError):
|
||||
message = _("Polling request timed out.")
|
||||
if CONFIG.simulate_events:
|
||||
# Without event let, this just calls time.sleep.
|
||||
def poll_until(retriever, condition=lambda value: value,
|
||||
sleep_time=1, time_out=None):
|
||||
"""Retrieves object until it passes condition, then returns it.
|
||||
|
||||
If time_out_limit is passed in, PollTimeOut will be raised once that
|
||||
amount of time is eclipsed.
|
||||
|
||||
# Without event let, this just calls time.sleep.
|
||||
def poll_until(retriever, condition=lambda value: value,
|
||||
sleep_time=1, time_out=None):
|
||||
"""Retrieves object until it passes condition, then returns it.
|
||||
"""
|
||||
start_time = time.time()
|
||||
|
||||
If time_out_limit is passed in, PollTimeOut will be raised once that
|
||||
amount of time is eclipsed.
|
||||
def check_timeout():
|
||||
if time_out is not None and time.time() > start_time + time_out:
|
||||
raise PollTimeOut
|
||||
|
||||
"""
|
||||
start_time = time.time()
|
||||
|
||||
def check_timeout():
|
||||
if time_out is not None and time.time() > start_time + time_out:
|
||||
raise PollTimeOut
|
||||
|
||||
while True:
|
||||
obj = retriever()
|
||||
if condition(obj):
|
||||
return
|
||||
check_timeout()
|
||||
time.sleep(sleep_time)
|
||||
while True:
|
||||
obj = retriever()
|
||||
if condition(obj):
|
||||
return
|
||||
check_timeout()
|
||||
time.sleep(sleep_time)
|
||||
else:
|
||||
from reddwarf.common.utils import poll_until
|
||||
|
||||
|
||||
class LocalSqlClient(object):
|
||||
|
Loading…
Reference in New Issue
Block a user