Merge pull request #1137 from mwhudson/move-apt_configurer-to-mirror-controller
move apt configurer to mirror controller
This commit is contained in:
commit
baa8465ded
|
@ -14,6 +14,7 @@
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
|
import functools
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
import tempfile
|
import tempfile
|
||||||
|
@ -29,12 +30,100 @@ from subiquitycore.utils import arun_command
|
||||||
from subiquity.server.curtin import run_curtin_command
|
from subiquity.server.curtin import run_curtin_command
|
||||||
|
|
||||||
|
|
||||||
|
class _MountBase:
|
||||||
|
|
||||||
|
def p(self, *args):
|
||||||
|
for a in args:
|
||||||
|
if a.startswith('/'):
|
||||||
|
raise Exception('no absolute paths here please')
|
||||||
|
return os.path.join(self.mountpoint, *args)
|
||||||
|
|
||||||
|
def write(self, path, content):
|
||||||
|
with open(self.p(path), 'w') as fp:
|
||||||
|
fp.write(content)
|
||||||
|
|
||||||
|
|
||||||
|
class Mountpoint(_MountBase):
|
||||||
|
def __init__(self, *, mountpoint):
|
||||||
|
self.mountpoint = mountpoint
|
||||||
|
|
||||||
|
|
||||||
|
class OverlayMountpoint(_MountBase):
|
||||||
|
def __init__(self, *, lowers, upperdir, mountpoint):
|
||||||
|
self.lowers = lowers
|
||||||
|
self.upperdir = upperdir
|
||||||
|
self.mountpoint = mountpoint
|
||||||
|
|
||||||
|
|
||||||
|
@functools.singledispatch
|
||||||
|
def lowerdir_for(x):
|
||||||
|
"""Return value suitable for passing to the lowerdir= overlayfs option."""
|
||||||
|
raise NotImplementedError(x)
|
||||||
|
|
||||||
|
|
||||||
|
@lowerdir_for.register(str)
|
||||||
|
def _lowerdir_for_str(path):
|
||||||
|
return path
|
||||||
|
|
||||||
|
|
||||||
|
@lowerdir_for.register(Mountpoint)
|
||||||
|
def _lowerdir_for_mnt(mnt):
|
||||||
|
return mnt.mountpoint
|
||||||
|
|
||||||
|
|
||||||
|
@lowerdir_for.register(OverlayMountpoint)
|
||||||
|
def _lowerdir_for_ovmnt(ovmnt):
|
||||||
|
# One cannot indefinitely stack overlayfses so construct an
|
||||||
|
# explicit list of the layers of the overlayfs.
|
||||||
|
return lowerdir_for(ovmnt.lowers + [ovmnt.upperdir])
|
||||||
|
|
||||||
|
|
||||||
|
@lowerdir_for.register(list)
|
||||||
|
def _lowerdir_for_lst(lst):
|
||||||
|
return ':'.join(reversed([lowerdir_for(item) for item in lst]))
|
||||||
|
|
||||||
|
|
||||||
class AptConfigurer:
|
class AptConfigurer:
|
||||||
|
# We configure apt during installation so that installs from the pool on
|
||||||
|
# the cdrom are preferred during installation but remove this again in the
|
||||||
|
# installed system.
|
||||||
|
#
|
||||||
|
# First we create an overlay ('configured_tree') over the installation
|
||||||
|
# source and configure that overlay as we want the target system to end up
|
||||||
|
# by running curtin's apt-config subcommand. This is done in the
|
||||||
|
# apply_apt_config method.
|
||||||
|
#
|
||||||
|
# Then in configure_for_install we create a fresh overlay ('install_tree')
|
||||||
|
# over the first one and configure it for the installation. This means:
|
||||||
|
#
|
||||||
|
# 1. Bind-mounting /cdrom into this new overlay.
|
||||||
|
#
|
||||||
|
# 2. When the network is expected to be working, copying the original
|
||||||
|
# /etc/apt/sources.list to /etc/apt/sources.list.d/original.list.
|
||||||
|
#
|
||||||
|
# 3. writing "deb file:///cdrom $(lsb_release -sc) main restricted"
|
||||||
|
# to /etc/apt/sources.list.
|
||||||
|
#
|
||||||
|
# 4. running "apt-get update" in the new overlay.
|
||||||
|
#
|
||||||
|
# When the install is done the deconfigure method makes the installed
|
||||||
|
# system's apt state look as if the pool had never been configured. So
|
||||||
|
# this means:
|
||||||
|
#
|
||||||
|
# 1. Removing /cdrom from the installed system.
|
||||||
|
#
|
||||||
|
# 2. Copying /etc/apt from the 'configured' overlay to the installed
|
||||||
|
# system.
|
||||||
|
#
|
||||||
|
# 3. If the network is working, run apt-get update in the installed
|
||||||
|
# system, or if it is not, just copy /var/lib/apt/lists from the
|
||||||
|
# 'configured_tree' overlay.
|
||||||
|
|
||||||
def __init__(self, app, source):
|
def __init__(self, app, source):
|
||||||
self.app = app
|
self.app = app
|
||||||
self.source = source
|
self.source = source
|
||||||
self.configured = None
|
self.configured_tree = None
|
||||||
|
self.install_mount = None
|
||||||
self._mounts = []
|
self._mounts = []
|
||||||
self._tdirs = []
|
self._tdirs = []
|
||||||
|
|
||||||
|
@ -51,21 +140,31 @@ class AptConfigurer:
|
||||||
opts.extend(['-t', type])
|
opts.extend(['-t', type])
|
||||||
await self.app.command_runner.run(
|
await self.app.command_runner.run(
|
||||||
['mount'] + opts + [device, mountpoint])
|
['mount'] + opts + [device, mountpoint])
|
||||||
self._mounts.append(mountpoint)
|
m = Mountpoint(mountpoint=mountpoint)
|
||||||
|
self._mounts.append(m)
|
||||||
|
return m
|
||||||
|
|
||||||
async def unmount(self, mountpoint):
|
async def unmount(self, mountpoint):
|
||||||
await self.app.command_runner.run(['umount', mountpoint])
|
await self.app.command_runner.run(['umount', mountpoint])
|
||||||
|
|
||||||
async def setup_overlay(self, source, target):
|
async def setup_overlay(self, lowers):
|
||||||
tdir = self.tdir()
|
tdir = self.tdir()
|
||||||
w = f'{tdir}/work'
|
target = f'{tdir}/mount'
|
||||||
u = f'{tdir}/upper'
|
lowerdir = lowerdir_for(lowers)
|
||||||
for d in w, u:
|
upperdir = f'{tdir}/upper'
|
||||||
|
workdir = f'{tdir}/work'
|
||||||
|
for d in target, workdir, upperdir:
|
||||||
os.mkdir(d)
|
os.mkdir(d)
|
||||||
await self.mount(
|
|
||||||
'overlay', target, type='overlay',
|
options = f'lowerdir={lowerdir},upperdir={upperdir},workdir={workdir}'
|
||||||
options=f'lowerdir={source},upperdir={u},workdir={w}')
|
|
||||||
return u
|
mount = await self.mount(
|
||||||
|
'overlay', target, options=options, type='overlay')
|
||||||
|
|
||||||
|
return OverlayMountpoint(
|
||||||
|
lowers=lowers,
|
||||||
|
mountpoint=mount.p(),
|
||||||
|
upperdir=upperdir)
|
||||||
|
|
||||||
def apt_config(self):
|
def apt_config(self):
|
||||||
cfg = {}
|
cfg = {}
|
||||||
|
@ -73,42 +172,8 @@ class AptConfigurer:
|
||||||
merge_config(cfg, self.app.base_model.proxy.get_apt_config())
|
merge_config(cfg, self.app.base_model.proxy.get_apt_config())
|
||||||
return {'apt': cfg}
|
return {'apt': cfg}
|
||||||
|
|
||||||
async def configure(self, context):
|
async def apply_apt_config(self, context):
|
||||||
# Configure apt so that installs from the pool on the cdrom are
|
self.configured_tree = await self.setup_overlay(self.source)
|
||||||
# preferred during installation but not in the installed system.
|
|
||||||
#
|
|
||||||
# First we create an overlay ('configured') over the installation
|
|
||||||
# source and configure that overlay as we want the target system to
|
|
||||||
# end up by running curtin's apt-config subcommand.
|
|
||||||
#
|
|
||||||
# Then we create a fresh overlay ('for_install') over the first one
|
|
||||||
# and configure it for the installation. This means:
|
|
||||||
#
|
|
||||||
# 1. Bind-mounting /cdrom into this new overlay.
|
|
||||||
#
|
|
||||||
# 2. When the network is expected to be working, copying the original
|
|
||||||
# /etc/apt/sources.list to /etc/apt/sources.list.d/original.list.
|
|
||||||
#
|
|
||||||
# 3. writing "deb file:///cdrom $(lsb_release -sc) main restricted"
|
|
||||||
# to /etc/apt/sources.list.
|
|
||||||
#
|
|
||||||
# 4. running "apt-get update" in the new overlay.
|
|
||||||
#
|
|
||||||
# When the install is done we try to make the installed system's apt
|
|
||||||
# state look as if the pool had never been configured. So this means:
|
|
||||||
#
|
|
||||||
# 1. Removing /cdrom from the installed system.
|
|
||||||
#
|
|
||||||
# 2. Copying /etc/apt from the 'configured' overlay to the installed
|
|
||||||
# system.
|
|
||||||
#
|
|
||||||
# 3. If the network is working, run apt-get update in the installed
|
|
||||||
# system, or if it is not, just copy /var/lib/apt/lists from the
|
|
||||||
# 'configured' overlay.
|
|
||||||
|
|
||||||
self.configured = self.tdir()
|
|
||||||
|
|
||||||
config_upper = await self.setup_overlay(self.source, self.configured)
|
|
||||||
|
|
||||||
config_location = os.path.join(
|
config_location = os.path.join(
|
||||||
self.app.root, 'var/log/installer/subiquity-curtin-apt.conf')
|
self.app.root, 'var/log/installer/subiquity-curtin-apt.conf')
|
||||||
|
@ -120,71 +185,81 @@ class AptConfigurer:
|
||||||
self.app.note_data_for_apport("CurtinAptConfig", config_location)
|
self.app.note_data_for_apport("CurtinAptConfig", config_location)
|
||||||
|
|
||||||
await run_curtin_command(
|
await run_curtin_command(
|
||||||
self.app, context, 'apt-config', '-t', self.configured,
|
self.app, context, 'apt-config', '-t', self.configured_tree.p(),
|
||||||
config=config_location)
|
config=config_location)
|
||||||
|
|
||||||
for_install = self.tdir()
|
async def configure_for_install(self, context):
|
||||||
await self.setup_overlay(config_upper + ':' + self.source, for_install)
|
assert self.configured_tree is not None
|
||||||
|
|
||||||
os.mkdir(f'{for_install}/cdrom')
|
self.install_tree = await self.setup_overlay(self.configured_tree)
|
||||||
await self.mount('/cdrom', f'{for_install}/cdrom', options='bind')
|
|
||||||
|
os.mkdir(self.install_tree.p('cdrom'))
|
||||||
|
await self.mount(
|
||||||
|
'/cdrom', self.install_tree.p('cdrom'), options='bind')
|
||||||
|
|
||||||
if self.app.base_model.network.has_network:
|
if self.app.base_model.network.has_network:
|
||||||
os.rename(
|
os.rename(
|
||||||
f'{for_install}/etc/apt/sources.list',
|
self.install_tree.p('etc/apt/sources.list'),
|
||||||
f'{for_install}/etc/apt/sources.list.d/original.list')
|
self.install_tree.p('etc/apt/sources.list.d/original.list'))
|
||||||
else:
|
else:
|
||||||
proxy_path = f'{for_install}/etc/apt/apt.conf.d/90curtin-aptproxy'
|
proxy_path = self.install_tree.p(
|
||||||
|
'etc/apt/apt.conf.d/90curtin-aptproxy')
|
||||||
if os.path.exists(proxy_path):
|
if os.path.exists(proxy_path):
|
||||||
os.unlink(proxy_path)
|
os.unlink(proxy_path)
|
||||||
|
|
||||||
codename = lsb_release()['codename']
|
codename = lsb_release()['codename']
|
||||||
|
|
||||||
write_file(
|
write_file(
|
||||||
f'{for_install}/etc/apt/sources.list',
|
self.install_tree.p('etc/apt/sources.list'),
|
||||||
f'deb [check-date=no] file:///cdrom {codename} main restricted\n')
|
f'deb [check-date=no] file:///cdrom {codename} main restricted\n')
|
||||||
|
|
||||||
await run_curtin_command(
|
await run_curtin_command(
|
||||||
self.app, context, "in-target", "-t", for_install,
|
self.app, context, "in-target", "-t", self.install_tree.p(),
|
||||||
"--", "apt-get", "update")
|
"--", "apt-get", "update")
|
||||||
|
|
||||||
return for_install
|
return self.install_tree.p()
|
||||||
|
|
||||||
async def deconfigure(self, context, target):
|
|
||||||
await self.unmount(f'{target}/cdrom')
|
|
||||||
os.rmdir(f'{target}/cdrom')
|
|
||||||
|
|
||||||
restore_dirs = ['etc/apt']
|
|
||||||
if not self.app.base_model.network.has_network:
|
|
||||||
restore_dirs.append('var/lib/apt/lists')
|
|
||||||
for dir in restore_dirs:
|
|
||||||
shutil.rmtree(f'{target}/{dir}')
|
|
||||||
await self.app.command_runner.run([
|
|
||||||
'cp', '-aT', f'{self.configured}/{dir}', f'{target}/{dir}',
|
|
||||||
])
|
|
||||||
|
|
||||||
if self.app.base_model.network.has_network:
|
|
||||||
await run_curtin_command(
|
|
||||||
self.app, context, "in-target", "-t", target,
|
|
||||||
"--", "apt-get", "update")
|
|
||||||
|
|
||||||
|
async def cleanup(self):
|
||||||
for m in reversed(self._mounts):
|
for m in reversed(self._mounts):
|
||||||
await self.unmount(m)
|
await self.unmount(m.mountpoint)
|
||||||
for d in self._tdirs:
|
for d in self._tdirs:
|
||||||
shutil.rmtree(d)
|
shutil.rmtree(d)
|
||||||
|
|
||||||
|
async def deconfigure(self, context, target):
|
||||||
|
target = Mountpoint(mountpoint=target)
|
||||||
|
|
||||||
|
async def _restore_dir(dir):
|
||||||
|
shutil.rmtree(target.p(dir))
|
||||||
|
await self.app.command_runner.run([
|
||||||
|
'cp', '-aT', self.configured_tree.p(dir), target.p(dir),
|
||||||
|
])
|
||||||
|
|
||||||
|
await self.unmount(target.p('cdrom'))
|
||||||
|
os.rmdir(target.p('cdrom'))
|
||||||
|
|
||||||
|
await _restore_dir('etc/apt')
|
||||||
|
|
||||||
if self.app.base_model.network.has_network:
|
if self.app.base_model.network.has_network:
|
||||||
await run_curtin_command(
|
await run_curtin_command(
|
||||||
self.app, context, "in-target", "-t", target,
|
self.app, context, "in-target", "-t", target.p(),
|
||||||
|
"--", "apt-get", "update")
|
||||||
|
else:
|
||||||
|
await _restore_dir('var/lib/apt/lists')
|
||||||
|
|
||||||
|
await self.cleanup()
|
||||||
|
|
||||||
|
if self.app.base_model.network.has_network:
|
||||||
|
await run_curtin_command(
|
||||||
|
self.app, context, "in-target", "-t", target.p(),
|
||||||
"--", "apt-get", "update")
|
"--", "apt-get", "update")
|
||||||
|
|
||||||
|
|
||||||
class DryRunAptConfigurer(AptConfigurer):
|
class DryRunAptConfigurer(AptConfigurer):
|
||||||
|
|
||||||
async def setup_overlay(self, source, target):
|
async def setup_overlay(self, source):
|
||||||
if source.startswith('u+'):
|
if isinstance(source, OverlayMountpoint):
|
||||||
# Please excuse the obscure way the path is transmitted
|
source = source.lowers[0]
|
||||||
# from the first invocation of this method to the second :/
|
target = self.tdir()
|
||||||
source = source.split(':')[0][2:]
|
|
||||||
os.mkdir(f'{target}/etc')
|
os.mkdir(f'{target}/etc')
|
||||||
await arun_command([
|
await arun_command([
|
||||||
'cp', '-aT', f'{source}/etc/apt', f'{target}/etc/apt',
|
'cp', '-aT', f'{source}/etc/apt', f'{target}/etc/apt',
|
||||||
|
@ -192,7 +267,10 @@ class DryRunAptConfigurer(AptConfigurer):
|
||||||
if os.path.isdir(f'{target}/etc/apt/sources.list.d'):
|
if os.path.isdir(f'{target}/etc/apt/sources.list.d'):
|
||||||
shutil.rmtree(f'{target}/etc/apt/sources.list.d')
|
shutil.rmtree(f'{target}/etc/apt/sources.list.d')
|
||||||
os.mkdir(f'{target}/etc/apt/sources.list.d')
|
os.mkdir(f'{target}/etc/apt/sources.list.d')
|
||||||
return 'u+' + target
|
return OverlayMountpoint(
|
||||||
|
lowers=[source],
|
||||||
|
mountpoint=target,
|
||||||
|
upperdir=None)
|
||||||
|
|
||||||
async def deconfigure(self, context, target):
|
async def deconfigure(self, context, target):
|
||||||
return
|
return
|
||||||
|
|
|
@ -19,12 +19,11 @@ import os
|
||||||
import re
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
|
|
||||||
from curtin.commands.extract import get_handler_for_source
|
|
||||||
from curtin.commands.install import (
|
from curtin.commands.install import (
|
||||||
ERROR_TARFILE,
|
ERROR_TARFILE,
|
||||||
INSTALL_LOG,
|
INSTALL_LOG,
|
||||||
)
|
)
|
||||||
from curtin.util import sanitize_source, write_file
|
from curtin.util import write_file
|
||||||
|
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
|
@ -40,7 +39,6 @@ from subiquity.common.types import (
|
||||||
from subiquity.journald import (
|
from subiquity.journald import (
|
||||||
journald_listen,
|
journald_listen,
|
||||||
)
|
)
|
||||||
from subiquity.server.apt import get_apt_configurer
|
|
||||||
from subiquity.server.controller import (
|
from subiquity.server.controller import (
|
||||||
SubiquityController,
|
SubiquityController,
|
||||||
)
|
)
|
||||||
|
@ -80,7 +78,6 @@ class InstallController(SubiquityController):
|
||||||
self.unattended_upgrades_cmd = None
|
self.unattended_upgrades_cmd = None
|
||||||
self.unattended_upgrades_ctx = None
|
self.unattended_upgrades_ctx = None
|
||||||
self.tb_extractor = TracebackExtractor()
|
self.tb_extractor = TracebackExtractor()
|
||||||
self.apt_configurer = None
|
|
||||||
|
|
||||||
def interactive(self):
|
def interactive(self):
|
||||||
return True
|
return True
|
||||||
|
@ -129,7 +126,9 @@ class InstallController(SubiquityController):
|
||||||
@with_context(
|
@with_context(
|
||||||
description="configuring apt", level="INFO", childlevel="DEBUG")
|
description="configuring apt", level="INFO", childlevel="DEBUG")
|
||||||
async def configure_apt(self, *, context):
|
async def configure_apt(self, *, context):
|
||||||
return await self.apt_configurer.configure(context)
|
mirror = self.app.controllers.Mirror
|
||||||
|
configurer = await mirror.wait_config()
|
||||||
|
return await configurer.configure_for_install(context)
|
||||||
|
|
||||||
@with_context(
|
@with_context(
|
||||||
description="installing system", level="INFO", childlevel="DEBUG")
|
description="installing system", level="INFO", childlevel="DEBUG")
|
||||||
|
@ -157,16 +156,6 @@ class InstallController(SubiquityController):
|
||||||
|
|
||||||
self.app.update_state(ApplicationState.RUNNING)
|
self.app.update_state(ApplicationState.RUNNING)
|
||||||
|
|
||||||
handler = get_handler_for_source(
|
|
||||||
sanitize_source(self.model.source.get_source()))
|
|
||||||
|
|
||||||
if self.app.opts.dry_run:
|
|
||||||
path = '/'
|
|
||||||
else:
|
|
||||||
path = handler.setup()
|
|
||||||
|
|
||||||
self.apt_configurer = get_apt_configurer(self.app, path)
|
|
||||||
|
|
||||||
for_install_path = await self.configure_apt(context=context)
|
for_install_path = await self.configure_apt(context=context)
|
||||||
|
|
||||||
if os.path.exists(self.model.target):
|
if os.path.exists(self.model.target):
|
||||||
|
@ -231,7 +220,8 @@ class InstallController(SubiquityController):
|
||||||
|
|
||||||
@with_context(description="restoring apt configuration")
|
@with_context(description="restoring apt configuration")
|
||||||
async def restore_apt_config(self, context):
|
async def restore_apt_config(self, context):
|
||||||
await self.apt_configurer.deconfigure(context, self.tpath())
|
configurer = self.app.controllers.Mirror.apt_configurer
|
||||||
|
await configurer.deconfigure(context, self.tpath())
|
||||||
|
|
||||||
@with_context(description="downloading and installing {policy} updates")
|
@with_context(description="downloading and installing {policy} updates")
|
||||||
async def run_unattended_upgrades(self, context, policy):
|
async def run_unattended_upgrades(self, context, policy):
|
||||||
|
|
|
@ -20,9 +20,11 @@ from typing import List
|
||||||
|
|
||||||
from curtin.config import merge_config
|
from curtin.config import merge_config
|
||||||
|
|
||||||
|
from subiquitycore.async_helpers import SingleInstanceTask
|
||||||
from subiquitycore.context import with_context
|
from subiquitycore.context import with_context
|
||||||
|
|
||||||
from subiquity.common.apidef import API
|
from subiquity.common.apidef import API
|
||||||
|
from subiquity.server.apt import get_apt_configurer
|
||||||
from subiquity.server.controller import SubiquityController
|
from subiquity.server.controller import SubiquityController
|
||||||
from subiquity.server.types import InstallerChannels
|
from subiquity.server.types import InstallerChannels
|
||||||
|
|
||||||
|
@ -57,7 +59,14 @@ class MirrorController(SubiquityController):
|
||||||
super().__init__(app)
|
super().__init__(app)
|
||||||
self.geoip_enabled = True
|
self.geoip_enabled = True
|
||||||
self.app.hub.subscribe(InstallerChannels.GEOIP, self.on_geoip)
|
self.app.hub.subscribe(InstallerChannels.GEOIP, self.on_geoip)
|
||||||
|
self.app.hub.subscribe(
|
||||||
|
(InstallerChannels.CONFIGURED, 'source'), self.on_source)
|
||||||
self.cc_event = asyncio.Event()
|
self.cc_event = asyncio.Event()
|
||||||
|
self.configured_once = True
|
||||||
|
self._apt_config_key = None
|
||||||
|
self._apply_apt_config_task = SingleInstanceTask(
|
||||||
|
self._apply_apt_config)
|
||||||
|
self.apt_configurer = None
|
||||||
|
|
||||||
def load_autoinstall_data(self, data):
|
def load_autoinstall_data(self, data):
|
||||||
if data is None:
|
if data is None:
|
||||||
|
@ -81,6 +90,10 @@ class MirrorController(SubiquityController):
|
||||||
self.model.set_country(self.app.geoip.countrycode)
|
self.model.set_country(self.app.geoip.countrycode)
|
||||||
self.cc_event.set()
|
self.cc_event.set()
|
||||||
|
|
||||||
|
def on_source(self):
|
||||||
|
if self.configured_once:
|
||||||
|
self._apply_apt_config_task.start_sync()
|
||||||
|
|
||||||
def serialize(self):
|
def serialize(self):
|
||||||
return self.model.get_mirror()
|
return self.model.get_mirror()
|
||||||
|
|
||||||
|
@ -92,6 +105,22 @@ class MirrorController(SubiquityController):
|
||||||
r['geoip'] = self.geoip_enabled
|
r['geoip'] = self.geoip_enabled
|
||||||
return r
|
return r
|
||||||
|
|
||||||
|
async def configured(self):
|
||||||
|
await super().configured()
|
||||||
|
self.configured_once = True
|
||||||
|
self._apply_apt_config_task.start_sync()
|
||||||
|
|
||||||
|
async def _apply_apt_config(self):
|
||||||
|
if self.apt_configurer is not None:
|
||||||
|
self.apt_configurer.cleanup()
|
||||||
|
self.apt_configurer = get_apt_configurer(
|
||||||
|
self.app, self.app.controllers.Source.source_path)
|
||||||
|
await self.apt_configurer.apply_apt_config(self.context)
|
||||||
|
|
||||||
|
async def wait_config(self):
|
||||||
|
await self._apply_apt_config_task.wait()
|
||||||
|
return self.apt_configurer
|
||||||
|
|
||||||
async def GET(self) -> str:
|
async def GET(self) -> str:
|
||||||
return self.model.get_mirror()
|
return self.model.get_mirror()
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,9 @@
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
from curtin.commands.extract import get_handler_for_source
|
||||||
|
from curtin.util import sanitize_source
|
||||||
|
|
||||||
from subiquity.common.apidef import API
|
from subiquity.common.apidef import API
|
||||||
from subiquity.common.types import (
|
from subiquity.common.types import (
|
||||||
SourceSelection,
|
SourceSelection,
|
||||||
|
@ -48,6 +51,11 @@ class SourceController(SubiquityController):
|
||||||
|
|
||||||
endpoint = API.source
|
endpoint = API.source
|
||||||
|
|
||||||
|
def __init__(self, app):
|
||||||
|
super().__init__(app)
|
||||||
|
self._handler = None
|
||||||
|
self.source_path = None
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
path = '/cdrom/casper/install-sources.yaml'
|
path = '/cdrom/casper/install-sources.yaml'
|
||||||
if self.app.opts.source_catalog is not None:
|
if self.app.opts.source_catalog is not None:
|
||||||
|
@ -80,6 +88,14 @@ class SourceController(SubiquityController):
|
||||||
self.model.current.id)
|
self.model.current.id)
|
||||||
|
|
||||||
async def configured(self):
|
async def configured(self):
|
||||||
|
if self._handler is not None:
|
||||||
|
self._handler.cleanup()
|
||||||
|
self._handler = get_handler_for_source(
|
||||||
|
sanitize_source(self.model.get_source()))
|
||||||
|
if self.app.opts.dry_run:
|
||||||
|
self.source_path = '/'
|
||||||
|
else:
|
||||||
|
self.source_path = self._handler.setup()
|
||||||
await super().configured()
|
await super().configured()
|
||||||
self.app.base_model.set_source_variant(self.model.current.variant)
|
self.app.base_model.set_source_variant(self.model.current.variant)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue