Esempio n. 1
0
    def __init__(self):
        self.logger = Logger()
        self.app_path = sys.path[0]
        self.current_module = None
        self.current_module_name = None
        self.dispatcher = Dispatcher()
        self.modules = self._list_modules()
        self.modules_history = []
        self.config = load_config()
        self.completer_nested_dict = self._get_dict_completion()
        self.console_completer = NestedCompleter.from_nested_dict(
            self.completer_nested_dict)
        self.global_options = {}
        self.prompt_style = Style.from_dict({
            # User input (default text), no value = system default.
            '':
            self.config['THEME']['user_input'],

            # Prompt.
            'base':
            self.config['THEME']['base'],
            'pound':
            self.config['THEME']['pound'],
            'module':
            self.config['THEME']['module'],
            'category':
            self.config['THEME']['category'],
        })
        self.prompt = [
            ('class:base', '[hbf] '),
            ('class:module', ''),
            ('class:category', ''),
            ('class:pound', '> '),
        ]
Esempio n. 2
0
 def __init__(self, hbf_config):
     self.name = None
     self.meta = {
         'name': '',
         'version': '',
         'description': '',
         'author': ''
     }
     self.logger = Logger()
     self.options = []
     self.config = hbf_config
Esempio n. 3
0
class Validator:
    """
    Class allowing to check module options (if set and if format is ok).
    """
    def __init__(self):
        self.logger = Logger()

    def _args_validator(self, options_dict):
        """
        Check arguments type validity & Convert to the specified format.
        :param options_dict: module options dictionary
        :return: Bool
        """
        for option in options_dict:
            try:
                if option["Type"] == "int":
                    if not isinstance(option["Value"], int):
                        option["Value"] = int(option["Value"], 10)
                if option["Type"] == "bool":
                    if not isinstance(option["Value"], bool):
                        if str(option["Value"]).upper() == "FALSE":
                            option["Value"] = False
                        elif str(option["Value"]).upper() == "TRUE":
                            option["Value"] = True
                        else:
                            raise ValueError
                if option["Value"] == "None":
                    option["Value"] = None
            except ValueError:
                self.logger.handle(
                    "Value error: {} is not a member of {}".format(
                        option["Name"], option["Type"]))
                return False
        return True

    def check_args(self, options_dict):
        """
        Check if all arguments are defined by user, or set default value if available.
        :param options_dict: module options dictionary
        :return: Bool
        """
        if len(options_dict) > 0:
            for option in options_dict:
                if option["Required"] and option["Value"] == "":
                    if option["Default"] == "":
                        self.logger.handle(
                            "OptionValidateError: The following options failed to validate: {}."
                            .format(option["Name"]), Logger.ERROR)
                        return False
                    else:
                        option["Value"] = option["Default"]
            if not self._args_validator(options_dict):
                return False
        return True
def hb_connect(device, baudrate, timeout):
    """
    Connect to the hydrabus device.
    :param device: String, hydrabus device path.
    :param baudrate: integer, baudrate speed to communicate with hydrabus.
    :param timeout: integer, read timeout value (sec).
    :return: serial instance.
    """
    try:
        serial_instance = serial.Serial(device, baudrate, timeout=timeout)
        return serial_instance
    except serial.serialutil.SerialException as err:
        Logger().handle(err, Logger.ERROR)
        return False
Esempio n. 5
0
 def __init__(self, hbf_config):
     super(Baudrate, self).__init__(hbf_config)
     self.logger = Logger()
     self.vowels = ["a", "A", "e", "E", "i", "I", "o", "O", "u", "U"]
     self.whitespace = [" ", "\t", "\r", "\n"]
     self.punctation = [".", ",", ":", ";", "?", "!"]
     self.control = [b'\x0e', b'\x0f', b'\xe0', b'\xfe', b'\xc0']
     self.baudrates = [9600, 19200, 38400, 57600, 115200]
     self.hb_serial = None
     self.meta.update({
         'name': 'UART baudrate detection',
         'version': '0.0.1',
         'description': 'Automatically detect baudrate of a target device',
         'author': 'Jordan Ovrè'
     })
     self.options = [
         {"Name": "hydrabus", "Value": "", "Required": True, "Type": "string",
          "Description": "Hydrabus device", "Default": self.config["HYDRABUS"]["port"]},
         {"Name": "timeout", "Value": "", "Required": True, "Type": "int",
          "Description": "Hydrabus read timeout", "Default": self.config["HYDRABUS"]["read_timeout"]},
         {"Name": "trigger", "Value": "", "Required": True, "Type": "bool",
          "Description": "If true, trigger the device if hydrabus didn't receive anything from the target",
          "Default": False}
     ]
