Exemplo n.º 1
0
def _get_env_info():
    """
    Retrieve number of env nodes and the last two ip digits to add to the testrail title
    """
    number_of_nodes = len(GeneralStorageRouter.get_storage_routers())
    split_ip = GeneralStorageRouter.get_local_storagerouter().ip.split('.')
    return str(number_of_nodes) + 'N-' + split_ip[2] + '.' + split_ip[3]
Exemplo n.º 2
0
    def prepare_alba_backend(name=None):
        """
        Create an ALBA backend and claim disks
        :param name: Name for the backend
        :return: None
        """
        # @TODO: Fix this, because backend_type should not be configurable if you always create an ALBA backend
        # @TODO 2: Get rid of these asserts, any test (or testsuite) should verify the required params first before starting execution
        autotest_config = General.get_config()
        if name is None:
            name = autotest_config.get('backend', 'name')
        nr_of_disks_to_claim = autotest_config.getint('backend', 'nr_of_disks_to_claim')
        type_of_disks_to_claim = autotest_config.get('backend', 'type_of_disks_to_claim')
        assert name,\
            "Please fill out a valid backend name in autotest.cfg file"

        storage_routers = GeneralStorageRouter.get_storage_routers()
        for sr in storage_routers:
            if GeneralStorageRouter.has_roles(storagerouter=sr, roles='DB') is False:
                GeneralDisk.add_db_role(sr)
            if GeneralStorageRouter.has_roles(storagerouter=sr, roles=['SCRUB', 'WRITE']) is False:
                GeneralDisk.add_write_scrub_roles(sr)
        backend = GeneralBackend.get_by_name(name)
        if not backend:
            alba_backend = GeneralAlba.add_alba_backend(name)
        else:
            alba_backend = backend.alba_backend
        GeneralAlba.claim_asds(alba_backend, nr_of_disks_to_claim, type_of_disks_to_claim)
        if GeneralAlba.has_preset(alba_backend=alba_backend,
                                  preset_name=GeneralAlba.ONE_DISK_PRESET) is False:
            GeneralAlba.add_preset(alba_backend=alba_backend,
                                   name=GeneralAlba.ONE_DISK_PRESET,
                                   policies=[[1, 1, 1, 2]])
Exemplo n.º 3
0
def setup():
    """
    Setup for Arakoon package, will be executed when any test in this package is being executed
    Make necessary changes before being able to run the tests
    :return: None
    """
    autotest_config = General.get_config()
    backend_name = autotest_config.get('backend', 'name')
    assert backend_name, 'Please fill out a backend name in the autotest.cfg file'
    backend = GeneralBackend.get_by_name(backend_name)
    if backend is not None:
        GeneralAlba.remove_alba_backend(backend.alba_backend)

    for storagerouter in GeneralStorageRouter.get_masters():
        root_client = SSHClient(storagerouter, username='******')
        if GeneralService.get_service_status(name='ovs-scheduled-tasks',
                                             client=root_client) is True:
            GeneralService.stop_service(name='ovs-scheduled-tasks',
                                        client=root_client)

    storagerouters = GeneralStorageRouter.get_storage_routers()
    for sr in storagerouters:
        root_client = SSHClient(sr, username='******')
        GeneralDisk.add_db_role(sr)

        for location in TEST_CLEANUP:
            root_client.run('rm -rf {0}'.format(location))

    GeneralAlba.add_alba_backend(backend_name)
    GeneralArakoon.voldrv_arakoon_checkup()
    def json_files_check_test():
        """
        Verify some configuration files in json format
        """
        issues_found = ''

        srs = GeneralStorageRouter.get_storage_routers()
        for sr in srs:
            config_contents = EtcdConfiguration.get('/ovs/framework/hosts/{0}/setupcompleted'.format(sr.machine_id), raw = True)
            if "true" not in config_contents:
                issues_found += "Setup not completed for node {0}\n".format(sr.name)

        assert issues_found == '', "Found the following issues while checking for the setupcompleted:{0}\n".format(issues_found)
    def fdl_0001_match_model_with_reality_test():
        """
        FDL-0001 - disks in ovs model should match actual physical disk configuration
        """
        if TestFlexibleDiskLayout.continue_testing.state is False:
            logger.info('Test suite signaled to stop')
            return
        GeneralStorageRouter.sync_with_reality()

        physical_disks = dict()
        modelled_disks = dict()
        loops = dict()

        storagerouters = GeneralStorageRouter.get_storage_routers()
        for storagerouter in storagerouters:
            root_client = SSHClient(storagerouter, username='******')
            hdds, ssds = GeneralDisk.get_physical_disks(client=root_client)
            physical_disks[storagerouter.guid] = hdds
            physical_disks[storagerouter.guid].update(ssds)
            loop_devices = General.get_loop_devices(client=root_client)
            loops[storagerouter.guid] = loop_devices

        disks = GeneralDisk.get_disks()
        for disk in disks:
            if disk.storagerouter_guid not in modelled_disks:
                modelled_disks[disk.storagerouter_guid] = dict()
            if disk.name not in loops[disk.storagerouter_guid]:
                modelled_disks[disk.storagerouter_guid][disk.name] = {'is_ssd': disk.is_ssd}

        logger.info('PDISKS: {0}'.format(physical_disks))
        logger.info('MDISKS: {0}'.format(modelled_disks))

        assert len(modelled_disks.keys()) == len(physical_disks.keys()),\
            "Nr of modelled/physical disks is NOT equal!:\n PDISKS: {0}\nMDISKS: {1}".format(modelled_disks,
                                                                                             physical_disks)

        for guid in physical_disks.keys():
            assert len(physical_disks[guid]) == len(modelled_disks[guid]),\
                "Nr of modelled/physical disks differs for storagerouter {0}:\n{1}\n{2}".format(guid,
                                                                                                physical_disks[guid],
                                                                                                modelled_disks[guid])

        # basic check on hdd/ssd
        for guid in physical_disks.keys():
            mdisks = modelled_disks[guid]
            pdisks = physical_disks[guid]
            for key in mdisks.iterkeys():
                assert mdisks[key]['is_ssd'] == pdisks[key]['is_ssd'],\
                    "Disk incorrectly modelled for storagerouter {0}\n,mdisk:{1}\n,pdisk:{2}".format(guid,
                                                                                                     mdisks[key],
                                                                                                     pdisks[key])
