@@ -460,10 +460,13 @@ parse_args() {
460460 LB_RULES_JSON=" []"
461461 DEFAULT_NIC=" true"
462462 VM_DATA=" "
463+ VM_DATA_FILE=" "
463464 DOMAIN=" "
464465 EXTENSION_IP=" "
465466 RESTORE_DATA=" "
467+ RESTORE_DATA_FILE=" "
466468 FW_RULES_JSON=" "
469+ FW_RULES_FILE=" "
467470
468471 while [ $# -gt 0 ]; do
469472 case " $1 " in
@@ -495,10 +498,13 @@ parse_args() {
495498 --lb-rules) LB_RULES_JSON=" $2 " ; shift 2 ;;
496499 --default-nic) DEFAULT_NIC=" $2 " ; shift 2 ;;
497500 --vm-data) VM_DATA=" $2 " ; shift 2 ;;
501+ --vm-data-file) VM_DATA_FILE=" $2 " ; shift 2 ;;
498502 --domain) DOMAIN=" $2 " ; shift 2 ;;
499503 --extension-ip) EXTENSION_IP=" $2 " ; shift 2 ;;
500504 --restore-data) RESTORE_DATA=" $2 " ; shift 2 ;;
505+ --restore-data-file) RESTORE_DATA_FILE=" $2 " ; shift 2 ;;
501506 --fw-rules) FW_RULES_JSON=" $2 " ; shift 2 ;;
507+ --fw-rules-file) FW_RULES_FILE=" $2 " ; shift 2 ;;
502508 # consumed by _pre_scan_args — skip silently
503509 --physical-network-extension-details|--network-extension-details)
504510 shift 2 ;;
@@ -2231,20 +2237,36 @@ cmd_save_vm_data() {
22312237 acquire_lock " ${NETWORK_ID} "
22322238 log " save-vm-data: network=${NETWORK_ID} ip=${VM_IP} "
22332239 [ -z " ${VM_IP} " ] && die " save-vm-data: missing --ip"
2234- [ -z " ${VM_DATA} " ] && die " save-vm-data: missing --vm-data"
2240+
2241+ local vm_data_file=" ${VM_DATA_FILE} "
2242+ local cleanup_vm_data_file=" false"
2243+ if [ -z " ${vm_data_file} " ]; then
2244+ [ -z " ${VM_DATA} " ] && die " save-vm-data: missing --vm-data or --vm-data-file"
2245+ vm_data_file=$( mktemp /tmp/cs-extnet-vm-data-XXXXXX)
2246+ cleanup_vm_data_file=" true"
2247+ printf ' %s' " ${VM_DATA} " > " ${vm_data_file} "
2248+ fi
2249+ [ -f " ${vm_data_file} " ] || die " save-vm-data: payload file not found: ${vm_data_file} "
22352250
22362251 local meta_dir; meta_dir=$( _metadata_dir)
22372252 local passwd_f; passwd_f=$( _passwd_file)
22382253 mkdir -p " ${meta_dir} " " $( dirname " ${passwd_f} " ) "
22392254 touch " ${passwd_f} "
22402255
2241- python3 - " ${VM_IP} " " ${meta_dir} " " ${passwd_f} " " ${VM_DATA } " << 'PYEOF '
2256+ python3 - " ${VM_IP} " " ${meta_dir} " " ${passwd_f} " " ${vm_data_file } " << 'PYEOF '
22422257import base64, json, os, sys
22432258
22442259vm_ip = sys.argv[1]
22452260meta_dir = sys.argv[2]
22462261passwd_f = sys.argv[3]
2247- data_b64 = sys.argv[4]
2262+ data_file = sys.argv[4]
2263+
2264+ try:
2265+ with open(data_file, 'r', encoding='utf-8') as f:
2266+ data_b64 = f.read().strip()
2267+ except Exception as e:
2268+ print(f"save-vm-data: failed to read vm-data file: {e}", file=sys.stderr)
2269+ sys.exit(1)
22482270
22492271# Decode the outer base64 wrapper, then parse the JSON array
22502272try:
@@ -2321,6 +2343,10 @@ if password_written:
23212343print(f"save-vm-data: wrote {len(entries)} entries for {vm_ip}")
23222344PYEOF
23232345
2346+ if [ " ${cleanup_vm_data_file} " = " true" ]; then
2347+ rm -f " ${vm_data_file} " 2> /dev/null || true
2348+ fi
2349+
23242350 _write_apache2_conf
23252351 _svc_start_or_reload_apache2
23262352 _svc_start_or_reload_passwd_server
@@ -2389,6 +2415,15 @@ cmd_apply_fw_rules() {
23892415 acquire_lock " ${NETWORK_ID} "
23902416 log " apply-fw-rules: network=${NETWORK_ID} ns=${NAMESPACE} "
23912417
2418+ local fw_rules_file=" ${FW_RULES_FILE} "
2419+ local cleanup_fw_rules_file=" false"
2420+ if [ -z " ${fw_rules_file} " ]; then
2421+ fw_rules_file=$( mktemp /tmp/cs-extnet-fw-rules-XXXXXX)
2422+ cleanup_fw_rules_file=" true"
2423+ printf ' %s' " ${FW_RULES_JSON:- } " > " ${fw_rules_file} "
2424+ fi
2425+ [ -f " ${fw_rules_file} " ] || die " apply-fw-rules: payload file not found: ${fw_rules_file} "
2426+
23922427 local veth_n fchain fw_chain
23932428 veth_n=$( veth_ns_name " ${VLAN} " " ${CHOSEN_ID} " )
23942429 fchain=$( filter_chain " ${NETWORK_ID} " )
@@ -2406,15 +2441,22 @@ cmd_apply_fw_rules() {
24062441 ip netns exec " ${NAMESPACE} " iptables -t filter -N " ${fw_chain} "
24072442
24082443 # ---- 4. Build iptables rules via Python ----
2409- python3 - " ${NAMESPACE} " " ${FW_RULES_JSON :- } " " ${veth_n} " \
2444+ python3 - " ${NAMESPACE} " " ${fw_rules_file } " " ${veth_n} " \
24102445 " ${fw_chain} " << 'PYEOF '
24112446import base64, json, re, subprocess, sys
24122447
24132448namespace = sys.argv[1]
2414- rules_b64 = sys.argv[2]
2449+ rules_file = sys.argv[2]
24152450veth_n = sys.argv[3]
24162451fw_chain = sys.argv[4] # filter table egress chain (CS_EXTNET_FWRULES_<N>)
24172452
2453+ try:
2454+ with open(rules_file, 'r', encoding='utf-8') as f:
2455+ rules_b64 = f.read().strip()
2456+ except Exception as e:
2457+ print(f"apply-fw-rules: failed to read rules file: {e}", file=sys.stderr)
2458+ sys.exit(1)
2459+
24182460# Prefix for per-public-IP ingress chains in the mangle table.
24192461# e.g. CS_EXTNET_FWI_10.0.56.20
24202462FW_INGRESS_PREFIX = 'CS_EXTNET_FWI_'
@@ -2592,6 +2634,11 @@ print(f"apply-fw-rules: built {n_in} ingress rule(s) across {len(pub_ip_rules)}
25922634PYEOF
25932635
25942636 local py_exit=$?
2637+
2638+ if [ " ${cleanup_fw_rules_file} " = " true" ]; then
2639+ rm -f " ${fw_rules_file} " 2> /dev/null || true
2640+ fi
2641+
25952642 if [ ${py_exit} -ne 0 ]; then
25962643 # Python script failed — leave chain empty but continue so that the
25972644 # fchain catch-all rules remain effective (fail-open for existing traffic).
@@ -2768,7 +2815,16 @@ cmd_restore_network() {
27682815 _load_state
27692816 acquire_lock " ${NETWORK_ID} "
27702817 log " restore-network: network=${NETWORK_ID} ns=${NAMESPACE} "
2771- [ -z " ${RESTORE_DATA} " ] && die " restore-network: missing --restore-data"
2818+
2819+ local restore_data_file=" ${RESTORE_DATA_FILE} "
2820+ local cleanup_restore_data_file=" false"
2821+ if [ -z " ${restore_data_file} " ]; then
2822+ [ -z " ${RESTORE_DATA} " ] && die " restore-network: missing --restore-data or --restore-data-file"
2823+ restore_data_file=$( mktemp /tmp/cs-extnet-restore-data-XXXXXX)
2824+ cleanup_restore_data_file=" true"
2825+ printf ' %s' " ${RESTORE_DATA} " > " ${restore_data_file} "
2826+ fi
2827+ [ -f " ${restore_data_file} " ] || die " restore-network: payload file not found: ${restore_data_file} "
27722828
27732829 local dhcp_hosts; dhcp_hosts=$( _dnsmasq_dhcp_hosts)
27742830 local dhcp_opts; dhcp_opts=$( _dnsmasq_dhcp_opts)
@@ -2780,19 +2836,26 @@ cmd_restore_network() {
27802836 touch " ${dhcp_hosts} " " ${dhcp_opts} " " ${dns_hosts} " " ${passwd_f} "
27812837
27822838 python3 - \
2783- " ${RESTORE_DATA } " \
2839+ " ${restore_data_file } " \
27842840 " ${dhcp_hosts} " " ${dhcp_opts} " " ${dns_hosts} " \
27852841 " ${meta_dir} " " ${passwd_f} " \
27862842 << 'PYEOF '
27872843import base64, json, os, sys
27882844
2789- restore_b64 = sys.argv[1]
2845+ restore_file = sys.argv[1]
27902846dhcp_hosts_f = sys.argv[2]
27912847dhcp_opts_f = sys.argv[3]
27922848dns_hosts_f = sys.argv[4]
27932849meta_dir = sys.argv[5]
27942850passwd_f = sys.argv[6]
27952851
2852+ try:
2853+ with open(restore_file, 'r', encoding='utf-8') as f:
2854+ restore_b64 = f.read().strip()
2855+ except Exception as e:
2856+ print(f"restore-network: failed to read restore-data file: {e}", file=sys.stderr)
2857+ sys.exit(1)
2858+
27962859# ---- Decode the outer base64, then parse JSON ----
27972860try:
27982861 data = json.loads(base64.b64decode(restore_b64).decode('utf-8'))
@@ -2938,23 +3001,27 @@ print("restore-network: done")
29383001PYEOF
29393002
29403003 # ------------------------------------------------------------------
2941- # Decode dhcp_enabled / dns_enabled from RESTORE_DATA so we can
3004+ # Decode dhcp_enabled / dns_enabled from restore_data_file so we can
29423005 # reconfigure dnsmasq correctly even when the namespace (and therefore
2943- # dnsmasq.conf) was deleted and recreated. RESTORE_DATA is passed as
2944- # a positional argument to avoid shell-quoting issues with base64 data.
3006+ # dnsmasq.conf) was deleted and recreated.
29453007 # ------------------------------------------------------------------
29463008 local _r_flags
2947- _r_flags=$( python3 - " ${RESTORE_DATA } " 2> /dev/null << 'PYFLAGSEOF '
2948- import base64, json, sys
3009+ _r_flags=$( python3 - " ${restore_data_file } " 2> /dev/null << 'PYFLAGSEOF '
3010+ import base64, json, sys, pathlib
29493011try:
2950- d = json.loads(base64.b64decode(sys.argv[1]).decode('utf-8'))
3012+ b64_data = pathlib.Path(sys.argv[1]).read_text(encoding='utf-8').strip()
3013+ d = json.loads(base64.b64decode(b64_data).decode('utf-8'))
29513014 dhcp = 'true' if d.get('dhcp_enabled', False) else 'false'
29523015 dns = 'true' if d.get('dns_enabled', False) else 'false'
29533016 print(dhcp + ' ' + dns)
29543017except Exception:
29553018 print('false false')
29563019PYFLAGSEOF
29573020)
3021+
3022+ if [ " ${cleanup_restore_data_file} " = " true" ]; then
3023+ rm -f " ${restore_data_file} " 2> /dev/null || true
3024+ fi
29583025 local _r_dhcp _r_dns
29593026 _r_dhcp=" ${_r_flags%% * } " ; _r_dhcp=" ${_r_dhcp:- false} "
29603027 _r_dns=" ${_r_flags##* } " ; _r_dns=" ${_r_dns:- false} "
0 commit comments