Skip to content

Commit

Permalink
comments
Browse files Browse the repository at this point in the history
  • Loading branch information
holmanb committed Jul 24, 2024
1 parent 49bebbf commit 40992ea
Show file tree
Hide file tree
Showing 15 changed files with 55 additions and 17 deletions.
9 changes: 7 additions & 2 deletions cloudinit/cmd/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -1151,6 +1151,11 @@ def main(sysv_args=None):
setattr(args, "skip_log_setup", False)
if not args.all_stages:
return sub_main(args)
return all_stages(parser)


def all_stages(parser):
"""Run all stages in a single process using an ordering protocol."""
LOG.info("Running cloud-init in single process mode.")

# this _must_ be called before sd_notify is called otherwise netcat may
Expand All @@ -1167,7 +1172,7 @@ def main(sysv_args=None):
# run local stage
sub_main(args)

# wait for cloud-init.service to start
# wait for cloud-init-network.service to start
with sync("network"):
# skip re-setting up logger
args = parser.parse_args(args=["init"])
Expand All @@ -1191,7 +1196,7 @@ def main(sysv_args=None):
# run final stage
sub_main(args)

# signal completion to cloud-init.service
# signal completion to cloud-init-main.service
if sync.first_exception:
socket.sd_notify(
"STATUS=Completed with failure, first exception received: "
Expand Down
3 changes: 2 additions & 1 deletion cloudinit/cmd/status.py
Original file line number Diff line number Diff line change
Expand Up @@ -318,8 +318,9 @@ def systemd_failed(wait: bool) -> bool:
for service in [
"cloud-final.service",
"cloud-config.service",
"cloud-init.service",
"cloud-init-network.service",
"cloud-init-local.service",
"cloud-init-main.service",
]:
try:
stdout = query_systemctl(
Expand Down
3 changes: 2 additions & 1 deletion cloudinit/config/cc_mounts.py
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,8 @@ def handle(name: str, cfg: Config, cloud: Cloud, args: list) -> None:
uses_systemd = cloud.distro.uses_systemd()
if uses_systemd:
def_mnt_opts = (
"defaults,nofail,x-systemd.after=cloud-init.service,_netdev"
"defaults,nofail,x-systemd.after=cloud-"
"init-network.service,_netdev"
)

defvals = [None, None, "auto", def_mnt_opts, "0", "2"]
Expand Down
4 changes: 2 additions & 2 deletions cloudinit/config/schemas/schema-cloud-config-v1.json
Original file line number Diff line number Diff line change
Expand Up @@ -2017,12 +2017,12 @@
},
"mount_default_fields": {
"type": "array",
"description": "Default mount configuration for any mount entry with less than 6 options provided. When specified, 6 items are required and represent ``/etc/fstab`` entries. Default: ``defaults,nofail,x-systemd.after=cloud-init.service,_netdev``",
"description": "Default mount configuration for any mount entry with less than 6 options provided. When specified, 6 items are required and represent ``/etc/fstab`` entries. Default: ``defaults,nofail,x-systemd.after=cloud-init-network.service,_netdev``",
"default": [
null,
null,
"auto",
"defaults,nofail,x-systemd.after=cloud-init.service",
"defaults,nofail,x-systemd.after=cloud-init-network.service",
"0",
"2"
],
Expand Down
12 changes: 7 additions & 5 deletions cloudinit/socket.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,13 @@ def __enter__(self):
Once the message has been received, enter the context.
"""
if os.isatty(sys.stdin.fileno()):
LOG.info("Not syncing, stdin is a tty.")
LOG.info(
"Stdin is a tty, so skipping stage synchronization protocol"
)
return
sd_notify(
"STATUS=Waiting on external services to "
f"complete ({self.stage} stage)"
f"complete before starting the {self.stage} stage."
)
start_time = time.monotonic()
# block until init system sends us data
Expand All @@ -126,7 +128,7 @@ def __enter__(self):
raise ValueError(f"Unexpected path to unix socket: {self.remote}")

total = time.monotonic() - start_time
time_msg = f"took {total: .3f}s " if total > 0.1 else ""
time_msg = f"took {total: .3f}s to " if total > 0.01 else ""
sd_notify(f"STATUS=Running ({self.stage} stage)")
LOG.debug("sync(%s): synchronization %scomplete", self.stage, time_msg)
return self
Expand All @@ -140,8 +142,8 @@ def __exit__(self, exc_type, exc_val, exc_tb):
systemd_exit_code = "1"
status = f"{repr(exc_val)} in {exc_tb.tb_frame}"
message = (
'fatal error, run "systemctl cloud-init.service" for more '
"details"
'fatal error, run "systemctl status cloud-init-main.service" '
'and "cloud-init status --long" for more details'
)
if not self.first_exception:
self.first_exception = message
Expand Down
7 changes: 7 additions & 0 deletions systemd/cloud-config.service.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ ConditionEnvironment=!KERNEL_CMDLINE=cloud-init=disabled

[Service]
Type=oneshot
# This service is a shim which preserves systemd ordering while allowing a
# single Python process to run cloud-init's logic. This works by communicating
# with the cloud-init process over a unix socket to tell the process that this
# stage can start, and then wait on a return socket until the cloud-init
# process has completed this stage. The output from the return socket is piped
# into a shell so that the process can send a completion message (defaults to
# "done", otherwise includes an error message) and an exit code to systemd.
ExecStart=sh -c 'echo "start" | nc.openbsd -Uu -W1 /run/cloud-init/share/config.sock -s /run/cloud-init/share/config-return.sock | sh'
RemainAfterExit=yes
TimeoutSec=0
Expand Down
7 changes: 7 additions & 0 deletions systemd/cloud-final.service.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@ ConditionEnvironment=!KERNEL_CMDLINE=cloud-init=disabled

[Service]
Type=oneshot
# This service is a shim which preserves systemd ordering while allowing a
# single Python process to run cloud-init's logic. This works by communicating
# with the cloud-init process over a unix socket to tell the process that this
# stage can start, and then wait on a return socket until the cloud-init
# process has completed this stage. The output from the return socket is piped
# into a shell so that the process can send a completion message (defaults to
# "done", otherwise includes an error message) and an exit code to systemd.
ExecStart=sh -c 'echo "start" | nc.openbsd -Uu -W1 /run/cloud-init/share/final.sock -s /run/cloud-init/share/final-return.sock | sh'
RemainAfterExit=yes
TimeoutSec=0
Expand Down
7 changes: 7 additions & 0 deletions systemd/cloud-init-local.service.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ ExecStartPre=/bin/mkdir -p /run/cloud-init
ExecStartPre=/sbin/restorecon /run/cloud-init
ExecStartPre=/usr/bin/touch /run/cloud-init/enabled
{% endif %}
# This service is a shim which preserves systemd ordering while allowing a
# single Python process to run cloud-init's logic. This works by communicating
# with the cloud-init process over a unix socket to tell the process that this
# stage can start, and then wait on a return socket until the cloud-init
# process has completed this stage. The output from the return socket is piped
# into a shell so that the process can send a completion message (defaults to
# "done", otherwise includes an error message) and an exit code to systemd.
ExecStart=sh -c 'echo "start" | nc.openbsd -Uu -W1 /run/cloud-init/share/local.sock -s /run/cloud-init/share/local-return.sock | sh'
RemainAfterExit=yes
TimeoutSec=0
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,13 @@ ConditionEnvironment=!KERNEL_CMDLINE=cloud-init=disabled

[Service]
Type=oneshot
# This service is a shim which preserves systemd ordering while allowing a
# single Python process to run cloud-init's logic. This works by communicating
# with the cloud-init process over a unix socket to tell the process that this
# stage can start, and then wait on a return socket until the cloud-init
# process has completed this stage. The output from the return socket is piped
# into a shell so that the process can send a completion message (defaults to
# "done", otherwise includes an error message) and an exit code to systemd.
ExecStart=sh -c 'echo "start" | nc.openbsd -Uu -W1 /run/cloud-init/share/network.sock -s /run/cloud-init/share/network-return.sock | sh'
RemainAfterExit=yes
TimeoutSec=0
Expand Down
2 changes: 1 addition & 1 deletion tests/integration_tests/assets/enable_coverage.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

services = [
"cloud-init-local.service",
"cloud-init.service",
"cloud-init-network.service",
"cloud-config.service",
"cloud-final.service",
]
Expand Down
2 changes: 1 addition & 1 deletion tests/integration_tests/assets/enable_profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

services = [
"cloud-init-local.service",
"cloud-init.service",
"cloud-init-network.service",
"cloud-config.service",
"cloud-final.service",
]
Expand Down
2 changes: 1 addition & 1 deletion tests/integration_tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ def _collect_profile(instance: IntegrationInstance, log_dir: Path):
log_dir / "profile" / "local.stats",
)
instance.pull_file(
"/var/log/cloud-init.service.stats",
"/var/log/cloud-init-network.service.stats",
log_dir / "profile" / "network.stats",
)
instance.pull_file(
Expand Down
4 changes: 2 additions & 2 deletions tests/integration_tests/datasources/test_nocloud.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ def test_smbios_seed_network(self, client: IntegrationInstance):
"""\
[Unit]
Description=Serve a local webserver
Before=cloud-init.service
Before=cloud-init-network.service
Wants=cloud-init-local.service
DefaultDependencies=no
After=systemd-networkd-wait-online.service
Expand Down Expand Up @@ -353,7 +353,7 @@ def _boot_with_cmdline(
# and NoCloud operates in network timeframe
After=systemd-networkd-wait-online.service
After=networking.service
Before=cloud-init.service
Before=cloud-init-network.service
[Service]
Type=exec
Expand Down
3 changes: 2 additions & 1 deletion tests/unittests/test_all_stages.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ def test_all_stages_exception(tmp_path):
1 / 0 # pylint: disable=W0104

assert (
b'echo \'fatal error, run "systemctl cloud-init.service" for '
b"echo 'fatal error, run \"systemctl status cloud-init-main."
b'service" and "cloud-init status --long" for '
b"more details'; exit 1;" == first.receive()
)

0 comments on commit 40992ea

Please sign in to comment.