Skip to content

Commit

Permalink
Allow setting ip address with network
Browse files Browse the repository at this point in the history
Signed-off-by: Yussuf Shaikh <yussuf.shaikh@ibm.com>
  • Loading branch information
yussufsh authored and hkantare committed Sep 30, 2021
1 parent e8cebd9 commit 3e85433
Show file tree
Hide file tree
Showing 3 changed files with 188 additions and 63 deletions.
179 changes: 120 additions & 59 deletions ibm/resource_ibm_pi_instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ const (
activeTimeOut = 2 * time.Minute
// power service instance capabilities
CUSTOM_VIRTUAL_CORES = "custom-virtualcores"
PIInstanceNetwork = "pi_network"
)

func resourceIBMPIInstance() *schema.Resource {
Expand Down Expand Up @@ -94,10 +95,12 @@ func resourceIBMPIInstance() *schema.Resource {
},
helpers.PIInstanceNetworkIds: {
Type: schema.TypeList,
Required: true,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
Description: "List of Networks that have been configured for the account",
DiffSuppressFunc: applyOnce,
Deprecated: "Use pi_network instead",
ConflictsWith: []string{PIInstanceNetwork},
},

helpers.PIInstanceVolumeIds: {
Expand Down Expand Up @@ -129,10 +132,48 @@ func resourceIBMPIInstance() *schema.Resource {
ValidateFunc: validateAllowedStringValue([]string{"vSCSI"}),
Description: "Storage Connectivity Group for server deployment",
},

PIInstanceNetwork: {
Type: schema.TypeList,
// TODO: Once pi_network_ids is removed this will be a required field
Optional: true,
ConflictsWith: []string{helpers.PIInstanceNetworkIds},
Computed: true,
DiffSuppressFunc: applyOnce,
Description: "List of one or more networks to attach to the instance",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"ip_address": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"mac_address": {
Type: schema.TypeString,
Computed: true,
},
"network_id": {
Type: schema.TypeString,
Required: true,
},
"network_name": {
Type: schema.TypeString,
Computed: true,
},
"type": {
Type: schema.TypeString,
Computed: true,
},
"external_ip": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
"addresses": {
Type: schema.TypeList,
Computed: true,
Deprecated: "Use pi_network instead",
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"ip": {
Expand Down Expand Up @@ -306,7 +347,22 @@ func resourceIBMPIInstanceCreate(d *schema.ResourceData, meta interface{}) error
mem := d.Get(helpers.PIInstanceMemory).(float64)
procs := d.Get(helpers.PIInstanceProcessors).(float64)
systype := d.Get(helpers.PIInstanceSystemType).(string)
networks := expandStringList(d.Get(helpers.PIInstanceNetworkIds).([]interface{}))

var pvmNetworks []*models.PVMInstanceAddNetwork
// Either pi_network_ids or pi_network is provided
// TODO: Once pi_network_ids is removed pi_network will be a required field
if v, ok := d.GetOk(helpers.PIInstanceNetworkIds); ok {
networks := expandStringList(v.([]interface{}))
pvmNetworks = buildPVMNetworks(networks)
}
if v, ok := d.GetOk(PIInstanceNetwork); ok {
networksMap := v.([]interface{})
pvmNetworks = expandPVMNetworks(networksMap)
}
if len(pvmNetworks) <= 0 {
return fmt.Errorf("one of pi_network_ids or pi_network must be configured")
}

var volids []string
if v, ok := d.GetOk(helpers.PIInstanceVolumeIds); ok {
volids = expandStringList((v.(*schema.Set)).List())
Expand Down Expand Up @@ -366,7 +422,7 @@ func resourceIBMPIInstanceCreate(d *schema.ResourceData, meta interface{}) error
UserData: userData,
ReplicantNamingScheme: ptrToString(replicationNamingScheme),
ReplicantAffinityPolicy: ptrToString(replicationpolicy),
Networks: buildPVMNetworks(networks),
Networks: pvmNetworks,
Migratable: &migratable,
}
if len(volids) > 0 {
Expand Down Expand Up @@ -451,52 +507,56 @@ func resourceIBMPIInstanceRead(d *schema.ResourceData, meta interface{}) error {
if powervmdata.Migratable != nil {
d.Set("pi_migratable", powervmdata.Migratable)
}
if &powervmdata.Minproc != nil {
d.Set("min_processors", powervmdata.Minproc)
}
if &powervmdata.Progress != nil {
d.Set(helpers.PIInstanceProgress, powervmdata.Progress)
}
if &powervmdata.StorageType != nil {
d.Set("min_processors", powervmdata.Minproc)
d.Set(helpers.PIInstanceProgress, powervmdata.Progress)
if powervmdata.StorageType != nil {
d.Set(helpers.PIInstanceStorageType, powervmdata.StorageType)
}
d.Set(helpers.PICloudInstanceId, powerinstanceid)
if powervmdata.PvmInstanceID != nil {
d.Set("instance_id", powervmdata.PvmInstanceID)
}
d.Set("instance_id", powervmdata.PvmInstanceID)
d.Set(helpers.PIInstanceName, powervmdata.ServerName)
d.Set(helpers.PIInstanceImageName, powervmdata.ImageID)
var networks []string
networks = make([]string, 0)
if powervmdata.Networks != nil {
for _, n := range powervmdata.Networks {
if n != nil {
networks = append(networks, n.NetworkID)
if _, ok := d.GetOk(helpers.PIInstanceNetworkIds); ok {
var networks []string
networks = make([]string, 0)
if powervmdata.Networks != nil {
for _, n := range powervmdata.Networks {
if n != nil {
networks = append(networks, n.NetworkID)
}
}
}
d.Set(helpers.PIInstanceNetworkIds, networks)
} else {
networksMap := []map[string]interface{}{}
if powervmdata.Networks != nil {
for _, n := range powervmdata.Networks {
if n != nil {
v := map[string]interface{}{
"ip_address": n.IPAddress,
"mac_address": n.MacAddress,
"network_id": n.NetworkID,
"network_name": n.NetworkName,
"type": n.Type,
"external_ip": n.ExternalIP,
}
networksMap = append(networksMap, v)
}
}

}
d.Set(PIInstanceNetwork, networksMap)
}
d.Set(helpers.PIInstanceNetworkIds, networks)

if powervmdata.VolumeIds != nil {
d.Set(helpers.PIInstanceVolumeIds, powervmdata.VolumeIds)
}
d.Set(helpers.PIInstanceSystemType, powervmdata.SysType)
if &powervmdata.Minmem != nil {
d.Set("min_memory", powervmdata.Minmem)
}
if &powervmdata.Maxproc != nil {
d.Set("max_processors", powervmdata.Maxproc)
}
if &powervmdata.Maxmem != nil {
d.Set("max_memory", powervmdata.Maxmem)
}
if &powervmdata.PinPolicy != nil {
d.Set("pin_policy", powervmdata.PinPolicy)
}
if &powervmdata.OperatingSystem != nil {
d.Set("operating_system", powervmdata.OperatingSystem)
}
if &powervmdata.OsType != nil {
d.Set("min_memory", powervmdata.Minmem)
d.Set("max_processors", powervmdata.Maxproc)
d.Set("max_memory", powervmdata.Maxmem)
d.Set("pin_policy", powervmdata.PinPolicy)
d.Set("operating_system", powervmdata.OperatingSystem)
if powervmdata.OsType != nil {
d.Set("os_type", powervmdata.OsType)
}

Expand All @@ -506,24 +566,12 @@ func resourceIBMPIInstanceRead(d *schema.ResourceData, meta interface{}) error {
log.Printf("Now entering the powervm address space....")

p := make(map[string]interface{})
if &pvmip.IP != nil {
p["ip"] = pvmip.IP
}
if &pvmip.NetworkName != nil {
p["network_name"] = pvmip.NetworkName
}
if &pvmip.NetworkID != nil {
p["network_id"] = pvmip.NetworkID
}
if &pvmip.MacAddress != nil {
p["macaddress"] = pvmip.MacAddress
}
if &pvmip.Type != nil {
p["type"] = pvmip.Type
}
if &pvmip.ExternalIP != nil {
p["external_ip"] = pvmip.ExternalIP
}
p["ip"] = pvmip.IP
p["network_name"] = pvmip.NetworkName
p["network_id"] = pvmip.NetworkID
p["macaddress"] = pvmip.MacAddress
p["type"] = pvmip.Type
p["external_ip"] = pvmip.ExternalIP
pvmaddress[i] = p
}
d.Set("addresses", pvmaddress)
Expand Down Expand Up @@ -677,7 +725,7 @@ func resourceIBMPIInstanceUpdate(d *schema.ResourceData, meta interface{}) error
migratable := m.(bool)
body.Migratable = &migratable
}
if cores_enabled == true {
if cores_enabled {
log.Printf("support for %s is enabled", CUSTOM_VIRTUAL_CORES)
body.VirtualCores = &models.VirtualCores{Assigned: &assignedVirtualCores}
} else {
Expand Down Expand Up @@ -983,6 +1031,19 @@ func buildPVMNetworks(networks []string) []*models.PVMInstanceAddNetwork {
return pvmNetworks
}

func expandPVMNetworks(networks []interface{}) []*models.PVMInstanceAddNetwork {
pvmNetworks := make([]*models.PVMInstanceAddNetwork, 0, len(networks))
for _, v := range networks {
network := v.(map[string]interface{})
pvmInstanceNetwork := &models.PVMInstanceAddNetwork{
IPAddress: network["ip_address"].(string),
NetworkID: ptrToString(network["network_id"].(string)),
}
pvmNetworks = append(pvmNetworks, pvmInstanceNetwork)
}
return pvmNetworks
}

func checkCloudInstanceCapability(cloudInstance *models.CloudInstance, custom_capability string) bool {
log.Printf("Checking for the following capability %s", custom_capability)
log.Printf("the instance features are %s", cloudInstance.Capabilities)
Expand Down
49 changes: 49 additions & 0 deletions ibm/resource_ibm_pi_instance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,3 +127,52 @@ func testAccCheckIBMPIInstanceConfig(name string) string {
}
`, pi_cloud_instance_id, name)
}

func TestAccIBMPIInstanceNetwork(t *testing.T) {
instanceRes := "ibm_pi_instance.power_instance"
name := fmt.Sprintf("tf-pi-instance-%d", acctest.RandIntRange(10, 100))
privateNetIP := "192.112.111.220"

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckIBMPIInstanceDestroy,
Steps: []resource.TestStep{
{
Config: testAccIBMPIInstanceNetworkConfig(name, privateNetIP),
Check: resource.ComposeTestCheckFunc(
testAccCheckIBMPIInstanceExists(instanceRes),
resource.TestCheckResourceAttr(instanceRes, "pi_instance_name", name),
resource.TestCheckResourceAttrSet(instanceRes, "pi_network.0.network_id"),
resource.TestCheckResourceAttrSet(instanceRes, "pi_network.0.mac_address"),
resource.TestCheckResourceAttr(instanceRes, "pi_network.0.ip_address", privateNetIP),
),
},
},
})
}

func testAccIBMPIInstanceNetworkConfig(name, privateNetIP 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 AAAAB3NzaC1yc2EAAAABJQAAAQEArb2aK0mekAdbYdY9rwcmeNSxqVCwez3WZTYEq+1Nwju0x5/vQFPSD2Kp9LpKBbxx3OVLN4VffgGUJznz9DAr7veLkWaf3iwEil6U4rdrhBo32TuDtoBwiczkZ9gn1uJzfIaCJAJdnO80Kv9k0smbQFq5CSb9H+F5VGyFue/iVd5/b30MLYFAz6Jg1GGWgw8yzA4Gq+nO7HtyuA2FnvXdNA3yK/NmrTiPCdJAtEPZkGu9LcelkQ8y90ArlKfjtfzGzYDE4WhOufFxyWxciUePh425J2eZvElnXSdGha+FCfYjQcvqpCVoBAG70U4fJBGjB+HL/GpCXLyiYXPrSnzC9w=="
}
resource "ibm_pi_instance" "power_instance" {
pi_memory = "2"
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_sys_type = "e980"
pi_storage_type = "tier3"
pi_cloud_instance_id = "%[1]s"
pi_network {
network_id = "tf-cloudconnection-23"
ip_address = "%[3]s"
}
}
`, pi_cloud_instance_id, name, privateNetIP)
}
23 changes: 19 additions & 4 deletions website/docs/r/pi_instance.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@ resource "ibm_pi_instance" "test-instance" {
pi_instance_name = "test-vm"
pi_proc_type = "shared"
pi_image_id = "${data.ibm_pi_image.powerimages.id}"
pi_network_ids = [data.ibm_pi_public_network.dsnetwork.id]
pi_key_pair_name = ibm_pi_key.key.key_id
pi_sys_type = "s922"
pi_cloud_instance_id = "51e1879c-bcbe-4ee1-a008-49cdba0eaf60"
pi_pin_policy = "none"
pi_health_status = "WARNING"
pi_network {
network_id = data.ibm_pi_public_network.dsnetwork.id
}
}
```

Expand Down Expand Up @@ -62,7 +64,8 @@ Review the argument references that you can specify for your resource.
- `pi_key_pair_name` - (Required, String) The name of the SSH key that you want to use to access your Power Systems Virtual Server instance. The SSH key must be uploaded to IBM Cloud.
- `pi_memory` - (Required, Float) The amount of memory that you want to assign to your instance in gigabytes.
- `pi_migratable`- (Optional, Bool) Indicates the VM is migrated or not.
- `pi_network_ids` - (Required, String) The list of network IDs that you want to assign to the instance.
- `pi_network_ids` - (Required, List of String) The list of network IDs that you want to assign to the instance. This attribute is **Deprecated** use `pi_network` instead.
- `pi_network` - (Required, List of Map) List of one or more networks to attach to the instance. The `pi_network` object structure is documented below.
- `pi_pin_policy` - (Optional, String) Select the pinning policy for your Power Systems Virtual Server instance. Supported values are `soft`, `hard`, and `none`. **Note** You can choose to soft pin (`soft`) or hard pin (`hard`) a virtual server to the physical host where it runs. When you soft pin an instance for high availability, the instance automatically migrates back to the original host once the host is back to its operating state. If the instance has a licensing restriction with the host, the hard pin option restricts the movement of the instance during remote restart, automated remote restart, DRO, and live partition migration. The default pinning policy is `none`.
- `pi_processors` - (Required, Float) The number of vCPUs to assign to the VM as visible within the guest Operating System.
- `pi_proc_type` - (Required, String) The type of processor mode in which the VM will run with `shared` or `dedicated`.
Expand All @@ -74,13 +77,16 @@ Review the argument references that you can specify for your resource.
- `pi_sys_type` - (Required, String) The type of system on which to create the VM (s922/e880/any).
- `pi_user_data` - (Optional, String) The base64 encoded form of the user data `cloud-init` to pass to the instance during creation.
- `pi_virtual_cores_assigned` - (Optional, Integer) Specify the number of virtual cores to be assigned.
- `pi_volume_ids` - (Required, String) The list of volume IDs that you want to attach to the instance during creation.
- `pi_volume_ids` - (Required, List of String) The list of volume IDs that you want to attach to the instance during creation.

The `pi_network` block supports:
- `network_id` - (String) The network ID to assign to the instance.
- `ip_address` - (String) The ip address to be used of this network.

## Attribute reference
In addition to all argument reference list, you can access the following attribute reference after your resource is created.

- `addresses` - Map of strings - A list of addresses that are assigned to the instance.
- `addresses` - Map of strings - A list of addresses that are assigned to the instance. This attribute is **Deprecated** use `pi_network` instead.

Nested scheme for `addresses`:
- `ip` - (String) The IP address of the instance.
Expand All @@ -102,6 +108,15 @@ In addition to all argument reference list, you can access the following attribu
- `status` - (String) The status of the instance.
- `pin_policy` - (String) The pinning policy of the instance.
- `progress` - (Float) - Specifies the overall progress of the instance deployment process in percentage.
- `pi_network` - (List of Map) - A list of networks that are assigned to the instance.

Nested scheme for `pi_network`:
- `ip_address` - (String) The IP address of the network.
- `mac_address` - (String) The MAC address of the network.
- `network_id` - (String) The ID of the network.
- `network_name` - (String) The name of the network.
- `type` - (String) The type of network.
- `external_ip` - (String) The external IP address of the network.

## Import

Expand Down

0 comments on commit 3e85433

Please sign in to comment.