diff --git a/go.mod b/go.mod index d10e015289..087a96bf74 100644 --- a/go.mod +++ b/go.mod @@ -38,7 +38,7 @@ require ( github.com/IBM/secrets-manager-go-sdk/v2 v2.0.15 github.com/IBM/vmware-go-sdk v0.1.5 github.com/IBM/vpc-beta-go-sdk v0.8.0 - github.com/IBM/vpc-go-sdk v0.73.0 + github.com/IBM/vpc-go-sdk v0.74.0 github.com/ScaleFT/sshkeys v0.0.0-20200327173127-6142f742bca5 github.com/akamai/AkamaiOPEN-edgegrid-golang v1.2.2 github.com/akamai/AkamaiOPEN-edgegrid-golang/v5 v5.0.0 diff --git a/go.sum b/go.sum index 83d14d411d..9070d6713c 100644 --- a/go.sum +++ b/go.sum @@ -125,6 +125,8 @@ github.com/IBM/go-sdk-core/v5 v5.6.3/go.mod h1:tt/B9rxLkRtglE7pvqLuYikgCXaZFL3bt github.com/IBM/go-sdk-core/v5 v5.9.5/go.mod h1:YlOwV9LeuclmT/qi/LAK2AsobbAP42veV0j68/rlZsE= github.com/IBM/go-sdk-core/v5 v5.10.2/go.mod h1:WZPFasUzsKab/2mzt29xPcfruSk5js2ywAPwW4VJjdI= github.com/IBM/go-sdk-core/v5 v5.17.4/go.mod h1:KsAAI7eStAWwQa4F96MLy+whYSh39JzNjklZRbN/8ns= +github.com/IBM/go-sdk-core/v5 v5.20.1 h1:dzeyifh1kfRLw8VfAIIS5okZYuqLTqplPZP/Kcsgdlo= +github.com/IBM/go-sdk-core/v5 v5.20.1/go.mod h1:Q3BYO6iDA2zweQPDGbNTtqft5tDcEpm6RTuqMlPcvbw= github.com/IBM/go-sdk-core/v5 v5.21.0 h1:DUnYhvC4SoC8T84rx5omnhY3+xcQg/Whyoa3mDPIMkk= github.com/IBM/go-sdk-core/v5 v5.21.0/go.mod h1:Q3BYO6iDA2zweQPDGbNTtqft5tDcEpm6RTuqMlPcvbw= github.com/IBM/ibm-backup-recovery-sdk-go v1.0.3 h1:9TZHocmCfgmF8TGVrpP1kFyQbjcqLNW7+bM07lefpKQ= @@ -170,6 +172,8 @@ github.com/IBM/vpc-beta-go-sdk v0.8.0 h1:cEPpv4iw3Ba5W2d0AWg3TIbKeJ8y1nPuUuibR5J github.com/IBM/vpc-beta-go-sdk v0.8.0/go.mod h1:hORgIyTFRzXrZIK9IohaWmCRBBlYiDRagsufi7M6akE= github.com/IBM/vpc-go-sdk v0.73.0 h1:gMVR6NSzw8Y7pCkcDa92+heQTzu5X64q8bnBBpLJpFE= github.com/IBM/vpc-go-sdk v0.73.0/go.mod h1:K3vVlje72PYE3ZRt1iouE+jSIq+vCyYzT1HiFC06hUA= +github.com/IBM/vpc-go-sdk v0.74.0 h1:41tRWn4Tw6r5so/tXsMEy6eYftSPOeRI1YGnECOydNw= +github.com/IBM/vpc-go-sdk v0.74.0/go.mod h1:8lX6TpeYBbx1Vd4KTgM3PPQ4y3auGOPuD6qq3UBDdug= github.com/Logicalis/asn1 v0.0.0-20190312173541-d60463189a56 h1:vuquMR410psHNax14XKNWa0Ae/kYgWJcXi0IFuX60N0= github.com/Logicalis/asn1 v0.0.0-20190312173541-d60463189a56/go.mod h1:Zb3OT4l0mf7P/GOs2w2Ilj5sdm5Whoq3pa24dAEBHFc= github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0= diff --git a/ibm/service/vpc/data_source_ibm_is_instance.go b/ibm/service/vpc/data_source_ibm_is_instance.go index 4e8eaf2252..99e8ca107a 100644 --- a/ibm/service/vpc/data_source_ibm_is_instance.go +++ b/ibm/service/vpc/data_source_ibm_is_instance.go @@ -251,6 +251,11 @@ func DataSourceIBMISInstance() *schema.Resource { Computed: true, Description: "The total bandwidth (in megabits per second) shared across the instance's network interfaces and storage volumes", }, + isInstanceVolumeBandwidthQoSMode: { + Type: schema.TypeString, + Computed: true, + Description: "The volume bandwidth QoS mode for this virtual server instance.", + }, isInstanceTotalNetworkBandwidth: { Type: schema.TypeInt, @@ -1473,6 +1478,12 @@ func instanceGetByName(context context.Context, d *schema.ResourceData, meta int } } + if instance.VolumeBandwidthQosMode != nil { + if err = d.Set(isInstanceVolumeBandwidthQoSMode, string(*instance.VolumeBandwidthQosMode)); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting volume_bandwidth_qos_mode: %s", err), "(Data) ibm_is_instance", "read", "set-volume_bandwidth_qos_mode").GetDiag() + } + } + if instance.TotalNetworkBandwidth != nil { if err = d.Set("total_network_bandwidth", flex.IntValue(instance.TotalNetworkBandwidth)); err != nil { return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting total_network_bandwidth: %s", err), "(Data) ibm_is_instance", "read", "set-total_network_bandwidth").GetDiag() diff --git a/ibm/service/vpc/data_source_ibm_is_instance_profile.go b/ibm/service/vpc/data_source_ibm_is_instance_profile.go index b1c045ccc9..d38cbe3e9c 100644 --- a/ibm/service/vpc/data_source_ibm_is_instance_profile.go +++ b/ibm/service/vpc/data_source_ibm_is_instance_profile.go @@ -780,6 +780,32 @@ func DataSourceIBMISInstanceProfile() *schema.Resource { }, }, }, + "volume_bandwidth_qos_modes": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "type": { + Type: schema.TypeString, + Computed: true, + Description: "The type for this profile field.", + }, + "default": { + Type: schema.TypeString, + Computed: true, + Description: "The default volume bandwidth QoS mode for this profile.", + }, + "values": { + Type: schema.TypeList, + Computed: true, + Description: "The permitted volume bandwidth QoS modes for an instance using this profile.", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, }, } } @@ -992,6 +1018,12 @@ func instanceProfileGet(context context.Context, d *schema.ResourceData, meta in return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting vcpu_count: %s", err), "(Data) ibm_is_instance_profile", "read", "set-vcpu_count").GetDiag() } } + if profile.VolumeBandwidthQosModes != nil { + err = d.Set("volume_bandwidth_qos_modes", dataSourceInstanceProfileFlattenVolumeBandwidthQoSMode(*profile.VolumeBandwidthQosModes.(*vpcv1.InstanceProfileVolumeBandwidthQoSModes))) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting volume_bandwidth_qos_modes: %s", err), "(Data) ibm_is_instance_profile", "read", "set-volume_bandwidth_qos_modes").GetDiag() + } + } return nil } @@ -1318,6 +1350,13 @@ func dataSourceInstanceProfileFlattenVcpuCount(result vpcv1.InstanceProfileVcpu) return finalList } +func dataSourceInstanceProfileFlattenVolumeBandwidthQoSMode(result vpcv1.InstanceProfileVolumeBandwidthQoSModes) (finalList []map[string]interface{}) { + finalList = []map[string]interface{}{} + finalMap := dataSourceInstanceProfileVolumeBandwidthQoSModeToMap(result) + finalList = append(finalList, finalMap) + + return finalList +} func dataSourceInstanceProfileVcpuCountToMap(vcpuCountItem vpcv1.InstanceProfileVcpu) (vcpuCountMap map[string]interface{}) { vcpuCountMap = map[string]interface{}{} @@ -1347,6 +1386,21 @@ func dataSourceInstanceProfileVcpuCountToMap(vcpuCountItem vpcv1.InstanceProfile return vcpuCountMap } +func dataSourceInstanceProfileVolumeBandwidthQoSModeToMap(volumeBandwidthQoSModeItem vpcv1.InstanceProfileVolumeBandwidthQoSModes) (volumeBandwidthQoSModeItemMap map[string]interface{}) { + volumeBandwidthQoSModeItemMap = map[string]interface{}{} + + if volumeBandwidthQoSModeItem.Type != nil { + volumeBandwidthQoSModeItemMap["type"] = volumeBandwidthQoSModeItem.Type + } + if volumeBandwidthQoSModeItem.Default != nil { + volumeBandwidthQoSModeItemMap["default"] = volumeBandwidthQoSModeItem.Default + } + if volumeBandwidthQoSModeItem.Values != nil { + volumeBandwidthQoSModeItemMap["values"] = volumeBandwidthQoSModeItem.Values + } + return volumeBandwidthQoSModeItemMap +} + func dataSourceInstanceProfileFlattenDisks(result []vpcv1.InstanceProfileDisk) (disks []map[string]interface{}) { for _, disksItem := range result { disks = append(disks, dataSourceInstanceProfileDisksToMap(disksItem)) diff --git a/ibm/service/vpc/data_source_ibm_is_instance_profile_test.go b/ibm/service/vpc/data_source_ibm_is_instance_profile_test.go index a43c45e14b..7f934f26e2 100644 --- a/ibm/service/vpc/data_source_ibm_is_instance_profile_test.go +++ b/ibm/service/vpc/data_source_ibm_is_instance_profile_test.go @@ -46,6 +46,43 @@ func TestAccIBMISInstanceProfileDataSource_basic(t *testing.T) { }, }) } + +func TestAccIBMISInstanceProfileDataSource_QoSMode(t *testing.T) { + resName := "data.ibm_is_instance_profile.test1" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccCheckIBMISInstanceProfileDataSourceConfig(), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resName, "name", acc.InstanceProfileName), + resource.TestCheckResourceAttrSet(resName, "family"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profile.test1", "bandwidth.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profile.test1", "family"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profile.test1", "href"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profile.test1", "memory.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profile.test1", "architecture"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profile.test1", "port_speed.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profile.test1", "vcpu_architecture.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profile.test1", "vcpu_count.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profile.test1", "vcpu_manufacturer.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profile.test1", "vcpu_manufacturer.0.type"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profile.test1", "vcpu_manufacturer.0.value"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profile.test1", "network_interface_count.0.type"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profile.test1", "network_attachment_count.0.type"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profile.test1", "network_attachment_count.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profile.test1", "reservation_terms.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profile.test1", "reservation_terms.0.type"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profile.test1", "reservation_terms.0.values"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profile.test1", "volume_bandwidth_qos_modes.#"), + ), + }, + }, + }) +} + func TestAccIBMISInstanceProfileDataSource_cluster(t *testing.T) { resName := "data.ibm_is_instance_profile.test1" diff --git a/ibm/service/vpc/data_source_ibm_is_instance_profiles.go b/ibm/service/vpc/data_source_ibm_is_instance_profiles.go index d7b96a7478..28c15ef5b6 100644 --- a/ibm/service/vpc/data_source_ibm_is_instance_profiles.go +++ b/ibm/service/vpc/data_source_ibm_is_instance_profiles.go @@ -759,6 +759,32 @@ func DataSourceIBMISInstanceProfiles() *schema.Resource { }, }, }, + "volume_bandwidth_qos_modes": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "type": { + Type: schema.TypeString, + Computed: true, + Description: "The type for this profile field.", + }, + "default": { + Type: schema.TypeString, + Computed: true, + Description: "The default volume bandwidth QoS mode for this profile.", + }, + "values": { + Type: schema.TypeList, + Computed: true, + Description: "The permitted volume bandwidth QoS modes for an instance using this profile.", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, "vcpu_manufacturer": &schema.Schema{ Type: schema.TypeList, Computed: true, @@ -948,6 +974,12 @@ func instanceProfilesList(context context.Context, d *schema.ResourceData, meta vcpuCountList = append(vcpuCountList, vcpuCountMap) l["vcpu_count"] = vcpuCountList } + if profile.VolumeBandwidthQosModes != nil { + volumeBandwidthQosModesList := []map[string]interface{}{} + volumeBandwidthQosModesMap := dataSourceInstanceProfileVolumeBandwidthQoSModeToMap(*profile.VolumeBandwidthQosModes.(*vpcv1.InstanceProfileVolumeBandwidthQoSModes)) + volumeBandwidthQosModesList = append(volumeBandwidthQosModesList, volumeBandwidthQosModesMap) + l["volume_bandwidth_qos_modes"] = volumeBandwidthQosModesList + } // Changes for manufacturer for AMD Support. // reduce the line of code here. - sumit's suggestions if profile.VcpuManufacturer != nil { diff --git a/ibm/service/vpc/data_source_ibm_is_instance_profiles_test.go b/ibm/service/vpc/data_source_ibm_is_instance_profiles_test.go index 0bea56e11e..d1b7fe84c6 100644 --- a/ibm/service/vpc/data_source_ibm_is_instance_profiles_test.go +++ b/ibm/service/vpc/data_source_ibm_is_instance_profiles_test.go @@ -47,6 +47,44 @@ func TestAccIBMISInstanceProfilesDataSource_basic(t *testing.T) { }, }) } + +func TestAccIBMISInstanceProfilesDataSource_QoS(t *testing.T) { + resName := "data.ibm_is_instance_profiles.test1" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccCheckIBMISInstanceProfilesDataSourceConfig(), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet(resName, "profiles.0.name"), + resource.TestCheckResourceAttrSet(resName, "profiles.0.family"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profiles.test1", "profiles.0.bandwidth.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profiles.test1", "profiles.0.family"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profiles.test1", "profiles.0.href"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profiles.test1", "profiles.0.memory.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profiles.test1", "profiles.0.architecture"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profiles.test1", "profiles.0.port_speed.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profiles.test1", "profiles.0.vcpu_architecture.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profiles.test1", "profiles.0.vcpu_count.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profiles.test1", "profiles.0.network_interface_count.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profiles.test1", "profiles.0.network_interface_count.0.type"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profiles.test1", "profiles.0.network_attachment_count.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profiles.test1", "profiles.0.network_attachment_count.0.type"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profiles.test1", "profiles.0.vcpu_manufacturer.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profiles.test1", "profiles.0.vcpu_manufacturer.0.type"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profiles.test1", "profiles.0.vcpu_manufacturer.0.value"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profiles.test1", "profiles.0.reservation_terms.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profiles.test1", "profiles.0.reservation_terms.0.type"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profiles.test1", "profiles.0.reservation_terms.0.values"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profiles.test1", "profiles.0.volume_bandwidth_qos_modes.#"), + ), + }, + }, + }) +} + func TestAccIBMISInstanceProfilesDataSource_cluster(t *testing.T) { resName := "data.ibm_is_instance_profiles.test1" diff --git a/ibm/service/vpc/data_source_ibm_is_instance_template.go b/ibm/service/vpc/data_source_ibm_is_instance_template.go index aa3beceaf7..4a7d42b27b 100644 --- a/ibm/service/vpc/data_source_ibm_is_instance_template.go +++ b/ibm/service/vpc/data_source_ibm_is_instance_template.go @@ -214,6 +214,11 @@ func DataSourceIBMISInstanceTemplate() *schema.Resource { Computed: true, Description: "The amount of bandwidth (in megabits per second) allocated exclusively to instance storage volumes", }, + isInstanceVolumeBandwidthQoSMode: { + Type: schema.TypeString, + Computed: true, + Description: "The volume bandwidth QoS mode for this virtual server instance.", + }, isInstanceDefaultTrustedProfileAutoLink: { Type: schema.TypeBool, Computed: true, @@ -1226,6 +1231,12 @@ func dataSourceIBMISInstanceTemplateRead(context context.Context, d *schema.Reso return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting total_volume_bandwidth: %s", err), "(Data) ibm_is_instance_template", "read", "set-total_volume_bandwidth").GetDiag() } } + if instanceTemplate.VolumeBandwidthQosMode != nil { + d.Set(isInstanceVolumeBandwidthQoSMode, string(*instanceTemplate.VolumeBandwidthQosMode)) + if err = d.Set(isInstanceVolumeBandwidthQoSMode, string(*instanceTemplate.VolumeBandwidthQosMode)); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting volume_bandwidth_qos_mode: %s", err), "(Data) ibm_is_instance_template", "read", "set-volume_bandwidth_qos_mode").GetDiag() + } + } if instanceTemplate.PrimaryNetworkInterface != nil { interfaceList := make([]map[string]interface{}, 0) @@ -1640,6 +1651,12 @@ func dataSourceIBMISInstanceTemplateRead(context context.Context, d *schema.Reso return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting total_volume_bandwidth: %s", err), "(Data) ibm_is_instance_template", "read", "set-total_volume_bandwidth").GetDiag() } } + if instanceTemplate.VolumeBandwidthQosMode != nil { + d.Set(isInstanceVolumeBandwidthQoSMode, string(*instanceTemplate.VolumeBandwidthQosMode)) + if err = d.Set(isInstanceVolumeBandwidthQoSMode, string(*instanceTemplate.VolumeBandwidthQosMode)); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting volume_bandwidth_qos_mode: %s", err), "(Data) ibm_is_instance_template", "read", "set-volume_bandwidth_qos_mode").GetDiag() + } + } if instanceTemplate.PrimaryNetworkInterface != nil { interfaceList := make([]map[string]interface{}, 0) @@ -2165,6 +2182,12 @@ func dataSourceIBMISInstanceTemplateRead(context context.Context, d *schema.Reso return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting total_volume_bandwidth: %s", err), "(Data) ibm_is_instance_template", "read", "set-total_volume_bandwidth").GetDiag() } } + if instanceTemplate.VolumeBandwidthQosMode != nil { + d.Set(isInstanceVolumeBandwidthQoSMode, string(*instanceTemplate.VolumeBandwidthQosMode)) + if err = d.Set(isInstanceVolumeBandwidthQoSMode, string(*instanceTemplate.VolumeBandwidthQosMode)); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting volume_bandwidth_qos_mode: %s", err), "(Data) ibm_is_instance_template", "read", "set-volume_bandwidth_qos_mode").GetDiag() + } + } if instanceTemplate.Image != nil { imageInf := instanceTemplate.Image @@ -2540,6 +2563,12 @@ func dataSourceIBMISInstanceTemplateRead(context context.Context, d *schema.Reso return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting total_volume_bandwidth: %s", err), "(Data) ibm_is_instance_template", "read", "set-total_volume_bandwidth").GetDiag() } } + if instanceTemplate.VolumeBandwidthQosMode != nil { + d.Set(isInstanceVolumeBandwidthQoSMode, string(*instanceTemplate.VolumeBandwidthQosMode)) + if err = d.Set(isInstanceVolumeBandwidthQoSMode, string(*instanceTemplate.VolumeBandwidthQosMode)); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting volume_bandwidth_qos_mode: %s", err), "(Data) ibm_is_instance_template", "read", "set-volume_bandwidth_qos_mode").GetDiag() + } + } if instanceTemplate.VPC != nil { vpcInf := instanceTemplate.VPC diff --git a/ibm/service/vpc/data_source_ibm_is_instance_template_test.go b/ibm/service/vpc/data_source_ibm_is_instance_template_test.go index 3e25fe8868..3ff4f1bef3 100644 --- a/ibm/service/vpc/data_source_ibm_is_instance_template_test.go +++ b/ibm/service/vpc/data_source_ibm_is_instance_template_test.go @@ -40,6 +40,36 @@ func TestAccIBMISInstanceTemplate_dataBasic(t *testing.T) { }, }) } + +func TestAccIBMISInstanceTemplate_QoS(t *testing.T) { + randInt := acctest.RandIntRange(600, 700) + publicKey := strings.TrimSpace(` + ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDQ+WiiUR1Jg3oGSmB/2//GJ3XnotriBiGN6t3iwGces6sUsvRkza1t0Mf05DKZxC/zp0WvDTvbit2gTkF9sD37OZSn5aCJk1F5URk/JNPmz25ZogkICFL4OUfhrE3mnyKio6Bk1JIEIypR5PRtGxY9vFDUfruADDLfRi+dGwHF6U9RpvrDRo3FNtI8T0GwvWwFE7bg63vLz65CjYY5XqH9z/YWz/asH6BKumkwiphLGhuGn03+DV6DkIZqr3Oh13UDjMnTdgv1y/Kou5UM3CK1dVsmLRXPEf2KUWUq1EwRfrJXkPOrBwn8to+Yydo57FgrRM9Qw8uzvKmnVxfKW6iG3oSGA0L6ROuCq1lq0MD8ySLd56+d1ftSDaUq+0/Yt9vK3olzVP0/iZobD7chbGqTLMCzL4/CaIUR/UmX08EA0Oh0DdyAdj3UUNETAj3W8gBrV6xLR7fZAJ8roX2BKb4K8Ed3YqzgiY0zgjqvpBYl9xZl0jgVX0qMFaEa6+CeGI8= root@ffd8363b1226 + `) + vpcName := fmt.Sprintf("testvpc%d", randInt) + subnetName := fmt.Sprintf("testsubnet%d", randInt) + templateName := fmt.Sprintf("testtemplate%d", randInt) + sshKeyName := fmt.Sprintf("testsshkey%d", randInt) + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIBMISInstanceGroupDestroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckIBMISInstanceTemplateDConfig(vpcName, subnetName, sshKeyName, publicKey, templateName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "data.ibm_is_instance_template.instance_template_data", "name", templateName), + resource.TestCheckResourceAttrSet( + "data.ibm_is_instance_template.instance_template_data", "availability_policy_host_failure"), + resource.TestCheckResourceAttrSet( + "data.ibm_is_instance_template.instance_template_data", "volume_bandwidth_qos_mode"), + ), + }, + }, + }) +} + func TestAccIBMISInstanceTemplateDatasourceCluster(t *testing.T) { randInt := acctest.RandIntRange(600, 700) publicKey := strings.TrimSpace(` diff --git a/ibm/service/vpc/data_source_ibm_is_instance_templates.go b/ibm/service/vpc/data_source_ibm_is_instance_templates.go index 48744aa57e..2cd462c511 100644 --- a/ibm/service/vpc/data_source_ibm_is_instance_templates.go +++ b/ibm/service/vpc/data_source_ibm_is_instance_templates.go @@ -278,6 +278,11 @@ func DataSourceIBMISInstanceTemplates() *schema.Resource { Computed: true, Description: "The amount of bandwidth (in megabits per second) allocated exclusively to instance storage volumes", }, + isInstanceVolumeBandwidthQoSMode: { + Type: schema.TypeString, + Computed: true, + Description: "The volume bandwidth QoS mode for this virtual server instance.", + }, isInstanceDefaultTrustedProfileAutoLink: { Type: schema.TypeBool, Computed: true, @@ -1177,6 +1182,10 @@ func dataSourceIBMISInstanceTemplatesRead(context context.Context, d *schema.Res template[isInstanceTotalVolumeBandwidth] = int(*instance.TotalVolumeBandwidth) } + if instance.VolumeBandwidthQosMode != nil { + template[isInstanceVolumeBandwidthQoSMode] = *instance.VolumeBandwidthQosMode + } + // vni networkAttachments := []map[string]interface{}{} @@ -1527,6 +1536,10 @@ func dataSourceIBMISInstanceTemplatesRead(context context.Context, d *schema.Res template[isInstanceTotalVolumeBandwidth] = int(*instance.TotalVolumeBandwidth) } + if instance.VolumeBandwidthQosMode != nil { + template[isInstanceVolumeBandwidthQoSMode] = *instance.VolumeBandwidthQosMode + } + // vni networkAttachments := []map[string]interface{}{} diff --git a/ibm/service/vpc/data_source_ibm_is_instance_templates_test.go b/ibm/service/vpc/data_source_ibm_is_instance_templates_test.go index c7d9331c89..73b4144291 100644 --- a/ibm/service/vpc/data_source_ibm_is_instance_templates_test.go +++ b/ibm/service/vpc/data_source_ibm_is_instance_templates_test.go @@ -40,6 +40,36 @@ func TestAccIBMISInstanceTemplates_dataBasic(t *testing.T) { }, }) } + +func TestAccIBMISInstanceTemplates_QoS(t *testing.T) { + randInt := acctest.RandIntRange(600, 700) + publicKey := strings.TrimSpace(` + ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDQ+WiiUR1Jg3oGSmB/2//GJ3XnotriBiGN6t3iwGces6sUsvRkza1t0Mf05DKZxC/zp0WvDTvbit2gTkF9sD37OZSn5aCJk1F5URk/JNPmz25ZogkICFL4OUfhrE3mnyKio6Bk1JIEIypR5PRtGxY9vFDUfruADDLfRi+dGwHF6U9RpvrDRo3FNtI8T0GwvWwFE7bg63vLz65CjYY5XqH9z/YWz/asH6BKumkwiphLGhuGn03+DV6DkIZqr3Oh13UDjMnTdgv1y/Kou5UM3CK1dVsmLRXPEf2KUWUq1EwRfrJXkPOrBwn8to+Yydo57FgrRM9Qw8uzvKmnVxfKW6iG3oSGA0L6ROuCq1lq0MD8ySLd56+d1ftSDaUq+0/Yt9vK3olzVP0/iZobD7chbGqTLMCzL4/CaIUR/UmX08EA0Oh0DdyAdj3UUNETAj3W8gBrV6xLR7fZAJ8roX2BKb4K8Ed3YqzgiY0zgjqvpBYl9xZl0jgVX0qMFaEa6+CeGI8= root@ffd8363b1226 + `) + vpcName := fmt.Sprintf("testvpc%d", randInt) + subnetName := fmt.Sprintf("testsubnet%d", randInt) + templateName := fmt.Sprintf("testtemplate%d", randInt) + sshKeyName := fmt.Sprintf("testsshkey%d", randInt) + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIBMISInstanceGroupDestroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckIBMISInstanceTemplatesDConfig(vpcName, subnetName, sshKeyName, publicKey, templateName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet( + "data.ibm_is_instance_templates.instance_templates_data", "templates.0.id"), + resource.TestCheckResourceAttrSet( + "data.ibm_is_instance_templates.instance_templates_data", "templates.0.name"), + resource.TestCheckResourceAttrSet( + "data.ibm_is_instance_templates.instance_templates_data", "templates.0.volume_bandwidth_qos_mode"), + ), + }, + }, + }) +} + func TestAccIBMISInstanceTemplatesDataSourceCluster(t *testing.T) { randInt := acctest.RandIntRange(600, 700) publicKey := strings.TrimSpace(` diff --git a/ibm/service/vpc/data_source_ibm_is_instances.go b/ibm/service/vpc/data_source_ibm_is_instances.go index 6d9c3da751..a28c8f5119 100644 --- a/ibm/service/vpc/data_source_ibm_is_instances.go +++ b/ibm/service/vpc/data_source_ibm_is_instances.go @@ -1015,6 +1015,12 @@ func DataSourceIBMISInstances() *schema.Resource { Description: "The total bandwidth (in megabits per second) shared across the instance's network interfaces and storage volumes", }, + isInstanceVolumeBandwidthQoSMode: { + Type: schema.TypeString, + Computed: true, + Description: "The volume bandwidth QoS mode for this virtual server instance.", + }, + isInstanceTotalNetworkBandwidth: { Type: schema.TypeInt, Computed: true, @@ -1506,6 +1512,9 @@ func instancesList(context context.Context, d *schema.ResourceData, meta interfa if instance.Bandwidth != nil { l[isInstanceBandwidth] = int(*instance.Bandwidth) } + if instance.VolumeBandwidthQosMode != nil { + l[isInstanceVolumeBandwidthQoSMode] = string(*instance.VolumeBandwidthQosMode) + } if instance.TotalNetworkBandwidth != nil { l[isInstanceTotalNetworkBandwidth] = int(*instance.TotalNetworkBandwidth) diff --git a/ibm/service/vpc/data_source_ibm_is_instances_test.go b/ibm/service/vpc/data_source_ibm_is_instances_test.go index b9cbbfe570..394e2e8f3f 100644 --- a/ibm/service/vpc/data_source_ibm_is_instances_test.go +++ b/ibm/service/vpc/data_source_ibm_is_instances_test.go @@ -63,6 +63,58 @@ ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCKVmnMOlHKcZK8tpt3MP1lqOLAcqcJzhsvJcjscgVE }, }) } + +func TestAccIBMISInstancesDataSource_QoSMode(t *testing.T) { + var instance string + vpcname := fmt.Sprintf("tfins-vpc-%d", acctest.RandIntRange(10, 100)) + subnetname := fmt.Sprintf("tfins-subnet-%d", acctest.RandIntRange(10, 100)) + publicKey := strings.TrimSpace(` +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCKVmnMOlHKcZK8tpt3MP1lqOLAcqcJzhsvJcjscgVERRN7/9484SOBJ3HSKxxNG5JN8owAjy5f9yYwcUg+JaUVuytn5Pv3aeYROHGGg+5G346xaq3DAwX6Y5ykr2fvjObgncQBnuU5KHWCECO/4h8uWuwh/kfniXPVjFToc+gnkqA+3RKpAecZhFXwfalQ9mMuYGFxn+fwn8cYEApsJbsEmb0iJwPiZ5hjFC8wREuiTlhPHDgkBLOiycd20op2nXzDbHfCHInquEe/gYxEitALONxm0swBOwJZwlTDOB7C6y2dzlrtxr1L59m7pCkWI4EtTRLvleehBoj3u7jB4usR +`) + sshname := fmt.Sprintf("tfins-ssh-%d", acctest.RandIntRange(10, 100)) + instanceName := fmt.Sprintf("tfins-name-%d", acctest.RandIntRange(10, 100)) + resName := "data.ibm_is_instances.ds_instances" + userData := "a" + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccCheckIBMISInstanceConfig(vpcname, subnetname, sshname, publicKey, instanceName, userData), + Check: resource.ComposeTestCheckFunc( + testAccCheckIBMISInstanceExists("ibm_is_instance.testacc_instance", instance), + resource.TestCheckResourceAttr( + "ibm_is_instance.testacc_instance", "name", instanceName), + resource.TestCheckResourceAttr( + "ibm_is_instance.testacc_instance", "zone", acc.ISZoneName), + ), + }, + { + Config: testAccCheckIBMISInstancesDataSourceConfig(), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet(resName, "instances.0.name"), + resource.TestCheckResourceAttrSet(resName, "instances.0.memory"), + resource.TestCheckResourceAttrSet(resName, "instances.0.status"), + resource.TestCheckResourceAttrSet(resName, "instances.0.resource_group"), + resource.TestCheckResourceAttrSet(resName, "instances.0.vpc"), + resource.TestCheckResourceAttrSet(resName, "instances.0.boot_volume.#"), + resource.TestCheckResourceAttrSet(resName, "instances.0.volume_attachments.#"), + resource.TestCheckResourceAttrSet(resName, "instances.0.primary_network_interface.#"), + resource.TestCheckResourceAttrSet(resName, "instances.0.network_interfaces.#"), + resource.TestCheckResourceAttrSet(resName, "instances.0.profile"), + resource.TestCheckResourceAttrSet(resName, "instances.0.vcpu.#"), + resource.TestCheckResourceAttrSet(resName, "instances.0.zone"), + resource.TestCheckResourceAttrSet(resName, "instances.0.availability_policy_host_failure"), + resource.TestCheckResourceAttrSet(resName, "instances.0.lifecycle_state"), + resource.TestCheckResourceAttr(resName, "instances.0.lifecycle_reasons.#", "0"), + resource.TestCheckResourceAttrSet(resName, "instances.0.vcpu.0.manufacturer"), + resource.TestCheckResourceAttrSet(resName, "instances.0.volume_bandwidth_qos_mode"), + ), + }, + }, + }) +} + func TestAccIBMISInstancesDS_basicCluster(t *testing.T) { // var instance string // vpcname := fmt.Sprintf("tfins-vpc-%d", acctest.RandIntRange(10, 100)) diff --git a/ibm/service/vpc/resource_ibm_is_instance.go b/ibm/service/vpc/resource_ibm_is_instance.go index a8cfd5e2e0..0d54b379fd 100644 --- a/ibm/service/vpc/resource_ibm_is_instance.go +++ b/ibm/service/vpc/resource_ibm_is_instance.go @@ -130,6 +130,7 @@ const ( isInstanceMetadataServiceEnabled1 = "enabled" isInstanceMetadataServiceProtocol = "protocol" isInstanceMetadataServiceRespHopLimit = "response_hop_limit" + isInstanceVolumeBandwidthQoSMode = "volume_bandwidth_qos_mode" ) func ResourceIBMISInstance() *schema.Resource { @@ -480,6 +481,14 @@ func ResourceIBMISInstance() *schema.Resource { Description: "The amount of bandwidth (in megabits per second) allocated exclusively to instance storage volumes", }, + isInstanceVolumeBandwidthQoSMode: &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + ValidateFunc: validate.InvokeValidator("ibm_is_instance", isInstanceVolumeBandwidthQoSMode), + Description: "The volume bandwidth QoS mode for this virtual server instance.", + }, + isInstanceBandwidth: { Type: schema.TypeInt, Computed: true, @@ -2251,6 +2260,17 @@ func ResourceIBMISInstanceValidator() *validate.ResourceValidator { MinValueLength: 1, MaxValueLength: 128}) + validateSchema = append(validateSchema, validate.ValidateSchema{ + Identifier: isInstanceVolumeBandwidthQoSMode, + ValidateFunctionIdentifier: validate.ValidateAllowedStringValue, + Type: validate.TypeString, + Optional: true, + AllowedValues: "pooled, weighted", + Regexp: `^[a-z][a-z0-9]*(_[a-z0-9]+)*$`, + MinValueLength: 1, + MaxValueLength: 128, + }) + ibmISInstanceValidator := validate.ResourceValidator{ResourceName: "ibm_is_instance", Schema: validateSchema} return &ibmISInstanceValidator } @@ -2420,6 +2440,10 @@ func instanceCreateByImage(context context.Context, d *schema.ResourceData, meta totalVolBandwidthStr := int64(totalVolBandwidthIntf.(int)) instanceproto.TotalVolumeBandwidth = &totalVolBandwidthStr } + if volumeBandwidthQoSModeIntf, ok := d.GetOk(isInstanceVolumeBandwidthQoSMode); ok { + volumeBandwidthQoSModeStr := volumeBandwidthQoSModeIntf.(string) + instanceproto.VolumeBandwidthQosMode = &volumeBandwidthQoSModeStr + } if dHostIdInf, ok := d.GetOk(isPlacementTargetDedicatedHost); ok { dHostIdStr := dHostIdInf.(string) dHostPlaementTarget := &vpcv1.InstancePlacementTargetPrototypeDedicatedHostIdentity{ @@ -3026,6 +3050,10 @@ func instanceCreateByCatalogOffering(context context.Context, d *schema.Resource totalVolBandwidthStr := int64(totalVolBandwidthIntf.(int)) instanceproto.TotalVolumeBandwidth = &totalVolBandwidthStr } + if volumeBandwidthQoSModeIntf, ok := d.GetOk(isInstanceVolumeBandwidthQoSMode); ok { + volumeBandwidthQoSModeStr := volumeBandwidthQoSModeIntf.(string) + instanceproto.VolumeBandwidthQosMode = &volumeBandwidthQoSModeStr + } if dHostIdInf, ok := d.GetOk(isPlacementTargetDedicatedHost); ok { dHostIdStr := dHostIdInf.(string) dHostPlaementTarget := &vpcv1.InstancePlacementTargetPrototypeDedicatedHostIdentity{ @@ -3572,7 +3600,10 @@ func instanceCreateByTemplate(context context.Context, d *schema.ResourceData, m totalVolBandwidthStr := int64(totalVolBandwidthIntf.(int)) instanceproto.TotalVolumeBandwidth = &totalVolBandwidthStr } - + if volumeBandwidthQoSModeIntf, ok := d.GetOk(isInstanceVolumeBandwidthQoSMode); ok { + volumeBandwidthQoSModeStr := volumeBandwidthQoSModeIntf.(string) + instanceproto.VolumeBandwidthQosMode = &volumeBandwidthQoSModeStr + } if vpcID != "" { instanceproto.VPC = &vpcv1.VPCIdentity{ ID: &vpcID, @@ -4279,6 +4310,10 @@ func instanceCreateBySnapshot(context context.Context, d *schema.ResourceData, m totalVolBandwidthStr := int64(totalVolBandwidthIntf.(int)) instanceproto.TotalVolumeBandwidth = &totalVolBandwidthStr } + if volumeBandwidthQoSModeIntf, ok := d.GetOk(isInstanceVolumeBandwidthQoSMode); ok { + volumeBandwidthQoSModeStr := volumeBandwidthQoSModeIntf.(string) + instanceproto.VolumeBandwidthQosMode = &volumeBandwidthQoSModeStr + } if networkattachmentsintf, ok := d.GetOk("network_attachments"); ok { networkAttachments := []vpcv1.InstanceNetworkAttachmentPrototype{} @@ -4802,6 +4837,10 @@ func instanceCreateByVolume(context context.Context, d *schema.ResourceData, met totalVolBandwidthStr := int64(totalVolBandwidthIntf.(int)) instanceproto.TotalVolumeBandwidth = &totalVolBandwidthStr } + if volumeBandwidthQoSModeIntf, ok := d.GetOk(isInstanceVolumeBandwidthQoSMode); ok { + volumeBandwidthQoSModeStr := volumeBandwidthQoSModeIntf.(string) + instanceproto.VolumeBandwidthQosMode = &volumeBandwidthQoSModeStr + } if networkattachmentsintf, ok := d.GetOk("network_attachments"); ok { networkAttachments := []vpcv1.InstanceNetworkAttachmentPrototype{} for i, networkAttachmentsItem := range networkattachmentsintf.([]interface{}) { @@ -5438,6 +5477,12 @@ func instanceGet(context context.Context, d *schema.ResourceData, meta interface return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_instance", "read", "set-total_volume_bandwidth").GetDiag() } } + if instance.VolumeBandwidthQosMode != nil { + if err = d.Set(isInstanceVolumeBandwidthQoSMode, string(*instance.VolumeBandwidthQosMode)); err != nil { + err = fmt.Errorf("Error setting volume_bandwidth_qos_mode: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_instance", "read", "set-volume_bandwidth_qos_mode").GetDiag() + } + } if err = d.Set("memory", flex.IntValue(instance.Memory)); err != nil { err = fmt.Errorf("Error setting memory: %s", err) @@ -7330,7 +7375,7 @@ func instanceUpdate(context context.Context, d *schema.ResourceData, meta interf } - if (d.HasChange(isInstanceName) || d.HasChange("confidential_compute_mode") || d.HasChange("enable_secure_boot")) && !d.IsNewResource() { + if (d.HasChange(isInstanceName) || d.HasChange("confidential_compute_mode") || d.HasChange("enable_secure_boot") || d.HasChange(isInstanceVolumeBandwidthQoSMode)) && !d.IsNewResource() { restartNeeded := false serverstopped := false name := d.Get(isInstanceName).(string) @@ -7344,6 +7389,12 @@ func instanceUpdate(context context.Context, d *schema.ResourceData, meta interf } if _, ok := d.GetOkExists("enable_secure_boot"); ok && d.HasChange("enable_secure_boot") { instanceCCMPatchModel.EnableSecureBoot = core.BoolPtr(d.Get("enable_secure_boot").(bool)) + restartNeeded = true + } + + if _, ok := d.GetOkExists(isInstanceVolumeBandwidthQoSMode); ok && d.HasChange(isInstanceVolumeBandwidthQoSMode) { + instanceCCMPatchModel.VolumeBandwidthQosMode = core.StringPtr(d.Get(isInstanceVolumeBandwidthQoSMode).(string)) + restartNeeded = true } if d.HasChange("name") { instanceCCMPatchModel.Name = &name diff --git a/ibm/service/vpc/resource_ibm_is_instance_template.go b/ibm/service/vpc/resource_ibm_is_instance_template.go index cec5e8a9c8..b19db8c657 100644 --- a/ibm/service/vpc/resource_ibm_is_instance_template.go +++ b/ibm/service/vpc/resource_ibm_is_instance_template.go @@ -326,7 +326,13 @@ func ResourceIBMISInstanceTemplate() *schema.Resource { ValidateFunc: validate.InvokeValidator("ibm_is_instance_template", isInstanceTotalVolumeBandwidth), Description: "The amount of bandwidth (in megabits per second) allocated exclusively to instance storage volumes", }, - + isInstanceVolumeBandwidthQoSMode: { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validate.InvokeValidator("ibm_is_instance_template", isInstanceVolumeBandwidthQoSMode), + Description: "The volume bandwidth QoS mode for this virtual server instance.", + }, isInstanceTemplateKeys: { Type: schema.TypeSet, Required: true, @@ -1411,6 +1417,16 @@ func ResourceIBMISInstanceTemplateValidator() *validate.ResourceValidator { Regexp: `^[A-Za-z0-9:_ .-]+$`, MinValueLength: 1, MaxValueLength: 128}) + validateSchema = append(validateSchema, validate.ValidateSchema{ + Identifier: isInstanceVolumeBandwidthQoSMode, + ValidateFunctionIdentifier: validate.ValidateAllowedStringValue, + Type: validate.TypeString, + Optional: true, + AllowedValues: "pooled, weighted", + Regexp: `^[a-z][a-z0-9]*(_[a-z0-9]+)*$`, + MinValueLength: 1, + MaxValueLength: 128, + }) ibmISInstanceTemplateValidator := validate.ResourceValidator{ResourceName: "ibm_is_instance_template", Schema: validateSchema} return &ibmISInstanceTemplateValidator } @@ -1648,6 +1664,11 @@ func instanceTemplateCreateBySourceSnapshot(context context.Context, d *schema.R instanceproto.TotalVolumeBandwidth = &totalVolBandwidthStr } + if volumeBandwidthQoSModeIntf, ok := d.GetOk(isInstanceVolumeBandwidthQoSMode); ok { + volumeBandwidthQoSModeStr := volumeBandwidthQoSModeIntf.(string) + instanceproto.VolumeBandwidthQosMode = &volumeBandwidthQoSModeStr + } + // BOOT VOLUME ATTACHMENT for instance template if boot, ok := d.GetOk(isInstanceTemplateBootVolume); ok { bootvol := boot.([]interface{})[0].(map[string]interface{}) @@ -2207,6 +2228,11 @@ func instanceTemplateCreateByCatalogOffering(context context.Context, d *schema. instanceproto.TotalVolumeBandwidth = &totalVolBandwidthStr } + if volumeBandwidthQoSModeIntf, ok := d.GetOk(isInstanceVolumeBandwidthQoSMode); ok { + volumeBandwidthQoSModeStr := volumeBandwidthQoSModeIntf.(string) + instanceproto.VolumeBandwidthQosMode = &volumeBandwidthQoSModeStr + } + // BOOT VOLUME ATTACHMENT for instance template if boot, ok := d.GetOk(isInstanceTemplateBootVolume); ok { bootvol := boot.([]interface{})[0].(map[string]interface{}) @@ -2759,6 +2785,11 @@ func instanceTemplateCreate(context context.Context, d *schema.ResourceData, met instanceproto.TotalVolumeBandwidth = &totalVolBandwidthStr } + if volumeBandwidthQoSModeIntf, ok := d.GetOk(isInstanceVolumeBandwidthQoSMode); ok { + volumeBandwidthQoSModeStr := volumeBandwidthQoSModeIntf.(string) + instanceproto.VolumeBandwidthQosMode = &volumeBandwidthQoSModeStr + } + // BOOT VOLUME ATTACHMENT for instance template if boot, ok := d.GetOk(isInstanceTemplateBootVolume); ok { bootvol := boot.([]interface{})[0].(map[string]interface{}) @@ -3300,6 +3331,12 @@ func instanceTemplateGet(context context.Context, d *schema.ResourceData, meta i return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_instance_template", "read", "set-total_volume_bandwidth").GetDiag() } } + if instanceTemplate.VolumeBandwidthQosMode != nil { + if err = d.Set(isInstanceVolumeBandwidthQoSMode, string(*instanceTemplate.VolumeBandwidthQosMode)); err != nil { + err = fmt.Errorf("Error setting volume_bandwidth_qos_mode: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_instance_template", "read", "set-volume_bandwidth_qos_mode").GetDiag() + } + } if instanceTemplate.MetadataService != nil { if err = d.Set(isInstanceTemplateMetadataServiceEnabled, instanceTemplate.MetadataService.Enabled); err != nil { err = fmt.Errorf("Error setting metadata_service_enabled: %s", err) @@ -3752,6 +3789,12 @@ func instanceTemplateGet(context context.Context, d *schema.ResourceData, meta i return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_instance_template", "read", "set-total_volume_bandwidth").GetDiag() } } + if instanceTemplate.VolumeBandwidthQosMode != nil { + if err = d.Set(isInstanceVolumeBandwidthQoSMode, string(*instanceTemplate.VolumeBandwidthQosMode)); err != nil { + err = fmt.Errorf("Error setting volume_bandwidth_qos_mode: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_instance_template", "read", "set-volume_bandwidth_qos_mode").GetDiag() + } + } if instanceTemplate.MetadataService != nil { if err = d.Set(isInstanceTemplateMetadataServiceEnabled, instanceTemplate.MetadataService.Enabled); err != nil { err = fmt.Errorf("Error setting metadata_service_enabled: %s", err) diff --git a/ibm/service/vpc/resource_ibm_is_instance_template_test.go b/ibm/service/vpc/resource_ibm_is_instance_template_test.go index fa30702326..43eba139cf 100644 --- a/ibm/service/vpc/resource_ibm_is_instance_template_test.go +++ b/ibm/service/vpc/resource_ibm_is_instance_template_test.go @@ -1532,3 +1532,75 @@ func testAccCheckIBMISInstanceTemplateWith_AllowedUse(vpcname, subnetname, sshna `, templateName, apiVersion, bareMetalServer, instanceVal, apiVersion, bareMetalServer, instanceVal, acc.ISZoneName) } + +func TestAccIBMISInstanceTemplate_QoSMode(t *testing.T) { + randInt := acctest.RandIntRange(10, 100) + + publicKey := strings.TrimSpace(` + ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDVtuCfWKVGKaRmaRG6JQZY8YdxnDgGzVOK93IrV9R5Hl0JP1oiLLWlZQS2reAKb8lBqyDVEREpaoRUDjqDqXG8J/kR42FKN51su914pjSBc86wJ02VtT1Wm1zRbSg67kT+g8/T1jCgB5XBODqbcICHVP8Z1lXkgbiHLwlUrbz6OZkGJHo/M/kD1Eme8lctceIYNz/Ilm7ewMXZA4fsidpto9AjyarrJLufrOBl4MRVcZTDSJ7rLP982aHpu9pi5eJAjOZc7Og7n4ns3NFppiCwgVMCVUQbN5GBlWhZ1OsT84ZiTf+Zy8ew+Yg5T7Il8HuC7loWnz+esQPf0s3xhC/kTsGgZreIDoh/rxJfD67wKXetNSh5RH/n5BqjaOuXPFeNXmMhKlhj9nJ8scayx/wsvOGuocEIkbyJSLj3sLUU403OafgatEdnJOwbqg6rUNNF5RIjpJpL7eEWlKIi1j9LyhmPJ+fEO7TmOES82VpCMHpLbe4gf/MhhJ/Xy8DKh9s= root@ffd8363b1226 + `) + vpcName := fmt.Sprintf("tf-testvpc%d", randInt) + subnetName := fmt.Sprintf("tf-testsubnet%d", randInt) + templateName := fmt.Sprintf("tf-testtemplate%d", randInt) + sshKeyName := fmt.Sprintf("tf-testsshkey%d", randInt) + qosMode := "pooled" + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIBMISInstanceTemplateDestroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckIBMISInstanceTemplateConfig_QoSMode(vpcName, subnetName, sshKeyName, publicKey, templateName, qosMode), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "ibm_is_instance_template.instancetemplate1", "name", templateName), + resource.TestCheckResourceAttrSet( + "ibm_is_instance_template.instancetemplate1", "profile"), + resource.TestCheckResourceAttr( + "ibm_is_instance_template.instancetemplate1", "volume_bandwidth_qos_mode", qosMode), + ), + }, + }, + }) +} + +func testAccCheckIBMISInstanceTemplateConfig_QoSMode(vpcName, subnetName, sshKeyName, publicKey, templateName, qosMode string) string { + return fmt.Sprintf(` + resource "ibm_is_vpc" "vpc2" { + name = "%s" + } + + resource "ibm_is_subnet" "subnet2" { + name = "%s" + vpc = ibm_is_vpc.vpc2.id + zone = "us-south-2" + ipv4_cidr_block = "10.240.64.0/28" + } + + resource "ibm_is_ssh_key" "sshkey" { + name = "%s" + public_key = "%s" + } + + data "ibm_is_images" "is_images" { + } + + resource "ibm_is_instance_template" "instancetemplate1" { + name = "%s" + image = data.ibm_is_images.is_images.images.0.id + profile = "bx2-8x32" + + primary_network_interface { + subnet = ibm_is_subnet.subnet2.id + } + + vpc = ibm_is_vpc.vpc2.id + zone = "us-south-2" + keys = [ibm_is_ssh_key.sshkey.id] + volume_bandwidth_qos_mode = "%s" + } + + + `, vpcName, subnetName, sshKeyName, publicKey, templateName, qosMode) + +} diff --git a/ibm/service/vpc/resource_ibm_is_instance_test.go b/ibm/service/vpc/resource_ibm_is_instance_test.go index 3b8f4179b3..d12f772a92 100644 --- a/ibm/service/vpc/resource_ibm_is_instance_test.go +++ b/ibm/service/vpc/resource_ibm_is_instance_test.go @@ -775,6 +775,55 @@ ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCKVmnMOlHKcZK8tpt3MP1lqOLAcqcJzhsvJcjscgVE }) } +func TestAccIBMISInstance_QoS(t *testing.T) { + var instance string + vpcname := fmt.Sprintf("tf-vpc-%d", acctest.RandIntRange(10, 100)) + name := fmt.Sprintf("tf-instnace-%d", acctest.RandIntRange(10, 100)) + subnetname := fmt.Sprintf("tf-subnet-%d", acctest.RandIntRange(10, 100)) + publicKey := strings.TrimSpace(` +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCKVmnMOlHKcZK8tpt3MP1lqOLAcqcJzhsvJcjscgVERRN7/9484SOBJ3HSKxxNG5JN8owAjy5f9yYwcUg+JaUVuytn5Pv3aeYROHGGg+5G346xaq3DAwX6Y5ykr2fvjObgncQBnuU5KHWCECO/4h8uWuwh/kfniXPVjFToc+gnkqA+3RKpAecZhFXwfalQ9mMuYGFxn+fwn8cYEApsJbsEmb0iJwPiZ5hjFC8wREuiTlhPHDgkBLOiycd20op2nXzDbHfCHInquEe/gYxEitALONxm0swBOwJZwlTDOB7C6y2dzlrtxr1L59m7pCkWI4EtTRLvleehBoj3u7jB4usR +`) + sshname := fmt.Sprintf("tf-ssh-%d", acctest.RandIntRange(10, 100)) + totalVolumeBandwidth := 1000 + qosMode := "weighted" + qosModeUpdated := "weighted" + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIBMISInstanceDestroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckIBMISInstanceQOSConfig(vpcname, subnetname, sshname, publicKey, name, qosMode, totalVolumeBandwidth), + Check: resource.ComposeTestCheckFunc( + testAccCheckIBMISInstanceExists("ibm_is_instance.testacc_instance", instance), + resource.TestCheckResourceAttr( + "ibm_is_instance.testacc_instance", "name", name), + resource.TestCheckResourceAttr( + "ibm_is_instance.testacc_instance", "zone", acc.ISZoneName), + resource.TestCheckResourceAttr( + "ibm_is_instance.testacc_instance", "total_volume_bandwidth", strconv.Itoa(totalVolumeBandwidth)), + resource.TestCheckResourceAttr( + "ibm_is_instance.testacc_instance", "volume_bandwidth_qos_mode", qosMode), + ), + }, + { + Config: testAccCheckIBMISInstanceQOSConfig(vpcname, subnetname, sshname, publicKey, name, qosModeUpdated, totalVolumeBandwidth), + Check: resource.ComposeTestCheckFunc( + testAccCheckIBMISInstanceExists("ibm_is_instance.testacc_instance", instance), + resource.TestCheckResourceAttr( + "ibm_is_instance.testacc_instance", "name", name), + resource.TestCheckResourceAttr( + "ibm_is_instance.testacc_instance", "zone", acc.ISZoneName), + resource.TestCheckResourceAttr( + "ibm_is_instance.testacc_instance", "total_volume_bandwidth", strconv.Itoa(totalVolumeBandwidth)), + resource.TestCheckResourceAttr( + "ibm_is_instance.testacc_instance", "volume_bandwidth_qos_mode", qosModeUpdated), + ), + }, + }, + }) +} + func TestAccIBMISInstanceWithSecurityGroup_basic(t *testing.T) { var instance string vpcname := fmt.Sprintf("tf-vpc-%d", acctest.RandIntRange(10, 100)) @@ -1985,6 +2034,43 @@ func testAccCheckIBMISInstanceRenameConfig(vpcname, subnetname, sshname, publicK `, vpcname, subnetname, acc.ISZoneName, acc.ISCIDR, sshname, publicKey, name, acc.IsImage, acc.InstanceProfileName, rename, userData, acc.ISZoneName) } +func testAccCheckIBMISInstanceQOSConfig(vpcname, subnetname, sshname, publicKey, name, qosMode string, bandwidth int) string { + return fmt.Sprintf(` + resource "ibm_is_vpc" "testacc_vpc" { + name = "%s" + } + + resource "ibm_is_subnet" "testacc_subnet" { + name = "%s" + vpc = ibm_is_vpc.testacc_vpc.id + zone = "%s" + ipv4_cidr_block = "%s" + } + + resource "ibm_is_ssh_key" "testacc_sshkey" { + name = "%s" + public_key = "%s" + } + + resource "ibm_is_instance" "testacc_instance" { + name = "%s" + image = "%s" + profile = "%s" + primary_network_interface { + subnet = ibm_is_subnet.testacc_subnet.id + } + total_volume_bandwidth = %d + vpc = ibm_is_vpc.testacc_vpc.id + zone = "%s" + keys = [ibm_is_ssh_key.testacc_sshkey.id] + network_interfaces { + subnet = ibm_is_subnet.testacc_subnet.id + name = "eth1" + } + volume_bandwidth_qos_mode = "%s" + }`, vpcname, subnetname, acc.ISZoneName, acc.ISCIDR, sshname, publicKey, name, acc.IsImage, acc.InstanceProfileName, bandwidth, acc.ISZoneName, qosMode) +} + func testAccCheckIBMISInstanceBandwidthConfig(vpcname, subnetname, sshname, publicKey, name string, bandwidth int) string { return fmt.Sprintf(` resource "ibm_is_vpc" "testacc_vpc" { diff --git a/website/docs/d/is_instance.html.markdown b/website/docs/d/is_instance.html.markdown index 18b9c10a9b..cc90440ec0 100644 --- a/website/docs/d/is_instance.html.markdown +++ b/website/docs/d/is_instance.html.markdown @@ -381,4 +381,5 @@ In addition to all argument reference list, you can access the following attribu - `name` - (String) The name of the volume attachment. - `volume_id` - (String) The ID of the volume that is associated with the volume attachment. - `volume_name` - (String) The name of the volume that is associated with the volume attachment. +- `volume_bandwidth_qos_mode` - (String) The volume bandwidth QoS mode to use for this virtual server instance. - `zone` - (String) The zone where the instance was created. diff --git a/website/docs/d/is_instance_profile.html.markdown b/website/docs/d/is_instance_profile.html.markdown index 7d9c593aba..635066e1cc 100644 --- a/website/docs/d/is_instance_profile.html.markdown +++ b/website/docs/d/is_instance_profile.html.markdown @@ -206,3 +206,9 @@ In addition to the argument reference list, you can access the following attribu - `default` - (String) The default VCPU manufacturer for an instance with this profile. - `type` - (String) The type for this profile field. - `value` - (String) The VCPU manufacturer for an instance with this profile. +- `volume_bandwidth_qos_modes` - (List) Nested `volume_bandwidth_qos_modes` blocks have the following structure: + + Nested scheme for `volume_bandwidth_qos_modes`: + - `default` - (String) The default volume bandwidth QoS mode for this profile. + - `type` - (String) The type for this profile field. + - `values` - (String) The permitted volume bandwidth QoS modes for an instance using this profile. diff --git a/website/docs/d/is_instance_profiles.html.markdown b/website/docs/d/is_instance_profiles.html.markdown index 5bbc7a3b17..4c3dec1686 100644 --- a/website/docs/d/is_instance_profiles.html.markdown +++ b/website/docs/d/is_instance_profiles.html.markdown @@ -207,4 +207,10 @@ You can access the following attribute references after your data source is crea Nested scheme for `vcpu_manufacturer`: - `default` - (String) The default VCPU manufacturer for an instance with this profile. - `type` - (String) The type for this profile field. - - `value` - (String) The VCPU manufacturer for an instance with this profile. \ No newline at end of file + - `value` - (String) The VCPU manufacturer for an instance with this profile. + - `volume_bandwidth_qos_modes` - (List) Nested `volume_bandwidth_qos_modes` blocks have the following structure: + + Nested scheme for `volume_bandwidth_qos_modes`: + - `default` - (String) The default volume bandwidth QoS mode for this profile. + - `type` - (String) The type for this profile field. + - `values` - (String) The permitted volume bandwidth QoS modes for an instance using this profile. \ No newline at end of file diff --git a/website/docs/d/is_instance_template.html.markdown b/website/docs/d/is_instance_template.html.markdown index d062b3e288..c4ac4bd071 100644 --- a/website/docs/d/is_instance_template.html.markdown +++ b/website/docs/d/is_instance_template.html.markdown @@ -274,5 +274,6 @@ You can access the following attribute references after your data source is crea - `profile` - (String) The global unique name for the volume profile to use for the volume. - `source_snapshot` - The snapshot to use as a source for the volume's data. To create a volume from a `source_snapshot`, the volume profile and the source snapshot must have the same `storage_generation` value. - `tags` - (String) User Tags associated with the volume. (https://cloud.ibm.com/apidocs/tagging#types-of-tags) +- `volume_bandwidth_qos_mode` - (String) The volume bandwidth QoS mode to use for this virtual server instance. - `vpc` - (String) The VPC ID that the instance templates needs to be created. - `zone` - (String) The name of the zone. diff --git a/website/docs/d/is_instance_templates.html.markdown b/website/docs/d/is_instance_templates.html.markdown index b2eb739bcf..ded6bd3d74 100644 --- a/website/docs/d/is_instance_templates.html.markdown +++ b/website/docs/d/is_instance_templates.html.markdown @@ -261,5 +261,6 @@ You can access the following attribute references after your data source is crea - `profile` - (String) The global unique name for the volume profile to use for the volume. - `source_snapshot` - The snapshot to use as a source for the volume's data. To create a volume from a `source_snapshot`, the volume profile and the source snapshot must have the same `storage_generation` value. - `tags` - (String) User Tags associated with the volume. (https://cloud.ibm.com/apidocs/tagging#types-of-tags) + - `volume_bandwidth_qos_mode` - (String) The volume bandwidth QoS mode to use for this virtual server instance. - `vpc` - (String) The VPC ID that the instance templates needs to be created. - `zone` - (String) The name of the zone. diff --git a/website/docs/d/is_instances.html.markdown b/website/docs/d/is_instances.html.markdown index 32fd8110be..f0b0f2bcc9 100644 --- a/website/docs/d/is_instances.html.markdown +++ b/website/docs/d/is_instances.html.markdown @@ -313,5 +313,6 @@ In addition to all argument reference list, you can access the following attribu - `architecture` - (String) The architecture of the virtual CPU. - `manufacturer` - (String) The manufacturer of the virtual CPU. - `count`- (Integer) The number of virtual CPUs that are allocated to the instance. + - `volume_bandwidth_qos_mode` - (String) The volume bandwidth QoS mode to use for this virtual server instance. - `vpc` - (String) The ID of the VPC that the instance belongs to. - `zone` - (String) The zone where the instance was created. diff --git a/website/docs/r/is_instance.html.markdown b/website/docs/r/is_instance.html.markdown index e6edb31218..9a16844aea 100644 --- a/website/docs/r/is_instance.html.markdown +++ b/website/docs/r/is_instance.html.markdown @@ -955,6 +955,7 @@ Review the argument references that you can specify for your resource. **•** `gpu.memory` - (integer) The overall amount of GPU memory in GiB (gibibytes).
**•** `gpu.model` - (string) The GPU model.
**•** `enable_secure_boot` - (boolean) Indicates whether secure boot is enabled.
+- `volume_bandwidth_qos_mode` - (Optional, String) The volume bandwidth QoS mode to use for this virtual server instance. The specified value must be listed in the instance profile's volume_bandwidth_qos_modes. If unspecified, the default volume bandwidth QoS mode from the profile will be used. - `vpc` - (Required, Forces new resource, String) The ID of the VPC where you want to create the instance. When using `instance_template`, `vpc` is not required. - `zone` - (Required, Forces new resource, String) The name of the VPC zone where you want to create the instance. When using `instance_template`, `zone` is not required. diff --git a/website/docs/r/is_instance_template.html.markdown b/website/docs/r/is_instance_template.html.markdown index a41a351c62..df7ba29540 100644 --- a/website/docs/r/is_instance_template.html.markdown +++ b/website/docs/r/is_instance_template.html.markdown @@ -534,6 +534,7 @@ Review the argument references that you can specify for your resource. ~>**Note:** `volume_attachments` provides either `volume` with a storage volume ID, or `volume_prototype` to create a new volume. If you plan to use this template with instance group, provide the `volume_prototype`. Instance group does not support template with existing storage volume IDs. +- `volume_bandwidth_qos_mode` - (Optional, String) The volume bandwidth QoS mode to use for this virtual server instance. The specified value must be listed in the instance profile's volume_bandwidth_qos_modes. If unspecified, the default volume bandwidth QoS mode from the profile will be used. - `vpc` - (Required, String) The VPC ID that the instance templates needs to be created. - `user_data` - (Optional, String) The user data provided for the instance. - `zone` - (Required, String) The name of the zone.