-
Notifications
You must be signed in to change notification settings - Fork 2
/
install.sh
executable file
·392 lines (356 loc) · 13.1 KB
/
install.sh
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
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
#!/bin/bash
# This script installs FIREWHEEL. This should be run on every node in your
# FIREWHEEL cluster.
#
# Prior to running this script, you should check the config variable settings
# in provision_env.sh. Generally the defaults are safe. However PYTHON_BIN is
# likely to change between environments.
#
# On clusters of more than one node, FIREWHEEL_NODES, EXPERIMENT_INTERFACE,
# and GRPC_THREADS should be set. Additionally, if VLANs cannot be used to
# route traffic between FIREWHEEL nodes, then USE_GRE should be set to `true`.
#
# Once this script has run on each node, you should run `firewheel sync` on the
# head node. Then your FIREWHEEL cluster will be ready to use!
#
# Requirements:
# * Python >=3.7, with the path to its executable specified by PYTHON_BIN
# (we recommend using virtual environments).
# * minimega and discovery installed and configured.
# This script will load `provision_env.sh` to get values for the following
# variables if they are not already set:
# sid
# FIREWHEEL_NODES
# HEAD_NODE
# FIREWHEEL_ROOT_DIR
# FIREWHEEL_VENV
# PYTHON_BIN
# EXPERIMENT_INTERFACE
# USE_GRE
# MM_BASE
# MM_GROUP
# MM_CONTEXT
# MM_INSTALL_DIR
# DISCOVERY_PORT
# DISCOVERY_HOSTNAME
# GRPC_HOSTNAME
# GRPC_PORT
# GRPC_THREADS
# FIREWHEEL_GROUP
# MC_BRANCH
# MC_DIR
# MC_REPO_GROUP
# DEFAULT_OUTPUT_DIR
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
source "${SCRIPT_DIR}/provision_env.sh"
#######################################
# Standardized error logging function to STDERR.
# Arguments:
# Error strings to log to stderr
# Outputs:
# Outputs error message to stderr
#######################################
function err() {
echo "[$(date -u +'%Y-%m-%dT%H:%M:%S%z')]: $*" >&2
}
#######################################
# Set up the default directory for output
# and ensure it has the correct permissions.
# Arguments:
# None
# Globals:
# DEFAULT_OUTPUT_DIR
# FIREWHEEL_GROUP
#######################################
function setup_dirs() {
if ! mkdir -p "${DEFAULT_OUTPUT_DIR}"; then
err "FIREWHEEL failed to create default output directory: \"${DEFAULT_OUTPUT_DIR}\". Aborting."
exit 1
fi
if ! chgrp "${FIREWHEEL_GROUP}" "${DEFAULT_OUTPUT_DIR}"; then
err "FIREWHEEL failed to alter group ownership of default output directory: \"${DEFAULT_OUTPUT_DIR}\". Aborting."
exit 1
fi
if ! chmod -R g=u "${DEFAULT_OUTPUT_DIR}"; then
err "FIREWHEEL failed to permissions of default output directory: \"${DEFAULT_OUTPUT_DIR}\". Aborting."
exit 1
fi
}
#######################################
# Clone a few of the most common Model Component Repositories (base, linux, vyos).
# There is some error handling to ensure group permissions are set and
# that the repositories are cloned correctly.
# Arguments:
# None
# Globals:
# FIREWHEEL_GROUP
# MC_BRANCH
# MC_DIR
# MC_REPO_GROUP
#######################################
function clone_repos() {
if ! mkdir -p "${MC_DIR}"; then
err "FIREWHEEL failed to create model component directory: \"${MC_DIR}\". Aborting."
exit 1
fi
if ! chgrp -R "${FIREWHEEL_GROUP}" "${MC_DIR}"; then
err "FIREWHEEL failed to alter group ownership of model component directory: \"${MC_DIR}\". Aborting."
exit 1
fi
if ! chmod -R g=u "${MC_DIR}"; then
err "FIREWHEEL failed to permissions of model component directory: \"${MC_DIR}\". Aborting."
exit 1
fi
pushd "${MC_DIR}"
local fail_count=1
local max_attempts=5
if [[ ! -d "base" ]]; then
fail_count=1
until (( fail_count > max_attempts )) || git clone $GIT_CLONE_OPTS "${MC_REPO_GROUP}/base.git" --branch "${MC_BRANCH}"; do
fail_count=$((fail_count+1))
rate_mod=$((2**(fail_count)))
r_sleep=$((RANDOM % rate_mod))
err "Failed to clone $fail_count out of $max_attempts times. Sleeping for ${r_sleep} to rate limit."
sleep ${r_sleep}
done
if (( fail_count > max_attempts )); then
err "FIREWHEEL failed to clone required git repository: \"${MC_REPO_GROUP}/base.git\". Aborting."
exit 1
fi
else
err "Directory \"${MC_REPO_GROUP}/base\" already exists. Skipping git clone."
fi
if [[ ! -d "linux" ]]; then
fail_count=1
until (( fail_count > max_attempts )) || git clone $GIT_CLONE_OPTS "${MC_REPO_GROUP}/linux.git" --branch "${MC_BRANCH}"; do
fail_count=$((fail_count+1))
rate_mod=$((2**(fail_count)))
r_sleep=$((RANDOM % rate_mod))
err "Failed to clone $fail_count out of $max_attempts times. Sleeping for ${r_sleep} to rate limit."
sleep ${r_sleep}
done
if (( fail_count > max_attempts )); then
err "FIREWHEEL failed to clone required git repository: \"${MC_REPO_GROUP}/linux.git\". Aborting."
exit 1
fi
else
err "Directory \"${MC_REPO_GROUP}/linux\" already exists. Skipping git clone."
fi
if [[ ! -d "vyos" ]]; then
fail_count=1
until (( fail_count > max_attempts )) || git clone $GIT_CLONE_OPTS "${MC_REPO_GROUP}/vyos.git" --branch "${MC_BRANCH}"; do
fail_count=$((fail_count+1))
rate_mod=$((2**(fail_count)))
r_sleep=$((RANDOM % rate_mod))
err "Failed to clone $fail_count out of $max_attempts times. Sleeping for ${r_sleep} to rate limit."
sleep ${r_sleep}
done
if (( fail_count > max_attempts )); then
err "FIREWHEEL failed to clone required git repository: \"${MC_REPO_GROUP}/vyos.git\". Aborting."
exit 1
fi
else
err "Directory \"${MC_REPO_GROUP}/vyos\" already exists. Skipping git clone."
fi
popd
}
#######################################
# Check for the installation of minimega
# Arguments:
# None
# Globals:
# FIREWHEEL_GROUP
#######################################
function check_deps() {
if [[ `id -Gn | grep -q "\b${FIREWHEEL_GROUP}\b"` ]]; then
err "FIREWHEEL requires current user to be a member of the firewheel group: \"${FIREWHEEL_GROUP}\"."
err "Consult the FIREWHEEL installation tutorial for user and group setup prerequisites. Aborting."
exit 1
fi
if ! command -v minimega >/dev/null 2>&1; then
err "FIREWHEEL requires minimega to be installed and located in PATH. Aborting."
exit 1
fi
}
#######################################
# Basic setup for upgrading the virtual envionment tools and
# building the FIREWHEEL whl file.
# Arguments:
# None
# Globals:
# PIP_ARGS
# PYTHON_BIN
#######################################
function install_firewheel_generic() {
if ! ${PYTHON_BIN} -m pip install ${PIP_ARGS} build; then
err "FIREWHEEL setup failed to pip install 'build'."
err "Consult the pip error logs, and verify network connectivity. Aborting."
exit 1
fi
if ! ${PYTHON_BIN} -m build; then
err "FIREWHEEL setup failed to build the source distribution and wheel."
err "Consult the error logs, and verify network connectivity. Aborting."
exit 1
fi
}
#######################################
# Installing the FIREWHEEL package with standard dependencies.
# Arguments:
# None
# Globals:
# FIREWHEEL_ROOT
# PIP_ARGS
# PYTHON_BIN
#######################################
function install_firewheel() {
pushd "${FIREWHEEL_ROOT_DIR}"
${PYTHON_BIN} -m pip install ${PIP_ARGS} firewheel
if [ ! $? -eq 0 ];
then
install_firewheel_generic
${PYTHON_BIN} -m pip install ${PIP_ARGS} --prefer-binary ./dist/firewheel-2.6.0.tar.gz
fi
popd
}
#######################################
# Installing the FIREWHEEL package with development dependencies.
# Arguments:
# None
# Globals:
# FIREWHEEL_ROOT
# PIP_ARGS
# PYTHON_BIN
#######################################
function install_firewheel_development() {
pushd "${FIREWHEEL_ROOT_DIR}"
install_firewheel_generic
# Install the development version.
${PYTHON_BIN} -m pip install ${PIP_ARGS} -e .[dev]
popd
}
#######################################
# Set many typical FIREWHEEL configuration options and then
# run the ``firewheel init`` command which verifies our dependencies.
# Arguments:
# None
# Globals:
# DEFAULT_OUTPUT_DIR
# DISCOVERY_HOSTNAME
# EXPERIMENT_INTERFACE
# FIREWHEEL_NODES
# GRPC_HOSTNAME
# GRPC_THREADS
# HEAD_NODE
# MM_INSTALL_DIR
# USE_GRE
#######################################
function init_firewheel() {
firewheel config set -s system.default_output_dir "${DEFAULT_OUTPUT_DIR}"
firewheel config set -s cluster.compute "${FIREWHEEL_NODES}"
firewheel config set -s cluster.control "${HEAD_NODE}"
firewheel config set -s discovery.hostname "${DISCOVERY_HOSTNAME}"
firewheel config set -s grpc.hostname "${GRPC_HOSTNAME}"
firewheel config set -s grpc.port "${GRPC_PORT}"
firewheel config set -s grpc.threads "${GRPC_THREADS}"
firewheel config set -s minimega.experiment_interface "${EXPERIMENT_INTERFACE}"
firewheel config set -s minimega.use_gre "${USE_GRE}"
firewheel config set -s minimega.install_dir "${MM_INSTALL_DIR}"
firewheel config set -s minimega.base_dir "${MM_BASE}"
firewheel config set -s minimega.files_dir "${MM_BASE}/files"
firewheel config set -s discovery.port "${DISCOVERY_PORT}"
firewheel config set -s discovery.hostname "${DISCOVERY_HOSTNAME}"
firewheel config set -s system.default_group "${FIREWHEEL_GROUP}"
firewheel config set -s python.venv "${FIREWHEEL_VENV}"
firewheel config set -s python.bin "${PYTHON_BIN}"
# Ensure that if static mode is used it is properly passed through
if [[ $1 -eq 1 ]]; then
firewheel init static
else
firewheel init
fi
}
#######################################
# Prepare the FIREWHEEL tab completion script.
# This copies the tab completion script from a template, filling in
# environment variable values and then enabling it to be installed
# by the user post-installation.
# Arguments:
# None
#######################################
function configure_tab_complete() {
completion_script=$(
${PYTHON_BIN} -m firewheel.cli.completion.prepare_completion_script --print-path
)
source $completion_script
}
#######################################
# Echo out a few final commands which are useful for running FIREWHEEL.
# Arguments:
# None
#######################################
function post_install() {
echo -e "To use the FIREWHEEL CLI without activating the Python virtual environment we recommend running the following command:"
echo -e "\tsudo ln -s $(which firewheel) /usr/bin/firewheel\n"
echo -e "Once the entire cluster is provisioned we recommend proactively caching the CLI Helpers by using the command:"
echo -e "\tfirewheel sync\n"
}
#######################################
# Echo the usage of this script
#######################################
function usage() {
echo -e "Useful script to install FIREWHEEL and ensure proper system configuration.\n"
echo "usage: install.sh [-h | --help] [-d | --development] [-nc | --no-clone] [-s | --static]"
echo -e "\n\nOptional Arguments:"
echo " -h, --help Show this help message and exit"
echo " -d, --development Install FIREWHEEL in development mode, an 'editable' installation"
echo " including all development dependencies."
echo " -nc, --no-clone Prevents the install script from cloning/installing any model component"
echo " repositories."
echo " -s, --static Does not check if necessary system services are running (e.g., minimega)."
}
#######################################
# Install firewheel in development or normal mode.
#######################################
function main() {
local dev=0
local clone=1
local static=0
while [[ "$1" != "" ]]; do
case $1 in
-d | --development ) shift
dev=1 ;;
-nc | --no-clone ) shift
clone=0 ;;
-s | --static ) shift
static=1 ;;
-h | --help ) usage
exit ;;
* ) usage
exit 1
esac
done
fw_str="FIREWHEEL Installation:"
echo "${fw_str} Checking dependencies."
check_deps
echo "${fw_str} Setting up temporary directory."
setup_dirs
if [[ $clone -eq 1 ]]; then
echo "${fw_str} Cloning model component repositories."
clone_repos
fi
if [[ $dev -eq 1 ]]; then
echo "${fw_str} Installing FIREWHEEL in development mode."
install_firewheel_development
else
echo "${fw_str} Installing FIREWHEEL without development dependencies."
install_firewheel
fi
echo "${fw_str} Setting configuration options."
init_firewheel $static
echo "${fw_str} Preparing FIREWHEEL CLI tab complete."
configure_tab_complete
touch /tmp/firewheel-install-done
echo "${fw_str} Complete!!!"
post_install
}
main "$@"