예제 #1
0
    def __getattr__(self, item):
        from ovs_extensions.generic.toolbox import ExtensionsToolbox

        if item.startswith('configure_'):
            section = ExtensionsToolbox.remove_prefix(item, 'configure_')
            return lambda **kwargs: self._add(section, **kwargs)
        if item.startswith('clear_'):
            section = ExtensionsToolbox.remove_prefix(item, 'clear_')
            return lambda: self._delete(section)
 def list(self, key, recursive=False):
     # type: (str, bool) -> Generator[str]
     """
     List all keys starting with specified key
     :param key: Key to list
     :type key: str
     :param recursive: List keys recursively
     :type recursive: bool
     :return: Generator with all keys
     :rtype: generator
     """
     key = self._clean_key(key)
     entries = []
     for entry in self._client.prefix(key):
         if entry.startswith('_'):
             continue
         if recursive is True:
             parts = entry.split('/')
             for index, part in enumerate(parts):
                 if index == len(parts) - 1:  # Last part
                     yield entry  # Every entry is unique, so when having reached last part, we yield it
                 else:
                     dir_name = '{0}/'.format('/'.join(parts[:index + 1]))
                     if dir_name not in entries:
                         entries.append(dir_name)
                         yield dir_name
         else:
             if key == '' or entry.startswith(key.rstrip('/') + '/'):
                 cleaned = ExtensionsToolbox.remove_prefix(
                     entry, key).strip('/').split('/')[0]
                 if cleaned not in entries:
                     entries.append(cleaned)
                     yield cleaned
예제 #3
0
 def regenerate_service(self, name, client, target_name):
     # type: (str, SSHClient, str) -> None
     """
     Regenerates the service files of a service.
     :param name: Template name of the service to regenerate
     :type name: str
     :param client: Client on which to regenerate the service
     :type client: ovs_extensions.generic.sshclient.SSHClient
     :param target_name: The current service name eg ovs-volumedriver_flash01.service
     :type target_name: str
     :return: None
     :rtype: NoneType
     :raises: RuntimeError if the regeneration failed
     """
     configuration_key = self.service_config_key.format(self._system.get_my_machine_id(client),
                                                        ExtensionsToolbox.remove_prefix(target_name, self.OVS_SERVICE_PREFIX))
     # If the entry is stored in arakoon, it means the service file was previously made
     if not self._configuration.exists(configuration_key):
         raise RuntimeError('Service {0} was not previously added and cannot be regenerated.'.format(target_name))
     # Rewrite the service file
     service_params = self._configuration.get(configuration_key)
     startup_dependency = service_params['STARTUP_DEPENDENCY']
     if startup_dependency == '':
         startup_dependency = None
     else:
         startup_dependency = '.'.join(startup_dependency.split('.')[:-1])  # Remove .service from startup dependency
     output = self.add_service(name=name,
                               client=client,
                               params=service_params,
                               target_name=target_name,
                               startup_dependency=startup_dependency,
                               delay_registration=True)
     if output is None:
         raise RuntimeError('Regenerating files for service {0} has failed'.format(target_name))
예제 #4
0
    def add_service(self, name, client, params=None, target_name=None, startup_dependency=None, delay_registration=False, path=None):
        # type: (str, SSHClient, dict, str, str, bool, str) -> dict
        """
        Add a service
        :param name: Template name of the service to add
        :type name: str
        :param client: Client on which to add the service
        :type client: ovs_extensions.generic.sshclient.SSHClient
        :param params: Additional information about the service
        :type params: dict or None
        :param target_name: Overrule default name of the service with this name
        :type target_name: str or None
        :param startup_dependency: Additional startup dependency
        :type startup_dependency: str or None
        :param delay_registration: Register the service parameters in the config management right away or not
        :type delay_registration: bool
        :param path: path to add service to
        :type path: str
        :return: Parameters used by the service
        :rtype: dict
        """
        if params is None:
            params = {}
        if path is None:
            path = self._config_template_dir.format('systemd')
        else:
            path = path.format('systemd')
        service_name = self._get_name(name, client, path)

        template_file = '{0}/{1}.service'.format(path, service_name)

        if not client.file_exists(template_file):
            # Given template doesn't exist so we are probably using system init scripts
            return {}

        if target_name is not None:
            service_name = target_name

        params.update({'SERVICE_NAME': ExtensionsToolbox.remove_prefix(service_name, 'ovs-'),
                       'RUN_FILE_DIR': self._run_file_dir,
                       'STARTUP_DEPENDENCY': '' if startup_dependency is None else '{0}.service'.format(startup_dependency)})
        template_content = client.file_read(template_file)
        for key, value in params.iteritems():
            template_content = template_content.replace('<{0}>'.format(key), str(value))
        service_path = self.get_service_file_path(service_name)
        client.file_write(service_path, template_content)

        try:
            client.run(['systemctl', 'daemon-reload'])
            client.run(['systemctl', 'enable', '{0}.service'.format(service_name)])
        except CalledProcessError as cpe:
            self._logger.exception('Add {0}.service failed, {1}'.format(service_name, cpe.output))
            raise Exception('Add {0}.service failed, {1}'.format(service_name, cpe.output))

        if delay_registration is False:
            self.register_service(service_metadata=params, node_name=self._system.get_my_machine_id(client))
        return params
