Merge ~pieq/bugit/+git/qabro:fix-sosreport-dpkg-logs into bugit:master

Proposed by Pierre Equoy
Status: Superseded
Proposed branch: ~pieq/bugit/+git/qabro:fix-sosreport-dpkg-logs
Merge into: bugit:master
Diff against target: 364 lines (+154/-72)
9 files modified
dev/null (+0/-11)
patches/sosreport-dpkg-l.patch (+12/-0)
patches/sosreport-env-path-snap.patch (+14/-21)
qabro/__version__.py (+1/-1)
qabro/bug_assistant.py (+5/-1)
qabro/data/tags.json (+68/-0)
qabro/ui.py (+46/-37)
setup.py (+1/-0)
snap/snapcraft.yaml (+7/-1)
Reviewer Review Type Date Requested Status
OEM Services QA Pending
Review via email: mp+385631@code.launchpad.net

This proposal supersedes a proposal from 2020-06-12.

Description of the change

See commit message for more info

To test (on Ubuntu classic):

1. Run `snapcraft` from this branch to build a `qabro_0.13dev_amd64.snap` file
2. Install the snap:
    sudo snap install qabro_0.13dev_amd64.snap --devmode
3. Run sosreport from the snap:
    sudo qabro.sosreport
It will generate a /root/snap/qabro/common/sosreport-*.tar.gz archive

4. Copy the archive and modify the permissions, then open it to check the content of `sos_commands/dpkg/`:

    sudo cp /root/snap/qabro/common/sosreport-*.tar.gz /tmp
    sudo chown $USER:$USER /tmp/sosreport-*.tar.gz
    xdg-open /tmp/sosreport-*.tar.gz

You should find the list of packages installed on your system.

To post a comment you must log in.

Unmerged commits

8ffa378... by Pierre Equoy

Add dpkg and patch sosreport to provide proper `dpkg -l` logs

Until now, on classic systems, the list of packages installed (the
output of `dpkg -l`) was empty in the archive report generated by
sosreport.

This commit addresses the issue. The list of installed packages can now
be found in `sos_commands/dpkg/`.

LP: #1880071

d971493... by Pierre Equoy

Add features and vendors tag lists

We used to have our own list of "bug type" tags. We are now using two
up-to-date lists of features and vendors tags that are shared among
teams.

These two lists are shown in two columns under the text field to enter
tags. The user can select as many impacted features/vendors as required,
and this updates the list of tags submitted to Launchpad dynamically.

LP: #1880538, #1880071

a059e29... by Pierre Equoy

Cleanup code look

36143db... by Pierre Equoy

Update for sosreport 3.9

sosreport 3.9 is now available in the bionic-updates pocket, so we need
to make the following changes to be able to build QABro from now on:

