授之以渔-运维平台发布模块二(Jenkins篇)

接上篇《授之以渔-运维平台发布模块一(Jenkins篇)》,今天介绍下结合着Saltstack的MasterEven,用来做发布系统的结果监控。

一、Event介绍

SaltStack 0.10版本中, 新增了Event系统, 官方在 Release Notes 对其描述如下:

The Salt Master now comes equipped with a new event system. This event system has replaced some of the back end of the Salt client and offers the beginning of a system which will make plugging external applications into Salt. The event system relies on a local ZeroMQ publish socket and other processes can connect to this socket and listen for events. The new events can be easily managed via Salt‘s event library.
同时官方也在 Salt Event系统 页面中提供了监听event的例子程序, 基于其进行下Event系统学习.
我们所需要的就是监听event,然后把结果存储到Mysql,Redis之类,以便于我们后续进行处理。

二、Event代码:

import salt.utils.event
import redis

def redis_conect_db6():
    try:
        r = redis.StrictRedis(‘172.18.11.126‘, 6379, 6)
    except:
        pass
    return r

event = salt.utils.event.MasterEvent(‘/var/run/salt/master‘)
for data in event.iter_events(full=True):
	r = redis_conect_db6()
	ret = data[‘data‘]
	if ‘salt/job/‘ in data[‘tag‘]:
		if ret.has_key("id") and ret.has_key("return") and ret.has_key("fun") :
			if ret[‘fun‘] != ‘mine.update‘:
				if len(ret[‘fun_args‘]) >0 and ‘wwwlogs‘ not in ret[‘fun_args‘][0]:
					print data
					print "====================================================="
					if ret[‘fun‘] == ‘pkg.get_repo‘ and ret[‘return‘] != {}:
							r.set(‘%s:%s-%s‘%(ret[‘return‘][‘name‘],ret[‘id‘],ret[‘fun‘]), ret)
					elif ret[‘fun‘] == ‘pkg.upgrade_available‘ :
							r.set(‘%s:%s-%s‘%(ret[‘fun_args‘][0],ret[‘id‘],ret[‘fun‘]), ret)
					elif ret[‘fun‘] == ‘pkg.install‘ and ret[‘return‘] != {}:
							r.set(‘%s:%s-%s‘%(ret[‘fun_args‘][0],ret[‘id‘],ret[‘fun‘]), ret)

这段event脚本的大体实现了过滤一些非必要信息,把fun中包含pkg.get_repo(验证Yum是否存在),pkg.upgrade_available(验证Yum是否更新),pkg.install(安装)存储到Redis中。然后我只需要去Redis中取出数据,并通过highcharts.js汇出图即可。

三、后端处理Redis数据绘图代码:

