Skip to content

Conversation

@luhengsw
Copy link

@luhengsw luhengsw commented Feb 4, 2026

reinstall.sh dd --img 添加 --cloud-data 选项,支持在 dd 镜像写入磁盘后自动配置 cloud-init NoCloud
数据源,采用标准的cloud-init配置流水线(区别于--ci模式通过脚本直接改写网络等操作)

合并原因和目的

问题背景

当前使用 dd --img 部署cloud-image的时候,无法便捷地注入 标准cloud-init 配置工作流

解决方案价值

  1. 自动化部署:支持通过 cloud-init 标准工作流的配置。
  2. 标准化接口:采用 cloud-init NoCloud 数据源,兼容所有支持 cloud-init 的 Linux 发行版。
  3. 灵活性:支持本地目录和远程 URL 两种方式提供配置文件。

影响范围

  • 新增功能:不影响现有任何功能
  • 向后兼容:未使用 --cloud-data 时行为完全不变
  • 代码质量:遵循现有代码风格,注释清晰

实现内容

1. reinstall.sh 修改(3处)

添加 --cloud-data 选项解析

  • 新增 getopt 长选项 cloud-data:
  • 解析并保存到 $cloud_data 变量

在 host 端收集并打包配置文件

  • 支持本地目录:直接复制 user-datameta-datanetwork-config 文件
  • 支持远程 URL:在 host 上下载上述文件
  • 统一打包到 initrd 的 /configs/cloud-data/ 目录
  • 校验:至少必须包含 user-data 文件

2. trans.sh 修改(3处)

新增 setup_nocloud() 函数

实现 NoCloud 数据源配置:

  1. 写入 /etc/cloud/cloud.cfg.d/99-datasource.cfg 指定 NoCloud 数据源
  2. 复制 seed 文件到 /var/lib/cloud/seed/nocloud/
  3. 移除 cloud-init.disabled 禁用标记
  4. 清除旧的 cloud-init 状态,确保首次启动重新执行

扩展 modify_os_on_disk() 支持 nocloud 模式

  • 修改 dd linux 早退逻辑,nocloud 模式下继续处理
  • 复用现有的分区挂载逻辑
  • 新增 nocloud 分支调用 setup_nocloud()
  • 添加显式 umount /os 确保清理

集成到 dd 工作流

  • dd_raw_with_extract 后检查 /configs/cloud-data 是否存在
  • 如存在则调用 modify_os_on_disk nocloud 进行配置

使用方法

# 本地配置目录
bash reinstall.sh dd --img "https://cloud-images.ubuntu.com/xxx.img" --cloud-data /tmp/seed/

# 远程配置 URL
bash reinstall.sh dd --img "https://cloud-images.ubuntu.com/xxx.img" --cloud-data "http://server/seed/"

配置目录/URL 需包含:

  • user-data(必需):cloud-init 用户配置
  • meta-data(可选):实例元数据
  • network-config(可选):网络配置

配置示例

# user-data
#cloud-config
password: mypassword
chpasswd: { expire: false }
ssh_pwauth: true
ssh_authorized_keys:
  - ssh-rsa AAAAB3NzaC1yc2E...
# meta-data
instance-id: server-001
local-hostname: myserver

技术细节

  1. host 端统一处理:所有下载和打包在 host 完成,Alpine 仅负责复制
  2. 不修改用户文件:直接使用用户提供的配置,不做任何修改
  3. 复用现有逻辑:复用 modify_os_on_disk 的挂载和遍历逻辑
  4. 兼容性好:不影响现有的 dd windows 和 dd linux 流程

执行流程

[Host] 解析 --cloud-data → 下载/收集文件 → 打包进 initrd
  ↓
[Alpine] dd 写入镜像 → 检测 /configs/cloud-data
  ↓
[Alpine] 挂载目标系统 → 配置 NoCloud → 复制 seed 文件
  ↓
[Target] 首次启动 → cloud-init 读取 NoCloud → 执行自动配置

@gemini-code-assist
Copy link

Summary of Changes

Hello @luhengsw, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

此拉取请求旨在增强 reinstall.sh 脚本的 dd --img 功能,使其能够自动化配置通过 dd 写入的云镜像。通过引入 --cloud-data 选项和集成 cloud-init 的 NoCloud 数据源,用户现在可以便捷地注入标准 cloud-init 配置,从而实现云镜像的自动化部署和标准化初始化。

