Skip to content

Commit bc9e722

Browse files
authored
Merge pull request #34 from dhslove/codex/v2k-cutover-sata-fallback
v2k cutover 부트스트랩 실패 시 SATA fallback 추가
2 parents 656638f + af38c5d commit bc9e722

6 files changed

Lines changed: 160 additions & 40 deletions

File tree

.github/workflows/build.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -292,14 +292,14 @@ jobs:
292292
if [[ "${ROCKY_MINOR}" == "9.6" ]]; then
293293
REPO_ROOT="https://dl.rockylinux.org/vault/rocky/${ROCKY_MINOR}"
294294
elif [[ "${ROCKY_MINOR}" == "9.7" ]]; then
295-
REPO_ROOT="https://dl.rockylinux.org/pub/rocky/${ROCKY_MINOR}"
295+
REPO_ROOT="https://dl.rockylinux.org/vault/rocky/${ROCKY_MINOR}"
296296
else
297297
echo "[ERR] Unsupported Rocky minor for V2K build: ${ROCKY_MINOR}" >&2
298298
exit 2
299299
fi
300300
301301
# Keep V2K build inputs pinned to the intended Rocky minor.
302-
# 9.6 uses vault; 9.7 uses the normal public tree.
302+
# 9.6 and 9.7 use vault because fixed minor trees may be removed from pub.
303303
cat > "/etc/yum.repos.d/${REPO_PREFIX}.repo" <<EOF
304304
[${REPO_PREFIX}-baseos]
305305
name=Rocky Linux ${ROCKY_MINOR} - BaseOS
@@ -338,7 +338,7 @@ jobs:
338338
if [[ "${ROCKY_MINOR}" == "9.6" ]]; then
339339
REPO_ROOT="https://dl.rockylinux.org/vault/rocky/${ROCKY_MINOR}"
340340
elif [[ "${ROCKY_MINOR}" == "9.7" ]]; then
341-
REPO_ROOT="https://dl.rockylinux.org/pub/rocky/${ROCKY_MINOR}"
341+
REPO_ROOT="https://dl.rockylinux.org/vault/rocky/${ROCKY_MINOR}"
342342
else
343343
echo "[ERR] Unsupported Rocky minor for V2K build: ${ROCKY_MINOR}" >&2
344344
exit 2
@@ -577,7 +577,7 @@ jobs:
577577
if [[ "${ROCKY_MINOR}" == "9.6" ]]; then
578578
REPO_ROOT="https://dl.rockylinux.org/vault/rocky/${ROCKY_MINOR}"
579579
elif [[ "${ROCKY_MINOR}" == "9.7" ]]; then
580-
REPO_ROOT="https://dl.rockylinux.org/pub/rocky/${ROCKY_MINOR}"
580+
REPO_ROOT="https://dl.rockylinux.org/vault/rocky/${ROCKY_MINOR}"
581581
else
582582
echo "[ERR] Unsupported Rocky minor for N2K build: ${ROCKY_MINOR}" >&2
583583
exit 2

bin/ablestack_v2k.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,8 @@ Options:
412412
--winpe-timeout <SEC> Default: 600
413413
--linux-bootstrap Default: auto for Linux guests
414414
--no-linux-bootstrap
415+
--bootstrap-fallback sata|off Default: sata
416+
--no-bootstrap-fallback Same as --bootstrap-fallback off
415417
--safe-mode Default: off
416418
--force-cleanup Default: off
417419

completions/ablestack_v2k

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,13 @@ _ablestack_v2k()
264264
;;
265265

