From 7405ec8acb3344283d8adc91c5d06af3abc2a282 Mon Sep 17 00:00:00 2001 From: Andre Kantek Date: Mon, 14 Jul 2025 09:20:00 -0300 Subject: [PATCH] Remove previous default routes before ifup command on cloud-init This change checks if 50-cloud-init contains a gateway configuration and if it does removes the previous default route left over from the factory installation, to not conflict with the new gateway. In case of error it does recreate the previous default route. Test Plan --------- [PASS] execute enrollment of a subcloud Closes-Bug: 2119628 Change-Id: Ie8c27f28e8c1ec7d4d20d509420ce5b7314f3c9f Signed-off-by: Andre Kantek --- .../seed-config/run-cloud-init-from-seed.sh | 212 +++++++++++++++++- 1 file changed, 211 insertions(+), 1 deletion(-) diff --git a/tools/nocloud-factory-install/seed-config/run-cloud-init-from-seed.sh b/tools/nocloud-factory-install/seed-config/run-cloud-init-from-seed.sh index c09a62aa..d904aab3 100755 --- a/tools/nocloud-factory-install/seed-config/run-cloud-init-from-seed.sh +++ b/tools/nocloud-factory-install/seed-config/run-cloud-init-from-seed.sh @@ -157,14 +157,224 @@ fi # The --force option is used here to prevent ifup from pausing in case the new # OAM address is configured with a different address, but in the same VLAN and # interface. -IFUP_OUTPUT=$(ifup -i $CLOUD_INIT_IF_FILE -a --force 2>&1) + +# Store initial default routes before any network changes +declare -A INITIAL_ROUTES +INITIAL_ROUTES["ipv4"]=$(ip -4 route show | grep default 2>&1) +INITIAL_ROUTES["ipv6"]=$(ip -6 route show | grep default 2>&1) + +# Function to restore default routes +restore_default_routes() { + log_info "Attempting to restore initial default routes..." + + if [ -n "${INITIAL_ROUTES["ipv4"]}" ]; then + + local initial_v4_gateway + local initial_v4_dev + local remove_current_ipv4_default + local restore_initial_ipv4_default + + initial_v4_gateway=$(echo "${INITIAL_ROUTES["ipv4"]}" | awk '{print $3}') + initial_v4_dev=$(echo "${INITIAL_ROUTES["ipv4"]}" | awk '{print $5}') + remove_current_ipv4_default=0 + restore_initial_ipv4_default=0 + + # Check if a default IPv4 route already exists (ifup might have added one) + CURRENT_V4_DEFAULT=$(ip -4 route show | grep default 2>&1) + if [ -z "$CURRENT_V4_DEFAULT" ]; then + remove_current_ipv4_default=0 + restore_initial_ipv4_default=1 + elif [ "$CURRENT_V4_DEFAULT" == "${INITIAL_ROUTES["ipv4"]}" ]; then + remove_current_ipv4_default=0 + restore_initial_ipv4_default=0 + else + remove_current_ipv4_default=1 + restore_initial_ipv4_default=1 + fi + + if [ "$remove_current_ipv4_default" -eq 1 ]; then + log_info "IPv4 default route already exists, removing '$CURRENT_V4_DEFAULT' to restore." + sudo ip -4 route del default + if [ $? -eq 0 ]; then + log_info "Default IPv4 route successfully removed." + else + log_info "Error: Failed to remove the default IPv4 route. Check permissions or if the route still exists." + fi + fi + + if [ "$restore_initial_ipv4_default" -eq 1 ]; then + log_info "Restoring initial IPv4 default route..." + if [ -n "$initial_v4_gateway" ] && [ -n "$initial_v4_dev" ]; then + sudo ip -4 route add default via "$initial_v4_gateway" dev "$initial_v4_dev" + if [ $? -eq 0 ]; then + log_info "IPv4 default route restored successfully: default via $initial_v4_gateway dev $initial_v4_dev" + else + log_info "Error: Failed to restore IPv4 default route." + fi + else + log_info "Warning: Could not parse original IPv4 default gateway/device for restoration. Manual intervention may be needed." + fi + fi + else + log_info "No initial IPv4 default route to restore." + fi + + if [ -n "${INITIAL_ROUTES["ipv6"]}" ]; then + local initial_v6_gateway + local initial_v6_dev + local remove_current_ipv6_default + local restore_initial_ipv6_default + + initial_v6_gateway=$(echo "${INITIAL_ROUTES["ipv6"]}" | awk '{print $3}') + initial_v6_dev=$(echo "${INITIAL_ROUTES["ipv6"]}" | awk '{print $5}') + remove_current_ipv6_default=0 + restore_initial_ipv6_default=0 + + # Check if a default IPv6 route already exists (ifup might have added one) + CURRENT_V6_DEFAULT=$(ip -6 route show | grep default 2>&1) + if [ -z "$CURRENT_V6_DEFAULT" ]; then + remove_current_ipv6_default=0 + restore_initial_ipv6_default=1 + elif [ "$CURRENT_V6_DEFAULT" == "${INITIAL_ROUTES["ipv6"]}" ]; then + remove_current_ipv4_default=0 + restore_initial_ipv4_default=0 + else + remove_current_ipv6_default=1 + restore_initial_ipv6_default=1 + fi + + if [ "$remove_current_ipv6_default" -eq 1 ]; then + log_info "IPv6 default route already exists, removing '$CURRENT_V6_DEFAULT' to restore." + sudo ip -6 route del default + if [ $? -eq 0 ]; then + log_info "Default IPv6 route successfully removed." + else + log_info "Error: Failed to remove the default IPv6 route. Check permissions or if the route still exists." + fi + fi + + if [ "$restore_initial_ipv6_default" -eq 1 ]; then + log_info "Restoring initial IPv6 default route..." + if [ -n "$initial_v6_gateway" ] && [ -n "$initial_v6_dev" ]; then + sudo ip -6 route add default via "$initial_v6_gateway" dev "$initial_v6_dev" + if [ $? -eq 0 ]; then + log_info "IPv6 default route restored successfully: default via $initial_v6_gateway dev $initial_v6_dev" + else + log_info "Error: Failed to restore IPv6 default route." + fi + else + log_info "Warning: Could not parse original IPv6 default gateway/device for restoration. Manual intervention may be needed." + fi + fi + else + log_info "No initial IPv6 default route to restore." + fi +} + +remove_current_default_routes() { + CURRENT_DEFAULT_IPv4_ROUTE=$(ip -4 route show | grep default 2>&1) + if [ -n "$CURRENT_DEFAULT_IPv4_ROUTE" ]; then + if grep -q -E "iface .* inet static" "$CLOUD_INIT_IF_FILE"; then + log_info "Default IPv4 route found. Removing '${CURRENT_DEFAULT_IPv4_ROUTE}'" + sudo ip -4 route del default + if [ $? -eq 0 ]; then + log_info "Default IPv4 route successfully removed." + else + log_info "Error: Failed to remove the default IPv4 route. Check permissions or if the route still exists." + fi + else + log_info "file ${CLOUD_INIT_IF_FILE} isn't inet. do not remove IPv4 default route." + fi + else + log_info "No default IPv4 route found." + fi + + CURRENT_DEFAULT_IPv6_ROUTE=$(ip -6 route show | grep default 2>&1) + if [ -n "$CURRENT_DEFAULT_IPv6_ROUTE" ]; then + if grep -q -E "iface .* inet6 static" "$CLOUD_INIT_IF_FILE"; then + log_info "Default IPv6 route found. Removing '${CURRENT_DEFAULT_IPv6_ROUTE}'" + sudo ip -6 route del default + if [ $? -eq 0 ]; then + log_info "Default IPv6 route successfully removed." + else + log_info "Error: Failed to remove the default IPv6 route. Check permissions or if the route still exists." + fi + else + log_info "file ${CLOUD_INIT_IF_FILE} isn't inet6, do not remove IPv6 default route." + fi + else + log_info "No default IPv6 route found." + fi +} + +cloud_init_iface='' +cloud_init_gateway='' +cloud_init_proto='' + +# Check if CLOUD_INIT_IF_FILE exists and contains "gateway" +if [ -f "$CLOUD_INIT_IF_FILE" ] && grep -q "gateway" "$CLOUD_INIT_IF_FILE"; then + log_info "Cloud-init interface file '$CLOUD_INIT_IF_FILE' contains 'gateway'. Will attempt to remove existing default routes." + cloud_init_iface=$(awk '/iface.*inet.*static/ {print $2}' $CLOUD_INIT_IF_FILE) + cloud_init_gateway=$(awk '/gateway/ {print $2}' $CLOUD_INIT_IF_FILE) + cloud_init_proto=$(awk '/iface.*inet.*static/ {print $3}' $CLOUD_INIT_IF_FILE) + remove_current_default_routes +else + log_info "Cloud-init interface file '$CLOUD_INIT_IF_FILE' does not exist or does not contain 'gateway'. Skipping removal of existing default routes." +fi + +IFUP_OUTPUT=$(ifup -i $CLOUD_INIT_IF_FILE -a -v --force 2>&1) CLOUD_INIT_RC=$? log_info "ifup output: $IFUP_OUTPUT" if [ $CLOUD_INIT_RC -ne 0 ]; then restore_cloud_init_config + restore_default_routes check_rc_die $CLOUD_INIT_RC "ifup failed during cloud-init initialization." +else + declare -A LATEST_ROUTES + LATEST_ROUTES["ipv4"]=$(ip -4 route show exact default 2>&1) + LATEST_ROUTES["ipv6"]=$(ip -6 route show exact default 2>&1) + log_info "default routes:" + for key in "${!LATEST_ROUTES[@]}"; do + log_info "$key routes: ${LATEST_ROUTES[$key]}" + done + if [[ -n "${cloud_init_iface}" && -n "${cloud_init_gateway}" ]]; then + ip_version="" + if [[ "${cloud_init_proto}" == "inet" ]]; then + ip_version="-4" + elif [[ "${cloud_init_proto}" == "inet6" ]]; then + ip_version="-6" + fi + search=$(ip ${ip_version} route show exact default via "${cloud_init_gateway}" dev "${cloud_init_iface}" 2>&1) + if [[ ! "${search}" =~ ^default ]]; then + log_info "ifup completed successfully, but no cloud-init default route exists, creating" + ip ${ip_version} route add default via "${cloud_init_gateway}" dev "${cloud_init_iface}" + if [ $? -eq 0 ]; then + log_info "default route restored successfully: default via $cloud_init_gateway dev $cloud_init_iface" + else + latest_default=$(ip ${ip_version} route show exact default 2>&1) + log_info "Error: Failed to restore cloud_init_gateway, output:${latest_default}" + restore_default_routes + fi + else + log_info "ifup completed successfully. No route restoration needed." + fi + else + if [[ -z "${LATEST_ROUTES["ipv4"]}" || -z "${LATEST_ROUTES["ipv6"]}" ]]; then + log_info "Still have missing default route, restore to previous value" + restore_default_routes + else + log_info "ifup completed successfully. No route restoration needed." + fi + fi fi +NET_ADDR_STATE=$(echo "======= Addresses post config"; ip -br addr | grep -v -E "cali" 2>&1) +log_info "network address state output post config: $NET_ADDR_STATE" +NET_ROUTE4_STATE=$(echo "======= IPv4 Routes post config"; ip -4 route 2>&1) +log_info "network routes state output post config: $NET_ROUTE4_STATE" +NET_ROUTE6_STATE=$(echo "======= IPv6 Routes post config"; ip -6 route 2>&1) +log_info "network routes state output post config: $NET_ROUTE6_STATE" + # After the network is set up, we run cloud-init config and final # modes to apply the configuration and finalize the instance. # This includes running any user-data scripts and applying any