Thank you for this submission. I was awaiting feedback on this bug to determine if you'd like to solve the outstanding issue that Extend... links aren't presented on the software-properties-gtk UI for unattached machines (and/or) dropping the error messages from the console. But, as you mentioned error console messaging isn't presented to the UI so this is a non-issue that we can remedy in future uploads.
That said, I also discovered that changes in ubuntu-advantage-tools 27.2 which have already SRU'd into xenial, bionic, focal and render this current logic broken.
I've filed LP: #1939732 to capture upcoming features needed in the UI to better inform about Extending your support if desired on Bionic/Focal etc.
import logging
@@ -79,24 +80,20 @@
# which has already run `ua status`. Calling ua status directly on
# network disconnected machines will raise a TimeoutException trying to
# access contracts.canonical.com/v1/resources.
- try:
- # Success writes UA_STATUS_JSON
- result = subprocess.run(['ua', 'status', '--format=json'], stdout=subprocess.PIPE)
- except Exception as e:
- print("Failed to call ubuntu advantage client:\n%s" % e)
- return {}
- if result.returncode != 0:
- print("Ubuntu advantage client returned code %d" % result.returncode)
- return {}
-
- try:
- status_file = open(UA_STATUS_JSON, "r")
- except Exception as e:
- print("No ua status file written:\n%s" % e)
- return {}
-
- with status_file as stream:
- status_json = stream.read()
+ if os.path.exists(UA_STATUS_JSON):
+ with open(UA_STATUS_JSON) as stream:
+ status_json = stream.read()
+ else:
+ try:
+ # Success writes UA_STATUS_JSON
+ result = subprocess.run(['ua', 'status', '--format=json'], stdout=subprocess.PIPE)
+ except Exception as e:
+ print("Failed to call ubuntu advantage client:\n%s" % e)
+ return {}
+ if result.returncode != 0:
+ print("Ubuntu advantage client returned code %d" % result.returncode)
+ return {}
+ status_json = result.stdout
try:
status = json.loads(status_json)
except json.JSONDecodeError as e:
The UX "updates" tab no longer can correctly determine that the machine is attached because a new field "available" has been published in status.json.
Current utils.py:get_ua_service_status relies on a now incorrect check:
if service.get("available"): # then we are not attached
if service["available"] == "yes": available = True service_status = "disabled" # Disabled since unattached
Since ua status output on attach machines now provides "available": "yes" in version 27.2 it broke the assumption that "available" keys represented a detached system.
This 2nd issue could be fixed by this diff
--- /usr/lib/python3/dist-packages/softwareproperties/gtk/utils.py.old 2021-08-12 13:56:59.695413561 -0600
+++ /usr/lib/python3/dist-packages/softwareproperties/gtk/utils.py 2021-08-12 13:57:13.951629355 -0600
@@ -123,7 +123,7 @@
service_status = "n/a"
for service in status.get("services", []):
if service.get("name") == service_name:
- if service.get("available"): # then we are not attached
+ if status.get("attached", False) == False: # we are not attached
if service["available"] == "yes": available = True service_status = "disabled" # Disabled since unattached
the third issue is that the contract expiry date format of v 27.2 doesn't conform to software-properties-gtk expectations: with the above patches, we still see issues with ability to decode the expiry string in the console
unconverted data remains: +00:00 (<--- added print of the exception msg)
Unable to determine UA contract expiry
this patch would be needed to suport expiry datestring formatting for ua-tools 27.2 in bionic focal etc
--- /usr/lib/python3/dist-packages/softwareproperties/gtk/SoftwarePropertiesGtk.py.old 2021-08-12 14:43:33.570530853 -0600
+++ /usr/lib/python3/dist-packages/softwareproperties/gtk/SoftwarePropertiesGtk.py 2021-08-12 14:43:50.594751621 -0600
@@ -394,8 +394,11 @@
# gives software properties dialogs a chance to interact about
# renewals if needed. try:
+ # Ignore timezone to simplify formatting python < 3.7
+ # 3.7+ has datetime.fromisoformat()
+ dt, _sep, _tz = status.get("expires").partition("+") eol_date = datetime.datetime.strptime(
- status.get("expires"), "%Y-%m-%dT%H:%M:%S"
+ dt, "%Y-%m-%dT%H:%M:%S" ).date() except ValueError: print("Unable to determine UA contract expiry")
Thank you for this submission. I was awaiting feedback on this bug to determine if you'd like to solve the outstanding issue that Extend... links aren't presented on the software- properties- gtk UI for unattached machines (and/or) dropping the error messages from the console. But, as you mentioned error console messaging isn't presented to the UI so this is a non-issue that we can remedy in future uploads.
That said, I also discovered that changes in ubuntu- advantage- tools 27.2 which have already SRU'd into xenial, bionic, focal and render this current logic broken.
I've filed LP: #1939732 to capture upcoming features needed in the UI to better inform about Extending your support if desired on Bionic/Focal etc.
LP 1939732 could be fixed by this diff:
--- /usr/lib/ python3/ dist-packages/ softwarepropert ies/gtk/ utils.py. old 2021-08-12 13:56:59.695413561 -0600 python3/ dist-packages/ softwarepropert ies/gtk/ utils.py 2021-08-12 14:12:28.597659801 -0600 version( "Gtk", "3.0")
+++ /usr/lib/
@@ -26,6 +26,7 @@
gi.require_
from gi.repository import Gio, Gtk
import json
+import os
import subprocess
import logging canonical. com/v1/ resources. run(['ua' , 'status', '--format=json'], stdout= subprocess. PIPE) STATUS_ JSON, "r") exists( UA_STATUS_ JSON): STATUS_ JSON) as stream: run(['ua' , 'status', '--format=json'], stdout= subprocess. PIPE) status_ json) Error as e:
@@ -79,24 +80,20 @@
# which has already run `ua status`. Calling ua status directly on
# network disconnected machines will raise a TimeoutException trying to
# access contracts.
- try:
- # Success writes UA_STATUS_JSON
- result = subprocess.
- except Exception as e:
- print("Failed to call ubuntu advantage client:\n%s" % e)
- return {}
- if result.returncode != 0:
- print("Ubuntu advantage client returned code %d" % result.returncode)
- return {}
-
- try:
- status_file = open(UA_
- except Exception as e:
- print("No ua status file written:\n%s" % e)
- return {}
-
- with status_file as stream:
- status_json = stream.read()
+ if os.path.
+ with open(UA_
+ status_json = stream.read()
+ else:
+ try:
+ # Success writes UA_STATUS_JSON
+ result = subprocess.
+ except Exception as e:
+ print("Failed to call ubuntu advantage client:\n%s" % e)
+ return {}
+ if result.returncode != 0:
+ print("Ubuntu advantage client returned code %d" % result.returncode)
+ return {}
+ status_json = result.stdout
try:
status = json.loads(
except json.JSONDecode
The UX "updates" tab no longer can correctly determine that the machine is attached because a new field "available" has been published in status.json.
Current utils.py: get_ua_ service_ status relies on a now incorrect check:
if service. get("available" ): # then we are not attached "available" ] == "yes":
available = True
service_ status = "disabled" # Disabled since unattached
if service[
Since ua status output on attach machines now provides "available": "yes" in version 27.2 it broke the assumption that "available" keys represented a detached system.
This 2nd issue could be fixed by this diff
--- /usr/lib/ python3/ dist-packages/ softwarepropert ies/gtk/ utils.py. old 2021-08-12 13:56:59.695413561 -0600 python3/ dist-packages/ softwarepropert ies/gtk/ utils.py 2021-08-12 13:57:13.951629355 -0600 get("services" , []): get("available" ): # then we are not attached get("attached" , False) == False: # we are not attached "available" ] == "yes":
available = True
service_ status = "disabled" # Disabled since unattached
+++ /usr/lib/
@@ -123,7 +123,7 @@
service_status = "n/a"
for service in status.
if service.get("name") == service_name:
- if service.
+ if status.
if service[
the third issue is that the contract expiry date format of v 27.2 doesn't conform to software- properties- gtk expectations: with the above patches, we still see issues with ability to decode the expiry string in the console
unconverted data remains: +00:00 (<--- added print of the exception msg)
Unable to determine UA contract expiry
this patch would be needed to suport expiry datestring formatting for ua-tools 27.2 in bionic focal etc python3/ dist-packages/ softwarepropert ies/gtk/ SoftwarePropert iesGtk. py.old 2021-08-12 14:43:33.570530853 -0600 python3/ dist-packages/ softwarepropert ies/gtk/ SoftwarePropert iesGtk. py 2021-08-12 14:43:50.594751621 -0600
try: fromisoformat( ) get("expires" ).partition( "+")
eol_ date = datetime. datetime. strptime( get("expires" ), "%Y-%m-%dT%H:%M:%S"
).date( )
except ValueError:
print( "Unable to determine UA contract expiry")
--- /usr/lib/
+++ /usr/lib/
@@ -394,8 +394,11 @@
# gives software properties dialogs a chance to interact about
# renewals if needed.
+ # Ignore timezone to simplify formatting python < 3.7
+ # 3.7+ has datetime.
+ dt, _sep, _tz = status.
- status.
+ dt, "%Y-%m-%dT%H:%M:%S"
The combined patches required against this upload is as follows: /paste. ubuntu. com/p/cgC56mTZ6 g/
https:/