[saltstack]二次开发和扩展
SALT API
salt 支持restful API和本地接口api
API基础
安装配置
yum install gcc make python-devel libffi-devel yum install salt-api -y
使用RESTful API 接口访问salt:
需要安装独立的 SALT-API 程序
rm -rf /etc/pki/tls/certs/localhost.crt salt-call tls.create_self_signed_cert local: Created Private Key: "/etc/pki/tls/certs/localhost.key." Created Certificate: "/etc/pki/tls/certs/localhost.crt." # useradd -M -s /sbin/nologin saltapi # echo "xxxxxxxx"|passwd saltapi --stdin
# 配置文件
/etc/salt/master.d/api.conf rest_cherrypy: port: 8000 # ssl_crt: /etc/pki/tls/certs/localhost.crt # ssl_key: /etc/pki/tls/certs/localhost.key eauth.conf external_auth: pam: #认证方式 saltapi: #用户名
/etc/init.d/salt-api start
注意把 start stop 之间加个 sleep ,貌似restart的时候 容易失败
启动salt-api之前好像还需要把salt-master也重启一下才行。否则会报401 Unauthorized
通过cherrypy API调用
# 用户权限
# 用以获取 token curl -k https://192.168.102.74:8000/login \ -H "Accept: application/x-yaml" \ -d username='saltapi' \ -d password='xxxxxxx' \ -d eauth='pam' # 使用token访问 curl -k https://192.168.102.74:8000 \ -H "Accept: application/json" \ -H "X-Auth-Token: cffda36ae00eb32045ae71d3d7934a1ab98c75ed" \ -d client='local' \ -d tgt='website1' \ -d fun='cmd.run' \ -d arg="uptime"
cmd_async是异步执行的,不用等待,直接返回一个jid
异步获取结果
# params = {'client':'runner','fun':'jobs.lookup_jid','jid':'20160215133245031359'} # params = {'client':'local_async', 'fun':'state.sls', 'arg':'prod.nginx.service','tgt':'platddb7'} 结果: {u'outputter': u'highstate', u'data': {u'platddb7........................'}
开发举例:
def subscribe_return(func): """ 提供给salt异步方法的装饰器,用于根据jid从redis获取每个minion的执行结果 需要传入一个handler函数处理订阅到的每条消息 :return: {'success': True, 'return': 'Wed Oct 30 18:29:49 CST 2019', 'retcode': 0, 'jid': '20191030182949404233', 'fun': 'cmd.run', 'fun_args': ['date'], 'id': 'zijie-test-1'} """ @wraps(func) def get_job_result(*args, **kwargs): timeout = kwargs.get('timeout', 60) jid = func(*args) tgt = args[1] handler = kwargs.get('handler', None) print(locals()) rs = RedisSubscribe(tgt, 'ret:' + jid, handler) return rs.subscribe(timeout) return get_job_result @subscribe_return def async_remote_execution(self, tgt: list, fun, arg, handler=None, timeout=60): """ 异步执行 :param tgt: :param arg: :param handler: 处理每个minion return数据的方法 :return: 20190514155309184714 """ jid = self.asyncPostRequest(client='local_async', tgt=tgt, fun=fun, ret='redis_pub', tgt_type='list', arg=arg) return jid
local.cmd 调用master本地接口
wheel接口(管理、配置saltmaster)
import salt.config import salt.wheel opts = salt.config.master_config('/etc/salt/master') wheel = salt.wheel.WheelClient(opts) # key 操作 >>> wheel.cmd('key.accept', ['minion1']) {'minions': ['minion1']} # 异步命令 >>> wheel.cmd_async({'fun': 'key.delete', 'match': 'minion1'}) {'jid': '20160826201244808521', 'tag': 'salt/wheel/20160826201244808521'} # 同步命令 >>> wheel.cmd('key.list',['accepted']) >>> wheel.cmd('key.delete',[minion_id])
def list_all_key(self): params={'client':'wheel','fun':'key.list_all'} obj=urllib.urlencode(params) content = self.postRequest(obj) minions = content['return'][0]['data']['return']['minions'] minions_pre = content['return'][0]['data']['return']['minions_pre'] return minons,minions_pre params={'client':'wheel','fun':'key.delete','match':node_name} params={'client':'wheel','fun':'key.accept','match':node_name} client: >>> import salt.client >>> local = salt.client.LocalClient() >>> local.cmd('*', 'cmd.run', ['whoami']) local.cmd('*', 'test.ping')
自2017.x版本后 参数expr_form ==> tgt_type # 组 local.cmd('website','cmd.run',['ls -al'],expr_form='nodegroup') # minion列表 local.cmd(hosts,'test.ping',[],expr_form='list') # 多个命令 client.cmd('*', ['cmd.run', 'test.ping', 'test.echo'], [['ls -l'], [], ['foo']]) # cmd.script local.cmd('website1','cmd.script',['salt://MyScript.sh','-o']) >>> local.cmd('website1','cmd.run',['su - ecp -c whoami']) {'website1': 'ecp'} # salt-ssh 的调用方法 from salt.client.ssh.client import SSHClient client = SSHClient() print client.cmd(tgt='192.168.21.1', fun='test.ping') {'192.168.21.1': {'fun_args': [], 'jid': '20151120134918813118', 'return': True, 'retcode': 0, 'fun': 'test.ping', 'id': '192.168.21.1'}} print client.cmd(tgt='192.168.21.1', fun='cmd.run',arg=['uptime']) {'192.168.21.1': {'fun_args': ['uptime'], 'jid': '20151121062535759565', 'return': ' 06:25:35 up 18 days, 15:33, 0 users, load average: 0.13, 0.11, 0.09', 'retcode': 0, 'fun': 'cmd.run', 'id': '192.168.21.1'}} import salt.grains.core hostname = salt.grains.core.hostname()['fqdn'] # 查看本地是不是有这个命令 >>> import salt.utils >>> salt.utils.which('dig') '/usr/bin/dig' # 自带的json方法 import salt.utils.json salt.utils.json.dumps(ret)