Exemplo n.º 6
0
    def validate_alba_backend_removal(alba_backend_info):
        """
        Validate whether the backend has been deleted properly
        alba_backend_info should be a dictionary containing:
            - guid
            - name
            - maintenance_service_names
        :param alba_backend_info: Information about the backend
        :return: None
        """
        Toolbox.verify_required_params(actual_params=alba_backend_info,
                                       required_params={'name': (str, None),
                                                        'guid': (str, Toolbox.regex_guid),
                                                        'maintenance_service_names': (list, None)},
                                       exact_match=True)

        alba_backend_guid = alba_backend_info['guid']
        alba_backend_name = alba_backend_info['name']
        backend = GeneralBackend.get_by_name(alba_backend_name)
        assert backend is None,\
            'Still found a backend in the model with name {0}'.format(alba_backend_name)

        # Validate services removed from model
        for service in GeneralService.get_services_by_name(ServiceType.SERVICE_TYPES.ALBA_MGR):
            assert service.name != '{0}-abm'.format(alba_backend_name),\
                'An AlbaManager service has been found with name {0}'.format(alba_backend_name)
        for service in GeneralService.get_services_by_name(ServiceType.SERVICE_TYPES.NS_MGR):
            assert service.name.startswith('{0}-nsm_'.format(alba_backend_name)) is False,\
                'An NamespaceManager service has been found with name {0}'.format(alba_backend_name)

        # Validate ALBA backend configuration structure
        alba_backend_key = '/ovs/alba/backends'
        actual_configuration_keys = [key for key in Configuration.list(alba_backend_key)]
        assert alba_backend_guid not in actual_configuration_keys,\
            'Configuration still contains an entry in {0} with guid {1}'.format(alba_backend_key, alba_backend_guid)

        # Validate Arakoon configuration structure
        arakoon_keys = [key for key in Configuration.list('/ovs/arakoon') if key.startswith(alba_backend_name)]
        assert len(arakoon_keys) == 0,\
            'Configuration still contains configurations for clusters: {0}'.format(', '.join(arakoon_keys))

        # Validate services
        for storagerouter in GeneralStorageRouter.get_storage_routers():
            root_client = SSHClient(endpoint=storagerouter, username='******')
            maintenance_services = alba_backend_info['maintenance_service_names']
            abm_arakoon_service_name = 'ovs-arakoon-{0}-abm'.format(alba_backend_name)
            nsm_arakoon_service_name = 'ovs-arakoon-{0}-nsm_0'.format(alba_backend_name)
            for service_name in [abm_arakoon_service_name, nsm_arakoon_service_name] + maintenance_services:
                assert GeneralService.has_service(name=service_name, client=root_client) is False,\
                    'Service {0} still deployed on Storage Router {1}'.format(service_name, storagerouter.name)
    def add_vpool(vpool_parameters=None, storagerouters=None):
        """
        Create a vPool based on the kwargs provided or default parameters found in the autotest.cfg
        :param vpool_parameters: Parameters to be used for vPool creation
        :type vpool_parameters: dict

        :param storagerouters: Guids of the Storage Routers on which to create and extend this vPool
        :type storagerouters: list

        :return: Created or extended vPool
        :rtype: VPool
        """
        if storagerouters is None:
            storagerouters = list(GeneralStorageRouter.get_storage_routers())
        if vpool_parameters is None:
            vpool_parameters = {}
        if not isinstance(storagerouters, list) or len(storagerouters) == 0:
            raise ValueError("Storage Routers should be a list and contain at least 1 element to add a vPool on")

        vpool_name = None
        storagerouter_param_map = dict(
            (sr, GeneralVPool.get_add_vpool_params(storagerouter=sr, **vpool_parameters)) for sr in storagerouters
        )
        for index, sr in enumerate(storagerouters):
            vpool_name = storagerouter_param_map[sr]["vpool_name"]
            if GeneralStorageRouter.has_roles(storagerouter=sr, roles="DB") is False and sr.node_type == "MASTER":
                GeneralDisk.add_db_role(sr)
            if GeneralStorageRouter.has_roles(storagerouter=sr, roles=["SCRUB", "WRITE"]) is False:
                GeneralDisk.add_write_scrub_roles(sr)

            print storagerouter_param_map[sr]
            task_result = GeneralVPool.api.execute_post_action(
                component="storagerouters",
                guid=sr.guid,
                action="add_vpool",
                data={"call_parameters": storagerouter_param_map[sr]},
                wait=True,
                timeout=GeneralVPool.TIMEOUT_ADD_VPOOL,
            )
            if task_result[0] is not True:
                raise RuntimeError(
                    "vPool was not {0} successfully: {1}".format("extended" if index > 0 else "created", task_result[1])
                )

        vpool = GeneralVPool.get_vpool_by_name(vpool_name)
        if vpool is None:
            raise RuntimeError("vPool with name {0} could not be found in model".format(vpool_name))
        return vpool, storagerouter_param_map
    def ovs_3671_validate_archiving_of_existing_arakoon_data_on_create_test():
        """
        Validate arakoon archiving on extending a cluster with already existing data
        """
        first_sr = GeneralStorageRouter.get_storage_routers()[0]

        cluster_name = 'OVS_3671-single-node-cluster'
        cluster_basedir = '/var/tmp'

        root_client = SSHClient(first_sr, username='******')
        for directory in ['/'.join([cluster_basedir, 'arakoon']), '/var/log/arakoon']:
            root_client.dir_create(os.path.dirname(directory))
            root_client.dir_chmod(os.path.dirname(directory), 0755, recursive=True)
            root_client.dir_chown(os.path.dirname(directory), 'ovs', 'ovs', recursive=True)

        files_to_create = ['/'.join([cluster_basedir, 'arakoon', cluster_name, 'db', 'one.db']),
                           '/'.join([cluster_basedir, 'arakoon', cluster_name, 'tlogs', 'one.tlog'])]

        client = SSHClient(first_sr, username='******')
        for filename in files_to_create:
            client.dir_create(os.path.dirname(filename))
            client.dir_chmod(os.path.dirname(filename), 0755, recursive=True)
            client.dir_chown(os.path.dirname(filename), 'ovs', 'ovs', recursive=True)

        client.file_create(files_to_create)
        for filename in files_to_create:
            assert client.file_exists(filename) is True, 'File {0} not present'.format(filename)

        TestArakoon.logger.info('===================================================')
        TestArakoon.logger.info('setup and validate single node cluster')
        create_info = ArakoonInstaller.create_cluster(cluster_name, ServiceType.ARAKOON_CLUSTER_TYPES.FWK, first_sr.ip,
                                                      cluster_basedir, filesystem=False)
        TestArakoon.logger.info('create_info: \n{0}'.format(create_info))
        ArakoonInstaller.start_cluster(cluster_name, first_sr.ip, False)
        ArakoonInstaller.claim_cluster(cluster_name, first_sr, False, metadata=create_info['metadata'])
        TestArakoon.validate_arakoon_config_files([first_sr], cluster_name)
        TestArakoon.verify_arakoon_structure(root_client, cluster_name, True, True)
        for filename in files_to_create:
            assert client.file_exists(filename) is False, 'File {0} is missing'.format(filename)

        TestArakoon.logger.info('===================================================')
        TestArakoon.logger.info('remove cluster')
        ArakoonInstaller.delete_cluster(cluster_name, first_sr.ip, False)
        for filename in files_to_create:
            assert client.file_exists(filename) is False, 'File {0} is missing'.format(filename)
        TestArakoon.verify_arakoon_structure(root_client, cluster_name, False, False)
