工具介绍:
创建虚拟机会使用多线程队列的方式去控制同时创建的虚拟机数量 如果在创建的虚拟机比较多,会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,如需转载请自行联系原作者