Merge lp:~harlowja/cloud-init/cmdline-kernel-logging into lp:~cloud-init-dev/cloud-init/trunk

Proposed by Joshua Harlow
Status: Rejected
Rejected by: Chad Smith
Proposed branch: lp:~harlowja/cloud-init/cmdline-kernel-logging
Merge into: lp:~cloud-init-dev/cloud-init/trunk
Diff against target: 212 lines (+106/-29)
4 files modified
bin/cloud-init (+1/-1)
cloudinit/log.py (+54/-8)
cloudinit/util.py (+23/-20)
doc/examples/cloud-config-log-level.txt (+28/-0)
To merge this branch: bzr merge lp:~harlowja/cloud-init/cmdline-kernel-logging
Reviewer Review Type Date Requested Status
Server Team CI bot continuous-integration Needs Fixing
cloud-init Commiters Pending
Review via email: mp+122755@code.launchpad.net

Description of the change

Add the ability to override the logging levels via cloud-config/kernel, instead of forcing users to alter the large '05_logging.cfg' blob.

To post a comment you must log in.
Revision history for this message
Server Team CI bot (server-team-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Chad Smith (chad.smith) wrote :

Hello,
Thank you for taking the time to contribute to cloud-init. Cloud-init has moved its revision control system to git. As a result, we are marking all bzr merge proposals as 'rejected'. If you would like to re-submit this proposal for review, please do so by following the current HACKING documentation at http://cloudinit.readthedocs.io/en/latest/topics/hacking.html.

Also, it seems an evolution of this logging configuration has already landed in cloud-init master under the logcfg cloud-config module. If you feel current cloud-init changes don't meet your needs please either file a but against cloud-init or propose an iteration of this branch against master.
https://cloudinit.readthedocs.io/en/latest/topics/logging.html

Unmerged revisions

647. By Joshua Harlow

Add log level cloud config example.

646. By Joshua Harlow

Instead of using a new kernel cli, allow
the cloud-config yaml (and corresponding kernel text)
to alter the logging level via a simpler manner
then replacing the whole logging blob via a new
log_level key that can provide the desired logging
level to use to override the systems setup level.

645. By Joshua Harlow

Add the ability to use a log mode/level from
the command line from the kernel to influence
the applicable logging level (for basic logging
and after logging has been configured).

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'bin/cloud-init'
2--- bin/cloud-init 2012-08-10 03:48:01 +0000
3+++ bin/cloud-init 2012-09-04 20:51:20 +0000
4@@ -490,7 +490,7 @@
5 args = parser.parse_args()
6
7 # Setup basic logging to start (until reinitialized)
8- # iff in debug mode...
9+ # iff in debug mode (or cmdline provides a level)...
10 if args.debug:
11 logging.setupBasicLogging()
12
13
14=== modified file 'cloudinit/log.py'
15--- cloudinit/log.py 2012-08-22 18:12:32 +0000
16+++ cloudinit/log.py 2012-09-04 20:51:20 +0000
17@@ -40,17 +40,34 @@
18 DEBUG = logging.DEBUG
19 NOTSET = logging.NOTSET
20
21+# String -> log level mapping
22+LEVEL_NAMES = {
23+ 'CRITICAL': CRITICAL,
24+ 'C': CRITICAL,
25+ 'FATAL': FATAL,
26+ 'F': FATAL,
27+ 'ERROR': ERROR,
28+ 'E': ERROR,
29+ 'WARNING': WARNING,
30+ 'W': WARNING,
31+ 'WARN': WARNING,
32+ 'INFO': INFO,
33+ 'I': INFO,
34+ 'DEBUG': DEBUG,
35+ 'D': DEBUG,
36+}
37+
38 # Default basic format
39 DEF_CON_FORMAT = '%(asctime)s - %(filename)s[%(levelname)s]: %(message)s'
40
41
42-def setupBasicLogging():
43+def setupBasicLogging(log_level=DEBUG):
44 root = logging.getLogger()
45 console = logging.StreamHandler(sys.stderr)
46 console.setFormatter(logging.Formatter(DEF_CON_FORMAT))
47- console.setLevel(DEBUG)
48+ console.setLevel(log_level)
49 root.addHandler(console)
50- root.setLevel(DEBUG)
51+ root.setLevel(log_level)
52
53
54 def setupLogging(cfg=None):
55@@ -76,6 +93,7 @@
56
57 # See if any of them actually load...
58 am_tried = 0
59+ am_worked = 0
60 for log_cfg in log_cfgs:
61 try:
62 am_tried += 1
63@@ -90,7 +108,8 @@
64 # Attempt to load its config
65 logging.config.fileConfig(log_cfg)
66 # The first one to work wins!
67- return
68+ am_worked += 1
69+ break
70 except Exception:
71 # We do not write any logs of this here, because the default
72 # configuration includes an attempt at using /dev/log, followed
73@@ -99,13 +118,40 @@
74 pass
75
76 # If it didn't work, at least setup a basic logger (if desired)
77- basic_enabled = cfg.get('log_basic', True)
78-
79- sys.stderr.write(("WARN: no logging configured!"
80- " (tried %s configs)\n") % (am_tried))
81+ basic_enabled = False
82+ if not am_worked:
83+ basic_enabled = cfg.get('log_basic', True)
84+ sys.stderr.write(("WARN: no logging configured!"
85+ " (tried %s configs)\n") % (am_tried))
86 if basic_enabled:
87 sys.stderr.write("Setting up basic logging...\n")
88 setupBasicLogging()
89+ if 'log_level' in cfg:
90+ override_level = translateLevels([cfg['log_level']])
91+ if override_level:
92+ # Adjust the root and the cloud-init logger
93+ # to be the level desired, possibly overriding
94+ # any configured levels...
95+ for logger in [logging.getLogger(), getLogger()]:
96+ logger.setLevel(override_level)
97+
98+
99+def translateLevels(levels, quiet=True):
100+ # First filter to known levels
101+ known_levels = []
102+ for level_name in levels:
103+ level_name = level_name.strip().upper()
104+ if level_name not in LEVEL_NAMES:
105+ if quiet:
106+ continue
107+ else:
108+ raise ValueError("Untranslatable log level %s" % (level_name))
109+ known_levels.append(LEVEL_NAMES[level_name])
110+ if not known_levels:
111+ return None
112+ # Pick the lowest level
113+ known_levels.sort()
114+ return known_levels[0]
115
116
117 def getLogger(name='cloudinit'):
118
119=== modified file 'cloudinit/util.py'
120--- cloudinit/util.py 2012-08-28 03:51:00 +0000
121+++ cloudinit/util.py 2012-09-04 20:51:20 +0000
122@@ -700,34 +700,37 @@
123 return mergedict(confd_cfg, cfg)
124
125
126-def read_cc_from_cmdline(cmdline=None):
127- # this should support reading cloud-config information from
128- # the kernel command line. It is intended to support content of the
129- # format:
130- # cc: <yaml content here> [end_cc]
131- # this would include:
132- # cc: ssh_import_id: [smoser, kirkland]\\n
133- # cc: ssh_import_id: [smoser, bob]\\nruncmd: [ [ ls, -l ], echo hi ] end_cc
134- # cc:ssh_import_id: [smoser] end_cc cc:runcmd: [ [ ls, -l ] ] end_cc
135+def read_tokens_from_cmdline(tok_begin, tok_end, cmdline=None):
136 if cmdline is None:
137 cmdline = get_cmdline()
138-
139- tag_begin = "cc:"
140- tag_end = "end_cc"
141- begin_l = len(tag_begin)
142- end_l = len(tag_end)
143+ tokens = []
144+ begin_l = len(tok_begin)
145+ end_l = len(tok_end)
146 clen = len(cmdline)
147- tokens = []
148- begin = cmdline.find(tag_begin)
149+ begin = cmdline.find(tok_begin)
150 while begin >= 0:
151- end = cmdline.find(tag_end, begin + begin_l)
152+ end = cmdline.find(tok_end, begin + begin_l)
153 if end < 0:
154 end = clen
155 tokens.append(cmdline[begin + begin_l:end].lstrip().replace("\\n",
156 "\n"))
157-
158- begin = cmdline.find(tag_begin, end + end_l)
159-
160+ begin = cmdline.find(tok_begin, end + end_l)
161+ return tokens
162+
163+
164+def read_cc_from_cmdline(cmdline=None):
165+ # This should support reading cloud-config information from
166+ # the kernel command line.
167+ # It is intended to support content of the format:
168+ #
169+ # cc: <yaml content here> [end_cc]
170+ #
171+ # For example:
172+ #
173+ # cc: ssh_import_id: [smoser, kirkland]\\n
174+ # cc: ssh_import_id: [smoser, bob]\\nruncmd: [ [ ls, -l ], echo hi ] end_cc
175+ # cc: ssh_import_id: [smoser] end_cc cc:runcmd: [ [ ls, -l ] ] end_cc
176+ tokens = read_tokens_from_cmdline("cc:", "end_cc", cmdline)
177 return '\n'.join(tokens)
178
179
180
181=== added file 'doc/examples/cloud-config-log-level.txt'
182--- doc/examples/cloud-config-log-level.txt 1970-01-01 00:00:00 +0000
183+++ doc/examples/cloud-config-log-level.txt 2012-09-04 20:51:20 +0000
184@@ -0,0 +1,28 @@
185+#cloud-config
186+# vim: syntax=yaml
187+#
188+# This is the configuration syntax that can be used to alter the logging
189+# level of the cloud-init python logging subsystem. It is typically easier
190+# to use this new setting than overriding the full logging config that is
191+# setup by cloud-init. This syntax can also be used in the cc: <yaml> end_cc
192+# style of specifying this configuration via the kernel command line.
193+#
194+log_level: DEBUG
195+# This will override the system logging and make it use DEBUG level instead
196+# of the typical WARN level.
197+#
198+# Other valid options here are the following:
199+# C => 'CRITICAL'
200+# E => 'ERROR'
201+# D => 'DEBUG'
202+# F => 'FATAL'
203+# I => 'INFO'
204+# WARN => 'WARNING'
205+# W => 'WARNING'
206+# ERROR
207+# DEBUG
208+# FATAL
209+# INFO
210+# WARNING
211+# CRITICAL
212+