core: 初步实现 cloud image

This commit is contained in:
bin456789 2023-07-18 00:22:51 +08:00
parent 9c78006b9e
commit 5008114096
No known key found for this signature in database
GPG Key ID: EE301B386DE6C11B
2 changed files with 229 additions and 81 deletions

View File

@ -54,6 +54,10 @@ is_in_arch() {
[ -f /etc/arch-release ]
}
is_use_cloud_image() {
[ -n "$cloud_image" ] && [ "$cloud_image" = 1 ]
}
is_host_has_ipv4_and_ipv6() {
install_pkg dig
# dig会显示cname结果cname结果以.结尾grep -v '\.$' 用于去除 cname 结果
@ -178,16 +182,24 @@ setos() {
}
setos_debian() {
if [ "$localtest" = 1 ]; then
mirror=$confhome/debian/install.amd
eval ${step}_vmlinuz=$mirror/vmlinuz
eval ${step}_initrd=$mirror/initrd.gz
else
case "$releasever" in
12) codename=bookworm ;;
11) codename=bullseye ;;
10) codename=buster ;;
esac
if is_use_cloud_image; then
# cloud image
ci_mirror=https://cloud.debian.org/images/cloud
is_virt && ci_type=genericcloud || ci_type=generic
eval ${step}_img=$ci_mirror/$codename/latest/debian-$releasever-$ci_type-$basearch_alt.qcow2
else
# 传统安装
if [ "$localtest" = 1 ]; then
mirror=$confhome/debian/install.amd
eval ${step}_vmlinuz=$mirror/vmlinuz
eval ${step}_initrd=$mirror/initrd.gz
else
if is_in_china; then
hostname=ftp.cn.debian.org
else
@ -198,30 +210,46 @@ setos() {
eval ${step}_initrd=$mirror/initrd.gz
fi
eval ${step}_ks=$confhome/preseed.cfg
fi
}
setos_ubuntu() {
if is_use_cloud_image; then
# cloud image
# TODO: Minimal 镜像
if is_in_china; then
ci_mirror=https://mirror.nju.edu.cn/ubuntu-cloud-images/releases
else
ci_mirror=https://cloud-images.ubuntu.com/releases/$releasever/release
fi
eval ${step}_img=$ci_mirror/ubuntu-$releasever-server-cloudimg-$basearch_alt.img
else
# 传统安装
if [ "$localtest" = 1 ]; then
mirror=$confhome/
else
if is_in_china; then
case "$basearch" in
"x86_64") mirror=https://mirrors.tuna.tsinghua.edu.cn/ubuntu-releases/$releasever/ ;;
"aarch64") mirror=https://mirrors.tuna.tsinghua.edu.cn/ubuntu-cdimage/releases/$releasever/release/ ;;
"x86_64") mirror=https://mirrors.tuna.tsinghua.edu.cn/ubuntu-releases/$releasever ;;
"aarch64") mirror=https://mirrors.tuna.tsinghua.edu.cn/ubuntu-cdimage/releases/$releasever/release ;;
esac
else
case "$basearch" in
"x86_64") mirror=https://releases.ubuntu.com/$releasever/ ;;
"aarch64") mirror=https://cdimage.ubuntu.com/releases/$releasever/release/ ;;
"x86_64") mirror=https://releases.ubuntu.com/$releasever ;;
"aarch64") mirror=https://cdimage.ubuntu.com/releases/$releasever/release ;;
esac
fi
fi
filename=$(curl $mirror | grep -oP "ubuntu-$releasever.*?-live-server-$basearch_alt.iso" | head -1)
iso=$mirror$filename
# iso
filename=$(curl -L $mirror | grep -oP "ubuntu-$releasever.*?-live-server-$basearch_alt.iso" | head -1)
iso=$mirror/$filename
test_url $iso iso || exit 1
eval ${step}_iso=$iso
# ks
eval ${step}_ks=$confhome/user-data
fi
}
setos_windows() {
@ -249,6 +277,41 @@ setos() {
}
setos_redhat() {
if is_use_cloud_image; then
# ci
[ "$distro" = "centos" ] && [ "$releasever" = "7" ] && stream_suffix="" || stream_suffix="-stream"
if is_in_china; then
case $distro in
"centos") ci_mirror="https://mirror.nju.edu.cn/centos-cloud/centos" ;;
"alma") ci_mirror="https://mirror.nju.edu.cn/almalinux/$releasever/cloud/$basearch/images" ;;
"rocky") ci_mirror="https://mirror.nju.edu.cn/rocky/$releasever/images/$basearch" ;;
"fedora") ci_mirror="https://mirror.nju.edu.cn/fedora/releases/$releasever/Cloud/$basearch/images" ;;
esac
else
case $distro in
"centos") ci_mirror="https://cloud.centos.org/centos" ;;
"alma") ci_mirror="https://repo.almalinux.org/almalinux/$releasever/cloud/$basearch/images" ;;
"rocky") ci_mirror="https://download.rockylinux.org/pub/rocky/$releasever/images/$basearch" ;;
"fedora") ci_mirror="https://download.fedoraproject.org/pub/fedora/linux/releases/$releasever/Cloud/$basearch/images" ;;
esac
fi
case $distro in
"centos")
case $releasever in
"7") ci_image=$ci_mirror/$releasever$stream_suffix/images/CentOS-7-$basearch-GenericCloud.qcow2 ;;
"8" | "9") ci_image=$ci_mirror/$releasever$stream_suffix/$basearch/images/CentOS-Stream-GenericCloud-$releasever-latest.$basearch.qcow2 ;;
esac
;;
# TODO: alma8 有独立的uefi镜像
"alma") ci_image=$ci_mirror/AlmaLinux-$releasever-GenericCloud-latest.$basearch.qcow2 ;;
"rocky") ci_image=$ci_mirror/Rocky-$releasever-GenericCloud-Base.latest.$basearch.qcow2 ;;
# TODO: 小版本号
"fedora") ci_image=$ci_mirror/Fedora-Cloud-Base-$releasever-1.6.$basearch.qcow2 ;;
esac
eval ${step}_img=${ci_image}
else
# 传统安装
if [ "$localtest" = 1 ]; then
mirror=$confhome/$releasever/
else
@ -264,6 +327,7 @@ setos() {
"rocky") mirrorlist="https://mirrors.rockylinux.org/mirrorlist?arch=$basearch&repo=BaseOS-$releasever" ;;
"fedora") mirrorlist="https://mirrors.fedoraproject.org/mirrorlist?arch=$basearch&repo=fedora-$releasever" ;;
esac
# rocky/centos9 需要删除第一行注释, alma 需要替换$basearch
for cur_mirror in $(curl -L $mirrorlist | sed "/^#/d" | sed "s,\$basearch,$basearch,"); do
host=$(get_host_by_url $cur_mirror)
@ -273,19 +337,22 @@ setos() {
break
fi
done
if [ -z "$mirror" ]; then
error_and_exit "All mirror failed."
fi
eval "${step}_mirrorlist='${mirrorlist}'"
fi
eval ${step}_ks=$confhome/ks.cfg
eval ${step}_vmlinuz=${mirror}images/pxeboot/vmlinuz
eval ${step}_initrd=${mirror}images/pxeboot/initrd.img
eval ${step}_squashfs=${mirror}images/install.img
if [ "$releasever" = 7 ]; then
eval ${step}_squashfs=${mirror}LiveOS/squashfs.img
fi
fi
}
eval ${step}_distro=$distro
@ -401,9 +468,17 @@ check_ram() {
error_and_exit "Could not detect RAM size."
fi
# ram 足够就用普通方法安装否则如果内存大于512就用 cloud image
if [ $ram_size -lt $ram_requirement ]; then
# TODO: 测试 256 384 内存
ram_requirement=512
if false && [ $ram_size -ge $ram_requirement ]; then
info "RAM < $ram_requirement MB. Switch to cloud image mode"
cloud_image=1
else
error_and_exit "Could not install $distro: RAM < $ram_requirement MB."
fi
fi
}
is_efi() {
@ -511,7 +586,7 @@ if ! is_in_windows; then
fi
# 整理参数
if ! opts=$(getopt -n $0 -o "" --long localtest,debug,sleep:,iso:,image-name:,img: -- "$@"); then
if ! opts=$(getopt -n $0 -o "" --long localtest,debug,sleep:,iso:,image-name:,img:,ci,cloud-image -- "$@"); then
usage_and_exit
fi
@ -528,6 +603,10 @@ while true; do
set -x
shift
;;
--ci | --cloud-image)
cloud_image=1
shift
;;
--sleep)
sleep=$2
shift 2
@ -571,7 +650,9 @@ if is_in_alpine; then
fi
# 检查内存
check_ram
if ! is_use_cloud_image; then
check_ram
fi
# 检查硬件架构
# x86强制使用x64
@ -586,10 +667,12 @@ esac
set_github_proxy
# 以下目标系统需要进入alpine环境安装
# ubuntu/alpine
# cloud image
# ubuntu/alpine/windows/dd
# el8/9/fedora 任何架构 <2g
# el7 aarch64 <1.5g
if [ "$distro" = "ubuntu" ] ||
if is_use_cloud_image ||
[ "$distro" = "ubuntu" ] ||
[ "$distro" = "alpine" ] ||
[ "$distro" = "windows" ] ||
[ "$distro" = "dd" ] ||
@ -603,9 +686,14 @@ else
setos nextos $distro $releasever
fi
# 下载启动内核
# shellcheck disable=SC2154
{
# 测试 cloud img 链接
if is_use_cloud_image; then
test_url $finalos_img
fi
# 下载 nextos 内核
info download vmlnuz and initrd
echo $nextos_vmlinuz
curl -Lo /reinstall-vmlinuz $nextos_vmlinuz
@ -628,7 +716,7 @@ build_finalos_cmdline() {
}
build_extra_cmdline() {
for key in localtest confhome sleep; do
for key in localtest confhome sleep cloud_image; do
value=${!key}
if [ -n "$value" ]; then
extra_cmdline+=" extra.$key='$value'"

View File

@ -78,6 +78,10 @@ is_efi() {
[ -d /sys/firmware/efi/ ]
}
is_use_cloud_image() {
[ -n "$cloud_image" ] && [ "$cloud_image" = 1 ]
}
setup_nginx() {
apk add nginx
cat <<EOF >/etc/nginx/http.d/default.conf
@ -323,6 +327,14 @@ if [ "$distro" = windows ]; then
mkfs.ext4 -F -L os /dev/$xda*1 #1 os
mkfs.ntfs -f -F -L installer /dev/$xda*2 #2 installer
fi
elif is_use_cloud_image; then
parted /dev/$xda -s -- \
mklabel gpt \
mkpart '" "' ext4 1MiB -1GiB \
mkpart '" "' ext4 -1GiB 100%
update_part /dev/$xda
mkfs.ext4 -F -L os /dev/$xda*1 #1 os
mkfs.ext4 -F -L installer /dev/$xda*2 #2 installer
else
# 对于红帽系是临时分区表,安装时除了 installer 分区,其他分区会重建为默认的大小
# 对于ubuntu是最终分区表因为 ubuntu 的安装器不能调整个别分区,只能重建整个分区表
@ -366,20 +378,68 @@ fi
update_part /dev/$xda
# 挂载主分区
mkdir -p /os
mount /dev/disk/by-label/os /os
if is_use_cloud_image; then
apk add qemu-img
# 挂载其他分区
mkdir -p /os/boot/efi
if is_efi; then
mkdir -p /installer
mount /dev/disk/by-label/installer /installer
qcow_file=/installer/cloud_image.qcow2
download $img $qcow_file
# qcow_virtualx_size=$(qemu-img info $qcow_file | grep 'virtual size' | grep -oE '[0-9]+' | tail -1)
# TODO: centos dd 需要 8g 空间,改成手动释放文件
if true; then
modprobe nbd
qemu-nbd -c /dev/nbd0 $qcow_file
# 将前1M dd到内存
dd if=/dev/nbd0 of=/first-1M bs=1M count=1
# 将1M之后 dd到硬盘
case 3 in
1)
# BusyBox dd
dd if=/dev/nbd0 of=/dev/$xda bs=1M skip=1 seek=1
;;
2)
# 用原版 dd status=progress但没有进度和剩余时间
apk add coreutils
dd if=/dev/nbd0 of=/dev/$xda bs=1M skip=1 seek=1 status=progress
;;
3)
# 用 pv
apk add pv
pv -f /dev/nbd0 | dd of=/dev/$xda bs=1M skip=1 seek=1 iflag=fullblock
;;
esac
qemu-nbd -d /dev/nbd0
else
# 将前1M dd到内存将1M之后 dd到硬盘
qemu-img dd if=$qcow_file of=/first-1M bs=1M count=1
qemu-img dd if=$qcow_file of=/dev/disk/by-label/os bs=1M skip=1
fi
# 将前1M从内存 dd 到硬盘
umount /installer/
dd if=/first-1M of=/dev/$xda
update_part /dev/$xda
exit
else
# 挂载主分区
mkdir -p /os
mount /dev/disk/by-label/os /os
# 挂载其他分区
mkdir -p /os/boot/efi
if is_efi; then
mount /dev/disk/by-label/efi /os/boot/efi
fi
mkdir -p /os/installer
if [ "$distro" = windows ]; then
fi
mkdir -p /os/installer
if [ "$distro" = windows ]; then
mount_args="-t ntfs3"
fi
mount $mount_args /dev/disk/by-label/installer /os/installer
fi
mount $mount_args /dev/disk/by-label/installer /os/installer
# shellcheck disable=SC2154
if [ "$distro" = "windows" ]; then