Exemplo n.º 9
0
def setup():
    """
    Setup for Arakoon package, will be executed when any test in this package is being executed
    Make necessary changes before being able to run the tests
    :return: None
    """
    for storagerouter in GeneralStorageRouter.get_masters():
        root_client = SSHClient(storagerouter, username='******')
        if GeneralService.get_service_status(name='ovs-scheduled-tasks',
                                             client=root_client) is True:
            GeneralService.stop_service(name='ovs-scheduled-tasks',
                                        client=root_client)

    for sr in GeneralStorageRouter.get_storage_routers():
        root_client = SSHClient(sr, username='******')
        for location in TEST_CLEANUP:
            root_client.run(['rm', '-rf', location])
    def ovs_4509_validate_arakoon_collapse_test():
        """
        Validate arakoon collapse
        """
        node_ips = [sr.ip for sr in GeneralStorageRouter.get_storage_routers()]
        node_ips.sort()
        for node_ip in node_ips:
            root_client = SSHClient(node_ip, username='******')
            arakoon_clusters = []
            for service in ServiceList.get_services():
                if service.is_internal is True and service.storagerouter.ip == node_ip and \
                    service.type.name in (ServiceType.SERVICE_TYPES.ARAKOON,
                                          ServiceType.SERVICE_TYPES.NS_MGR,
                                          ServiceType.SERVICE_TYPES.ALBA_MGR):
                    arakoon_clusters.append(service.name.replace('arakoon-', ''))

            for arakoon_cluster in arakoon_clusters:
                arakoon_config_path = Configuration.get_configuration_path('/ovs/arakoon/{0}/config'.format(arakoon_cluster))
                tlog_location = '/opt/OpenvStorage/db/arakoon/{0}/tlogs'.format(arakoon_cluster)

                # read_tlog_dir
                with remote(node_ip, [Configuration]) as rem:
                    config_contents = rem.Configuration.get('/ovs/arakoon/{0}/config'.format(arakoon_cluster), raw=True)
                for line in config_contents.splitlines():
                    if 'tlog_dir' in line:
                        tlog_location = line.split()[-1]

                nr_of_tlogs = TestArakoon.get_nr_of_tlogs_in_folder(root_client, tlog_location)
                old_headdb_timestamp = 0
                if root_client.file_exists('/'.join([tlog_location, 'head.db'])):
                    old_headdb_timestamp = root_client.run(['stat', '--format=%Y', tlog_location + '/head.db'])
                if nr_of_tlogs <= 2:
                    benchmark_command = ['arakoon', '--benchmark', '-n_clients', '1', '-max_n', '5_000', '-config', arakoon_config_path]
                    root_client.run(benchmark_command)

                GenericController.collapse_arakoon()

                nr_of_tlogs = TestArakoon.get_nr_of_tlogs_in_folder(root_client, tlog_location)
                new_headdb_timestamp = root_client.run(['stat', '--format=%Y', tlog_location + '/head.db'])
                assert nr_of_tlogs <= 2,\
                    'Arakoon collapse left {0} tlogs on the environment, expecting less than 2'.format(nr_of_tlogs)
                assert old_headdb_timestamp != new_headdb_timestamp,\
                    'Timestamp of the head_db file was not changed in the process of collapsing tlogs'
    def ovs_3671_validate_archiving_of_existing_arakoon_data_on_create_and_extend_test():
        """
        Validate arakoon archiving when creating and extending an arakoon cluster
        """
        storagerouters = GeneralStorageRouter.get_storage_routers()
        storagerouters.sort(key=lambda k: k.ip)
        if len(storagerouters) < 2:
            TestArakoon.logger.info('Environment has only {0} node(s)'.format(len(storagerouters)))
            return

        cluster_name = 'OVS_3671-multi-node-cluster'
        cluster_basedir = '/var/tmp'

        archived_files = []
        files_to_create = []
        for index, sr in enumerate(storagerouters):
            root_client = SSHClient(sr, username='******')
            for directory in ['/'.join([cluster_basedir, 'arakoon']), '/var/log/arakoon']:
                root_client.dir_create(os.path.dirname(directory))
                root_client.dir_chmod(os.path.dirname(directory), 0755, recursive=True)
                root_client.dir_chown(os.path.dirname(directory), 'ovs', 'ovs', recursive=True)

            files_to_create = ['/'.join([cluster_basedir, 'arakoon', cluster_name, 'db', 'one.db']),
                               '/'.join([cluster_basedir, 'arakoon', cluster_name, 'tlogs', 'one.tlog'])]

            client = SSHClient(sr, username='******')
            for filename in files_to_create:
                client.dir_create(os.path.dirname(filename))
                client.dir_chmod(os.path.dirname(filename), 0755, recursive=True)
                client.dir_chown(os.path.dirname(filename), 'ovs', 'ovs', recursive=True)

            client.file_create(files_to_create)
            for filename in files_to_create:
                assert client.file_exists(filename) is True, 'File {0} not present'.format(filename)

            archived_files = ['/'.join(['/var/log/arakoon', cluster_name, 'archive', 'one.log'])]

            TestArakoon.logger.info('===================================================')
            TestArakoon.logger.info('setup and validate single node cluster')
            if index == 0:
                create_info = ArakoonInstaller.create_cluster(cluster_name, ServiceType.ARAKOON_CLUSTER_TYPES.FWK,
                                                              sr.ip, cluster_basedir, filesystem=False)
                TestArakoon.logger.info('create_info: \n{0}'.format(create_info))
                ArakoonInstaller.start_cluster(cluster_name, sr.ip, False)
                ArakoonInstaller.claim_cluster(cluster_name, sr, False, metadata=create_info['metadata'])
            else:
                ArakoonInstaller.extend_cluster(storagerouters[0].ip, sr.ip, cluster_name, cluster_basedir)
            TestArakoon.validate_arakoon_config_files(storagerouters[:index + 1], cluster_name)
            TestArakoon.verify_arakoon_structure(root_client, cluster_name, True, True)
            TestArakoon.check_archived_directory(client, archived_files)
            for filename in files_to_create:
                assert client.file_exists(filename) is False, 'File {0} is missing'.format(filename)

        TestArakoon.logger.info('===================================================')
        TestArakoon.logger.info('remove cluster')
        ArakoonInstaller.delete_cluster(cluster_name, storagerouters[0].ip, False)

        for sr in storagerouters:
            client = SSHClient(sr, username='******')
            TestArakoon.check_archived_directory(client, archived_files)
            for filename in files_to_create:
                assert client.file_exists(filename) is False, 'File {0} is missing'.format(filename)
            TestArakoon.verify_arakoon_structure(client, cluster_name, False, False)
 def ovs_3554_4_node_cluster_config_validation_test():
     """
     Arakoon config validation of a 4 node cluster
     """
     TestArakoon.validate_arakoon_config_files(GeneralStorageRouter.get_storage_routers())
 def ar_0002_arakoon_cluster_validation_test():
     """
     Arakoon cluster validation
     """
     TestArakoon.validate_arakoon_config_files(GeneralStorageRouter.get_storage_routers())
    def ar_0001_validate_create_extend_shrink_delete_cluster_test():
        """
        Validate extending and shrinking of arakoon clusters
        """
        storagerouters = GeneralStorageRouter.get_storage_routers()
        if not len(storagerouters) >= 3:
            TestArakoon.logger.info('Environment has only {0} node(s)'.format(len(storagerouters)))
            return

        cluster_name = 'ar_0001'
        cluster_basedir = '/var/tmp/'
        first_sr = storagerouters[0]
        second_sr = storagerouters[1]
        third_sr = storagerouters[2]
        first_root_client = SSHClient(first_sr, username='******')
        second_root_client = SSHClient(second_sr, username='******')
        third_root_client = SSHClient(third_sr, username='******')

        TestArakoon.logger.info('===================================================')
        TestArakoon.logger.info('setup and validate single node cluster')
        create_info = ArakoonInstaller.create_cluster(cluster_name, ServiceType.ARAKOON_CLUSTER_TYPES.FWK, first_sr.ip,
                                                      cluster_basedir, filesystem=False)
        TestArakoon.logger.info('create_info: \n{0}'.format(create_info))
        ArakoonInstaller.start_cluster(cluster_name, first_sr.ip, False)
        ArakoonInstaller.claim_cluster(cluster_name, first_sr, False, metadata=create_info['metadata'])
        TestArakoon.validate_arakoon_config_files([first_sr], cluster_name)
        TestArakoon.verify_arakoon_structure(first_root_client, cluster_name, True, True)

        TestArakoon.logger.info('===================================================')
        TestArakoon.logger.info('setup and validate two node cluster')
        ArakoonInstaller.extend_cluster(first_sr.ip, second_sr.ip, cluster_name, cluster_basedir)
        TestArakoon.validate_arakoon_config_files([first_sr, second_sr], cluster_name)
        TestArakoon.verify_arakoon_structure(first_root_client, cluster_name, True, True)
        TestArakoon.verify_arakoon_structure(second_root_client, cluster_name, True, True)

        TestArakoon.logger.info('===================================================')
        TestArakoon.logger.info('setup and validate three node cluster')
        ArakoonInstaller.extend_cluster(first_sr.ip, third_sr.ip, cluster_name, cluster_basedir)
        TestArakoon.validate_arakoon_config_files([first_sr, second_sr, third_sr], cluster_name)

        for client in [first_root_client, second_root_client, third_root_client]:
            TestArakoon.verify_arakoon_structure(client, cluster_name, True, True)

        TestArakoon.logger.info('===================================================')
        TestArakoon.logger.info('reduce and validate three node to two node cluster')
        ArakoonInstaller.shrink_cluster(second_sr.ip, first_sr.ip, cluster_name)
        TestArakoon.validate_arakoon_config_files([first_sr, third_sr], cluster_name)
        TestArakoon.verify_arakoon_structure(first_root_client, cluster_name, True, True)
        TestArakoon.verify_arakoon_structure(second_root_client, cluster_name, True, False)
        TestArakoon.verify_arakoon_structure(third_root_client, cluster_name, True, True)

        TestArakoon.logger.info('===================================================')
        TestArakoon.logger.info('reduce and validate two node to one node cluster')
        ArakoonInstaller.shrink_cluster(first_sr.ip, third_sr.ip, cluster_name)
        TestArakoon.validate_arakoon_config_files([third_sr], cluster_name)

        TestArakoon.verify_arakoon_structure(first_root_client, cluster_name, True, False)
        TestArakoon.verify_arakoon_structure(second_root_client, cluster_name, True, False)
        TestArakoon.verify_arakoon_structure(third_root_client, cluster_name, True, True)

        TestArakoon.logger.info('===================================================')
        TestArakoon.logger.info('remove cluster')
        ArakoonInstaller.delete_cluster(cluster_name, third_sr.ip, False)

        for client in [first_root_client, second_root_client, third_root_client]:
            TestArakoon.verify_arakoon_structure(client, cluster_name, False, False)

        GeneralArakoon.delete_config(cluster_name)
    def test_basic_logrotate():
        """
        Verify current openvstorage logrotate configuration
        Apply the openvstorage logrotate on custom logfile and see if it rotates as predicted
        Update ownership of custom file and verify logrotate raises issue
        """
        storagerouters = GeneralStorageRouter.get_storage_routers()
        logrotate_content = """{0} {{
    rotate 5
    size 20M
    compress
    copytruncate
    notifempty
}}

{1} {{
    su ovs ovs
    rotate 10
    size 19M
    compress
    delaycompress
    notifempty
    create 666 ovs ovs
    postrotate
        /usr/bin/pkill -SIGUSR1 arakoon
    endscript
}}"""
        if len(storagerouters) == 0:
            raise ValueError('No Storage Routers found in the model')

        logrotate_include_dir = '/etc/logrotate.d'
        logrotate_cfg_file = '/etc/logrotate.conf'
        logrotate_cron_file = '/etc/cron.daily/logrotate'
        logrotate_ovs_file = '{0}/openvstorage-logs'.format(logrotate_include_dir)
        expected_logrotate_content = logrotate_content.format('/var/log/ovs/*.log', '/var/log/arakoon/*/*.log')

        # Verify basic logrotate configurations
        for storagerouter in storagerouters:
            root_client = SSHClient(endpoint=storagerouter, username='******')
            assert_true(expr=root_client.file_exists(filename=logrotate_cfg_file),
                        msg='Logrotate config {0} does not exist on Storage Router {1}'.format(logrotate_cfg_file, storagerouter.name))
            assert_true(expr=root_client.file_exists(filename=logrotate_ovs_file),
                        msg='Logrotate file {0} does not exist on Storage Router {1}'.format(logrotate_ovs_file, storagerouter.name))
            assert_true(expr=root_client.file_exists(filename=logrotate_cron_file),
                        msg='Logrotate file {0} does not exist on Storage Router {1}'.format(logrotate_cron_file, storagerouter.name))
            assert_true(expr='include {0}'.format(logrotate_include_dir) in root_client.file_read(filename=logrotate_cfg_file).splitlines(),
                        msg='Logrotate on Storage Router {0} does not include {1}'.format(storagerouter.name, logrotate_include_dir))
            assert_true(expr='/usr/sbin/logrotate /etc/logrotate.conf' in root_client.file_read(filename=logrotate_cron_file).splitlines(),
                        msg='Logrotate will not be executed on Storage Router {0}'.format(storagerouter.name))
            actual_file_contents = root_client.file_read(filename=logrotate_ovs_file).rstrip('\n')
            assert_equal(first=expected_logrotate_content,
                         second=actual_file_contents,
                         msg='Logrotate contents does not match expected contents on Storage Router {0}'.format(storagerouter.name))

        # Create custom logrotate file for testing purposes
        custom_logrotate_cfg_file = '/opt/OpenvStorage/ci/logrotate-conf'
        custom_logrotate_dir = '/opt/OpenvStorage/ci/logrotate'
        custom_logrotate_file1 = '{0}/logrotate_test_file1.log'.format(custom_logrotate_dir)
        custom_logrotate_file2 = '{0}/logrotate_test_file2.log'.format(custom_logrotate_dir)
        custom_logrotate_content = logrotate_content.format(custom_logrotate_file1, custom_logrotate_file2)
        local_sr = GeneralStorageRouter.get_local_storagerouter()
        root_client = SSHClient(endpoint=local_sr, username='******')
        root_client.file_write(filename=custom_logrotate_cfg_file, contents=custom_logrotate_content)

        # No logfile present --> logrotate should fail
        assert_raises(excClass=CalledProcessError,
                      callableObj=root_client.run,
                      command='logrotate {0}'.format(custom_logrotate_cfg_file))

        ##########################################
        # Test 1st logrotate configuration entry #
        ##########################################
        root_client.dir_create(directories=custom_logrotate_dir)
        root_client.dir_chown(directories=custom_logrotate_dir,
                              user='******',
                              group='ovs',
                              recursive=True)
        root_client.run(command='touch {0}'.format(custom_logrotate_file1))
        root_client.run(command='touch {0}'.format(custom_logrotate_file2))
        root_client.file_chmod(filename=custom_logrotate_file1, mode=666)
        root_client.file_chmod(filename=custom_logrotate_file2, mode=666)

        # Write data to the file less than size for rotation and verify rotation
        GeneralVDisk.write_to_volume(location=custom_logrotate_file1,
                                     count=15,
                                     bs='1M',
                                     input_type='zero',
                                     root_client=root_client)
        root_client.run('logrotate {0}'.format(custom_logrotate_cfg_file))
        assert_equal(first=len(root_client.file_list(directory=custom_logrotate_dir)),
                     second=2,
                     msg='More files than expected present in {0}'.format(custom_logrotate_dir))

        # Write data to file larger than size in configuration and verify amount of rotations
        files_to_delete = []
        for counter in range(7):
            expected_file = '{0}.{1}.gz'.format(custom_logrotate_file1, counter + 1 if counter < 5 else 5)
            GeneralVDisk.write_to_volume(location=custom_logrotate_file1,
                                         count=30,
                                         bs='1M',
                                         input_type='zero',
                                         root_client=root_client)
            root_client.run('logrotate {0}'.format(custom_logrotate_cfg_file))
            assert_equal(first=len(root_client.file_list(directory=custom_logrotate_dir)),
                         second=counter + 3 if counter < 5 else 7,
                         msg='Not the expected amount of files present in {0}'.format(custom_logrotate_dir))
            assert_true(expr=root_client.file_exists(filename=expected_file),
                        msg='Logrotate did not create the expected file {0}'.format(expected_file))
            user_info = General.get_owner_group_for_path(path=expected_file,
                                                         root_client=root_client)
            assert_equal(first='root',
                         second=user_info['user']['name'],
                         msg='Expected file to be owned by user "root", but instead its owned by "{0}"'.format(user_info['user']['name']))
            assert_equal(first='root',
                         second=user_info['group']['name'],
                         msg='Expected file to be owned by group "root", but instead its owned by "{0}"'.format(user_info['group']['name']))
            files_to_delete.append(expected_file)
        root_client.file_delete(filenames=files_to_delete)

        ##########################################
        # Test 2nd logrotate configuration entry #
        ##########################################
        root_client.file_chown(filenames=custom_logrotate_file2,
                               user='******',
                               group='ovs')

        # Write data to the file less than size for rotation and verify rotation
        GeneralVDisk.write_to_volume(location=custom_logrotate_file2,
                                     count=15,
                                     bs='1M',
                                     input_type='zero',
                                     root_client=root_client)
        root_client.run('logrotate {0}'.format(custom_logrotate_cfg_file))
        assert_equal(first=len(root_client.file_list(directory=custom_logrotate_dir)),
                     second=2,
                     msg='More files than expected present in {0}'.format(custom_logrotate_dir))

        # Write data to file larger than size in configuration and verify amount of rotations
        for counter in range(12):
            if counter == 0:  # Delaycompress --> file is not compressed during initial cycle
                expected_file = '{0}.1'.format(custom_logrotate_file2)
            else:
                expected_file = '{0}.{1}.gz'.format(custom_logrotate_file2, counter + 1 if counter < 10 else 10)
            GeneralVDisk.write_to_volume(location=custom_logrotate_file2,
                                         count=30,
                                         bs='1M',
                                         input_type='zero',
                                         root_client=root_client)
            root_client.run('logrotate {0}'.format(custom_logrotate_cfg_file))
            assert_equal(first=len(root_client.file_list(directory=custom_logrotate_dir)),
                         second=counter + 3 if counter < 10 else 12,
                         msg='Not the expected amount of files present in {0}'.format(custom_logrotate_dir))
            assert_true(expr=root_client.file_exists(filename=expected_file),
                        msg='Logrotate did not create the expected file {0}'.format(expected_file))
            user_info = General.get_owner_group_for_path(path=expected_file,
                                                         root_client=root_client)
            assert_equal(first='ovs',
                         second=user_info['user']['name'],
                         msg='Expected file to be owned by user "root", but instead its owned by "{0}"'.format(user_info['user']['name']))
            assert_equal(first='ovs',
                         second=user_info['group']['name'],
                         msg='Expected file to be owned by group "root", but instead its owned by "{0}"'.format(user_info['group']['name']))

        root_client.dir_delete(directories=custom_logrotate_dir)
        root_client.file_delete(filenames=custom_logrotate_cfg_file)
