工具介紹:

建立虛擬機器會使用多執行緒佇列的方式去控制同時建立的虛擬機器數量

如果在建立的虛擬機器比較多,會2次建立。第一次會在各個宿主機上建立一臺,其餘的會再第一次建立成功後建立。

因為第一次建立需要傳輸映象會比較慢,在宿主機上已經有對應的映象後,再次建立相同映象的虛擬機器,不再需要傳輸相應的映象(所有相同映象的虛擬機器共用同一個後端映象,openstack對映象管理使用copy on write技術)

查詢和更改主要都是通過查詢資料庫實現。

其它功能自測。



使用幫助:

python openstack_manager.py --help


建立虛擬機器:

python openstack_manager.py -c -f vmhost -t nslm

-c, 指定是要進行建立虛擬機器 , -f  指定要建立的虛擬機器列表檔案 , -t 指定要給那個專案建立虛擬機器


刪除虛擬機器:

python openstack_manager.py -d ip1 ip2

-d  指定要刪除的ip ,可以跟多個



檢視某個虛擬機器資訊

python openstack_manager.py -i ip1 ip2

-i 指定ip,後面可以跟上多個值


檢視宿主機下的虛擬機器資訊

python openstack_manager.py -n node1 node2

-n 指定node,可以跟上多個值



更改虛擬機器配置:

python openstack_manager.py -u ip -F flavor

-u指定某個ip, -F 指定某個配置



批量ping:

python openstack_manager.py -p -f vmhost

-p指定進行批量ping,-f指定檔案


從檔案中獲取建立虛擬機器的命令

(建立過程中某個虛擬機器出錯,可以進行檢視建立虛擬機器命令進行手動建立)

python openstack_manager.py -g -f vmhost -t

-g指定要進行獲取命令,-f指定檔案,-t指定專案

-f 指定檔案的檔案格式:

批量ping是檢查ip虛擬機器是否存在,指定的檔案也是參照此格式

nodename instance_ip flavor

一行一個虛擬機器

其它使用資訊:

指令碼中的flavor對應的flavor id,專案帳號密碼和映象ID,資料庫帳號等替換成自己生產環境中的資訊

#!/usr/bin/python
#coding:utf8
#Auth by lust
import sys,commands,os,MySQLdb
import Queue, threading,time
from fabric.colors import *
from optparse import OptionParser
class vmListAnaly():
    def __init__(self,vmlist_file):
        self.f_handle = open(vmlist_file)
        self.vmlist = {}
        while True:
            self.file_tmp = self.f_handle.readline()
            if self.file_tmp:
                if self.vmlist.has_key(self.file_tmp.split()[0]):      
                    self.vmlist[self.file_tmp.split()[0]].append((self.file_tmp.split()[1],self.file_tmp.split()[2]))
                else:
                    self.vmlist[self.file_tmp.split()[0]] = []
                    self.vmlist[self.file_tmp.split()[0]].append((self.file_tmp.split()[1],self.file_tmp.split()[2]))
            else:
                break
    def getAllIps(self):
        ips = []
        for __host in self.vmlist:
            for i in self.vmlist[__host]:
                ips.append(i[0])
        return ips
    def getFirstIps(self):
        ips = []
        for __host in self.vmlist:
            ips.append(self.vmlist[__host][0][0])
        return ips
    def getSecondIps(self):
        ips = []
        for __host in self.vmlist:
            del self.vmlist[__host][0]
        for __host in self.vmlist:
            for i in self.vmlist[__host]:
                ips.append(i[0])
        return ips
    def getAllCreInfo(self):
        return self.vmlist
    def getFirstCreInfo(self):
        results = []
        for __host in self.vmlist:
            self.vmlist[__host] = [self.vmlist[__host][0]]
        return self.vmlist
    def getSecondCreInfo(self):
        for __host in self.vmlist:
            del self.vmlist[__host][0]
        return self.vmlist
    def __del__(self):
        self.f_handle.close()
class getCmd():
    def __init__(self,project,vminfo,flavor,mysql_host,mysql_user,mysql_passwd):
        self.mysql_user = mysql_user
        self.mysql_host = mysql_host
        self.mysql_passwd = mysql_passwd
        self.project = project
        self.vminfo = vminfo
        self.flavor = flavor
        self.create_cmd = []
    def get_cmd(self):
        quantum_obj = mysqlEng(host=self.mysql_host,user=self.mysql_user,passwd=self.mysql_passwd)
        for __host in self.vminfo:
            if self.vminfo[__host]:
                for i in self.vminfo[__host]:
                    __ip = i[0]
                    __flavor = i[1]
                    __network_id = quantum_obj.getNetworkID(__ip)
                    __tmp = "nova --os-username %s --os-password %s --os-tenant-name %s boot --security-groups %s --flavor %s --p_w_picpath %s --nic net-id=%s,v4-fixed-ip=%s --meta lan=%s --availability-zone nova:%s %s" % (self.project[`OS_USERNAME`],self.project[`OS_PASSWORD`],self.project[`OS_TENANT_NAME`],self.project[`SECURITY_GROUPS`],flavor[__flavor],self.project[`IMAGE_ID`],__network_id,__ip,__ip,__host,__ip)
                    self.create_cmd.append(__tmp)
        return self.create_cmd
