Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added an update-image-copy feature #185

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
240 changes: 139 additions & 101 deletions flash
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
# Linux initial version by Matt Williams - matt@matthewkwilliams.com
# MIT License

set -eo pipefail
set -exo pipefail

error()
{
Expand All @@ -22,23 +22,24 @@ version()
usage()
{
cat << EOF
usage: $0 [options] [name-of-rpi.img]
usage: $0 [options] [name-of-rpi.img] [name-of-rpi-copy.img]

Flash a local or remote Raspberry Pi SD card image.

OPTIONS:
--help|-h Show this message
--bootconf|-C Copy this config file to /boot/config.txt
--config|-c Copy this config file to /boot/device-init.yaml (or occidentalis.txt)
--hostname|-n Set hostname for this SD image
--ssid|-s Set WiFi SSID for this SD image
--password|-p Set WiFI password for this SD image
--clusterlab|-l Start Cluster-Lab on boot: true or false
--device|-d Card device to flash to (e.g. /dev/sdb in Linux or /dev/disk2 in OSX)
--force|-f Force flash without security prompt (for automation)
--userdata|-u Copy this cloud-init file to /boot/user-data
--metadata|-m Copy this cloud-init file to /boot/meta-data
--file|-F Copy this file to /boot
--help|-h Show this message
--bootconf|-C Copy this config file to /boot/config.txt
--config|-c Copy this config file to /boot/device-init.yaml (or occidentalis.txt)
--hostname|-n Set hostname for this SD image
--ssid|-s Set WiFi SSID for this SD image
--password|-p Set WiFI password for this SD image
--clusterlab|-l Start Cluster-Lab on boot: true or false
--device|-d Card device to flash to (e.g. /dev/sdb in Linux or /dev/disk2 in OSX)
--force|-f Force flash without security prompt (for automation)
--userdata|-u Copy this cloud-init file to /boot/user-data
--metadata|-m Copy this cloud-init file to /boot/meta-data
--files|-F Copy files to /boot (use a , to separate multiple files to be copied)
--update-image|-U Update an image copy and do not flash to disk

If no image is specified, the script will try to configure an existing
image. This is useful to try several configuration without the need to
Expand All @@ -57,7 +58,7 @@ wifi:

For HypriotOS v1.7.0 and higher:

The config file user-data config file is the cloud-init configuration.
The config file config file is the cloud-init configuration.
See http://cloudinit.readthedocs.io/en/0.7.9/ for more details.
EOF
exit 1
Expand All @@ -80,7 +81,8 @@ do
--force) args="${args}-f ";;
--userdata) args="${args}-u ";;
--metadata) args="${args}-m ";;
--file) args="${args}-F ";;
--files) args="${args}-F ";;
--update-image) args="${args}-U ";;
# pass through anything else
*) [[ "${arg:0:1}" == "-" ]] || delim="\""
args="${args}${delim}${arg}${delim} ";;
Expand All @@ -89,7 +91,7 @@ done
# reset the translated args
eval set -- "$args"
# now we can process with getopt
while getopts ":h:vc:n:s:p:C:l:d:fu:m:F:" opt; do
while getopts ":h:vc:n:s:p:C:l:d:fu:m:F:U" opt; do
case $opt in
h) usage ;;
v) version ;;
Expand All @@ -104,6 +106,7 @@ while getopts ":h:vc:n:s:p:C:l:d:fu:m:F:" opt; do
u) USER_DATA=$OPTARG ;;
m) META_DATA=$OPTARG ;;
F) FILE=$OPTARG ;;
U) UPDATE_IMAGE=1 ;;
\?) usage ;;
:)
echo "option -$OPTARG requires an argument"
Expand All @@ -124,6 +127,7 @@ if [[ "$1" == "--help" ]]; then
usage
fi
image=$1
image_copy=$2

if [[ -z $image ]]; then
CONFIGURE_ONLY=1
Expand Down Expand Up @@ -465,6 +469,22 @@ case "${OSTYPE}" in
ls -la "${mount_point}"
}

