FEAT: added rerunTrigger to tasks

master 3.7.2.3
idziubenko 2 years ago
parent 5db585b43c
commit e6092b6edb

@ -17,6 +17,9 @@ from calculate.lib.datavars import DataVars
import calculate.contrib
from spyne import Service
class RerunTrigger(Exception):
pass
class CoreServiceInterface():
########
# Fields

@ -26,7 +26,7 @@ from os import path
import glob
import traceback
from traceback import print_exc
from .core_interfaces import (CoreServiceInterface, MethodsInterface)
from .core_interfaces import CoreServiceInterface, MethodsInterface, RerunTrigger
from calculate.install.distr import Distributive
from calculate.lib.cl_log import log
from calculate.lib.utils.colortext import convert_console_to_xml
@ -398,7 +398,7 @@ class Action(MethodsInterface):
# список исключений, которые выводятся в сокращенном формате
# (ожидаемые ошибки)
# остальные выводятся с именем модуля и номером строки
native_error = ()
native_error = None
# сообщение об удачном завершении действия
successMessage = None
@ -573,34 +573,42 @@ class Action(MethodsInterface):
return print_func, self.formatMessage(self.clVars, action[field])
return None, None
def get_tasks(self, tasks, result, all_result):
class TaskGenerator():
"""
Герератор задач (поддержка линейной обработки задач в группах)
"""
for task in tasks:
if "group" in task or "tasks" in task:
if all(self.get_condition_context(task, result,
all_result).values()):
self.group_name = task.get("group", "")
if "while" in task:
depend = task.get("while", [])
depend = (depend
if type(depend) in (list, tuple) else [depend])
depend.append(~Tasks.has_any("interrupt"))
while all([x(result, all_result) for x in depend]):
for action in self.get_tasks(task["tasks"],
result, all_result):
def __init__(self, parent) -> None:
self.parent = parent
def get_tasks(self, tasks, result, all_result):
for task in tasks:
if "group" in task or "tasks" in task:
if all(self.parent.get_condition_context(task, result,
all_result).values()):
self.parent.group_name = task.get("group", "")
if "while" in task:
depend = task.get("while", [])
depend = (depend
if type(depend) in (list, tuple) else [depend])
depend.append(~Tasks.has_any("interrupt"))
while all([x(result, all_result) for x in depend]):
for action in self.get_tasks(task["tasks"],
result, all_result):
yield action
else:
for action in self.get_tasks(task["tasks"], result,
all_result):
yield action
else:
for action in self.get_tasks(task["tasks"], result,
all_result):
yield action
if not self.group_name:
self.endGroup()
else:
self.group_name = ""
else:
yield task
if not self.parent.group_name:
self.parent.endGroup()
else:
self.parent.group_name = ""
else:
yield task
def make_task_generator(self):
return self.TaskGenerator(self)
def get_condition_context(self, action, result, all_result):
"""
@ -640,9 +648,6 @@ class Action(MethodsInterface):
def info(self, s):
pass
result = {}
all_result = {}
self.group_name = ""
self.clVars = dv
if dv.Get('cl_env_debug_set') == 'off' or \
@ -658,171 +663,195 @@ class Action(MethodsInterface):
obj.clVars = dv
if hasattr(obj, "init"):
obj.init()
try:
self.beginFrame()
logger.info("Start {methodname}".format(
methodname=self.method_name))
for action in self.get_tasks(self.tasks, result, all_result):
foreach = action.get("foreach", "")
if foreach:
foreach = self.clVars.Get(foreach)
else:
foreach = [""]
self.eachvar = ""
for eachvar in foreach:
self.eachvar = eachvar
group, op, name = action.get("name",
"<unknown>").rpartition(':')
res = True
task = False
self.clVars.Set('cl_task_name', name, force=True)
try:
run_context = self.get_condition_context(action, result,
all_result)
actinfo = "Run" if all(run_context.values()) else "Skip"
logger.info(
"{action} {name}: condition: {condition}, "
"depend: {depend}".format(
action=actinfo,
name=name,
condition=run_context['condition'],
depend=run_context['depend']))
elsePrint, elseMessage = (
self.getFormatMessage(action, "else_error",
"else_warning",
"else_message"))
if (run_context['depend'] and
not run_context['condition'] and elseMessage):
if "else_error" in action:
all_result[name] = False
if action.get("essential", True):
result[name] = False
elsePrint(elseMessage)
if all(run_context.values()):
self.writeFile()
if self.group_name:
self.startGroup(str(self.group_name))
self.group_name = None
printFunc, message = self.getFormatMessage(
action, "error", "warning", "message")
if "confirm" in action and message:
all_result[name] = \
self.askConfirm(str(message),
action["confirm"])
result[name] = all_result[name]
continue
elif message:
# если действие с командой
if ("error" not in action and
"method" in action or
"command" in action):
self.startTask(str(message))
task = True
# действие содержит только сообщение
else:
if "error" in action:
rerun = True
skip_strings = []
while rerun:
result = {}
all_result = {}
rerun = False
tg = self.make_task_generator()
try:
self.beginFrame()
logger.info("Start {methodname}".format(
methodname=self.method_name))
for action in tg.get_tasks(self.tasks, result, all_result):
foreach = action.get("foreach", "")
if foreach:
foreach = self.clVars.Get(foreach)
else:
foreach = [""]
self.eachvar = ""
for eachvar in foreach:
self.eachvar = eachvar
group, op, name = action.get("name",
"<unknown>").rpartition(':')
res = True
task = False
self.clVars.Set('cl_task_name', name, force=True)
try:
run_context = self.get_condition_context(action, result,
all_result)
actinfo = "Run" if all(run_context.values()) else "Skip"
logger.info(
"{action} {name}: condition: {condition}, "
"depend: {depend}".format(
action=actinfo,
name=name,
condition=run_context['condition'],
depend=run_context['depend']))
elsePrint, elseMessage = (
self.getFormatMessage(action, "else_error",
"else_warning",
"else_message"))
if (run_context['depend'] and
not run_context['condition'] and elseMessage):
if "else_error" in action:
all_result[name] = False
if action.get("essential", True):
result[name] = False
elsePrint(elseMessage)
if all(run_context.values()):
self.writeFile()
if self.group_name:
if not(len(skip_strings) >= 0\
and self.group_name.s\
and self.group_name.s\
in skip_strings):
self.startGroup(str(self.group_name))
self.group_name = None
printFunc, message = self.getFormatMessage(
action, "error", "warning", "message")
if "confirm" in action and message:
all_result[name] = \
self.askConfirm(str(message),
action["confirm"])
result[name] = all_result[name]
continue
elif message:
# если действие с командой
if ("error" not in action and
"method" in action or
"command" in action):
self.startTask(str(message))
task = True
# действие содержит только сообщение
else:
if "error" in action:
res = False
printFunc(message)
# запустить метод объекта
if "method" in action:
try:
method, args = self.parseMethod(
objs, dv, action["method"], name)
if "decoration" in action:
decfunc, decargs = self.parseMethod(
objs, dv, action["decoration"],
name)
method = decfunc(*decargs)(method)
res = method(*args)
if res is None:
res = False
except CriticalError as e:
self.printERROR(str(e))
self.endFrame()
return False
except RerunTrigger as e:
raise e
except self.native_error as e:
if action.get('essential', True):
printerror = self.printERROR
else:
printerror = self.printWARNING
if hasattr(e, "addon") and e.addon:
printerror(str(e.addon))
printerror(str(e))
res = False
printFunc(message)
# запустить метод объекта
if "method" in action:
try:
method, args = self.parseMethod(
objs, dv, action["method"], name)
if "decoration" in action:
decfunc, decargs = self.parseMethod(
objs, dv, action["decoration"],
name)
method = decfunc(*decargs)(method)
res = method(*args)
if res is None:
except Exception:
error = shortTraceback(*sys.exc_info())
self.printERROR(error)
res = False
except CriticalError as e:
self.printERROR(str(e))
self.endFrame()
return False
except self.native_error as e:
if action.get('essential', True):
printerror = self.printERROR
else:
printerror = self.printWARNING
if hasattr(e, "addon") and e.addon:
printerror(str(e.addon))
printerror(str(e))
res = False
except Exception:
error = shortTraceback(*sys.exc_info())
self.printERROR(error)
res = False
# запустить системную команду
if "command" in action:
hideout = action.get("hideout", False)
cmdParam = [x.strip('"\'') for x
in re.findall('["\'][^"\']+["\']|\S+', action["command"])]
cmd = processProgress(*cmdParam)
for line in cmd.progress():
if not hideout:
self.printSUCCESS(line)
if cmd.failed():
lineCmd = cmd.pipe.stderr.read().split('\n')
for line in (x for x in lineCmd if x):
self.printERROR(line)
res = cmd.success()
all_result[name] = res
# запустить системную команду
if "command" in action:
hideout = action.get("hideout", False)
cmdParam = [x.strip('"\'') for x
in re.findall('["\'][^"\']+["\']|\S+', action["command"])]
cmd = processProgress(*cmdParam)
for line in cmd.progress():
if not hideout:
self.printSUCCESS(line)
if cmd.failed():
lineCmd = cmd.pipe.stderr.read().split('\n')
for line in (x for x in lineCmd if x):
self.printERROR(line)
res = cmd.success()
all_result[name] = res
if action.get("essential", True):
result[name] = res
failedPrint, failedMessage = (
self.getFormatMessage(action, "failed_error",
"failed_warning",
"failed_message"))
if not res and failedPrint:
failedPrint(failedMessage)
if task and res in (True, False, "skip"):
self.endTask(res)
logger.info("{name}: Result is {result}".format(
name=name, result=res))
if res is True:
on_success = action.get('on_success', None)
if on_success:
on_success()
# else:
# print "[-] Skip ",name
except KeyboardInterrupt:
all_result[name] = False
if action.get("essential", True):
result[name] = res
failedPrint, failedMessage = (
self.getFormatMessage(action, "failed_error",
"failed_warning",
"failed_message"))
if not res and failedPrint:
failedPrint(failedMessage)
if task and res in (True, False, "skip"):
self.endTask(res)
logger.info("{name}: Result is {result}".format(
name=name, result=res))
if res is True:
on_success = action.get('on_success', None)
if on_success:
on_success()
# else:
# print "[-] Skip ",name
except KeyboardInterrupt:
all_result[name] = False
if action.get("essential", True):
result[name] = False
self.endTask(False)
self.printWARNING(_("Task interrupted"))
all_result["interrupt"] = False
result["interrupt"] = False
logger.info("{name}: Interrupeted".format(name=name))
except RerunTrigger as e:
self.endFrame()
raise e
except self.native_error as e:
if action.get('essential', True):
printerror = self.printERROR
else:
printerror = self.printWARNING
if hasattr(e, "addon") and e.addon:
printerror(str(e.addon))
printerror(str(e))
result[name] = False
self.endTask(False)
self.printWARNING(_("Task interrupted"))
all_result["interrupt"] = False
result["interrupt"] = False
logger.info("{name}: Interrupeted".format(name=name))
except self.native_error as e:
if action.get('essential', True):
printerror = self.printERROR
else:
printerror = self.printWARNING
if hasattr(e, "addon") and e.addon:
printerror(str(e.addon))
printerror(str(e))
result[name] = False
all_result[name] = False
logger.info("{name}: Native error".format(name=name))
except CriticalError as e:
self.printERROR(str(e))
self.endFrame()
return False
except BaseException as e:
result[name] = False
all_result[name] = False
error = shortTraceback(*sys.exc_info())
self.printERROR("%s:%s" % (name, error))
logger.info("{name}: Unknown exception {exp}".format(
name=name, exp=e.__class__.__name__))
finally:
dv.close()
self.endFrame()
if any(x in ("failed", "interrupt") for x in result):
return False
all_result[name] = False
logger.info("{name}: Native error".format(name=name))
except CriticalError as e:
self.printERROR(str(e))
self.endFrame()
return False
except BaseException as e:
result[name] = False
all_result[name] = False
error = shortTraceback(*sys.exc_info())
self.printERROR("%s:%s" % (name, error))
logger.info("{name}: Unknown exception {exp}".format(
name=name, exp=e.__class__.__name__))
except RerunTrigger as e:
self.printWARNING(str(e))
logger.info("{name}: rerun initiated".format(name=name))
rerun = True
#skips first group name
skip_strings = ["Repositories synchronization"]
finally:
dv.close()
self.endFrame()
if any(x in ("failed", "interrupt") for x in result):
return False
return True
# Never used. Why do we need it?
@ -1499,7 +1528,6 @@ class CoreWsdl(CoreServiceInterface):
def get_lang(cls, sid, method_name=""):
""" get clients lang """
lang = None
SIDS_DIR = cls.sids
with cls.sid_locker:

Loading…
Cancel
Save