hooks: execute hook scripts as builtin late commands

When executing late commands, we now start by executing run-parts over
the /etc/subiquity/postinst.d directory (by default) if it exists.

A failure in run-parts is not considered critical so any other
late_commands will run no matter what.

Signed-off-by: Olivier Gayot <olivier.gayot@canonical.com>
This commit is contained in:
Olivier Gayot 2022-08-08 15:03:52 +02:00
parent e33640371b
commit 34d4acd264
4 changed files with 58 additions and 2 deletions

View File

@ -7,7 +7,8 @@ PYTHONPATH=$(shell pwd):$(shell pwd)/probert:$(shell pwd)/curtin
PROBERTDIR=./probert PROBERTDIR=./probert
PROBERT_REPO=https://github.com/canonical/probert PROBERT_REPO=https://github.com/canonical/probert
DRYRUN?=--dry-run --bootloader uefi --machine-config examples/simple.json \ DRYRUN?=--dry-run --bootloader uefi --machine-config examples/simple.json \
--source-catalog examples/install-sources.yaml --source-catalog examples/install-sources.yaml \
--postinst-hooks-dir examples/postinst.d/
SYSTEM_SETUP_DRYRUN?=--dry-run SYSTEM_SETUP_DRYRUN?=--dry-run
export PYTHONPATH export PYTHONPATH
CWD := $(shell pwd) CWD := $(shell pwd)

View File

@ -0,0 +1,35 @@
#!/bin/bash
prefix="$TARGET_MOUNT_POINT"/etc/NetworkManager/system-connections
echo "Copying NM connections to target"
mkdir --parents -- "$prefix"
cat > "$prefix"/subiquity-test.nmconnection << EOF
[connection]
id=Subiquity Test
uuid=5bbf9dda-f3a9-4967-970e-aba55c8b18f0
type=wifi
interface-name=wlp0s20f3
permissions=
[wifi]
mode=infrastructure
ssid=TestConnection-5G
[wifi-security]
auth-alg=open
key-mgmt=wpa-psk
psk=nCjIqJ4G
[ipv4]
dns-search=
method=auto
[ipv6]
addr-gen-mode=stable-privacy
dns-search=
method=auto
[proxy]
EOF

View File

@ -16,6 +16,7 @@
import argparse import argparse
import logging import logging
import os import os
import pathlib
import shlex import shlex
import sys import sys
@ -104,6 +105,9 @@ def make_server_args_parser():
'--storage-version', action='store', type=int) '--storage-version', action='store', type=int)
parser.add_argument( parser.add_argument(
'--use-os-prober', action='store_true', default=False) '--use-os-prober', action='store_true', default=False)
parser.add_argument(
'--postinst-hooks-dir', default='/etc/subiquity/postinst.d',
type=pathlib.Path)
return parser return parser

View File

@ -57,6 +57,7 @@ class CmdListController(NonInteractiveController):
'items': {'type': 'string'}, 'items': {'type': 'string'},
}, },
} }
builtin_cmds: Sequence[Command] = ()
cmds: Sequence[Command] = () cmds: Sequence[Command] = ()
cmd_check = True cmd_check = True
syslog_id = None syslog_id = None
@ -74,7 +75,7 @@ class CmdListController(NonInteractiveController):
@with_context() @with_context()
async def run(self, context): async def run(self, context):
env = self.env() env = self.env()
for i, cmd in enumerate(self.cmds): for i, cmd in enumerate(tuple(self.builtin_cmds) + tuple(self.cmds)):
desc = cmd.desc() desc = cmd.desc()
with context.child("command_{}".format(i), desc): with context.child("command_{}".format(i), desc):
args = cmd.as_args_list() args = cmd.as_args_list()
@ -109,6 +110,21 @@ class LateController(CmdListController):
super().__init__(app) super().__init__(app)
self.syslog_id = app.log_syslog_id self.syslog_id = app.log_syslog_id
try:
hooks_dir = self.app.opts.postinst_hooks_dir
except AttributeError:
# NOTE: system_setup imports this controller ; but does not use the
# postinst hooks mechanism.
pass
else:
if hooks_dir.is_dir():
self.builtin_cmds = [
Command(
args=["run-parts", "--debug", "--", str(hooks_dir)],
check=False,
),
]
def env(self): def env(self):
env = super().env() env = super().env()
env['TARGET_MOUNT_POINT'] = self.app.base_model.target env['TARGET_MOUNT_POINT'] = self.app.base_model.target