# Mount the boot image to the specified point
#
# @param arg1 the image to mount.
# @param arg2 mount point
mount_image() {
local image=$1
local mount_point=$2

# We need to grab the byte offset for the fat16 boot partition
offset=$(sudo parted -m ${image} unit B print | grep ':fat' | cut --delimiter=":" --fields=2)

sudo mount -o loop,offset="${offset%B}",uid="$(id -u)",gid="$(id -g)" "${image}" "${mount_point}"

ls -la "${mount_point}"
}

cleanup() {
rmdir "$1"
}
Expand Down Expand Up @@ -493,14 +513,16 @@ case "${OSTYPE}" in
;;
esac

if endswith microsoft-standard "$(uname -r)"; then
echo This script does not work in WSL2.
exit 11
fi
if [[ -z $UPDATE_IMAGE ]] ; then
if endswith microsoft-standard "$(uname -r)"; then
echo This script does not work in WSL2.
exit 11
fi

if endswith Microsoft "$(uname -r)"; then
echo This script does not work in WSL1.
exit 11
if endswith Microsoft "$(uname -r)"; then
echo This script does not work in WSL1.
exit 11
fi
fi

check_requirements
Expand Down Expand Up @@ -538,14 +560,16 @@ if [ -n "${META_DATA}" ]; then
fi
fi

