目標:
弄清楚st2rulesengine服務原理
1和2的分析參見:
https://blog.csdn.net/qingyuanluofeng/article/details/105374863
3的分析參見:
https://blog.csdn.net/qingyuanluofeng/article/details/105374978
4 分析RulesEngine規則引擎
分析RulesEngine類對象的handle_trigger_instance方法
class RulesEngine(object):
def handle_trigger_instance(self, trigger_instance):
# Find matching rules for trigger instance.
matching_rules = self.get_matching_rules_for_trigger(trigger_instance)
if matching_rules:
# Create rule enforcers.
enforcers = self.create_rule_enforcers(trigger_instance, matching_rules)
# Enforce the rules.
self.enforce_rules(enforcers)
else:
LOG.info('No matching rules found for trigger instance %s.', trigger_instance['id'])
分析:
handle_trigger_instance(self, trigger_instance):
1 根據給定的trigger_instance,形如:
(Pdb) p trigger_instance
<TriggerInstanceDB: TriggerInstanceDB(id=5e79d4d58dc0dd00ea0f362f, occurrence_time="2020-03-24 09:31:27.463733+00:00", payload={'executed_at': '2020-03-24 09:17:33.887548+00:00', 'schedule': None}, status="processing", trigger="core.8c13d9a3-12a3-4cff-88d3-66c804a47590")>
2 調用get_matching_rules_for_trigger方法,獲得匹配的rule列表,具體是:
3 調用create_rule_enforcers(self, trigger_instance, matching_rules):
遍歷所有匹配的rule列表,對每個rule,實例化一個RuleEnforcer(trigger_instance, matching_rule)並加入
結果列表中,最後返回結果列表
4 調用enforce_rules(self, enforcers):
遍歷enforcers中每個enforcer,對每個enforcer,調用enforce方法,具體是
4.1) 分析get_matching_rules_for_trigger方法
class RulesEngine(object):
def get_matching_rules_for_trigger(self, trigger_instance):
trigger = trigger_instance.trigger
trigger_db = get_trigger_db_by_ref(trigger_instance.trigger)
if not trigger_db:
LOG.error('No matching trigger found in db for trigger instance %s.', trigger_instance)
return None
rules = get_rules_given_trigger(trigger=trigger)
LOG.info('Found %d rules defined for trigger %s', len(rules),
trigger_db.get_reference().ref)
if len(rules) < 1:
return rules
matcher = RulesMatcher(trigger_instance=trigger_instance,
trigger=trigger_db, rules=rules)
matching_rules = matcher.get_matching_rules()
LOG.info('Matched %s rule(s) for trigger_instance %s (trigger=%s)', len(matching_rules),
trigger_instance['id'], trigger_db.ref)
return matching_rules
分析:
get_matching_rules_for_trigger(self, trigger_instance):
1 根據給定trigger_instance中的trigger信息,形如:
(Pdb) p trigger
u'core.8c13d9a3-12a3-4cff-88d3-66c804a47590'
向trigger_d_b表查詢該trigger記錄
2 根據trigger記錄查詢到對應的rules。
原理: 由於特定的觸發器會在trigger表生成一條trigger記錄,包含ref字段。
而rule中會持有這個trigger的ref。所以通過trigger的ref可以查詢到對應的rule。
3 用trigger_instance,trigger,rules實例化一個RulesMatcher。
對rules列表處理,對每個rule根據trigger_instance,trigger等信息實例化RuleFileter對象, 調用其filter方法,
判斷其trigger_instance中的payload是否符合rule中criteria字典的校驗要求。返回匹配criteria的rules列表。
4.2) 分析enforce_rules(self, enforcers)方法
class RulesEngine(object):
def enforce_rules(self, enforcers):
for enforcer in enforcers:
try:
enforcer.enforce() # Should this happen in an eventlet pool?
except:
LOG.exception('Exception enforcing rule %s.', enforcer.rule)
分析:
遍歷enforcers中每個enforcer,對每個enforcer,調用enforce方法,
4.2.1) 調用RuleEnforcer的
class RuleEnforcer(object):
def __init__(self, trigger_instance, rule):
self.trigger_instance = trigger_instance
self.rule = rule
try:
self.data_transformer = get_transformer(trigger_instance.payload)
except Exception as e:
message = ('Failed to template-ize trigger payload: %s. If the payload contains '
'special characters such as "{{" which dont\'t reference value in '
'a datastore, those characters need to be escaped' % (str(e)))
raise ValueError(message)
def enforce(self):
rule_spec = {'ref': self.rule.ref, 'id': str(self.rule.id), 'uid': self.rule.uid}
enforcement_db = RuleEnforcementDB(trigger_instance_id=str(self.trigger_instance.id),
rule=rule_spec)
extra = {
'trigger_instance_db': self.trigger_instance,
'rule_db': self.rule
}
execution_db = None
try:
execution_db = self._do_enforce()
# pylint: disable=no-member
enforcement_db.execution_id = str(execution_db.id)
extra['execution_db'] = execution_db
except Exception as e:
# Record the failure reason in the RuleEnforcement.
enforcement_db.failure_reason = e.message
LOG.exception('Failed kicking off execution for rule %s.', self.rule, extra=extra)
finally:
self._update_enforcement(enforcement_db)
# pylint: disable=no-member
if not execution_db or execution_db.status not in EXEC_KICKED_OFF_STATES:
LOG.audit('Rule enforcement failed. Execution of Action %s failed. '
'TriggerInstance: %s and Rule: %s',
self.rule.action.ref, self.trigger_instance, self.rule,
extra=extra)
else:
LOG.audit('Rule enforced. Execution %s, TriggerInstance %s and Rule %s.',
execution_db, self.trigger_instance, self.rule, extra=extra)
return execution_db
分析:
enforce(self):
1 根據trigger_instance_id和 rule_spec具體是一個字典,實例化一個rule_enforcement_d_b
rule_spec 樣例:{'ref': self.rule.ref, 'id': str(self.rule.id), 'uid': self.rule.uid}
2 調用_do_enforce方法,具體是:
3 指定enforcement_db的execution_id爲execution對象的id,相當於做了關聯,然後更新rule_enforcement,
4 返回execution_db,樣例如下:
<ActionExecutionDB: ActionExecutionDB(action={'name': u'mistral-network-check', 'runner_type': u'mistral-v2', 'tags': [], 'description': u'Run network check script and output the result then send email.', 'enabled': True, 'entry_point': u'workflows/mistral-network-check.yaml', 'notify': {}, 'uid': u'action:email:mistral-network-check', 'parameters': {u'email_account': {u'default': u'esdozer', u'type': u'string'}, u'cmd': {u'required': True, u'type': u'string'}, u'email_to': {u'required': True, u'type': u'array'}, u'email_from': {u'type': u'string'}, u'timeout': {u'default': 1800, u'type': u'integer'}}, 'ref': u'email.mistral-network-check', 'id': '5e8067ae146db400130967e8', 'pack': u'email'}, children=[], context={'trigger_instance': {'id': '5e81d44bb99f2a002b34aeed', 'name': None}, 'trace_context': {'id_': '5e81d44bb99f2a002b34aeee', 'trace_tag': u'st2.IntervalTimer-ac7abf3a-9966-480a-8376-1b156bdbef56'}, 'rule': {'id': '5e8067b3146db4001309686c', 'name': u'network-check'}, 'user': '[email protected]'}, end_timestamp=None, id=5e81d44cb99f2a002b34aef0, liveaction={'callback': {}, 'runner_info': {}, 'parameters': {u'cmd': u'curl busybox:80/cmd/network/check.sh%20cn', u'email_to': [u'[email protected]'], u'email_from': u'[email protected]'}, 'action': u'email.mistral-network-check', 'action_is_workflow': True, 'id': '5e81d44cb99f2a002b34aeef'}, log=[{'status': 'requested', 'timestamp': datetime.datetime(2020, 3, 30, 11, 13, 16, 797752, tzinfo=tzutc())}], parameters={u'cmd': u'curl busybox:80/cmd/network/check.sh%20cn', u'email_to': [u'[email protected]'], u'email_from': u'[email protected]'}, parent=None, result={}, rule={'description': u'Check L3 vRouter & LB & DHCP', 'tags': [], 'ref': u'email.network-check', 'enabled': True, 'trigger': {'type': u'core.st2.IntervalTimer', 'ref': u'core.ac7abf3a-9966-480a-8376-1b156bdbef56', 'parameters': {u'unit': u'minutes', u'delta': 10}}, 'context': {}, 'criteria': {}, 'action': {'ref': u'email.mistral-network-check', 'parameters': {u'cmd': u'curl busybox:80/cmd/network/check.sh%20cn', u'email_to': [u'[email protected]'], u'email_from': u'[email protected]'}}, 'uid': u'rule:email:network-check', 'pack': u'email', 'type': {'ref': u'standard', 'parameters': {}}, 'id': '5e8067b3146db4001309686c', 'name': u'network-check'}, runner={'runner_module': u'mistral_v2', 'uid': u'runner_type:mistral-v2', 'name': u'mistral-v2', 'enabled': True, 'query_module': u'mistral_v2', 'runner_parameters': {u'skip_notify': {u'default': [], u'type': u'array', u'description': u'List of tasks to skip notifications for.'}, u'task': {u'type': u'string', u'description': u'The name of the task to run for reverse workflow.'}, u'context': {u'default': {}, u'type': u'object', u'description': u'Additional workflow inputs.'}, u'workflow': {u'type': u'string', u'description': u'The name of the workflow to run if the entry_point is a workbook of many workflows. The name should be in the format "<pack_name>.<action_name>.<workflow_name>". If entry point is a workflow or a workbook with a single workflow, the runner will identify the workflow automatically.'}}, 'id': '5e806772146db40013096339', 'description': u'A runner for executing mistral v2 workflow.'}, start_timestamp="2020-03-30 11:13:16.718857+00:00", status="requested", trigger={'uid': u'trigger:core:ac7abf3a-9966-480a-8376-1b156bdbef56:d561c05e470c37028940525af03d7eb5', 'parameters': {u'unit': u'minutes', u'delta': 10}, 'type': u'core.st2.IntervalTimer', 'pack': u'core', 'ref': u'core.ac7abf3a-9966-480a-8376-1b156bdbef56', 'id': '5e8160e028d08b002d5ecd0c', 'name': u'ac7abf3a-9966-480a-8376-1b156bdbef56'}, trigger_instance={'status': u'processing', 'occurrence_time': '2020-03-30T11:13:15.815000Z', 'trigger': u'core.ac7abf3a-9966-480a-8376-1b156bdbef56', 'id': '5e81d44bb99f2a002b34aeed', 'payload': {u'executed_at': u'2020-03-30 11:13:15.770559+00:00', u'schedule': None}}, trigger_type={'uid': u'trigger_type:core:st2.IntervalTimer', 'tags': [], 'parameters_schema': {u'additionalProperties': False, u'type': u'object', u'properties': {u'timezone': {u'type': u'string'}, u'unit': {u'enum': [u'weeks', u'days', u'hours', u'minutes', u'seconds'], u'required': True}, u'delta': {u'required': True, u'type': u'integer'}}}, 'name': u'st2.IntervalTimer', 'payload_schema': {u'type': u'object', u'properties': {u'executed_at': {u'default': u'2014-07-30 05:04:24.578325', u'type': u'string', u'format': u'date-time'}, u'schedule': {u'default': {u'units': u'seconds', u'delta': 30}, u'type': u'object'}}}, 'pack': u'core', 'ref': u'core.st2.IntervalTimer', 'id': '5e80674e4a20a500018b1713', 'description': u'Triggers on specified intervals. e.g. every 30s, 1week etc.'}, web_url="https://dozer-st2rulesengine-5b6cc5466-ttchq/#/history/5e81d44cb99f2a002b34aef0/general")>
4.2.2) 分析_do_enforce方法
class RuleEnforcer(object):
def _do_enforce(self):
params = self.get_resolved_parameters()
LOG.info('Invoking action %s for trigger_instance %s with params %s.',
self.rule.action.ref, self.trigger_instance.id,
json.dumps(params))
# update trace before invoking the action.
trace_context = self._update_trace()
LOG.debug('Updated trace %s with rule %s.', trace_context, self.rule.id)
context = {
'trigger_instance': reference.get_ref_from_model(self.trigger_instance),
'rule': reference.get_ref_from_model(self.rule),
'user': get_system_username(),
TRACE_CONTEXT: trace_context
}
return RuleEnforcer._invoke_action(self.rule.action, params, context)
分析:
_do_enforce(self):
1 獲取參數字典,形如:
{u'cmd': u'curl busybox:80/cmd/network/check.sh%20cn', u'email_to': [u'[email protected]'], u'email_from': u'[email protected]'}
2 調用 update_trace方法,具體是:
s1 調用get_trace_db_by_trigger_instance(trigger_instance=None, trigger_instance_id=None):
根據trigger_instance的id,調用_get_single_trace_by_component(**component_filter):
根據形如如下的參數:
{'trigger_instances__object_id': '5e79d4d58dc0dd00ea0f362f'}
向trace_d_b表查詢屬於該trigger_instance id的trace記錄,結果樣例如下:
<TraceDB: TraceDB(action_executions=[], id=5e79ec278dc0dd00ea0f3630, rules=[], start_timestamp="2020-03-24 11:09:19.309179+00:00", trace_tag="st2.IntervalTimer-8c13d9a3-12a3-4cff-88d3-66c804a47590", trigger_instances=[<TraceComponentDB: TraceComponentDB@(object_id:5e79d4d58dc0dd00ea0f362f, updated_at:2020-03-24 11:14:41.289695+00:00)>], uid="trace:aaa8de00c846febf51ac71bd86a776c9")>
s2 更新trace記錄,設置該trace記錄的rules爲形如如下的結果
[{'caused_by': {'type': 'trigger_instance', 'id': '5e79d4d58dc0dd00ea0f362f'}, 'ref': u'email.network-check', 'id': '5e660433c75b50001c06b822'}]
s3 返回TraceContext對象的字典
3 調用RuleEnforcer._invoke_action(self.rule.action, params, context)方法
4.2.3) 分析RuleEnforcer._invoke_action方法
class RuleEnforcer(object):
@staticmethod
def _invoke_action(action_exec_spec, params, context=None):
"""
Schedule an action execution.
:type action_exec_spec: :class:`ActionExecutionSpecDB`
:param params: Parameters to execute the action with.
:type params: ``dict``
:rtype: :class:`LiveActionDB` on successful schedueling, None otherwise.
"""
action_ref = action_exec_spec['ref']
# prior to shipping off the params cast them to the right type.
params = action_param_utils.cast_params(action_ref, params)
liveaction = LiveActionDB(action=action_ref, context=context, parameters=params)
liveaction, execution = action_service.request(liveaction)
return execution
分析:
_invoke_action(action_exec_spec, params, context=None):
1 根據輸入參數,樣例如下:
(Pdb) p action_exec_spec
<ActionExecutionSpecDB: ActionExecutionSpecDB@71113936(ref="email.mistral-network-check", parameters="{u'cmd': u'curl busybox:80/cmd/network/check.sh%20cn', u'email_to': [u'[email protected]'], u'email_from': u'[email protected]'}")>
(Pdb) p params
{u'cmd': u'curl busybox:80/cmd/network/check.sh%20cn', u'email_to': [u'[email protected]'], u'email_from': u'[email protected]'}
(Pdb) p context
{'trigger_instance': {'id': '5e79d4d58dc0dd00ea0f362f', 'name': None}, 'trace_context': {'id_': '5e79ec278dc0dd00ea0f3630', 'trace_tag': u'st2.IntervalTimer-8c13d9a3-12a3-4cff-88d3-66c804a47590'}, 'user': '[email protected]', 'rule': {'id': '5e660433c75b50001c06b822', 'name': u'network-check'}}
2 解析獲得參數字典,形如:
{u'cmd': u'curl busybox:80/cmd/network/check.sh%20cn', u'email_to': [u'[email protected]'], u'email_from': u'[email protected]'}
3 實例化一個LiveActionDB(action=action_ref, context=context, parameters=params)對象,形如:
<LiveActionDB: LiveActionDB(action="email.mistral-network-check", action_is_workflow=False, callback={}, context={'trigger_instance': {'id': '5e79d4d58dc0dd00ea0f362f', 'name': None}, 'trace_context': {'id_': '5e79ec278dc0dd00ea0f3630', 'trace_tag': u'st2.IntervalTimer-8c13d9a3-12a3-4cff-88d3-66c804a47590'}, 'rule': {'id': '5e660433c75b50001c06b822', 'name': u'network-check'}, 'user': '[email protected]'}, end_timestamp=None, id=None, notify=None, parameters={u'cmd': u'curl busybox:80/cmd/network/check.sh%20cn', u'email_to': [u'[email protected]'], u'email_from': u'[email protected]'}, result={}, runner_info={}, start_timestamp="2020-03-24 13:24:21.009098+00:00", status=None)>
4 調用/opt/stackstorm/st2/lib/python2.7/site-packages/st2common/services/action.py(155)request(liveaction)方法
4.2.4) 分析/opt/stackstorm/st2/lib/python2.7/site-packages/st2common/services/action.py的request(liveaction)方法
def request(liveaction):
liveaction, execution = create_request(liveaction)
liveaction, execution = publish_request(liveaction, execution)
return liveaction, execution
分析:
request(liveaction):
1 根據輸入參數liveaction,樣例如下:
<LiveActionDB: LiveActionDB(action="email.mistral-network-check", action_is_workflow=False, callback={}, context={'trigger_instance': {'id': '5e79d4d58dc0dd00ea0f362f', 'name': None}, 'trace_context': {'id_': '5e79ec278dc0dd00ea0f3630', 'trace_tag': u'st2.IntervalTimer-8c13d9a3-12a3-4cff-88d3-66c804a47590'}, 'rule': {'id': '5e660433c75b50001c06b822', 'name': u'network-check'}, 'user': '[email protected]'}, end_timestamp=None, id=None, notify=None, parameters={u'cmd': u'curl busybox:80/cmd/network/check.sh%20cn', u'email_to': [u'[email protected]'], u'email_from': u'[email protected]'}, result={}, runner_info={}, start_timestamp="2020-03-24 13:24:21.009098+00:00", status=None)>
2 調用 create_request(liveaction): 創建一個action的執行,返回(liveaction, execution)
3 調用 publish_request(liveaction, execution),具體是
4 返回: liveaction, execution
樣例如下:
(Pdb) p liveaction
<LiveActionDB: LiveActionDB(action="email.mistral-network-check", action_is_workflow=True, callback={}, context={'trigger_instance': {'id': '5e81d44bb99f2a002b34aeed', 'name': None}, 'trace_context': {'id_': '5e81d44bb99f2a002b34aeee', 'trace_tag': u'st2.IntervalTimer-ac7abf3a-9966-480a-8376-1b156bdbef56'}, 'rule': {'id': '5e8067b3146db4001309686c', 'name': u'network-check'}, 'user': '[email protected]'}, end_timestamp=None, id=5e81d44cb99f2a002b34aeef, notify=None, parameters={u'cmd': u'curl busybox:80/cmd/network/check.sh%20cn', u'email_to': [u'[email protected]'], u'email_from': u'[email protected]'}, result={}, runner_info={}, start_timestamp="2020-03-30 11:13:16.718857+00:00", status="requested")>
(Pdb) p execution
<ActionExecutionDB: ActionExecutionDB(action={'name': u'mistral-network-check', 'runner_type': u'mistral-v2', 'tags': [], 'description': u'Run network check script and output the result then send email.', 'enabled': True, 'entry_point': u'workflows/mistral-network-check.yaml', 'notify': {}, 'uid': u'action:email:mistral-network-check', 'parameters': {u'email_account': {u'default': u'esdozer', u'type': u'string'}, u'cmd': {u'required': True, u'type': u'string'}, u'email_to': {u'required': True, u'type': u'array'}, u'email_from': {u'type': u'string'}, u'timeout': {u'default': 1800, u'type': u'integer'}}, 'ref': u'email.mistral-network-check', 'id': '5e8067ae146db400130967e8', 'pack': u'email'}, children=[], context={'trigger_instance': {'id': '5e81d44bb99f2a002b34aeed', 'name': None}, 'trace_context': {'id_': '5e81d44bb99f2a002b34aeee', 'trace_tag': u'st2.IntervalTimer-ac7abf3a-9966-480a-8376-1b156bdbef56'}, 'rule': {'id': '5e8067b3146db4001309686c', 'name': u'network-check'}, 'user': '[email protected]'}, end_timestamp=None, id=5e81d44cb99f2a002b34aef0, liveaction={'callback': {}, 'runner_info': {}, 'parameters': {u'cmd': u'curl busybox:80/cmd/network/check.sh%20cn', u'email_to': [u'[email protected]'], u'email_from': u'[email protected]'}, 'action': u'email.mistral-network-check', 'action_is_workflow': True, 'id': '5e81d44cb99f2a002b34aeef'}, log=[{'status': 'requested', 'timestamp': datetime.datetime(2020, 3, 30, 11, 13, 16, 797752, tzinfo=tzutc())}], parameters={u'cmd': u'curl busybox:80/cmd/network/check.sh%20cn', u'email_to': [u'[email protected]'], u'email_from': u'[email protected]'}, parent=None, result={}, rule={'description': u'Check L3 vRouter & LB & DHCP', 'tags': [], 'ref': u'email.network-check', 'enabled': True, 'trigger': {'type': u'core.st2.IntervalTimer', 'ref': u'core.ac7abf3a-9966-480a-8376-1b156bdbef56', 'parameters': {u'unit': u'minutes', u'delta': 10}}, 'context': {}, 'criteria': {}, 'action': {'ref': u'email.mistral-network-check', 'parameters': {u'cmd': u'curl busybox:80/cmd/network/check.sh%20cn', u'email_to': [u'[email protected]'], u'email_from': u'[email protected]'}}, 'uid': u'rule:email:network-check', 'pack': u'email', 'type': {'ref': u'standard', 'parameters': {}}, 'id': '5e8067b3146db4001309686c', 'name': u'network-check'}, runner={'runner_module': u'mistral_v2', 'uid': u'runner_type:mistral-v2', 'name': u'mistral-v2', 'enabled': True, 'query_module': u'mistral_v2', 'runner_parameters': {u'skip_notify': {u'default': [], u'type': u'array', u'description': u'List of tasks to skip notifications for.'}, u'task': {u'type': u'string', u'description': u'The name of the task to run for reverse workflow.'}, u'context': {u'default': {}, u'type': u'object', u'description': u'Additional workflow inputs.'}, u'workflow': {u'type': u'string', u'description': u'The name of the workflow to run if the entry_point is a workbook of many workflows. The name should be in the format "<pack_name>.<action_name>.<workflow_name>". If entry point is a workflow or a workbook with a single workflow, the runner will identify the workflow automatically.'}}, 'id': '5e806772146db40013096339', 'description': u'A runner for executing mistral v2 workflow.'}, start_timestamp="2020-03-30 11:13:16.718857+00:00", status="requested", trigger={'uid': u'trigger:core:ac7abf3a-9966-480a-8376-1b156bdbef56:d561c05e470c37028940525af03d7eb5', 'parameters': {u'unit': u'minutes', u'delta': 10}, 'type': u'core.st2.IntervalTimer', 'pack': u'core', 'ref': u'core.ac7abf3a-9966-480a-8376-1b156bdbef56', 'id': '5e8160e028d08b002d5ecd0c', 'name': u'ac7abf3a-9966-480a-8376-1b156bdbef56'}, trigger_instance={'status': u'processing', 'occurrence_time': '2020-03-30T11:13:15.815000Z', 'trigger': u'core.ac7abf3a-9966-480a-8376-1b156bdbef56', 'id': '5e81d44bb99f2a002b34aeed', 'payload': {u'executed_at': u'2020-03-30 11:13:15.770559+00:00', u'schedule': None}}, trigger_type={'uid': u'trigger_type:core:st2.IntervalTimer', 'tags': [], 'parameters_schema': {u'additionalProperties': False, u'type': u'object', u'properties': {u'timezone': {u'type': u'string'}, u'unit': {u'enum': [u'weeks', u'days', u'hours', u'minutes', u'seconds'], u'required': True}, u'delta': {u'required': True, u'type': u'integer'}}}, 'name': u'st2.IntervalTimer', 'payload_schema': {u'type': u'object', u'properties': {u'executed_at': {u'default': u'2014-07-30 05:04:24.578325', u'type': u'string', u'format': u'date-time'}, u'schedule': {u'default': {u'units': u'seconds', u'delta': 30}, u'type': u'object'}}}, 'pack': u'core', 'ref': u'core.st2.IntervalTimer', 'id': '5e80674e4a20a500018b1713', 'description': u'Triggers on specified intervals. e.g. every 30s, 1week etc.'}, web_url="https://dozer-st2rulesengine-5b6cc5466-ttchq/#/history/5e81d44cb99f2a002b34aef0/general")>
4.2.5) 分析create_request(liveaction)方法
def create_request(liveaction):
"""
Create an action execution.
:return: (liveaction, execution)
:rtype: tuple
"""
# Use the user context from the parent action execution. Subtasks in a workflow
# action can be invoked by a system user and so we want to use the user context
# from the original workflow action.
parent_context = executions.get_parent_context(liveaction)
if parent_context:
parent_user = parent_context.get('user', None)
if parent_user:
liveaction.context['user'] = parent_user
# Validate action.
action_db = action_utils.get_action_by_ref(liveaction.action)
if not action_db:
raise ValueError('Action "%s" cannot be found.' % liveaction.action)
if not action_db.enabled:
raise ValueError('Unable to execute. Action "%s" is disabled.' % liveaction.action)
runnertype_db = action_utils.get_runnertype_by_name(action_db.runner_type['name'])
if not hasattr(liveaction, 'parameters'):
liveaction.parameters = dict()
# Validate action parameters.
schema = util_schema.get_schema_for_action_parameters(action_db)
validator = util_schema.get_validator()
util_schema.validate(liveaction.parameters, schema, validator, use_default=True,
allow_default_none=True)
# validate that no immutable params are being overriden. Although possible to
# ignore the override it is safer to inform the user to avoid surprises.
immutables = _get_immutable_params(action_db.parameters)
immutables.extend(_get_immutable_params(runnertype_db.runner_parameters))
overridden_immutables = [p for p in six.iterkeys(liveaction.parameters) if p in immutables]
if len(overridden_immutables) > 0:
raise ValueError('Override of immutable parameter(s) %s is unsupported.'
% str(overridden_immutables))
# Set notification settings for action.
# XXX: There are cases when we don't want notifications to be sent for a particular
# execution. So we should look at liveaction.parameters['notify']
# and not set liveaction.notify.
if not _is_notify_empty(action_db.notify):
liveaction.notify = action_db.notify
# Write to database and send to message queue.
liveaction.status = action_constants.LIVEACTION_STATUS_REQUESTED
liveaction.start_timestamp = date_utils.get_datetime_utc_now()
# Set the "action_is_workflow" attribute
liveaction.action_is_workflow = action_db.is_workflow()
# Publish creation after both liveaction and actionexecution are created.
liveaction = LiveAction.add_or_update(liveaction, publish=False)
# Get trace_db if it exists. This could throw. If it throws, we have to cleanup
# liveaction object so we don't see things in requested mode.
trace_db = None
try:
_, trace_db = trace_service.get_trace_db_by_live_action(liveaction)
except db_exc.StackStormDBObjectNotFoundError as e:
_cleanup_liveaction(liveaction)
raise trace_exc.TraceNotFoundException(str(e))
execution = executions.create_execution_object(liveaction, publish=False)
if trace_db:
trace_service.add_or_update_given_trace_db(
trace_db=trace_db,
action_executions=[
trace_service.get_trace_component_for_action_execution(execution, liveaction)
])
return liveaction, execution
分析:
create_request(liveaction): 創建一個action的執行,返回(liveaction, execution)
1 根據輸入參數liveaction,樣例如下:
<LiveActionDB: LiveActionDB(action="email.mistral-network-check", action_is_workflow=False, callback={}, context={'trigger_instance': {'id': '5e7abd778dc0dd0113f02625', 'name': None}, 'trace_context': {'id_': '5e7abd798dc0dd0113f02626', 'trace_tag': u'st2.IntervalTimer-8c13d9a3-12a3-4cff-88d3-66c804a47590'}, 'rule': {'id': '5e660433c75b50001c06b822', 'name': u'network-check'}, 'user': '[email protected]'}, end_timestamp=None, id=None, notify=None, parameters={u'cmd': u'curl busybox:80/cmd/network/check.sh%20cn', u'email_to': [u'[email protected]'], u'email_from': u'[email protected]'}, result={}, runner_info={}, start_timestamp="2020-03-25 02:10:02.048723+00:00", status=None)>
2 根據liveaction.action(例如: u'email.mistral-network-check'),查詢到對應action記錄,樣例如下:
<ActionDB: ActionDB(description="Run network check script and output the result then send email.", enabled=True, entry_point="workflows/mistral-network-check.yaml", id=5e660431c75b50001c06b807, name="mistral-network-check", notify=NotifySchema@74879184(on_complete="None", on_success="None", on_failure="None"), pack="email", parameters={u'email_account': {u'default': u'esdozer', u'type': u'string'}, u'cmd': {u'required': True, u'type': u'string'}, u'email_to': {u'required': True, u'type': u'array'}, u'email_from': {u'type': u'string'}, u'timeout': {u'default': 1800, u'type': u'integer'}}, ref="email.mistral-network-check", runner_type={u'name': u'mistral-v2'}, tags=[], uid="action:email:mistral-network-check")>
3 根據action_db.runner_type['name'] (例如: u'mistral-v2'),查詢到runnertype_db,樣例如下:
<RunnerTypeDB: RunnerTypeDB(description="A runner for executing mistral v2 workflow.", enabled=True, id=5e6603dcc75b50001c06b2ec, name="mistral-v2", query_module="mistral_v2", runner_module="mistral_v2", runner_parameters={u'skip_notify': {u'default': [], u'type': u'array', u'description': u'List of tasks to skip notifications for.'}, u'task': {u'type': u'string', u'description': u'The name of the task to run for reverse workflow.'}, u'context': {u'default': {}, u'type': u'object', u'description': u'Additional workflow inputs.'}, u'workflow': {u'type': u'string', u'description': u'The name of the workflow to run if the entry_point is a workbook of many workflows. The name should be in the format "<pack_name>.<action_name>.<workflow_name>". If entry point is a workflow or a workbook with a single workflow, the runner will identify the workflow automatically.'}}, uid="runner_type:mistral-v2")>
4 根據如下代碼來向live_action_d_b表添加或更新liveaction
liveaction = LiveAction.add_or_update(liveaction, publish=False)
返回結果樣例如下:
<LiveActionDB: LiveActionDB(action="email.mistral-network-check", action_is_workflow=True, callback={}, context={'trigger_instance': {'id': '5e7abd778dc0dd0113f02625', 'name': None}, 'trace_context': {'id_': '5e7abd798dc0dd0113f02626', 'trace_tag': u'st2.IntervalTimer-8c13d9a3-12a3-4cff-88d3-66c804a47590'}, 'rule': {'id': '5e660433c75b50001c06b822', 'name': u'network-check'}, 'user': '[email protected]'}, end_timestamp=None, id=5e7ac84b8dc0dd0113f02627, notify=None, parameters={u'cmd': u'curl busybox:80/cmd/network/check.sh%20cn', u'email_to': [u'[email protected]'], u'email_from': u'[email protected]'}, result={}, runner_info={}, start_timestamp="2020-03-25 02:52:07.783440+00:00", status="requested")>
5 獲取該liveaction的trace信息
6 調用create_execution_object方法來創建execution。具體如下:
create_execution_object(liveaction, publish=True):
s1 根據輸入參數,樣例如下:
(Pdb) p liveaction
<LiveActionDB: LiveActionDB(action="email.mistral-network-check", action_is_workflow=True, callback={}, context={'trigger_instance': {'id': '5e7abd778dc0dd0113f02625', 'name': None}, 'trace_context': {'id_': '5e7abd798dc0dd0113f02626', 'trace_tag': u'st2.IntervalTimer-8c13d9a3-12a3-4cff-88d3-66c804a47590'}, 'rule': {'id': '5e660433c75b50001c06b822', 'name': u'network-check'}, 'user': '[email protected]'}, end_timestamp=None, id=5e7ac84b8dc0dd0113f02627, notify=None, parameters={u'cmd': u'curl busybox:80/cmd/network/check.sh%20cn', u'email_to': [u'[email protected]'], u'email_from': u'[email protected]'}, result={}, runner_info={}, start_timestamp="2020-03-25 02:52:07.783440+00:00", status="requested")>
(Pdb) p publish
False
s2 根據liveaction.action(例如: u'email.mistral-network-check')查詢到action信息,樣例如下:
<ActionDB: ActionDB(description="Run network check script and output the result then send email.", enabled=True, entry_point="workflows/mistral-network-check.yaml", id=5e660431c75b50001c06b807, name="mistral-network-check", notify=NotifySchema@75062992(on_complete="None", on_success="None", on_failure="None"), pack="email", parameters={u'email_account': {u'default': u'esdozer', u'type': u'string'}, u'cmd': {u'required': True, u'type': u'string'}, u'email_to': {u'required': True, u'type': u'array'}, u'email_from': {u'type': u'string'}, u'timeout': {u'default': 1800, u'type': u'integer'}}, ref="email.mistral-network-check", runner_type={u'name': u'mistral-v2'}, tags=[], uid="action:email:mistral-network-check")>
s3 根據action_db.runner_type['name'](例如: u'mistral-v2')查詢到runner信息,樣例如下:
<RunnerTypeDB: RunnerTypeDB(description="A runner for executing mistral v2 workflow.", enabled=True, id=5e6603dcc75b50001c06b2ec, name="mistral-v2", query_module="mistral_v2", runner_module="mistral_v2", runner_parameters={u'skip_notify': {u'default': [], u'type': u'array', u'description': u'List of tasks to skip notifications for.'}, u'task': {u'type': u'string', u'description': u'The name of the task to run for reverse workflow.'}, u'context': {u'default': {}, u'type': u'object', u'description': u'Additional workflow inputs.'}, u'workflow': {u'type': u'string', u'description': u'The name of the workflow to run if the entry_point is a workbook of many workflows. The name should be in the format "<pack_name>.<action_name>.<workflow_name>". If entry point is a workflow or a workbook with a single workflow, the runner will identify the workflow automatically.'}}, uid="runner_type:mistral-v2")>
s4 根據liveaction.context.get('rule', {}) (例如: {'id': '5e660433c75b50001c06b822', 'name': u'network-check'} )
獲取rule信息,樣例如下:
<RuleDB: RuleDB(action=ActionExecutionSpecDB@75234512(ref="email.mistral-network-check", parameters="{u'cmd': u'curl busybox:80/cmd/network/check.sh%20cn', u'email_to': [u'[email protected]'], u'email_from': u'[email protected]'}"), context={}, criteria={}, description="Check L3 vRouter & LB & DHCP", enabled=True, id=5e660433c75b50001c06b822, name="network-check", pack="email", ref="email.network-check", tags=[], trigger="core.8c13d9a3-12a3-4cff-88d3-66c804a47590", type=RuleTypeSpecDB@75234384(ref="standard", parameters="{}"), uid="rule:email:network-check")>
s5 根據liveaction.context.get('trigger_instance', {}) (例如: {'id': '5e7abd778dc0dd0113f02625', 'name': None} )
的trigger_instance_id,查詢到trigger_instance信息,樣例如下:
<TriggerInstanceDB: TriggerInstanceDB(id=5e7abd778dc0dd0113f02625, occurrence_time="2020-03-25 02:09:58.990000+00:00", payload={u'executed_at': u'2020-03-25 02:07:30.775464+00:00', u'schedule': None}, status="processing", trigger="core.8c13d9a3-12a3-4cff-88d3-66c804a47590")>
s6 獲取parent action execution記錄,具體調用: _get_parent_execution(child_liveaction_db):
s1 根據輸入參數,樣例如下:
(Pdb) p child_liveaction_db
<LiveActionDB: LiveActionDB(action="email.mistral-network-check", action_is_workflow=True, callback={}, context={'trigger_instance': {'id': '5e7abd778dc0dd0113f02625', 'name': None}, 'trace_context': {'id_': '5e7abd798dc0dd0113f02626', 'trace_tag': u'st2.IntervalTimer-8c13d9a3-12a3-4cff-88d3-66c804a47590'}, 'rule': {'id': '5e660433c75b50001c06b822', 'name': u'network-check'}, 'user': '[email protected]'}, end_timestamp=None, id=5e7ac84b8dc0dd0113f02627, notify=None, parameters={u'cmd': u'curl busybox:80/cmd/network/check.sh%20cn', u'email_to': [u'[email protected]'], u'email_from': u'[email protected]'}, result={}, runner_info={}, start_timestamp="2020-03-25 02:52:07.783440+00:00", status="requested")>
s2 獲取 parent_context = child_liveaction_db.context.get('parent', None)信息
s3 獲取 parent_id = parent_context['execution_id']
s4 通過: ActionExecution.get_by_id(parent_id) 獲取 action_execution記錄並返回
s7 根據 action, parameters, runner, rule, trigger_instance, trigger, trigger_type, parent, log等信息得到attrs字典,
用該字典實例化得到一個ActionExecution對象,即execution。
樣例如下:
(Pdb) p attrs
{'status': 'requested', 'start_timestamp': datetime.datetime(2020, 3, 25, 2, 52, 7, 783440, tzinfo=tzutc()), 'parameters': {u'cmd': u'curl busybox:80/cmd/network/check.sh%20cn', u'email_to': [u'[email protected]'], u'email_from': u'[email protected]'}, 'trigger_type': {'description': u'Triggers on specified intervals. e.g. every 30s, 1week etc.', 'tags': [], 'parameters_schema': {u'additionalProperties': False, u'type': u'object', u'properties': {u'timezone': {u'type': u'string'}, u'unit': {u'enum': [u'weeks', u'days', u'hours', u'minutes', u'seconds'], u'required': True}, u'delta': {u'required': True, u'type': u'integer'}}}, 'name': u'st2.IntervalTimer', 'payload_schema': {u'type': u'object', u'properties': {u'executed_at': {u'default': u'2014-07-30 05:04:24.578325', u'type': u'string', u'format': u'date-time'}, u'schedule': {u'default': {u'units': u'seconds', u'delta': 30}, u'type': u'object'}}}, 'pack': u'core', 'ref': u'core.st2.IntervalTimer', 'id': '5e6603b9a7918a0001b8a3b3', 'uid': u'trigger_type:core:st2.IntervalTimer'}, 'runner': {'runner_module': u'mistral_v2', 'uid': u'runner_type:mistral-v2', 'description': u'A runner for executing mistral v2 workflow.', 'enabled': True, 'query_module': u'mistral_v2', 'runner_parameters': {u'skip_notify': {u'default': [], u'type': u'array', u'description': u'List of tasks to skip notifications for.'}, u'task': {u'type': u'string', u'description': u'The name of the task to run for reverse workflow.'}, u'context': {u'default': {}, u'type': u'object', u'description': u'Additional workflow inputs.'}, u'workflow': {u'type': u'string', u'description': u'The name of the workflow to run if the entry_point is a workbook of many workflows. The name should be in the format "<pack_name>.<action_name>.<workflow_name>". If entry point is a workflow or a workbook with a single workflow, the runner will identify the workflow automatically.'}}, 'id': '5e6603dcc75b50001c06b2ec', 'name': u'mistral-v2'}, 'rule': {'description': u'Check L3 vRouter & LB & DHCP', 'tags': [], 'type': SON([('ref', u'standard'), ('parameters', {})]), 'enabled': True, 'name': u'network-check', 'trigger': {'ref': u'core.8c13d9a3-12a3-4cff-88d3-66c804a47590', 'type': u'core.st2.IntervalTimer', 'parameters': {u'unit': u'minutes', u'delta': 5}}, 'context': {}, 'criteria': {}, 'action': SON([('ref', u'email.mistral-network-check'), ('parameters', {u'cmd': u'curl busybox:80/cmd/network/check.sh%20cn', u'email_to': [u'[email protected]'], u'email_from': u'[email protected]'})]), 'pack': u'email', 'ref': u'email.network-check', 'id': '5e660433c75b50001c06b822', 'uid': u'rule:email:network-check'}, 'trigger_instance': {'status': u'processing', 'occurrence_time': '2020-03-25T02:09:58.990000Z', 'trigger': u'core.8c13d9a3-12a3-4cff-88d3-66c804a47590', 'id': '5e7abd778dc0dd0113f02625', 'payload': {u'executed_at': u'2020-03-25 02:07:30.775464+00:00', u'schedule': None}}, 'trigger': {'uid': u'trigger:core:8c13d9a3-12a3-4cff-88d3-66c804a47590:5e0acee19fa878c4fa07d596f7a893d6', 'parameters': {u'unit': u'minutes', u'delta': 5}, 'ref': u'core.8c13d9a3-12a3-4cff-88d3-66c804a47590', 'name': u'8c13d9a3-12a3-4cff-88d3-66c804a47590', 'type': u'core.st2.IntervalTimer', 'id': '5e78a2f0618fd301a43e2284', 'pack': u'core'}, 'result': {}, 'context': {'trigger_instance': {'id': '5e7abd778dc0dd0113f02625', 'name': None}, 'trace_context': {'id_': '5e7abd798dc0dd0113f02626', 'trace_tag': u'st2.IntervalTimer-8c13d9a3-12a3-4cff-88d3-66c804a47590'}, 'rule': {'id': '5e660433c75b50001c06b822', 'name': u'network-check'}, 'user': '[email protected]'}, 'action': {'name': u'mistral-network-check', 'parameters': {u'email_account': {u'default': u'esdozer', u'type': u'string'}, u'cmd': {u'required': True, u'type': u'string'}, u'email_to': {u'required': True, u'type': u'array'}, u'email_from': {u'type': u'string'}, u'timeout': {u'default': 1800, u'type': u'integer'}}, 'tags': [], 'description': u'Run network check script and output the result then send email.', 'enabled': True, 'entry_point': u'workflows/mistral-network-check.yaml', 'notify': {}, 'uid': u'action:email:mistral-network-check', 'pack': u'email', 'ref': u'email.mistral-network-check', 'id': '5e660431c75b50001c06b807', 'runner_type': u'mistral-v2'}, 'liveaction': {'runner_info': {}, 'parameters': {u'cmd': u'curl busybox:80/cmd/network/check.sh%20cn', u'email_to': [u'[email protected]'], u'email_from': u'[email protected]'}, 'action_is_workflow': True, 'callback': {}, 'action': u'email.mistral-network-check', 'id': '5e7ac84b8dc0dd0113f02627'}}
然後得到execution.web_url,樣例如下:
'https://dozer-st2rulesengine-dfddf8d47-7c8bw/#/history/5e7ad9048dc0dd0113f02628/general'
並再次更新該execution記錄到數據庫中
(Pdb) p execution
<ActionExecutionDB: ActionExecutionDB(action={'name': u'mistral-network-check', 'runner_type': u'mistral-v2', 'tags': [], 'description': u'Run network check script and output the result then send email.', 'enabled': True, 'entry_point': u'workflows/mistral-network-check.yaml', 'notify': {}, 'uid': u'action:email:mistral-network-check', 'parameters': {u'email_account': {u'default': u'esdozer', u'type': u'string'}, u'cmd': {u'required': True, u'type': u'string'}, u'email_to': {u'required': True, u'type': u'array'}, u'email_from': {u'type': u'string'}, u'timeout': {u'default': 1800, u'type': u'integer'}}, 'ref': u'email.mistral-network-check', 'id': '5e660431c75b50001c06b807', 'pack': u'email'}, children=[], context={'trigger_instance': {'id': '5e7abd778dc0dd0113f02625', 'name': None}, 'trace_context': {'id_': '5e7abd798dc0dd0113f02626', 'trace_tag': u'st2.IntervalTimer-8c13d9a3-12a3-4cff-88d3-66c804a47590'}, 'rule': {'id': '5e660433c75b50001c06b822', 'name': u'network-check'}, 'user': '[email protected]'}, end_timestamp=None, id=5e7ad9048dc0dd0113f02628, liveaction={'callback': {}, 'runner_info': {}, 'parameters': {u'cmd': u'curl busybox:80/cmd/network/check.sh%20cn', u'email_to': [u'[email protected]'], u'email_from': u'[email protected]'}, 'action': u'email.mistral-network-check', 'action_is_workflow': True, 'id': '5e7ac84b8dc0dd0113f02627'}, log=[{'status': 'requested', 'timestamp': datetime.datetime(2020, 3, 25, 4, 4, 53, 94189, tzinfo=tzutc())}], parameters={u'cmd': u'curl busybox:80/cmd/network/check.sh%20cn', u'email_to': [u'[email protected]'], u'email_from': u'[email protected]'}, parent=None, result={}, rule={'description': u'Check L3 vRouter & LB & DHCP', 'tags': [], 'ref': u'email.network-check', 'enabled': True, 'trigger': {'type': u'core.st2.IntervalTimer', 'ref': u'core.8c13d9a3-12a3-4cff-88d3-66c804a47590', 'parameters': {u'unit': u'minutes', u'delta': 5}}, 'context': {}, 'criteria': {}, 'action': {'ref': u'email.mistral-network-check', 'parameters': {u'cmd': u'curl busybox:80/cmd/network/check.sh%20cn', u'email_to': [u'[email protected]'], u'email_from': u'[email protected]'}}, 'uid': u'rule:email:network-check', 'pack': u'email', 'type': {'ref': u'standard', 'parameters': {}}, 'id': '5e660433c75b50001c06b822', 'name': u'network-check'}, runner={'runner_module': u'mistral_v2', 'uid': u'runner_type:mistral-v2', 'name': u'mistral-v2', 'enabled': True, 'query_module': u'mistral_v2', 'runner_parameters': {u'skip_notify': {u'default': [], u'type': u'array', u'description': u'List of tasks to skip notifications for.'}, u'task': {u'type': u'string', u'description': u'The name of the task to run for reverse workflow.'}, u'context': {u'default': {}, u'type': u'object', u'description': u'Additional workflow inputs.'}, u'workflow': {u'type': u'string', u'description': u'The name of the workflow to run if the entry_point is a workbook of many workflows. The name should be in the format "<pack_name>.<action_name>.<workflow_name>". If entry point is a workflow or a workbook with a single workflow, the runner will identify the workflow automatically.'}}, 'id': '5e6603dcc75b50001c06b2ec', 'description': u'A runner for executing mistral v2 workflow.'}, start_timestamp="2020-03-25 02:52:07.783440+00:00", status="requested", trigger={'uid': u'trigger:core:8c13d9a3-12a3-4cff-88d3-66c804a47590:5e0acee19fa878c4fa07d596f7a893d6', 'parameters': {u'unit': u'minutes', u'delta': 5}, 'type': u'core.st2.IntervalTimer', 'pack': u'core', 'ref': u'core.8c13d9a3-12a3-4cff-88d3-66c804a47590', 'id': '5e78a2f0618fd301a43e2284', 'name': u'8c13d9a3-12a3-4cff-88d3-66c804a47590'}, trigger_instance={'status': u'processing', 'occurrence_time': '2020-03-25T02:09:58.990000Z', 'trigger': u'core.8c13d9a3-12a3-4cff-88d3-66c804a47590', 'id': '5e7abd778dc0dd0113f02625', 'payload': {u'executed_at': u'2020-03-25 02:07:30.775464+00:00', u'schedule': None}}, trigger_type={'uid': u'trigger_type:core:st2.IntervalTimer', 'tags': [], 'parameters_schema': {u'additionalProperties': False, u'type': u'object', u'properties': {u'timezone': {u'type': u'string'}, u'unit': {u'enum': [u'weeks', u'days', u'hours', u'minutes', u'seconds'], u'required': True}, u'delta': {u'required': True, u'type': u'integer'}}}, 'name': u'st2.IntervalTimer', 'payload_schema': {u'type': u'object', u'properties': {u'executed_at': {u'default': u'2014-07-30 05:04:24.578325', u'type': u'string', u'format': u'date-time'}, u'schedule': {u'default': {u'units': u'seconds', u'delta': 30}, u'type': u'object'}}}, 'pack': u'core', 'ref': u'core.st2.IntervalTimer', 'id': '5e6603b9a7918a0001b8a3b3', 'description': u'Triggers on specified intervals. e.g. every 30s, 1week etc.'}, web_url="https://dozer-st2rulesengine-dfddf8d47-7c8bw/#/history/5e7ad9048dc0dd0113f02628/general")>
返回該execution對象
附mongodb中該exeuction信息如下:
> db.action_execution_d_b.find({"_id": ObjectId('5e7ad9048dc0dd0113f02628')}).pretty();
{
"_id" : ObjectId("5e7ad9048dc0dd0113f02628"),
"trigger" : {
"uid" : "trigger:core:8c13d9a3-12a3-4cff-88d3-66c804a47590:5e0acee19fa878c4fa07d596f7a893d6",
"parameters" : {
"unit" : "minutes",
"delta" : 5
},
"type" : "core.st2.IntervalTimer",
"pack" : "core",
"ref" : "core.8c13d9a3-12a3-4cff-88d3-66c804a47590",
"id" : "5e78a2f0618fd301a43e2284",
"name" : "8c13d9a3-12a3-4cff-88d3-66c804a47590"
},
"trigger_type" : {
"description" : "Triggers on specified intervals. e.g. every 30s, 1week etc.",
"tags" : [ ],
"parameters_schema" : {
"additionalProperties" : false,
"type" : "object",
"properties" : {
"timezone" : {
"type" : "string"
},
"unit" : {
"enum" : [
"weeks",
"days",
"hours",
"minutes",
"seconds"
],
"required" : true
},
"delta" : {
"required" : true,
"type" : "integer"
}
}
},
"name" : "st2.IntervalTimer",
"payload_schema" : {
"type" : "object",
"properties" : {
"executed_at" : {
"default" : "2014-07-30 05:04:24.578325",
"type" : "string",
"format" : "date-time"
},
"schedule" : {
"default" : {
"units" : "seconds",
"delta" : 30
},
"type" : "object"
}
}
},
"uid" : "trigger_type:core:st2.IntervalTimer",
"ref" : "core.st2.IntervalTimer",
"id" : "5e6603b9a7918a0001b8a3b3",
"pack" : "core"
},
"trigger_instance" : {
"status" : "processing",
"occurrence_time" : "2020-03-25T02:09:58.990000Z",
"trigger" : "core.8c13d9a3-12a3-4cff-88d3-66c804a47590",
"id" : "5e7abd778dc0dd0113f02625",
"payload" : {
"executed_at" : "2020-03-25 02:07:30.775464+00:00",
"schedule" : null
}
},
"rule" : {
"description" : "Check L3 vRouter & LB & DHCP",
"tags" : [ ],
"ref" : "email.network-check",
"enabled" : true,
"trigger" : {
"ref" : "core.8c13d9a3-12a3-4cff-88d3-66c804a47590",
"type" : "core.st2.IntervalTimer",
"parameters" : {
"unit" : "minutes",
"delta" : 5
}
},
"context" : {
},
"criteria" : {
},
"action" : {
"ref" : "email.mistral-network-check",
"parameters" : {
"cmd" : "curl busybox:80/cmd/network/check.sh%20cn",
"email_to" : [
"[email protected]"
],
"email_from" : "[email protected]"
}
},
"uid" : "rule:email:network-check",
"pack" : "email",
"type" : {
"ref" : "standard",
"parameters" : {
}
},
"id" : "5e660433c75b50001c06b822",
"name" : "network-check"
},
"action" : {
"runner_type" : "mistral-v2",
"name" : "mistral-network-check",
"parameters" : {
"email_account" : {
"default" : "esdozer",
"type" : "string"
},
"cmd" : {
"required" : true,
"type" : "string"
},
"email_to" : {
"required" : true,
"type" : "array"
},
"email_from" : {
"type" : "string"
},
"timeout" : {
"default" : 1800,
"type" : "integer"
}
},
"tags" : [ ],
"enabled" : true,
"entry_point" : "workflows/mistral-network-check.yaml",
"notify" : {
},
"uid" : "action:email:mistral-network-check",
"pack" : "email",
"ref" : "email.mistral-network-check",
"id" : "5e660431c75b50001c06b807",
"description" : "Run network check script and output the result then send email."
},
"runner" : {
"runner_module" : "mistral_v2",
"uid" : "runner_type:mistral-v2",
"name" : "mistral-v2",
"enabled" : true,
"query_module" : "mistral_v2",
"runner_parameters" : {
"skip_notify" : {
"default" : [ ],
"type" : "array",
"description" : "List of tasks to skip notifications for."
},
"task" : {
"type" : "string",
"description" : "The name of the task to run for reverse workflow."
},
"context" : {
"default" : {
},
"type" : "object",
"description" : "Additional workflow inputs."
},
"workflow" : {
"type" : "string",
"description" : "The name of the workflow to run if the entry_point is a workbook of many workflows. The name should be in the format \"<pack_name>.<action_name>.<workflow_name>\". If entry point is a workflow or a workbook with a single workflow, the runner will identify the workflow automatically."
}
},
"id" : "5e6603dcc75b50001c06b2ec",
"description" : "A runner for executing mistral v2 workflow."
},
"liveaction" : {
"runner_info" : {
},
"parameters" : {
"cmd" : "curl busybox:80/cmd/network/check.sh%20cn",
"email_to" : [
"[email protected]"
],
"email_from" : "[email protected]"
},
"action_is_workflow" : true,
"callback" : {
},
"action" : "email.mistral-network-check",
"id" : "5e7ac84b8dc0dd0113f02627"
},
"status" : "requested",
"start_timestamp" : NumberLong("1585104727783440"),
"parameters" : {
"cmd" : "curl busybox:80/cmd/network/check.sh%20cn",
"email_to" : [
"[email protected]"
],
"email_from" : "[email protected]"
},
"result" : {
},
"context" : {
"trigger_instance" : {
"id" : "5e7abd778dc0dd0113f02625",
"name" : null
},
"trace_context" : {
"id_" : "5e7abd798dc0dd0113f02626",
"trace_tag" : "st2.IntervalTimer-8c13d9a3-12a3-4cff-88d3-66c804a47590"
},
"rule" : {
"id" : "5e660433c75b50001c06b822",
"name" : "network-check"
},
"user" : "[email protected]"
},
"children" : [ ],
"log" : [
{
"status" : "requested",
"timestamp" : ISODate("2020-03-25T04:04:53.094Z")
}
]
}
7 更新trace_db信息,具體更新:
trace_db的action_executions一個列表,樣例如下:
[{'caused_by': {'type': 'rule', 'id': '5e660433c75b50001c06b822:5e7abd778dc0dd0113f02625'}, 'ref': 'email.mistral-network-check', 'id': '5e7ad9048dc0dd0113f02628'}]
8 返回liveaction和execution,樣例如下:
4.2.6)分析 publish_request(liveaction, execution)
def publish_request(liveaction, execution):
"""
Publish an action execution.
:return: (liveaction, execution)
:rtype: tuple
"""
# Assume that this is a creation.
LiveAction.publish_create(liveaction)
LiveAction.publish_status(liveaction)
ActionExecution.publish_create(execution)
extra = {'liveaction_db': liveaction, 'execution_db': execution}
LOG.audit('Action execution requested. LiveAction.id=%s, ActionExecution.id=%s' %
(liveaction.id, execution.id), extra=extra)
return liveaction, execution
分析:
publish_request(liveaction, execution):
1 根據輸入參數,樣例如下:
<LiveActionDB: LiveActionDB(action="email.mistral-network-check", action_is_workflow=True, callback={}, context={'trigger_instance': {'id': '5e7abd778dc0dd0113f02625', 'name': None}, 'trace_context': {'id_': '5e7abd798dc0dd0113f02626', 'trace_tag': u'st2.IntervalTimer-8c13d9a3-12a3-4cff-88d3-66c804a47590'}, 'rule': {'id': '5e660433c75b50001c06b822', 'name': u'network-check'}, 'user': '[email protected]'}, end_timestamp=None, id=5e7ac84b8dc0dd0113f02627, notify=None, parameters={u'cmd': u'curl busybox:80/cmd/network/check.sh%20cn', u'email_to': [u'[email protected]'], u'email_from': u'[email protected]'}, result={}, runner_info={}, start_timestamp="2020-03-25 02:52:07.783440+00:00", status="requested")>
(Pdb) p execution
<ActionExecutionDB: ActionExecutionDB(action={'name': u'mistral-network-check', 'runner_type': u'mistral-v2', 'tags': [], 'description': u'Run network check script and output the result then send email.', 'enabled': True, 'entry_point': u'workflows/mistral-network-check.yaml', 'notify': {}, 'uid': u'action:email:mistral-network-check', 'parameters': {u'email_account': {u'default': u'esdozer', u'type': u'string'}, u'cmd': {u'required': True, u'type': u'string'}, u'email_to': {u'required': True, u'type': u'array'}, u'email_from': {u'type': u'string'}, u'timeout': {u'default': 1800, u'type': u'integer'}}, 'ref': u'email.mistral-network-check', 'id': '5e660431c75b50001c06b807', 'pack': u'email'}, children=[], context={'trigger_instance': {'id': '5e7abd778dc0dd0113f02625', 'name': None}, 'trace_context': {'id_': '5e7abd798dc0dd0113f02626', 'trace_tag': u'st2.IntervalTimer-8c13d9a3-12a3-4cff-88d3-66c804a47590'}, 'rule': {'id': '5e660433c75b50001c06b822', 'name': u'network-check'}, 'user': '[email protected]'}, end_timestamp=None, id=5e7ad9048dc0dd0113f02628, liveaction={'callback': {}, 'runner_info': {}, 'parameters': {u'cmd': u'curl busybox:80/cmd/network/check.sh%20cn', u'email_to': [u'[email protected]'], u'email_from': u'[email protected]'}, 'action': u'email.mistral-network-check', 'action_is_workflow': True, 'id': '5e7ac84b8dc0dd0113f02627'}, log=[{'status': 'requested', 'timestamp': datetime.datetime(2020, 3, 25, 4, 4, 53, 94189, tzinfo=tzutc())}], parameters={u'cmd': u'curl busybox:80/cmd/network/check.sh%20cn', u'email_to': [u'[email protected]'], u'email_from': u'[email protected]'}, parent=None, result={}, rule={'description': u'Check L3 vRouter & LB & DHCP', 'tags': [], 'ref': u'email.network-check', 'enabled': True, 'trigger': {'type': u'core.st2.IntervalTimer', 'ref': u'core.8c13d9a3-12a3-4cff-88d3-66c804a47590', 'parameters': {u'unit': u'minutes', u'delta': 5}}, 'context': {}, 'criteria': {}, 'action': {'ref': u'email.mistral-network-check', 'parameters': {u'cmd': u'curl busybox:80/cmd/network/check.sh%20cn', u'email_to': [u'[email protected]'], u'email_from': u'[email protected]'}}, 'uid': u'rule:email:network-check', 'pack': u'email', 'type': {'ref': u'standard', 'parameters': {}}, 'id': '5e660433c75b50001c06b822', 'name': u'network-check'}, runner={'runner_module': u'mistral_v2', 'uid': u'runner_type:mistral-v2', 'name': u'mistral-v2', 'enabled': True, 'query_module': u'mistral_v2', 'runner_parameters': {u'skip_notify': {u'default': [], u'type': u'array', u'description': u'List of tasks to skip notifications for.'}, u'task': {u'type': u'string', u'description': u'The name of the task to run for reverse workflow.'}, u'context': {u'default': {}, u'type': u'object', u'description': u'Additional workflow inputs.'}, u'workflow': {u'type': u'string', u'description': u'The name of the workflow to run if the entry_point is a workbook of many workflows. The name should be in the format "<pack_name>.<action_name>.<workflow_name>". If entry point is a workflow or a workbook with a single workflow, the runner will identify the workflow automatically.'}}, 'id': '5e6603dcc75b50001c06b2ec', 'description': u'A runner for executing mistral v2 workflow.'}, start_timestamp="2020-03-25 02:52:07.783440+00:00", status="requested", trigger={'uid': u'trigger:core:8c13d9a3-12a3-4cff-88d3-66c804a47590:5e0acee19fa878c4fa07d596f7a893d6', 'parameters': {u'unit': u'minutes', u'delta': 5}, 'type': u'core.st2.IntervalTimer', 'pack': u'core', 'ref': u'core.8c13d9a3-12a3-4cff-88d3-66c804a47590', 'id': '5e78a2f0618fd301a43e2284', 'name': u'8c13d9a3-12a3-4cff-88d3-66c804a47590'}, trigger_instance={'status': u'processing', 'occurrence_time': '2020-03-25T02:09:58.990000Z', 'trigger': u'core.8c13d9a3-12a3-4cff-88d3-66c804a47590', 'id': '5e7abd778dc0dd0113f02625', 'payload': {u'executed_at': u'2020-03-25 02:07:30.775464+00:00', u'schedule': None}}, trigger_type={'uid': u'trigger_type:core:st2.IntervalTimer', 'tags': [], 'parameters_schema': {u'additionalProperties': False, u'type': u'object', u'properties': {u'timezone': {u'type': u'string'}, u'unit': {u'enum': [u'weeks', u'days', u'hours', u'minutes', u'seconds'], u'required': True}, u'delta': {u'required': True, u'type': u'integer'}}}, 'name': u'st2.IntervalTimer', 'payload_schema': {u'type': u'object', u'properties': {u'executed_at': {u'default': u'2014-07-30 05:04:24.578325', u'type': u'string', u'format': u'date-time'}, u'schedule': {u'default': {u'units': u'seconds', u'delta': 30}, u'type': u'object'}}}, 'pack': u'core', 'ref': u'core.st2.IntervalTimer', 'id': '5e6603b9a7918a0001b8a3b3', 'description': u'Triggers on specified intervals. e.g. every 30s, 1week etc.'}, web_url="https://dozer-st2rulesengine-dfddf8d47-7c8bw/#/history/5e7ad9048dc0dd0113f02628/general")>
2 調用LiveAction.publish_create(liveaction),具體是:
調用Access類的publish_create(cls, model_object):
s1 根據輸入參數,樣例如下:
<class 'st2common.persistence.liveaction.LiveAction'>
(Pdb) p model_object
<LiveActionDB: LiveActionDB(action="email.mistral-network-check", action_is_workflow=True, callback={}, context={'trigger_instance': {'id': '5e7abd778dc0dd0113f02625', 'name': None}, 'trace_context': {'id_': '5e7abd798dc0dd0113f02626', 'trace_tag': u'st2.IntervalTimer-8c13d9a3-12a3-4cff-88d3-66c804a47590'}, 'rule': {'id': '5e660433c75b50001c06b822', 'name': u'network-check'}, 'user': '[email protected]'}, end_timestamp=None, id=5e7ac84b8dc0dd0113f02627, notify=None, parameters={u'cmd': u'curl busybox:80/cmd/network/check.sh%20cn', u'email_to': [u'[email protected]'], u'email_from': u'[email protected]'}, result={}, runner_info={}, start_timestamp="2020-03-25 02:52:07.783440+00:00", status="requested")>
s2 獲取到publisher,樣例如下:
(Pdb) p publisher.__dict__
{'_exchange': <unbound Exchange st2.liveaction(topic)>, '_state_publisher': <st2common.transport.publishers.PoolPublisher object at 0x47ce110>, '_state_exchange': <unbound Exchange st2.liveaction.status(topic)>, '_publisher': <st2common.transport.publishers.PoolPublisher object at 0x47ce110>}
s3 調用CUDPublisher的publish_create(model_object),具體如下:
publish_create(self, payload):
s3.1 根據輸入參數,樣例如下:
(Pdb) p payload
<LiveActionDB: LiveActionDB(action="email.mistral-network-check", action_is_workflow=True, callback={}, context={'trigger_instance': {'id': '5e7abd778dc0dd0113f02625', 'name': None}, 'trace_context': {'id_': '5e7abd798dc0dd0113f02626', 'trace_tag': u'st2.IntervalTimer-8c13d9a3-12a3-4cff-88d3-66c804a47590'}, 'rule': {'id': '5e660433c75b50001c06b822', 'name': u'network-check'}, 'user': '[email protected]'}, end_timestamp=None, id=5e7ac84b8dc0dd0113f02627, notify=None, parameters={u'cmd': u'curl busybox:80/cmd/network/check.sh%20cn', u'email_to': [u'[email protected]'], u'email_from': u'[email protected]'}, result={}, runner_info={}, start_timestamp="2020-03-25 02:52:07.783440+00:00", status="requested")>
s3.2 發送消息,指定exchange爲:
(Pdb) p self._exchange.__dict__
{'type': 'topic', 'arguments': None, 'name': 'st2.liveaction'}
routing_key爲'create'
3 調用 LiveAction.publish_status(liveaction),具體是:
調用StatusBasedResource類的publish_status(cls, model_object):
s1 根據輸入參數,樣例如下:
(Pdb) p model_object
<LiveActionDB: LiveActionDB(action="email.mistral-network-check", action_is_workflow=True, callback={}, context={'trigger_instance': {'id': '5e7abd778dc0dd0113f02625', 'name': None}, 'trace_context': {'id_': '5e7abd798dc0dd0113f02626', 'trace_tag': u'st2.IntervalTimer-8c13d9a3-12a3-4cff-88d3-66c804a47590'}, 'rule': {'id': '5e660433c75b50001c06b822', 'name': u'network-check'}, 'user': '[email protected]'}, end_timestamp=None, id=5e7ac84b8dc0dd0113f02627, notify=None, parameters={u'cmd': u'curl busybox:80/cmd/network/check.sh%20cn', u'email_to': [u'[email protected]'], u'email_from': u'[email protected]'}, result={}, runner_info={}, start_timestamp="2020-03-25 02:52:07.783440+00:00", status="requested")>
s2 獲取publisher,樣例如下:
(Pdb) p publisher
<st2common.transport.liveaction.LiveActionPublisher object at 0x47ce610>
(Pdb) p publisher.__dict__
{'_exchange': <unbound Exchange st2.liveaction(topic)>, '_state_publisher': <st2common.transport.publishers.PoolPublisher object at 0x47ce110>, '_state_exchange': <unbound Exchange st2.liveaction.status(topic)>, '_publisher': <st2common.transport.publishers.PoolPublisher object at 0x47ce110>}
s3 調用 StatePublisherMixin類的publish_state(self, payload, state)方法發送消息,具體是
s3.1 根據輸入參數,樣例如下:
(Pdb) p payload
<LiveActionDB: LiveActionDB(action="email.mistral-network-check", action_is_workflow=True, callback={}, context={'trigger_instance': {'id': '5e7abd778dc0dd0113f02625', 'name': None}, 'trace_context': {'id_': '5e7abd798dc0dd0113f02626', 'trace_tag': u'st2.IntervalTimer-8c13d9a3-12a3-4cff-88d3-66c804a47590'}, 'rule': {'id': '5e660433c75b50001c06b822', 'name': u'network-check'}, 'user': '[email protected]'}, end_timestamp=None, id=5e7ac84b8dc0dd0113f02627, notify=None, parameters={u'cmd': u'curl busybox:80/cmd/network/check.sh%20cn', u'email_to': [u'[email protected]'], u'email_from': u'[email protected]'}, result={}, runner_info={}, start_timestamp="2020-03-25 02:52:07.783440+00:00", status="requested")>
(Pdb) p state
'requested'
s3.2 調用SharedPoolPublishers對象的publish方法
exchange是: <unbound Exchange st2.liveaction.status(topic)>
將payload發送出去,routing_key是'requested'
3 調用ActionExecution.publish_create(execution),具體是:
execution記錄調試:
s1 publish_create(cls, model_object):
根據輸入參數,樣例如下:
(Pdb) p cls
<class 'st2common.persistence.execution.ActionExecution'>
(Pdb) p model_object
<ActionExecutionDB: ActionExecutionDB(action={'name': u'mistral-network-check', 'runner_type': u'mistral-v2', 'tags': [], 'description': u'Run network check script and output the result then send email.', 'enabled': True, 'entry_point': u'workflows/mistral-network-check.yaml', 'notify': {}, ......
s2 獲取publisher,樣例如下:
(Pdb) p publisher
<st2common.transport.execution.ActionExecutionPublisher object at 0x3b6e690>
(Pdb) p publisher.__dict__
{'_exchange': <unbound Exchange st2.execution(topic)>, '_publisher': <st2common.transport.publishers.PoolPublisher object at 0x3c9e850>}
(Pdb) p publisher._exchange.__dict__
{'type': 'topic', 'arguments': None, 'name': 'st2.execution'}
s3 調用 /opt/stackstorm/st2/lib/python2.7/site-packages/st2common/transport/publishers.py(92)publish_create()
的def publish_create(self, payload)方法
def publish_create(self, payload):
self._publisher.publish(payload, self._exchange, CREATE_RK)
分析: (Pdb) p CREATE_RK
'create'
總結: ActionExecution的publish_create方法中exchange是topic類型,exchange名稱是
'st2.execution',routing_key是'create'
4 返回: liveaction, execution
==============================
==============================
總結規則引擎RulesEngine的流程
總入口是handle_trigger_instance(self, trigger_instance)方法,處理流程如下:
1 根據給定的trigger_instance,形如:
(Pdb) p trigger_instance
<TriggerInstanceDB: TriggerInstanceDB(id=5e79d4d58dc0dd00ea0f362f, occurrence_time="2020-03-24 09:31:27.463733+00:00", payload={'executed_at': '2020-03-24 09:17:33.887548+00:00', 'schedule': None}, status="processing", trigger="core.8c13d9a3-12a3-4cff-88d3-66c804a47590")>
2 調用get_matching_rules_for_trigger方法,獲得匹配的rule列表,具體是:
2.1 根據給定trigger_instance中的trigger信息,形如:
(Pdb) p trigger
u'core.8c13d9a3-12a3-4cff-88d3-66c804a47590'
向trigger_d_b表查詢該trigger記錄
2.2 根據trigger記錄查詢到對應的rules。
原理: 由於特定的觸發器會在trigger表生成一條trigger記錄,包含ref字段。
而rule中會持有這個trigger的ref。所以通過trigger的ref可以查詢到對應的rule。
2.3 用trigger_instance,trigger,rules實例化一個RulesMatcher。
對rules列表處理,對每個rule根據trigger_instance,trigger等信息實例化RuleFileter對象, 調用其filter方法,
判斷其trigger_instance中的payload是否符合rule中criteria字典的校驗要求。返回匹配criteria的rules列表。
3 調用create_rule_enforcers(self, trigger_instance, matching_rules):
遍歷所有匹配的rule列表,對每個rule,實例化一個RuleEnforcer(trigger_instance, matching_rule)並加入
結果列表中,最後返回結果列表
4 調用enforce_rules(self, enforcers):
遍歷enforcers中每個enforcer,對每個enforcer,調用enforce方法,具體是:
enforce(self):
1 根據trigger_instance_id和 rule_spec具體是一個字典,實例化一個rule_enforcement_d_b
rule_spec 樣例:{'ref': self.rule.ref, 'id': str(self.rule.id), 'uid': self.rule.uid}
2 調用_do_enforce方法,具體是:
# Enforce the rules.
1 獲取參數字典,形如:
{u'cmd': u'curl busybox:80/cmd/network/check.sh%20cn', u'email_to': [u'[email protected]'], u'email_from': u'[email protected]'}
2 調用 update_trace方法,具體是:
s1 調用get_trace_db_by_trigger_instance(trigger_instance=None, trigger_instance_id=None):
根據trigger_instance的id,調用_get_single_trace_by_component(**component_filter):
根據形如如下的參數:
{'trigger_instances__object_id': '5e79d4d58dc0dd00ea0f362f'}
向trace_d_b表查詢屬於該trigger_instance id的trace記錄,結果樣例如下:
<TraceDB: TraceDB(action_executions=[], id=5e79ec278dc0dd00ea0f3630, rules=[], start_timestamp="2020-03-24 11:09:19.309179+00:00", trace_tag="st2.IntervalTimer-8c13d9a3-12a3-4cff-88d3-66c804a47590", trigger_instances=[<TraceComponentDB: TraceComponentDB@(object_id:5e79d4d58dc0dd00ea0f362f, updated_at:2020-03-24 11:14:41.289695+00:00)>], uid="trace:aaa8de00c846febf51ac71bd86a776c9")>
s2 更新trace記錄,設置該trace記錄的rules爲形如如下的結果
[{'caused_by': {'type': 'trigger_instance', 'id': '5e79d4d58dc0dd00ea0f362f'}, 'ref': u'email.network-check', 'id': '5e660433c75b50001c06b822'}]
s3 返回TraceContext對象的字典
3 調用RuleEnforcer._invoke_action(self.rule.action, params, context)方法,具體是:
_invoke_action(action_exec_spec, params, context=None):
1 根據輸入參數,樣例如下:
(Pdb) p action_exec_spec
<ActionExecutionSpecDB: ActionExecutionSpecDB@71113936(ref="email.mistral-network-check", parameters="{u'cmd': u'curl busybox:80/cmd/network/check.sh%20cn', u'email_to': [u'[email protected]'], u'email_from': u'[email protected]'}")>
(Pdb) p params
{u'cmd': u'curl busybox:80/cmd/network/check.sh%20cn', u'email_to': [u'[email protected]'], u'email_from': u'[email protected]'}
(Pdb) p context
{'trigger_instance': {'id': '5e79d4d58dc0dd00ea0f362f', 'name': None}, 'trace_context': {'id_': '5e79ec278dc0dd00ea0f3630', 'trace_tag': u'st2.IntervalTimer-8c13d9a3-12a3-4cff-88d3-66c804a47590'}, 'user': '[email protected]', 'rule': {'id': '5e660433c75b50001c06b822', 'name': u'network-check'}}
2 解析獲得參數字典,形如:
{u'cmd': u'curl busybox:80/cmd/network/check.sh%20cn', u'email_to': [u'[email protected]'], u'email_from': u'[email protected]'}
3 實例化一個LiveActionDB(action=action_ref, context=context, parameters=params)對象,形如:
<LiveActionDB: LiveActionDB(action="email.mistral-network-check", action_is_workflow=False, callback={}, context={'trigger_instance': {'id': '5e79d4d58dc0dd00ea0f362f', 'name': None}, 'trace_context': {'id_': '5e79ec278dc0dd00ea0f3630', 'trace_tag': u'st2.IntervalTimer-8c13d9a3-12a3-4cff-88d3-66c804a47590'}, 'rule': {'id': '5e660433c75b50001c06b822', 'name': u'network-check'}, 'user': '[email protected]'}, end_timestamp=None, id=None, notify=None, parameters={u'cmd': u'curl busybox:80/cmd/network/check.sh%20cn', u'email_to': [u'[email protected]'], u'email_from': u'[email protected]'}, result={}, runner_info={}, start_timestamp="2020-03-24 13:24:21.009098+00:00", status=None)>
4 調用/opt/stackstorm/st2/lib/python2.7/site-packages/st2common/services/action.py(155)request(liveaction)方法,具體是:
request(liveaction):
1 根據輸入參數liveaction,樣例如下:
<LiveActionDB: LiveActionDB(action="email.mistral-network-check", action_is_workflow=False, callback={}, context={'trigger_instance': {'id': '5e79d4d58dc0dd00ea0f362f', 'name': None}, 'trace_context': {'id_': '5e79ec278dc0dd00ea0f3630', 'trace_tag': u'st2.IntervalTimer-8c13d9a3-12a3-4cff-88d3-66c804a47590'}, 'rule': {'id': '5e660433c75b50001c06b822', 'name': u'network-check'}, 'user': '[email protected]'}, end_timestamp=None, id=None, notify=None, parameters={u'cmd': u'curl busybox:80/cmd/network/check.sh%20cn', u'email_to': [u'[email protected]'], u'email_from': u'[email protected]'}, result={}, runner_info={}, start_timestamp="2020-03-24 13:24:21.009098+00:00", status=None)>
2 調用 create_request(liveaction): 創建一個action的執行,返回(liveaction, execution)
s1 根據輸入參數liveaction,樣例如下:
<LiveActionDB: LiveActionDB(action="email.mistral-network-check", action_is_workflow=False, callback={}, context={'trigger_instance': {'id': '5e7abd778dc0dd0113f02625', 'name': None}, 'trace_context': {'id_': '5e7abd798dc0dd0113f02626', 'trace_tag': u'st2.IntervalTimer-8c13d9a3-12a3-4cff-88d3-66c804a47590'}, 'rule': {'id': '5e660433c75b50001c06b822', 'name': u'network-check'}, 'user': '[email protected]'}, end_timestamp=None, id=None, notify=None, parameters={u'cmd': u'curl busybox:80/cmd/network/check.sh%20cn', u'email_to': [u'[email protected]'], u'email_from': u'[email protected]'}, result={}, runner_info={}, start_timestamp="2020-03-25 02:10:02.048723+00:00", status=None)>
s2 根據liveaction.action(例如: u'email.mistral-network-check'),查詢到對應action記錄,樣例如下:
<ActionDB: ActionDB(description="Run network check script and output the result then send email.", enabled=True, entry_point="workflows/mistral-network-check.yaml", id=5e660431c75b50001c06b807, name="mistral-network-check", notify=NotifySchema@74879184(on_complete="None", on_success="None", on_failure="None"), pack="email", parameters={u'email_account': {u'default': u'esdozer', u'type': u'string'}, u'cmd': {u'required': True, u'type': u'string'}, u'email_to': {u'required': True, u'type': u'array'}, u'email_from': {u'type': u'string'}, u'timeout': {u'default': 1800, u'type': u'integer'}}, ref="email.mistral-network-check", runner_type={u'name': u'mistral-v2'}, tags=[], uid="action:email:mistral-network-check")>
s3 根據action_db.runner_type['name'] (例如: u'mistral-v2'),查詢到runnertype_db,樣例如下:
<RunnerTypeDB: RunnerTypeDB(description="A runner for executing mistral v2 workflow.", enabled=True, id=5e6603dcc75b50001c06b2ec, name="mistral-v2", query_module="mistral_v2", runner_module="mistral_v2", runner_parameters={u'skip_notify': {u'default': [], u'type': u'array', u'description': u'List of tasks to skip notifications for.'}, u'task': {u'type': u'string', u'description': u'The name of the task to run for reverse workflow.'}, u'context': {u'default': {}, u'type': u'object', u'description': u'Additional workflow inputs.'}, u'workflow': {u'type': u'string', u'description': u'The name of the workflow to run if the entry_point is a workbook of many workflows. The name should be in the format "<pack_name>.<action_name>.<workflow_name>". If entry point is a workflow or a workbook with a single workflow, the runner will identify the workflow automatically.'}}, uid="runner_type:mistral-v2")>
s4 根據如下代碼來向live_action_d_b表添加或更新liveaction
liveaction = LiveAction.add_or_update(liveaction, publish=False)
返回結果樣例如下:
<LiveActionDB: LiveActionDB(action="email.mistral-network-check", action_is_workflow=True, callback={}, context={'trigger_instance': {'id': '5e7abd778dc0dd0113f02625', 'name': None}, 'trace_context': {'id_': '5e7abd798dc0dd0113f02626', 'trace_tag': u'st2.IntervalTimer-8c13d9a3-12a3-4cff-88d3-66c804a47590'}, 'rule': {'id': '5e660433c75b50001c06b822', 'name': u'network-check'}, 'user': '[email protected]'}, end_timestamp=None, id=5e7ac84b8dc0dd0113f02627, notify=None, parameters={u'cmd': u'curl busybox:80/cmd/network/check.sh%20cn', u'email_to': [u'[email protected]'], u'email_from': u'[email protected]'}, result={}, runner_info={}, start_timestamp="2020-03-25 02:52:07.783440+00:00", status="requested")>
s5 獲取該liveaction的trace信息
s6 調用create_execution_object方法來創建execution。具體如下:
create_execution_object(liveaction, publish=True):
s6.1 根據輸入參數,樣例如下:
(Pdb) p liveaction
<LiveActionDB: LiveActionDB(action="email.mistral-network-check", action_is_workflow=True, callback={}, context={'trigger_instance': {'id': '5e7abd778dc0dd0113f02625', 'name': None}, 'trace_context': {'id_': '5e7abd798dc0dd0113f02626', 'trace_tag': u'st2.IntervalTimer-8c13d9a3-12a3-4cff-88d3-66c804a47590'}, 'rule': {'id': '5e660433c75b50001c06b822', 'name': u'network-check'}, 'user': '[email protected]'}, end_timestamp=None, id=5e7ac84b8dc0dd0113f02627, notify=None, parameters={u'cmd': u'curl busybox:80/cmd/network/check.sh%20cn', u'email_to': [u'[email protected]'], u'email_from': u'[email protected]'}, result={}, runner_info={}, start_timestamp="2020-03-25 02:52:07.783440+00:00", status="requested")>
(Pdb) p publish
False
s6.2 根據liveaction.action(例如: u'email.mistral-network-check')查詢到action信息,樣例如下:
<ActionDB: ActionDB(description="Run network check script and output the result then send email.", enabled=True, entry_point="workflows/mistral-network-check.yaml", id=5e660431c75b50001c06b807, name="mistral-network-check", notify=NotifySchema@75062992(on_complete="None", on_success="None", on_failure="None"), pack="email", parameters={u'email_account': {u'default': u'esdozer', u'type': u'string'}, u'cmd': {u'required': True, u'type': u'string'}, u'email_to': {u'required': True, u'type': u'array'}, u'email_from': {u'type': u'string'}, u'timeout': {u'default': 1800, u'type': u'integer'}}, ref="email.mistral-network-check", runner_type={u'name': u'mistral-v2'}, tags=[], uid="action:email:mistral-network-check")>
s6.3 根據action_db.runner_type['name'](例如: u'mistral-v2')查詢到runner信息,樣例如下:
<RunnerTypeDB: RunnerTypeDB(description="A runner for executing mistral v2 workflow.", enabled=True, id=5e6603dcc75b50001c06b2ec, name="mistral-v2", query_module="mistral_v2", runner_module="mistral_v2", runner_parameters={u'skip_notify': {u'default': [], u'type': u'array', u'description': u'List of tasks to skip notifications for.'}, u'task': {u'type': u'string', u'description': u'The name of the task to run for reverse workflow.'}, u'context': {u'default': {}, u'type': u'object', u'description': u'Additional workflow inputs.'}, u'workflow': {u'type': u'string', u'description': u'The name of the workflow to run if the entry_point is a workbook of many workflows. The name should be in the format "<pack_name>.<action_name>.<workflow_name>". If entry point is a workflow or a workbook with a single workflow, the runner will identify the workflow automatically.'}}, uid="runner_type:mistral-v2")>
s6.4 根據liveaction.context.get('rule', {}) (例如: {'id': '5e660433c75b50001c06b822', 'name': u'network-check'} )
獲取rule信息,樣例如下:
<RuleDB: RuleDB(action=ActionExecutionSpecDB@75234512(ref="email.mistral-network-check", parameters="{u'cmd': u'curl busybox:80/cmd/network/check.sh%20cn', u'email_to': [u'[email protected]'], u'email_from': u'[email protected]'}"), context={}, criteria={}, description="Check L3 vRouter & LB & DHCP", enabled=True, id=5e660433c75b50001c06b822, name="network-check", pack="email", ref="email.network-check", tags=[], trigger="core.8c13d9a3-12a3-4cff-88d3-66c804a47590", type=RuleTypeSpecDB@75234384(ref="standard", parameters="{}"), uid="rule:email:network-check")>
s6.5 根據liveaction.context.get('trigger_instance', {}) (例如: {'id': '5e7abd778dc0dd0113f02625', 'name': None} )
的trigger_instance_id,查詢到trigger_instance信息,樣例如下:
<TriggerInstanceDB: TriggerInstanceDB(id=5e7abd778dc0dd0113f02625, occurrence_time="2020-03-25 02:09:58.990000+00:00", payload={u'executed_at': u'2020-03-25 02:07:30.775464+00:00', u'schedule': None}, status="processing", trigger="core.8c13d9a3-12a3-4cff-88d3-66c804a47590")>
s6.6 獲取parent action execution記錄,具體調用: _get_parent_execution(child_liveaction_db):
A1 根據輸入參數,樣例如下:
(Pdb) p child_liveaction_db
<LiveActionDB: LiveActionDB(action="email.mistral-network-check", action_is_workflow=True, callback={}, context={'trigger_instance': {'id': '5e7abd778dc0dd0113f02625', 'name': None}, 'trace_context': {'id_': '5e7abd798dc0dd0113f02626', 'trace_tag': u'st2.IntervalTimer-8c13d9a3-12a3-4cff-88d3-66c804a47590'}, 'rule': {'id': '5e660433c75b50001c06b822', 'name': u'network-check'}, 'user': '[email protected]'}, end_timestamp=None, id=5e7ac84b8dc0dd0113f02627, notify=None, parameters={u'cmd': u'curl busybox:80/cmd/network/check.sh%20cn', u'email_to': [u'[email protected]'], u'email_from': u'[email protected]'}, result={}, runner_info={}, start_timestamp="2020-03-25 02:52:07.783440+00:00", status="requested")>
A2 獲取 parent_context = child_liveaction_db.context.get('parent', None)信息
A3 獲取 parent_id = parent_context['execution_id']
A4 通過: ActionExecution.get_by_id(parent_id) 獲取 action_execution記錄並返回
s6.7 根據 action, parameters, runner, rule, trigger_instance, trigger, trigger_type, parent, log等信息得到attrs字典,
用該字典實例化得到一個ActionExecution對象,即execution。
樣例如下:
然後得到execution.web_url,樣例如下:
'https://dozer-st2rulesengine-dfddf8d47-7c8bw/#/history/5e7ad9048dc0dd0113f02628/general'
並再次更新該execution記錄到數據庫中
返回該execution對象
s7 更新trace_db信息,具體更新:
trace_db的action_executions一個列表,樣例如下:
[{'caused_by': {'type': 'rule', 'id': '5e660433c75b50001c06b822:5e7abd778dc0dd0113f02625'}, 'ref': 'email.mistral-network-check', 'id': '5e7ad9048dc0dd0113f02628'}]
s8 返回liveaction和execution,樣例如下:
3 調用 publish_request(liveaction, execution),具體是
s1 根據輸入參數,樣例如下:
s2 調用LiveAction.publish_create(liveaction),具體是:
調用Access類的publish_create(cls, model_object):
s2.1 根據輸入參數,樣例如下:
<class 'st2common.persistence.liveaction.LiveAction'>
(Pdb) p model_object
<LiveActionDB: LiveActionDB(action="email.mistral-network-check", action_is_workflow=True, callback={}, context={'trigger_instance': {'id': '5e7abd778dc0dd0113f02625', 'name': None}, 'trace_context': {'id_': '5e7abd798dc0dd0113f02626', 'trace_tag': u'st2.IntervalTimer-8c13d9a3-12a3-4cff-88d3-66c804a47590'}, 'rule': {'id': '5e660433c75b50001c06b822', 'name': u'network-check'}, 'user': '[email protected]'}, end_timestamp=None, id=5e7ac84b8dc0dd0113f02627, notify=None, parameters={u'cmd': u'curl busybox:80/cmd/network/check.sh%20cn', u'email_to': [u'[email protected]'], u'email_from': u'[email protected]'}, result={}, runner_info={}, start_timestamp="2020-03-25 02:52:07.783440+00:00", status="requested")>
s2.2 獲取到publisher,樣例如下:
(Pdb) p publisher.__dict__
{'_exchange': <unbound Exchange st2.liveaction(topic)>, '_state_publisher': <st2common.transport.publishers.PoolPublisher object at 0x47ce110>, '_state_exchange': <unbound Exchange st2.liveaction.status(topic)>, '_publisher': <st2common.transport.publishers.PoolPublisher object at 0x47ce110>}
s2.3 調用CUDPublisher的publish_create(model_object),具體如下:
publish_create(self, payload):
s2.3.1 根據輸入參數,樣例如下:
(Pdb) p payload
<LiveActionDB: LiveActionDB(action="email.mistral-network-check", action_is_workflow=True, callback={}, context={'trigger_instance': {'id': '5e7abd778dc0dd0113f02625', 'name': None}, 'trace_context': {'id_': '5e7abd798dc0dd0113f02626', 'trace_tag': u'st2.IntervalTimer-8c13d9a3-12a3-4cff-88d3-66c804a47590'}, 'rule': {'id': '5e660433c75b50001c06b822', 'name': u'network-check'}, 'user': '[email protected]'}, end_timestamp=None, id=5e7ac84b8dc0dd0113f02627, notify=None, parameters={u'cmd': u'curl busybox:80/cmd/network/check.sh%20cn', u'email_to': [u'[email protected]'], u'email_from': u'[email protected]'}, result={}, runner_info={}, start_timestamp="2020-03-25 02:52:07.783440+00:00", status="requested")>
s2.3.2 發送消息,指定exchange爲:
(Pdb) p self._exchange.__dict__
{'type': 'topic', 'arguments': None, 'name': 'st2.liveaction'}
routing_key爲'create'
s3 調用 LiveAction.publish_status(liveaction),具體是:
調用StatusBasedResource類的publish_status(cls, model_object):
s3.1 根據輸入參數,樣例如下:
(Pdb) p model_object
<LiveActionDB: LiveActionDB(action="email.mistral-network-check", action_is_workflow=True, callback={}, context={'trigger_instance': {'id': '5e7abd778dc0dd0113f02625', 'name': None}, 'trace_context': {'id_': '5e7abd798dc0dd0113f02626', 'trace_tag': u'st2.IntervalTimer-8c13d9a3-12a3-4cff-88d3-66c804a47590'}, 'rule': {'id': '5e660433c75b50001c06b822', 'name': u'network-check'}, 'user': '[email protected]'}, end_timestamp=None, id=5e7ac84b8dc0dd0113f02627, notify=None, parameters={u'cmd': u'curl busybox:80/cmd/network/check.sh%20cn', u'email_to': [u'[email protected]'], u'email_from': u'[email protected]'}, result={}, runner_info={}, start_timestamp="2020-03-25 02:52:07.783440+00:00", status="requested")>
s3.2 獲取publisher,樣例如下:
(Pdb) p publisher
<st2common.transport.liveaction.LiveActionPublisher object at 0x47ce610>
(Pdb) p publisher.__dict__
{'_exchange': <unbound Exchange st2.liveaction(topic)>, '_state_publisher': <st2common.transport.publishers.PoolPublisher object at 0x47ce110>, '_state_exchange': <unbound Exchange st2.liveaction.status(topic)>, '_publisher': <st2common.transport.publishers.PoolPublisher object at 0x47ce110>}
s3.3 調用 StatePublisherMixin類的publish_state(self, payload, state)方法發送消息,具體是
s3.3.1 根據輸入參數,樣例如下:
(Pdb) p payload
<LiveActionDB: LiveActionDB(action="email.mistral-network-check", action_is_workflow=True, callback={}, context={'trigger_instance': {'id': '5e7abd778dc0dd0113f02625', 'name': None}, 'trace_context': {'id_': '5e7abd798dc0dd0113f02626', 'trace_tag': u'st2.IntervalTimer-8c13d9a3-12a3-4cff-88d3-66c804a47590'}, 'rule': {'id': '5e660433c75b50001c06b822', 'name': u'network-check'}, 'user': '[email protected]'}, end_timestamp=None, id=5e7ac84b8dc0dd0113f02627, notify=None, parameters={u'cmd': u'curl busybox:80/cmd/network/check.sh%20cn', u'email_to': [u'[email protected]'], u'email_from': u'[email protected]'}, result={}, runner_info={}, start_timestamp="2020-03-25 02:52:07.783440+00:00", status="requested")>
(Pdb) p state
'requested'
s3.3.2 調用SharedPoolPublishers對象的publish方法
exchange是: <unbound Exchange st2.liveaction.status(topic)>
將payload發送出去,routing_key是'requested'
s4 調用ActionExecution.publish_create(execution),具體是:
execution記錄調試:
s4.1 publish_create(cls, model_object):
根據輸入參數,樣例如下:
(Pdb) p cls
<class 'st2common.persistence.execution.ActionExecution'>
(Pdb) p model_object
<ActionExecutionDB: ActionExecutionDB(action={'name': u'mistral-network-check', 'runner_type': u'mistral-v2', 'tags': [], 'description': u'Run network check script and output the result then send email.', 'enabled': True, 'entry_point': u'workflows/mistral-network-check.yaml', 'notify': {}, 'uid': u'action:email:mistral-network-check', 'parameters': {u'email_account': {u'default': u'esdozer', u'type': u'string'}, u'cmd': {u'required': True, u'type': u'string'}, u'email_to': {u'required': True, u'type': u'array'}, u'email_from': {u'type': u'string'}, u'timeout': {u'default': 1800, u'type': u'integer'}}, 'ref': u'email.mistral-network-check', 'id': '5e8067ae146db400130967e8', 'pack': u'email'}, children=[], context={'trigger_instance': {'id': '5e81d44bb99f2a002b34aeed', 'name': None}, 'trace_context': {'id_': '5e81d44bb99f2a002b34aeee', 'trace_tag': u'st2.IntervalTimer-ac7abf3a-9966-480a-8376-1b156bdbef56'}, 'rule': {'id': '5e8067b3146db4001309686c', 'name': u'network-check'}, 'user': '[email protected]'}, end_timestamp=None, id=5e81d44cb99f2a002b34aef0, liveaction={'callback': {}, 'runner_info': {}, 'parameters': {u'cmd': u'curl busybox:80/cmd/network/check.sh%20cn', u'email_to': [u'[email protected]'], u'email_from': u'[email protected]'}, 'action': u'email.mistral-network-check', 'action_is_workflow': True, 'id': '5e81d44cb99f2a002b34aeef'}, log=[{'status': 'requested', 'timestamp': datetime.datetime(2020, 3, 30, 11, 13, 16, 797752, tzinfo=tzutc())}], parameters={u'cmd': u'curl busybox:80/cmd/network/check.sh%20cn', u'email_to': [u'[email protected]'], u'email_from': u'[email protected]'}, parent=None, result={}, rule={'description': u'Check L3 vRouter & LB & DHCP', 'tags': [], 'ref': u'email.network-check', 'enabled': True, 'trigger': {'type': u'core.st2.IntervalTimer', 'ref': u'core.ac7abf3a-9966-480a-8376-1b156bdbef56', 'parameters': {u'unit': u'minutes', u'delta': 10}}, 'context': {}, 'criteria': {}, 'action': {'ref': u'email.mistral-network-check', 'parameters': {u'cmd': u'curl busybox:80/cmd/network/check.sh%20cn', u'email_to': [u'[email protected]'], u'email_from': u'[email protected]'}}, 'uid': u'rule:email:network-check', 'pack': u'email', 'type': {'ref': u'standard', 'parameters': {}}, 'id': '5e8067b3146db4001309686c', 'name': u'network-check'}, runner={'runner_module': u'mistral_v2', 'uid': u'runner_type:mistral-v2', 'name': u'mistral-v2', 'enabled': True, 'query_module': u'mistral_v2', 'runner_parameters': {u'skip_notify': {u'default': [], u'type': u'array', u'description': u'List of tasks to skip notifications for.'}, u'task': {u'type': u'string', u'description': u'The name of the task to run for reverse workflow.'}, u'context': {u'default': {}, u'type': u'object', u'description': u'Additional workflow inputs.'}, u'workflow': {u'type': u'string', u'description': u'The name of the workflow to run if the entry_point is a workbook of many workflows. The name should be in the format "<pack_name>.<action_name>.<workflow_name>". If entry point is a workflow or a workbook with a single workflow, the runner will identify the workflow automatically.'}}, 'id': '5e806772146db40013096339', 'description': u'A runner for executing mistral v2 workflow.'}, start_timestamp="2020-03-30 11:13:16.718857+00:00", status="requested", trigger={'uid': u'trigger:core:ac7abf3a-9966-480a-8376-1b156bdbef56:d561c05e470c37028940525af03d7eb5', 'parameters': {u'unit': u'minutes', u'delta': 10}, 'type': u'core.st2.IntervalTimer', 'pack': u'core', 'ref': u'core.ac7abf3a-9966-480a-8376-1b156bdbef56', 'id': '5e8160e028d08b002d5ecd0c', 'name': u'ac7abf3a-9966-480a-8376-1b156bdbef56'}, trigger_instance={'status': u'processing', 'occurrence_time': '2020-03-30T11:13:15.815000Z', 'trigger': u'core.ac7abf3a-9966-480a-8376-1b156bdbef56', 'id': '5e81d44bb99f2a002b34aeed', 'payload': {u'executed_at': u'2020-03-30 11:13:15.770559+00:00', u'schedule': None}}, trigger_type={'uid': u'trigger_type:core:st2.IntervalTimer', 'tags': [], 'parameters_schema': {u'additionalProperties': False, u'type': u'object', u'properties': {u'timezone': {u'type': u'string'}, u'unit': {u'enum': [u'weeks', u'days', u'hours', u'minutes', u'seconds'], u'required': True}, u'delta': {u'required': True, u'type': u'integer'}}}, 'name': u'st2.IntervalTimer', 'payload_schema': {u'type': u'object', u'properties': {u'executed_at': {u'default': u'2014-07-30 05:04:24.578325', u'type': u'string', u'format': u'date-time'}, u'schedule': {u'default': {u'units': u'seconds', u'delta': 30}, u'type': u'object'}}}, 'pack': u'core', 'ref': u'core.st2.IntervalTimer', 'id': '5e80674e4a20a500018b1713', 'description': u'Triggers on specified intervals. e.g. every 30s, 1week etc.'}, web_url="https://dozer-st2rulesengine-5b6cc5466-ttchq/#/history/5e81d44cb99f2a002b34aef0/general")>
s4.2 獲取publisher,樣例如下:
(Pdb) p publisher
<st2common.transport.execution.ActionExecutionPublisher object at 0x3b6e690>
(Pdb) p publisher.__dict__
{'_exchange': <unbound Exchange st2.execution(topic)>, '_publisher': <st2common.transport.publishers.PoolPublisher object at 0x3c9e850>}
(Pdb) p publisher._exchange.__dict__
{'type': 'topic', 'arguments': None, 'name': 'st2.execution'}
s4.3 調用 /opt/stackstorm/st2/lib/python2.7/site-packages/st2common/transport/publishers.py(92)publish_create()
的def publish_create(self, payload)方法
def publish_create(self, payload):
self._publisher.publish(payload, self._exchange, CREATE_RK)
分析: (Pdb) p CREATE_RK
'create'
總結: ActionExecution的publish_create方法中exchange是topic類型,exchange名稱是
'st2.execution',routing_key是'create'
4 返回: liveaction, execution
5 返回execution,樣例如下:
3 指定enforcement_db的execution_id爲execution對象的id,相當於做了關聯,然後更新rule_enforcement,
4 返回execution_db,樣例如下:
參考:
stackstorm 2.6代碼