diff --git a/vsphere/README.md b/vsphere/README.md new file mode 100644 index 0000000..39a6bd1 --- /dev/null +++ b/vsphere/README.md @@ -0,0 +1,29 @@ +# Lab of vSphere Machines + +Fetch the latest vSphere 7.0 installation iso and customize it for automated install. + +```sh +sudo mount VMware-VMvisor-Installer-7.0U1c-17325551.x86_64.iso /mnt -o loop,ro +sudo mkdir /tmp/vsphere-custom +sudo cp -rv /mnt/* /tmp/vsphere-custom +sudo umount /mnt +sudo sed -i -r 's|^(kernelopt=.*)|\1 ks=https://raw.githubusercontent.com/nmasse-itix/terraform-lab/main/vsphere/itix-ks.cfg|' /tmp/vsphere-custom/boot.cfg +sudo sed -i -r 's|^(kernelopt=.*)|\1 ks=https://raw.githubusercontent.com/nmasse-itix/terraform-lab/main/vsphere/itix-ks.cfg|' /tmp/vsphere-custom/efi/boot/boot.cfg +sudo dnf install genisoimage +sudo genisoimage -relaxed-filenames -J -R -o /tmp/vsphere-custom.iso -b isolinux.bin -c boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table -eltorito-alt-boot -e efiboot.img -no-emul-boot /tmp/vsphere-custom +sudo cp /tmp/vsphere-custom.iso /var/lib/libvirt/images/ +``` + +Then, deploy the lab. + +```sh +terraform init +terraform apply +``` + +## References + +* https://www.grottedubarbu.fr/nested-virtualization-esxi-kvm/ +* https://itsjustbytes.com/2020/12/14/kvm-esxi-7-as-a-nested-cluster/ +* https://fabianlee.org/2018/09/19/kvm-deploying-a-nested-version-of-vmware-esxi-6-7-inside-kvm/ +* http://vnews.fr/construire-un-custom-iso-de-vmware-vsphere-esxi-6/ diff --git a/vsphere/main.tf b/vsphere/main.tf new file mode 100644 index 0000000..fe98b5d --- /dev/null +++ b/vsphere/main.tf @@ -0,0 +1,21 @@ +terraform { + required_version = ">= 0.13" + required_providers { + libvirt = { + source = "dmacvicar/libvirt" + version = ">=0.6.3" + } + local = { + source = "hashicorp/local" + version = ">=2.0.0" + } + template = { + source = "hashicorp/template" + version = ">=2.2.0" + } + } +} + +output "machines" { + value = local.vsphere_machines +} diff --git a/vsphere/network.tf b/vsphere/network.tf new file mode 100644 index 0000000..c587d90 --- /dev/null +++ b/vsphere/network.tf @@ -0,0 +1,13 @@ +resource "libvirt_network" "lab_net" { + name = var.network_name + mode = "nat" + domain = var.network_domain + addresses = [var.network_ip_range] + autostart = true + dns { + enabled = true + } + dhcp { + enabled = true + } +} diff --git a/vsphere/patch.xslt b/vsphere/patch.xslt new file mode 100644 index 0000000..827efe4 --- /dev/null +++ b/vsphere/patch.xslt @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/vsphere/provider.tf b/vsphere/provider.tf new file mode 100644 index 0000000..21b377c --- /dev/null +++ b/vsphere/provider.tf @@ -0,0 +1,3 @@ +provider "libvirt" { + uri = "qemu:///system" +} \ No newline at end of file diff --git a/vsphere/variables.tf b/vsphere/variables.tf new file mode 100644 index 0000000..dda8623 --- /dev/null +++ b/vsphere/variables.tf @@ -0,0 +1,70 @@ +variable "vsphere_machine_count" { + type = number + default = 1 +} + +variable "pool_name" { + type = string + default = "default" +} + +variable "volume_format" { + type = string + default = "qcow2" +} + +variable "os_volume_size" { + type = number + default = 16 * 1024 * 1024 * 1024 +} + +variable "kvm_machine" { + type = string + default = "pc-q35-rhel8.2.0" +} + +variable "vmfs_volume_size" { + type = number + default = 200 * 1024 * 1024 * 1024 +} + +variable "vcpu_count" { + type = number + default = 4 +} + +variable "memory_size" { + type = number + default = 8192 +} + + +variable "vsphere_hostname_format" { + type = string + default = "esx-%02d" +} + +variable "vsphere_iso" { + type = string + default = "/var/lib/libvirt/images/vsphere-custom.iso" +} + +variable "network_name" { + type = string + default = "lab" +} + +variable "network_domain" { + type = string + default = "sample.lab" +} + +variable "bridge_network" { + type = string + default = "bridge" +} + +variable "network_ip_range" { + type = string + default = "10.10.0.0/24" +} diff --git a/vsphere/vsphere.tf b/vsphere/vsphere.tf new file mode 100644 index 0000000..4d876f5 --- /dev/null +++ b/vsphere/vsphere.tf @@ -0,0 +1,67 @@ +resource "libvirt_volume" "vsphere_os_disk" { + name = "${format(var.vsphere_hostname_format, count.index + 1)}-os.${var.volume_format}" + count = var.vsphere_machine_count + format = var.volume_format + pool = var.pool_name + size = var.os_volume_size +} + +resource "libvirt_volume" "vsphere_vmfs_disk" { + name = "${format(var.vsphere_hostname_format, count.index + 1)}-vmfs.${var.volume_format}" + count = var.vsphere_machine_count + format = var.volume_format + pool = var.pool_name + size = var.vmfs_volume_size +} + +resource "libvirt_domain" "vsphere_machine" { + count = var.vsphere_machine_count + name = format(var.vsphere_hostname_format, count.index + 1) + vcpu = var.vcpu_count + memory = var.memory_size + machine = var.kvm_machine + + boot_device { + dev = ["hd", "cdrom"] + } + + disk { + volume_id = element(libvirt_volume.vsphere_os_disk.*.id, count.index) + } + + disk { + volume_id = element(libvirt_volume.vsphere_vmfs_disk.*.id, count.index) + } + + cpu = { + mode = "host-passthrough" + } + + disk { + file = var.vsphere_iso + } + + graphics { + type = "vnc" + listen_type = "address" + } + + video { + type = "qxl" + } + + network_interface { + network_id = libvirt_network.lab_net.id + addresses = [cidrhost(var.network_ip_range, count.index + 11)] + hostname = format(var.vsphere_hostname_format, count.index + 1) + wait_for_lease = true + } + + xml { + xslt = file("patch.xslt") + } +} + +locals { + vsphere_machines = { for i in libvirt_domain.vsphere_machine : i.name => i.network_interface.0.addresses[0] } +}