File: state.sh

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 (150 lines) | stat: -rwxr-xr-x 6,020 bytes parent folder | download
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
#!/bin/bash

SNAPD_STATE_PATH="$TESTSTMP/snapd-state"
SNAPD_STATE_FILE="$TESTSTMP/snapd-state/snapd-state.tar"
SNAPD_ACTIVE_UNITS="$RUNTIME_STATE_PATH/snapd-active-units"

delete_snapd_state() {
    rm -rf "$SNAPD_STATE_PATH"
}

prepare_state() {
    mkdir -p "$SNAPD_STATE_PATH" "$RUNTIME_STATE_PATH"
}

is_snapd_state_saved() {
    if os.query is-core && [ -d "$SNAPD_STATE_PATH"/snapd-lib ]; then
        return 0
    elif os.query is-classic && [ -f "$SNAPD_STATE_FILE" ]; then
        return 0
    else
        return 1
    fi
}

get_active_snapd_units() {
    systemctl list-units --plain --state=active | grep -Eo '^snapd\..*(socket|service|timer)' || true
}

save_snapd_state() {
    prepare_state
    if os.query is-core; then
        boot_path="$("$TESTSTOOLS"/boot-state boot-path)"
        test -n "$boot_path" || return 1

        mkdir -p "$SNAPD_STATE_PATH"/system-units

        # Copy the state preserving the timestamps
        cp -a /var/lib/snapd "$SNAPD_STATE_PATH"/snapd-lib
        cp -rf /var/cache/snapd "$SNAPD_STATE_PATH"/snapd-cache
        cp -rf "$boot_path" "$SNAPD_STATE_PATH"/boot
        cp -f /etc/systemd/system/snap-*core*.mount "$SNAPD_STATE_PATH"/system-units
        mkdir -p "$SNAPD_STATE_PATH"/var-snap
        cp -a /var/snap/* "$SNAPD_STATE_PATH"/var-snap/
    else
        systemctl daemon-reload
        SNAP_MOUNT_DIR="$(os.paths snap-mount-dir)"
        escaped_snap_mount_dir="$(systemd-escape --path "$SNAP_MOUNT_DIR")"
        units="$(systemctl list-unit-files --full | grep -e "^${escaped_snap_mount_dir}[-.].*\\.mount" -e "^${escaped_snap_mount_dir}[-.].*\\.service" | cut -f1 -d ' ')"
        for unit in $units; do
            systemctl stop "$unit"
        done
        snapd_env=
        for e in /etc/environment /etc/default/snapd; do
            if [ -f "$e" ] ; then
                snapd_env="$e"
                break
            fi
        done
        snapd_service_env=$(ls -d /etc/systemd/system/snapd.*.d || true)
        snap_confine_profiles="$(ls /etc/apparmor.d/snap.snapd.* || true)"

        # shellcheck disable=SC2086
        tar cf "$SNAPD_STATE_FILE" \
            /var/lib/snapd \
            /var/cache/snapd \
            "$SNAP_MOUNT_DIR" \
            /etc/systemd/system/"$escaped_snap_mount_dir"-*snapd*.mount \
            /etc/systemd/system/snapd.mounts.target.wants/"$escaped_snap_mount_dir"-*snapd*.mount \
            /etc/systemd/system/multi-user.target.wants/"$escaped_snap_mount_dir"-*snapd*.mount \
            /etc/systemd/system/"$escaped_snap_mount_dir"-*core*.mount \
            /etc/systemd/system/snapd.mounts.target.wants/"$escaped_snap_mount_dir"-*core*.mount \
            /etc/systemd/system/multi-user.target.wants/"$escaped_snap_mount_dir"-*core*.mount \
            $snap_confine_profiles \
            $snapd_env \
            $snapd_service_env

        systemctl daemon-reload # Workaround for http://paste.ubuntu.com/17735820/
        core="$(readlink -f "$SNAP_MOUNT_DIR/core/current")"
        # on 14.04 it is possible that the core snap is still mounted at this point, unmount
        # to prevent errors starting the mount unit
        if os.query is-trusty && mount | grep -q "$core"; then
            umount "$core" || true
        fi
        for unit in $units; do
            systemctl start "$unit"
        done
    fi

    # Save the snapd active units
    get_active_snapd_units > "$SNAPD_ACTIVE_UNITS"
}

restore_snapd_state() {
    if os.query is-core; then
        # we need to ensure that we also restore the boot environment
        # fully for tests that break it
        boot_path="$("$TESTSTOOLS"/boot-state boot-path)"
        test -n "$boot_path" || return 1

        restore_snapd_lib
        cp -rf "$SNAPD_STATE_PATH"/snapd-cache/*  /var/cache/snapd
        cp -rf "$SNAPD_STATE_PATH"/boot/* "$boot_path"
        cp -f "$SNAPD_STATE_PATH"/system-units/*  /etc/systemd/system
        rm -rf /var/snap/*
        cp -a "$SNAPD_STATE_PATH"/var-snap/* /var/snap/
    else
        # Purge all the systemd service units config
        rm -rf /etc/systemd/system/snapd.service.d
        rm -rf /etc/systemd/system/snapd.socket.d

        # TODO: remove files created by the test
        tar -C/ -xf "$SNAPD_STATE_FILE"
    fi

    # Start all the units which have to be active
    while read -r unit; do
        if ! systemctl is-active "$unit"; then
            systemctl start "$unit"
        fi
    done  < "$SNAPD_ACTIVE_UNITS"
}

restore_snapd_lib() {
    # Clean all the state but the snaps, seed, cache and kernel dirs. Then make
    # a selective clean for snaps, seed and cache dirs leaving the .snap files
    # which then are going to be synchronized. We cannot touch kernel dir as it
    # is bind mounted in /lib/{modules,firmware}.
    find /var/lib/snapd/* -maxdepth 0 ! \( -name 'snaps' -o -name 'seed' -o -name 'cache' -o -name 'kernel' \) -exec rm -rf {} \;

    # Copy the whole state but the snaps, seed, cache and kernel dirs
    find "$SNAPD_STATE_PATH"/snapd-lib/* -maxdepth 0 ! \( -name 'snaps' -o -name 'seed' -o -name 'cache' -o -name 'kernel' \) -exec cp -rf {} /var/lib/snapd \;

    # Synchronize snaps, seed and cache directories. The this is done separately in order to avoid copying
    # the snap files due to it is a heavy task and take most of the time of the restore phase.
    rsync -av --delete "$SNAPD_STATE_PATH"/snapd-lib/snaps /var/lib/snapd
    if os.query is-core16 || os.query is-core18; then
        rsync -av --delete "$SNAPD_STATE_PATH"/snapd-lib/seed/ /var/lib/snapd/seed/
    else
        # TODO:UC20: /var/lib/snapd/seed is a read only bind mount, use the rw
        # mount or later mount seed as needed
        rsync -av --delete "$SNAPD_STATE_PATH"/snapd-lib/seed/ /run/mnt/ubuntu-seed/
    fi
    rsync -av --delete "$SNAPD_STATE_PATH"/snapd-lib/cache /var/lib/snapd
}

remove_disabled_snaps() {
    snap list --all | grep disabled | while read -r name _ revision _ ; do
        snap remove "$name" --revision="$revision"
    done
}