blob: 7c3e6bb1c6c4b52b578da0f75b163245250b03f7 [file] [log] [blame]
Andy Doan61b4d772012-04-24 10:03:28 -05001#!/usr/bin/python
2
Andy Doan61b4d772012-04-24 10:03:28 -05003import os
Andy Doan61b4d772012-04-24 10:03:28 -05004import sys
Fathi Boudrac14068b2012-12-06 17:42:11 +02005import json
Andy Doan61b4d772012-04-24 10:03:28 -05006import xmlrpclib
Fathi Boudrac14068b2012-12-06 17:42:11 +02007import re
Andy Doan61b4d772012-04-24 10:03:28 -05008
Fathi Boudra2486ee12013-06-28 13:39:07 +03009tests_timeout = {
10 'bluetooth-enablement': 7200,
Fathi Boudra63d5cbb2013-08-02 08:55:36 +030011 'bootchart': 800,
12 'busybox': 800,
Fathi Boudra8c7aa552013-09-17 09:19:41 +030013 'cyclictest': 86400,
Fathi Boudra63d5cbb2013-08-02 08:55:36 +030014 'device-tree': 800,
Fathi Boudra2486ee12013-06-28 13:39:07 +030015 'e2eaudiotest': 7200,
Fathi Boudra63d5cbb2013-08-02 08:55:36 +030016 'ethernet': 800,
Fathi Boudra2486ee12013-06-28 13:39:07 +030017 'gatortests': 1200,
Andrew McDermotte47afbd2013-09-23 19:19:51 +010018 'jtreg-setup': 3600,
19 'jtreg-hotspot-compiler': 3600,
20 'jtreg-hotspot-gc': 3600,
21 'jtreg-hotspot-runtime': 3600,
22 'jtreg-hotspot-sanity': 3600,
23 'jtreg-hotspot-serviceability': 3600,
24 'jtreg-hotspot-testlibrary': 3600,
25 'jtreg-jdk_beans1': 3600,
26 'jtreg-jdk_io': 3600,
27 'jtreg-jdk_lang': 3600,
28 'jtreg-jdk_math': 3600,
29 'jtreg-jdk_net': 3600,
30 'jtreg-jdk_other': 3600,
31 'jtreg-jdk_security1': 3600,
32 'jtreg-jdk_text': 3600,
33 'jtreg-jdk_time': 3600,
34 'jtreg-jdk_util': 3600,
Fathi Boudra63d5cbb2013-08-02 08:55:36 +030035 'kernel-version': 800,
Fathi Boudra2486ee12013-06-28 13:39:07 +030036 'leb-basic-graphics': 7200,
37 'ltp': 7200,
Fathi Boudra63d5cbb2013-08-02 08:55:36 +030038 'mysql': 800,
Fathi Boudrac13926a2013-07-03 11:36:37 +030039 'network-tests-basic': 1200,
Fathi Boudra63d5cbb2013-08-02 08:55:36 +030040 'perf': 800,
41 'phpinfo': 800,
42 'phpmysql': 800,
43 'pwrmgmt': 800,
44 'sdkhelloc': 800,
45 'sdkhellocxx': 800,
Fathi Boudra2486ee12013-06-28 13:39:07 +030046 'smoke-tests-basic': 1200,
Fathi Boudra63d5cbb2013-08-02 08:55:36 +030047 'toolchain': 800,
Fathi Boudra2486ee12013-06-28 13:39:07 +030048 'wifi-enablement': 7200,
49}
50
Fathi Boudrac14068b2012-12-06 17:42:11 +020051tests_nano = [
52 'device-tree',
53 'gatortests',
Fathi Boudrac13926a2013-07-03 11:36:37 +030054 'network-tests-basic',
Fathi Boudrac14068b2012-12-06 17:42:11 +020055 'perf',
56 'pwrmgmt',
Fathi Boudra2486ee12013-06-28 13:39:07 +030057 'smoke-tests-basic',
Fathi Boudra3f7ace92013-04-11 13:06:11 +030058]
Fathi Boudrac14068b2012-12-06 17:42:11 +020059
60tests_alip = [
61 'bootchart',
Fathi Boudra3f7ace92013-04-11 13:06:11 +030062]
Fathi Boudrac14068b2012-12-06 17:42:11 +020063
64tests_desktop = [
65 'e2eaudiotest',
66 'bluetooth-enablement',
67 'wifi-enablement',
68 'leb-basic-graphics',
Fathi Boudra3f7ace92013-04-11 13:06:11 +030069]
Fathi Boudrac14068b2012-12-06 17:42:11 +020070
Fathi Boudra60d0e972013-04-19 10:49:47 +030071tests_openembedded_minimal = [
Marcin Juszkiewicz59172832013-04-18 09:35:00 +020072 'busybox',
Marcin Juszkiewicz1678f112013-04-09 09:55:46 +020073 'device-tree',
Marcin Juszkiewicz59172832013-04-18 09:35:00 +020074 'ethernet',
75 'kernel-version',
Marcin Juszkiewicz1678f112013-04-09 09:55:46 +020076 'perf',
Marcin Juszkiewicz59172832013-04-18 09:35:00 +020077 'toolchain',
Fathi Boudra3f7ace92013-04-11 13:06:11 +030078]
Andy Doan61b4d772012-04-24 10:03:28 -050079
Fathi Boudra60d0e972013-04-19 10:49:47 +030080tests_openembedded_lamp = [
Fathi Boudra60d0e972013-04-19 10:49:47 +030081 'mysql',
82 'phpinfo',
83 'phpmysql',
84 'sdkhelloc',
85 'sdkhellocxx',
86]
87
Andrew McDermottb62dfaf2013-06-26 12:32:30 +010088tests_openembedded_leg_java = [
Andrew McDermottedd9b8d2013-08-24 00:07:53 +010089 'openjdk7-sanity',
90 'openjdk8-sanity',
Andrew McDermott114e7662013-07-03 16:12:37 +010091 'mauve',
Andrew McDermotte47afbd2013-09-23 19:19:51 +010092 'jtreg-setup',
93 'jtreg-hotspot-compiler',
94 'jtreg-hotspot-gc',
95 'jtreg-hotspot-runtime',
96 'jtreg-hotspot-sanity',
97 'jtreg-hotspot-serviceability',
98 'jtreg-hotspot-testlibrary',
99 'jtreg-jdk_beans1',
100 'jtreg-jdk_io',
101 'jtreg-jdk_lang',
102 'jtreg-jdk_math',
103 'jtreg-jdk_net',
104 'jtreg-jdk_other',
105 'jtreg-jdk_security1',
106 'jtreg-jdk_text',
107 'jtreg-jdk_time',
108 'jtreg-jdk_util',
Andrew McDermottb62dfaf2013-06-26 12:32:30 +0100109]
110
Fathi Boudra8e4ce562012-12-08 14:35:17 +0200111# Mapping device type - bundle stream
Andy Doan3462e4c2012-05-18 10:58:06 -0500112DEVICE_STREAM = {
Fathi Boudra8b59a502013-01-18 10:20:04 +0200113 'arndale': 'arndale',
Fathi Boudra8e4ce562012-12-08 14:35:17 +0200114 'beaglexm': 'beaglexm',
Fathi Boudrab97042a2013-04-04 17:49:22 +0300115 'highbank': 'highbank',
Fathi Boudra8e4ce562012-12-08 14:35:17 +0200116 'origen': 'leb-origen',
Andy Doan3462e4c2012-05-18 10:58:06 -0500117 'panda': 'leb-panda-4430',
Paul Larson27308512012-08-17 14:09:05 -0500118 'panda-es': 'leb-panda-es',
Fathi Boudra8e4ce562012-12-08 14:35:17 +0200119 'rtsm_foundation-armv8': 'vexpress64',
120 'rtsm_ve-a15x1-a7x1': 'vexpress',
121 'rtsm_ve-a15x4-a7x4': 'vexpress',
122 'rtsm_ve-armv8': 'vexpress',
Andy Doan3462e4c2012-05-18 10:58:06 -0500123 'snowball_sd': 'leb-snowball',
Fathi Boudra8e4ce562012-12-08 14:35:17 +0200124 'vexpress-a5': 'vexpress',
Fathi Boudra76551e52012-09-19 17:51:33 +0300125 'vexpress-a9': 'vexpress',
Fathi Boudra8e4ce562012-12-08 14:35:17 +0200126 'vexpress-tc2': 'vexpress',
Andy Doan3462e4c2012-05-18 10:58:06 -0500127}
128
Andy Doan61b4d772012-04-24 10:03:28 -0500129
130def obfuscate_credentials(s):
Fathi Boudra3f7ace92013-04-11 13:06:11 +0300131 return re.sub(r'([^ ]:).+?(@)', r'\1xxx\2', s)
Andy Doan61b4d772012-04-24 10:03:28 -0500132
Fathi Boudrac14068b2012-12-06 17:42:11 +0200133
Andy Doan61b4d772012-04-24 10:03:28 -0500134def main():
Fathi Boudra8e4ce562012-12-08 14:35:17 +0200135 """Script entry point: return some JSON based on calling args.
136 We should be called from Jenkins and expect the following to be defined:
137 $HWPACK_BUILD_NUMBER $HWPACK_JOB_NAME HWPACK_FILE_NAME $DEVICE_TYPE
138 """
Andy Doan61b4d772012-04-24 10:03:28 -0500139
Fathi Boudrad1f9a862012-12-28 14:46:04 +0200140 # CI base URL
Fathi Boudra3f7ace92013-04-11 13:06:11 +0300141 ci_base_url = 'https://ci.linaro.org/jenkins/job/'
Fathi Boudra8e4ce562012-12-08 14:35:17 +0200142 # Snapshots base URL
Fathi Boudra3f7ace92013-04-11 13:06:11 +0300143 snapshots_url = 'http://snapshots.linaro.org'
Fathi Boudra8e4ce562012-12-08 14:35:17 +0200144
145 # Name of the hardware pack project
Fathi Boudra3f7ace92013-04-11 13:06:11 +0300146 hwpack_job_name = os.environ.get('HWPACK_JOB_NAME')
Fathi Boudra8e4ce562012-12-08 14:35:17 +0200147 # The hardware pack build number
Fathi Boudra3f7ace92013-04-11 13:06:11 +0300148 hwpack_build_number = os.environ.get('HWPACK_BUILD_NUMBER')
Fathi Boudra8e4ce562012-12-08 14:35:17 +0200149 # Hardware pack file name
Fathi Boudra3f7ace92013-04-11 13:06:11 +0300150 hwpack_file_name = os.environ.get('HWPACK_FILE_NAME', 'Undefined')
151 if hwpack_file_name == 'Undefined':
152 sys.exit('Hardware pack is not defined.')
153
Fathi Boudra8e4ce562012-12-08 14:35:17 +0200154 # Device type
Fathi Boudra3f7ace92013-04-11 13:06:11 +0300155 device_type = os.environ.get('DEVICE_TYPE', 'Undefined')
156 if device_type == 'Undefined':
157 sys.exit('Device type is not defined.')
Fathi Boudra8e4ce562012-12-08 14:35:17 +0200158
159 # Distribution, architecture and hardware pack type
Fathi Boudra3f7ace92013-04-11 13:06:11 +0300160 ret_split = hwpack_job_name.split('-', 2)
161 (distribution, architecture, hwpack_type) = \
162 ret_split[0], ret_split[1], ret_split[2]
Fathi Boudra8e4ce562012-12-08 14:35:17 +0200163 if hwpack_type.startswith('pre-built-images-'):
Fathi Boudra3f7ace92013-04-11 13:06:11 +0300164 hwpack_type = hwpack_type[(len('pre-built-images-')):]
Fathi Boudra65aaf1a2013-01-10 10:35:57 +0200165 if '=' in hwpack_type:
Fathi Boudra3f7ace92013-04-11 13:06:11 +0300166 hwpack_type = hwpack_type[(len('pre-built-images/hwpack=')):]
Fathi Boudra8e4ce562012-12-08 14:35:17 +0200167 # Rootfs type, default is developer
Fathi Boudra3f7ace92013-04-11 13:06:11 +0300168 rootfs_type = os.getenv('ROOTFS_TYPE', 'developer')
Fathi Boudrac14068b2012-12-06 17:42:11 +0200169
170 # Bundle stream name
Fathi Boudra3f7ace92013-04-11 13:06:11 +0300171 bundle_stream_name = os.environ.get(
172 'BUNDLE_STREAM_NAME',
173 '/private/team/linaro/pre-built-%s/' % DEVICE_STREAM[device_type])
174
Fathi Boudrac14068b2012-12-06 17:42:11 +0200175 # LAVA user
Fathi Boudra3f7ace92013-04-11 13:06:11 +0300176 lava_user = os.environ.get('LAVA_USER')
177 if lava_user is None:
Fathi Boudrac14068b2012-12-06 17:42:11 +0200178 f = open('/var/run/lava/lava-user')
179 lava_user = f.read().strip()
180 f.close()
Fathi Boudra3f7ace92013-04-11 13:06:11 +0300181
Fathi Boudrac14068b2012-12-06 17:42:11 +0200182 # LAVA token
Fathi Boudra3f7ace92013-04-11 13:06:11 +0300183 lava_token = os.environ.get('LAVA_TOKEN')
184 if lava_token is None:
Fathi Boudrac14068b2012-12-06 17:42:11 +0200185 f = open('/var/run/lava/lava-token')
186 lava_token = f.read().strip()
187 f.close()
Fathi Boudrac14068b2012-12-06 17:42:11 +0200188
Fathi Boudra3f7ace92013-04-11 13:06:11 +0300189 # LAVA server URL
190 lava_server = os.environ.get('LAVA_SERVER',
Fathi Boudra62997d92013-07-27 09:58:28 +0300191 'validation.linaro.org/RPC2/')
Fathi Boudra3f7ace92013-04-11 13:06:11 +0300192 # LAVA server base URL
193 lava_server_root = lava_server.rstrip('/')
194 if lava_server_root.endswith('/RPC2'):
195 lava_server_root = lava_server_root[:-len('/RPC2')]
196
197 image_url = '%s/%s/pre-built/%s/%s/%s' % \
198 (snapshots_url,
199 distribution,
200 hwpack_type,
201 hwpack_build_number,
Fathi Boudra8e4ce562012-12-08 14:35:17 +0200202 hwpack_file_name)
203
Fathi Boudra3f7ace92013-04-11 13:06:11 +0300204 git_repo = 'git://git.linaro.org/qa/test-definitions.git'
Senthil Kumaran672ac4d2012-12-19 15:10:59 +0530205
Fathi Boudra8e4ce562012-12-08 14:35:17 +0200206 # tests set specific to an image
Fathi Boudra60d0e972013-04-19 10:49:47 +0300207 if distribution == 'openembedded':
208 tests = tests_openembedded_minimal
Fathi Boudrad2bd08b2013-05-06 15:00:00 +0300209 elif distribution == 'ubuntu' or distribution == 'quantal' or distribution == 'raring':
Fathi Boudra60d0e972013-04-19 10:49:47 +0300210 tests = tests_nano
Fathi Boudrac51e0912012-06-15 18:18:41 +0300211
Ricardo Salveti de Araujoacf28542012-06-27 18:56:00 -0300212 # if ubuntu-desktop, cover more test cases (LEB)
Fathi Boudra8e4ce562012-12-08 14:35:17 +0200213 if rootfs_type == 'ubuntu-desktop':
Fathi Boudrac51e0912012-06-15 18:18:41 +0300214 tests += tests_desktop
Andy Doanbc19b7c2012-05-17 12:08:16 -0500215
Ricardo Salveti de Araujo6ad94332012-06-29 02:48:18 -0300216 # if alip, specific tests like bootchart (which should be first)
Fathi Boudra8e4ce562012-12-08 14:35:17 +0200217 if rootfs_type == 'alip':
Ricardo Salveti de Araujo6ad94332012-06-29 02:48:18 -0300218 tests = tests_alip + tests
219
Fathi Boudra60d0e972013-04-19 10:49:47 +0300220 if 'lamp' in rootfs_type:
221 tests += tests_openembedded_lamp
222
Andrew McDermottb62dfaf2013-06-26 12:32:30 +0100223 if 'leg-java' in rootfs_type:
224 tests += tests_openembedded_leg_java
225
Ricardo Salveti de Araujoacf28542012-06-27 18:56:00 -0300226 # removing bluetooth and wifi for devices that don't support it
Fathi Boudra8e4ce562012-12-08 14:35:17 +0200227 if device_type in ['beaglexm', 'vexpress-a9', 'mx53loco']:
Ricardo Salveti de Araujodd780972012-06-29 11:48:47 -0300228 try:
229 tests.remove('bluetooth-enablement')
230 tests.remove('wifi-enablement')
231 except ValueError:
232 pass
Ricardo Salveti de Araujoacf28542012-06-27 18:56:00 -0300233
234 # vexpress doesn't support PM, so disable pwrmgmt
Fathi Boudra8e4ce562012-12-08 14:35:17 +0200235 if device_type in ['vexpress-a9']:
Ricardo Salveti de Araujodd780972012-06-29 11:48:47 -0300236 try:
237 tests.remove('pwrmgmt')
238 except ValueError:
239 pass
Andy Doane9bf2152012-06-12 15:42:10 -0500240
Fathi Boudra62eb6a92012-12-06 19:02:56 +0200241 if distribution == 'openembedded':
Fathi Boudra4079a582012-12-06 19:42:58 +0200242 actions = [{
Fathi Boudra3f7ace92013-04-11 13:06:11 +0300243 'command': 'deploy_linaro_image',
244 'parameters': {
245 'image': '%s' % image_url,
246 },
247 'metadata': {
248 'hwpack.type': '%s' % hwpack_type,
249 'hwpack.build': '%s' % hwpack_build_number,
250 'rootfs.type': '%s' % rootfs_type,
251 'distribution': '%s' % distribution,
252 }
253 },
254 {
255 'command': 'boot_linaro_image',
256 'parameters': {
257 'options': ['boot_cmds=boot_cmds_oe']
258 }
259 }]
Fathi Boudrad2bd08b2013-05-06 15:00:00 +0300260 elif distribution == 'ubuntu' or distribution == 'quantal' or distribution == 'raring':
Fathi Boudra4079a582012-12-06 19:42:58 +0200261 actions = [{
Fathi Boudra3f7ace92013-04-11 13:06:11 +0300262 'command': 'deploy_linaro_image',
263 'parameters': {
264 'image': '%s' % image_url,
265 },
266 'metadata': {
267 'ubuntu.name': '%s' % hwpack_type,
268 'ubuntu.build': '%s' % hwpack_build_number,
269 'rootfs.type': '%s' % rootfs_type,
270 'ubuntu.distribution': '%s' % distribution,
271 }
272 }]
Fathi Boudra4079a582012-12-06 19:42:58 +0200273
Fathi Boudraa9bbadb2012-12-07 16:10:29 +0200274 if len(tests) > 0:
Fathi Boudrad2bd08b2013-05-06 15:00:00 +0300275 if distribution == 'quantal' or distribution == 'raring':
Fathi Boudra60d0e972013-04-19 10:49:47 +0300276 distribution = 'ubuntu'
Senthil Kumaranb30d7382012-12-19 15:11:47 +0530277 for test in tests:
Fathi Boudraebb2f192013-06-17 10:01:09 +0300278 test_list = [(
Fathi Boudra3f7ace92013-04-11 13:06:11 +0300279 {'git-repo': git_repo,
280 'testdef': '{distribution:>s}/{test:>s}.yaml'.format(
Fathi Boudraebb2f192013-06-17 10:01:09 +0300281 distribution=distribution, test=test)})]
Senthil Kumaran007181c2013-04-16 14:43:19 +0530282
Fathi Boudraebb2f192013-06-17 10:01:09 +0300283 actions.append({
284 'command': 'lava_test_shell',
285 'parameters': {
Fathi Boudrab088b142013-07-19 09:54:04 +0300286 'timeout': tests_timeout.get(test, 18000),
Fathi Boudraebb2f192013-06-17 10:01:09 +0300287 'testdef_repos': test_list
288 }
289 })
Fathi Boudrac14068b2012-12-06 17:42:11 +0200290
291 actions.append({
Fathi Boudra3f7ace92013-04-11 13:06:11 +0300292 'command': 'submit_results',
293 'parameters': {
294 'stream': bundle_stream_name,
295 'server': '%s%s' % ('http://', lava_server)
Fathi Boudrac14068b2012-12-06 17:42:11 +0200296 }
297 })
298
Fathi Boudra3f7ace92013-04-11 13:06:11 +0300299 config = json.dumps({'timeout': 18000,
300 'actions': actions,
301 'job_name': '%s%s/%s/' % (ci_base_url,
302 hwpack_job_name,
Fathi Boudrad1f9a862012-12-28 14:46:04 +0200303 hwpack_build_number),
Fathi Boudra3f7ace92013-04-11 13:06:11 +0300304 'device_type': device_type,
Fathi Boudrac14068b2012-12-06 17:42:11 +0200305 }, indent=2)
Fathi Boudra79c1e8b2012-12-02 10:36:57 +0200306
Fathi Boudra8e4ce562012-12-08 14:35:17 +0200307 print config
308
Fathi Boudra3f7ace92013-04-11 13:06:11 +0300309 skip_lava = os.environ.get('SKIP_LAVA')
310 if skip_lava is None:
Fathi Boudra79c1e8b2012-12-02 10:36:57 +0200311 try:
Fathi Boudrac14068b2012-12-06 17:42:11 +0200312 server_url = \
Fathi Boudra3f7ace92013-04-11 13:06:11 +0300313 'https://{lava_user:>s}:{lava_token:>s}@{lava_server:>s}'
Fathi Boudrac14068b2012-12-06 17:42:11 +0200314 server = \
Fathi Boudra3f7ace92013-04-11 13:06:11 +0300315 xmlrpclib.ServerProxy(server_url.format(
316 lava_user=lava_user,
317 lava_token=lava_token,
Fathi Boudrac14068b2012-12-06 17:42:11 +0200318 lava_server=lava_server))
319 lava_job_id = server.scheduler.submit_job(config)
Fathi Boudra79c1e8b2012-12-02 10:36:57 +0200320 except xmlrpclib.ProtocolError, e:
Fathi Boudra3f7ace92013-04-11 13:06:11 +0300321 print 'Error making a LAVA request:', obfuscate_credentials(str(e))
Fathi Boudra79c1e8b2012-12-02 10:36:57 +0200322 sys.exit(1)
Fathi Boudrac14068b2012-12-06 17:42:11 +0200323
Fathi Boudra3f7ace92013-04-11 13:06:11 +0300324 print 'LAVA Job Id: %s, URL: http://%s/scheduler/job/%s' % \
Fathi Boudra8e4ce562012-12-08 14:35:17 +0200325 (lava_job_id, lava_server_root, lava_job_id)
Fathi Boudra3f7ace92013-04-11 13:06:11 +0300326 json.dump({'lava_url': 'http://' + lava_server_root,
Fathi Boudrac14068b2012-12-06 17:42:11 +0200327 'job_id': lava_job_id},
Fathi Boudra3f7ace92013-04-11 13:06:11 +0300328 open('lava-job-info', 'w'))
Fathi Boudra8e4ce562012-12-08 14:35:17 +0200329
Fathi Boudra3f7ace92013-04-11 13:06:11 +0300330 lava_job_info_orig = hwpack_file_name.replace('.img.gz', '.html')
331 top_dir = os.environ.get('WORKSPACE', '.')
Fathi Boudrade020592012-12-10 13:25:14 +0200332 for root, dirs, files in os.walk(top_dir):
333 for file in files:
334 if file == lava_job_info_orig:
Fathi Boudra3f7ace92013-04-11 13:06:11 +0300335 lava_job_info_orig = os.path.join(root, file)
Fathi Boudra5e481022012-12-08 19:21:16 +0200336
Fathi Boudrade020592012-12-10 13:25:14 +0200337 with open(lava_job_info_orig) as f:
338 buffer = f.read()
Fathi Boudra5e481022012-12-08 19:21:16 +0200339
Fathi Boudra3f7ace92013-04-11 13:06:11 +0300340 buffer = buffer.replace(
341 'var lavaJobId = 0',
342 'var lavaJobId = ' + str(lava_job_id), 1)
Fathi Boudrade020592012-12-10 13:25:14 +0200343
Fathi Boudra3f7ace92013-04-11 13:06:11 +0300344 lava_job_info = lava_job_info_orig.replace(
345 '.html',
346 '-' + device_type + '.html')
Fathi Boudrade020592012-12-10 13:25:14 +0200347 with open(lava_job_info, 'w') as f:
348 f.write(buffer)
349 os.remove(lava_job_info_orig)
Fathi Boudra79c1e8b2012-12-02 10:36:57 +0200350 else:
Fathi Boudra3f7ace92013-04-11 13:06:11 +0300351 print 'LAVA job submission skipped.'
Andy Doan61b4d772012-04-24 10:03:28 -0500352
Fathi Boudra3f7ace92013-04-11 13:06:11 +0300353
354if __name__ == '__main__':
Andy Doan61b4d772012-04-24 10:03:28 -0500355 main()