install
Base installation helpers
To import...
from dynamite_nsm.services.base import install
        BaseInstallManager
    An interface used to assist with a variety of common service installation tasks
__init__(self, name, verbose=False, requires_root=True, stdout=True, log_level=20)
  
      special
  
    Build a custom service installer
Parameters:
| Name | Type | Description | Default | 
|---|---|---|---|
| name | str | The name of the service | required | 
| requires_root | Optional[bool] | If True, then the uninstaller will check that the user is root | True | 
| stdout | Optional[bool] | Print output to console | True | 
| verbose | Optional[bool] | Include detailed debug messages | False | 
| log_level |  | The minimum logging.LOG_LEVEL to be handled | 20 | 
Source code in dynamite_nsm/services/base/install.py
          def __init__(self, name: str, verbose: Optional[bool] = False, requires_root: Optional[bool] = True,
             stdout: Optional[bool] = True, log_level=logging.INFO):
    """
    Build a custom service installer
    Args:
        name: The name of the service
        requires_root: If True, then the uninstaller will check that the user is root
        stdout: Print output to console
        verbose: Include detailed debug messages
        log_level: The minimum logging.LOG_LEVEL to be handled
    """
    if not utilities.is_setup():
        raise exceptions.DynamiteNotSetupError()
    if requires_root and not utilities.is_root():
        raise exceptions.RequiresRootError()
    if verbose:
        log_level = logging.DEBUG
    self.stdout = stdout
    self.verbose = verbose
    self.logger = get_logger(str(name).upper(), level=log_level, stdout=stdout)
    self.dynamite_environ = utilities.get_environment_file_dict()
    utilities.makedirs(const.INSTALL_CACHE)
    utilities.create_dynamite_user()
compile_source_package(self, source_root_directory, compile_args=None, parallel_threads=None, expected_lines_printed=None)
    A simple make; make install wrapper
Parameters:
| Name | Type | Description | Default | 
|---|---|---|---|
| source_root_directory | str | The directory containing the MAKEFILE | required | 
| compile_args | Optional[List[str]] | make arguments | None | 
| parallel_threads | Optional[int] | The number of parallel threads to use during compilation (jemalloc) | None | 
| expected_lines_printed | Optional[int] | The number of lines produced by this process (used to generate a progressbar) | None | 
Returns: None
Source code in dynamite_nsm/services/base/install.py
          def compile_source_package(self, source_root_directory: str, compile_args: Optional[List[str]] = None,
                           parallel_threads: Optional[int] = None,
                           expected_lines_printed: Optional[int] = None) -> None:
    """A simple make; make install wrapper
    Args:
        source_root_directory: The directory containing the MAKEFILE
        compile_args: make arguments
        parallel_threads: The number of parallel threads to use during compilation (jemalloc)
        expected_lines_printed: The number of lines produced by this process (used to generate a progressbar)
    Returns: None
    """
    if not parallel_threads:
        parallel_threads = get_parallel_threads()
    if compile_args:
        compile_args.extend(['-j', parallel_threads])
    else:
        compile_args = ['-j', parallel_threads]
    temp_compile_args = [f'{const.SYS_BIN}/make']
    temp_compile_args.extend(compile_args)
    temp_compile_args = [str(a) for a in temp_compile_args]
    compile_args = temp_compile_args
    compile_args.extend([';', f'{const.SYS_BIN}/make', 'install'])
    self.logger.info(f'Compiling: {source_root_directory}.')
    self.logger.debug(" ".join(compile_args))
    popen_make_args = dict(
        args=' '.join(compile_args),
        shell=True,
        cwd=source_root_directory,
    )
    if not self.verbose:
        popen_make_args['stdout'] = subprocess.PIPE
        popen_make_args['stderr'] = subprocess.PIPE
        ret = utilities.run_subprocess_with_status(subprocess.Popen(**popen_make_args),
                                                   expected_lines=expected_lines_printed)
    else:
        p = subprocess.Popen(**popen_make_args)
        p.communicate()
        ret = p.returncode
    if ret != 0:
        self.logger.error(f'Exited: {ret}; Process Info: {compile_args}')
        raise exceptions.CallProcessError(f'Exited with {ret}')
