summaryrefslogtreecommitdiff
path: root/openwrt/config_generation.sh
blob: f4b25c50c622a07d8eb10e8a4f5a7fc34fa07e02 (plain)
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
#!/bin/sh /etc/rc.common

EXTRA_COMMANDS="apply_reboot prepare_reload apply_reload commit"
START=99

_unregister_script() {
    /etc/init.d/config_generation disable
    rm /etc/init.d/config_generation
}

_rollback() {
    rm -rf /overlay/upper.dead
    mv /overlay/upper /overlay/upper.dead
    # this should never fail, unless something *else* is also mucking
    # with overlayfs state.
    if mv -T /overlay/upper.prev /overlay/upper; then
        rm -rf /overlay/upper.dead
    else
        echo "rollback failed, manual recovery needed. check /overlay/upper.dead!" >&2
        exit 1
    fi
}

_prepare_apply() {
    CYAN='\e[36m'
    RED='\e[31m'
    NORMAL='\e[0m'

    log() {
        printf "$CYAN>> %s$NORMAL\n" "$*"
    }

    log_err() {
        printf "$RED>> %s$NORMAL\n" "$*"
    }

    if [ -e /overlay/upper.dead ]; then
        log_err "previous failed deployment still needs recovery"
        exit 1
    fi

    if ! rm -rf /overlay/upper.prev/ \
        || ! cp -al /overlay/upper/ /overlay/upper.prev/ \
        || ! rm -rf /overlay/upper.prev/etc/ \
        || ! cp -a /overlay/upper/etc/ /overlay/upper.prev/
    then
        log_err "failed to snapshot old config"
        rm -rf /overlay/upper.prev
        exit 1
    fi

    if ! /etc/init.d/config_generation enable
    then
        log_err "failed to schedule rollback"
        rm -rf /overlay/upper.prev
        exit 1
    fi
}

_run_steps() {
    (
        set -e
        @deploy_steps@
    )
}

apply_reboot() {
    _prepare_apply

    # everything after this point may fail. if it does we'll simply roll back
    # immediately and reboot.

    trap 'reboot &' EXIT

    if ! _run_steps; then
        log_err 'deployment failed, rolling back and rebooting ...'
        _rollback
        exit 1
    fi

    log 'rebooting device ...'
}

prepare_reload() {
    mkdir /overlay/upper.prev
    /etc/init.d/config_generation enable
}

apply_reload() {
    _prepare_apply

    # everything after this point may fail. if it does we'll simply roll back
    # immediately and reboot.

    trap 'reboot &' EXIT

    if _run_steps; then
        trap '' EXIT
        log 'reloading config ...'
        reload_config
        # give service restarts a chance
        log 'waiting @reload_service_wait@s for services ...'
        sleep @reload_service_wait@
        exit 0
    else
        log_err 'deployment failed, rolling back and rebooting ...'
        _rollback
        exit 1
    fi
}

commit() {
    if ! [ -e /overlay/upper.prev ]; then
        exit 1
    fi
    touch /tmp/.abort-rollback
}

start() {
    [ -d /overlay/upper.prev ] || {
        _unregister_script
        exit 0
    }

    local needs_rollback=true
    local timeout=@rollback_timeout@

    while [ $timeout -gt 0 ]; do
        timeout=$(( timeout - 1 ))
        [ -e /tmp/.abort-rollback ] && {
            needs_rollback=false
            rm /tmp/.abort-rollback
            break
        }
        sleep 1
    done

    if $needs_rollback; then
        _rollback
        _unregister_script
        reboot
    else
        rm -rf /overlay/upper.prev
        _unregister_script
    fi
}