Dell Infrastructure-as-a-code: Terraforming with PowerStore

Ambar Hassani
9 min readJan 24, 2024

This blog is part of the Dell Infrastructure-as-a-code saga series. In this blog, we will build on the narrative expressed in my previous one Dell Infrastructure-as-a-code: Terraforming with PowerFlex 4.5 Software Defined Storage | by Ambar Hassani | Jan, 2024 | Medium

However, this time we will gain experiential knowledge on IaC-Terraform with Dell PowerStore. We will use Terraform to quickly spin up volumes on the PowerStore storage. But that’s not all, we can do much more and if interested one can read here… dell/terraform-provider-powerstore: Terraform Provider for Dell EMC PowerStore (github.com)

A short note of Dell PowerStore is imminent. As a summary, PowerStore is Dell Technologies award winning1 and a revolutionary storage appliance that’s designed for the data era. It provides customers with a data-centric, intelligent, and adaptable infrastructure solution. In tandem with the CSI support and a unified storage platform for Block, File and vVols, it packs a strong punch for the traditional and cloud native persistent workloads.

And when we combine this beast with another one, i.e. Terraform, one can expect nothing but the best yield for IT teams.

Less talk., more action! Let’s begin.

Create the following files

variables.tf

variable "username" {
type = string
description = "Stores the username of PowerStore host."
default = "admin"
}

variable "password" {
type = string
description = "Stores the password of PowerStore host."
default = "<replace-me"
}

variable "timeout" {
type = string
description = "Stores the timeout of PowerStore host."
default = "120"
}

variable "endpoint" {
type = string
description = "Stores the endpoint of PowerStore host. eg: https://10.1.1.1/api/rest"
default = "https://10.204.109.70/api/rest"
}

main.tf (note we are using loop to derive output as an array map)

terraform {
required_providers {
powerstore = {
version = "1.1.0"
source = "registry.terraform.io/dell/powerstore"
}
}
}

provider "powerstore" {
username = var.username
password = var.password
endpoint = var.endpoint
insecure = true
timeout = var.timeout
}
resource "powerstore_volume" "test1" {
count = 4
name = "dell-iac-test-${count.index}"
size = 8
capacity_unit = "GB"
}
output "volumeid" {
value = [for volume in powerstore_volume.test1 : volume.id]
description = "Powerstore Volume ID"
}

Let’s observe the initial state of our volumes in PowerStore UI

9 Volumes can be seen and none of them bear the prefix dell-iac-test

Let’s deploy our Terraform template

terraform init

terraform init

Initializing the backend...

Initializing provider plugins...
- Finding dell/powerstore versions matching "1.1.0"...
- Installing dell/powerstore v1.1.0...
- Installed dell/powerstore v1.1.0 (signed by a HashiCorp partner, key ID 3D55C2542D9DE477)

Partner and community providers are signed by their developers.
If you'd like to know more about provider signing, you can read about it here:
https://www.terraform.io/docs/cli/plugins/signing.html

Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

terraform plan

terraform plan

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following
symbols:
+ create

Terraform will perform the following actions:

# powerstore_volume.test1[0] will be created
+ resource "powerstore_volume" "test1" {
+ app_type = (known after apply)
+ app_type_other = (known after apply)
+ appliance_id = (known after apply)
+ capacity_unit = "GB"
+ creation_timestamp = (known after apply)
+ description = (known after apply)
+ host_group_id = (known after apply)
+ host_id = (known after apply)
+ id = (known after apply)
+ is_replication_destination = (known after apply)
+ logical_unit_number = (known after apply)
+ logical_used = (known after apply)
+ name = "dell-iac-test-0"
+ nguid = (known after apply)
+ node_affinity = (known after apply)
+ nsid = (known after apply)
+ performance_policy_id = "default_medium"
+ protection_policy_id = (known after apply)
+ sector_size = 512
+ size = 8
+ state = (known after apply)
+ type = (known after apply)
+ volume_group_id = (known after apply)
+ wwn = (known after apply)
}

