From e9c7690af470fd8452ddec88e2845336bdfbef67 Mon Sep 17 00:00:00 2001 From: Liam Young Date: Thu, 7 Mar 2019 16:03:42 +0000 Subject: [PATCH] Enable masakari instance monitor tests Add helpers and a test to test a guest dying and being resurrected by masakari instance monitor. --- .../.test_zaza_utilities_openstack.py.swp | Bin 0 -> 61440 bytes .../test_zaza_utilities_openstack.py | 49 +++++++++ zaza/charm_tests/masakari/tests.py | 95 ++++++++++++++++-- zaza/configure/masakari.py | 17 ++++ zaza/utilities/.openstack.py.swp | Bin 0 -> 16384 bytes zaza/utilities/exceptions.py | 6 ++ zaza/utilities/openstack.py | 32 ++++++ 7 files changed, 192 insertions(+), 7 deletions(-) create mode 100644 unit_tests/utilities/.test_zaza_utilities_openstack.py.swp create mode 100644 zaza/utilities/.openstack.py.swp diff --git a/unit_tests/utilities/.test_zaza_utilities_openstack.py.swp b/unit_tests/utilities/.test_zaza_utilities_openstack.py.swp new file mode 100644 index 0000000000000000000000000000000000000000..752be8519224f1d649a3b5a336e28f65409a5e48 GIT binary patch literal 61440 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 literal 0 HcmV?d00001 diff --git a/unit_tests/utilities/test_zaza_utilities_openstack.py b/unit_tests/utilities/test_zaza_utilities_openstack.py index 6a9cbf0..f40098f 100644 --- a/unit_tests/utilities/test_zaza_utilities_openstack.py +++ b/unit_tests/utilities/test_zaza_utilities_openstack.py @@ -13,6 +13,7 @@ # limitations under the License. import copy +import datetime import io import mock import tenacity @@ -854,6 +855,54 @@ class TestOpenStackUtils(ut_utils.BaseTestCase): 'myvm', 'org-hypervisor') + def test_wait_for_server_update_and_active(self): + openstack_utils.wait_for_server_migration.retry.stop = \ + tenacity.stop_after_attempt(1) + novaclient = mock.MagicMock() + servermock = mock.MagicMock() + servermock.updated = '2019-03-07T13:41:58Z' + servermock.status = 'ACTIVE' + novaclient.servers.find.return_value = servermock + # Implicit assertion that exception is not raised. + openstack_utils.wait_for_server_update_and_active( + novaclient, + 'myvm', + datetime.datetime.strptime( + '2019-03-07T13:40:58Z', + '%Y-%m-%dT%H:%M:%SZ')) + + def test_wait_for_server_update_and_active_fail_no_meeta_update(self): + openstack_utils.wait_for_server_update_and_active.retry.stop = \ + tenacity.stop_after_attempt(1) + novaclient = mock.MagicMock() + servermock = mock.MagicMock() + servermock.updated = '2019-03-07T13:41:58Z' + servermock.status = 'ACTIVE' + novaclient.servers.find.return_value = servermock + with self.assertRaises(exceptions.NovaGuestRestartFailed): + openstack_utils.wait_for_server_update_and_active( + novaclient, + 'myvm', + datetime.datetime.strptime( + '2019-03-07T13:41:58Z', + '%Y-%m-%dT%H:%M:%SZ')) + + def test_wait_for_server_update_and_active_fail_not_active(self): + openstack_utils.wait_for_server_update_and_active.retry.stop = \ + tenacity.stop_after_attempt(1) + novaclient = mock.MagicMock() + servermock = mock.MagicMock() + servermock.updated = '2019-03-07T13:41:58Z' + servermock.status = 'NOTACTIVE' + novaclient.servers.find.return_value = servermock + with self.assertRaises(exceptions.NovaGuestRestartFailed): + openstack_utils.wait_for_server_update_and_active( + novaclient, + 'myvm', + datetime.datetime.strptime( + '2019-03-07T13:40:58Z', + '%Y-%m-%dT%H:%M:%SZ')) + def test_enable_all_nova_services(self): novaclient = mock.MagicMock() svc_mock1 = mock.MagicMock() diff --git a/zaza/charm_tests/masakari/tests.py b/zaza/charm_tests/masakari/tests.py index f74ad8a..5168bbf 100644 --- a/zaza/charm_tests/masakari/tests.py +++ b/zaza/charm_tests/masakari/tests.py @@ -16,6 +16,7 @@ """Encapsulate masakari testing.""" +from datetime import datetime import logging import novaclient @@ -40,27 +41,74 @@ class MasakariTest(test_utils.OpenStackBaseTest): cls.nova_client = openstack_utils.get_nova_session_client( cls.keystone_session) - def test_instance_failover(self): - """Test masakari managed guest migration.""" - # Launch guest - vm_name = 'zaza-test-instance-failover' + @classmethod + def tearDown(cls): + """Bring hypervisors and services back up.""" + logging.info('Running teardown') + for unit in zaza.model.get_units('nova-compute', + model_name=cls.model_name): + zaza.configure.masakari.simulate_compute_host_recovery( + unit.entity_id, + model_name=cls.model_name) + zaza.utilities.openstack.enable_all_nova_services(cls.nova_client) + zaza.configure.masakari.enable_hosts() + + def ensure_guest(self, vm_name): + """Return the existing guest or boot a new one. + + :param vm_name: Name of guest to lookup + :type vm_name: str + """ try: - self.nova_client.servers.find(name=vm_name) + guest = self.nova_client.servers.find(name=vm_name) logging.info('Found existing guest') except novaclient.exceptions.NotFound: logging.info('Launching new guest') - zaza.configure.guest.launch_instance( + guest = zaza.configure.guest.launch_instance( 'bionic', use_boot_volume=True, vm_name=vm_name) + return guest - # Locate hypervisor hosting guest and shut it down + def get_guests_compute_info(self, vm_name): + """Return the hostname & juju unit of compute host hosting vm. + + :param vm_name: Name of guest to lookup + :type vm_name: str + """ current_hypervisor = zaza.utilities.openstack.get_hypervisor_for_guest( self.nova_client, vm_name) unit_name = juju_utils.get_unit_name_from_host_name( current_hypervisor, 'nova-compute') + return current_hypervisor, unit_name + + def get_guest_qemu_pid(self, compute_unit_name, vm_uuid, model_name=None): + """Return the qemu pid of process running guest. + + :param compute_unit_name: Juju unit name of hypervisor running guest + :type compute_unit_name: str + :param vm_uuid: Guests UUID + :type vm_uuid: str + :param model_name: Name of model running cloud. + :type model_name: str + """ + pid_find_cmd = 'pgrep -u libvirt-qemu -f {}'.format(vm_uuid) + out = zaza.model.run_on_unit( + compute_unit_name, + pid_find_cmd, + model_name=self.model_name) + return int(out['Stdout'].strip()) + + def test_instance_failover(self): + """Test masakari managed guest migration.""" + # Launch guest + vm_name = 'zaza-test-instance-failover' + self.ensure_guest(vm_name) + + # Locate hypervisor hosting guest and shut it down + current_hypervisor, unit_name = self.get_guests_compute_info(vm_name) zaza.configure.masakari.simulate_compute_host_failure( unit_name, model_name=self.model_name) @@ -80,3 +128,36 @@ class MasakariTest(test_utils.OpenStackBaseTest): model_name=self.model_name) zaza.utilities.openstack.enable_all_nova_services(self.nova_client) zaza.configure.masakari.enable_hosts() + + def test_instance_restart_on_fail(self): + """Test singlee guest crash and recovery.""" + vm_name = 'zaza-test-instance-failover' + vm = self.ensure_guest(vm_name) + _, unit_name = self.get_guests_compute_info(vm_name) + logging.info('{} is running on {}'.format(vm_name, unit_name)) + guest_pid = self.get_guest_qemu_pid( + unit_name, + vm.id, + model_name=self.model_name) + logging.info('{} pid is {}'.format(vm_name, guest_pid)) + inital_update_time = datetime.strptime( + vm.updated, + "%Y-%m-%dT%H:%M:%SZ") + logging.info('Simulating vm crash of {}'.format(vm_name)) + zaza.configure.masakari.simulate_vm_crash( + guest_pid, + unit_name, + model_name=self.model_name) + logging.info('Waiting for {} to be updated and become active'.format( + vm_name)) + zaza.utilities.openstack.wait_for_server_update_and_active( + self.nova_client, + vm_name, + inital_update_time) + new_guest_pid = self.get_guest_qemu_pid( + unit_name, + vm.id, + model_name=self.model_name) + logging.info('{} pid is now {}'.format(vm_name, guest_pid)) + assert new_guest_pid and new_guest_pid != guest_pid, ( + "Restart failed or never happened") diff --git a/zaza/configure/masakari.py b/zaza/configure/masakari.py index f4f84ac..75c6076 100644 --- a/zaza/configure/masakari.py +++ b/zaza/configure/masakari.py @@ -167,3 +167,20 @@ def simulate_compute_host_recovery(unit_name, model_name): 'start', ['corosync', 'pacemaker', 'nova-compute'], model_name) + + +def simulate_guest_crash(guest_pid, compute_unit_name, model_name): + """Simulate a guest crashing. + + :param guest_pid: PID of running qemu provess for guest. + :type guest_pid: str + :param compute_unit_name: Juju name of hypervisor hosting guest (app/n) + :type compute_unit_name: str + :param model_name: Name of model unit_name resides in. + :type model_name: str + """ + pid_kill_cmd = 'kill -9 {}' + zaza.model.run_on_unit( + compute_unit_name, + pid_kill_cmd.format(guest_pid), + model_name=model_name) diff --git a/zaza/utilities/.openstack.py.swp b/zaza/utilities/.openstack.py.swp new file mode 100644 index 0000000000000000000000000000000000000000..04d4ce13fa765e596706bd444653543bdee3ef47 GIT binary patch literal 16384 zcmeHNON<;x8EyzpjKML)oWjACaiC|>PLI95B#SIO9*;L8@9wPTv5qm$sHUf8rm{WV z?S9O7ylgBGiI7kfDY*ec5DpvwDa1JhP>d2l5jQ|w5aMa&ghU8n6C5YutFG#Kc{U=% zIYjD~zTN5iANAK)kM6&^8VA;kE94&IfQIWMn)b@#7e4p!8KOOQP}9OjXa}JXy!F+# zLuZg_P(R>~y|BIRL(*Zk?|2*8hDU9)!~E=ddY;NZVZbdOaFjVNv;BaY8-_dB-d`d~ z7)Tg+I}GgB4lNvvruzQWU1aYawYOuO=q3y#3?vLB3?vLB3?vLB3?vLB47|q~2;7fp z7tn_Ht9Hcc_WRU*{QpgLwN?4~Dft^p-caR#o|3<=b;`bYi&TvL|69pFtL&eel3!Kwrjqaaz@+^ZC3lqE zo|6Ad$xS8y{gnKlN^U9nksXu%|DohDKi`{@zcS^2_pOume^+u(`FE$}FDv;2O8%EA z`QMcMw2~jWZPLG@OS?ffrNpCfrNpCfrNpCfrNpCfrNpCfrNo~i2;g) zbuWDH75Ol}|Ht|NpY~|lAAqj|r+_Sw0j}S!Y1e>f02lZK@W>{627V6w6nFvn7Vu5L1&#op0d4_)@gYt74)8_bJm3K?umao(T;8Q=PXZla z5x5ta1NH&818;s%)2;w70lx!&30wj$0^bIn03HUu1ayHl;0TZcb^$wq+ki_uHSNoQ z2V{X)k+WU}t^h9qzX2`+j{p~dvp@y-B(M+I1H6np`32y|z;}VK01p5sfdcR;;C1Bc zSApLG7lB8B3%~}j1l$Si1wIN~$G*Vxz!q>6*a7?u$@QbaI{=oC8zDPDTQ6Mf|9Ne%R+RWf=MiBa$F7tibW>C`CX=nw+ zW~}Lxz#$DrxQ(+M)Z*t^Q{S4`A`dg12;+w3m>W=&T6$0TifTStDxX*`<&M=W)m*h! zsTc0g7uKr9(rSeqMqrwDCi1(f+q4^nVKQzxT^2A;pC@`Sa7AhUzFc{wUOlx|sGQcv zG|t3f%~TwoLCG|!-)T71YwEGZsKQxVvKb>CliSU=2uMnAbltXaLWXVE4kf+O%w}QW zId-N^1Jj3&hnsLTHkW2Z+mrqgx9VB64b=*+4&GPRtr2?sXXU|HLq;$5Djo)^G@p;MKc zGtHlzEjOzUIg6(1P*dw>)ggxJR1MMSy=nf{gr6K}@%$FGj4gn2-IRk|3_f+~n;x^U z=CiGg&%7SB@+}+s7XsT znw6y->9OUAeqpRMM}@N-^cLy|V)IeF6O|}4%w45$L-WKWma@A1rzw@m?l(+^&PQb8 zzZz$~1v##Iht!CP7f%`nor4B%f=_gP9HJUI6H2knN3Ub($#7#08IRFB6l?S9gM^Xo;8is)FHjY}g*h zwwWpBTs(D4YlT(3CFW1m)oM_wujPv6iX?gs02E#v3X{ zf!!v39&|`)c;FdnNGi1=J#DL6iOxoA+J0j3F2~EbSbRt*UNcG1VPu(`I6%z|C{!35 zFN&%cD!$81-ol!O-f4$exJlbV+iVe%%e*d+h7}rNH{s=Ev3g&rRwXBM<#KMdTExpz zsZ8>v)ni5ZI$kVis-rhq-I;fvB%Da+=HLSfKV4Tn6!ZouxMY@N!uRM5s{5> zoAf_Aj6OCU7k8}*l4$_Vfzq^{fP}v21vE~q;2=gkFhp2b$q=@9&zIw1s`FGo zjuVxOVvKuuo~+Af89{s`EzDEOC^h%#DBwKe!y9ZTAPWZ$-b3=#7Ef<#k>vpWA@cth zku$fESBv~V{yzI6a{Z@)$AKPD0CoVcA>aQI@I&BP;8DN=Hh_D9TY)!_@BbS3KF|Q} z2KECf;IGKEwR_2b{Py= z=o>BM$!YQ7<8V7KPKtBBX*zT>G{L;@=UTom6+ zNUs}tS|mu*WO1}_G%8<3JtEp z+aO{K#Kdk>Gx9*Bp%$4S;IbrBBs`+saRSyEwr$v4Dg!mNCPU0DsE>5&NU-ZsGty(# z&r1Wz=OV@$8N0^xqK-hC=o{FnL*AM8d!`{sMv{qN4Q^9!AUh;>Fwrrof-n<3vbjZ& z=x%PM3s~W7I>E%Q~d>D3(|{-b09d)GHI5>Xlj^Uvesf(hl~L zu>TNH4}(aLsa3;UvB@l-NgCoV(#z6Bj3_vvE$q|~)59k~(xOP-xAP?IJ<5^ikG39- zRZQC@F*%jfHnjf&Ymyx= literal 0 HcmV?d00001 diff --git a/zaza/utilities/exceptions.py b/zaza/utilities/exceptions.py index dc52cca..868a7c6 100644 --- a/zaza/utilities/exceptions.py +++ b/zaza/utilities/exceptions.py @@ -166,3 +166,9 @@ class NovaGuestMigrationFailed(Exception): """Nova guest migration failed.""" pass + + +class NovaGuestRestartFailed(Exception): + """Nova guest restart failed.""" + + pass diff --git a/zaza/utilities/openstack.py b/zaza/utilities/openstack.py index ad171cb..7dca504 100644 --- a/zaza/utilities/openstack.py +++ b/zaza/utilities/openstack.py @@ -42,6 +42,7 @@ from neutronclient.common import exceptions as neutronexceptions from octaviaclient.api.v2 import octavia as octaviaclient from swiftclient import client as swiftclient +import datetime import io import juju_wait import logging @@ -1922,6 +1923,37 @@ def wait_for_server_migration(nova_client, vm_name, original_hypervisor): current_hypervisor)) +@tenacity.retry(wait=tenacity.wait_exponential(multiplier=1, max=60), + reraise=True, stop=tenacity.stop_after_attempt(80), + retry=tenacity.retry_if_exception_type( + exceptions.NovaGuestRestartFailed)) +def wait_for_server_update_and_active(nova_client, vm_name, + original_updatetime): + """Wait for guests metadata to be updated and for status to become active. + + :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_updatetime: The time the metadata was previously updated. + :type original_updatetime: datetime + :raises: exceptions.NovaGuestMigrationFailed + """ + server = nova_client.servers.find(name=vm_name) + current_updatetime = datetime.datetime.strptime( + server.updated, + "%Y-%m-%dT%H:%M:%SZ") + if current_updatetime <= original_updatetime or server.status != 'ACTIVE': + logging.info('{} Updated: {} Satus: {})'.format( + vm_name, + current_updatetime, + server.status)) + raise exceptions.NovaGuestRestartFailed( + 'Restart of {} after crash failed'.format(vm_name)) + else: + logging.info('SUCCESS {} has restarted'.format(vm_name)) + + def enable_all_nova_services(nova_client): """Enable all nova services.