class mysqlEng():
    def __init__(self,host=`127.0.0.1`,user=`root`,passwd=``,port=`3306`):
        self.conn = MySQLdb.connect(host=host,user=user,passwd=passwd,port=3306)
        self.cur = self.conn.cursor()
    def getNetworkID(self,ip):
        self.conn.select_db(`quantum`)
        net = "%s.%s.%s.0/24"%(ip.split(`.`)[0],ip.split(`.`)[1],ip.split(`.`)[2])
        __sql = "select network_id from subnets where name=`%s`" % net
        self.cur.execute(__sql)
        ret = self.cur.fetchall()
        return ret[0][0]
    def getVmstate(self,ip):
        self.conn.select_db(`nova`)
        __sql = "select instances.uuid,instance_metadata.value,instances.host,instances.vm_state from instance_metadata,instances where instances.uuid = instance_metadata.instance_uuid and instance_metadata.value = %s and instances.vm_state not in (`error`,`deleted`);"
        self.cur.execute(__sql,ip)
        ret = self.cur.fetchall()
        return ret[0][3]
    def getActNum(self,ips):
        self.conn.select_db(`nova`)
        __sql = "select count(*) from instance_metadata,instances where instances.uuid = instance_metadata.instance_uuid and instance_metadata.value in (`%s`) and instances.vm_state = `active`;" % "`,`".join(ips)
        self.cur.execute(__sql)
        ret = self.cur.fetchall()
        return ret[0][0]
    def updateInstanceFlavor(self,ip,flavor):
        self.conn.select_db(`nova`)
        __get_flavor_info_sql="select id,memory_mb,vcpus from instance_types where flavorid = `%s` and deleted = 0;" % flavor
        self.cur.execute(__get_flavor_info_sql)
        __flavor_info = self.cur.fetchall()
        __flavor_id = __flavor_info[0][0]
        __mem = __flavor_info[0][1]
        __vcpus = __flavor_info[0][2]
        __update_flavor_info_sql="update instances set instance_type_id=`%d`,vcpus=`%d`,memory_mb=`%d` where hostname=`%s` AND vm_state != `deleted` AND vm_state != `error`;" % (__flavor_id,__vcpus,__mem,ip)
        self.cur.execute(__update_flavor_info_sql)
        self.conn.commit()
    def getInstanceFlavor(self,ip):
        self.conn.select_db(`nova`)
        __get_instance_flavor_sql = "select vcpus,memory_mb from instances where hostname=`%s` AND vm_state != `deleted` AND vm_state != `error`;" % ip
        self.cur.execute(__get_instance_flavor_sql)
        ret = self.cur.fetchall()
        results = (ip,ret[0][0],ret[0][1])
        return results
    def getInstanceInfo(self,ips):
        self.conn.select_db(`nova`)
        __get_instance_info_sql = "select instances.uuid,instance_metadata.value,instances.host,instances.vm_state,memory_mb from instance_metadata,instances where instances.uuid = instance_metadata.instance_uuid and instance_metadata.value in (`%s`) and instances.vm_state !=`error` and instances.vm_state != `deleted`;" % "`,`".join(ips)
        self.cur.execute(__get_instance_info_sql)
        ret = self.cur.fetchall()
        return ret
    def getNodeInfo(self,nodes):
        self.conn.select_db(`nova`)
        __get_node_info_sql = "select instances.uuid,instance_metadata.value,instances.host,instances.vm_state,memory_mb from instance_metadata,instances where instances.uuid = instance_metadata.instance_uuid and instances.host in (`%s`) and instances.vm_state !=`error` and instances.vm_state != `deleted`;" % "`,`".join(nodes)
        self.cur.execute(__get_node_info_sql)
        ret = self.cur.fetchall()
        return ret
    def __del__(self):
        self.cur.close()
        self.conn.close()