def hb_wait_ubtn(serial_instance):
    """
    Loop until user press hydrabus UBTN.
    :param serial_instance: hydrabus serial instance.
    :return: Nothing.
    """
    # timeout=1 minute
    timeout = time.time() + 60 * 1
    try:
        while True:
            if serial_instance.hydrabus.read(1) == 'B'.encode('utf-8'):
                if serial_instance.hydrabus.read(3) == 'BIO'.encode('utf-8'):
                    # carriage return needed to reset interface
                    serial_instance.hydrabus.write(b'\x0D\x0A')
                    time.sleep(0.2)
                    serial_instance.read(serial_instance.hydrabus.in_waiting)
                    break
            if time.time() > timeout:
                Logger().handle("Wait UBTN timeout reached", Logger.ERROR)
                break
    except KeyboardInterrupt:
        pass
Esempio n. 7
0
class Baudrate(AModule):
    """
    Iterate baudrate to find the correct value
    TODO: Add Parity bit and Stop bit option
    """
    def __init__(self, hbf_config):
        super(Baudrate, self).__init__(hbf_config)
        self.logger = Logger()
        self.vowels = ["a", "A", "e", "E", "i", "I", "o", "O", "u", "U"]
        self.whitespace = [" ", "\t", "\r", "\n"]
        self.punctation = [".", ",", ":", ";", "?", "!"]
        self.control = [b'\x0e', b'\x0f', b'\xe0', b'\xfe', b'\xc0']
        self.baudrates = [9600, 19200, 38400, 57600, 115200]
        self.hb_serial = None
        self.meta.update({
            'name': 'UART baudrate detection',
            'version': '0.0.1',
            'description': 'Automatically detect baudrate of a target device',
            'author': 'Jordan Ovrè'
        })
        self.options = [
            {"Name": "hydrabus", "Value": "", "Required": True, "Type": "string",
             "Description": "Hydrabus device", "Default": self.config["HYDRABUS"]["port"]},
            {"Name": "timeout", "Value": "", "Required": True, "Type": "int",
             "Description": "Hydrabus read timeout", "Default": self.config["HYDRABUS"]["read_timeout"]},
            {"Name": "trigger", "Value": "", "Required": True, "Type": "bool",
             "Description": "If true, trigger the device if hydrabus didn't receive anything from the target",
             "Default": False}
        ]

    def gen_char_list(self):
        """
        Generate human readable characters list.
        :return: character's list
        """
        c = ' '
        valid_characters = []
        while c <= '~':
            valid_characters.append(c)
            c = chr(ord(c) + 1)

        for c in self.whitespace:
            if c not in valid_characters:
                valid_characters.append(c)

        for c in self.control:
            if c not in valid_characters:
                valid_characters.append(c)
        return valid_characters

    def change_baudrate(self, baudrate):
        """
        This function change the baudrate speed for the target device.
        It is necessary to stop echo UART RX to read the return of the
        change baudrate function from Hydrabus.
        :param baudrate: Baudrate speed dictionary (decimal and hexadecimal value)
        :return: bool
        """
        self.init_hb()
        self.hb_serial.baud = baudrate
        if self.hb_serial.baud != baudrate:
            self.logger.handle(f'Unable to switch to baudrate {baudrate}', Logger.ERROR)
            return False
        else:
            # Starting binary UART bridge mode
            self.logger.handle(f'switching to baudrate {baudrate}...', Logger.INFO)
            self.logger.handle("Starting BBIO_UART_BRIDGE", Logger.INFO)
            self.hb_serial.bridge()
            return True

    def trigger_device(self):
        """
        Send a carriage return to trigger the target device
        in case no byte(s) is received
        """
        self.logger.handle("Trigger the device", Logger.INFO)
        self.hb_serial.write(b'\x0D\x0A')
        # Read back \r\n characters
        self.hb_serial.read(2)
        time.sleep(0.5)

    def baudrate_detect(self):
        """
        The main function. Change the baudrate speed
        and check if the received byte(s) from RX pin are valid characters.
        25 valid characters are required to identify the correct baudrate value.
        """
        count = 0
        whitespace = 0
        punctuation = 0
        vowels = 0
        threshold = 25
        valid_characters = self.gen_char_list()

        try:
            trigger = self.get_option_value("trigger")
        except UserWarning:
            self.logger.handle("Unable to recover trigger settings, set it to False", Logger.ERROR)
            trigger = False

        self.logger.handle("Starting baurate detection, turn on your serial device now", Logger.HEADER)
        self.logger.handle("Press Ctrl+C to cancel", Logger.HEADER)

        for baudrate in self.baudrates:
            loop = 0
            if self.change_baudrate(baudrate):
                progress = self.logger.progress('Read byte')
                while True:
                    tmp = self.hb_serial.read(1)
                    if len(tmp) > 0:
                        # Dynamic print
                        try:
                            tmp.decode()
                            progress.status(tmp.decode())
                        except UnicodeDecodeError:
                            tmp2 = tmp
                            progress.status('0x{}'.format(codecs.encode(tmp2, 'hex').decode()))
                        try:
                            byte = tmp.decode('utf-8')
                        except UnicodeDecodeError:
                            byte = tmp
                        if byte in valid_characters:
                            if byte in self.whitespace:
                                whitespace += 1
                            elif byte in self.punctation:
                                punctuation += 1
                            elif byte in self.vowels:
                                vowels += 1
                            count += 1
                        else:
                            whitespace = 0
                            punctuation = 0
                            vowels = 0
                            count = 0
                            progress.stop()
                            self.logger.handle("Please press hydrabus ubtn in order to switch baudrate speed",
                                               Logger.USER_INTERACT)
                            hb_wait_ubtn(self.hb_serial)
                            break
                        if count >= threshold and whitespace > 0 and punctuation >= 0 and vowels > 0:
                            progress.stop()
                            self.logger.handle("Valid Baudrate found: {}".format(baudrate), Logger.RESULT)
                            resp = prompt('Would you like to open a miniterm session ? N/y: ')
                            if resp.upper() == 'Y':
                                self.hb_serial.hydrabus.close()
                                config = load_config()
                                config['HYDRABUS']['port'] = self.get_option_value("hydrabus")
                                miniterm(config=config)
                                # Run init_hb again to properly reset and close the hydrabus session
                                self.init_hb()
                                self.logger.handle("Please press hydrabus ubtn in order to return BBIO mode",
                                                   Logger.USER_INTERACT)
                                hb_wait_ubtn(self.hb_serial)
                                break
                            break
                    elif trigger and loop < 3:
                        loop += 1
                        self.trigger_device()
                        continue
                    else:
                        progress.stop()
                        self.logger.handle("Please press hydrabus ubtn in order to switch baudrate speed",
                                           Logger.USER_INTERACT)
                        hb_wait_ubtn(self.hb_serial)
                        break
            else:
                self.logger.handle("Please press hydrabus ubtn in order to switch baudrate speed", Logger.USER_INTERACT)
                hb_wait_ubtn(self.hb_serial)
                break

    def init_hb(self):
        try:
            device = self.get_option_value("hydrabus")
            timeout = int(self.get_option_value("timeout"))
            self.hb_serial = UART(device)
            self.hb_serial.timeout = timeout
            return True
        except serial.SerialException as err:
            self.logger.handle("{}".format(err), Logger.ERROR)
            return False

    def run(self):
        if self.init_hb():
            self.baudrate_detect()
            self.logger.handle("Reset hydrabus to console mode", Logger.INFO)
            self.hb_serial.hydrabus.exit_bbio()
            self.hb_serial.hydrabus.close()
        else:
            self.logger.handle("Unable to init hydrabus in UART mode, please try the 'reset' command", Logger.ERROR)
