Misc methods to support vm migration tests

Misc methods to support vm migration tests.
This commit is contained in:
Liam Young
2019-03-05 19:30:57 +00:00
parent 933cb5518d
commit 3118f122b4
5 changed files with 166 additions and 0 deletions

View File

@@ -119,6 +119,18 @@ class TestJujuUtils(ut_utils.BaseTestCase):
self.subordinate_application),
[self.machine])
def test_get_unit_name_from_host_name(self):
unit_mock1 = mock.MagicMock()
unit_mock1.data = {'machine-id': 12}
unit_mock1.entity_id = 'myapp/2'
unit_mock2 = mock.MagicMock()
unit_mock2.data = {'machine-id': 15}
unit_mock2.entity_id = 'myapp/5'
self.model.get_units.return_value = [unit_mock1, unit_mock2]
self.assertEqual(
juju_utils.get_unit_name_from_host_name('juju-model-12', 'myapp'),
'myapp/2')
def test_get_machine_status(self):
self.patch_object(juju_utils, "get_full_juju_status")
self.get_full_juju_status.return_value = self.juju_status

View File

@@ -811,3 +811,78 @@ class TestOpenStackUtils(ut_utils.BaseTestCase):
ksclient, project_name, domain_name=domain_name), project_id)
ksclient.domains.list.assert_called_once_with(name=domain_name)
ksclient.projects.list.assert_called_once_with(domain=domain_id)
def test_wait_for_server_migration(self):
openstack_utils.wait_for_server_migration.retry.stop = \
tenacity.stop_after_attempt(1)
novaclient = mock.MagicMock()
servermock = mock.MagicMock()
setattr(servermock, 'OS-EXT-SRV-ATTR:host', 'newhypervisor')
servermock.status = 'ACTIVE'
novaclient.servers.find.return_value = servermock
# Implicit assertion that exception is not raised.
openstack_utils.wait_for_server_migration(
novaclient,
'myvm',
'org-hypervisor')
def test_wait_for_server_migration_fail_no_host_change(self):
openstack_utils.wait_for_server_migration.retry.stop = \
tenacity.stop_after_attempt(1)
novaclient = mock.MagicMock()
servermock = mock.MagicMock()
setattr(servermock, 'OS-EXT-SRV-ATTR:host', 'org-hypervisor')
servermock.status = 'ACTIVE'
novaclient.servers.find.return_value = servermock
with self.assertRaises(exceptions.NovaGuestMigrationFailed):
openstack_utils.wait_for_server_migration(
novaclient,
'myvm',
'org-hypervisor')
def test_wait_for_server_migration_fail_not_active(self):
openstack_utils.wait_for_server_migration.retry.stop = \
tenacity.stop_after_attempt(1)
novaclient = mock.MagicMock()
servermock = mock.MagicMock()
setattr(servermock, 'OS-EXT-SRV-ATTR:host', 'newhypervisor')
servermock.status = 'NOTACTIVE'
novaclient.servers.find.return_value = servermock
with self.assertRaises(exceptions.NovaGuestMigrationFailed):
openstack_utils.wait_for_server_migration(
novaclient,
'myvm',
'org-hypervisor')
def test_enable_all_nova_services(self):
novaclient = mock.MagicMock()
svc_mock1 = mock.MagicMock()
svc_mock1.status = 'disabled'
svc_mock1.binary = 'nova-compute'
svc_mock1.host = 'juju-bb659c-zaza-ad7c662d7f1d-13'
svc_mock2 = mock.MagicMock()
svc_mock2.status = 'enabled'
svc_mock2.binary = 'nova-compute'
svc_mock2.host = 'juju-bb659c-zaza-ad7c662d7f1d-14'
svc_mock3 = mock.MagicMock()
svc_mock3.status = 'disabled'
svc_mock3.binary = 'nova-compute'
svc_mock3.host = 'juju-bb659c-zaza-ad7c662d7f1d-15'
novaclient.services.list.return_value = [
svc_mock1,
svc_mock2,
svc_mock3]
openstack_utils.enable_all_nova_services(novaclient)
expected_calls = [
mock.call('juju-bb659c-zaza-ad7c662d7f1d-13', 'nova-compute'),
mock.call('juju-bb659c-zaza-ad7c662d7f1d-15', 'nova-compute')]
novaclient.services.enable.assert_has_calls(expected_calls)
def test_get_hypervisor_for_guest(self):
novaclient = mock.MagicMock()
servermock = mock.MagicMock()
setattr(servermock, 'OS-EXT-SRV-ATTR:host', 'newhypervisor')
novaclient.servers.find.return_value = servermock
self.assertEqual(
openstack_utils.get_hypervisor_for_guest(novaclient, 'vmname'),
'newhypervisor')