# powerstore_volume.test1[1] will be created
+ resource "powerstore_volume" "test1" {
+ app_type = (known after apply)
+ app_type_other = (known after apply)
+ appliance_id = (known after apply)
+ capacity_unit = "GB"
+ creation_timestamp = (known after apply)
+ description = (known after apply)
+ host_group_id = (known after apply)
+ host_id = (known after apply)
+ id = (known after apply)
+ is_replication_destination = (known after apply)
+ logical_unit_number = (known after apply)
+ logical_used = (known after apply)
+ name = "dell-iac-test-1"
+ nguid = (known after apply)
+ node_affinity = (known after apply)
+ nsid = (known after apply)
+ performance_policy_id = "default_medium"
+ protection_policy_id = (known after apply)
+ sector_size = 512
+ size = 8
+ state = (known after apply)
+ type = (known after apply)
+ volume_group_id = (known after apply)
+ wwn = (known after apply)
}

# powerstore_volume.test1[2] will be created
+ resource "powerstore_volume" "test1" {
+ app_type = (known after apply)
+ app_type_other = (known after apply)
+ appliance_id = (known after apply)
+ capacity_unit = "GB"
+ creation_timestamp = (known after apply)
+ description = (known after apply)
+ host_group_id = (known after apply)
+ host_id = (known after apply)
+ id = (known after apply)
+ is_replication_destination = (known after apply)
+ logical_unit_number = (known after apply)
+ logical_used = (known after apply)
+ name = "dell-iac-test-2"
+ nguid = (known after apply)
+ node_affinity = (known after apply)
+ nsid = (known after apply)
+ performance_policy_id = "default_medium"
+ protection_policy_id = (known after apply)
+ sector_size = 512
+ size = 8
+ state = (known after apply)
+ type = (known after apply)
+ volume_group_id = (known after apply)
+ wwn = (known after apply)
}

# powerstore_volume.test1[3] will be created
+ resource "powerstore_volume" "test1" {
+ app_type = (known after apply)
+ app_type_other = (known after apply)
+ appliance_id = (known after apply)
+ capacity_unit = "GB"
+ creation_timestamp = (known after apply)
+ description = (known after apply)
+ host_group_id = (known after apply)
+ host_id = (known after apply)
+ id = (known after apply)
+ is_replication_destination = (known after apply)
+ logical_unit_number = (known after apply)
+ logical_used = (known after apply)
+ name = "dell-iac-test-3"
+ nguid = (known after apply)
+ node_affinity = (known after apply)
+ nsid = (known after apply)
+ performance_policy_id = "default_medium"
+ protection_policy_id = (known after apply)
+ sector_size = 512
+ size = 8
+ state = (known after apply)
+ type = (known after apply)
+ volume_group_id = (known after apply)
+ wwn = (known after apply)
}

Plan: 4 to add, 0 to change, 0 to destroy.

Changes to Outputs:
+ volumeid = [
+ (known after apply),
+ (known after apply),
+ (known after apply),
+ (known after apply),
]

terraform apply -auto-approve

terraform apply -auto-approve

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following
symbols:
+ create

Terraform will perform the following actions:

# powerstore_volume.test1[0] will be created
+ resource "powerstore_volume" "test1" {
+ app_type = (known after apply)
+ app_type_other = (known after apply)
+ appliance_id = (known after apply)
+ capacity_unit = "GB"
+ creation_timestamp = (known after apply)
+ description = (known after apply)
+ host_group_id = (known after apply)
+ host_id = (known after apply)
+ id = (known after apply)
+ is_replication_destination = (known after apply)
+ logical_unit_number = (known after apply)
+ logical_used = (known after apply)
+ name = "dell-iac-test-0"
+ nguid = (known after apply)
+ node_affinity = (known after apply)
+ nsid = (known after apply)
+ performance_policy_id = "default_medium"
+ protection_policy_id = (known after apply)
+ sector_size = 512
+ size = 8
+ state = (known after apply)
+ type = (known after apply)
+ volume_group_id = (known after apply)
+ wwn = (known after apply)
}

# powerstore_volume.test1[1] will be created
+ resource "powerstore_volume" "test1" {
+ app_type = (known after apply)
+ app_type_other = (known after apply)
+ appliance_id = (known after apply)
+ capacity_unit = "GB"
+ creation_timestamp = (known after apply)
+ description = (known after apply)
+ host_group_id = (known after apply)
+ host_id = (known after apply)
+ id = (known after apply)
+ is_replication_destination = (known after apply)
+ logical_unit_number = (known after apply)
+ logical_used = (known after apply)
+ name = "dell-iac-test-1"
+ nguid = (known after apply)
+ node_affinity = (known after apply)
+ nsid = (known after apply)
+ performance_policy_id = "default_medium"
+ protection_policy_id = (known after apply)
+ sector_size = 512
+ size = 8
+ state = (known after apply)
+ type = (known after apply)
+ volume_group_id = (known after apply)
+ wwn = (known after apply)
}

