Merge lp:~brian-murray/ubuntu-release-upgrader/patching-get-distro into lp:ubuntu-release-upgrader

Proposed by Brian Murray
Status: Merged
Merged at revision: 2937
Proposed branch: lp:~brian-murray/ubuntu-release-upgrader/patching-get-distro
Merge into: lp:ubuntu-release-upgrader
Diff against target: 332 lines (+167/-23)
3 files modified
DistUpgrade/DistUpgradeController.py (+55/-19)
tests/data-sources-list-test/sources.list.obsolete_mirror (+10/-0)
tests/test_sources_list.py (+102/-4)
To merge this branch: bzr merge lp:~brian-murray/ubuntu-release-upgrader/patching-get-distro
Reviewer Review Type Date Requested Status
Barry Warsaw (community) Needs Fixing
Review via email: mp+277770@code.launchpad.net

Description of the change

I want to update the code that only adds new mirrors to ubuntu-release-upgrader to also remove mirrors. However, if that change is made and you have an obsolete mirror you'll be left with a sources.list file that only contains main for the destination release. This'll result in a bad upgrade experience. See the linked bug for details.

I've modified the release upgrader to copy the disabled entries in sources.list and replace the server uri so that the upgrade will proceed and not leave a bunch of packages unupgraded. I've added a test, test_sources_list_inactive_mirror, for this.

To post a comment you must log in.
Revision history for this message
Barry Warsaw (barry) wrote :

LGTM, with just a few style nits. However, there's a merge conflict that needs to be fixed first.

review: Needs Fixing
2942. By Brian Murray

nitpick changes based off reviewer feedback

2943. By Brian Murray

Continue to leave BaseMetaPkgs commented out in the test version of DistUpgrade.cfg as it breaks other tests, set BaseMetaPkgs in the tests that require it.

2944. By Brian Murray