- remove the apt-no-auth-conf patch (it's been merged in sosreport 3.9)
and remove it from the snapcraft recipe
- adapt the env-path-snap patch
- modify the way we retrieve the path to the .tar.gz archive generated
by sosreport

985f5a4... by Pierre Equoy

Bump to v0.13dev

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/patches/sosreport-apt-no-auth-conf.patch b/patches/sosreport-apt-no-auth-conf.patch
0deleted file mode 1006440deleted file mode 100644
index b2c6514..0000000
--- a/patches/sosreport-apt-no-auth-conf.patch
+++ /dev/null
@@ -1,11 +0,0 @@
1--- a/sos/plugins/apt.py
2+++ /usr/share/sosreport/sos/plugins/apt.py
3@@ -23,6 +23,8 @@
4 "/etc/apt", "/var/log/apt"
5 ])
6
7+ self.add_forbidden_path("/etc/apt/auth.conf")
8+
9 self.add_cmd_output([
10 "apt-get check",
11 "apt-config dump",
diff --git a/patches/sosreport-dpkg-l.patch b/patches/sosreport-dpkg-l.patch
12new file mode 1006440new file mode 100644
index 0000000..c73c141
--- /dev/null
+++ b/patches/sosreport-dpkg-l.patch
@@ -0,0 +1,12 @@
1diff -u /tmp/sos-3.9/sos/plugins/dpkg.py usr/share/sosreport/sos/plugins/dpkg.py
2--- /tmp/sos-3.9/sos/plugins/dpkg.py 2020-06-12 15:00:20.955904359 +0800
3+++ usr/share/sosreport/sos/plugins/dpkg.py 2020-06-12 15:01:18.930341885 +0800
4@@ -19,7 +19,7 @@
5 profiles = ('sysmgmt', 'packagemanager')
6
7 def setup(self):
8- self.add_cmd_output("dpkg -l", root_symlink="installed-debs")
9+ self.add_cmd_output("dpkg -l --admindir=/var/lib/snapd/hostfs/var/lib/dpkg", root_symlink="installed-debs")
10 if self.get_option("verify"):
11 self.add_cmd_output("dpkg -V")
12 self.add_cmd_output("dpkg -C")
diff --git a/patches/sosreport-env-path-snap.patch b/patches/sosreport-env-path-snap.patch
index b4f95c1..f20b1c8 100644
--- a/patches/sosreport-env-path-snap.patch
+++ b/patches/sosreport-env-path-snap.patch
@@ -1,22 +1,15 @@
1diff -ru /tmp/sos-3.5/sos/policies/ubuntu.py usr/share/sosreport/sos/policies/ubuntu.py1diff -u /tmp/sos-3.9/sos/policies/ubuntu.py usr/share/sosreport/sos/policies/ubuntu.py
2--- /tmp/sos-3.5/sos/policies/ubuntu.py 2017-11-02 20:54:47.000000000 +08002--- /tmp/sos-3.9/sos/policies/ubuntu.py 2020-06-03 15:14:14.151559473 +0800
3+++ usr/share/sosreport/sos/policies/ubuntu.py 2018-10-24 15:28:46.439206314 +08003+++ usr/share/sosreport/sos/policies/ubuntu.py 2020-06-03 15:17:11.178575436 +0800
4@@ -3,11 +3,18 @@4@@ -11,7 +11,10 @@
5 from sos.plugins import UbuntuPlugin, DebianPlugin5 vendor = "Canonical"
6 from sos.policies.debian import DebianPolicy6 vendor_url = "https://www.ubuntu.com/"
7 7 PATH = "/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games" \
8+import os8- + ":/usr/local/sbin:/usr/local/bin:/snap/bin"
9 9+ + ":/usr/local/sbin:/usr/local/bin:/snap/bin" \
10 class UbuntuPolicy(DebianPolicy):10+ + ":$SNAP/usr/sbin:$SNAP/usr/bin:$SNAP/sbin:$SNAP/bin:$SNAP/usr/games" \
11 distro = "Ubuntu"11+ + ":$SNAP/usr/local/games:$SNAP/usr/local/sbin:$SNAP/usr/local/bin"
12 vendor = "Ubuntu"
13 vendor_url = "http://www.ubuntu.com/"
14+ PATH = ("/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games"
15+ ":/usr/local/sbin:/usr/local/bin"
16+ ":$SNAP/usr/sbin:$SNAP/usr/bin:$SNAP/sbin:$SNAP/bin:$SNAP/usr/games"
17+ ":$SNAP/usr/local/games:$SNAP/usr/local/sbin:$SNAP/usr/local/bin"
18+ )
19+ PATH = os.path.expandvars(PATH)12+ PATH = os.path.expandvars(PATH)
20 13 _upload_url = "https://files.support.canonical.com/uploads/"
21 def __init__(self, sysroot=None):14 _upload_user = "ubuntu"
22 super(UbuntuPolicy, self).__init__(sysroot=sysroot)15 _upload_password = "ubuntu"
diff --git a/qabro/__version__.py b/qabro/__version__.py
index 0fe7cd3..a5c2cc5 100644
--- a/qabro/__version__.py
+++ b/qabro/__version__.py
@@ -1,5 +1,5 @@
1__title__ = 'qabro'1__title__ = 'qabro'
2__version__ = '0.12'2__version__ = '0.13dev'
3__description__ = 'Tool to generate a Launchpad bug report and attach useful logs (using sosreport and the like).'3__description__ = 'Tool to generate a Launchpad bug report and attach useful logs (using sosreport and the like).'
4__author__ = 'Pierre Equoy'4__author__ = 'Pierre Equoy'
5__author_email__ = 'pierre.equoy@canonical.com'5__author_email__ = 'pierre.equoy@canonical.com'
diff --git a/qabro/bug_assistant.py b/qabro/bug_assistant.py
index 1ab9532..a32fd96 100644
--- a/qabro/bug_assistant.py
+++ b/qabro/bug_assistant.py
@@ -230,7 +230,11 @@ class AttachmentAssistant:
230 "sosreport", "--no-report", "--batch", "--tmp-dir",230 "sosreport", "--no-report", "--batch", "--tmp-dir",
231 home_dir, "-z", "gzip"]231 home_dir, "-z", "gzip"]
232 output = subprocess.check_output(command).decode('utf-8')232 output = subprocess.check_output(command).decode('utf-8')
233 archive_path = output.splitlines()[-6].strip()233 # sosreport outputs a summary that includes a line with a
234 # path to the archive. We retrieve this:
235 for line in output.splitlines():
236 if ".tar.gz" in line:
237 archive_path = line.strip()
234 print("Report generated: {}".format(archive_path))238 print("Report generated: {}".format(archive_path))
235 command = ["sudo", "chown", "{}:{}".format(user, user), archive_path]239 command = ["sudo", "chown", "{}:{}".format(user, user), archive_path]
236 subprocess.check_call(command)240 subprocess.check_call(command)
diff --git a/qabro/data/tags.json b/qabro/data/tags.json
237new file mode 100644241new file mode 100644
index 0000000..8a779a5
--- /dev/null
+++ b/qabro/data/tags.json
@@ -0,0 +1,68 @@
1[{
2 "category": "features",
3 "type": "public",
4 "description": "Features",
5 "tags": {
6 "Audio": ["hwe-audio"],
7 "Bluetooth": ["hwe-bluetooth"],
8 "Brightness": ["hwe-brightness"],
9 "CANBus": ["hwe-canbus"],
10 "Camera": ["oem-camera"],
11 "Checkbox": ["checkbox test-case"],
12 "External Storage": ["oem-storage"],
13 "Fingerprint Reader": ["hwe-fingerprint"],
14 "Firmware": ["hwe-firmware"],
15 "Full Disk Encryption": ["oem-fde"],
16 "GPIO": ["hwe-gpio"],
17 "Hotkeys": ["hwe-hotkeys"],
18 "I2C": ["hwe-i2c"],
19 "Install": ["hwe-installer"],
20 "LED": ["hwe-led"],
21 "Media Card": ["hwe-media"],
22 "Missing driver": ["hwe-needs-driver"],
23 "Model Assertion": ["oem-assertions"],
24 "Model Pivot / Remodelling": ["oem-assertions"],
25 "Networking (ethernet)": ["hwe-networking-ethernet", "oem-networking"],
26 "Networking (modem)": ["hwe-networking-modem", "oem-networking"],
27 "Networking (wifi)": ["hwe-networking-wifi", "oem-networking"],
28 "Other Problem": ["oem-other"],
29 "Performance": ["oem-performance"],
30 "Power Management": ["hwe-suspend-resume"],
31 "Power On/Off": ["hwe-powercycle"],
32 "Recovery": ["oem-recovery"],
33 "Secure Boot": ["oem-secureboot"],
34 "Sensor": ["hwe-sensor"],
35 "Serial Assertion": ["oem-assertions"],
36 "Serial": ["hwe-serial"],
37 "Snapd": ["oem-snapd"],
38 "Store": ["oem-store"],
39 "Stress": ["oem-stress"],
40 "TPM": ["hwe-tpm"],
41 "Touchpad": ["hwe-touchpad"],
42 "Touchscreen": ["oem-touchscreen"],
43 "Video": ["hwe-graphics"],
44 "Watchdog": ["hwe-watchdog"],
45 "Zigbee": ["hwe-zigbee"]
46 }
47 },
48 {
49 "category": "vendors",
50 "type": "public",
51 "description": "Vendors",
52 "tags": {
53 "AMD": ["ihv-amd"],
54 "Atheros/Qualcomm": ["ihv-qualcomm-atheros"],
55 "Gemalto": ["ihv-gemalto"],
56 "Intel": ["ihv-intel"],
57 "MTK": ["ihv-mtk"],
58 "Marvell": ["ihv-marvell"],
59 "Mighty Gecko": ["ihv-mightygecko"],
60 "Nvidia": ["ihv-nvidia"],
61 "Quectel": ["ihv-quectel"],
62 "Realtek": ["ihv-realtek"],
63 "Redpine": ["ihv-redpine"],
64 "Sierra": ["ihv-sierra"],
65 "Telegesis": ["ihv-telegesis"],
66 "Telit": ["ihv-telit"]
67 }
68}]
0\ No newline at end of file69\ No newline at end of file
diff --git a/qabro/ui.py b/qabro/ui.py
index ab8a343..695b3ca 100644
--- a/qabro/ui.py
+++ b/qabro/ui.py
@@ -1,8 +1,10 @@
1import json
2from pathlib import Path
1import sys3import sys
2import urwid4import urwid
35
4from qabro.bug_assistant import AttachmentAssistant, BugReport
5from qabro.__version__ import __version__ as qversion, __title__ as qtitle6from qabro.__version__ import __version__ as qversion, __title__ as qtitle
7from qabro.bug_assistant import AttachmentAssistant, BugReport
68
79
8class ReportScreen:10class ReportScreen:
@@ -11,7 +13,7 @@ class ReportScreen:
11 ('title', 'white', 'black', 'bold'),13 ('title', 'white', 'black', 'bold'),
12 ('key', 'yellow,bold', ''),14 ('key', 'yellow,bold', ''),
13 ('error', 'dark red,bold', ''),15 ('error', 'dark red,bold', ''),
14 ]16 ]
1517
16 footer_text = [18 footer_text = [
17 qtitle + ' v' + qversion + ' ',19 qtitle + ' v' + qversion + ' ',
@@ -26,31 +28,20 @@ class ReportScreen:
26 'Medium',28 'Medium',
27 'High',29 'High',
28 'Critical')30 'Critical')
29 bug_types = {"Audio": "hwe-audio",
30 "Bluetooth": "hwe-bluetooth",
31 "Camera": "oem-camera",
32 "External storage": "oem-storage",
33 "Touchpad": "hwe-touchpad",
34 "Touchscreen": "oem-touchscreen",
35 "Install": "hwe-installer",
36 "Media Card": "hwe-media",
37 "Networking (ethernet)": "hwe-networking-ethernet",
38 "Networking (wifi)": "hwe-networking-wifi",
39 "Networking (modem)": "hwe-networking-modem",
40 "Power management": "hwe-suspend-resume",
41 "Checkbox": "checkbox test-case",
42 "Video": "hwe-graphics",
43 "Hotkeys": "hwe-hotkeys",
44 "Firmware": "hwe-firmware",
45 "Missing driver": "hwe-needs-driver",
46 "Performance": "oem-performance",
47 "Other problem": "oem-other"}
4831
49 default_description = ("[Summary]\n\n"32 default_description = ("[Summary]\n\n"
50 "[Steps to reproduce]\n\n"33 "[Steps to reproduce]\n\n"
51 "[Expected result]\n\n"34 "[Expected result]\n\n"
52 "[Actual result]\n\n"35 "[Actual result]\n\n"
53 "[Failure rate]\n\n")36 "[Failure rate]\n\n")
37 with open(Path(__file__).parent / "data/tags.json") as f:
38 _data = json.load(f)
39 tags = dict()
40 for d in _data:
41 if d["category"] == "features":
42 tags["features"] = d["tags"]
43 elif d["category"] == "vendors":
44 tags["vendors"] = d["tags"]
5445
55 def __init__(self, project='', tags='', assignee=''):46 def __init__(self, project='', tags='', assignee=''):
56 # Adding standard info (CPU, BIOS, GPU, etc.) to the description47 # Adding standard info (CPU, BIOS, GPU, etc.) to the description
@@ -60,7 +51,7 @@ class ReportScreen:
6051
61 self._title = urwid.LineBox(urwid.Edit(), 'Bug Title')52 self._title = urwid.LineBox(urwid.Edit(), 'Bug Title')
62 self._description = urwid.LineBox(urwid.Edit(edit_text=self.default_description,53 self._description = urwid.LineBox(urwid.Edit(edit_text=self.default_description,
63 multiline=True),54 multiline=True),
64 "Description (including steps to reproduce)")55 "Description (including steps to reproduce)")
65 self._project = urwid.LineBox(urwid.Edit(edit_text=project), 'Project')56 self._project = urwid.LineBox(urwid.Edit(edit_text=project), 'Project')
66 self._series = urwid.LineBox(urwid.Edit(), 'Series')57 self._series = urwid.LineBox(urwid.Edit(), 'Series')
@@ -70,17 +61,28 @@ class ReportScreen:
70 self._importance = []61 self._importance = []
71 for i in self.importances:62 for i in self.importances:
72 rb = urwid.RadioButton(self._importance, i, 'first True', None)63 rb = urwid.RadioButton(self._importance, i, 'first True', None)
73 self._bug_type = []64 self._bug_features = []
74 for i in sorted(self.bug_types):65 for feature in sorted(self.tags["features"]):
75 rb = urwid.RadioButton(self._bug_type, i, state=False,66 cb = urwid.CheckBox(label=feature, state=False,
76 on_state_change=self.add_tag)67 on_state_change=self.toggle_tag,
68 user_data=self.tags["features"])
69 self._bug_features.append(cb)
70 self._bug_vendors = []
71 for vendor in sorted(self.tags["vendors"]):
72 cb = urwid.CheckBox(label=vendor, state=False,
73 on_state_change=self.toggle_tag,
74 user_data=self.tags["vendors"])
75 self._bug_vendors.append(cb)
77 self._assignee = urwid.LineBox(urwid.Edit(edit_text=assignee), 'Assigned To (Launchpad ID)')76 self._assignee = urwid.LineBox(urwid.Edit(edit_text=assignee), 'Assigned To (Launchpad ID)')
78 self._tags = urwid.LineBox(urwid.Edit(edit_text=tags), 'Tags')77 self._tags = urwid.LineBox(urwid.Edit(edit_text=tags), 'Tags')
79 status_list = urwid.LineBox(urwid.Pile(self._status), 'Status')78 status_list = urwid.LineBox(urwid.Pile(self._status), 'Status')
80 importance_list = urwid.LineBox(urwid.Pile(self._importance), 'Importance')79 importance_list = urwid.LineBox(urwid.Pile(self._importance), 'Importance')
81 bug_types_list = urwid.LineBox(urwid.Pile(self._bug_type), 'Bug Type')80 self.bug_features_list = urwid.LineBox(urwid.Pile(self._bug_features), 'Impacted Feature(s)')
81 self.bug_vendors_list = urwid.LineBox(urwid.Pile(self._bug_vendors), 'Impacted Vendor(s)')
82 self.message = urwid.Text('')82 self.message = urwid.Text('')
83 self.footer = urwid.AttrMap(urwid.Text(self.footer_text), 'foot')83 self.footer = urwid.AttrMap(urwid.Text(self.footer_text), 'foot')
84 self.bug_tags_lists = urwid.Columns([self.bug_features_list,
85 self.bug_vendors_list])
84 self.pile = urwid.Pile([self.message,86 self.pile = urwid.Pile([self.message,
85 self._title,87 self._title,
86 self._description,88 self._description,
@@ -90,20 +92,27 @@ class ReportScreen:
90 importance_list,92 importance_list,
91 self._assignee,93 self._assignee,
92 self._tags,94 self._tags,
93 bug_types_list])95 self.bug_tags_lists])
94 self.view = urwid.Frame(urwid.Filler(self.pile, 'top'), footer=self.footer)96 self.view = urwid.Frame(urwid.Filler(self.pile, 'top'), footer=self.footer)
9597
96 def add_tag(self, rb, state):98 def toggle_tag(self, cb, state, user_data):
99 tags = user_data[cb.label]
97 if state:100 if state:
98 # for the selected radio button101 # if checkbox is ticked
99 tag = self.bug_types[rb.label]102 self._tags.base_widget.edit_text += ' ' + ' '.join(tags)
100 self._tags.base_widget.edit_text += ' ' + tag
101 else:103 else:
102 # for the previously selected radio button104 # if checkbox is unticked
103 tag = self.bug_types[rb.label]105 for tag in tags:
104 self._tags.base_widget.edit_text = self._tags.base_widget.edit_text.replace(tag, '')106 self._tags.base_widget.edit_text = self._tags.base_widget.edit_text.replace(tag, '')
105 # clean up the list of tags to remove unwanted white spaces107 # clean up the list of tags to
106 self._tags.base_widget.edit_text = " ".join(self._tags.base_widget.edit_text.split())108 # - remove unwanted white spaces
109 # - remove duplicated tags
110 current_tags = self._tags.base_widget.edit_text.split()
111 dedup_tags = []
112 for tag in current_tags:
113 if tag not in dedup_tags:
114 dedup_tags.append(tag)
115 self._tags.base_widget.edit_text = " ".join(dedup_tags)
107116
108 def run(self):117 def run(self):
109 """Run the urwid MainLoop."""118 """Run the urwid MainLoop."""
diff --git a/setup.py b/setup.py
index 9ca0a66..d01f071 100644
--- a/setup.py
+++ b/setup.py
@@ -20,6 +20,7 @@ qabro is a tool to report bugs against Launchpad projects and
20automatically attach relevent information to them (log files).20automatically attach relevent information to them (log files).
21""",21""",
22 packages=packages,22 packages=packages,
23 package_data={'qabro': ['data/tags.json']},
23 entry_points={24 entry_points={
24 'console_scripts': ['qabro = qabro.__init__:main']25 'console_scripts': ['qabro = qabro.__init__:main']
25 },26 },
diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml
index e307ff0..de2580d 100644
--- a/snap/snapcraft.yaml
+++ b/snap/snapcraft.yaml
@@ -43,6 +43,11 @@ parts:
43 - python3-urwid43 - python3-urwid
44 - ubuntu-report44 - ubuntu-report
4545
46 dpkg:
47 plugin: nil
48 stage-packages:
49 - dpkg
50
46 sosreport:51 sosreport:
47 after: [patches]52 after: [patches]
48 plugin: nil53 plugin: nil
@@ -56,8 +61,9 @@ parts:
56 # variable used by sosreport to call other commands.61 # variable used by sosreport to call other commands.
57 patch $SNAPCRAFT_PART_INSTALL/usr/share/sosreport/sos/policies/ubuntu.py $SNAPCRAFT_STAGE/patches/sosreport-env-path-snap.patch62 patch $SNAPCRAFT_PART_INSTALL/usr/share/sosreport/sos/policies/ubuntu.py $SNAPCRAFT_STAGE/patches/sosreport-env-path-snap.patch
58 # patches from YC Chen63 # patches from YC Chen
59 patch $SNAPCRAFT_PART_INSTALL/usr/share/sosreport/sos/plugins/apt.py $SNAPCRAFT_STAGE/patches/sosreport-apt-no-auth-conf.patch
60 patch $SNAPCRAFT_PART_INSTALL/usr/share/sosreport/sos/plugins/apt.py $SNAPCRAFT_STAGE/patches/sosreport-apt-remove-user-pwd.patch64 patch $SNAPCRAFT_PART_INSTALL/usr/share/sosreport/sos/plugins/apt.py $SNAPCRAFT_STAGE/patches/sosreport-apt-remove-user-pwd.patch
65 # patch to be able to have data from `dpkg -l` command
66 patch $SNAPCRAFT_PART_INSTALL/usr/share/sosreport/sos/plugins/dpkg.py $SNAPCRAFT_STAGE/patches/sosreport-dpkg-l.patch
6167
62 sosreport-plugins:68 sosreport-plugins:
63 after: [sosreport]69 after: [sosreport]

Subscribers

People subscribed via source and target branches

to all changes: