首先,贴上官方地址:https://docs.saltstack.cn/
salt,一种全新的基础设施管理方式,部署轻松,在几分钟内可运行起来,扩展性好,很容易管理上万台服务器,速度够快,服务器之间秒级通讯。
salt底层采用动态的连接总线, 使其可以用于编配, 远程执行, 配置管理等等.
什么是saltstack
• Saltstack是基于python开发的一套C/S架构配置管理工具
• 使用SSL证书签方的方式进行认证管理
• 底层使用ZeroMQ消息队列pub/sub方式通信
– 号称世界上最快的消息队列ZeroMQ能快速在成千上万台主机上进行各种操作
– 采用RSA Key方式确认身
Salt 是:
一个配置管理系统,能够维护预定义状态的远程节点(比如,确保指定的报被安装,指定的服务在运行)
一个分布式远程执行系统,用来在远程节点(可以是单个节点,也可以是任意规则挑选出来的节点)
上执行命令和查询数据
开发其的目的是为远程执行提供最好的解决方案,并使远程执行变得更好,更快,更简单
既要考虑大规模部署,又要考虑小规模系统,提供适应多种场合的应用让人沮丧,但Salt非常容易设置和维护,
而不用考虑项目的大小。从数量可观的本地网络系统,到跨数据中心的互联网部署,
Salt设计为在任意数量的server下都可工作。
salt的拓扑使用简单的server/client模式,需求的功能内建在一组daemon中。
salt在几乎不改动配置的情况下就可以工作,也可以调整从而满足特定的需求。
Salt的核心功能:
使命令发送到远程系统是并行的而不是串行的
使用安全加密的协议
使用最小最快的网络载荷
提供简单的编程接口
Salt同样引入了更加细致化的领域控制系统来远程执行,使得系统成为目标不止可以通过主机名,还可以通过系统属性。
主要功能
• Saltstack最主要的两个功能是:配置管理与远程执行
• Saltstack不只是一个配置管理工具,还是一个云计算与数据中心架构编排的利器
• Saltstack已经支持Docker相关模块
• 在友好地支持各大云平台之后,配合Saltstack的Mine实时发现功能可以实现各种云平台业务的自动扩展
• Saltstack基于C/S架构
– 服务器端称作Master
– 客户端称作Minion
• 可以实现传统处理方式,即:客户端发送请求给服务器,服务器收到请求后处理请求,再将结果返回
• 也可以使用消息队列中的发布与订阅(pub/sub)服务模式
Master和Minion都以守护进程的方式运行
Master监听配置文件里定义的ret_port(接收minion请求),和publish_port(发布消息)的端口
当Minion运行时,它会自动连接到配置文件里定义的Master地址ret_port端口进行连接认证
当Master和Minion可以正常通信后,就可以进行各种各样的配置管理工作了
[root@master ~]# yum -y install salt-api pyOpenSSL
[root@master ~]# systemctl restart salt-api
[root@master ~]# useradd -M -s /sbin/nologin wmm
[root@master ~]# echo 'wmm' | passwd wmm --stdin
Last login: Sat Sep 7 19:08:35 2019 from 192.168.10.1
[root@master ~]# cat /etc/salt/master.d/api.conf
rest_cherrypy:
port: 8888
#ssl_crt: /etc/pki/tls/certs/localhost.crt
#ssl_key: /etc/pki/tls/certs/localhost.key
disable_ssl: True
external_auth:
pam:
wmm:
- .*
- '@wheel'
- '@runner'
[root@master ~]#
rest_cherrypy:
port: 8000
#ssl_crt: /etc/pki/tls/certs/localhost.crt
#ssl_key: /etc/pki/tls/private/localhost.key
disable_ssl: True
external_auth:
pam:
wmm:
- .*
- '@wheel'
- '@runner'
[root@master ~]# salt-call tls.create_self_signed_cert
local:
Certificate "localhost" already exists
提示已经存在时,可以删除/etc/pki/tls/certs/localhost.crt /etc/pki/tls/certs/localhost.key重新生成
如果这里报异常,请先确认下有没有未认证的主机:
[root@master ~]# salt-key -L
Accepted Keys:
minion-01
minion-02
Denied Keys:
Unaccepted Keys:
Rejected Keys:
[root@master ~]#
[oot@master ~]# curl -k https://192.168.10.12:8000/login -H "Accept: application/x-yaml" -d username='wmm' -d password='wmm' -d eauth='pam'
return:
- eauth: pam
expire: 1480714218.787106
perms:
- .*
- '@wheel'
- '@runner'
start: 1480671018.787106
token: ab3749a9a0fe83386b8a5d558d10e346c252e336
user: wmm
重启salt-api后token会改变
[root@master ~]# curl -k https://192.168.10.12:8000 -H "Accept: application/x-yaml" -H "X-Auth-Token: ab3749a9a0fe83386b8a5d558d10e346c252e336" -d client='local' -d tgt='*' -d fun='test.ping'
return:
- minion-02: true
[root@master ~]# curl -k https://192.168.10.12:8000 -H "Accept: application/x-yaml" -H "X-Auth-Token: ab3749a9a0fe83386b8a5d558d10e346c252e336" -d client='local' -d tgt='*' -d fun='cmd.run' -d arg='free -m'
return:
- minion-02: ' total used free shared buffers cached
Mem: 988 932 56 1 19 107
-/+ buffers/cache: 805 182
Swap: 1983 382 1601'
[root@master ~]# curl -k https://192.168.62.200:8000 -H "Accept: application/x-yaml" -H "X-Auth-Token: ab3749a9a0fe83386b8a5d558d10e346c252e336" -d client='local' -d tgt='operation,slave01' -d expr_form='list' -d fun='cmd.run' -d arg='free -m'
return:
- minion-02: ' total used free shared buffers cached
Mem: 988 925 63 1 21 81
-/+ buffers/cache: 821 166
Swap: 1983 393 1590'
minion-01: ' total used free shared buffers cached
Mem: 1870 622 1248 6 79 300
-/+ buffers/cache: 242 1628
Swap: 2047 0 2047'
[root@master ~]#
查看minion key状态
[root@master ~]#curl -k https://192.168.10.12:8000 -H "Accept: application/x-yaml" -H "X-Auth-Token: ab3749a9a0fe83386b8a5d558d10e346c252e336" -d client='wheel' -d fun='key.list_all'
return:
- data:
_stamp: '2019-09-14S09:30:35.235660'
fun: wheel.key.list_all
jid: '20190914173034905379'
return:
local:
- master.pem
- master.pub
minions:
- minion-01
- minion-02
minions_denied: []
minions_pre: []
minions_rejected: []
success: true
tag: salt/wheel/20161202173034905379
user: wmm
tag: salt/wheel/20161202173034905379
[root@master ~]# curl -k https://192.168.10.12:8000 -H "Accept: application/x-yaml" -H "X-Auth-Token: 2ea1a20373900c311cf4ab1a707da5de4c9c44fc" -d client='wheel' -d fun='file_roots.list_roots'
return:
- data:
_stamp: '2019-09-14S09:30:35.235951'
fun: wheel.file_roots.list_roots
jid: '20190914173034906684'
return:
app:
- /data/salt/app:
memcached:
file:
install_memcached-1.4.15.tar.gz: f
init.sls: f
install.sls: f
nginx:
conf.sls: f
file:
nginx: f
nginx-1.2.5.tar.gz: f
nginx.conf: f
nginx_log_cut.sh: f
vhost.conf: f
init.sls: f
install.sls: f
vhost.sls: f
查看saltenv环境配置
[root@master ~] # curl -k https://192.168.10.12:8000 -H "Accept: application/x-yaml" -H "X-Auth-Token: 2ea1a20373900c311cf4ab1a707da5de4c9c44fc" -d client='runner' -d fun='fileserver.envs'
return:
- - app
- base
- online
查看minion运行状态
[root@master ~]# curl -k https://192.168.62.200:8000 -H "Accept: application/x-yaml" -H "X-Auth-Token: ab3749a9a0fe83386b8a5d558d10e346c252e336" -d client='runner' -d fun='manage.status'
return:
- down:
- minion-01
up:
- minion-02
异步执行命令job:
# curl -k https://192.168.10.12:8000 -H "Accept: application/x-yaml" -H "X-Auth-Token: 14e719b94839b680e7860bfa34db7a385070dd53" -d client="local_async" -d expr_form="glob" -d tgt="minion-01" -d fun="cmd.run" -d arg="free -m"
return:
- jid: '20190914111629216443'
minions:
- operation
# curl -k https://192.168.10.12:8000/jobs/20161205111629216443 -H "Accept: application/x-yaml" -H "X-Auth-Token: 14e719b94839b680e7860bfa34db7a385070dd53"
info:
- Arguments:
- free -m
Function: cmd.run
Minions:
- minion-01
Result:
minion-01:
return: ' total used free shared buffers cached
Mem: 988 928 59 1 17 75
-/+ buffers/cache: 836 152
Swap: 1983 330 1653'
StartTime: 2019, Dec 14 11:16:29.216443
Target: minion-01
Target-type: glob
User: wmm
jid: '20190914111629216443'
return:
- minion-01: ' total used free shared buffers cached
Mem: 988 928 59 1 17 75
-/+ buffers/cache: 836 152
Swap: 1983 330 1653'
这里之前查阅资料过前辈们概括的整个大致过程:
首先是服务端认证,通过每个请求传递会话令牌来执行身份验证,token通过Login URL生成。
token认证采用两种方法发送:一种是hearder头添加认证token,另一种作为会话cookie。
用法:
请求主体必须是一组命令。使用此工作流程来构建命令:
1. 选择一个客户端界面。
2. 选择一个功能。
3.填写所选客户端所需的其余参数。
client字段是对Salt的python api中使用的主要python类的引用。
local:向本地发送命令的“本地”使用。等同于salt 命令。
runner:调用master的runner 模块。等同于salt-run命令。
wheel:调用master的wheel模块。wheel没有知己额的CLI命令,它通常广利Master-side资源,例如状态文件,支柱文件,salt配置文件,以及salt-key类似的功能。
在执行LocalClient,它需要将命令转发给Minions,所以需要tgt参数来指定minionid.
也需要arg(数组)和kwarg(之前)参数,这些值被发送到minions并用作请求函数的参数。
RunnerClient和WheelClient直接在Master上执行,因此不需要接受这些参数。
header头设置:
REST接口在接受什么样的数据格式以及它将返回什么格式(例如,JSON,YAML,urlencoded)方面是灵活的
通过包含Content-type头来指定请求正文中的数据格式。
使用Accept头指定相应主体所需的数据格式。
关于CherryPy的并发:
CherryPy服务器是一个生成就绪的线程HTTP服务器,用Python编写。它使用线程池来处理HTTP请求,所以不适合维护大量的并发同步连接,在配置默认设置的中等硬件上,他最高大约30到50个并发连接。
注意:每个salt的命令运行都会启动一个实例化的进程(LocalClient),它将自己的监听器实例化为salt事件总线,并发出自己的周期性salturil.find_job查询来确定Minion是否仍在运行该命令,不完全是一个轻量级操作。
超时:
CherryPy还可以设置HTTP超时时间。LocalClient和RunnerClient都可以在顶级关键字(timeout)中设置自己的超时参数。
异步操作:
由于性能开销和HTTP超时,长时间运行上述操作,可以使用local_asyn,runner_asyn,wheel_asyn进行异步方式运行更能节省开销。执行结果可以通过 /jobs/<jid> URL 从缓存中获取,也可以使用salt的Rerutner 系统收集到数据存储中。
/events URL专门用户处理长时间运行的HTTP请求,并包含了作业返回的salt事件总线,但该操作具有不同步性。
性能调整:
设置thread_pool和socket_queue_size 可以用来增加处理传入请求的rest_cherrypy的能力。设置这些配置时需要留意RAM的使用情况以及可用文件句柄。由于salt-api是基于salt使用,同时还需要考虑salt的性能。
#!/usr/bin/env python
# -*- coding:utf-8 -*-
__author__ = '40kuai'
__version__ = 'v0.0.1'
"""
1. 整合 salt-api 功能
2. 获取token多次使用,发现token过期后重新获取token从当前失败任务重新继续执行
3. 可选:出现接口或服务异常(501),本次操作尝试几次重新执行
arg 为模块需要传入的参数,kwargs为pillar或grains参数。
分为以下几个类:
1. salt-api 方法类
2. 发送请求的类
"""
from urlparse import urljoin
import requests
class Salt_Api():
def __init__(self, url, username, password):
self.url = url
self._username = username
self._password = password
self.get_token()
def get_token(self, eauth='pam', ):
"""获取salt-api使用的token"""
get_token_url = urljoin(self.url, 'login')
json_data = {'username': self._username, 'password': self._password, 'eauth': eauth}
token_obj = requests.post(get_token_url, json=json_data, verify=False)
if token_obj.status_code != 200:
raise Exception(token_obj.status_code)
self.token = token_obj.json()['return'][0]['token']
def post(self, prefix='/', json_data=None, headers=None):
post_url = urljoin(self.url, prefix)
if headers is None:
headers = {'X-Auth-Token': self.token, 'Accept': 'application/json'}
else:
headers = {'X-Auth-Token': self.token, }.update(headers)
post_requests = requests.post(post_url, json=json_data, headers=headers, verify=False)
return post_requests.json()
def get(self, prefix='/', json_data=None, headers=None):
post_url = urljoin(self.url, prefix)
if headers is None:
headers = {'X-Auth-Token': self.token, 'Accept': 'application/json'}
else:
headers = {'X-Auth-Token': self.token, }.update(headers)
get_requests = requests.get(post_url, json=json_data, headers=headers, verify=False)
return get_requests.json()
def get_all_key(self):
"""获取所有minion的key"""
json_data = {'client': 'wheel', 'fun': 'key.list_all'}
content = self.post(json_data=json_data)
minions = content['return'][0]['data']['return']['minions']
minions_pre = content['return'][0]['data']['return']['minions_pre']
return minions, minions_pre
def accept_key(self, minion_id):
"""认证minion_id,返回Ture or False"""
json_data = {'client': 'wheel', 'fun': 'key.accept', 'match': minion_id}
content = self.post(json_data=json_data)
return content['return'][0]['data']['success']
def delete_key(self, node_name):
"""删除minion_id,返回Ture or False"""
json_data = {'client': 'wheel', 'fun': 'key.delete', 'match': node_name}
content = self.post(json_data=json_data)
return content['return'][0]['data']['success']
def host_remote_module(self, tgt, fun, arg=None):
"""根据主机执行函数或模块,模块的参数为arg"""
json_data = {'client': 'local', 'tgt': tgt, 'fun': fun, }
if arg:
json_data.update({'arg': arg})
content = self.post(json_data=json_data)
return content['return']
def group_remote_module(self, tgt, fun, arg=None):
"""根据分组执行函数或模块,模块的参数为arg"""
json_data = {'client': 'local', 'tgt': tgt, 'fun': fun, 'expr_form': 'nodegroup'}
if arg:
json_data.update({'arg': arg})
content = self.post(json_data=json_data)
return content['return']
def host_sls_async(self, tgt, arg):
'''主机异步sls '''
json_data = {'client': 'local_async', 'tgt': tgt, 'fun': 'state.sls', 'arg': arg}
content = self.post(json_data=json_data)
return content['return']
def group_sls_async(self, tgt, arg):
'''分组异步sls '''
json_data = {'client': 'local_async', 'tgt': tgt, 'fun': 'state.sls', 'arg': arg, 'expr_form': 'nodegroup'}
content = self.post(json_data=json_data)
return content['return']
def server_hosts_pillar(self, tgt, arg, **kwargs):
'''针对主机执行sls and pillar '''
print kwargs
kwargs = {'pillar': kwargs['kwargs']}
json_data = {"client": "local", "tgt": tgt, "fun": "state.sls", "arg": arg, "kwarg": kwargs}
content = self.post(json_data=json_data)
return content['return']
def server_group_pillar(self, tgt, arg, **kwargs):
'''分组进行sls and pillar'''
kwargs = {'pillar': kwargs['kwargs']}
json_data = {'client': 'local', 'tgt': tgt, 'fun': 'state.sls', 'arg': arg, 'expr_form': 'nodegroup',
'kwarg': kwargs}
content = self.post(json_data=json_data)
return content['return']
def jobs_all_list(self):
'''打印所有jid缓存'''
json_data = {"client": "runner", "fun": "jobs.list_jobs"}
content = self.post(json_data=json_data)
return content['return']
def jobs_jid_status(self, jid):
'''查看jid运行状态'''
json_data = {"client": "runner", "fun": "jobs.lookup_jid", "jid": jid}
content = self.post(json_data=json_data)
return content['return']
def keys_minion(self, hostname):
"""Show the list of minion keys or detail on a specific key"""
content = self.get('keys/%s' % hostname)
return content
if __name__ == '__main__':
url = 'https://local:8000/'
obj = Salt_Api(url, 'username', 'password')
print obj.keys_minion('minionid')
salt-api
我在运维平台中针对于IP地址的获取,使用的是这样的思路,因为大家可以看到:
[root@master ~]# ip a
1: lo: ,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
2: enp0s3: ,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 08:00:27:10:97:0f brd ff:ff:ff:ff:ff:ff
inet 192.168.10.12/24 brd 192.168.10.255 scope global dynamic enp0s3
valid_lft 1097sec preferred_lft 1097sec
[root@master ~]#
这里会出现两个IP 地址,而且运维平台中的资产管理,是根据IP和主机名进行区分的,所以要首先过滤掉127.0.0.1,这个IP地址:
项目中的核心代码如下
def getHostInfo():
### salt调用 ###
local = salt.client.LocalClient() # api
### 目标主机指定 ###
tgt = "*"
### 获取grains,disk信息 ###
grains = local.cmd(tgt,"grains.items") # api
(status, grains_return) = subprocess.getstatusoutput(" ssh 127.0.0.1 'salt \"*\" --out raw grains.items' ")
grains = eval(grains_return.replace('}}\n{', '},'))
diskusage = local.cmd(tgt,"disk.usage") # api
(status, diskusage) = subprocess.getstatusoutput(" ssh 127.0.0.1 'salt \"*\" --out raw disk.usage' ")
diskusage = eval(diskusage.replace('}}\n{', '},'))
for i in grains.keys():
try:
###去掉127.0.0.1这个地址
hostname = grains[i]["nodename"]
ip = str(grains[i]["ipv4"]).strip('[]')
ip = ip.replace("\'", "")
ip = ip.replace("127.0.0.1,", "")
ip = ip.replace(", 127.0.0.1", "")
ip = ''.join(ip.split())
ip = ip.replace(",", " | ")
mem = grains[i]["mem_total"] / 1024 + 1
num_cpu = grains[i]["num_cpus"]
OS = grains[i]["os"] + ' ' + grains[i]["osrelease"]
cpu = grains[i]["cpu_model"]
virtual1 = grains[i]["virtual"]
status = '连接'
# 磁盘容量
if "/" not in diskusage[i]:
disk_used = " "
disk_capacity = " "
else:
disk_used = float(diskusage[i]["/"]["1K-blocks"]) / 1048576
disk_capacity = diskusage[i]["/"]["capacity"]
if "/data" not in diskusage[i]:
disk_data_used = " "
disk_data_capacity = " "
else:
disk_data_used = float(diskusage[i]["/data"]["1K-blocks"]) / 1048576
disk_data_capacity = diskusage[i]["/data"]["capacity"]
if "/data1" not in diskusage[i]:
disk_data1_used = " "
disk_data1_capacity = " "
else:
disk_data1_used = float(diskusage[i]["/data"]["1K-blocks"]) / 1048576
disk_data1_capacity = diskusage[i]["/data"]["capacity"]
####获取网卡mac信息####
# if "eth0" not in grains[i]["hwaddr_interfaces"]:
# eth0=" "
# else:
# eth0=grains[i]["hwaddr_interfaces"]["eth0"]
#
# if "eth1" not in grains[i]["hwaddr_interfaces"]:
# eth1=" "
# else:
# eth1=grains[i]["hwaddr_interfaces"]["eth1"]
grains[i]["hwaddr_interfaces"].pop("lo")
hostnames = hostinfo.objects.values_list('hostname', flat=True) # 获取资产列表中的主机名
if hostnames:
if hostname in hostnames: ##判断主机是否已经入库,如果存在输出提示,不存在则入库
hostinfoupdate = hostinfo.objects.get(hostname=hostname)
hostinfoupdate.hostname = hostname
hostinfoupdate.IP = ip
hostinfoupdate.Mem = mem
hostinfoupdate.CPU = cpu
hostinfoupdate.CPUS = num_cpu
hostinfoupdate.OS = OS
hostinfoupdate.virtual1 = virtual1
hostinfoupdate.status = status
hostinfoupdate.save()
else:
hostinfoadd = hostinfo()
hostinfoadd.hostname = hostname
hostinfoadd.IP = ip
hostinfoadd.Mem = mem
hostinfoadd.CPU = cpu
hostinfoadd.CPUS = num_cpu
hostinfoadd.OS = OS
hostinfoadd.virtual1 = virtual1
hostinfoadd.status = status
hostinfoadd.save()
else:
hostinfoadd = hostinfo()
hostinfoadd.hostname = hostname
hostinfoadd.IP = ip
hostinfoadd.Mem = mem
hostinfoadd.CPU = cpu
hostinfoadd.CPUS = num_cpu
hostinfoadd.OS = OS
hostinfoadd.virtual1 = virtual1
hostinfoadd.status = status
hostinfoadd.save()
except:
hostnames = hostinfo.objects.values_list('hostname', flat=True) # 获取资产列表中的主机名
if i in hostnames:
hostinfoupstatus = hostinfo.objects.get(hostname=i)
hostinfoupstatus.status = '未连接'
hostinfoupstatus.save()
continue
后面也使用了salt api进行自动部署minion,并且添加主机:
项目中涉及代码如下:
@login_required
def serverAdd(request):
result = ''
check_ip_inro = 0 # 检查主机是否存在,0不存在,1存在
if request.method == "POST":
form = autoArrMinionForm(request.POST)
if form.is_valid():
ip = request.POST.get('add_ip') # 需要安装minion端的ip
username = request.POST.get('add_username') # 需要安装minion端的用户名
password = request.POST.get('add_password') # 需要安装minion端的密码
check_ip_list = hostinfo.objects.values_list('IP', flat=True) # 获取已经安装minion的ip列表
for i in check_ip_list: # 将有多个ip的主机ip分开,自成一个列表供匹配检查主机是否已经存在
if " | " in i:
check_ip_list_two = i.split(" | ")
if ip in check_ip_list_two: # 判断输入的ip是否在主机列表中
check_ip_inro = 1
break
if ip not in check_ip_list and check_ip_inro == 0:
try:
os.system("echo '" + ip + ":'>> /etc/salt/roster && \
echo ' host: " + ip + "'>> /etc/salt/roster && \
echo ' user: " + username + "'>> /etc/salt/roster && \
echo ' passwd: " + password + "'>> /etc/salt/roster && \
echo ' sudo: True'>> /etc/salt/roster && \
echo ' tty: True'>> /etc/salt/roster && \
echo ' timeout: 10'>> /etc/salt/roster")
os.system("salt-ssh '" + ip + "' -ir 'easy_install certifi'") # 安装cretifi模块
(status_gethostname, resultgethostname) = subprocess.getstatusoutput(
"salt-ssh -ir '" + ip + "' 'hostname'") # 获取hostname
os.system(
"salt-ssh '" + ip + "' -ir 'echo ''" + ip + "' '" + resultgethostname + "''>> /etc/hosts'") # 添加hosts
(status, result) = subprocess.getstatusoutput(
"salt-ssh -i '" + ip + "' state.sls minions.install") # 执行安装命令,并返回结果
except:
result = "注意:无法连接该主机,请检查ip和用户密码是否正确!"
else:
result = "提示:这台主机已加入主机列表!"
else:
result = "注意:请填写正确的ip、用户名或密码!"
else:
form = autoArrMinionForm()
re = {
"form": form,
"result": result
}
return render(request, "serveradd.html", re)
@login_required
def serverList(request, id=0):
'''
服务器列表
'''
if id != 0:
hostinfo.objects.filter(id=id).delete()
if request.method == "POST":
getHostInfo()
print(request.POST)
pageSize = request.POST.get('pageSize') # how manufactoryy items per page
pageNumber = request.POST.get('pageNumber')
offset = request.POST.get('offset') # how many items in total in the DB
search = request.POST.get('search')
sort_column = request.POST.get('sort') # which column need to sort
order = request.POST.get('order') # ascending or descending
if search: # 判断是否有搜索字
all_records = hostinfo.objects.filter(id=search, asset_type=search, business_unit=search, idc=search)
else:
all_records = hostinfo.objects.all() # must be wirte the line code here
if sort_column: # 判断是否有排序需求
sort_column = sort_column.replace('asset_', '')
if sort_column in ['id', 'asset_type', 'sn', 'name', 'management_ip', 'manufactory',
'type']: # 如果排序的列表在这些内容里面
if order == 'desc': # 如果排序是反向
sort_column = '-%s' % (sort_column)
all_records = hostinfo.objects.all().order_by(sort_column)
elif sort_column in ['salt_minion_id', 'os_release', ]:
# server__ 表示asset下的外键关联的表server下面的os_release或者其他的字段进行排序
sort_column = "server__%s" % (sort_column)
if order == 'desc':
sort_column = '-%s' % (sort_column)
all_records = hostinfo.objects.all().order_by(sort_column)
elif sort_column in ['cpu_model', 'cpu_count', 'cpu_core_count']:
sort_column = "cpu__%s" % (sort_column)
if order == 'desc':
sort_column = '-%s' % (sort_column)
all_records = hostinfo.objects.all().order_by(sort_column)
elif sort_column in ['rams_size', ]:
if order == 'desc':
sort_column = '-rams_size'
else:
sort_column = 'rams_size'
all_records = hostinfo.objects.all().annotate(rams_size=Sum('ram__capacity')).order_by(sort_column)
elif sort_column in [
'localdisks_size', ]: # using variable of localdisks_size because there have a annotation below of this line
if order == "desc":
sort_column = '-localdisks_size'
else:
sort_column = 'localdisks_size'
# annotate 是注释的功能,localdisks_size前端传过来的是这个值,后端也必须这样写,Sum方法是django里面的,不是小写的sum方法,
# 两者的区别需要注意,Sum('disk__capacity‘)表示对disk表下面的capacity进行加法计算,返回一个总值.
all_records = hostinfo.objects.all().annotate(localdisks_size=Sum('disk__capacity')).order_by(
sort_column)
elif sort_column in ['idc', ]:
sort_column = "idc__%s" % (sort_column)
if order == 'desc':
sort_column = '-%s' % (sort_column)
all_records = hostinfo.objects.all().order_by(sort_column)
elif sort_column in ['trade_date', 'create_date']:
if order == 'desc':
sort_column = '-%s' % sort_column
all_records = User.objects.all().order_by(sort_column)
all_records_count = all_records.count()
if not offset:
offset = 0
if not pageSize:
pageSize = 10 # 默认是每页20行的内容,与前端默认行数一致
pageinator = Paginator(all_records, pageSize) # 开始做分页
page = int(int(offset) / int(pageSize) + 1)
response_data = {'total': all_records_count, 'rows': []}
for server_li in pageinator.page(page):
response_data['rows'].append({
"id": server_li.id if server_li.id else "",
"hostname": server_li.hostname if server_li.hostname else "",
"IP": server_li.IP if server_li.IP else "",
"Mem": server_li.Mem if server_li.Mem else "",
"CPU": server_li.CPU if server_li.CPU else "",
"CPUS": server_li.CPUS if server_li.CPUS else "",
"OS": server_li.OS if server_li.OS else "",
"virtual1": server_li.virtual1 if server_li.virtual1 else "",
"status": server_li.status if server_li.status else "",
})
return HttpResponse(json.dumps(response_data))
return render(request, 'serverlist.html')
下篇博客将单独进行salt-api与运维相关的管理命令的使用就想hostinfo的获取:
快速进入:saltstack 自动化运维工具管理命令的详细使用,获取指定数据集