SaltStack实战应用
来源:互联网 发布:如何开通淘宝 编辑:程序博客网 时间:2024/06/10 22:35
ZMQ (以下 ZeroMQ 简称 ZMQ),封装好的 socket library传输层消息队列处理库,让 Socket 编程更加简单、简洁和性能更高,可在多个线程、内核和主机盒之间弹性伸缩。它无疑是极具前景的、并且是人们更加需要的“传统”BSD 套接字之上的一层封装。ZMQ 让编写高性能网络应用程序极为简单和有趣。
类似于 Socket 的一系列接口,他跟 Socket 的区别是:普通的 socket 是端到端的(1:1的关系),而 ZMQ 却是可以N:M 的关系,人们对 BSD 套接字的了解较多的是点对点的连接,点对点连接需要显式地建立连接、销毁连接、选择协议(TCP/UDP)和处理错误等,而 ZMQ 屏蔽了这些细节,让你的网络编程更为简单。ZMQ 用于 node 与 node 间的通信,node 可以是主机或者是进程。
tcp 0 0 0.0.0.0:4505 0.0.0.0:* LISTEN 45667/python2.6
[root@NameNode ~]# netstat -ntupl|grep 4506
tcp 0 0 0.0.0.0:4506 0.0.0.0:* LISTEN 45674/python2.6
在file_roots里设置,注意YAM的语法。
执行/etc/salt/production/路径下info_clooection目录下sls目录下的hardware_info_collect的sls文件,用 . 代替目录的 /,这也是语法。
#!/bin/env python# -*- coding: utf-8 -*-# @Time:2017/4/14 14:53import salt.configimport salt.loaderimport subprocessimport os__opts__ = salt.config.minion_config('/etc/salt/minion')__grains__ = salt.loader.grains(__opts__)def network_info(): network_dict = {} nic_list = {} for nic, mac in __grains__['hwaddr_interfaces'].items(): nic_list[nic] = [mac] try: nic_list[nic].append( __grains__['ip_interfaces'][nic][0]) except IndexError: nic_list[nic].append('') network_dict['nic_device'] = nic_list network_dict['dns'] = __grains__['dns']['nameservers'] default_gateway = subprocess.Popen("route | grep default | awk '{print $2}'",shell=True,stdout=subprocess.PIPE) gateway = default_gateway.stdout.read().strip("\n") if gateway: network_dict['gateway'] = gateway else: network_dict['gateway'] = '' return network_dictdef ram_info(): ram_dict = {} # ram_raw_info = subprocess.check_output('/usr/sbin/dmidecode -t 17',shell=True) ram_list = [] ram_unit_list = [] ram_unit = False ram_info_list = [] ram_raw_info = subprocess.Popen("/usr/sbin/dmidecode -t 17",shell=True,stdout=subprocess.PIPE) # gateway = default_gateway.stdout.read().strip("\n") dmi_memory_list = ram_raw_info.stdout.read().split('\n') for index,line in enumerate(dmi_memory_list): if line.startswith("Memory Device"): ram_unit = True if not line.startswith("Memory Device") and ram_unit: if line.startswith('Handle'): ram_unit = False ram_list.append(ram_unit_list) ram_unit_list = [] else: ram_unit_list.append(line.strip()) if index == len(dmi_memory_list)-1: ram_list.append(ram_unit_list) for ram_item in ram_list: for item in ram_item: item_list = item.split(':') if len(item_list) == 2: k,v = item_list if k == 'Size': if v.strip() != "No Module Installed": ram_item_dic = {} ram_item_dic['capacity'] = v.strip() else: break if k == "Locator": ram_item_dic['slot'] = v.strip() if k == "Type": ram_item_dic['model'] = v.strip() if k == 'Type Detail': ram_item_dic['model'] = ram_item_dic['model'] + " " + v.strip() if k == "Speed": ram_item_dic['model'] = ram_item_dic['model'] + " " + v.strip() if k == "Manufacturer": ram_item_dic['manufacture'] = v.strip() if k == "Serial Number": ram_item_dic['sn'] = v.strip() ram_info_list.append(ram_item_dic) swap = subprocess.Popen("free -m | grep Swap | awk '{print $2}'",shell=True,stdout=subprocess.PIPE) swap_capacity = swap.stdout.read().strip("\n") if swap_capacity: ram_dict['swap'] = "%sMB" % swap_capacity else: ram_dict['swap'] = "" ram_dict['Physical_Ram_Total'] = "%sMB" % __grains__['mem_total'] ram_dict['Physical_Ram_Detail'] = ram_info_list # print (ram_info_list) return ram_dictdef os_info(): os_dict = {} os_dict['osmajorrelease'] = __grains__['osmajorrelease'] os_dict['os_family'] = __grains__['os_family'] os_dict['os_distribution'] = '%s %s' %(__grains__['osfullname'], __grains__['osrelease']) os_dict['osrelease'] = __grains__['osrelease'] os_dict['osarch'] = __grains__['osarch'] return os_dictdef cpu_info(): cpu_dict = {} cpu_dict['cpu_mode'] = __grains__['cpu_model'] cpu_dict['num_cpus'] = __grains__['num_cpus'] cpu_dict['cpuarch'] = __grains__['cpuarch'] return cpu_dictdef fc_disk(disk_name_list, disk_and_size): disk_fc = subprocess.Popen("ls -l /dev/disk/by-path/ | tail -n +2 | awk '(filed=NF){if($(filed-2) !~ /part.*$/ && $(filed-2) ~/-fc-/) print $(filed-2),$NF}' | sort -nr | sed 's/^.*:0x/0x/g'", shell=True,stdout=subprocess.PIPE) disk_fc_str = disk_fc.stdout.read().strip("\n") #stdout.read is synchronous fc_disk_dict = {} if disk_fc_str: #has fc storage disk_dict = {} disk_fc_list = disk_fc_str.split("\n") disk_fc_new = [ i.split() for i in disk_fc_list] for disk in disk_fc_new: disk_dict.update({disk[0]:disk[1]}) #The keys of a dictionary are inherently unique,use a dictionary to #remove duplicate disk(Multipath disk) diskname_fc_list = [ i.lstrip('../../') for i in disk_dict.values()] fc_parttion_list = list(set(disk_name_list).intersection(set(diskname_fc_list))) #fc disk list for fc_disk in fc_parttion_list: fc_disk_dict.update({fc_disk:disk_and_size[fc_disk]}) return fc_disk_dictdef iscsi_disk(disk_name_list, disk_and_size): iscsi_disk_dict = {} disk_iscsi = subprocess.Popen("ls -l /dev/disk/by-path/ | tail -n +2 | awk '(filed=NF){if($(filed-2) !~ /part.*$/ && $(filed-2) ~/-iscsi-/) print $(filed-2),$NF}' | sort -nr",shell=True,stdout=subprocess.PIPE) disk_iscsi_str = disk_iscsi.stdout.read().strip("\n") if disk_iscsi_str: #has iscsi storage disk_dict = {} disk_iscsi_iqn_list = [] disk_iscsi_list = disk_iscsi_str.split("\n") disk_iscsi_new = [ i.split() for i in disk_iscsi_list] for target in disk_iscsi_new: j = [] m=target[0].split("-iscsi-") j.append(m[1]) j.append(target[1]) disk_iscsi_iqn_list.append(j) for disk in disk_iscsi_iqn_list: disk_dict.update({disk[0]:disk[1]}) #The keys of a dictionary are inherently unique,use a dictionary to #remove duplicate disk(Multipath disk) diskname_iscsi_list = [ i.lstrip('../../') for i in disk_dict.values()] iscsi_parttion_list = list(set(disk_name_list).intersection(set(diskname_iscsi_list))) # iscsi disk list for iscsi_disk in iscsi_parttion_list: iscsi_disk_dict.update({iscsi_disk:disk_and_size[iscsi_disk]}) return iscsi_disk_dictdef local_disk(disk_name_list, disk_and_size): disk_local = subprocess.Popen("ls -l /dev/disk/by-path/ | tail -n +2 | awk '(filed=NF){if($(filed-2) !~ /part.*$/ && $(filed-2) !~/-fc-/ && $(filed-2) !~/-iscsi-/) print $(filed-2),$NF}'",shell=True,stdout=subprocess.PIPE) disk_local_str = disk_local.stdout.read().strip("\n") local_disk_dict = {} if disk_local_str: #local storage disk_local_list = disk_local_str.split("\n") disk_local_new = [ i.split() for i in disk_local_list] diskname_local_list = [ i[1].lstrip('../../') for i in disk_local_new ] local_parttion_list = list(set(disk_name_list).intersection(set(diskname_local_list))) #local disk list if local_parttion_list: for local_disk in local_parttion_list: local_disk_dict.update({local_disk:disk_and_size[local_disk]}) cciss_disk=os.path.exists('/proc/driver/cciss/') #hp cciss driver disk if cciss_disk: cciss_disk_list = [ i for i in disk_name_list if 'cciss/' in i and 'p' not in i] for cciss in cciss_disk_list: local_disk_dict.update({cciss:disk_and_size[cciss]}) return local_disk_dictdef disk_info(): disk_dict = {} disk_and_size = {} #from /proc/partitions disk_parttion = subprocess.Popen("cat /proc/partitions | tail -n +2 | awk '{print $3,$4}'", shell=True, stdout=subprocess.PIPE ) df_parttion = subprocess.Popen( "df -P | tail -n +2 | awk '$1 ~/\/dev/ {print $1}' | sed 's/\/dev\///g'", shell=True, stdout=subprocess.PIPE ) disk_parttion_str = disk_parttion.stdout.read().strip("\n") df_parttion_str = disk_parttion.stdout.read().strip("\n") disk_parttion_list = [ i.split() for i in disk_parttion_str.strip().split("\n")] # # list item include disk name and partition size for i in disk_parttion_list: #disk size dict key: disk name value: disk size disk_and_size.update({i[1]:i[0]}) disk_name_list = [ i[1] for i in disk_parttion_list] #get disk name from /proc/parttions localdisk = local_disk(disk_name_list, disk_and_size) fcdisk = fc_disk(disk_name_list, disk_and_size) iscsidisk = iscsi_disk(disk_name_list, disk_and_size) disk_dict['local'] = localdisk disk_dict['fc'] = fcdisk disk_dict['iscsi'] = iscsidisk return disk_dictdef info_collect(): host_info_dict = {} network = network_info() ram = ram_info() os = os_info() cpu = cpu_info() disk = disk_info() host_info_dict['os'] = os host_info_dict['cpu'] = cpu host_info_dict['ram'] = ram host_info_dict['network'] = network host_info_dict['disk'] = disk host_info_dict['productname'] = __grains__['productname'] host_info_dict['manufacturer'] = __grains__['manufacturer'] host_info_dict['serialnumber'] = __grains__['serialnumber'] host_info_dict['hostname'] = __grains__['host'] host_info_dict['hosttype'] = 'physical' if __grains__['virtual'] == 'physical' else 'virtual' host_info_dict['kernelrelease'] = __grains__['kernelrelease'] host_info_dict['shell'] = __grains__['shell'] host_info_dict['saltversion'] = __grains__['saltversion'] print (host_info_dict)if __name__ == "__main__": info_collect()
vim /etc/salt/minion 添加下面内容master: - 132.122.137.3 - 132.122.137.4 id: 132.126.56.2 启动服务/etc/init.d/salt-minion start
在master1上:vim /etc/salt/masterauto_accept: True #去掉对该行的注释,并修改False为True启动服务/etc/init.d/salt-master start在master2和master3上:执行salt-maser1上的1之后,还有最关键的一步scp salt-maser1的 /etc/salt/pki/master/master.pem和/etc/salt/pki/master/master.pub,覆盖本地的启动服务/etc/init.d/salt-master start
参数
必填
类型
说明
参数输入位置
eauth
yes
string
接口进行验证的方法。
由于一般我们使用PAM模块来进行用户认证。该参数值请固定输入“pam”。
http request body
username
yes
string
接口用户名.该参数请在
http request body
password
yes
string
接口用户密码。该参数请
http request body
字段
字段类型
字段说明
perms
列表
用户可以使用的saltstack模块和函数
starts
float
session token生效的的时间戳
token
string
用户通过验证后获取的session token
expire
float
session token失效的的时间戳
user
string
接口用户名
eauth
string
接口验证用户身份的方法
参数
必填
类型
说明
参数输入位置
X-Auth-Token
yes
string
用户登录api后,api返回给用户的session token。请通过用户登录验证接口获取该值
http request header
tgt
yes
string
应用原子能力的目标主机
http request body
fun
yes
string
使用的saltstack 模块.函数。该参数请取值state.sls
http request body
arg
yes
string
指定该原子能力对应的state file
http request body
client
yes
string
local
http request body
expr_form
no
string
该值指定了目标主机的匹配模式。如果不指定,默认为glob。取值请见下面详细说明
http request body
{ "return":[ { "salt-minion1":{ "service_|-restart vsftpd service_|-vsftpd_|-running":{ "comment":"The service vsftpd is already running", "name":"vsftpd", "start_time":"14:48:42.446673", "result":true, "duration":43.535, "__run_num__":2, "changes":{ }, "__id__":"restart vsftpd service" }, "file_|-add prohibit anonymous login configuration_|-/etc/vsftpd/vsftpd.conf_|-append":{ "comment":"File /etc/vsftpd/vsftpd.conf is in correct state", "pchanges":{ }, "name":"/etc/vsftpd/vsftpd.conf", "start_time":"14:48:42.415706", "result":true, "duration":16.213, "__run_num__":0, "changes":{ }, "__id__":"add prohibit anonymous login configuration" }, "file_|-delete allow anonymous login configuration_|-/etc/vsftpd/vsftpd.conf_|-replace":{ "comment":"No changes needed to be made", "pchanges":{ }, "name":"/etc/vsftpd/vsftpd.conf", "start_time":"14:48:42.432250", "result":true, "duration":3.798, "__run_num__":1, "changes":{ }, "__id__":"delete allow anonymous login configuration" } }, "salt-master":{ "test_|-vsftpd is not install_|-vsftpd is not install_|-nop":{ "comment":"Success!", "name":"vsftpd is not install", "start_time":"14:49:04.098507", "result":true, "duration":0.646, "__run_num__":0, "changes":{ }, "__id__":"vsftpd is not install" } } } ]}
字段
字段类型
字段说明
return
列表
它的值是每台目标主机执行结果的详细信息
name
string
对应该STATE DECLARATION的name参数值(一个STATE DECLARATION 对应一个子操作)
comment
string
执行结果描述信息
result
true:操作执行成功
false:操作执行失败
none:操作为test mode
有多种可能导致result值为false ,具体可能请见下面说明
changes
字典
描述该项操作做了哪些配置变更
__run_num__
int
该子操作执行顺序
start_time
string
表示该子操作执行的开始时间
duration
float
表示该子操作花费的时间
#!/usr/bin/env python# _*_ coding:utf-8 _*___author__ = 'junxi'import requestsimport jsontry: import cookielibexcept: import http.cookiejar as cookielib# 使用urllib2请求https出错,做的设置import sslcontext = ssl._create_unverified_context()# 使用requests请求https出现警告,做的设置from requests.packages.urllib3.exceptions import InsecureRequestWarningrequests.packages.urllib3.disable_warnings(InsecureRequestWarning)salt_api = "https://172.16.0.19:8001/"class SaltApi: """ 定义salt api接口的类 初始化获得token """ def __init__(self, url): self.url = url self.username = "saltapi" self.password = "salt2017" self.headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36", "Content-type": "application/json" # "Content-type": "application/x-yaml" } self.params = {'client': 'local', 'fun': '', 'tgt': ''} # self.params = {'client': 'local', 'fun': '', 'tgt': '', 'arg': ''} self.login_url = salt_api + "login" self.login_params = {'username': self.username, 'password': self.password, 'eauth': 'pam'} self.token = self.get_data(self.login_url, self.login_params)['token'] self.headers['X-Auth-Token'] = self.token def get_data(self, url, params): send_data = json.dumps(params) request = requests.post(url, data=send_data, headers=self.headers, verify=False) # response = request.text # response = eval(response) 使用x-yaml格式时使用这个命令把回应的内容转换成字典 # print response # print request # print type(request) response = request.json() result = dict(response) # print result return result['return'][0] def salt_command(self, tgt, method, arg=None): """远程执行命令,相当于salt 'client1' cmd.run 'free -m'""" if arg: params = {'client': 'local', 'fun': method, 'tgt': tgt, 'arg': arg} else: params = {'client': 'local', 'fun': method, 'tgt': tgt} print '命令参数: ', params result = self.get_data(self.url, params) return resultdef main(): print '==================' print '同步执行命令' salt = SaltApi(salt_api) print salt.token salt_client = '*' salt_test = 'test.ping' salt_method = 'cmd.run' salt_params = 'free -m' # print salt.salt_command(salt_client, salt_method, salt_params) # 下面只是为了打印结果好看点 result1 = salt.salt_command(salt_client, salt_test) for i in result1.keys(): print i, ': ', result1[i] result2 = salt.salt_command(salt_client, salt_method, salt_params) for i in result2.keys(): print i print result2[i] printif __name__ == '__main__': main()
- SaltStack实战应用
- saltstack实战--优化
- SaltStack实战之SaltStack快速入门
- saltstack实战之基础配置
- 实战使用saltstack源码安装配置mysql
- SaltStack实战之数据系统-Grains
- SaltStack实战之数据系统-Pillar
- SaltStack实战之远程执行-Targeting
- SaltStack实战之远程执行-Modules
- SaltStack实战之远程执行-Returners
- SaltStack实战之配置管理-YAML编写技巧
- SaltStack实战之配置管理-LAMP自动化部署
- SaltStack实战之配置管理-状态间关系
- SaltStack实战之配置管理-Jinja2模板
- saltstack
- saltstack
- Saltstack
- Saltstack
- http、https 等 常用默认端口号
- 第十周项目一——验证算法之层序遍历算法的验证
- 【bzoj2527】[Poi2011]Meteors
- Android 软键盘的打开关闭监听
- set() get()
- SaltStack实战应用
- 我是如何向老婆解释MapReduce的?
- 括号匹配问题
- 第十周项目1-验证算法(4)
- angularJS 学习
- 第8周项目2-顺序串算法
- Android Studio快捷键
- 如何成为一个合格的程序员杂谈(对于工作上的一些看法 勿喷)
- GitHub创建新仓库并上传项目(笔记)