Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Write /etc/environment before the lingering session is started #362

Merged
merged 3 commits into from
Nov 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions hack/test-example.sh
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ function diagnose() {
set +x -e
}

export ftp_proxy=http://localhost:2121

INFO "Starting \"$NAME\" from \"$FILE\""
defer "limactl delete -f \"$NAME\""
set -x
Expand All @@ -106,6 +108,17 @@ limactl shell "$NAME" uname -a
limactl shell "$NAME" cat /etc/os-release
set +x

INFO "Testing proxy settings are imported"
got=$(limactl shell "$NAME" env | grep FTP_PROXY)
# Expected: FTP_PROXY is set in addition to ftp_proxy, localhost is replaced
# by the gateway address, and the value is set immediately without a restart
expected="FTP_PROXY=http://192.168.5.2:2121"
INFO "FTP_PROXY: expected=${expected} got=${got}"
if [ "$got" != "$expected" ]; then
ERROR "proxy environment variable not set to correct value"
exit 1
fi

INFO "Testing limactl copy command"
tmpfile="$HOME/lima-hostname"
rm -f "$tmpfile"
Expand Down Expand Up @@ -212,9 +225,19 @@ if [[ -n ${CHECKS["restart"]} ]]; then
limactl stop "$NAME"
sleep 3

export ftp_proxy=my.proxy:8021
INFO "Restarting \"$NAME\""
limactl start "$NAME"

INFO "Make sure proxy setting is updated"
got=$(limactl shell "$NAME" env | grep FTP_PROXY)
expected="FTP_PROXY=my.proxy:8021"
INFO "FTP_PROXY: expected=${expected} got=${got}"
if [ "$got" != "$expected" ]; then
ERROR "proxy environment variable not set to correct value"
exit 1
fi

# shellcheck disable=SC2016
if ! limactl shell "$NAME" sh -c 'test -f $HOME/sweet-home'; then
ERROR "Guest home directory does not persist across restarts"
Expand Down
15 changes: 7 additions & 8 deletions pkg/cidata/cidata.TEMPLATE.d/boot.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ done <"${LIMA_CIDATA_MNT}"/etc_environment

CODE=0

# Don't make any changes to /etc or /var/lib until the boot/* scripts have run
# because they might move the directories to /mnt/data on first boot, so changes
# made on restart would be lost.
# Don't make any changes to /etc or /var/lib until boot/05-persistent-data-volume.sh
# has run because it might move the directories to /mnt/data on first boot. In that
# case changes made on restart would be lost.

