def check_base_sections(config: configparser.RawConfigParser): edited = False try: for i in ['service', 'logging', "notify", 'tasklist']: try: if not config.has_section(i): print(f"ERROR: no section {i}") edited = write_section(i, default[i]) if i == 'tasklist': for taskName in ["disk_c", "app_log", "my_app", "my_http_server"]: write_section(taskName, default[taskName]) except Exception as e: print(e) continue if edited: print("WARNING: created new sections in config file. Restart me to apply them") sleep(3) raise SystemExit(1) except Exception as e: print(f"ERROR: Fail to create configuration file: {e}") sleep(3) raise SystemExit(1)
def verify_log_task(sec: str, parent: dict = None): try: if parent: if not parent['workDir']: if not parent['exePath']: raise Exception(f'not found parameter exePath in [{parent["task"]}]') else: path = parent['exePath'] else: path = parent['workDir'] if not path.endswith('/'): path = path + '/' cfg["tasks"]["logTask"][parent['task']] = tmp = {} tmp["file"] = config.get(sec, "file").replace('{{appDir}}', path) else: cfg["tasks"]["logTask"][sec] = tmp = {} tmp["file"] = config.get(sec, "file") tmp["tmpl"] = [i.strip() for i in config.get(sec, "templates").split(';')] except Exception as e: log.error(f"incorrect parameters in [{sec}]: {e}") sleep(3) raise SystemExit(1)
def get_svc_params() -> list: try: return [ config.get("service", "Name"), config.get("service", "DisplayName"), config.get("service", "Description")] except Exception as e: e = f"incorrect parameters in [Service]: {e}" if 'log' in locals(): log.error(e) else: print(e) sleep(3) raise SystemExit(1)
def open_config() -> configparser.RawConfigParser: try: open(f"{homeDir}{cfgFileName}", encoding='utf-8') except IOError: open(f"{homeDir}{cfgFileName}", 'tw', encoding='utf-8') config = configparser.RawConfigParser(allow_no_value=True) config = lowcase_sections(config) try: config.read(f"{homeDir}{cfgFileName}") except Exception as e: print(f"Fail to read configuration file: {e}") sleep(3) raise SystemExit(1) return config
def load_notifier(cfg: dict, log: logging.Logger) -> Notify: try: name = cfg["notify"]["type"] if name != '': log.info(f'Load notifier {name}') # TODO import * # but now for pyInstaller need like # import notifier.email # import notifier.discord # import notifier.slack # notifier = getattr(__import__(f'notifier.{name}'), name) # notify = notifier.Notify(name) # на случай упаковки в бинарник, но тогда нужно всю стандартную либу включать # dict_obj = {} with open(f'{homeDir}notifier/{name}.py', encoding='utf-8') as src: scrCode = src.read() a = globals() # exec(scrCode, globals(), dict_obj) # notify = dict_obj['Notify'](name) exec(scrCode, globals(), globals()) notify = a['Notify'](name) try: if not config.has_section(name): log.warning(f'Create new section {name}') if write_section(name, notify.defaultCfg): log.warning("created new sections in config file. Restart me to apply them") sleep(3) raise SystemExit(1) except Exception as e: log.error(f"Fail to load notify configuration: {e}") cfg["notify"][name] = notify.load_config(config, cfg['notify']['proxy']) return notify except ImportError: log.error(f'Fail import notifier: {name}: {traceback.format_exc()}') raise SystemExit(1) except AttributeError as e: log.error(f'Wrong notifier: {e}') raise SystemExit(1) except Exception: log.error(f'Fail load notifier: {traceback.format_exc()}') raise SystemExit(1)
def create_logger(config: configparser.RawConfigParser) -> (logging.Logger, logging.Logger, logging.StreamHandler): level = logging.INFO logSize = 10240 logCount = 5 try: if not config.getboolean("logging", "enable"): level = 0 else: logLevel = config.get("logging", "loglevel").lower() if logLevel == "full": level = logging.DEBUG logSize = config.getint("logging", "logmaxsizekbs") logCount = config.getint("logging", "logmaxfiles") except Exception as e: print("WARNING: Check parameters for Logging.", str(e)) sleep(3) raise SystemExit(1) log_formatter = logging.Formatter('%(asctime)s %(name)s %(levelname)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S') my_handler = RotatingFileHandler( f"{homeDir}logs/AppWatch.log", maxBytes=logSize * 1024, backupCount=logCount, encoding='utf-8') my_handler.setFormatter(log_formatter) console = logging.StreamHandler(stream=sys.stdout) # вывод в основной поток console.setFormatter(log_formatter) console.setLevel(level) # logging.getLogger('root').addHandler(console) log = logging.getLogger('AppWatch') log.addHandler(my_handler) log.setLevel(level) log.addHandler(console) # disable requests logging logging.getLogger('urllib3.connectionpool').setLevel(logging.CRITICAL) return log, console
def verify_scheduler() -> list: ls = [] try: active = config.getint('tasklist', "active") cfg["tasks"]["intervalCheckMin"] = config.getint('tasklist', "intervalCheckMin") * 60 log.info(f"Activated {active} tasks") if active <= 0: raise Exception('Schedule is enabled, but no one task is active') else: for n in range(1, active + 1): taskName = config.get('tasklist', str(n)) if not config.has_section(taskName): raise Exception(f'Not found task section {taskName}') else: ls.append(taskName) return ls except Exception as e: log.error(f"incorrect parameters in [tasklist]: {e}") sleep(3) raise SystemExit(1)
def __load_templates(self, log: logging.Logger): log.info(f"Load templates.cfg") try: _ = open(f"{homeDir}templates.cfg", encoding='utf-8') except IOError: open(f"{homeDir}templates.cfg", 'tw', encoding='utf-8') config2 = configparser.RawConfigParser(comment_prefixes=('#', ';', '//'), allow_no_value=True) try: config2.read(f"{homeDir}templates.cfg", encoding="utf-8") for s in config2.sections(): if s not in self._tmpl: self._tmpl[s] = {} for p, v in config2.items(s): self._tmpl[s][p] = v if len(self._tmpl) == 0: raise Exception("templates.cfg is empty") except Exception as e: print("Error to read configuration file:", str(traceback.format_exc())) sleep(3) raise SystemExit(1)
def verify_notify(): try: cfg["notify"]["localName"] = config.get("notify", "localName") cfg["notify"]["localIp"] = config.get("notify", "localIp") log.info("Local server is %s (%s)" % (cfg["notify"]["localIp"], cfg["notify"]["localName"])) except Exception as e: log.error(f"incorrect parameters in [notify]: {e}") sleep(3) raise SystemExit(1) try: cfg["notify"]["resendTime"] = config.getint("notify", "resendTimeoutM") cfg["notify"]["onlyChanges"] = config.getboolean("notify", "onlyChanges") cfg["notify"]["type"] = config.get("notify", "type").lower() if cfg["notify"]["type"].strip() == '': raise Exception(f'Wrong Notify type: {cfg["notify"]["type"]}') cfg["notify"]["useproxy"] = config.getboolean("notify", "useproxy") if cfg['notify']["useproxy"]: log.warning("Using proxy for notifier") if not config.has_section('proxy'): if write_section('proxy', default['proxy']): log.warning("created new sections in config file. Restart me to apply them") sleep(3) raise SystemExit(1) cfg['notify']['proxy'] = {'http': {}, 'https': {}} added = False for k in cfg['notify']['proxy']: if config.has_option('proxy', k): added = True cfg['notify']['proxy'][k] = config.get('proxy', k) if not added: raise Exception(f"Ebabled Proxy, but no one proxy added") except Exception as e: log.error("%s" % e) sleep(3) raise SystemExit(1)
def verify_tasks(taskList: list): for task in taskList: try: # disk tasks if config.has_option(task, 'disk'): cfg["tasks"]["diskTask"][task] = tmp = {} tmp["diskWarn"] = config.getint(task, "Warning") tmp["critFree"] = config.getint(task, "Critical") tmp["diskUsage"] = config.get(task, "disk") log.info(f'monitoring disk space: {tmp["diskUsage"]}') continue # log tasks if config.has_option(task, 'file'): verify_log_task(task) continue # process tasks jobListTmp = {} jobListTmp['task'] = task jobListTmp['exe'] = config.get(task, "exe") jobListTmp['doRestart'] = config.getboolean(task, "doRestart") jobListTmp['alwaysWork'] = config.getboolean(task, "alwaysWork") jobListTmp['restartTime'] = config.getint(task, "timeForRestartingSec") jobListTmp['whatStart'] = whatStart = config.get(task, "whatStart") if config.has_option(task, 'exePath'): jobListTmp['exePath'] = config.get(task, "exePath").replace('\\', '/', -1) if not jobListTmp['exePath'].endswith('/'): jobListTmp['exePath'] = jobListTmp['exePath'] + '/' else: jobListTmp['exePath'] = None if config.has_option(task, 'workdir'): jobListTmp['workDir'] = config.get(task, "workdir").replace('\\', '/', -1) if not jobListTmp['workDir'].endswith('/'): jobListTmp['workDir'] = jobListTmp['workDir'] + '/' jobListTmp['checkPath'] = jobListTmp['workDir'] else: jobListTmp['workDir'] = None jobListTmp['checkPath'] = jobListTmp['exePath'] if not config.has_option(task, 'exePath') and not config.has_option(task, 'workDir'): raise Exception("set any parameter: exePath, workDir ") if config.has_option(task, 'timeForResponse'): jobListTmp['respTime'] = config.getint(task, "timeForResponse") else: jobListTmp['respTime'] = 10 jobListTmp['checkUrl'] = config.getboolean(task, "checkUrl") if jobListTmp['checkUrl']: jobListTmp['url'] = config.get(task, "url") if whatStart == 'exe': if not config.has_option(task, 'exePath'): raise Exception("Used whatStart=exe, but no parameter exePath") if config.has_option(task, 'exeKey'): jobListTmp['exeKey'] = config.get(task, "exeKey") else: jobListTmp['exeKey'] = '' elif whatStart == 'command': jobListTmp['command'] = config.get(task, "command") elif whatStart == 'service': jobListTmp['service'] = config.get(task, "service") else: raise Exception('Wrong parameter whatStart. Allowed: exe, command, service') if config.has_option(task, 'logInspector'): jobListTmp['logInspector'] = config.get(task, 'logInspector') verify_log_task(jobListTmp['logInspector'], jobListTmp) cfg["tasks"]["jobList"][task] = jobListTmp except Exception as e: log.error(f"incorrect parameters in [{task}]: {e}") sleep(3) raise SystemExit(1)
raise Exception(f"No script {fileName}. Try to set full path.") except AttributeError as e: raise Exception(f'Wrong script: {e}') except Exception as e: raise Exception(f'Fail import script: {e}') for sec in ['diskTask', 'logTask', 'jobList']: for k, v in cfg['tasks'][sec].items(): if config.has_option(k, 'eventScript'): scriptName = config.get(k, 'eventScript') log.info(f"loading script {scriptName} ({k})") v['eventScript'] = load_script(scriptName) return cfg if __name__ != "__main__": try: create_dirs([f"{homeDir}{'logs'}"]) except Exception as e: print(e) sleep(3) raise SystemExit(-1) config = open_config() check_base_sections(config) log, console = create_logger(config) cfg = verify_config(config, log) cfg = load_event_scripts(cfg) templater = Templater(log) notify = load_notifier(cfg, log)