From 7ded7c1ac736175b33204b11ef69405caabc2491 Mon Sep 17 00:00:00 2001 From: Michael Hudson-Doyle Date: Fri, 24 Jan 2020 15:55:48 +1300 Subject: [PATCH 1/3] refactor how mirror data is handled This is prep work for allowing autoinstalls to specify a complete apt config. --- subiquity/controllers/mirror.py | 10 ++--- subiquity/models/mirror.py | 56 +++++++++++++++++------- subiquity/models/subiquity.py | 4 -- subiquity/models/tests/test_mirror.py | 44 +++++++++++++++++++ subiquity/models/tests/test_subiquity.py | 12 ++--- subiquity/ui/views/mirror.py | 2 +- 6 files changed, 98 insertions(+), 30 deletions(-) create mode 100644 subiquity/models/tests/test_mirror.py diff --git a/subiquity/controllers/mirror.py b/subiquity/controllers/mirror.py index b2242d8b..6f3eff99 100644 --- a/subiquity/controllers/mirror.py +++ b/subiquity/controllers/mirror.py @@ -92,21 +92,21 @@ class MirrorController(SubiquityController): self.done(self.answers['mirror']) elif 'country-code' in self.answers \ or 'accept-default' in self.answers: - self.done(self.model.mirror) + self.done(self.model.get_mirror()) def cancel(self): self.app.prev_screen() def serialize(self): - return self.model.mirror + return self.model.get_mirror() def deserialize(self, data): super().deserialize(data) - self.model.mirror = data + self.model.set_mirror(data) def done(self, mirror): log.debug("MirrorController.done next_screen mirror=%s", mirror) - if mirror != self.model.mirror: - self.model.mirror = mirror + if mirror != self.model.get_mirror(): + self.model.set_mirror(mirror) self.configured() self.app.next_screen() diff --git a/subiquity/models/mirror.py b/subiquity/models/mirror.py index 6e3913d1..179bba9a 100644 --- a/subiquity/models/mirror.py +++ b/subiquity/models/mirror.py @@ -13,35 +13,61 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . +import copy import logging -import platform from urllib import parse +from curtin.commands.apt_config import ( + get_arch_mirrorconfig, + get_mirror, + PRIMARY_ARCHES, + ) +from curtin.util import get_architecture + log = logging.getLogger('subiquitycore.models.mirror') -# correct default mirror for most arches -DEFAULT_MIRROR = 'http://ports.ubuntu.com/ubuntu-ports' -# apart from the two snowflakes -if platform.machine() in ['i686', 'x86_64']: - DEFAULT_MIRROR = 'http://archive.ubuntu.com/ubuntu' + +DEFAULT = { + "preserve_sources_list": False, + "primary": [ + { + "arches": PRIMARY_ARCHES, + "uri": "http://archive.ubuntu.com/ubuntu", + }, + { + "arches": ["default"], + "uri": "http://ports.ubuntu.com/ubuntu-ports", + }, + ], +} + + +def get_default_mirror(): + return get_mirror(DEFAULT, "primary", get_architecture()) class MirrorModel(object): def __init__(self): - self.mirror = DEFAULT_MIRROR + self.config = copy.deepcopy(DEFAULT) def set_country(self, cc): - parsed = parse.urlparse(DEFAULT_MIRROR) + uri = self.get_mirror() + if uri != get_default_mirror(): + return + parsed = parse.urlparse(uri) new = parsed._replace(netloc=cc + '.' + parsed.netloc) - self.mirror = parse.urlunparse(new) + self.set_mirror(parse.urlunparse(new)) + + def get_mirror(self): + return get_mirror(self.config, "primary", get_architecture()) + + def set_mirror(self, mirror): + config = get_arch_mirrorconfig( + self.config, "primary", get_architecture()) + config["uri"] = mirror def render(self): return { - 'apt': { - 'primary': [{ - 'arches': ["default"], - 'uri': self.mirror, - }], - } + 'apt': self.config } diff --git a/subiquity/models/subiquity.py b/subiquity/models/subiquity.py index 4a458145..f5a2df7f 100644 --- a/subiquity/models/subiquity.py +++ b/subiquity/models/subiquity.py @@ -207,10 +207,6 @@ class SubiquityModel: def render(self, syslog_identifier): config = { - 'apt': { - 'preserve_sources_list': False, - }, - 'sources': { 'ubuntu00': 'cp:///media/filesystem' }, diff --git a/subiquity/models/tests/test_mirror.py b/subiquity/models/tests/test_mirror.py new file mode 100644 index 00000000..8a5bf424 --- /dev/null +++ b/subiquity/models/tests/test_mirror.py @@ -0,0 +1,44 @@ +# Copyright 2019 Canonical, Ltd. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +import unittest + +from subiquity.models.mirror import ( + MirrorModel, + ) + + +class TestMirrorModel(unittest.TestCase): + + def test_set_country(self): + model = MirrorModel() + model.set_country("CC") + self.assertIn( + model.get_mirror(), + [ + "http://CC.archive.ubuntu.com/ubuntu", + "http://CC.ports.ubuntu.com/ubuntu-ports", + ]) + + def test_set_mirror(self): + model = MirrorModel() + model.set_mirror("http://mymirror.invalid/") + self.assertEqual(model.get_mirror(), "http://mymirror.invalid/") + + def test_set_country_after_set_mirror(self): + model = MirrorModel() + model.set_mirror("http://mymirror.invalid/") + model.set_country("CC") + self.assertEqual(model.get_mirror(), "http://mymirror.invalid/") diff --git a/subiquity/models/tests/test_subiquity.py b/subiquity/models/tests/test_subiquity.py index ff37f95b..5ada1c07 100644 --- a/subiquity/models/tests/test_subiquity.py +++ b/subiquity/models/tests/test_subiquity.py @@ -129,9 +129,11 @@ class TestSubiquityModel(unittest.TestCase): def test_mirror(self): model = SubiquityModel('test') - mirror_val = model.mirror.mirror = 'http://my-mirror' + mirror_val = 'http://my-mirror' + model.mirror.set_mirror(mirror_val) config = model.render('ident') - val = self.configVal(config, 'apt.primary') - self.assertEqual(len(val), 1) - val = val[0] - self.assertEqual(val['uri'], mirror_val) + from curtin.commands.apt_config import get_mirror + from curtin.util import get_architecture + self.assertEqual( + get_mirror(config["apt"], "primary", get_architecture()), + mirror_val) diff --git a/subiquity/ui/views/mirror.py b/subiquity/ui/views/mirror.py index 9721b847..7b2ba194 100644 --- a/subiquity/ui/views/mirror.py +++ b/subiquity/ui/views/mirror.py @@ -50,7 +50,7 @@ class MirrorView(BaseView): self.model = model self.controller = controller - self.form = MirrorForm(initial={'url': self.model.mirror}) + self.form = MirrorForm(initial={'url': self.model.get_mirror()}) connect_signal(self.form, 'submit', self.done) connect_signal(self.form, 'cancel', self.cancel) From 52fc18b77bd2f73fb6a6b18842265746cd0dc824 Mon Sep 17 00:00:00 2001 From: Michael Hudson-Doyle Date: Mon, 3 Feb 2020 15:45:48 +1300 Subject: [PATCH 2/3] calculate some things that will not change just once --- subiquity/models/mirror.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/subiquity/models/mirror.py b/subiquity/models/mirror.py index 179bba9a..d993188a 100644 --- a/subiquity/models/mirror.py +++ b/subiquity/models/mirror.py @@ -41,9 +41,8 @@ DEFAULT = { ], } - -def get_default_mirror(): - return get_mirror(DEFAULT, "primary", get_architecture()) +ARCHITECTURE = get_architecture() +DEFAULT_MIRROR = get_mirror(DEFAULT, "primary", ARCHITECTURE) class MirrorModel(object): @@ -53,21 +52,20 @@ class MirrorModel(object): def set_country(self, cc): uri = self.get_mirror() - if uri != get_default_mirror(): + if uri != DEFAULT_MIRROR: return parsed = parse.urlparse(uri) new = parsed._replace(netloc=cc + '.' + parsed.netloc) self.set_mirror(parse.urlunparse(new)) def get_mirror(self): - return get_mirror(self.config, "primary", get_architecture()) + return get_mirror(self.config, "primary", ARCHITECTURE) def set_mirror(self, mirror): - config = get_arch_mirrorconfig( - self.config, "primary", get_architecture()) + config = get_arch_mirrorconfig(self.config, "primary", ARCHITECTURE) config["uri"] = mirror def render(self): return { - 'apt': self.config + 'apt': copy.deepcopy(self.config) } From 2c1d350ea04f6d6fa1b55cf8bc210aaa96f4752c Mon Sep 17 00:00:00 2001 From: Michael Hudson-Doyle Date: Tue, 4 Feb 2020 13:45:46 +1300 Subject: [PATCH 3/3] do less at import time --- subiquity/models/mirror.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/subiquity/models/mirror.py b/subiquity/models/mirror.py index d993188a..2a64e699 100644 --- a/subiquity/models/mirror.py +++ b/subiquity/models/mirror.py @@ -41,28 +41,28 @@ DEFAULT = { ], } -ARCHITECTURE = get_architecture() -DEFAULT_MIRROR = get_mirror(DEFAULT, "primary", ARCHITECTURE) - class MirrorModel(object): def __init__(self): self.config = copy.deepcopy(DEFAULT) + self.architecture = get_architecture() + self.default_mirror = self.get_mirror() def set_country(self, cc): uri = self.get_mirror() - if uri != DEFAULT_MIRROR: + if uri != self.default_mirror: return parsed = parse.urlparse(uri) new = parsed._replace(netloc=cc + '.' + parsed.netloc) self.set_mirror(parse.urlunparse(new)) def get_mirror(self): - return get_mirror(self.config, "primary", ARCHITECTURE) + return get_mirror(self.config, "primary", self.architecture) def set_mirror(self, mirror): - config = get_arch_mirrorconfig(self.config, "primary", ARCHITECTURE) + config = get_arch_mirrorconfig( + self.config, "primary", self.architecture) config["uri"] = mirror def render(self):