# Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you 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. import logging import random import SignedAPICall import time import XenAPI from solidfire.factory import ElementFactory from util import sf_util # All tests inherit from cloudstackTestCase from marvin.cloudstackTestCase import cloudstackTestCase # Import Integration Libraries # base - contains all resources as entities and defines create, delete, list operations on them from marvin.lib.base import Account, ServiceOffering, User, Host, StoragePool, VirtualMachine # common - commonly used methods for all tests are listed here from marvin.lib.common import get_domain, get_template, get_zone, list_clusters, list_hosts, list_volumes # utils - utility classes for common cleanup, external library wrappers, etc. from marvin.lib.utils import cleanup_resources # Prerequisites: # Only one zone # Only one pod # Only one cluster (two hosts for XenServer / one host for KVM with another added/removed during the tests) # # Running the tests: # Change the "hypervisor_type" variable to control which hypervisor type to test. # If using XenServer, set a breakpoint on each test after the first one. When the breakpoint is hit, reset the # added/removed host to a snapshot state and re-start it. Once it's up and running, run the test code. # Check that ip_address_of_new_xenserver_host / ip_address_of_new_kvm_host is correct. # If using XenServer, verify the "xen_server_master_hostname" variable is correct. # If using KVM, verify the "kvm_1_ip_address" variable is correct. # # Note: # If you do have more than one cluster, you might need to change this line: cls.cluster = list_clusters(cls.apiClient)[0] and # this variable's value: TestData.clusterId. class TestData: #constants account = "account" capacityBytes = "capacitybytes" capacityIops = "capacityiops" clusterId = "clusterId" computeOffering = "computeoffering" displayText = "displaytext" diskSize = "disksize" domainId = "domainId" hypervisor = "hypervisor" kvm = "kvm" mvip = "mvip" name = "name" newXenServerHost = "newXenServerHost" newKvmHost = "newKvmHost" newHostDisplayName = "newHostDisplayName" password = "password" podId = "podid" port = "port" primaryStorage = "primarystorage" primaryStorage2 = "primarystorage2" provider = "provider" scope = "scope" solidFire = "solidfire" storageTag = "SolidFire_SAN_1" storageTag2 = "SolidFire_Volume_1" tags = "tags" url = "url" user = "user" username = "username" virtualMachine = "virtualmachine" volume_1 = "volume_1" xenServer = "xenserver" zoneId = "zoneid" # modify to control which hypervisor type to test hypervisor_type = xenServer xen_server_master_hostname = "XenServer-6.5-1" kvm_1_ip_address = "10.117.40.111" ip_address_of_new_xenserver_host = "10.117.40.118" ip_address_of_new_kvm_host = "10.117.40.115" def __init__(self): self.testdata = { TestData.solidFire: { TestData.mvip: "10.117.78.225", TestData.username: "admin", TestData.password: "admin", TestData.port: 443, TestData.url: "https://10.117.78.225:443" }, TestData.kvm: { TestData.username: "root", TestData.password: "solidfire" }, TestData.xenServer: { TestData.username: "root", TestData.password: "solidfire" }, TestData.account: { "email": "test@test.com", "firstname": "John", "lastname": "Doe", TestData.username: "test", TestData.password: "test" }, TestData.user: { "email": "user@test.com", "firstname": "Jane", "lastname": "Doe", TestData.username: "testuser", TestData.password: "password" }, TestData.newXenServerHost: { TestData.username: "root", TestData.password: "solidfire", TestData.url: "http://" + TestData.ip_address_of_new_xenserver_host, TestData.podId : "1", TestData.zoneId: "1" }, TestData.newKvmHost: { TestData.username: "root", TestData.password: "solidfire", TestData.url: "http://" + TestData.ip_address_of_new_kvm_host, TestData.podId : "1", TestData.zoneId: "1" }, TestData.primaryStorage: { TestData.name: "SolidFire-%d" % random.randint(0, 100), TestData.scope: "ZONE", TestData.url: "MVIP=10.117.78.225;SVIP=10.117.94.225;" + "clusterAdminUsername=admin;clusterAdminPassword=admin;" + "clusterDefaultMinIops=10000;clusterDefaultMaxIops=15000;" + "clusterDefaultBurstIopsPercentOfMaxIops=1.5;", TestData.provider: "SolidFire", TestData.tags: TestData.storageTag, TestData.capacityIops: 4500000, TestData.capacityBytes: 2251799813685248, TestData.hypervisor: "Any" }, TestData.primaryStorage2: { TestData.name: "SolidFireShared-%d" % random.randint(0, 100), TestData.scope: "CLUSTER", TestData.url: "MVIP=10.117.78.225;SVIP=10.117.94.225;" + "clusterAdminUsername=admin;clusterAdminPassword=admin;" + "minIops=5000;maxIops=50000;burstIops=75000", TestData.provider: "SolidFireShared", TestData.tags: TestData.storageTag2, TestData.capacityIops: 5000, TestData.capacityBytes: 1099511627776, TestData.hypervisor: "XenServer", TestData.podId: 1 }, TestData.virtualMachine: { TestData.name: "TestVM", "displayname": "Test VM" }, TestData.computeOffering: { TestData.name: "SF_CO_1", TestData.displayText: "SF_CO_1 (Min IOPS = 10,000; Max IOPS = 15,000)", "cpunumber": 1, "cpuspeed": 100, "memory": 128, "storagetype": "shared", "customizediops": False, "miniops": "10000", "maxiops": "15000", "hypervisorsnapshotreserve": 200, TestData.tags: TestData.storageTag }, TestData.volume_1: { "diskname": "testvolume", }, TestData.newHostDisplayName: "XenServer-6.5-3", TestData.zoneId: 1, TestData.clusterId: 1, TestData.domainId: 1, TestData.url: "10.117.40.114" } class TestAddRemoveHosts(cloudstackTestCase): _vag_id_should_be_non_zero_int_err_msg = "The SolidFire VAG ID should be a non-zero integer." _sf_account_id_should_be_non_zero_int_err_msg = "The SolidFire account ID should be a non-zero integer." @classmethod def setUpClass(cls): # Set up API client testclient = super(TestAddRemoveHosts, cls).getClsTestClient() cls.apiClient = testclient.getApiClient() cls.configData = testclient.getParsedTestDataConfig() cls.dbConnection = testclient.getDbConnection() cls.testdata = TestData().testdata if TestData.hypervisor_type == TestData.xenServer: cls.xs_pool_master_ip = list_hosts(cls.apiClient, clusterid=cls.testdata[TestData.clusterId], name=TestData.xen_server_master_hostname)[0].ipaddress cls._connect_to_hypervisor() # Set up SolidFire connection solidfire = cls.testdata[TestData.solidFire] cls.sfe = ElementFactory.create(solidfire[TestData.mvip], solidfire[TestData.username], solidfire[TestData.password]) # Get Resources from Cloud Infrastructure cls.zone = get_zone(cls.apiClient, zone_id=cls.testdata[TestData.zoneId]) cls.cluster = list_clusters(cls.apiClient)[0] cls.template = get_template(cls.apiClient, cls.zone.id, hypervisor=TestData.hypervisor_type) cls.domain = get_domain(cls.apiClient, cls.testdata[TestData.domainId]) # Create test account cls.account = Account.create( cls.apiClient, cls.testdata[TestData.account], admin=1 ) # Set up connection to make customized API calls user = User.create( cls.apiClient, cls.testdata[TestData.user], account=cls.account.name, domainid=cls.domain.id ) url = cls.testdata[TestData.url] api_url = "http://" + url + ":8080/client/api" userkeys = User.registerUserKeys(cls.apiClient, user.id) cls.cs_api = SignedAPICall.CloudStack(api_url, userkeys.apikey, userkeys.secretkey) cls.compute_offering = ServiceOffering.create( cls.apiClient, cls.testdata[TestData.computeOffering] ) cls._cleanup = [ cls.compute_offering, user, cls.account ] @classmethod def tearDownClass(cls): try: cleanup_resources(cls.apiClient, cls._cleanup) sf_util.purge_solidfire_volumes(cls.sfe) except Exception as e: logging.debug("Exception in tearDownClass(cls): %s" % e) def setUp(self): self.virtual_machine = None self.cleanup = [] def tearDown(self): try: if self.virtual_machine is not None: self.virtual_machine.delete(self.apiClient, True) cleanup_resources(self.apiClient, self.cleanup) except Exception as e: logging.debug("Exception in tearDown(self): %s" % e) def test_add_remove_host_with_solidfire_plugin_1(self): primarystorage = self.testdata[TestData.primaryStorage] primary_storage = StoragePool.create( self.apiClient, primarystorage, scope=primarystorage[TestData.scope], zoneid=self.zone.id, provider=primarystorage[TestData.provider], tags=primarystorage[TestData.tags], capacityiops=primarystorage[TestData.capacityIops], capacitybytes=primarystorage[TestData.capacityBytes], hypervisor=primarystorage[TestData.hypervisor] ) self.cleanup.append(primary_storage) self.virtual_machine = VirtualMachine.create( self.apiClient, self.testdata[TestData.virtualMachine], accountid=self.account.name, zoneid=self.zone.id, serviceofferingid=self.compute_offering.id, templateid=self.template.id, domainid=self.domain.id, startvm=True ) if TestData.hypervisor_type == TestData.xenServer: root_volume = self._get_root_volume(self.virtual_machine) sf_iscsi_name = sf_util.get_iqn(self.cs_api, root_volume, self) self._perform_add_remove_xenserver_host(primary_storage.id, sf_iscsi_name) elif TestData.hypervisor_type == TestData.kvm: self._perform_add_remove_kvm_host(primary_storage.id) else: self.assertTrue(False, "Invalid hypervisor type") def test_add_remove_host_with_solidfire_plugin_2(self): if TestData.hypervisor_type != TestData.xenServer: return primarystorage2 = self.testdata[TestData.primaryStorage2] primary_storage_2 = StoragePool.create( self.apiClient, primarystorage2, scope=primarystorage2[TestData.scope], zoneid=self.zone.id, clusterid=self.cluster.id, provider=primarystorage2[TestData.provider], tags=primarystorage2[TestData.tags], capacityiops=primarystorage2[TestData.capacityIops], capacitybytes=primarystorage2[TestData.capacityBytes], hypervisor=primarystorage2[TestData.hypervisor] ) self.cleanup.append(primary_storage_2) sf_iscsi_name = self._get_iqn_2(primary_storage_2) self._perform_add_remove_xenserver_host(primary_storage_2.id, sf_iscsi_name) def test_add_remove_host_with_solidfire_plugin_3(self): if TestData.hypervisor_type != TestData.xenServer: return primarystorage = self.testdata[TestData.primaryStorage] primary_storage = StoragePool.create( self.apiClient, primarystorage, scope=primarystorage[TestData.scope], zoneid=self.zone.id, provider=primarystorage[TestData.provider], tags=primarystorage[TestData.tags], capacityiops=primarystorage[TestData.capacityIops], capacitybytes=primarystorage[TestData.capacityBytes], hypervisor=primarystorage[TestData.hypervisor] ) self.cleanup.append(primary_storage) self.virtual_machine = VirtualMachine.create( self.apiClient, self.testdata[TestData.virtualMachine], accountid=self.account.name, zoneid=self.zone.id, serviceofferingid=self.compute_offering.id, templateid=self.template.id, domainid=self.domain.id, startvm=True ) root_volume = self._get_root_volume(self.virtual_machine) sf_iscsi_name = sf_util.get_iqn(self.cs_api, root_volume, self) primarystorage2 = self.testdata[TestData.primaryStorage2] primary_storage_2 = StoragePool.create( self.apiClient, primarystorage2, scope=primarystorage2[TestData.scope], zoneid=self.zone.id, clusterid=self.cluster.id, provider=primarystorage2[TestData.provider], tags=primarystorage2[TestData.tags], capacityiops=primarystorage2[TestData.capacityIops], capacitybytes=primarystorage2[TestData.capacityBytes], hypervisor=primarystorage2[TestData.hypervisor] ) self.cleanup.append(primary_storage_2) self._perform_add_remove_xenserver_host(primary_storage.id, sf_iscsi_name) def test_add_remove_host_with_solidfire_plugin_4(self): if TestData.hypervisor_type != TestData.xenServer: return primarystorage2 = self.testdata[TestData.primaryStorage2] primary_storage_2 = StoragePool.create( self.apiClient, primarystorage2, scope=primarystorage2[TestData.scope], zoneid=self.zone.id, clusterid=self.cluster.id, provider=primarystorage2[TestData.provider], tags=primarystorage2[TestData.tags], capacityiops=primarystorage2[TestData.capacityIops], capacitybytes=primarystorage2[TestData.capacityBytes], hypervisor=primarystorage2[TestData.hypervisor] ) self.cleanup.append(primary_storage_2) sf_iscsi_name = self._get_iqn_2(primary_storage_2) primarystorage = self.testdata[TestData.primaryStorage] primary_storage = StoragePool.create( self.apiClient, primarystorage, scope=primarystorage[TestData.scope], zoneid=self.zone.id, provider=primarystorage[TestData.provider], tags=primarystorage[TestData.tags], capacityiops=primarystorage[TestData.capacityIops], capacitybytes=primarystorage[TestData.capacityBytes], hypervisor=primarystorage[TestData.hypervisor] ) self.cleanup.append(primary_storage) self.virtual_machine = VirtualMachine.create( self.apiClient, self.testdata[TestData.virtualMachine], accountid=self.account.name, zoneid=self.zone.id, serviceofferingid=self.compute_offering.id, templateid=self.template.id, domainid=self.domain.id, startvm=True ) self._perform_add_remove_xenserver_host(primary_storage_2.id, sf_iscsi_name) # Make sure each host is in its own VAG. # Create a VM that needs a new volume from the storage that has a VAG per host. # Verify the volume is in all VAGs. # Remove one of the hosts. # Check that the IQN is no longer in its previous VAG, but that the volume ID is still in that VAG, though. # Add the host back into the cluster. The IQN should be added to a VAG that already has an IQN from this cluster in it. def test_vag_per_host_5(self): hosts = list_hosts(self.apiClient, clusterid=self.cluster.id) self.assertTrue( len(hosts) >= 2, "There needs to be at least two hosts." ) unique_vag_ids = self._get_unique_vag_ids(hosts) self.assertTrue(len(hosts) == len(unique_vag_ids), "To run this test, each host should be in its own VAG.") primarystorage = self.testdata[TestData.primaryStorage] primary_storage = StoragePool.create( self.apiClient, primarystorage, scope=primarystorage[TestData.scope], zoneid=self.zone.id, provider=primarystorage[TestData.provider], tags=primarystorage[TestData.tags], capacityiops=primarystorage[TestData.capacityIops], capacitybytes=primarystorage[TestData.capacityBytes], hypervisor=primarystorage[TestData.hypervisor] ) self.cleanup.append(primary_storage) self.virtual_machine = VirtualMachine.create( self.apiClient, self.testdata[TestData.virtualMachine], accountid=self.account.name, zoneid=self.zone.id, serviceofferingid=self.compute_offering.id, templateid=self.template.id, domainid=self.domain.id, startvm=True ) root_volume = self._get_root_volume(self.virtual_machine) sf_account_id = sf_util.get_sf_account_id(self.cs_api, self.account.id, primary_storage.id, self, TestAddRemoveHosts._sf_account_id_should_be_non_zero_int_err_msg) sf_volumes = sf_util.get_active_sf_volumes(self.sfe, sf_account_id) sf_volume = sf_util.check_and_get_sf_volume(sf_volumes, root_volume.name, self) sf_vag_ids = sf_util.get_vag_ids(self.cs_api, self.cluster.id, primary_storage.id, self) sf_util.check_vags(sf_volume, sf_vag_ids, self) host = Host(hosts[0].__dict__) host_iqn = self._get_host_iqn(host) all_vags = sf_util.get_all_vags(self.sfe) host_vag = self._get_host_vag(host_iqn, all_vags) self.assertTrue(host_vag != None, "The host should be in a VAG.") host.delete(self.apiClient) sf_volumes = sf_util.get_active_sf_volumes(self.sfe, sf_account_id) sf_volume = sf_util.check_and_get_sf_volume(sf_volumes, root_volume.name, self) sf_util.check_vags(sf_volume, sf_vag_ids, self) all_vags = sf_util.get_all_vags(self.sfe) host_vag = self._get_host_vag(host_iqn, all_vags) self.assertTrue(host_vag == None, "The host should not be in a VAG.") details = { TestData.username: "root", TestData.password: "solidfire", TestData.url: "http://" + host.ipaddress, TestData.podId : host.podid, TestData.zoneId: host.zoneid } host = Host.create( self.apiClient, self.cluster, details, hypervisor=host.hypervisor ) self.assertTrue( isinstance(host, Host), "'host' is not a 'Host'." ) hosts = list_hosts(self.apiClient, clusterid=self.cluster.id) unique_vag_ids = self._get_unique_vag_ids(hosts) self.assertTrue(len(hosts) == len(unique_vag_ids) + 1, "There should be one more host than unique VAG.") def _get_unique_vag_ids(self, hosts): all_vags = sf_util.get_all_vags(self.sfe) unique_vag_ids = [] for host in hosts: host = Host(host.__dict__) host_iqn = self._get_host_iqn(host) host_vag = self._get_host_vag(host_iqn, all_vags) if host_vag != None and host_vag.volume_access_group_id not in unique_vag_ids: unique_vag_ids.append(host_vag.volume_access_group_id) return unique_vag_ids def _get_host_vag(self, host_iqn, vags): self.assertTrue(host_iqn, "'host_iqn' should not be 'None'.") self.assertTrue(vags, "'vags' should not be 'None'.") self.assertTrue(isinstance(host_iqn, basestring), "'host_iqn' should be a 'string'.") self.assertTrue(isinstance(vags, list), "'vags' should be a 'list'.") for vag in vags: if host_iqn in vag.initiators: return vag return None def _perform_add_remove_xenserver_host(self, primary_storage_id, sr_name): xen_sr = self.xen_session.xenapi.SR.get_by_name_label(sr_name)[0] pbds = self.xen_session.xenapi.SR.get_PBDs(xen_sr) self._verify_all_pbds_attached(pbds) num_pbds = len(pbds) sf_vag_id = sf_util.get_vag_id(self.cs_api, self.cluster.id, primary_storage_id, self) host_iscsi_iqns = self._get_xenserver_host_iscsi_iqns() sf_vag = self._get_sf_vag(sf_vag_id) sf_vag_initiators = self._get_sf_vag_initiators(sf_vag) self._verifyVag(host_iscsi_iqns, sf_vag_initiators) sf_vag_initiators_len_orig = len(sf_vag_initiators) xen_session = XenAPI.Session("https://" + TestData.ip_address_of_new_xenserver_host) xenserver = self.testdata[TestData.xenServer] xen_session.xenapi.login_with_password(xenserver[TestData.username], xenserver[TestData.password]) xen_session.xenapi.pool.join(self.xs_pool_master_ip, xenserver[TestData.username], xenserver[TestData.password]) time.sleep(60) pbds = self.xen_session.xenapi.SR.get_PBDs(xen_sr) self.assertEqual( len(pbds), num_pbds + 1, "'len(pbds)' is not equal to 'num_pbds + 1'." ) num_pbds = num_pbds + 1 num_pbds_not_attached = 0 for pbd in pbds: pbd_record = self.xen_session.xenapi.PBD.get_record(pbd) if pbd_record["currently_attached"] == False: num_pbds_not_attached = num_pbds_not_attached + 1 self.assertEqual( num_pbds_not_attached, 1, "'num_pbds_not_attached' is not equal to 1." ) host = Host.create( self.apiClient, self.cluster, self.testdata[TestData.newXenServerHost], hypervisor="XenServer" ) self.assertTrue( isinstance(host, Host), "'host' is not a 'Host'." ) pbds = self.xen_session.xenapi.SR.get_PBDs(xen_sr) self.assertEqual( len(pbds), num_pbds, "'len(pbds)' is not equal to 'num_pbds'." ) self._verify_all_pbds_attached(pbds) host_iscsi_iqns = self._get_xenserver_host_iscsi_iqns() sf_vag = self._get_sf_vag(sf_vag_id) sf_vag_initiators = self._get_sf_vag_initiators(sf_vag) self._verifyVag(host_iscsi_iqns, sf_vag_initiators) sf_vag_initiators_len_new = len(sf_vag_initiators) self.assertEqual( sf_vag_initiators_len_new, sf_vag_initiators_len_orig + 1, "sf_vag_initiators_len_new' != sf_vag_initiators_len_orig + 1" ) host.delete(self.apiClient) pbds = self.xen_session.xenapi.SR.get_PBDs(xen_sr) self.assertEqual( len(pbds), num_pbds, "'len(pbds)' is not equal to 'num_pbds'." ) self._verify_all_pbds_attached(pbds) host_iscsi_iqns = self._get_xenserver_host_iscsi_iqns() sf_vag = self._get_sf_vag(sf_vag_id) sf_vag_initiators = self._get_sf_vag_initiators(sf_vag) self.assertEqual( len(host_iscsi_iqns) - 1, len(sf_vag_initiators), "'len(host_iscsi_iqns) - 1' is not equal to 'len(sf_vag_initiators)'." ) host_ref = self.xen_session.xenapi.host.get_by_name_label(self.testdata[TestData.newHostDisplayName])[0] self.xen_session.xenapi.pool.eject(host_ref) time.sleep(120) pbds = self.xen_session.xenapi.SR.get_PBDs(xen_sr) self.assertEqual( len(pbds), num_pbds - 1, "'len(pbds)' is not equal to 'num_pbds - 1'." ) self._verify_all_pbds_attached(pbds) host_iscsi_iqns = self._get_xenserver_host_iscsi_iqns() sf_vag = self._get_sf_vag(sf_vag_id) sf_vag_initiators = self._get_sf_vag_initiators(sf_vag) self._verifyVag(host_iscsi_iqns, sf_vag_initiators) sf_vag_initiators_len_new = len(sf_vag_initiators) self.assertEqual( sf_vag_initiators_len_new, sf_vag_initiators_len_orig, "sf_vag_initiators_len_new' != sf_vag_initiators_len_orig" ) def _perform_add_remove_kvm_host(self, primary_storage_id): sf_vag_id = sf_util.get_vag_id(self.cs_api, self.cluster.id, primary_storage_id, self) kvm_login = self.testdata[TestData.kvm] kvm_hosts = [] kvm_hosts.append(TestData.kvm_1_ip_address) host_iscsi_iqns = self._get_kvm_host_iscsi_iqns(kvm_hosts, kvm_login[TestData.username], kvm_login[TestData.password]) sf_vag = self._get_sf_vag(sf_vag_id) sf_vag_initiators = self._get_sf_vag_initiators(sf_vag) self._verifyVag(host_iscsi_iqns, sf_vag_initiators) sf_vag_initiators_len_orig = len(sf_vag_initiators) host = Host.create( self.apiClient, self.cluster, self.testdata[TestData.newKvmHost], hypervisor="KVM" ) self.assertTrue( isinstance(host, Host), "'host' is not a 'Host'." ) kvm_hosts = [] kvm_hosts.append(TestData.kvm_1_ip_address) kvm_hosts.append(TestData.ip_address_of_new_kvm_host) host_iscsi_iqns = self._get_kvm_host_iscsi_iqns(kvm_hosts, kvm_login[TestData.username], kvm_login[TestData.password]) sf_vag = self._get_sf_vag(sf_vag_id) sf_vag_initiators = self._get_sf_vag_initiators(sf_vag) self._verifyVag(host_iscsi_iqns, sf_vag_initiators) sf_vag_initiators_len_new = len(sf_vag_initiators) self.assertEqual( sf_vag_initiators_len_new, sf_vag_initiators_len_orig + 1, "sf_vag_initiators_len_new' != sf_vag_initiators_len_orig + 1" ) host.delete(self.apiClient) kvm_hosts = [] kvm_hosts.append(TestData.kvm_1_ip_address) host_iscsi_iqns = self._get_kvm_host_iscsi_iqns(kvm_hosts, kvm_login[TestData.username], kvm_login[TestData.password]) sf_vag = self._get_sf_vag(sf_vag_id) sf_vag_initiators = self._get_sf_vag_initiators(sf_vag) self._verifyVag(host_iscsi_iqns, sf_vag_initiators) sf_vag_initiators_len_new = len(sf_vag_initiators) self.assertEqual( sf_vag_initiators_len_new, sf_vag_initiators_len_orig, "sf_vag_initiators_len_new' != sf_vag_initiators_len_orig" ) def _verify_all_pbds_attached(self, pbds): for pbd in pbds: pbd_record = self.xen_session.xenapi.PBD.get_record(pbd) self.assertEqual( pbd_record["currently_attached"], True, "Not all PBDs are currently attached." ) def _get_root_volume(self, vm): list_volumes_response = list_volumes( self.apiClient, virtualmachineid=vm.id, listall=True ) self.assertNotEqual( list_volumes_response, None, "'list_volumes_response' should not be equal to 'None'." ) self.assertEqual( len(list_volumes_response) > 0, True, "'len(list_volumes_response)' should be greater than 0." ) for volume in list_volumes_response: if volume.type.upper() == "ROOT": return volume self.assert_(False, "Unable to locate the ROOT volume of the VM with the following ID: " + str(vm.id)) def _get_iqn_2(self, primary_storage): sql_query = "Select path From storage_pool Where uuid = '" + str(primary_storage.id) + "'" # make sure you can connect to MySQL: https://teamtreehouse.com/community/cant-connect-remotely-to-mysql-server-with-mysql-workbench sql_result = self.dbConnection.execute(sql_query) return sql_result[0][0] def _get_host_iqn(self, host): sql_query = "Select url From host Where uuid = '" + str(host.id) + "'" # make sure you can connect to MySQL: https://teamtreehouse.com/community/cant-connect-remotely-to-mysql-server-with-mysql-workbench sql_result = self.dbConnection.execute(sql_query) return sql_result[0][0] def _get_xenserver_host_iscsi_iqns(self): hosts = self.xen_session.xenapi.host.get_all() self.assertEqual( isinstance(hosts, list), True, "'hosts' is not a list." ) host_iscsi_iqns = [] for host in hosts: host_iscsi_iqns.append(self._get_xenserver_host_iscsi_iqn(host)) return host_iscsi_iqns def _get_xenserver_host_iscsi_iqn(self, host): other_config = self.xen_session.xenapi.host.get_other_config(host) return other_config["iscsi_iqn"] def _get_kvm_host_iscsi_iqns(self, kvm_ip_addresses, common_username, common_password): host_iscsi_iqns = [] for kvm_ip_address in kvm_ip_addresses: host_iscsi_iqn = self._get_kvm_iqn(kvm_ip_address, common_username, common_password) host_iscsi_iqns.append(host_iscsi_iqn) return host_iscsi_iqns def _get_kvm_iqn(self, ip_address, username, password): ssh_connection = sf_util.get_ssh_connection(ip_address, username, password) searchFor = "InitiatorName=" stdout = ssh_connection.exec_command("sudo grep " + searchFor + " /etc/iscsi/initiatorname.iscsi")[1] result = stdout.read() ssh_connection.close() self.assertFalse(result is None, "Unable to locate the IQN of the KVM host (None)") self.assertFalse(len(result.strip()) == 0, "Unable to locate the IQN of the KVM host (Zero-length string)") return result[len(searchFor):].strip() def _get_sf_vag(self, sf_vag_id): return self.sfe.list_volume_access_groups(sf_vag_id, 1).volume_access_groups[0] def _get_sf_vag_initiators(self, sf_vag): return sf_vag.initiators def _verifyVag(self, host_iscsi_iqns, sf_vag_initiators): self.assertEqual( isinstance(host_iscsi_iqns, list), True, "'host_iscsi_iqns' is not a list." ) self.assertEqual( isinstance(sf_vag_initiators, list), True, "'sf_vag_initiators' is not a list." ) self.assertEqual( len(host_iscsi_iqns), len(sf_vag_initiators), "Lists are not the same size." ) for host_iscsi_iqn in host_iscsi_iqns: # an error should occur if host_iscsi_iqn is not in sf_vag_initiators sf_vag_initiators.index(host_iscsi_iqn) @classmethod def _connect_to_hypervisor(cls): if TestData.hypervisor_type == TestData.kvm: pass elif TestData.hypervisor_type == TestData.xenServer: host_ip = "https://" + \ list_hosts(cls.apiClient, clusterid=cls.testdata[TestData.clusterId], name=TestData.xen_server_master_hostname)[0].ipaddress cls.xen_session = XenAPI.Session(host_ip) xen_server = cls.testdata[TestData.xenServer] cls.xen_session.xenapi.login_with_password(xen_server[TestData.username], xen_server[TestData.password])