def release_status(request):
    request.GET:
        svn_name = request.GET[]
        Svn_name = Svn.objects.get(= svn_name)
        r = redis_conect_db6()
        svn_list = []
        nodes = [{:,:,:,:[],:% (Svn_name.svn_name)}]
        svn_host (Svn_name.svn_hosts).split():
            area_dict1 = {}
            area_dict2 = {}
            area_dict3 = {}
            svn_list_dict = {}
            area_dict1[] = area_dict1[] = (Svn_name.svn_hosts).split().index(svn_host)
            area_dict1[] = % (svn_host)
            area_dict1[] = [{:,:}]
            area_dict1[] = nodes.append(area_dict1)
            area_dict2[] = area_dict2[] = (Svn_name.svn_hosts).split().index(svn_host)
            area_dict2[] = % (svn_host)
            area_dict2[] = [{:,:(area_dict2[])}]
            area_dict2[] = nodes.append(area_dict2)
            area_dict3[] = area_dict3[] = (Svn_name.svn_hosts).split().index(svn_host)
            area_dict3[] = % (svn_host)
            area_dict3[] = [{:,:(area_dict3[])}]
            area_dict3[] = nodes.append(area_dict3)
            :
                (Svn_name) r.get(% (svn_name, svn_host,)):
                    nodes[] = {:,:,:,:[],:% (Svn_name.svn_name)}

                    nodes[][] == :
                        area_dict1[] = :
                            json.loads(r.get(% (svn_name, svn_host, )).replace(, ).replace(,).replace(,))[] == :
                                area_dict1[] = :
                                area_dict1[] = :
                            area_dict1[] = area_dict1[] = area_dict1[] = (Svn_name.svn_hosts).split().index(svn_host)
                        area_dict1[] = % (svn_host)
                        area_dict1[] = [{:,:}]
                        svn_list_dict[] = svn_host
                        svn_list_dict[] = Svn_name
                        svn_list_dict[] = Svn_name.svn_no

                        :
                            svn_list_dict[] = json.loads(r.get(% (svn_name, svn_host, )).replace(, ).replace(,).replace(,))[]
                        :
                            svn_list_dict[] = nodes.append(area_dict1)
                        ,nodes[][]
                    :
                        area_dict1[] = nodes[][] == :
                        area_dict2[] = :
                            json.loads(r.get(% (svn_name, svn_host, )).replace(, ).replace(,).replace(,))[] == :
                                area_dict2[] = :
                                area_dict2[] = :
                            area_dict2[] = area_dict2[] = area_dict2[] = (Svn_name.svn_hosts).split().index(svn_host)
                        area_dict2[] = % (svn_host)
                        area_dict2[] = [{:,:(area_dict2[])}]

                        :
                            svn_list_dict[] = json.loads(r.get(% (svn_name, svn_host, )).replace(, ).replace(,).replace(,))[]
                        :
                            svn_list_dict[] = nodes.append(area_dict2)
                    :
                        area_dict2[] = nodes[][]  == :
                        area_dict3[] = :
                            json.loads(r.get(% (svn_name, svn_host, )).replace(, ).replace(,).replace(,))[] == :
                                json.loads(r.get(% (svn_name, svn_host, )).replace(, ).replace(,).replace(,))[][% svn_name][] != :
                                    release_old = json.loads(r.get(% (svn_name, svn_host, )).replace(, ).replace(,).replace(,))[][% svn_name][].split()[]
                                :
                                    release_old = :
                                    release_new = json.loads(r.get(% (svn_name, svn_host, )).replace(, ).replace(,).replace(,))[][% svn_name][].split()[]
                                :
                                    release_new = ((release_old)+== (release_new)) ((release_new) == (Svn_name.svn_no)):
                                    area_dict3[] = (release_old) == (release_new):
                                    area_dict3[] = :
                                    area_dict3[] = :
                                area_dict3[] = :
                            area_dict3[] = area_dict3[] = area_dict3[] = (Svn_name.svn_hosts).split().index(svn_host)
                        area_dict3[] = % (svn_host)
                        area_dict3[] = [{:,:(area_dict3[])}]
                        :
                            svn_list_dict[] = json.loads(r.get(% (svn_name, svn_host, )).replace(, ).replace(,).replace(,))[]

                            svn_list_dict[] = release_new
                        :
                            svn_list_dict[] = nodes.append(area_dict3)
                    :
                        area_dict3[] = :
                    svn_list.append(svn_list_dict)
            err:
                ,err
        render_to_response(,{:svn_list,:nodes},=RequestContext(request))
    :
        render_to_response(,=RequestContext(request))

这段代码大体实现了通过判断pkg.get_repo(验证Yum是否存在),pkg.upgrade_available(验证Yum是否更新),pkg.install(安装)返回的状态,来输出不同的status,前端会根据不同的status,绘制不同的颜色。

四、效果图:

五、前端代码:

<script src="../assets/global/plugins/cmdb/highcharts.js" type="text/javascript"></script>