configure_source_package(self, source_root_directory, configure_args=None)
    A configure wrapper for the build/make process
Parameters:
| Name | Type | Description | Default | 
|---|---|---|---|
| source_root_directory | str | A directory containing the configuration.in file | required | 
| configure_args | Optional[List[str]] | configure arguments | None | 
Returns:
| Type | Description | 
|---|---|
| None | None | 
Source code in dynamite_nsm/services/base/install.py
          def configure_source_package(self, source_root_directory: str, configure_args: Optional[List[str]] = None) -> None:
    """A configure wrapper for the build/make process
    Args:
        source_root_directory: A directory containing the configuration.in file
        configure_args: configure arguments
    Returns:
        None
    """
    temp_config_args = ['./configure']
    temp_config_args.extend(configure_args)
    temp_config_args = [str(a) for a in temp_config_args]
    configure_args = temp_config_args
    self.logger.info(f'Configuring build: {source_root_directory}.')
    self.logger.debug(" ".join(configure_args))
    popen_args = dict(
        args=' '.join(configure_args),
        shell=True,
        cwd=source_root_directory,
    )
    if not self.verbose:
        popen_args['stdout'] = subprocess.PIPE
        popen_args['stderr'] = subprocess.PIPE
        ret = utilities.run_subprocess_with_status(subprocess.Popen(**popen_args),
                                                   expected_lines=None)
    else:
        p = subprocess.Popen(**popen_args)
        p.communicate()
        ret = p.returncode
    if ret != 0:
        self.logger.error(f'Exited: {ret}; Process Info: {configure_args}')
        raise exceptions.CallProcessError(f'Exited with {ret}')
copy_file_or_directory_to_destination(self, file_or_dir, destination_file_or_dir)
    Copy a file or directory to another file or directory
Parameters:
| Name | Type | Description | Default | 
|---|---|---|---|
| file_or_dir | str | The file or directory to copy | required | 
| destination_file_or_dir | str | The file or directory destination | required | 
Returns:
| Type | Description | 
|---|---|
| None | None | 
Source code in dynamite_nsm/services/base/install.py
          def copy_file_or_directory_to_destination(self, file_or_dir: str, destination_file_or_dir: str) -> None:
    """
    Copy a file or directory to another file or directory
    Args:
        file_or_dir: The file or directory to copy
        destination_file_or_dir: The file or directory destination
    Returns:
        None
    """
    file_or_dir = file_or_dir.rstrip('/')
    destination_location = f'{destination_file_or_dir}/{os.path.basename(file_or_dir)}'
    if os.path.isdir(file_or_dir):
        utilities.makedirs(destination_location, exist_ok=True)
        self.logger.debug(f'Creating directory: {destination_location}')
        try:
            self.logger.debug(f'Copying directory {file_or_dir} -> {destination_location}')
            utilities.copytree(file_or_dir, destination_location)
        except shutil.Error as e:
            if 'exist' in str(e):
                self.logger.warning(f'{destination_file_or_dir} directory already exists. Skipping.')
            else:
                raise e
    else:
        try:
            self.logger.debug(f'Copying file {file_or_dir} -> {destination_file_or_dir}')
            shutil.copy(file_or_dir, destination_file_or_dir)
        except FileNotFoundError:
            parent_directory = os.path.dirname(destination_file_or_dir)
            self.logger.debug(f'Creating parent directory: {parent_directory}')
            utilities.makedirs(parent_directory)
            shutil.copy(file_or_dir, destination_file_or_dir)
        except shutil.Error as e:
            if 'exist' in str(e):
                self.logger.warning(f'{destination_file_or_dir} file already exists. Skipping.')
            else:
                raise e
