Actions是可以执行随意修复任务的代码片。它们可以被任意编程语言所编写。
下面时可以被实现的简短的任务列表。
重启一个服务器的服务
创建一个新的云主机
....
当一个Rule的准则criteria被匹配的时候,动作就被触发了。
多个动作可以被设计在一起作为一个工作流。
动作也可以通过客户端以命令行,API或者UI的形式直接被执行。
命令行通过st2 action
查看可执行的命令列表,运行如下命令:
st2 action --help
输出结果:
usage: st2 action [-h]
{list,get,create,update,delete,enable,disable,execute} ...
An activity that happens as a response to the external event.
positional arguments:
{list,get,create,update,delete,enable,disable,execute}
List of commands for managing actions.
list Get the list of actions.
get Get individual action.
create Create a new action.
update Updating an existing action.
delete Delete an existing action.
enable Enable an existing action.
disable Disable an existing action.
execute Invoke an action manually.
optional arguments:
-h, --help show this help message and exit
为了获取一个action命令更多的信息,运行: st2 action
例如,下面将会提供list命令的帮助信息。
st2 action list -h
输出结果:
usage: st2 action list [-h] [-t TOKEN] [--api-key API_KEY] [-j] [-y]
[-a ATTR [ATTR ...]] [-w WIDTH [WIDTH ...]] [-p PACK]
Get the list of actions.
optional arguments:
-h, --help show this help message and exit
-t TOKEN, --token TOKEN
Access token for user authentication. Get
ST2_AUTH_TOKEN from the environment variables by
default.
--api-key API_KEY Api Key for user authentication. Get ST2_API_KEY from
the environment variables by default.
-j, --json Print output in JSON format.
-y, --yaml Print output in YAML format.
-a ATTR [ATTR ...], --attr ATTR [ATTR ...]
List of attributes to include in the output. "all"
will return all attributes.
-w WIDTH [WIDTH ...], --width WIDTH [WIDTH ...]
Set the width of columns in output.
-p PACK, --pack PACK Only return resources belonging to the provided pack
下面的命令显示了如何获取可用的actions和它们的参数
列出所有可用的动作:
st2 action list
输出结果:
+----------------------------------------------------+----------+----------------------------------------------------+
| ref | pack | description |
+----------------------------------------------------+----------+----------------------------------------------------+
| chatops.format_execution_result | chatops | Format an execution result for chatops |
| chatops.match | chatops | Match a string to an action alias |
| chatops.match_and_execute | chatops | Execute a chatops string to an action alias |
| chatops.post_message | chatops | Post a message to stream for chatops |
| chatops.post_result | chatops | Post an execution result to stream for chatops |
| chatops.run | chatops | Match a text chatops command, execute it and post |
| | | the result |
| core.announcement | core | Action that broadcasts the announcement to all |
| | | stream consumers. |
| core.ask | core | Action for initiating an Inquiry (usually in a |
| | | workflow) |
| core.echo | core | Action that executes the Linux echo command on the |
| | | localhost. |
| core.http | core | Action that performs an http request. |
| core.inject_trigger | core | Action which injects a new trigger in the system. |
| core.local | core | Action that executes an arbitrary Linux command on |
| | | the localhost.
......
列出linux 包的所有动作
st2 action list -p linux
输出结果:
+-----------------------+-------+----------------------------------------------------+
| ref | pack | description |
+-----------------------+-------+----------------------------------------------------+
| linux.check_loadavg | linux | Check CPU Load Average on a Host |
| linux.check_processes | linux | Check Interesting Processes |
| linux.cp | linux | Copy file(s) |
| linux.diag_loadavg | linux | Diagnostic workflow for high load alert |
| linux.dig | linux | Dig action |
| linux.file_touch | linux | Touches a file |
| linux.lsof | linux | Run lsof |
| linux.lsof_pids | linux | Run lsof for a group of PIDs |
| linux.mv | linux | Move file(s) |
| linux.netstat | linux | Run netstat |
| linux.netstat_grep | linux | Grep netstat results |
| linux.pkill | linux | Kill processes using pkill |
| linux.rm | linux | Remove file(s) |
| linux.rsync | linux | Copy file(s) from one place to another w/ rsync |
| linux.scp | linux | Secure copy file(s) |
| linux.service | linux | Stops, Starts, or Restarts a service |
| linux.traceroute | linux | Traceroute a Host |
| linux.vmstat | linux | Run vmstat |
| linux.wait_for_ssh | linux | Action which waits for a SSH server to become |
| | | accessible. By default, if no credentials are |
| | | provided, this action will try to authenticate |
| | | using the system user username and key file. |
+-----------------------+-------+----------------------------------------------------+
展示一个特定的动作 linux.check_loadavg
st2 action get linux.check_loadavg
输出结果:
+---------------+--------------------------------------------------------------+
| Property | Value |
+---------------+--------------------------------------------------------------+
| id | 5c3823a79dc6d67dc88dbdb1 |
| uid | action:linux:check_loadavg |
| ref | linux.check_loadavg |
| pack | linux |
| name | check_loadavg |
| description | Check CPU Load Average on a Host |
| enabled | True |
| entry_point | checks/check_loadavg.py |
| runner_type | remote-shell-script |
| parameters | { |
| | "period": { |
| | "default": "all", |
| | "position": 0, |
| | "enum": [ |
| | "1", |
| | "5", |
| | "15", |
| | "all" |
| | ], |
| | "type": "string", |
| | "description": "Time period for load avg: 1,5,15 |
| | minutes, or 'all'" |
| | } |
| | } |
| metadata_file | actions/check_loadavg.yaml |
| notify | |
| output_schema | |
| tags | |
+---------------+--------------------------------------------------------------+
获取action的参数
st2 run linux.check_loadavg -h
输出结果:
Check CPU Load Average on a Host
Required Parameters:
hosts
A comma delimited string of a list of hosts where the remote command
will be executed.
Type: string
Optional Parameters:
period
Time period for load avg: 1,5,15 minutes, or 'all'
Type: string
Enum: 1, 5, 15, all
Default: all
bastion_host
The host SSH connections will be proxied through. Note: This
connection is made using the same parameters as the final connection,
and is only used in ParamikoSSHRunner.
Type: string
cwd
Working directory where the script will be executed in.
Type: string
Default: /tmp
dir
The working directory where the script will be copied to on the remote
host.
Type: string
Default: /tmp
......
为了能够手动执行一个动作,你可以使用 st2 run
st2 action execute
立即执行动作并显示结果
st2 run core.http url="http://httpbin.org/get"
输出结果:
.
id: 5c388ae79dc6d602090eb7ec
status: succeeded
parameters:
url: http://httpbin.org/get
result:
body:
args: {}
headers:
Accept: '*/*'
Accept-Encoding: gzip, deflate
Connection: close
Host: httpbin.org
User-Agent: st2/v2.10.1
X-Stanley-Action: http
origin: 218.94.118.90
url: http://httpbin.org/get
headers:
Access-Control-Allow-Credentials: 'true'
Access-Control-Allow-Origin: '*'
Connection: keep-alive
Content-Length: '288'
Content-Type: application/json
Date: Fri, 11 Jan 2019 12:24:08 GMT
Server: gunicorn/19.9.0
Via: 1.1 vegur
parsed: true
status_code: 200
调度action执行
st2 action execute core.http url="http://httpbin.org/get"
输出结果:
To get the results, execute:
st2 execution get 5c388b2f9dc6d602090eb7ef
To view output in real-time, execute:
st2 execution tail 5c388b2f9dc6d602090eb7ef
执行:
st2 execution get 5c388b2f9dc6d602090eb7ef
输出结果:
id: 5c388b2f9dc6d602090eb7ef
status: succeeded (1s elapsed)
parameters:
url: http://httpbin.org/get
result:
body:
args: {}
headers:
Accept: '*/*'
Accept-Encoding: gzip, deflate
Connection: close
Host: httpbin.org
User-Agent: st2/v2.10.1
X-Stanley-Action: http
origin: 218.94.118.90
url: http://httpbin.org/get
headers:
Access-Control-Allow-Credentials: 'true'
Access-Control-Allow-Origin: '*'
Connection: keep-alive
Content-Length: '288'
Content-Type: application/json
Date: Fri, 11 Jan 2019 12:25:20 GMT
Server: gunicorn/19.9.0
Via: 1.1 vegur
parsed: true
status_code: 200
执行:
st2 execution tail 5c388b2f9dc6d602090eb7ef
输出结果:
Execution 5c388b2f9dc6d602090eb7ef has completed (status=succeeded).
如果你想要添加追踪标记到执行中,你可以使用:
st2 run core.local cmd=date --trace-tag="simple-date-check-`date +%s`"
输出结果:
.
id: 5c388be19dc6d602090eb7f2
status: succeeded
parameters:
cmd: date
result:
failed: false
return_code: 0
stderr: ''
stdout: "2019年 01月 11日 星期五 20:28:17 CST"
succeeded: true
一个action runner时用户实现的动作在环境中的执行过程。
StackStorm用预先指定号的动作runners例如remote runner和shell runner
,这样用户可以进行远程(通过ssh)和本地的用户动作。目的时为了允许动作的开发者可以聚焦
到动作本身而非时设置环境。
action运行的环境是被runner所指定的。目前系统提供了如下的runner:
1) local-shell-cmd
这时一个本地的runner。这个runner执行本地宿主机上的linux命令。
2) local-shell-script
这个时本地的runner。动作以脚本的形式实现。它们被有StackStorm运行的
宿主机所执行。
3) remote-shell-cmd
这个是远程的runner。这个runner执行一个或多个远程主机上的linux命令。
4) remote-shell-script
这是一个远程runner。动作以脚本的形式实现。它们运行在一个或多个远程主机上。
5) python-script
这个时python的runner。动作以Python类的形式实现,该类有一个run()方法。
它们运行在StackStorm组件运行的机器上。run()方法的返回值要么是一个
成功状态该标记和结果对象的元组,要么是结果对象。
更多信息请参考:
https://docs.stackstorm.com/reference/runners.html
6) http-request
可以执行http请求来运行http动作的http客户端。
7) action-chain
这个runner支持执行简单的线性工作流。
8) mistral-v2
这个runner被内置在Mistral Openstack项目,并且支持执行复杂的工作流。
更多信息请参见Workflows和Mistral的文章。
9) cloudlang
这个runner被内置在CloudSlang项目中,并且支持复杂的工作流。
10) inquirer
这个runner提供了Inquires特性核心的逻辑。
11) winrm-cmd
这个WinRM命令runner允许你通过WinRM协议来执行Windows宿主机上的命令行
12) winrm-ps-cmd
这个WinRM PowerShell命令runner允许你通过WinRM协议来执行
在Windows宿主机上的PowerShell脚本。
Runners有它们自己的输入参数集合。当一个动作被执行,它集成了这些runner的参数,
另外添加它们自己的参数。
一个action由两部分组成:
1) 一个YAML 元数据文件用来描述动作,和它的输入。
2) 一个脚本文件用来实现动作的逻辑。
正如上述提到的,一个动作脚本可以被任意编程语言实现,只要它遵循下面这些规则:
1) 脚本应该以0状态码作为成功,以非0作为失败
2) 所有日志消息应该被打印到标准错误上
Action元数据
Action 元数据被用来描述动作,并被定义为YAML格式。这些属性可以
在元数据文件中存在:
name: 动作名称
runner_type: 执行动作的运行器类型
enabled: 当为disabled时,动作不能被调用
entry_point: 动作发布脚本相关的位置。
/opt/stackstorm/packs/${pack_name}/actions/
目录。
parameters: 一个参数字典和可选的用于描述类型和默认的元数据。
这个元数据以JSON格式来组织数据。共同的参数类型可以时:
string, boolean, number(例如 1.0, 1, 3.3333等),
object, integer(例如 1000)和array。
如果元数据被提供了,输入参数可以在动作执行的时候被校验。
否则,校验会省略。
tags: 动作的一个tags数组,用于提供信息的补充。
下面是一个元数据文件的样例,通过Twilio web服务发送SMS:
---
name: "send_sms"
runner_type: "python-script"
description: "This sends an SMS using twilio."
enabled: true
entry_point: "send_sms.py"
parameters:
from_number:
type: "string"
description: "Your twilio 'from' number in E.164 format. Example +14151234567."
required: true
position: 0
to_number:
type: "string"
description: "Recipient number in E.164 format. Example +14151234567."
required: true
position: 1
secret: true
body:
type: "string"
description: "Body of the message."
required: true
position: 2
default: "Hello {% if system.user %} {{ st2kv.system.user }} {% else %} dude {% endif %}!"
可以通过st2kv.system来获取参数。例如:
parameters:
user:
type: "string"
description: "User of this action."
required: true
default: "{{action_context.api_user}}"
前缀action_context被用于参考action context变量。
你也可以通过你的pack配置来访问config_context.
样例如下:
---
name: "send_sms"
runner_type: "python-script"
description: "This sends an SMS using twilio."
enabled: true
entry_point: "send_sms.py"
parameters:
from_number:
type: "string"
description: "Your twilio 'from' number in E.164 format. Example +14151234567."
required: false
position: 0
default: "{{config_context.from_number}}"
to_number:
type: "string"
description: "Recipient number in E.164 format. Example +14151234567."
required: true
position: 1
secret: true
body:
type: "string"
description: "Body of the message."
required: true
position: 2
default: "Hello {% if system.user %} {{ st2kv.system.user }} {% else %} dude {% endif %}!"
在ActionChains和工作流中,工作流中的每个task可以访问父亲的execution_id。
例如,下面是一个动作链的任务:
...
-
name: "c2"
ref: "core.local"
parameters:
cmd: "echo \"c2: parent exec is {{action_context.parent.execution_id}}.\""
on-success: "c3"
on-failure: "c4"
...
为了注册一个新的动作:
1) 将它放在内容位置
2) 告诉系统这个动作是可以获取的
这个动作被防止在packs中,位置在 /opt/stackstorm/packs
惯例的动作,是使用default pack,仅仅在
/opt/stackstorm/packs/default/actions 创建你的动作,
一旦你已经测试出结果,你可以将它移动到一个专用的pack中。
通过
st2 action create my_action_metadata.yaml
来注册一个单独的动作。为了加载所有的动作,请使用
st2ctl reload --register-actions
当配置metadata的时候,有以恶邪内置的参数可以使用,可以
覆盖来修改默认功能的各种runners:
args - (local-shell-script, remote-shell-script)
默认,StackStorm将使用用户定义的参数。
cmd - (local-shell-script, remote-shell-script)
配置目标系统将要运行的命令
cwd - (local-shell-script, remote-shell-script)
执行的位置
env - (local-shell-script, local-shell-script-script, remote-shell-script, remote-shell-script-script, python-script)
环境变量
dir - (local-shell-script, remote-shell-script)
配置脚本拷贝的目录,默认是/tmp
linux.rsync动作覆盖了remote-shell-cmd运行器的cmd参数。
样例如下:
---
name: 'rsync'
runner_type: 'remote-shell-cmd'
description: 'Copy file(s) from one place to another w/ rsync'
enabled: true
entry_point: ''
parameters:
source:
type: 'string'
description: 'List of files/directories to to be copied'
required: true
dest_server:
type: 'string'
description: "Destination server for rsync'd files"
required: true
destination:
type: 'string'
description: 'Destination of files/directories on target server'
required: true
cmd:
immutable: true
default: 'rsync {{args}} {{source}} {{dest_server}}:{{destination}}'
connect_timeout:
type: 'integer'
description: 'SSH connect timeout in seconds'
default: 30
args:
description: 'Command line arguments passed to rysnc'
default: '-avz -e "ssh -o ConnectTimeout={{connect_timeout}}"'
默认 local, remote和Python运行器可以获取如下的环境变量
ST2_ACTION_PACK_NAME - Name of the pack to which the currently executed action belongs to.
ST2_ACTION_EXECUTION_ID - Execution ID of the action being currently executed.
ST2_ACTION_API_URL - Full URL to the public API endpoint.
ST2_ACTION_AUTH_TOKEN - Auth token which is available to the action until it completes. When the action completes, the token gets revoked.
下面是一个例子
#!/usr/bin/env bash
# Retrieve a list of actions by hitting the API using cURL and the information provided
# via environment variables
RESULT=$(curl -H "X-Auth-Token: ${ST2_ACTION_AUTH_TOKEN}" ${ST2_ACTION_API_URL}/actions)
echo ${RESULT}
如果你有一个已经存在的用任意语言编写的独立脚本,你可以将它转换成一个
action动作,处理过程非常简单。
遵循如下步骤:
1) 确保脚本转换遵守约定
你应该确保脚本成功退出时返回0,异常退出时返回1.这个非常重要,因为
退出状态码会被StackSTorm用于确定该脚本是否成功完成。
2)创建一个metadata文件
你需要创建一个元数据文件来描述脚本的名称,描述,entry point,使用的哪个runner以及脚本参数(
如果有的话)。
当转换一个已经存在的脚本,你可以使用local-shell-script或者remote-shell-script的runner。
3) 在脚本中更新参数解析
本地和远程脚本runners识别两种类型的参数:
A. named: 这些参数不包含在position属性
B. positional: 这些参数包含position属性
所有的参数都会通过命令行参数传递给脚本。
命名named(实际就是键值对类似的参数)参数通过如下形式传递给脚本:
script.sh --param1=value --param2=value --param3=value
默认,每隔参数的前缀是两个横杠(--)。如果你想要使用单个横杠(-),一些其他的
前缀或者没有前缀,你可以在元数据文件中配置使用kwarg_op参数。
例如:
---
name: "my_script"
runner_type: "remote-shell-script"
description: "Script which prints arguments to stdout."
enabled: true
entry_point: "script.sh"
parameters:
key1:
type: "string"
required: true
key2:
type: "string"
required: true
key3:
type: "string"
required: true
kwarg_op:
type: "string"
immutable: true
default: "-"
在这种情况下,参数以如下形式传递给脚本:
script.sh -key1=value1 -key2=value2 -key3=value3
位置参数通过position的值以固定顺序被传递到脚本:
script.sh value2 value1 value3
如果你的脚本仅仅使用位置参数,你可以在metadata文件中声明
正确的position值。位置参数基于如下的简单规则来被序列化。
1) string, integer, float - 序列话为一个字符串
2) boolean 序列化为字符串1(true)或0(false)
3) array 序列化为逗号分割的字符串(例如: foo,bar,baz)
4) object 序列化为一个JSON
使用这个简单的序列化格式允许用户在他们的脚本中很容易地通过
使用标准的Bash functionality(-z用于检查一个值是否被提供,
-eq用于比较1/0, IFS用于将一个字符串分割为一个数组)使用这些值.
如果没有值用来提供给一个固定位置参数,StackStorm将会传递一个空字符串
""作为这个参数的值来传递给脚本。
例如,如果第二个参数是可选的,并且用户没有提供值,脚本会被如下形式调用:
script.sh value1 "" value3
immutable值定义了是否参数的默认值可以被修改。
加入我们有一个简单的Base脚本叫做send_to_syslog.sh,该脚本
通过命令行参数将消息写入到syslog中。
这个脚本有两个参数:
1) syslog server的地址
2) 将要写入的信息
#!/usr/bin/env bash
SERVER=$1
MESSAGE=$2
logger -n ${SERVER} ${MESSAGE}
既然这个脚本使用了固定位置参数,你值需要在元文件中进行如下定义:
---
name: "send_to_syslog.log"
runner_type: "remote-shell-script"
description: "Send a message to a provided syslog server."
enabled: true
entry_point: "send_to_syslog.sh"
parameters:
server:
type: "string"
description: "Address of the syslog server"
required: true
position: 0
message:
type: "string"
description: "Message to write"
required: true
position: 1
正如你所看到的,我们声明了两个参数: server和message。
它们两个都声明了一个position属性(0用于server,1用于message),
这意味着它们将要以固定参数被传入到动作脚本中,因此你的脚本不需要做任何改动。
在最简单的形式中,一个Python动作是一个模块。该模块暴露了一个类,这个类集成自
st2common.runners.base_action.Action,并实现了一个run方法
12.1 简单的Python动作
下面是元数据文件(my_echo_action.yaml):
---
name: "echo_action"
runner_type: "python-script"
description: "Print message to standard output."
enabled: true
entry_point: "my_echo_action.py"
parameters:
message:
type: "string"
description: "Message to print."
required: true
position: 0
动作脚本文件(my_echo_action.py):
import sys
from st2common.runners.base_action import Action
class MyEchoAction(Action):
def run(self, message):
print(message)
if message == 'working':
return (True, message)
return (False, message)
这个Python动作打印了通过message参数提供的文本到标准输出上。
正如你所看到的,用户提供的action参数是被传递到run方法作为keyword参数。
如果run方法完成过程中没有异常,那么本次执行是成功的,该方法返回值
(任何值: boolean, string, list, dict等等)会被考虑为它的结果。
跑出异常将会报告此次执行是失败的。
另一种方式来指定一次执行的状态是返回一个包含两个元素的元组:
第一个元素是一个布尔值来表明状态,第二个元素是结果本身。
例如,return False将会导致一个携带有result为False的成功执行,
而return (False, "Failed!")是一次携带有"Failed!"作为结果的失败的执行。
在上述例子中,如果message参数是以working被传入到action中,那么action将会被认为是成功的
(结果中的第一个标记表明动作的状态该是True)。如果另一个消息被传入进来,
action会被认为是failed(结果元组中第一个标记表明动作状态是False)。
Pytyhon动作可以在配置文件中存储任意的配置,该配置文件是对整个pack生效的。
这个配置被存储在一个名叫
/opt/stackstorm/configs/ 目录。
配置完呢键的格式是YAML。配置自动被解析,并通过config参数传递到动作类的构造函数中。
所有动作中的日志都会被logggerf来执行,该loggger指定了这个动作以及通过self.logger类属性可以获得。
这个logger是一个来自logging模块的标准Python loggger,因此所有的logger方法如预期般工作(
例如logger.debug, logger.info等等)。
例如:
def run(self):
...
success = call_some_method()
if success:
self.logger.info('Action successfully completed')
else:
self.logger.error('Action failed...')
与sensors相似,在实例化后,action_service是可以在每个动作实例中获得的。
Action service为action通过public方法提供了不同的服务。现在,它支持
datastore管理方法的支持。这就允许动作可以利用datastore来存executions之间的储任意数据。
Action服务提供了相同的datastore管理方法,正如sensor服务中可以获取到一样。
你可以在sensor datastore management 中找到功多细节。
存储dict为JSON的例子:
def run(self):
data = {'somedata': 'foobar'}
# Add a value to the datastore
self.action_service.set_value(name='cache', value=json.dumps(data))
# Retrieve a value
value = self.action_service.get_value('cache')
retrieved_data = json.loads(value)
# Retrieve an encrypted value
value = self.action_service.get_value('ma_password', decrypt=True)
retrieved_data = json.loads(value)
# Delete a value
self.action_service.delete_value('cache')
在Python传感器和Actions中共享代码
参考文档在python动作和传感器只见共享共同的代码
StackStorm有一些预先定义的动作。它们在core包中。
1) core.local: 这个动作允许在本地执行任意的的 *nix/shell命令。
你可以通过命令行来执行这个命令:
st2 run core.local cmd='ls -l'
2) core.remote: 这个动作允许在本地执行任意的的 *nix/shell命令。
通过命令行执行命令:
st2 run core.remote cmd=='ls -l' hosts='host1,host2' username='user1'
3) core.http: 这个动作允许执行http请求的执行。在StackStorm中执行curl:
st2 run core.http url="http://httpbin.org/get" method="GET"
与curl相似,这个动作支持当提供一个用户名和密码的基本校验:
st2 run core.http url="http://httpbin.org/get" method="GET" username=user1 password=pass1
查看core pack的所有动作请执行:
st2 action list --pack=core
参考:
https://docs.stackstorm.com/actions.html