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
|
#!/usr/bin/python
#
# wait4guesttasks
# usage: wait4guesttasks <--guestname name | --guestrecipe recipe> \
# [--timeout NN[s|m|h|d]] [--interval NN[s|m|h|d]] \
# [/task/name /task2/name ...]
# this script will take a name or recipeid of the guest and list of task to be
# waited to for completion and a timeout value to wait for all tasks to be
# completed. If the tasks inside the guest complete with the optional statuses,
# it'll exit with exit code of 0. If anything goes wrong, it'll exit with an
# exit code other than zero. timeout argument can take an optional and
# case-insensitive suffix of s,m,h,d corresponding to seconds,minutes,hours,days
# respectively.
# Everything but either guestname or guestrecipeid is optional. Default values
# follows:
# timeout: none. ie. it'll run forever until the tasks are completed.
# interval: set to 120 seconds.
# tasks: default is all tasks inside the guest to be completed.
# Additionally, a desired result for any task can be given. For that the syntax
# is :
# taskname=result for example /distribution/install=Pass
# If no desired status are given, then the script will just wait until the task
# is completed. For example the following syntax:
# .waitforguesttasks.py --guestname myguest /distribution/install=Pass\
# /my/test
# will wait until /distribution/install test inside myguest has completed and
# Passed AND the test /my/test has completed. If /distribution/install has a
# result other than Pass, it'll exit with an error code. The results are
# case-insensitive, so /distribution/install=Pass|pass|PASS are all same.
#
import os
import sys
import xmlrpclib
import xml.dom.minidom
import time
from optparse import OptionParser
# findguestrecipe
# looks up the recipeid of the guest.
# should be called from the hostmachine where the hypervisor's recipeid will be
# available. assumes that a connection to global proxy object is established
# already.
def findguestrecipe(name):
recipe_xml = proxy.get_my_recipe(dict(recipe_id=os.environ['RECIPEID']))
doc = xml.dom.minidom.parseString(recipe_xml)
for guestrecipe in doc.getElementsByTagName('guestrecipe'):
if guestrecipe.getAttribute('guestname') == name:
return guestrecipe.getAttribute('id')
#if we didn't find it, return None
return None
tasks_list = None
tasks_dict = { }
total_sleep = 0
timeout = -1
interval = 20
errors = []
parser = OptionParser()
proxy = xmlrpclib.ServerProxy('http://%s:8000/RPC2' % os.environ['LAB_CONTROLLER'])
# add options to parser all the options...
parser.add_option("--guestname", dest="guestname", help="Name of guest",
metavar="GUESTNAME")
parser.add_option("--guestrecipe", dest="guestrecipe", help="Recipeid of guest",
metavar="GUESTRECIPE")
parser.add_option("--timeout", dest="timeout", help="Time to wait until the \
tasks are completed", metavar="TIMEOUT")
parser.add_option("--interval", dest="interval", help="How often to query the \
lab controller to check on the tasks", metavar="INTERVAL")
(options, args) = parser.parse_args()
if not options.guestname and not options.guestrecipe:
print "no guestname or guestrecipe"
print "either one of them must be supplied"
sys.exit(1)
if options.guestrecipe:
guestrecipe = options.guestrecipe
else:
guestrecipe = findguestrecipe(options.guestname)
if not guestrecipe:
print "Can't find recipeid for %s", (options.guestname)
sys.exit(3)
if options.timeout:
timeout = options.timeout
if timeout[-1] == 's' or timeout[-1] == 'S':
timeout = int(timeout[:-1])
elif timeout[-1] == 'm' or timeout[-1] == 'M':
timeout = int(timeout[:-1])
timeout = timeout * 60
elif timeout[-1] == 'h' or timeout[-1] == 'H':
timeout = int(timeout[:-1])
timeout = timeout * 3600
elif timeout[-1] == 'd' or timeout[-1] == 'D':
timeout = int(timeout[:-1])
timeout = timeout * 86400
timeout = int(timeout)
if options.interval:
interval = options.interval
if interval[-1] == 's' or interval[-1] == 'S':
interval = int(interval[:-1])
elif interval[-1] == 'm' or interval[-1] == 'M':
interval = int(interval[:-1])
interval = interval * 60
elif interval[-1] == 'h' or interval[-1] == 'H':
interval = int(interval[:-1])
interval = interval * 3600
elif interval[-1] == 'd' or interval[-1] == 'D':
interval = int(interval[:-1])
interval = interval * 86400
interval = int(interval)
# if there are any args, they'll be the tasks.
tasks_list = args
# default tasks_list is all
if not tasks_list:
tasks_list = []
# find all the tasks inside the guest
recipe_xml = proxy.get_my_recipe(dict(recipe_id=guestrecipe))
doc = xml.dom.minidom.parseString(recipe_xml)
for xmltasks in doc.getElementsByTagName('task'):
taskname = xmltasks.getAttribute('name')
tasks_list.append(taskname)
print "guestrecipe that'll be used is: " + guestrecipe
# walk thru tasks and see what (if any) results that needs to be completed
for task in tasks_list:
idv_task = task.split('=')
if len(idv_task) > 1:
tasks_dict[idv_task[0]] = idv_task[1]
else:
tasks_dict[idv_task[0]] = None
print "waiting for below tasks to be completed in %s :" % (guestrecipe)
print "Task name Result "
for key,value in tasks_dict.iteritems():
print "%s %s" % (key,value)
while len(tasks_dict) > 0:
if timeout > -1:
if total_sleep > timeout:
print "Timeout waiting for the tasks to complete."
if len(errors) > 0:
print "Also these tasks didn't have the expected result: "
print errors
sys.exit(5)
recipe_xml = proxy.get_my_recipe(dict(recipe_id=os.environ['RECIPEID']))
doc = xml.dom.minidom.parseString(recipe_xml)
for xmltasks in doc.getElementsByTagName('task'):
taskname = xmltasks.getAttribute('name')
taskstatus = xmltasks.getAttribute('status')
taskresult = xmltasks.getAttribute('result')
if taskstatus != 'Completed':
continue
if taskname in tasks_dict:
# check if we need to be aware of the result
if tasks_dict[taskname] is not None:
if taskresult.lower() != tasks_dict[taskname].lower():
print "For %s looking for %s but got %s" \
% (taskname,tasks_dict[taskname],taskresult)
errors.append(taskname)
del tasks_dict[taskname]
else:
print "Got %s done" % (taskname)
del tasks_dict[taskname]
if len(tasks_dict) > 0:
print "Now waiting for : "
for key,value in tasks_dict.iteritems():
print "%s %s" % (key,value)
else:
print "Got %s done" % (taskname)
del tasks_dict[taskname]
if len(tasks_dict) > 0:
print "Now waiting for : "
for key,value in tasks_dict.iteritems():
print "%s %s" % (key,value)
if len(tasks_dict) == 0:
break
total_sleep = total_sleep + interval
time.sleep(interval)
if len(errors) > 0:
print "These tasks didn't have the expected result: "
print errors
sys.exit(2)
sys.exit(0)
|