class checkIps():
    def __init__(self):
        self.ping_queue = Queue.Queue()
        self.up_ip = []
        self.down_ip =[]
    def __check(self,q):
        while q.qsize():
            __ip = q.get()
            __cmd = "ping -c 2 %s" % __ip
            if commands.getstatusoutput(__cmd)[0] == 0:
                self.up_ip.append(__ip)
            else:
                self.down_ip.append(__ip)
            q.task_done()
    def put2q(self,ips):
        for __ip in ips:
            self.ping_queue.put(__ip)
    def checking(self):
        print yellow(`Checking ips ...`)
        for i in xrange(100):
            __pingd = threading.Thread(target=self.__check,args=(self.ping_queue,))
            __pingd.setDaemon
            __pingd.start()
        self.ping_queue.join()
        return {`up`:self.up_ip,`down`:self.down_ip}
class createVm():
    def __init__(self,mysql_host,mysql_user,mysql_passwd):
        self.create_queue = Queue.Queue()
        self.mysql_user =  mysql_user
        self.mysql_host = mysql_host
        self.mysql_passwd = mysql_passwd
    def __put2q(self,cmd_list,q):
        while len(cmd_list) > 0:
            while q.qsize() <= 3:
                q.put(cmd_list.pop())
                time.sleep(1)
                if not cmd_list: break
        time.sleep(1)
    def __create(self,q):
        time.sleep(5)
        while q.qsize() > 0:
            __cmd = q.get()
            __ip = __cmd.split()[-1]
            print "Building %s"% __ip
            ret = commands.getstatusoutput(__cmd)
            if ret[0] == 0:
                time.sleep(2)  
                __vm_state = `building`
                while __vm_state != `active`:
                    time.sleep(5)
                    __vm_state = mysqlEng(host=self.mysql_host,user=self.mysql_user,passwd=self.mysql_passwd).getVmstate(__ip)
                    if __vm_state == `error`:
                        self.error_vms+=1
                        print red("虛擬機器建立出錯,IP:%s") % __ip
                        break
                self.ok_vms+=1
                print green("%s 建立成功,此次建立虛擬機器總數:%s , 成功的虛擬機器:%s ,出錯的虛擬機器:%s") % (__ip,self.all_vms,self.ok_vms,self.error_vms)
            else:
                self.error_vms+=1
                print red("執行命令出錯,IP:%s,出錯資訊: %s 
")%(__ip,ret[1])
    def creating(self,cmds,ths):
        self.all_vms = len(cmds)
        self.ok_vms = 0
        self.error_vms = 0
        __put_thread = threading.Thread(target=self.__put2q, args=(cmds,self.create_queue,))
        __put_thread.setDaemon
        __put_thread.start()
        for i in xrange(ths):
            __created = threading.Thread(target=self.__create, args=(self.create_queue,))
            __created.setDaemon
            __created.start()
            time.sleep(10)
class createAllvm():
    def __init__(self,vmlist,flavor,mysql_host,mysql_user,mysql_passwd):
        self.vmlist = vmlist
        self.mysql_host = mysql_host
        self.mysql_user = mysql_user
        self.mysql_passwd = mysql_passwd
        self.flavor = flavor
    def start(self):
        create_obj = createVm(mysql_host=self.mysql_host,mysql_user=self.mysql_user,mysql_passwd=self.mysql_passwd)
                                                                                                                                                                                                                                                                                        
        first_create_cmd = getCmd(project_info,vmListAnaly(self.vmlist).getFirstCreInfo(),self.flavor,mysql_host=self.mysql_host,mysql_user=self.mysql_user,mysql_passwd=self.mysql_passwd).get_cmd()
        create_obj.creating(first_create_cmd,2)
        first_ips = vmListAnaly(`vmhost`).getFirstIps()
        while True:
            time.sleep(10)
            if mysqlEng(host=self.mysql_host,user=self.mysql_user,passwd=self.mysql_passwd).getActNum(first_ips) == len(first_ips): break
        print `第一波建立完畢`
        second_create_cmd = getCmd(project_info,vmListAnaly(self.vmlist).getSecondCreInfo(),self.flavor,mysql_host=self.mysql_host,mysql_user=self.mysql_user,mysql_passwd=self.mysql_passwd).get_cmd()
        if not second_create_cmd:
            print green(`只有一波了..建立完畢`)
            sys.exit()
        create_obj.creating(second_create_cmd,3)
        second_ips = vmListAnaly(`vmhost`).getSecondIps()
        while True:
            time.sleep(10)
            if mysqlEng(host=self.mysql_host,user=self.mysql_user,passwd=self.mysql_passwd).getActNum(second_ips) == len(second_ips): break
        print `第二波建立完畢`
if __name__ == `__main__`:
    #project_name = sys.argv[1]
    #vmlist = sys.argv[2]
    mysql_host = `127.0.0.1`
    mysql_user = `root`
    mysql_passwd = `123456`
    parser = OptionParser()
    parser.add_option("-c","--create",dest="create",action="store_true",default=False,help="create vm in filename")
    parser.add_option("-u","--update",dest="update",help="update ip to a flavor")
    parser.add_option("-p","--ping",dest="ping",action="store_true",default=False,help="multil threading to ping")
    parser.add_option("-i","--instances",dest="instances",help="query a ip`s info")
    parser.add_option("-n","--nodes",dest="nodes",help="query a host`s info")
    parser.add_option("-g","--getcmd",dest="getcmd",action="store_true",default=False,help="get build vm commands from a file")
    parser.add_option("-d","--delete",dest="delete",help="delete a instance")
    parser.add_option("-f","--filename",dest="filename",help="Specify a file")
    parser.add_option("-F","--flavor",dest="flavor",help="Specify a flavor")
    parser.add_option("-t","--tenant",dest="tenant",help="Specify a tenant")
    (options,args) = parser.parse_args()
    project_conf={
        `test`:{
            `OS_USERNAME`:`test`,
            `OS_PASSWORD`:`test`,
            `OS_TENANT_NAME`:`test`,
            `SECURITY_GROUPS`:`default`,
            `IMAGE_ID`:`25b349f2-a105-4d2d-aabe-89253e8b4eb1`,
        },
        `test2`:{
            `OS_USERNAME`:`test2`,
            `OS_PASSWORD`:`test2`,
            `OS_TENANT_NAME`:`test2`,
            `SECURITY_GROUPS`:`default`,
            `IMAGE_ID`:`a6955dde-7794-45cc-a468-65ce7d2473c1`,  
        },
    }
    flavor={
        `1`:`1`,
        `2`:`2`,
        `4`:`4`,
        `6`:`6`,
        `8`:`8`,
        `12`:`12`,
        `16`:`16`,
    }
    the_mysql_obj = mysqlEng(host=mysql_host,user=mysql_user,passwd=mysql_passwd)
    if options.create:
        project_info = project_conf[options.tenant]
        vmfile = options.filename
        the_create_obj = createAllvm(vmlist=vmfile,flavor=flavor,mysql_host=mysql_host,mysql_user=mysql_user,mysql_passwd=mysql_passwd)
        the_create_obj.start()
    if options.update:
        ip = options.update
        flavor = options.flavor
        the_mysql_obj.updateInstanceFlavor(ip,flavor)
        print "update ok,now the vm %s is %s cups and %sMB memory" % the_mysql_obj.getInstanceFlavor(ip)
        instance_id = the_mysql_obj.getInstanceInfo([ip])[0][0]
        print red(`please command == nova reboot --hard %s == to effect` % instance_id)
    if options.ping:
        filename = options.filename
        allip = vmListAnaly(filename).getAllIps()
        check_obj = checkIps()
        check_obj.put2q(allip)
        check_ret = check_obj.checking()
        if check_ret[`up`]:
            for ip in check_ret[`up`]:
                print red("%s is up,please check...") % ip
            sys.exit(9)
        else:
            print green(`All ip is check ok...,you can create these vms`)
    if options.instances:
        args.append(options.instances)
        ips = args
        instances_info = the_mysql_obj.getInstanceInfo(ips)
        print "id					ip		node			state	memory"
        for i in instances_info:
            print "%s	%s	%s	%s	%s" % i
    if options.nodes:
        args.append(options.nodes)
        nodes = args
        nodes_info = the_mysql_obj.getNodeInfo(nodes)
        print "id					ip		node			state	memory"
        for i in nodes_info:
            print "%s	%s	%s	%s	%s" % i
    if options.getcmd:
        filename = options.filename
        tenant = options.tenant
        project_info = project_conf[tenant]
        result = getCmd(project_info,vmListAnaly(filename).getAllCreInfo(),flavor,mysql_host=mysql_host,mysql_user=mysql_user,mysql_passwd=mysql_passwd).get_cmd()
        for i in result:
            print i
    if options.delete:
        args.append(options.delete)
        ips = args
        instances_ids=[]
        instances_info = the_mysql_obj.getInstanceInfo(ips)
        for i in instances_info:
            instances_ids.append(i[0])
        if not instances_ids:
            print red("no instance found")
            sys.exit(8)
        delete_cmd = "nova delete " + ` `.join(instances_ids)
        result = commands.getstatusoutput(delete_cmd)
        if result[0] == 0:
            print green(`OK`)
        else:
            print red("error info: %s" % result[1])