Exemplo n.º 16
0
    def validate_alba_backend_sanity_without_claimed_disks(alba_backend):
        """
        Validate whether the ALBA backend is configured correctly
        :param alba_backend: ALBA backend
        :return: None
        """
        # Attribute validation
        assert alba_backend.available is True,\
            'ALBA backend {0} is not available'.format(alba_backend.backend.name)
        assert len(alba_backend.presets) >= 1,\
            'No preset found for ALBA backend {0}'.format(alba_backend.backend.name)
        assert len([default for default in alba_backend.presets if default['is_default'] is True]) == 1,\
            'Could not find default preset for backend {0}'.format(alba_backend.backend.name)
        assert alba_backend.backend.backend_type.code == 'alba',\
            'Backend type for ALBA backend is {0}'.format(alba_backend.backend.backend_type.code)
        assert alba_backend.backend.status == 'RUNNING',\
            'Status for ALBA backend is {0}'.format(alba_backend.backend.status)

        # Validate ABM and NSM services
        storagerouters = GeneralStorageRouter.get_storage_routers()
        storagerouters_with_db_role = [sr for sr in storagerouters if GeneralStorageRouter.has_roles(storagerouter=sr, roles='DB') is True and sr.node_type == 'MASTER']

        assert len(alba_backend.abm_services) == len(storagerouters_with_db_role),\
            'Not enough ABM services found'
        assert len(alba_backend.nsm_services) == len(storagerouters_with_db_role),\
            'Not enough NSM services found'

        # Validate ALBA backend configuration structure
        alba_backend_key = '/ovs/alba/backends'
        assert Configuration.dir_exists(key=alba_backend_key) is True,\
            'Configuration does not contain key {0}'.format(alba_backend_key)

        actual_config_keys = [key for key in Configuration.list(alba_backend_key)]
        expected_config_keys = ['global_gui_error_interval', alba_backend.guid, 'default_nsm_hosts']
        optional_config_keys = ['verification_factor']

        expected_keys_amount = 0
        for optional_key in optional_config_keys:
            if optional_key in actual_config_keys:
                expected_keys_amount += 1

        for expected_key in expected_config_keys:
            if not re.match(Toolbox.regex_guid, expected_key):
                expected_keys_amount += 1
            assert expected_key in actual_config_keys,\
                'Key {0} was not found in tree {1}'.format(expected_key, alba_backend_key)

        for actual_key in list(actual_config_keys):
            if re.match(Toolbox.regex_guid, actual_key):
                actual_config_keys.remove(actual_key)  # Remove all alba backend keys
        assert len(actual_config_keys) == expected_keys_amount,\
            'Another key was added to the {0} tree'.format(alba_backend_key)

        this_alba_backend_key = '{0}/{1}'.format(alba_backend_key, alba_backend.guid)
        actual_keys = [key for key in Configuration.list(this_alba_backend_key)]
        expected_keys = ['maintenance']
        assert actual_keys == expected_keys,\
            'Actual keys: {0} - Expected keys: {1}'.format(actual_keys, expected_keys)

        maintenance_key = '{0}/maintenance'.format(this_alba_backend_key)
        actual_keys = [key for key in Configuration.list(maintenance_key)]
        expected_keys = ['nr_of_agents', 'config']
        assert set(actual_keys) == set(expected_keys),\
            'Actual keys: {0} - Expected keys: {1}'.format(actual_keys, expected_keys)
        # @TODO: Add validation for config values

        # Validate ASD node configuration structure
        alba_nodes = GeneralAlba.get_alba_nodes()
        assert len(alba_nodes) > 0,\
            'Could not find any ALBA nodes in the model'
        alba_node_key = '/ovs/alba/asdnodes'
        actual_keys = [key for key in Configuration.list(alba_node_key)]
        assert len(alba_nodes) == len(actual_keys),\
            'Amount of ALBA nodes in model: {0} >< amount of ALBA nodes in configuration: {1}.'.format(len(alba_nodes),
                                                                                                       len(actual_keys))
        for alba_node in alba_nodes:
            assert alba_node.node_id in actual_keys,\
                'ALBA node with ID {0} not present in configuration'.format(alba_node.node_id)

            actual_asdnode_keys = [key for key in Configuration.list('{0}/{1}'.format(alba_node_key, alba_node.node_id))]
            expected_asdnode_keys = ['config', 'services']
            assert actual_asdnode_keys == expected_asdnode_keys,\
                'Actual keys: {0} - Expected keys: {1}'.format(actual_asdnode_keys, expected_asdnode_keys)

            actual_config_keys = [key for key in Configuration.list('{0}/{1}/config'.format(alba_node_key, alba_node.node_id))]
            expected_config_keys = ['main', 'network']
            assert set(actual_config_keys) == set(expected_config_keys),\
                'Actual keys: {0} - Expected keys: {1}'.format(actual_config_keys, expected_config_keys)
            # @TODO: Add validation for main and network values

        # Validate Arakoon configuration structure
        arakoon_abm_key = '/ovs/arakoon/{0}/config'.format(alba_backend.abm_services[0].service.name).replace('arakoon-', '')
        arakoon_nsm_key = '/ovs/arakoon/{0}/config'.format(alba_backend.nsm_services[0].service.name).replace('arakoon-', '')
        assert Configuration.exists(key=arakoon_abm_key, raw=True) is True,\
            'Configuration key {0} does not exist'.format(arakoon_abm_key)
        assert Configuration.exists(key=arakoon_nsm_key, raw=True) is True,\
            'Configuration key {0} does not exist'.format(arakoon_nsm_key)
        # @TODO: Add validation for config values

        # Validate maintenance agents
        actual_amount_agents = len([service for node_services in [alba_node.client.list_maintenance_services() for alba_node in alba_nodes] for service in node_services])
        expected_amount_agents = 1
        assert actual_amount_agents == expected_amount_agents,\
            'Amount of maintenance agents is incorrect. Found {0} - Expected {1}'.format(actual_amount_agents,
                                                                                         expected_amount_agents)

        # Validate arakoon services
        machine_ids = [sr.machine_id for sr in storagerouters_with_db_role]
        abm_service_name = alba_backend.abm_services[0].service.name
        nsm_service_name = alba_backend.nsm_services[0].service.name
        for storagerouter in storagerouters_with_db_role:
            root_client = SSHClient(endpoint=storagerouter, username='******')
            for service_name in [abm_service_name, nsm_service_name]:
                assert GeneralService.has_service(name=service_name, client=root_client) is True,\
                    'Service {0} not deployed on Storage Router {1}'.format(service_name, storagerouter.name)
                exitcode, output = GeneralService.get_service_status(name=service_name, client=root_client)
                assert exitcode is True,\
                    'Service {0} not running on Storage Router {1} - {2}'.format(service_name, storagerouter.name,
                                                                                 output)
                out, err, _ = General.execute_command('arakoon --who-master -config {0}'.format(Configuration.get_configuration_path('/ovs/arakoon/{0}/config'.format(abm_service_name.replace('arakoon-', '')))))
                assert out.strip() in machine_ids,\
                    'Arakoon master is {0}, but should be 1 of "{1}"'.format(out.strip(), ', '.join(machine_ids))
