diff --git a/subiquity/controller.py b/subiquity/controller.py index 78c597d9..dff858b3 100644 --- a/subiquity/controller.py +++ b/subiquity/controller.py @@ -74,6 +74,9 @@ class SubiquityController(BaseController): def deserialize(self, state): self.configured() + def make_autoinstall(self): + return {} + class NoUIController(SubiquityController): @@ -101,3 +104,6 @@ class RepeatedController(RepeatedController): def interactive(self): return self.orig.interactive() + + def make_autoinstall(self): + return {} diff --git a/subiquity/controllers/filesystem.py b/subiquity/controllers/filesystem.py index 9565a74a..3cddbdd1 100644 --- a/subiquity/controllers/filesystem.py +++ b/subiquity/controllers/filesystem.py @@ -695,3 +695,13 @@ class FilesystemController(SubiquityController): fstype="ext4", mount="/", )) + + def make_autoinstall(self): + rendered = self.model.render() + r = { + 'config': rendered['storage']['config'] + } + for k in 'swap', 'grub': + if k in rendered: + r[k] = rendered[k] + return r diff --git a/subiquity/controllers/identity.py b/subiquity/controllers/identity.py index 106d9a77..463434bf 100644 --- a/subiquity/controllers/identity.py +++ b/subiquity/controllers/identity.py @@ -15,6 +15,8 @@ import logging +import attr + from subiquity.controller import SubiquityController from subiquity.ui.views import IdentityView @@ -57,3 +59,8 @@ class IdentityController(SubiquityController): self.model.add_user(user_spec) self.configured() self.app.next_screen() + + def make_autoinstall(self): + r = attr.asdict(self.model.user) + r['hostname'] = self.model.hostname + return r diff --git a/subiquity/controllers/installprogress.py b/subiquity/controllers/installprogress.py index 843d61f3..8543f346 100644 --- a/subiquity/controllers/installprogress.py +++ b/subiquity/controllers/installprogress.py @@ -29,6 +29,7 @@ from curtin.commands.install import ( ERROR_TARFILE, INSTALL_LOG, ) +from curtin.util import write_file from systemd import journal @@ -323,6 +324,11 @@ class InstallProgressController(SubiquityController): @install_step( "final system configuration", level="INFO", childlevel="DEBUG") async def postinstall(self, context): + autoinstall_path = os.path.join( + self.app.root, 'var/log/installer/autoinstall-user-data') + autoinstall_config = "#cloud-config\n" + yaml.dump( + {"autoinstall": self.app.make_autoinstall()}) + write_file(autoinstall_path, autoinstall_config, mode=0o600) await self.configure_cloud_init(context) if self.model.ssh.install_server: await self.install_openssh(context) @@ -401,17 +407,19 @@ class InstallProgressController(SubiquityController): @install_step("copying logs to installed system") async def copy_logs_to_target(self, context): - if self.opts.dry_run: - if 'copy-logs-fail' in self.app.debug_flags: - raise PermissionError() - return + if self.opts.dry_run and 'copy-logs-fail' in self.app.debug_flags: + raise PermissionError() target_logs = self.tpath('var/log/installer') - await arun_command(['cp', '-aT', '/var/log/installer', target_logs]) + if self.opts.dry_run: + os.makedirs(target_logs, exist_ok=True) + else: + await arun_command( + ['cp', '-aT', '/var/log/installer', target_logs]) + journal_txt = os.path.join(target_logs, 'installer-journal.txt') try: - with open(os.path.join(target_logs, - 'installer-journal.txt'), 'w') as output: + with open(journal_txt, 'w') as output: await arun_command( - ['journalctl'], + ['journalctl', '-b'], stdout=output, stderr=subprocess.STDOUT) except Exception: log.exception("saving journal failed") diff --git a/subiquity/controllers/keyboard.py b/subiquity/controllers/keyboard.py index dd7b7078..4eed7169 100644 --- a/subiquity/controllers/keyboard.py +++ b/subiquity/controllers/keyboard.py @@ -15,6 +15,8 @@ import logging +import attr + from subiquitycore.async_helpers import schedule_task from subiquity.controller import SubiquityController @@ -68,3 +70,6 @@ class KeyboardController(SubiquityController): def cancel(self): self.app.prev_screen() + + def make_autoinstall(self): + return attr.asdict(self.model.setting) diff --git a/subiquity/controllers/mirror.py b/subiquity/controllers/mirror.py index 0fe408c5..fed5bda8 100644 --- a/subiquity/controllers/mirror.py +++ b/subiquity/controllers/mirror.py @@ -133,3 +133,8 @@ class MirrorController(SubiquityController): self.model.set_mirror(mirror) self.configured() self.app.next_screen() + + def make_autoinstall(self): + r = self.model.render()['apt'] + r['geoip'] = self.geoip_enabled + return r diff --git a/subiquity/controllers/network.py b/subiquity/controllers/network.py index 5441c4bc..49ff04bb 100644 --- a/subiquity/controllers/network.py +++ b/subiquity/controllers/network.py @@ -25,3 +25,6 @@ class NetworkController(NetworkController, SubiquityController): def done(self): self.configured() super().done() + + def make_autoinstall(self): + return self.model.render()['network'] diff --git a/subiquity/controllers/proxy.py b/subiquity/controllers/proxy.py index d69d0163..d2387490 100644 --- a/subiquity/controllers/proxy.py +++ b/subiquity/controllers/proxy.py @@ -64,3 +64,6 @@ class ProxyController(SubiquityController): self.signal.emit_signal('network-proxy-set') self.configured() self.app.next_screen() + + def make_autoinstall(self): + return self.model.proxy diff --git a/subiquity/controllers/ssh.py b/subiquity/controllers/ssh.py index 368d4f1e..6f499ced 100644 --- a/subiquity/controllers/ssh.py +++ b/subiquity/controllers/ssh.py @@ -126,3 +126,10 @@ class SSHController(SubiquityController): self.model.ssh_import_id = result.get('ssh_import_id', None) self.configured() self.app.next_screen() + + def make_autoinstall(self): + return { + 'install-server': self.model.install_server, + 'authorized-keys': self.model.authorized_keys, + 'allow-pw': self.model.pwauth, + } diff --git a/subiquity/controllers/welcome.py b/subiquity/controllers/welcome.py index cb250c58..7facfac9 100644 --- a/subiquity/controllers/welcome.py +++ b/subiquity/controllers/welcome.py @@ -64,3 +64,6 @@ class WelcomeController(SubiquityController): def deserialize(self, data): super().deserialize(data) self.model.switch_language(data) + + def make_autoinstall(self): + return self.model.selected_language diff --git a/subiquity/core.py b/subiquity/core.py index 0a050feb..8e2c221d 100644 --- a/subiquity/core.py +++ b/subiquity/core.py @@ -308,3 +308,11 @@ class Subiquity(Application): return self.ui.body.show_stretchy_overlay( ErrorReportStretchy(self, self.ui.body, report)) + + def make_autoinstall(self): + config = {} + for controller in self.controllers.instances: + controller_conf = controller.make_autoinstall() + if controller_conf: + config[controller.autoinstall_key] = controller_conf + return config