Merge "functional: Change order of two classes"
This commit is contained in:
commit
8e18f38b2d
|
@ -73,6 +73,150 @@ def generate_new_element(items, prefix, numeric=False):
|
|||
LOG.debug("Random collision on %s", candidate)
|
||||
|
||||
|
||||
class InstanceHelperMixin(object):
|
||||
def _wait_for_server_parameter(self, admin_api, server, expected_params,
|
||||
max_retries=10):
|
||||
retry_count = 0
|
||||
while True:
|
||||
server = admin_api.get_server(server['id'])
|
||||
if all([server[attr] == expected_params[attr]
|
||||
for attr in expected_params]):
|
||||
break
|
||||
retry_count += 1
|
||||
if retry_count == max_retries:
|
||||
self.fail('Wait for state change failed, '
|
||||
'expected_params=%s, server=%s' % (
|
||||
expected_params, server))
|
||||
time.sleep(0.5)
|
||||
|
||||
return server
|
||||
|
||||
def _wait_for_state_change(self, admin_api, server, expected_status,
|
||||
max_retries=10):
|
||||
return self._wait_for_server_parameter(
|
||||
admin_api, server, {'status': expected_status}, max_retries)
|
||||
|
||||
def _build_minimal_create_server_request(self, api, name, image_uuid=None,
|
||||
flavor_id=None, networks=None,
|
||||
az=None, host=None):
|
||||
server = {}
|
||||
|
||||
# We now have a valid imageId
|
||||
server['imageRef'] = image_uuid or api.get_images()[0]['id']
|
||||
|
||||
if not flavor_id:
|
||||
# Set a valid flavorId
|
||||
flavor_id = api.get_flavors()[1]['id']
|
||||
server['flavorRef'] = ('http://fake.server/%s' % flavor_id)
|
||||
server['name'] = name
|
||||
if networks is not None:
|
||||
server['networks'] = networks
|
||||
if az is not None:
|
||||
server['availability_zone'] = az
|
||||
# This requires at least microversion 2.74 to work
|
||||
if host is not None:
|
||||
server['host'] = host
|
||||
return server
|
||||
|
||||
def _wait_until_deleted(self, server):
|
||||
initially_in_error = (server['status'] == 'ERROR')
|
||||
try:
|
||||
for i in range(40):
|
||||
server = self.api.get_server(server['id'])
|
||||
if not initially_in_error and server['status'] == 'ERROR':
|
||||
self.fail('Server went to error state instead of'
|
||||
'disappearing.')
|
||||
time.sleep(0.5)
|
||||
|
||||
self.fail('Server failed to delete.')
|
||||
except api_client.OpenStackApiNotFoundException:
|
||||
return
|
||||
|
||||
def _wait_for_action_fail_completion(
|
||||
self, server, expected_action, event_name, api=None):
|
||||
"""Polls instance action events for the given instance, action and
|
||||
action event name until it finds the action event with an error
|
||||
result.
|
||||
"""
|
||||
if api is None:
|
||||
api = self.api
|
||||
return self._wait_for_instance_action_event(
|
||||
api, server, expected_action, event_name, event_result='error')
|
||||
|
||||
def _wait_for_instance_action_event(
|
||||
self, api, server, action_name, event_name, event_result):
|
||||
"""Polls the instance action events for the given instance, action,
|
||||
event, and event result until it finds the event.
|
||||
"""
|
||||
actions = []
|
||||
events = []
|
||||
for attempt in range(10):
|
||||
actions = api.get_instance_actions(server['id'])
|
||||
# The API returns the newest event first
|
||||
for action in actions:
|
||||
if action['action'] == action_name:
|
||||
events = (
|
||||
api.api_get(
|
||||
'/servers/%s/os-instance-actions/%s' %
|
||||
(server['id'], action['request_id'])
|
||||
).body['instanceAction']['events'])
|
||||
# Look for the action event being in error state.
|
||||
for event in events:
|
||||
result = event['result']
|
||||
if (event['event'] == event_name and
|
||||
result is not None and
|
||||
result.lower() == event_result.lower()):
|
||||
return event
|
||||
# We didn't find the completion event yet, so wait a bit.
|
||||
time.sleep(0.5)
|
||||
|
||||
self.fail(
|
||||
'Timed out waiting for %s instance action event. Current instance '
|
||||
'actions: %s. Events in the last matching action: %s'
|
||||
% (event_name, actions, events))
|
||||
|
||||
def _assert_resize_migrate_action_fail(self, server, action, error_in_tb):
|
||||
"""Waits for the conductor_migrate_server action event to fail for
|
||||
the given action and asserts the error is in the event traceback.
|
||||
|
||||
:param server: API response dict of the server being resized/migrated
|
||||
:param action: Either "resize" or "migrate" instance action.
|
||||
:param error_in_tb: Some expected part of the error event traceback.
|
||||
"""
|
||||
api = self.admin_api if hasattr(self, 'admin_api') else self.api
|
||||
event = self._wait_for_action_fail_completion(
|
||||
server, action, 'conductor_migrate_server', api=api)
|
||||
self.assertIn(error_in_tb, event['traceback'])
|
||||
|
||||
def _wait_for_migration_status(self, server, expected_statuses):
|
||||
"""Waits for a migration record with the given statuses to be found
|
||||
for the given server, else the test fails. The migration record, if
|
||||
found, is returned.
|
||||
"""
|
||||
api = getattr(self, 'admin_api', None)
|
||||
if api is None:
|
||||
api = self.api
|
||||
|
||||
statuses = [status.lower() for status in expected_statuses]
|
||||
for attempt in range(10):
|
||||
migrations = api.api_get('/os-migrations').body['migrations']
|
||||
for migration in migrations:
|
||||
if (migration['instance_uuid'] == server['id'] and
|
||||
migration['status'].lower() in statuses):
|
||||
return migration
|
||||
time.sleep(0.5)
|
||||
self.fail('Timed out waiting for migration with status "%s" for '
|
||||
'instance: %s' % (expected_statuses, server['id']))
|
||||
|
||||
def _wait_for_log(self, log_line):
|
||||
for i in range(10):
|
||||
if log_line in self.stdlog.logger.output:
|
||||
return
|
||||
time.sleep(0.5)
|
||||
|
||||
self.fail('The line "%(log_line)s" did not appear in the log')
|
||||
|
||||
|
||||
class _IntegratedTestBase(test.TestCase):
|
||||
REQUIRES_LOCKING = True
|
||||
ADMIN_API = False
|
||||
|
@ -251,150 +395,6 @@ class _IntegratedTestBase(test.TestCase):
|
|||
"existed") % expected_middleware)
|
||||
|
||||
|
||||
class InstanceHelperMixin(object):
|
||||
def _wait_for_server_parameter(self, admin_api, server, expected_params,
|
||||
max_retries=10):
|
||||
retry_count = 0
|
||||
while True:
|
||||
server = admin_api.get_server(server['id'])
|
||||
if all([server[attr] == expected_params[attr]
|
||||
for attr in expected_params]):
|
||||
break
|
||||
retry_count += 1
|
||||
if retry_count == max_retries:
|
||||
self.fail('Wait for state change failed, '
|
||||
'expected_params=%s, server=%s' % (
|
||||
expected_params, server))
|
||||
time.sleep(0.5)
|
||||
|
||||
return server
|
||||
|
||||
def _wait_for_state_change(self, admin_api, server, expected_status,
|
||||
max_retries=10):
|
||||
return self._wait_for_server_parameter(
|
||||
admin_api, server, {'status': expected_status}, max_retries)
|
||||
|
||||
def _build_minimal_create_server_request(self, api, name, image_uuid=None,
|
||||
flavor_id=None, networks=None,
|
||||
az=None, host=None):
|
||||
server = {}
|
||||
|
||||
# We now have a valid imageId
|
||||
server['imageRef'] = image_uuid or api.get_images()[0]['id']
|
||||
|
||||
if not flavor_id:
|
||||
# Set a valid flavorId
|
||||
flavor_id = api.get_flavors()[1]['id']
|
||||
server['flavorRef'] = ('http://fake.server/%s' % flavor_id)
|
||||
server['name'] = name
|
||||
if networks is not None:
|
||||
server['networks'] = networks
|
||||
if az is not None:
|
||||
server['availability_zone'] = az
|
||||
# This requires at least microversion 2.74 to work
|
||||
if host is not None:
|
||||
server['host'] = host
|
||||
return server
|
||||
|
||||
def _wait_until_deleted(self, server):
|
||||
initially_in_error = (server['status'] == 'ERROR')
|
||||
try:
|
||||
for i in range(40):
|
||||
server = self.api.get_server(server['id'])
|
||||
if not initially_in_error and server['status'] == 'ERROR':
|
||||
self.fail('Server went to error state instead of'
|
||||
'disappearing.')
|
||||
time.sleep(0.5)
|
||||
|
||||
self.fail('Server failed to delete.')
|
||||
except api_client.OpenStackApiNotFoundException:
|
||||
return
|
||||
|
||||
def _wait_for_action_fail_completion(
|
||||
self, server, expected_action, event_name, api=None):
|
||||
"""Polls instance action events for the given instance, action and
|
||||
action event name until it finds the action event with an error
|
||||
result.
|
||||
"""
|
||||
if api is None:
|
||||
api = self.api
|
||||
return self._wait_for_instance_action_event(
|
||||
api, server, expected_action, event_name, event_result='error')
|
||||
|
||||
def _wait_for_instance_action_event(
|
||||
self, api, server, action_name, event_name, event_result):
|
||||
"""Polls the instance action events for the given instance, action,
|
||||
event, and event result until it finds the event.
|
||||
"""
|
||||
actions = []
|
||||
events = []
|
||||
for attempt in range(10):
|
||||
actions = api.get_instance_actions(server['id'])
|
||||
# The API returns the newest event first
|
||||
for action in actions:
|
||||
if action['action'] == action_name:
|
||||
events = (
|
||||
api.api_get(
|
||||
'/servers/%s/os-instance-actions/%s' %
|
||||
(server['id'], action['request_id'])
|
||||
).body['instanceAction']['events'])
|
||||
# Look for the action event being in error state.
|
||||
for event in events:
|
||||
result = event['result']
|
||||
if (event['event'] == event_name and
|
||||
result is not None and
|
||||
result.lower() == event_result.lower()):
|
||||
return event
|
||||
# We didn't find the completion event yet, so wait a bit.
|
||||
time.sleep(0.5)
|
||||
|
||||
self.fail(
|
||||
'Timed out waiting for %s instance action event. Current instance '
|
||||
'actions: %s. Events in the last matching action: %s'
|
||||
% (event_name, actions, events))
|
||||
|
||||
def _assert_resize_migrate_action_fail(self, server, action, error_in_tb):
|
||||
"""Waits for the conductor_migrate_server action event to fail for
|
||||
the given action and asserts the error is in the event traceback.
|
||||
|
||||
:param server: API response dict of the server being resized/migrated
|
||||
:param action: Either "resize" or "migrate" instance action.
|
||||
:param error_in_tb: Some expected part of the error event traceback.
|
||||
"""
|
||||
api = self.admin_api if hasattr(self, 'admin_api') else self.api
|
||||
event = self._wait_for_action_fail_completion(
|
||||
server, action, 'conductor_migrate_server', api=api)
|
||||
self.assertIn(error_in_tb, event['traceback'])
|
||||
|
||||
def _wait_for_migration_status(self, server, expected_statuses):
|
||||
"""Waits for a migration record with the given statuses to be found
|
||||
for the given server, else the test fails. The migration record, if
|
||||
found, is returned.
|
||||
"""
|
||||
api = getattr(self, 'admin_api', None)
|
||||
if api is None:
|
||||
api = self.api
|
||||
|
||||
statuses = [status.lower() for status in expected_statuses]
|
||||
for attempt in range(10):
|
||||
migrations = api.api_get('/os-migrations').body['migrations']
|
||||
for migration in migrations:
|
||||
if (migration['instance_uuid'] == server['id'] and
|
||||
migration['status'].lower() in statuses):
|
||||
return migration
|
||||
time.sleep(0.5)
|
||||
self.fail('Timed out waiting for migration with status "%s" for '
|
||||
'instance: %s' % (expected_statuses, server['id']))
|
||||
|
||||
def _wait_for_log(self, log_line):
|
||||
for i in range(10):
|
||||
if log_line in self.stdlog.logger.output:
|
||||
return
|
||||
time.sleep(0.5)
|
||||
|
||||
self.fail('The line "%(log_line)s" did not appear in the log')
|
||||
|
||||
|
||||
class ProviderUsageBaseTestCase(test.TestCase, InstanceHelperMixin):
|
||||
"""Base test class for functional tests that check provider usage
|
||||
and consumer allocations in Placement during various operations.
|
||||
|
|
Loading…
Reference in New Issue