mirror of https://github.com/lukechilds/umbrel.git
4 changed files with 173 additions and 32 deletions
@ -0,0 +1,144 @@ |
|||
#!/usr/bin/env bash |
|||
|
|||
set -euo pipefail |
|||
|
|||
# This script will: |
|||
# - Look for external storage devices |
|||
# - Check if they contain an Umbrel install |
|||
# - If yes |
|||
# - - Mount it |
|||
# - If no |
|||
# - - Format it |
|||
# - - Mount it |
|||
# - - Install Umbrel on it |
|||
# - Bind mount the external installation on top of the local installation |
|||
|
|||
UMBREL_ROOT="$(readlink -f $(dirname "${BASH_SOURCE[0]}")/../..)" |
|||
MOUNT_POINT="/mnt/data" |
|||
EXTERNAL_UMBREL_ROOT="${MOUNT_POINT}/umbrel" |
|||
|
|||
check_root () { |
|||
if [[ $UID != 0 ]]; then |
|||
echo "This script must be run as root" |
|||
exit 1 |
|||
fi |
|||
} |
|||
|
|||
check_dependencies () { |
|||
for cmd in "$@"; do |
|||
if ! command -v $cmd >/dev/null 2>&1; then |
|||
echo "This script requires \"${cmd}\" to be installed" |
|||
exit 1 |
|||
fi |
|||
done |
|||
} |
|||
|
|||
# Returns a list of block device paths |
|||
list_block_devices () { |
|||
# We use "2>/dev/null || true" to swallow errors if there are |
|||
# no block devices. In that case the function just returns nothing |
|||
# instead of an error which is what we want. |
|||
# |
|||
# sed 's!.*/!!' is to return the device path so we get sda |
|||
# instead of /sys/block/sda |
|||
(ls -d /sys/block/sd* 2>/dev/null || true) | sed 's!.*/!!' |
|||
} |
|||
|
|||
# Returns the vendor and model name of a block device |
|||
get_block_device_model () { |
|||
device="${1}" |
|||
vendor=$(cat "/sys/block/${device}/device/vendor") |
|||
model=$(cat "/sys/block/${device}/device/model") |
|||
|
|||
# We echo in a subshell without quotes to strip surrounding whitespace |
|||
echo "$(echo $vendor) $(echo $model)" |
|||
} |
|||
|
|||
# Wipes a block device and reformats it with a single EXT4 partition |
|||
format_block_device () { |
|||
device="${1}" |
|||
device_path="/dev/${device}" |
|||
partition_path="${device_path}1" |
|||
wipefs -a "${device_path}" |
|||
parted --script "${device_path}" mklabel gpt |
|||
parted --script "${device_path}" mkpart primary ext4 0% 100% |
|||
# We need to run sync here to make sure the filesystem is reflecting the |
|||
# the latest changes in /dev/* |
|||
sync |
|||
mkfs.ext4 -F -L umbrel "${partition_path}" |
|||
} |
|||
|
|||
# Mounts the device given in the first argument at $MOUNT_POINT |
|||
mount_partition () { |
|||
partition_path="${1}" |
|||
mkdir -p "${MOUNT_POINT}" |
|||
mount "${partition_path}" "${MOUNT_POINT}" |
|||
} |
|||
|
|||
# Unmounts $MOUNT_POINT |
|||
unmount_partition () { |
|||
umount "${MOUNT_POINT}" |
|||
} |
|||
|
|||
main () { |
|||
echo "Running external storage mount script..." |
|||
check_root |
|||
check_dependencies sed wipefs parted mount sync |
|||
|
|||
block_devices=$(list_block_devices) |
|||
no_of_block_devices=$(list_block_devices | wc -l) |
|||
|
|||
if [[ $no_of_block_devices -lt 1 ]]; then |
|||
echo "No block devices found" |
|||
echo "Exiting mount script without doing anything" |
|||
exit |
|||
fi |
|||
|
|||
if [[ $no_of_block_devices -gt 1 ]]; then |
|||
echo "Multiple block devices found, only one drive is supported" |
|||
echo "Exiting mount script without doing anything" |
|||
exit 1 |
|||
fi |
|||
|
|||
# At this point we know there is only one block device attached |
|||
block_device=$block_devices |
|||
partition_path="/dev/${block_device}1" |
|||
block_device_model=$(get_block_device_model $block_device) |
|||
echo "Found device \"${block_device_model}\"" |
|||
|
|||
echo "Checking if device contains an Umbrel install..." |
|||
mount_partition "${partition_path}" |
|||
if [[ -f "${EXTERNAL_UMBREL_ROOT}"/.umbrel ]]; then |
|||
echo "Yes, it does" |
|||
else |
|||
echo "No, it doesn't" |
|||
|
|||
echo "Unmounting partition..." |
|||
unmount_partition |
|||
|
|||
echo "Formatting device..." |
|||
format_block_device $block_device |
|||
|
|||
echo "Mounting partition..." |
|||
mount_partition "${partition_path}" |
|||
|
|||
echo "Copying Umbrel install to external storage..." |
|||
mkdir -p "${EXTERNAL_UMBREL_ROOT}" |
|||
cp --recursive \ |
|||
--archive \ |
|||
--no-target-directory \ |
|||
"${UMBREL_ROOT}" "${EXTERNAL_UMBREL_ROOT}" |
|||
fi |
|||
|
|||
echo "Bind mounting external storage over local Umbrel installation..." |
|||
mount --bind "${EXTERNAL_UMBREL_ROOT}" "${UMBREL_ROOT}" |
|||
|
|||
echo "Checking Umbrel root is now on external storage..." |
|||
sync |
|||
sleep 1 |
|||
"${UMBREL_ROOT}/scripts/umbrel-os/is-on-external-storage" |
|||
|
|||
echo "Mount script completed successfully!" |
|||
} |
|||
|
|||
main |
@ -0,0 +1,10 @@ |
|||
#!/usr/bin/env bash |
|||
|
|||
set -euo pipefail |
|||
|
|||
# This script returns a non-zero exit code if $UMBREL_ROOT is NOT |
|||
# mounted on external storage. |
|||
|
|||
UMBREL_ROOT="$(readlink -f $(dirname "${BASH_SOURCE[0]}")/../..)" |
|||
|
|||
df -h "${UMBREL_ROOT}" | grep --quiet '/dev/sd' |
Loading…
Reference in new issue