您的位置:首页 > 大数据 > 云计算

检测openstack云平台是否存在脑裂的虚拟机,加入zabbix告警

2017-10-11 21:03 501 查看
           在openstack运维中,有时会遇到虚拟机热迁移,evacuate等操作中,发生虚拟机脑裂的情况,即同一个虚拟机同时在两个hypervisor上面运行,在使用ceph等共享存储时,十有八九会造成虚拟机文件系统损伤,运气好的情况下能修复文件系统错误,重则数据混乱,虚拟机无法启动.为此,我写了一个Python脚本,用于检测openstack的hypervisor(KVM)是否存在脑裂虚拟机,其原理是通过libvirt的API,获取hypervisor上面的虚拟机的名字,比较是否不同的hypervisor上面有相同的虚拟机名字.脚本需要在控制节点运行(需要openrc的环境变量文件),且该控制节点与计算节点打通了ssh秘钥验证,/etc/hosts解析所有hypervisor的主机名.笔者测试在liberty版本和Mitika能正常运行.

#!/usr/bin/env python

# -*- coding: utf-8 -*-

# @File    : VMSplitCheck.py

import re

import os

import sys

import libvirt

from novaclient import client

from multiprocessing import Pool,Queue

from collections import Counter,defaultdict

import pdb

q=Queue()

EnvFile='/root/openrc'

# 获取nova的认证token

def get_nova_creds():

    d={}

    try:

        pattern_save=re.compile(r'^export.*=.*')

        pattern_split=re.compile(r'=')

        with open(EnvFile,'r') as f:

            for i in f.readlines():

                match=pattern_save.search(i)

                if match:

                    temp_str = match.group(0).strip("export").strip()

                    environ_value_dic = pattern_split.split(temp_str)

                    os.environ[environ_value_dic[0]] = environ_value_dic[1].strip("'")

        d['username'] = os.environ['OS_USERNAME']

        d['api_key'] = os.environ['OS_PASSWORD']

        d['auth_url'] = os.environ['OS_AUTH_URL']

        d['project_id'] = os.environ['OS_TENANT_NAME']

        d['region_name']= os.environ['OS_REGION_NAME']

        return d

    except:

        print  "error"

        sys.exit(5)

#通过调用novaclient获取hypervisor,笔者环境hypervisor主机名都为node-xxx.domain.tld

def getHypervisor():

    HypervisorHostname = []

    pattern = re.compile(r'node-\d\.domain.tld')

    creds = get_nova_creds()

    nova = client.Client('2', **creds)

    for i in nova.hypervisors.list():

        match = pattern.search(i.hypervisor_hostname)

        if match:

            HypervisorHostname.append(match.group())

    return  HypervisorHostname

#获取各个hypervisor上面的虚拟机的名字,放入队列

def getVM(node):

    try:

        virtcon=libvirt.open("qemu+ssh://%s/system" %node)

    except libvirtError,e:

        print "wrong to connect"

    for id  in virtcon.listDomainsID():

        vminfo=virtcon.lookupByID(id)

        q.put((node,vminfo.name()))

# 获取所有运行的虚拟机名字的的列表,和以各个hypervisor的主机名为key,
ae61
上面运行虚拟机为value的字典

def getVMList():

    InstanceNameList=[]

    # a=getHypervisor()

    # HyperDict = {}.fromkeys(a, [])

    HyperDict=defaultdict(list)

    while not q.empty():

        node,vm=q.get()

        InstanceNameList.append(vm)

        HyperDict[node].append(vm)

    return InstanceNameList,HyperDict

# 检测是否有脑裂虚拟机,如果存在,获取此脑裂虚拟机运行在哪些hypervisor上面.

def VMSplitCheck(instancelist,nodedict):

    SplitList=[]

    SplitDict=defaultdict(list)

    c=Counter(instancelist)

    for k,v in c.iteritems():

        if v>=2:

            SplitList.append(k)

    if len(SplitList)==0:

        print "no split vm"

    else:

       for i in SplitList:

           for k,v in nodedict.iteritems():

               if i in v:

                   SplitDict[i].append(k)

    return SplitDict

# 主函数

def main():

    hypername=getHypervisor()

#    pdb.set_trace()

#    print hypername

    p=Pool()

    for i in hypername:

        p.apply_async(getVM,args=(i,))

    p.close()

    p.join()

    inslist,hydict=getVMList()

#    print inslist,hydict

    vmsplit=VMSplitCheck(inslist,hydict)

    print  len(vmsplit)

if __name__ =="__main__":

    main()

笔者测试如下:

如下图,有2台虚拟机同时在node-4和node-6运行


运行脚本后,返回以脑裂虚拟机名字为key,同时运行的hypervisor主机名为value的字典.


2 增加zabbix报警设置

      zabbix-agent增加item


         zabbix-dashboard操作

  


测试item能否正常





增加一个触发器

表达式:{node-1.domain.tld:vm.split.status.last(0)}>0



参考:
https://www.ibm.com/developerworks/cn/cloud/library/cl-openstack-pythonapis/ http://blog.csdn.net/gzhouc/article/details/52915822
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: