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}
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)
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())
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
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')
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
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
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')