Skip to content

Commit

Permalink
Test image export over devlxd socket (#240)
Browse files Browse the repository at this point in the history
Adds tests for the devlxd socket in a container. These tests are based
on the devlxd tests for VMs, with additional testing for image export
over the socket.

Note: I wasn't sure where else to add this test other than in the github
workflow.

Also note: This test will fail on edge until
canonical/lxd#13730 is merged.
  • Loading branch information
tomponline authored Jul 29, 2024
2 parents 99675f0 + f156789 commit 5b45519
Show file tree
Hide file tree
Showing 2 changed files with 138 additions and 0 deletions.
1 change: 1 addition & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ jobs:
- conversion
- cpu-vm
- devlxd-vm
- devlxd-container
- docker
- efi-vars-editor-vm
- interception
Expand Down
137 changes: 137 additions & 0 deletions tests/devlxd-container
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
#!/bin/sh
set -eux

# Install dependencies
install_deps jq

# Install LXD
install_lxd

# Configure LXD
lxc network create lxdbr0
lxc profile device add default eth0 nic network=lxdbr0

poolName="ctpool$$"
poolDriver=dir

echo "==> Create storage pool using driver ${poolDriver}"
lxc storage create "${poolName}" "${poolDriver}"

echo "==> Create container and boot"
lxc launch "${TEST_IMG:-ubuntu-minimal-daily:24.04}" c1 -s "${poolName}" -c security.nesting=true
lxc info c1

echo "==> Checking devlxd is working"

# devlxd is enabled by default and should work
lxc exec c1 -- curl -s --unix-socket /dev/lxd/sock http://custom.socket/1.0 | jq
if hasNeededAPIExtension cloud_init; then
lxc exec c1 -- curl -s --unix-socket /dev/lxd/sock http://custom.socket/1.0/devices | jq
fi
lxc exec c1 -- curl -s --unix-socket /dev/lxd/sock http://custom.socket/1.0/config | jq
lxc exec c1 -- curl -s --unix-socket /dev/lxd/sock http://custom.socket/1.0/meta-data | grep -q '#cloud-config'

# Restart the container
lxc restart -f c1

# devlxd should be running after restart
lxc exec c1 -- curl -s --unix-socket /dev/lxd/sock http://custom.socket/1.0 | jq
if hasNeededAPIExtension cloud_init; then
lxc exec c1 -- curl -s --unix-socket /dev/lxd/sock http://custom.socket/1.0/devices | jq
fi
lxc exec c1 -- curl -s --unix-socket /dev/lxd/sock http://custom.socket/1.0/config | jq
lxc exec c1 -- curl -s --unix-socket /dev/lxd/sock http://custom.socket/1.0/meta-data | grep -q '#cloud-config'

# Disable devlxd
lxc config set c1 security.devlxd false

echo "==> Checking devlxd is not working"

! lxc exec c1 -- curl -s --unix-socket /dev/lxd/sock http://custom.socket/1.0 || false

lxc restart -f c1

# devlxd should not be running after restart
! lxc exec c1 -- curl -s --unix-socket /dev/lxd/sock http://custom.socket/1.0 || false

echo "==> Checking devlxd can be enabled live"

# Enable devlxd
lxc config set c1 security.devlxd true
if hasNeededAPIExtension devlxd_images; then
lxc config set c1 security.devlxd.images true
fi

# devlxd should be running after the config is enabled
lxc exec c1 -- curl -s --unix-socket /dev/lxd/sock http://custom.socket/1.0 | jq
if hasNeededAPIExtension cloud_init; then
lxc exec c1 -- curl -s --unix-socket /dev/lxd/sock http://custom.socket/1.0/devices | jq
fi
lxc exec c1 -- curl -s --unix-socket /dev/lxd/sock http://custom.socket/1.0/config | jq
lxc exec c1 -- curl -s --unix-socket /dev/lxd/sock http://custom.socket/1.0/meta-data | grep -q '#cloud-config'

if hasNeededAPIExtension instance_ready_state; then
# test instance Ready state
lxc exec c1 -- curl -s --unix-socket /dev/lxd/sock -X PATCH -d '{"state":"Ready"}' http://custom.socket/1.0
[ "$(lxc config get c1 volatile.last_state.ready)" = "true" ]

lxc exec c1 -- curl -s --unix-socket /dev/lxd/sock -X PATCH -d '{"state":"Started"}' http://custom.socket/1.0
[ "$(lxc config get c1 volatile.last_state.ready)" = "false" ]

lxc exec c1 -- curl -s --unix-socket /dev/lxd/sock -X PATCH -d '{"state":"Ready"}' http://custom.socket/1.0
[ "$(lxc config get c1 volatile.last_state.ready)" = "true" ]
lxc stop -f c1
sleep 5
[ "$(lxc config get c1 volatile.last_state.ready)" = "false" ]

lxc start c1
else
echo "Skipping instance Ready state tests, not supported"
fi

# Below tests for image export rely on an event being emitted on export. This will not be backported to 4.0 or 5.0,
# so exit the test here.
if [ "${LXD_SNAP_CHANNEL}" = "4.0/edge" ] || [ "${LXD_SNAP_CHANNEL}" = "5.0/edge" ]; then
echo "Skipping devlxd image export tests, not supported"
FAIL=0
exit
fi

# We need snapd to be ready before the next tests. Finagle the waitSnapdSeed function definition into the container and run it.
# shellcheck disable=SC3044 # Ignore "declare is undefined" shellcheck error.
lxc exec c1 -- sh -c "$(declare -f waitSnapdSeed); waitSnapdSeed"
lxc exec c1 -- snap remove --purge lxd || true
lxc exec c1 -- snap install lxd --channel="${LXD_SNAP_CHANNEL}"
lxc exec c1 -- /snap/bin/lxd init --auto

monitorPID=""
if hasNeededAPIExtension devlxd_images && hasNeededAPIExtension event_lifecycle; then
lxc monitor --type lifecycle --format json > monitor.json 2>&1 &
monitorPID="${!}"
fi

# Launch an image we know is on the host.
lxc exec c1 -- /snap/bin/lxc launch "${TEST_IMG:-ubuntu-minimal-daily:24.04}" c1c1
lxc exec c1 -- /snap/bin/lxc info c1c1 | grep -F RUNNING

if hasNeededAPIExtension devlxd_images && hasNeededAPIExtension event_lifecycle; then
kill -9 "${monitorPID}"

# If the guest retrieved the image from the host, the host should emit an "image-retrieved" lifecycle event. The
# requestor address tells us that this was definitely the guest.
[ "$(grep -wF 'image-retrieved' monitor.json | jq -r '.metadata.requestor.address')" = "@devlxd" ]
rm monitor.json
fi

echo "==> Deleting container"
lxc delete -f c1
lxc profile device remove default eth0

echo "==> Deleting storage pool"
lxc storage delete "${poolName}"

echo "==> Deleting storage pool"
lxc network delete lxdbr0

# shellcheck disable=SC2034
FAIL=0

0 comments on commit 5b45519

Please sign in to comment.