diff --git a/data/data/vsphere/bootstrap/main.tf b/data/data/vsphere/bootstrap/main.tf index 8e65cd69c61..d7318a2e7c6 100644 --- a/data/data/vsphere/bootstrap/main.tf +++ b/data/data/vsphere/bootstrap/main.tf @@ -1,5 +1,7 @@ locals { description = "Created By OpenShift Installer" + bootstrap_key = keys(var.vcenter_region_zone_map)[0] + region = var.vcenter_region_zone_map[local.bootstrap_key].region } provider "vsphere" { @@ -11,12 +13,14 @@ provider "vsphere" { resource "vsphere_virtual_machine" "vm_bootstrap" { name = "${var.cluster_id}-bootstrap" - resource_pool_id = var.resource_pool - datastore_id = var.datastore + resource_pool_id = var.cluster[local.bootstrap_key].resource_pool_id + datastore_id = var.datastore[local.bootstrap_key].id num_cpus = 4 memory = 16384 - guest_id = var.guest_id - folder = var.folder + guest_id = var.template[local.bootstrap_key].guest_id + + + folder = var.folder[local.bootstrap_key].path enable_disk_uuid = "true" annotation = local.description @@ -24,18 +28,18 @@ resource "vsphere_virtual_machine" "vm_bootstrap" { wait_for_guest_net_routable = false network_interface { - network_id = var.network + network_id = var.template[local.bootstrap_key].network_interfaces.0.network_id } disk { label = "disk0" size = 120 - eagerly_scrub = var.scrub_disk - thin_provisioned = var.thin_disk + eagerly_scrub = var.template[local.bootstrap_key].disks.0.eagerly_scrub + thin_provisioned = var.template[local.bootstrap_key].disks.0.thin_provisioned } clone { - template_uuid = var.template + template_uuid = var.template[local.bootstrap_key].id } extra_config = { diff --git a/data/data/vsphere/bootstrap/variables.tf b/data/data/vsphere/bootstrap/variables.tf index 66d839037d3..f85df4b0890 100644 --- a/data/data/vsphere/bootstrap/variables.tf +++ b/data/data/vsphere/bootstrap/variables.tf @@ -1,39 +1,39 @@ -variable "resource_pool" { - type = string +variable "datacenter" { + type = map } -variable "folder" { - type = string +variable "datastore" { + type = map } -variable "datastore" { - type = string +variable "cluster" { + type = map } -variable "network" { - type = string +variable "folder" { + type = map } -variable "datacenter" { - type = string +variable "ovaimport" { + type = map } variable "template" { - type = string + type = map } -variable "guest_id" { - type = string +variable "tags" { + type = list } -variable "tags" { - type = list +variable "cluster_domain" { + type = string } -variable "thin_disk" { - type = bool +variable "cluster_id" { +type = string } -variable "scrub_disk" { - type = bool +variable "vcenter_region_zone_map" { + type = map } diff --git a/data/data/vsphere/master/main.tf b/data/data/vsphere/master/main.tf index 6f56449be8c..a71df094fb8 100644 --- a/data/data/vsphere/master/main.tf +++ b/data/data/vsphere/master/main.tf @@ -1,5 +1,7 @@ locals { description = "Created By OpenShift Installer" + zone_keys = keys(var.vcenter_region_zone_map) + } provider "vsphere" { @@ -9,17 +11,25 @@ provider "vsphere" { allow_unverified_ssl = false } + resource "vsphere_virtual_machine" "vm_master" { count = var.master_count name = "${var.cluster_id}-master-${count.index}" - resource_pool_id = var.resource_pool - datastore_id = var.datastore + + // TODO: This needs to be changed to a correct existing resource pool + // TODO: as defined + resource_pool_id = var.cluster[local.zone_keys[count.index]].resource_pool_id + datastore_id = var.datastore[local.zone_keys[count.index]].id + num_cpus = var.vsphere_control_plane_num_cpus num_cores_per_socket = var.vsphere_control_plane_cores_per_socket memory = var.vsphere_control_plane_memory_mib - guest_id = var.guest_id - folder = var.folder + + guest_id = var.template[local.zone_keys[count.index]].guest_id + + + folder = var.folder[local.zone_keys[count.index]].path enable_disk_uuid = "true" annotation = local.description @@ -27,18 +37,21 @@ resource "vsphere_virtual_machine" "vm_master" { wait_for_guest_net_routable = "false" network_interface { - network_id = var.network + +// TODO: don't do this...Use Robert's fix +// TODO: unless we cheat ;-) + network_id = var.template[local.zone_keys[count.index]].network_interfaces.0.network_id } disk { label = "disk0" size = var.vsphere_control_plane_disk_gib - eagerly_scrub = var.scrub_disk - thin_provisioned = var.thin_disk + eagerly_scrub = var.template[local.zone_keys[count.index]].disks.0.eagerly_scrub + thin_provisioned = var.template[local.zone_keys[count.index]].disks.0.thin_provisioned } clone { - template_uuid = var.template + template_uuid = var.template[local.zone_keys[count.index]].uuid } extra_config = { diff --git a/data/data/vsphere/master/variables.tf b/data/data/vsphere/master/variables.tf index 66d839037d3..a397866f2c9 100644 --- a/data/data/vsphere/master/variables.tf +++ b/data/data/vsphere/master/variables.tf @@ -1,39 +1,31 @@ -variable "resource_pool" { - type = string -} - -variable "folder" { - type = string +variable "datacenter" { + type = map } variable "datastore" { - type = string + type = map } -variable "network" { - type = string +variable "cluster" { + type = map } -variable "datacenter" { - type = string +variable "folder" { + type = map } -variable "template" { - type = string +variable "ovaimport" { + type = map } -variable "guest_id" { - type = string +variable "template" { + type = map } variable "tags" { type = list } -variable "thin_disk" { - type = bool -} - -variable "scrub_disk" { - type = bool +variable "vcenter_region_zone_map" { + type = map } diff --git a/data/data/vsphere/pre-bootstrap/main.tf b/data/data/vsphere/pre-bootstrap/main.tf index 6d387a8d4f1..1433ecbb3e1 100644 --- a/data/data/vsphere/pre-bootstrap/main.tf +++ b/data/data/vsphere/pre-bootstrap/main.tf @@ -1,6 +1,41 @@ locals { - folder = var.vsphere_preexisting_folder ? var.vsphere_folder : vsphere_folder.folder[0].path - description = "Created By OpenShift Installer" + vcenter_region_zone_flatten = flatten([ + for v in var.vsphere_vcenters : [ + for r in v.regions : [ + for z in r.zones : { + region = r.name + zone = z.name + datacenter = r.datacenter + cluster = z.cluster + datastore = z.datastore + network = z.network + vsphere_server = v.server + user = v.user + password = v.password + } + ] + ] + ]) + + vcenter_region_zone_map = { + for obj in local.vcenter_region_zone_flatten : "${obj.vsphere_server}-${obj.region}-${obj.zone}" => obj + } + + vcenter_region_flatten = flatten([ + for v in var.vsphere_vcenters : [ + for r in v.regions : { + region = r.name + datacenter = r.datacenter + vsphere_server = v.server + user = v.user + password = v.password + } + ] + ]) + + vcenter_region_map = { + for obj in local.vcenter_region_flatten : "${obj.vsphere_server}-${obj.region}" => obj + } } provider "vsphere" { @@ -9,7 +44,6 @@ provider "vsphere" { vsphere_server = var.vsphere_url allow_unverified_ssl = false } - provider "vsphereprivate" { user = var.vsphere_username password = var.vsphere_password @@ -17,45 +51,92 @@ provider "vsphereprivate" { allow_unverified_ssl = false } -data "vsphere_datacenter" "datacenter" { - name = var.vsphere_datacenter +data "vsphere_datacenter" "datacenter_zoning" { + for_each = local.vcenter_region_map + name = each.value.datacenter } -data "vsphere_compute_cluster" "cluster" { - name = var.vsphere_cluster - datacenter_id = data.vsphere_datacenter.datacenter.id +data "vsphere_compute_cluster" "cluster_zoning" { + for_each = local.vcenter_region_zone_map + name = each.value.cluster + datacenter_id = data.vsphere_datacenter.datacenter_zoning["${each.value.vsphere_server}-${each.value.region}"].id } -data "vsphere_resource_pool" "resource_pool" { - name = var.vsphere_resource_pool +data "vsphere_datastore" "datastore_zoning" { + for_each = local.vcenter_region_zone_map + name = each.value.datastore + datacenter_id = data.vsphere_datacenter.datacenter_zoning["${each.value.vsphere_server}-${each.value.region}"].id } -data "vsphere_datastore" "datastore" { - name = var.vsphere_datastore - datacenter_id = data.vsphere_datacenter.datacenter.id +data "vsphere_virtual_machine" "template" { + for_each = local.vcenter_region_zone_map + name = vsphereprivate_import_ova.import[each.key].name + datacenter_id = data.vsphere_datacenter.datacenter_zoning["${each.value.vsphere_server}-${each.value.region}"].id } -data "vsphere_network" "network" { - name = var.vsphere_network - datacenter_id = data.vsphere_datacenter.datacenter.id +resource "vsphereprivate_import_ova" "import" { + for_each = local.vcenter_region_zone_map + + name = "${var.vsphere_template}-${each.value.zone}" + filename = var.vsphere_ova_filepath + cluster = each.value.cluster + datacenter = each.value.datacenter + datastore = each.value.datastore + network = each.value.network + folder = local.folders[each.value.region] + tag = vsphere_tag.tag.id } -data "vsphere_virtual_machine" "template" { - name = vsphereprivate_import_ova.import.name - datacenter_id = data.vsphere_datacenter.datacenter.id +resource "vsphere_tag_category" "region_tag_category" { + name = "openshift-region" + description = "Added by openshift-install do not remove" + cardinality = "SINGLE" + + associable_types = [ + "Datacenter" + ] } -resource "vsphereprivate_import_ova" "import" { - name = var.vsphere_template - filename = var.vsphere_ova_filepath - cluster = var.vsphere_cluster - resource_pool = var.vsphere_resource_pool - datacenter = var.vsphere_datacenter - datastore = var.vsphere_datastore - network = var.vsphere_network - folder = local.folder - tag = vsphere_tag.tag.id - disk_type = var.vsphere_disk_type +resource "vsphere_tag_category" "zone_tag_category" { + name = "openshift-zone" + description = "Added by openshift-install do not remove" + cardinality = "SINGLE" + + associable_types = [ + "ClusterComputeResource" + ] +} + +resource "vsphere_tag" "regions_tags" { + for_each = local.vcenter_region_map + name = each.key.region + category_id = vsphere_tag_category.region_tag_category.id + description = "Added by openshift-install do not remove" +} + +resource "vsphereprivate_tag_attach" "regions_datacenters" { + for_each = local.vcenter_region_map + + objectid = data.vsphere_datacenter.datacenter_zoning[each.key].id + objecttype = "Datacenter" + + tagid = vsphere_tag.regions_tags[each.key].id +} + +resource "vsphere_tag" "zones_tags" { + for_each = local.vcenter_region_zone_map + name = each.value.zone + category_id = vsphere_tag_category.zone_tag_category.id + description = "Added by openshift-install do not remove" +} + +resource "vsphereprivate_tag_attach" "zones_clusters" { + for_each = local.vcenter_region_zone_map + + objectid = data.vsphere_compute_cluster.cluster_zoning[each.key].id + objecttype = "ClusterComputeResource" + + tagid = vsphere_tag.zones_tags[each.key].id } resource "vsphere_tag_category" "category" { @@ -78,11 +159,19 @@ resource "vsphere_tag" "tag" { description = "Added by openshift-install do not remove" } -resource "vsphere_folder" "folder" { - count = var.vsphere_preexisting_folder ? 0 : 1 +resource "vsphere_folder" "vm_folders" { + for_each = local.vcenter_region_map - path = var.vsphere_folder + path = "${var.vsphere_folder}-${each.value.region}" type = "vm" - datacenter_id = data.vsphere_datacenter.datacenter.id + datacenter_id = data.vsphere_datacenter.datacenter_zoning[each.key].id tags = [vsphere_tag.tag.id] } + +data "vsphere_folder" "folder" { + for_each = local.vcenter_region_zone_map + path = "${each.value.datacenter}/vm/${var.vsphere_folder}-${each.value.region}" +} + + + diff --git a/data/data/vsphere/pre-bootstrap/outputs.tf b/data/data/vsphere/pre-bootstrap/outputs.tf index 12fd8e95f7a..f83ef49110f 100644 --- a/data/data/vsphere/pre-bootstrap/outputs.tf +++ b/data/data/vsphere/pre-bootstrap/outputs.tf @@ -1,37 +1,29 @@ -output "resource_pool" { - value = data.vsphere_resource_pool.resource_pool.id +output "datacenter" { + value = data.vsphere_datacenter.datacenter_zoning } output "datastore" { - value = data.vsphere_datastore.datastore.id + value = data.vsphere_datastore.datastore_zoning } -output "folder" { - value = local.folder +output "cluster" { + value = data.vsphere_compute_cluster.cluster_zoning } -output "network" { - value = data.vsphere_network.network.id +output "folder" { + value = data.vsphere_folder.folder } -output "datacenter" { - value = data.vsphere_datacenter.datacenter.id +output "ovaimport" { + value = vsphereprivate_import_ova.import } output "template" { - value = data.vsphere_virtual_machine.template.id -} - -output "guest_id" { - value = data.vsphere_virtual_machine.template.guest_id + value = data.vsphere_virtual_machine.template } -output "thin_disk" { - value = data.vsphere_virtual_machine.template.disks.0.thin_provisioned -} - -output "scrub_disk" { - value = data.vsphere_virtual_machine.template.disks.0.eagerly_scrub +output "tags" { + value = [vsphere_tag.tag.id] } output "cluster_domain" { @@ -42,6 +34,6 @@ output "cluster_id" { value = var.cluster_id } -output "tags" { - value = [vsphere_tag.tag.id] +output "vcenter_region_zone_map" { + value = local.vcenter_region_zone_map } diff --git a/data/data/vsphere/variables-vsphere.tf b/data/data/vsphere/variables-vsphere.tf index 0b760995a4d..77c4314b94b 100644 --- a/data/data/vsphere/variables-vsphere.tf +++ b/data/data/vsphere/variables-vsphere.tf @@ -85,3 +85,8 @@ variable "vsphere_disk_type" { type = string default = "thick" } + +variable "vsphere_vcenters" { + type = list + default = [] +} diff --git a/pkg/asset/cluster/tfvars.go b/pkg/asset/cluster/tfvars.go index d3da40c3898..6dba0f93abc 100644 --- a/pkg/asset/cluster/tfvars.go +++ b/pkg/asset/cluster/tfvars.go @@ -672,6 +672,16 @@ func (t *TerraformVariables) Generate(parents asset.Parents) error { // Set this flag to use an existing folder specified in the install-config. Otherwise, create one. preexistingFolder := installConfig.Config.Platform.VSphere.Folder != "" + /* TODO: + * controlplaneconfigs will be resolved with machine change + * Will needs regions and zones in TFVarsSources + * + * if VCenters is defined use the server, username, password from there + * ignore platform.VCenter + + + */ + data, err = vspheretfvars.TFVars( vspheretfvars.TFVarsSources{ ControlPlaneConfigs: controlPlaneConfigs, @@ -681,6 +691,7 @@ func (t *TerraformVariables) Generate(parents asset.Parents) error { ImageURL: string(*rhcosImage), PreexistingFolder: preexistingFolder, DiskType: installConfig.Config.Platform.VSphere.DiskType, + InstallConfig: installConfig, }, ) if err != nil { diff --git a/pkg/tfvars/vsphere/vsphere.go b/pkg/tfvars/vsphere/vsphere.go index 5deaf217813..30512e7f9eb 100644 --- a/pkg/tfvars/vsphere/vsphere.go +++ b/pkg/tfvars/vsphere/vsphere.go @@ -2,6 +2,7 @@ package vsphere import ( "encoding/json" + "github.com/openshift/installer/pkg/asset/installconfig" "strings" "github.com/pkg/errors" @@ -9,6 +10,7 @@ import ( machineapi "github.com/openshift/api/machine/v1beta1" "github.com/openshift/installer/pkg/tfvars/internal/cache" "github.com/openshift/installer/pkg/types/vsphere" + vspheretypes "github.com/openshift/installer/pkg/types/vsphere" ) type config struct { @@ -29,6 +31,8 @@ type config struct { OvaFilePath string `json:"vsphere_ova_filepath"` PreexistingFolder bool `json:"vsphere_preexisting_folder"` DiskType vsphere.DiskType `json:"vsphere_disk_type"` + + VCenters *[]vspheretypes.VCenter `json:"vsphere_vcenters"` } // TFVarsSources contains the parameters to be converted into Terraform variables @@ -40,11 +44,16 @@ type TFVarsSources struct { ImageURL string PreexistingFolder bool DiskType vsphere.DiskType + InstallConfig *installconfig.InstallConfig } //TFVars generate vSphere-specific Terraform variables func TFVars(sources TFVarsSources) ([]byte, error) { - controlPlaneConfig := sources.ControlPlaneConfigs[0] + + platform := sources.InstallConfig.Config.VSphere + + // TODO: This needs to be the slice + controlPlaneConfig := sources.ControlPlaneConfigs cachedImage, err := cache.DownloadImageFile(sources.ImageURL) if err != nil { @@ -54,26 +63,30 @@ func TFVars(sources TFVarsSources) ([]byte, error) { // The vSphere provider needs the relativepath of the folder, // so get the relPath from the absolute path. Absolute path is always of the form // //vm/ so we can split on "vm/". - folderRelPath := strings.SplitAfterN(controlPlaneConfig.Workspace.Folder, "vm/", 2)[1] + folderRelPath := strings.SplitAfterN(controlPlaneConfig[0].Workspace.Folder, "vm/", 2)[1] + // TODO: do not break existing install cfg := &config{ - VSphereURL: controlPlaneConfig.Workspace.Server, + VSphereURL: controlPlaneConfig[0].Workspace.Server, VSphereUsername: sources.Username, VSpherePassword: sources.Password, - MemoryMiB: controlPlaneConfig.MemoryMiB, - DiskGiB: controlPlaneConfig.DiskGiB, - NumCPUs: controlPlaneConfig.NumCPUs, - NumCoresPerSocket: controlPlaneConfig.NumCoresPerSocket, + MemoryMiB: controlPlaneConfig[0].MemoryMiB, + DiskGiB: controlPlaneConfig[0].DiskGiB, + NumCPUs: controlPlaneConfig[0].NumCPUs, + NumCoresPerSocket: controlPlaneConfig[0].NumCoresPerSocket, Cluster: sources.Cluster, - ResourcePool: controlPlaneConfig.Workspace.ResourcePool, - Datacenter: controlPlaneConfig.Workspace.Datacenter, - Datastore: controlPlaneConfig.Workspace.Datastore, + ResourcePool: controlPlaneConfig[0].Workspace.ResourcePool, + Datacenter: controlPlaneConfig[0].Workspace.Datacenter, + Datastore: controlPlaneConfig[0].Workspace.Datastore, Folder: folderRelPath, - Network: controlPlaneConfig.Network.Devices[0].NetworkName, - Template: controlPlaneConfig.Template, + Network: controlPlaneConfig[0].Network.Devices[0].NetworkName, + + // TODO: change me... + Template: controlPlaneConfig[0].Template, OvaFilePath: cachedImage, PreexistingFolder: sources.PreexistingFolder, DiskType: sources.DiskType, + VCenters: &platform.VCenters, } return json.MarshalIndent(cfg, "", " ")