Merge lp:~le-chi-thu/lava-dispatcher/improve-logging-2 into lp:lava-dispatcher

Proposed by Le Chi Thu
Status: Merged
Approved by: Zygmunt Krynicki
Approved revision: 207
Merged at revision: 221
Proposed branch: lp:~le-chi-thu/lava-dispatcher/improve-logging-2
Merge into: lp:lava-dispatcher
Diff against target: 316 lines (+58/-17)
7 files modified
lava_dispatcher/actions/boot_control.py (+0/-2)
lava_dispatcher/actions/launch_control.py (+4/-3)
lava_dispatcher/client/base.py (+4/-1)
lava_dispatcher/client/master.py (+13/-5)
lava_dispatcher/connection.py (+1/-1)
lava_dispatcher/job.py (+32/-1)
lava_dispatcher/utils.py (+4/-4)
To merge this branch: bzr merge lp:~le-chi-thu/lava-dispatcher/improve-logging-2
Reviewer Review Type Date Requested Status
Le Chi Thu (community) Needs Resubmitting
Yongqin Liu Approve
Review via email: mp+90253@code.launchpad.net

Description of the change

make it easier to follow the flow and outcome of actions

To post a comment you must log in.
Revision history for this message
Yongqin Liu (liuyq0307) wrote :

the logging level has been set in lava-dispatcher/lava-dispatch with the default value specified in lava-dispatcher.conf.
is it necessary that we change that to use the value specified in job file, and delete the _set_logging_level method?

review: Approve
Revision history for this message
Zygmunt Krynicki (zyga) wrote :

Hi ChiThu

59 - rc = session.run('lava-test help', response="list-test", timeout=60)
60 + rc = session.run('lava-test -h', response="list-test", timeout=60)

I understand this is not related to logging

294 + def _set_logging_level(self):
295 + # set logging level is optional
296 + try:
297 + logging.root.setLevel(self.logging_level)
298 + except :
299 + pass

I understand the intent was to ignore missing entries in the job file (and in that case accessing self.logging_level would raise KeyError). I think this is somewhat confusing and I'd suggest wrapping that inside the def logging_level(self) property method. To users of this class this should be a normal property, not something that may raise an unexpected KeyError. In addition, I think we should validate the values of logging level that are passed. Instead of using raw integers that few users will understand (is 0 more verbose than 100?) I would just use the standard set of logging.XXX names {DEBUG, INFO, WARNING, ERROR, CRITICAL}.

I can show you how to make code like that elegant and how to validate the input quickly.

Revision history for this message
Le Chi Thu (le-chi-thu) wrote :

wait merging util I have updated according to the discussion below.

<zyga> ChiThu: so for that isuse: I was suggesting to use foo.set_logging_level("info") instead of 0 or 100 or whatever in between
<zyga> ChiThu: you can convert a string to an integer (for logging) using...
<zyga> ChiThu: try logging.getLevelName("INFO")
<zyga> ChiThu: then I was hoping that we actually validate the dispatcher job file
<zyga> ChiThu: a simple schema could check if the log level is in the valid set ("INFO", "DEBUG", etc)
<zyga> ChiThu: for doing that I could point you to json-schema-validator documentation
<zyga> ChiThu: and to json-document documentation (for better tutorial-like approach)
* antipov (~antipov@gateway/tor-sasl/antipov) has joined #linaro
<plars> zyga, ChiThu: Adding a schema for the dispatcher would also go a long way toward documenting the dispatcher
<ChiThu> zyga, yes, good idea about schema for dispatcher

Revision history for this message
Paul Larson (pwlars) wrote :

I don't think adding a schema and validator should be part of this merge, though I do thing we should do it. I'll add a blueprint for it as I think it would improve reliability and documentation in the dispatcher. Is that something you'd like to work on ChiThu?

Revision history for this message
Le Chi Thu (le-chi-thu) wrote :

I can update the log_level to string and let the let schema and validator feature be in an other patch.

