diff --git a/modules/compute-vm/README.md b/modules/compute-vm/README.md
index 97e653b6e..393400091 100644
--- a/modules/compute-vm/README.md
+++ b/modules/compute-vm/README.md
@@ -31,6 +31,7 @@ In both modes, an optional service account can be created and assigned to either
- [Spot VM](#spot-vm)
- [Confidential compute](#confidential-compute)
- [Disk encryption with Cloud KMS](#disk-encryption-with-cloud-kms)
+ - [Advanced machine features](#advanced-machine-features)
- [Instance template](#instance-template)
- [Instance group](#instance-group)
- [Instance Schedule](#instance-schedule)
@@ -614,6 +615,31 @@ module "kms-vm-example" {
# tftest inventory=cmek.yaml e2e
```
+### Advanced machine features
+
+Advanced machine features can be configured via the `options.advanced_machine_features` variable.
+
+```hcl
+module "simple-vm-example" {
+ source = "./fabric/modules/compute-vm"
+ project_id = var.project_id
+ zone = "${var.region}-b"
+ name = "test"
+ network_interfaces = [{
+ network = var.vpc.self_link
+ subnetwork = var.subnet.self_link
+ }]
+ options = {
+ advanced_machine_features = {
+ enable_nested_virtualization = true
+ enable_turbo_mode = true
+ threads_per_core = 2
+ }
+ }
+}
+# tftest modules=1 resources=1
+```
+
### Instance template
This example shows how to use the module to manage an instance template that defines an additional attached disk for each instance, and overrides defaults for the boot disk image and service account.
@@ -886,8 +912,8 @@ module "sole-tenancy" {
|---|---|:---:|:---:|:---:|
| [name](variables.tf#L264) | Instance name. | string | ✓ | |
| [network_interfaces](variables.tf#L276) | Network interfaces configuration. Use self links for Shared VPC, set addresses to null if not needed. | list(object({…})) | ✓ | |
-| [project_id](variables.tf#L322) | Project id. | string | ✓ | |
-| [zone](variables.tf#L420) | Compute zone. | string | ✓ | |
+| [project_id](variables.tf#L345) | Project id. | string | ✓ | |
+| [zone](variables.tf#L443) | Compute zone. | string | ✓ | |
| [attached_disk_defaults](variables.tf#L17) | Defaults for attached disks options. | object({…}) | | {…} |
| [attached_disks](variables.tf#L37) | Additional disks, if options is null defaults will be used in its place. Source type is one of 'image' (zonal disks in vms and template), 'snapshot' (vm), 'existing', and null. | list(object({…})) | | [] |
| [boot_disk](variables.tf#L83) | Boot disk properties. | object({…}) | | {…} |
@@ -907,14 +933,14 @@ module "sole-tenancy" {
| [metadata](variables.tf#L252) | Instance metadata. | map(string) | | {} |
| [min_cpu_platform](variables.tf#L258) | Minimum CPU platform. | string | | null |
| [network_attached_interfaces](variables.tf#L269) | Network interfaces using network attachments. | list(string) | | [] |
-| [options](variables.tf#L292) | Instance options. | object({…}) | | {…} |
-| [scratch_disks](variables.tf#L327) | Scratch disks configuration. | object({…}) | | {…} |
-| [service_account](variables.tf#L339) | Service account email and scopes. If email is null, the default Compute service account will be used unless auto_create is true, in which case a service account will be created. Set the variable to null to avoid attaching a service account. | object({…}) | | {} |
-| [shielded_config](variables.tf#L349) | Shielded VM configuration of the instances. | object({…}) | | null |
-| [snapshot_schedules](variables.tf#L359) | Snapshot schedule resource policies that can be attached to disks. | map(object({…})) | | {} |
-| [tag_bindings](variables.tf#L402) | Resource manager tag bindings for this instance, in tag key => tag value format. | map(string) | | null |
-| [tag_bindings_firewall](variables.tf#L408) | Firewall (network scoped) tag bindings for this instance, in tag key => tag value format. | map(string) | | null |
-| [tags](variables.tf#L414) | Instance network tags for firewall rule targets. | list(string) | | [] |
+| [options](variables.tf#L292) | Instance options. | object({…}) | | {…} |
+| [scratch_disks](variables.tf#L350) | Scratch disks configuration. | object({…}) | | {…} |
+| [service_account](variables.tf#L362) | Service account email and scopes. If email is null, the default Compute service account will be used unless auto_create is true, in which case a service account will be created. Set the variable to null to avoid attaching a service account. | object({…}) | | {} |
+| [shielded_config](variables.tf#L372) | Shielded VM configuration of the instances. | object({…}) | | null |
+| [snapshot_schedules](variables.tf#L382) | Snapshot schedule resource policies that can be attached to disks. | map(object({…})) | | {} |
+| [tag_bindings](variables.tf#L425) | Resource manager tag bindings for this instance, in tag key => tag value format. | map(string) | | null |
+| [tag_bindings_firewall](variables.tf#L431) | Firewall (network scoped) tag bindings for this instance, in tag key => tag value format. | map(string) | | null |
+| [tags](variables.tf#L437) | Instance network tags for firewall rule targets. | list(string) | | [] |
## Outputs
diff --git a/modules/compute-vm/main.tf b/modules/compute-vm/main.tf
index 1a1c97e2b..bf215af06 100644
--- a/modules/compute-vm/main.tf
+++ b/modules/compute-vm/main.tf
@@ -15,6 +15,7 @@
*/
locals {
+ advanced_mf = var.options.advanced_machine_features
attached_disks = {
for disk in var.attached_disks :
(disk.name != null ? disk.name : disk.device_name) => merge(disk, {
@@ -165,6 +166,20 @@ resource "google_compute_instance" "default" {
metadata = var.metadata
resource_policies = local.ischedule_attach
+ dynamic "advanced_machine_features" {
+ for_each = local.advanced_mf != null ? [""] : []
+ content {
+ enable_nested_virtualization = local.advanced_mf.enable_nested_virtualization
+ enable_uefi_networking = local.advanced_mf.enable_uefi_networking
+ performance_monitoring_unit = local.advanced_mf.performance_monitoring_unit
+ threads_per_core = local.advanced_mf.threads_per_core
+ turbo_mode = (
+ local.advanced_mf.enable_turbo_mode ? "ALL_CORE_MAX" : null
+ )
+ visible_core_count = local.advanced_mf.visible_core_count
+ }
+ }
+
dynamic "attached_disk" {
for_each = local.attached_disks_zonal
iterator = config
@@ -369,6 +384,20 @@ resource "google_compute_instance_template" "default" {
labels = var.labels
resource_manager_tags = local.tags_combined
+ dynamic "advanced_machine_features" {
+ for_each = local.advanced_mf != null ? [""] : []
+ content {
+ enable_nested_virtualization = local.advanced_mf.enable_nested_virtualization
+ enable_uefi_networking = local.advanced_mf.enable_uefi_networking
+ performance_monitoring_unit = local.advanced_mf.performance_monitoring_unit
+ threads_per_core = local.advanced_mf.threads_per_core
+ turbo_mode = (
+ local.advanced_mf.enable_turbo_mode ? "ALL_CORE_MAX" : null
+ )
+ visible_core_count = local.advanced_mf.visible_core_count
+ }
+ }
+
disk {
auto_delete = var.boot_disk.auto_delete
boot = true
diff --git a/modules/compute-vm/variables.tf b/modules/compute-vm/variables.tf
index 8d6e8bc37..6e84daa84 100644
--- a/modules/compute-vm/variables.tf
+++ b/modules/compute-vm/variables.tf
@@ -292,6 +292,14 @@ variable "network_interfaces" {
variable "options" {
description = "Instance options."
type = object({
+ advanced_machine_features = optional(object({
+ enable_nested_virtualization = optional(bool)
+ enable_turbo_mode = optional(bool)
+ enable_uefi_networking = optional(bool)
+ performance_monitoring_unit = optional(string)
+ threads_per_core = optional(number)
+ visible_core_count = optional(number)
+ }))
allow_stopping_for_update = optional(bool, true)
deletion_protection = optional(bool, false)
max_run_duration = optional(object({
@@ -312,11 +320,26 @@ variable "options" {
termination_action = null
}
validation {
- condition = (var.options.termination_action == null
+ condition = (
+ var.options.termination_action == null
||
- contains(["STOP", "DELETE"], coalesce(var.options.termination_action, "1")))
+ contains(["STOP", "DELETE"], coalesce(var.options.termination_action, "1"))
+ )
error_message = "Allowed values for options.termination_action are 'STOP', 'DELETE' and null."
}
+ validation {
+ condition = (
+ try(var.options.advanced_machine_features.performance_monitoring_unit, null) == null
+ ||
+ contains(["ARCHITECTURAL", "ENHANCED", "STANDARD"], coalesce(
+ try(
+ var.options.advanced_machine_features.performance_monitoring_unit, null
+ ), "-"
+ )
+ )
+ )
+ error_message = "Allowed values for options.advanced_machine_features.performance_monitoring_unit are ARCHITECTURAL', 'ENHANCED', 'STANDARD' and null."
+ }
}
variable "project_id" {