Esempio n. 8
0
class HydraFramework:
    """
    Framework core engine
    """
    def __init__(self):
        self.logger = Logger()
        self.app_path = sys.path[0]
        self.current_module = None
        self.current_module_name = None
        self.dispatcher = Dispatcher()
        self.modules = self._list_modules()
        self.modules_history = []
        self.config = load_config()
        self.completer_nested_dict = self._get_dict_completion()
        self.console_completer = NestedCompleter.from_nested_dict(
            self.completer_nested_dict)
        self.global_options = {}
        self.prompt_style = Style.from_dict({
            # User input (default text), no value = system default.
            '':
            self.config['THEME']['user_input'],

            # Prompt.
            'base':
            self.config['THEME']['base'],
            'pound':
            self.config['THEME']['pound'],
            'module':
            self.config['THEME']['module'],
            'category':
            self.config['THEME']['category'],
        })
        self.prompt = [
            ('class:base', '[hbf] '),
            ('class:module', ''),
            ('class:category', ''),
            ('class:pound', '> '),
        ]

    def update_prompt(self):
        """
        Update the user prompt.
        """
        if self.current_module_name is not None:
            category = self.current_module_name.split("/")[0]
            module = self.current_module_name.split("/")[1]
            self.prompt = [
                ('class:base', '[hbf] '),
                ('class:category', '{}'.format(category)),
                ('class:module', '({})'.format(module)),
                ('class:pound', '> '),
            ]
        else:
            self.prompt = [
                ('class:base', '[hbf] '),
                ('class:category', ''),
                ('class:module', ''),
                ('class:pound', '> '),
            ]

    def _get_dict_completion(self):
        """
        Get all command with associated arguments and return a dict for NestedCompleter.
        nested_dict = {
            'set': {
                'hydrabus': None,
                ...
            },
            'setc': {
                {
                    'section1': {
                        {key1: None},
                        {key2: None}
                    }
                }
            'exit': None
            'use': {
                {'module1': None},
                ...
            }
        }
        :return: nested dictionary
        """
        nested_completion_dict = {}
        modules_dict = {}
        config_dict = {}
        # Get all based command
        for command in self.dispatcher.commands:
            if len(command["arguments"]) == 0:
                nested_completion_dict.update({command["name"]: None})
            else:
                nested_completion_dict.update(
                    {command["name"]: command["arguments"]})
        # Append all loaded module to use command
        for module in self.modules:
            modules_dict.update({module["path"]: None})
        nested_completion_dict["use"] = modules_dict
        # Append all config section and key to setc command
        for section in self.config:
            if section != "DEFAULT":
                config_key_dict = {}
                config_dict.update({section: None})
                if len(self.config[section]) > 0:
                    for key in self.config[section]:
                        config_key_dict.update({key: None})
                    config_dict[section] = config_key_dict
        nested_completion_dict["setc"] = config_dict
        return nested_completion_dict

    def update_completer_options_list(self):
        """
        Update prompt completer options list when loading a new module.
        :return: Nothing
        """
        options = {}
        if isinstance(self.current_module, AModule):
            for option in self.current_module.options:
                options.update({option["Name"]: None})
        self.completer_nested_dict["set"] = options
        self.completer_nested_dict["unset"] = options
        self.console_completer = NestedCompleter.from_nested_dict(
            self.completer_nested_dict)

    def update_completer_global_options_list(self):
        """
        Update prompt completer global options list when loading a new module.
        :return: Nothing
        """
        options = {}
        for keys, _ in self.global_options.items():
            options.update({keys: None})
        self.completer_nested_dict["setg"] = options
        self.completer_nested_dict["unsetg"] = options
        self.console_completer = NestedCompleter.from_nested_dict(
            self.completer_nested_dict)

    def _list_modules(self):
        """
        Generate modules path and attributes list.
        :return: List of available modules
        """
        modules = []
        module_name = "hbfmodules"

        try:
            package = import_module(module_name)
        except ImportError:
            self.logger.handle(
                "Unable to find any modules, please run 'hbfupdate' "
                "script to install available modules...", Logger.ERROR)
        else:
            for loader, module, is_pkg in pkgutil.walk_packages(
                    package.__path__, prefix=package.__name__ + '.'):
                try:
                    imported_module = import_module(module)
                    for x in dir(imported_module):
                        obj = getattr(imported_module, x)
                        if inspect.isclass(obj) and issubclass(
                                obj, AModule) and obj is not AModule:
                            module_path = module.replace('hbfmodules.',
                                                         '').replace('.', '/')
                            modules.append({"path": module_path, "class": obj})
                except ImportError:
                    self.logger.handle(
                        'Error dynamically import package "{}"...'.format(
                            module), Logger.ERROR)
        self.logger.handle(
            "{} modules loaded, run 'hbfupdate' command to install the latest modules"
            .format(len(modules)), Logger.USER_INTERACT)
        return modules

    def run(self, file_script=None):
        """
        Main loop, waiting for user input.
        :return:
        """
        session = PromptSession()
        # This parts is used to automate test by passing file script
        if file_script is not None:
            file_script = Path(file_script)
            if file_script.is_file():
                with file_script.open() as f:
                    commands = f.readlines()
                for command in commands:
                    command = session.prompt(self.prompt,
                                             style=self.prompt_style,
                                             default=command.strip(),
                                             accept_default=True)
                    self.dispatcher.handle(self, command)
                    self.update_prompt()
            else:
                self.logger.handle("File does not exist or it is not a file",
                                   self.logger.ERROR)
        # Normal mode waiting for user_input
        while True:
            try:
                command = session.prompt(self.prompt,
                                         style=self.prompt_style,
                                         completer=self.console_completer,
                                         complete_while_typing=False)
                self.dispatcher.handle(self, command)
                self.update_prompt()
            except KeyboardInterrupt:
                self.logger.handle(
                    "Please use 'exit' command or ctrl+D key to properly quit the framework",
                    Logger.INFO)
            except EOFError:
                exit(0)
