saltstack操作zabbix的一个小模块

需求:
自动化扩容期间,想给通过saltstack将主机自动加入SOA组,自动添加JMX(监控jvm)模板;
期间没有记录模块执行日志,而是使用golang和lua的处理方式,将错误直接返回;
另外实现的功能非常少,主要是注释比较多

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Create from 2018/11/05

import subprocess
import json
import requests
#import salt.utils
from salt.exceptions import CommandExecutionError

__virtualname__ = "zabbix_modify"

class zabbix_check():
    def __init__(self,template=None,group=None):
        self.user = "devops"
        self.password = "1234567890"
        self.zabbix_url = "http://1.2.3.4/api_jsonrpc.php"
        self.zabbix_header = {"Content-Type": "application/json"}
        if group:
            self.zabbix_group_name = group
        else:
            self.zabbix_group_name = "SOA"
        if template:
            self.zabbix_template_name = template
        else:
            self.zabbix_template_name = "JMX"
        self.zabbix_etc = "/usr/local/services/zabbix-3.0.0/etc/zabbix_agentd.conf"

    def _get_hostname(self):
        """
        用系统命令获取zabbix的Hostname
        """
        cmd = "grep ^Hostname %s | awk -F'=' '{print $2}'" % self.zabbix_etc
        ret = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        ret.wait()
        if ret.returncode == 0:
            return ret.stdout.read(),None
        else:
            return None,ret.stderr.read()

    def _get_test_return(self,res):
        """
        统一进行 临时测试/验证 数据返回,一般用于zabbix api的get相关方法,直接回复ret["result"]进行测试
        """
        if res.status_code == 200:
            ret = res.json()
            if "result" in ret.keys():
                return ret["result"]
            else:
                return None,"发生错误: {1}".format(ret['error'])
        else:
            return None,"结果非200!"

    def _get_return(self,res,keywords):
        """
        统一进行数据返回,一般用于zabbix api的get相关方法
        """
        if res.status_code == 200:
            ret = res.json()
            if "result" in ret.keys():
                if keywords in ret['result'][0].keys():
                    return ret['result'][0][keywords],None
                else:
                    return None,"zabbix-server上没有{0}相关信息".format(keywords)
            else:
                return None,"获取{0}发生错误: {1}".format(keywords,ret['error'])
        else:
            return None,"获取{0}结果非200!".format(keywords)

    def _update_return(self,res,keywords,ext_keywords=None):
        """
        统一进行结果验证,一般用于zabbix api的update相关方法
        """
        if res.status_code == 200:
            ret = res.json()
            if "result" in ret.keys():
                if keywords in ret['result']:
                    return ret['result'][keywords],None
                else:
                    return None,"更新zabbix-server上{0}.{1}相关信息".format(keywords,ext_keywords)
            else:
                return None,"更新{0}.{1}发生错误: {2}".format(keywords,ext_keywords,ret['error'])
        else:
            return None,"更新{0}.{1}结果非200!".format(keywords,ext_keywords)

    def _get_sessionid(self):
        """
        获得访问zabbix的session,在这一步抓捕网络连接异常,剩下的与zabbix api交互中忽略了网络异常的处理
        """
        data = {
            "jsonrpc": "2.0",
            "method": "user.login",
            "params": {
                "user": self.user,
                "password": self.password
            },
            "id": 0
        }
        try:
            res = requests.post(url=self.zabbix_url, headers=self.zabbix_header, data=json.dumps(data))
        except Exception as e:
            return None,"Connection Error: {0}".format(e)

        # 这个结果单独处理了
        if res.status_code == 200:
            if "result" in res.json().keys():
                return eval(str(res.text))['result'],None
            else:
                return None,"获取session id失败!"
        else:
            return None,"获取zabbix session_id结果非200!"

    def _get_hosid(self,hostname,session_id):
        """
        判断此主机是否存在于zabbi-server上,存在就返回hostid
        Request:
        {
            "jsonrpc": "2.0",
            "method": "host.get",
            "params": {
                "output": ["hostid"],
                "filter": {
                    "host": [
                        "Zabbix server"
                    ]
                }
            },
            "auth": "038e1d7b1735c6a5436ee9eae095879e",
            "id": 1
        }

        Response:
        {
            "jsonrpc": "2.0",
            "result": [{
                    "hostid": "10160"
            },]
            "id": 1
        }
        """
        data = {
            "jsonrpc": "2.0",
            "method": "host.get",
            "params": {
                "output": ["hostid"],
                "filter": {
                    "host": [hostname]
                }
            },
            "auth": session_id,
            "id": 1}

        res = requests.post(url=self.zabbix_url, headers=self.zabbix_header, data=json.dumps(data))
        return self._get_return(res,"hostid")

    def _get_groupid(self,session_id):
        """
        返回某个特定group的id
        Request:
        {
            "jsonrpc": "2.0",
            "method": "hostgroup.get",
            "params": {
                "output": "extend",
                "filter": {
                    "name": [
                        "Zabbix servers",
                        "Linux servers"
                    ]
                }
            },
            "auth": "6f38cddc44cfbb6c1bd186f9a220b5a0",
            "id": 1
        }

        Response:
        {
            "jsonrpc": "2.0",
            "result": [
                {
                    "groupid": "2",
                    "name": "Linux servers",
                    "internal": "0"
                },
                {
                    "groupid": "4",
                    "name": "Zabbix servers",
                    "internal": "0"
                }
            ],
            "id": 1
        }
        """
        data = {
            "jsonrpc": "2.0",
            "method": "hostgroup.get",
            "params": {
                "output": ["groupid"],
                "filter": {
                    "name": [self.zabbix_group_name]
                }
            },
            "auth": session_id,
            "id": 0}
        res = requests.post(url=self.zabbix_url, headers=self.zabbix_header, data=json.dumps(data))
        return self._get_return(res,"groupid")

    def _get_templateid(self,session_id):
        """
        返回指定template的id
        {
            "jsonrpc": "2.0",
            "method": "template.get",
            "params": {
                "output": ["templateid"],
                "filter": {
                    "host": [
                        "Template OS Linux",
                        "Template OS Windows"
                    ]
                }
            },
            "auth": "038e1d7b1735c6a5436ee9eae095879e",
            "id": 1
        }

        Response:
        {
            "jsonrpc": "2.0",
            "result": [
                {
                    "templateid": "10001"
                },
                {
                    "templateid": "10081",
                }
            ],
            "id": 1
        }
        """
        data = {
            "jsonrpc": "2.0",
            "method": "template.get",
            "params": {
                "output": ["templateid"],
                "filter": {
                    "host": [self.zabbix_template_name]
                    }
            },
            "auth": session_id,
            "id": 0
        }
        res = requests.post(url=self.zabbix_url, headers=self.zabbix_header, data=json.dumps(data))
        return self._get_return(res,"templateid")

    def _get_groups(self,session_id,hostid):
        """
        返回指定主机所属的所有groups id
        Request:
        {
            "jsonrpc": "2.0",
            "method": "host.get",
            "params": {
                "output": ["groupid"],
                "selectGroups": ["groupid"],
                "hostids": "10084"
            },
            "auth": "038e1d7b1735c6a5436ee9eae095879e",
            "id": 2
        }

        Response:
        {
            "jsonrpc": "2.0",
            "result": [
                {
                    "hostid": "10085",
                    "groups": [  #注意,groups的值是一个列表,列表下的元素是字典
                        {
                            "groupid": "2",
                        },
                        {
                            "groupid": "4",
                        }
                    ]
                }
            ],
            "id": 2
        }
        """
        data = {
            "jsonrpc": "2.0",
            "method": "host.get",
            "params": {
                "output": ["hostid"],
                "selectGroups": ["groupid"],
                "hostids": hostid
            },
            "auth": session_id,
            "id": 2
        }
        res = requests.post(url=self.zabbix_url, headers=self.zabbix_header, data=json.dumps(data))
        return self._get_return(res,"groups")

    def _get_templates(self,session_id,hostid):
        """
        返回主机关联的所有template id
        Request:
        {
            "jsonrpc": "2.0",
            "method": "host.get",
            "params": {
                "output": ["hostid"],
                "selectParentTemplates": ["templateid"],
                "hostids": "10084"
            },
            "id": 1,
            "auth": "70785d2b494a7302309b48afcdb3a401"
        }

        Response:
        {
            "jsonrpc": "2.0",
            "result": [
                {
                    "hostid": "10084",
                    "parentTemplates": [
                        {
                            "templateid": "10001"
                        },
                        {
                            "templateid": "10047"
                        }
                    ]
                }
            ],
            "id": 1
        }
        """
        data = {
            "jsonrpc": "2.0",
            "method": "host.get",
            "params": {
                "output": ["hostid"],
                "selectParentTemplates": ["templateid"],
                "hostids": hostid
            },
            "auth": session_id,
            "id": 2
        }
        res = requests.post(url=self.zabbix_url, headers=self.zabbix_header, data=json.dumps(data))
        return self._get_return(res,"parentTemplates")

    def _update_groups(self,session_id,hostid,groups):
        """
        注意: 这里的groups还是一个列表,列表的元素是字典,字典只有一个键值对,键是"groupid"
        更新主机所属的组
        {
            "jsonrpc": "2.0",
            "method": "host.update",
            "params": {
                "hostid": "10126",
                "groups": [
                    {
                        "groupid": "10124"
                    },
                ]
            },
            "auth": "038e1d7b1735c6a5436ee9eae095879e",
            "id": 1
        }

        结果:
        {
            "jsonrpc": "2.0",
            "result": {
                "hostids": [
                    "10126"
                ]
            },
            "id": 1
        }
        判断里面是否有"hostids"
        """
        data = {
            "jsonrpc": "2.0",
            "method": "host.update",
            "params": {
                "hostid": hostid,
                "groups": groups
            },
            "auth": session_id,
            "id": 1
        }
        res = requests.post(url=self.zabbix_url, headers=self.zabbix_header, data=json.dumps(data))
        return self._update_return(res,"hostids","groups")

    def _update_templates(self,session_id,hostid,templates,operate):
        """
        给主机添加template,注意,templates其实是替换,类似groups,这里templates仍然是一个列表,统一进行更新或者clear template
        涉及到update,一定要小心,必须验证
        Request:
        {
            "jsonrpc": "2.0",
            "method": "host.update",
            "params": {
                "hostid": "10126",
                "templates": [
                    {
                        "templateid": "10124"
                    },
                    {
                        "templateid": "10125"
                    }
                ]
            },
            "auth": "038e1d7b1735c6a5436ee9eae095879e",
            "id": 1
        }

        Response:
        {
            "jsonrpc": "2.0",
            "result": {
                "hostids": [
                    "10126"
                ]
            },
            "id": 1
        }

        """
        if operate == "add":
            operation = "templates"
        else:
            operation = "templates_clear"
        data = {
            "jsonrpc": "2.0",
            "method": "host.update",
            "params": {
                "hostid": hostid,
                operation: templates
            },
            "auth": session_id,
            "id": 1
        }
        res = requests.post(url=self.zabbix_url, headers=self.zabbix_header, data=json.dumps(data))
        return self._update_return(res,"hostids","templates")

    def add_group(self):
        zabagent_hostname, err = self._get_hostname()
        if err:
            raise CommandExecutionError("无法获取本机zabbix-agent的hostname: {0}".format(err))
            #print("无法获取本机zabbix-agent的hostname: {0}".format(err))
        else:
            zabagent_hostname = zabagent_hostname.strip("\n")

        zabbix_session, err = self._get_sessionid()
        if err:
            raise CommandExecutionError(err)
            #print(err)

        host_id,err = self._get_hosid(zabagent_hostname,zabbix_session)
        if err:
            raise CommandExecutionError(err)
            # print(host_id_err)

        # 判断是否在soa主机组里面,如果不在,添加
        target_groupid, err = self._get_groupid(zabbix_session)
        if err:
            raise CommandExecutionError(err)
            #print(err)
        groups,err = self._get_groups(zabbix_session,host_id)
        if err:
            raise CommandExecutionError(err)
            #print(err)
        groups_list = [id["groupid"] for id in groups]
        if target_groupid not in groups_list:
            groups.append({"groupid": target_groupid})
            update_groups_ret,err = self._update_groups(zabbix_session,host_id,groups)
            if err:
                raise CommandExecutionError(err)
                #print(err)
            else:
                return "success: 当前主机{0}加入{1}组内成功".format(zabagent_hostname,self.zabbix_group_name)
        else:
            return "success: 当前主机{0}已经在{1}组内,不需添加".format(zabagent_hostname,self.zabbix_group_name)

    def _template_common(self,operate):
        zabagent_hostname, err = self._get_hostname()
        if err:
            raise CommandExecutionError("无法获取本机zabbix-agent的hostname: {0}".format(err))
            #print("无法获取本机zabbix-agent的hostname: {0}".format(err))
        else:
            zabagent_hostname = zabagent_hostname.strip("\n")

        zabbix_session, err = self._get_sessionid()
        if err:
            raise CommandExecutionError(err)
            #print(err)

        host_id,err = self._get_hosid(zabagent_hostname,zabbix_session)
        if err:
            raise CommandExecutionError(err)
            # print(host_id_err)

        # 判断是否在关联了目标监控模板,如果没有,则关联
        target_templateid,err = self._get_templateid(zabbix_session)
        if err:
            raise CommandExecutionError(err)
            #print(err)
        templates,err = self._get_templates(zabbix_session,host_id)
        if err:
            raise CommandExecutionError(err)
            #print(err)
        templates_list = [template["templateid"] for template in templates]
        if operate== "add" and target_templateid not in templates_list:
            templates.append({"templateid": target_templateid})
            update_templates_ret,err = self._update_templates(zabbix_session,host_id,templates,operate)
            if err:
                raise CommandExecutionError(err)
                #print(update_templates_ret_err)
            else:
                return "sucess: 当前主机{0}关联{1}模板成功".format(zabagent_hostname,self.zabbix_template_name)
        elif operate == "add" and target_templateid in templates_list:
            return "success: 当前主机{0}已经关联{1}模板,不需要继续关联.".format(zabagent_hostname,self.zabbix_template_name)
        elif operate == "unlink_clear" and target_templateid in templates_list:
            # 这边就是清除当前主机关联的目标template
            update_templates_ret,err = self._update_templates(zabbix_session,host_id,[{"templateid": target_templateid}],operate)
            if err:
                raise CommandExecutionError(err)
                #print(update_templates_ret_err)
            else:
                return "sucess: 当前主机{0} unlink and clear {1} 模板成功".format(zabagent_hostname,self.zabbix_template_name)

        elif operate == "unlink_clear" and target_templateid not in templates_list:
            return "success: 当前主机{0}没有关联{1}模板,不需要删除关联.".format(zabagent_hostname,self.zabbix_template_name)

    def add_template(self):
        return self._template_common("add")

    def unlink_clear_template(self):
        return self._template_common("unlink_clear")

def add_host_to_group(group=None):
    zabbix_operation = zabbix_check(group)
    return zabbix_operation.add_group()

def link_template(template=None):
    zabbix_operation = zabbix_check(template)
    return zabbix_operation.add_template()

def unlink_clear_template(template=None):
    zabbix_operation = zabbix_check(template)
    return zabbix_operation.unlink_clear_template()

# if __name__ == "__main__":
#     add_template()
#模块经测试有效,只是暂时没有记录日志
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值