Highlights

  • 新增 --cloud-data 选项: 为 reinstall.sh dd --img 命令新增 --cloud-data 选项,支持自动化配置 cloud-init NoCloud 数据源。
  • Host 端文件收集与打包: 实现在 host 端收集 user-datameta-datanetwork-config 文件(支持本地目录或远程 URL),并将其打包到 initrd 的 /configs/cloud-data/ 目录中,并校验 user-data 文件的存在。
  • NoCloud 配置函数: trans.sh 新增 setup_nocloud 函数,用于在目标系统上配置 NoCloud 数据源、复制 seed 文件、确保 cloud-init 启用并清除旧状态。
  • 扩展 modify_os_on_disk: 扩展 modify_os_on_disk 函数,使其在 nocloud 模式下能够处理 dd 写入的 Linux 镜像,并调用 setup_nocloud 进行配置。
  • 集成自动化配置流程: 将 NoCloud 配置流程集成到 dd_raw_with_extract 工作流中,实现云镜像的自动化初始配置。

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • reinstall.sh
    • 更新了 confhome 变量的 URL。
    • 新增逻辑以解析 --cloud-data 选项,并将指定目录或 URL 中的 user-datameta-datanetwork-config 文件收集并打包到 initrd 的 /configs/cloud-data/ 目录中。
    • 添加了对 user-data 文件存在的校验。
    • getopt 选项列表中添加了 cloud-data:
  • trans.sh
    • 新增 setup_nocloud() 函数,负责在目标文件系统上配置 cloud-init 的 NoCloud 数据源,包括创建配置文件、复制 seed 文件、移除 cloud-init.disabled 标记以及清除旧的 cloud-init 状态。
    • 修改 modify_os_on_disk() 函数,使其在 dd linux 模式下,如果指定了 nocloud 进程,则不再提前返回,并新增分支调用 setup_nocloud() 函数。
    • trans() 函数的 dd_raw_with_extract 之后,添加了检查 /configs/cloud-data 是否存在的逻辑,如果存在则调用 modify_os_on_disk nocloud 来触发 NoCloud 配置。
Activity
  • 目前没有与此拉取请求相关的活动信息。
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

本次 PR 添加了 --cloud-data 选项,用于在 dd 镜像时自动配置 cloud-init NoCloud 数据源,这是一个非常有价值的功能,增强了云镜像部署的自动化能力。代码实现思路清晰,在 host 端处理文件收集,在 Alpine initrd 中完成配置,复用了现有逻辑,整体设计良好。

我发现了一些可以改进的地方:

  1. 一个关键的配置 confhome 指向了个人开发分支,这在合并前需要修正。
  2. 在处理本地 --cloud-data 目录时,文件复制命令在目录为空的情况下会提前报错,可以优化以提供更友好的错误提示。
  3. 脚本中有几处文件路径变量未加引号,虽然在当前上下文中可能不会出错,但为了代码的健壮性建议修复。

具体的修改建议请见代码行评论。总体来说,这是一个很棒的改进!

I am having trouble creating individual review comments. Click here to see my feedback.

reinstall.sh (6)

critical

confhome URL 指向了个人的开发分支。在合并之前,请务必将其改回主仓库的 URL,以确保脚本的稳定性和安全性。

confhome=https://raw.githubusercontent.com/bin456789/reinstall/main

reinstall.sh (3754)

high

$cloud_data 是一个空目录时,cp "$cloud_data"/* 命令中的 glob 模式 * 将不会匹配任何文件。由于脚本设置了 set -e,这会导致 cp 命令因找不到文件而失败,从而中断整个脚本。建议使用 shopt -s nullglob 来优雅地处理空目录的情况,这样如果目录为空,cp 命令将不会执行,脚本会继续执行到后面的 user-data 文件校验逻辑,从而给出更明确的错误信息。

            (shopt -s nullglob; cp "$cloud_data"/* $initrd_dir/configs/cloud-data/)

reinstall.sh (3758)

medium

curl 命令的 -o 选项指定输出文件时,文件路径 $initrd_dir/configs/cloud-data/$f 没有被引号包围。虽然目前 $initrd_dir 的值 /reinstall-tmp/initrd 不包含空格,但为了代码的健壮性和未来的可维护性,建议为所有包含变量的文件路径添加引号。

                curl -sSfL "$cloud_data/$f" -o "$initrd_dir/configs/cloud-data/$f" 2>/dev/null || true

trans.sh (3801)

medium

setup_nocloud 函数中,多处使用了 $os_dir 变量来构建文件路径,但没有用引号包围。如果 $os_dir 路径中包含空格或特殊字符,这可能会导致命令执行失败。为了增强脚本的健壮性,建议将所有用作路径的变量都用双引号包围。此问题在本函数中多处存在。

    mkdir -p "$os_dir/etc/cloud/cloud.cfg.d"

@luhengsw
Copy link
Author

luhengsw commented Feb 4, 2026

测试结果

情况 1:目录有文件

✅ 使用 nullglob:正常复制
✅ 不用 nullglob:正常复制

情况 2:空目录

❌ 使用 nullglob:
cp: missing destination file operand after '/tmp/test-nullglob/dest/'
脚本立即退出(set -e)

❌ 不用 nullglob:
cp: cannot stat '/tmp/test-nullglob/empty/*': No such file or directory
脚本立即退出(set -e)

发现的问题

Review 意见有误!它说:
"脚本会继续执行到后面的 user-data 文件校验逻辑"

但实际上:

  • 空目录时,无论是否使用 nullglob,cp 都会失败
  • 脚本都会因为 set -e 立即退出
  • 都不会执行到后面的校验逻辑

唯一的区别是错误信息:

  • 不用 nullglob: cannot stat '/path/*': No such file or directory
  • 用 nullglob: missing destination file operand

结论

使用 nullglob:

  • ✅ 不会引入新的 bug(有文件时行为一样)
  • ✅ 不会引入逻辑错误(空目录时都会失败)
  • ⚠️ 但也没有达到 review 说的效果(无法继续执行到校验逻辑)
  • ⚠️ 错误信息反而更晦涩("missing destination file operand" 不如 "cannot stat")

建议:去掉 nullglob,因为它没有实际好处,反而让错误信息更不清楚。

@luhengsw
Copy link
Author

luhengsw commented Feb 9, 2026

Addressed all review comments, ready for another look

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants