File: task.yaml

package info (click to toggle)
snapd 2.71-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 79,536 kB
  • sloc: ansic: 16,114; sh: 16,105; python: 9,941; makefile: 1,890; exp: 190; awk: 40; xml: 22
file content (193 lines) | stat: -rw-r--r-- 9,478 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
summary: Each snap app and hook is tracked via cgroups

details: |
    This test creates a snap process that suspends itself and ensures that it
    placed into the appropriate hierarchy.

systems:
    # Ubuntu 14.04's special version of systemd doesn't have StartTransientUnit API.
    # This is covered in more depth in the sister cgroup-tracking-failure test.
    - -ubuntu-14.04-*

environment:
    USER/root: root
    USER/test: test

prepare: |
    snap pack test-snapd-tracking
    tests.cleanup defer rm -f test-snapd-tracking_1_all.snap

    snap install --dangerous ./test-snapd-tracking_1_all.snap
    tests.cleanup defer snap remove test-snapd-tracking

    tests.session -u "$USER" prepare
    tests.cleanup defer tests.session -u "$USER" restore

restore: |
    rm -f /tmp/*.pid /tmp/*.stamp

    if [ "$USER" = root ]; then
        systemctl --user stop dbus.service || true
    fi

debug: |
    cat /proc/self/cgroup
    systemctl --version || true
    cat /proc/cmdline

execute: |
    # This test varies between Ubuntu 16.04, Ubuntu 18.04 and Fedora 31.
    # This combination exercises each of the three cases below, namely:
    # - pure cgroup v2 system, like Fedora 31
    # - hybrid cgroup system, like Ubuntu 18.04
    # - pure cgroup v1 system, like Ubuntu 16.04
    echo "Find the path and id of the cgroup snapd uses for tracking."
    if [ "$(stat -f --print=%T /sys/fs/cgroup)" = "cgroup2fs" ]; then
        base_cg_path=/sys/fs/cgroup
        base_cg_id=0
    elif [ "$(stat -f --print=%T /sys/fs/cgroup/unified)" = "cgroup2fs" ]; then
        base_cg_path=/sys/fs/cgroup/unified
        base_cg_id=0
    elif [ "$(stat -f --print=%T /sys/fs/cgroup/systemd)" = "cgroupfs" ]; then
        base_cg_path=/sys/fs/cgroup/systemd
        base_cg_id="$(grep -F 'name=systemd' < /proc/self/cgroup | cut -d : -f 1)"
    else
        echo "cannot find any tracking cgroup"
        exit 1
    fi
    echo "Sanity check, base directory of selected cgroup exists."
    test -d "$base_cg_path"

    # The configure hook was executed and used a scope for tracking. The scope
    # was attached to the system slice, as it is not associated with any user.
    test -f /var/snap/test-snapd-tracking/common/configure.cgroup
    hook_tracking_cg_path="$(grep -E "^$base_cg_id:" < /var/snap/test-snapd-tracking/common/configure.cgroup | cut -d : -f 3)"
    echo "$hook_tracking_cg_path" | MATCH '/system\.slice/snap\.test-snapd-tracking\.hook\.configure-[0-9a-f-]+\.scope'

    # The nap service was executed and was tracked as a systemd service.
    test -f /var/snap/test-snapd-tracking/common/nap.cgroup
    service_tracking_cg_path="$(grep -E "^$base_cg_id:" < /var/snap/test-snapd-tracking/common/nap.cgroup | cut -d : -f 3)"
    echo "$service_tracking_cg_path" | MATCH '/system\.slice/snap\.test-snapd-tracking\.nap\.service'

    # The application tracking is tested below.
    systemd_ver="$(systemctl --version | awk '/systemd [0-9]+/ { print $2 }' | cut -f1 -d"~")"
    if [ "$USER" = test ] && "$TESTSTOOLS"/version-compare --strict "$systemd_ver" -lt 238; then
        echo "Systemd running as user session manager cannot start transient units"
        echo "that cross ownership boundary. This test effectively runs through root"
        echo "that is using ssh to connect to a test machine. Crossing the boundary"
        echo "of cgroup ownership is allowed by systemd 238 or newer, thanks to"
        echo "org.freedesktop.systemd1.Manager.AttachProcessesToUnit method,"
        echo "offered by systemd running as system manager, which allows"
        echo "overcoming this kernel limitation".
        echo "SKIP: systemd is too old to perform this test as user"

        # This effectively can run starting with Ubuntu 19.10, Fedora 30,
        # Debian 10 (but no version of openSUSE Leap yet) - older versions will
        # not perform in this unique environment that spread provides for us.
        # In typical desktop environment going all the way back to 16.04 should
        # work fine, as far as the intended use-case is concerned.

        exit 0
    fi

    if [ "$USER" = test ]; then
        case "$SPREAD_SYSTEM" in
            # XXX: this may now pass on core18+, verify that.
            ubuntu-core-*)
                echo "On core systems there is no session bus so the test variant does not make much sense"
                echo "Please see the cgroup-tracking-failure test for more extensive analysis"
                echo "SKIP: core systems don't have session services / session bus"
                exit 0
                ;;
        esac
    fi

    echo "Start a \"sleep\" process in the background, in a new session"
    # NOTE: tests.session handles PAM and that necessitates a management process
    # that eventually performs PAM termination activities. The PID returned from
    # invoking tests.session in the background will not be that of the invoked program
    # but rather of the monitoring helper process.
    tests.session -p /tmp/1.pid -u "$USER" exec snap run test-snapd-tracking.sh -c 'touch /tmp/1.stamp && exec sleep 3m' &
    session1_pid=$!
    trap "pkill sleep || true" EXIT
    echo "Ensure that snap-confine has finished its task and that the snap process"
    echo "is active. Note that we don't want to wait forever either."
    retry -n 30 test -e /tmp/snap-private-tmp/snap.test-snapd-tracking/tmp/1.stamp
    pid1_sleep=$(cat /tmp/1.pid)

    echo "During startup snap-run has asked systemd to move the process to a"
    echo "new transient scope. The scope name is \"snap.\$random.test-snapd-tracking.sh\"."
    echo "Let's verify that."
    pid1_tracking_cg_path="$(grep -E "^$base_cg_id:" < "/proc/$pid1_sleep/cgroup" | cut -d : -f 3)"
    echo "$pid1_tracking_cg_path" | MATCH '.*/snap\.test-snapd-tracking\.sh-[0-9a-f-]+\.scope'

    echo "Sanity check, cgroup associated with the scope exists."
    test -d "${base_cg_path}${pid1_tracking_cg_path}"

    echo "While the process is alive its PID can be seen in the cgroup.procs file."
    MATCH "$pid1_sleep" < "${base_cg_path}${pid1_tracking_cg_path}/cgroup.procs"

    echo "Start a second process so that we can check each scope is independent."
    #shellcheck disable=SC2016
    tests.session -p /tmp/2.pid -u "$USER" exec snap run test-snapd-tracking.sh -c 'touch /tmp/2.stamp && exec sleep 2m' &
    session2_pid=$!
    retry -n 30 test -e /tmp/snap-private-tmp/snap.test-snapd-tracking/tmp/2.stamp
    pid2_sleep=$(cat /tmp/2.pid)
    pid2_tracking_cg_path="$(grep -E "^$base_cg_id:" < "/proc/$pid2_sleep/cgroup" | cut -d : -f 3)"
    echo "$pid2_tracking_cg_path" | MATCH '.*/snap\.test-snapd-tracking\.sh-[0-9a-f-]+\.scope'
    MATCH "$pid2_sleep" < "${base_cg_path}${pid2_tracking_cg_path}/cgroup.procs"

    echo "Each invocation uses a new transient scope and thus a new cgroup path."
    test "$pid1_tracking_cg_path" != "$pid2_tracking_cg_path"

    echo "When the process terminates, the control group it used to exist in is"
    echo "automatically removed by systemd, though perhaps not instantly"
    kill "$pid1_sleep"
    wait "$session1_pid" || true  # wait returns the exit code and we kill the process
    retry -n 10 test ! -e "${base_cg_path}${pid1_tracking_cg_path}"

    kill "$pid2_sleep"
    wait "$session2_pid" || true  # same as above
    retry -n 10 test ! -e "${base_cg_path}${pid2_tracking_cg_path}"

    echo "If a snap command forks a child process it is also tracked."
    #shellcheck disable=SC2016
    tests.session -p /tmp/3.pid -u "$USER" exec snap run test-snapd-tracking.sh -c 'touch /tmp/3.stamp && sleep 1m' &
    session3_pid=$!
    retry -n 30 test -e /tmp/snap-private-tmp/snap.test-snapd-tracking/tmp/3.stamp
    pid3_sh=$(cat /tmp/3.pid)
    pid3_tracking_cg_path="$(grep -E "^$base_cg_id:" < "/proc/$pid3_sh/cgroup" | cut -d : -f 3)"
    MATCH "$pid3_sh" < "${base_cg_path}${pid3_tracking_cg_path}/cgroup.procs"

    echo "Because the script above used \"sleep 1m\" instead of \"exec sleep 1m\" there"
    echo "are now two processes: the shell and sleep."
    cgroup_procs_path="${base_cg_path}${pid3_tracking_cg_path}/cgroup.procs"
    test "$(wc -l < "$cgroup_procs_path")" -eq 2
    kill "$pid3_sh"
    #shellcheck disable=SC2016
    cgroup_procs_path="$cgroup_procs_path" retry -n 10 --wait 0.5 sh -c 'test "$(wc -l < $cgroup_procs_path)" -eq 1'

    wait "$session3_pid" || true  # same as above
    # When tests.session is used with systemd-run
    if [ "$systemd_ver" -gt 252 ]; then
        pid3_sleep="$(cat "$cgroup_procs_path")"
        test -e "${base_cg_path}${pid3_tracking_cg_path}"
        kill "$pid3_sleep"
    fi
    retry -n 10 test ! -e "${base_cg_path}${pid3_tracking_cg_path}"

    if [ "$USER" != "root" ]; then
        # since the service we run here writes under /var/snap/ we need to make
        # that location writable
        chmod a+w /var/snap/test-snapd-tracking/common
    fi
    echo "A service run directly as the user will also get a tracking scope"
    rm -f /var/snap/test-snapd-tracking/common/nap.cgroup
    tests.session -p /tmp/4.pid -u "$USER" exec snap run test-snapd-tracking.nap &
    session4_pid=$!
    retry -n 30 test -e /var/snap/test-snapd-tracking/common/nap.cgroup
    pid4=$(cat /tmp/4.pid)
    pid4_tracking_cg_path="$(grep -E "^$base_cg_id:" < "/proc/$pid4/cgroup" | cut -d : -f 3)"
    echo "$pid4_tracking_cg_path" | MATCH '.*/snap\.test-snapd-tracking\.nap-[0-9a-f-]+\.scope'
    kill "$pid4"
    wait "$session4_pid" || true