Merge ~barryprice/charm-canonical-livepatch/+git/canonical-livepatch-charm:master into ~livepatch-charmers/charm-canonical-livepatch:master

Proposed by Barry Price
Status: Merged
Merge reported by: Barry Price
Merged at revision: 1bcbce669e1c6f9a1cd0f7c046937060ef77c73e
Proposed branch: ~barryprice/charm-canonical-livepatch/+git/canonical-livepatch-charm:master
Merge into: ~livepatch-charmers/charm-canonical-livepatch:master
Diff against target: 171 lines (+54/-26)
1 file modified
reactive/canonical_livepatch.py (+54/-26)
Reviewer Review Type Date Requested Status
Paul Gear (community) Approve
Stuart Bishop (community) Approve
Review via email: mp+331851@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Barry Price (barryprice) wrote :
Revision history for this message
Barry Price (barryprice) wrote :
Revision history for this message
Stuart Bishop (stub) wrote :

I guess at least with livepatch being a snap we don't have to worry about supporting the old format. Might be worth letting them know that this output is being scraped and if they change it they break things.

The patch looks good. I see a lot of hookenv.log() calls logging errors at the default INFO level, which you might want to fix. I'm unsure how much it matters with current Juju.

review: Approve
Revision history for this message
Paul Gear (paulgear) wrote :

See Stuart's comments about errors. I think all but one need changing.

review: Needs Fixing
Revision history for this message
Stuart Bishop (stub) wrote :

logging errors doesn't cause the charm to fail.

948802a... by Barry Price

Address LP#1721915, use appropriate log levels

2674170... by Barry Price

Address LP#1721915, use appropriate log levels

Revision history for this message
Paul Gear (paulgear) wrote :

Some stylistic comments inline, but LGTM.

review: Approve
1bcbce6... by Barry Price