예제 #5
0
    def collapse_arakoon():
        """
        Collapse Arakoon's Tlogs
        :return: None
        """
        from ovs_extensions.generic.toolbox import ExtensionsToolbox

        GenericController._logger.info('Arakoon collapse started')
        cluster_info = []
        storagerouters = StorageRouterList.get_storagerouters()
        if os.environ.get('RUNNING_UNITTESTS') != 'True':
            cluster_info = [('cacc', storagerouters[0])]

        cluster_names = []
        for service in ServiceList.get_services():
            if service.is_internal is True and service.type.name in (ServiceType.SERVICE_TYPES.ARAKOON,
                                                                     ServiceType.SERVICE_TYPES.NS_MGR,
                                                                     ServiceType.SERVICE_TYPES.ALBA_MGR):
                cluster = ExtensionsToolbox.remove_prefix(service.name, 'arakoon-')
                if cluster in cluster_names and cluster not in [ARAKOON_NAME, ARAKOON_NAME_UNITTEST]:
                    continue
                cluster_names.append(cluster)
                cluster_info.append((cluster, service.storagerouter))
        workload = {}
        cluster_config_map = {}
        for cluster, storagerouter in cluster_info:
            GenericController._logger.debug('  Collecting info for cluster {0}'.format(cluster))
            ip = storagerouter.ip if cluster in [ARAKOON_NAME, ARAKOON_NAME_UNITTEST] else None
            try:
                config = ArakoonClusterConfig(cluster_id=cluster, source_ip=ip)
                cluster_config_map[cluster] = config
            except:
                GenericController._logger.exception('  Retrieving cluster information on {0} for {1} failed'.format(storagerouter.ip, cluster))
                continue
            for node in config.nodes:
                if node.ip not in workload:
                    workload[node.ip] = {'node_id': node.name,
                                         'clusters': []}
                workload[node.ip]['clusters'].append((cluster, ip))
        for storagerouter in storagerouters:
            try:
                if storagerouter.ip not in workload:
                    continue
                node_workload = workload[storagerouter.ip]
                client = SSHClient(storagerouter)
                for cluster, ip in node_workload['clusters']:
                    try:
                        GenericController._logger.debug('  Collapsing cluster {0} on {1}'.format(cluster, storagerouter.ip))
                        client.run(['arakoon', '--collapse-local', node_workload['node_id'], '2', '-config', cluster_config_map[cluster].external_config_path])
                        GenericController._logger.debug('  Collapsing cluster {0} on {1} completed'.format(cluster, storagerouter.ip))
                    except:
                        GenericController._logger.exception('  Collapsing cluster {0} on {1} failed'.format(cluster, storagerouter.ip))
            except UnableToConnectException:
                GenericController._logger.error('  Could not collapse any cluster on {0} (not reachable)'.format(storagerouter.name))
        GenericController._logger.info('Arakoon collapse finished')
예제 #6
0
 def get_run_file_path(self, name):
     # type: (str) -> str
     """
     Get the path to the run file for the given service
     This is tied to the template files as they specify something like `/opt/OpenvStorage/run/<SERVICE_NAME>.version`
     :param name: Name of the service
     :type name: str
     :return: Path to the file
     :rtype: str
     """
     non_ovs_name = ExtensionsToolbox.remove_prefix(name, self.OVS_SERVICE_PREFIX)
     return os.path.join(self._run_file_dir, non_ovs_name, '.version')
예제 #7
0
 def unregister_service(self, node_name, service_name):
     # type: (str, str) -> None
     """
     Un-register the metadata of a service from the configuration management
     :param node_name: Name of the node on which to un-register the service
     :type node_name: str
     :param service_name: Name of the service to clean from the configuration management
     :type service_name: str
     :return: None
     :rtype: NoneType
     """
     self._configuration.delete(key=self.service_config_key.format(node_name, ExtensionsToolbox.remove_prefix(service_name, self.OVS_SERVICE_PREFIX)))
예제 #8
0
 def register_service(self, node_name, service_metadata):
     # type: (str, dict) -> None
     """
     Register the metadata of the service to the configuration management
     :param node_name: Name of the node on which the service is running
     :type node_name: str
     :param service_metadata: Metadata of the service
     :type service_metadata: dict
     :return: None
     :rtype: NoneType
     """
     service_name = service_metadata['SERVICE_NAME']
     self._configuration.set(key=self.service_config_key.format(node_name, ExtensionsToolbox.remove_prefix(service_name, self.OVS_SERVICE_PREFIX)),
                             value=service_metadata)
예제 #9
0
    def add_service(self, name, client, params=None, target_name=None, startup_dependency=None, delay_registration=False, path=None):
        """
        Adds a mocked service
        """
        _ = path

        if params is None:
            params = {}

        key = 'None' if client is None else client.ip
        name = name if target_name is None else target_name
        params.update({'SERVICE_NAME': ExtensionsToolbox.remove_prefix(name, 'ovs-'),
                       'STARTUP_DEPENDENCY': '' if startup_dependency is None else '{0}.service'.format(startup_dependency)})
        if self.has_service(name=name, client=client) is False:
            if key not in SystemdMock.services:
                SystemdMock.services[key] = {}
            SystemdMock.services[key].update({name: {'state': 'HALTED', 'pid': None}})
        if delay_registration is False:
            self.register_service(node_name=self._system.get_my_machine_id(client), service_metadata=params)
        return params