diff --git a/ibm/acctest/acctest.go b/ibm/acctest/acctest.go index dbcc0de99e..7f56a6de32 100644 --- a/ibm/acctest/acctest.go +++ b/ibm/acctest/acctest.go @@ -240,6 +240,7 @@ var ( Pi_spp_placement_group_id string Pi_storage_connection string Pi_target_storage_tier string + Pi_virtual_serial_number string Pi_volume_clone_task_id string Pi_volume_group_id string Pi_volume_group_name string @@ -1322,6 +1323,12 @@ func init() { fmt.Println("[INFO] Set the environment variable PI_VOLUME_CLONE_TASK_ID for testing Pi_volume_clone_task_id resource else it is set to default value 'terraform-test-volume-clone-task-id'") } + Pi_virtual_serial_number = os.Getenv("PI_VIRTUAL_SERIAL_NUMBER") + if Pi_volume_clone_task_id == "" { + Pi_volume_clone_task_id = "terraform_test_power" + fmt.Println("[INFO] Set the environment variable PI_VIRTUAL_SERIAL_NUMBER for testing ibm_pi_virtual_serial_number data source else it is set to default value 'terraform-test-power'") + } + Pi_resource_group_id = os.Getenv("PI_RESOURCE_GROUP_ID") if Pi_resource_group_id == "" { Pi_resource_group_id = "" diff --git a/ibm/provider/provider.go b/ibm/provider/provider.go index 71d6d365a5..1dfaffcd87 100644 --- a/ibm/provider/provider.go +++ b/ibm/provider/provider.go @@ -708,6 +708,8 @@ func Provider() *schema.Provider { "ibm_pi_storage_types_capacity": power.DataSourceIBMPIStorageTypesCapacity(), "ibm_pi_system_pools": power.DataSourceIBMPISystemPools(), "ibm_pi_tenant": power.DataSourceIBMPITenant(), + "ibm_pi_virtual_serial_number": power.DataSourceIBMPIVirtualSerialNumber(), + "ibm_pi_virtual_serial_numbers": power.DataSourceIBMPIVirtualSerialNumbers(), "ibm_pi_volume_clone": power.DataSourceIBMPIVolumeClone(), "ibm_pi_volume_flash_copy_mappings": power.DataSourceIBMPIVolumeFlashCopyMappings(), "ibm_pi_volume_group_details": power.DataSourceIBMPIVolumeGroupDetails(), @@ -1370,6 +1372,7 @@ func Provider() *schema.Provider { "ibm_pi_shared_processor_pool": power.ResourceIBMPISharedProcessorPool(), "ibm_pi_snapshot": power.ResourceIBMPISnapshot(), "ibm_pi_spp_placement_group": power.ResourceIBMPISPPPlacementGroup(), + "ibm_pi_virtual_serial_number": power.ResourceIBMPIVirtualSerialNumber(), "ibm_pi_volume_attach": power.ResourceIBMPIVolumeAttach(), "ibm_pi_volume_clone": power.ResourceIBMPIVolumeClone(), "ibm_pi_volume_group_action": power.ResourceIBMPIVolumeGroupAction(), diff --git a/ibm/service/power/data_source_ibm_pi_instance.go b/ibm/service/power/data_source_ibm_pi_instance.go index 95d20b330e..bb2f9b4e78 100644 --- a/ibm/service/power/data_source_ibm_pi_instance.go +++ b/ibm/service/power/data_source_ibm_pi_instance.go @@ -232,6 +232,25 @@ func DataSourceIBMPIInstance() *schema.Resource { Description: "The virtual cores that are assigned to the instance.", Type: schema.TypeInt, }, + Attr_VirtualSerialNumber: { + Computed: true, + Description: "Virtual Serial Number information", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + Attr_Description: { + Computed: true, + Description: "Description of the Virtual Serial Number", + Type: schema.TypeString, + }, + Attr_Serial: { + Computed: true, + Description: "Virtual serial number.", + Type: schema.TypeString, + }, + }, + }, + Type: schema.TypeList, + }, Attr_Volumes: { Computed: true, Description: "List of volume IDs that are attached to the instance.", @@ -311,6 +330,9 @@ func dataSourceIBMPIInstancesRead(ctx context.Context, d *schema.ResourceData, m if powervmdata.Fault != nil { d.Set(Attr_Fault, flattenPvmInstanceFault(powervmdata.Fault)) } + if powervmdata.VirtualSerialNumber != nil { + d.Set(Attr_VirtualSerialNumber, flattenVirtualSerialNumberToList(powervmdata.VirtualSerialNumber)) + } return nil } diff --git a/ibm/service/power/data_source_ibm_pi_instances.go b/ibm/service/power/data_source_ibm_pi_instances.go index fcfc9ff25c..3eaf053446 100644 --- a/ibm/service/power/data_source_ibm_pi_instances.go +++ b/ibm/service/power/data_source_ibm_pi_instances.go @@ -213,6 +213,25 @@ func DataSourceIBMPIInstances() *schema.Resource { Description: "The virtual cores that are assigned to the instance.", Type: schema.TypeInt, }, + Attr_VirtualSerialNumber: { + Computed: true, + Description: "Virtual Serial Number information", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + Attr_Description: { + Computed: true, + Description: "Description of the Virtual Serial Number", + Type: schema.TypeString, + }, + Attr_Serial: { + Computed: true, + Description: "Virtual serial number.", + Type: schema.TypeString, + }, + }, + }, + Type: schema.TypeList, + }, }, }, Type: schema.TypeList, @@ -290,6 +309,10 @@ func flattenPvmInstances(list []*models.PVMInstanceReference, meta interface{}) l[Attr_Fault] = flattenPvmInstanceFault(i.Fault) } + if i.VirtualSerialNumber != nil { + l[Attr_VirtualSerialNumber] = flattenVirtualSerialNumberToList(i.VirtualSerialNumber) + } + result = append(result, l) } return result diff --git a/ibm/service/power/data_source_ibm_pi_virtual_serial_number.go b/ibm/service/power/data_source_ibm_pi_virtual_serial_number.go new file mode 100644 index 0000000000..3e53008b1c --- /dev/null +++ b/ibm/service/power/data_source_ibm_pi_virtual_serial_number.go @@ -0,0 +1,73 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package power + +import ( + "context" + + "github.com/IBM-Cloud/power-go-client/clients/instance" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" +) + +// Datasource to get a virtual serial number in a power instance +func DataSourceIBMPIVirtualSerialNumber() *schema.Resource { + return &schema.Resource{ + ReadContext: dataSourceIBMPIVirtualSerialNumberRead, + Schema: map[string]*schema.Schema{ + // Arguments + Arg_CloudInstanceID: { + Description: "The GUID of the service instance associated with an account.", + Required: true, + Type: schema.TypeString, + ValidateFunc: validation.NoZeroValues, + }, + Arg_Serial: { + Description: "Virtual serial number.", + Required: true, + Type: schema.TypeString, + ValidateFunc: validation.NoZeroValues, + }, + + // Attributes + Attr_Description: { + Computed: true, + Description: "Description of virtual serial number.", + Type: schema.TypeString, + }, + Attr_InstanceID: { + Computed: true, + Description: "ID of PVM instance virtual serial number is attached to.", + Type: schema.TypeString, + }, + }, + } +} + +func dataSourceIBMPIVirtualSerialNumberRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + sess, err := meta.(conns.ClientSession).IBMPISession() + if err != nil { + return diag.FromErr(err) + } + + cloudInstanceID := d.Get(Arg_CloudInstanceID).(string) + client := instance.NewIBMPIVSNClient(ctx, sess, cloudInstanceID) + + vsnInput := d.Get(Arg_Serial).(string) + virtualSerialNumberData, err := client.Get(vsnInput) + if err != nil { + return diag.FromErr(err) + } + + id := *virtualSerialNumberData.Serial + d.SetId(id) + d.Set(Attr_Description, virtualSerialNumberData.Description) + if virtualSerialNumberData.PvmInstanceID != nil { + d.Set(Attr_InstanceID, virtualSerialNumberData.PvmInstanceID) + } + + return nil +} diff --git a/ibm/service/power/data_source_ibm_pi_virtual_serial_number_test.go b/ibm/service/power/data_source_ibm_pi_virtual_serial_number_test.go new file mode 100644 index 0000000000..b55842dafc --- /dev/null +++ b/ibm/service/power/data_source_ibm_pi_virtual_serial_number_test.go @@ -0,0 +1,37 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package power_test + +import ( + "fmt" + "testing" + + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func TestAccIBMPIVirtualSerialNumber(t *testing.T) { + vsnData := "data.ibm_pi_virtual_serial_number.testacc_virtual_serial_number" + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccCheckIBMPIVirtualSerialNumberConfig(), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet(vsnData, "id"), + ), + }, + }, + }) +} + +func testAccCheckIBMPIVirtualSerialNumberConfig() string { + return fmt.Sprintf(` + data "ibm_pi_virtual_serial_number" "testacc_virtual_serial_number" { + pi_cloud_instance_id = "%s" + pi_serial = "%s" + }`, acc.Pi_cloud_instance_id, acc.Pi_virtual_serial_number) +} diff --git a/ibm/service/power/data_source_ibm_pi_virtual_serial_numbers.go b/ibm/service/power/data_source_ibm_pi_virtual_serial_numbers.go new file mode 100644 index 0000000000..095838e7c4 --- /dev/null +++ b/ibm/service/power/data_source_ibm_pi_virtual_serial_numbers.go @@ -0,0 +1,96 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package power + +import ( + "context" + + "github.com/IBM-Cloud/power-go-client/clients/instance" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/hashicorp/go-uuid" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" +) + +// Datasource to list Cloud Connections in a power instance +func DataSourceIBMPIVirtualSerialNumbers() *schema.Resource { + return &schema.Resource{ + ReadContext: dataSourceIBMPIVirtualSerialNumbersRead, + Schema: map[string]*schema.Schema{ + // Arguments + Arg_CloudInstanceID: { + Description: "The GUID of the service instance associated with an account.", + Required: true, + Type: schema.TypeString, + ValidateFunc: validation.NoZeroValues, + }, + Arg_InstanceID: { + Description: "ID of PVM instance to get virtual serial number attached to.", + Optional: true, + Type: schema.TypeString, + }, + + // Attributes + Attr_VirtualSerialNumbers: { + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + Attr_Description: { + Computed: true, + Description: "Description of virtual serial number.", + Type: schema.TypeString, + }, + Attr_InstanceID: { + Computed: true, + Description: "ID of PVM instance virtual serial number is attached to.", + Type: schema.TypeString, + }, + Attr_Serial: { + Computed: true, + Description: "Virtual Serial Number.", + Type: schema.TypeString, + }, + }, + }, + Type: schema.TypeList, + }, + }, + } +} + +func dataSourceIBMPIVirtualSerialNumbersRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + sess, err := meta.(conns.ClientSession).IBMPISession() + if err != nil { + return diag.FromErr(err) + } + + cloudInstanceID := d.Get(Arg_CloudInstanceID).(string) + + client := instance.NewIBMPIVSNClient(ctx, sess, cloudInstanceID) + + var pvmInstanceID string + if instanceID, ok := d.GetOk(Arg_InstanceID); ok { + pvmInstanceID = instanceID.(string) + } + + vsns, err := client.GetAll(&pvmInstanceID) + if err != nil { + return diag.FromErr(err) + } + + vsnMapList := make([]map[string]interface{}, 0) + for _, vsn := range vsns { + v := make(map[string]interface{}) + v[Attr_Description] = vsn.Description + v[Attr_InstanceID] = vsn.PvmInstanceID + v[Attr_Serial] = vsn.Serial + vsnMapList = append(vsnMapList, v) + } + + var clientgenU, _ = uuid.GenerateUUID() + d.SetId(clientgenU) + d.Set(Attr_VirtualSerialNumbers, vsnMapList) + return nil +} diff --git a/ibm/service/power/data_source_ibm_pi_virtual_serial_numbers_test.go b/ibm/service/power/data_source_ibm_pi_virtual_serial_numbers_test.go new file mode 100644 index 0000000000..85f9ebfeb9 --- /dev/null +++ b/ibm/service/power/data_source_ibm_pi_virtual_serial_numbers_test.go @@ -0,0 +1,37 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package power_test + +import ( + "fmt" + "testing" + + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func TestAccIBMPIVirtualSerialNumbers(t *testing.T) { + vsnData := "data.ibm_pi_virtual_serial_numbers.testacc_virtual_serial_numbers" + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccCheckIBMPIVirtualSerialNumbersConfig(), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet(vsnData, "id"), + resource.TestCheckResourceAttrSet(vsnData, "virtual_serial_numbers.#"), + ), + }, + }, + }) +} + +func testAccCheckIBMPIVirtualSerialNumbersConfig() string { + return fmt.Sprintf(` + data "ibm_pi_virtual_serial_numbers" "testacc_virtual_serial_numbers" { + pi_cloud_instance_id = "%s" + }`, acc.Pi_cloud_instance_id) +} diff --git a/ibm/service/power/ibm_pi_constants.go b/ibm/service/power/ibm_pi_constants.go index 53513daffc..6c8400cf06 100644 --- a/ibm/service/power/ibm_pi_constants.go +++ b/ibm/service/power/ibm_pi_constants.go @@ -73,10 +73,12 @@ const ( Arg_ReplicationScheme = "pi_replication_scheme" Arg_ReplicationSites = "pi_replication_sites" Arg_ResourceGroupID = "pi_resource_group_id" + Arg_RetainVirtualSerialNumber = "pi_retain_virtual_serial_number" Arg_SAP = "sap" Arg_SAPDeploymentType = "pi_sap_deployment_type" Arg_SAPProfileID = "pi_sap_profile_id" Arg_Secondaries = "pi_secondaries" + Arg_Serial = "pi_serial" Arg_SharedProcessorPool = "pi_shared_processor_pool" Arg_SharedProcessorPoolHostGroup = "pi_shared_processor_pool_host_group" Arg_SharedProcessorPoolID = "pi_shared_processor_pool_id" @@ -103,6 +105,7 @@ const ( Arg_UserTags = "pi_user_tags" Arg_VirtualCoresAssigned = "pi_virtual_cores_assigned" Arg_VirtualOpticalDevice = "pi_virtual_optical_device" + Arg_VirtualSerialNumber = "pi_virtual_serial_number" Arg_VolumeCloneName = "pi_volume_clone_name" Arg_VolumeCloneTaskID = "pi_volume_clone_task_id" Arg_VolumeGroupID = "pi_volume_group_id" @@ -338,6 +341,7 @@ const ( Attr_Rules = "rules" Attr_SAPS = "saps" Attr_Secondaries = "secondaries" + Attr_Serial = "serial" Attr_ServerName = "server_name" Attr_Servers = "servers" Attr_Shareable = "shreable" @@ -407,6 +411,8 @@ const ( Attr_VCPUs = "vcpus" Attr_Vendor = "vendor" Attr_VirtualCoresAssigned = "virtual_cores_assigned" + Attr_VirtualSerialNumber = "virtual_serial_number" + Attr_VirtualSerialNumbers = "virtual_serial_numbers" Attr_VLanID = "vlan_id" Attr_VolumeGroupID = "volume_group_id" Attr_VolumeGroupName = "volume_group_name" @@ -452,6 +458,7 @@ const ( Allow = "allow" AntiAffinity = "anti-affinity" Attach = "attach" + AutoAssign = "auto-assign" BYOL = "byol" Capped = "capped" Critical = "CRITICAL" diff --git a/ibm/service/power/resource_ibm_pi_instance.go b/ibm/service/power/resource_ibm_pi_instance.go index c73c01bd14..ecf9c280b9 100644 --- a/ibm/service/power/resource_ibm_pi_instance.go +++ b/ibm/service/power/resource_ibm_pi_instance.go @@ -1,4 +1,4 @@ -// Copyright IBM Corp. 2017, 2021 All Rights Reserved. +// Copyright IBM Corp. 2017, 2021, 2024 All Rights Reserved. // Licensed under the Mozilla Public License v2.0 package power @@ -258,6 +258,12 @@ func ResourceIBMPIInstance() *schema.Resource { Set: schema.HashString, Type: schema.TypeSet, }, + Arg_RetainVirtualSerialNumber: { + Default: false, + Description: "Indicates whether to retain virtual serial number when changed or deleted.", + Optional: true, + Type: schema.TypeBool, + }, Arg_SAPProfileID: { ConflictsWith: []string{Arg_Processors, Arg_Memory, Arg_ProcType}, Description: "SAP Profile ID for the amount of cores and memory", @@ -333,6 +339,28 @@ func ResourceIBMPIInstance() *schema.Resource { Type: schema.TypeString, ValidateFunc: validate.ValidateAllowedStringValues([]string{Attach}), }, + Arg_VirtualSerialNumber: { + ConflictsWith: []string{Arg_SAPProfileID}, + Description: "Virtual Serial Number information", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + Attr_Description: { + Description: "Description of the Virtual Serial Number", + Optional: true, + Type: schema.TypeString, + }, + Attr_Serial: { + Description: "Provide an existing reserved Virtual Serial Number or specify 'auto-assign' for auto generated Virtual Serial Number.", + Required: true, + DiffSuppressFunc: supressVSNDiffAutoAssign, + Type: schema.TypeString, + }, + }, + }, + MaxItems: 1, + Optional: true, + Type: schema.TypeList, + }, Arg_VolumeIDs: { Description: "List of PI volumes", DiffSuppressFunc: flex.ApplyOnce, @@ -635,6 +663,13 @@ func resourceIBMPIInstanceRead(ctx context.Context, d *schema.ResourceData, meta } else { d.Set(Attr_Fault, nil) } + + if powervmdata.VirtualSerialNumber != nil { + d.Set(Arg_VirtualSerialNumber, flattenVirtualSerialNumberToList(powervmdata.VirtualSerialNumber)) + } else { + d.Set(Arg_VirtualSerialNumber, nil) + } + return nil } @@ -940,6 +975,76 @@ func resourceIBMPIInstanceUpdate(ctx context.Context, d *schema.ResourceData, me } } + if d.HasChange(Arg_VirtualSerialNumber) { + vsnClient := instance.NewIBMPIVSNClient(ctx, sess, cloudInstanceID) + + if d.HasChange(Arg_VirtualSerialNumber + ".0." + Attr_Serial) { + instanceRestart := false + status := d.Get(Attr_Status).(string) + if strings.ToLower(status) != State_Shutoff { + err := stopLparForResourceChange(ctx, client, instanceID, d) + if err != nil { + return diag.FromErr(err) + } + instanceRestart = true + } + + oldVSN, newVSN := d.GetChange(Arg_VirtualSerialNumber) + if len(oldVSN.([]interface{})) > 0 { + retainVSN := d.Get(Arg_RetainVirtualSerialNumber).(bool) + deleteBody := &models.DeleteServerVirtualSerialNumber{ + RetainVSN: retainVSN, + } + err := vsnClient.PVMInstanceDeleteVSN(instanceID, deleteBody) + if err != nil { + return diag.FromErr(err) + } + + _, err = isWaitForPIInstanceStopped(ctx, client, instanceID, d.Timeout(schema.TimeoutUpdate)) + if err != nil { + return diag.FromErr(err) + } + } + + if len(newVSN.([]interface{})) > 0 { + newVSNMap := newVSN.([]interface{})[0].(map[string]interface{}) + description := newVSNMap[Attr_Description].(string) + serial := newVSNMap[Attr_Serial].(string) + addBody := &models.AddServerVirtualSerialNumber{ + Description: description, + Serial: &serial, + } + _, err := vsnClient.PVMInstanceAttachVSN(instanceID, addBody) + if err != nil { + return diag.FromErr(err) + } + + _, err = isWaitForPIInstanceStopped(ctx, client, instanceID, d.Timeout(schema.TimeoutUpdate)) + if err != nil { + return diag.FromErr(err) + } + } + + if instanceRestart { + err = startLparAfterResourceChange(ctx, client, instanceID, d) + if err != nil { + return diag.FromErr(err) + } + } + } + + if !d.HasChange(Arg_VirtualSerialNumber+".0."+Attr_Serial) && d.HasChange(Arg_VirtualSerialNumber+".0."+Attr_Description) { + newDescriptionString := d.Get(Arg_VirtualSerialNumber + ".0." + Attr_Description).(string) + updateBody := &models.UpdateServerVirtualSerialNumber{ + Description: &newDescriptionString, + } + _, err = vsnClient.PVMInstanceUpdateVSN(instanceID, updateBody) + if err != nil { + return diag.FromErr(err) + } + } + } + return resourceIBMPIInstanceRead(ctx, d, meta) } @@ -957,7 +1062,15 @@ func resourceIBMPIInstanceDelete(ctx context.Context, d *schema.ResourceData, me cloudInstanceID := idArr[0] client := instance.NewIBMPIInstanceClient(ctx, sess, cloudInstanceID) for _, instanceID := range idArr[1:] { - err = client.Delete(instanceID) + retainVSNBool := d.Get(Arg_RetainVirtualSerialNumber).(bool) + if _, ok := d.GetOk(Arg_VirtualSerialNumber); ok && retainVSNBool { + body := &models.PVMInstanceDelete{ + RetainVSN: &retainVSNBool, + } + err = client.DeleteWithBody(instanceID, body) + } else { + err = client.Delete(instanceID) + } if err != nil { return diag.FromErr(err) } @@ -1703,6 +1816,12 @@ func createPVMInstance(d *schema.ResourceData, client *instance.IBMPIInstanceCli if tags, ok := d.GetOk(Arg_UserTags); ok { body.UserTags = flex.FlattenSet(tags.(*schema.Set)) } + if vsn, ok := d.GetOk(Arg_VirtualSerialNumber); ok { + vsnListType := vsn.([]interface{}) + vsnCreateModel := vsnSetToCreateModel(vsnListType, d) + body.VirtualSerialNumber = vsnCreateModel + } + pvmList, err := client.Create(body) if err != nil { @@ -1732,3 +1851,29 @@ func splitID(id string) (id1, id2 string, err error) { id2 = parts[1] return } +func vsnSetToCreateModel(vsnSetList []interface{}, d *schema.ResourceData) *models.CreateServerVirtualSerialNumber { + vsnItemMap := vsnSetList[0].(map[string]interface{}) + serialString := vsnItemMap[Attr_Serial].(string) + model := &models.CreateServerVirtualSerialNumber{ + Serial: &serialString, + } + description := vsnItemMap[Attr_Description].(string) + if description != "" { + model.Description = description + } + + return model +} +func flattenVirtualSerialNumberToList(vsn *models.GetServerVirtualSerialNumber) []map[string]interface{} { + v := make([]map[string]interface{}, 1) + v[0] = map[string]interface{}{ + Attr_Description: vsn.Description, + Attr_Serial: vsn.Serial, + } + return v +} + +// Do not show a diff if VSN is changed to existing assigned VSN +func supressVSNDiffAutoAssign(k, old, new string, d *schema.ResourceData) bool { + return new == old || (new == AutoAssign && old != "") +} diff --git a/ibm/service/power/resource_ibm_pi_instance_test.go b/ibm/service/power/resource_ibm_pi_instance_test.go index 7c2974f1d2..7dd77ce04a 100644 --- a/ibm/service/power/resource_ibm_pi_instance_test.go +++ b/ibm/service/power/resource_ibm_pi_instance_test.go @@ -872,6 +872,64 @@ func TestAccIBMPIInstanceDeploymentTypeNoStorage(t *testing.T) { }) } +func TestAccIBMPIInstanceVirtualSerialNumber(t *testing.T) { + instanceRes := "ibm_pi_instance.power_instance" + name := fmt.Sprintf("tf-pi-instance-%d", acctest.RandIntRange(10, 100)) + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIBMPIInstanceDestroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckIBMPIInstanceVirtualSerialNumber(name, power.OK, "s922"), + Check: resource.ComposeTestCheckFunc( + testAccCheckIBMPIInstanceExists(instanceRes), + resource.TestCheckResourceAttr(instanceRes, "pi_instance_name", name), + resource.TestCheckResourceAttrSet(instanceRes, "pi_virtual_serial_number.0.serial"), + resource.TestCheckResourceAttr(instanceRes, "pi_virtual_serial_number.0.description", "VSN for TF test"), + ), + }, + }, + }) +} + +func testAccCheckIBMPIInstanceVirtualSerialNumber(name, instanceHealthStatus, systype string) string { + return fmt.Sprintf(` + resource "ibm_pi_key" "key" { + pi_cloud_instance_id = "%[1]s" + pi_key_name = "%[2]s" + pi_ssh_key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCKVmnMOlHKcZK8tpt3MP1lqOLAcqcJzhsvJcjscgVERRN7/9484SOBJ3HSKxxNG5JN8owAjy5f9yYwcUg+JaUVuytn5Pv3aeYROHGGg+5G346xaq3DAwX6Y5ykr2fvjObgncQBnuU5KHWCECO/4h8uWuwh/kfniXPVjFToc+gnkqA+3RKpAecZhFXwfalQ9mMuYGFxn+fwn8cYEApsJbsEmb0iJwPiZ5hjFC8wREuiTlhPHDgkBLOiycd20op2nXzDbHfCHInquEe/gYxEitALONxm0swBOwJZwlTDOB7C6y2dzlrtxr1L59m7pCkWI4EtTRLvleehBoj3u7jB4usR" + } + data "ibm_pi_image" "power_image" { + pi_cloud_instance_id = "%[1]s" + pi_image_name = "%[3]s" + } + data "ibm_pi_network" "power_networks" { + pi_cloud_instance_id = "%[1]s" + pi_network_name = "%[4]s" + } + resource "ibm_pi_instance" "power_instance" { + pi_cloud_instance_id = "%[1]s" + pi_health_status = "%[5]s" + pi_image_id = data.ibm_pi_image.power_image.id + pi_instance_name = "%[2]s" + pi_key_pair_name = ibm_pi_key.key.name + pi_memory = "2" + pi_proc_type = "shared" + pi_processors = "0.25" + pi_storage_type = "%[7]s" + pi_sys_type = "%[6]s" + pi_network { + network_id = data.ibm_pi_network.power_networks.id + } + pi_virtual_serial_number { + serial = "auto-assign" + description = "VSN for TF test" + } + } + `, acc.Pi_cloud_instance_id, name, acc.Pi_image, acc.Pi_network_name, instanceHealthStatus, systype, acc.PiStorageType) +} + func TestAccIBMPIInstanceDeploymentGRS(t *testing.T) { instanceRes := "ibm_pi_instance.power_instance" bootVolumeData := "data.ibm_pi_volume.power_boot_volume_data" diff --git a/ibm/service/power/resource_ibm_pi_virtual_serial_number.go b/ibm/service/power/resource_ibm_pi_virtual_serial_number.go new file mode 100644 index 0000000000..14b1f17156 --- /dev/null +++ b/ibm/service/power/resource_ibm_pi_virtual_serial_number.go @@ -0,0 +1,398 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package power + +import ( + "context" + "fmt" + "strings" + "time" + + "github.com/IBM-Cloud/power-go-client/clients/instance" + "github.com/IBM-Cloud/power-go-client/power/models" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func ResourceIBMPIVirtualSerialNumber() *schema.Resource { + return &schema.Resource{ + CreateContext: resourceIBMPIVirtualSerialNumberCreate, + ReadContext: resourceIBMPIVirtualSerialNumberRead, + UpdateContext: resourceIBMPIVirtualSerialNumberUpdate, + DeleteContext: resourceIBMPIVirtualSerialNumberDelete, + Importer: &schema.ResourceImporter{}, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(45 * time.Minute), + Update: schema.DefaultTimeout(45 * time.Minute), + Delete: schema.DefaultTimeout(45 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + // Arguments + Arg_CloudInstanceID: { + Description: "This is the Power Instance id that is assigned to the account", + ForceNew: true, + Required: true, + Type: schema.TypeString, + }, + Arg_Description: { + Description: "Description of virtual serial number.", + Optional: true, + Type: schema.TypeString, + }, + Arg_InstanceID: { + Description: "PVM Instance to attach VSN to.", + Optional: true, + Type: schema.TypeString, + }, + Arg_RetainVirtualSerialNumber: { + Description: "Indicates whether to retain virtual serial number after unassigning from PVM instance during deletion.", + Optional: true, + RequiredWith: []string{Arg_InstanceID}, + Type: schema.TypeBool, + }, + Arg_Serial: { + Description: "Virtual serial number.", + DiffSuppressFunc: supressVSNDiffAutoAssign, + ForceNew: true, + Required: true, + Type: schema.TypeString, + }, + }, + } +} + +func resourceIBMPIVirtualSerialNumberCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + sess, err := meta.(conns.ClientSession).IBMPISession() + if err != nil { + return diag.FromErr(err) + } + + cloudInstanceID := d.Get(Arg_CloudInstanceID).(string) + client := instance.NewIBMPIVSNClient(ctx, sess, cloudInstanceID) + + vsnArg := d.Get(Arg_Serial).(string) + if _, ok := d.GetOk(Arg_InstanceID); !ok && vsnArg == AutoAssign { + return diag.Errorf("cannot use '%s' unless %s is specified", AutoAssign, Arg_InstanceID) + } + + serialString := "" + oldPvmInstanceId := "" + if vsnArg != AutoAssign { + vsn, err := client.Get(vsnArg) + if err != nil { + return diag.FromErr(err) + } + if vsn.PvmInstanceID != nil { + oldPvmInstanceId = *vsn.PvmInstanceID + } + if v, ok := d.GetOk(Arg_Description); ok { + description := v.(string) + if description != *vsn.Description { + if oldPvmInstanceId != "" { + updateBody := &models.UpdateServerVirtualSerialNumber{ + Description: &description, + } + _, err := client.PVMInstanceUpdateVSN(oldPvmInstanceId, updateBody) + if err != nil { + return diag.FromErr(err) + } + } else { + updateBody := &models.UpdateVirtualSerialNumber{ + Description: &description, + } + _, err := client.Update(vsnArg, updateBody) + if err != nil { + return diag.FromErr(err) + } + } + } + } + serialString = vsnArg + } + + if pvmInstanceId, ok := d.GetOk(Arg_InstanceID); ok { + pvmInstanceIdArg := pvmInstanceId.(string) + if oldPvmInstanceId != "" && pvmInstanceIdArg != oldPvmInstanceId { + return diag.Errorf("please detach virtual serial number from current pvm instance before specifying %s in creation", Arg_InstanceID) + } + instanceClient := instance.NewIBMPIInstanceClient(ctx, sess, cloudInstanceID) + restartInstance, err := stopLparForVSNChange(ctx, instanceClient, pvmInstanceIdArg, d.Timeout(schema.TimeoutCreate)) + if err != nil { + return diag.FromErr(err) + } + + if oldPvmInstanceId == "" { + serialNumber := d.Get(Arg_Serial).(string) + addBody := &models.AddServerVirtualSerialNumber{ + Serial: &serialNumber, + } + if v, ok := d.GetOk(Arg_Description); ok { + addBody.Description = v.(string) + } + _, err = client.PVMInstanceAttachVSN(pvmInstanceIdArg, addBody) + if err != nil { + return diag.FromErr(err) + } + + _, err = isWaitForPIInstanceStopped(ctx, instanceClient, pvmInstanceIdArg, d.Timeout(schema.TimeoutCreate)) + if err != nil { + return diag.FromErr(err) + } + + if restartInstance { + err = startLparAfterVSNChange(ctx, instanceClient, pvmInstanceIdArg, d.Timeout(schema.TimeoutCreate)) + if err != nil { + return diag.FromErr(err) + } + } + } + + if vsnArg == AutoAssign { + vsns, err := client.GetAll(&pvmInstanceIdArg) + if err != nil { + return diag.FromErr(err) + } + serialString = *vsns[0].Serial + + } else { + serialString = vsnArg + } + } + + id := cloudInstanceID + "/" + serialString + d.SetId(id) + + return resourceIBMPIVirtualSerialNumberRead(ctx, d, meta) +} + +func resourceIBMPIVirtualSerialNumberRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + sess, err := meta.(conns.ClientSession).IBMPISession() + if err != nil { + return diag.FromErr(err) + } + + idArr, err := flex.IdParts(d.Id()) + if err != nil { + return diag.FromErr(err) + } + + cloudInstanceID := idArr[0] + serial := idArr[1] + client := instance.NewIBMPIVSNClient(ctx, sess, cloudInstanceID) + + vsn, err := client.Get(serial) + if err != nil { + if strings.Contains(strings.ToLower(err.Error()), NotFound) { + d.SetId("") + return nil + } + return diag.FromErr(err) + } + d.Set(Arg_Description, vsn.Description) + d.Set(Arg_InstanceID, vsn.PvmInstanceID) + d.Set(Arg_Serial, vsn.Serial) + + return nil +} + +func resourceIBMPIVirtualSerialNumberDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + sess, err := meta.(conns.ClientSession).IBMPISession() + if err != nil { + return diag.FromErr(err) + } + + idArr, err := flex.IdParts(d.Id()) + if err != nil { + return diag.FromErr(err) + } + cloudInstanceID := idArr[0] + client := instance.NewIBMPIVSNClient(ctx, sess, cloudInstanceID) + + if v, ok := d.GetOk(Arg_InstanceID); ok { + pvmInstanceId := v.(string) + instanceClient := instance.NewIBMPIInstanceClient(ctx, sess, cloudInstanceID) + restartInstance, err := stopLparForVSNChange(ctx, instanceClient, pvmInstanceId, d.Timeout(schema.TimeoutDelete)) + if err != nil { + return diag.FromErr(err) + } + + retainVSN := false + if v, ok := d.GetOk(Arg_RetainVirtualSerialNumber); ok { + retainVSN = v.(bool) + } + deleteBody := &models.DeleteServerVirtualSerialNumber{ + RetainVSN: retainVSN, + } + err = client.PVMInstanceDeleteVSN(pvmInstanceId, deleteBody) + if err != nil { + return diag.FromErr(err) + } + + _, err = isWaitForPIInstanceStopped(ctx, instanceClient, pvmInstanceId, d.Timeout(schema.TimeoutUpdate)) + if err != nil { + return diag.FromErr(err) + } + + if restartInstance { + err = startLparAfterVSNChange(ctx, instanceClient, pvmInstanceId, d.Timeout(schema.TimeoutDelete)) + if err != nil { + return diag.FromErr(err) + } + } + + } else { + serialNumber := d.Get(Arg_Serial).(string) + err = client.Delete(serialNumber) + if err != nil { + return diag.FromErr(err) + } + } + + d.SetId("") + + return nil +} + +func resourceIBMPIVirtualSerialNumberUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + sess, err := meta.(conns.ClientSession).IBMPISession() + if err != nil { + return diag.FromErr(err) + } + cloudInstanceID := d.Get(Arg_CloudInstanceID).(string) + client := instance.NewIBMPIVSNClient(ctx, sess, cloudInstanceID) + + if d.HasChange(Arg_Description) && !d.HasChange(Arg_InstanceID) { + newDescription := d.Get(Arg_Description).(string) + if v, ok := d.GetOk(Arg_InstanceID); ok { + pvmInstanceId := v.(string) + updateBody := &models.UpdateServerVirtualSerialNumber{ + Description: &newDescription, + } + + _, err = client.PVMInstanceUpdateVSN(pvmInstanceId, updateBody) + if err != nil { + return diag.FromErr(err) + } + } else { + updateBody := &models.UpdateVirtualSerialNumber{ + Description: &newDescription, + } + + vsnArg := d.Get(Arg_Serial).(string) + + _, err = client.Update(vsnArg, updateBody) + if err != nil { + return diag.FromErr(err) + } + } + } + + if d.HasChange(Arg_InstanceID) { + oldId, newId := d.GetChange(Arg_InstanceID) + oldIdString, newIdString := oldId.(string), newId.(string) + instanceClient := instance.NewIBMPIInstanceClient(ctx, sess, cloudInstanceID) + + if oldIdString != "" { + restartInstance, err := stopLparForVSNChange(ctx, instanceClient, oldIdString, d.Timeout(schema.TimeoutUpdate)) + if err != nil { + return diag.FromErr(err) + } + + detachBody := &models.DeleteServerVirtualSerialNumber{ + RetainVSN: true, + } + err = client.PVMInstanceDeleteVSN(oldIdString, detachBody) + if err != nil { + return diag.FromErr(err) + } + + _, err = isWaitForPIInstanceStopped(ctx, instanceClient, oldIdString, d.Timeout(schema.TimeoutUpdate)) + if err != nil { + return diag.FromErr(err) + } + + if restartInstance { + err = startLparAfterVSNChange(ctx, instanceClient, oldIdString, d.Timeout(schema.TimeoutUpdate)) + if err != nil { + return diag.FromErr(err) + } + } + } + + if newIdString != "" { + restartInstance, err := stopLparForVSNChange(ctx, instanceClient, newIdString, d.Timeout(schema.TimeoutUpdate)) + if err != nil { + return diag.FromErr(err) + } + + serial := d.Get(Arg_Serial).(string) + addBody := &models.AddServerVirtualSerialNumber{ + Serial: &serial, + } + if v, ok := d.GetOk(Arg_Description); ok { + description := v.(string) + addBody.Description = description + } + _, err = client.PVMInstanceAttachVSN(newIdString, addBody) + if err != nil { + return diag.FromErr(err) + } + + _, err = isWaitForPIInstanceStopped(ctx, instanceClient, newIdString, d.Timeout(schema.TimeoutUpdate)) + if err != nil { + return diag.FromErr(err) + } + + if restartInstance { + err = startLparAfterVSNChange(ctx, instanceClient, newIdString, d.Timeout(schema.TimeoutUpdate)) + if err != nil { + return diag.FromErr(err) + } + } + } + } + + return resourceIBMPIVirtualSerialNumberRead(ctx, d, meta) +} + +func startLparAfterVSNChange(ctx context.Context, client *instance.IBMPIInstanceClient, id string, timeout time.Duration) error { + body := &models.PVMInstanceAction{ + Action: flex.PtrToString(Action_Start), + } + err := client.Action(id, body) + if err != nil { + return fmt.Errorf("failed to perform the start action on the pvm instance %v", err) + } + + _, err = isWaitForPIInstanceAvailable(ctx, client, id, OK, timeout) + + return err +} + +func stopLparForVSNChange(ctx context.Context, client *instance.IBMPIInstanceClient, id string, timeout time.Duration) (bool, error) { + instanceRestart := false + ins, err := client.Get(id) + if err != nil { + return false, fmt.Errorf("failed to get pvm instance (%s): %v", id, err) + } + status := *ins.Status + if strings.ToLower(status) != State_Shutoff { + body := &models.PVMInstanceAction{ + Action: flex.PtrToString(Action_ImmediateShutdown), + } + err := client.Action(id, body) + if err != nil { + return false, fmt.Errorf("failed to perform the stop action on the pvm instance %v", err) + } + instanceRestart = true + } + + _, err = isWaitForPIInstanceStopped(ctx, client, id, timeout) + + return instanceRestart, err +} diff --git a/ibm/service/power/resource_ibm_pi_virtual_serial_number_test.go b/ibm/service/power/resource_ibm_pi_virtual_serial_number_test.go new file mode 100644 index 0000000000..6b347cad38 --- /dev/null +++ b/ibm/service/power/resource_ibm_pi_virtual_serial_number_test.go @@ -0,0 +1,133 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package power_test + +import ( + "context" + "errors" + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + + st "github.com/IBM-Cloud/power-go-client/clients/instance" + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" +) + +func TestAccIBMPIVirtualSerialNumberBasic(t *testing.T) { + resLocator := "ibm_pi_virtual_serial_number.power_virtual_serial_number" + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccIBMPIVirtualSerialNumberBasicConfig(), + Check: resource.ComposeTestCheckFunc( + testAccCheckIBMPIVirtualSerialNumberExists(resLocator), + resource.TestCheckResourceAttrSet(resLocator, "id"), + ), + }, + }, + }) +} + +func TestAccIBMPIVirtualSerialNumberWithInstance(t *testing.T) { + resLocator := "ibm_pi_virtual_serial_number.power_virtual_serial_number" + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIBMPIVirtualSerialNumberDestroy, + Steps: []resource.TestStep{ + { + Config: testAccIBMPIVirtualSerialNumberWithInstanceConfig(), + Check: resource.ComposeTestCheckFunc( + testAccCheckIBMPIVirtualSerialNumberExists(resLocator), + resource.TestCheckResourceAttrSet(resLocator, "id"), + resource.TestCheckResourceAttrSet(resLocator, "pi_serial"), + resource.TestCheckResourceAttr(resLocator, "pi_description", "TF test description"), + resource.TestCheckResourceAttrSet(resLocator, "pi_instance_id"), + ), + }, + }, + }) +} + +func testAccCheckIBMPIVirtualSerialNumberExists(n string) resource.TestCheckFunc { + return func(s *terraform.State) error { + + rs, ok := s.RootModule().Resources[n] + + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + if rs.Primary.ID == "" { + return errors.New("No Record ID is set") + } + + sess, err := acc.TestAccProvider.Meta().(conns.ClientSession).IBMPISession() + if err != nil { + return err + } + parts, err := flex.IdParts(rs.Primary.ID) + if err != nil { + return err + } + cloudInstanceId := parts[0] + + client := st.NewIBMPIVSNClient(context.Background(), sess, cloudInstanceId) + + _, err = client.Get(parts[1]) + if err != nil { + return err + } + return nil + } +} + +func testAccCheckIBMPIVirtualSerialNumberDestroy(s *terraform.State) error { + sess, err := acc.TestAccProvider.Meta().(conns.ClientSession).IBMPISession() + if err != nil { + return err + } + for _, rs := range s.RootModule().Resources { + if rs.Type != "ibm_pi_virtual_serial_number" { + continue + } + parts, _ := flex.IdParts(rs.Primary.ID) + cloudInstanceId := parts[0] + vsnClient := st.NewIBMPIVSNClient(context.Background(), sess, cloudInstanceId) + _, err = vsnClient.Get(parts[1]) + if err == nil { + return fmt.Errorf("PI virtual serial number still exists: %s", rs.Primary.ID) + } + } + + return nil +} + +func testAccIBMPIVirtualSerialNumberBasicConfig() string { + return fmt.Sprintf(` + resource "ibm_pi_virtual_serial_number" "power_virtual_serial_number" { + pi_cloud_instance_id = "%[1]s" + pi_description = "TF test description" + pi_serial = "%[2]s" + } + `, acc.Pi_cloud_instance_id, acc.Pi_virtual_serial_number) +} + +func testAccIBMPIVirtualSerialNumberWithInstanceConfig() string { + return fmt.Sprintf(` + resource "ibm_pi_virtual_serial_number" "power_virtual_serial_number" { + pi_cloud_instance_id = "%[1]s" + pi_description = "TF test description" + pi_instance_id = "%[2]s" + pi_retain_virtual_serial_number = false + pi_serial = "auto-assign" + } + `, acc.Pi_cloud_instance_id, acc.Pi_instance_name) +} diff --git a/website/docs/d/pi_instance.html.markdown b/website/docs/d/pi_instance.html.markdown index 1b5785f36f..2d25bae4d0 100644 --- a/website/docs/d/pi_instance.html.markdown +++ b/website/docs/d/pi_instance.html.markdown @@ -98,4 +98,9 @@ In addition to all argument reference list, you can access the following attribu - `storage_type` - (String) The storage type where server is deployed. - `user_tags` - (List) List of user tags attached to the resource. - `virtual_cores_assigned` - (Integer) The virtual cores that are assigned to the instance. +- `virtual_serial_number` - (List) Virtual serial number information + + Nested scheme for `virtual_serial_number`: + - `description` - (String) Description for virtual serial number. + - `serial` - (String) Virtual serial number. - `volumes` - (List) List of volume IDs that are attached to the instance. diff --git a/website/docs/d/pi_instances.html.markdown b/website/docs/d/pi_instances.html.markdown index 0897d28cf3..d3914c0102 100644 --- a/website/docs/d/pi_instances.html.markdown +++ b/website/docs/d/pi_instances.html.markdown @@ -91,3 +91,9 @@ In addition to all argument reference list, you can access the following attribu - `storage_type` - (String) The storage type where server is deployed. - `user_tags` - (List) List of user tags attached to the resource. - `virtual_cores_assigned` - (Integer) The virtual cores that are assigned to the instance. + - `virtual_serial_number` - (List) Virtual serial number information + + Nested scheme for `virtual_serial_number`: + - `description` - (String) Description for virtual serial number. + - `serial` - (String) Virtual serial number. + diff --git a/website/docs/d/pi_virtual_serial_number.html.markdown b/website/docs/d/pi_virtual_serial_number.html.markdown new file mode 100644 index 0000000000..0e545d2926 --- /dev/null +++ b/website/docs/d/pi_virtual_serial_number.html.markdown @@ -0,0 +1,44 @@ +--- +subcategory: "Power Systems" +layout: "ibm" +page_title: "IBM: ibm_pi_virtual_serial_number" +description: |- + Provides data for a virtual_serial_number in an IBM Power Virtual Server cloud. +--- + +# ibm_virtual_serial_number +Retrieve information about an existing virtual serial number as a read-only data source. For more information, about IBM power virtual server cloud, see [getting started with IBM Power Systems Virtual Servers](https://cloud.ibm.com/docs/power-iaas?topic=power-iaas-getting-started). + +## Example usage +```terraform +data "ibm_pi_virtual_serial_number" "ds_virtual_serial_number" { + pi_cloud_instance_id = "" + pi_serial = "" +} +``` + +### Notes +- Please find [supported Regions](https://cloud.ibm.com/apidocs/power-cloud#endpoint) for endpoints. +- If a Power cloud instance is provisioned at `lon04`, The provider level attributes should be as follows: + - `region` - `lon` + - `zone` - `lon04` + +Example usage: + ```terraform + provider "ibm" { + region = "lon" + zone = "lon04" + } + ``` + +## Argument reference +Review the argument reference that you can specify for your data source. + +- `pi_cloud_instance_id` - (Required, String) The GUID of the service instance associated with an account. +- `pi_serial` - (Required, String) Virtual serial number. + +## Attribute reference +In addition to the argument reference list, you can access the following attribute references after your data source is created. + +- `description` - (String) Description for virtual serial number. +- `pvm_instance_id` - (String) ID of PVM virtual serial number is attached to. diff --git a/website/docs/d/pi_virtual_serial_numbers.html.markdown b/website/docs/d/pi_virtual_serial_numbers.html.markdown new file mode 100644 index 0000000000..cee66f53af --- /dev/null +++ b/website/docs/d/pi_virtual_serial_numbers.html.markdown @@ -0,0 +1,53 @@ +--- +subcategory: "Power Systems" +layout: "ibm" +page_title: "IBM: ibm_pi_virtual_serial_numbers" +description: |- + Provides data for a virtual_serial_number in an IBM Power Virtual Server cloud. +--- + +# ibm_virtual_serial_numbers + +Retrieve information about existing virtual serial numbers as a read-only data source. For more information, about IBM power virtual server cloud, see [getting started with IBM Power Systems Virtual Servers](https://cloud.ibm.com/docs/power-iaas?topic=power-iaas-getting-started). + +## Example usage + +```terraform +data "ibm_pi_virtual_serial_numbers" "ds_virtual_serial_number" { + pi_cloud_instance_id = "" + pi_virtual_serial_number = "" +} +``` + +### Notes + +- Please find [supported Regions](https://cloud.ibm.com/apidocs/power-cloud#endpoint) for endpoints. +- If a Power cloud instance is provisioned at `lon04`, The provider level attributes should be as follows: + - `region` - `lon` + - `zone` - `lon04` + +Example usage: + ```terraform + provider "ibm" { + region = "lon" + zone = "lon04" + } + ``` + +## Argument reference + +Review the argument reference that you can specify for your data source. + +- `pi_cloud_instance_id` - (Required, String) The GUID of the service instance associated with an account. +- `pi_instance_id` - (Optional, String) Power virtual server instance ID. + +## Attribute reference + +In addition to the argument reference list, you can access the following attribute references after your data source is created. + +- `virtual_serial_numbers` - (List) List of virtual serial numbers + + Nested scheme for `virtual_serial_numbers`: + - `description` - (String) Description for virtual serial number. + - `pvm_instance_id` - (String) ID of PVM virtual serial number is attached to. + - `serial` - (String) Virtual serial number. diff --git a/website/docs/r/pi_instance.html.markdown b/website/docs/r/pi_instance.html.markdown index 1761b45f43..22dc544e37 100644 --- a/website/docs/r/pi_instance.html.markdown +++ b/website/docs/r/pi_instance.html.markdown @@ -108,6 +108,7 @@ Review the argument references that you can specify for your resource. - `pi_replication_policy` - (Optional, String) The replication policy that you want to use, either `affinity`, `anti-affinity` or `none`. If this parameter is not set, `none` is used by default. - `pi_replication_scheme` - (Optional, String) The replication scheme that you want to set, either `prefix` or `suffix`. - `pi_replication_sites` - (Optional, List) Indicates the replication sites of the boot volume. +- `pi_retain_virtual_serial_number` - (Optional, Boolean) Indicates whether attached virtual serial number will be reserved when serial assigned to instance is changed, removed, or instance is deleted. If using `ibm_pi_virtual_serial_number` resource, will unassign and unreserved virtual serial number attached to instance if set to false. Default value is `false`. - `pi_sap_profile_id` - (Optional, String) SAP Profile ID for the amount of cores and memory. - Required only when creating SAP instances. - `pi_sap_deployment_type` - (Optional, String) Custom SAP deployment type information (For Internal Use Only). @@ -122,6 +123,13 @@ Review the argument references that you can specify for your resource. - `pi_user_tags` - (Optional, List) The user tags attached to this resource. - `pi_virtual_cores_assigned` - (Optional, Integer) Specify the number of virtual cores to be assigned. - `pi_virtual_optical_device` - (Optional, String) Virtual Machine's Cloud Initialization Virtual Optical Device. +- `pi_virtual_serial_number` - (Optional, List) Virtual Serial Number information. If using `ibm_pi_virtual_serial_number` resource to manage a virtual serial number assigned to this instance, it is strongly recommended to ignore changes in this argument using the `ignore_changes` meta-argument in the `lifecycle`. + + Nested scheme for `pi_virtual_serial_number`: + - `description` - (String, Optional) Description of virtual serial number. + - `serial` - (String, Required) Provide an existing reserved Virtual Serial Number or specify 'auto-assign' for auto generated Virtual Serial Number. + + ~> **Note** When set to "auto-assign", changes to `serial` outside of terraform will not be detected. In addition, if a new generated virtual serial number is needed, the old serial must be removed before a new one is generated. - `pi_volume_ids` - (Optional, List of String) The list of volume IDs that you want to attach to the instance during creation. ## Attribute reference diff --git a/website/docs/r/pi_virtual_serial_number.html.markdown b/website/docs/r/pi_virtual_serial_number.html.markdown new file mode 100644 index 0000000000..192846dd70 --- /dev/null +++ b/website/docs/r/pi_virtual_serial_number.html.markdown @@ -0,0 +1,77 @@ +--- +subcategory: "Power Systems" +layout: "ibm" +page_title: "IBM: pi_virtual_serial_number" +description: |- + Manages a virtual serial number in IBM Power +--- + +# ibm_pi_virtual_serial_number + +Create, get, update or delete an existing virtual serial number. + +## Example usage + +The following example enables you to create a virtual serial number: + +```terraform +resource "ibm_pi_virtual_serial_number" "testacc_virtual_serial_number" { + pi_serial = "" + pi_cloud_instance_id = "" + pi_description = "" +} +``` + +### Notes + +- Please find [supported Regions](https://cloud.ibm.com/apidocs/power-cloud#endpoint) for endpoints. +- If a Power cloud instance is provisioned at `lon04`, The provider level attributes should be as follows: + - `region` - `lon` + - `zone` - `lon04` + +Example usage: + + ```terraform + provider "ibm" { + region = "lon" + zone = "lon04" + } + ``` + +**Note** +- This resource is used to create a virtual serial number by assigning to a power instance using 'auto-assign'. Otherwise, it can only be used to manage an existing virtual serial number. If deleting an instance with a `ibm_pi_virtual_serial_number` resource assigned, it is recommended to unassign the virtual serial number resource from the instance before destruction. + +## Timeouts + +ibm_pi_virtual_serial_number provides the following [timeouts](https://www.terraform.io/docs/language/resources/syntax.html) configuration options: + +- **create** - (Default 45 minutes) Used for creating a virtual serial number. +- **update** - (Default 45 minutes) Used for updating a virtual serial number. +- **delete** - (Default 45 minutes) Used for deleting a reserved virtual serial number. + +## Argument reference + +Review the argument references that you can specify for your resource. + +- `pi_cloud_instance_id` - (Required, String) The GUID of the service instance associated with an account. +- `pi_description` - (Optional, String) Desired description for virtual serial number. +- `pi_instance_id` - (Optional, String) Power instance ID to assign created or existing virtual serial number to. Must unassign from previous power instance if different than current assignment. Cannot use the instance name, only ID. Please see note on `pi_virtual_serial_number` in the `ibm_pi_instance` resource documentation. +- `pi_retain_virtual_serial_number` - (Optional, Boolean) Indicates whether to reserve or delete virtual serial number when detached from power instance during deletion. Required with `pi_instance_id`. Default behavior does not retain virtual serial number after deletion. +- `pi_serial` - (Required, String) Virtual serial number of existing serial. Cannot use 'auto-assign' unless `pi_instance_id` is specified. + + ~> **Note** When set to "auto-assign" in the configuration, changes to `pi_serial` outside of terraform will not be detected. + +## Attribute reference + In addition to all argument reference list, you can access the following attribute reference after your resource is created. + +- `id` - (String) The unique identifier of the virtual serial number. Composed of `/` + +## Import + +The `ibm_virtual_serial_number` resource can be imported by using `pi_cloud_instance_id` and `serial`. + +### Example + +```bash +$ terraform import ibm_pi_virtual_serial_number.example d7bec597-4726-451f-8a63-e62e6f19c32c/VS0762Y +```