clarify notes regarding old code

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'DistUpgrade/DistUpgradeController.py'
2--- DistUpgrade/DistUpgradeController.py 2015-10-27 01:51:21 +0000
3+++ DistUpgrade/DistUpgradeController.py 2015-11-18 18:42:17 +0000
4@@ -506,14 +506,17 @@
5 logging.debug("verifySourcesListEntry: %s" % entry)
6 # no way to verify without network
7 if not self.useNetwork:
8- logging.debug("skiping downloadable check (no network)")
9+ logging.debug("skipping downloadable check (no network)")
10 return True
11 # check if the entry points to something we can download
12 uri = "%s/dists/%s/Release" % (entry.uri, entry.dist)
13 return url_downloadable(uri, logging.debug)
14
15 def rewriteSourcesList(self, mirror_check=True):
16- logging.debug("rewriteSourcesList()")
17+ if mirror_check:
18+ logging.debug("rewriteSourcesList() with mirror_check")
19+ else:
20+ logging.debug("rewriteSourcesList()")
21
22 sync_components = self.config.getlist("Sources","Components")
23
24@@ -525,12 +528,15 @@
25 mirror_check=False
26
27 # check if we need to enable main
28+ main_was_missing = False
29 if mirror_check == True and self.useNetwork:
30 # now check if the base-meta pkgs are available in
31 # the archive or only available as "now"
32 # -> if not that means that "main" is missing and we
33- # need to enable it
34- for pkgname in self.config.getlist("Distro","BaseMetaPkgs"):
35+ # need to enable it
36+ logging.debug(self.config.getlist("Distro", "BaseMetaPkgs"))
37+ for pkgname in self.config.getlist("Distro", "BaseMetaPkgs"):
38+ logging.debug("Checking pkg: %s" % pkgname)
39 if ((not pkgname in self.cache or
40 not self.cache[pkgname].candidate or
41 len(self.cache[pkgname].candidate.origins) == 0)
42@@ -544,17 +550,24 @@
43 distro = get_distro()
44 distro.get_sources(self.sources)
45 distro.enable_component("main")
46- except NoDistroTemplateException:
47+ main_was_missing = True
48+ except NoDistroTemplateException as e:
49+ logging.exception('NoDistroTemplateException raised: %s' % e)
50 # fallback if everything else does not work,
51- # we replace the sources.list with a single
52- # line to ubuntu-main
53- logging.warning('get_distro().enable_component("main") failed, overwriting sources.list instead as last resort')
54- s = "# auto generated by ubuntu-release-upgrader"
55- s += "deb http://archive.ubuntu.com/ubuntu %s main restricted" % self.toDist
56- s += "deb http://archive.ubuntu.com/ubuntu %s-updates main restricted" % self.toDist
57- s += "deb http://security.ubuntu.com/ubuntu %s-security main restricted" % self.toDist
58- with open("/etc/apt/sources.list","w") as f:
59- f.write(s)
60+ # we replace the sources.list with lines to
61+ # main and restricted
62+ logging.debug('get_distro().enable_component("main") failed, overwriting sources.list instead as last resort')
63+ comment = " auto generated by ubuntu-release-upgrader"
64+ comps = ["main", "restricted"]
65+ uri = "http://archive.ubuntu.com/ubuntu"
66+ self.sources.add("deb", uri, self.toDist, comps,
67+ comment)
68+ self.sources.add("deb", uri, self.toDist+"-updates",
69+ comps, comment)
70+ self.sources.add("deb",
71+ "http://security.ubuntu.com/ubuntu",
72+ self.toDist+"-security", comps,
73+ comment)
74 break
75
76 # this must map, i.e. second in "from" must be the second in "to"
77@@ -609,7 +622,7 @@
78 "dists",
79 entry.dist,
80 "Release")):
81- logging.warning("disabling cdrom source '%s' because it has no Release file" % entry)
82+ logging.warning("disabling cdrom source '%s' because it has no Release file" % entry)
83 entry.disabled = True
84 continue
85
86@@ -626,6 +639,7 @@
87
88 # special case for landscape.canonical.com because they
89 # don't use a standard archive layout (gutsy->hardy)
90+ # XXX - Is this still relevant?
91 if (not entry.disabled and
92 entry.uri.startswith("http://landscape.canonical.com/packages/%s" % self.fromDist)):
93 logging.debug("commenting landscape.canonical.com out")
94@@ -693,8 +707,8 @@
95 self.sources_disabled = True
96 logging.debug("entry '%s' was disabled (unknown dist)" % get_string_with_no_auth_from_source_entry(entry))
97
98- # if we make it to this point, we have a official or third-party mirror
99-
100+ # if we make it to this point, we have an official or third-party mirror
101+ # XXX - is this still relevant?
102 # check if the arch is powerpc or sparc and if so, transition
103 # to ports.ubuntu.com (powerpc got demoted in gutsy, sparc
104 # in hardy)
105@@ -710,7 +724,7 @@
106 "%s-security" % self.toDist]:
107 # create entry if needed, ignore disabled
108 # entries and deb-src
109- self.found_components.setdefault(d,set())
110+ self.found_components.setdefault(d, set())
111 if (not entry.disabled and entry.dist == d and
112 entry.type == "deb"):
113 for comp in entry.comps:
114@@ -731,12 +745,34 @@
115 entry.disabled = True
116 self.sources_disabled = True
117 logging.debug("entry '%s' was disabled (unknown mirror)" % get_string_with_no_auth_from_source_entry(entry))
118+ # if its not a valid mirror and we manually added main, be
119+ # nice and add pockets and components corresponding to what we
120+ # disabled.
121+ if main_was_missing:
122+ if entry.dist in fromDists:
123+ entry.dist = toDists[fromDists.index(entry.dist)]
124+ # gather what components are enabled and are inconsistent
125+ for d in ["%s" % self.toDist,
126+ "%s-updates" % self.toDist,
127+ "%s-security" % self.toDist]:
128+ # create entry if needed, ignore deb-src entries
129+ self.found_components.setdefault(d, set())
130+ if entry.dist == d and entry.type == "deb":
131+ for comp in entry.comps:
132+ # only sync components we know about
133+ if not comp in sync_components:
134+ continue
135+ self.found_components[d].add(comp)
136+ logging.debug("Adding entry: %s %s %s" % (entry.type, entry.dist, entry.comps))
137+ uri = "http://archive.ubuntu.com/ubuntu"
138+ comment = " auto generated by ubuntu-release-upgrader"
139+ self.sources.add(entry.type, uri, entry.dist, entry.comps, comment)
140
141 # now go over the list again and check for missing components
142 # in $dist-updates and $dist-security and add them
143 for entry in self.sources.list[:]:
144 # skip all comps that are not relevant (including e.g. "hardy")
145- if (entry.invalid or entry.disabled or entry.type == "deb-src" or
146+ if (entry.invalid or entry.disabled or entry.type == "deb-src" or
147 entry.uri.startswith("cdrom:") or entry.dist == self.toDist):
148 continue
149 # now check for "$dist-updates" and "$dist-security" and add any inconsistencies
150
151=== added file 'tests/data-sources-list-test/sources.list.obsolete_mirror'
152--- tests/data-sources-list-test/sources.list.obsolete_mirror 1970-01-01 00:00:00 +0000
153+++ tests/data-sources-list-test/sources.list.obsolete_mirror 2015-11-18 18:42:17 +0000
154@@ -0,0 +1,10 @@
155+
156+# main repo
157+deb http://mirror.mcs.anl.gov/ubuntu feisty main restricted universe multiverse
158+deb http://mirror.mcs.anl.gov/ubuntu feisty-updates main restricted universe multiverse
159+#deb http://mirror.mcs.anl.gov/ubuntu feisty-proposed main restricted universe multiverse
160+deb http://mirror.mcs.anl.gov/ubuntu feisty-security main restricted universe multiverse
161+deb-src http://mirror.mcs.anl.gov/ubuntu feisty main restricted universe multiverse
162+deb-src http://mirror.mcs.anl.gov/ubuntu feisty-updates main restricted universe multiverse
163+##deb-src http://mirror.mcs.anl.gov/ubuntu feisty-proposed main restricted universe multiverse
164+deb-src http://mirror.mcs.anl.gov/ubuntu feisty-security main restricted universe multiverse
165
166=== modified file 'tests/test_sources_list.py'
167--- tests/test_sources_list.py 2015-01-20 22:30:06 +0000
168+++ tests/test_sources_list.py 2015-11-18 18:42:17 +0000
169@@ -18,6 +18,10 @@
170 )
171 from DistUpgrade import DistUpgradeConfigParser
172 from DistUpgrade.utils import url_downloadable
173+from DistUpgrade.distro import (
174+ UbuntuDistribution,
175+ NoDistroTemplateException
176+)
177 import logging
178 import mock
179
180@@ -87,7 +91,8 @@
181 deb http://security.ubuntu.com/ubuntu/ gutsy-security main restricted
182 """)
183
184- def test_sources_list_rewrite(self):
185+ @mock.patch("DistUpgrade.DistUpgradeController.get_distro")
186+ def test_sources_list_rewrite(self, mock_get_distro):
187 """
188 test regular sources.list rewrite
189 """
190@@ -96,8 +101,13 @@
191 apt_pkg.config.set("Dir::Etc::sourcelist", "sources.list")
192 v = DistUpgradeViewNonInteractive()
193 d = DistUpgradeController(v, datadir=self.testdir)
194+ d.config.set("Distro", "BaseMetaPkgs", "ubuntu-minimal")
195+ mock_get_distro.return_value = UbuntuDistribution("Ubuntu", "feisty",
196+ "Ubuntu Feisty Fawn",
197+ "7.04")
198 d.openCache(lock=False)
199 res = d.updateSourcesList()
200+ self.assertTrue(mock_get_distro.called)
201 self.assertTrue(res)
202
203 # now test the result
204@@ -117,6 +127,90 @@
205 apt_pkg.config.find_file("Dir::Etc::sourcelist") + ".distUpgrade"
206 ]))
207
208+ @mock.patch("DistUpgrade.DistUpgradeController.get_distro")
209+ def test_sources_list_inactive_mirror(self, mock_get_distro):
210+ """
211+ test sources.list rewrite of an obsolete mirror
212+ """
213+ shutil.copy(os.path.join(self.testdir, "sources.list.obsolete_mirror"),
214+ os.path.join(self.testdir, "sources.list"))
215+ apt_pkg.config.set("Dir::Etc::sourcelist", "sources.list")
216+ v = DistUpgradeViewNonInteractive()
217+ d = DistUpgradeController(v, datadir=self.testdir)
218+ d.config.set("Distro", "BaseMetaPkgs", "ubuntu-minimal")
219+ mock_get_distro.return_value = UbuntuDistribution("Ubuntu", "feisty",
220+ "Ubuntu Feisty Fawn",
221+ "7.04")
222+ d.openCache(lock=False)
223+ res = d.updateSourcesList()
224+ self.assertTrue(mock_get_distro.called)
225+ self.assertTrue(res)
226+
227+ # now test the result
228+ #print(open(os.path.join(self.testdir,"sources.list")).read())
229+ self._verifySources("""
230+# main repo
231+# deb http://mirror.mcs.anl.gov/ubuntu gutsy main restricted universe multiverse # disabled on upgrade to gutsy
232+# deb http://mirror.mcs.anl.gov/ubuntu gutsy-updates main restricted universe multiverse # disabled on upgrade to gutsy
233+# deb http://mirror.mcs.anl.gov/ubuntu feisty-proposed main restricted universe multiverse
234+# deb http://mirror.mcs.anl.gov/ubuntu gutsy-security main restricted universe multiverse # disabled on upgrade to gutsy
235+# deb-src http://mirror.mcs.anl.gov/ubuntu gutsy main restricted universe multiverse # disabled on upgrade to gutsy
236+# deb-src http://mirror.mcs.anl.gov/ubuntu gutsy-updates main restricted universe multiverse # disabled on upgrade to gutsy
237+##deb-src http://mirror.mcs.anl.gov/ubuntu feisty-proposed main restricted universe multiverse
238+deb http://archive.ubuntu.com/ubuntu/ gutsy main
239+deb http://archive.ubuntu.com/ubuntu gutsy main restricted universe multiverse # auto generated by ubuntu-release-upgrader
240+deb http://archive.ubuntu.com/ubuntu gutsy-updates main restricted universe multiverse # auto generated by ubuntu-release-upgrader
241+deb http://archive.ubuntu.com/ubuntu gutsy-security main restricted universe multiverse # auto generated by ubuntu-release-upgrader
242+# deb-src http://mirror.mcs.anl.gov/ubuntu gutsy-security main restricted universe multiverse # disabled on upgrade to gutsy
243+""")
244+ # check that the backup file was created correctly
245+ self.assertEqual(0, subprocess.call(
246+ ["cmp",
247+ apt_pkg.config.find_file("Dir::Etc::sourcelist") + ".obsolete_mirror",
248+ apt_pkg.config.find_file("Dir::Etc::sourcelist") + ".distUpgrade"
249+ ]))
250+
251+ @mock.patch("DistUpgrade.DistUpgradeController.get_distro")
252+ def test_sources_list_no_template(self, mock_get_distro):
253+ """
254+ test sources.list rewrite when there is no distro template
255+ """
256+ shutil.copy(os.path.join(self.testdir, "sources.list.obsolete_mirror"),
257+ os.path.join(self.testdir, "sources.list"))
258+ apt_pkg.config.set("Dir::Etc::sourcelist", "sources.list")
259+ v = DistUpgradeViewNonInteractive()
260+ d = DistUpgradeController(v, datadir=self.testdir)
261+ d.config.set("Distro", "BaseMetaPkgs", "ubuntu-minimal")
262+ mock_get_distro.side_effect = NoDistroTemplateException("No distro template.")
263+ d.openCache(lock=False)
264+ res = d.updateSourcesList()
265+ self.assertTrue(mock_get_distro.called)
266+ self.assertTrue(res)
267+
268+ # now test the result
269+ #print(open(os.path.join(self.testdir,"sources.list")).read())
270+ self._verifySources("""
271+# main repo
272+# deb http://mirror.mcs.anl.gov/ubuntu gutsy main restricted universe multiverse # disabled on upgrade to gutsy
273+# deb http://mirror.mcs.anl.gov/ubuntu feisty-updates main restricted universe multiverse # disabled on upgrade to gutsy
274+# deb http://mirror.mcs.anl.gov/ubuntu feisty-proposed main restricted universe multiverse
275+# deb http://mirror.mcs.anl.gov/ubuntu feisty-security main restricted universe multiverse # disabled on upgrade to gutsy
276+# deb-src http://mirror.mcs.anl.gov/ubuntu gutsy main restricted universe multiverse # disabled on upgrade to gutsy
277+# deb-src http://mirror.mcs.anl.gov/ubuntu feisty-updates main restricted universe multiverse # disabled on upgrade to gutsy
278+##deb-src http://mirror.mcs.anl.gov/ubuntu feisty-proposed main restricted universe multiverse
279+deb http://archive.ubuntu.com/ubuntu gutsy main restricted # auto generated by ubuntu-release-upgrader
280+deb http://archive.ubuntu.com/ubuntu gutsy-updates main restricted # auto generated by ubuntu-release-upgrader
281+deb http://security.ubuntu.com/ubuntu gutsy-security main restricted # auto generated by ubuntu-release-upgrader
282+# deb-src http://mirror.mcs.anl.gov/ubuntu feisty-security main restricted universe multiverse # disabled on upgrade to gutsy
283+""")
284+
285+ # check that the backup file was created correctly
286+ self.assertEqual(0, subprocess.call(
287+ ["cmp",
288+ apt_pkg.config.find_file("Dir::Etc::sourcelist") + ".obsolete_mirror",
289+ apt_pkg.config.find_file("Dir::Etc::sourcelist") + ".distUpgrade"
290+ ]))
291+
292 def test_commercial_transition(self):
293 """
294 test transition of pre-gutsy archive.canonical.com archives
295@@ -137,7 +231,8 @@
296 deb http://archive.canonical.com/ubuntu gutsy partner
297 """)
298
299- def test_extras_removal(self):
300+ @mock.patch("DistUpgrade.DistUpgradeController.get_distro")
301+ def test_extras_removal(self, mock_get_distro):
302 """
303 test removal of extras.ubuntu.com archives
304 """
305@@ -149,6 +244,9 @@
306 os.path.join(self.testdir, "sources.list.d"))
307 v = DistUpgradeViewNonInteractive()
308 d = DistUpgradeController(v, datadir=self.testdir)
309+ mock_get_distro.return_value = UbuntuDistribution("Ubuntu", "feisty",
310+ "Ubuntu Feisty Fawn",
311+ "7.04")
312 d.openCache(lock=False)
313 res = d.updateSourcesList()
314 self.assertTrue(res)
315@@ -252,7 +350,7 @@
316 "http://us.archive.ubuntu.com/ubuntu", logging.debug),
317 "Could not reach mirror")
318 def testEOL2SupportedWithMirrorUpgrade(self):
319- " test upgrade from a EOL release to a supported release with mirror"
320+ " test upgrade from a EOL release to a supported release with mirror "
321 # Use us.archive.ubuntu.com, because it is available in Canonical's
322 # data center, unlike most mirrors. This lets this test pass when
323 # when run in their Jenkins test environment.
324@@ -387,7 +485,7 @@
325
326 def test_unicode_comments(self):
327 """
328- test transition of apt-cacher/apt-torrent uris
329+ test a sources.list file with unicode comments
330 """
331 shutil.copy(os.path.join(self.testdir, "sources.list.unicode"),
332 os.path.join(self.testdir, "sources.list"))

Subscribers

People subscribed via source and target branches