Esempio n. 9
0
def reset_hb(hbf_instance):
    """
    Return hydrabus into console mode.
    :param hbf_instance: Hydrabus framework instance (self).
    :return: Nothing.
    """
    logger = Logger()
    hydrabus_cfg = hbf_instance.config['HYDRABUS']
    if hydrabus_cfg['port'] is None or hydrabus_cfg['port'] == '-':
        logger.handle('port is not set on the configuration (setc command)',
                      Logger.ERROR)
    else:
        try:
            serial_instance = hb_connect(device=hydrabus_cfg['port'],
                                         baudrate=115200,
                                         timeout=1)
        except serial.SerialException as e:
            logger.handle(
                "could not open port {!r}: {}".format(hydrabus_cfg['port'], e),
                logger.ERROR)
            return
        except UserWarning as err:
            logger.handle("{}".format(err), Logger.ERROR)
            return
        if isinstance(serial_instance, serial.Serial):
            hb_reset(serial_instance)
            hb_close(serial_instance)
            logger.handle("Reset sequence successfully sent to Hydrabus...",
                          Logger.SUCCESS)
        else:
            logger.handle(
                "Unable to reset Hydrabus due to connection error...",
                Logger.ERROR)
Esempio n. 10
0
 def __init__(self):
     self.github_base_url = 'https://api.github.com'
     self.logger = Logger()
     self.not_updated = []
     self.to_update = []
     self.to_install = []
