Merge ~kyrofa/ubuntu-release-upgrader:feature/ros-quirk into ubuntu-release-upgrader:ubuntu/master

Proposed by Kyle Fazzari
Status: Merged
Merged at revision: 82eb14ed4511a9f6217b7381f10e7d5248d87179
Proposed branch: ~kyrofa/ubuntu-release-upgrader:feature/ros-quirk
Merge into: ubuntu-release-upgrader:ubuntu/master
Diff against target: 156 lines (+120/-0)
2 files modified
DistUpgrade/DistUpgradeQuirks.py (+50/-0)
tests/test_quirks.py (+70/-0)
Reviewer Review Type Date Requested Status
Brian Murray Approve
Review via email: mp+388145@code.launchpad.net

Commit message

Add quirk to check and warn if ROS is installed

Description of the change

Each ROS release is very strict about the versions of Ubuntu it supports. Operating outside of that guidance can easily lead to upgrade errors that are hard to debug. Add a quirk to detect if ROS is installed, and warn the user of this situation before they continue with the upgrade.

To post a comment you must log in.
Revision history for this message
Brian Murray (brian-murray) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/DistUpgrade/DistUpgradeQuirks.py b/DistUpgrade/DistUpgradeQuirks.py
2index c414424..72e713e 100644
3--- a/DistUpgrade/DistUpgradeQuirks.py
4+++ b/DistUpgrade/DistUpgradeQuirks.py
5@@ -117,7 +117,10 @@ class DistUpgradeQuirks(object):
6 logging.debug("running Quirks.groovyPostInitialUpdate")
7 self._get_from_and_to_version()
8 self._test_and_fail_on_i386()
9+
10 cache = self.controller.cache
11+ self._test_and_warn_if_ros_installed(cache)
12+
13 if 'ubuntu-desktop' not in cache or \
14 'snapd' not in cache:
15 logging.debug("package required for Quirk not in cache")
16@@ -363,6 +366,53 @@ class DistUpgradeQuirks(object):
17 self.controller.abort()
18 self._view.processEvents()
19
20+ def _test_and_warn_if_ros_installed(self, cache):
21+ """
22+ Test and warn if ROS is installed. A given ROS release only
23+ supports specific Ubuntu releases, and can cause the upgrade
24+ to fail in an overly-cryptic manner.
25+ """
26+
27+ # These are the root ROS 1 and 2 dependencies as of 07/27/2020
28+ ros_package_patterns = set()
29+ for package_name in (
30+ "catkin",
31+ "rosboost-cfg",
32+ "rosclean",
33+ "ros-environment",
34+ "ros-workspace"):
35+ ros_package_patterns.add(
36+ re.compile("ros-[^\-]+-%s" % package_name))
37+
38+ ros_is_installed = False
39+ for pkg in cache:
40+ if ros_is_installed:
41+ break
42+
43+ for pattern in ros_package_patterns:
44+ if pattern.match(pkg.name):
45+ if pkg.is_installed or pkg.marked_install:
46+ ros_is_installed = True
47+ break
48+
49+ if ros_is_installed:
50+ res = self._view.askYesNoQuestion(
51+ _("The Robot Operating System (ROS) is installed"),
52+ _("It appears that ROS is currently installed. Each ROS "
53+ "release is very strict about the versions of Ubuntu "
54+ "it supports, and Ubuntu upgrades can fail if that "
55+ "guidance isn't followed. Before continuing, please "
56+ "either uninstall ROS, or ensure the ROS release you "
57+ "have installed supports the version of Ubuntu to "
58+ "which you're upgrading.\n\n"
59+ "For ROS 1 releases, refer to REP 3:\n"
60+ "https://www.ros.org/reps/rep-0003.html\n\n"
61+ "For ROS 2 releases, refer to REP 2000:\n"
62+ "https://www.ros.org/reps/rep-2000.html\n\n"
63+ "Are you sure you want to continue?"))
64+ if not res:
65+ self.controller.abort()
66+
67 def _checkArmCPU(self):
68 """
69 parse /proc/cpuinfo and search for ARMv6 or greater
70diff --git a/tests/test_quirks.py b/tests/test_quirks.py
71index 0725b67..66aae13 100644
72--- a/tests/test_quirks.py
73+++ b/tests/test_quirks.py
74@@ -163,6 +163,7 @@ def make_mock_pkg(name, is_installed, candidate_rec=""):
75 mock_pkg = mock.Mock()
76 mock_pkg.name = name
77 mock_pkg.is_installed = is_installed
78+ mock_pkg.marked_install = False
79 if candidate_rec:
80 mock_pkg.candidate = mock.Mock()
81 mock_pkg.candidate.record = candidate_rec
82@@ -364,6 +365,75 @@ class TestQuirks(unittest.TestCase):
83 pkgname = q._get_linux_metapackage(mock_cache, headers=False)
84 self.assertEqual(pkgname, "linux-generic-lts-quantal")
85
86+ def test_ros_installed_warning(self):
87+ ros_packages = (
88+ "ros-melodic-catkin",
89+ "ros-noetic-rosboost-cfg",
90+ "ros-foxy-rosclean",
91+ "ros-kinetic-ros-environment",
92+ "ros-dashing-ros-workspace")
93+ for package_name in ros_packages:
94+ mock_controller = mock.Mock()
95+ mock_question = mock_controller._view.askYesNoQuestion
96+ mock_question.return_value = True
97+
98+ q = DistUpgradeQuirks(mock_controller, mock.Mock())
99+ mock_cache = set([
100+ make_mock_pkg(
101+ name=package_name,
102+ is_installed=True,
103+ ),
104+ ])
105+ q._test_and_warn_if_ros_installed(mock_cache)
106+ mock_question.assert_called_once_with(mock.ANY, mock.ANY)
107+ self.assertFalse(len(mock_controller.abort.mock_calls))
108+
109+ mock_controller.reset_mock()
110+ mock_question.reset_mock()
111+ mock_question.return_value = False
112+
113+ mock_cache = set([
114+ make_mock_pkg(
115+ name=package_name,
116+ is_installed=True,
117+ ),
118+ ])
119+ q._test_and_warn_if_ros_installed(mock_cache)
120+ mock_question.assert_called_once_with(mock.ANY, mock.ANY)
121+ mock_controller.abort.assert_called_once_with()
122+
123+ def test_ros_not_installed_no_warning(self):
124+ mock_controller = mock.Mock()
125+ mock_question = mock_controller._view.askYesNoQuestion
126+ mock_question.return_value = False
127+
128+ q = DistUpgradeQuirks(mock_controller, mock.Mock())
129+ mock_cache = set([
130+ make_mock_pkg(
131+ name="ros-melodic-catkin",
132+ is_installed=False,
133+ ),
134+ make_mock_pkg(
135+ name="ros-noetic-rosboost-cfg",
136+ is_installed=False,
137+ ),
138+ make_mock_pkg(
139+ name="ros-foxy-rosclean",
140+ is_installed=False,
141+ ),
142+ make_mock_pkg(
143+ name="ros-kinetic-ros-environment",
144+ is_installed=False,
145+ ),
146+ make_mock_pkg(
147+ name="ros-dashing-ros-workspace",
148+ is_installed=False,
149+ ),
150+ ])
151+ q._test_and_warn_if_ros_installed(mock_cache)
152+ self.assertFalse(len(mock_question.mock_calls))
153+ self.assertFalse(len(mock_controller.abort.mock_calls))
154+
155
156 class TestSnapQuirks(unittest.TestCase):
157

Subscribers

People subscribed via source and target branches