-
Notifications
You must be signed in to change notification settings - Fork 1
129 lines (114 loc) · 5.36 KB
/
automatic-instance-shelving.yml
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
name: Automatic Instance Shelving
on:
schedule:
# Run every 5 mins
- cron: "* * * * *"
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ vars.MORPHOCLOUD_OS_CLOUD }}
cancel-in-progress: true
permissions:
issues: write
contents: read
jobs:
auto-shelve:
runs-on: self-hosted
steps:
- uses: actions/checkout@v4
- uses: actions/create-github-app-token@31c86eb3b33c9b601a1f60f98dcbfd1d70f379b4 # v1.10.3
id: app-token
with:
app-id: ${{ vars.MORPHOCLOUD_WORKFLOW_APP_ID }}
private-key: ${{ secrets.MORPHOCLOUD_WORKFLOW_APP_PRIVATE_KEY }}
- name: Auto Shelve
run: |
source ~/venv/bin/activate
instance_prefix=${PREFIX:+${PREFIX}_}
instance_basename="${instance_prefix}instance"
openstack server list --name "^${instance_basename}-\d+" -f json | \
jq -r '.[] | [.Name, .Status, ."OS-EXT-STS:task_state"] | @tsv' | \
while IFS=$'\t' read -r instance_name status task_state; do
echo "instance_name [$instance_name] status [$status] task_state [$task_state]"
# Skip the instance if it is not active
if [[ "$status" != "ACTIVE" ]]; then
continue
fi
# Skip the instance if it is currently undergoing a status update
if [[ "$task_state" != "" ]]; then
continue
fi
# Extract the issue number from the instance name
issue_number=${instance_name##*-}
echo "issue_number [$issue_number]"
# Retrieve the IP address of the instance
instance_ip=$(
openstack server show $instance_name -c addresses -f json | \
jq -r '.addresses.auto_allocated_network[1]'
)
echo "instance_ip [$instance_ip]"
# Skip the instance if the IP address could not be retrieved
if [[ "$instance_ip" == "null" ]]; then
echo "::warning ::Failed to retrieve $instance_name IP"
continue
fi
# Notes on SSH usage:
# * Redirecting SSH standard input to /dev/null ('< /dev/null') is required to work around
# an issue where SSH breaks out of the while loop in Bash.
# Reference: https://stackoverflow.com/questions/9393038/ssh-breaks-out-of-while-loop-in-bash
has_check_instance_shelve_script=$(ssh \
-o StrictHostKeyChecking=no \
-o UserKnownHostsFile=/dev/null \
-o LogLevel=ERROR \
exouser@$instance_ip \
'bash -c "[[ -f /opt/instance-config-support/dist/check-instance-shelve.sh ]] && echo yes || echo no"' < /dev/null)
if [[ $? -ne 0 ]]; then
echo "::warning ::Failed to check if 'check-instance-shelve.sh' was found on $instance_name using IP $instance_ip"
continue
fi
if [[ "$has_check_instance_shelve_script" == "yes" ]]; then
uptime_hours=$(ssh \
-o StrictHostKeyChecking=no \
-o UserKnownHostsFile=/dev/null \
-o LogLevel=ERROR \
exouser@$instance_ip \
'/opt/instance-config-support/dist/check-instance-shelve.sh -d' < /dev/null)
if [[ $? -ne 0 ]]; then
echo "::warning ::Failed to retrieve uptime for $instance_name using IP $instance_ip"
continue
fi
else
# Retrieve the instance uptime using SSH
uptime_seconds=$(ssh \
-o StrictHostKeyChecking=no \
-o UserKnownHostsFile=/dev/null \
-o LogLevel=ERROR \
exouser@$instance_ip \
'cat /proc/uptime | awk "{print \$1}"' < /dev/null)
if [[ $? -ne 0 ]]; then
echo "::warning ::Failed to retrieve uptime for $instance_name using IP $instance_ip"
continue
fi
# Convert uptime from seconds to hours
uptime_hours=$(echo "scale=2; $uptime_seconds / 3600" | bc)
fi
# Check uptime and define action
if $(python3 -c "valid=($uptime_hours > 3.5 and $uptime_hours <= 4.0); EXIT_SUCCESS=0; EXIT_FAILURE=1; exit(EXIT_SUCCESS if valid else EXIT_FAILURE)"); then
action="notify"
elif $(python3 -c "valid=($uptime_hours > 4.0); EXIT_SUCCESS=0; EXIT_FAILURE=1; exit(EXIT_SUCCESS if valid else EXIT_FAILURE)"); then
action="shelve"
else
action=""
fi
echo "instance_name [$instance_name], has_check_instance_shelve_script [$has_check_instance_shelve_script], uptime_hours [$uptime_hours] -> action[$action]"
# Perform action
if [[ "$action" == "shelve" ]]; then
gh workflow run control-instance-from-workflow.yml \
-f issue_number=$issue_number \
-f command_name=shelve
fi
done
env:
OS_CLOUD: ${{ vars.MORPHOCLOUD_OS_CLOUD }}
GH_TOKEN: ${{ steps.app-token.outputs.token }}
GH_REPO: ${{ github.repository }}
PREFIX: ${{ vars.INSTANCE_NAME_PREFIX }}