Esempio n. 11
0
class HBFUpdate:
    def __init__(self):
        self.github_base_url = 'https://api.github.com'
        self.logger = Logger()
        self.not_updated = []
        self.to_update = []
        self.to_install = []

    def _get_installed_modules(self):
        """
        Return a dict of currently installed module(s).
        :return: A dict of currently installed module(s) {'module_name': 'version', ...}.
        """
        module_name = "hbfmodules"
        installed_modules = {}
        try:
            package = import_module(module_name)
        except ImportError:
            self.logger.handle('No modules currently installed', Logger.ERROR)
            return installed_modules
        for loader, module, is_pkg in pkgutil.walk_packages(
                package.__path__, prefix=package.__name__ + '.'):
            try:
                imported_module = import_module(module)
                for x in dir(imported_module):
                    obj = getattr(imported_module, x)
                    if inspect.isclass(obj) and issubclass(
                            obj, AModule) and obj is not AModule:
                        installed_modules[
                            module] = pkg_resources.get_distribution(
                                module).version
            except ImportError:
                self.logger.handle(
                    'Error dynamically import package "{}"... Unable to update it'
                    .format(module), Logger.ERROR)
                self.not_updated.append(module)
        return installed_modules

    def _get_available_modules(self):
        """
        Return a dict of module that have a release on the hydrabus-framework organization.
        :return: A dict of available module {'module_name': 'version', ...}.
        """
        invalids = ['hbfmodules.skeleton', 'framework']
        modules = {}
        resp = requests.get('{}{}'.format(self.github_base_url,
                                          '/orgs/hydrabus-framework/repos'))
        if resp.status_code == 200:
            for pkg in resp.json():
                if pkg["name"] not in invalids:
                    module_release_url = self.github_base_url +\
                                         '/repos/hydrabus-framework/{}/releases/latest'.format(pkg["name"])
                    resp = requests.get(module_release_url)
                    if resp.status_code == 200:
                        modules[pkg["name"]] = resp.json()['tag_name']
        return modules

    def _get_latest_framework_version(self):
        """
        Return the latest release version of the Hydrabus framework.
        :return: string.
        """
        module_release_url = self.github_base_url + '/repos/hydrabus-framework/framework/releases/latest'
        resp = requests.get(module_release_url)
        if resp.status_code == 200:
            return resp.json()['tag_name']
        else:
            self.logger.handle(
                'Unable to get the latest framework released version',
                Logger.ERROR)
            return None

    def _get_latest_release_url(self, module_name):
        """
        Get the latest release URL of a module or framework.
        :param module_name: module name.
        :return: url or None if not found.
        """
        module_release_url = self.github_base_url + '/repos/hydrabus-framework/{}/releases/latest'.format(
            module_name)
        resp = requests.get(module_release_url)
        if resp.status_code == 200:
            return resp.json()["tarball_url"]
        else:
            self.logger.handle(
                f"Unable to retrieve latest release URL for module '{module_name}'",
                Logger.ERROR)
            return None

    @staticmethod
    def _get_filename_from_cd(cd):
        """
        Get filename from content-disposition.
        :param cd: Content-Disposition HTTP header.
        :return: filename from Content-Disposition or None
        """
        if not cd:
            return None
        fname = re.findall('filename=(.+)', cd)
        if len(fname) == 0:
            return None
        return fname[0]

    def _download_release(self, module_tarball_url, package_name):
        """
        Download the latest release of a module or framework.
        :param module_tarball_url: release URL.
        :param package_name: The package name downloaded (module or framework).
        :return: filename or None.
        """
        self.logger.handle("Downloading {}...".format(package_name))
        resp = requests.get(module_tarball_url, stream=True)
        if resp.status_code == 200:
            filename = '/tmp/hbfmodules/{}'.format(
                self._get_filename_from_cd(
                    resp.headers.get('content-disposition')))
            if not os.path.exists(os.path.dirname(filename)):
                try:
                    os.makedirs(os.path.dirname(filename))
                except OSError as exc:
                    if exc.errno != errno.EEXIST:
                        raise
            open(filename, 'wb').write(resp.content)
            return filename
        return None

    @staticmethod
    def _extract_tarball(filename):
        """
        Extract the specified tarball.
        :param filename: the tarball file path
        :return: Directory path of the extracted archive
        """
        tar = tarfile.open(filename)
        path = re.sub(r'\.tar.gz$', '', filename)
        setup_dir = '{}/{}'.format(path, tar.getmembers()[0].name)
        tar.extractall(path)
        tar.close()
        return setup_dir

    def _manage_install(self, package_name):
        """
        Manage the installation of the specified package (module or framework).
        :param package_name: The package name to install (module or framework).
        :return: Bool: True if successfully update, False otherwise.
        """
        release_tarball_url = self._get_latest_release_url(package_name)
        if release_tarball_url:
            filename = self._download_release(release_tarball_url,
                                              package_name)
            if filename:
                setup_dir = self._extract_tarball(filename)
                try:
                    return_code = subprocess.call(
                        ['python', 'setup.py', 'install'],
                        cwd=setup_dir,
                        stdout=subprocess.DEVNULL)
                    if return_code != 0:
                        return False
                    else:
                        self.logger.handle(
                            "'{}' successfully installed".format(package_name),
                            Logger.SUCCESS)
                        return True
                except:
                    self.logger.handle(
                        "The setup command are failed for the '{}' module".
                        format(package_name), Logger.ERROR)
                    traceback.print_exc()
                    return False
            else:
                self.logger.handle(
                    "Failed to download the latest release for the module '{}'"
                    .format(package_name), Logger.ERROR)
                return False
        else:
            return False

    def update(self, update_framework=None):
        """
        This script check all released Hydrabus Framework modules and compare it with currently installed modules.
        If an update is available, this script install it. Moreover, if a module is available and not installed, it will
        be installed.
        :param update_framework: if True check if a framework update is available.
        :return: Nothing
        """
        if update_framework:
            latest_release_version = self._get_latest_framework_version()
            if latest_release_version:
                if latest_release_version > pkg_resources.get_distribution(
                        'hydrabus_framework').version:
                    self.logger.handle(
                        'A new framework release is available, running update...',
                        Logger.INFO)
                    if not self._manage_install('framework'):
                        self.not_updated.append('framework')
                else:
                    self.logger.handle('Hydrabus framework is up-to-date',
                                       Logger.SUCCESS)
            else:
                self.not_updated.append('framework')
        available_modules = self._get_available_modules()
        installed_modules = self._get_installed_modules()
        for module, version in available_modules.items():
            installed_module_version = installed_modules.get(module, None)
            if installed_module_version is not None:
                if installed_module_version < version:
                    self.to_update.append(module)
            else:
                self.to_install.append(module)
        for module_name in self.to_update:
            self.logger.handle("Update module '{}'".format(module_name),
                               Logger.INFO)
            if not self._manage_install(module_name):
                self.not_updated.append(module_name)
        for module_name in self.to_install:
            self.logger.handle("Install module '{}'".format(module_name),
                               Logger.INFO)
            if not self._manage_install(module_name):
                self.not_updated.append(module_name)
        if len(self.not_updated) > 0:
            self.logger.handle(
                "Unable to update/install the following package:",
                Logger.ERROR)
            for module in self.not_updated:
                print(" - {}".format(module))
