From ebdea9a261c133a55413cb1f89e4af435bf57436 Mon Sep 17 00:00:00 2001 From: avivm Date: Mon, 22 Sep 2025 09:02:34 +0000 Subject: [PATCH] VWAN | Added maintenance mode support --- .../high_availability_existing_vnet/README.md | 2 ++ .../high_availability_existing_vnet/main.tf | 31 +++++++++++++++++-- .../variables.tf | 12 +++++++ modules/high_availability_new_vnet/README.md | 2 ++ modules/high_availability_new_vnet/main.tf | 31 +++++++++++++++++-- .../high_availability_new_vnet/variables.tf | 12 +++++++ 6 files changed, 86 insertions(+), 4 deletions(-) diff --git a/modules/high_availability_existing_vnet/README.md b/modules/high_availability_existing_vnet/README.md index 0a9d890..21a06f5 100755 --- a/modules/high_availability_existing_vnet/README.md +++ b/modules/high_availability_existing_vnet/README.md @@ -36,6 +36,7 @@ module "example_module" { backend_subnet_name = "backend" frontend_IP_addresses = [5, 6, 7] backend_IP_addresses = [5, 6, 7] + vips_names = [] admin_password = "xxxxxxxxxxxx" smart_1_cloud_token_a = "xxxxxxxxxxxx" smart_1_cloud_token_b = "xxxxxxxxxxxx" @@ -121,6 +122,7 @@ module "example_module" { | **use_public_ip_prefix** | Indicates whether the public IP resources will be deployed with public IP prefix | boolean | true;
false;
**Default:** false | | **create_public_ip_prefix** | Indicates whether the public IP prefix will be created or an existing one will be used | boolean | true;
false;
**Default:** false | | **existing_public_ip_prefix_id** | The existing public IP prefix resource ID | string | Existing public IP prefix resource ID
| +| **vips_names** | Names for additional Virtual IP addresses beyond the primary cluster VIP. Each name creates a corresponding public IP resource. | list(string) | **Default:** [] | | **admin_shell** | Enables selecting different admin shells | string | /etc/cli.sh;
/bin/bash;
/bin/csh;
/bin/tcsh;
| | **serial_console_password_hash** | Optional parameter, used to enable serial console connection in case of SSH key as authentication type | string | | | **maintenance_mode_password_hash** | Maintenance mode password hash, relevant only for R81.20 and higher versions | string | | diff --git a/modules/high_availability_existing_vnet/main.tf b/modules/high_availability_existing_vnet/main.tf index b0a109c..ae75f1c 100755 --- a/modules/high_availability_existing_vnet/main.tf +++ b/modules/high_availability_existing_vnet/main.tf @@ -35,7 +35,7 @@ resource "azurerm_public_ip_prefix" "public_ip_prefix" { name = "${module.common.resource_group_name}-ipprefix" location = module.common.resource_group_location resource_group_name = module.common.resource_group_name - prefix_length = 30 + prefix_length = length(var.vips_names) > 4 ? 28 : length(var.vips_names) > 0 ? 29 : 30 tags = merge(lookup(var.tags, "public-ip-prefix", {}), lookup(var.tags, "all", {})) } @@ -74,10 +74,24 @@ resource "azurerm_public_ip" "cluster-vip" { tags = merge(lookup(var.tags, "public-ip", {}), lookup(var.tags, "all", {})) } +resource "azurerm_public_ip" "vips" { + count = length(var.vips_names) + name = var.vips_names[count.index] + location = module.common.resource_group_location + resource_group_name = module.common.resource_group_name + allocation_method = var.vnet_allocation_method + sku = var.sku + domain_name_label = "${lower(var.vips_names[count.index])}-${count.index}-vip-${random_id.random_id.hex}" + public_ip_prefix_id = var.use_public_ip_prefix ? (var.create_public_ip_prefix ? azurerm_public_ip_prefix.public_ip_prefix[0].id : var.existing_public_ip_prefix_id) : null + tags = merge(lookup(var.tags, "public-ip", {}), lookup(var.tags, "all", {})) +} + resource "azurerm_network_interface" "nic_vip" { depends_on = [ azurerm_public_ip.cluster-vip, - azurerm_public_ip.public-ip] + azurerm_public_ip.public-ip, + azurerm_public_ip.vips, + ] name = "${var.cluster_name}1-eth0" location = module.common.resource_group_location resource_group_name = module.common.resource_group_name @@ -100,6 +114,19 @@ resource "azurerm_network_interface" "nic_vip" { private_ip_address = cidrhost(data.azurerm_subnet.frontend.address_prefixes[0], var.frontend_IP_addresses[2]) public_ip_address_id = azurerm_public_ip.cluster-vip.id } + + dynamic "ip_configuration" { + for_each = var.vips_names + content { + name = "cluster-vip-${index(var.vips_names, ip_configuration.value) + 1}" + subnet_id = data.azurerm_subnet.frontend.id + primary = false + private_ip_address_allocation = var.vnet_allocation_method + private_ip_address = cidrhost(data.azurerm_subnet.frontend.address_prefixes[0], 7 + index(var.vips_names, ip_configuration.value) + 1) + public_ip_address_id = azurerm_public_ip.vips[index(var.vips_names, ip_configuration.value)].id + } + } + lifecycle { ignore_changes = [ # Ignore changes to ip_configuration when Re-applying, e.g. because a cluster failover and associating the cluster- vip with the other member. diff --git a/modules/high_availability_existing_vnet/variables.tf b/modules/high_availability_existing_vnet/variables.tf index b6c662e..cbec18c 100755 --- a/modules/high_availability_existing_vnet/variables.tf +++ b/modules/high_availability_existing_vnet/variables.tf @@ -326,4 +326,16 @@ variable "tags" { description = "Assign tags by resource." type = map(map(string)) default = {} +} + +variable "vips_names" { + description = "Names to be used for the VIPs" + type = list(string) + default = [] + + # More than 10 VIPs may result in not enough available IPs available in IpPrefix + validation { + condition = length(var.vips_names) < 10 + error_message = "The number of VIPs must be less than 10." + } } \ No newline at end of file diff --git a/modules/high_availability_new_vnet/README.md b/modules/high_availability_new_vnet/README.md index 6d5fed4..995a7ec 100755 --- a/modules/high_availability_new_vnet/README.md +++ b/modules/high_availability_new_vnet/README.md @@ -57,6 +57,7 @@ module "example_module" { use_public_ip_prefix = false create_public_ip_prefix = false existing_public_ip_prefix_id = "" + vips_names = [] admin_shell = "/etc/cli.sh" serial_console_password_hash = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" maintenance_mode_password_hash = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" @@ -122,6 +123,7 @@ module "example_module" { | **use_public_ip_prefix** | Indicates whether the public IP resources will be deployed with public IP prefix | boolean | true;
false;
**Default:** false | | **create_public_ip_prefix** | Indicates whether the public IP prefix will be created or an existing one will be used | boolean | true;
false;
**Default:** false | | **existing_public_ip_prefix_id** | The existing public IP prefix resource ID | string | Existing public IP prefix resource ID
**Default:** "" | +| **vips_names** | Names for additional Virtual IP addresses beyond the primary cluster VIP. Each name creates a corresponding public IP resource. | list(string) | **Default:** [] | | **admin_shell** | Enables selecting different admin shells | string | /etc/cli.sh;
/bin/bash;
/bin/csh;
/bin/tcsh;
**Default:** "/etc/cli.sh" | | **serial_console_password_hash** | Optional parameter to enable serial console connection in case of SSH key as authentication type | string | | | **maintenance_mode_password_hash**| Maintenance mode password hash, relevant only for R81.20 and higher versions | string | | diff --git a/modules/high_availability_new_vnet/main.tf b/modules/high_availability_new_vnet/main.tf index 13d3771..29c605c 100755 --- a/modules/high_availability_new_vnet/main.tf +++ b/modules/high_availability_new_vnet/main.tf @@ -56,7 +56,7 @@ resource "azurerm_public_ip_prefix" "public_ip_prefix" { name = "${module.common.resource_group_name}-ipprefix" location = module.common.resource_group_location resource_group_name = module.common.resource_group_name - prefix_length = 30 + prefix_length = length(var.vips_names) > 4 ? 28 : length(var.vips_names) > 0 ? 29 : 30 tags = merge(lookup(var.tags, "public-ip-prefix", {}), lookup(var.tags, "all", {})) } @@ -83,10 +83,24 @@ resource "azurerm_public_ip" "cluster-vip" { tags = merge(lookup(var.tags, "public-ip", {}), lookup(var.tags, "all", {})) } +resource "azurerm_public_ip" "vips" { + count = length(var.vips_names) + name = var.vips_names[count.index] + location = module.common.resource_group_location + resource_group_name = module.common.resource_group_name + allocation_method = module.vnet.allocation_method + sku = var.sku + domain_name_label = "${lower(var.vips_names[count.index])}-${count.index}-vip-${random_id.random_id.hex}" + public_ip_prefix_id = var.use_public_ip_prefix ? (var.create_public_ip_prefix ? azurerm_public_ip_prefix.public_ip_prefix[0].id : var.existing_public_ip_prefix_id) : null + tags = merge(lookup(var.tags, "public-ip", {}), lookup(var.tags, "all", {})) +} + resource "azurerm_network_interface" "nic_vip" { depends_on = [ azurerm_public_ip.cluster-vip, - azurerm_public_ip.public-ip] + azurerm_public_ip.public-ip, + azurerm_public_ip.vips, + ] name = "${var.cluster_name}1-eth0" location = module.common.resource_group_location resource_group_name = module.common.resource_group_name @@ -109,6 +123,19 @@ resource "azurerm_network_interface" "nic_vip" { private_ip_address = cidrhost(module.vnet.subnet_prefixes[0], 7) public_ip_address_id = azurerm_public_ip.cluster-vip.id } + + dynamic "ip_configuration" { + for_each = var.vips_names + content { + name = "cluster-vip-${index(var.vips_names, ip_configuration.value) + 1}" + subnet_id = module.vnet.vnet_subnets[0] + primary = false + private_ip_address_allocation = module.vnet.allocation_method + private_ip_address = cidrhost(module.vnet.subnet_prefixes[0], 7 + index(var.vips_names, ip_configuration.value) + 1) + public_ip_address_id = azurerm_public_ip.vips[index(var.vips_names, ip_configuration.value)].id + } + } + lifecycle { ignore_changes = [ # Ignore changes to ip_configuration when Re-applying, e.g. because a cluster failover and associating the cluster- vip with the other member. diff --git a/modules/high_availability_new_vnet/variables.tf b/modules/high_availability_new_vnet/variables.tf index a3c51d8..63b245d 100755 --- a/modules/high_availability_new_vnet/variables.tf +++ b/modules/high_availability_new_vnet/variables.tf @@ -326,4 +326,16 @@ variable "tags" { description = "Assign tags by resource." type = map(map(string)) default = {} +} + +variable "vips_names" { + description = "Names to be used for the VIPs" + type = list(string) + default = [] + + # More than 10 VIPs may result in not enough available IPs available in IpPrefix + validation { + condition = length(var.vips_names) < 10 + error_message = "The number of VIPs must be less than 10." + } } \ No newline at end of file