266266
cutover)
267+
case "${prev}" in
268+
--bootstrap-fallback)
269+
COMPREPLY=( $(compgen -W "sata off" -- "${cur}") )
270+
return 0
271+
;;
272+
esac
273+
267274
local -a cutover_opts=(
268275
--shutdown --shutdown-force --shutdown-timeout
269276
--define-only --apply --start
@@ -272,6 +279,7 @@ _ablestack_v2k()
272279
--winpe-bootstrap --no-winpe-bootstrap
273280
--winpe-iso --virtio-iso --winpe-timeout
274281
--linux-bootstrap --no-linux-bootstrap
282+
--bootstrap-fallback --no-bootstrap-fallback
275283
--safe-mode
276284
--force-cleanup
277285
--target-provider

lib/v2k/engine.sh

Lines changed: 120 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2540,6 +2540,65 @@ v2k_cloud_windows_winpe_bootstrap() {
25402540
v2k_windows_winpe_bootstrap_libvirt "${tmp_manifest}" "${tmp_vm}" "${winpe_iso}" "${virtio_iso}" "${winpe_timeout}" 1
25412541
}
25422542

2543+
v2k_bootstrap_fallback_enabled() {
2544+
local policy="${1:-sata}"
2545+
case "${policy}" in
2546+
sata|auto|"") return 0 ;;
2547+
off|none|false|0) return 1 ;;
2548+
*)
2549+
echo "Invalid bootstrap fallback policy: ${policy}" >&2
2550+
return 2
2551+
;;
2552+
esac
2553+
}
2554+
2555+
v2k_select_bootstrap_fallback() {
2556+
local manifest="$1" phase="$2" code="$3" reason="$4" policy="${5:-sata}"
2557+
local bus="sata"
2558+
2559+
if ! v2k_bootstrap_fallback_enabled "${policy}"; then
2560+
return 1
2561+
fi
2562+
2563+
v2k_manifest_runtime_set "${manifest}" ".bootstrap_fallback" \
2564+
"$(jq -nc \
2565+
--arg bus "${bus}" \
2566+
--arg phase "${phase}" \
2567+
--arg reason "${reason}" \
2568+
--argjson code "${code}" \
2569+
'{enabled:true,bus:$bus,phase:$phase,code:$code,reason:$reason}')" || true
2570+
v2k_event WARN "cutover" "" "bootstrap_fallback_selected" \
2571+
"$(jq -nc \
2572+
--arg bus "${bus}" \
2573+
--arg phase "${phase}" \
2574+
--arg reason "${reason}" \
2575+
--argjson code "${code}" \
2576+
'{bus:$bus,phase:$phase,code:$code,reason:$reason}')" || true
2577+
if [[ "${V2K_JSON_OUT:-0}" -ne 1 ]]; then
2578+
echo "[v2k] ${reason}. Falling back to SATA disk controller."
2579+
fi
2580+
return 0
2581+
}
2582+
2583+
v2k_libvirt_redefine_with_bootstrap_fallback() {
2584+
local manifest="$1" vcpu="$2" memory="$3" bridge="$4" vlan="$5" network="$6"
2585+
local vm xml_path
2586+
vm="$(jq -r '.target.libvirt.name' "${manifest}")"
2587+
v2k_target_undefine_libvirt "${vm}" || true
2588+
if [[ -n "${bridge}" ]]; then
2589+
xml_path="$(v2k_target_generate_libvirt_xml "${manifest}" \
2590+
--vcpu "${vcpu}" --memory "${memory}" \
2591+
--bridge "${bridge}" $( [[ -n "${vlan}" ]] && echo --vlan "${vlan}" ) \
2592+
)"
2593+
else
2594+
xml_path="$(v2k_target_generate_libvirt_xml "${manifest}" \
2595+
--vcpu "${vcpu}" --memory "${memory}" \
2596+
--network "${network}" \
2597+
)"
2598+
fi
2599+
v2k_target_define_libvirt "${xml_path}"
2600+
}
2601+
25432602
v2k_cmd_cutover() {
25442603
v2k_require_manifest
25452604
v2k_load_runtime_flags_from_manifest
@@ -2561,6 +2620,7 @@ v2k_cmd_cutover() {
25612620
local vcpu_set=0 memory_set=0
25622621
local network="default" bridge="" vlan=""
25632622
local force_cleanup=0
2623+
local bootstrap_fallback="${V2K_BOOTSTRAP_FALLBACK:-sata}"
25642624

25652625
#Linux bootstrap (host-chroot initramfs rebuild)
25662626
local linux_bootstrap=-1
@@ -2600,6 +2660,18 @@ v2k_cmd_cutover() {
26002660
linux_bootstrap=0
26012661
shift 1
26022662
;;
2663+
--bootstrap-fallback)
2664+
bootstrap_fallback="${2:-}"
2665+
case "${bootstrap_fallback}" in
2666+
sata|auto|off|none|false|0) ;;
2667+
*) echo "Invalid --bootstrap-fallback: ${bootstrap_fallback}" >&2; exit 2 ;;
2668+
esac
2669+
shift 2
2670+
;;
2671+
--no-bootstrap-fallback)
2672+
bootstrap_fallback="off"
2673+
shift 1
2674+
;;
26032675
--target-provider) target_provider="${2:-}"; target_provider_arg_set=1; shift 2;;
26042676
--cloud-endpoint) cloud_endpoint="${2:-}"; cloud_config_arg_set=1; shift 2;;
26052677
--cloud-api-key) cloud_api_key="${2:-}"; shift 2;;
@@ -2794,19 +2866,21 @@ v2k_cmd_cutover() {
27942866
if [[ "${V2K_JSON_OUT:-0}" -ne 1 ]]; then
27952867
echo "[v2k] Cloud Linux bootstrap(initramfs) requested (guestFamily=linuxGuest)"
27962868
fi
2797-
v2k_linux_bootstrap_initramfs "${V2K_MANIFEST}"
2798-
local rc=$?
2799-
if [[ "${rc}" -ne 0 ]]; then
2869+
if v2k_linux_bootstrap_initramfs "${V2K_MANIFEST}"; then
2870+
v2k_event INFO "cutover" "" "cloud_linux_bootstrap_done" "{}"
2871+
if [[ "${V2K_JSON_OUT:-0}" -ne 1 ]]; then
2872+
echo "[v2k] Cloud Linux bootstrap(initramfs) done (guestFamily=linuxGuest)"
2873+
fi
2874+
else
2875+
local rc=$?
28002876
v2k_event ERROR "cutover" "" "cloud_linux_bootstrap_failed" "{\"code\":${rc}}"
28012877
if [[ "${V2K_JSON_OUT:-0}" -ne 1 ]]; then
28022878
echo "[v2k] Cloud Linux bootstrap(initramfs) failed (guestFamily=linuxGuest)"
28032879
fi
2804-
echo "Cloud Linux bootstrap (initramfs rebuild) failed. code=${rc}" >&2
2805-
exit 74
2806-
fi
2807-
v2k_event INFO "cutover" "" "cloud_linux_bootstrap_done" "{}"
2808-
if [[ "${V2K_JSON_OUT:-0}" -ne 1 ]]; then
2809-
echo "[v2k] Cloud Linux bootstrap(initramfs) done (guestFamily=linuxGuest)"
2880+
if ! v2k_select_bootstrap_fallback "${V2K_MANIFEST}" "linux_bootstrap" "${rc}" "Cloud Linux bootstrap(initramfs) failed" "${bootstrap_fallback}"; then
2881+
echo "Cloud Linux bootstrap (initramfs rebuild) failed. code=${rc}" >&2
2882+
exit 74
2883+
fi
28102884
fi
28112885
else
28122886
v2k_event INFO "cutover" "" "cloud_linux_bootstrap_skipped" "{\"reason\":\"cli_or_policy\"}"
@@ -2817,16 +2891,18 @@ v2k_cmd_cutover() {
28172891
if [[ "${V2K_JSON_OUT:-0}" -ne 1 ]]; then
28182892
echo "[v2k] Cloud Windows WinPE bootstrap requested (guestFamily=windowsGuest)"
28192893
fi
2820-
v2k_cloud_windows_winpe_bootstrap "${winpe_iso}" "${virtio_iso}" "${winpe_timeout}"
2821-
local rc=$?
2822-
if [[ "${rc}" -ne 0 ]]; then
2894+
if v2k_cloud_windows_winpe_bootstrap "${winpe_iso}" "${virtio_iso}" "${winpe_timeout}"; then
2895+
v2k_event INFO "cutover" "" "cloud_winpe_bootstrap_done" "{}"
2896+
if [[ "${V2K_JSON_OUT:-0}" -ne 1 ]]; then
2897+
echo "[v2k] Cloud Windows WinPE bootstrap done (guestFamily=windowsGuest)"
2898+
fi
2899+
else
2900+
local rc=$?
28232901
v2k_event ERROR "cutover" "" "cloud_winpe_bootstrap_failed" "{\"code\":${rc}}"
2824-
echo "Cloud Windows WinPE bootstrap failed. code=${rc}" >&2
2825-
exit "${rc}"
2826-
fi
2827-
v2k_event INFO "cutover" "" "cloud_winpe_bootstrap_done" "{}"
2828-
if [[ "${V2K_JSON_OUT:-0}" -ne 1 ]]; then
2829-
echo "[v2k] Cloud Windows WinPE bootstrap done (guestFamily=windowsGuest)"
2902+
if ! v2k_select_bootstrap_fallback "${V2K_MANIFEST}" "winpe_bootstrap" "${rc}" "Cloud Windows WinPE bootstrap failed" "${bootstrap_fallback}"; then
2903+
echo "Cloud Windows WinPE bootstrap failed. code=${rc}" >&2
2904+
exit "${rc}"
2905+
fi
28302906
fi
28312907
fi
28322908

@@ -2876,19 +2952,21 @@ v2k_cmd_cutover() {
28762952
if [[ "${V2K_JSON_OUT:-0}" -ne 1 ]]; then
28772953
echo "[v2k] Linux bootstrap(initramfs) requested (guestFamily=linuxGuest)"
28782954
fi
2879-
v2k_linux_bootstrap_initramfs "${V2K_MANIFEST}"
2880-
local rc=$?
2881-
if [[ "${rc}" -ne 0 ]]; then
2955+
if v2k_linux_bootstrap_initramfs "${V2K_MANIFEST}"; then
2956+
v2k_event INFO "cutover" "" "linux_bootstrap_done" "{}"
2957+
if [[ "${V2K_JSON_OUT:-0}" -ne 1 ]]; then
2958+
echo "[v2k] Linux bootstrap(initramfs) done (guestFamily=linuxGuest)"
2959+
fi
2960+
else
2961+
local rc=$?
28822962
v2k_event ERROR "cutover" "" "linux_bootstrap_failed" "{\"code\":${rc}}"
28832963
if [[ "${V2K_JSON_OUT:-0}" -ne 1 ]]; then
28842964
echo "[v2k] Linux bootstrap(initramfs) failed (guestFamily=linuxGuest)"
28852965
fi
2886-
echo "Linux bootstrap (initramfs rebuild) failed. code=${rc}" >&2
2887-
exit 74
2888-
fi
2889-
v2k_event INFO "cutover" "" "linux_bootstrap_done" "{}"
2890-
if [[ "${V2K_JSON_OUT:-0}" -ne 1 ]]; then
2891-
echo "[v2k] Linux bootstrap(initramfs) done (guestFamily=linuxGuest)"
2966+
if ! v2k_select_bootstrap_fallback "${V2K_MANIFEST}" "linux_bootstrap" "${rc}" "Linux bootstrap(initramfs) failed" "${bootstrap_fallback}"; then
2967+
echo "Linux bootstrap (initramfs rebuild) failed. code=${rc}" >&2
2968+
exit 74
2969+
fi
28922970
fi
28932971
else
28942972
v2k_event INFO "cutover" "" "linux_bootstrap_skipped" "{\"reason\":\"cli_or_policy\"}"
@@ -2941,7 +3019,21 @@ v2k_cmd_cutover() {
29413019
if [[ "${winpe_bootstrap}" -eq 1 ]]; then
29423020
local vm
29433021
vm="$(jq -r '.target.libvirt.name' "${V2K_MANIFEST}")"
2944-
v2k_windows_winpe_bootstrap_libvirt "${V2K_MANIFEST}" "${vm}" "${winpe_iso}" "${virtio_iso}" "${winpe_timeout}" 0
3022+
if v2k_windows_winpe_bootstrap_libvirt "${V2K_MANIFEST}" "${vm}" "${winpe_iso}" "${virtio_iso}" "${winpe_timeout}" 0; then
3023+
:
3024+
else
3025+
local rc=$?
3026+
v2k_event ERROR "cutover" "" "libvirt_winpe_bootstrap_failed" "{\"code\":${rc}}"
3027+
if v2k_select_bootstrap_fallback "${V2K_MANIFEST}" "winpe_bootstrap" "${rc}" "Windows WinPE bootstrap failed" "${bootstrap_fallback}"; then
3028+
if ! v2k_libvirt_redefine_with_bootstrap_fallback "${V2K_MANIFEST}" "${vcpu}" "${memory}" "${bridge}" "${vlan}" "${network}"; then
3029+
echo "libvirt redefine with SATA fallback failed." >&2
3030+
exit 65
3031+
fi
3032+
else
3033+
echo "Windows WinPE bootstrap failed. code=${rc}" >&2
3034+
exit "${rc}"
3035+
fi
3036+
fi
29453037
fi
29463038

29473039
# WinPE may trigger host-side auto-unmap on guest shutdown. Re-prepare persistent RBD maps before the final boot.

lib/v2k/target_cloud.sh

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,8 +223,10 @@ v2k_cloud_target_source_deploy_params_json() {
223223
| ((.target.cloud.cpu_speed // "1000") | tostring) as $cpu_speed
224224
| (($vm.firmware // "") | tostring | ascii_downcase) as $firmware
225225
| (($vm.secure_boot // false) == true) as $secure_boot
226-
| (controller(.disks[0].controller.type // "")) as $root_controller
227-
| (controller((.disks[1:] // [] | map(.controller.type // "") | map(select((. | tostring | length) > 0)) | first) // "")) as $data_controller
226+
| ((.runtime.bootstrap_fallback.bus // "") | tostring | ascii_downcase) as $fallback_bus
227+
| ((.disks // []) | length) as $disk_count
228+
| (if $fallback_bus == "sata" then "sata" else controller(.disks[0].controller.type // "") end) as $root_controller
229+
| (if $fallback_bus == "sata" and $disk_count > 1 then "sata" else controller((.disks[1:] // [] | map(.controller.type // "") | map(select((. | tostring | length) > 0)) | first) // "") end) as $data_controller
228230
| {}
229231
+ (if $cpu > 0 then {"details[0].cpuNumber": ($cpu | floor | tostring)} else {} end)
230232
+ {"details[0].cpuSpeed": $cpu_speed}

lib/v2k/target_libvirt.sh

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,14 @@ _v2k_rbd_dev_path_from_uri() {
8686

8787
_v2k_target_disk_xml() {
8888
local manifest="$1" idx="$2"
89-
local path bus dev st
89+
local path bus dev st fallback_bus
9090
path="$(jq -r ".disks[$idx].transfer.target_path" "${manifest}")"
91-
bus="$(_v2k_disk_bus_from_controller_type "$(jq -r ".disks[$idx].controller.type // empty" "${manifest}")")"
91+
fallback_bus="$(jq -r '.runtime.bootstrap_fallback.bus // empty' "${manifest}" 2>/dev/null || true)"
92+
if [[ "${fallback_bus}" == "sata" ]]; then
93+
bus="sata"
94+
else
95+
bus="$(_v2k_disk_bus_from_controller_type "$(jq -r ".disks[$idx].controller.type // empty" "${manifest}")")"
96+
fi
9297
dev="sd$(_v2k_letter "$idx")"
9398
st="$(jq -r '.target.storage.type // "file"' "${manifest}")"
9499

@@ -98,6 +103,11 @@ _v2k_target_disk_xml() {
98103
if [[ -z "${block_path}" ]]; then
99104
block_path="$(_v2k_rbd_dev_path_from_uri "${path}")"
100105
fi
106+
local address_xml=""
107+
if [[ "${bus}" != "sata" ]]; then
108+
address_xml=" <alias name='scsi0-0-0-${idx}'/>
109+
<address type='drive' controller='0' bus='0' target='0' unit='${idx}'/>"
110+
fi
101111
serial="$(printf ''%s'' "${path#rbd:}" | tr -cd ''[:alnum:]'' | cut -c1-20)"
102112
[[ -n "${serial}" ]] || serial="rbd${idx}"
103113
cat <<EOF
@@ -106,8 +116,7 @@ _v2k_target_disk_xml() {
106116
<source dev='$(_v2k_escape_xml "${block_path}")' index='${idx}'/>
107117
<target dev='${dev}' bus='${bus}'/>
108118
<serial>${serial}</serial>
109-
<alias name='scsi0-0-0-${idx}'/>
110-
<address type='drive' controller='0' bus='0' target='0' unit='${idx}'/>
119+
${address_xml}
111120
</disk>
112121
EOF
113122
return 0
@@ -252,7 +261,14 @@ v2k_target_generate_libvirt_xml() {
252261
fi
253262

254263
local disks_xml=""
255-
local count
264+
local fallback_bus controller_xml
265+
fallback_bus="$(jq -r '.runtime.bootstrap_fallback.bus // empty' "${manifest}" 2>/dev/null || true)"
266+
if [[ "${fallback_bus}" == "sata" ]]; then
267+
controller_xml="<controller type='sata' index='0'/>"
268+
else
269+
controller_xml="<controller type='scsi' index='0' model='virtio-scsi'/>"
270+
fi
271+
local count i
256272
count="$(jq -r '.disks | length' "${manifest}")"
257273

258274
for ((i=0;i<count;i++)); do
@@ -287,7 +303,7 @@ $(_v2k_target_disk_xml "${manifest}" "$i")"
287303
<topology sockets='1' cores='${vcpu}' threads='1'/>
288304
</cpu>
289305
<devices>
290-
<controller type='scsi' index='0' model='virtio-scsi'/>
306+
${controller_xml}
291307
${disks_xml}
292308
${iface_xml}
293309
${tpm_xml}

0 commit comments

Comments
 (0)