Use preferred return syntax

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/reactive/canonical_livepatch.py b/reactive/canonical_livepatch.py
2index bb9d547..8b39eab 100644
3--- a/reactive/canonical_livepatch.py
4+++ b/reactive/canonical_livepatch.py
5@@ -7,7 +7,6 @@ from subprocess import check_call, check_output, CalledProcessError
6 from time import sleep
7 from os import path, uname
8 from yaml import load, dump
9-from platform import release
10 from distutils.version import LooseVersion
11
12
13@@ -42,7 +41,10 @@ def wait_for_path(file_path, timeout=30):
14 sleep(interval)
15 seconds_waited += interval
16 if seconds_waited >= timeout:
17- hookenv.log('Giving up waiting for {}'.format(file_path))
18+ hookenv.log(
19+ 'Giving up waiting for {}'.format(file_path),
20+ hookenv.ERROR
21+ )
22 return
23 return
24
25@@ -57,37 +59,44 @@ def unit_update(status=None, message=None):
26 if status and message:
27 hookenv.status_set(status, message)
28 else:
29- hookenv.status_set('active', 'Effective kernel {}'.format(
30- get_equiv_kernel_version())
31+ patch_details = get_patch_details()
32+ hookenv.status_set(
33+ 'active',
34+ 'Running kernel {}, patchState: {}'.format(*patch_details)
35 )
36
37
38-def get_equiv_kernel_version():
39- # default to actual running kernel
40- version_string = release()
41- livepatch_status = ''
42+def get_patch_details():
43+ kernel = patch_state = 'unknown'
44
45 cmd = ['/snap/bin/canonical-livepatch', 'status']
46 try:
47- livepatch_status = check_output(cmd, universal_newlines=True)
48+ livepatch_state = check_output(cmd, universal_newlines=True)
49 except CalledProcessError as e:
50- hookenv.log('Unable to get status: {}'.format(str(e)))
51- return version_string
52+ hookenv.log('Unable to get status: {}'.format(str(e)), hookenv.ERROR)
53+ return kernel, patch_state
54
55 # status will usually pass YAML (but not always!)
56 try:
57- status_yaml = load(livepatch_status)
58+ status_yaml = load(livepatch_state)
59 except Exception:
60- hookenv.log('Unable to parse status yaml')
61- return version_string
62+ hookenv.log('Unable to parse status yaml', hookenv.ERROR)
63+ return kernel, patch_state
64
65 # even if we got YAML, be paranoid
66 try:
67- version_string = status_yaml['kernel']
68+ for k in status_yaml['status']:
69+ if k['running'] is True:
70+ kernel = k['kernel']
71+ patch_state = k['livepatch']['patchState']
72 except Exception:
73- hookenv.log('Unable to find kernel line in status yaml')
74+ hookenv.log(
75+ 'Unable to find patching details in status yaml',
76+ hookenv.ERROR
77+ )
78+ return kernel, patch_state
79
80- return version_string
81+ return kernel, patch_state
82
83
84 def get_yaml_if_exists(path_to_yaml):
85@@ -97,7 +106,8 @@ def get_yaml_if_exists(path_to_yaml):
86 conf_yaml = load(stream)
87 except Exception:
88 hookenv.log(
89- 'Unable to load YAML from {}'.format(path_to_yaml)
90+ 'Unable to load YAML from {}'.format(path_to_yaml),
91+ hookenv.ERROR
92 )
93 else:
94 conf_yaml = {}
95@@ -148,7 +158,7 @@ def restart_livepatch():
96 try:
97 check_call(cmd, universal_newlines=True)
98 except CalledProcessError:
99- hookenv.log('Failed to stop the service')
100+ hookenv.log('Failed to stop the service', hookenv.ERROR)
101
102 # and now try to start it again, it may fail the first time!
103 cmd = [
104@@ -161,7 +171,8 @@ def restart_livepatch():
105 check_call(cmd, universal_newlines=True)
106 except CalledProcessError:
107 hookenv.log(
108- 'Failed to start the service - waiting 5s and then trying again'
109+ 'Failed to start the service - waiting 5s and then trying again',
110+ hookenv.ERROR
111 )
112 sleep(5)
113 check_call(cmd, universal_newlines=True)
114@@ -182,7 +193,10 @@ def activate_livepatch():
115 try:
116 check_output(cmd, universal_newlines=True)
117 except CalledProcessError as e:
118- hookenv.log('Unable to deactivate: {}'.format(str(e)))
119+ hookenv.log(
120+ 'Unable to deactivate: {}'.format(str(e)),
121+ hookenv.ERROR
122+ )
123
124 cmd = [
125 '/snap/bin/canonical-livepatch',
126@@ -193,7 +207,10 @@ def activate_livepatch():
127 try:
128 check_output(cmd, universal_newlines=True)
129 except CalledProcessError as e:
130- hookenv.log('Unable to activate: {}'.format(str(e)))
131+ hookenv.log(
132+ 'Unable to activate: {}'.format(str(e)),
133+ hookenv.ERROR
134+ )
135 remove_state('canonical-livepatch.active')
136 unit_update('blocked', 'Activation failed')
137 else:
138@@ -201,7 +218,8 @@ def activate_livepatch():
139 unit_update()
140 else:
141 hookenv.log(
142- 'Unable to activate canonical-livepatch as no key has been set'
143+ 'Unable to activate canonical-livepatch as no key has been set',
144+ hookenv.ERROR
145 )
146 remove_state('canonical-livepatch.active')
147 unit_update(
148@@ -214,10 +232,20 @@ def activate_livepatch():
149 def livepatch_supported():
150 arch = uname()[4]
151 opts = layer.options('snap')
152- supported_archs = opts['canonical-livepatch'].pop('supported-architectures', None)
153+ supported_archs = opts['canonical-livepatch'].pop(
154+ 'supported-architectures',
155+ None
156+ )
157 if supported_archs and arch not in supported_archs:
158- hookenv.log('Livepatch does not currently support this architecture: {}'.format(arch))
159- unit_update('blocked', 'Architecture {} is not supported by livepatch'.format(arch))
160+ hookenv.log(
161+ 'Livepatch does not currently support {} architecture'.format(
162+ arch
163+ )
164+ )
165+ unit_update(
166+ 'blocked',
167+ 'Architecture {} is not supported by livepatch'.format(arch)
168+ )
169 if is_container():
170 hookenv.log('OS container detected, livepatch is not needed')
171 unit_update('blocked', 'Livepatch is not needed in OS containers')

Subscribers

People subscribed via source and target branches