Add cache-mode test for volume-backed live migration

Implements: RHELOSP-27741
Change-Id: Id954525b7a18b29aabf1a35cd73d56a8f70d52c8
This commit is contained in:
Matthew Booth 2018-12-19 11:56:35 -05:00
parent 8f4d347736
commit 200fbd819d

View File

@ -0,0 +1,123 @@
# 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
import xml.etree.ElementTree as ET
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
from whitebox_tempest_plugin.common import utils as whitebox_utils
from whitebox_tempest_plugin.services import clients
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.BaseTest):
# 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)
def _get_server_libvirt_domain(self, server_id):
compute_node_address = whitebox_utils.get_hypervisor_ip(
self.servers_client, server_id)
LOG.debug("Connecting to hypervisor %s for server %s",
compute_node_address, server_id)
virshxml = clients.VirshXMLClient(compute_node_address)
xml = virshxml.dumpxml(server_id)
return ET.fromstring(xml)
@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_libvirt_domain(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())