def family_case(): """ case block as a family example """ return ( Family("case_var").add( Task("case").add( Defstatus("complete"), Edit(VAR=1)), Task("when_1").add( Trigger("case:VAR == 1"), Complete("case:VAR != 1")), Task("when_2").add( Trigger("case:VAR eq 2"), Complete("case:VAR ne 2"))), Family("case_meter").add( Task("case").add( Meter("STEP", -1, 48)), Task("when_1").add( Trigger("case:STEP eq 1"), Complete("case==complete")), Task("when_2").add( Trigger("case:STEP eq 2"), Complete("case eq complete"))))
def process(): """ provide 'daily' example family """ return (Family("process").add( Trigger("process ne aborted"), # STOP ASAP Family("daily").add( Task("simple"), Repeat("YMD", 20180101, 20321212, kind="date"), Family("decade").add(Task("simple"), Label("info", "Show-Icons-Complete"), Complete("../daily:YMD % 10 ne 0"))), Family("monthly").add( Task("simple"), Trigger("monthly:YM lt daily:YMD / 100 or daily eq complete"), Repeat(kind="enum", name="YM", start=[ "%d" % YM for YM in range(201801, 203212 + 1) if (YM % 100) < 13 and (YM % 100) != 0 ]), Family("odd").add(Task("simple"), Complete("../monthly:YM % 2 eq 0"))), Family("yearly").add( Task("simple"), Repeat("Y", 2018, 2032, kind="integer"), Trigger("yearly:Y lt daily:YMD / 10000 or daily eq complete"), Family("decade").add(Task("simple"), Complete("(../yearly:Y % 10) ne 0")), Family("century").add(Task("simple"), Complete("(../yearly:Y % 100) ne 0")))))
def create(name=os.getenv("SUITE", "elearning")): return Suite(name).add( Defstatus("suspended"), # start immediately or not for this demo Clock("real"), Edit(ECF_INCLUDE=HOME, # header files ECF_FILES=HOME, # script template .ecf ECF_HOME=HOME), # job + local output files Family("f1").add( Task("t1").add( Event(1), Label("info", ""), Meter("step", -1, 100)), Task("t2").add( Late("-c 01:00"), Meter("step", -1, 100), Event("a"), Event("b"), Trigger("t1:step gt 0")), Task("t3").add( Trigger("t2:a")), Task("t4").add( Complete("t2:b"), Trigger("t2 eq complete and not t2:b"))), Family("f2").add( Task("t1").add( Time("00:30 23:30 00:30")), Task("t2").add( Day("sunday")), Task("t3").add( Time("12:00"), Date("1.*.*")), Task("t4").add( Time("+00:02")), Task("t5").add( Time("00:02"))))
def family_limiter(): """ alternative example """ return ( Family("limiter").add( Limit("total", 10), Inlimit("total"), Task("alarm").add( Complete("limits eq complete"), Trigger("../limiter:total gt 8")), # relative path Family("limits").add( Defstatus("complete"), Family("weaker").add( # weaker is located above, not to be shadowed Trigger("../limiter:total le 10"), [Family("%03d" % step).add( Task("process"), Variables(STEP=step)) for step in range(0, 120, 3)]), Family("prio").add( # favourite shall not lead weaker to starve Trigger("../limiter:total le 15"), [Family("%03d" % step).add( Task("process"), Variables(STEP=step)) for step in range(0, 120, 3)]))))
def create(name): """ suite provider """ return Suite(name).add( Defstatus("suspended"), Edit(ECF_INCLUDE=HOME, # header files ECF_FILES=HOME, # script template .ecf ECF_HOME=HOME), # job + local output files Family("f1").add( Task("t1").add( Label("info", ""), Late("-c 01:00"), Meter("step", -1, 100)), Task("t2").add( Meter("step", -1, 100), Event("a"), Event("b"), Trigger("t1:step gt 0")), Task("t3").add( Trigger("t2:a")), Task("t4").add( Complete("t2:b"), Trigger("t2 eq complete and not t2:b"))), Family("f2").add( Task("t1").add( Time("00:30 23:30 00:30")), Task("t2").add( Day("sunday")), Task("t3").add( Time("12:00"), Date("1.*.*")), Task("t4").add( Time("+00:02")), Task("t5").add( Time("00:02"))))
def family_if(): """ if block as a family example """ return ( Family("if_then_else").add( Task("if").add(Event(1)), Task("then").add(Trigger("if:1"), Complete("if==complete and not if:1")), Task("else").add(Complete("if:1"), Trigger("if eq complete and not if:1"))), Family("if").add( # one script Task("model").add(Event(1))), Family("then").add(Trigger("if/model:1"), Complete("if eq complete and not if/model:1"), Task("model")), Family("else").add(Complete("if/model:1"), Trigger("if eq complete and not if/model:1"), Task("model")))
acq = "acquisition" deploy("echo acq %TASK%", files + acq + extn) # create wrapper post = "postproc" deploy("ecflow_client --label info %TASK%", files + post + extn) suite = Suite("course").add( Defstatus("suspended"), Repeat("YMD", 20180101, 20321212, kind="date"), Variables(ECF_HOME=home, # jobs files are created there by ecflow ECF_FILES=home + "/files", # task-wrappers location ECF_INCLUDE=home + "/include", # include files location # ECF_OUT=home, # output files location on remote systems, # no directory created there by ecflow... ECF_EXTN=extn, ), # task wrapper extension Task(acq).add(Event(1)), Family("ensemble").add( # ENS Complete(acq + ":1"), [Family("%02d" % num).add( Variables(ID=num), model(360, dependencies="../../" + acq)) # relative path... for num in xrange(0, 10)]), model(240, dependencies=acq), # HRES Task(post).add( Trigger("model eq complete"), Label("info", ""))) ##################################################################### head = """#!/bin/bash set -e # stop the shell on first error set -u # fail when using an undefined variable set -x # echo script lines as they are executed
from ecf import (Defstatus, Suite, Family, Task, Variables, Trigger, Event, Complete) ECF_HOME = os.path.join(os.getenv("HOME"), "ecflow_server") NAME = os.getenv("SUITE", "elearning") DEFS = ecflow.Defs() DEFS.add( # suite definition Suite(NAME).add( Defstatus("suspended"), # so that jobs do not start immediately Variables( # add multiple variables at once: ECF_HOME=ECF_HOME, # where job files are created by ecflow ECF_FILES=ECF_HOME + "/files", # where to find script template ECF_INCLUDE=ECF_HOME + "/include", # where to find head.h tail.h SLEEP=5), Family("f1").add( Task("t1"), Task("t2").add(Trigger("t1 eq complete"), Event("a"), Event("1")), Task("t3").add(Trigger("t2:a")), Task("t4").add( Complete("t2:1"), Trigger("t2 eq complete"), )))) if __name__ == '__main__': HOST = os.getenv("ECF_HOST", "localhost") PORT = int(os.getenv("ECF_PORT", "%d" % (1500 + os.getuid()))) CLIENT = ecflow.Client(HOST, PORT) NODE = "/" + NAME # replace top CLIENT.replace(NODE, DEFS) print("replaced node %s into" % NODE, HOST, PORT)