create_update_env_variable(self, name, value)
    Write the environment variable into our root owned environment file
Parameters:
| Name | Type | Description | Default | 
|---|---|---|---|
| name | str | The name of the variable | required | 
| value | str | The value of the variable | required | 
Returns:
| Type | Description | 
|---|---|
| None | None | 
Source code in dynamite_nsm/services/base/install.py
          def create_update_env_variable(self, name: str, value: str) -> None:
    """Write the environment variable into our root owned environment file
    Args:
        name: The name of the variable
        value: The value of the variable
    Returns:
        None
    """
    name = str(name)
    value = str(value)
    env_file_path = f'{const.CONFIG_PATH}/environment'
    if not os.path.exists(env_file_path):
        with open(env_file_path, 'w') as env_f:
            env_f.write('')
    overwrite_line_no = -1
    with open(env_file_path) as env_fr:
        read_lines = env_fr.readlines()
        for idx, line in enumerate(read_lines):
            if str(line).startswith(name):
                overwrite_line_no = idx
                break
    if overwrite_line_no == -1:
        with open(env_file_path, 'a') as env_fa:
            env_fa.write(f'{name}={value}\n')
            self.logger.debug(f'Setting {name} -> {value}')
    else:
        self.logger.debug(f'Overwriting {name} -> {value}')
        if value.endswith('\n'):
            read_lines[overwrite_line_no] = f'{name}={value}'
        else:
            read_lines[overwrite_line_no] = f'{name}={value}\n'
        with open(env_file_path, 'w') as env_fw:
            env_fw.writelines(read_lines)
    utilities.set_ownership_of_file(env_file_path)
download_from_mirror(self, mirror_path)
    Download a Dynamite service from a mirror
Parameters:
| Name | Type | Description | Default | 
|---|---|---|---|
| mirror_path | str | The path to the mirror | required | 
Returns:
| Type | Description | 
|---|---|
| Tuple[str, str, Optional[str]] | The mirror url, archive name, and directory name (once the archive has been extracted) | 
Source code in dynamite_nsm/services/base/install.py
          def download_from_mirror(self, mirror_path: str) -> Tuple[str, str, Optional[str]]:
    """Download a Dynamite service from a mirror
    Args:
        mirror_path: The path to the mirror
    Returns:
        The mirror url, archive name, and directory name (once the archive has been extracted)
    """
    with open(mirror_path) as mirror_f:
        res, err = None, None
        for mirror in mirror_f.readlines():
            try:
                url, archive_name, dir_name = [token.strip() for token in mirror.split(',')]
            except ValueError:
                url = mirror
                archive_name = os.path.basename(url)
                dir_name = None
            self.logger.info("Downloading {} from {}".format(archive_name, url))
            fqdn_dir_name = f'{const.INSTALL_CACHE}/{str(dir_name)}'
            if os.path.exists(fqdn_dir_name):
                shutil.rmtree(fqdn_dir_name, ignore_errors=True)
            try:
                res = utilities.download_file(url, archive_name, stdout=self.stdout)
            except Exception as e:
                res, err = False, e
                self.logger.warning(f'Failed to download {archive_name} from {url}; {e}')
            if res:
                break
        if not res:
            self.logger.error(f'An error occurred while attempting to download: {err}')
            raise exceptions.DownloadError(
                f'General error while attempting to download {archive_name} from all mirrors.')
        return url, archive_name, dir_name
extract_archive(archive_path)
  
      staticmethod
  
    Extract a tar.gz archive to disk
Parameters:
| Name | Type | Description | Default | 
|---|---|---|---|
| archive_path | str | The full path to the archive. | required | 
Returns:
| Type | Description | 
|---|---|
| None | None | 
Source code in dynamite_nsm/services/base/install.py
          @staticmethod