<script type="text/javascript">
    $(function () {
        var chart = new Highcharts.Chart({
            chart: {
                renderTo: ‘container_drawing‘,
                events: {
                    load: drawing
                }
            },
            title: {
                text: ‘‘
            }
        });
    });
    /* 画图自定义函数 */
    function drawing(){
        // Draw the flow chart
        var ren = this.renderer;
        var rightArrow = [‘M‘, 0, 0, ‘L‘, 100, 0, ‘L‘, 95, 5, ‘M‘, 100, 0, ‘L‘, 95, -5];
        var colors = [‘#2570a1‘,‘#d71345‘,‘#decb00‘,‘#1d953f‘];//四种状态对应的颜色:未启动,告警,正在运行,完成

        // 分割线1
        ren.path([‘M‘, 270, 40, ‘L‘, 270, 600]).attr({‘stroke-width‘: 3,stroke: ‘silver‘,dashstyle: ‘dash‘}).add();
        // 分割线2
        ren.path([‘M‘, 520, 40, ‘L‘, 520, 600]).attr({‘stroke-width‘: 3,stroke: ‘silver‘,dashstyle: ‘dash‘}).add();
        // 分割线3
        ren.path([‘M‘, 770, 40, ‘L‘, 770, 600]).attr({‘stroke-width‘: 3,stroke: ‘silver‘,dashstyle: ‘dash‘}).add();
        // 分割线4
//        ren.path([‘M‘, 1020, 40, ‘L‘, 1020, 600]).attr({‘stroke-width‘: 3,stroke: ‘silver‘,dashstyle: ‘dash‘}).add();
        // 分割线5
//        ren.path([‘M‘, 1270, 40, ‘L‘, 1270, 600]).attr({‘stroke-width‘: 3,stroke: ‘silver‘,dashstyle: ‘dash‘}).add();

        // 区域标题

        ren.label(‘包构建‘, 110,50).css({fontWeight: ‘bold‘}).add();
        ren.label(‘验证源‘, 370,50).css({fontWeight: ‘bold‘}).add();
        ren.label(‘验证包更新‘, 610, 50).css({fontWeight: ‘bold‘}).add();
//        ren.label(‘前置命令‘, 880, 50).css({fontWeight: ‘bold‘}).add();
        ren.label(‘项目包安装‘, 880, 50).css({fontWeight: ‘bold‘}).add();
//        ren.label(‘后置命令‘, 1380, 50).css({fontWeight: ‘bold‘}).add();

        // 遍历生成图形
        /**
            area:区域编码,值为:0,1,2,null.
            no:节点序号,值为:0,1,...,N,null.
            label:节点内容.
            status:节点状态值为:0为未执行,1为错误,2为执行中,3为执行完毕
            parea:父节点区域编码,值为:0,1,2,null.
            pno:父节点序号,值为:0,1,...,N,null.
        */
//        var nodes = [{"area":5,"status":2,"no":0,"parent":[{"parea":4,"pno":0}],"label":"md25-qnzs-app-13.youth.cn"},{"area":4,"status":3,"no":0,"parent":[{"parea":3,"pno":0}],"label":"md25-qnzs-app-13.youth.cn"},{"area":3,"status":3,"no":0,"parent":[{"parea":2,"pno":0}],"label":"md25-qnzs-app-13.youth.cn"},{"area":2,"status":3,"no":0,"parent":[{"parea":1,"pno":0},{"parea":1,"pno":1}],"label":"md25-qnzs-app-13.youth.cn"},{"area":1,"status":1,"no":0,"parent":[{"parea":0,"pno":0},{"parea":0,"pno":1},{"parea":0,"pno":3}],"label":"md25-qnzs-app-13.youth.cn"},{"area":1,"status":0,"no":1,"parent":[{"parea":0,"pno":1},{"parea":0,"pno":2}],"label":"md25-qnzs-app-13.youth.cn"},{"area":0,"status":0,"no":0,"parent":[],"label":"md25-qnzs-app-13.youth.cn"},{"area":0,"status":1,"no":1,"parent":[],"label":"md25-qnzs-app-13.youth.cn"},{"area":0,"status":2,"no":2,"parent":[],"label":"md25-qnzs-app-13.youth.cn"},{"area":0,"status":1,"no":3,"parent":[],"label":"md25-qnzs-app-13.youth.cn"}];
        var nodes = {% autoescape off %}{{ nodes}}{% endautoescape %}
        for(var i=0;i<nodes.length;i++){
            var node = nodes[i];
            ren.label(node.label, 30+node.area*250, 80+node.no*50).attr({fill: colors[node.status],stroke: ‘#f2eada‘,‘stroke-width‘: 2,padding: 5,r: 9,width:220,height:20}).css({color: ‘white‘,fontSize:‘xx-small‘,textAlign:‘center‘,fontWeight: ‘bold‘}).add().shadow(true);
            for(var j=0;j<node.parent.length;j++){
                var parent = node.parent[j];
               ren.path([‘M‘, 30+node.area*250, 75+node.no*50+20, ‘L‘, 2+parent.parea*250+250+10, 75+parent.pno*50+20]).attr({‘stroke-width‘: 2,stroke: ‘#4169E1‘}).translate(0, 0).add();//
            }
        }
    }
时间: 2024-11-03 22:26:29

授之以渔-运维平台发布模块二(Jenkins篇)的相关文章

[转载] 运维平台规划体系全介绍

原文: http://www.infoq.com/cn/articles/operation-platform-planning-introduction 很多观点我都比较赞同, 特别是工作流引擎+运维可视化的观点 识别运维平台的边界在哪儿,才能更好地构建平台,从而协助运维的日常工作. 在之前的文章中,谈到过“运维的本质——可视化”,在可视化的篇幅中,着重介绍自动化的可视化和数据的可视化:在后续的篇章中又介绍了“互联网运维的价值体系”,里面分解了几个维度:质量.成本.效率.安全等.以上都是为了清

OMS运维平台设计、过程实现

闲来无事,一直想用py框架写个运维平台出来(瞎搞),从去年一直到现在接触自动化运维理念,形成自己对自动化运维的一些观念,然后就想把这些想法实现出来,就搞了这么个平台..没个什么实战经验,全自己理解,有些不到位的地方,看官们请指点,,虚心接受,谢谢!! 流程设计: 1.IDC,一台新机器从采购到上架装机,第一次进机房装机,2块光盘装几台服务器,在机房耗费了半天+的时间,当时一个想法就是,特么讨厌来机房,接触多了就有了下面这些 前置机器信息录入(IP地址分配.主机名) ->  IDC同事验货,上架插

BAT解密:互联网技术发展之路(10)- 运维平台技术

备注:本来想自己写一篇运维体系的文章的,但毕竟不是专业运维人员出身,担心讲的太肤浅,因此转载我的好朋友王金银(江湖人称老王)同学发表在InfoQ的运维体系介绍.老王的牛逼相信很多同学已经领教过了,全球运维技术大会深圳站一个人专场讲运维能讲3个小时,而且会场还爆满,更多老王的介绍可以参考文章的最后,也可以关注老王的微信公众号:互联网运维杂谈. 原文链接:运维平台规划体系全介绍 =============================================================

3.运维平台之账户系统

历程: 0. 账户系统(accounts)分为用户认证和权限分配两部分. 1. 刚开始运维平台业务比较单一,只提供给运维组人员使用即可,根本没有用户账号的概念. 2. django系统本身有用户.用户组.权限,需要进行一些扩展开发,以满足需求. 在16年独立出用户认证注册模块,形成accounts项目,简单API认证. 3. 在17年时,前端设计获得很大突破,基于Django实现RBAC权限管理. 需求: 1.需要用户认证和角色权限管理,实现资源控制访问. 2.基于用户-角色-权限数据链,在多模

用友iuap云运维平台支持基于K8s的微服务架构

什么是微服务架构? 微服务(MicroServices)架构是当前互联网业界的一个技术热点,业内各公司也都纷纷开展微服务化体系建设.微服务架构的本质,是用一些功能比较明确.业务比较精练的服务去解决更大.更实际的问题.该架构强调的一些准则:单一职责.协议轻量.进程隔离.数据分离.独立部署.按需伸缩. 什么是Kubernetes? Kubernetes是Google开源的容器集群管理系统,其提供应用部署.维护. 扩展机制等功能,利用Kubernetes能方便地管理跨机器运行容器化的应用,其主要功能:

自动化运维平台之系统自动化安装Cobbler系统使用详解

一.简介 Cobbler是一个快速网络安装linux的服务,而且在经过调整也可以支持网络安装windows.该工具使用python开发,小巧轻便(才15k行python代码),使用简单的命令即可完成PXE网络安装环境的配置,同时还可以管理DHCP.DNS.以及yum仓库.构造系统ISO镜像. Cobbler支持命令行管理,web界面管理,还提供了API接口,可以方便二次开发使用. Cobbler客户端Koan支持虚拟机安装和操作系统重新安装,使重装系统更便捷. 二.cobbler提供的功能 使用

运维平台相关开发

最近在做一些运维平台的东东 原文链接:http://www.cnblogs.com/caoguo/p/6003150.html 1.支持查看ucloud主机统计及主机分布情况2.支持ucloud主机及数据库资产信息3.支持针对单台主机执行命令4.支持针对单台主机部署服务5.支持对主机业务分组,并关联联系人6.支持代码发布7.支持权限管理 现在上一些图,图片如果看不清,可以右键打开大图查询 a).ucloud平台查询 b).Saltstack 相关部署接口的开发 c).发布系统rsync+ssh

第二个运维平台项目

把之前的运维平台重新整理和改写,主要实现的思路是从服务器采购开始,采购之后,从网络部申请得到IP地址:通过厂商那里得到的MAC地址直接定制装机,装机时候直接指定IP地址:后期硬件信息采集的方式取消saltstack的grain方式,直接跑脚本做定期资产录入,提供API的接口方式:录入CMDB之后,通过平台实现把CMDB关联到zabbix数据库,批量对zabbix主机进行批量绑定和解绑,包括维护周期等:时间人力有限后面版本再退出批量管理和git发布系统.系统完成要感谢51reboot的rock和p

使用google authenticator打造运维平台的动态口令

前沿: 在腾讯,百度,阿里,360运维人员登录堡垒机,或者是单点登录引导的各种运维平台,好多都需要用动态口令令牌的,用rsa的多点,这栋系价格不便宜,国内也有些便宜的,一些游戏公司的将军令就是从国内x厂商定制买的,有兴趣的可以搜搜,价格还算可以,给你提供服务端的一些源码,让你方便的使用. 当然了,并不是每个公司都会这玩意感兴趣的,咋办?  不知道大家有没有用过 支付宝.dnspod.yy的电子口令,每30s换一次密码.dnspod.yy手机令牌貌似用的是google的token方案. 下图就是各