Copilot commented on code in PR #252:
URL:
https://github.com/apache/cloudstack-terraform-provider/pull/252#discussion_r3557384320
##########
cloudstack/resource_cloudstack_service_offering.go:
##########
@@ -233,141 +585,356 @@ func resourceCloudStackServiceOfferingCreate(d
*schema.ResourceData, meta interf
p.SetServiceofferingdetails(serviceOfferingDetails)
}
Review Comment:
GPU-specific attributes (gpu_card/gpu_type) are not merged into
service_offering_details. As written, gpu_card is never sent to CloudStack, and
gpu_type only sets vgpuprofileid (not vgpuType detail), which contradicts the
resource schema/docs and can prevent GPU offerings from being
created/configured as intended.
##########
cloudstack/resource_cloudstack_service_offering.go:
##########
@@ -50,157 +49,492 @@ func resourceCloudStackServiceOffering() *schema.Resource
{
ForceNew: true,
},
"cpu_speed": {
- Description: "Speed of CPU in Mhz",
+ Description: "Speed of CPU in MHz",
+ Type: schema.TypeInt,
+ Optional: true,
+ ForceNew: true,
+ },
+ "memory": {
+ Description: "Amount of memory in MB",
Type: schema.TypeInt,
Optional: true,
ForceNew: true,
},
"host_tags": {
- Description: "The host tag for this service
offering",
+ Description: "The host tags for this service
offering",
Type: schema.TypeString,
Optional: true,
},
- "limit_cpu_use": {
- Description: "Restrict the CPU usage to
committed service offering",
+ "storage_type": {
+ Description: "The storage type of the service
offering",
+ Type: schema.TypeString,
+ Optional: true,
+ ForceNew: true,
+ Default: "shared",
+ },
Review Comment:
storage_type no longer validates allowed values. This allows invalid values
into plans and defers failures to the CloudStack API.
##########
cloudstack/resource_cloudstack_service_offering.go:
##########
@@ -233,141 +585,356 @@ func resourceCloudStackServiceOfferingCreate(d
*schema.ResourceData, meta interf
p.SetServiceofferingdetails(serviceOfferingDetails)
}
- log.Printf("[DEBUG] Creating Service Offering %s", name)
- s, err := cs.ServiceOffering.CreateServiceOffering(p)
+ if v, ok := d.GetOk("zone_id"); ok {
+ zones := make([]string, 0)
+ for _, z := range v.([]interface{}) {
+ zones = append(zones, z.(string))
+ }
+ p.SetZoneid(zones)
+ }
Review Comment:
domain_id is defined in the schema but never sent in Create. As a result,
configured domain scoping is silently ignored.
##########
cloudstack/data_source_cloudstack_service_offering.go:
##########
@@ -46,6 +46,186 @@ func dataSourceCloudstackServiceOffering() *schema.Resource
{
Type: schema.TypeString,
Computed: true,
},
+ "cpu_number": {
+ Type: schema.TypeInt,
+ Computed: true,
+ },
+ "cpu_speed": {
+ Type: schema.TypeInt,
+ Computed: true,
+ },
+ "memory": {
+ Type: schema.TypeInt,
+ Computed: true,
+ },
+ "created": {
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ "domain_id": {
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ "domain": {
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ "host_tags": {
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ "is_customized": {
+ Type: schema.TypeBool,
+ Computed: true,
+ },
+ "is_system": {
+ Type: schema.TypeBool,
+ Computed: true,
+ },
+ "is_volatile": {
+ Type: schema.TypeBool,
+ Computed: true,
+ },
+ "limit_cpu_use": {
+ Type: schema.TypeBool,
+ Computed: true,
+ },
+ "network_rate": {
+ Type: schema.TypeInt,
+ Computed: true,
+ },
+ "storage_type": {
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ "system_vm_type": {
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ "deployment_planner": {
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ "offer_ha": {
+ Type: schema.TypeBool,
+ Computed: true,
+ },
+ "tags": {
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ "provisioning_type": {
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ "min_iops": {
+ Type: schema.TypeInt,
+ Computed: true,
+ },
+ "max_iops": {
+ Type: schema.TypeInt,
+ Computed: true,
+ },
+ "hypervisor_snapshot_reserve": {
+ Type: schema.TypeInt,
+ Computed: true,
+ },
+ "disk_iops": {
+ Type: schema.TypeInt,
+ Computed: true,
+ },
Review Comment:
The data source schema defines a disk_iops attribute, but
serviceOfferingDescriptionAttributes never sets it. This will always be
unset/zero and is misleading for users.
##########
cloudstack/resource_cloudstack_service_offering.go:
##########
@@ -50,157 +49,492 @@ func resourceCloudStackServiceOffering() *schema.Resource
{
ForceNew: true,
},
"cpu_speed": {
- Description: "Speed of CPU in Mhz",
+ Description: "Speed of CPU in MHz",
+ Type: schema.TypeInt,
+ Optional: true,
+ ForceNew: true,
+ },
+ "memory": {
+ Description: "Amount of memory in MB",
Type: schema.TypeInt,
Optional: true,
ForceNew: true,
},
"host_tags": {
- Description: "The host tag for this service
offering",
+ Description: "The host tags for this service
offering",
Type: schema.TypeString,
Optional: true,
},
- "limit_cpu_use": {
- Description: "Restrict the CPU usage to
committed service offering",
+ "storage_type": {
+ Description: "The storage type of the service
offering",
+ Type: schema.TypeString,
+ Optional: true,
+ ForceNew: true,
+ Default: "shared",
+ },
+ "service_offering_details": {
+ Description: "Service offering details for
custom configuration",
+ Type: schema.TypeMap,
+ Optional: true,
+ ForceNew: true,
+ Elem: &schema.Schema{
+ Type: schema.TypeString,
+ },
+ },
+ "customized": {
+ Description: "Whether service offering allows
custom CPU/memory or not. If not specified, CloudStack automatically determines
based on cpu_number and memory presence: creates customizable offering (true)
when cpu_number/memory are omitted, or fixed offering (false) when they are
provided.",
Type: schema.TypeBool,
Optional: true,
ForceNew: true,
- Default: false,
},
- "memory": {
- Description: "The total memory of the service
offering in MB",
+ "gpu_card": {
+ Description: "GPU card name (e.g., 'Tesla P100
Auto Created')",
+ Type: schema.TypeString,
+ Optional: true,
+ ForceNew: true,
+ },
+ "gpu_type": {
+ Description: "GPU profile/type (e.g.,
'passthrough', 'GRID V100-8Q')",
+ Type: schema.TypeString,
+ Optional: true,
+ ForceNew: true,
+ },
+ "gpu_count": {
+ Description: "Number of GPUs",
Type: schema.TypeInt,
Optional: true,
ForceNew: true,
},
+
+ // Behavior settings
"offer_ha": {
- Description: "The HA for the service offering",
+ Description: "Whether to offer HA to the VMs
created with this offering",
Type: schema.TypeBool,
Optional: true,
+ Computed: true, // CloudStack returns
default value
ForceNew: true,
- Default: false,
},
- "storage_type": {
- Description: "The storage type of the service
offering. Values are local and shared",
- Type: schema.TypeString,
+
+ "dynamic_scaling_enabled": {
+ Description: "Whether to enable dynamic
scaling",
+ Type: schema.TypeBool,
Optional: true,
+ Computed: true, // CloudStack returns
default value
ForceNew: true,
- Default: "shared",
- ValidateFunc: func(val interface{}, key string)
(warns []string, errs []error) {
- v := val.(string)
-
- if v == "local" || v == "shared" {
- return
- }
+ },
- errs = append(errs, fmt.Errorf("storage
type should be either local or shared, got %s", v))
+ // Disk configuration
+ "root_disk_size": {
+ Description: "Root disk size in GB",
+ Type: schema.TypeInt,
+ Optional: true,
+ ForceNew: true,
+ },
- return
- },
+ "provisioning_type": {
+ Description: "Provisioning type: thin, sparse,
or fat",
+ Type: schema.TypeString,
+ Optional: true,
+ Computed: true, // CloudStack returns
default value
+ ForceNew: true,
},
- "customized": {
- Description: "Whether service offering allows
custom CPU/memory or not",
+
+ // Security
+ "encrypt_root": {
+ Description: "Whether to encrypt the root disk
or not",
Type: schema.TypeBool,
Optional: true,
+ Computed: true, // CloudStack returns
default value
ForceNew: true,
- Computed: true,
- },
+ }, // Customized Offering Limits
"min_cpu_number": {
- Description: "Minimum number of CPU cores
allowed",
+ Description: "Minimum number of CPUs for
customized offerings",
Type: schema.TypeInt,
Optional: true,
ForceNew: true,
},
+
"max_cpu_number": {
- Description: "Maximum number of CPU cores
allowed",
+ Description: "Maximum number of CPUs for
customized offerings",
Type: schema.TypeInt,
Optional: true,
ForceNew: true,
},
+
"min_memory": {
- Description: "Minimum memory allowed (MB)",
+ Description: "Minimum memory in MB for
customized offerings",
Type: schema.TypeInt,
Optional: true,
ForceNew: true,
},
+
"max_memory": {
- Description: "Maximum memory allowed (MB)",
+ Description: "Maximum memory in MB for
customized offerings",
Type: schema.TypeInt,
Optional: true,
ForceNew: true,
},
- "encrypt_root": {
- Description: "Encrypt the root disk for VMs
using this service offering",
+
+ // IOPS Limits
+ "min_iops": {
+ Description: "Minimum IOPS",
+ Type: schema.TypeInt,
+ Optional: true,
+ Computed: true,
+ ForceNew: true,
+ },
+
+ "max_iops": {
+ Description: "Maximum IOPS",
+ Type: schema.TypeInt,
+ Optional: true,
+ Computed: true,
+ ForceNew: true,
+ },
+
+ // GPU Display
+ "gpu_display": {
+ Description: "Whether to display GPU in UI or
not",
Type: schema.TypeBool,
Optional: true,
+ Computed: true, // CloudStack returns
default value
ForceNew: true,
},
- "storage_tags": {
- Description: "Storage tags to associate with
the service offering",
+
+ // High Priority Parameters
+ "limit_cpu_use": {
+ Description: "Restrict CPU usage to the service
offering value",
+ Type: schema.TypeBool,
+ Optional: true,
+ Computed: true, // CloudStack returns
default value
+ ForceNew: true,
+ },
+
+ "is_volatile": {
+ Description: "True if the virtual machine needs
to be volatile (root disk destroyed on stop)",
+ Type: schema.TypeBool,
+ Optional: true,
+ Computed: true, // CloudStack returns
default value
+ ForceNew: true,
+ },
+
+ "customized_iops": {
+ Description: "Whether compute offering iops is
custom or not",
+ Type: schema.TypeBool,
+ Optional: true,
+ Computed: true, // CloudStack returns
default value
+ ForceNew: true,
+ },
+
+ "tags": {
+ Description: "Comma-separated list of tags for
the service offering",
Type: schema.TypeString,
Optional: true,
+ ForceNew: true,
},
- "service_offering_details": {
- Description: "Service offering details for GPU
configuration and other advanced settings",
+
+ "domain_id": {
+ Description: "The ID(s) of the domain(s) to
which the service offering belongs",
+ Type: schema.TypeList,
+ Optional: true,
+ ForceNew: true,
+ Elem: &schema.Schema{Type:
schema.TypeString},
+ },
+
+ "zone_id": {
+ Description: "The ID(s) of the zone(s) this
service offering belongs to",
+ Type: schema.TypeList,
+ Optional: true,
+ ForceNew: true,
+ Elem: &schema.Schema{Type:
schema.TypeString},
+ },
+
+ // IOPS/Bandwidth parameters (Phase 2)
+ // Note: CloudStack API does not support updating these
after creation
+ "disk_iops_read_rate": {
+ Description: "IO requests read rate of the disk
offering",
+ Type: schema.TypeInt,
+ Optional: true,
+ Computed: true,
+ ForceNew: true, // Cannot be updated after
creation
+ },
+
+ "disk_iops_write_rate": {
+ Description: "IO requests write rate of the
disk offering",
+ Type: schema.TypeInt,
+ Optional: true,
+ Computed: true,
+ ForceNew: true, // Cannot be updated after
creation
+ },
+
+ "disk_iops_read_rate_max": {
+ Description: "IO requests read rate max of the
disk offering",
+ Type: schema.TypeInt,
+ Optional: true,
+ Computed: true,
+ ForceNew: true, // Cannot be updated after
creation
+ },
+
+ "disk_iops_write_rate_max": {
+ Description: "IO requests write rate max of the
disk offering",
+ Type: schema.TypeInt,
+ Optional: true,
+ Computed: true,
+ ForceNew: true, // Cannot be updated after
creation
+ },
+
+ "disk_iops_read_rate_max_length": {
+ Description: "Burst duration in seconds for
read rate max",
+ Type: schema.TypeInt,
+ Optional: true,
+ Computed: true,
+ ForceNew: true, // Cannot be updated after
creation
+ },
+
+ "disk_iops_write_rate_max_length": {
+ Description: "Burst duration in seconds for
write rate max",
+ Type: schema.TypeInt,
+ Optional: true,
+ Computed: true,
+ ForceNew: true, // Cannot be updated after
creation
+ },
+
+ "disk_bytes_read_rate": {
+ Description: "Bytes read rate of the disk
offering",
+ Type: schema.TypeInt,
+ Optional: true,
+ Computed: true,
+ ForceNew: true, // Cannot be updated after
creation
+ },
+
+ "disk_bytes_write_rate": {
+ Description: "Bytes write rate of the disk
offering",
+ Type: schema.TypeInt,
+ Optional: true,
+ Computed: true,
+ ForceNew: true, // Cannot be updated after
creation
+ },
+
+ "disk_bytes_read_rate_max": {
+ Description: "Bytes read rate max of the disk
offering",
+ Type: schema.TypeInt,
+ Optional: true,
+ Computed: true,
+ ForceNew: true, // Cannot be updated after
creation
+ },
+
+ "disk_bytes_write_rate_max": {
+ Description: "Bytes write rate max of the disk
offering",
+ Type: schema.TypeInt,
+ Optional: true,
+ Computed: true,
+ ForceNew: true, // Cannot be updated after
creation
+ },
+
+ "bytes_read_rate_max_length": {
+ Description: "Burst duration in seconds for
bytes read rate max",
+ Type: schema.TypeInt,
+ Optional: true,
+ Computed: true,
+ ForceNew: true, // Cannot be updated after
creation
+ },
+
+ "bytes_write_rate_max_length": {
+ Description: "Burst duration in seconds for
bytes write rate max",
+ Type: schema.TypeInt,
+ Optional: true,
+ Computed: true,
+ ForceNew: true, // Cannot be updated after
creation
+ }, // Hypervisor Parameters (Phase 3)
+ "hypervisor_snapshot_reserve": {
+ Description: "Hypervisor snapshot reserve space
as a percent of a volume (for managed storage using Xen or VMware)",
+ Type: schema.TypeInt,
+ Optional: true,
+ Computed: true,
+ },
+
+ "cache_mode": {
+ Description: "The cache mode to use for the
disk offering. Valid values: none, writeback, writethrough",
+ Type: schema.TypeString,
+ Optional: true,
+ Computed: true,
+ },
+
+ "deployment_planner": {
+ Description: "Deployment planner heuristics to
use for the service offering",
+ Type: schema.TypeString,
+ Optional: true,
+ Computed: true,
+ },
+
+ "storage_policy": {
+ Description: "Name of the storage policy (for
VMware)",
+ Type: schema.TypeString,
+ Optional: true,
+ Computed: true,
+ },
Review Comment:
cache_mode, deployment_planner, and storage_policy are set during Create but
are not ForceNew and are not updated in Update. Also, the Read path comments
that storage_policy is write-only, which conflicts with Computed=true in the
schema and can lead to unstable plans/state.
##########
website/docs/r/service_offering.html.markdown:
##########
@@ -1,107 +1,406 @@
---
layout: default
-title: "CloudStack: cloudstack_service_offering"
+page_title: "CloudStack: cloudstack_service_offering"
sidebar_current: "docs-cloudstack-resource-service_offering"
description: |-
- Creates a Service Offering
+ Creates and manages a Service Offering in CloudStack
---
-# CloudStack: cloudstack_service_offering
+# cloudstack_service_offering
-A `cloudstack_service_offering` resource manages a service offering within
CloudStack.
+Provides a CloudStack Service Offering resource. This resource can be used to
create, modify, and delete service offerings that define the compute resources
(CPU, memory, storage) available to virtual machines.
+
+## Understanding CloudStack Service Offering Types
+
+CloudStack supports **three types** of service offerings based on the
`customized` parameter and how CPU/memory are configured:
+
+### 1. Fixed Offering (Fixed CPU and Memory)
+
+Users **cannot** change CPU or memory when deploying VMs. The values are fixed.
+
+**How to create:** Specify both `cpu_number` AND `memory` (do NOT set
`customized`).
+
+```hcl
+resource "cloudstack_service_offering" "fixed" {
+ name = "small-fixed"
+ display_text = "Small Fixed Instance - 2 CPU, 4GB RAM"
+ cpu_number = 2
+ cpu_speed = 2000
+ memory = 4096
+ # customized is automatically set to false
+}
+```
+
+### 2. Custom Constrained Offering (User Choice with Limits)
+
+Users **can** choose CPU and memory **within** the min/max limits you define.
+
+**How to create:** Set `customized = true` AND specify min/max constraints.
+
+```hcl
+resource "cloudstack_service_offering" "constrained" {
+ name = "custom-constrained"
+ display_text = "Custom Constrained - Choose between 2-8 CPU, 2-16GB RAM"
+ customized = true
+ min_cpu_number = 2
+ max_cpu_number = 8
+ min_memory = 2048 # 2 GB
+ max_memory = 16384 # 16 GB
+}
+```
+
+### 3. Custom Unconstrained Offering (User Choice without Limits)
+
+Users **can** choose **any** CPU and memory values (no restrictions).
+
+**How to create:** Set `customized = true` WITHOUT min/max constraints.
+
+```hcl
+resource "cloudstack_service_offering" "unconstrained" {
+ name = "custom-unlimited"
+ display_text = "Custom Unlimited - Choose any CPU/RAM"
+ customized = true
+ # No min/max limits - users have complete freedom
+}
+```
## Example Usage
-### Basic Service Offering
+### Basic Fixed Service Offering
```hcl
-resource "cloudstack_service_offering" "example" {
- name = "example-service-offering"
- display_text = "Example Service Offering"
- cpu_number = 2
- memory = 4096
+resource "cloudstack_service_offering" "basic" {
+ name = "basic-offering"
+ display_text = "Basic Service Offering"
+ cpu_number = 2
+ memory = 4096
}
```
### GPU Service Offering
```hcl
-resource "cloudstack_service_offering" "gpu_offering" {
- name = "gpu-a6000"
- display_text = "GPU A6000 Instance"
- cpu_number = 4
- memory = 16384
-
- service_offering_details = {
- pciDevice = "Group of NVIDIA A6000 GPUs"
- vgpuType = "A6000-8A"
- }
+resource "cloudstack_service_offering" "gpu" {
+ name = "gpu-a6000"
+ display_text = "GPU A6000 Instance"
+ cpu_number = 8
+ memory = 32768
+
+ service_offering_details = {
+ pciDevice = "Group of NVIDIA A6000 GPUs"
+ vgpuType = "A6000-8A"
+ }
+}
+```
+
+### GPU Service Offering with Direct GPU Parameters
+
+```hcl
+resource "cloudstack_service_offering" "tesla_p100_passthrough" {
+ name = "tesla-p100-passthrough"
+ display_text = "Tesla P100 GPU - 2 vCPU, 1GB RAM (Passthrough Mode)"
+
+ # Fixed CPU and Memory configuration
+ cpu_number = 2
+ cpu_speed = 1000
+ memory = 1024 # 1 GB
+
+ # Storage configuration
+ storage_type = "shared"
+ provisioning_type = "thin"
+
+ # Performance and HA settings
+ offer_ha = false
+ limit_cpu_use = false
+ is_volatile = false
+ dynamic_scaling_enabled = true
+ encrypt_root = false
+
+ # Cache mode
+ cache_mode = "none"
+
+ # GPU Configuration - Direct API mapping
+ # gpu_card -> serviceofferingdetails["pciDevice"] -> resolves to gpucardid
+ # gpu_type -> SetVgpuprofileid() + serviceofferingdetails["vgpuType"] ->
resolves to vgpuprofileid/vgpuprofilename
+ # gpu_count -> SetGpucount() -> number of GPUs
+
+ gpu_card = "Tesla P100 Auto Created" # GPU Card Name
+ gpu_type = "8cb04cca-8395-44f8-9d1b-48eb08d48bed" # vGPU Profile
UUID
+ gpu_count = 1 # Number of GPUs
}
```
+### High Performance with IOPS Limits
+
+```hcl
+resource "cloudstack_service_offering" "high_performance" {
+ name = "high-performance"
+ display_text = "High Performance Instance"
+ cpu_number = 4
+ memory = 8192
+ storage_type = "shared"
+
+ # IOPS configuration
+ bytes_read_rate = 10485760 # 10 MB/s
+ bytes_write_rate = 10485760 # 10 MB/s
+ iops_read_rate = 1000
+ iops_write_rate = 1000
+
+ # Additional settings
+ offer_ha = true
+ limit_cpu_use = true
+ host_tags = "high-performance"
+ storage_tags = "ssd"
+}
+```
+
+### Dynamic Scaling Enabled
+
+```hcl
+resource "cloudstack_service_offering" "scalable" {
+ name = "scalable-offering"
+ display_text = "Dynamically Scalable Instance"
+ cpu_number = 4
+ memory = 8192
+ dynamic_scaling_enabled = true
+ disk_iops_min = 500
+ disk_iops_max = 2000
+}
+```
## Argument Reference
The following arguments are supported:
-* `name` - (Required) Name of the service offering.
- Changing this forces a new resource to be created.
+### Required Arguments
+
+* `name` - (Required) The name of the service offering. Changing this forces a
new resource to be created.
+
+### Basic Configuration
+
+* `display_text` - (Optional) The display text of the service offering. If not
provided, defaults to the name.
+
+### CPU and Memory Configuration
+
+* `cpu_number` - (Optional) The number of CPU cores. **Note:** When specified
together with `memory`, creates a **Fixed Offering** (users cannot change
CPU/memory). Changing this forces a new resource to be created.
+
+* `cpu_speed` - (Optional) The clock rate of the CPU cores in MHz. Changing
this forces a new resource to be created.
+
+* `memory` - (Optional) The total memory for the service offering in MB.
**Note:** When specified together with `cpu_number`, creates a **Fixed
Offering** (users cannot change CPU/memory). Changing this forces a new
resource to be created.
+
+### Customization Options (Choose Offering Type)
+
+* `customized` - (Optional) Controls whether users can choose CPU and memory
when deploying VMs:
+ - **Not set** + `cpu_number` + `memory` specified = **Fixed Offering** (no
user choice)
+ - **`true`** + min/max limits = **Custom Constrained** (user choice within
limits)
+ - **`true`** + no limits = **Custom Unconstrained** (any user choice)
+
+ Changing this forces a new resource to be created.
+
+* `customized_iops` - (Optional) Whether compute offering IOPS should be
customizable. Changing this forces a new resource to be created.
+
+### Custom Constrained Limits
+
+Use these **only** when `customized = true` to set boundaries:
+
+* `min_cpu_number` - (Optional) Minimum number of CPU cores users can select.
Changing this forces a new resource to be created.
+
+* `max_cpu_number` - (Optional) Maximum number of CPU cores users can select.
Changing this forces a new resource to be created.
+
+* `min_memory` - (Optional) Minimum memory in MB users can select. Changing
this forces a new resource to be created.
+
+* `max_memory` - (Optional) Maximum memory in MB users can select. Changing
this forces a new resource to be created.
+
+### Storage Configuration
+
+* `storage_type` - (Optional) The storage type of the service offering. Valid
values are `local` and `shared`. Changing this forces a new resource to be
created.
+
+* `storage_tags` - (Optional) Comma-separated list of tags for matching
storage pools. Changing this forces a new resource to be created.
Review Comment:
The docs list a storage_tags argument, but the unified
cloudstack_service_offering schema in this PR does not define storage_tags (it
defines tags instead). This will mislead users and break copy/paste configs.
##########
website/docs/r/service_offering.html.markdown:
##########
@@ -1,107 +1,406 @@
---
layout: default
-title: "CloudStack: cloudstack_service_offering"
+page_title: "CloudStack: cloudstack_service_offering"
sidebar_current: "docs-cloudstack-resource-service_offering"
description: |-
- Creates a Service Offering
+ Creates and manages a Service Offering in CloudStack
---
-# CloudStack: cloudstack_service_offering
+# cloudstack_service_offering
-A `cloudstack_service_offering` resource manages a service offering within
CloudStack.
+Provides a CloudStack Service Offering resource. This resource can be used to
create, modify, and delete service offerings that define the compute resources
(CPU, memory, storage) available to virtual machines.
+
+## Understanding CloudStack Service Offering Types
+
+CloudStack supports **three types** of service offerings based on the
`customized` parameter and how CPU/memory are configured:
+
+### 1. Fixed Offering (Fixed CPU and Memory)
+
+Users **cannot** change CPU or memory when deploying VMs. The values are fixed.
+
+**How to create:** Specify both `cpu_number` AND `memory` (do NOT set
`customized`).
+
+```hcl
+resource "cloudstack_service_offering" "fixed" {
+ name = "small-fixed"
+ display_text = "Small Fixed Instance - 2 CPU, 4GB RAM"
+ cpu_number = 2
+ cpu_speed = 2000
+ memory = 4096
+ # customized is automatically set to false
+}
+```
+
+### 2. Custom Constrained Offering (User Choice with Limits)
+
+Users **can** choose CPU and memory **within** the min/max limits you define.
+
+**How to create:** Set `customized = true` AND specify min/max constraints.
+
+```hcl
+resource "cloudstack_service_offering" "constrained" {
+ name = "custom-constrained"
+ display_text = "Custom Constrained - Choose between 2-8 CPU, 2-16GB RAM"
+ customized = true
+ min_cpu_number = 2
+ max_cpu_number = 8
+ min_memory = 2048 # 2 GB
+ max_memory = 16384 # 16 GB
+}
+```
+
+### 3. Custom Unconstrained Offering (User Choice without Limits)
+
+Users **can** choose **any** CPU and memory values (no restrictions).
+
+**How to create:** Set `customized = true` WITHOUT min/max constraints.
+
+```hcl
+resource "cloudstack_service_offering" "unconstrained" {
+ name = "custom-unlimited"
+ display_text = "Custom Unlimited - Choose any CPU/RAM"
+ customized = true
+ # No min/max limits - users have complete freedom
+}
+```
## Example Usage
-### Basic Service Offering
+### Basic Fixed Service Offering
```hcl
-resource "cloudstack_service_offering" "example" {
- name = "example-service-offering"
- display_text = "Example Service Offering"
- cpu_number = 2
- memory = 4096
+resource "cloudstack_service_offering" "basic" {
+ name = "basic-offering"
+ display_text = "Basic Service Offering"
+ cpu_number = 2
+ memory = 4096
}
```
### GPU Service Offering
```hcl
-resource "cloudstack_service_offering" "gpu_offering" {
- name = "gpu-a6000"
- display_text = "GPU A6000 Instance"
- cpu_number = 4
- memory = 16384
-
- service_offering_details = {
- pciDevice = "Group of NVIDIA A6000 GPUs"
- vgpuType = "A6000-8A"
- }
+resource "cloudstack_service_offering" "gpu" {
+ name = "gpu-a6000"
+ display_text = "GPU A6000 Instance"
+ cpu_number = 8
+ memory = 32768
+
+ service_offering_details = {
+ pciDevice = "Group of NVIDIA A6000 GPUs"
+ vgpuType = "A6000-8A"
+ }
+}
+```
+
+### GPU Service Offering with Direct GPU Parameters
+
+```hcl
+resource "cloudstack_service_offering" "tesla_p100_passthrough" {
+ name = "tesla-p100-passthrough"
+ display_text = "Tesla P100 GPU - 2 vCPU, 1GB RAM (Passthrough Mode)"
+
+ # Fixed CPU and Memory configuration
+ cpu_number = 2
+ cpu_speed = 1000
+ memory = 1024 # 1 GB
+
+ # Storage configuration
+ storage_type = "shared"
+ provisioning_type = "thin"
+
+ # Performance and HA settings
+ offer_ha = false
+ limit_cpu_use = false
+ is_volatile = false
+ dynamic_scaling_enabled = true
+ encrypt_root = false
+
+ # Cache mode
+ cache_mode = "none"
+
+ # GPU Configuration - Direct API mapping
+ # gpu_card -> serviceofferingdetails["pciDevice"] -> resolves to gpucardid
+ # gpu_type -> SetVgpuprofileid() + serviceofferingdetails["vgpuType"] ->
resolves to vgpuprofileid/vgpuprofilename
+ # gpu_count -> SetGpucount() -> number of GPUs
+
+ gpu_card = "Tesla P100 Auto Created" # GPU Card Name
+ gpu_type = "8cb04cca-8395-44f8-9d1b-48eb08d48bed" # vGPU Profile
UUID
+ gpu_count = 1 # Number of GPUs
}
```
+### High Performance with IOPS Limits
+
+```hcl
+resource "cloudstack_service_offering" "high_performance" {
+ name = "high-performance"
+ display_text = "High Performance Instance"
+ cpu_number = 4
+ memory = 8192
+ storage_type = "shared"
+
+ # IOPS configuration
+ bytes_read_rate = 10485760 # 10 MB/s
+ bytes_write_rate = 10485760 # 10 MB/s
+ iops_read_rate = 1000
+ iops_write_rate = 1000
+
+ # Additional settings
+ offer_ha = true
+ limit_cpu_use = true
+ host_tags = "high-performance"
+ storage_tags = "ssd"
+}
+```
+
+### Dynamic Scaling Enabled
+
+```hcl
+resource "cloudstack_service_offering" "scalable" {
+ name = "scalable-offering"
+ display_text = "Dynamically Scalable Instance"
+ cpu_number = 4
+ memory = 8192
+ dynamic_scaling_enabled = true
+ disk_iops_min = 500
+ disk_iops_max = 2000
+}
+```
## Argument Reference
The following arguments are supported:
-* `name` - (Required) Name of the service offering.
- Changing this forces a new resource to be created.
+### Required Arguments
+
+* `name` - (Required) The name of the service offering. Changing this forces a
new resource to be created.
+
+### Basic Configuration
+
+* `display_text` - (Optional) The display text of the service offering. If not
provided, defaults to the name.
+
+### CPU and Memory Configuration
+
+* `cpu_number` - (Optional) The number of CPU cores. **Note:** When specified
together with `memory`, creates a **Fixed Offering** (users cannot change
CPU/memory). Changing this forces a new resource to be created.
+
+* `cpu_speed` - (Optional) The clock rate of the CPU cores in MHz. Changing
this forces a new resource to be created.
+
+* `memory` - (Optional) The total memory for the service offering in MB.
**Note:** When specified together with `cpu_number`, creates a **Fixed
Offering** (users cannot change CPU/memory). Changing this forces a new
resource to be created.
+
+### Customization Options (Choose Offering Type)
+
+* `customized` - (Optional) Controls whether users can choose CPU and memory
when deploying VMs:
+ - **Not set** + `cpu_number` + `memory` specified = **Fixed Offering** (no
user choice)
+ - **`true`** + min/max limits = **Custom Constrained** (user choice within
limits)
+ - **`true`** + no limits = **Custom Unconstrained** (any user choice)
+
+ Changing this forces a new resource to be created.
+
+* `customized_iops` - (Optional) Whether compute offering IOPS should be
customizable. Changing this forces a new resource to be created.
+
+### Custom Constrained Limits
+
+Use these **only** when `customized = true` to set boundaries:
+
+* `min_cpu_number` - (Optional) Minimum number of CPU cores users can select.
Changing this forces a new resource to be created.
+
+* `max_cpu_number` - (Optional) Maximum number of CPU cores users can select.
Changing this forces a new resource to be created.
+
+* `min_memory` - (Optional) Minimum memory in MB users can select. Changing
this forces a new resource to be created.
+
+* `max_memory` - (Optional) Maximum memory in MB users can select. Changing
this forces a new resource to be created.
+
+### Storage Configuration
+
+* `storage_type` - (Optional) The storage type of the service offering. Valid
values are `local` and `shared`. Changing this forces a new resource to be
created.
+
+* `storage_tags` - (Optional) Comma-separated list of tags for matching
storage pools. Changing this forces a new resource to be created.
-* `display_text` - (Optional) The display text of the service offering.
+* `host_tags` - (Optional) Comma-separated list of tags for matching hosts.
Changing this forces a new resource to be created.
-* `cpu_number` - (Optional) The number of CPU cores.
- Changing this forces a new resource to be created.
+* `root_disk_size` - (Optional) The root disk size in GB. Changing this forces
a new resource to be created.
-* `cpu_speed` - (Optional) The speed of the CPU in Mhz.
- Changing this forces a new resource to be created.
+* `encrypt_root` - (Optional) Whether to encrypt the root disk. Changing this
forces a new resource to be created.
-* `memory` - (Optional) Memory reserved by the VM in MB.
- Changing this forces a new resource to be created.
+### GPU Configuration
-* `host_tags` - (Optional) The host tags for the service offering.
+* `gpu_card` - (Optional) The GPU card name for GPU-enabled service offerings.
This maps to `serviceofferingdetails["pciDevice"]` and CloudStack automatically
resolves it to `gpucardid`. Example: `"Tesla P100 Auto Created"`. Changing this
forces a new resource to be created.
-* `limit_cpu_use` - (Optional) Restrict the CPU usage to committed service
offering.
- Changing this forces a new resource to be created.
+* `gpu_type` - (Optional) The vGPU profile UUID or type for GPU-enabled
service offerings. This parameter serves dual purposes:
+ - Sets the vGPU profile ID via `SetVgpuprofileid()` API parameter
+ - Populates `serviceofferingdetails["vgpuType"]`
+ - CloudStack uses this to determine both `vgpuprofileid` and
`vgpuprofilename`
+
+ Example: `"8cb04cca-8395-44f8-9d1b-48eb08d48bed"` for passthrough mode.
Changing this forces a new resource to be created.
-* `offer_ha` - (Optional) The HA for the service offering.
- Changing this forces a new resource to be created.
+* `gpu_count` - (Optional) The number of GPUs to allocate for this service
offering. Maps directly to `SetGpucount()` API parameter. Default is `1` if not
specified. Changing this forces a new resource to be created.
-* `storage_type` - (Optional) The storage type of the service offering. Values
are `local` and `shared`.
- Changing this forces a new resource to be created.
+~> **Note:** For GPU offerings, ensure your CloudStack hosts are properly
configured with GPU passthrough and that the GPU card names and vGPU profile
UUIDs match your physical GPU configuration.
-* `customized` - (Optional) Whether the service offering allows custom CPU and
memory values. Set to `true` to enable users to specify CPU/memory within the
min/max constraints for constrained offerings and any value for unconstrained
offerings.
- Changing this forces a new resource to be created.
+### IOPS and Bandwidth Limits
-* `min_cpu_number` - (Optional) Minimum number of CPU cores allowed for
customized offerings.
- Changing this forces a new resource to be created.
+~> **Note:** All IOPS and bandwidth parameters are immutable after creation.
Any changes will force recreation of the service offering.
-* `max_cpu_number` - (Optional) Maximum number of CPU cores allowed for
customized offerings.
- Changing this forces a new resource to be created.
+* `bytes_read_rate` - (Optional) Bytes read rate in bytes per second. Changing
this forces a new resource to be created.
-* `min_memory` - (Optional) Minimum memory (in MB) allowed for customized
offerings.
- Changing this forces a new resource to be created.
+* `bytes_read_rate_max` - (Optional) Burst bytes read rate in bytes per
second. Changing this forces a new resource to be created.
-* `max_memory` - (Optional) Maximum memory (in MB) allowed for customized
offerings.
- Changing this forces a new resource to be created.
+* `bytes_read_rate_max_length` - (Optional) Length of the burst bytes read
rate in seconds. Changing this forces a new resource to be created.
-* `encrypt_root` - (Optional) Whether to encrypt the root disk for VMs using
this service offering.
- Changing this forces a new resource to be created.
+* `bytes_write_rate` - (Optional) Bytes write rate in bytes per second.
Changing this forces a new resource to be created.
-* `storage_tags` - (Optional) Storage tags to associate with the service
offering.
+* `bytes_write_rate_max` - (Optional) Burst bytes write rate in bytes per
second. Changing this forces a new resource to be created.
-* `service_offering_details` - (Optional) A map of service offering details
for GPU configuration and other advanced settings. Common keys include
`pciDevice` and `vgpuType` for GPU offerings.
- Changing this forces a new resource to be created.
+* `bytes_write_rate_max_length` - (Optional) Length of the burst bytes write
rate in seconds. Changing this forces a new resource to be created.
+
+* `iops_read_rate` - (Optional) IO requests read rate in IOPS. Changing this
forces a new resource to be created.
+
+* `iops_read_rate_max` - (Optional) Burst IO requests read rate in IOPS.
Changing this forces a new resource to be created.
+
+* `iops_read_rate_max_length` - (Optional) Length of the burst IO requests
read rate in seconds. Changing this forces a new resource to be created.
+
+* `iops_write_rate` - (Optional) IO requests write rate in IOPS. Changing this
forces a new resource to be created.
+
+* `iops_write_rate_max` - (Optional) Burst IO requests write rate in IOPS.
Changing this forces a new resource to be created.
+
+* `iops_write_rate_max_length` - (Optional) Length of the burst IO requests
write rate in seconds. Changing this forces a new resource to be created.
Review Comment:
The IOPS/Bandwidth argument list documents iops_read_rate/iops_write_rate
and related max fields, but the implemented schema uses
disk_iops_read_rate/disk_iops_write_rate (and disk_iops_*_max/_max_length). The
documented names won't work.
##########
cloudstack/resource_cloudstack_service_offering_test.go:
##########
@@ -84,31 +170,59 @@ func testAccCheckCloudStackServiceOfferingExists(n string,
so *cloudstack.Servic
}
}
-func TestAccCloudStackServiceOffering_customized(t *testing.T) {
+func testAccCheckCloudStackServiceOfferingDestroy(s *terraform.State) error {
+ cs := testAccProvider.Meta().(*cloudstack.CloudStackClient)
+
+ for _, rs := range s.RootModule().Resources {
+ if rs.Type != testServiceOfferingResourceName {
+ continue
+ }
+
+ if rs.Primary.ID == "" {
+ continue
+ }
+
+ resp, _, err :=
cs.ServiceOffering.GetServiceOfferingByID(rs.Primary.ID)
+ if err != nil {
+ // CloudStack returns 431 error code when the resource
doesn't exist
+ // Just return nil in this case as the resource is gone
+ return nil
+ }
Review Comment:
The destroy check treats any error from GetServiceOfferingByID as success,
which can mask real API/permission/transport failures and produce
false-positive test passes. It should only ignore the specific CloudStack 'not
found' error (not every error).
##########
cloudstack/resource_cloudstack_service_offering.go:
##########
@@ -233,141 +585,356 @@ func resourceCloudStackServiceOfferingCreate(d
*schema.ResourceData, meta interf
p.SetServiceofferingdetails(serviceOfferingDetails)
}
- log.Printf("[DEBUG] Creating Service Offering %s", name)
- s, err := cs.ServiceOffering.CreateServiceOffering(p)
+ if v, ok := d.GetOk("zone_id"); ok {
+ zones := make([]string, 0)
+ for _, z := range v.([]interface{}) {
+ zones = append(zones, z.(string))
+ }
+ p.SetZoneid(zones)
+ }
+
+ if v, ok := d.GetOk("disk_iops_read_rate"); ok {
+ p.SetIopsreadrate(int64(v.(int)))
+ }
+
+ if v, ok := d.GetOk("disk_iops_write_rate"); ok {
+ p.SetIopswriterate(int64(v.(int)))
+ }
+
+ if v, ok := d.GetOk("disk_iops_read_rate_max"); ok {
+ p.SetIopsreadratemax(int64(v.(int)))
+ }
+
+ if v, ok := d.GetOk("disk_iops_write_rate_max"); ok {
+ p.SetIopswriteratemax(int64(v.(int)))
+ }
+
+ if v, ok := d.GetOk("disk_iops_read_rate_max_length"); ok {
+ p.SetIopsreadratemaxlength(int64(v.(int)))
+ }
+
+ if v, ok := d.GetOk("disk_iops_write_rate_max_length"); ok {
+ p.SetIopswriteratemaxlength(int64(v.(int)))
+ }
+
+ if v, ok := d.GetOk("disk_bytes_read_rate"); ok {
+ p.SetBytesreadrate(int64(v.(int)))
+ }
+
+ if v, ok := d.GetOk("disk_bytes_write_rate"); ok {
+ p.SetByteswriterate(int64(v.(int)))
+ }
+
+ if v, ok := d.GetOk("disk_bytes_read_rate_max"); ok {
+ p.SetBytesreadratemax(int64(v.(int)))
+ }
+
+ if v, ok := d.GetOk("disk_bytes_write_rate_max"); ok {
+ p.SetByteswriteratemax(int64(v.(int)))
+ }
+
+ if v, ok := d.GetOk("bytes_read_rate_max_length"); ok {
+ p.SetBytesreadratemaxlength(int64(v.(int)))
+ }
+
+ if v, ok := d.GetOk("bytes_write_rate_max_length"); ok {
+ p.SetByteswriteratemaxlength(int64(v.(int)))
+ }
+
+ if v, ok := d.GetOk("hypervisor_snapshot_reserve"); ok {
+ p.SetHypervisorsnapshotreserve(v.(int))
+ }
+
+ if v, ok := d.GetOk("cache_mode"); ok {
+ p.SetCachemode(v.(string))
+ }
+
+ if v, ok := d.GetOk("deployment_planner"); ok {
+ p.SetDeploymentplanner(v.(string))
+ }
+
+ if v, ok := d.GetOk("storage_policy"); ok {
+ p.SetStoragepolicy(v.(string))
+ }
+ if v, ok := d.GetOk("network_rate"); ok {
+ p.SetNetworkrate(v.(int))
+ }
+
+ if v, ok := d.GetOk("purge_resources"); ok {
+ p.SetPurgeresources(v.(bool))
+ }
+
+ if v, ok := d.GetOk("system_vm_type"); ok {
+ p.SetSystemvmtype(v.(string))
+ }
+
+ if v, ok := d.GetOk("disk_offering_id"); ok {
+ p.SetDiskofferingid(v.(string))
+ }
+
+ if v, ok := d.GetOk("disk_offering_strictness"); ok {
+ p.SetDiskofferingstrictness(v.(bool))
+ }
+
+ if v, ok := d.GetOk("external_details"); ok {
+ extDetails := make(map[string]string)
+ for key, value := range v.(map[string]interface{}) {
+ extDetails[key] = value.(string)
+ }
+ p.SetExternaldetails(extDetails)
+ }
+
+ if v, ok := d.GetOk("is_system"); ok {
+ p.SetIssystem(v.(bool))
+ }
+
+ if v, ok := d.GetOk("lease_duration"); ok {
+ p.SetLeaseduration(v.(int))
+ }
+
+ if v, ok := d.GetOk("lease_expiry_action"); ok {
+ p.SetLeaseexpiryaction(v.(string))
+ }
+
+ if v, ok := d.GetOk("service_offering_details"); ok {
+ details := make(map[string]string)
+ for key, value := range v.(map[string]interface{}) {
+ details[key] = value.(string)
+ }
+ p.SetServiceofferingdetails(details)
+ }
Review Comment:
service_offering_details is set a second time later in Create. This
duplicates logic and can override the earlier merged details (including
gpu_card/gpu_type-derived keys), causing GPU configuration to be dropped when
service_offering_details is also provided.
##########
cloudstack/resource_cloudstack_service_offering.go:
##########
@@ -50,157 +49,492 @@ func resourceCloudStackServiceOffering() *schema.Resource
{
ForceNew: true,
},
"cpu_speed": {
- Description: "Speed of CPU in Mhz",
+ Description: "Speed of CPU in MHz",
+ Type: schema.TypeInt,
+ Optional: true,
+ ForceNew: true,
+ },
+ "memory": {
+ Description: "Amount of memory in MB",
Type: schema.TypeInt,
Optional: true,
ForceNew: true,
},
"host_tags": {
- Description: "The host tag for this service
offering",
+ Description: "The host tags for this service
offering",
Type: schema.TypeString,
Optional: true,
},
- "limit_cpu_use": {
- Description: "Restrict the CPU usage to
committed service offering",
+ "storage_type": {
+ Description: "The storage type of the service
offering",
+ Type: schema.TypeString,
+ Optional: true,
+ ForceNew: true,
+ Default: "shared",
+ },
+ "service_offering_details": {
+ Description: "Service offering details for
custom configuration",
+ Type: schema.TypeMap,
+ Optional: true,
+ ForceNew: true,
+ Elem: &schema.Schema{
+ Type: schema.TypeString,
+ },
+ },
+ "customized": {
+ Description: "Whether service offering allows
custom CPU/memory or not. If not specified, CloudStack automatically determines
based on cpu_number and memory presence: creates customizable offering (true)
when cpu_number/memory are omitted, or fixed offering (false) when they are
provided.",
Type: schema.TypeBool,
Optional: true,
ForceNew: true,
- Default: false,
},
- "memory": {
- Description: "The total memory of the service
offering in MB",
+ "gpu_card": {
+ Description: "GPU card name (e.g., 'Tesla P100
Auto Created')",
+ Type: schema.TypeString,
+ Optional: true,
+ ForceNew: true,
+ },
+ "gpu_type": {
+ Description: "GPU profile/type (e.g.,
'passthrough', 'GRID V100-8Q')",
+ Type: schema.TypeString,
+ Optional: true,
+ ForceNew: true,
+ },
+ "gpu_count": {
+ Description: "Number of GPUs",
Type: schema.TypeInt,
Optional: true,
ForceNew: true,
},
+
+ // Behavior settings
"offer_ha": {
- Description: "The HA for the service offering",
+ Description: "Whether to offer HA to the VMs
created with this offering",
Type: schema.TypeBool,
Optional: true,
+ Computed: true, // CloudStack returns
default value
ForceNew: true,
- Default: false,
},
- "storage_type": {
- Description: "The storage type of the service
offering. Values are local and shared",
- Type: schema.TypeString,
+
+ "dynamic_scaling_enabled": {
+ Description: "Whether to enable dynamic
scaling",
+ Type: schema.TypeBool,
Optional: true,
+ Computed: true, // CloudStack returns
default value
ForceNew: true,
- Default: "shared",
- ValidateFunc: func(val interface{}, key string)
(warns []string, errs []error) {
- v := val.(string)
-
- if v == "local" || v == "shared" {
- return
- }
+ },
- errs = append(errs, fmt.Errorf("storage
type should be either local or shared, got %s", v))
+ // Disk configuration
+ "root_disk_size": {
+ Description: "Root disk size in GB",
+ Type: schema.TypeInt,
+ Optional: true,
+ ForceNew: true,
+ },
- return
- },
+ "provisioning_type": {
+ Description: "Provisioning type: thin, sparse,
or fat",
+ Type: schema.TypeString,
+ Optional: true,
+ Computed: true, // CloudStack returns
default value
+ ForceNew: true,
},
- "customized": {
- Description: "Whether service offering allows
custom CPU/memory or not",
+
+ // Security
+ "encrypt_root": {
+ Description: "Whether to encrypt the root disk
or not",
Type: schema.TypeBool,
Optional: true,
+ Computed: true, // CloudStack returns
default value
ForceNew: true,
- Computed: true,
- },
+ }, // Customized Offering Limits
"min_cpu_number": {
- Description: "Minimum number of CPU cores
allowed",
+ Description: "Minimum number of CPUs for
customized offerings",
Type: schema.TypeInt,
Optional: true,
ForceNew: true,
},
+
"max_cpu_number": {
- Description: "Maximum number of CPU cores
allowed",
+ Description: "Maximum number of CPUs for
customized offerings",
Type: schema.TypeInt,
Optional: true,
ForceNew: true,
},
+
"min_memory": {
- Description: "Minimum memory allowed (MB)",
+ Description: "Minimum memory in MB for
customized offerings",
Type: schema.TypeInt,
Optional: true,
ForceNew: true,
},
+
"max_memory": {
- Description: "Maximum memory allowed (MB)",
+ Description: "Maximum memory in MB for
customized offerings",
Type: schema.TypeInt,
Optional: true,
ForceNew: true,
},
- "encrypt_root": {
- Description: "Encrypt the root disk for VMs
using this service offering",
+
+ // IOPS Limits
+ "min_iops": {
+ Description: "Minimum IOPS",
+ Type: schema.TypeInt,
+ Optional: true,
+ Computed: true,
+ ForceNew: true,
+ },
+
+ "max_iops": {
+ Description: "Maximum IOPS",
+ Type: schema.TypeInt,
+ Optional: true,
+ Computed: true,
+ ForceNew: true,
+ },
+
+ // GPU Display
+ "gpu_display": {
+ Description: "Whether to display GPU in UI or
not",
Type: schema.TypeBool,
Optional: true,
+ Computed: true, // CloudStack returns
default value
ForceNew: true,
},
- "storage_tags": {
- Description: "Storage tags to associate with
the service offering",
+
+ // High Priority Parameters
+ "limit_cpu_use": {
+ Description: "Restrict CPU usage to the service
offering value",
+ Type: schema.TypeBool,
+ Optional: true,
+ Computed: true, // CloudStack returns
default value
+ ForceNew: true,
+ },
+
+ "is_volatile": {
+ Description: "True if the virtual machine needs
to be volatile (root disk destroyed on stop)",
+ Type: schema.TypeBool,
+ Optional: true,
+ Computed: true, // CloudStack returns
default value
+ ForceNew: true,
+ },
+
+ "customized_iops": {
+ Description: "Whether compute offering iops is
custom or not",
+ Type: schema.TypeBool,
+ Optional: true,
+ Computed: true, // CloudStack returns
default value
+ ForceNew: true,
+ },
+
+ "tags": {
+ Description: "Comma-separated list of tags for
the service offering",
Type: schema.TypeString,
Optional: true,
+ ForceNew: true,
},
- "service_offering_details": {
- Description: "Service offering details for GPU
configuration and other advanced settings",
+
+ "domain_id": {
+ Description: "The ID(s) of the domain(s) to
which the service offering belongs",
+ Type: schema.TypeList,
+ Optional: true,
+ ForceNew: true,
+ Elem: &schema.Schema{Type:
schema.TypeString},
+ },
+
+ "zone_id": {
+ Description: "The ID(s) of the zone(s) this
service offering belongs to",
+ Type: schema.TypeList,
+ Optional: true,
+ ForceNew: true,
+ Elem: &schema.Schema{Type:
schema.TypeString},
+ },
+
+ // IOPS/Bandwidth parameters (Phase 2)
+ // Note: CloudStack API does not support updating these
after creation
+ "disk_iops_read_rate": {
+ Description: "IO requests read rate of the disk
offering",
+ Type: schema.TypeInt,
+ Optional: true,
+ Computed: true,
+ ForceNew: true, // Cannot be updated after
creation
+ },
+
+ "disk_iops_write_rate": {
+ Description: "IO requests write rate of the
disk offering",
+ Type: schema.TypeInt,
+ Optional: true,
+ Computed: true,
+ ForceNew: true, // Cannot be updated after
creation
+ },
+
+ "disk_iops_read_rate_max": {
+ Description: "IO requests read rate max of the
disk offering",
+ Type: schema.TypeInt,
+ Optional: true,
+ Computed: true,
+ ForceNew: true, // Cannot be updated after
creation
+ },
+
+ "disk_iops_write_rate_max": {
+ Description: "IO requests write rate max of the
disk offering",
+ Type: schema.TypeInt,
+ Optional: true,
+ Computed: true,
+ ForceNew: true, // Cannot be updated after
creation
+ },
+
+ "disk_iops_read_rate_max_length": {
+ Description: "Burst duration in seconds for
read rate max",
+ Type: schema.TypeInt,
+ Optional: true,
+ Computed: true,
+ ForceNew: true, // Cannot be updated after
creation
+ },
+
+ "disk_iops_write_rate_max_length": {
+ Description: "Burst duration in seconds for
write rate max",
+ Type: schema.TypeInt,
+ Optional: true,
+ Computed: true,
+ ForceNew: true, // Cannot be updated after
creation
+ },
+
+ "disk_bytes_read_rate": {
+ Description: "Bytes read rate of the disk
offering",
+ Type: schema.TypeInt,
+ Optional: true,
+ Computed: true,
+ ForceNew: true, // Cannot be updated after
creation
+ },
+
+ "disk_bytes_write_rate": {
+ Description: "Bytes write rate of the disk
offering",
+ Type: schema.TypeInt,
+ Optional: true,
+ Computed: true,
+ ForceNew: true, // Cannot be updated after
creation
+ },
+
+ "disk_bytes_read_rate_max": {
+ Description: "Bytes read rate max of the disk
offering",
+ Type: schema.TypeInt,
+ Optional: true,
+ Computed: true,
+ ForceNew: true, // Cannot be updated after
creation
+ },
+
+ "disk_bytes_write_rate_max": {
+ Description: "Bytes write rate max of the disk
offering",
+ Type: schema.TypeInt,
+ Optional: true,
+ Computed: true,
+ ForceNew: true, // Cannot be updated after
creation
+ },
+
+ "bytes_read_rate_max_length": {
+ Description: "Burst duration in seconds for
bytes read rate max",
+ Type: schema.TypeInt,
+ Optional: true,
+ Computed: true,
+ ForceNew: true, // Cannot be updated after
creation
+ },
+
+ "bytes_write_rate_max_length": {
+ Description: "Burst duration in seconds for
bytes write rate max",
+ Type: schema.TypeInt,
+ Optional: true,
+ Computed: true,
+ ForceNew: true, // Cannot be updated after
creation
+ }, // Hypervisor Parameters (Phase 3)
+ "hypervisor_snapshot_reserve": {
+ Description: "Hypervisor snapshot reserve space
as a percent of a volume (for managed storage using Xen or VMware)",
+ Type: schema.TypeInt,
+ Optional: true,
+ Computed: true,
+ },
Review Comment:
hypervisor_snapshot_reserve is set during Create but the schema doesn't
ForceNew and Update doesn't handle it. Changing this value will produce a
perpetual diff (or a no-op Update) instead of correctly forcing recreation.
##########
cloudstack/resource_cloudstack_service_offering.go:
##########
@@ -50,157 +49,492 @@ func resourceCloudStackServiceOffering() *schema.Resource
{
ForceNew: true,
},
"cpu_speed": {
- Description: "Speed of CPU in Mhz",
+ Description: "Speed of CPU in MHz",
+ Type: schema.TypeInt,
+ Optional: true,
+ ForceNew: true,
+ },
+ "memory": {
+ Description: "Amount of memory in MB",
Type: schema.TypeInt,
Optional: true,
ForceNew: true,
},
"host_tags": {
- Description: "The host tag for this service
offering",
+ Description: "The host tags for this service
offering",
Type: schema.TypeString,
Optional: true,
},
- "limit_cpu_use": {
- Description: "Restrict the CPU usage to
committed service offering",
+ "storage_type": {
+ Description: "The storage type of the service
offering",
+ Type: schema.TypeString,
+ Optional: true,
+ ForceNew: true,
+ Default: "shared",
+ },
+ "service_offering_details": {
+ Description: "Service offering details for
custom configuration",
+ Type: schema.TypeMap,
+ Optional: true,
+ ForceNew: true,
+ Elem: &schema.Schema{
+ Type: schema.TypeString,
+ },
+ },
+ "customized": {
+ Description: "Whether service offering allows
custom CPU/memory or not. If not specified, CloudStack automatically determines
based on cpu_number and memory presence: creates customizable offering (true)
when cpu_number/memory are omitted, or fixed offering (false) when they are
provided.",
Type: schema.TypeBool,
Optional: true,
ForceNew: true,
- Default: false,
},
- "memory": {
- Description: "The total memory of the service
offering in MB",
+ "gpu_card": {
+ Description: "GPU card name (e.g., 'Tesla P100
Auto Created')",
+ Type: schema.TypeString,
+ Optional: true,
+ ForceNew: true,
+ },
+ "gpu_type": {
+ Description: "GPU profile/type (e.g.,
'passthrough', 'GRID V100-8Q')",
+ Type: schema.TypeString,
+ Optional: true,
+ ForceNew: true,
+ },
+ "gpu_count": {
+ Description: "Number of GPUs",
Type: schema.TypeInt,
Optional: true,
ForceNew: true,
},
+
+ // Behavior settings
"offer_ha": {
- Description: "The HA for the service offering",
+ Description: "Whether to offer HA to the VMs
created with this offering",
Type: schema.TypeBool,
Optional: true,
+ Computed: true, // CloudStack returns
default value
ForceNew: true,
- Default: false,
},
- "storage_type": {
- Description: "The storage type of the service
offering. Values are local and shared",
- Type: schema.TypeString,
+
+ "dynamic_scaling_enabled": {
+ Description: "Whether to enable dynamic
scaling",
+ Type: schema.TypeBool,
Optional: true,
+ Computed: true, // CloudStack returns
default value
ForceNew: true,
- Default: "shared",
- ValidateFunc: func(val interface{}, key string)
(warns []string, errs []error) {
- v := val.(string)
-
- if v == "local" || v == "shared" {
- return
- }
+ },
- errs = append(errs, fmt.Errorf("storage
type should be either local or shared, got %s", v))
+ // Disk configuration
+ "root_disk_size": {
+ Description: "Root disk size in GB",
+ Type: schema.TypeInt,
+ Optional: true,
+ ForceNew: true,
+ },
- return
- },
+ "provisioning_type": {
+ Description: "Provisioning type: thin, sparse,
or fat",
+ Type: schema.TypeString,
+ Optional: true,
+ Computed: true, // CloudStack returns
default value
+ ForceNew: true,
},
- "customized": {
- Description: "Whether service offering allows
custom CPU/memory or not",
+
+ // Security
+ "encrypt_root": {
+ Description: "Whether to encrypt the root disk
or not",
Type: schema.TypeBool,
Optional: true,
+ Computed: true, // CloudStack returns
default value
ForceNew: true,
- Computed: true,
- },
+ }, // Customized Offering Limits
"min_cpu_number": {
- Description: "Minimum number of CPU cores
allowed",
+ Description: "Minimum number of CPUs for
customized offerings",
Type: schema.TypeInt,
Optional: true,
ForceNew: true,
},
+
"max_cpu_number": {
- Description: "Maximum number of CPU cores
allowed",
+ Description: "Maximum number of CPUs for
customized offerings",
Type: schema.TypeInt,
Optional: true,
ForceNew: true,
},
+
"min_memory": {
- Description: "Minimum memory allowed (MB)",
+ Description: "Minimum memory in MB for
customized offerings",
Type: schema.TypeInt,
Optional: true,
ForceNew: true,
},
+
"max_memory": {
- Description: "Maximum memory allowed (MB)",
+ Description: "Maximum memory in MB for
customized offerings",
Type: schema.TypeInt,
Optional: true,
ForceNew: true,
},
- "encrypt_root": {
- Description: "Encrypt the root disk for VMs
using this service offering",
+
+ // IOPS Limits
+ "min_iops": {
+ Description: "Minimum IOPS",
+ Type: schema.TypeInt,
+ Optional: true,
+ Computed: true,
+ ForceNew: true,
+ },
+
+ "max_iops": {
+ Description: "Maximum IOPS",
+ Type: schema.TypeInt,
+ Optional: true,
+ Computed: true,
+ ForceNew: true,
+ },
+
+ // GPU Display
+ "gpu_display": {
+ Description: "Whether to display GPU in UI or
not",
Type: schema.TypeBool,
Optional: true,
+ Computed: true, // CloudStack returns
default value
ForceNew: true,
},
- "storage_tags": {
- Description: "Storage tags to associate with
the service offering",
+
+ // High Priority Parameters
+ "limit_cpu_use": {
+ Description: "Restrict CPU usage to the service
offering value",
+ Type: schema.TypeBool,
+ Optional: true,
+ Computed: true, // CloudStack returns
default value
+ ForceNew: true,
+ },
+
+ "is_volatile": {
+ Description: "True if the virtual machine needs
to be volatile (root disk destroyed on stop)",
+ Type: schema.TypeBool,
+ Optional: true,
+ Computed: true, // CloudStack returns
default value
+ ForceNew: true,
+ },
+
+ "customized_iops": {
+ Description: "Whether compute offering iops is
custom or not",
+ Type: schema.TypeBool,
+ Optional: true,
+ Computed: true, // CloudStack returns
default value
+ ForceNew: true,
+ },
+
+ "tags": {
+ Description: "Comma-separated list of tags for
the service offering",
Type: schema.TypeString,
Optional: true,
+ ForceNew: true,
},
Review Comment:
This PR replaces the previous storage_tags field with tags, but the
description still reads like generic service offering tags. In this provider,
tags appears to be used for storage pool matching (CloudStack storagetags),
which is also what the data source populates. The schema description should be
updated to prevent confusing/incorrect usage.
##########
website/docs/r/service_offering.html.markdown:
##########
@@ -1,107 +1,406 @@
---
layout: default
-title: "CloudStack: cloudstack_service_offering"
+page_title: "CloudStack: cloudstack_service_offering"
sidebar_current: "docs-cloudstack-resource-service_offering"
description: |-
- Creates a Service Offering
+ Creates and manages a Service Offering in CloudStack
---
-# CloudStack: cloudstack_service_offering
+# cloudstack_service_offering
-A `cloudstack_service_offering` resource manages a service offering within
CloudStack.
+Provides a CloudStack Service Offering resource. This resource can be used to
create, modify, and delete service offerings that define the compute resources
(CPU, memory, storage) available to virtual machines.
+
+## Understanding CloudStack Service Offering Types
+
+CloudStack supports **three types** of service offerings based on the
`customized` parameter and how CPU/memory are configured:
+
+### 1. Fixed Offering (Fixed CPU and Memory)
+
+Users **cannot** change CPU or memory when deploying VMs. The values are fixed.
+
+**How to create:** Specify both `cpu_number` AND `memory` (do NOT set
`customized`).
+
+```hcl
+resource "cloudstack_service_offering" "fixed" {
+ name = "small-fixed"
+ display_text = "Small Fixed Instance - 2 CPU, 4GB RAM"
+ cpu_number = 2
+ cpu_speed = 2000
+ memory = 4096
+ # customized is automatically set to false
+}
+```
+
+### 2. Custom Constrained Offering (User Choice with Limits)
+
+Users **can** choose CPU and memory **within** the min/max limits you define.
+
+**How to create:** Set `customized = true` AND specify min/max constraints.
+
+```hcl
+resource "cloudstack_service_offering" "constrained" {
+ name = "custom-constrained"
+ display_text = "Custom Constrained - Choose between 2-8 CPU, 2-16GB RAM"
+ customized = true
+ min_cpu_number = 2
+ max_cpu_number = 8
+ min_memory = 2048 # 2 GB
+ max_memory = 16384 # 16 GB
+}
+```
+
+### 3. Custom Unconstrained Offering (User Choice without Limits)
+
+Users **can** choose **any** CPU and memory values (no restrictions).
+
+**How to create:** Set `customized = true` WITHOUT min/max constraints.
+
+```hcl
+resource "cloudstack_service_offering" "unconstrained" {
+ name = "custom-unlimited"
+ display_text = "Custom Unlimited - Choose any CPU/RAM"
+ customized = true
+ # No min/max limits - users have complete freedom
+}
+```
## Example Usage
-### Basic Service Offering
+### Basic Fixed Service Offering
```hcl
-resource "cloudstack_service_offering" "example" {
- name = "example-service-offering"
- display_text = "Example Service Offering"
- cpu_number = 2
- memory = 4096
+resource "cloudstack_service_offering" "basic" {
+ name = "basic-offering"
+ display_text = "Basic Service Offering"
+ cpu_number = 2
+ memory = 4096
}
```
### GPU Service Offering
```hcl
-resource "cloudstack_service_offering" "gpu_offering" {
- name = "gpu-a6000"
- display_text = "GPU A6000 Instance"
- cpu_number = 4
- memory = 16384
-
- service_offering_details = {
- pciDevice = "Group of NVIDIA A6000 GPUs"
- vgpuType = "A6000-8A"
- }
+resource "cloudstack_service_offering" "gpu" {
+ name = "gpu-a6000"
+ display_text = "GPU A6000 Instance"
+ cpu_number = 8
+ memory = 32768
+
+ service_offering_details = {
+ pciDevice = "Group of NVIDIA A6000 GPUs"
+ vgpuType = "A6000-8A"
+ }
+}
+```
+
+### GPU Service Offering with Direct GPU Parameters
+
+```hcl
+resource "cloudstack_service_offering" "tesla_p100_passthrough" {
+ name = "tesla-p100-passthrough"
+ display_text = "Tesla P100 GPU - 2 vCPU, 1GB RAM (Passthrough Mode)"
+
+ # Fixed CPU and Memory configuration
+ cpu_number = 2
+ cpu_speed = 1000
+ memory = 1024 # 1 GB
+
+ # Storage configuration
+ storage_type = "shared"
+ provisioning_type = "thin"
+
+ # Performance and HA settings
+ offer_ha = false
+ limit_cpu_use = false
+ is_volatile = false
+ dynamic_scaling_enabled = true
+ encrypt_root = false
+
+ # Cache mode
+ cache_mode = "none"
+
+ # GPU Configuration - Direct API mapping
+ # gpu_card -> serviceofferingdetails["pciDevice"] -> resolves to gpucardid
+ # gpu_type -> SetVgpuprofileid() + serviceofferingdetails["vgpuType"] ->
resolves to vgpuprofileid/vgpuprofilename
+ # gpu_count -> SetGpucount() -> number of GPUs
+
+ gpu_card = "Tesla P100 Auto Created" # GPU Card Name
+ gpu_type = "8cb04cca-8395-44f8-9d1b-48eb08d48bed" # vGPU Profile
UUID
+ gpu_count = 1 # Number of GPUs
}
```
+### High Performance with IOPS Limits
+
+```hcl
+resource "cloudstack_service_offering" "high_performance" {
+ name = "high-performance"
+ display_text = "High Performance Instance"
+ cpu_number = 4
+ memory = 8192
+ storage_type = "shared"
+
+ # IOPS configuration
+ bytes_read_rate = 10485760 # 10 MB/s
+ bytes_write_rate = 10485760 # 10 MB/s
+ iops_read_rate = 1000
+ iops_write_rate = 1000
+
+ # Additional settings
+ offer_ha = true
+ limit_cpu_use = true
+ host_tags = "high-performance"
+ storage_tags = "ssd"
+}
+```
+
+### Dynamic Scaling Enabled
+
+```hcl
+resource "cloudstack_service_offering" "scalable" {
+ name = "scalable-offering"
+ display_text = "Dynamically Scalable Instance"
+ cpu_number = 4
+ memory = 8192
+ dynamic_scaling_enabled = true
+ disk_iops_min = 500
+ disk_iops_max = 2000
+}
+```
## Argument Reference
The following arguments are supported:
-* `name` - (Required) Name of the service offering.
- Changing this forces a new resource to be created.
+### Required Arguments
+
+* `name` - (Required) The name of the service offering. Changing this forces a
new resource to be created.
+
+### Basic Configuration
+
+* `display_text` - (Optional) The display text of the service offering. If not
provided, defaults to the name.
+
+### CPU and Memory Configuration
+
+* `cpu_number` - (Optional) The number of CPU cores. **Note:** When specified
together with `memory`, creates a **Fixed Offering** (users cannot change
CPU/memory). Changing this forces a new resource to be created.
+
+* `cpu_speed` - (Optional) The clock rate of the CPU cores in MHz. Changing
this forces a new resource to be created.
+
+* `memory` - (Optional) The total memory for the service offering in MB.
**Note:** When specified together with `cpu_number`, creates a **Fixed
Offering** (users cannot change CPU/memory). Changing this forces a new
resource to be created.
+
+### Customization Options (Choose Offering Type)
+
+* `customized` - (Optional) Controls whether users can choose CPU and memory
when deploying VMs:
+ - **Not set** + `cpu_number` + `memory` specified = **Fixed Offering** (no
user choice)
+ - **`true`** + min/max limits = **Custom Constrained** (user choice within
limits)
+ - **`true`** + no limits = **Custom Unconstrained** (any user choice)
+
+ Changing this forces a new resource to be created.
+
+* `customized_iops` - (Optional) Whether compute offering IOPS should be
customizable. Changing this forces a new resource to be created.
+
+### Custom Constrained Limits
+
+Use these **only** when `customized = true` to set boundaries:
+
+* `min_cpu_number` - (Optional) Minimum number of CPU cores users can select.
Changing this forces a new resource to be created.
+
+* `max_cpu_number` - (Optional) Maximum number of CPU cores users can select.
Changing this forces a new resource to be created.
+
+* `min_memory` - (Optional) Minimum memory in MB users can select. Changing
this forces a new resource to be created.
+
+* `max_memory` - (Optional) Maximum memory in MB users can select. Changing
this forces a new resource to be created.
+
+### Storage Configuration
+
+* `storage_type` - (Optional) The storage type of the service offering. Valid
values are `local` and `shared`. Changing this forces a new resource to be
created.
+
+* `storage_tags` - (Optional) Comma-separated list of tags for matching
storage pools. Changing this forces a new resource to be created.
-* `display_text` - (Optional) The display text of the service offering.
+* `host_tags` - (Optional) Comma-separated list of tags for matching hosts.
Changing this forces a new resource to be created.
-* `cpu_number` - (Optional) The number of CPU cores.
- Changing this forces a new resource to be created.
+* `root_disk_size` - (Optional) The root disk size in GB. Changing this forces
a new resource to be created.
-* `cpu_speed` - (Optional) The speed of the CPU in Mhz.
- Changing this forces a new resource to be created.
+* `encrypt_root` - (Optional) Whether to encrypt the root disk. Changing this
forces a new resource to be created.
-* `memory` - (Optional) Memory reserved by the VM in MB.
- Changing this forces a new resource to be created.
+### GPU Configuration
-* `host_tags` - (Optional) The host tags for the service offering.
+* `gpu_card` - (Optional) The GPU card name for GPU-enabled service offerings.
This maps to `serviceofferingdetails["pciDevice"]` and CloudStack automatically
resolves it to `gpucardid`. Example: `"Tesla P100 Auto Created"`. Changing this
forces a new resource to be created.
-* `limit_cpu_use` - (Optional) Restrict the CPU usage to committed service
offering.
- Changing this forces a new resource to be created.
+* `gpu_type` - (Optional) The vGPU profile UUID or type for GPU-enabled
service offerings. This parameter serves dual purposes:
+ - Sets the vGPU profile ID via `SetVgpuprofileid()` API parameter
+ - Populates `serviceofferingdetails["vgpuType"]`
+ - CloudStack uses this to determine both `vgpuprofileid` and
`vgpuprofilename`
+
+ Example: `"8cb04cca-8395-44f8-9d1b-48eb08d48bed"` for passthrough mode.
Changing this forces a new resource to be created.
-* `offer_ha` - (Optional) The HA for the service offering.
- Changing this forces a new resource to be created.
+* `gpu_count` - (Optional) The number of GPUs to allocate for this service
offering. Maps directly to `SetGpucount()` API parameter. Default is `1` if not
specified. Changing this forces a new resource to be created.
-* `storage_type` - (Optional) The storage type of the service offering. Values
are `local` and `shared`.
- Changing this forces a new resource to be created.
+~> **Note:** For GPU offerings, ensure your CloudStack hosts are properly
configured with GPU passthrough and that the GPU card names and vGPU profile
UUIDs match your physical GPU configuration.
-* `customized` - (Optional) Whether the service offering allows custom CPU and
memory values. Set to `true` to enable users to specify CPU/memory within the
min/max constraints for constrained offerings and any value for unconstrained
offerings.
- Changing this forces a new resource to be created.
+### IOPS and Bandwidth Limits
-* `min_cpu_number` - (Optional) Minimum number of CPU cores allowed for
customized offerings.
- Changing this forces a new resource to be created.
+~> **Note:** All IOPS and bandwidth parameters are immutable after creation.
Any changes will force recreation of the service offering.
-* `max_cpu_number` - (Optional) Maximum number of CPU cores allowed for
customized offerings.
- Changing this forces a new resource to be created.
+* `bytes_read_rate` - (Optional) Bytes read rate in bytes per second. Changing
this forces a new resource to be created.
-* `min_memory` - (Optional) Minimum memory (in MB) allowed for customized
offerings.
- Changing this forces a new resource to be created.
+* `bytes_read_rate_max` - (Optional) Burst bytes read rate in bytes per
second. Changing this forces a new resource to be created.
-* `max_memory` - (Optional) Maximum memory (in MB) allowed for customized
offerings.
- Changing this forces a new resource to be created.
+* `bytes_read_rate_max_length` - (Optional) Length of the burst bytes read
rate in seconds. Changing this forces a new resource to be created.
Review Comment:
The IOPS/Bandwidth argument list documents bytes_read_rate/bytes_write_rate
and their max variants, but the implemented schema uses
disk_bytes_read_rate/disk_bytes_write_rate (and disk_bytes_*_max) along with
bytes_*_max_length. The current names won't work.
##########
website/docs/r/service_offering.html.markdown:
##########
@@ -1,107 +1,406 @@
---
layout: default
-title: "CloudStack: cloudstack_service_offering"
+page_title: "CloudStack: cloudstack_service_offering"
sidebar_current: "docs-cloudstack-resource-service_offering"
description: |-
- Creates a Service Offering
+ Creates and manages a Service Offering in CloudStack
---
-# CloudStack: cloudstack_service_offering
+# cloudstack_service_offering
-A `cloudstack_service_offering` resource manages a service offering within
CloudStack.
+Provides a CloudStack Service Offering resource. This resource can be used to
create, modify, and delete service offerings that define the compute resources
(CPU, memory, storage) available to virtual machines.
+
+## Understanding CloudStack Service Offering Types
+
+CloudStack supports **three types** of service offerings based on the
`customized` parameter and how CPU/memory are configured:
+
+### 1. Fixed Offering (Fixed CPU and Memory)
+
+Users **cannot** change CPU or memory when deploying VMs. The values are fixed.
+
+**How to create:** Specify both `cpu_number` AND `memory` (do NOT set
`customized`).
+
+```hcl
+resource "cloudstack_service_offering" "fixed" {
+ name = "small-fixed"
+ display_text = "Small Fixed Instance - 2 CPU, 4GB RAM"
+ cpu_number = 2
+ cpu_speed = 2000
+ memory = 4096
+ # customized is automatically set to false
+}
+```
+
+### 2. Custom Constrained Offering (User Choice with Limits)
+
+Users **can** choose CPU and memory **within** the min/max limits you define.
+
+**How to create:** Set `customized = true` AND specify min/max constraints.
+
+```hcl
+resource "cloudstack_service_offering" "constrained" {
+ name = "custom-constrained"
+ display_text = "Custom Constrained - Choose between 2-8 CPU, 2-16GB RAM"
+ customized = true
+ min_cpu_number = 2
+ max_cpu_number = 8
+ min_memory = 2048 # 2 GB
+ max_memory = 16384 # 16 GB
+}
+```
+
+### 3. Custom Unconstrained Offering (User Choice without Limits)
+
+Users **can** choose **any** CPU and memory values (no restrictions).
+
+**How to create:** Set `customized = true` WITHOUT min/max constraints.
+
+```hcl
+resource "cloudstack_service_offering" "unconstrained" {
+ name = "custom-unlimited"
+ display_text = "Custom Unlimited - Choose any CPU/RAM"
+ customized = true
+ # No min/max limits - users have complete freedom
+}
+```
## Example Usage
-### Basic Service Offering
+### Basic Fixed Service Offering
```hcl
-resource "cloudstack_service_offering" "example" {
- name = "example-service-offering"
- display_text = "Example Service Offering"
- cpu_number = 2
- memory = 4096
+resource "cloudstack_service_offering" "basic" {
+ name = "basic-offering"
+ display_text = "Basic Service Offering"
+ cpu_number = 2
+ memory = 4096
}
```
### GPU Service Offering
```hcl
-resource "cloudstack_service_offering" "gpu_offering" {
- name = "gpu-a6000"
- display_text = "GPU A6000 Instance"
- cpu_number = 4
- memory = 16384
-
- service_offering_details = {
- pciDevice = "Group of NVIDIA A6000 GPUs"
- vgpuType = "A6000-8A"
- }
+resource "cloudstack_service_offering" "gpu" {
+ name = "gpu-a6000"
+ display_text = "GPU A6000 Instance"
+ cpu_number = 8
+ memory = 32768
+
+ service_offering_details = {
+ pciDevice = "Group of NVIDIA A6000 GPUs"
+ vgpuType = "A6000-8A"
+ }
+}
+```
+
+### GPU Service Offering with Direct GPU Parameters
+
+```hcl
+resource "cloudstack_service_offering" "tesla_p100_passthrough" {
+ name = "tesla-p100-passthrough"
+ display_text = "Tesla P100 GPU - 2 vCPU, 1GB RAM (Passthrough Mode)"
+
+ # Fixed CPU and Memory configuration
+ cpu_number = 2
+ cpu_speed = 1000
+ memory = 1024 # 1 GB
+
+ # Storage configuration
+ storage_type = "shared"
+ provisioning_type = "thin"
+
+ # Performance and HA settings
+ offer_ha = false
+ limit_cpu_use = false
+ is_volatile = false
+ dynamic_scaling_enabled = true
+ encrypt_root = false
+
+ # Cache mode
+ cache_mode = "none"
+
+ # GPU Configuration - Direct API mapping
+ # gpu_card -> serviceofferingdetails["pciDevice"] -> resolves to gpucardid
+ # gpu_type -> SetVgpuprofileid() + serviceofferingdetails["vgpuType"] ->
resolves to vgpuprofileid/vgpuprofilename
+ # gpu_count -> SetGpucount() -> number of GPUs
+
+ gpu_card = "Tesla P100 Auto Created" # GPU Card Name
+ gpu_type = "8cb04cca-8395-44f8-9d1b-48eb08d48bed" # vGPU Profile
UUID
+ gpu_count = 1 # Number of GPUs
}
```
+### High Performance with IOPS Limits
+
+```hcl
+resource "cloudstack_service_offering" "high_performance" {
+ name = "high-performance"
+ display_text = "High Performance Instance"
+ cpu_number = 4
+ memory = 8192
+ storage_type = "shared"
+
+ # IOPS configuration
+ bytes_read_rate = 10485760 # 10 MB/s
+ bytes_write_rate = 10485760 # 10 MB/s
+ iops_read_rate = 1000
+ iops_write_rate = 1000
+
+ # Additional settings
+ offer_ha = true
+ limit_cpu_use = true
+ host_tags = "high-performance"
+ storage_tags = "ssd"
+}
Review Comment:
The High Performance example uses argument names
(bytes_read_rate/iops_read_rate/storage_tags) that do not exist in the resource
schema implemented in this PR. The resource uses disk_bytes_* and disk_iops_*
names, and the storage-pool tag argument is tags (not storage_tags).
##########
website/docs/r/service_offering.html.markdown:
##########
@@ -1,107 +1,406 @@
---
layout: default
-title: "CloudStack: cloudstack_service_offering"
+page_title: "CloudStack: cloudstack_service_offering"
sidebar_current: "docs-cloudstack-resource-service_offering"
description: |-
- Creates a Service Offering
+ Creates and manages a Service Offering in CloudStack
---
-# CloudStack: cloudstack_service_offering
+# cloudstack_service_offering
-A `cloudstack_service_offering` resource manages a service offering within
CloudStack.
+Provides a CloudStack Service Offering resource. This resource can be used to
create, modify, and delete service offerings that define the compute resources
(CPU, memory, storage) available to virtual machines.
+
+## Understanding CloudStack Service Offering Types
+
+CloudStack supports **three types** of service offerings based on the
`customized` parameter and how CPU/memory are configured:
+
+### 1. Fixed Offering (Fixed CPU and Memory)
+
+Users **cannot** change CPU or memory when deploying VMs. The values are fixed.
+
+**How to create:** Specify both `cpu_number` AND `memory` (do NOT set
`customized`).
+
+```hcl
+resource "cloudstack_service_offering" "fixed" {
+ name = "small-fixed"
+ display_text = "Small Fixed Instance - 2 CPU, 4GB RAM"
+ cpu_number = 2
+ cpu_speed = 2000
+ memory = 4096
+ # customized is automatically set to false
+}
+```
+
+### 2. Custom Constrained Offering (User Choice with Limits)
+
+Users **can** choose CPU and memory **within** the min/max limits you define.
+
+**How to create:** Set `customized = true` AND specify min/max constraints.
+
+```hcl
+resource "cloudstack_service_offering" "constrained" {
+ name = "custom-constrained"
+ display_text = "Custom Constrained - Choose between 2-8 CPU, 2-16GB RAM"
+ customized = true
+ min_cpu_number = 2
+ max_cpu_number = 8
+ min_memory = 2048 # 2 GB
+ max_memory = 16384 # 16 GB
+}
+```
+
+### 3. Custom Unconstrained Offering (User Choice without Limits)
+
+Users **can** choose **any** CPU and memory values (no restrictions).
+
+**How to create:** Set `customized = true` WITHOUT min/max constraints.
+
+```hcl
+resource "cloudstack_service_offering" "unconstrained" {
+ name = "custom-unlimited"
+ display_text = "Custom Unlimited - Choose any CPU/RAM"
+ customized = true
+ # No min/max limits - users have complete freedom
+}
+```
## Example Usage
-### Basic Service Offering
+### Basic Fixed Service Offering
```hcl
-resource "cloudstack_service_offering" "example" {
- name = "example-service-offering"
- display_text = "Example Service Offering"
- cpu_number = 2
- memory = 4096
+resource "cloudstack_service_offering" "basic" {
+ name = "basic-offering"
+ display_text = "Basic Service Offering"
+ cpu_number = 2
+ memory = 4096
}
```
### GPU Service Offering
```hcl
-resource "cloudstack_service_offering" "gpu_offering" {
- name = "gpu-a6000"
- display_text = "GPU A6000 Instance"
- cpu_number = 4
- memory = 16384
-
- service_offering_details = {
- pciDevice = "Group of NVIDIA A6000 GPUs"
- vgpuType = "A6000-8A"
- }
+resource "cloudstack_service_offering" "gpu" {
+ name = "gpu-a6000"
+ display_text = "GPU A6000 Instance"
+ cpu_number = 8
+ memory = 32768
+
+ service_offering_details = {
+ pciDevice = "Group of NVIDIA A6000 GPUs"
+ vgpuType = "A6000-8A"
+ }
+}
+```
+
+### GPU Service Offering with Direct GPU Parameters
+
+```hcl
+resource "cloudstack_service_offering" "tesla_p100_passthrough" {
+ name = "tesla-p100-passthrough"
+ display_text = "Tesla P100 GPU - 2 vCPU, 1GB RAM (Passthrough Mode)"
+
+ # Fixed CPU and Memory configuration
+ cpu_number = 2
+ cpu_speed = 1000
+ memory = 1024 # 1 GB
+
+ # Storage configuration
+ storage_type = "shared"
+ provisioning_type = "thin"
+
+ # Performance and HA settings
+ offer_ha = false
+ limit_cpu_use = false
+ is_volatile = false
+ dynamic_scaling_enabled = true
+ encrypt_root = false
+
+ # Cache mode
+ cache_mode = "none"
+
+ # GPU Configuration - Direct API mapping
+ # gpu_card -> serviceofferingdetails["pciDevice"] -> resolves to gpucardid
+ # gpu_type -> SetVgpuprofileid() + serviceofferingdetails["vgpuType"] ->
resolves to vgpuprofileid/vgpuprofilename
+ # gpu_count -> SetGpucount() -> number of GPUs
+
+ gpu_card = "Tesla P100 Auto Created" # GPU Card Name
+ gpu_type = "8cb04cca-8395-44f8-9d1b-48eb08d48bed" # vGPU Profile
UUID
+ gpu_count = 1 # Number of GPUs
}
```
+### High Performance with IOPS Limits
+
+```hcl
+resource "cloudstack_service_offering" "high_performance" {
+ name = "high-performance"
+ display_text = "High Performance Instance"
+ cpu_number = 4
+ memory = 8192
+ storage_type = "shared"
+
+ # IOPS configuration
+ bytes_read_rate = 10485760 # 10 MB/s
+ bytes_write_rate = 10485760 # 10 MB/s
+ iops_read_rate = 1000
+ iops_write_rate = 1000
+
+ # Additional settings
+ offer_ha = true
+ limit_cpu_use = true
+ host_tags = "high-performance"
+ storage_tags = "ssd"
+}
+```
+
+### Dynamic Scaling Enabled
+
+```hcl
+resource "cloudstack_service_offering" "scalable" {
+ name = "scalable-offering"
+ display_text = "Dynamically Scalable Instance"
+ cpu_number = 4
+ memory = 8192
+ dynamic_scaling_enabled = true
+ disk_iops_min = 500
+ disk_iops_max = 2000
+}
+```
## Argument Reference
The following arguments are supported:
-* `name` - (Required) Name of the service offering.
- Changing this forces a new resource to be created.
+### Required Arguments
+
+* `name` - (Required) The name of the service offering. Changing this forces a
new resource to be created.
+
+### Basic Configuration
+
+* `display_text` - (Optional) The display text of the service offering. If not
provided, defaults to the name.
+
+### CPU and Memory Configuration
+
+* `cpu_number` - (Optional) The number of CPU cores. **Note:** When specified
together with `memory`, creates a **Fixed Offering** (users cannot change
CPU/memory). Changing this forces a new resource to be created.
+
+* `cpu_speed` - (Optional) The clock rate of the CPU cores in MHz. Changing
this forces a new resource to be created.
+
+* `memory` - (Optional) The total memory for the service offering in MB.
**Note:** When specified together with `cpu_number`, creates a **Fixed
Offering** (users cannot change CPU/memory). Changing this forces a new
resource to be created.
+
+### Customization Options (Choose Offering Type)
+
+* `customized` - (Optional) Controls whether users can choose CPU and memory
when deploying VMs:
+ - **Not set** + `cpu_number` + `memory` specified = **Fixed Offering** (no
user choice)
+ - **`true`** + min/max limits = **Custom Constrained** (user choice within
limits)
+ - **`true`** + no limits = **Custom Unconstrained** (any user choice)
+
+ Changing this forces a new resource to be created.
+
+* `customized_iops` - (Optional) Whether compute offering IOPS should be
customizable. Changing this forces a new resource to be created.
+
+### Custom Constrained Limits
+
+Use these **only** when `customized = true` to set boundaries:
+
+* `min_cpu_number` - (Optional) Minimum number of CPU cores users can select.
Changing this forces a new resource to be created.
+
+* `max_cpu_number` - (Optional) Maximum number of CPU cores users can select.
Changing this forces a new resource to be created.
+
+* `min_memory` - (Optional) Minimum memory in MB users can select. Changing
this forces a new resource to be created.
+
+* `max_memory` - (Optional) Maximum memory in MB users can select. Changing
this forces a new resource to be created.
+
+### Storage Configuration
+
+* `storage_type` - (Optional) The storage type of the service offering. Valid
values are `local` and `shared`. Changing this forces a new resource to be
created.
+
+* `storage_tags` - (Optional) Comma-separated list of tags for matching
storage pools. Changing this forces a new resource to be created.
-* `display_text` - (Optional) The display text of the service offering.
+* `host_tags` - (Optional) Comma-separated list of tags for matching hosts.
Changing this forces a new resource to be created.
-* `cpu_number` - (Optional) The number of CPU cores.
- Changing this forces a new resource to be created.
+* `root_disk_size` - (Optional) The root disk size in GB. Changing this forces
a new resource to be created.
-* `cpu_speed` - (Optional) The speed of the CPU in Mhz.
- Changing this forces a new resource to be created.
+* `encrypt_root` - (Optional) Whether to encrypt the root disk. Changing this
forces a new resource to be created.
-* `memory` - (Optional) Memory reserved by the VM in MB.
- Changing this forces a new resource to be created.
+### GPU Configuration
-* `host_tags` - (Optional) The host tags for the service offering.
+* `gpu_card` - (Optional) The GPU card name for GPU-enabled service offerings.
This maps to `serviceofferingdetails["pciDevice"]` and CloudStack automatically
resolves it to `gpucardid`. Example: `"Tesla P100 Auto Created"`. Changing this
forces a new resource to be created.
-* `limit_cpu_use` - (Optional) Restrict the CPU usage to committed service
offering.
- Changing this forces a new resource to be created.
+* `gpu_type` - (Optional) The vGPU profile UUID or type for GPU-enabled
service offerings. This parameter serves dual purposes:
+ - Sets the vGPU profile ID via `SetVgpuprofileid()` API parameter
+ - Populates `serviceofferingdetails["vgpuType"]`
+ - CloudStack uses this to determine both `vgpuprofileid` and
`vgpuprofilename`
+
+ Example: `"8cb04cca-8395-44f8-9d1b-48eb08d48bed"` for passthrough mode.
Changing this forces a new resource to be created.
-* `offer_ha` - (Optional) The HA for the service offering.
- Changing this forces a new resource to be created.
+* `gpu_count` - (Optional) The number of GPUs to allocate for this service
offering. Maps directly to `SetGpucount()` API parameter. Default is `1` if not
specified. Changing this forces a new resource to be created.
-* `storage_type` - (Optional) The storage type of the service offering. Values
are `local` and `shared`.
- Changing this forces a new resource to be created.
+~> **Note:** For GPU offerings, ensure your CloudStack hosts are properly
configured with GPU passthrough and that the GPU card names and vGPU profile
UUIDs match your physical GPU configuration.
-* `customized` - (Optional) Whether the service offering allows custom CPU and
memory values. Set to `true` to enable users to specify CPU/memory within the
min/max constraints for constrained offerings and any value for unconstrained
offerings.
- Changing this forces a new resource to be created.
+### IOPS and Bandwidth Limits
-* `min_cpu_number` - (Optional) Minimum number of CPU cores allowed for
customized offerings.
- Changing this forces a new resource to be created.
+~> **Note:** All IOPS and bandwidth parameters are immutable after creation.
Any changes will force recreation of the service offering.
-* `max_cpu_number` - (Optional) Maximum number of CPU cores allowed for
customized offerings.
- Changing this forces a new resource to be created.
+* `bytes_read_rate` - (Optional) Bytes read rate in bytes per second. Changing
this forces a new resource to be created.
-* `min_memory` - (Optional) Minimum memory (in MB) allowed for customized
offerings.
- Changing this forces a new resource to be created.
+* `bytes_read_rate_max` - (Optional) Burst bytes read rate in bytes per
second. Changing this forces a new resource to be created.
-* `max_memory` - (Optional) Maximum memory (in MB) allowed for customized
offerings.
- Changing this forces a new resource to be created.
+* `bytes_read_rate_max_length` - (Optional) Length of the burst bytes read
rate in seconds. Changing this forces a new resource to be created.
-* `encrypt_root` - (Optional) Whether to encrypt the root disk for VMs using
this service offering.
- Changing this forces a new resource to be created.
+* `bytes_write_rate` - (Optional) Bytes write rate in bytes per second.
Changing this forces a new resource to be created.
-* `storage_tags` - (Optional) Storage tags to associate with the service
offering.
+* `bytes_write_rate_max` - (Optional) Burst bytes write rate in bytes per
second. Changing this forces a new resource to be created.
-* `service_offering_details` - (Optional) A map of service offering details
for GPU configuration and other advanced settings. Common keys include
`pciDevice` and `vgpuType` for GPU offerings.
- Changing this forces a new resource to be created.
+* `bytes_write_rate_max_length` - (Optional) Length of the burst bytes write
rate in seconds. Changing this forces a new resource to be created.
+
+* `iops_read_rate` - (Optional) IO requests read rate in IOPS. Changing this
forces a new resource to be created.
+
+* `iops_read_rate_max` - (Optional) Burst IO requests read rate in IOPS.
Changing this forces a new resource to be created.
+
+* `iops_read_rate_max_length` - (Optional) Length of the burst IO requests
read rate in seconds. Changing this forces a new resource to be created.
+
+* `iops_write_rate` - (Optional) IO requests write rate in IOPS. Changing this
forces a new resource to be created.
+
+* `iops_write_rate_max` - (Optional) Burst IO requests write rate in IOPS.
Changing this forces a new resource to be created.
+
+* `iops_write_rate_max_length` - (Optional) Length of the burst IO requests
write rate in seconds. Changing this forces a new resource to be created.
+
+### Dynamic Scaling and IOPS
+
+* `disk_iops_min` - (Optional) Minimum IOPS for the disk. Changing this forces
a new resource to be created.
+
+* `disk_iops_max` - (Optional) Maximum IOPS for the disk. Changing this forces
a new resource to be created.
+
Review Comment:
The docs refer to disk_iops_min/disk_iops_max, but the implemented schema
uses min_iops/max_iops. The documented names won't work.
##########
website/docs/r/service_offering.html.markdown:
##########
@@ -1,107 +1,406 @@
---
layout: default
-title: "CloudStack: cloudstack_service_offering"
+page_title: "CloudStack: cloudstack_service_offering"
sidebar_current: "docs-cloudstack-resource-service_offering"
description: |-
- Creates a Service Offering
+ Creates and manages a Service Offering in CloudStack
---
-# CloudStack: cloudstack_service_offering
+# cloudstack_service_offering
-A `cloudstack_service_offering` resource manages a service offering within
CloudStack.
+Provides a CloudStack Service Offering resource. This resource can be used to
create, modify, and delete service offerings that define the compute resources
(CPU, memory, storage) available to virtual machines.
+
+## Understanding CloudStack Service Offering Types
+
+CloudStack supports **three types** of service offerings based on the
`customized` parameter and how CPU/memory are configured:
+
+### 1. Fixed Offering (Fixed CPU and Memory)
+
+Users **cannot** change CPU or memory when deploying VMs. The values are fixed.
+
+**How to create:** Specify both `cpu_number` AND `memory` (do NOT set
`customized`).
+
+```hcl
+resource "cloudstack_service_offering" "fixed" {
+ name = "small-fixed"
+ display_text = "Small Fixed Instance - 2 CPU, 4GB RAM"
+ cpu_number = 2
+ cpu_speed = 2000
+ memory = 4096
+ # customized is automatically set to false
+}
+```
+
+### 2. Custom Constrained Offering (User Choice with Limits)
+
+Users **can** choose CPU and memory **within** the min/max limits you define.
+
+**How to create:** Set `customized = true` AND specify min/max constraints.
+
+```hcl
+resource "cloudstack_service_offering" "constrained" {
+ name = "custom-constrained"
+ display_text = "Custom Constrained - Choose between 2-8 CPU, 2-16GB RAM"
+ customized = true
+ min_cpu_number = 2
+ max_cpu_number = 8
+ min_memory = 2048 # 2 GB
+ max_memory = 16384 # 16 GB
+}
+```
+
+### 3. Custom Unconstrained Offering (User Choice without Limits)
+
+Users **can** choose **any** CPU and memory values (no restrictions).
+
+**How to create:** Set `customized = true` WITHOUT min/max constraints.
+
+```hcl
+resource "cloudstack_service_offering" "unconstrained" {
+ name = "custom-unlimited"
+ display_text = "Custom Unlimited - Choose any CPU/RAM"
+ customized = true
+ # No min/max limits - users have complete freedom
+}
+```
## Example Usage
-### Basic Service Offering
+### Basic Fixed Service Offering
```hcl
-resource "cloudstack_service_offering" "example" {
- name = "example-service-offering"
- display_text = "Example Service Offering"
- cpu_number = 2
- memory = 4096
+resource "cloudstack_service_offering" "basic" {
+ name = "basic-offering"
+ display_text = "Basic Service Offering"
+ cpu_number = 2
+ memory = 4096
}
```
### GPU Service Offering
```hcl
-resource "cloudstack_service_offering" "gpu_offering" {
- name = "gpu-a6000"
- display_text = "GPU A6000 Instance"
- cpu_number = 4
- memory = 16384
-
- service_offering_details = {
- pciDevice = "Group of NVIDIA A6000 GPUs"
- vgpuType = "A6000-8A"
- }
+resource "cloudstack_service_offering" "gpu" {
+ name = "gpu-a6000"
+ display_text = "GPU A6000 Instance"
+ cpu_number = 8
+ memory = 32768
+
+ service_offering_details = {
+ pciDevice = "Group of NVIDIA A6000 GPUs"
+ vgpuType = "A6000-8A"
+ }
+}
+```
+
+### GPU Service Offering with Direct GPU Parameters
+
+```hcl
+resource "cloudstack_service_offering" "tesla_p100_passthrough" {
+ name = "tesla-p100-passthrough"
+ display_text = "Tesla P100 GPU - 2 vCPU, 1GB RAM (Passthrough Mode)"
+
+ # Fixed CPU and Memory configuration
+ cpu_number = 2
+ cpu_speed = 1000
+ memory = 1024 # 1 GB
+
+ # Storage configuration
+ storage_type = "shared"
+ provisioning_type = "thin"
+
+ # Performance and HA settings
+ offer_ha = false
+ limit_cpu_use = false
+ is_volatile = false
+ dynamic_scaling_enabled = true
+ encrypt_root = false
+
+ # Cache mode
+ cache_mode = "none"
+
+ # GPU Configuration - Direct API mapping
+ # gpu_card -> serviceofferingdetails["pciDevice"] -> resolves to gpucardid
+ # gpu_type -> SetVgpuprofileid() + serviceofferingdetails["vgpuType"] ->
resolves to vgpuprofileid/vgpuprofilename
+ # gpu_count -> SetGpucount() -> number of GPUs
+
+ gpu_card = "Tesla P100 Auto Created" # GPU Card Name
+ gpu_type = "8cb04cca-8395-44f8-9d1b-48eb08d48bed" # vGPU Profile
UUID
+ gpu_count = 1 # Number of GPUs
}
```
+### High Performance with IOPS Limits
+
+```hcl
+resource "cloudstack_service_offering" "high_performance" {
+ name = "high-performance"
+ display_text = "High Performance Instance"
+ cpu_number = 4
+ memory = 8192
+ storage_type = "shared"
+
+ # IOPS configuration
+ bytes_read_rate = 10485760 # 10 MB/s
+ bytes_write_rate = 10485760 # 10 MB/s
+ iops_read_rate = 1000
+ iops_write_rate = 1000
+
+ # Additional settings
+ offer_ha = true
+ limit_cpu_use = true
+ host_tags = "high-performance"
+ storage_tags = "ssd"
+}
+```
+
+### Dynamic Scaling Enabled
+
+```hcl
+resource "cloudstack_service_offering" "scalable" {
+ name = "scalable-offering"
+ display_text = "Dynamically Scalable Instance"
+ cpu_number = 4
+ memory = 8192
+ dynamic_scaling_enabled = true
+ disk_iops_min = 500
+ disk_iops_max = 2000
+}
+```
## Argument Reference
The following arguments are supported:
-* `name` - (Required) Name of the service offering.
- Changing this forces a new resource to be created.
+### Required Arguments
+
+* `name` - (Required) The name of the service offering. Changing this forces a
new resource to be created.
+
+### Basic Configuration
+
+* `display_text` - (Optional) The display text of the service offering. If not
provided, defaults to the name.
+
+### CPU and Memory Configuration
+
+* `cpu_number` - (Optional) The number of CPU cores. **Note:** When specified
together with `memory`, creates a **Fixed Offering** (users cannot change
CPU/memory). Changing this forces a new resource to be created.
+
+* `cpu_speed` - (Optional) The clock rate of the CPU cores in MHz. Changing
this forces a new resource to be created.
+
+* `memory` - (Optional) The total memory for the service offering in MB.
**Note:** When specified together with `cpu_number`, creates a **Fixed
Offering** (users cannot change CPU/memory). Changing this forces a new
resource to be created.
+
+### Customization Options (Choose Offering Type)
+
+* `customized` - (Optional) Controls whether users can choose CPU and memory
when deploying VMs:
+ - **Not set** + `cpu_number` + `memory` specified = **Fixed Offering** (no
user choice)
+ - **`true`** + min/max limits = **Custom Constrained** (user choice within
limits)
+ - **`true`** + no limits = **Custom Unconstrained** (any user choice)
+
+ Changing this forces a new resource to be created.
+
+* `customized_iops` - (Optional) Whether compute offering IOPS should be
customizable. Changing this forces a new resource to be created.
+
+### Custom Constrained Limits
+
+Use these **only** when `customized = true` to set boundaries:
+
+* `min_cpu_number` - (Optional) Minimum number of CPU cores users can select.
Changing this forces a new resource to be created.
+
+* `max_cpu_number` - (Optional) Maximum number of CPU cores users can select.
Changing this forces a new resource to be created.
+
+* `min_memory` - (Optional) Minimum memory in MB users can select. Changing
this forces a new resource to be created.
+
+* `max_memory` - (Optional) Maximum memory in MB users can select. Changing
this forces a new resource to be created.
+
+### Storage Configuration
+
+* `storage_type` - (Optional) The storage type of the service offering. Valid
values are `local` and `shared`. Changing this forces a new resource to be
created.
+
+* `storage_tags` - (Optional) Comma-separated list of tags for matching
storage pools. Changing this forces a new resource to be created.
-* `display_text` - (Optional) The display text of the service offering.
+* `host_tags` - (Optional) Comma-separated list of tags for matching hosts.
Changing this forces a new resource to be created.
-* `cpu_number` - (Optional) The number of CPU cores.
- Changing this forces a new resource to be created.
+* `root_disk_size` - (Optional) The root disk size in GB. Changing this forces
a new resource to be created.
-* `cpu_speed` - (Optional) The speed of the CPU in Mhz.
- Changing this forces a new resource to be created.
+* `encrypt_root` - (Optional) Whether to encrypt the root disk. Changing this
forces a new resource to be created.
-* `memory` - (Optional) Memory reserved by the VM in MB.
- Changing this forces a new resource to be created.
+### GPU Configuration
-* `host_tags` - (Optional) The host tags for the service offering.
+* `gpu_card` - (Optional) The GPU card name for GPU-enabled service offerings.
This maps to `serviceofferingdetails["pciDevice"]` and CloudStack automatically
resolves it to `gpucardid`. Example: `"Tesla P100 Auto Created"`. Changing this
forces a new resource to be created.
-* `limit_cpu_use` - (Optional) Restrict the CPU usage to committed service
offering.
- Changing this forces a new resource to be created.
+* `gpu_type` - (Optional) The vGPU profile UUID or type for GPU-enabled
service offerings. This parameter serves dual purposes:
+ - Sets the vGPU profile ID via `SetVgpuprofileid()` API parameter
+ - Populates `serviceofferingdetails["vgpuType"]`
+ - CloudStack uses this to determine both `vgpuprofileid` and
`vgpuprofilename`
+
+ Example: `"8cb04cca-8395-44f8-9d1b-48eb08d48bed"` for passthrough mode.
Changing this forces a new resource to be created.
-* `offer_ha` - (Optional) The HA for the service offering.
- Changing this forces a new resource to be created.
+* `gpu_count` - (Optional) The number of GPUs to allocate for this service
offering. Maps directly to `SetGpucount()` API parameter. Default is `1` if not
specified. Changing this forces a new resource to be created.
-* `storage_type` - (Optional) The storage type of the service offering. Values
are `local` and `shared`.
- Changing this forces a new resource to be created.
+~> **Note:** For GPU offerings, ensure your CloudStack hosts are properly
configured with GPU passthrough and that the GPU card names and vGPU profile
UUIDs match your physical GPU configuration.
-* `customized` - (Optional) Whether the service offering allows custom CPU and
memory values. Set to `true` to enable users to specify CPU/memory within the
min/max constraints for constrained offerings and any value for unconstrained
offerings.
- Changing this forces a new resource to be created.
+### IOPS and Bandwidth Limits
-* `min_cpu_number` - (Optional) Minimum number of CPU cores allowed for
customized offerings.
- Changing this forces a new resource to be created.
+~> **Note:** All IOPS and bandwidth parameters are immutable after creation.
Any changes will force recreation of the service offering.
-* `max_cpu_number` - (Optional) Maximum number of CPU cores allowed for
customized offerings.
- Changing this forces a new resource to be created.
+* `bytes_read_rate` - (Optional) Bytes read rate in bytes per second. Changing
this forces a new resource to be created.
-* `min_memory` - (Optional) Minimum memory (in MB) allowed for customized
offerings.
- Changing this forces a new resource to be created.
+* `bytes_read_rate_max` - (Optional) Burst bytes read rate in bytes per
second. Changing this forces a new resource to be created.
-* `max_memory` - (Optional) Maximum memory (in MB) allowed for customized
offerings.
- Changing this forces a new resource to be created.
+* `bytes_read_rate_max_length` - (Optional) Length of the burst bytes read
rate in seconds. Changing this forces a new resource to be created.
-* `encrypt_root` - (Optional) Whether to encrypt the root disk for VMs using
this service offering.
- Changing this forces a new resource to be created.
+* `bytes_write_rate` - (Optional) Bytes write rate in bytes per second.
Changing this forces a new resource to be created.
-* `storage_tags` - (Optional) Storage tags to associate with the service
offering.
+* `bytes_write_rate_max` - (Optional) Burst bytes write rate in bytes per
second. Changing this forces a new resource to be created.
-* `service_offering_details` - (Optional) A map of service offering details
for GPU configuration and other advanced settings. Common keys include
`pciDevice` and `vgpuType` for GPU offerings.
- Changing this forces a new resource to be created.
+* `bytes_write_rate_max_length` - (Optional) Length of the burst bytes write
rate in seconds. Changing this forces a new resource to be created.
+
+* `iops_read_rate` - (Optional) IO requests read rate in IOPS. Changing this
forces a new resource to be created.
+
+* `iops_read_rate_max` - (Optional) Burst IO requests read rate in IOPS.
Changing this forces a new resource to be created.
+
+* `iops_read_rate_max_length` - (Optional) Length of the burst IO requests
read rate in seconds. Changing this forces a new resource to be created.
+
+* `iops_write_rate` - (Optional) IO requests write rate in IOPS. Changing this
forces a new resource to be created.
+
+* `iops_write_rate_max` - (Optional) Burst IO requests write rate in IOPS.
Changing this forces a new resource to be created.
+
+* `iops_write_rate_max_length` - (Optional) Length of the burst IO requests
write rate in seconds. Changing this forces a new resource to be created.
+
+### Dynamic Scaling and IOPS
+
+* `disk_iops_min` - (Optional) Minimum IOPS for the disk. Changing this forces
a new resource to be created.
+
+* `disk_iops_max` - (Optional) Maximum IOPS for the disk. Changing this forces
a new resource to be created.
+
+* `hypervisor_snapshot_reserve` - (Optional) Hypervisor snapshot reserve space
as a percent of a volume (for managed storage using Xen or VMware). Changing
this forces a new resource to be created.
+
+### High Availability and Performance
+
+* `offer_ha` - (Optional) Whether HA (High Availability) is enabled for the
service offering. Changing this forces a new resource to be created.
+
+* `limit_cpu_use` - (Optional) Restrict the CPU usage to the committed service
offering percentage. Changing this forces a new resource to be created.
+
+* `dynamic_scaling_enabled` - (Optional) Enable dynamic scaling of VM CPU and
memory. Changing this forces a new resource to be created.
+
+### Cache and Deployment
+
+* `cache_mode` - (Optional) The cache mode to use. Valid values: `none`,
`writeback`, `writethrough`. Changing this forces a new resource to be created.
+
+* `deployment_planner` - (Optional) The deployment planner heuristics used to
deploy VMs. Changing this forces a new resource to be created.
+
+### System VM Configuration
+
+* `is_system` - (Optional) Whether the offering is for system VMs. Changing
this forces a new resource to be created.
+
+* `system_vm_type` - (Optional) The system VM type. Required when `is_system`
is true. Valid values: `domainrouter`, `consoleproxy`, `secondarystoragevm`.
Changing this forces a new resource to be created.
+
+### Zone and Domain
+
+* `zone_id` - (Optional) The ID of the zone for which the service offering is
available. Changing this forces a new resource to be created.
+
+* `domain_id` - (Optional) The ID of the domain for which the service offering
is available. Changing this forces a new resource to be created.
+
+### Provisioning
+
+* `provisioning_type` - (Optional) Provisioning type used to create volumes.
Valid values: `thin`, `sparse`, `fat`. Changing this forces a new resource to
be created.
+
+* `is_volatile` - (Optional) If true, the VM's original root disk is destroyed
and recreated on every reboot. Changing this forces a new resource to be
created.
+
+### Advanced Settings
+
+* `service_offering_details` - (Optional) A map of service offering details
for GPU configuration and other advanced settings. Common keys include:
+ - `pciDevice` - PCI device for GPU passthrough
+ - `vgpuType` - vGPU type for GPU offerings
+
+ ~> **Note:** CloudStack may add system keys (like `External:key`,
`purge.db.entities`) to this map. Terraform automatically filters these out to
prevent state drift.
+
+ Changing this forces a new resource to be created.
## Attributes Reference
-The following attributes are exported:
+In addition to all arguments above, the following attributes are exported:
* `id` - The ID of the service offering.
+* `created` - The date when the service offering was created.
Review Comment:
The docs claim a created attribute is exported by the resource, but the
resource schema/Read implementation in this PR does not set a created field.
This will cause confusion for users.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]