OpenStack Compute (Nova)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

122 lines
4.4KB

  1. # Copyright 2017 Ericsson
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. import time
  15. from oslo_log import log as logging
  16. from nova import test
  17. from nova.tests import fixtures as nova_fixtures
  18. from nova.tests.functional import integrated_helpers
  19. from nova.tests.unit import fake_network
  20. from nova.tests.unit import fake_notifier
  21. import nova.tests.unit.image.fake
  22. from nova.tests.unit import policy_fixture
  23. LOG = logging.getLogger(__name__)
  24. class FailedEvacuateStateTests(test.TestCase,
  25. integrated_helpers.InstanceHelperMixin):
  26. """Regression Tests for bug #1713783
  27. When evacuation fails with NoValidHost, the migration status remains
  28. 'accepted' instead of 'error'. This causes problem in case the compute
  29. service starts up again and looks for migrations with status 'accepted',
  30. as it then removes the local instances for those migrations even though
  31. the instance never actually migrated to another host.
  32. """
  33. microversion = 'latest'
  34. def setUp(self):
  35. super(FailedEvacuateStateTests, self).setUp()
  36. self.useFixture(policy_fixture.RealPolicyFixture())
  37. self.useFixture(nova_fixtures.NeutronFixture(self))
  38. self.useFixture(nova_fixtures.PlacementFixture())
  39. api_fixture = self.useFixture(nova_fixtures.OSAPIFixture(
  40. api_version='v2.1'))
  41. self.api = api_fixture.admin_api
  42. self.api.microversion = self.microversion
  43. nova.tests.unit.image.fake.stub_out_image_service(self)
  44. self.start_service('conductor')
  45. self.start_service('scheduler')
  46. self.addCleanup(nova.tests.unit.image.fake.FakeImageService_reset)
  47. self.hostname = 'host1'
  48. self.compute1 = self.start_service('compute', host=self.hostname)
  49. fake_network.set_stub_network_methods(self)
  50. flavors = self.api.get_flavors()
  51. self.flavor1 = flavors[0]
  52. def _wait_for_notification_event_type(self, event_type, max_retries=10):
  53. retry_counter = 0
  54. while True:
  55. if len(fake_notifier.NOTIFICATIONS) > 0:
  56. for notification in fake_notifier.NOTIFICATIONS:
  57. if notification.event_type == event_type:
  58. return
  59. if retry_counter == max_retries:
  60. self.fail('Wait for notification event type (%s) failed'
  61. % event_type)
  62. retry_counter += 1
  63. time.sleep(0.5)
  64. def _boot_a_server(self):
  65. server_req = self._build_minimal_create_server_request(
  66. self.api, 'some-server', flavor_id=self.flavor1['id'],
  67. image_uuid='155d900f-4e14-4e4c-a73d-069cbf4541e6',
  68. networks='none')
  69. LOG.info('booting on %s', self.hostname)
  70. created_server = self.api.post_server({'server': server_req})
  71. return self._wait_for_state_change(
  72. self.api, created_server, 'ACTIVE')
  73. def test_evacuate_no_valid_host(self):
  74. # Boot a server
  75. server = self._boot_a_server()
  76. # Force source compute down
  77. compute_id = self.api.get_services(
  78. host=self.hostname, binary='nova-compute')[0]['id']
  79. self.api.put_service(compute_id, {'forced_down': 'true'})
  80. fake_notifier.stub_notifier(self)
  81. fake_notifier.reset()
  82. # Initiate evacuation
  83. post = {'evacuate': {}}
  84. self.api.post_server_action(server['id'], post)
  85. self._wait_for_notification_event_type('compute_task.rebuild_server')
  86. server = self._wait_for_state_change(self.api, server, 'ACTIVE')
  87. self.assertEqual(self.hostname, server['OS-EXT-SRV-ATTR:host'])
  88. # Check migrations
  89. migrations = self.api.get_migrations()
  90. self.assertEqual(1, len(migrations))
  91. self.assertEqual('evacuation', migrations[0]['migration_type'])
  92. self.assertEqual(server['id'], migrations[0]['instance_uuid'])
  93. self.assertEqual(self.hostname, migrations[0]['source_compute'])
  94. self.assertEqual('error', migrations[0]['status'])