Revision history for this message
Paul Larson (pwlars) wrote :

You may want to take a look at logging._checklevel, should simplify this so that it can take either a string, or numerical argument

206. By Le Chi Thu <email address hidden> <email address hidden>

Use string as logging level

207. By Le Chi Thu <email address hidden> <email address hidden>

Synched with trunk

Revision history for this message
Le Chi Thu (le-chi-thu) wrote :

Updated according to the comments.
* Use string as logging level.
* Removed not logging related changes
* Sync with trunk

review: Needs Resubmitting
Revision history for this message
Zygmunt Krynicki (zyga) wrote :

ChiThu: resubmit == submit another proposal I think

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lava_dispatcher/actions/boot_control.py'
--- lava_dispatcher/actions/boot_control.py 2011-11-24 03:00:54 +0000
+++ lava_dispatcher/actions/boot_control.py 2012-02-07 19:21:18 +0000
@@ -43,7 +43,6 @@
43 client = self.client43 client = self.client
44 status = 'pass'44 status = 'pass'
45 try:45 try:
46 logging.info("Boot Linaro image")
47 client.boot_linaro_image()46 client.boot_linaro_image()
48 except:47 except:
49 logging.exception("boot_linaro_image failed")48 logging.exception("boot_linaro_image failed")
@@ -58,5 +57,4 @@
58 """57 """
59 def run(self):58 def run(self):
60 client = self.client59 client = self.client
61 logging.info("Boot master image")
62 client.boot_master_image()60 client.boot_master_image()
6361
=== modified file 'lava_dispatcher/actions/launch_control.py'
--- lava_dispatcher/actions/launch_control.py 2012-02-02 01:56:11 +0000
+++ lava_dispatcher/actions/launch_control.py 2012-02-07 19:21:18 +0000
@@ -62,8 +62,9 @@
62 json_bundle = json.dumps(main_bundle)62 json_bundle = json.dumps(main_bundle)
63 job_name = self.context.job_data.get('job_name', "LAVA Results")63 job_name = self.context.job_data.get('job_name', "LAVA Results")
64 try:64 try:
65 print >> self.context.oob_file, 'dashboard-put-result:', \65 result = dashboard.put_ex(json_bundle, job_name, stream)
66 dashboard.put_ex(json_bundle, job_name, stream)66 print >> self.context.oob_file, 'dashboard-put-result:', result
67 logging.info("Dashboard : %s" %result)
67 except xmlrpclib.Fault, err:68 except xmlrpclib.Fault, err:
68 logging.warning("xmlrpclib.Fault occurred")69 logging.warning("xmlrpclib.Fault occurred")
69 logging.warning("Fault code: %d" % err.faultCode)70 logging.warning("Fault code: %d" % err.faultCode)
@@ -176,6 +177,6 @@
176 logging.warn("The url seems not RPC2 or xml-rpc endpoints, please make sure it's a valid one!!!")177 logging.warn("The url seems not RPC2 or xml-rpc endpoints, please make sure it's a valid one!!!")
177 dashboard = srv.dashboard178 dashboard = srv.dashboard
178179
179 logging.info("server RPC endpoint URL: %s" % server)180 logging.debug("server RPC endpoint URL: %s" % server)
180 return dashboard181 return dashboard
181182
182183
=== modified file 'lava_dispatcher/client/base.py'
--- lava_dispatcher/client/base.py 2012-02-07 18:42:14 +0000
+++ lava_dispatcher/client/base.py 2012-02-07 19:21:18 +0000
@@ -374,7 +374,6 @@
374 timeout=timeout)374 timeout=timeout)
375 if match_id == 1:375 if match_id == 1:
376 raise OperationFailed376 raise OperationFailed
377 logging.info("System is in test image now")
378377
379 def deploy_linaro(self, hwpack, rootfs, kernel_matrix=None, use_cache=True, rootfstype='ext3'):378 def deploy_linaro(self, hwpack, rootfs, kernel_matrix=None, use_cache=True, rootfstype='ext3'):
380 raise NotImplementedError(self.deploy_linaro)379 raise NotImplementedError(self.deploy_linaro)
@@ -386,6 +385,8 @@
386 """385 """
387 Reboot the system to the test image386 Reboot the system to the test image
388 """387 """
388 logging.info("Boot the test image")
389
389 self.proc._boot(self.boot_cmds)390 self.proc._boot(self.boot_cmds)
390 self.in_test_shell(300)391 self.in_test_shell(300)
391 # set PS1 to include return value of last command392 # set PS1 to include return value of last command
@@ -395,6 +396,8 @@
395 self.proc.sendline('export PS1="$PS1 [rc=$(echo \$?)]: "')396 self.proc.sendline('export PS1="$PS1 [rc=$(echo \$?)]: "')
396 self.proc.expect(self.tester_str, timeout=10)397 self.proc.expect(self.tester_str, timeout=10)
397398
399 logging.info("System is in test image now")
400
398 def get_seriallog(self):401 def get_seriallog(self):
399 return self.sio.getvalue()402 return self.sio.getvalue()
400403
401404
=== modified file 'lava_dispatcher/client/master.py'
--- lava_dispatcher/client/master.py 2012-01-27 03:23:09 +0000
+++ lava_dispatcher/client/master.py 2012-02-07 19:21:18 +0000
@@ -121,7 +121,7 @@
121 session.run('umount /mnt/lava/boot')121 session.run('umount /mnt/lava/boot')
122122
123def _recreate_uInitrd(session):123def _recreate_uInitrd(session):
124 logging.info("Recreate uInitrd")124 logging.debug("Recreate uInitrd")
125 # Original android sdcard partition layout by l-a-m-c125 # Original android sdcard partition layout by l-a-m-c
126 sys_part_org = session._client.device_option("sys_part_android_org")126 sys_part_org = session._client.device_option("sys_part_android_org")
127 cache_part_org = session._client.device_option("cache_part_android_org")127 cache_part_org = session._client.device_option("cache_part_android_org")
@@ -245,9 +245,8 @@
245 self.run(245 self.run(
246 cmd, [pattern1, pexpect.EOF, pexpect.TIMEOUT], timeout=5)246 cmd, [pattern1, pexpect.EOF, pexpect.TIMEOUT], timeout=5)
247 if self.match_id == 0:247 if self.match_id == 0:
248 logging.info("\nmatching pattern is %s" % self.match_id)
249 ip = self.match.group(1)248 ip = self.match.group(1)
250 logging.info("Master IP is %s" % ip)249 logging.debug("Master image IP is %s" % ip)
251 return ip250 return ip
252 return None251 return None
253252
@@ -269,9 +268,11 @@
269 boot_tgz, root_tgz = self._generate_tarballs(268 boot_tgz, root_tgz = self._generate_tarballs(
270 hwpack, rootfs, kernel_matrix, use_cache)269 hwpack, rootfs, kernel_matrix, use_cache)
271 except:270 except:
271 logging.error("Deployment tarballs preparation failed")
272 tb = traceback.format_exc()272 tb = traceback.format_exc()
273 self.sio.write(tb)273 self.sio.write(tb)
274 raise CriticalError("Deployment tarballs preparation failed")274 raise CriticalError("Deployment tarballs preparation failed")
275
275 logging.info("Booting master image")276 logging.info("Booting master image")
276 try:277 try:
277 self.boot_master_image()278 self.boot_master_image()
@@ -288,6 +289,7 @@
288 try:289 try:
289 session.wait_network_up()290 session.wait_network_up()
290 except:291 except:
292 logging.error("Unable to reach LAVA server, check network")
291 tb = traceback.format_exc()293 tb = traceback.format_exc()
292 self.sio.write(tb)294 self.sio.write(tb)
293 raise CriticalError("Unable to reach LAVA server, check network")295 raise CriticalError("Unable to reach LAVA server, check network")
@@ -296,6 +298,7 @@
296 _deploy_linaro_rootfs(session, root_url)298 _deploy_linaro_rootfs(session, root_url)
297 _deploy_linaro_bootfs(session, boot_url)299 _deploy_linaro_bootfs(session, boot_url)
298 except:300 except:
301 logging.error("Deployment failed")
299 tb = traceback.format_exc()302 tb = traceback.format_exc()
300 self.sio.write(tb)303 self.sio.write(tb)
301 raise CriticalError("Deployment failed")304 raise CriticalError("Deployment failed")
@@ -317,6 +320,7 @@
317 try:320 try:
318 session.wait_network_up()321 session.wait_network_up()
319 except:322 except:
323 logging.error("Unable to reach LAVA server, check network")
320 tb = traceback.format_exc()324 tb = traceback.format_exc()
321 self.sio.write(tb)325 self.sio.write(tb)
322 raise CriticalError("Unable to reach LAVA server, check network")326 raise CriticalError("Unable to reach LAVA server, check network")
@@ -325,6 +329,7 @@
325 boot_tbz2, system_tbz2, data_tbz2, pkg_tbz2 = \329 boot_tbz2, system_tbz2, data_tbz2, pkg_tbz2 = \
326 self._download_tarballs(boot, system, data, pkg, use_cache)330 self._download_tarballs(boot, system, data, pkg, use_cache)
327 except:331 except:
332 logging.error("Unable to download artifacts for deployment")
328 tb = traceback.format_exc()333 tb = traceback.format_exc()
329 self.sio.write(tb)334 self.sio.write(tb)
330 raise CriticalError("Unable to download artifacts for deployment")335 raise CriticalError("Unable to download artifacts for deployment")
@@ -353,6 +358,7 @@
353# _purge_linaro_android_sdcard(session)358# _purge_linaro_android_sdcard(session)
354 _deploy_linaro_android_data(session, data_url)359 _deploy_linaro_android_data(session, data_url)
355 except:360 except:
361 logging.error("Android deployment failed")
356 tb = traceback.format_exc()362 tb = traceback.format_exc()
357 self.sio.write(tb)363 self.sio.write(tb)
358 raise CriticalError("Android deployment failed")364 raise CriticalError("Android deployment failed")
@@ -400,6 +406,7 @@
400 """406 """
401 reboot the system, and check that we are in a master shell407 reboot the system, and check that we are in a master shell
402 """408 """
409 logging.info("Boot the system master image")
403 self.proc.soft_reboot()410 self.proc.soft_reboot()
404 try:411 try:
405 self.proc.expect("Starting kernel")412 self.proc.expect("Starting kernel")
@@ -410,6 +417,7 @@
410 self._in_master_shell(300)417 self._in_master_shell(300)
411 self.proc.sendline('export PS1="$PS1 [rc=$(echo \$?)]: "')418 self.proc.sendline('export PS1="$PS1 [rc=$(echo \$?)]: "')
412 self.proc.expect(self.master_str, timeout=10, lava_no_logging=1)419 self.proc.expect(self.master_str, timeout=10, lava_no_logging=1)
420 logging.info("System is in master image now")
413421
414 def _format_testpartition(self, session, fstype):422 def _format_testpartition(self, session, fstype):
415 logging.info("Format testboot and testrootfs partitions")423 logging.info("Format testboot and testrootfs partitions")
@@ -434,6 +442,7 @@
434 _extract_partition(image_file, self.boot_part, boot_tgz)442 _extract_partition(image_file, self.boot_part, boot_tgz)
435 _extract_partition(image_file, self.root_part, root_tgz)443 _extract_partition(image_file, self.root_part, root_tgz)
436 except:444 except:
445 logging.error("Failed to generate tarballs")
437 shutil.rmtree(tarball_dir)446 shutil.rmtree(tarball_dir)
438 tb = traceback.format_exc()447 tb = traceback.format_exc()
439 self.sio.write(tb)448 self.sio.write(tb)
@@ -553,8 +562,7 @@
553 [self.master_str, pexpect.TIMEOUT], timeout=timeout, lava_no_logging=1)562 [self.master_str, pexpect.TIMEOUT], timeout=timeout, lava_no_logging=1)
554 if match_id == 1:563 if match_id == 1:
555 raise OperationFailed564 raise OperationFailed
556 logging.info("System is in master image now")565
557
558 @contextlib.contextmanager566 @contextlib.contextmanager
559 def _master_session(self):567 def _master_session(self):
560 """A session that can be used to run commands in the master image.568 """A session that can be used to run commands in the master image.
561569
=== modified file 'lava_dispatcher/connection.py'
--- lava_dispatcher/connection.py 2012-01-12 23:08:03 +0000
+++ lava_dispatcher/connection.py 2012-02-07 19:21:18 +0000
@@ -82,13 +82,13 @@
82 self.sendline("")82 self.sendline("")
8383
84 def soft_reboot(self):84 def soft_reboot(self):
85 logging.info("Perform soft reboot the system")
85 cmd = self.device_option("soft_boot_cmd")86 cmd = self.device_option("soft_boot_cmd")
86 if cmd != "":87 if cmd != "":
87 self.sendline(cmd)88 self.sendline(cmd)
88 else:89 else:
89 self.sendline("reboot")90 self.sendline("reboot")
90 # set soft reboot timeout 120s, or do a hard reset91 # set soft reboot timeout 120s, or do a hard reset
91 logging.info("Rebooting the system")
92 id = self.expect(92 id = self.expect(
93 ['Restarting system.', 'The system is going down for reboot NOW',93 ['Restarting system.', 'The system is going down for reboot NOW',
94 'Will now restart', pexpect.TIMEOUT], timeout=120)94 'Will now restart', pexpect.TIMEOUT], timeout=120)
9595
=== modified file 'lava_dispatcher/job.py'
--- lava_dispatcher/job.py 2012-02-02 11:01:31 +0000
+++ lava_dispatcher/job.py 2012-02-07 19:21:18 +0000
@@ -67,6 +67,9 @@
67 'type': 'integer',67 'type': 'integer',
68 'optional': False,68 'optional': False,
69 },69 },
70 'logging_level': {
71 'optional': True,
72 },
70 },73 },
71 }74 }
7275
@@ -85,6 +88,13 @@
85 return self.job_data['target']88 return self.job_data['target']
8689
87 @property90 @property
91 def logging_level(self):
92 try:
93 return self.job_data['logging_level']
94 except :
95 return None
96
97 @property
88 def image_type(self):98 def image_type(self):
89 return self.job_data.get('image_type')99 return self.job_data.get('image_type')
90100
@@ -101,6 +111,7 @@
101111
102 def run(self):112 def run(self):
103 self.validate()113 self.validate()
114 self._set_logging_level()
104 lava_commands = get_all_cmds()115 lava_commands = get_all_cmds()
105116
106 if self.job_data['actions'][-1]['command'].startswith("submit_results"):117 if self.job_data['actions'][-1]['command'].startswith("submit_results"):
@@ -119,6 +130,7 @@
119 try:130 try:
120 for cmd in self.job_data['actions']:131 for cmd in self.job_data['actions']:
121 params = cmd.get('parameters', {})132 params = cmd.get('parameters', {})
133 logging.info("[ACTION-B] Command %s is started with parameters %s." % (cmd['command'],params))
122 metadata = cmd.get('metadata', {})134 metadata = cmd.get('metadata', {})
123 self.context.test_data.add_metadata(metadata)135 self.context.test_data.add_metadata(metadata)
124 action = lava_commands[cmd['command']](self.context)136 action = lava_commands[cmd['command']](self.context)
@@ -135,8 +147,8 @@
135 status = 'pass'147 status = 'pass'
136 finally:148 finally:
137 err_msg = ""149 err_msg = ""
138 logging.info("Action %s finished." % cmd['command'])
139 if status == 'fail':150 if status == 'fail':
151 logging.warning("[ACTION-E] %s is finished with error (%s)." %(cmd['command'], err))
140 err_msg = "Lava failed at action %s with error: %s\n" %\152 err_msg = "Lava failed at action %s with error: %s\n" %\
141 (cmd['command'], unicode(str(err), 'ascii', 'replace'))153 (cmd['command'], unicode(str(err), 'ascii', 'replace'))
142 if cmd['command'] == 'lava_test_run':154 if cmd['command'] == 'lava_test_run':
@@ -146,6 +158,7 @@
146 # output to both serial log and logfile158 # output to both serial log and logfile
147 self.context.client.sio.write(err_msg)159 self.context.client.sio.write(err_msg)
148 else:160 else:
161 logging.info("[ACTION-E] %s is finished successfully." %cmd['command'])
149 err_msg = ""162 err_msg = ""
150 self.context.test_data.add_result(163 self.context.test_data.add_result(
151 action.test_name(**params), status, err_msg)164 action.test_name(**params), status, err_msg)
@@ -159,3 +172,21 @@
159 action = lava_commands[submit_results['command']](172 action = lava_commands[submit_results['command']](
160 self.context)173 self.context)
161 action.run(**params)174 action.run(**params)
175
176 def _set_logging_level(self):
177 # set logging level is optional
178 level = self.logging_level
179 # CRITICAL, ERROR, WARNING, INFO or DEBUG
180 if level:
181 if level == 'DEBUG':
182 logging.root.setLevel(logging.DEBUG)
183 elif level == 'INFO':
184 logging.root.setLevel(logging.INFO)
185 elif level == 'WARNING':
186 logging.root.setLevel(logging.WARNING)
187 elif level == 'ERROR':
188 logging.root.setLevel(logging.ERROR)
189 elif level == 'CRITICAL':
190 logging.root.setLevel(logging.CRITICAL)
191 else:
192 logging.warning("Unknown logging level in the job '%s'. Allow level are : CRITICAL, ERROR, WARNING, INFO or DEBUG" %level)
162193
=== modified file 'lava_dispatcher/utils.py'
--- lava_dispatcher/utils.py 2012-01-26 10:11:27 +0000
+++ lava_dispatcher/utils.py 2012-02-07 19:21:18 +0000
@@ -55,9 +55,9 @@
55 if err.errno == errno.EXDEV:55 if err.errno == errno.EXDEV:
56 shutil.copy(cache_loc, file_location)56 shutil.copy(cache_loc, file_location)
57 if err.errno == errno.EEXIST:57 if err.errno == errno.EEXIST:
58 logging.info("Cached copy of %s already exists" % url)58 logging.debug("Cached copy of %s already exists" % url)
59 else:59 else:
60 logging.exception("os.link failed")60 logging.exception("os.link '%s' with '%s' failed"%(cache_loc,file_location))
61 else:61 else:
62 file_location = download(url, path)62 file_location = download(url, path)
63 try:63 try:
@@ -70,7 +70,7 @@
70 if err.errno == errno.EXDEV:70 if err.errno == errno.EXDEV:
71 shutil.copy(file_location, cache_loc)71 shutil.copy(file_location, cache_loc)
72 if err.errno == errno.EEXIST:72 if err.errno == errno.EEXIST:
73 logging.info("Cached copy of %s already exists" % url)73 logging.debug("Cached copy of %s already exists" % url)
74 else:74 else:
75 logging.exception("os.link failed")75 logging.exception("os.link failed")
76 return file_location76 return file_location
@@ -90,6 +90,6 @@
90 return map(strip_newlines, list(splitter))90 return map(strip_newlines, list(splitter))
9191
92def logging_system(cmd):92def logging_system(cmd):
93 logging.info('executing %r'%cmd)93 logging.debug("Executing on host : '%r'"%cmd)
94 return os.system(cmd)94 return os.system(cmd)
9595

Subscribers

People subscribed via source and target branches