【python】openstack管理小工具(增删查改,批量ping)
工具介绍: 创建虚拟机会使用多线程队列的方式去控制同时创建的虚拟机数量 如果在创建的虚拟机比较多,会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,数据库帐号等替换成自己生产环境中的信息 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 #!/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 --image %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 \n" ) % (__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\t\t\t\t\tip\t\tnode\t\t\tstate\tmemory" for i in instances_info: print "%s\t%s\t%s\t%s\t%s" % i if options.nodes: args.append(options.nodes) nodes = args nodes_info = the_mysql_obj.getNodeInfo(nodes) print "id\t\t\t\t\tip\t\tnode\t\t\tstate\tmemory" for i in nodes_info: print "%s\t%s\t%s\t%s\t%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 ]) 本文转自lustlost 51CTO博客,原文链接:http://blog.51cto.com/lustlost/1375779,如需转载请自行联系原作者