From ef807de6791d89c0ce1251217662b3ea218cc996 Mon Sep 17 00:00:00 2001 From: nichollri Date: Fri, 27 Sep 2024 14:42:37 -0400 Subject: [PATCH 01/28] Added new directory and readme for replicate work --- Terraform/fsxn-replicate/README.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Terraform/fsxn-replicate/README.md diff --git a/Terraform/fsxn-replicate/README.md b/Terraform/fsxn-replicate/README.md new file mode 100644 index 0000000..185a31d --- /dev/null +++ b/Terraform/fsxn-replicate/README.md @@ -0,0 +1,2 @@ +## Repository Overview +This repostory contians a method to take an existing FSxN system and replicate volumes to a new FSx ONTAP instancefor disaster recovery or backup purposes. It leverages both AWS FSx Terraform provider as well as the ONTAP Terraform provider. From f638a720161b2ff6372c46617aa04be25a1fa346 Mon Sep 17 00:00:00 2001 From: nichollri Date: Mon, 30 Sep 2024 21:39:51 -0400 Subject: [PATCH 02/28] add files with values for first basic test --- Terraform/fsxn-replicate/main.tf | 83 +++++++++++++++++++++++++++ Terraform/fsxn-replicate/output.tf | 10 ++++ Terraform/fsxn-replicate/variables.tf | 49 ++++++++++++++++ 3 files changed, 142 insertions(+) create mode 100644 Terraform/fsxn-replicate/main.tf create mode 100644 Terraform/fsxn-replicate/output.tf create mode 100644 Terraform/fsxn-replicate/variables.tf diff --git a/Terraform/fsxn-replicate/main.tf b/Terraform/fsxn-replicate/main.tf new file mode 100644 index 0000000..3956ae0 --- /dev/null +++ b/Terraform/fsxn-replicate/main.tf @@ -0,0 +1,83 @@ +terraform { + required_providers { + netapp-ontap = { + source = "NetApp/netapp-ontap" + version = "1.1.4" + } + + aws = { + source = "hashicorp/aws" + version = ">= 5.68.0" + } + } +} + +provider "aws" { + region = var.secrets_aws_region +} + +data "aws_secretsmanager_secret_version" "ontap_prime_username_pass" { + secret_id = var.username_pass_secrets_id +} + +data "aws_secretsmanager_secret_version" "ontap_dr_username_pass" { + secret_id = var.dr_username_pass_secrets_id +} + + +provider "netapp-ontap" { + # A connection profile defines how to interface with an ONTAP cluster or svm. + # At least one is required. + connection_profiles = [ + { + name = "primary_clus" + hostname = var.prime_hostname + username = jsondecode(data.aws_secretsmanager_secret_version.ontap_prime_username_pass.secret_string)["username"] + password = jsondecode(data.aws_secretsmanager_secret_version.ontap_prime_username_pass.secret_string)["password"] + validate_certs = var.validate_certs + }, + { + name = "dr_clus" + username = jsondecode(data.aws_secretsmanager_secret_version.ontap_dr_username_pass.secret_string)["username"] + password = jsondecode(data.aws_secretsmanager_secret_version.ontap_dr_username_pass.secret_string)["password"] + hostname = var.dr_hostname + validate_certs = var.validate_certs + }, + ] +} + +data "netapp-ontap_storage_volume_data_source" "my_vol" { + for_each = toset(var.list_of_volumes_to_replicate) + cx_profile_name = "primary_clus" + svm_name = var.prime_svm + name = each.value +} + +resource "netapp-ontap_storage_volume_resource" "example" { + cx_profile_name = "primary_clus" + name = "rvwn_vol1_tf" + svm_name = var.prime_svm + aggregates = [ + { + name = "aggr1" + }, + ] + space_guarantee = "none" + snapshot_policy = "default" + space = { + size = 100 + size_unit = "gb" + logical_space = { + enforcement = true + reporting = true + } + } + tiering = { + policy_name = "auto" + } + nas = { + export_policy_name = "default" + security_style = "unix" + junction_path = "/rvwn_vol1_tf" + } +} \ No newline at end of file diff --git a/Terraform/fsxn-replicate/output.tf b/Terraform/fsxn-replicate/output.tf new file mode 100644 index 0000000..ad54c9f --- /dev/null +++ b/Terraform/fsxn-replicate/output.tf @@ -0,0 +1,10 @@ +output "volume_details" { + value = { + for key, volume in data.netapp-ontap_storage_volume_data_source.my_vol : key => { + name = volume.name + type = volume.type + size = "${volume.space.size}${volume.space.size_unit}" + } + } + description = "Details of the volumes including name, type, size, and size unit" +} \ No newline at end of file diff --git a/Terraform/fsxn-replicate/variables.tf b/Terraform/fsxn-replicate/variables.tf new file mode 100644 index 0000000..04a8435 --- /dev/null +++ b/Terraform/fsxn-replicate/variables.tf @@ -0,0 +1,49 @@ +variable "prime_hostname" { + description = "Hostname or IP address of primary cluster." + type = string +# Development FSxN + default = "198.19.253.210" +} + +variable "prime_svm" { + description = "Name of svm for replication in the primary cluster." + type = string + default = "vs1cli" +} + +variable "secrets_aws_region" { + description = "Region where the AWS secret for username/password reside" + type = string + default = "us-west-2" +} + +variable "username_pass_secrets_id" { + description = "Name of secret ID in AWS secrets" + type = string + default = "rvwn_replicate_ontap_creds" +} + +variable "list_of_volumes_to_replicate" { + description = "list of volumes to replicate to dr fsxn" + type = list(string) + default = ["cifs_share", "rvwn_from_bxp", "unix"] +} + +variable "dr_username_pass_secrets_id" { + description = "Name of secret ID in AWS secrets" + type = string + default = "rvwn_replicate_ontap_creds" +} + +variable "dr_hostname" { + description = "Hostname or IP address of disaster recovery cluster." + type = string +# Prod DR FSxN + default = "198.19.254.83" +} + +variable "validate_certs" { + description = "Do we validate the cluster certs (true or false)" + type = string + default = "false" +} \ No newline at end of file From 80cbd3abd0324e9780da2632e06ae18594db1605 Mon Sep 17 00:00:00 2001 From: nichollri Date: Thu, 3 Oct 2024 08:15:47 -0500 Subject: [PATCH 03/28] added deploy of DR system, commented out source stuff for now --- Terraform/fsxn-replicate/main.tf | 135 ++++++---- Terraform/fsxn-replicate/output.tf | 20 +- Terraform/fsxn-replicate/security_groups.tf | 269 ++++++++++++++++++++ Terraform/fsxn-replicate/variables.tf | 173 ++++++++++++- 4 files changed, 535 insertions(+), 62 deletions(-) create mode 100644 Terraform/fsxn-replicate/security_groups.tf diff --git a/Terraform/fsxn-replicate/main.tf b/Terraform/fsxn-replicate/main.tf index 3956ae0..05df2da 100644 --- a/Terraform/fsxn-replicate/main.tf +++ b/Terraform/fsxn-replicate/main.tf @@ -25,59 +25,94 @@ data "aws_secretsmanager_secret_version" "ontap_dr_username_pass" { } -provider "netapp-ontap" { +#provider "netapp-ontap" { # A connection profile defines how to interface with an ONTAP cluster or svm. # At least one is required. - connection_profiles = [ - { - name = "primary_clus" - hostname = var.prime_hostname - username = jsondecode(data.aws_secretsmanager_secret_version.ontap_prime_username_pass.secret_string)["username"] - password = jsondecode(data.aws_secretsmanager_secret_version.ontap_prime_username_pass.secret_string)["password"] - validate_certs = var.validate_certs - }, - { - name = "dr_clus" - username = jsondecode(data.aws_secretsmanager_secret_version.ontap_dr_username_pass.secret_string)["username"] - password = jsondecode(data.aws_secretsmanager_secret_version.ontap_dr_username_pass.secret_string)["password"] - hostname = var.dr_hostname - validate_certs = var.validate_certs - }, - ] -} +# connection_profiles = [ +# { +# name = "primary_clus" +# hostname = var.prime_hostname +# username = jsondecode(data.aws_secretsmanager_secret_version.ontap_prime_username_pass.secret_string)["username"] +# password = jsondecode(data.aws_secretsmanager_secret_version.ontap_prime_username_pass.secret_string)["password"] +# validate_certs = var.validate_certs +# }, +# { +# name = "dr_clus" +# username = jsondecode(data.aws_secretsmanager_secret_version.ontap_dr_username_pass.secret_string)["username"] +# password = jsondecode(data.aws_secretsmanager_secret_version.ontap_dr_username_pass.secret_string)["password"] +# hostname = var.dr_hostname +# validate_certs = var.validate_certs +# }, +# ] +#} -data "netapp-ontap_storage_volume_data_source" "my_vol" { - for_each = toset(var.list_of_volumes_to_replicate) - cx_profile_name = "primary_clus" - svm_name = var.prime_svm - name = each.value -} +resource "aws_fsx_ontap_file_system" "terraform-fsxn" { + subnet_ids = var.dr_fsx_deploy_type == "MULTI_AZ_1" || var.dr_fsx_deploy_type == "MULTI_AZ_2" ? [var.dr_fsx_subnets["primarysub"], var.dr_fsx_subnets["secondarysub"]] : [var.dr_fsx_subnets["primarysub"]] + preferred_subnet_id = var.dr_fsx_subnets["primarysub"] + + storage_capacity = var.dr_fsx_capacity_size_gb + security_group_ids = var.create_sg ? [element(aws_security_group.fsx_sg[*].id, 0)] : var.security_group_ids + deployment_type = var.dr_fsx_deploy_type + throughput_capacity_per_ha_pair = var.dr_fsx_tput_in_MBps + ha_pairs = var.dr_ha_pairs + endpoint_ip_address_range = var.dr_endpoint_ip_address_range + route_table_ids = var.dr_route_table_ids + dynamic "disk_iops_configuration" { + for_each = length(var.dr_disk_iops_configuration) > 0 ? [var.dr_disk_iops_configuration] : [] -resource "netapp-ontap_storage_volume_resource" "example" { - cx_profile_name = "primary_clus" - name = "rvwn_vol1_tf" - svm_name = var.prime_svm - aggregates = [ - { - name = "aggr1" - }, - ] - space_guarantee = "none" - snapshot_policy = "default" - space = { - size = 100 - size_unit = "gb" - logical_space = { - enforcement = true - reporting = true + content { + iops = try(disk_iops_configuration.value.iops, null) + mode = try(disk_iops_configuration.value.mode, null) } } - tiering = { - policy_name = "auto" - } - nas = { - export_policy_name = "default" - security_style = "unix" - junction_path = "/rvwn_vol1_tf" - } -} \ No newline at end of file + + tags = merge(var.dr_tags, {Name = var.dr_fsx_name}) + weekly_maintenance_start_time = var.dr_maintenance_start_time + kms_key_id = var.dr_kms_key_id + automatic_backup_retention_days = var.dr_backup_retention_days + daily_automatic_backup_start_time = var.dr_backup_retention_days > 0 ? var.dr_daily_backup_start_time : null + fsx_admin_password = jsondecode(data.aws_secretsmanager_secret_version.ontap_dr_username_pass.secret_string)["password"] +} + +# Define a storage virtual machine. +resource "aws_fsx_ontap_storage_virtual_machine" "mysvm" { + file_system_id = aws_fsx_ontap_file_system.terraform-fsxn.id + name = var.dr_svm_name + root_volume_security_style = var.dr_root_vol_sec_style +} + +#data "netapp-ontap_storage_volume_data_source" "my_vol" { +# for_each = toset(var.list_of_volumes_to_replicate) +# cx_profile_name = "primary_clus" +# svm_name = var.prime_svm +# name = each.value +#} + +# resource "netapp-ontap_storage_volume_resource" "example" { +# cx_profile_name = "primary_clus" +# name = "rvwn_vol1_tf" +# svm_name = var.prime_svm +# aggregates = [ +# { +# name = "aggr1" +# }, +# ] +# space_guarantee = "none" +# snapshot_policy = "default" +# space = { +# size = 100 +# size_unit = "gb" +# logical_space = { +# enforcement = true +# reporting = true +# } +# } +# tiering = { +# policy_name = "auto" +# } +# nas = { +# export_policy_name = "default" +# security_style = "unix" +# junction_path = "/rvwn_vol1_tf" +# } +#} diff --git a/Terraform/fsxn-replicate/output.tf b/Terraform/fsxn-replicate/output.tf index ad54c9f..fdff0a4 100644 --- a/Terraform/fsxn-replicate/output.tf +++ b/Terraform/fsxn-replicate/output.tf @@ -1,10 +1,10 @@ -output "volume_details" { - value = { - for key, volume in data.netapp-ontap_storage_volume_data_source.my_vol : key => { - name = volume.name - type = volume.type - size = "${volume.space.size}${volume.space.size_unit}" - } - } - description = "Details of the volumes including name, type, size, and size unit" -} \ No newline at end of file +#output "volume_details" { +# value = { +# for key, volume in data.netapp-ontap_storage_volume_data_source.my_vol : key => { +# name = volume.name +# type = volume.type +# size = "${volume.space.size}${volume.space.size_unit}" +# } +# } +# description = "Details of the volumes including name, type, size, and size unit" +#} diff --git a/Terraform/fsxn-replicate/security_groups.tf b/Terraform/fsxn-replicate/security_groups.tf new file mode 100644 index 0000000..ccac53c --- /dev/null +++ b/Terraform/fsxn-replicate/security_groups.tf @@ -0,0 +1,269 @@ +/* + * The following defines a Security Group for FSx ONTAP that allows the required ports for NFS, CIFS, + * Kerberos, and iSCSI as well as SnapMirror. + * + * While you don't have to use this SG, one will need to be assigned to the FSx ONTAP file system, + * otherwise it won't be able to communicate with the clients. + * + * To not create the security group, set the variable create_sg to false in the variables.tf file. + * Will will also need to set the security_group_id to the ID of the security group you want to use + * in the variables.tf file. + * + */ + +resource "aws_security_group" "fsx_sg" { + description = "Allow FSx ONTAP required ports" + count = var.create_sg ? 1 : 0 + name_prefix = var.security_group_name_prefix + vpc_id = var.dr_vpc_id +} + +resource "aws_vpc_security_group_ingress_rule" "all_icmp" { + description = "Allow all ICMP traffic" + count = var.create_sg ? 1 : 0 + security_group_id = aws_security_group.fsx_sg[count.index].id + cidr_ipv4 = (var.cidr_for_sg != "" ? var.cidr_for_sg : null) + referenced_security_group_id = (var.source_sg_id != "" ? var.source_sg_id : null) + from_port = -1 + to_port = -1 + ip_protocol = "icmp" +} + +resource "aws_vpc_security_group_ingress_rule" "nfs_tcp" { + description = "Remote procedure call for NFS" + count = var.create_sg ? 1 : 0 + security_group_id = aws_security_group.fsx_sg[count.index].id + cidr_ipv4 = (var.cidr_for_sg != "" ? var.cidr_for_sg : null) + referenced_security_group_id = (var.source_sg_id != "" ? var.source_sg_id : null) + from_port = 111 + to_port = 111 + ip_protocol = "tcp" +} + +resource "aws_vpc_security_group_ingress_rule" "nfs_udp" { + description = "Remote procedure call for NFS" + count = var.create_sg ? 1 : 0 + security_group_id = aws_security_group.fsx_sg[count.index].id + cidr_ipv4 = (var.cidr_for_sg != "" ? var.cidr_for_sg : null) + referenced_security_group_id = (var.source_sg_id != "" ? var.source_sg_id : null) + from_port = 111 + to_port = 111 + ip_protocol = "udp" +} + +resource "aws_vpc_security_group_ingress_rule" "cifs" { + description = "NetBIOS service session for CIFS" + count = var.create_sg ? 1 : 0 + security_group_id = aws_security_group.fsx_sg[count.index].id + cidr_ipv4 = (var.cidr_for_sg != "" ? var.cidr_for_sg : null) + referenced_security_group_id = (var.source_sg_id != "" ? var.source_sg_id : null) + from_port = 139 + to_port = 139 + ip_protocol = "tcp" +} + +resource "aws_vpc_security_group_ingress_rule" "snmp_tcp" { + description = "Simple network management protocol for log collection" + count = var.create_sg ? 1 : 0 + security_group_id = aws_security_group.fsx_sg[count.index].id + cidr_ipv4 = (var.cidr_for_sg != "" ? var.cidr_for_sg : null) + referenced_security_group_id = (var.source_sg_id != "" ? var.source_sg_id : null) + from_port = 161 + to_port = 162 + ip_protocol = "tcp" +} + +resource "aws_vpc_security_group_ingress_rule" "snmp_udp" { + description = "Simple network management protocol for log collection" + count = var.create_sg ? 1 : 0 + security_group_id = aws_security_group.fsx_sg[count.index].id + cidr_ipv4 = (var.cidr_for_sg != "" ? var.cidr_for_sg : null) + referenced_security_group_id = (var.source_sg_id != "" ? var.source_sg_id : null) + from_port = 161 + to_port = 162 + ip_protocol = "udp" +} + +resource "aws_vpc_security_group_ingress_rule" "smb_cifs" { + description = "Microsoft SMB/CIFS over TCP with NetBIOS framing" + count = var.create_sg ? 1 : 0 + security_group_id = aws_security_group.fsx_sg[count.index].id + cidr_ipv4 = (var.cidr_for_sg != "" ? var.cidr_for_sg : null) + referenced_security_group_id = (var.source_sg_id != "" ? var.source_sg_id : null) + from_port = 445 + to_port = 445 + ip_protocol = "tcp" +} + +resource "aws_vpc_security_group_ingress_rule" "nfs_mount_tcp" { + description = "NFS mount" + count = var.create_sg ? 1 : 0 + security_group_id = aws_security_group.fsx_sg[count.index].id + cidr_ipv4 = (var.cidr_for_sg != "" ? var.cidr_for_sg : null) + referenced_security_group_id = (var.source_sg_id != "" ? var.source_sg_id : null) + from_port = 635 + to_port = 635 + ip_protocol = "tcp" +} + +resource "aws_vpc_security_group_ingress_rule" "kerberos" { + description = "Kerberos authentication" + count = var.create_sg ? 1 : 0 + security_group_id = aws_security_group.fsx_sg[count.index].id + cidr_ipv4 = (var.cidr_for_sg != "" ? var.cidr_for_sg : null) + referenced_security_group_id = (var.source_sg_id != "" ? var.source_sg_id : null) + from_port = 749 + to_port = 749 + ip_protocol = "tcp" +} + +resource "aws_vpc_security_group_ingress_rule" "nfs_server_daemon" { + description = "NFS server daemon" + count = var.create_sg ? 1 : 0 + security_group_id = aws_security_group.fsx_sg[count.index].id + cidr_ipv4 = (var.cidr_for_sg != "" ? var.cidr_for_sg : null) + referenced_security_group_id = (var.source_sg_id != "" ? var.source_sg_id : null) + from_port = 2049 + to_port = 2049 + ip_protocol = "tcp" +} + +resource "aws_vpc_security_group_ingress_rule" "nfs_server_daemon_udp" { + description = "NFS server daemon" + count = var.create_sg ? 1 : 0 + security_group_id = aws_security_group.fsx_sg[count.index].id + cidr_ipv4 = (var.cidr_for_sg != "" ? var.cidr_for_sg : null) + referenced_security_group_id = (var.source_sg_id != "" ? var.source_sg_id : null) + from_port = 2049 + to_port = 2049 + ip_protocol = "udp" +} + +resource "aws_vpc_security_group_ingress_rule" "nfs_lock_daemon" { + description = "NFS lock daemon" + count = var.create_sg ? 1 : 0 + security_group_id = aws_security_group.fsx_sg[count.index].id + cidr_ipv4 = (var.cidr_for_sg != "" ? var.cidr_for_sg : null) + referenced_security_group_id = (var.source_sg_id != "" ? var.source_sg_id : null) + from_port = 4045 + to_port = 4045 + ip_protocol = "tcp" +} + +resource "aws_vpc_security_group_ingress_rule" "nfs_lock_daemon_udp" { + description = "NFS lock daemon" + count = var.create_sg ? 1 : 0 + security_group_id = aws_security_group.fsx_sg[count.index].id + cidr_ipv4 = (var.cidr_for_sg != "" ? var.cidr_for_sg : null) + referenced_security_group_id = (var.source_sg_id != "" ? var.source_sg_id : null) + from_port = 4045 + to_port = 4045 + ip_protocol = "udp" +} + +resource "aws_vpc_security_group_ingress_rule" "nfs_status_monitor" { + description = "Status monitor for NFS" + count = var.create_sg ? 1 : 0 + security_group_id = aws_security_group.fsx_sg[count.index].id + cidr_ipv4 = (var.cidr_for_sg != "" ? var.cidr_for_sg : null) + referenced_security_group_id = (var.source_sg_id != "" ? var.source_sg_id : null) + from_port = 4046 + to_port = 4046 + ip_protocol = "tcp" +} + +resource "aws_vpc_security_group_ingress_rule" "nfs_status_monitor_udp" { + description = "Status monitor for NFS" + count = var.create_sg ? 1 : 0 + security_group_id = aws_security_group.fsx_sg[count.index].id + cidr_ipv4 = (var.cidr_for_sg != "" ? var.cidr_for_sg : null) + referenced_security_group_id = (var.source_sg_id != "" ? var.source_sg_id : null) + from_port = 4046 + to_port = 4046 + ip_protocol = "udp" +} + +resource "aws_vpc_security_group_ingress_rule" "nfs_rquotad" { + description = "Remote quota server for NFS" + count = var.create_sg ? 1 : 0 + security_group_id = aws_security_group.fsx_sg[count.index].id + cidr_ipv4 = (var.cidr_for_sg != "" ? var.cidr_for_sg : null) + referenced_security_group_id = (var.source_sg_id != "" ? var.source_sg_id : null) + from_port = 4049 + to_port = 4049 + ip_protocol = "udp" +} + +resource "aws_vpc_security_group_ingress_rule" "iscsi_tcp" { + description = "iSCSI" + count = var.create_sg ? 1 : 0 + security_group_id = aws_security_group.fsx_sg[count.index].id + cidr_ipv4 = (var.cidr_for_sg != "" ? var.cidr_for_sg : null) + referenced_security_group_id = (var.source_sg_id != "" ? var.source_sg_id : null) + from_port = 3260 + to_port = 3260 + ip_protocol = "tcp" +} + +resource "aws_vpc_security_group_ingress_rule" "Snapmirror_Intercluster_communication" { + description = "Snapmirror Intercluster communication" + count = var.create_sg ? 1 : 0 + security_group_id = aws_security_group.fsx_sg[count.index].id + cidr_ipv4 = (var.cidr_for_sg != "" ? var.cidr_for_sg : null) + referenced_security_group_id = (var.source_sg_id != "" ? var.source_sg_id : null) + from_port = 11104 + to_port = 11104 + ip_protocol = "tcp" +} + +resource "aws_vpc_security_group_ingress_rule" "Snapmirror_data_transfer" { + description = "Snapmirror data transfer" + count = var.create_sg ? 1 : 0 + security_group_id = aws_security_group.fsx_sg[count.index].id + cidr_ipv4 = (var.cidr_for_sg != "" ? var.cidr_for_sg : null) + referenced_security_group_id = (var.source_sg_id != "" ? var.source_sg_id : null) + from_port = 11105 + to_port = 11105 + ip_protocol = "tcp" +} + +resource "aws_vpc_security_group_ingress_rule" "nfs_mount_udp" { + description = "NFS mount" + count = var.create_sg ? 1 : 0 + security_group_id = aws_security_group.fsx_sg[count.index].id + cidr_ipv4 = (var.cidr_for_sg != "" ? var.cidr_for_sg : null) + referenced_security_group_id = (var.source_sg_id != "" ? var.source_sg_id : null) + from_port = 635 + to_port = 635 + ip_protocol = "udp" +} + +resource "aws_vpc_security_group_ingress_rule" "ssh" { + description = "ssh" + count = var.create_sg ? 1 : 0 + security_group_id = aws_security_group.fsx_sg[count.index].id + cidr_ipv4 = (var.cidr_for_sg != "" ? var.cidr_for_sg : null) + referenced_security_group_id = (var.source_sg_id != "" ? var.source_sg_id : null) + from_port = 22 + to_port = 22 + ip_protocol = "tcp" +} + +resource "aws_vpc_security_group_ingress_rule" "s3_and_api" { + description = "Provice acccess to S3 and the ONTAP REST API" + count = var.create_sg ? 1 : 0 + security_group_id = aws_security_group.fsx_sg[count.index].id + cidr_ipv4 = (var.cidr_for_sg != "" ? var.cidr_for_sg : null) + referenced_security_group_id = (var.source_sg_id != "" ? var.source_sg_id : null) + from_port = 443 + to_port = 443 + ip_protocol = "tcp" +} + +resource "aws_vpc_security_group_egress_rule" "allow_all_traffic" { + count = var.create_sg ? 1 : 0 + description = "Allow all out bound traffic" + security_group_id = aws_security_group.fsx_sg[count.index].id + cidr_ipv4 = "0.0.0.0/0" + ip_protocol = "-1" +} diff --git a/Terraform/fsxn-replicate/variables.tf b/Terraform/fsxn-replicate/variables.tf index 04a8435..f0379d2 100644 --- a/Terraform/fsxn-replicate/variables.tf +++ b/Terraform/fsxn-replicate/variables.tf @@ -14,7 +14,7 @@ variable "prime_svm" { variable "secrets_aws_region" { description = "Region where the AWS secret for username/password reside" type = string - default = "us-west-2" + default = "us-east-2" } variable "username_pass_secrets_id" { @@ -29,6 +29,175 @@ variable "list_of_volumes_to_replicate" { default = ["cifs_share", "rvwn_from_bxp", "unix"] } +variable "dr_fsx_name" { + description = "The name to assign to the destination FSxN file system." + type = string + default = "terraform-dr-fsxn" +} + +variable "dr_fsx_deploy_type" { + description = "The file system deployment type. Supported values are 'MULTI_AZ_1', 'SINGLE_AZ_1', 'MULTI_AZ_2', and 'SINGLE_AZ_2'. MULTI_AZ_1 and SINGLE_AZ_1 are Gen 1. MULTI_AZ_2 and SINGLE_AZ_2 are Gen 2." + type = string + default = "SINGLE_AZ_1" + validation { + condition = contains(["MULTI_AZ_1", "SINGLE_AZ_1", "MULTI_AZ_2", "SINGLE_AZ_2"], var.dr_fsx_deploy_type) + error_message = "Invalid deployment type. Valid values are MULTI_AZ_1, SINGLE_AZ_1, MULTI_AZ_2 or SINGLE_AZ_2." + } +} + +variable "dr_fsx_subnets" { + description = "The primary subnet ID, and secondary subnet ID if you are deploying in a Multi AZ environment, file system will be accessible from. For MULTI_AZ deployment types both subnets are required. For SINGLE_AZ deployment type, only the primary subnet is used." + type = map(any) + default = { + "primarysub" = "subnet-0a64530a9c7afc84c" + "secondarysub" = "subnet-33333333" + } +} + +variable "dr_fsx_capacity_size_gb" { + description = "The storage capacity in GiBs of the FSxN file system. Valid values between 1024 (1 TiB) and 1048576 (1 PiB). Gen 1 deployment types are limited to 192 TiB. Gen 2 Multi AZ is limited to 512 TiB. Gen 2 Single AZ is limited to 1 PiB." + type = number + default = 1024 + validation { + condition = var.dr_fsx_capacity_size_gb >= 1024 && var.dr_fsx_capacity_size_gb <= 1048576 + error_message = "Invalid capacity size. Valid values are between 1024 (1TiB) and 1045876 (1 PiB)." + } +} + +variable "dr_fsx_tput_in_MBps" { + description = "The throughput capacity (in MBps) for the file system. Valid values are 128, 256, 512, 1024, 2048, and 4096 for Gen 1, and 384, 768, 1536, 3072 and 6144 for Gen 2." + type = string + default = "128" + validation { + condition = contains(["128", "256", "384", "512", "768", "1024", "1536", "2048", "3072", "4086", "6144"], var.dr_fsx_tput_in_MBps) + error_message = "Invalid throughput value. Valid values are 128, 256, 384, 512, 768, 1024, 1536, 2048, 3072, 4086, 6144." + } +} + +variable "dr_ha_pairs" { + description = "The number of HA pairs in the file system. Valid values are from 1 through 12. Only single AZ Gen 2 deployment type supports more than 1 HA pair." + type = number + default = 1 + validation { + condition = var.dr_ha_pairs >= 1 && var.dr_ha_pairs <= 12 + error_message = "Invalid number of HA pairs. Valid values are from 1 through 12." + } +} + +variable "dr_endpoint_ip_address_range" { + description = "The IP address range that the FSxN file system will be accessible from. This is only used for Multi AZ deployment types and must be left a null for Single AZ deployment types." + type = string + default = null +} + +variable "dr_route_table_ids" { + description = "An array of routing table IDs that will be modified to allow access to the FSxN file system. This is only used for Multi AZ deployment types and must be left as null for Single AZ deployment types." + type = list(string) + default = [] +} + +variable "dr_disk_iops_configuration" { + description = "The SSD IOPS configuration for the file system. Valid modes are 'AUTOMATIC' (3 iops per GB provisioned) or 'USER_PROVISIONED'. NOTE: Due to a bug in the AWS FSx provider, if you want AUTOMATIC, then leave this variable empty. If you want USER_PROVISIONED, then add a 'mode=USER_PROVISIONED' (with USER_PROVISIONED enclosed in double quotes) and 'iops=number' where number is between 1 and 160000." + type = map(any) + default = {} +} + +variable "dr_tags" { + description = "Tags to be applied to the FSxN file system. The format is '{Name1 = value, Name2 = value}' where value should be enclosed in double quotes." + type = map(any) + default = {} +} + +variable "dr_maintenance_start_time" { + description = "The preferred start time to perform weekly maintenance, in UTC time zone. The format is 'D:HH:MM' format. D is the day of the week, where 1=Monday and 7=Sunday." + type = string + default = "7:00:00" +} + +variable "dr_kms_key_id" { + description = "ARN for the KMS Key to encrypt the file system at rest. Defaults to an AWS managed KMS Key." + type = string + default = null +} + +variable "dr_backup_retention_days" { + description = "The number of days to retain automatic backups. Setting this to 0 disables automatic backups. You can retain automatic backups for a maximum of 90 days." + type = number + default = 0 + validation { + condition = var.dr_backup_retention_days >= 0 && var.dr_backup_retention_days <= 90 + error_message = "Invalid backup retention days. Valid values are between 0 and 90." + } +} + +variable "dr_daily_backup_start_time" { + description = "A recurring daily time, in the format HH:MM. HH is the zero-padded hour of the day (0-23), and MM is the zero-padded minute of the hour. Requires automatic_backup_retention_days to be set." + type = string + default = "00:00" +} + +variable "dr_svm_name" { + description = "The name of the Storage Virtual Machine" + type = string + default = "fsx-dr" +} + +variable "dr_root_vol_sec_style" { + description = "Specifies the root volume security style, Valid values are UNIX, NTFS, and MIXED (although MIXED is not recommended). All volumes created under this SVM will inherit the root security style unless the security style is specified on the volume." + type = string + default = "UNIX" +} + +/* + * These last set of variables have to do with a security group that can be optionally + * created. The security group will have all the ingress rules that will allow access + * to all the protocols that an FSxN supports (e.g. SMB, NFS, etc). See the security_groups.tf + * for more information. + * + * If you decide to create the security group, you can specify either the CIDR block to + * be used as the source to the ingress rules OR the ID of a security group to be used as + * the source to the ingress rules. You can't specify both. + * + * If you decide not to create the security group, you must set the security_group_id to + * the ID of the security group that you want to use. + * + */ +variable "create_sg" { + description = "Determines whether the Security Group should be created as part of this deployment or not." + type = bool + default = true +} + +variable "security_group_ids" { + description = "If you are not creating the security group, provide a list of IDs of security groups to be used." + type = list(string) + default = [] +} + +variable "security_group_name_prefix" { + description = "The prefix to the security group name that will be created." + type = string + default = "fsxn-sg" +} + +variable "cidr_for_sg" { + description = "The cidr block to be used for the created security ingress rules. Set to an empty string if you want to use the source_sg_id as the source." + type = string + default = "10.0.0.0/8" +} + +variable "source_sg_id" { + description = "The ID of the security group to allow access to the FSxN file system. Set to an empty string if you want to use the cidr_for_sg as the source." + type = string + default = "" +} + +variable "dr_vpc_id" { + description = "The VPC ID where the security group will be created." + type = string + default = "vpc-0684c5d22c4b48dd4" +} + variable "dr_username_pass_secrets_id" { description = "Name of secret ID in AWS secrets" type = string @@ -46,4 +215,4 @@ variable "validate_certs" { description = "Do we validate the cluster certs (true or false)" type = string default = "false" -} \ No newline at end of file +} From 09d67798cb02bedb1f798d486e741efa67558acf Mon Sep 17 00:00:00 2001 From: nichollri Date: Mon, 7 Oct 2024 15:43:04 -0500 Subject: [PATCH 04/28] preliminary steps, 2 regions, create dr-fsxn, new sg logic --- Terraform/fsxn-replicate/main.tf | 106 +++++++------- Terraform/fsxn-replicate/output.tf | 20 +-- Terraform/fsxn-replicate/security_groups.tf | 146 +++++++++++--------- Terraform/fsxn-replicate/variables.tf | 10 +- 4 files changed, 149 insertions(+), 133 deletions(-) diff --git a/Terraform/fsxn-replicate/main.tf b/Terraform/fsxn-replicate/main.tf index 05df2da..628270a 100644 --- a/Terraform/fsxn-replicate/main.tf +++ b/Terraform/fsxn-replicate/main.tf @@ -13,10 +13,16 @@ terraform { } provider "aws" { - region = var.secrets_aws_region + region = var.dr_aws_region +} + +provider "aws" { + alias = "prime-aws-region" + region = var.prime_aws_region } data "aws_secretsmanager_secret_version" "ontap_prime_username_pass" { + provider = aws.prime-aws-region secret_id = var.username_pass_secrets_id } @@ -25,26 +31,20 @@ data "aws_secretsmanager_secret_version" "ontap_dr_username_pass" { } -#provider "netapp-ontap" { +provider "netapp-ontap" { # A connection profile defines how to interface with an ONTAP cluster or svm. # At least one is required. -# connection_profiles = [ -# { -# name = "primary_clus" -# hostname = var.prime_hostname -# username = jsondecode(data.aws_secretsmanager_secret_version.ontap_prime_username_pass.secret_string)["username"] -# password = jsondecode(data.aws_secretsmanager_secret_version.ontap_prime_username_pass.secret_string)["password"] -# validate_certs = var.validate_certs -# }, -# { -# name = "dr_clus" -# username = jsondecode(data.aws_secretsmanager_secret_version.ontap_dr_username_pass.secret_string)["username"] -# password = jsondecode(data.aws_secretsmanager_secret_version.ontap_dr_username_pass.secret_string)["password"] -# hostname = var.dr_hostname -# validate_certs = var.validate_certs -# }, -# ] -#} + connection_profiles = [ + { + name = "primary_clus" + hostname = var.prime_hostname + username = jsondecode(data.aws_secretsmanager_secret_version.ontap_prime_username_pass.secret_string)["username"] + password = jsondecode(data.aws_secretsmanager_secret_version.ontap_prime_username_pass.secret_string)["password"] + validate_certs = var.validate_certs + } + + ] +} resource "aws_fsx_ontap_file_system" "terraform-fsxn" { subnet_ids = var.dr_fsx_deploy_type == "MULTI_AZ_1" || var.dr_fsx_deploy_type == "MULTI_AZ_2" ? [var.dr_fsx_subnets["primarysub"], var.dr_fsx_subnets["secondarysub"]] : [var.dr_fsx_subnets["primarysub"]] @@ -81,38 +81,38 @@ resource "aws_fsx_ontap_storage_virtual_machine" "mysvm" { root_volume_security_style = var.dr_root_vol_sec_style } -#data "netapp-ontap_storage_volume_data_source" "my_vol" { -# for_each = toset(var.list_of_volumes_to_replicate) -# cx_profile_name = "primary_clus" -# svm_name = var.prime_svm -# name = each.value -#} +data "netapp-ontap_storage_volume_data_source" "my_vol" { + for_each = toset(var.list_of_volumes_to_replicate) + cx_profile_name = "primary_clus" + svm_name = var.prime_svm + name = each.value +} -# resource "netapp-ontap_storage_volume_resource" "example" { -# cx_profile_name = "primary_clus" -# name = "rvwn_vol1_tf" -# svm_name = var.prime_svm -# aggregates = [ -# { -# name = "aggr1" -# }, -# ] -# space_guarantee = "none" -# snapshot_policy = "default" -# space = { -# size = 100 -# size_unit = "gb" -# logical_space = { -# enforcement = true -# reporting = true -# } -# } -# tiering = { -# policy_name = "auto" -# } -# nas = { -# export_policy_name = "default" -# security_style = "unix" -# junction_path = "/rvwn_vol1_tf" -# } -#} + resource "netapp-ontap_storage_volume_resource" "example" { + cx_profile_name = "primary_clus" + name = "rvwn_vol1_tf" + svm_name = var.prime_svm + aggregates = [ + { + name = "aggr1" + }, + ] + space_guarantee = "none" + snapshot_policy = "default" + space = { + size = 100 + size_unit = "gb" + logical_space = { + enforcement = true + reporting = true + } + } + tiering = { + policy_name = "auto" + } + nas = { + export_policy_name = "default" + security_style = "unix" + junction_path = "/rvwn_vol1_tf" + } +} diff --git a/Terraform/fsxn-replicate/output.tf b/Terraform/fsxn-replicate/output.tf index fdff0a4..1c97bcc 100644 --- a/Terraform/fsxn-replicate/output.tf +++ b/Terraform/fsxn-replicate/output.tf @@ -1,10 +1,10 @@ -#output "volume_details" { -# value = { -# for key, volume in data.netapp-ontap_storage_volume_data_source.my_vol : key => { -# name = volume.name -# type = volume.type -# size = "${volume.space.size}${volume.space.size_unit}" -# } -# } -# description = "Details of the volumes including name, type, size, and size unit" -#} +output "volume_details" { + value = { + for key, volume in data.netapp-ontap_storage_volume_data_source.my_vol : key => { + name = volume.name + type = volume.type + size = "${volume.space.size}${volume.space.size_unit}" + } + } + description = "Details of the volumes including name, type, size, and size unit" +} diff --git a/Terraform/fsxn-replicate/security_groups.tf b/Terraform/fsxn-replicate/security_groups.tf index ccac53c..0c882f6 100644 --- a/Terraform/fsxn-replicate/security_groups.tf +++ b/Terraform/fsxn-replicate/security_groups.tf @@ -11,19 +11,29 @@ * */ +locals { + mycount = var.create_sg ? 1 : 0 + my_ref_sec_group_id = (var.source_sg_id != "" ? var.source_sg_id : null) + my_cidr = (var.cidr_for_sg != "" ? var.cidr_for_sg : null) +} + resource "aws_security_group" "fsx_sg" { description = "Allow FSx ONTAP required ports" - count = var.create_sg ? 1 : 0 + count = local.mycount name_prefix = var.security_group_name_prefix vpc_id = var.dr_vpc_id } +# locals { +# my_security_group_id = aws_security_group.fsx_sg[count.index].id +# } + resource "aws_vpc_security_group_ingress_rule" "all_icmp" { description = "Allow all ICMP traffic" - count = var.create_sg ? 1 : 0 + count = local.mycount security_group_id = aws_security_group.fsx_sg[count.index].id - cidr_ipv4 = (var.cidr_for_sg != "" ? var.cidr_for_sg : null) - referenced_security_group_id = (var.source_sg_id != "" ? var.source_sg_id : null) + cidr_ipv4 = local.my_cidr + referenced_security_group_id = local.my_ref_sec_group_id from_port = -1 to_port = -1 ip_protocol = "icmp" @@ -31,10 +41,10 @@ resource "aws_vpc_security_group_ingress_rule" "all_icmp" { resource "aws_vpc_security_group_ingress_rule" "nfs_tcp" { description = "Remote procedure call for NFS" - count = var.create_sg ? 1 : 0 + count = local.mycount security_group_id = aws_security_group.fsx_sg[count.index].id - cidr_ipv4 = (var.cidr_for_sg != "" ? var.cidr_for_sg : null) - referenced_security_group_id = (var.source_sg_id != "" ? var.source_sg_id : null) + cidr_ipv4 = local.my_cidr + referenced_security_group_id = local.my_ref_sec_group_id from_port = 111 to_port = 111 ip_protocol = "tcp" @@ -42,10 +52,10 @@ resource "aws_vpc_security_group_ingress_rule" "nfs_tcp" { resource "aws_vpc_security_group_ingress_rule" "nfs_udp" { description = "Remote procedure call for NFS" - count = var.create_sg ? 1 : 0 + count = local.mycount security_group_id = aws_security_group.fsx_sg[count.index].id - cidr_ipv4 = (var.cidr_for_sg != "" ? var.cidr_for_sg : null) - referenced_security_group_id = (var.source_sg_id != "" ? var.source_sg_id : null) + cidr_ipv4 = local.my_cidr + referenced_security_group_id = local.my_ref_sec_group_id from_port = 111 to_port = 111 ip_protocol = "udp" @@ -53,10 +63,10 @@ resource "aws_vpc_security_group_ingress_rule" "nfs_udp" { resource "aws_vpc_security_group_ingress_rule" "cifs" { description = "NetBIOS service session for CIFS" - count = var.create_sg ? 1 : 0 + count = local.mycount security_group_id = aws_security_group.fsx_sg[count.index].id - cidr_ipv4 = (var.cidr_for_sg != "" ? var.cidr_for_sg : null) - referenced_security_group_id = (var.source_sg_id != "" ? var.source_sg_id : null) + cidr_ipv4 = local.my_cidr + referenced_security_group_id = local.my_ref_sec_group_id from_port = 139 to_port = 139 ip_protocol = "tcp" @@ -64,10 +74,10 @@ resource "aws_vpc_security_group_ingress_rule" "cifs" { resource "aws_vpc_security_group_ingress_rule" "snmp_tcp" { description = "Simple network management protocol for log collection" - count = var.create_sg ? 1 : 0 + count = local.mycount security_group_id = aws_security_group.fsx_sg[count.index].id - cidr_ipv4 = (var.cidr_for_sg != "" ? var.cidr_for_sg : null) - referenced_security_group_id = (var.source_sg_id != "" ? var.source_sg_id : null) + cidr_ipv4 = local.my_cidr + referenced_security_group_id = local.my_ref_sec_group_id from_port = 161 to_port = 162 ip_protocol = "tcp" @@ -75,10 +85,10 @@ resource "aws_vpc_security_group_ingress_rule" "snmp_tcp" { resource "aws_vpc_security_group_ingress_rule" "snmp_udp" { description = "Simple network management protocol for log collection" - count = var.create_sg ? 1 : 0 + count = local.mycount security_group_id = aws_security_group.fsx_sg[count.index].id - cidr_ipv4 = (var.cidr_for_sg != "" ? var.cidr_for_sg : null) - referenced_security_group_id = (var.source_sg_id != "" ? var.source_sg_id : null) + cidr_ipv4 = local.my_cidr + referenced_security_group_id = local.my_ref_sec_group_id from_port = 161 to_port = 162 ip_protocol = "udp" @@ -86,10 +96,10 @@ resource "aws_vpc_security_group_ingress_rule" "snmp_udp" { resource "aws_vpc_security_group_ingress_rule" "smb_cifs" { description = "Microsoft SMB/CIFS over TCP with NetBIOS framing" - count = var.create_sg ? 1 : 0 + count = local.mycount security_group_id = aws_security_group.fsx_sg[count.index].id - cidr_ipv4 = (var.cidr_for_sg != "" ? var.cidr_for_sg : null) - referenced_security_group_id = (var.source_sg_id != "" ? var.source_sg_id : null) + cidr_ipv4 = local.my_cidr + referenced_security_group_id = local.my_ref_sec_group_id from_port = 445 to_port = 445 ip_protocol = "tcp" @@ -97,10 +107,10 @@ resource "aws_vpc_security_group_ingress_rule" "smb_cifs" { resource "aws_vpc_security_group_ingress_rule" "nfs_mount_tcp" { description = "NFS mount" - count = var.create_sg ? 1 : 0 + count = local.mycount security_group_id = aws_security_group.fsx_sg[count.index].id - cidr_ipv4 = (var.cidr_for_sg != "" ? var.cidr_for_sg : null) - referenced_security_group_id = (var.source_sg_id != "" ? var.source_sg_id : null) + cidr_ipv4 = local.my_cidr + referenced_security_group_id = local.my_ref_sec_group_id from_port = 635 to_port = 635 ip_protocol = "tcp" @@ -108,10 +118,10 @@ resource "aws_vpc_security_group_ingress_rule" "nfs_mount_tcp" { resource "aws_vpc_security_group_ingress_rule" "kerberos" { description = "Kerberos authentication" - count = var.create_sg ? 1 : 0 + count = local.mycount security_group_id = aws_security_group.fsx_sg[count.index].id - cidr_ipv4 = (var.cidr_for_sg != "" ? var.cidr_for_sg : null) - referenced_security_group_id = (var.source_sg_id != "" ? var.source_sg_id : null) + cidr_ipv4 = local.my_cidr + referenced_security_group_id = local.my_ref_sec_group_id from_port = 749 to_port = 749 ip_protocol = "tcp" @@ -119,10 +129,10 @@ resource "aws_vpc_security_group_ingress_rule" "kerberos" { resource "aws_vpc_security_group_ingress_rule" "nfs_server_daemon" { description = "NFS server daemon" - count = var.create_sg ? 1 : 0 + count = local.mycount security_group_id = aws_security_group.fsx_sg[count.index].id - cidr_ipv4 = (var.cidr_for_sg != "" ? var.cidr_for_sg : null) - referenced_security_group_id = (var.source_sg_id != "" ? var.source_sg_id : null) + cidr_ipv4 = local.my_cidr + referenced_security_group_id = local.my_ref_sec_group_id from_port = 2049 to_port = 2049 ip_protocol = "tcp" @@ -130,10 +140,10 @@ resource "aws_vpc_security_group_ingress_rule" "nfs_server_daemon" { resource "aws_vpc_security_group_ingress_rule" "nfs_server_daemon_udp" { description = "NFS server daemon" - count = var.create_sg ? 1 : 0 + count = local.mycount security_group_id = aws_security_group.fsx_sg[count.index].id - cidr_ipv4 = (var.cidr_for_sg != "" ? var.cidr_for_sg : null) - referenced_security_group_id = (var.source_sg_id != "" ? var.source_sg_id : null) + cidr_ipv4 = local.my_cidr + referenced_security_group_id = local.my_ref_sec_group_id from_port = 2049 to_port = 2049 ip_protocol = "udp" @@ -141,10 +151,10 @@ resource "aws_vpc_security_group_ingress_rule" "nfs_server_daemon_udp" { resource "aws_vpc_security_group_ingress_rule" "nfs_lock_daemon" { description = "NFS lock daemon" - count = var.create_sg ? 1 : 0 + count = local.mycount security_group_id = aws_security_group.fsx_sg[count.index].id - cidr_ipv4 = (var.cidr_for_sg != "" ? var.cidr_for_sg : null) - referenced_security_group_id = (var.source_sg_id != "" ? var.source_sg_id : null) + cidr_ipv4 = local.my_cidr + referenced_security_group_id = local.my_ref_sec_group_id from_port = 4045 to_port = 4045 ip_protocol = "tcp" @@ -152,10 +162,10 @@ resource "aws_vpc_security_group_ingress_rule" "nfs_lock_daemon" { resource "aws_vpc_security_group_ingress_rule" "nfs_lock_daemon_udp" { description = "NFS lock daemon" - count = var.create_sg ? 1 : 0 + count = local.mycount security_group_id = aws_security_group.fsx_sg[count.index].id - cidr_ipv4 = (var.cidr_for_sg != "" ? var.cidr_for_sg : null) - referenced_security_group_id = (var.source_sg_id != "" ? var.source_sg_id : null) + cidr_ipv4 = local.my_cidr + referenced_security_group_id = local.my_ref_sec_group_id from_port = 4045 to_port = 4045 ip_protocol = "udp" @@ -163,10 +173,10 @@ resource "aws_vpc_security_group_ingress_rule" "nfs_lock_daemon_udp" { resource "aws_vpc_security_group_ingress_rule" "nfs_status_monitor" { description = "Status monitor for NFS" - count = var.create_sg ? 1 : 0 + count = local.mycount security_group_id = aws_security_group.fsx_sg[count.index].id - cidr_ipv4 = (var.cidr_for_sg != "" ? var.cidr_for_sg : null) - referenced_security_group_id = (var.source_sg_id != "" ? var.source_sg_id : null) + cidr_ipv4 = local.my_cidr + referenced_security_group_id = local.my_ref_sec_group_id from_port = 4046 to_port = 4046 ip_protocol = "tcp" @@ -174,10 +184,10 @@ resource "aws_vpc_security_group_ingress_rule" "nfs_status_monitor" { resource "aws_vpc_security_group_ingress_rule" "nfs_status_monitor_udp" { description = "Status monitor for NFS" - count = var.create_sg ? 1 : 0 + count = local.mycount security_group_id = aws_security_group.fsx_sg[count.index].id - cidr_ipv4 = (var.cidr_for_sg != "" ? var.cidr_for_sg : null) - referenced_security_group_id = (var.source_sg_id != "" ? var.source_sg_id : null) + cidr_ipv4 = local.my_cidr + referenced_security_group_id = local.my_ref_sec_group_id from_port = 4046 to_port = 4046 ip_protocol = "udp" @@ -185,10 +195,10 @@ resource "aws_vpc_security_group_ingress_rule" "nfs_status_monitor_udp" { resource "aws_vpc_security_group_ingress_rule" "nfs_rquotad" { description = "Remote quota server for NFS" - count = var.create_sg ? 1 : 0 + count = local.mycount security_group_id = aws_security_group.fsx_sg[count.index].id - cidr_ipv4 = (var.cidr_for_sg != "" ? var.cidr_for_sg : null) - referenced_security_group_id = (var.source_sg_id != "" ? var.source_sg_id : null) + cidr_ipv4 = local.my_cidr + referenced_security_group_id = local.my_ref_sec_group_id from_port = 4049 to_port = 4049 ip_protocol = "udp" @@ -196,10 +206,10 @@ resource "aws_vpc_security_group_ingress_rule" "nfs_rquotad" { resource "aws_vpc_security_group_ingress_rule" "iscsi_tcp" { description = "iSCSI" - count = var.create_sg ? 1 : 0 + count = local.mycount security_group_id = aws_security_group.fsx_sg[count.index].id - cidr_ipv4 = (var.cidr_for_sg != "" ? var.cidr_for_sg : null) - referenced_security_group_id = (var.source_sg_id != "" ? var.source_sg_id : null) + cidr_ipv4 = local.my_cidr + referenced_security_group_id = local.my_ref_sec_group_id from_port = 3260 to_port = 3260 ip_protocol = "tcp" @@ -207,10 +217,10 @@ resource "aws_vpc_security_group_ingress_rule" "iscsi_tcp" { resource "aws_vpc_security_group_ingress_rule" "Snapmirror_Intercluster_communication" { description = "Snapmirror Intercluster communication" - count = var.create_sg ? 1 : 0 + count = local.mycount security_group_id = aws_security_group.fsx_sg[count.index].id - cidr_ipv4 = (var.cidr_for_sg != "" ? var.cidr_for_sg : null) - referenced_security_group_id = (var.source_sg_id != "" ? var.source_sg_id : null) + cidr_ipv4 = local.my_cidr + referenced_security_group_id = local.my_ref_sec_group_id from_port = 11104 to_port = 11104 ip_protocol = "tcp" @@ -218,10 +228,10 @@ resource "aws_vpc_security_group_ingress_rule" "Snapmirror_Intercluster_communic resource "aws_vpc_security_group_ingress_rule" "Snapmirror_data_transfer" { description = "Snapmirror data transfer" - count = var.create_sg ? 1 : 0 + count = local.mycount security_group_id = aws_security_group.fsx_sg[count.index].id - cidr_ipv4 = (var.cidr_for_sg != "" ? var.cidr_for_sg : null) - referenced_security_group_id = (var.source_sg_id != "" ? var.source_sg_id : null) + cidr_ipv4 = local.my_cidr + referenced_security_group_id = local.my_ref_sec_group_id from_port = 11105 to_port = 11105 ip_protocol = "tcp" @@ -229,10 +239,10 @@ resource "aws_vpc_security_group_ingress_rule" "Snapmirror_data_transfer" { resource "aws_vpc_security_group_ingress_rule" "nfs_mount_udp" { description = "NFS mount" - count = var.create_sg ? 1 : 0 + count = local.mycount security_group_id = aws_security_group.fsx_sg[count.index].id - cidr_ipv4 = (var.cidr_for_sg != "" ? var.cidr_for_sg : null) - referenced_security_group_id = (var.source_sg_id != "" ? var.source_sg_id : null) + cidr_ipv4 = local.my_cidr + referenced_security_group_id = local.my_ref_sec_group_id from_port = 635 to_port = 635 ip_protocol = "udp" @@ -240,10 +250,10 @@ resource "aws_vpc_security_group_ingress_rule" "nfs_mount_udp" { resource "aws_vpc_security_group_ingress_rule" "ssh" { description = "ssh" - count = var.create_sg ? 1 : 0 + count = local.mycount security_group_id = aws_security_group.fsx_sg[count.index].id - cidr_ipv4 = (var.cidr_for_sg != "" ? var.cidr_for_sg : null) - referenced_security_group_id = (var.source_sg_id != "" ? var.source_sg_id : null) + cidr_ipv4 = local.my_cidr + referenced_security_group_id = local.my_ref_sec_group_id from_port = 22 to_port = 22 ip_protocol = "tcp" @@ -251,17 +261,17 @@ resource "aws_vpc_security_group_ingress_rule" "ssh" { resource "aws_vpc_security_group_ingress_rule" "s3_and_api" { description = "Provice acccess to S3 and the ONTAP REST API" - count = var.create_sg ? 1 : 0 + count = local.mycount security_group_id = aws_security_group.fsx_sg[count.index].id - cidr_ipv4 = (var.cidr_for_sg != "" ? var.cidr_for_sg : null) - referenced_security_group_id = (var.source_sg_id != "" ? var.source_sg_id : null) + cidr_ipv4 = local.my_cidr + referenced_security_group_id = local.my_ref_sec_group_id from_port = 443 to_port = 443 ip_protocol = "tcp" } resource "aws_vpc_security_group_egress_rule" "allow_all_traffic" { - count = var.create_sg ? 1 : 0 + count = local.mycount description = "Allow all out bound traffic" security_group_id = aws_security_group.fsx_sg[count.index].id cidr_ipv4 = "0.0.0.0/0" diff --git a/Terraform/fsxn-replicate/variables.tf b/Terraform/fsxn-replicate/variables.tf index f0379d2..534aea8 100644 --- a/Terraform/fsxn-replicate/variables.tf +++ b/Terraform/fsxn-replicate/variables.tf @@ -11,8 +11,14 @@ variable "prime_svm" { default = "vs1cli" } -variable "secrets_aws_region" { - description = "Region where the AWS secret for username/password reside" +variable "prime_aws_region" { + description = "AWS regionfor the Primary ONTAP FSxN" + type = string + default = "us-west-2" +} + +variable "dr_aws_region" { + description = "AWS regionfor the Secondary(DR) ONTAP FSxN" type = string default = "us-east-2" } From 27fc5f62d55370aade397360dc76ea9be7ad71c7 Mon Sep 17 00:00:00 2001 From: nichollri Date: Thu, 10 Oct 2024 13:52:11 -0500 Subject: [PATCH 05/28] used ONTAP provider to add volume to DR system after DR FSxN was created by Terraform --- Terraform/fsxn-replicate/main.tf | 15 +++++++++---- Terraform/fsxn-replicate/security_groups.tf | 8 +++---- Terraform/fsxn-replicate/variables.tf | 25 ++++++++------------- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/Terraform/fsxn-replicate/main.tf b/Terraform/fsxn-replicate/main.tf index 628270a..3c67dc9 100644 --- a/Terraform/fsxn-replicate/main.tf +++ b/Terraform/fsxn-replicate/main.tf @@ -41,6 +41,13 @@ provider "netapp-ontap" { username = jsondecode(data.aws_secretsmanager_secret_version.ontap_prime_username_pass.secret_string)["username"] password = jsondecode(data.aws_secretsmanager_secret_version.ontap_prime_username_pass.secret_string)["password"] validate_certs = var.validate_certs + }, + { + name = "dr_clus" + hostname = join("", aws_fsx_ontap_file_system.terraform-fsxn.endpoints[0].management[0].ip_addresses) + username = jsondecode(data.aws_secretsmanager_secret_version.ontap_prime_username_pass.secret_string)["username"] + password = jsondecode(data.aws_secretsmanager_secret_version.ontap_prime_username_pass.secret_string)["password"] + validate_certs = var.validate_certs } ] @@ -51,7 +58,7 @@ resource "aws_fsx_ontap_file_system" "terraform-fsxn" { preferred_subnet_id = var.dr_fsx_subnets["primarysub"] storage_capacity = var.dr_fsx_capacity_size_gb - security_group_ids = var.create_sg ? [element(aws_security_group.fsx_sg[*].id, 0)] : var.security_group_ids + security_group_ids = var.dr_create_sg ? [element(aws_security_group.fsx_sg[*].id, 0)] : var.dr_security_group_ids deployment_type = var.dr_fsx_deploy_type throughput_capacity_per_ha_pair = var.dr_fsx_tput_in_MBps ha_pairs = var.dr_ha_pairs @@ -88,10 +95,10 @@ data "netapp-ontap_storage_volume_data_source" "my_vol" { name = each.value } - resource "netapp-ontap_storage_volume_resource" "example" { - cx_profile_name = "primary_clus" + resource "netapp-ontap_storage_volume_resource" "example2" { + cx_profile_name = "dr_clus" name = "rvwn_vol1_tf" - svm_name = var.prime_svm + svm_name = aws_fsx_ontap_storage_virtual_machine.mysvm.name aggregates = [ { name = "aggr1" diff --git a/Terraform/fsxn-replicate/security_groups.tf b/Terraform/fsxn-replicate/security_groups.tf index 0c882f6..3de9588 100644 --- a/Terraform/fsxn-replicate/security_groups.tf +++ b/Terraform/fsxn-replicate/security_groups.tf @@ -12,15 +12,15 @@ */ locals { - mycount = var.create_sg ? 1 : 0 - my_ref_sec_group_id = (var.source_sg_id != "" ? var.source_sg_id : null) - my_cidr = (var.cidr_for_sg != "" ? var.cidr_for_sg : null) + mycount = var.dr_create_sg ? 1 : 0 + my_ref_sec_group_id = (var.dr_source_sg_id != "" ? var.dr_source_sg_id : null) + my_cidr = (var.dr_cidr_for_sg != "" ? var.dr_cidr_for_sg : null) } resource "aws_security_group" "fsx_sg" { description = "Allow FSx ONTAP required ports" count = local.mycount - name_prefix = var.security_group_name_prefix + name_prefix = var.dr_security_group_name_prefix vpc_id = var.dr_vpc_id } diff --git a/Terraform/fsxn-replicate/variables.tf b/Terraform/fsxn-replicate/variables.tf index 534aea8..3c6029f 100644 --- a/Terraform/fsxn-replicate/variables.tf +++ b/Terraform/fsxn-replicate/variables.tf @@ -20,7 +20,7 @@ variable "prime_aws_region" { variable "dr_aws_region" { description = "AWS regionfor the Secondary(DR) ONTAP FSxN" type = string - default = "us-east-2" + default = "us-west-2" } variable "username_pass_secrets_id" { @@ -55,7 +55,7 @@ variable "dr_fsx_subnets" { description = "The primary subnet ID, and secondary subnet ID if you are deploying in a Multi AZ environment, file system will be accessible from. For MULTI_AZ deployment types both subnets are required. For SINGLE_AZ deployment type, only the primary subnet is used." type = map(any) default = { - "primarysub" = "subnet-0a64530a9c7afc84c" + "primarysub" = "subnet-8fba81f8" "secondarysub" = "subnet-33333333" } } @@ -168,40 +168,40 @@ variable "dr_root_vol_sec_style" { * the ID of the security group that you want to use. * */ -variable "create_sg" { +variable "dr_create_sg" { description = "Determines whether the Security Group should be created as part of this deployment or not." type = bool default = true } -variable "security_group_ids" { +variable "dr_security_group_ids" { description = "If you are not creating the security group, provide a list of IDs of security groups to be used." type = list(string) default = [] } -variable "security_group_name_prefix" { +variable "dr_security_group_name_prefix" { description = "The prefix to the security group name that will be created." type = string default = "fsxn-sg" } -variable "cidr_for_sg" { +variable "dr_cidr_for_sg" { description = "The cidr block to be used for the created security ingress rules. Set to an empty string if you want to use the source_sg_id as the source." type = string default = "10.0.0.0/8" } -variable "source_sg_id" { +variable "dr_source_sg_id" { description = "The ID of the security group to allow access to the FSxN file system. Set to an empty string if you want to use the cidr_for_sg as the source." type = string default = "" } variable "dr_vpc_id" { - description = "The VPC ID where the security group will be created." + description = "The VPC ID where the DR FSxN and security group will be created." type = string - default = "vpc-0684c5d22c4b48dd4" + default = "vpc-445d4f21" } variable "dr_username_pass_secrets_id" { @@ -210,13 +210,6 @@ variable "dr_username_pass_secrets_id" { default = "rvwn_replicate_ontap_creds" } -variable "dr_hostname" { - description = "Hostname or IP address of disaster recovery cluster." - type = string -# Prod DR FSxN - default = "198.19.254.83" -} - variable "validate_certs" { description = "Do we validate the cluster certs (true or false)" type = string From 92ad129de2a004cd5f1c2736e3a23865ceab2010 Mon Sep 17 00:00:00 2001 From: nichollri Date: Thu, 17 Oct 2024 14:10:02 -0500 Subject: [PATCH 06/28] created volumes on FSxN destination with size info from source cluster --- Terraform/fsxn-replicate/main.tf | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Terraform/fsxn-replicate/main.tf b/Terraform/fsxn-replicate/main.tf index 3c67dc9..f633c8d 100644 --- a/Terraform/fsxn-replicate/main.tf +++ b/Terraform/fsxn-replicate/main.tf @@ -95,9 +95,11 @@ data "netapp-ontap_storage_volume_data_source" "my_vol" { name = each.value } - resource "netapp-ontap_storage_volume_resource" "example2" { +resource "netapp-ontap_storage_volume_resource" "volloop" { + for_each = data.netapp-ontap_storage_volume_data_source.my_vol cx_profile_name = "dr_clus" - name = "rvwn_vol1_tf" + name = "${each.value.name}_dp" + type = "DP" svm_name = aws_fsx_ontap_storage_virtual_machine.mysvm.name aggregates = [ { @@ -105,21 +107,20 @@ data "netapp-ontap_storage_volume_data_source" "my_vol" { }, ] space_guarantee = "none" - snapshot_policy = "default" space = { - size = 100 - size_unit = "gb" + size = each.value.space.size + size_unit = each.value.space.size_unit logical_space = { enforcement = true reporting = true } } tiering = { - policy_name = "auto" + policy_name = "all" } nas = { export_policy_name = "default" security_style = "unix" - junction_path = "/rvwn_vol1_tf" + # junction_path = join("", ["/",each.value.name]) } } From d25b88ce4262a76a792bc5cea8fa81e63f267c9d Mon Sep 17 00:00:00 2001 From: nichollri Date: Fri, 18 Oct 2024 14:48:34 -0500 Subject: [PATCH 07/28] added cluster peering, but getting an error on remote.ip_addresses not being an array --- Terraform/fsxn-replicate/main.tf | 45 +++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/Terraform/fsxn-replicate/main.tf b/Terraform/fsxn-replicate/main.tf index f633c8d..d09d9da 100644 --- a/Terraform/fsxn-replicate/main.tf +++ b/Terraform/fsxn-replicate/main.tf @@ -99,7 +99,7 @@ resource "netapp-ontap_storage_volume_resource" "volloop" { for_each = data.netapp-ontap_storage_volume_data_source.my_vol cx_profile_name = "dr_clus" name = "${each.value.name}_dp" - type = "DP" + type = "dp" svm_name = aws_fsx_ontap_storage_virtual_machine.mysvm.name aggregates = [ { @@ -124,3 +124,46 @@ resource "netapp-ontap_storage_volume_resource" "volloop" { # junction_path = join("", ["/",each.value.name]) } } + +# Now that we have the DP volumes created on the newly deployed destination cluster, +# let's get the intercluster LIFs so we can peer the clusters. + +# For existing FSx ONTAP cluster +data "netapp-ontap_networking_ip_interfaces_data_source" "primary_intercluster_lifs" { + cx_profile_name = "primary_clus" + filter = { + svm_name = var.prime_svm + name = "inter*" # Filter to only get intercluster LIFs + } +} + +# For newly created FSx ONTAP cluster +data "netapp-ontap_networking_ip_interfaces_data_source" "dr_intercluster_lifs" { + cx_profile_name = "dr_clus" + filter = { + svm_name = aws_fsx_ontap_storage_virtual_machine.mysvm.name + name = "inter*" # Filter to only get intercluster LIFs + } +} + + +# Now udse the LIF names and IP addresses to peer the clusters + +resource "netapp-ontap_cluster_peers_resource" "cluster_peer" { + cx_profile_name = "primary_clus" # Source cluster profile + peer_cx_profile_name = "dr_clus" # Destination (peer) cluster profile + + remote = { + # Destination cluster (DR) intercluster LIF IPs + ip_addresses = [for lif in data.netapp-ontap_networking_ip_interfaces_data_source.dr_intercluster_lifs.ip_interfaces : lif.ip_address] + } + + source_details = { + # Source cluster (primary) intercluster LIF IPs + ip_addresses = [for lif in data.netapp-ontap_networking_ip_interfaces_data_source.primary_intercluster_lifs.ip_interfaces : lif.ip_address] + } + + # Optional: Add authentication, passphrase or any other required settings + # passphrase = var.cluster_peer_passphrase # Optional, if you use passphrase for peering + peer_applications = ["snapmirror"] +} From 775e73d97067f302c98be109df3465ef29b4085e Mon Sep 17 00:00:00 2001 From: nichollri Date: Tue, 22 Oct 2024 10:18:32 -0500 Subject: [PATCH 08/28] Still working on getting intercluster LIFs to work, I can get svm data LIFs --- Terraform/fsxn-replicate/main.tf | 33 +++++++++++++++--------------- Terraform/fsxn-replicate/output.tf | 18 ++++++++++++++++ 2 files changed, 35 insertions(+), 16 deletions(-) diff --git a/Terraform/fsxn-replicate/main.tf b/Terraform/fsxn-replicate/main.tf index d09d9da..866f2ed 100644 --- a/Terraform/fsxn-replicate/main.tf +++ b/Terraform/fsxn-replicate/main.tf @@ -120,7 +120,7 @@ resource "netapp-ontap_storage_volume_resource" "volloop" { } nas = { export_policy_name = "default" - security_style = "unix" +# security_style = "unix" # junction_path = join("", ["/",each.value.name]) } } @@ -133,7 +133,8 @@ data "netapp-ontap_networking_ip_interfaces_data_source" "primary_intercluster_l cx_profile_name = "primary_clus" filter = { svm_name = var.prime_svm - name = "inter*" # Filter to only get intercluster LIFs +# svm_name = "FsxId020de2687bd98ccf7" + name = "iscsi_*" # Filter to only get intercluster LIFs } } @@ -149,21 +150,21 @@ data "netapp-ontap_networking_ip_interfaces_data_source" "dr_intercluster_lifs" # Now udse the LIF names and IP addresses to peer the clusters -resource "netapp-ontap_cluster_peers_resource" "cluster_peer" { - cx_profile_name = "primary_clus" # Source cluster profile - peer_cx_profile_name = "dr_clus" # Destination (peer) cluster profile +# resource "netapp-ontap_cluster_peers_resource" "cluster_peer" { +# cx_profile_name = "primary_clus" # Source cluster profile +# peer_cx_profile_name = "dr_clus" # Destination (peer) cluster profile +# +# remote = { +# # Destination cluster (DR) intercluster LIF IPs +# ip_addresses = [for lif in data.netapp-ontap_networking_ip_interfaces_data_source.dr_intercluster_lifs.ip_interfaces : lif.ip_address] +# } - remote = { - # Destination cluster (DR) intercluster LIF IPs - ip_addresses = [for lif in data.netapp-ontap_networking_ip_interfaces_data_source.dr_intercluster_lifs.ip_interfaces : lif.ip_address] - } - - source_details = { - # Source cluster (primary) intercluster LIF IPs - ip_addresses = [for lif in data.netapp-ontap_networking_ip_interfaces_data_source.primary_intercluster_lifs.ip_interfaces : lif.ip_address] - } +# source_details = { + # Source cluster (primary) intercluster LIF IPs +# ip_addresses = [for lif in data.netapp-ontap_networking_ip_interfaces_data_source.primary_intercluster_lifs.ip_interfaces : lif.ip_address] +# } # Optional: Add authentication, passphrase or any other required settings # passphrase = var.cluster_peer_passphrase # Optional, if you use passphrase for peering - peer_applications = ["snapmirror"] -} +# peer_applications = ["snapmirror"] +#} diff --git a/Terraform/fsxn-replicate/output.tf b/Terraform/fsxn-replicate/output.tf index 1c97bcc..bd500c4 100644 --- a/Terraform/fsxn-replicate/output.tf +++ b/Terraform/fsxn-replicate/output.tf @@ -8,3 +8,21 @@ output "volume_details" { } description = "Details of the volumes including name, type, size, and size unit" } + +#output "lifs" { +# value = { +# for key, lif in data.netapp-ontap_networking_ip_interfaces_data_source.primary_intercluster_lifs : key => { +# name = lif.ip_interfaces.name +# ip_address = lif.ip_interfaces.ip.ip_address +# } +# } +# description = "Details of source intercluster LIFs" +#} + +output "primary_intercluster_lifs_details" { + value = { + for lif in data.netapp-ontap_networking_ip_interfaces_data_source.primary_intercluster_lifs.ip_interfaces : lif.name => lif.ip.address + } + description = "Intercluster LIF names and IP addresses for the primary existing cluster" +} + From 304f7a6e0c049a478318c434bcb6897184535d3a Mon Sep 17 00:00:00 2001 From: nichollri Date: Tue, 22 Oct 2024 15:24:33 -0500 Subject: [PATCH 09/28] successful cluster peer, read IC LIFs from AWS FSxN provider --- Terraform/fsxn-replicate/main.tf | 32 +++++++++++++++------------ Terraform/fsxn-replicate/output.tf | 11 +++++++++ Terraform/fsxn-replicate/variables.tf | 7 ++++++ 3 files changed, 36 insertions(+), 14 deletions(-) diff --git a/Terraform/fsxn-replicate/main.tf b/Terraform/fsxn-replicate/main.tf index 866f2ed..6db79da 100644 --- a/Terraform/fsxn-replicate/main.tf +++ b/Terraform/fsxn-replicate/main.tf @@ -147,24 +147,28 @@ data "netapp-ontap_networking_ip_interfaces_data_source" "dr_intercluster_lifs" } } +# For now let's try to get the source and destination IC LIFs via AWS TF provider. +data "aws_fsx_ontap_file_system" "source_fsxn" { + id = var.prime_fsxid +} # Now udse the LIF names and IP addresses to peer the clusters -# resource "netapp-ontap_cluster_peers_resource" "cluster_peer" { -# cx_profile_name = "primary_clus" # Source cluster profile -# peer_cx_profile_name = "dr_clus" # Destination (peer) cluster profile -# -# remote = { -# # Destination cluster (DR) intercluster LIF IPs -# ip_addresses = [for lif in data.netapp-ontap_networking_ip_interfaces_data_source.dr_intercluster_lifs.ip_interfaces : lif.ip_address] -# } +resource "netapp-ontap_cluster_peers_resource" "cluster_peer" { + cx_profile_name = "primary_clus" # Source cluster profile + peer_cx_profile_name = "dr_clus" # Destination (peer) cluster profile -# source_details = { - # Source cluster (primary) intercluster LIF IPs -# ip_addresses = [for lif in data.netapp-ontap_networking_ip_interfaces_data_source.primary_intercluster_lifs.ip_interfaces : lif.ip_address] -# } + remote = { + # Destination cluster (DR) intercluster LIF IPs + ip_addresses = aws_fsx_ontap_file_system.terraform-fsxn.endpoints[0].intercluster[0].ip_addresses + } + + source_details = { + # Source cluster (primary) intercluster LIF IPs + ip_addresses = data.aws_fsx_ontap_file_system.source_fsxn.endpoints[0].intercluster[0].ip_addresses + } # Optional: Add authentication, passphrase or any other required settings # passphrase = var.cluster_peer_passphrase # Optional, if you use passphrase for peering -# peer_applications = ["snapmirror"] -#} + peer_applications = ["snapmirror"] +} diff --git a/Terraform/fsxn-replicate/output.tf b/Terraform/fsxn-replicate/output.tf index bd500c4..9957ecf 100644 --- a/Terraform/fsxn-replicate/output.tf +++ b/Terraform/fsxn-replicate/output.tf @@ -26,3 +26,14 @@ output "primary_intercluster_lifs_details" { description = "Intercluster LIF names and IP addresses for the primary existing cluster" } +output "data_from_aws_fsxn" { + value = { + intercluster = { +# dns_name = data.aws_fsx_ontap_file_system.source_fsxn.endpoints[0].intercluster[0].dns_name +# ip_addresses = data.aws_fsx_ontap_file_system.source_fsxn.endpoints[0].intercluster[0].ip_addresses + all_of_it = data.aws_fsx_ontap_file_system.source_fsxn + } + } + description = "All data from aws fsxn provider" +} + diff --git a/Terraform/fsxn-replicate/variables.tf b/Terraform/fsxn-replicate/variables.tf index 3c6029f..b4f3e70 100644 --- a/Terraform/fsxn-replicate/variables.tf +++ b/Terraform/fsxn-replicate/variables.tf @@ -5,6 +5,13 @@ variable "prime_hostname" { default = "198.19.253.210" } +variable "prime_fsxid" { + description = "FSx ID of the primary cluster." + type = string +# Development FSxN + default = "fs-020de2687bd98ccf7" +} + variable "prime_svm" { description = "Name of svm for replication in the primary cluster." type = string From d40844e1fe2255d89d3ef5d5f6f3b6c30818bafa Mon Sep 17 00:00:00 2001 From: nichollri Date: Fri, 25 Oct 2024 19:15:14 -0500 Subject: [PATCH 10/28] first working version that includes snapmirror creation. --- Terraform/fsxn-replicate/main.tf | 120 +++++++++++++++----------- Terraform/fsxn-replicate/output.tf | 45 +++------- Terraform/fsxn-replicate/variables.tf | 24 +++++- 3 files changed, 104 insertions(+), 85 deletions(-) diff --git a/Terraform/fsxn-replicate/main.tf b/Terraform/fsxn-replicate/main.tf index 6db79da..1b6fa42 100644 --- a/Terraform/fsxn-replicate/main.tf +++ b/Terraform/fsxn-replicate/main.tf @@ -36,14 +36,14 @@ provider "netapp-ontap" { # At least one is required. connection_profiles = [ { - name = "primary_clus" + name = var.prime_clus_name hostname = var.prime_hostname username = jsondecode(data.aws_secretsmanager_secret_version.ontap_prime_username_pass.secret_string)["username"] password = jsondecode(data.aws_secretsmanager_secret_version.ontap_prime_username_pass.secret_string)["password"] validate_certs = var.validate_certs }, { - name = "dr_clus" + name = var.dr_clus_name hostname = join("", aws_fsx_ontap_file_system.terraform-fsxn.endpoints[0].management[0].ip_addresses) username = jsondecode(data.aws_secretsmanager_secret_version.ontap_prime_username_pass.secret_string)["username"] password = jsondecode(data.aws_secretsmanager_secret_version.ontap_prime_username_pass.secret_string)["password"] @@ -88,65 +88,53 @@ resource "aws_fsx_ontap_storage_virtual_machine" "mysvm" { root_volume_security_style = var.dr_root_vol_sec_style } -data "netapp-ontap_storage_volume_data_source" "my_vol" { +data "netapp-ontap_storage_volume_data_source" "src_vols" { for_each = toset(var.list_of_volumes_to_replicate) - cx_profile_name = "primary_clus" + cx_profile_name = var.prime_clus_name svm_name = var.prime_svm name = each.value } -resource "netapp-ontap_storage_volume_resource" "volloop" { - for_each = data.netapp-ontap_storage_volume_data_source.my_vol - cx_profile_name = "dr_clus" - name = "${each.value.name}_dp" - type = "dp" - svm_name = aws_fsx_ontap_storage_virtual_machine.mysvm.name - aggregates = [ - { - name = "aggr1" - }, - ] - space_guarantee = "none" - space = { - size = each.value.space.size - size_unit = each.value.space.size_unit - logical_space = { - enforcement = true - reporting = true - } - } - tiering = { - policy_name = "all" - } - nas = { - export_policy_name = "default" -# security_style = "unix" - # junction_path = join("", ["/",each.value.name]) +variable "size_in_mb" { + type = map(string) + + # Conversion to MBs + default = { + "mb" = 1 + "MB" = 1 + "gb" = 1024 + "GB" = 1024 + "tb" = 1024*1024 + "TB" = 1024*1024 } } -# Now that we have the DP volumes created on the newly deployed destination cluster, -# let's get the intercluster LIFs so we can peer the clusters. -# For existing FSx ONTAP cluster -data "netapp-ontap_networking_ip_interfaces_data_source" "primary_intercluster_lifs" { - cx_profile_name = "primary_clus" - filter = { - svm_name = var.prime_svm -# svm_name = "FsxId020de2687bd98ccf7" - name = "iscsi_*" # Filter to only get intercluster LIFs +resource "aws_fsx_ontap_volume" "dp_volumes" { + for_each = data.netapp-ontap_storage_volume_data_source.src_vols + storage_virtual_machine_id = aws_fsx_ontap_storage_virtual_machine.mysvm.id + name = "${each.value.name}_dp" + ontap_volume_type = "DP" + size_in_megabytes = each.value.space.size * lookup(var.size_in_mb, each.value.space.size_unit, 0) + tiering_policy { + name = "ALL" } + skip_final_backup = true } -# For newly created FSx ONTAP cluster -data "netapp-ontap_networking_ip_interfaces_data_source" "dr_intercluster_lifs" { - cx_profile_name = "dr_clus" - filter = { - svm_name = aws_fsx_ontap_storage_virtual_machine.mysvm.name - name = "inter*" # Filter to only get intercluster LIFs - } +resource "aws_fsx_ontap_volume" "test_src" { + storage_virtual_machine_id = aws_fsx_ontap_storage_virtual_machine.mysvm.id + name = "volx_src" + ontap_volume_type = "RW" + size_in_megabytes = 1024 + junction_path = "/volx_src" + storage_efficiency_enabled = true } +# Now that we have the DP volumes created on the newly deployed destination cluster, +# let's get the intercluster LIFs so we can peer the clusters. + + # For now let's try to get the source and destination IC LIFs via AWS TF provider. data "aws_fsx_ontap_file_system" "source_fsxn" { id = var.prime_fsxid @@ -155,8 +143,8 @@ data "aws_fsx_ontap_file_system" "source_fsxn" { # Now udse the LIF names and IP addresses to peer the clusters resource "netapp-ontap_cluster_peers_resource" "cluster_peer" { - cx_profile_name = "primary_clus" # Source cluster profile - peer_cx_profile_name = "dr_clus" # Destination (peer) cluster profile + cx_profile_name = var.prime_clus_name # Source cluster profile + peer_cx_profile_name = var.dr_clus_name # Destination (peer) cluster profile remote = { # Destination cluster (DR) intercluster LIF IPs @@ -172,3 +160,37 @@ resource "netapp-ontap_cluster_peers_resource" "cluster_peer" { # passphrase = var.cluster_peer_passphrase # Optional, if you use passphrase for peering peer_applications = ["snapmirror"] } + +resource "netapp-ontap_svm_peers_resource" "peer_svms" { + cx_profile_name = var.dr_clus_name + svm = { + name = aws_fsx_ontap_storage_virtual_machine.mysvm.name + } + peer = { + svm = { + name = var.prime_svm + } + cluster = { + name = var.prime_cluster_vserver + } + peer_cx_profile_name = var.prime_clus_name + } + applications = ["snapmirror", "flexcache"] + depends_on = [ + netapp-ontap_cluster_peers_resource.cluster_peer + ] +} + +resource "netapp-ontap_snapmirror_resource" "snapmirror" { + for_each = data.netapp-ontap_storage_volume_data_source.src_vols + cx_profile_name = var.dr_clus_name + source_endpoint = { + path = join(":",[var.prime_svm,each.value.name]) + } + destination_endpoint = { + path = join(":",[aws_fsx_ontap_storage_virtual_machine.mysvm.name, "${each.value.name}_dp"]) + } + depends_on = [ + netapp-ontap_svm_peers_resource.peer_svms + ] +} diff --git a/Terraform/fsxn-replicate/output.tf b/Terraform/fsxn-replicate/output.tf index 9957ecf..7827cc3 100644 --- a/Terraform/fsxn-replicate/output.tf +++ b/Terraform/fsxn-replicate/output.tf @@ -1,39 +1,18 @@ -output "volume_details" { - value = { - for key, volume in data.netapp-ontap_storage_volume_data_source.my_vol : key => { - name = volume.name - type = volume.type - size = "${volume.space.size}${volume.space.size_unit}" - } - } - description = "Details of the volumes including name, type, size, and size unit" -} - -#output "lifs" { +#output "volume_details" { # value = { -# for key, lif in data.netapp-ontap_networking_ip_interfaces_data_source.primary_intercluster_lifs : key => { -# name = lif.ip_interfaces.name -# ip_address = lif.ip_interfaces.ip.ip_address +# for key, volume in data.netapp-ontap_storage_volume_data_source.src_vols : key => { +# name = volume.name +# type = volume.type +# size = "${volume.space.size}${volume.space.size_unit}" # } # } -# description = "Details of source intercluster LIFs" +# description = "Details of the volumes including name, type, size, and size unit" #} -output "primary_intercluster_lifs_details" { - value = { - for lif in data.netapp-ontap_networking_ip_interfaces_data_source.primary_intercluster_lifs.ip_interfaces : lif.name => lif.ip.address - } - description = "Intercluster LIF names and IP addresses for the primary existing cluster" -} - -output "data_from_aws_fsxn" { - value = { - intercluster = { -# dns_name = data.aws_fsx_ontap_file_system.source_fsxn.endpoints[0].intercluster[0].dns_name -# ip_addresses = data.aws_fsx_ontap_file_system.source_fsxn.endpoints[0].intercluster[0].ip_addresses - all_of_it = data.aws_fsx_ontap_file_system.source_fsxn - } - } - description = "All data from aws fsxn provider" -} +#output "data_from_aws_fsxn" { +# value = { +# all_of_it = data.aws_fsx_ontap_file_system.source_fsxn +# } +# description = "All data from aws fsxn provider" +#} diff --git a/Terraform/fsxn-replicate/variables.tf b/Terraform/fsxn-replicate/variables.tf index b4f3e70..f485ec4 100644 --- a/Terraform/fsxn-replicate/variables.tf +++ b/Terraform/fsxn-replicate/variables.tf @@ -12,12 +12,24 @@ variable "prime_fsxid" { default = "fs-020de2687bd98ccf7" } +variable "prime_clus_name" { + description = "This is the name of the cluster given for ONTAP TF connection profile. This is a user creatred value, that can be any string. It is referenced in many ONTAP TF resources." + type = string + default = "primary_clus" +} + variable "prime_svm" { description = "Name of svm for replication in the primary cluster." type = string default = "vs1cli" } +variable "prime_cluster_vserver" { + description = "Name of cluster vserver for inter cluster lifs in the primary cluster. This can be found by running network interface show on the source cluster" + type = string + default = "FsxId020de2687bd98ccf7" +} + variable "prime_aws_region" { description = "AWS regionfor the Primary ONTAP FSxN" type = string @@ -39,7 +51,7 @@ variable "username_pass_secrets_id" { variable "list_of_volumes_to_replicate" { description = "list of volumes to replicate to dr fsxn" type = list(string) - default = ["cifs_share", "rvwn_from_bxp", "unix"] + default = ["cifs_share", "rvwn_from_bxp", "rvwn_voltb", "rvwn_volmb"] } variable "dr_fsx_name" { @@ -48,6 +60,12 @@ variable "dr_fsx_name" { default = "terraform-dr-fsxn" } +variable "dr_clus_name" { + description = "This is the name of the cluster given for ONTAP TF connection profile. This is a user creatred value, that can be any string. It is referenced in many ONTAP TF resources." + type = string + default = "dr_clus" +} + variable "dr_fsx_deploy_type" { description = "The file system deployment type. Supported values are 'MULTI_AZ_1', 'SINGLE_AZ_1', 'MULTI_AZ_2', and 'SINGLE_AZ_2'. MULTI_AZ_1 and SINGLE_AZ_1 are Gen 1. MULTI_AZ_2 and SINGLE_AZ_2 are Gen 2." type = string @@ -70,7 +88,7 @@ variable "dr_fsx_subnets" { variable "dr_fsx_capacity_size_gb" { description = "The storage capacity in GiBs of the FSxN file system. Valid values between 1024 (1 TiB) and 1048576 (1 PiB). Gen 1 deployment types are limited to 192 TiB. Gen 2 Multi AZ is limited to 512 TiB. Gen 2 Single AZ is limited to 1 PiB." type = number - default = 1024 + default = 2048 validation { condition = var.dr_fsx_capacity_size_gb >= 1024 && var.dr_fsx_capacity_size_gb <= 1048576 error_message = "Invalid capacity size. Valid values are between 1024 (1TiB) and 1045876 (1 PiB)." @@ -214,7 +232,7 @@ variable "dr_vpc_id" { variable "dr_username_pass_secrets_id" { description = "Name of secret ID in AWS secrets" type = string - default = "rvwn_replicate_ontap_creds" + default = "rvwn_replicate_ontap_creds_dr" } variable "validate_certs" { From 48a3481873ccc4c6ca10b0cf8b1698c09bd6370d Mon Sep 17 00:00:00 2001 From: Richard Nicholl Date: Mon, 28 Oct 2024 15:46:45 -0400 Subject: [PATCH 11/28] Update README.md --- Terraform/fsxn-replicate/README.md | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/Terraform/fsxn-replicate/README.md b/Terraform/fsxn-replicate/README.md index 185a31d..e21ac64 100644 --- a/Terraform/fsxn-replicate/README.md +++ b/Terraform/fsxn-replicate/README.md @@ -1,2 +1,28 @@ -## Repository Overview -This repostory contians a method to take an existing FSxN system and replicate volumes to a new FSx ONTAP instancefor disaster recovery or backup purposes. It leverages both AWS FSx Terraform provider as well as the ONTAP Terraform provider. +# Deploy DR FSx ONTAP cluster and create SnapMirror relationships from source FSxN + +## Introduction +This repository contains a method to take an existing FSxN system and replicate volumes to a new FSx ONTAP instance for disaster recovery or backup purposes. It leverages both AWS FSx Terraform provider as well as the ONTAP Terraform provider. + +## Setup + +You will need to define some key characteristics of your destination FSxN cluster to be created, such as deployment type and througput, full list below. You also will need to define the source SVM and list of volumes to replicate, and replication parameters. + +These values can be found in the following .tfvars files: Primary_FSxN_variables.tfvar and DR_FSxN_variables.tfvar + + + +## Author Information + +This repository is maintained by the contributors listed on [GitHub](https://github.com/NetApp/FSx-ONTAP-samples-scripts/graphs/contributors). + +## License + +Licensed under the Apache License, Version 2.0 (the "License"). + +You may obtain a copy of the License at [apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0). + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, without WARRANTIES or conditions of any kind, either express or implied. + +See the License for the specific language governing permissions and limitations under the License. + +© 2024 NetApp, Inc. All Rights Reserved. From dc18f81d664d14d9c861447eaac6719755ee1ee0 Mon Sep 17 00:00:00 2001 From: nichollri Date: Tue, 29 Oct 2024 14:57:11 -0500 Subject: [PATCH 12/28] added snapmirror policy and broke out variables.tf into two files --- .../{variables.tf => DR_FSxN_variables.tf} | 70 +++---------------- .../fsxn-replicate/Primary_FSxN_variables.tf | 53 ++++++++++++++ Terraform/fsxn-replicate/README.md | 2 +- Terraform/fsxn-replicate/main.tf | 33 ++++++--- 4 files changed, 88 insertions(+), 70 deletions(-) rename Terraform/fsxn-replicate/{variables.tf => DR_FSxN_variables.tf} (78%) create mode 100644 Terraform/fsxn-replicate/Primary_FSxN_variables.tf diff --git a/Terraform/fsxn-replicate/variables.tf b/Terraform/fsxn-replicate/DR_FSxN_variables.tf similarity index 78% rename from Terraform/fsxn-replicate/variables.tf rename to Terraform/fsxn-replicate/DR_FSxN_variables.tf index f485ec4..ceb85c5 100644 --- a/Terraform/fsxn-replicate/variables.tf +++ b/Terraform/fsxn-replicate/DR_FSxN_variables.tf @@ -1,63 +1,15 @@ -variable "prime_hostname" { - description = "Hostname or IP address of primary cluster." - type = string -# Development FSxN - default = "198.19.253.210" -} - -variable "prime_fsxid" { - description = "FSx ID of the primary cluster." - type = string -# Development FSxN - default = "fs-020de2687bd98ccf7" -} - -variable "prime_clus_name" { - description = "This is the name of the cluster given for ONTAP TF connection profile. This is a user creatred value, that can be any string. It is referenced in many ONTAP TF resources." - type = string - default = "primary_clus" -} - -variable "prime_svm" { - description = "Name of svm for replication in the primary cluster." - type = string - default = "vs1cli" -} - -variable "prime_cluster_vserver" { - description = "Name of cluster vserver for inter cluster lifs in the primary cluster. This can be found by running network interface show on the source cluster" - type = string - default = "FsxId020de2687bd98ccf7" -} - -variable "prime_aws_region" { - description = "AWS regionfor the Primary ONTAP FSxN" - type = string - default = "us-west-2" -} +# Variables for the Disaster Recovery FSxN system to be created. variable "dr_aws_region" { description = "AWS regionfor the Secondary(DR) ONTAP FSxN" type = string - default = "us-west-2" -} - -variable "username_pass_secrets_id" { - description = "Name of secret ID in AWS secrets" - type = string - default = "rvwn_replicate_ontap_creds" -} - -variable "list_of_volumes_to_replicate" { - description = "list of volumes to replicate to dr fsxn" - type = list(string) - default = ["cifs_share", "rvwn_from_bxp", "rvwn_voltb", "rvwn_volmb"] + default = "" } variable "dr_fsx_name" { description = "The name to assign to the destination FSxN file system." type = string - default = "terraform-dr-fsxn" + default = "" } variable "dr_clus_name" { @@ -80,7 +32,7 @@ variable "dr_fsx_subnets" { description = "The primary subnet ID, and secondary subnet ID if you are deploying in a Multi AZ environment, file system will be accessible from. For MULTI_AZ deployment types both subnets are required. For SINGLE_AZ deployment type, only the primary subnet is used." type = map(any) default = { - "primarysub" = "subnet-8fba81f8" + "primarysub" = "subnet-11111111" "secondarysub" = "subnet-33333333" } } @@ -88,7 +40,7 @@ variable "dr_fsx_subnets" { variable "dr_fsx_capacity_size_gb" { description = "The storage capacity in GiBs of the FSxN file system. Valid values between 1024 (1 TiB) and 1048576 (1 PiB). Gen 1 deployment types are limited to 192 TiB. Gen 2 Multi AZ is limited to 512 TiB. Gen 2 Single AZ is limited to 1 PiB." type = number - default = 2048 + default = 1024 validation { condition = var.dr_fsx_capacity_size_gb >= 1024 && var.dr_fsx_capacity_size_gb <= 1048576 error_message = "Invalid capacity size. Valid values are between 1024 (1TiB) and 1045876 (1 PiB)." @@ -170,7 +122,7 @@ variable "dr_daily_backup_start_time" { variable "dr_svm_name" { description = "The name of the Storage Virtual Machine" type = string - default = "fsx-dr" + default = "" } variable "dr_root_vol_sec_style" { @@ -226,17 +178,17 @@ variable "dr_source_sg_id" { variable "dr_vpc_id" { description = "The VPC ID where the DR FSxN and security group will be created." type = string - default = "vpc-445d4f21" + default = "" } variable "dr_username_pass_secrets_id" { description = "Name of secret ID in AWS secrets" type = string - default = "rvwn_replicate_ontap_creds_dr" + default = "" } -variable "validate_certs" { - description = "Do we validate the cluster certs (true or false)" +variable "dr_snapmirror_policy_name" { + description = "Name of snamirror policy to create" type = string - default = "false" + default = "" } diff --git a/Terraform/fsxn-replicate/Primary_FSxN_variables.tf b/Terraform/fsxn-replicate/Primary_FSxN_variables.tf new file mode 100644 index 0000000..05c4bfd --- /dev/null +++ b/Terraform/fsxn-replicate/Primary_FSxN_variables.tf @@ -0,0 +1,53 @@ +variable "prime_hostname" { + description = "Hostname or IP address of primary cluster." + type = string + default = "" +} + +variable "prime_fsxid" { + description = "FSx ID of the primary cluster." + type = string + default = "" +} + +variable "prime_clus_name" { + description = "This is the name of the cluster given for ONTAP TF connection profile. This is a user creatred value, that can be any string. It is referenced in many ONTAP TF resources." + type = string + default = "primary_clus" +} + +variable "prime_svm" { + description = "Name of svm for replication in the primary cluster." + type = string + default = "" +} + +variable "prime_cluster_vserver" { + description = "Name of cluster vserver for inter cluster lifs in the primary cluster. This can be found by running network interface show on the source cluster. It will be formatted like this FsxIdxxxxxxxx" + type = string + default = "" +} + +variable "prime_aws_region" { + description = "AWS regionfor the Primary ONTAP FSxN" + type = string + default = "" +} + +variable "username_pass_secrets_id" { + description = "Name of secret ID in AWS secrets" + type = string + default = "" +} + +variable "list_of_volumes_to_replicate" { + description = "list of volumes to replicate to dr fsxn" + type = list(string) + default = [] +} + +variable "validate_certs" { + description = "Do we validate the cluster certs (true or false)" + type = string + default = "false" +} diff --git a/Terraform/fsxn-replicate/README.md b/Terraform/fsxn-replicate/README.md index e21ac64..1b36e7d 100644 --- a/Terraform/fsxn-replicate/README.md +++ b/Terraform/fsxn-replicate/README.md @@ -7,7 +7,7 @@ This repository contains a method to take an existing FSxN system and replicate You will need to define some key characteristics of your destination FSxN cluster to be created, such as deployment type and througput, full list below. You also will need to define the source SVM and list of volumes to replicate, and replication parameters. -These values can be found in the following .tfvars files: Primary_FSxN_variables.tfvar and DR_FSxN_variables.tfvar +These values can be found in the following variables files: Primary_FSxN_variables.tf and DR_FSxN_variables.tf diff --git a/Terraform/fsxn-replicate/main.tf b/Terraform/fsxn-replicate/main.tf index 1b6fa42..51a48f2 100644 --- a/Terraform/fsxn-replicate/main.tf +++ b/Terraform/fsxn-replicate/main.tf @@ -122,15 +122,6 @@ resource "aws_fsx_ontap_volume" "dp_volumes" { skip_final_backup = true } -resource "aws_fsx_ontap_volume" "test_src" { - storage_virtual_machine_id = aws_fsx_ontap_storage_virtual_machine.mysvm.id - name = "volx_src" - ontap_volume_type = "RW" - size_in_megabytes = 1024 - junction_path = "/volx_src" - storage_efficiency_enabled = true -} - # Now that we have the DP volumes created on the newly deployed destination cluster, # let's get the intercluster LIFs so we can peer the clusters. @@ -181,6 +172,24 @@ resource "netapp-ontap_svm_peers_resource" "peer_svms" { ] } +resource "netapp-ontap_snapmirror_policy_resource" "snapmirror_policy_async" { + # required to know which system to interface with + cx_profile_name = var.dr_clus_name + name = var.dr_snapmirror_policy_name + svm_name = aws_fsx_ontap_storage_virtual_machine.mysvm.name + type = "async" + retention = [{ + label = "weekly" + count = 2 + }, + { + label = "daily", + count = 7 + } + ] +} + + resource "netapp-ontap_snapmirror_resource" "snapmirror" { for_each = data.netapp-ontap_storage_volume_data_source.src_vols cx_profile_name = var.dr_clus_name @@ -190,7 +199,11 @@ resource "netapp-ontap_snapmirror_resource" "snapmirror" { destination_endpoint = { path = join(":",[aws_fsx_ontap_storage_virtual_machine.mysvm.name, "${each.value.name}_dp"]) } + policy = { + name = netapp-ontap_snapmirror_policy_resource.snapmirror_policy_async.name + } depends_on = [ - netapp-ontap_svm_peers_resource.peer_svms + netapp-ontap_svm_peers_resource.peer_svms, + aws_fsx_ontap_volume.dp_volumes ] } From d84a0d96950147a2631cd67a156c41016c5ce1b8 Mon Sep 17 00:00:00 2001 From: Richard Nicholl Date: Wed, 30 Oct 2024 11:12:11 -0400 Subject: [PATCH 13/28] Update README.md to include primary cluster variables. --- Terraform/fsxn-replicate/README.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/Terraform/fsxn-replicate/README.md b/Terraform/fsxn-replicate/README.md index 1b36e7d..bb2e0d7 100644 --- a/Terraform/fsxn-replicate/README.md +++ b/Terraform/fsxn-replicate/README.md @@ -9,6 +9,29 @@ You will need to define some key characteristics of your destination FSxN cluste These values can be found in the following variables files: Primary_FSxN_variables.tf and DR_FSxN_variables.tf +## Prerequisites +You have an existing FSx ONTAP system that you want to replicate to a new FSxN system. There is proper networking connectivy between the source FSxN system and the region/VPC/subnets where the destination FSxN system will be deployed. + +SnapMirror replication requires **ICMP** and ports **11104** and **11105**. + +## Primary Inputs + +| Name | Description | Type | Default | Required | +| --------------------- | ------------------------------------------------------------------------------------------------------------- | -------------- | ------------------------------------ | :------: | +| prime_hostname | Hostname or IP address of primary cluster. | `string` | | Yes | +| prime_fsxid | FSx ID of the primary cluster. | `string` | | Yes | +| prime_clus_name | This is the name of the cluster given for ONTAP TF connection profile. This is a user created value, that can be any string. It is referenced in many ONTAP TF resources | `string` | primary_clus | Yes | +| prime_svm | Name of the primary SVM for the volumes that will be replicated. | `string` | | Yes | +| prime_cluster_vserver | Name of the ONTAP cluster vserver for intercluster LIFs in the primary cluster. Can be found by running `network interface show` on the primary cluster. It will have the format FsxId################# | `string` | Yes | +| prime_aws_region | AWS region of the primary FSx ONTAP system | `string` | | Yes | +| username_pass_secrets_id | Name of the secrets ID in AWS secrets. The AWS Secret should has format of a key `username` which should be fsxadmin and a key `password` and the password of the FSxN | `string` | | Yes | +| validate_certs | Do we validate the cluster certs (true or false) | `string` | false | No | +| list_of_volumes_to_replicate | List of volume names to replicate to the destination FSx ONTAP system | `list(string)` | | Yes | + + + + + ## Author Information From b4993735c88219f01a3cf23008f790b11ef624d0 Mon Sep 17 00:00:00 2001 From: Richard Nicholl Date: Wed, 30 Oct 2024 18:15:44 -0400 Subject: [PATCH 14/28] Update README.md --- Terraform/fsxn-replicate/README.md | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/Terraform/fsxn-replicate/README.md b/Terraform/fsxn-replicate/README.md index bb2e0d7..78bc3f1 100644 --- a/Terraform/fsxn-replicate/README.md +++ b/Terraform/fsxn-replicate/README.md @@ -5,7 +5,7 @@ This repository contains a method to take an existing FSxN system and replicate ## Setup -You will need to define some key characteristics of your destination FSxN cluster to be created, such as deployment type and througput, full list below. You also will need to define the source SVM and list of volumes to replicate, and replication parameters. +You will need to define some key characteristics of the destination FSxN cluster that will be created, such as deployment type and througput, full list below. You also will need to define the source SVM and list of volumes to replicate, and replication parameters. These values can be found in the following variables files: Primary_FSxN_variables.tf and DR_FSxN_variables.tf @@ -14,7 +14,7 @@ You have an existing FSx ONTAP system that you want to replicate to a new FSxN s SnapMirror replication requires **ICMP** and ports **11104** and **11105**. -## Primary Inputs +## Inputs (Primary Cluster) | Name | Description | Type | Default | Required | | --------------------- | ------------------------------------------------------------------------------------------------------------- | -------------- | ------------------------------------ | :------: | @@ -25,11 +25,28 @@ SnapMirror replication requires **ICMP** and ports **11104** and **11105**. | prime_cluster_vserver | Name of the ONTAP cluster vserver for intercluster LIFs in the primary cluster. Can be found by running `network interface show` on the primary cluster. It will have the format FsxId################# | `string` | Yes | | prime_aws_region | AWS region of the primary FSx ONTAP system | `string` | | Yes | | username_pass_secrets_id | Name of the secrets ID in AWS secrets. The AWS Secret should has format of a key `username` which should be fsxadmin and a key `password` and the password of the FSxN | `string` | | Yes | -| validate_certs | Do we validate the cluster certs (true or false) | `string` | false | No | +| validate_certs | When connecting to ONTAP do we validate the cluster certs (true or false). | `string` | false | No | | list_of_volumes_to_replicate | List of volume names to replicate to the destination FSx ONTAP system | `list(string)` | | Yes | +## Inputs (DR Cluster) - - +| Name | Description | Type | Default | Required | +| --------------------- | ------------------------------------------------------------------------------------------------------------- | -------------- | ------------------------------------ | :------: | +| dr_aws_region | AWS regionfor the Secondary(DR) ONTAP system. | `string` | | Yes | +| dr_fsx_name | The name to assign to the destination FSxN file system that will be created. | `string` | | Yes | +| dr_clus_name | This is the name of the cluster given for ONTAP TF connection profile. This is a user created value, that can be any string. It is referenced in many ONTAP TF resources | `string` | Yes | +| dr_fsx_deploy_type | The file system deployment type. Supported values are 'MULTI_AZ_1', 'SINGLE_AZ_1', 'MULTI_AZ_2', and 'SINGLE_AZ_2'. MULTI_AZ_1 and SINGLE_AZ_1 are Gen 1. MULTI_AZ_2 and SINGLE_AZ_2 are Gen 2. | SINGLE_AZ_1 | Yes | +| dr_fsx_subnets | The primary subnet ID, and secondary subnet ID if you are deploying in a Multi AZ environment, file system will be accessible from. For MULTI_AZ deployment types both subnets are required. For SINGLE_AZ deployment type, only the primary subnet is used. `map(any)` | | Yes | +| dr_fsx_capacity_size_gb | The storage capacity in GiBs of the FSxN file system. Valid values between 1024 (1 TiB) and 1048576 (1 PiB). Gen 1 deployment types are limited to 192 TiB. Gen 2 Multi AZ is limited to 512 TiB. Gen 2 Single AZ is limited to 1 PiB. The sizing should take into account the size of the volumes you plan to replicate and the tiering policy of the volumes. | `number` | 1024 | Yes | +| dr_fsx_tput_in_MBps | The throughput capacity (in MBps) for the file system. Valid values are 128, 256, 512, 1024, 2048, and 4096 for Gen 1, and 384, 768, 1536, 3072 and 6144 for Gen 2. | `string` | 128 | Yes | +| dr_ha_pairs | The number of HA pairs in the file system. Valid values are from 1 through 12. Only single AZ Gen 2 deployment type supports more than 1 HA pair. | `number` | 1 | Yes | +| dr_endpoint_ip_address_range | The IP address range that the FSxN file system will be accessible from. This is only used for Multi AZ deployment types and must be left a null for Single AZ deployment types. | `string` | null | No | +| dr_route_table_ids | An array of routing table IDs that will be modified to allow access to the FSxN file system. This is only used for Multi AZ deployment types and must be left as null for Single AZ deployment types. | `list(string)` | [] | Only required for Multi-AZ | +| dr_disk_iops_configuration | The SSD IOPS configuration for the file system. Valid modes are 'AUTOMATIC' (3 iops per GB provisioned) or 'USER_PROVISIONED'. NOTE: Due to a bug in the AWS FSx provider, if you want AUTOMATIC, then leave this variable empty. If you want USER_PROVISIONED, then add a 'mode=USER_PROVISIONED' (with USER_PROVISIONED enclosed in double quotes) and 'iops=number' where number is between 1 and 160000. | `map(any)` | {} | No | +| dr_tags | Tags to be applied to the FSxN file system. The format is '{Name1 = value, Name2 = value}' where value should be enclosed in double quotes. | `map(any)` | {} | No | +| dr_maintenance_start_time | The preferred start time to perform weekly maintenance, in UTC time zone. The format is 'D:HH:MM' format. D is the day of the week, where 1=Monday and 7=Sunday. | `string` | 7:00:00 | No | +| dr_svm_name | The name of the Storage Virtual Machine that will house the replicated volumes. | `string` | | Yes | +| dr_root_vol_sec_style | Specifies the root volume security style, Valid values are UNIX, NTFS, and MIXED (although MIXED is not recommended). All volumes created under this SVM will inherit the root security style unless the security style is specified on the volume. | `string` | UNIX | Yes | +| dr_username_pass_secrets_id | Name of the secrets ID in AWS secrets. The AWS Secret should has format of a key `username` where the value should be fsxadmin and a key `password` with the value being the password to be assigned to the destination FSxN filesystem. | `string` | | Yes | From 9564d98273b34a39114fc8a2f686e8f4be172a91 Mon Sep 17 00:00:00 2001 From: Richard Nicholl Date: Thu, 31 Oct 2024 11:22:28 -0400 Subject: [PATCH 15/28] Update README.md --- Terraform/fsxn-replicate/README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Terraform/fsxn-replicate/README.md b/Terraform/fsxn-replicate/README.md index 78bc3f1..d1f64de 100644 --- a/Terraform/fsxn-replicate/README.md +++ b/Terraform/fsxn-replicate/README.md @@ -27,6 +27,8 @@ SnapMirror replication requires **ICMP** and ports **11104** and **11105**. | username_pass_secrets_id | Name of the secrets ID in AWS secrets. The AWS Secret should has format of a key `username` which should be fsxadmin and a key `password` and the password of the FSxN | `string` | | Yes | | validate_certs | When connecting to ONTAP do we validate the cluster certs (true or false). | `string` | false | No | | list_of_volumes_to_replicate | List of volume names to replicate to the destination FSx ONTAP system | `list(string)` | | Yes | + + ## Inputs (DR Cluster) | Name | Description | Type | Default | Required | @@ -48,7 +50,15 @@ SnapMirror replication requires **ICMP** and ports **11104** and **11105**. | dr_root_vol_sec_style | Specifies the root volume security style, Valid values are UNIX, NTFS, and MIXED (although MIXED is not recommended). All volumes created under this SVM will inherit the root security style unless the security style is specified on the volume. | `string` | UNIX | Yes | | dr_username_pass_secrets_id | Name of the secrets ID in AWS secrets. The AWS Secret should has format of a key `username` where the value should be fsxadmin and a key `password` with the value being the password to be assigned to the destination FSxN filesystem. | `string` | | Yes | +## Inputs (Security Group - DR Cluster) +| Name | Description | Type | Default | Required | +| --------------------- | ------------------------------------------------------------------------------------------------------------- | -------------- | ------------------------------------ | :------: | +| dr_create_sg | Determines whether the Security Group should be created as part of this deployment or not. | `bool` | true | Yes | +| dr_security_group_ids | If you are not creating the security group, provide a list of IDs of security groups to be used. | `list(string)` | [] | No | +| dr_security_group_name_prefix | The prefix to the security group name that will be created. | `string` | fsxn-sg | No | +| dr_cidr_for_sg | The VPC ID where the DR FSxN and security group will be created. | `string` | 10.0.0.0/8 | No | +| dr_source_sg_id | The ID of the security group to allow access to the FSxN file system. Set to an empty string if you want to use the cidr_for_sg as the source. | `string` | | No | ## Author Information From 02f7ebd47f0fca58aca54d33101a54a1c71511ad Mon Sep 17 00:00:00 2001 From: nichollri Date: Thu, 31 Oct 2024 14:00:45 -0500 Subject: [PATCH 16/28] added sample.tfvars file and updated readme --- Terraform/fsxn-replicate/README.md | 109 +++++++++++++++++- .../fsxn-replicate/terraform.sample.tfvars | 23 ++++ 2 files changed, 131 insertions(+), 1 deletion(-) create mode 100644 Terraform/fsxn-replicate/terraform.sample.tfvars diff --git a/Terraform/fsxn-replicate/README.md b/Terraform/fsxn-replicate/README.md index d1f64de..b9bebee 100644 --- a/Terraform/fsxn-replicate/README.md +++ b/Terraform/fsxn-replicate/README.md @@ -20,7 +20,7 @@ SnapMirror replication requires **ICMP** and ports **11104** and **11105**. | --------------------- | ------------------------------------------------------------------------------------------------------------- | -------------- | ------------------------------------ | :------: | | prime_hostname | Hostname or IP address of primary cluster. | `string` | | Yes | | prime_fsxid | FSx ID of the primary cluster. | `string` | | Yes | -| prime_clus_name | This is the name of the cluster given for ONTAP TF connection profile. This is a user created value, that can be any string. It is referenced in many ONTAP TF resources | `string` | primary_clus | Yes | +| prime_clus_name | This is the name of the cluster given for ONTAP TF connection profile. This is a user created value, that can be any string. It is referenced in many ONTAP TF resources | `string` | primary_clus | Yes | | prime_svm | Name of the primary SVM for the volumes that will be replicated. | `string` | | Yes | | prime_cluster_vserver | Name of the ONTAP cluster vserver for intercluster LIFs in the primary cluster. Can be found by running `network interface show` on the primary cluster. It will have the format FsxId################# | `string` | Yes | | prime_aws_region | AWS region of the primary FSx ONTAP system | `string` | | Yes | @@ -60,6 +60,113 @@ SnapMirror replication requires **ICMP** and ports **11104** and **11105**. | dr_cidr_for_sg | The VPC ID where the DR FSxN and security group will be created. | `string` | 10.0.0.0/8 | No | | dr_source_sg_id | The ID of the security group to allow access to the FSxN file system. Set to an empty string if you want to use the cidr_for_sg as the source. | `string` | | No | +## Usage + +#### 1. Clone the repository + +In your server's terminal, navigate to the location where you wish to store this Terraform repository, and clone the repository using your preferred authentication type. In this example we are using HTTPS clone: + +```shell +git clone https://github.com/NetApp/FSx-ONTAP-samples-scripts +``` + +#### 2. Navigate to the directory + +```shell +cd Terraform/fsxn-replicate +``` + +#### 3. Initialize Terraform + +This directory represents a standalone Terraform module. Run the following command to initialize the module and install all dependencies: + +```shell +terraform init +``` + +A succesfull initialization should display the following output: + +```shell + +Initializing the backend... +Initializing modules... + +Initializing provider plugins... +- Reusing previous version of netapp/netapp-ontap from the dependency lock file +- Reusing previous version of hashicorp/aws from the dependency lock file +- Using previously-installed netapp/netapp-ontap v1.1.4 +- Using previously-installed hashicorp/aws v5.69.0 + +Terraform has been successfully initialized! + +You may now begin working with Terraform. Try running "terraform plan" to see +any changes that are required for your infrastructure. All Terraform commands +should now work. + +If you ever set or change modules or backend configuration for Terraform, +rerun this command to reinitialize your working directory. If you forget, other +commands will detect it and remind you to do so if necessary. + +``` + +You can see that Terraform recognizes the modules required by our configuration: `hashicorp/aws` and `hashicorpt/netapp-ontap`. + +#### 4. Create Variables Values + +- Copy or Rename the file **`terraform.sample.tfvars`** to **`terraform.tfvars`** + +- Open the **`terraform.tfvars`** file in your preferred text editor. Update the values of the variables to match your preferences and save the file. This will ensure that the Terraform code deploys resources according to your specifications. + +- Set the parameters in terraform.tfvars + + ##### Sample file + + *** + + ```ini + # Primary FSxN variables + prime_hostname = "" + prime_fsxid = "fs-xxxxxxxxxxxxxxxxx" + prime_svm = "fsx" + prime_cluster_vserver = "FsxIdxxxxxxxxxxxxxxxx" + prime_aws_region = "us-west-2" + username_pass_secrets_id = "" + list_of_volumes_to_replicate = ["vol1", "vol2", "vol3"] + + # DR FSxN variables + dr_aws_region = "us-west-2" + dr_fsx_name = "terraform-dr-fsxn" + dr_fsx_subnets = { + "primarysub" = "subnet-11111111" + "secondarysub" = "subnet-33333333" + } + dr_svm_name = "fsx-dr" + dr_security_group_name_prefix = "fsxn-sg" + dr_vpc_id = "vpc-xxxxxxxx" + dr_username_pass_secrets_id = "" + dr_snapmirror_policy_name = "" + ``` + +> [!IMPORTANT] +> **Make sure to replace the values with ones that match your AWS environment and needs.** + +#### 5. Create a Terraform plan + +Run the following command to create an execution plan, which lets you preview the changes that Terraform plans to make to your infrastructure: + +```shell +terraform plan +``` + +Ensure that the proposed changes match what you expected before you apply the changes! + +#### 6. Apply the Terraform plan + +Run the following command to execute the Terrafom code and apply the changes proposed in the `plan` step: + +```shell +terraform apply +``` ## Author Information diff --git a/Terraform/fsxn-replicate/terraform.sample.tfvars b/Terraform/fsxn-replicate/terraform.sample.tfvars new file mode 100644 index 0000000..497d825 --- /dev/null +++ b/Terraform/fsxn-replicate/terraform.sample.tfvars @@ -0,0 +1,23 @@ +# Variables for my environment. Source is Development FSxN system. + +# Primary FSxN variables +prime_hostname = "" +prime_fsxid = "fs-xxxxxxxxxxxxxxxxx" +prime_svm = "fsx" +prime_cluster_vserver = "FsxIdxxxxxxxxxxxxxxxx" +prime_aws_region = "us-west-2" +username_pass_secrets_id = "" +list_of_volumes_to_replicate = ["vol1", "vol2", "vol3"] + +# DR FSxN variables +dr_aws_region = "us-west-2" +dr_fsx_name = "terraform-dr-fsxn" +dr_fsx_subnets = { + "primarysub" = "subnet-11111111" + "secondarysub" = "subnet-33333333" + } +dr_svm_name = "fsx-dr" +dr_security_group_name_prefix = "fsxn-sg" +dr_vpc_id = "vpc-xxxxxxxx" +dr_username_pass_secrets_id = "" +dr_snapmirror_policy_name = "" From 0805801af6824cd1f36bfbb3b70aae66cfff10a9 Mon Sep 17 00:00:00 2001 From: nichollri Date: Tue, 5 Nov 2024 15:37:07 -0600 Subject: [PATCH 17/28] Made adjustments and fixes from Keith's comments. --- Terraform/fsxn-replicate/DR_FSxN_variables.tf | 24 ++++---- .../fsxn-replicate/Primary_FSxN_variables.tf | 12 ++-- Terraform/fsxn-replicate/README.md | 59 ++++++++++--------- Terraform/fsxn-replicate/main.tf | 1 + Terraform/fsxn-replicate/output.tf | 7 +++ .../fsxn-replicate/terraform.sample.tfvars | 2 +- 6 files changed, 59 insertions(+), 46 deletions(-) diff --git a/Terraform/fsxn-replicate/DR_FSxN_variables.tf b/Terraform/fsxn-replicate/DR_FSxN_variables.tf index ceb85c5..24d2433 100644 --- a/Terraform/fsxn-replicate/DR_FSxN_variables.tf +++ b/Terraform/fsxn-replicate/DR_FSxN_variables.tf @@ -1,13 +1,13 @@ -# Variables for the Disaster Recovery FSxN system to be created. +# Variables for the Disaster Recovery FSx for ONTAP file system to be created. variable "dr_aws_region" { - description = "AWS regionfor the Secondary(DR) ONTAP FSxN" + description = "AWS region where you want the Secondary(DR) FSx for ONTAP file system." type = string default = "" } variable "dr_fsx_name" { - description = "The name to assign to the destination FSxN file system." + description = "The name to assign to the destination FSx for ONTAP file system." type = string default = "" } @@ -38,7 +38,7 @@ variable "dr_fsx_subnets" { } variable "dr_fsx_capacity_size_gb" { - description = "The storage capacity in GiBs of the FSxN file system. Valid values between 1024 (1 TiB) and 1048576 (1 PiB). Gen 1 deployment types are limited to 192 TiB. Gen 2 Multi AZ is limited to 512 TiB. Gen 2 Single AZ is limited to 1 PiB." + description = "The storage capacity in GiBs of the FSx for ONTAP file system. Valid values between 1024 (1 TiB) and 1048576 (1 PiB). Gen 1 deployment types are limited to 192 TiB. Gen 2 Multi AZ is limited to 512 TiB. Gen 2 Single AZ is limited to 1 PiB." type = number default = 1024 validation { @@ -68,13 +68,13 @@ variable "dr_ha_pairs" { } variable "dr_endpoint_ip_address_range" { - description = "The IP address range that the FSxN file system will be accessible from. This is only used for Multi AZ deployment types and must be left a null for Single AZ deployment types." + description = "The IP address range that the FSx for ONTAP file system will be accessible from. This is only used for Multi AZ deployment types and must be left a null for Single AZ deployment types." type = string default = null } variable "dr_route_table_ids" { - description = "An array of routing table IDs that will be modified to allow access to the FSxN file system. This is only used for Multi AZ deployment types and must be left as null for Single AZ deployment types." + description = "An array of routing table IDs that will be modified to allow access to the FSx for ONTAP file system. This is only used for Multi AZ deployment types and must be left as null for Single AZ deployment types." type = list(string) default = [] } @@ -86,7 +86,7 @@ variable "dr_disk_iops_configuration" { } variable "dr_tags" { - description = "Tags to be applied to the FSxN file system. The format is '{Name1 = value, Name2 = value}' where value should be enclosed in double quotes." + description = "Tags to be applied to the FSx for ONTAP file system. The format is '{Name1 = value, Name2 = value}' where value should be enclosed in double quotes." type = map(any) default = {} } @@ -122,7 +122,7 @@ variable "dr_daily_backup_start_time" { variable "dr_svm_name" { description = "The name of the Storage Virtual Machine" type = string - default = "" + default = "fsx_dr" } variable "dr_root_vol_sec_style" { @@ -134,7 +134,7 @@ variable "dr_root_vol_sec_style" { /* * These last set of variables have to do with a security group that can be optionally * created. The security group will have all the ingress rules that will allow access - * to all the protocols that an FSxN supports (e.g. SMB, NFS, etc). See the security_groups.tf + * to all the protocols that an FSx for ONTAP file system supports (e.g. SMB, NFS, etc). See the security_groups.tf * for more information. * * If you decide to create the security group, you can specify either the CIDR block to @@ -170,19 +170,19 @@ variable "dr_cidr_for_sg" { } variable "dr_source_sg_id" { - description = "The ID of the security group to allow access to the FSxN file system. Set to an empty string if you want to use the cidr_for_sg as the source." + description = "The ID of the security group to allow access to the FSx for ONTAP file system. Set to an empty string if you want to use the cidr_for_sg as the source." type = string default = "" } variable "dr_vpc_id" { - description = "The VPC ID where the DR FSxN and security group will be created." + description = "The VPC ID where the DR FSx for ONTAP file system and security group will be created." type = string default = "" } variable "dr_username_pass_secrets_id" { - description = "Name of secret ID in AWS secrets" + description = "Name of secret ID in AWS secrets. This secret needs to be in the same region as the DR FSx for ONTAP file system." type = string default = "" } diff --git a/Terraform/fsxn-replicate/Primary_FSxN_variables.tf b/Terraform/fsxn-replicate/Primary_FSxN_variables.tf index 05c4bfd..c82718d 100644 --- a/Terraform/fsxn-replicate/Primary_FSxN_variables.tf +++ b/Terraform/fsxn-replicate/Primary_FSxN_variables.tf @@ -5,13 +5,13 @@ variable "prime_hostname" { } variable "prime_fsxid" { - description = "FSx ID of the primary cluster." + description = "FSx for ONTAP file system ID of the primary cluster." type = string default = "" } variable "prime_clus_name" { - description = "This is the name of the cluster given for ONTAP TF connection profile. This is a user creatred value, that can be any string. It is referenced in many ONTAP TF resources." + description = "This is the name of the cluster given for ONTAP TerraForm connection profile. This is a user creatred value, that can be any string. It is referenced in many ONTAP TF resources." type = string default = "primary_clus" } @@ -23,19 +23,19 @@ variable "prime_svm" { } variable "prime_cluster_vserver" { - description = "Name of cluster vserver for inter cluster lifs in the primary cluster. This can be found by running network interface show on the source cluster. It will be formatted like this FsxIdxxxxxxxx" + description = "Name of cluster vserver for inter cluster lifs in the primary cluster. This can be found by running network interface show on the source cluster (network interface show -services default-intercluster). It will be formatted like this FsxIdxxxxxxxx" type = string default = "" } variable "prime_aws_region" { - description = "AWS regionfor the Primary ONTAP FSxN" + description = "AWS regionfor the Primary FSx for ONTAP file system" type = string default = "" } variable "username_pass_secrets_id" { - description = "Name of secret ID in AWS secrets" + description = "Name of secret ID in AWS secrets. This secret needs to be in the same region as the Primary FSx for ONTAP file system." type = string default = "" } @@ -47,7 +47,7 @@ variable "list_of_volumes_to_replicate" { } variable "validate_certs" { - description = "Do we validate the cluster certs (true or false)" + description = "Do we validate the cluster certs (true or false). If true then ONTAP requires valid, non-self signed SSL certificates." type = string default = "false" } diff --git a/Terraform/fsxn-replicate/README.md b/Terraform/fsxn-replicate/README.md index b9bebee..f5d150c 100644 --- a/Terraform/fsxn-replicate/README.md +++ b/Terraform/fsxn-replicate/README.md @@ -1,54 +1,59 @@ -# Deploy DR FSx ONTAP cluster and create SnapMirror relationships from source FSxN +# Deploy DR FSx for ONTAP file system and create SnapMirror relationships from source FSx for ONTAP file system ## Introduction -This repository contains a method to take an existing FSxN system and replicate volumes to a new FSx ONTAP instance for disaster recovery or backup purposes. It leverages both AWS FSx Terraform provider as well as the ONTAP Terraform provider. +This repository contains a method to take an existing FSx for ONTAP file system and replicate volumes to a new FSx for ONTAP file system for disaster recovery or backup purposes. It leverages both AWS FSx Terraform provider as well as the ONTAP Terraform provider. +Note: Currently supports replicating volumes within a single SVM. ## Setup -You will need to define some key characteristics of the destination FSxN cluster that will be created, such as deployment type and througput, full list below. You also will need to define the source SVM and list of volumes to replicate, and replication parameters. +### Overview + +You will need to define some key characteristics of the destination FSx for ONTAP file system that will be created, such as deployment type and througput, full list below. You also will need to define the source SVM and list of volumes to replicate, and replication parameters. These values can be found in the following variables files: Primary_FSxN_variables.tf and DR_FSxN_variables.tf -## Prerequisites -You have an existing FSx ONTAP system that you want to replicate to a new FSxN system. There is proper networking connectivy between the source FSxN system and the region/VPC/subnets where the destination FSxN system will be deployed. +### Prerequisites +You have an existing FSx for ONTAP file system that you want to replicate to a new FSx for ONTAP file system. There is proper networking connectivy between the source FSx for ONTAP file system and the region/VPC/subnets where the destination FSx for ONTAP file system will be deployed. SnapMirror replication requires **ICMP** and ports **11104** and **11105**. -## Inputs (Primary Cluster) +### Inputs (Primary Cluster) + +These variables are to be filled in the terraform.tfvars file, please see instruction below in the Usage section. | Name | Description | Type | Default | Required | | --------------------- | ------------------------------------------------------------------------------------------------------------- | -------------- | ------------------------------------ | :------: | -| prime_hostname | Hostname or IP address of primary cluster. | `string` | | Yes | -| prime_fsxid | FSx ID of the primary cluster. | `string` | | Yes | -| prime_clus_name | This is the name of the cluster given for ONTAP TF connection profile. This is a user created value, that can be any string. It is referenced in many ONTAP TF resources | `string` | primary_clus | Yes | +| prime_hostname | Hostname or IP address of primary FSx for ONTAP file system. | `string` | | Yes | +| prime_fsxid | FSx for ONTAP file system ID of the primary cluster. | `string` | | Yes | | prime_svm | Name of the primary SVM for the volumes that will be replicated. | `string` | | Yes | -| prime_cluster_vserver | Name of the ONTAP cluster vserver for intercluster LIFs in the primary cluster. Can be found by running `network interface show` on the primary cluster. It will have the format FsxId################# | `string` | Yes | -| prime_aws_region | AWS region of the primary FSx ONTAP system | `string` | | Yes | +| prime_cluster_vserver | Name of the ONTAP cluster vserver for intercluster LIFs in the primary cluster. Can be found by running `network interface show -services default-intercluster` on the primary cluster. It will have the format FsxId################# | `string` | Yes | +| prime_aws_region | AWS region of the primary FSx for ONTAP file system | `string` | | Yes | | username_pass_secrets_id | Name of the secrets ID in AWS secrets. The AWS Secret should has format of a key `username` which should be fsxadmin and a key `password` and the password of the FSxN | `string` | | Yes | | validate_certs | When connecting to ONTAP do we validate the cluster certs (true or false). | `string` | false | No | -| list_of_volumes_to_replicate | List of volume names to replicate to the destination FSx ONTAP system | `list(string)` | | Yes | +| list_of_volumes_to_replicate | List of volume names to replicate to the destination FSx for ONTAP file system | `list(string)` | | Yes | -## Inputs (DR Cluster) +### Inputs (DR Cluster) | Name | Description | Type | Default | Required | | --------------------- | ------------------------------------------------------------------------------------------------------------- | -------------- | ------------------------------------ | :------: | -| dr_aws_region | AWS regionfor the Secondary(DR) ONTAP system. | `string` | | Yes | -| dr_fsx_name | The name to assign to the destination FSxN file system that will be created. | `string` | | Yes | -| dr_clus_name | This is the name of the cluster given for ONTAP TF connection profile. This is a user created value, that can be any string. It is referenced in many ONTAP TF resources | `string` | Yes | -| dr_fsx_deploy_type | The file system deployment type. Supported values are 'MULTI_AZ_1', 'SINGLE_AZ_1', 'MULTI_AZ_2', and 'SINGLE_AZ_2'. MULTI_AZ_1 and SINGLE_AZ_1 are Gen 1. MULTI_AZ_2 and SINGLE_AZ_2 are Gen 2. | SINGLE_AZ_1 | Yes | -| dr_fsx_subnets | The primary subnet ID, and secondary subnet ID if you are deploying in a Multi AZ environment, file system will be accessible from. For MULTI_AZ deployment types both subnets are required. For SINGLE_AZ deployment type, only the primary subnet is used. `map(any)` | | Yes | -| dr_fsx_capacity_size_gb | The storage capacity in GiBs of the FSxN file system. Valid values between 1024 (1 TiB) and 1048576 (1 PiB). Gen 1 deployment types are limited to 192 TiB. Gen 2 Multi AZ is limited to 512 TiB. Gen 2 Single AZ is limited to 1 PiB. The sizing should take into account the size of the volumes you plan to replicate and the tiering policy of the volumes. | `number` | 1024 | Yes | +| dr_aws_region | AWS region where you want the Secondary(DR) FSx for ONTAP file system to be deployed. | `string` | | Yes | +| dr_fsx_name | The name to assign to the destination FSx for ONTAP file system that will be created. | `string` | | Yes | +| dr_fsx_deploy_type | The file system deployment type. Supported values are 'MULTI_AZ_1', 'SINGLE_AZ_1', 'MULTI_AZ_2', and 'SINGLE_AZ_2'. MULTI_AZ_1 and SINGLE_AZ_1 are Gen 1. MULTI_AZ_2 and SINGLE_AZ_2 are Gen 2. | `string` | SINGLE_AZ_1 | Yes | +| dr_fsx_subnets | The primary subnet ID, and secondary subnet ID if you are deploying in a Multi AZ environment, file system will be accessible from. For MULTI_AZ deployment types both subnets are required. For SINGLE_AZ deployment type, only the primary subnet is used. | `map(any)` | | Yes | +| dr_fsx_capacity_size_gb | The storage capacity in GiBs of the FSx for ONTAP file system. Valid values between 1024 (1 TiB) and 1048576 (1 PiB). Gen 1 deployment types are limited to 192 TiB. Gen 2 Multi AZ is limited to 512 TiB. Gen 2 Single AZ is limited to 1 PiB. The sizing should take into account the size of the volumes you plan to replicate and the tiering policy of the volumes. | `number` | 1024 | Yes | | dr_fsx_tput_in_MBps | The throughput capacity (in MBps) for the file system. Valid values are 128, 256, 512, 1024, 2048, and 4096 for Gen 1, and 384, 768, 1536, 3072 and 6144 for Gen 2. | `string` | 128 | Yes | | dr_ha_pairs | The number of HA pairs in the file system. Valid values are from 1 through 12. Only single AZ Gen 2 deployment type supports more than 1 HA pair. | `number` | 1 | Yes | -| dr_endpoint_ip_address_range | The IP address range that the FSxN file system will be accessible from. This is only used for Multi AZ deployment types and must be left a null for Single AZ deployment types. | `string` | null | No | -| dr_route_table_ids | An array of routing table IDs that will be modified to allow access to the FSxN file system. This is only used for Multi AZ deployment types and must be left as null for Single AZ deployment types. | `list(string)` | [] | Only required for Multi-AZ | +| dr_endpoint_ip_address_range | The IP address range that the FSx for ONTAP file system will be accessible from. This is only used for Multi AZ deployment types and must be left a null for Single AZ deployment types. | `string` | null | No | +| dr_route_table_ids | An array of routing table IDs that will be modified to allow access to the FSx for ONTAP file system. This is only used for Multi AZ deployment types and must be left as null for Single AZ deployment types. | `list(string)` | [] | Only required for Multi-AZ | | dr_disk_iops_configuration | The SSD IOPS configuration for the file system. Valid modes are 'AUTOMATIC' (3 iops per GB provisioned) or 'USER_PROVISIONED'. NOTE: Due to a bug in the AWS FSx provider, if you want AUTOMATIC, then leave this variable empty. If you want USER_PROVISIONED, then add a 'mode=USER_PROVISIONED' (with USER_PROVISIONED enclosed in double quotes) and 'iops=number' where number is between 1 and 160000. | `map(any)` | {} | No | -| dr_tags | Tags to be applied to the FSxN file system. The format is '{Name1 = value, Name2 = value}' where value should be enclosed in double quotes. | `map(any)` | {} | No | +| dr_tags | Tags to be applied to the FSx for ONTAP file system. The format is '{Name1 = value, Name2 = value}' where value should be enclosed in double quotes. | `map(any)` | {} | No | | dr_maintenance_start_time | The preferred start time to perform weekly maintenance, in UTC time zone. The format is 'D:HH:MM' format. D is the day of the week, where 1=Monday and 7=Sunday. | `string` | 7:00:00 | No | -| dr_svm_name | The name of the Storage Virtual Machine that will house the replicated volumes. | `string` | | Yes | +| dr_svm_name | The name of the Storage Virtual Machine that will house the replicated volumes. | `string` | fsx_dr | Yes | | dr_root_vol_sec_style | Specifies the root volume security style, Valid values are UNIX, NTFS, and MIXED (although MIXED is not recommended). All volumes created under this SVM will inherit the root security style unless the security style is specified on the volume. | `string` | UNIX | Yes | -| dr_username_pass_secrets_id | Name of the secrets ID in AWS secrets. The AWS Secret should has format of a key `username` where the value should be fsxadmin and a key `password` with the value being the password to be assigned to the destination FSxN filesystem. | `string` | | Yes | +| dr_username_pass_secrets_id | Name of the secrets ID in AWS secrets. The AWS Secret should has format of a key `username` where the value should be fsxadmin and a key `password` with the value being the password to be assigned to the destination FSx for ONTAP file system. | `string` | | Yes | +| dr_vpc_id | The VPC ID where the DR FSx for ONTAP file system (and security group if this option is selected) will be created. | `string` | | Yes | +| dr_snapmirror_policy_name | Name of snamirror policy to create. | `string` | | Yes | ## Inputs (Security Group - DR Cluster) @@ -57,8 +62,8 @@ SnapMirror replication requires **ICMP** and ports **11104** and **11105**. | dr_create_sg | Determines whether the Security Group should be created as part of this deployment or not. | `bool` | true | Yes | | dr_security_group_ids | If you are not creating the security group, provide a list of IDs of security groups to be used. | `list(string)` | [] | No | | dr_security_group_name_prefix | The prefix to the security group name that will be created. | `string` | fsxn-sg | No | -| dr_cidr_for_sg | The VPC ID where the DR FSxN and security group will be created. | `string` | 10.0.0.0/8 | No | -| dr_source_sg_id | The ID of the security group to allow access to the FSxN file system. Set to an empty string if you want to use the cidr_for_sg as the source. | `string` | | No | +| dr_cidr_for_sg | The cidr block to be used for the created security ingress rules. Set to an empty string if you want to use the source_sg_id as the source. | `string` | 10.0.0.0/8 | No | +| dr_source_sg_id | The ID of the security group to allow access to the FSx for ONTAP file system. Set to an empty string if you want to use the cidr_for_sg as the source. | `string` | | No | ## Usage @@ -125,7 +130,7 @@ You can see that Terraform recognizes the modules required by our configuration: ```ini # Primary FSxN variables - prime_hostname = "" + prime_hostname = "" prime_fsxid = "fs-xxxxxxxxxxxxxxxxx" prime_svm = "fsx" prime_cluster_vserver = "FsxIdxxxxxxxxxxxxxxxx" diff --git a/Terraform/fsxn-replicate/main.tf b/Terraform/fsxn-replicate/main.tf index 51a48f2..b06830e 100644 --- a/Terraform/fsxn-replicate/main.tf +++ b/Terraform/fsxn-replicate/main.tf @@ -128,6 +128,7 @@ resource "aws_fsx_ontap_volume" "dp_volumes" { # For now let's try to get the source and destination IC LIFs via AWS TF provider. data "aws_fsx_ontap_file_system" "source_fsxn" { + provider = aws.prime-aws-region id = var.prime_fsxid } diff --git a/Terraform/fsxn-replicate/output.tf b/Terraform/fsxn-replicate/output.tf index 7827cc3..c70f066 100644 --- a/Terraform/fsxn-replicate/output.tf +++ b/Terraform/fsxn-replicate/output.tf @@ -16,3 +16,10 @@ # description = "All data from aws fsxn provider" #} + +output "dr_fsxn_system" { + value = { + cluster_mgmt_ip = aws_fsx_ontap_file_system.terraform-fsxn.endpoints[0].management[0].ip_addresses + } + description = "Cluster management IP address of the created DR cluster" +} diff --git a/Terraform/fsxn-replicate/terraform.sample.tfvars b/Terraform/fsxn-replicate/terraform.sample.tfvars index 497d825..945c965 100644 --- a/Terraform/fsxn-replicate/terraform.sample.tfvars +++ b/Terraform/fsxn-replicate/terraform.sample.tfvars @@ -1,7 +1,7 @@ # Variables for my environment. Source is Development FSxN system. # Primary FSxN variables -prime_hostname = "" +prime_hostname = "" prime_fsxid = "fs-xxxxxxxxxxxxxxxxx" prime_svm = "fsx" prime_cluster_vserver = "FsxIdxxxxxxxxxxxxxxxx" From 81e8aa781c2c4f8d4e5efab34f79fe447f37ac69 Mon Sep 17 00:00:00 2001 From: Richard Nicholl Date: Wed, 6 Nov 2024 10:52:38 -0500 Subject: [PATCH 18/28] Update README.md --- Terraform/fsxn-replicate/README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Terraform/fsxn-replicate/README.md b/Terraform/fsxn-replicate/README.md index f5d150c..090a161 100644 --- a/Terraform/fsxn-replicate/README.md +++ b/Terraform/fsxn-replicate/README.md @@ -2,7 +2,8 @@ ## Introduction This repository contains a method to take an existing FSx for ONTAP file system and replicate volumes to a new FSx for ONTAP file system for disaster recovery or backup purposes. It leverages both AWS FSx Terraform provider as well as the ONTAP Terraform provider. -Note: Currently supports replicating volumes within a single SVM. + +Note: Currently it supports replicating volumes within a single SVM. ## Setup @@ -26,7 +27,7 @@ These variables are to be filled in the terraform.tfvars file, please see instru | prime_hostname | Hostname or IP address of primary FSx for ONTAP file system. | `string` | | Yes | | prime_fsxid | FSx for ONTAP file system ID of the primary cluster. | `string` | | Yes | | prime_svm | Name of the primary SVM for the volumes that will be replicated. | `string` | | Yes | -| prime_cluster_vserver | Name of the ONTAP cluster vserver for intercluster LIFs in the primary cluster. Can be found by running `network interface show -services default-intercluster` on the primary cluster. It will have the format FsxId################# | `string` | Yes | +| prime_cluster_vserver | Name of the ONTAP cluster vserver for intercluster LIFs in the primary cluster. Can be found by running `network interface show -services default-intercluster` on the primary cluster. It will have the format FsxId################# | `string` | | Yes | | prime_aws_region | AWS region of the primary FSx for ONTAP file system | `string` | | Yes | | username_pass_secrets_id | Name of the secrets ID in AWS secrets. The AWS Secret should has format of a key `username` which should be fsxadmin and a key `password` and the password of the FSxN | `string` | | Yes | | validate_certs | When connecting to ONTAP do we validate the cluster certs (true or false). | `string` | false | No | From 6a8486c991487ee424af5074b4d50aef0677550e Mon Sep 17 00:00:00 2001 From: nichollri Date: Wed, 6 Nov 2024 14:18:05 -0600 Subject: [PATCH 19/28] added some snapmirror variables and improved README sections. --- Terraform/fsxn-replicate/DR_FSxN_variables.tf | 22 +++++++++++++++++++ Terraform/fsxn-replicate/README.md | 3 ++- Terraform/fsxn-replicate/main.tf | 15 +++++-------- Terraform/fsxn-replicate/output.tf | 17 ++++++++++++++ 4 files changed, 47 insertions(+), 10 deletions(-) diff --git a/Terraform/fsxn-replicate/DR_FSxN_variables.tf b/Terraform/fsxn-replicate/DR_FSxN_variables.tf index 24d2433..098a998 100644 --- a/Terraform/fsxn-replicate/DR_FSxN_variables.tf +++ b/Terraform/fsxn-replicate/DR_FSxN_variables.tf @@ -192,3 +192,25 @@ variable "dr_snapmirror_policy_name" { type = string default = "" } + +variable "dr_transfer_schedule" { + description = "The schedule used to update asynchronous relationships." + type = string + default = "hourly" +} + +variable "dr_retention" { + description = "Rules for Snapshot copy retention." + type = string + default = <<-EOF +[{ + "label": "weekly", + "count": 4 +}, +{ + "label": "daily", + "count": 7 +}] +EOF +} + diff --git a/Terraform/fsxn-replicate/README.md b/Terraform/fsxn-replicate/README.md index 090a161..08455ef 100644 --- a/Terraform/fsxn-replicate/README.md +++ b/Terraform/fsxn-replicate/README.md @@ -55,7 +55,8 @@ These variables are to be filled in the terraform.tfvars file, please see instru | dr_username_pass_secrets_id | Name of the secrets ID in AWS secrets. The AWS Secret should has format of a key `username` where the value should be fsxadmin and a key `password` with the value being the password to be assigned to the destination FSx for ONTAP file system. | `string` | | Yes | | dr_vpc_id | The VPC ID where the DR FSx for ONTAP file system (and security group if this option is selected) will be created. | `string` | | Yes | | dr_snapmirror_policy_name | Name of snamirror policy to create. | `string` | | Yes | - +| dr_transfer_schedule | The schedule used to update asynchronous relationships. | `string` | hourly | No | +| dr_retention | Rules for Snapshot copy retention. See [Retention Schema] (https://registry.terraform.io/providers/NetApp/netapp-ontap/latest/docs/resources/snapmirror_policy_resource#retention) | `string` | 4 weekly, 2 daily | Yes | ## Inputs (Security Group - DR Cluster) | Name | Description | Type | Default | Required | diff --git a/Terraform/fsxn-replicate/main.tf b/Terraform/fsxn-replicate/main.tf index b06830e..0cfb6b6 100644 --- a/Terraform/fsxn-replicate/main.tf +++ b/Terraform/fsxn-replicate/main.tf @@ -173,21 +173,18 @@ resource "netapp-ontap_svm_peers_resource" "peer_svms" { ] } +locals { + dr_retention_parsed = jsondecode(var.dr_retention) +} + resource "netapp-ontap_snapmirror_policy_resource" "snapmirror_policy_async" { # required to know which system to interface with cx_profile_name = var.dr_clus_name name = var.dr_snapmirror_policy_name svm_name = aws_fsx_ontap_storage_virtual_machine.mysvm.name type = "async" - retention = [{ - label = "weekly" - count = 2 - }, - { - label = "daily", - count = 7 - } - ] + transfer_schedule_name = var.dr_transfer_schedule + retention = local.dr_retention_parsed } diff --git a/Terraform/fsxn-replicate/output.tf b/Terraform/fsxn-replicate/output.tf index c70f066..c7e7ac8 100644 --- a/Terraform/fsxn-replicate/output.tf +++ b/Terraform/fsxn-replicate/output.tf @@ -23,3 +23,20 @@ output "dr_fsxn_system" { } description = "Cluster management IP address of the created DR cluster" } + +#output "replication_relationships" { +# value = { +# full_data = netapp-ontap_snapmirror_resource.snapmirror +# } +# description = "Replication relationships" +#} + +output "snapmirror_details" { + value = { for id, snapmirror in netapp-ontap_snapmirror_resource.snapmirror : id => { + source_path = snapmirror.source_endpoint.path + destination_path = snapmirror.destination_endpoint.path + policy_name = snapmirror.policy.name + }} + description = "A map of all snapmirror details." +} + From cd03094ead66de6a6936e1f118ab919e519cefd9 Mon Sep 17 00:00:00 2001 From: Richard Nicholl Date: Fri, 8 Nov 2024 15:17:06 -0500 Subject: [PATCH 20/28] Update README.md with validate certs and secrets information update. --- Terraform/fsxn-replicate/README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Terraform/fsxn-replicate/README.md b/Terraform/fsxn-replicate/README.md index 08455ef..74e7fdd 100644 --- a/Terraform/fsxn-replicate/README.md +++ b/Terraform/fsxn-replicate/README.md @@ -11,7 +11,7 @@ Note: Currently it supports replicating volumes within a single SVM. You will need to define some key characteristics of the destination FSx for ONTAP file system that will be created, such as deployment type and througput, full list below. You also will need to define the source SVM and list of volumes to replicate, and replication parameters. -These values can be found in the following variables files: Primary_FSxN_variables.tf and DR_FSxN_variables.tf +These values can be found in the following variables files: Primary_FSxN_variables.tf and DR_FSxN_variables.tf files. The values should be set in the terraform.tfvars file. ### Prerequisites You have an existing FSx for ONTAP file system that you want to replicate to a new FSx for ONTAP file system. There is proper networking connectivy between the source FSx for ONTAP file system and the region/VPC/subnets where the destination FSx for ONTAP file system will be deployed. @@ -29,8 +29,8 @@ These variables are to be filled in the terraform.tfvars file, please see instru | prime_svm | Name of the primary SVM for the volumes that will be replicated. | `string` | | Yes | | prime_cluster_vserver | Name of the ONTAP cluster vserver for intercluster LIFs in the primary cluster. Can be found by running `network interface show -services default-intercluster` on the primary cluster. It will have the format FsxId################# | `string` | | Yes | | prime_aws_region | AWS region of the primary FSx for ONTAP file system | `string` | | Yes | -| username_pass_secrets_id | Name of the secrets ID in AWS secrets. The AWS Secret should has format of a key `username` which should be fsxadmin and a key `password` and the password of the FSxN | `string` | | Yes | -| validate_certs | When connecting to ONTAP do we validate the cluster certs (true or false). | `string` | false | No | +| username_pass_secrets_id | Name of the secrets ID in AWS secrets. The AWS Secret should have a format of a key `username`, which should have a value of `fsxadmin,` and another key `password` with its value set to the password of the FSxN. *Note*: The secret must be in the same region as the FSx for ONTAP file system it is associated with. | `string` | | Yes | +| validate_certs | When connecting to an FSx for ONTAP file system, should Terraform validate the SSL certificate (true or false)? This should be set to `false` if you are using the default self-signed SSL certificate. | `string` | false | No | | list_of_volumes_to_replicate | List of volume names to replicate to the destination FSx for ONTAP file system | `list(string)` | | Yes | @@ -40,7 +40,7 @@ These variables are to be filled in the terraform.tfvars file, please see instru | --------------------- | ------------------------------------------------------------------------------------------------------------- | -------------- | ------------------------------------ | :------: | | dr_aws_region | AWS region where you want the Secondary(DR) FSx for ONTAP file system to be deployed. | `string` | | Yes | | dr_fsx_name | The name to assign to the destination FSx for ONTAP file system that will be created. | `string` | | Yes | -| dr_fsx_deploy_type | The file system deployment type. Supported values are 'MULTI_AZ_1', 'SINGLE_AZ_1', 'MULTI_AZ_2', and 'SINGLE_AZ_2'. MULTI_AZ_1 and SINGLE_AZ_1 are Gen 1. MULTI_AZ_2 and SINGLE_AZ_2 are Gen 2. | `string` | SINGLE_AZ_1 | Yes | +| dr_fsx_deploy_type | The file system deploment type. Supported values are 'MULTI_AZ_1', 'SINGLE_AZ_1', 'MULTI_AZ_2', and 'SINGLE_AZ_2'. MULTI_AZ_1 and SINGLE_AZ_1 are Gen 1. MULTI_AZ_2 and SINGLE_AZ_2 are Gen 2. | `string` | SINGLE_AZ_1 | Yes | | dr_fsx_subnets | The primary subnet ID, and secondary subnet ID if you are deploying in a Multi AZ environment, file system will be accessible from. For MULTI_AZ deployment types both subnets are required. For SINGLE_AZ deployment type, only the primary subnet is used. | `map(any)` | | Yes | | dr_fsx_capacity_size_gb | The storage capacity in GiBs of the FSx for ONTAP file system. Valid values between 1024 (1 TiB) and 1048576 (1 PiB). Gen 1 deployment types are limited to 192 TiB. Gen 2 Multi AZ is limited to 512 TiB. Gen 2 Single AZ is limited to 1 PiB. The sizing should take into account the size of the volumes you plan to replicate and the tiering policy of the volumes. | `number` | 1024 | Yes | | dr_fsx_tput_in_MBps | The throughput capacity (in MBps) for the file system. Valid values are 128, 256, 512, 1024, 2048, and 4096 for Gen 1, and 384, 768, 1536, 3072 and 6144 for Gen 2. | `string` | 128 | Yes | @@ -52,11 +52,11 @@ These variables are to be filled in the terraform.tfvars file, please see instru | dr_maintenance_start_time | The preferred start time to perform weekly maintenance, in UTC time zone. The format is 'D:HH:MM' format. D is the day of the week, where 1=Monday and 7=Sunday. | `string` | 7:00:00 | No | | dr_svm_name | The name of the Storage Virtual Machine that will house the replicated volumes. | `string` | fsx_dr | Yes | | dr_root_vol_sec_style | Specifies the root volume security style, Valid values are UNIX, NTFS, and MIXED (although MIXED is not recommended). All volumes created under this SVM will inherit the root security style unless the security style is specified on the volume. | `string` | UNIX | Yes | -| dr_username_pass_secrets_id | Name of the secrets ID in AWS secrets. The AWS Secret should has format of a key `username` where the value should be fsxadmin and a key `password` with the value being the password to be assigned to the destination FSx for ONTAP file system. | `string` | | Yes | +| dr_username_pass_secrets_id | Name of the secrets ID in AWS secrets. The AWS Secret should have a format of a key `username`, which should have a value of `fsxadmin,` and another key `password` with its value set to the password of the FSxN. *Note*: The secret must be in the same region as the FSx for ONTAP file system it is associated with. | `string` | | Yes | | dr_vpc_id | The VPC ID where the DR FSx for ONTAP file system (and security group if this option is selected) will be created. | `string` | | Yes | | dr_snapmirror_policy_name | Name of snamirror policy to create. | `string` | | Yes | | dr_transfer_schedule | The schedule used to update asynchronous relationships. | `string` | hourly | No | -| dr_retention | Rules for Snapshot copy retention. See [Retention Schema] (https://registry.terraform.io/providers/NetApp/netapp-ontap/latest/docs/resources/snapmirror_policy_resource#retention) | `string` | 4 weekly, 2 daily | Yes | +| dr_retention | Rules for Snapshot copy retention. See [Retention Schema](https://registry.terraform.io/providers/NetApp/netapp-ontap/latest/docs/resources/snapmirror_policy_resource#retention) | `string` | 4 weekly, 2 daily | Yes | ## Inputs (Security Group - DR Cluster) | Name | Description | Type | Default | Required | From 46e1ad4e8030b069509dec0da437822544e41209 Mon Sep 17 00:00:00 2001 From: Richard Nicholl Date: Fri, 8 Nov 2024 15:23:33 -0500 Subject: [PATCH 21/28] Update main.tf - switched from using prime_hostname variable to referencing from pulled AWS data resource. --- Terraform/fsxn-replicate/main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Terraform/fsxn-replicate/main.tf b/Terraform/fsxn-replicate/main.tf index 0cfb6b6..6078a64 100644 --- a/Terraform/fsxn-replicate/main.tf +++ b/Terraform/fsxn-replicate/main.tf @@ -37,7 +37,7 @@ provider "netapp-ontap" { connection_profiles = [ { name = var.prime_clus_name - hostname = var.prime_hostname + hostname = join("", data.aws_fsx_ontap_file_system.source_fsxn.endpoints[0].management[0].ip_addresses) username = jsondecode(data.aws_secretsmanager_secret_version.ontap_prime_username_pass.secret_string)["username"] password = jsondecode(data.aws_secretsmanager_secret_version.ontap_prime_username_pass.secret_string)["password"] validate_certs = var.validate_certs From 8196e54d0dc1b612bff2775b1b2682edc1872282 Mon Sep 17 00:00:00 2001 From: Richard Nicholl Date: Fri, 8 Nov 2024 15:24:16 -0500 Subject: [PATCH 22/28] Update Primary_FSxN_variables.tf to remove prime_hostname variable --- Terraform/fsxn-replicate/Primary_FSxN_variables.tf | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Terraform/fsxn-replicate/Primary_FSxN_variables.tf b/Terraform/fsxn-replicate/Primary_FSxN_variables.tf index c82718d..0e3b1c5 100644 --- a/Terraform/fsxn-replicate/Primary_FSxN_variables.tf +++ b/Terraform/fsxn-replicate/Primary_FSxN_variables.tf @@ -1,9 +1,3 @@ -variable "prime_hostname" { - description = "Hostname or IP address of primary cluster." - type = string - default = "" -} - variable "prime_fsxid" { description = "FSx for ONTAP file system ID of the primary cluster." type = string From 12b308124f2af29c111ea82ff89a8d6df32fa6e1 Mon Sep 17 00:00:00 2001 From: Richard Nicholl Date: Fri, 8 Nov 2024 15:25:09 -0500 Subject: [PATCH 23/28] Update README.md - removed prime_hostname --- Terraform/fsxn-replicate/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/Terraform/fsxn-replicate/README.md b/Terraform/fsxn-replicate/README.md index 74e7fdd..2593bf2 100644 --- a/Terraform/fsxn-replicate/README.md +++ b/Terraform/fsxn-replicate/README.md @@ -24,7 +24,6 @@ These variables are to be filled in the terraform.tfvars file, please see instru | Name | Description | Type | Default | Required | | --------------------- | ------------------------------------------------------------------------------------------------------------- | -------------- | ------------------------------------ | :------: | -| prime_hostname | Hostname or IP address of primary FSx for ONTAP file system. | `string` | | Yes | | prime_fsxid | FSx for ONTAP file system ID of the primary cluster. | `string` | | Yes | | prime_svm | Name of the primary SVM for the volumes that will be replicated. | `string` | | Yes | | prime_cluster_vserver | Name of the ONTAP cluster vserver for intercluster LIFs in the primary cluster. Can be found by running `network interface show -services default-intercluster` on the primary cluster. It will have the format FsxId################# | `string` | | Yes | From 7bada13d410d70f8d552964ce84e295fae2f25ea Mon Sep 17 00:00:00 2001 From: Keith Cantrell Date: Fri, 8 Nov 2024 17:57:45 -0600 Subject: [PATCH 24/28] Updated the directory to 'cd' into. --- Terraform/fsxn-replicate/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Terraform/fsxn-replicate/README.md b/Terraform/fsxn-replicate/README.md index 2593bf2..23b6a0f 100644 --- a/Terraform/fsxn-replicate/README.md +++ b/Terraform/fsxn-replicate/README.md @@ -55,7 +55,7 @@ These variables are to be filled in the terraform.tfvars file, please see instru | dr_vpc_id | The VPC ID where the DR FSx for ONTAP file system (and security group if this option is selected) will be created. | `string` | | Yes | | dr_snapmirror_policy_name | Name of snamirror policy to create. | `string` | | Yes | | dr_transfer_schedule | The schedule used to update asynchronous relationships. | `string` | hourly | No | -| dr_retention | Rules for Snapshot copy retention. See [Retention Schema](https://registry.terraform.io/providers/NetApp/netapp-ontap/latest/docs/resources/snapmirror_policy_resource#retention) | `string` | 4 weekly, 2 daily | Yes | +| dr_retention | Rules for Snapshot copy retention. See [Retention Schema](https://registry.terraform.io/providers/NetApp/netapp-ontap/latest/docs/resources/snapmirror_policy_resource#retention) for more information. | `string` | [{ "label": "weekly", "count": 4 }, { "label": "daily", "count": 7 }] | No | ## Inputs (Security Group - DR Cluster) | Name | Description | Type | Default | Required | @@ -79,7 +79,7 @@ git clone https://github.com/NetApp/FSx-ONTAP-samples-scripts #### 2. Navigate to the directory ```shell -cd Terraform/fsxn-replicate +cd FSx-ONTAP-samples-scripts/Terraform/fsxn-replicate ``` #### 3. Initialize Terraform @@ -92,7 +92,7 @@ terraform init A succesfull initialization should display the following output: -```shell +``` Initializing the backend... Initializing modules... @@ -146,7 +146,7 @@ You can see that Terraform recognizes the modules required by our configuration: "primarysub" = "subnet-11111111" "secondarysub" = "subnet-33333333" } - dr_svm_name = "fsx-dr" + dr_svm_name = "fsx_dr" dr_security_group_name_prefix = "fsxn-sg" dr_vpc_id = "vpc-xxxxxxxx" dr_username_pass_secrets_id = "" From 0b9b2b9396321da3132eaa6e1e6290b31cd7eceb Mon Sep 17 00:00:00 2001 From: Keith Cantrell Date: Fri, 8 Nov 2024 18:21:40 -0600 Subject: [PATCH 25/28] Added the output from a sucessful 'teraform apply' command. --- Terraform/fsxn-replicate/README.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/Terraform/fsxn-replicate/README.md b/Terraform/fsxn-replicate/README.md index 23b6a0f..b3cc378 100644 --- a/Terraform/fsxn-replicate/README.md +++ b/Terraform/fsxn-replicate/README.md @@ -174,6 +174,32 @@ Run the following command to execute the Terrafom code and apply the changes pro terraform apply ``` +There will be a lot of output from the `terraform apply` command. At the end, the output +should look simlar to: +``` +Apply complete! Resources: 33 added, 0 changed, 0 destroyed. + +Outputs: + +dr_fsxn_system = { + "cluster_mgmt_ip" = toset([ + "192.168.61.96", + ]) +} +snapmirror_details = { + "unix" = { + "destination_path" = "fsx_dr:unix_dp" + "policy_name" = "dr_policy" + "source_path" = "vs1fsxninjas:unix" + } + "unix2" = { + "destination_path" = "fsx_dr:unix2_dp" + "policy_name" = "dr_policy" + "source_path" = "vs1fsxninjas:unix2" + } +} +``` +The above give you the cluster management IP address of the DR FSx for ONTAP file system, and the SnapMirror details for the volumes that were replicated. ## Author Information This repository is maintained by the contributors listed on [GitHub](https://github.com/NetApp/FSx-ONTAP-samples-scripts/graphs/contributors). From 5c27fc6c1be9c4f6cf6515342e49238df793100c Mon Sep 17 00:00:00 2001 From: Keith Cantrell Date: Fri, 8 Nov 2024 18:23:02 -0600 Subject: [PATCH 26/28] Added setting the 'dr_retention' variable since it might be confusing to someone doing that the first time. --- Terraform/fsxn-replicate/terraform.sample.tfvars | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Terraform/fsxn-replicate/terraform.sample.tfvars b/Terraform/fsxn-replicate/terraform.sample.tfvars index 945c965..caad928 100644 --- a/Terraform/fsxn-replicate/terraform.sample.tfvars +++ b/Terraform/fsxn-replicate/terraform.sample.tfvars @@ -16,8 +16,9 @@ dr_fsx_subnets = { "primarysub" = "subnet-11111111" "secondarysub" = "subnet-33333333" } -dr_svm_name = "fsx-dr" +dr_svm_name = "fsx_dr" dr_security_group_name_prefix = "fsxn-sg" dr_vpc_id = "vpc-xxxxxxxx" dr_username_pass_secrets_id = "" dr_snapmirror_policy_name = "" +dr_retention = "[{ \"label\": \"weekly\", \"count\": 4 }, { \"label\": \"daily\", \"count\": 7 }]" From dfe9d185e9fbfd155128a9b75381be77243f21fb Mon Sep 17 00:00:00 2001 From: Keith Cantrell Date: Fri, 8 Nov 2024 18:27:48 -0600 Subject: [PATCH 27/28] Added owner to fsxn-replicate --- .github/CODEOWNERS | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 952003f..c0c3a40 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -20,3 +20,4 @@ /Terraform/deploy-fsx-ontap-sqlserver/ @varunrai /Terraform/deploy-fsx-ontap-fileshare-access/ @varunrai /Terraform/deploy-fsx-ontap/ @kcantrel +/Terraform/fsxn-replicate/ @nichollri From 79ff957e7ae7929d26c14c2a70861c5a5d4135f7 Mon Sep 17 00:00:00 2001 From: Keith Cantrell Date: Fri, 8 Nov 2024 18:39:29 -0600 Subject: [PATCH 28/28] Added the new 'FSxN Replication' sample. --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 80c8345..86f66f9 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,9 @@ Have a great idea? We'd love to hear it! Please email us at [ng-fsxn-github-samp * [AI](/AI) * [GenAI ChatBot application sample](/AI/GenAI-ChatBot-application-sample) +* [Anisble](/Ansible) + * [FSx ONTAP inventory report](/Ansible/fsx_inventory_report) + * [SnapMirror report](/Ansible/snapmirror_report) * [CloudFormation](/CloudFormation) * [deploy-fsx-ontap](/CloudFormation/deploy-fsx-ontap) * [EKS](/EKS) @@ -39,6 +42,7 @@ Have a great idea? We'd love to hear it! Please email us at [ng-fsxn-github-samp * [k8s applications non-stdout logs collection into ELK](/Solutions/EKS-logs-to-ELK) * [Terraform](/Terraform) * [FSx ONTAP deployment using Terraform](/Terraform/deploy-fsx-ontap) + * [FSx ONTAP Replication](/Terraform/fsxn-replication) * [Deployment of SQL Server on EC2 with FSx ONTAP](/Terraform/deploy-fsx-ontap-sqlserver) * [Deployment of FSx ONTAP with VPN for File Share Access](/Terraform/deploy-fsx-ontap-fileshare-access)