Exemplo n.º 17
0
    def check_vpool_cleanup(vpool_info, storagerouters=None):
        """
        Check if everything related to a vPool has been cleaned up on the storagerouters provided
        vpool_info should be a dictionary containing:
            - type
            - guid
            - files
            - directories
            - name (optional)
            - vpool (optional)
            If vpool is provided:
                - storagerouters need to be provided, because on these Storage Routers, we check whether the vPool has been cleaned up
            If name is provided:
                - If storagerouters is NOT provided, all Storage Routers will be checked for a correct vPool removal
                - If storagerouters is provided, only these Storage Routers will be checked for a correct vPool removal

        :param vpool_info: Information about the vPool
        :param storagerouters: Storage Routers to check if vPool has been cleaned up
        :return: None
        """
        for required_param in ["type", "guid", "files", "directories"]:
            if required_param not in vpool_info:
                raise ValueError("Incorrect vpool_info provided")
        if "vpool" in vpool_info and "name" in vpool_info:
            raise ValueError("vpool and name are mutually exclusive")
        if "vpool" not in vpool_info and "name" not in vpool_info:
            raise ValueError("Either vpool or vpool_name needs to be provided")

        vpool = vpool_info.get("vpool")
        vpool_name = vpool_info.get("name")
        vpool_guid = vpool_info["guid"]
        vpool_type = vpool_info["type"]
        files = vpool_info["files"]
        directories = vpool_info["directories"]

        supported_backend_types = GeneralBackend.get_valid_backendtypes()
        if vpool_type not in supported_backend_types:
            raise ValueError(
                "Unsupported Backend Type provided. Please choose from: {0}".format(", ".join(supported_backend_types))
            )
        if storagerouters is None:
            storagerouters = GeneralStorageRouter.get_storage_routers()

        if vpool_name is not None:
            assert (
                GeneralVPool.get_vpool_by_name(vpool_name=vpool_name) is None
            ), "A vPool with name {0} still exists".format(vpool_name)

        # Prepare some fields to check
        vpool_name = vpool.name if vpool else vpool_name
        vpool_services = ["ovs-dtl_{0}".format(vpool_name), "ovs-volumedriver_{0}".format(vpool_name)]
        if vpool_type == "alba":
            vpool_services.append("ovs-albaproxy_{0}".format(vpool_name))

        # Check configuration
        if vpool is None:
            assert (
                Configuration.exists("/ovs/vpools/{0}".format(vpool_guid), raw=True) is False
            ), "vPool config still found in etcd"
        else:
            remaining_sd_ids = set([storagedriver.storagedriver_id for storagedriver in vpool.storagedrivers])
            current_sd_ids = set([item for item in Configuration.list("/ovs/vpools/{0}/hosts".format(vpool_guid))])
            assert not remaining_sd_ids.difference(
                current_sd_ids
            ), "There are more storagedrivers modelled than present in etcd"
            assert not current_sd_ids.difference(
                remaining_sd_ids
            ), "There are more storagedrivers in etcd than present in model"

        # Perform checks on all storagerouters where vpool was removed
        for storagerouter in storagerouters:

            # Check MDS services
            mds_services = GeneralService.get_services_by_name(ServiceType.SERVICE_TYPES.MD_SERVER)
            assert (
                len(
                    [
                        mds_service
                        for mds_service in mds_services
                        if mds_service.storagerouter_guid == storagerouter.guid
                    ]
                )
                == 0
            ), "There are still MDS services present for Storage Router {0}".format(storagerouter.ip)

            # Check services
            root_client = SSHClient(storagerouter, username="******")
            for service in vpool_services:
                if ServiceManager.has_service(service, client=root_client):
                    raise RuntimeError(
                        "Service {0} is still configured on Storage Router {1}".format(service, storagerouter.ip)
                    )

            # Check KVM vpool
            if GeneralHypervisor.get_hypervisor_type() == "KVM":
                vpool_overview = root_client.run(["virsh", "pool-list", "--all"]).splitlines()
                vpool_overview.pop(1)
                vpool_overview.pop(0)
                for vpool_info in vpool_overview:
                    kvm_vpool_name = vpool_info.split()[0].strip()
                    if vpool_name == kvm_vpool_name:
                        raise ValueError(
                            "vPool {0} is still defined on Storage Router {1}".format(vpool_name, storagerouter.ip)
                        )

            # Check file and directory existence
            if storagerouter.guid not in directories:
                raise ValueError("Could not find directory information for Storage Router {0}".format(storagerouter.ip))
            if storagerouter.guid not in files:
                raise ValueError("Could not find file information for Storage Router {0}".format(storagerouter.ip))

            for directory in directories[storagerouter.guid]:
                assert (
                    root_client.dir_exists(directory) is False
                ), "Directory {0} still exists on Storage Router {1}".format(directory, storagerouter.ip)
            for file_name in files[storagerouter.guid]:
                assert (
                    root_client.file_exists(file_name) is False
                ), "File {0} still exists on Storage Router {1}".format(file_name, storagerouter.ip)

            # Look for errors in storagedriver log
            for error_type in ["error", "fatal"]:
                cmd = "cat -vet /var/log/ovs/volumedriver/{0}.log | tail -1000 | grep ' {1} '; echo true > /dev/null".format(
                    vpool_name, error_type
                )
                errors = []
                for line in root_client.run(cmd, allow_insecure=True).splitlines():
                    if "HierarchicalArakoon" in line:
                        continue
                    errors.append(line)
                if len(errors) > 0:
                    if error_type == "error":
                        print "Volumedriver log file contains errors on Storage Router {0}\n - {1}".format(
                            storagerouter.ip, "\n - ".join(errors)
                        )
                    else:
                        raise RuntimeError(
                            "Fatal errors found in volumedriver log file on Storage Router {0}\n - {1}".format(
                                storagerouter.ip, "\n - ".join(errors)
                            )
                        )
    def check_license_headers_test():
        """
        Check license headers
        """
        license_header = re.compile('Copyright \(C\) 201[4-9] iNuron NV')
        license_to_check = ["",
                            " This file is part of Open vStorage Open Source Edition (OSE),",
                            " as available from",
                            "",
                            "     http://www.openvstorage.org and",
                            "     http://www.openvstorage.com.",
                            "",
                            " This file is free software; you can redistribute it and/or modify it",
                            " under the terms of the GNU Affero General Public License v3 (GNU AGPLv3)",
                            " as published by the Free Software Foundation, in version 3 as it comes",
                            " in the LICENSE.txt file of the Open vStorage OSE distribution.",
                            "",
                            " Open vStorage is distributed in the hope that it will be useful,",
                            " but WITHOUT ANY WARRANTY of any kind."]

        exclude_dirs = ['/opt/OpenvStorage/config/templates/cinder-unit-tests/',
                        '/opt/OpenvStorage/config/templates/cinder-volume-driver/',
                        '/opt/OpenvStorage/webapps/frontend/css/',
                        '/opt/OpenvStorage/webapps/frontend/lib/',
                        '/opt/OpenvStorage/ovs/extensions/db/arakoon/arakoon/arakoon/',
                        '/opt/OpenvStorage/ovs/extensions/db/arakoon/pyrakoon/pyrakoon/',
                        '/opt/asd-manager/source/tools/pyrakoon/pyrakoon/']
        include_dirs = ['/opt/OpenvStorage/webapps/frontend/lib/ovs/']
        exclude_files = ['/opt/OpenvStorage/ovs/extensions/generic/fakesleep.py']
        include_files = ['/opt/OpenvStorage/webapps/frontend/css/ovs.css']
        extension_comments_map = {'.py': ['#'],
                                  '.sh': ['#'],
                                  '.js': ['//'],
                                  '.html': ['<!--', '-->'],
                                  '.css': ['/*', '*', '*/']}

        storagerouters = GeneralStorageRouter.get_storage_routers()
        files_with_diff_licenses = {}
        for storagerouter in storagerouters:
            root_client = SSHClient(storagerouter, username='******')
            files_with_diff_licenses[storagerouter.guid] = []
            for root_folder in ['/opt/OpenvStorage', '/opt/asd-manager']:
                if not root_client.dir_exists(root_folder):
                    raise ValueError('Root folder {0} does not exist'.format(root_folder))

                unfiltered_files = root_client.file_list(directory=root_folder,
                                                         abs_path=True,
                                                         recursive=True)
                filtered_files = General.filter_files(files=unfiltered_files,
                                                      extensions=extension_comments_map.keys(),
                                                      exclude_dirs=exclude_dirs,
                                                      include_dirs=include_dirs,
                                                      exclude_files=exclude_files,
                                                      include_files=include_files)
                for file_name in filtered_files:
                    # Read file
                    with open(file_name, 'r') as utf_file:
                        data = utf_file.read().decode("utf-8-sig").encode("utf-8")
                        lines_to_check = data.splitlines()

                    # Check relevant comment type for current file
                    comments = []
                    for extension, cmts in extension_comments_map.iteritems():
                        if file_name.endswith(extension):
                            comments = cmts
                            break
                    if len(comments) == 0:
                        raise ValueError('Something must have gone wrong filtering the files, because file {0} does not have a correct extension'.format(file_name))

                    # Search license header
                    index = 0
                    lic_header_found = False
                    for index, line in enumerate(lines_to_check):
                        for comment in comments:
                            line = line.replace(comment, '', 1)
                        if re.match(license_header, line.strip()):
                            lic_header_found = True
                            break

                    # License header not found, continuing
                    if lic_header_found is False:
                        files_with_diff_licenses[storagerouter.guid].append(file_name)
                        continue

                    # License header found, checking rest of license
                    index += 1
                    for license_line in license_to_check:
                        line_to_check = lines_to_check[index]
                        for comment in comments:
                            line_to_check = line_to_check.replace(comment, '', 1)
                        if license_line.strip() == line_to_check.strip():
                            index += 1
                        else:
                            files_with_diff_licenses[storagerouter.guid].append(file_name)
                            break

        for storagerouter in storagerouters:
            assert len(files_with_diff_licenses[storagerouter.guid]) == 0, 'Following files were found with different licenses:\n - {0}'.format('\n - '.join(files_with_diff_licenses[storagerouter.guid]))
