This is an automated email from the ASF dual-hosted git repository.
sureshanaparti pushed a commit to branch main
in repository
https://gitbox.apache.org/repos/asf/cloudstack-terraform-provider.git
The following commit(s) were added to refs/heads/main by this push:
new ca078cc Declarative storage network IP range (#299)
ca078cc is described below
commit ca078cc21ec27b1290b3eed1691ac929f67a5843
Author: bddvlpr <[email protected]>
AuthorDate: Mon Aug 17 11:20:29 2026 +0200
Declarative storage network IP range (#299)
---
cloudstack/provider.go | 1 +
...resource_cloudstack_storage_network_ip_range.go | 169 +++++++++++++++++++++
...rce_cloudstack_storage_network_ip_range_test.go | 154 +++++++++++++++++++
website/cloudstack.erb | 4 +
.../docs/r/storage_network_ip_range.html.markdown | 56 +++++++
5 files changed, 384 insertions(+)
diff --git a/cloudstack/provider.go b/cloudstack/provider.go
index 4eba442..0e0ee80 100644
--- a/cloudstack/provider.go
+++ b/cloudstack/provider.go
@@ -146,6 +146,7 @@ func Provider() *schema.Provider {
"cloudstack_ssh_keypair":
resourceCloudStackSSHKeyPair(),
"cloudstack_static_nat":
resourceCloudStackStaticNAT(),
"cloudstack_static_route":
resourceCloudStackStaticRoute(),
+ "cloudstack_storage_network_ip_range":
resourceCloudStackStorageNetworkIpRange(),
"cloudstack_storage_pool":
resourceCloudStackStoragePool(),
"cloudstack_template":
resourceCloudStackTemplate(),
"cloudstack_traffic_type":
resourceCloudStackTrafficType(),
diff --git a/cloudstack/resource_cloudstack_storage_network_ip_range.go
b/cloudstack/resource_cloudstack_storage_network_ip_range.go
new file mode 100644
index 0000000..709108d
--- /dev/null
+++ b/cloudstack/resource_cloudstack_storage_network_ip_range.go
@@ -0,0 +1,169 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+package cloudstack
+
+import (
+ "fmt"
+ "log"
+
+ "github.com/apache/cloudstack-go/v2/cloudstack"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+)
+
+func resourceCloudStackStorageNetworkIpRange() *schema.Resource {
+ return &schema.Resource{
+ Create: resourceCloudStackStorageNetworkIpRangeCreate,
+ Read: resourceCloudStackStorageNetworkIpRangeRead,
+ Update: resourceCloudStackStorageNetworkIpRangeUpdate,
+ Delete: resourceCloudStackStorageNetworkIpRangeDelete,
+ Importer: &schema.ResourceImporter{
+ State: schema.ImportStatePassthrough,
+ },
+ Schema: map[string]*schema.Schema{
+ "gateway": {
+ Description: "the gateway for the storage
network IP range",
+ Type: schema.TypeString,
+ Required: true,
+ ForceNew: true,
+ },
+ "netmask": {
+ Description: "the netmask for the storage
network IP range",
+ Type: schema.TypeString,
+ Required: true,
+ },
+ "pod_id": {
+ Description: "the Pod ID for the storage
network IP range",
+ Type: schema.TypeString,
+ Required: true,
+ ForceNew: true,
+ },
+ "start_ip": {
+ Description: "the beginning IP address in the
storage network IP range",
+ Type: schema.TypeString,
+ Required: true,
+ },
+ "end_ip": {
+ Description: "the ending IP address in the
storage network IP range",
+ Type: schema.TypeString,
+ Optional: true,
+ Computed: true,
+ },
+ "vlan": {
+ Description: "the optional VLAN of the storage
network IP range",
+ Type: schema.TypeInt,
+ Optional: true,
+ },
+ "network_id": {
+ Description: "the network id of the storage
network IP range",
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ },
+ }
+}
+
+func resourceCloudStackStorageNetworkIpRangeCreate(d *schema.ResourceData,
meta interface{}) error {
+ cs := meta.(*cloudstack.CloudStackClient)
+
+ p := cs.Network.NewCreateStorageNetworkIpRangeParams(
+ d.Get("gateway").(string),
+ d.Get("netmask").(string),
+ d.Get("pod_id").(string),
+ d.Get("start_ip").(string),
+ )
+
+ if v, ok := d.GetOk("end_ip"); ok {
+ p.SetEndip(v.(string))
+ }
+ if v, ok := d.GetOk("vlan"); ok {
+ p.SetVlan(v.(int))
+ }
+
+ r, err := cs.Network.CreateStorageNetworkIpRange(p)
+ if err != nil {
+ return fmt.Errorf("Error creating storage network IP range:
%s", err)
+ }
+
+ d.SetId(r.Id)
+
+ return resourceCloudStackStorageNetworkIpRangeRead(d, meta)
+}
+
+func resourceCloudStackStorageNetworkIpRangeRead(d *schema.ResourceData, meta
interface{}) error {
+ cs := meta.(*cloudstack.CloudStackClient)
+
+ r, count, err := cs.Network.GetStorageNetworkIpRangeByID(d.Id())
+ if err != nil {
+ if count == 0 {
+ log.Printf("[DEBUG] Storage network IP range %s does no
longer exist", d.Id())
+ d.SetId("")
+ return nil
+ }
+
+ return err
+ }
+
+ d.Set("gateway", r.Gateway)
+ d.Set("netmask", r.Netmask)
+ d.Set("pod_id", r.Podid)
+ d.Set("start_ip", r.Startip)
+ d.Set("end_ip", r.Endip)
+ d.Set("vlan", r.Vlan)
+ d.Set("network_id", r.Networkid)
+
+ return nil
+}
+
+func resourceCloudStackStorageNetworkIpRangeUpdate(d *schema.ResourceData,
meta interface{}) error {
+ cs := meta.(*cloudstack.CloudStackClient)
+
+ p := cs.Network.NewUpdateStorageNetworkIpRangeParams(d.Id())
+
+ if v, ok := d.GetOk("netmask"); ok {
+ p.SetNetmask(v.(string))
+ }
+ if v, ok := d.GetOk("start_ip"); ok {
+ p.SetStartip(v.(string))
+ }
+ if v, ok := d.GetOk("end_ip"); ok {
+ p.SetEndip(v.(string))
+ }
+ if v, ok := d.GetOk("vlan"); ok {
+ p.SetVlan(v.(int))
+ }
+
+ _, err := cs.Network.UpdateStorageNetworkIpRange(p)
+ if err != nil {
+ return fmt.Errorf("Error updating storage network IP range:
%s", err)
+ }
+
+ return resourceCloudStackStorageNetworkIpRangeRead(d, meta)
+}
+
+func resourceCloudStackStorageNetworkIpRangeDelete(d *schema.ResourceData,
meta interface{}) error {
+ cs := meta.(*cloudstack.CloudStackClient)
+
+ _, err :=
cs.Network.DeleteStorageNetworkIpRange(cs.Network.NewDeleteStorageNetworkIpRangeParams(d.Id()))
+ if err != nil {
+ return fmt.Errorf("Error deleting storage network IP range:
%s", err)
+ }
+
+ return nil
+}
diff --git a/cloudstack/resource_cloudstack_storage_network_ip_range_test.go
b/cloudstack/resource_cloudstack_storage_network_ip_range_test.go
new file mode 100644
index 0000000..f8c833a
--- /dev/null
+++ b/cloudstack/resource_cloudstack_storage_network_ip_range_test.go
@@ -0,0 +1,154 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+package cloudstack
+
+import (
+ "testing"
+
+ "github.com/hashicorp/terraform-plugin-testing/helper/resource"
+)
+
+func TestAccCloudStackStorageNetworkIpRange_basic(t *testing.T) {
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ Providers: testAccProviders,
+ Steps: []resource.TestStep{
+ {
+ Config:
testAccCloudStackStorageNetworkIpRange_basic,
+ Check: resource.ComposeTestCheckFunc(
+
resource.TestCheckResourceAttr("cloudstack_storage_network_ip_range.test",
"gateway", "10.1.1.1"),
+
resource.TestCheckResourceAttr("cloudstack_storage_network_ip_range.test",
"netmask", "255.255.255.0"),
+
resource.TestCheckResourceAttr("cloudstack_storage_network_ip_range.test",
"start_ip", "10.1.1.2"),
+
resource.TestCheckResourceAttr("cloudstack_storage_network_ip_range.test",
"end_ip", "10.1.1.10"),
+
resource.TestCheckResourceAttr("cloudstack_storage_network_ip_range.test",
"vlan", "100"),
+ ),
+ },
+ {
+ Config:
testAccCloudStackStorageNetworkIpRange_update,
+ Check: resource.ComposeTestCheckFunc(
+
resource.TestCheckResourceAttr("cloudstack_storage_network_ip_range.test",
"gateway", "10.1.1.1"),
+
resource.TestCheckResourceAttr("cloudstack_storage_network_ip_range.test",
"netmask", "255.255.255.0"),
+
resource.TestCheckResourceAttr("cloudstack_storage_network_ip_range.test",
"start_ip", "10.1.1.20"),
+
resource.TestCheckResourceAttr("cloudstack_storage_network_ip_range.test",
"end_ip", "10.1.1.30"),
+
resource.TestCheckResourceAttr("cloudstack_storage_network_ip_range.test",
"vlan", "100"),
+ ),
+ },
+ },
+ })
+}
+
+func TestAccCloudStackStorageNetworkIpRange_noVlan(t *testing.T) {
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ Providers: testAccProviders,
+ Steps: []resource.TestStep{
+ {
+ Config:
testAccCloudStackStorageNetworkIpRange_noVlan,
+ Check: resource.ComposeTestCheckFunc(
+
resource.TestCheckResourceAttr("cloudstack_storage_network_ip_range.test",
"start_ip", "10.1.1.2"),
+
resource.TestCheckResourceAttr("cloudstack_storage_network_ip_range.test",
"end_ip", "10.1.1.10"),
+ ),
+ },
+ },
+ })
+}
+
+const testAccCloudStackStorageNetworkIpRange_basic = `
+resource "cloudstack_zone" "test" {
+ name = "acctest"
+ dns1 = "8.8.8.8"
+ dns2 = "8.8.8.8"
+ internal_dns1 = "8.8.4.4"
+ internal_dns2 = "8.8.4.4"
+ network_type = "Advanced"
+ domain = "cloudstack.apache.org"
+}
+resource "cloudstack_pod" "test" {
+ name = "acctestpod"
+ allocation_state = "Enabled"
+ zone_id = cloudstack_zone.test.id
+ gateway = "10.0.0.1"
+ netmask = "255.255.255.0"
+ start_ip = "10.0.0.2"
+}
+resource "cloudstack_storage_network_ip_range" "test" {
+ pod_id = cloudstack_pod.test.id
+ gateway = "10.1.1.1"
+ netmask = "255.255.255.0"
+ start_ip = "10.1.1.2"
+ end_ip = "10.1.1.10"
+ vlan = 100
+}
+`
+
+const testAccCloudStackStorageNetworkIpRange_update = `
+resource "cloudstack_zone" "test" {
+ name = "acctest"
+ dns1 = "8.8.8.8"
+ dns2 = "8.8.8.8"
+ internal_dns1 = "8.8.4.4"
+ internal_dns2 = "8.8.4.4"
+ network_type = "Advanced"
+ domain = "cloudstack.apache.org"
+}
+resource "cloudstack_pod" "test" {
+ name = "acctestpod"
+ allocation_state = "Enabled"
+ zone_id = cloudstack_zone.test.id
+ gateway = "10.0.0.1"
+ netmask = "255.255.255.0"
+ start_ip = "10.0.0.2"
+}
+resource "cloudstack_storage_network_ip_range" "test" {
+ pod_id = cloudstack_pod.test.id
+ gateway = "10.1.1.1"
+ netmask = "255.255.255.0"
+ start_ip = "10.1.1.20"
+ end_ip = "10.1.1.30"
+ vlan = 100
+}
+`
+
+const testAccCloudStackStorageNetworkIpRange_noVlan = `
+resource "cloudstack_zone" "test" {
+ name = "acctest"
+ dns1 = "8.8.8.8"
+ dns2 = "8.8.8.8"
+ internal_dns1 = "8.8.4.4"
+ internal_dns2 = "8.8.4.4"
+ network_type = "Advanced"
+ domain = "cloudstack.apache.org"
+}
+resource "cloudstack_pod" "test" {
+ name = "acctestpod"
+ allocation_state = "Enabled"
+ zone_id = cloudstack_zone.test.id
+ gateway = "10.0.0.1"
+ netmask = "255.255.255.0"
+ start_ip = "10.0.0.2"
+}
+resource "cloudstack_storage_network_ip_range" "test" {
+ pod_id = cloudstack_pod.test.id
+ gateway = "10.1.1.1"
+ netmask = "255.255.255.0"
+ start_ip = "10.1.1.2"
+ end_ip = "10.1.1.10"
+}
+`
diff --git a/website/cloudstack.erb b/website/cloudstack.erb
index 06b6a7c..09d14d9 100644
--- a/website/cloudstack.erb
+++ b/website/cloudstack.erb
@@ -109,6 +109,10 @@
<a
href="/docs/providers/cloudstack/r/static_route.html">cloudstack_static_route</a>
</li>
+ <li<%=
sidebar_current("docs-cloudstack-resource-storage-network-ip-range") %>>
+ <a
href="/docs/providers/cloudstack/r/storage_network_ip_range.html">cloudstack_storage_network_ip_range</a>
+ </li>
+
<li<%=
sidebar_current("docs-cloudstack-resource-template") %>>
<a
href="/docs/providers/cloudstack/r/template.html">cloudstack_template</a>
</li>
diff --git a/website/docs/r/storage_network_ip_range.html.markdown
b/website/docs/r/storage_network_ip_range.html.markdown
new file mode 100644
index 0000000..9deb789
--- /dev/null
+++ b/website/docs/r/storage_network_ip_range.html.markdown
@@ -0,0 +1,56 @@
+---
+layout: "cloudstack"
+page_title: "CloudStack: cloudstack_storage_network_ip_range"
+sidebar_current: "docs-cloudstack-resource-storage-network-ip-range"
+description: |-
+ Creates a storage network IP range.
+---
+
+# cloudstack_storage_network_ip_range
+
+Creates a storage network IP range for a pod.
+
+## Example Usage
+
+Basic usage:
+
+```hcl
+resource "cloudstack_storage_network_ip_range" "default" {
+ pod_id = cloudstack_pod.default.id
+ gateway = "10.1.1.1"
+ netmask = "255.255.255.0"
+ start_ip = "10.1.1.2"
+ end_ip = "10.1.1.10"
+ vlan = 100
+}
+```
+
+## Argument Reference
+
+The following arguments are supported:
+
+- `pod_id` - (Required) The Pod ID for the storage network IP range. Changing
+ this forces a new resource to be created.
+- `gateway` - (Required) The gateway for the storage network IP range. Changing
+ this forces a new resource to be created.
+- `netmask` - (Required) The netmask for the storage network IP range.
+- `start_ip` - (Required) The beginning IP address in the storage network IP
range.
+- `end_ip` - (Optional) The ending IP address in the storage network IP range.
+- `vlan` - (Optional) The optional VLAN of the storage network IP range.
+
+## Attributes Reference
+
+The following attributes are exported:
+
+- `id` - The ID of the storage network IP range.
+- `end_ip` - The ending IP address in the storage network IP range.
+- `network_id` - The network ID of the storage network IP range.
+
+## Import
+
+Storage network IP ranges can be imported; use `<ID>` as the import ID. For
+example:
+
+```shell
+terraform import cloudstack_storage_network_ip_range.default
5cf69677-7e4b-4bf4-b868-f0b02bb72ee0
+```