# powerstore_volume.test1[2] will be created
+ resource "powerstore_volume" "test1" {
+ app_type = (known after apply)
+ app_type_other = (known after apply)
+ appliance_id = (known after apply)
+ capacity_unit = "GB"
+ creation_timestamp = (known after apply)
+ description = (known after apply)
+ host_group_id = (known after apply)
+ host_id = (known after apply)
+ id = (known after apply)
+ is_replication_destination = (known after apply)
+ logical_unit_number = (known after apply)
+ logical_used = (known after apply)
+ name = "dell-iac-test-2"
+ nguid = (known after apply)
+ node_affinity = (known after apply)
+ nsid = (known after apply)
+ performance_policy_id = "default_medium"
+ protection_policy_id = (known after apply)
+ sector_size = 512
+ size = 8
+ state = (known after apply)
+ type = (known after apply)
+ volume_group_id = (known after apply)
+ wwn = (known after apply)
}

# powerstore_volume.test1[3] will be created
+ resource "powerstore_volume" "test1" {
+ app_type = (known after apply)
+ app_type_other = (known after apply)
+ appliance_id = (known after apply)
+ capacity_unit = "GB"
+ creation_timestamp = (known after apply)
+ description = (known after apply)
+ host_group_id = (known after apply)
+ host_id = (known after apply)
+ id = (known after apply)
+ is_replication_destination = (known after apply)
+ logical_unit_number = (known after apply)
+ logical_used = (known after apply)
+ name = "dell-iac-test-3"
+ nguid = (known after apply)
+ node_affinity = (known after apply)
+ nsid = (known after apply)
+ performance_policy_id = "default_medium"
+ protection_policy_id = (known after apply)
+ sector_size = 512
+ size = 8
+ state = (known after apply)
+ type = (known after apply)
+ volume_group_id = (known after apply)
+ wwn = (known after apply)
}

Plan: 4 to add, 0 to change, 0 to destroy.

Changes to Outputs:
+ volumeid = [
+ (known after apply),
+ (known after apply),
+ (known after apply),
+ (known after apply),
]
powerstore_volume.test1[3]: Creating...
powerstore_volume.test1[1]: Creating...
powerstore_volume.test1[0]: Creating...
powerstore_volume.test1[2]: Creating...
powerstore_volume.test1[0]: Creation complete after 0s [id=c5db2a37-9061-4d07-800c-4fd39ef8feaa]
powerstore_volume.test1[1]: Creation complete after 1s [id=1e663dbb-dfef-426f-8ff0-3b3304cac525]
powerstore_volume.test1[3]: Creation complete after 1s [id=e4aaa1cd-d814-4f9a-a4ec-89113511e83f]
powerstore_volume.test1[2]: Creation complete after 1s [id=0eb96891-2dba-4821-9976-8e75e3283ff9]

Apply complete! Resources: 4 added, 0 changed, 0 destroyed.

Outputs:

volumeid = [
"c5db2a37-9061-4d07-800c-4fd39ef8feaa",
"1e663dbb-dfef-426f-8ff0-3b3304cac525",
"0eb96891-2dba-4821-9976-8e75e3283ff9",
"e4aaa1cd-d814-4f9a-a4ec-89113511e83f",
]

Observe the last log for outputs. 4 Volume IDs are derived from the deployment.

Let’s verify this in PowerStore UI

Total volume count has increased to 13 with 4 incremental added via Terraform.

All 4 incremental volumes deployed by Terraform bear the dell-iac-test prefix as configured in the template. We can also correspond the volume ids as seen in the PowerStore UI and Terraform outputs., quite a handy affair!

That’s it for now!

Happing Terraform’ing and PowerStor’ing

cheers

Ambar@thecloudgarage

#iwork4dell

--

--

Ambar Hassani

24+ years of blended experience of technology & people leadership, startup management and disruptive acceleration/adoption of next-gen technologies