if [ -n "${FILE}" ]; then
http_download "$FILE" "flash.file"
FILE="$_RET"
if [ ! -f "${FILE}" ]; then
echo "File ${FILE} not found!"
exit 10
for i in ${FILE//,/ }; do
if [ -n "${i}" ]; then
http_download "$i" "flash.file"
i="$_RET"
if [ ! -f "${i}" ]; then
echo "File ${i} not found!"
exit 10
fi
fi
fi
done

if [ -n "${BOOT_CONF}" ]; then
http_download "$BOOT_CONF" "flash.config.txt"
Expand All @@ -565,7 +589,7 @@ if [ -n "${CONFIG_FILE}" ]; then
fi
fi

if [[ -z $CONFIGURE_ONLY ]] ; then
if [ -z $CONFIGURE_ONLY && -z $UPDATE_IMAGE ] ; then
if [ -f "/tmp/${filename}" ]; then
image=/tmp/${filename}
echo "Using cached image ${image}"
Expand Down Expand Up @@ -618,50 +642,50 @@ if [[ -z $CONFIGURE_ONLY ]] ; then
fi
fi

while true; do
disk="$DEVICE"
if [[ -z "${disk}" ]]; then
autodetect_device
disk="$_RET"

flash_image () {
while true; do
disk="$DEVICE"
if [[ -z "${disk}" ]]; then
show_devices
# shellcheck disable=SC2162
read -p "Please pick your device: "
disk="${REPLY}"
[[ ${disk} != /dev/* ]] && disk="/dev/${disk}"
autodetect_device
disk="$_RET"

if [[ -z "${disk}" ]]; then
show_devices
# shellcheck disable=SC2162
read -p "Please pick your device: "
disk="${REPLY}"
[[ ${disk} != /dev/* ]] && disk="/dev/${disk}"
fi
fi
if [[ -z "${FORCE}" ]]; then
while true; do
echo ""
read -rp "Is ${disk} correct? " yn
case $yn in
[Yy]* ) break;;
[Nn]* ) exit;;
* ) echo "Please answer yes or no.";;
esac
done
fi
fi
if [[ -z "${FORCE}" ]]; then
while true; do
echo ""
read -rp "Is ${disk} correct? " yn
case $yn in
[Yy]* ) break;;
[Nn]* ) exit;;
* ) echo "Please answer yes or no.";;
esac
done
fi

prepare_raw_disk "${disk}"
disk=$_RET
prepare_raw_disk "${disk}"
disk=$_RET

check_device_is_writable "${disk}"
writable=$_RET
check_device_is_writable "${disk}"
writable=$_RET

echo "Unmounting ${disk} ..."
umount_disk "${disk}"
echo "Unmounting ${disk} ..."
umount_disk "${disk}"

if [ "$writable" == "1" ]; then
break
else
play_warn
echo "The SD card is write protected. Please eject, remove protection and insert again."
fi
done
if [ "$writable" == "1" ]; then
break
else
play_warn
echo "The SD card is write protected. Please eject, remove protection and insert again."
fi
done

if [[ -z $CONFIGURE_ONLY ]] ; then
get_raw_device_filename "$disk"
rawdisk=$_RET

Expand All @@ -677,44 +701,52 @@ if [[ -z $CONFIGURE_ONLY ]] ; then
fi

wait_for_disk "${disk}"
fi
}

echo "Mounting Disk"
get_boot_mount_point "${disk}"
boot="$_RET"

echo "Mounting ${disk} to customize..."
mount_boot_disk "${disk}" "${boot}"
if [[ -z $UPDATE_IMAGE ]] ; then
echo "Mounting ${disk} to customize..."
mount_boot_disk "${disk}" "${boot}"
else
echo "Making copy of disk image"
cp ${image} "${image_copy}"
echo "Mounting ${disk} to customize..."
mount_image "${image_copy}" "${boot}"
fi

if [ -f "${CONFIG_FILE}" ]; then
if [[ "${CONFIG_FILE}" == *"occi"* ]]; then
echo "Copying ${CONFIG_FILE} to ${boot}/occidentalis.txt ..."
cp "${CONFIG_FILE}" "${boot}/occidentalis.txt"
else
echo "Copying ${CONFIG_FILE} to ${boot}/device-init.yaml ..."
cp "${CONFIG_FILE}" "${boot}/device-init.yaml"
fi
if [ -f "${CONFIG_FILE}" ]; then
if [[ "${CONFIG_FILE}" == *"occi"* ]]; then
echo "Copying ${CONFIG_FILE} to ${boot}/occidentalis.txt ..."
cp "${CONFIG_FILE}" "${boot}/occidentalis.txt"
else
echo "Copying ${CONFIG_FILE} to ${boot}/device-init.yaml ..."
cp "${CONFIG_FILE}" "${boot}/device-init.yaml"
fi
fi

if [[ -f "${BOOT_CONF}" ]]; then
echo "Copying ${BOOT_CONF} to ${boot}/config.txt ..."
cp "${BOOT_CONF}" "${boot}/config.txt"
fi
if [[ -f "${BOOT_CONF}" ]]; then
echo "Copying ${BOOT_CONF} to ${boot}/config.txt ..."
cp "${BOOT_CONF}" "${boot}/config.txt"
fi

if [ -f "${USER_DATA}" ]; then
echo "Copying cloud-init ${USER_DATA} to ${boot}/user-data ..."
cp "${USER_DATA}" "${boot}/user-data"
fi
if [ -f "${USER_DATA}" ]; then
echo "Copying cloud-init ${USER_DATA} to ${boot}/user-data ..."
cp "${USER_DATA}" "${boot}/user-data"
fi

if [ -f "${META_DATA}" ]; then
echo "Copying cloud-init ${META_DATA} to ${boot}/meta-data ..."
cp "${META_DATA}" "${boot}/meta-data"
fi
if [ -f "${META_DATA}" ]; then
echo "Copying cloud-init ${META_DATA} to ${boot}/meta-data ..."
cp "${META_DATA}" "${boot}/meta-data"
fi

if [ -f "${FILE}" ]; then
echo "Copying file ${FILE} to ${boot}/ ..."
cp "${FILE}" "${boot}/"
for i in ${FILE//,/ }; do
if [ -f "${i}" ]; then
echo "Copying file ${i} to ${boot}/ ..."
cp "${i}" "${boot}/"
fi
done

if [ -f "${boot}/device-init.yaml" ]; then
echo "Setting device-init"
Expand Down Expand Up @@ -780,11 +812,17 @@ if [ -f "${boot}/occidentalis.txt" ]; then
fi
fi

echo "Unmounting ${disk} ..."
sleep 5

set +e
detach "${disk}"
if [[ -z $UPDATE_IMAGE ]]; then
echo "Unmounting ${disk} ..."
sleep 5
set +e
detach "${disk}"
else
echo "Unmounting ${boot} ..."
sleep 5
set +e
sudo umount "${boot}"
fi

# shellcheck disable=SC2181
if [ $? -eq 0 ]; then
Expand Down