View File

@@ -160,3 +160,9 @@ class CephPoolNotFound(Exception):
"""Ceph pool not found."""
pass
class NovaGuestMigrationFailed(Exception):
"""Nova guest migration failed."""
pass

View File

@@ -98,6 +98,23 @@ def get_machines_for_application(application):
return machines
def get_unit_name_from_host_name(host_name, application):
"""Return the juju unit name corresponding to a hostname.
:param host_name: Host name to map to unit name.
:type host_name: string
:param application: Application name
:type application: string
"""
# Assume that a juju managed hostname always ends in the machine number.
machine_number = host_name.split('-')[-1]
unit_names = [
u.entity_id
for u in model.get_units(application_name=application)
if int(u.data['machine-id']) == int(machine_number)]
return unit_names[0]
def get_machine_status(machine, key=None):
"""Return the juju status for a machine.

View File

@@ -1889,3 +1889,59 @@ def neutron_bgp_speaker_appears_on_agent(neutron_client, agent_id):
'No BGP Speaker appeared on agent "{}"'
''.format(agent_id))
return result
@tenacity.retry(wait=tenacity.wait_exponential(multiplier=1, max=60),
reraise=True, stop=tenacity.stop_after_attempt(80))
def wait_for_server_migration(nova_client, vm_name, original_hypervisor):
"""Wait for guest to migrate to a different hypervisor.
:param nova_client: Authenticated nova client
:type nova_client: novaclient.v2.client.Client
:param vm_name: Name of guest to monitor
:type vm_name: str
:param original_hypervisor: Name of hypervisor that was hosting guest
prior to migration.
:type original_hypervisor: str
:raises: exceptions.NovaGuestMigrationFailed
"""
server = nova_client.servers.find(name=vm_name)
current_hypervisor = getattr(server, 'OS-EXT-SRV-ATTR:host')
logging.info('{} is on {} in state {}'.format(
vm_name,
current_hypervisor,
server.status))
if original_hypervisor == current_hypervisor or server.status != 'ACTIVE':
raise exceptions.NovaGuestMigrationFailed(
'Migration of {} away from {} timed out of failed'.format(
vm_name,
original_hypervisor))
else:
logging.info('SUCCESS {} has migrated to {}'.format(
vm_name,
current_hypervisor))
def enable_all_nova_services(nova_client):
"""Enable all nova services.
:param nova_client: Authenticated nova client
:type nova_client: novaclient.v2.client.Client
"""
for svc in nova_client.services.list():
if svc.status == 'disabled':
logging.info("Enabling {} on {}".format(svc.binary, svc.host))
nova_client.services.enable(svc.host, svc.binary)
def get_hypervisor_for_guest(nova_client, guest_name):
"""Return the name of the hypervisor hosting a guest.
:param nova_client: Authenticated nova client
:type nova_client: novaclient.v2.client.Client
:param vm_name: Name of guest to loohup
:type vm_name: str
"""
logging.info('Finding hosting hypervisor')
server = nova_client.servers.find(name=guest_name)
return getattr(server, 'OS-EXT-SRV-ATTR:host')