Merge ~robert-ancell/software-properties:esm-xenial into software-properties:ubuntu/xenial

Proposed by Robert Ancell
Status: Needs review
Proposed branch: ~robert-ancell/software-properties:esm-xenial
Merge into: software-properties:ubuntu/xenial
Diff against target: 336 lines (+211/-6)
5 files modified
data/gtkbuilder/main.ui (+106/-6)
debian/changelog (+6/-0)
debian/control (+1/-0)
softwareproperties/gtk/SoftwarePropertiesGtk.py (+23/-0)
softwareproperties/gtk/utils.py (+75/-0)
Reviewer Review Type Date Requested Status
Ubuntu Core Development Team Pending
Review via email: mp+400302@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Robert Ancell (robert-ancell) wrote :

Unmerged commits

7b8920c... by Robert Ancell

Show extended security maintenance status

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/data/gtkbuilder/main.ui b/data/gtkbuilder/main.ui
2index ed4abc1..d1704e9 100644
3--- a/data/gtkbuilder/main.ui
4+++ b/data/gtkbuilder/main.ui
5@@ -547,7 +547,18 @@
6 <packing>
7 <property name="expand">False</property>
8 <property name="fill">True</property>
9- <property name="position">0</property>
10+ </packing>
11+ </child>
12+ <child>
13+ <object class="GtkLabel">
14+ <property name="visible">True</property>
15+ <property name="can_focus">False</property>
16+ <property name="label" translatable="yes">Snap package updates are checked routinely and installed automatically.</property>
17+ <property name="xalign">0</property>
18+ </object>
19+ <packing>
20+ <property name="expand">False</property>
21+ <property name="fill">False</property>
22 </packing>
23 </child>
24 <child>
25@@ -562,6 +573,98 @@
26 <property name="can_focus">False</property>
27 <property name="spacing">6</property>
28 <child>
29+ <object class="GtkHBox">
30+ <property name="visible">True</property>
31+ <property name="can_focus">False</property>
32+ <property name="spacing">6</property>
33+ <child>
34+ <object class="GtkLabel" id="label_esm_heading">
35+ <property name="visible">True</property>
36+ <property name="can_focus">False</property>
37+ <property name="xalign">1</property>
38+ <property name="label" translatable="yes">For other packages, this system has:</property>
39+ </object>
40+ <packing>
41+ <property name="expand">False</property>
42+ <property name="fill">False</property>
43+ <property name="position">0</property>
44+ </packing>
45+ </child>
46+ <child>
47+ <object class="GtkHBox">
48+ <property name="visible">True</property>
49+ <property name="can_focus">False</property>
50+ <property name="spacing">6</property>
51+ <child>
52+ <object class="GtkLabel" id="label_esm_status">
53+ <property name="visible">True</property>
54+ <property name="can_focus">False</property>
55+ <property name="xalign">0</property>
56+ </object>
57+ <packing>
58+ <property name="expand">False</property>
59+ <property name="fill">True</property>
60+ </packing>
61+ </child>
62+ <child>
63+ <object class="GtkLabel" id="label_esm_subscribe">
64+ <property name="visible">True</property>
65+ <property name="can_focus">False</property>
66+ <property name="xalign">1</property>
67+ </object>
68+ <packing>
69+ <property name="expand">True</property>
70+ <property name="fill">True</property>
71+ </packing>
72+ </child>
73+ </object>
74+ <packing>
75+ <property name="expand">True</property>
76+ <property name="fill">True</property>
77+ <property name="position">1</property>
78+ </packing>
79+ </child>
80+ </object>
81+ <packing>
82+ <property name="expand">False</property>
83+ <property name="fill">False</property>
84+ </packing>
85+ </child>
86+ <child>
87+ <object class="GtkHBox">
88+ <property name="visible">True</property>
89+ <property name="can_focus">False</property>
90+ <property name="spacing">6</property>
91+ <child>
92+ <object class="GtkLabel" id="label_eol_heading">
93+ <property name="visible">True</property>
94+ <property name="can_focus">False</property>
95+ </object>
96+ <packing>
97+ <property name="expand">False</property>
98+ <property name="fill">False</property>
99+ <property name="position">0</property>
100+ </packing>
101+ </child>
102+ <child>
103+ <object class="GtkLabel" id="label_eol">
104+ <property name="visible">True</property>
105+ <property name="can_focus">False</property>
106+ <property name="xalign">0</property>
107+ </object>
108+ <packing>
109+ <property name="expand">True</property>
110+ <property name="fill">True</property>
111+ <property name="position">1</property>
112+ </packing>
113+ </child>
114+ </object>
115+ <packing>
116+ <property name="expand">False</property>
117+ <property name="fill">False</property>
118+ </packing>
119+ </child>
120+ <child>
121 <object class="GtkHBox" id="hbox_check_for_updates">
122 <property name="visible">True</property>
123 <property name="can_focus">False</property>
124@@ -601,7 +704,6 @@
125 <packing>
126 <property name="expand">False</property>
127 <property name="fill">False</property>
128- <property name="position">0</property>
129 </packing>
130 </child>
131 <child>
132@@ -644,7 +746,6 @@
133 <packing>
134 <property name="expand">False</property>
135 <property name="fill">False</property>
136- <property name="position">1</property>
137 </packing>
138 </child>
139 <child>
140@@ -687,7 +788,6 @@
141 <packing>
142 <property name="expand">False</property>
143 <property name="fill">False</property>
144- <property name="position">2</property>
145 </packing>
146 </child>
147 </object>
148@@ -696,7 +796,6 @@
149 <packing>
150 <property name="expand">True</property>
151 <property name="fill">True</property>
152- <property name="position">1</property>
153 </packing>
154 </child>
155 <child>
156@@ -746,7 +845,6 @@
157 <packing>
158 <property name="expand">False</property>
159 <property name="fill">False</property>
160- <property name="position">2</property>
161 </packing>
162 </child>
163 </object>
164@@ -1180,6 +1278,8 @@
165 </object>
166 <object class="GtkSizeGroup" id="sizegroup1">
167 <widgets>
168+ <widget name="label_esm_heading"/>
169+ <widget name="label_eol_heading"/>
170 <widget name="label3"/>
171 <widget name="label4"/>
172 <widget name="label5"/>
173diff --git a/debian/changelog b/debian/changelog
174index ce037cf..1d17ec0 100644
175--- a/debian/changelog
176+++ b/debian/changelog
177@@ -1,3 +1,9 @@
178+software-properties (0.96.20.11) UNRELEASED; urgency=medium
179+
180+ * Show ESM support status (LP: #1920836)
181+
182+ -- Robert Ancell <robert.ancell@canonical.com> Tue, 23 Mar 2021 11:51:12 +1300
183+
184 software-properties (0.96.20.10) xenial-security; urgency=medium
185
186 * SECURITY UPDATE: malicious repo could send ANSI sequences to terminal
187diff --git a/debian/control b/debian/control
188index 20d0e4b..a1dd141 100644
189--- a/debian/control
190+++ b/debian/control
191@@ -64,6 +64,7 @@ Depends: ${python3:Depends}, ${misc:Depends}, python3,
192 ubuntu-drivers-common (>= 1:0.2.75),
193 python3-gi,
194 libgtk2-perl,
195+ distro-info-data,
196 Description: manage the repositories that you install software from (gtk)
197 This software provides an abstraction of the used apt repositories.
198 It allows you to easily manage your distribution and independent software
199diff --git a/softwareproperties/gtk/SoftwarePropertiesGtk.py b/softwareproperties/gtk/SoftwarePropertiesGtk.py
200index 033c6b8..d9e462e 100644
201--- a/softwareproperties/gtk/SoftwarePropertiesGtk.py
202+++ b/softwareproperties/gtk/SoftwarePropertiesGtk.py
203@@ -26,6 +26,7 @@ from __future__ import absolute_import, print_function
204
205 import apt
206 import apt_pkg
207+import datetime
208 import dbus
209 from gettext import gettext as _
210 import gettext
211@@ -51,6 +52,12 @@ import softwareproperties.distro
212 from softwareproperties.SoftwareProperties import SoftwareProperties
213 import softwareproperties.SoftwareProperties
214
215+from softwareproperties.gtk.utils import (
216+ get_esm_apps_status,
217+ current_distro_eol,
218+ current_distro_eol_esm
219+)
220+
221 from UbuntuDrivers import detect
222
223 if GLib.pyglib_version < (3, 9, 1):
224@@ -349,6 +356,22 @@ class SoftwarePropertiesGtk(SoftwareProperties, SimpleGtkbuilderApp):
225 self.vbox_updates.add(checkbox)
226 checkbox.show()
227
228+ (esm_available, esm_enabled) = get_esm_apps_status()
229+ if esm_enabled:
230+ eol_text = _("Extended Security Maintenance")
231+ eol_date = current_distro_eol_esm()
232+ else:
233+ eol_text = _("Basic Security Maintenance")
234+ eol_date = current_distro_eol()
235+ self.label_esm_status.set_markup(eol_text)
236+ self.label_esm_subscribe.set_markup("<a href=\"https://ubuntu.com/security/esm\">%s</a>" % _("Extend…"))
237+ self.label_esm_subscribe.set_visible(esm_available and not esm_enabled)
238+ if datetime.datetime.now().date() > eol_date:
239+ eol_expiry_text = _("Ended %s") % eol_date.strftime("%x")
240+ else:
241+ eol_expiry_text = _("Active until %s") % eol_date.strftime("%x")
242+ self.label_eol.set_label(eol_expiry_text);
243+
244 # setup the server chooser
245 cell = Gtk.CellRendererText()
246 self.combobox_server.pack_start(cell, True)
247diff --git a/softwareproperties/gtk/utils.py b/softwareproperties/gtk/utils.py
248index 9554fea..8fe682c 100644
249--- a/softwareproperties/gtk/utils.py
250+++ b/softwareproperties/gtk/utils.py
251@@ -19,6 +19,11 @@
252 from __future__ import print_function
253
254 from gi.repository import Gtk
255+import aptsources.distro
256+import csv
257+import datetime
258+import json
259+import subprocess
260 import logging
261 LOG=logging.getLogger(__name__)
262
263@@ -34,3 +39,73 @@ def setup_ui(self, path, domain):
264 setattr(self, name, o)
265 else:
266 logging.debug("can not get name for object '%s'" % o)
267+
268+class DistroInfo:
269+ def __init__ (self, version, codename, series, created, release, eol, eol_server, eol_esm):
270+ self.version = version
271+ self.codename = codename
272+ self.series = series
273+ self.created = created
274+ self.release = release
275+ self.eol = eol
276+ self.eol_server = eol_server
277+ self.eol_esm = eol_esm
278+
279+def _parse_date(date_string):
280+ if date_string is None:
281+ return None
282+ try:
283+ return datetime.datetime.strptime(date_string, '%Y-%m-%d').date()
284+ except ValueError:
285+ return None
286+
287+def _current_distro():
288+ distro = aptsources.distro.get_distro()
289+ try:
290+ reader = csv.reader(open('/usr/share/distro-info/ubuntu.csv'))
291+ except Exception as e:
292+ print("Failed to read distro info:\n%s" % e)
293+ reader = []
294+
295+ for line in reader:
296+ (version, codename, series, created, release, eol, eol_server, eol_esm) = line[:8] + [None] * max(0, 8 - len(line))
297+ if series == distro.codename:
298+ return DistroInfo(version, codename, series, _parse_date(created), _parse_date(release), _parse_date(eol), _parse_date(eol_server), _parse_date(eol_esm))
299+
300+ return DistroInfo('', '', '', datetime.date.today(), datetime.date.today(), datetime.date.today(), datetime.date.today(), datetime.date.today())
301+
302+def current_distro_eol():
303+ return _current_distro().eol
304+
305+def current_distro_eol_esm():
306+ return _current_distro().eol_esm
307+
308+def get_esm_apps_status():
309+ try:
310+ result = subprocess.run(['ua', 'status', '--format=json'], stdout=subprocess.PIPE)
311+ except Exception as e:
312+ print("Failed to call ubuntu advantage client:\n%s" % e)
313+ return (False, False)
314+
315+ if result.returncode != 0:
316+ print("Ubuntu advantage client returned code %d" % result.returncode)
317+ return (False, False)
318+
319+ try:
320+ status = json.loads(result.stdout.decode("utf-8"))
321+ except Exception as e:
322+ print("Failed to parse ubuntu advantage client JSON:\n%s" % e)
323+ return (False, False)
324+
325+ services = status.get("services")
326+ if services == None:
327+ services = []
328+
329+ for service in services:
330+ if service.get("name") == "esm-apps":
331+ available = service.get("available") == "yes"
332+ entitled = service.get("entitled") == "yes"
333+ service_status = service.get("status")
334+ return (available or entitled, service_status == "enabled")
335+
336+ return (False, False)

Subscribers

People subscribed via source and target branches