Functional test for regression bug #1713783
Add functional test for evacuation, when no valid host available. Migration should end up in 'error' state. Change-Id: I1adc20f2a5261e6906a18b9aee5cd2c8ecf0cf4d Related-bug: #1713783
This commit is contained in:
parent
1fb132f2f3
commit
5687c170ea
@ -443,3 +443,6 @@ class TestOpenStackClient(object):
|
|||||||
def get_active_migrations(self, server_id):
|
def get_active_migrations(self, server_id):
|
||||||
return self.api_get('/servers/%s/migrations' %
|
return self.api_get('/servers/%s/migrations' %
|
||||||
server_id).body['migrations']
|
server_id).body['migrations']
|
||||||
|
|
||||||
|
def get_migrations(self):
|
||||||
|
return self.api_get('os-migrations').body['migrations']
|
||||||
|
124
nova/tests/functional/regressions/test_bug_1713783.py
Normal file
124
nova/tests/functional/regressions/test_bug_1713783.py
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
# Copyright 2017 Ericsson
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
import time
|
||||||
|
|
||||||
|
from oslo_log import log as logging
|
||||||
|
|
||||||
|
from nova import test
|
||||||
|
from nova.tests import fixtures as nova_fixtures
|
||||||
|
from nova.tests.functional import integrated_helpers
|
||||||
|
from nova.tests.unit import fake_network
|
||||||
|
from nova.tests.unit import fake_notifier
|
||||||
|
import nova.tests.unit.image.fake
|
||||||
|
from nova.tests.unit import policy_fixture
|
||||||
|
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class FailedEvacuateStateTests(test.TestCase,
|
||||||
|
integrated_helpers.InstanceHelperMixin):
|
||||||
|
"""Regression Tests for bug #1713783
|
||||||
|
|
||||||
|
When evacuation fails with NoValidHost, the migration status remains
|
||||||
|
'accepted' instead of 'error'. This causes problem in case the compute
|
||||||
|
service starts up again and looks for migrations with status 'accepted',
|
||||||
|
as it then removes the local instances for those migrations even though
|
||||||
|
the instance never actually migrated to another host.
|
||||||
|
"""
|
||||||
|
|
||||||
|
microversion = 'latest'
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(FailedEvacuateStateTests, self).setUp()
|
||||||
|
|
||||||
|
self.useFixture(policy_fixture.RealPolicyFixture())
|
||||||
|
self.useFixture(nova_fixtures.NeutronFixture(self))
|
||||||
|
self.useFixture(nova_fixtures.PlacementFixture())
|
||||||
|
|
||||||
|
api_fixture = self.useFixture(nova_fixtures.OSAPIFixture(
|
||||||
|
api_version='v2.1'))
|
||||||
|
|
||||||
|
self.api = api_fixture.admin_api
|
||||||
|
self.api.microversion = self.microversion
|
||||||
|
|
||||||
|
nova.tests.unit.image.fake.stub_out_image_service(self)
|
||||||
|
|
||||||
|
self.start_service('conductor')
|
||||||
|
self.start_service('scheduler')
|
||||||
|
|
||||||
|
self.addCleanup(nova.tests.unit.image.fake.FakeImageService_reset)
|
||||||
|
|
||||||
|
self.hostname = 'host1'
|
||||||
|
self.compute1 = self.start_service('compute', host=self.hostname)
|
||||||
|
fake_network.set_stub_network_methods(self)
|
||||||
|
|
||||||
|
flavors = self.api.get_flavors()
|
||||||
|
self.flavor1 = flavors[0]
|
||||||
|
|
||||||
|
def _wait_for_notification_event_type(self, event_type, max_retries=10):
|
||||||
|
retry_counter = 0
|
||||||
|
while True:
|
||||||
|
if len(fake_notifier.NOTIFICATIONS) > 0:
|
||||||
|
for notification in fake_notifier.NOTIFICATIONS:
|
||||||
|
if notification.event_type == event_type:
|
||||||
|
return
|
||||||
|
if retry_counter == max_retries:
|
||||||
|
self.fail('Wait for notification event type (%s) failed'
|
||||||
|
% event_type)
|
||||||
|
retry_counter += 1
|
||||||
|
time.sleep(0.5)
|
||||||
|
|
||||||
|
def _boot_a_server(self):
|
||||||
|
server_req = self._build_minimal_create_server_request(
|
||||||
|
self.api, 'some-server', flavor_id=self.flavor1['id'],
|
||||||
|
image_uuid='155d900f-4e14-4e4c-a73d-069cbf4541e6',
|
||||||
|
networks='none')
|
||||||
|
LOG.info('booting on %s', self.hostname)
|
||||||
|
created_server = self.api.post_server({'server': server_req})
|
||||||
|
return self._wait_for_state_change(
|
||||||
|
self.api, created_server, 'ACTIVE')
|
||||||
|
|
||||||
|
def test_evacuate_no_valid_host(self):
|
||||||
|
# Boot a server
|
||||||
|
server = self._boot_a_server()
|
||||||
|
|
||||||
|
# Force source compute down
|
||||||
|
compute_id = self.api.get_services(
|
||||||
|
host=self.hostname, binary='nova-compute')[0]['id']
|
||||||
|
self.api.put_service(compute_id, {'forced_down': 'true'})
|
||||||
|
|
||||||
|
fake_notifier.stub_notifier(self)
|
||||||
|
fake_notifier.reset()
|
||||||
|
|
||||||
|
# Initiate evacuation
|
||||||
|
post = {'evacuate': {}}
|
||||||
|
self.api.post_server_action(server['id'], post)
|
||||||
|
|
||||||
|
self._wait_for_notification_event_type('compute_task.rebuild_server')
|
||||||
|
|
||||||
|
server = self._wait_for_state_change(self.api, server, 'ACTIVE')
|
||||||
|
self.assertEqual(self.hostname, server['OS-EXT-SRV-ATTR:host'])
|
||||||
|
|
||||||
|
# Check migrations
|
||||||
|
migrations = self.api.get_migrations()
|
||||||
|
self.assertEqual(1, len(migrations))
|
||||||
|
self.assertEqual('evacuation', migrations[0]['migration_type'])
|
||||||
|
self.assertEqual(server['id'], migrations[0]['instance_uuid'])
|
||||||
|
self.assertEqual(self.hostname, migrations[0]['source_compute'])
|
||||||
|
self.assertEqual('accepted', migrations[0]['status'])
|
||||||
|
# NOTE(elod.illes): Migration status should be 'error' and not
|
||||||
|
# 'accepted'. Needs to be replaced when bug #1713783 is fixed.
|
||||||
|
# self.assertEqual('error', migrations[0]['status'])
|
Loading…
Reference in New Issue
Block a user