def extract_archive(archive_path: str) -> None:
    """
    Extract a tar.gz archive to disk
    Args:
        archive_path: The full path to the archive.
    Returns:
        None
    """
    try:
        tf = tarfile.open(archive_path)
        tf.extractall(path=const.INSTALL_CACHE)
    except IOError as e:
        raise exceptions.ArchiveExtractionError(
            f'Could not extract {archive_path} archive to {const.INSTALL_CACHE}; {e}')
    except Exception as e:
        raise exceptions.ArchiveExtractionError(
            f'General error while attempting to extract {archive_path} archive; {e}')
get_mirror_info(mirror_path)
  
      staticmethod
  
    Get information about a mirror
Parameters:
| Name | Type | Description | Default | 
|---|---|---|---|
| mirror_path | str | The path to the mirror | required | 
Returns:
| Type | Description | 
|---|---|
| Tuple[str, str, Optional[str]] | The mirror url, archive name, and directory name (once the archive has been extracted) | 
Source code in dynamite_nsm/services/base/install.py
          @staticmethod
def get_mirror_info(mirror_path: str) -> Tuple[str, str, Optional[str]]:
    """
    Get information about a mirror
    Args:
        mirror_path: The path to the mirror
    Returns:
        The mirror url, archive name, and directory name (once the archive has been extracted)
    """
    with open(mirror_path) as mirror_f:
        for mirror in mirror_f.readlines():
            try:
                url, archive_name, dir_name = [token.strip() for token in mirror.split(',')]
            except ValueError:
                url = mirror
                archive_name = os.path.basename(url)
                dir_name = None
    return url, archive_name, dir_name
install_dependencies(self, apt_get_packages=None, yum_packages=None, pre_install_function=None)
    Install OS dependencies through the package manager
Parameters:
| Name | Type | Description | Default | 
|---|---|---|---|
| apt_get_packages | Optional[List] | The name of the packages available in apt-get supported repos | None | 
| yum_packages | Optional[List] | The name of the packages available in yum supported repos | None | 
| pre_install_function | Optional[Callable] | A Python function to run prior to installing these packages | None | 
Returns:
| Type | Description | 
|---|---|
| None | None | 
Source code in dynamite_nsm/services/base/install.py
          def install_dependencies(self, apt_get_packages: Optional[List] = None, yum_packages: Optional[List] = None,
                         pre_install_function: Optional[Callable] = None) -> None:
    """
    Install OS dependencies through the package manager
    Args:
        apt_get_packages: The name of the packages available in apt-get supported repos
        yum_packages: The name of the packages available in yum supported repos
        pre_install_function: A Python function to run prior to installing these packages
    Returns:
        None
    """
    pacman = package_manager.OSPackageManager(stdout=self.stdout, verbose=self.verbose)
    packages = []
    if pacman.package_manager == 'apt-get':
        self.logger.info('apt-get detected. We will use this package manager to install dependencies.')
        packages = apt_get_packages
    elif pacman.package_manager == 'yum':
        self.logger.info('yum detected. We will use this package manager to install dependencies.')
        packages = yum_packages
    self.logger.info('Refreshing package indexes')
    if pre_install_function:
        self.logger.info('Running pre-installation function.')
        pre_install_function(pacman.package_manager)
    pacman.refresh_package_indexes()
    self.logger.debug(f'Packages: {packages}')
    if packages:
        self.logger.info(f'Installing {len(packages)} new packages.')
        pacman.install_packages(packages)
validate_inspect_interfaces(inspect_interfaces)
  
      staticmethod
  
    Determine if one or more capture interface actually exists
Parameters:
| Name | Type | Description | Default | 
|---|---|---|---|
| inspect_interfaces | List[str] | A list of network interface names to evaluate. | required | 
Returns:
| Type | Description | 
|---|---|
| bool | True, if all interfaces are valid | 
Source code in dynamite_nsm/services/base/install.py
          @staticmethod