for f in "${LIMA_CIDATA_MNT}"/boot/*; do
INFO "Executing $f"
Expand All @@ -31,11 +31,6 @@ for f in "${LIMA_CIDATA_MNT}"/boot/*; do
fi
done

if [ -e /etc/environment ]; then
sed -i '/#LIMA-START/,/#LIMA-END/d' /etc/environment
fi
cat "${LIMA_CIDATA_MNT}/etc_environment" >>/etc/environment

if [ -d "${LIMA_CIDATA_MNT}"/provision.system ]; then
for f in "${LIMA_CIDATA_MNT}"/provision.system/*; do
INFO "Executing $f"
Expand Down Expand Up @@ -64,5 +59,9 @@ if [ -d "${LIMA_CIDATA_MNT}"/provision.user ]; then
done
fi

# Signal that provisioning is done. The instance-id in the meta-data file changes on every boot,
# so any copy from a previous boot cycle will have different content.
cp "${LIMA_CIDATA_MNT}"/meta-data /run/lima-boot-done

INFO "Exiting with code $CODE"
exit "$CODE"
25 changes: 25 additions & 0 deletions pkg/cidata/cidata.TEMPLATE.d/boot/07-etc-environment.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/bin/sh
set -eux

# /etc/environment must be written after 05-persistent-data-volume.sh has run to
# make sure the changes on a restart are applied to the persisted version.

if [ -e /etc/environment ]; then
sed -i '/#LIMA-START/,/#LIMA-END/d' /etc/environment
fi
cat "${LIMA_CIDATA_MNT}/etc_environment" >>/etc/environment

# It is possible that a requirements script has started an ssh session before
# /etc/environment was updated, so we need to kill it to make sure it will
# restart with the updated environment before "linger" is being enabled.

if command -v loginctl >/dev/null 2>&1; then
loginctl terminate-user "${LIMA_CIDATA_USER}" || true
fi

# Make sure the guestagent socket from a previous boot is removed before we open the "lima-ssh-ready" gate.
rm -f /run/lima-guest-agent.sock

# Signal that provisioning is done. The instance-id in the meta-data file changes on every boot,
# so any copy from a previous boot cycle will have different content.
cp "${LIMA_CIDATA_MNT}"/meta-data /run/lima-ssh-ready
2 changes: 1 addition & 1 deletion pkg/cidata/cidata.TEMPLATE.d/boot/30-install-packages.sh
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ if [ -n "${LIMA_CIDATA_TCP_DNS_LOCAL_PORT}" ] && [ "${LIMA_CIDATA_TCP_DNS_LOCAL_
fi
if [ "${SETUP_DNS}" = 1 ]; then
# Try to setup iptables rule again, in case we just installed iptables
"${LIMA_CIDATA_MNT}/boot/07-host-dns-setup.sh"
"${LIMA_CIDATA_MNT}/boot/09-host-dns-setup.sh"
fi

# update_fuse_conf has to be called after installing all the packages,
Expand Down
3 changes: 3 additions & 0 deletions pkg/hostagent/hostagent.go
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,9 @@ func (a *HostAgent) startHostAgentRoutines(ctx context.Context) error {
if err := a.waitForRequirements(ctx, "optional", a.optionalRequirements()); err != nil {
mErr = multierror.Append(mErr, err)
}
if err := a.waitForRequirements(ctx, "final", a.finalRequirements()); err != nil {
mErr = multierror.Append(mErr, err)
}
return mErr
}

Expand Down
47 changes: 42 additions & 5 deletions pkg/hostagent/requirements.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,16 +60,33 @@ type requirement struct {

func (a *HostAgent) essentialRequirements() []requirement {
req := make([]requirement, 0)
req = append(req, requirement{
description: "ssh",
script: `#!/bin/bash
req = append(req,
requirement{
description: "ssh",
script: `#!/bin/bash
true
`,
debugHint: `Failed to SSH into the guest.
debugHint: `Failed to SSH into the guest.
Make sure that the YAML field "ssh.localPort" is not used by other processes on the host.
If any private key under ~/.ssh is protected with a passphrase, you need to have ssh-agent to be running.
`,
})
},
requirement{
description: "user session is ready for ssh",
script: `#!/bin/bash
set -eux -o pipefail
if ! timeout 30s bash -c "until sudo diff -q /run/lima-ssh-ready /mnt/lima-cidata/meta-data 2>/dev/null; do sleep 3; done"; then
echo >&2 "not ready to start persistent ssh session"
exit 1
fi
`,
debugHint: `The boot sequence will terminate any existing user session after updating
/etc/environment to make sure the session includes the new values.
Terminating the session will break the persistent SSH tunnel, so
it must not be created until the session reset is done.
`,
})

if len(a.y.Mounts) > 0 {
req = append(req, requirement{
description: "sshfs binary to be installed",
Expand Down Expand Up @@ -164,3 +181,23 @@ Also see "/var/log/cloud-init-output.log" in the guest.
}
return req
}

func (a *HostAgent) finalRequirements() []requirement {
req := make([]requirement, 0)
req = append(req,
requirement{
description: "boot scripts must have finished",
script: `#!/bin/bash
set -eux -o pipefail
if ! timeout 30s bash -c "until sudo diff -q /run/lima-boot-done /mnt/lima-cidata/meta-data 2>/dev/null; do sleep 3; done"; then
echo >&2 "boot scripts have not finished"
exit 1
fi
`,
debugHint: `All boot scripts, provisioning scripts, and readiness probes must
finish before the instance is considered "ready".
Check "/var/log/cloud-init-output.log" in the guest to see where the process is blocked!
`,
})
return req
}