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:
parent
96c0c91d8a
commit
67102261c3
|
@ -24,7 +24,7 @@ import pathlib
|
||||||
import platform
|
import platform
|
||||||
import tempfile
|
import tempfile
|
||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
from typing import List, Optional, Set, Union
|
from typing import List, Optional, Set, Tuple, Union
|
||||||
|
|
||||||
import attr
|
import attr
|
||||||
import more_itertools
|
import more_itertools
|
||||||
|
@ -2039,10 +2039,11 @@ class FilesystemModel(object):
|
||||||
self._actions.append(zpool)
|
self._actions.append(zpool)
|
||||||
return zpool
|
return zpool
|
||||||
|
|
||||||
async def live_packages(self):
|
async def live_packages(self) -> Tuple[Set, Set]:
|
||||||
r = []
|
before = set()
|
||||||
if self.reset_partition is not None:
|
during = set()
|
||||||
r.append("efibootmgr")
|
|
||||||
if self._one(type="zpool") is not None:
|
if self._one(type="zpool") is not None:
|
||||||
r.append("zfsutils-linux")
|
before.add("zfsutils-linux")
|
||||||
return r
|
if self.reset_partition is not None:
|
||||||
|
during.add("efibootmgr")
|
||||||
|
return (before, during)
|
||||||
|
|
|
@ -20,7 +20,7 @@ import logging
|
||||||
import os
|
import os
|
||||||
import uuid
|
import uuid
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from typing import Any, Dict, Set
|
from typing import Any, Dict, Set, Tuple
|
||||||
|
|
||||||
import yaml
|
import yaml
|
||||||
from cloudinit.config.schema import (
|
from cloudinit.config.schema import (
|
||||||
|
@ -390,13 +390,20 @@ class SubiquityModel:
|
||||||
packages.extend(await meth())
|
packages.extend(await meth())
|
||||||
return packages
|
return packages
|
||||||
|
|
||||||
async def live_packages(self):
|
async def live_packages(self) -> Tuple[Set, Set]:
|
||||||
packages = []
|
"""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():
|
for model_name in self._install_model_names.all():
|
||||||
meth = getattr(getattr(self, model_name), "live_packages", None)
|
meth = getattr(getattr(self, model_name), "live_packages", None)
|
||||||
if meth is not None:
|
if meth is not None:
|
||||||
packages.extend(await meth())
|
packages = await meth()
|
||||||
return packages
|
before |= packages[0]
|
||||||
|
during |= packages[1]
|
||||||
|
return (before, during)
|
||||||
|
|
||||||
def _cloud_init_files(self):
|
def _cloud_init_files(self):
|
||||||
# TODO, this should be moved to the in-target cloud-config seed so on
|
# TODO, this should be moved to the in-target cloud-config seed so on
|
||||||
|
|
|
@ -1526,3 +1526,35 @@ class TestRootfs(SubiTestCase):
|
||||||
m = make_model()
|
m = make_model()
|
||||||
make_zpool(model=m, mountpoint="/srv")
|
make_zpool(model=m, mountpoint="/srv")
|
||||||
self.assertFalse(m.is_root_mounted())
|
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)
|
||||||
|
|
|
@ -597,10 +597,18 @@ class InstallController(SubiquityController):
|
||||||
with open(self.tpath("etc/fstab"), "w") as fp:
|
with open(self.tpath("etc/fstab"), "w") as fp:
|
||||||
fp.write("/run/mnt/ubuntu-boot/EFI/ubuntu /boot/grub none bind\n")
|
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):
|
async def install_live_packages(self, *, context):
|
||||||
for package in await self.model.live_packages():
|
before, during = await self.model.live_packages()
|
||||||
await self.app.package_installer.install_pkg(package)
|
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()
|
@with_context()
|
||||||
async def install(self, *, context):
|
async def install(self, *, context):
|
||||||
|
@ -632,7 +640,7 @@ class InstallController(SubiquityController):
|
||||||
fsc = self.app.controllers.Filesystem
|
fsc = self.app.controllers.Filesystem
|
||||||
for_install_path = self.model.source.get_source(fsc._info.name)
|
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 self.model.target is not None:
|
||||||
if os.path.exists(self.model.target):
|
if os.path.exists(self.model.target):
|
||||||
|
|
Loading…
Reference in New Issue