mirror of
https://github.com/linuxkit/linuxkit.git
synced 2025-07-22 18:41:37 +00:00
Add a formatting container
This is based on the code we used for Docker Editions, and will format an external drive, to be used for example for `/var` for Docker image persistence. It does not `mount` the drive yet, as splitting format and mount gives better modularity. Example yaml fragment: ``` - name: format image: "mobylinux/format:097d4f22b20f976b1f89d8f0b8a5d074d35b856c" binds: - /dev:/dev capabilities: - CAP_SYS_ADMIN - CAP_MKNOD ``` Signed-off-by: Justin Cormack <justin.cormack@docker.com>
This commit is contained in:
parent
3223897232
commit
8bcb2c9e0e
13
pkg/format/Dockerfile
Normal file
13
pkg/format/Dockerfile
Normal file
@ -0,0 +1,13 @@
|
||||
FROM alpine:3.5
|
||||
|
||||
RUN \
|
||||
apk update && apk upgrade -a && \
|
||||
apk add --no-cache \
|
||||
e2fsprogs \
|
||||
e2fsprogs-extra \
|
||||
jq \
|
||||
sfdisk \
|
||||
&& true
|
||||
|
||||
COPY . ./
|
||||
CMD ["/bin/sh", "/format.sh"]
|
29
pkg/format/Makefile
Normal file
29
pkg/format/Makefile
Normal file
@ -0,0 +1,29 @@
|
||||
.PHONY: tag push
|
||||
|
||||
BASE=alpine:3.5
|
||||
IMAGE=format
|
||||
|
||||
default: push
|
||||
|
||||
hash: Dockerfile format.sh
|
||||
DOCKER_CONTENT_TRUST=1 docker pull $(BASE)
|
||||
tar cf - $^ | docker build --no-cache -t $(IMAGE):build -
|
||||
docker run --rm --entrypoint /bin/sh $(IMAGE):build -c "cat $^ /lib/apk/db/installed | sha1sum" | sed 's/ .*//' > $@
|
||||
|
||||
push: hash
|
||||
docker pull mobylinux/$(IMAGE):$(shell cat hash) || \
|
||||
(docker tag $(IMAGE):build mobylinux/$(IMAGE):$(shell cat hash) && \
|
||||
docker push mobylinux/$(IMAGE):$(shell cat hash))
|
||||
docker rmi $(IMAGE):build
|
||||
rm -f hash
|
||||
|
||||
tag: hash
|
||||
docker pull mobylinux/$(IMAGE):$(shell cat hash) || \
|
||||
docker tag $(IMAGE):build mobylinux/$(IMAGE):$(shell cat hash)
|
||||
docker rmi $(IMAGE):build
|
||||
rm -f hash
|
||||
|
||||
clean:
|
||||
rm -f hash
|
||||
|
||||
.DELETE_ON_ERROR:
|
113
pkg/format/format.sh
Executable file
113
pkg/format/format.sh
Executable file
@ -0,0 +1,113 @@
|
||||
#!/bin/sh
|
||||
|
||||
# this script assumes anything on the disk can be removed if corrupted
|
||||
# other use cases may need different scripts.
|
||||
|
||||
# currently only supports ext4 but should be expanded
|
||||
|
||||
do_fsck()
|
||||
{
|
||||
# preen
|
||||
/sbin/e2fsck -p $*
|
||||
EXIT_CODE=$?
|
||||
# exit code 1 is errors corrected
|
||||
[ "${EXIT_CODE}" -eq 1 ] && EXIT_CODE=0
|
||||
# exit code 2 or 3 means need to reboot
|
||||
[ "${EXIT_CODE}" -eq 2 -o "${EXIT_CODE}" -eq 3 ] && /sbin/reboot
|
||||
# exit code 4 or over is fatal
|
||||
[ "${EXIT_CODE}" -lt 4 ] && return "${EXIT_CODE}"
|
||||
|
||||
# try harder
|
||||
/sbin/e2fsck -y $*
|
||||
# exit code 1 is errors corrected
|
||||
[ "${EXIT_CODE}" -eq 1 ] && EXIT_CODE=0
|
||||
# exit code 2 or 3 means need to reboot
|
||||
[ "${EXIT_CODE}" -eq 2 -o "${EXIT_CODE}" -eq 3 ] && /sbin/reboot
|
||||
# exit code 4 or over is fatal
|
||||
[ "${EXIT_CODE}" -ge 4 ] && printf "Filesystem unrecoverably corrupted, will reformat\n"
|
||||
|
||||
return "${EXIT_CODE}"
|
||||
}
|
||||
|
||||
do_fsck_extend_mount()
|
||||
{
|
||||
DRIVE="$1"
|
||||
DATA="$2"
|
||||
|
||||
do_fsck "$DATA" || return 1
|
||||
|
||||
# only try to extend if there is a single partition and free space
|
||||
PARTITIONS=$(sfdisk -J "$DRIVE" | jq '.partitiontable.partitions | length')
|
||||
|
||||
if [ "$PARTITIONS" -eq 1 ] && \
|
||||
sfdisk -F "$DRIVE" | grep -q 'Unpartitioned space' &&
|
||||
! sfdisk -F "$DRIVE" | grep -q '0 B, 0 bytes, 0 sectors'
|
||||
then
|
||||
SPACE=$(sfdisk -F "$DRIVE" | grep 'Unpartitioned space')
|
||||
printf "Resizing disk partition: $SPACE\n"
|
||||
|
||||
START=$(sfdisk -J "$DRIVE" | jq -e '.partitiontable.partitions | map(select(.type=="83")) | .[0].start')
|
||||
|
||||
sfdisk -q --delete "$DRIVE" 2> /dev/null
|
||||
echo "${START},,83;" | sfdisk -q "$DRIVE"
|
||||
|
||||
# set bootable flag
|
||||
sfdisk -A "$DRIVE" 1
|
||||
|
||||
# update status
|
||||
blockdev --rereadpt $diskdev 2> /dev/null
|
||||
mdev -s
|
||||
|
||||
# wait for device
|
||||
for i in $(seq 1 50); do test -b "$DATA" && break || sleep .1; mdev -s; done
|
||||
|
||||
# resize2fs fails unless we use -f here
|
||||
do_fsck -f "$DATA" || return 1
|
||||
resize2fs "$DATA"
|
||||
|
||||
do_fsck "$DATA" || return 1
|
||||
fi
|
||||
}
|
||||
|
||||
do_mkfs()
|
||||
{
|
||||
diskdev="$1"
|
||||
|
||||
# new disks does not have an DOS signature in sector 0
|
||||
# this makes sfdisk complain. We can workaround this by letting
|
||||
# fdisk create that DOS signature, by just do a "w", a write.
|
||||
# http://bugs.alpinelinux.org/issues/145
|
||||
echo "w" | fdisk $diskdev >/dev/null
|
||||
|
||||
# format one large partition
|
||||
echo ";" | sfdisk --quiet $diskdev
|
||||
|
||||
# update status
|
||||
blockdev --rereadpt $diskdev 2> /dev/null
|
||||
mdev -s
|
||||
|
||||
FSOPTS="-O resize_inode,has_journal,extent,huge_file,flex_bg,uninit_bg,64bit,dir_nlink,extra_isize"
|
||||
|
||||
mkfs.ext4 -q -F $FSOPTS ${diskdev}1
|
||||
}
|
||||
|
||||
# TODO fix for multiple disks, cdroms etc
|
||||
DEV="$(find /dev -maxdepth 1 -type b ! -name 'loop*' | grep -v '[0-9]$' | sed 's@.*/dev/@@' | sort | head -1 )"
|
||||
|
||||
[ -z "${DEV}" ] && exit 1
|
||||
|
||||
DRIVE="/dev/${DEV}"
|
||||
|
||||
# see if it has a partition table already
|
||||
if sfdisk -d "${DRIVE}" >/dev/null 2>/dev/null
|
||||
then
|
||||
DATA=$(sfdisk -J "$DRIVE" | jq -e -r '.partitiontable.partitions | map(select(.type=="83")) | .[0].node')
|
||||
if [ $? -eq 0 ]
|
||||
then
|
||||
do_fsck_extend_mount "$DRIVE" "$DATA" || do_mkfs "$DRIVE"
|
||||
else
|
||||
do_mkfs "$DRIVE"
|
||||
fi
|
||||
else
|
||||
do_mkfs "$DRIVE"
|
||||
fi
|
Loading…
Reference in New Issue
Block a user