Skip to content

Commit d4e302d

Browse files
smoketest: Fix test_vm_life_cycle secure migration tests (apache#2715)
This fixes intermittently failing secure live VM migration tests on KVM. Signed-off-by: Rohit Yadav <[email protected]>
1 parent 539d7e1 commit d4e302d

File tree

1 file changed

+120
-172
lines changed

1 file changed

+120
-172
lines changed

test/integration/smoke/test_vm_life_cycle.py

+120-172
Original file line numberDiff line numberDiff line change
@@ -839,7 +839,6 @@ def setUpClass(cls):
839839

840840
@classmethod
841841
def tearDownClass(cls):
842-
843842
cls.apiclient = super(TestSecuredVmMigration, cls).getClsTestClient().getApiClient()
844843
try:
845844
cleanup_resources(cls.apiclient, cls._cleanup)
@@ -850,136 +849,30 @@ def setUp(self):
850849
self.apiclient = self.testClient.getApiClient()
851850
self.dbclient = self.testClient.getDbConnection()
852851
self.cleanup = []
852+
853853
if self.hypervisor.lower() not in ["kvm"]:
854854
self.skipTest("Secured migration is not supported on other than KVM")
855855

856+
self.hosts = Host.list(
857+
self.apiclient,
858+
zoneid=self.zone.id,
859+
type='Routing',
860+
hypervisor='KVM')
861+
862+
if len(self.hosts) < 2:
863+
self.skipTest("Requires at least two hosts for performing migration related tests")
864+
865+
self.secure_all_hosts()
856866
self.updateConfiguration("ca.plugin.root.auth.strictness", "false")
857-
self.make_all_hosts_secure()
858867

859868
def tearDown(self):
860-
self.make_all_hosts_secure()
861-
869+
self.secure_all_hosts()
870+
self.updateConfiguration("ca.plugin.root.auth.strictness", "true")
862871
try:
863872
cleanup_resources(self.apiclient, self.cleanup)
864873
except Exception as e:
865874
raise Exception("Warning: Exception during cleanup : %s" % e)
866875

867-
@attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false")
868-
def test_01_secured_vm_migration(self):
869-
"""Test secured VM migration"""
870-
871-
# Validate the following
872-
# 1. Environment has enough hosts for migration
873-
# 2. DeployVM on suitable host (with another host in the cluster)
874-
# 3. Migrate the VM and assert migration successful
875-
876-
hosts = self.get_hosts()
877-
878-
secured_hosts = []
879-
880-
for host in hosts:
881-
if host.details.secured == 'true':
882-
secured_hosts.append(host)
883-
884-
if len(secured_hosts) < 2:
885-
self.skipTest("At least two hosts should be present in the zone for migration")
886-
887-
origin_host = secured_hosts[0]
888-
889-
self.vm_to_migrate = self.deploy_vm(origin_host)
890-
891-
target_host = self.get_target_host(secured='true', virtualmachineid=self.vm_to_migrate.id)
892-
893-
self.migrate_and_check(origin_host, target_host, proto='tls')
894-
895-
@attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false")
896-
def test_02_not_secured_vm_migration(self):
897-
"""Test Non-secured VM Migration
898-
"""
899-
#self.skipTest()
900-
# Validate the following
901-
# 1. Prepare 2 hosts to run in non-secured more
902-
# 2. DeployVM on suitable host (with another host in the cluster)
903-
# 3. Migrate the VM and assert migration successful
904-
hosts = self.get_hosts()
905-
for host in hosts:
906-
self.make_unsecure_connection(host)
907-
908-
non_secured_hosts = []
909-
910-
hosts = self.get_hosts()
911-
912-
for host in hosts:
913-
if host.details.secured == 'false':
914-
non_secured_hosts.append(host)
915-
916-
if len(non_secured_hosts) < 2:
917-
self.skipTest("At least two hosts should be present in the zone for migration")
918-
origin_host = non_secured_hosts[0]
919-
920-
self.vm_to_migrate = self.deploy_vm(origin_host)
921-
922-
target_host = self.get_target_host(secured='false', virtualmachineid=self.vm_to_migrate.id)
923-
924-
self.migrate_and_check(origin_host, target_host, proto='tcp')
925-
926-
@attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false")
927-
def test_03_secured_to_nonsecured_vm_migration(self):
928-
"""Test destroy Virtual Machine
929-
"""
930-
931-
# Validate the following
932-
# 1. Makes one of the hosts non-secured
933-
# 2. Deploys a VM to a Secured host
934-
# 3. Migrates the VM to the non-secured host and assers the migration is via TCP.
935-
936-
hosts = self.get_hosts()
937-
938-
non_secured_host = self.make_unsecure_connection(hosts[0])
939-
940-
secured_hosts = []
941-
hosts = self.get_hosts()
942-
943-
for host in hosts:
944-
if host.details.secured == 'true':
945-
secured_hosts.append(host)
946-
947-
self.vm_to_migrate = self.deploy_vm(secured_hosts[0])
948-
try:
949-
self.migrate_and_check(origin_host=secured_hosts[0], destination_host=non_secured_host, proto='tcp')
950-
except Exception:
951-
pass
952-
else: self.fail("Migration succeed, instead it should fail")
953-
954-
@attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false")
955-
def test_04_nonsecured_to_secured_vm_migration(self):
956-
"""Test Non-secured VM Migration
957-
"""
958-
959-
# Validate the following
960-
# 1. Makes one of the hosts non-secured
961-
# 2. Deploys a VM to the non-secured host
962-
# 3. Migrates the VM to the secured host and assers the migration is via TCP.
963-
hosts = self.get_hosts()
964-
965-
non_secured_host = self.make_unsecure_connection(hosts[0])
966-
967-
secured_hosts = []
968-
969-
hosts = self.get_hosts()
970-
for host in hosts:
971-
if host.details.secured == 'true':
972-
secured_hosts.append(host)
973-
974-
self.vm_to_migrate = self.deploy_vm(non_secured_host)
975-
976-
try:
977-
self.migrate_and_check(origin_host=non_secured_host, destination_host=secured_hosts[0], proto='tcp')
978-
except Exception:
979-
pass
980-
else:
981-
self.fail("Migration succeed, instead it should fail")
982-
983876
def get_target_host(self, secured, virtualmachineid):
984877
target_hosts = Host.listForMigration(self.apiclient,
985878
virtualmachineid=virtualmachineid)
@@ -992,55 +885,44 @@ def get_target_host(self, secured, virtualmachineid):
992885

993886
def check_migration_protocol(self, protocol, host):
994887
resp = SshClient(host.ipaddress, port=22, user=self.hostConfig["username"],passwd=self.hostConfig["password"])\
995-
.execute("grep -a Live /var/log/cloudstack/agent/agent.log | tail -1")
888+
.execute("grep -a listen_%s=1 /etc/libvirt/libvirtd.conf | tail -1" % protocol)
996889

997890
if protocol not in resp[0]:
998-
cloudstackTestCase.fail(self, "Migration protocol was not as expected: '" + protocol + "\n"
999-
"Instead we got: " + resp[0])
1000-
1001-
def make_unsecure_connection(self, host):
1002-
SshClient(host.ipaddress, port=22, user=self.hostConfig["username"],passwd=self.hostConfig["password"])\
1003-
.execute("rm -f /etc/cloudstack/agent/cloud*")
1004-
1005-
SshClient(host.ipaddress, port=22, user=self.hostConfig["username"],passwd=self.hostConfig["password"])\
1006-
.execute("sed -i 's/listen_tls.*/listen_tls=0/g' /etc/libvirt/libvirtd.conf")
1007-
SshClient(host.ipaddress, port=22, user=self.hostConfig["username"],passwd=self.hostConfig["password"])\
1008-
.execute("sed -i 's/listen_tcp.*/listen_tcp=1/g' /etc/libvirt/libvirtd.conf ")
1009-
SshClient(host.ipaddress, port=22, user=self.hostConfig["username"],passwd=self.hostConfig["password"])\
1010-
.execute("sed -i '/.*_file.*/d' /etc/libvirt/libvirtd.conf")
1011-
SshClient(host.ipaddress, port=22, user=self.hostConfig["username"],passwd=self.hostConfig["password"])\
1012-
.execute("service libvirtd restart")
1013-
SshClient(host.ipaddress, port=22, user=self.hostConfig["username"],passwd=self.hostConfig["password"])\
1014-
.execute("service cloudstack-agent restart")
891+
cloudstackTestCase.fail(self, "Libvirt listen protocol expected: '" + protocol + "\n"
892+
"does not match actual: " + resp[0])
893+
894+
def migrate_and_check(self, vm, src_host, dest_host, proto='tls'):
895+
"""
896+
Migrates a VM from source host to destination host and checks status
897+
"""
898+
self.check_migration_protocol(protocol=proto, host=src_host)
899+
vm.migrate(self.apiclient, hostid=dest_host.id)
900+
vm_response = VirtualMachine.list(self.apiclient, id=vm.id)[0]
901+
self.assertEqual(vm_response.hostid, dest_host.id, "Check destination host ID of migrated VM")
902+
903+
def unsecure_host(self, host):
904+
SshClient(host.ipaddress, port=22, user=self.hostConfig["username"], passwd=self.hostConfig["password"])\
905+
.execute("rm -f /etc/cloudstack/agent/cloud* && \
906+
sed -i 's/listen_tls.*/listen_tls=0/g' /etc/libvirt/libvirtd.conf && \
907+
sed -i 's/listen_tcp.*/listen_tcp=1/g' /etc/libvirt/libvirtd.conf && \
908+
sed -i '/.*_file=.*/d' /etc/libvirt/libvirtd.conf && \
909+
service libvirtd restart && \
910+
service cloudstack-agent restart")
1015911

1016-
self.check_connection(host=host, secured='false')
1017912
time.sleep(10)
913+
self.check_connection(host=host, secured='false')
1018914
return host
1019915

1020-
def make_all_hosts_secure(self):
1021-
hosts = Host.list(
1022-
self.apiclient,
1023-
zoneid=self.zone.id,
1024-
type='Routing'
1025-
)
1026-
for host in hosts:
916+
def secure_all_hosts(self):
917+
for host in self.hosts:
1027918
cmd = provisionCertificate.provisionCertificateCmd()
1028919
cmd.hostid = host.id
920+
cmd.reconnect = True
1029921
self.apiclient.updateConfiguration(cmd)
1030922

1031-
for host in hosts:
923+
for host in self.hosts:
1032924
self.check_connection(secured='true', host=host)
1033925

1034-
def get_hosts(self):
1035-
1036-
hosts = Host.list(
1037-
self.apiclient,
1038-
zoneid=self.zone.id,
1039-
type='Routing'
1040-
)
1041-
self.assertEqual(validateList(hosts)[0], PASS, "hosts list validation failed")
1042-
return hosts
1043-
1044926
def deploy_vm(self, origin_host):
1045927
return VirtualMachine.create(
1046928
self.apiclient,
@@ -1049,10 +931,9 @@ def deploy_vm(self, origin_host):
1049931
domainid=self.account.domainid,
1050932
serviceofferingid=self.small_offering.id,
1051933
mode=self.services["mode"],
1052-
hostid=origin_host.id
1053-
)
934+
hostid=origin_host.id)
1054935

1055-
def check_connection(self, secured, host, retries=5, interval=5):
936+
def check_connection(self, secured, host, retries=20, interval=6):
1056937

1057938
while retries > -1:
1058939
time.sleep(interval)
@@ -1069,21 +950,88 @@ def check_connection(self, secured, host, retries=5, interval=5):
1069950
else:
1070951
return
1071952

1072-
raise Exception("Host communication is not as expected: " + secured +
1073-
". Instead it's: " + host.details.secured)
953+
raise Exception("Host detail 'secured' was expected: " + secured +
954+
", actual is: " + host.details.secured)
955+
956+
def updateConfiguration(self, name, value):
957+
cmd = updateConfiguration.updateConfigurationCmd()
958+
cmd.name = name
959+
cmd.value = value
960+
self.apiclient.updateConfiguration(cmd)
961+
962+
@attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg", "security"], required_hardware="false")
963+
def test_01_secure_vm_migration(self):
964+
"""Test secure VM migration"""
965+
# Validate the following
966+
# 1. Environment has enough hosts for migration
967+
# 2. DeployVM on suitable host (with another host in the cluster)
968+
# 3. Migrate the VM and assert migration successful
969+
970+
src_host = self.hosts[0]
971+
vm = self.deploy_vm(src_host)
972+
self.cleanup.append(vm)
973+
974+
dest_host = self.get_target_host(secured='true', virtualmachineid=vm.id)
975+
self.migrate_and_check(vm, src_host, dest_host)
976+
977+
@attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg", "security"], required_hardware="false")
978+
def test_02_unsecure_vm_migration(self):
979+
"""Test Non-secured VM Migration
980+
"""
981+
# Validate the following
982+
# 1. Prepare 2 hosts to run in non-secured more
983+
# 2. DeployVM on suitable host (with another host in the cluster)
984+
# 3. Migrate the VM and assert migration successful
1074985

1075-
def migrate_and_check(self, origin_host, destination_host, proto):
986+
for host in self.hosts:
987+
self.unsecure_host(host)
1076988

1077-
self.vm_to_migrate.migrate(self.apiclient, hostid=destination_host.id)
989+
src_host = self.hosts[0]
990+
vm = self.deploy_vm(src_host)
991+
self.cleanup.append(vm)
1078992

1079-
self.check_migration_protocol(protocol=proto, host=origin_host)
993+
dest_host = self.get_target_host(secured='false', virtualmachineid=vm.id)
994+
self.migrate_and_check(vm, src_host, dest_host, proto='tcp')
1080995

1081-
vm_response = VirtualMachine.list(self.apiclient, id=self.vm_to_migrate.id)[0]
996+
@attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg", "security"], required_hardware="false")
997+
def test_03_secured_to_nonsecured_vm_migration(self):
998+
"""Test destroy Virtual Machine
999+
"""
1000+
# Validate the following
1001+
# 1. Makes one of the hosts non-secured
1002+
# 2. Deploys a VM to a Secured host
1003+
# 3. Migrates the VM to the non-secured host via TLS, and ensure exception
10821004

1083-
self.assertEqual(vm_response.hostid, destination_host.id, "Check destination hostID of migrated VM")
1005+
unsecure_host = self.unsecure_host(self.hosts[0])
1006+
secure_host = self.hosts[1]
1007+
1008+
vm = self.deploy_vm(secure_host)
1009+
self.cleanup.append(vm)
1010+
1011+
try:
1012+
self.migrate_and_check(vm, secure_host, unsecure_host, proto='tls')
1013+
except Exception:
1014+
pass
1015+
else: self.fail("Migration succeeded, instead it should fail")
1016+
1017+
@attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg", "security"], required_hardware="false")
1018+
def test_04_nonsecured_to_secured_vm_migration(self):
1019+
"""Test Non-secured VM Migration
1020+
"""
1021+
# Validate the following
1022+
# 1. Makes one of the hosts non-secured
1023+
# 2. Deploys a VM to the non-secured host
1024+
# 3. Migrates the VM to the non-secured host via TCP, and ensure exception
1025+
1026+
unsecure_host = self.unsecure_host(self.hosts[0])
1027+
secure_host = self.hosts[1]
1028+
1029+
vm = self.deploy_vm(unsecure_host)
1030+
self.cleanup.append(vm)
1031+
1032+
try:
1033+
self.migrate_and_check(vm, unsecure_host, secure_host, proto='tcp')
1034+
except Exception:
1035+
pass
1036+
else: self.fail("Migration succeeded, instead it should fail")
10841037

1085-
def updateConfiguration(self, name, value):
1086-
cmd = updateConfiguration.updateConfigurationCmd()
1087-
cmd.name = name
1088-
cmd.value = value
1089-
self.apiclient.updateConfiguration(cmd)

0 commit comments

Comments
 (0)