Exemplo n.º 19
0
    def check_vpool_cleanup(vpool_info, storagerouters=None):
        """
        Check if everything related to a vPool has been cleaned up on the storagerouters provided
        vpool_info should be a dictionary containing:
            - type
            - guid
            - files
            - directories
            - name (optional)
            - vpool (optional)
            If vpool is provided:
                - storagerouters need to be provided, because on these Storage Routers, we check whether the vPool has been cleaned up
            If name is provided:
                - If storagerouters is NOT provided, all Storage Routers will be checked for a correct vPool removal
                - If storagerouters is provided, only these Storage Routers will be checked for a correct vPool removal

        :param vpool_info: Information about the vPool
        :param storagerouters: Storage Routers to check if vPool has been cleaned up
        :return: None
        """
        for required_param in ['type', 'guid', 'files', 'directories']:
            if required_param not in vpool_info:
                raise ValueError('Incorrect vpool_info provided')
        if 'vpool' in vpool_info and 'name' in vpool_info:
            raise ValueError('vpool and name are mutually exclusive')
        if 'vpool' not in vpool_info and 'name' not in vpool_info:
            raise ValueError('Either vpool or vpool_name needs to be provided')

        vpool = vpool_info.get('vpool')
        vpool_name = vpool_info.get('name')
        vpool_guid = vpool_info['guid']
        vpool_type = vpool_info['type']
        files = vpool_info['files']
        directories = vpool_info['directories']

        supported_backend_types = GeneralBackend.get_valid_backendtypes()
        if vpool_type not in supported_backend_types:
            raise ValueError('Unsupported Backend Type provided. Please choose from: {0}'.format(', '.join(supported_backend_types)))
        if storagerouters is None:
            storagerouters = GeneralStorageRouter.get_storage_routers()

        if vpool_name is not None:
            assert GeneralVPool.get_vpool_by_name(vpool_name=vpool_name) is None, 'A vPool with name {0} still exists'.format(vpool_name)

        # Prepare some fields to check
        vpool_name = vpool.name if vpool else vpool_name
        vpool_services = ['ovs-dtl_{0}'.format(vpool_name),
                          'ovs-volumedriver_{0}'.format(vpool_name)]
        if vpool_type == 'alba':
            vpool_services.append('ovs-albaproxy_{0}'.format(vpool_name))

        # Check etcd
        if vpool is None:
            assert EtcdConfiguration.exists('/ovs/vpools/{0}'.format(vpool_guid), raw=True) is False, 'vPool config still found in etcd'
        else:
            remaining_sd_ids = set([storagedriver.storagedriver_id for storagedriver in vpool.storagedrivers])
            current_sd_ids = set([item for item in EtcdConfiguration.list('/ovs/vpools/{0}/hosts'.format(vpool_guid))])
            assert not remaining_sd_ids.difference(current_sd_ids), 'There are more storagedrivers modelled than present in etcd'
            assert not current_sd_ids.difference(remaining_sd_ids), 'There are more storagedrivers in etcd than present in model'

        # Perform checks on all storagerouters where vpool was removed
        for storagerouter in storagerouters:
            # Check management center
            mgmt_center = GeneralManagementCenter.get_mgmt_center(pmachine=storagerouter.pmachine)
            if mgmt_center is not None:
                assert GeneralManagementCenter.is_host_configured(pmachine=storagerouter.pmachine) is False, 'Management Center is still configured on Storage Router {0}'.format(storagerouter.ip)

            # Check MDS services
            mds_services = GeneralService.get_services_by_name(ServiceType.SERVICE_TYPES.MD_SERVER)
            assert len([mds_service for mds_service in mds_services if mds_service.storagerouter_guid == storagerouter.guid]) == 0, 'There are still MDS services present for Storage Router {0}'.format(storagerouter.ip)

            # Check services
            root_client = SSHClient(storagerouter, username='******')
            for service in vpool_services:
                if ServiceManager.has_service(service, client=root_client):
                    raise RuntimeError('Service {0} is still configured on Storage Router {1}'.format(service, storagerouter.ip))

            # Check KVM vpool
            if storagerouter.pmachine.hvtype == 'KVM':
                vpool_overview = root_client.run('virsh pool-list --all').splitlines()
                vpool_overview.pop(1)
                vpool_overview.pop(0)
                for vpool_info in vpool_overview:
                    kvm_vpool_name = vpool_info.split()[0].strip()
                    if vpool_name == kvm_vpool_name:
                        raise ValueError('vPool {0} is still defined on Storage Router {1}'.format(vpool_name, storagerouter.ip))

            # Check file and directory existence
            if storagerouter.guid not in directories:
                raise ValueError('Could not find directory information for Storage Router {0}'.format(storagerouter.ip))
            if storagerouter.guid not in files:
                raise ValueError('Could not find file information for Storage Router {0}'.format(storagerouter.ip))

            for directory in directories[storagerouter.guid]:
                assert root_client.dir_exists(directory) is False, 'Directory {0} still exists on Storage Router {1}'.format(directory, storagerouter.ip)
            for file_name in files[storagerouter.guid]:
                assert root_client.file_exists(file_name) is False, 'File {0} still exists on Storage Router {1}'.format(file_name, storagerouter.ip)

            # Look for errors in storagedriver log
            for error_type in ['error', 'fatal']:
                cmd = "cat -vet /var/log/ovs/volumedriver/{0}.log | tail -1000 | grep ' {1} '; echo true > /dev/null".format(vpool_name, error_type)
                errors = []
                for line in root_client.run(cmd).splitlines():
                    if "HierarchicalArakoon" in line:
                        continue
                    errors.append(line)
                if len(errors) > 0:
                    if error_type == 'error':
                        print 'Volumedriver log file contains errors on Storage Router {0}\n - {1}'.format(storagerouter.ip, '\n - '.join(errors))
                    else:
                        raise RuntimeError('Fatal errors found in volumedriver log file on Storage Router {0}\n - {1}'.format(storagerouter.ip, '\n - '.join(errors)))
    def check_license_headers_test():
        """
        Check license headers
        """
        license_header = re.compile('Copyright 201[4-9] iNuron NV')
        license_to_check = ['',
                            '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.']

        exclude_dirs = ['/opt/OpenvStorage/config/templates/cinder-unit-tests/',
                        '/opt/OpenvStorage/config/templates/cinder-volume-driver/',
                        '/opt/OpenvStorage/webapps/frontend/css/',
                        '/opt/OpenvStorage/webapps/frontend/lib/',
                        '/opt/OpenvStorage/ovs/extensions/db/arakoon/arakoon/arakoon/',
                        '/opt/OpenvStorage/ovs/extensions/db/arakoon/pyrakoon/pyrakoon/']
        include_dirs = ['/opt/OpenvStorage/webapps/frontend/lib/ovs/']
        exclude_files = ['/opt/OpenvStorage/ovs/extensions/generic/fakesleep.py']
        include_files = ['/opt/OpenvStorage/webapps/frontend/css/ovs.css']
        extension_comments_map = {'.py': ['#'],
                                  '.js': ['//'],
                                  '.html': ['<!--', '-->'],
                                  '.css': ['/*', '*', '*/']}

        storagerouters = GeneralStorageRouter.get_storage_routers()
        files_with_diff_licenses = {}
        for storagerouter in storagerouters:
            root_client = SSHClient(storagerouter, username='******')
            files_with_diff_licenses[storagerouter.guid] = []
            for root_folder in ['/opt/OpenvStorage', '/opt/asd-manager']:
                if not root_client.dir_exists(root_folder):
                    raise ValueError('Root folder {0} does not exist'.format(root_folder))

                unfiltered_files = root_client.file_list(directory=root_folder,
                                                         abs_path=True,
                                                         recursive=True)
                filtered_files = General.filter_files(files=unfiltered_files,
                                                      extensions=extension_comments_map.keys(),
                                                      exclude_dirs=exclude_dirs,
                                                      include_dirs=include_dirs,
                                                      exclude_files=exclude_files,
                                                      include_files=include_files)
                for file_name in filtered_files:
                    # Read file
                    with open(file_name, 'r') as utf_file:
                        data = utf_file.read().decode("utf-8-sig").encode("utf-8")
                        lines_to_check = data.splitlines()

                    # Check relevant comment type for current file
                    comments = []
                    for extension, cmts in extension_comments_map.iteritems():
                        if file_name.endswith(extension):
                            comments = cmts
                            break
                    if len(comments) == 0:
                        raise ValueError('Something must have gone wrong filtering the files, because file {0} does not have a correct extension'.format(file_name))

                    # Search license header
                    index = 0
                    lic_header_found = False
                    for index, line in enumerate(lines_to_check):
                        for comment in comments:
                            line = line.replace(comment, '', 1)
                        if re.match(license_header, line.strip()):
                            lic_header_found = True
                            break

                    # License header not found, continuing
                    if lic_header_found is False:
                        files_with_diff_licenses[storagerouter.guid].append(file_name)
                        continue

                    # License header found, checking rest of license
                    index += 1
                    for license_line in license_to_check:
                        line_to_check = lines_to_check[index]
                        for comment in comments:
                            line_to_check = line_to_check.replace(comment, '', 1)
                        if license_line.strip() == line_to_check.strip():
                            index += 1
                            continue

                        files_with_diff_licenses[storagerouter.guid].append(file_name)
                        break

        for storagerouter in storagerouters:
            assert len(files_with_diff_licenses[storagerouter.guid]) == 0, 'Following files were found with different licenses:\n - {0}'.format('\n - '.join(files_with_diff_licenses[storagerouter.guid]))