Exemple #1
0
    def _connect(self):
        url = self._get_http_ipmi_host() + self.URL_LOGIN

        cookies = self._get_console_cookies()
        headers = self._get_console_headers()
        data = self._get_console_data()

        self._session = requests.session()

        for count in range(5):
            text = self._post(url, data, cookies, headers).text
            parsed, retryable = self._parse_response(text)
            if not parsed and retryable and count < 4:
                log.info('Will retry after {} seconds'.format(count))
                time.sleep(count)
            else:
                break

        if not parsed:
            log.error('Failed to create session')
            sys.exit(10)

        session_token = parsed[0]['SESSION_COOKIE']
        if session_token == 'Failure_Session_Creation':
            log.error('Probably reached session limit')
            sys.exit(10)

        CSRF_token = parsed[0]['CSRFTOKEN']

        self.session_token = {'SessionCookie': session_token}
        self.CSRF_token = {'CSRFTOKEN': CSRF_token}
Exemple #2
0
def get_config(config_path):
    try:
        extra_paths = []
        if os.getenv('SNAP_COMMON'):
            extra_paths.extend([os.path.expandvars('$SNAP_COMMON/bmcmanager')])

        if os.getenv('XDG_CONFIG_HOME'):
            extra_paths.extend([
                os.path.expandvars('$XDG_CONFIG_HOME/.config/bmcmanager'),
                os.path.expandvars('$XDG_CONFIG_HOME/bmcmanager')
            ])

        config = configparser.ConfigParser()
        which = config.read([
            config_path,
            os.getenv('BMCMANAGER_CONFIG', ''),
            os.path.expanduser('~/.config/bmcmanager'),
            '/etc/bmcmanager',
            *extra_paths,
        ])

        log.debug('Loaded config from {}'.format(which))

    except configparser.ParsingError as e:
        log.error('Invalid configuration file: {}'.format(e))
        sys.exit(1)

    return format_config(config)
Exemple #3
0
    def take_action(self, parsed_args):
        try:
            fetcher = firmware_fetchers[parsed_args.model]

        except KeyError as e:
            log.error('Unsupported device type: {}'.format(e))
            sys.exit(-1)

        result, _ = fetcher().get()

        new_firmware = []
        for item in result:
            if item['date'] > parsed_args.after:
                new_firmware.append('- {} / {} / {} / {}'.format(
                    item['date'],
                    item['component'],
                    item['version'],
                    item['name'],
                ))

        if new_firmware:
            state = nagios.CRITICAL
            msg = '{} new firmware version releases since {}'.format(
                len(new_firmware), parsed_args.after)
        else:
            state = nagios.OK
            msg = 'No new firmware version releases since {}'.format(
                parsed_args.after)

        nagios.result(state, msg, lines=new_firmware, pre='Firmware Versions')

        sys.exit(exitcode.get())
Exemple #4
0
    def _get_ipmi_address(self):
        args = self.parsed_args
        regex = {
            'ipv4': r'^IP Address\s*:\s*(?P<addr>\d+(\.\d+){3})',
            'mac':
            r'MAC Address\s*:\s*(?P<addr>[a-f0-9]{2}(\:[a-f0-9]{2}){5})',
        }.get(args.address_type)

        if regex is None:
            log.error('Unknown address type: {}'.format(args.address_type))
            return ''

        stdout = self._execute(['lan', 'print'], output=True)

        m = next(re.finditer(regex, stdout, re.MULTILINE), None)
        if m is None:
            log.error('No IPMI address found')
            return

        addr = m.group('addr')
        if args.address_type == 'mac':
            addr = addr.replace(':', '').upper()
            if args.domain:
                addr = '{}.{}'.format(addr, args.domain.lstrip('.'))
        if args.scheme:
            addr = '{}://{}'.format(args.scheme, addr)

        return addr
Exemple #5
0
    def refresh_firmware(self):
        custom_fields = {}
        firmwares = self._get_image_info()

        psus = []
        for firmware in firmwares:
            device_id = DEV_ID[firmware['DEV_TYPE']]
            version = firmware['CURIMG_VER']
            if device_id == 'BIOS':
                custom_fields['BIOS'] = version
            elif device_id == 'TSM':
                custom_fields['TSM'] = version
            elif device_id == 'PSU':
                psus.append('{}/{}: {}'.format(firmware['SLOT_NO'],
                                               firmware['DEV_IDENTIFIER'],
                                               version))

        custom_fields['PSU'] = ', '.join(sorted(psus))

        log.info('Patching custom fields: {}'.format(custom_fields))
        if not self.dcim.set_custom_fields(self.oob_info, custom_fields):
            log.error('Failed to refresh DCIM firmware versions')
Exemple #6
0
    def get(self):
        url = LENOVO_URL.format(self.model_name, self.device_name)
        try:
            log.debug('GET {}'.format(url))
            response = json.loads(urllib.request.urlopen(url).read())
            items = response['body']['DownloadItems']
        except (json.JSONDecodeError, urllib.error.URLError) as e:
            log.error('Could not fetch URL: {}'.format(e))
            return {}, []
        except KeyError as e:
            log.error('Invalid data format: {}'.format(e))
            return {}, []

        tracked_firmware = {**TRACKED_FIRMWARE, **self.extra_firmware}

        result = []
        downloads = []
        for item in items:
            try:
                component = tracked_firmware.get(item['Title'])
                if component is None:
                    continue

                fw = next(filter(
                    lambda f: f['TypeString'] != 'TXT README', item['Files']))

                downloads.append(fw['URL'])

                timestamp = datetime.fromtimestamp(fw['Date']['Unix'] / 1000)
                result.append({
                    'component': component,
                    'name': item['Title'],
                    'version': item['SummaryInfo']['Version'],
                    'date': str(timestamp),
                    'file': fw['URL'],
                })

            except ValueError as e:
                log.error('Invalid data format: {}'.format(e))

            except KeyError as e:
                log.error('Missing information: {}'.format(e))

        return result, downloads
Exemple #7
0
    def take_action(self, parsed_args):
        try:
            fetcher = firmware_fetchers[parsed_args.model]

        except KeyError as e:
            log.error('Unsupported device type: {}'.format(e))
            sys.exit(-1)

        result, downloads = fetcher().get()

        columns = ['component', 'name', 'version', 'date']
        values = [[item[col] for col in columns] for item in result]

        if parsed_args.download_to is None:
            return columns, values

        try:
            os.makedirs(parsed_args.download_to, exist_ok=True)
        except OSError as e:
            log.error('Could not create download directory: {}'.format(e))
            sys.exit(-1)

        for url in downloads:
            name = url[url.rfind('/') + 1:]
            file_name = os.path.join(parsed_args.download_to, name)
            log.info('Downloading {} to {}'.format(url, file_name))
            try:
                with open(file_name, 'wb') as fout:
                    fout.write(urllib.request.urlopen(url).read())
            except (urllib.error.URLError, OSError) as e:
                log.error('Failed: {}'.format(e))

            if parsed_args.innoextract and name.endswith('.exe'):
                log.info('Extracting with innoextract')
                self._execute_cmd(
                    ['innoextract', file_name, '-d', parsed_args.download_to])

        return columns, values
Exemple #8
0
 def refresh_ipmi_address(self):
     addr = self._get_ipmi_address()
     custom_fields = {'IPMI': addr}
     log.info('Patching custom fields: {}'.format(custom_fields))
     if not self.dcim.set_custom_fields(self.oob_info, custom_fields):
         log.error('Failed to refresh IPMI')