
Getting an instance's libvirt XML is a common operation in all tests. Create a helper for it. Change-Id: Ib1897cf683c205b1e283a69f6687c7d833fa53ff
110 lines
4.5 KiB
Python
110 lines
4.5 KiB
Python
# Copyright 2019 Red Hat, Inc.
|
|
# Copyright 2012 OpenStack Foundation
|
|
# All Rights Reserved.
|
|
#
|
|
# 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.
|
|
|
|
from oslo_log import log as logging
|
|
import testtools
|
|
|
|
from tempest.common import utils
|
|
from tempest.common import waiters
|
|
from tempest import config
|
|
from tempest.lib import decorators
|
|
|
|
from whitebox_tempest_plugin.api.compute import base
|
|
|
|
CONF = config.CONF
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
# NOTE(mdbooth): This test was originally based on
|
|
# tempest.api.compute.admin.test_live_migration
|
|
|
|
|
|
class LiveMigrationTest(base.BaseWhiteboxComputeTest):
|
|
# First support for block_migration='auto': since Mitaka (OSP9)
|
|
min_microversion = '2.25'
|
|
|
|
@classmethod
|
|
def skip_checks(cls):
|
|
super(LiveMigrationTest, cls).skip_checks()
|
|
|
|
if not CONF.compute_feature_enabled.live_migration:
|
|
skip_msg = ("%s skipped as live-migration is "
|
|
"not available" % cls.__name__)
|
|
raise cls.skipException(skip_msg)
|
|
if CONF.compute.min_compute_nodes < 2:
|
|
raise cls.skipException(
|
|
"Less than 2 compute nodes, skipping migration test.")
|
|
|
|
@classmethod
|
|
def setup_credentials(cls):
|
|
# These tests don't attempt any SSH validation nor do they use
|
|
# floating IPs on the instance, so all we need is a network and
|
|
# a subnet so the instance being migrated has a single port, but
|
|
# we need that to make sure we are properly updating the port
|
|
# host bindings during the live migration.
|
|
# TODO(mriedem): SSH validation before and after the instance is
|
|
# live migrated would be a nice test wrinkle addition.
|
|
cls.set_network_resources(network=True, subnet=True)
|
|
super(LiveMigrationTest, cls).setup_credentials()
|
|
|
|
@classmethod
|
|
def setup_clients(cls):
|
|
super(LiveMigrationTest, cls).setup_clients()
|
|
cls.admin_migration_client = cls.os_admin.migrations_client
|
|
|
|
def _live_migrate(self, server_id, target_host, state):
|
|
self.admin_servers_client.live_migrate_server(
|
|
server_id, host=target_host, block_migration='auto')
|
|
waiters.wait_for_server_status(self.servers_client, server_id, state)
|
|
migration_list = (self.admin_migration_client.list_migrations()
|
|
['migrations'])
|
|
|
|
msg = ("Live Migration failed. Migrations list for Instance "
|
|
"%s: [" % server_id)
|
|
for live_migration in migration_list:
|
|
if (live_migration['instance_uuid'] == server_id):
|
|
msg += "\n%s" % live_migration
|
|
msg += "]"
|
|
self.assertEqual(target_host, self.get_host_for_server(server_id),
|
|
msg)
|
|
|
|
@testtools.skipUnless(CONF.compute_feature_enabled.
|
|
volume_backed_live_migration,
|
|
'Volume-backed live migration not available')
|
|
@decorators.idempotent_id('41e92884-ed04-42da-89fc-ef8922646542')
|
|
@utils.services('volume')
|
|
def test_volume_backed_live_migration(self):
|
|
# Live migrate an instance to another host
|
|
server_id = self.create_test_server(wait_until="ACTIVE",
|
|
volume_backed=True)['id']
|
|
|
|
def root_disk_cache():
|
|
domain = self.get_server_xml(server_id)
|
|
return domain.find(
|
|
"devices/disk/target[@dev='vda']/../driver").attrib['cache']
|
|
|
|
# The initial value of disk cache depends on config and the storage in
|
|
# use. We can't guess it, so fetch it before we start.
|
|
cache_type = root_disk_cache()
|
|
|
|
source_host = self.get_host_for_server(server_id)
|
|
destination_host = self.get_host_other_than(server_id)
|
|
LOG.info("Live migrate from source %s to destination %s",
|
|
source_host, destination_host)
|
|
self._live_migrate(server_id, destination_host, 'ACTIVE')
|
|
|
|
# Assert cache-mode has not changed during live migration
|
|
self.assertEqual(cache_type, root_disk_cache())
|