From 2e2c40f89fd3d45b8c41a3478699ca40d3955afd Mon Sep 17 00:00:00 2001 From: jasonking3 Date: Fri, 1 May 2020 09:50:32 -0700 Subject: [PATCH 1/4] Ignore 0.0.0.0 as reported guest IP --- vmware/cedge_vmware/main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vmware/cedge_vmware/main.tf b/vmware/cedge_vmware/main.tf index 0e0f08c..4464b42 100644 --- a/vmware/cedge_vmware/main.tf +++ b/vmware/cedge_vmware/main.tf @@ -62,7 +62,7 @@ resource "vsphere_virtual_machine" "vm" { guest_id = data.vsphere_virtual_machine.template[0].guest_id scsi_type = data.vsphere_virtual_machine.template[0].scsi_type - ignored_guest_ips = ["192.168.1.1"] + ignored_guest_ips = ["192.168.1.1", "0.0.0.0"] wait_for_guest_net_routable = false cdrom { From 2b15275c290f268b195c63f63b7a350b09d195ac Mon Sep 17 00:00:00 2001 From: jasonking3 Date: Thu, 7 May 2020 15:52:45 -0700 Subject: [PATCH 2/4] Changes to support CSR1000v version 17.2 + improved VM folder support --- README.md | 19 ++++--- vmware/cedge_vmware/create_iso.tf | 54 +++++++++++++++++++ vmware/cedge_vmware/main.tf | 36 +++++-------- vmware/cedge_vmware/variables.tf | 9 ++++ .../cedge/ciscosdwan_cloud_init.cfg | 48 +++++++++++++++++ vmware/main.tf | 3 ++ vmware/viptela_vmware/create_iso.tf | 2 +- vmware/viptela_vmware/main.tf | 2 +- 8 files changed, 139 insertions(+), 34 deletions(-) create mode 100644 vmware/cedge_vmware/create_iso.tf create mode 100644 vmware/cloud-init/cedge/ciscosdwan_cloud_init.cfg diff --git a/README.md b/README.md index 5856016..e6efcd7 100644 --- a/README.md +++ b/README.md @@ -24,19 +24,22 @@ In the vCenter UI, create the Viptela VM templates: 1. In the "Select storage" section, set the virtual disk format to "Thin provisioned" to make more efficient use of the datastore disk space. After all of the OVFs have been deployed, edit the settings of each Viptela VM template and: -1. Add a "SCSI Controller" of type "LSI Logic Parallel" -1. Change "Hard disk 1" "Virtual Device Node" setting from "IDE 0" to "New SCSI controller" -1. Click OK +1. Add a "SCSI Controller" of type "LSI Logic Parallel". +1. Change "Hard disk 1" "Virtual Device Node" setting from "IDE 0" to "New SCSI controller". +1. Click OK. +1. The VM is now ready to use as a template for use with terraform. > Note: Do not add a second disk to the vManage template. Terraform will do this dynamically. -#### cEdge +#### CSR1000v In the vCenter UI, create the VM template for CSR1000v w/SD-WAN (aka cEdge): -1. Deploy the OVF (`csr1000v-ucmk9.16.12.1e.ova` or similar) +1. Deploy the OVF. (`csr1000v-ucmk9.16.12.1e.ova` or similar) 1. In the "Select storage" section, set the virtual disk format to "Thin provisioned" to make more efficient use of the datastore disk space. 1. In the "Customize template" section, just leave the values blank and click "Next". Terraform will set these properties when it clones the VM. -1. After the OVF is successfully deployed, power on the VM and watch the console until it finishes booting. This will take several minutes. -1. Once you see the login prompt, power down the VM. +1. After the OVF is successfully deployed, go to the "Configure" section and select "vApp Options" from the menu on the left. Click "Edit..." and unselect the "Enable vApp options" checkbox at the top. Say "Yes" to the dialog box, then click "OK". +1. Power on the VM and watch the console. +1. Power off the VM immediately after the first reboot. (If you miss this and power it off after it is fully up, delete the VM and repeat this process.) +1. The VM is now ready to use as a template for use with terraform. ### Using terraform to deploy SD-WAN components Change to the vmware directory. @@ -116,7 +119,7 @@ cedge_device_list = { > Note: the `*_template`, `datacenter`, `cluster`, `datastore` and `iso_datastore` values should be set to the names of the respective objects in vCenter. -> Note: `ipv4_address` is applied to VPN 0 must be set to either "dhcp" or a static IP address in address/prefix-length notation (i.e. 192.168.0.2/24). When specifying a static IP address, `ipv4_gateway` is also required. +> Note: `ipv4_address` is applied to VPN 0 must be set to either "dhcp" or a static IP address. Use address/prefix-length notation (i.e. 192.168.0.2/24) for Viptela components and address/netmask notation (i.e. 192.168.0.2 255.255.255.0) for CSR1000v. When specifying a static IP address, `ipv4_gateway` is also required. > Note: `folder` is the VM folder to place all VMs. It is optional. If it is not specified then all VMs will be placed at the root of the datacenter. diff --git a/vmware/cedge_vmware/create_iso.tf b/vmware/cedge_vmware/create_iso.tf new file mode 100644 index 0000000..5050e26 --- /dev/null +++ b/vmware/cedge_vmware/create_iso.tf @@ -0,0 +1,54 @@ +resource "template_dir" "cloudinit" { + for_each = var.device_list + source_dir = var.cloudinit_path + destination_dir = "${path.cwd}/ISO/${each.key}" + + vars = { + ipv4_address = lookup(each.value, "ipv4_address", "dhcp") + ipv4_gateway = lookup(each.value, "ipv4_gateway", "") + otp = lookup(each.value, "otp", "") + vbond = lookup(each.value, "vbond", "") + uuid = lookup(each.value, "uuid", "") + org = lookup(each.value, "org", "") + } +} + +resource "null_resource" "iso" { + for_each = var.device_list + + triggers = { + cloudinit = fileexists("${var.cloudinit_path}/ciscosdwan_cloud_init.cfg") ? filemd5("${var.cloudinit_path}/ciscosdwan_cloud_init.cfg") : "" + address = md5(each.value.ipv4_address) + data_dir = "${path.cwd}/ISO/${each.key}" + iso_file = "${path.cwd}/ISO/${each.key}.iso" + } + + provisioner "local-exec" { + command = "mkisofs -output ${self.triggers.iso_file} -volid cidata -joliet -rock ${self.triggers.data_dir}/ciscosdwan_cloud_init.cfg" + } + + # Requires terraform 0.12.23+ for issue #24139 fix (for_each destroy provisioner in module) + provisioner "local-exec" { + when = destroy + command = "rm ${self.triggers.iso_file}" + on_failure = continue + } + + depends_on = [ + template_dir.cloudinit + ] +} + +resource "vsphere_file" "iso" { + for_each = var.device_list + + datacenter = var.datacenter + datastore = var.iso_datastore + source_file = "${path.cwd}/ISO/${each.key}.iso" + destination_file = "${var.iso_path}/${var.folder}/${each.key}.iso" + + depends_on = [ + null_resource.iso, + template_dir.cloudinit + ] +} \ No newline at end of file diff --git a/vmware/cedge_vmware/main.tf b/vmware/cedge_vmware/main.tf index 4464b42..9586ba5 100644 --- a/vmware/cedge_vmware/main.tf +++ b/vmware/cedge_vmware/main.tf @@ -33,6 +33,11 @@ data "vsphere_datastore" "datastore" { datacenter_id = data.vsphere_datacenter.dc.id } +data "vsphere_datastore" "iso_datastore" { + name = var.iso_datastore + datacenter_id = data.vsphere_datacenter.dc.id +} + data "vsphere_network" "network" { for_each = { for network in local.networks : "${network.device_key}.${network.network_key}" => network @@ -66,7 +71,8 @@ resource "vsphere_virtual_machine" "vm" { wait_for_guest_net_routable = false cdrom { - client_device = true + datastore_id = data.vsphere_datastore.iso_datastore.id + path = "${var.iso_path}/${var.folder}/${each.key}.iso" } disk { @@ -101,27 +107,9 @@ resource "vsphere_virtual_machine" "vm" { template_uuid = data.vsphere_virtual_machine.template[0].id } - vapp { - properties = { - # "config-version" = "1.0" - # "domain-name" = "" - "enable-scp-server" = "True" - "enable-ssh-server" = "True" - "hostname" = each.key - # "license" = "ax" - "login-username" = "admin" - # "login-password" = "admin" - # "mgmt-interface" = "GigabitEthernet1" - "mgmt-ipv4-addr" = lookup(each.value, "ipv4_address", "dhcp") - "mgmt-ipv4-gateway" = lookup(each.value, "ipv4_gateway", "dhcp") - # "mgmt-ipv4-network" ="" - "mgmt-vlan" = "1" - # "pnsc-agent-local-port" = "" - # "pnsc-ipv4-addr" = "" - # "pnsc-shared-secret-key" = "" - # "privilege-password" = "" - # "remote-mgmt-ipv4-addr" = "" - # "resource-template" = "default" - } - } + depends_on = [ + vsphere_file.iso, + null_resource.iso, + template_dir.cloudinit + ] } diff --git a/vmware/cedge_vmware/variables.tf b/vmware/cedge_vmware/variables.tf index b449612..1d8eccb 100644 --- a/vmware/cedge_vmware/variables.tf +++ b/vmware/cedge_vmware/variables.tf @@ -10,6 +10,12 @@ variable "datastore" { variable "folder" { type = string } +variable "iso_datastore" { + type = string +} +variable "iso_path" { + type = string +} variable "resource_pool" { type = string } @@ -31,3 +37,6 @@ variable "vm_thin_provisioned" { variable "device_list" { type = any } +variable "cloudinit_path" { + type = string +} diff --git a/vmware/cloud-init/cedge/ciscosdwan_cloud_init.cfg b/vmware/cloud-init/cedge/ciscosdwan_cloud_init.cfg new file mode 100644 index 0000000..bc249f7 --- /dev/null +++ b/vmware/cloud-init/cedge/ciscosdwan_cloud_init.cfg @@ -0,0 +1,48 @@ +Content-Type: multipart/mixed; boundary="===============3067523750048488884==" +MIME-Version: 1.0 + +--===============3067523750048488884== +Content-Type: text/cloud-config; charset="us-ascii" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Content-Disposition: attachment; filename="cloud-config" + +#cloud-config +vinitparam: + %{ if otp != ""}- otp : ${otp}%{ else }- otp : none%{ endif } + %{ if vbond != ""}- vbond : ${vbond}%{ else }- vbond : 1.1.1.1%{ endif } + %{ if uuid != ""}- uuid : ${uuid}%{ else }- uuid : none%{ endif } + %{ if org != ""}- org : ${org}%{ else }- org : none%{ endif } + +--===============3067523750048488884== +Content-Type: text/cloud-boothook; charset="us-ascii" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Content-Disposition: attachment; filename="config-CSR-725caea2-41a4-497c-821d-a2e280be40a0.txt" + +#cloud-boothook + +hostname +logging persistent immediate filesize 8192 size 1000000 +aaa authentication login default local +aaa authorization exec default local none +interface GigabitEthernet1 + %{ if ipv4_address != "dhcp" }ip address ${ipv4_address}%{ else }ip address dhcp%{ endif } + no shutdown +exit +%{ if ipv4_gateway != ""}ip route 0.0.0.0 0.0.0.0 ${ipv4_gateway}%{ else }!%{ endif } +username admin privilege 15 secret 0 admin +service password-encryption +crypto key generate rsa label ssh-key modulus 2048 +ip ssh version 2 +ip ssh rsa keypair-name ssh-key +ip tcp window-size 8192 +ip ssh window-size 8192 +line vty 0 20 + transport input ssh +exit +ip domain +ip scp server enable +line bty 0 4 + login local + transport input ssh diff --git a/vmware/main.tf b/vmware/main.tf index b646d66..38c1493 100644 --- a/vmware/main.tf +++ b/vmware/main.tf @@ -103,9 +103,12 @@ module "provision_cedge_vmware" { datastore = var.datastore resource_pool = var.resource_pool folder = var.folder == "" ? "" : "${vsphere_folder.folder[0].path}" + iso_datastore = var.iso_datastore + iso_path = var.iso_path template = var.cedge_template vm_num_cpus = 1 vm_memory = 4096 vm_add_disks = [] vm_thin_provisioned = true + cloudinit_path = "${path.root}/cloud-init/cedge/" } \ No newline at end of file diff --git a/vmware/viptela_vmware/create_iso.tf b/vmware/viptela_vmware/create_iso.tf index 3433f31..4633048 100644 --- a/vmware/viptela_vmware/create_iso.tf +++ b/vmware/viptela_vmware/create_iso.tf @@ -41,7 +41,7 @@ resource "vsphere_file" "iso" { datacenter = var.datacenter datastore = var.iso_datastore source_file = "${path.cwd}/ISO/${each.key}.iso" - destination_file = "${var.iso_path}/${each.key}.iso" + destination_file = "${var.iso_path}/${var.folder}/${each.key}.iso" depends_on = [ null_resource.iso, diff --git a/vmware/viptela_vmware/main.tf b/vmware/viptela_vmware/main.tf index 06ed284..c6904d4 100644 --- a/vmware/viptela_vmware/main.tf +++ b/vmware/viptela_vmware/main.tf @@ -92,7 +92,7 @@ resource "vsphere_virtual_machine" "vm" { cdrom { datastore_id = data.vsphere_datastore.iso_datastore.id - path = "${var.iso_path}/${each.key}.iso" + path = "${var.iso_path}/${var.folder}/${each.key}.iso" } dynamic "network_interface" { From 0a2d6588ed85efb338317323f6291b0efc17ea4c Mon Sep 17 00:00:00 2001 From: jasonking3 Date: Fri, 8 May 2020 15:45:57 -0700 Subject: [PATCH 3/4] Updated for day0 config --- vmware/cedge_vmware/create_iso.tf | 1 + vmware/cloud-init/cedge/ciscosdwan_cloud_init.cfg | 12 +++++++----- vmware/cloud-init/vedge/user-data | 4 +++- vmware/viptela_vmware/create_iso.tf | 2 +- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/vmware/cedge_vmware/create_iso.tf b/vmware/cedge_vmware/create_iso.tf index 5050e26..c0660e5 100644 --- a/vmware/cedge_vmware/create_iso.tf +++ b/vmware/cedge_vmware/create_iso.tf @@ -6,6 +6,7 @@ resource "template_dir" "cloudinit" { vars = { ipv4_address = lookup(each.value, "ipv4_address", "dhcp") ipv4_gateway = lookup(each.value, "ipv4_gateway", "") + day0 = lookup(each.value, "day0", "") otp = lookup(each.value, "otp", "") vbond = lookup(each.value, "vbond", "") uuid = lookup(each.value, "uuid", "") diff --git a/vmware/cloud-init/cedge/ciscosdwan_cloud_init.cfg b/vmware/cloud-init/cedge/ciscosdwan_cloud_init.cfg index bc249f7..20dcdc9 100644 --- a/vmware/cloud-init/cedge/ciscosdwan_cloud_init.cfg +++ b/vmware/cloud-init/cedge/ciscosdwan_cloud_init.cfg @@ -1,3 +1,4 @@ +%{ if day0 != "" }${day0}%{ else } Content-Type: multipart/mixed; boundary="===============3067523750048488884==" MIME-Version: 1.0 @@ -9,10 +10,10 @@ Content-Disposition: attachment; filename="cloud-config" #cloud-config vinitparam: - %{ if otp != ""}- otp : ${otp}%{ else }- otp : none%{ endif } - %{ if vbond != ""}- vbond : ${vbond}%{ else }- vbond : 1.1.1.1%{ endif } - %{ if uuid != ""}- uuid : ${uuid}%{ else }- uuid : none%{ endif } - %{ if org != ""}- org : ${org}%{ else }- org : none%{ endif } + %{ if otp != "" }- otp : ${otp}%{ else }- otp : none%{ endif } + %{ if vbond != "" }- vbond : ${vbond}%{ else }- vbond : 1.1.1.1%{ endif } + %{ if uuid != "" }- uuid : ${uuid}%{ else }- uuid : none%{ endif } + %{ if org != "" }- org : ${org}%{ else }- org : none%{ endif } --===============3067523750048488884== Content-Type: text/cloud-boothook; charset="us-ascii" @@ -30,7 +31,7 @@ interface GigabitEthernet1 %{ if ipv4_address != "dhcp" }ip address ${ipv4_address}%{ else }ip address dhcp%{ endif } no shutdown exit -%{ if ipv4_gateway != ""}ip route 0.0.0.0 0.0.0.0 ${ipv4_gateway}%{ else }!%{ endif } +%{ if ipv4_gateway != "" }ip route 0.0.0.0 0.0.0.0 ${ipv4_gateway}%{ else }!%{ endif } username admin privilege 15 secret 0 admin service password-encryption crypto key generate rsa label ssh-key modulus 2048 @@ -46,3 +47,4 @@ ip scp server enable line bty 0 4 login local transport input ssh +%{ endif } \ No newline at end of file diff --git a/vmware/cloud-init/vedge/user-data b/vmware/cloud-init/vedge/user-data index b911d1b..a0983cd 100644 --- a/vmware/cloud-init/vedge/user-data +++ b/vmware/cloud-init/vedge/user-data @@ -1,3 +1,4 @@ +%{ if day0 != "" }${day0}%{ else } Content-Type: multipart/mixed; boundary="==BOUNDARY==" MIME-Version: 1.0 @@ -35,4 +36,5 @@ vpn 512 shutdown ! ! ---==BOUNDARY== \ No newline at end of file +--==BOUNDARY== +%{ endif } \ No newline at end of file diff --git a/vmware/viptela_vmware/create_iso.tf b/vmware/viptela_vmware/create_iso.tf index 4633048..d26244b 100644 --- a/vmware/viptela_vmware/create_iso.tf +++ b/vmware/viptela_vmware/create_iso.tf @@ -6,6 +6,7 @@ resource "template_dir" "cloudinit" { vars = { ipv4_address = lookup(each.value, "ipv4_address", "dhcp") ipv4_gateway = lookup(each.value, "ipv4_gateway", "") + day0 = lookup(each.value, "day0", "") } } @@ -14,7 +15,6 @@ resource "null_resource" "iso" { triggers = { cloudinit = fileexists("${var.cloudinit_path}/user-data") ? filemd5("${var.cloudinit_path}/user-data") : "" - address = md5(each.value.ipv4_address) data_dir = "${path.cwd}/ISO/${each.key}" iso_file = "${path.cwd}/ISO/${each.key}.iso" } From bebd3c8fdf40fffaf02ad89cb9e64d2c5fa1870e Mon Sep 17 00:00:00 2001 From: jasonking3 Date: Fri, 8 May 2020 15:47:50 -0700 Subject: [PATCH 4/4] Made ipv4_address optional --- vmware/cedge_vmware/create_iso.tf | 1 - 1 file changed, 1 deletion(-) diff --git a/vmware/cedge_vmware/create_iso.tf b/vmware/cedge_vmware/create_iso.tf index c0660e5..d09a9a5 100644 --- a/vmware/cedge_vmware/create_iso.tf +++ b/vmware/cedge_vmware/create_iso.tf @@ -19,7 +19,6 @@ resource "null_resource" "iso" { triggers = { cloudinit = fileexists("${var.cloudinit_path}/ciscosdwan_cloud_init.cfg") ? filemd5("${var.cloudinit_path}/ciscosdwan_cloud_init.cfg") : "" - address = md5(each.value.ipv4_address) data_dir = "${path.cwd}/ISO/${each.key}" iso_file = "${path.cwd}/ISO/${each.key}.iso" }