install: live pkgs can be installed in parallel

Split packages that must be done early from ones that can be done
in parallel with early install steps.
This commit is contained in:
Dan Bungert 2023-08-28 10:12:09 -06:00
parent 96c0c91d8a
commit 67102261c3
4 changed files with 64 additions and 16 deletions

View File

@ -24,7 +24,7 @@ import pathlib
import platform
import tempfile
from abc import ABC, abstractmethod
from typing import List, Optional, Set, Union
from typing import List, Optional, Set, Tuple, Union
import attr
import more_itertools
@ -2039,10 +2039,11 @@ class FilesystemModel(object):
self._actions.append(zpool)
return zpool
async def live_packages(self):
r = []
if self.reset_partition is not None:
r.append("efibootmgr")
async def live_packages(self) -> Tuple[Set, Set]:
before = set()
during = set()
if self._one(type="zpool") is not None:
r.append("zfsutils-linux")
return r
before.add("zfsutils-linux")
if self.reset_partition is not None:
during.add("efibootmgr")
return (before, during)

View File

@ -20,7 +20,7 @@ import logging
import os
import uuid
from collections import OrderedDict
from typing import Any, Dict, Set
from typing import Any, Dict, Set, Tuple
import yaml
from cloudinit.config.schema import (
@ -390,13 +390,20 @@ class SubiquityModel:
packages.extend(await meth())
return packages
async def live_packages(self):
packages = []
async def live_packages(self) -> Tuple[Set, Set]:
"""return a tuple of sets of packages to install into the live environment.
The first set must be installed before partitioning, the second set may be
allowed to run in parallel with partitioning.
"""
before = set()
during = set()
for model_name in self._install_model_names.all():
meth = getattr(getattr(self, model_name), "live_packages", None)
if meth is not None:
packages.extend(await meth())
return packages
packages = await meth()
before |= packages[0]
during |= packages[1]
return (before, during)
def _cloud_init_files(self):
# TODO, this should be moved to the in-target cloud-config seed so on

View File

@ -1526,3 +1526,35 @@ class TestRootfs(SubiTestCase):
m = make_model()
make_zpool(model=m, mountpoint="/srv")
self.assertFalse(m.is_root_mounted())
class TestLivePackages(SubiTestCase):
async def test_defaults(self):
m = make_model()
(before, during) = await m.live_packages()
self.assertEqual(set(), before)
self.assertEqual(set(), during)
async def test_zfs(self):
m = make_model()
make_zpool(model=m, mountpoint="/")
(before, during) = await m.live_packages()
self.assertEqual(set(["zfsutils-linux"]), before)
self.assertEqual(set(), during)
async def test_efibootmgr(self):
m = make_model()
d = make_disk(m)
m.reset_partition = make_partition(m, d)
(before, during) = await m.live_packages()
self.assertEqual(set(), before)
self.assertEqual(set(["efibootmgr"]), during)
async def test_both(self):
m = make_model()
d = make_disk(m)
make_zpool(model=m, mountpoint="/")
m.reset_partition = make_partition(m, d)
(before, during) = await m.live_packages()
self.assertEqual(set(["zfsutils-linux"]), before)
self.assertEqual(set(["efibootmgr"]), during)

View File

@ -597,10 +597,18 @@ class InstallController(SubiquityController):
with open(self.tpath("etc/fstab"), "w") as fp:
fp.write("/run/mnt/ubuntu-boot/EFI/ubuntu /boot/grub none bind\n")
@with_context(description="installing packages to live system")
async def install_live_packages(self, *, context):
for package in await self.model.live_packages():
await self.app.package_installer.install_pkg(package)
before, during = await self.model.live_packages()
if len(before) < 1 and len(during) < 1:
return
with context.child("live-packages", "installing packages to live system"):
for package in before:
state = await self.app.package_installer.install_pkg(package)
if state != PackageInstallState.DONE:
raise RuntimeError(f"could not install {package}")
for package in during:
self.app.package_installer.start_installing_pkg(package)
@with_context()
async def install(self, *, context):
@ -632,7 +640,7 @@ class InstallController(SubiquityController):
fsc = self.app.controllers.Filesystem
for_install_path = self.model.source.get_source(fsc._info.name)
await self.install_live_packages()
await self.install_live_packages(context=context)
if self.model.target is not None:
if os.path.exists(self.model.target):