Skip to content

Commit df36b2c

Browse files
committed
Use a power button listener service to watch /dev/input/eventX to sense power button press
As the hardened image lacks `systemd-logind`, the new service, power button listener, takes the responsibility of watching /dev/input/eventX which was previously done by `logind`. When it detects a power button press, or VM stop, it triggers systemd to stop services, including the listener itself. Then, it uses the service's ExecStop script to send SIGTERM to all containers.
1 parent 05d5f31 commit df36b2c

12 files changed

Lines changed: 285 additions & 49 deletions

File tree

launcher/cloudbuild.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ steps:
7272
export CGO_LDFLAGS="-L/workspace/keymanager/target/release"
7373
go build -o ../image/launcher -ldflags="-extldflags=-Wl,-z,lazy -X 'main.BuildCommit=${SHORT_SHA}'"
7474
75+
# Build the power button listener
76+
cd /workspace/launcher/power-button-listener
77+
go build -o /workspace/launcher/image/power-button-listener
78+
7579
- name: 'gcr.io/cloud-builders/gcloud'
7680
id: DownloadExpBinary
7781
entrypoint: 'gcloud'

launcher/image/container-cleanup.service

Lines changed: 0 additions & 16 deletions
This file was deleted.

launcher/image/container-cleanup.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
#!/bin/bash
2+
echo "Container cleanup script started"
23

34
SHUTDOWN_TIMEOUT_SEC=15
45

56
# Send SIGTERM to all running workloads so that they can shutdown gracefully.
67
for ns in $(ctr ns ls -q); do
78
tasks=$(ctr -n "$ns" task ls -q)
8-
9+
910
if [ -n "$tasks" ]; then
1011
# Send SIGTERM and move on. No waiting, no killing, no deleting.
1112
# A workload may decide to ignore or not handle SIGTERM.