Esempio n. 12
0
class AModule(ABC):
    def __init__(self, hbf_config):
        self.name = None
        self.meta = {
            'name': '',
            'version': '',
            'description': '',
            'author': ''
        }
        self.logger = Logger()
        self.options = []
        self.config = hbf_config

    def __name__(self):
        """
        Simply return the module name
        :return: module name
        """
        return self.name

    def get_option_value(self, option_name):
        """
        Return the value of a specific option.
        :param option_name: The needed option name.
        :return: Value.
        """
        for option in self.options:
            if option["Name"] == option_name:
                return option["Value"]
        else:
            raise UserWarning(
                "Value {} not found in module options".format(option_name))

    def show_options(self):
        """
        Print available options for the module to user console.
        :return: Nothing.
        """
        formatted_options = []
        if len(self.options) > 0:
            self.print_meta()
            for option in self.options:
                if option["Default"] != "" and option["Value"] == "":
                    formatted_options.append({
                        'Name':
                        option["Name"],
                        'Value':
                        option["Default"],
                        'Required':
                        option["Required"],
                        'Description':
                        option["Description"]
                    })
                else:
                    formatted_options.append({
                        'Name':
                        option["Name"],
                        'Value':
                        option["Value"],
                        'Required':
                        option["Required"],
                        'Description':
                        option["Description"]
                    })
            self.logger.print_tabulate(formatted_options,
                                       headers={
                                           "Name": "Name",
                                           "Description": "Description",
                                           "Value": "Value",
                                           "Required": "Required"
                                       })

    def print_meta(self):
        """
        Print meta of the module (author, module name, description).
        :return: Nothing.
        """
        self.logger.handle('Author: {}'.format(self.meta['author']),
                           Logger.HEADER)
        self.logger.handle(
            'Module name: {}, version {}'.format(self.meta['name'],
                                                 self.meta['version']),
            Logger.HEADER)
        self.logger.handle('Description: {}'.format(self.meta['description']),
                           Logger.HEADER)

    @abstractmethod
    def run(self):
        """
        Main function.
        :return:
        """
        pass
Esempio n. 13
0
 def __init__(self):
     self.logger = Logger()