def validate_inspect_interfaces(inspect_interfaces: List[str]) -> bool:
    """
    Determine if one or more capture interface actually exists
    Args:
        inspect_interfaces: A list of network interface names to evaluate.
    Returns:
        True, if all interfaces are valid
    """
    for interface in inspect_interfaces:
        if interface not in utilities.get_network_interface_names():
            return False
    return True
        BaseUninstallManager
    An interface used to assist with a variety of common service uninstall tasks
__init__(self, name, directories, environ_vars=None, process=None, sysctl_service_name=None, requires_root=True, verbose=False, stdout=True, log_level=20)
  
      special
  
    Remove installed files for a given service
Parameters:
| Name | Type | Description | Default | 
|---|---|---|---|
| name | str | The name of the process | required | 
| directories | List[str] | The directories to be removed | required | 
| process | Optional[dynamite_nsm.services.base.process.BaseProcessManager] | The process to be terminated | None | 
| sysctl_service_name | Optional[str] | The name any associated systemd unit file. | None | 
| requires_root | Optional[bool] | If True, then the uninstaller will check that the user is root | True | 
| stdout | Optional[bool] | Print output to console | True | 
| verbose | Optional[bool] | Include detailed debug messages | False | 
| log_level |  | The logging.LOG_LEVEL to use when logging | 20 | 
Source code in dynamite_nsm/services/base/install.py
          def __init__(self, name: str, directories: List[str], environ_vars: Optional[List[str]] = None,
             process: Optional[process.BaseProcessManager] = None,
             sysctl_service_name: Optional[str] = None, requires_root: Optional[bool] = True,
             verbose: Optional[bool] = False,
             stdout: Optional[bool] = True, log_level=logging.INFO):
    """Remove installed files for a given service
    Args:
        name: The name of the process
        directories: The directories to be removed
        process: The process to be terminated
        sysctl_service_name: The name any associated systemd unit file.
        requires_root: If True, then the uninstaller will check that the user is root
        stdout: Print output to console
        verbose: Include detailed debug messages
        log_level: The logging.LOG_LEVEL to use when logging
    """
    self.name = name
    self.directories = directories
    self.environ_vars = environ_vars
    self.process = process
    self.verbose = verbose
    self.sysctl_service_name = sysctl_service_name
    self.stdout = stdout
    if verbose:
        log_level = logging.DEBUG
    self.logger = get_logger(str(name).upper(), level=log_level, stdout=stdout)
    if requires_root and not utilities.is_root():
        raise exceptions.RequiresRootError()
uninstall(self)
    Stop and uninstall the service
Returns:
| Type | Description | 
|---|---|
|  | None | 
Source code in dynamite_nsm/services/base/install.py
          def uninstall(self):
    """Stop and uninstall the service
    Returns:
        None
    """
    sysctl = systemctl.SystemCtl(stdout=self.stdout, verbose=self.verbose)
    if self.process:
        self.process.stop()
    for dir in self.directories:
        self.logger.info(f'Removing {dir}')
        shutil.rmtree(dir, ignore_errors=True)
    if self.environ_vars:
        for var in self.environ_vars:
            self.delete_env_variable(var)
    if self.sysctl_service_name:
        try:
            self.logger.info(f'Uninstalling {self.sysctl_service_name}')
            sysctl.uninstall_and_disable(self.sysctl_service_name)
        except FileNotFoundError:
            self.logger.debug('Skipping service uninstallation as systemd was not implemented in this setup.')
    self.logger.info(f'Successfully uninstalled {self.name}')
        NetworkInterfaceNotFound
    Thrown when attempting to disable a non-existing interface
__init__(self, interfaces)
  
      special
  
    :param interfaces: A network interface
Source code in dynamite_nsm/services/base/install.py
          def __init__(self, interfaces: Union[str, List]):
    """
    :param interfaces: A network interface
    """
    msg = f'Network interface(s) does not exist: {interfaces}.'
    super(NetworkInterfaceNotFound, self).__init__(msg)