launcher/image/entrypoint.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
main() {
44
# Copy service files.
55
cp /usr/share/oem/confidential_space/container-runner.service /etc/systemd/system/container-runner.service
6-
cp /usr/share/oem/confidential_space/container-cleanup.service /etc/systemd/system/container-cleanup.service
6+
cp /usr/share/oem/confidential_space/power-button-listener.service /etc/systemd/system/power-button-listener.service
77
# Override default fluent-bit config.
88
cp /usr/share/oem/confidential_space/fluent-bit-cs.conf /etc/fluent-bit/fluent-bit.conf
99

@@ -16,8 +16,8 @@ main() {
1616
# Override default kernel-monitor.json for node-problem-detector.
1717
cp /usr/share/oem/confidential_space/kernel-monitor-cs.json /etc/node_problem_detector/kernel-monitor.json
1818
systemctl daemon-reload
19-
systemctl enable container-runner.service container-cleanup.service
20-
systemctl start container-runner.service container-cleanup.service
19+
systemctl enable container-runner.service power-button-listener.service
20+
systemctl start container-runner.service power-button-listener.service
2121
systemctl start fluent-bit.service
2222
}
2323

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
[Unit]
2+
Description=Power Button Listener
3+
After=containerd.service container-runner.service
4+
5+
[Service]
6+
Type=simple
7+
ExecStart=/usr/share/oem/confidential_space/power-button-listener
8+
ExecStop=/usr/share/oem/confidential_space/container-cleanup.sh
9+
Restart=on-failure
10+
RestartSec=5
11+
TTYPath=/dev/ttyS0
12+
StandardOutput=tty
13+
StandardError=tty
14+
15+
[Install]
16+
WantedBy=basic.target

launcher/image/preload.sh

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@ setup_launcher_systemd_unit() {
1919
cp exit_script.sh "${CS_PATH}/exit_script.sh"
2020
}
2121

22-
setup_container_cleanup_service() {
23-
cp container-cleanup.service "${CS_PATH}/container-cleanup.service"
22+
copy_power_button_listener() {
23+
cp power-button-listener "${CS_PATH}/power-button-listener"
24+
cp power-button-listener.service "${CS_PATH}/power-button-listener.service"
2425
cp container-cleanup.sh "${CS_PATH}/container-cleanup.sh"
2526
}
2627

@@ -118,8 +119,8 @@ main() {
118119
# Install container launcher.
119120
copy_launcher
120121
setup_launcher_systemd_unit
121-
# Install container cleanup service.
122-
setup_container_cleanup_service
122+
# Install power button listener.
123+
copy_power_button_listener
123124
# Minimum required COS version for 'e': cos-dev-105-17222-0-0.
124125
# Minimum required COS version for 'm': cos-dev-113-18203-0-0.
125126
append_cmdline "cos.protected_stateful_partition=m"

launcher/image/test/scripts/test_workload_cleanup.sh

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,31 @@ check_timeout() {
1919
echo $remaining
2020
}
2121

22-
echo "Polling for heartbeat..."
22+
echo "Starting to tail serial port in background..."
23+
gcloud compute instances tail-serial-port-output $MONITOR_VM --zone $ZONE > /workspace/serial_output.txt &
24+
TAIL_PID=$!
25+
26+
# Give gcloud a few seconds to establish the connection
27+
sleep 5
28+
29+
echo "Polling for heartbeat (Workload: $WORKLOAD_VM, Monitor: $MONITOR_VM)..."
2330
remaining=$(check_timeout "Timeout before heartbeat poll")
24-
timeout $remaining \
25-
gcloud compute instances tail-serial-port-output $MONITOR_VM --zone $ZONE | \
26-
grep -q 'Workload heartbeat' || \
27-
{ echo "failed: Heartbeat not found within timeout" > /workspace/status.txt; exit 0; }
31+
timeout $remaining bash -c "until grep -q 'Workload heartbeat' /workspace/serial_output.txt; do sleep 1; done" || {
32+
echo "failed: Heartbeat not found within timeout" > /workspace/status.txt
33+
kill $TAIL_PID
34+
exit 0
35+
}
2836

2937
echo "Stopping workload VM..."
3038
gcloud compute instances stop $WORKLOAD_VM --zone $ZONE
3139

3240
echo "Polling for graceful exit..."
3341
remaining=$(check_timeout "Timeout before graceful exit poll")
34-
timeout $remaining \
35-
gcloud compute instances tail-serial-port-output $MONITOR_VM --zone $ZONE | \
36-
grep -q 'Workload exiting gracefully' || \
37-
{ echo "failed: Graceful exit message not found within timeout" > /workspace/status.txt; exit 0; }
42+
timeout $remaining bash -c "until grep -q 'Workload exiting gracefully' /workspace/serial_output.txt; do sleep 1; done" || {
43+
echo "failed: Graceful exit message not found within timeout" > /workspace/status.txt
44+
kill $TAIL_PID
45+
exit 0
46+
}
47+
48+
# Success! Clean up the background process
49+
kill $TAIL_PID

launcher/image/test/test_workloadcleanup_cloudbuild.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ substitutions:
1010
'_IMAGE_PROJECT': ''
1111
'_CLEANUP': 'true'
1212
'_IMAGE_REPO': 'us-west1-docker.pkg.dev/confidential-space-images-dev/cs-integ-test-images'
13-
'_WORKLOAD_IMAGE': '${_IMAGE_REPO}/workloadcleanup/workload:latest'
13+
'_WORKLOAD_IMAGE': '${_IMAGE_REPO}/workloadcleanup:latest'
1414
'_ZONE': 'us-west1-a'
1515

1616
steps:
@@ -68,7 +68,7 @@ steps:
6868
MONITOR_IP=$(cat /workspace/monitor_ip.txt)
6969
bash create_vm.sh -i $IMAGE_NAME \
7070
-p $IMAGE_PROJECT \
71-
-m "tee-image-reference=$WORKLOAD_IMAGE,tee-container-log-redirect=true,tee-cmd=[\"--server-addr=${MONITOR_IP}:2020\"]" \
71+
-m "tee-image-reference=$WORKLOAD_IMAGE,tee-cmd=[\"--server-addr=${MONITOR_IP}:2020\"]" \
7272
-n cleanup-test-$BUILD_ID \
7373
-z $ZONE
7474

launcher/image/testworkloads/workloadcleanup/workload/Dockerfile renamed to launcher/image/testworkloads/workloadcleanup/Dockerfile

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
# From current directory:
22
# GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o main .
3-
# gcloud builds submit --tag us-west1-docker.pkg.dev/confidential-space-images-dev/cs-integ-test-images/workloadcleanup/workload:latest
3+
# gcloud builds submit --tag us-west1-docker.pkg.dev/confidential-space-images-dev/cs-integ-test-images/workloadcleanup:latest
44

55
FROM alpine
66

77
COPY main /
88

9-
LABEL "tee.launch_policy.log_redirect"="always"
109
LABEL "tee.launch_policy.allow_cmd_override"="true"
1110

1211
ENTRYPOINT ["/main"]

launcher/image/testworkloads/workloadcleanup/workload/main.go renamed to launcher/image/testworkloads/workloadcleanup/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Package main provides a test workload for cleanup.
1+
// A test workload for testing workload cleanup.
22
package main
33

44
import (

0 commit comments

Comments
 (0)