工具介绍:

创建虚拟机会使用多线程队列的方式去控制同时创建的虚拟机数量


如果在创建的虚拟机比较多,会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  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  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  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  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  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  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  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  in  result:
             print  i
     if  options.delete:
         args.append(options.delete)
         ips  =  args
         instances_ids = []
         instances_info  =  the_mysql_obj.getInstanceInfo(ips)
         for  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 ])