Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix deleting instances with replicant attribute set #5176

Merged
merged 15 commits into from
Apr 15, 2024
Merged
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ibm/service/power/data_source_ibm_pi_instance_ip.go
Original file line number Diff line number Diff line change
@@ -35,8 +35,8 @@ func DataSourceIBMPIInstanceIP() *schema.Resource {
},
Arg_NetworkName: {
Description: "The subnet that the instance belongs to.",
Type: schema.TypeString,
Required: true,
Type: schema.TypeString,
ValidateFunc: validation.NoZeroValues,
},

64 changes: 32 additions & 32 deletions ibm/service/power/ibm_pi_constants.go
Original file line number Diff line number Diff line change
@@ -14,22 +14,22 @@ const (
Arg_PlacementGroupName = "pi_placement_group_name"
Arg_SAP = "sap"
Arg_SAPProfileID = "pi_sap_profile_id"
Arg_SPPPlacementGroupID = "pi_spp_placement_group_id"
Arg_SPPPlacementGroupName = "pi_spp_placement_group_name"
Arg_SPPPlacementGroupPolicy = "pi_spp_placement_group_policy"
Arg_SharedProcessorPoolHostGroup = "pi_shared_processor_pool_host_group"
Arg_SharedProcessorPoolID = "pi_shared_processor_pool_id"
Arg_SharedProcessorPoolName = "pi_shared_processor_pool_name"
Arg_SharedProcessorPoolPlacementGroupID = "pi_shared_processor_pool_placement_group_id"
Arg_SharedProcessorPoolReservedCores = "pi_shared_processor_pool_reserved_cores"
Arg_SnapshotID = "pi_snapshot_id"
Arg_SPPPlacementGroupID = "pi_spp_placement_group_id"
Arg_SPPPlacementGroupName = "pi_spp_placement_group_name"
Arg_SPPPlacementGroupPolicy = "pi_spp_placement_group_policy"
Arg_StoragePool = "pi_storage_pool"
Arg_StorageType = "pi_storage_type"
Arg_VTL = "vtl"
Arg_VolumeGroupID = "pi_volume_group_id"
Arg_VolumeID = "pi_volume_id"
Arg_VolumeName = "pi_volume_name"
Arg_VolumeOnboardingID = "pi_volume_onboarding_id"
Arg_VTL = "vtl"

// Attributes
Attr_AccessConfig = "access_config"
@@ -43,14 +43,12 @@ const (
Attr_AvailabilityZone = "availability_zone"
Attr_AvailableCores = "available_cores"
Attr_AvailableIPCount = "available_ip_count"
Attr_BootVolumeID = "boot_volume_id"
Attr_Bootable = "bootable"
Attr_CIDR = "cidr"
Attr_CPUs = "cpus"
Attr_CRN = "crn"
Attr_BootVolumeID = "boot_volume_id"
Attr_Capabilities = "capabilities"
Attr_Capacity = "capacity"
Attr_Certified = "certified"
Attr_CIDR = "cidr"
Attr_ClassicEnabled = "classic_enabled"
Attr_CloudConnectionID = "cloud_connection_id"
Attr_CloudInstanceID = "cloud_instance_id"
@@ -65,18 +63,20 @@ const (
Attr_CopyType = "copy_type"
Attr_CoreMemoryRatio = "core_memory_ratio"
Attr_Cores = "cores"
Attr_CPUs = "cpus"
Attr_CreateTime = "create_time"
Attr_CreationDate = "creation_date"
Attr_CRN = "crn"
Attr_CyclePeriodSeconds = "cycle_period_seconds"
Attr_CyclingMode = "cycling_mode"
Attr_DNS = "dns"
Attr_Datacenters = "datacenters"
Attr_Default = "default"
Attr_DeploymentType = "deployment_type"
Attr_Description = "description"
Attr_DisasterRecoveryLocations = "disaster_recovery_locations"
Attr_DiskFormat = "disk_format"
Attr_DiskType = "disk_type"
Attr_DNS = "dns"
Attr_Enabled = "enabled"
Attr_Endianness = "endianness"
Attr_ExternalIP = "external_ip"
@@ -96,18 +96,18 @@ const (
Attr_HypervisorType = "hypervisor_type"
Attr_IBMIPAddress = "ibm_ip_address"
Attr_ID = "id"
Attr_IOThrottleRate = "io_throttle_rate"
Attr_IP = "ip"
Attr_IPAddress = "ipaddress"
Attr_IPOctet = "ipoctet"
Attr_ImageID = "image_id"
Attr_ImageInfo = "image_info"
Attr_ImageType = "image_type"
Attr_Images = "images"
Attr_ImageType = "image_type"
Attr_InputVolumes = "input_volumes"
Attr_Instances = "instances"
Attr_InstanceSnapshots = "instance_snapshots"
Attr_InstanceVolumes = "instance_volumes"
Attr_Instances = "instances"
Attr_IOThrottleRate = "io_throttle_rate"
Attr_IP = "ip"
Attr_IPAddress = "ipaddress"
Attr_IPOctet = "ipoctet"
Attr_IsActive = "is_active"
Attr_Jumbo = "jumbo"
Attr_Key = "key"
@@ -121,19 +121,18 @@ const (
Attr_Leases = "leases"
Attr_LicenseRepositoryCapacity = "license_repository_capacity"
Attr_Location = "location"
Attr_MTU = "mtu"
Attr_MacAddress = "macaddress"
Attr_MasterChangedVolumeName = "master_changed_volume_name"
Attr_MasterVolumeName = "master_volume_name"
Attr_Max = "max"
Attr_MaxAllocationSize = "max_allocation_size"
Attr_MaxAvailable = "max_available"
Attr_MaxCoresAvailable = "max_cores_available"
Attr_MaximumStorageAllocation = "max_storage_allocation"
Attr_MaxMem = "maxmem"
Attr_MaxMemoryAvailable = "max_memory_available"
Attr_MaxProc = "maxproc"
Attr_MaxVirtualCores = "max_virtual_cores"
Attr_MaximumStorageAllocation = "max_storage_allocation"
Attr_Members = "members"
Attr_Memory = "memory"
Attr_Message = "message"
@@ -143,6 +142,7 @@ const (
Attr_MinProc = "minproc"
Attr_MinVirtualCores = "min_virtual_cores"
Attr_MirroringState = "mirroring_state"
Attr_MTU = "mtu"
Attr_Name = "name"
Attr_NetworkID = "network_id"
Attr_NetworkName = "network_name"
@@ -151,9 +151,6 @@ const (
Attr_NumberOfVolumes = "number_of_volumes"
Attr_Onboardings = "onboardings"
Attr_OperatingSystem = "operating_system"
Attr_PVMInstanceID = "pvm_instance_id"
Attr_PVMInstances = "pvm_instances"
Attr_PVMSnapshots = "pvm_snapshots"
Attr_PercentComplete = "percent_complete"
Attr_PinPolicy = "pin_policy"
Attr_PlacementGroupID = "placement_group_id"
@@ -164,12 +161,15 @@ const (
Attr_Port = "port"
Attr_PortID = "portid"
Attr_PrimaryRole = "primary_role"
Attr_ProcType = "proctype"
Attr_Processors = "processors"
Attr_ProcType = "proctype"
Attr_ProfileID = "profile_id"
Attr_Profiles = "profiles"
Attr_Progress = "progress"
Attr_PublicIP = "public_ip"
Attr_PVMInstanceID = "pvm_instance_id"
Attr_PVMInstances = "pvm_instances"
Attr_PVMSnapshots = "pvm_snapshots"
Attr_Region = "region"
Attr_RemoteCopyID = "remote_copy_id"
Attr_RemoteCopyRelationshipNames = "remote_copy_relationship_names"
@@ -181,8 +181,6 @@ const (
Attr_ReservedCores = "reserved_cores"
Attr_ResultsOnboardedVolumes = "results_onboarded_volumes"
Attr_ResultsVolumeOnboardingFailures = "results_volume_onboarding_failures"
Attr_SPPPlacementGroups = "spp_placement_groups"
Attr_SSHKey = "ssh_key"
Attr_ServerName = "server_name"
Attr_Shareable = "shreable"
Attr_SharedCoreRatio = "shared_core_ratio"
@@ -196,19 +194,21 @@ const (
Attr_SharedProcessorPoolInstanceId = "id"
Attr_SharedProcessorPoolInstanceMemory = "memory"
Attr_SharedProcessorPoolInstanceName = "name"
Attr_SharedProcessorPoolInstances = "instances"
Attr_SharedProcessorPoolInstanceStatus = "status"
Attr_SharedProcessorPoolInstanceUncapped = "uncapped"
Attr_SharedProcessorPoolInstanceVcpus = "vcpus"
Attr_SharedProcessorPoolInstances = "instances"
Attr_SharedProcessorPoolName = "name"
Attr_SharedProcessorPoolPlacementGroups = "spp_placement_groups"
Attr_SharedProcessorPoolReservedCores = "reserved_cores"
Attr_SharedProcessorPools = "shared_processor_pools"
Attr_SharedProcessorPoolStatus = "status"
Attr_SharedProcessorPoolStatusDetail = "status_detail"
Attr_SharedProcessorPools = "shared_processor_pools"
Attr_Size = "size"
Attr_SourceVolumeName = "source_volume_name"
Attr_Speed = "speed"
Attr_SPPPlacementGroups = "spp_placement_groups"
Attr_SSHKey = "ssh_key"
Attr_StartTime = "start_time"
Attr_State = "state"
Attr_Status = "status"
@@ -220,10 +220,10 @@ const (
Attr_StorageType = "storage_type"
Attr_StorageTypesCapacity = "storage_types_capacity"
Attr_Synchronized = "synchronized"
Attr_SysType = "systype"
Attr_SystemPoolName = "system_pool_name"
Attr_SystemPools = "system_pools"
Attr_Systems = "systems"
Attr_SysType = "systype"
Attr_TargetVolumeName = "target_volume_name"
Attr_TenantID = "tenant_id"
Attr_TenantName = "tenant_name"
@@ -234,24 +234,24 @@ const (
Attr_TotalSSDStorageConsumed = "total_ssd_storage_consumed"
Attr_TotalStandardStorageConsumed = "total_standard_storage_consumed"
Attr_Type = "type"
Attr_URL = "url"
Attr_Uncapped = "uncapped"
Attr_URL = "url"
Attr_UsedIPCount = "used_ip_count"
Attr_UsedIPPercent = "used_ip_percent"
Attr_UserIPAddress = "user_ip_address"
Attr_VCPUs = "vcpus"
Attr_VLanID = "vlan_id"
Attr_VPCCRNs = "vpc_crns"
Attr_VPCEnabled = "vpc_enabled"
Attr_VirtualCoresAssigned = "virtual_cores_assigned"
Attr_VLanID = "vlan_id"
Attr_VolumeGroupName = "volume_group_name"
Attr_VolumeGroups = "volume_groups"
Attr_VolumeIDs = "volume_ids"
Attr_VolumePool = "volume_pool"
Attr_VolumeSnapshots = "volume_snapshots"
Attr_Volumes = "volumes"
Attr_WWN = "wwn"
Attr_VolumeSnapshots = "volume_snapshots"
Attr_VPCCRNs = "vpc_crns"
Attr_VPCEnabled = "vpc_enabled"
Attr_Workspaces = "workspaces"
Attr_WWN = "wwn"

// TODO: Second Half Cleanup, remove extra variables

38 changes: 24 additions & 14 deletions ibm/service/power/resource_ibm_pi_instance.go
Original file line number Diff line number Diff line change
@@ -183,7 +183,7 @@ func ResourceIBMPIInstance() *schema.Resource {
},
helpers.PIPlacementGroupID: {
Type: schema.TypeString,
ForceNew: true,
Computed: true,
Optional: true,
Description: "Placement group ID",
},
@@ -405,7 +405,13 @@ func resourceIBMPIInstanceCreate(ctx context.Context, d *schema.ResourceData, me
instanceReadyStatus = r.(string)
}

d.SetId(fmt.Sprintf("%s/%s", cloudInstanceID, *(*pvmList)[0].PvmInstanceID))
// id is a combination of the cloud instance id and all of the pvm instance ids
id := cloudInstanceID
for _, pvm := range *pvmList {
id += "/" + *pvm.PvmInstanceID
}

d.SetId(id)

for _, s := range *pvmList {
if dt, ok := d.GetOk(PIInstanceDeploymentType); ok && dt.(string) == "VMNoStorage" {
@@ -419,7 +425,6 @@ func resourceIBMPIInstanceCreate(ctx context.Context, d *schema.ResourceData, me
return diag.FromErr(err)
}
}

}

// If Storage Pool Affinity is given as false we need to update the vm instance.
@@ -454,7 +459,6 @@ func resourceIBMPIInstanceCreate(ctx context.Context, d *schema.ResourceData, me
}

return resourceIBMPIInstanceRead(ctx, d, meta)

}

func resourceIBMPIInstanceRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
@@ -463,11 +467,14 @@ func resourceIBMPIInstanceRead(ctx context.Context, d *schema.ResourceData, meta
return diag.FromErr(err)
}

cloudInstanceID, instanceID, err := splitID(d.Id())
idArr, err := flex.IdParts(d.Id())
if err != nil {
return diag.FromErr(err)
}

cloudInstanceID := idArr[0]
instanceID := idArr[1]

client := st.NewIBMPIInstanceClient(ctx, sess, cloudInstanceID)
powervmdata, err := client.Get(instanceID)
if err != nil {
@@ -840,20 +847,23 @@ func resourceIBMPIInstanceDelete(ctx context.Context, d *schema.ResourceData, me
return diag.FromErr(err)
}

cloudInstanceID, instanceID, err := splitID(d.Id())
idArr, err := flex.IdParts(d.Id())
if err != nil {
return diag.FromErr(err)
}

client := st.NewIBMPIInstanceClient(ctx, sess, cloudInstanceID)
err = client.Delete(instanceID)
if err != nil {
return diag.FromErr(err)
}
cloudInstanceID := idArr[0]
for _, instanceID := range idArr[1:] {
client := st.NewIBMPIInstanceClient(ctx, sess, cloudInstanceID)
err = client.Delete(instanceID)
if err != nil {
return diag.FromErr(err)
}

_, err = isWaitForPIInstanceDeleted(ctx, client, instanceID)
if err != nil {
return diag.FromErr(err)
_, err = isWaitForPIInstanceDeleted(ctx, client, instanceID)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If instead of delete-wait and loop again, can we have two loops? One loop will delete all the instances and the other loop will check the deletion status. This will save lots of time.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made changes.

if err != nil {
return diag.FromErr(err)
}
}

d.SetId("")
93 changes: 73 additions & 20 deletions ibm/service/power/resource_ibm_pi_instance_test.go
Original file line number Diff line number Diff line change
@@ -12,6 +12,7 @@ import (

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"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
@@ -85,7 +86,7 @@ func testAccCheckIBMPIInstanceDeploymentTypeConfig(name, instanceHealthStatus, e
pi_instance_name = "%[2]s"
pi_proc_type = "dedicated"
pi_image_id = data.ibm_pi_image.power_image.id
pi_key_pair_name = ibm_pi_key.key.key_id
pi_key_pair_name = ibm_pi_key.key.name
pi_sys_type = "%[7]s"
pi_cloud_instance_id = "%[1]s"
pi_storage_type = "%[8]s"
@@ -157,17 +158,17 @@ func testAccIBMPIInstanceNetworkConfig(name, privateNetIP string) string {
pi_processors = "0.25"
pi_instance_name = "%[2]s"
pi_proc_type = "shared"
pi_image_id = "f4501cad-d0f4-4517-9eea-85402309d90d"
pi_key_pair_name = ibm_pi_key.key.key_id
pi_image_id = "%[4]s"
pi_key_pair_name = ibm_pi_key.key.name
pi_sys_type = "e980"
pi_storage_type = "tier3"
pi_cloud_instance_id = "%[1]s"
pi_network {
network_id = resource.ibm_pi_network.power_networks.id
network_id = resource.ibm_pi_network.power_networks.network_id
ip_address = "%[3]s"
}
}
`, acc.Pi_cloud_instance_id, name, privateNetIP)
`, acc.Pi_cloud_instance_id, name, privateNetIP, acc.Pi_image)
}

func testAccIBMPIInstanceVTLConfig(name string) string {
@@ -191,7 +192,7 @@ func testAccIBMPIInstanceVTLConfig(name string) string {
pi_license_repository_capacity = "3"
pi_proc_type = "shared"
pi_image_id = "%[3]s"
pi_key_pair_name = ibm_pi_key.vtl_key.key_id
pi_key_pair_name = ibm_pi_key.vtl_key.name
pi_sys_type = "s922"
pi_cloud_instance_id = "%[1]s"
pi_storage_type = "tier1"
@@ -203,6 +204,27 @@ func testAccIBMPIInstanceVTLConfig(name string) string {
`, acc.Pi_cloud_instance_id, name, acc.Pi_image)
}

func testAccCheckIBMPIInstanceReplicantConfig(name string) string {
return fmt.Sprintf(`
resource "ibm_pi_instance" "power_instance" {
pi_cloud_instance_id = "%[1]s"
pi_memory = "2"
pi_processors = "1"
pi_instance_name = "%[2]s"
pi_proc_type = "shared"
pi_image_id = "%[3]s"
pi_sys_type = "s922"
pi_volume_ids = ["%[5]s"]
pi_network {
network_id = "%[4]s"
}
pi_replicants = 3
pi_replication_policy = "affinity"
pi_replication_scheme = "suffix"
}
`, acc.Pi_cloud_instance_id, name, acc.Pi_image, acc.Pi_network_name, acc.Pi_volume_name)
}

func testAccCheckIBMPIInstanceDestroy(s *terraform.State) error {
sess, err := acc.TestAccProvider.Meta().(conns.ClientSession).IBMPISession()
if err != nil {
@@ -213,19 +235,25 @@ func testAccCheckIBMPIInstanceDestroy(s *terraform.State) error {
if rs.Type != "ibm_pi_instance" {
continue
}
cloudInstanceID, instanceID, err := splitID(rs.Primary.ID)
if err == nil {

idArr, err := flex.IdParts(rs.Primary.ID)
if err != nil {
return err
}
client := st.NewIBMPIInstanceClient(context.Background(), sess, cloudInstanceID)
_, err = client.Get(instanceID)
if err == nil {
return fmt.Errorf("PI Instance still exists: %s", rs.Primary.ID)

cloudInstanceID := idArr[0]
for _, instanceID := range idArr[1:] {
client := st.NewIBMPIInstanceClient(context.Background(), sess, cloudInstanceID)
_, err = client.Get(instanceID)
if err == nil {
return fmt.Errorf("PI Instance still exists: %s", rs.Primary.ID)
}
}
}

return nil
}

func testAccCheckIBMPIInstanceExists(n string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
@@ -241,15 +269,18 @@ func testAccCheckIBMPIInstanceExists(n string) resource.TestCheckFunc {
return err
}

cloudInstanceID, instanceID, err := splitID(rs.Primary.ID)
if err == nil {
idArr, err := flex.IdParts(rs.Primary.ID)
if err != nil {
return err
}
client := st.NewIBMPIInstanceClient(context.Background(), sess, cloudInstanceID)

_, err = client.Get(instanceID)
if err != nil {
return err
cloudInstanceID := idArr[0]
for _, instanceID := range idArr[1:] {
client := st.NewIBMPIInstanceClient(context.Background(), sess, cloudInstanceID)
_, err = client.Get(instanceID)
if err != nil {
return err
}
}

return nil
@@ -328,6 +359,28 @@ func TestAccIBMPIInstanceIBMiLicense(t *testing.T) {
})
}

func TestAccIBMPIInstanceReplicant(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: testAccCheckIBMPIInstanceReplicantConfig(name),
Check: resource.ComposeTestCheckFunc(
testAccCheckIBMPIInstanceExists(instanceRes),
resource.TestCheckResourceAttr(instanceRes, "pi_replicants", "3"),
resource.TestCheckResourceAttr(instanceRes, "pi_replication_policy", "affinity"),
resource.TestCheckResourceAttr(instanceRes, "pi_replication_scheme", "suffix"),
),
ExpectNonEmptyPlan: true,
},
},
})
}

func TestAccIBMPIInstanceNetwork(t *testing.T) {
instanceRes := "ibm_pi_instance.power_instance"
name := fmt.Sprintf("tf-pi-instance-%d", acctest.RandIntRange(10, 100))
@@ -467,7 +520,7 @@ func testAccIBMPIInstanceMixedStorage(name string) string {
pi_instance_name = "%[2]s"
pi_proc_type = "shared"
pi_image_id = "ca4ea55f-b329-4cf5-bdce-d2f38cfc6da3"
pi_key_pair_name = ibm_pi_key.key.key_id
pi_key_pair_name = ibm_pi_key.key.name
pi_sys_type = "s922"
pi_storage_type = "tier1"
pi_storage_pool_affinity = false
@@ -609,7 +662,7 @@ func testAccCheckIBMPIStoppedInstanceConfigUpdate(name, instanceHealthStatus, pr
network_id = data.ibm_pi_network.power_networks.id
}
}
resource "ibm_pi_instance_action" "example" {
resource "ibm_pi_instance_action" "power_instance_action" {
pi_cloud_instance_id = "%[1]s"
pi_instance_id = ibm_pi_instance.power_instance.instance_id
pi_action = "%[8]s"
4 changes: 2 additions & 2 deletions website/docs/r/pi_instance.html.markdown
Original file line number Diff line number Diff line change
@@ -113,7 +113,7 @@ In addition to all argument reference list, you can access the following attribu

- `health_status` - (String) The health status of the VM.
- `ibmi_rds` - (Boolean) IBM i Rational Dev Studio.
- `id` - (String) The unique identifier of the instance. The ID is composed of `<power_instance_id>/<instance_id>`.
- `id` - (String) The unique identifier of the instance. The ID is composed of `<cloud_instance_id>/<instance_id_1>/.../<instance_id_n>`.
- `instance_id` - (String) The unique identifier of the instance.
- `max_processors`- (Float) The maximum number of processors that can be allocated to the instance with shutting down or rebooting the `LPAR`.
- `max_virtual_cores` - (Integer) The maximum number of virtual cores.
@@ -135,7 +135,7 @@ In addition to all argument reference list, you can access the following attribu
- `status` - (String) The status of the instance.
## Import

The `ibm_pi_instance` can be imported using `power_instance_id` and `instance_id`.
The `ibm_pi_instance` can be imported using `cloud_instance_id` and `instance_id`.

**Example**