From c80ddccc1233ef5950d1fb18cf2bb8725f80e17e Mon Sep 17 00:00:00 2001 From: Carles Figuerola Date: Thu, 14 Jan 2016 22:58:33 -0600 Subject: [PATCH 1/4] Add vlan, startip, endip and gateway for network creation --- .../cloudstack/resource_cloudstack_network.go | 79 ++++++++++++++++--- .../cloudstack/r/network.html.markdown | 14 ++++ 2 files changed, 83 insertions(+), 10 deletions(-) diff --git a/builtin/providers/cloudstack/resource_cloudstack_network.go b/builtin/providers/cloudstack/resource_cloudstack_network.go index a76beae32..7c45154ae 100644 --- a/builtin/providers/cloudstack/resource_cloudstack_network.go +++ b/builtin/providers/cloudstack/resource_cloudstack_network.go @@ -4,6 +4,7 @@ import ( "fmt" "log" "net" + "strconv" "strings" "github.com/hashicorp/terraform/helper/schema" @@ -35,11 +36,38 @@ func resourceCloudStackNetwork() *schema.Resource { ForceNew: true, }, + "gateway": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + }, + + "startip": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + }, + + "endip": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + }, + "network_offering": &schema.Schema{ Type: schema.TypeString, Required: true, }, + "vlan": &schema.Schema{ + Type: schema.TypeInt, + Optional: true, + ForceNew: true, + }, + "vpc": &schema.Schema{ Type: schema.TypeString, Optional: true, @@ -94,17 +122,34 @@ func resourceCloudStackNetworkCreate(d *schema.ResourceData, meta interface{}) e p := cs.Network.NewCreateNetworkParams(displaytext.(string), name, networkofferingid, zoneid) // Get the network details from the CIDR - m, err := parseCIDR(d.Get("cidr").(string)) + m := make(map[string]string, 4) + cidr := d.Get("cidr").(string) + m["cidr"] = cidr + if startip, ok := d.GetOk("startip"); ok { + m["startip"] = startip.(string) + } + if endip, ok := d.GetOk("endip"); ok { + m["endip"] = endip.(string) + } + if gateway, ok := d.GetOk("gateway"); ok { + m["gateway"] = gateway.(string) + } + + m, err := parseCIDR(m) if err != nil { return err } // Set the needed IP config - p.SetStartip(m["start"]) + p.SetStartip(m["startip"]) p.SetGateway(m["gateway"]) - p.SetEndip(m["end"]) + p.SetEndip(m["endip"]) p.SetNetmask(m["netmask"]) + if vlan, ok := d.GetOk("vlan"); ok { + p.SetVlan(strconv.Itoa(vlan.(int))) + } + // Check is this network needs to be created in a VPC vpc := d.Get("vpc").(string) if vpc != "" { @@ -240,22 +285,36 @@ func resourceCloudStackNetworkDelete(d *schema.ResourceData, meta interface{}) e return nil } -func parseCIDR(cidr string) (map[string]string, error) { +func parseCIDR(m_in map[string]string) (map[string]string, error) { m := make(map[string]string, 4) - ip, ipnet, err := net.ParseCIDR(cidr) + ip, ipnet, err := net.ParseCIDR(m_in["cidr"]) if err != nil { - return nil, fmt.Errorf("Unable to parse cidr %s: %s", cidr, err) + return nil, fmt.Errorf("Unable to parse cidr %s: %s", m_in["cidr"], err) } msk := ipnet.Mask sub := ip.Mask(msk) m["netmask"] = fmt.Sprintf("%d.%d.%d.%d", msk[0], msk[1], msk[2], msk[3]) - m["gateway"] = fmt.Sprintf("%d.%d.%d.%d", sub[0], sub[1], sub[2], sub[3]+1) - m["start"] = fmt.Sprintf("%d.%d.%d.%d", sub[0], sub[1], sub[2], sub[3]+2) - m["end"] = fmt.Sprintf("%d.%d.%d.%d", - sub[0]+(0xff-msk[0]), sub[1]+(0xff-msk[1]), sub[2]+(0xff-msk[2]), sub[3]+(0xff-msk[3]-1)) + if gateway, ok := m_in["gateway"]; ok { + m["gateway"] = gateway + } else { + m["gateway"] = fmt.Sprintf("%d.%d.%d.%d", sub[0], sub[1], sub[2], sub[3]+1) + } + + if startip, ok := m_in["startip"]; ok { + m["startip"] = startip + } else { + m["startip"] = fmt.Sprintf("%d.%d.%d.%d", sub[0], sub[1], sub[2], sub[3]+2) + } + + if endip, ok := m_in["endip"]; ok { + m["endip"] = endip + } else { + m["endip"] = fmt.Sprintf("%d.%d.%d.%d", + sub[0]+(0xff-msk[0]), sub[1]+(0xff-msk[1]), sub[2]+(0xff-msk[2]), sub[3]+(0xff-msk[3]-1)) + } return m, nil } diff --git a/website/source/docs/providers/cloudstack/r/network.html.markdown b/website/source/docs/providers/cloudstack/r/network.html.markdown index 4feb566b9..91b90f86e 100644 --- a/website/source/docs/providers/cloudstack/r/network.html.markdown +++ b/website/source/docs/providers/cloudstack/r/network.html.markdown @@ -34,9 +34,23 @@ The following arguments are supported: * `cidr` - (Required) The CIDR block for the network. Changing this forces a new resource to be created. +* `startip` - (Optional) Start of the IP block that will be available on the + network. It will be autocalculated to the second available IP in the range + if it's left out. + +* `endip` - (Optional) End of the IP block that will be available on the + network. It will be autocalculated to the last available IP in the range + if it's left out. + +* `gateway` - (Optional) Gateway that will be provided to the instances in this + network. It defaults to the first usable IP if it's left empty. + * `network_offering` - (Required) The name or ID of the network offering to use for this network. +* `vlan` - (Optional) The VLAN number (1-4095) the network will use. This might be + required by the Network Offering if specifyVlan=true is set. + * `vpc` - (Optional) The name or ID of the VPC to create this network for. Changing this forces a new resource to be created. From fab9b16de596ae07c7917dfa91c1e09e233949bb Mon Sep 17 00:00:00 2001 From: Carles Figuerola Date: Fri, 15 Jan 2016 14:24:18 -0600 Subject: [PATCH 2/4] Move tests to ParseCIDR in resource_cloudstack_network and add items in read section --- .../cloudstack/resource_cloudstack_network.go | 39 +++++++------------ 1 file changed, 14 insertions(+), 25 deletions(-) diff --git a/builtin/providers/cloudstack/resource_cloudstack_network.go b/builtin/providers/cloudstack/resource_cloudstack_network.go index 7c45154ae..bde4c4dc2 100644 --- a/builtin/providers/cloudstack/resource_cloudstack_network.go +++ b/builtin/providers/cloudstack/resource_cloudstack_network.go @@ -117,25 +117,10 @@ func resourceCloudStackNetworkCreate(d *schema.ResourceData, meta interface{}) e if !ok { displaytext = name } - // Create a new parameter struct p := cs.Network.NewCreateNetworkParams(displaytext.(string), name, networkofferingid, zoneid) - // Get the network details from the CIDR - m := make(map[string]string, 4) - cidr := d.Get("cidr").(string) - m["cidr"] = cidr - if startip, ok := d.GetOk("startip"); ok { - m["startip"] = startip.(string) - } - if endip, ok := d.GetOk("endip"); ok { - m["endip"] = endip.(string) - } - if gateway, ok := d.GetOk("gateway"); ok { - m["gateway"] = gateway.(string) - } - - m, err := parseCIDR(m) + m, err := parseCIDR(d) if err != nil { return err } @@ -211,6 +196,8 @@ func resourceCloudStackNetworkRead(d *schema.ResourceData, meta interface{}) err d.Set("name", n.Name) d.Set("display_text", n.Displaytext) d.Set("cidr", n.Cidr) + d.Set("gateway", n.Gateway) + d.Set("vlan", n.Vlan) setValueOrID(d, "network_offering", n.Networkofferingname, n.Networkofferingid) setValueOrID(d, "project", n.Project, n.Projectid) @@ -285,32 +272,34 @@ func resourceCloudStackNetworkDelete(d *schema.ResourceData, meta interface{}) e return nil } -func parseCIDR(m_in map[string]string) (map[string]string, error) { +func parseCIDR(d *schema.ResourceData) (map[string]string, error) { m := make(map[string]string, 4) - ip, ipnet, err := net.ParseCIDR(m_in["cidr"]) + cidr := d.Get("cidr").(string) + ip, ipnet, err := net.ParseCIDR(cidr) if err != nil { - return nil, fmt.Errorf("Unable to parse cidr %s: %s", m_in["cidr"], err) + return nil, fmt.Errorf("Unable to parse cidr %s: %s", cidr, err) } msk := ipnet.Mask sub := ip.Mask(msk) m["netmask"] = fmt.Sprintf("%d.%d.%d.%d", msk[0], msk[1], msk[2], msk[3]) - if gateway, ok := m_in["gateway"]; ok { - m["gateway"] = gateway + + if gateway, ok := d.GetOk("gateway"); ok { + m["gateway"] = gateway.(string) } else { m["gateway"] = fmt.Sprintf("%d.%d.%d.%d", sub[0], sub[1], sub[2], sub[3]+1) } - if startip, ok := m_in["startip"]; ok { - m["startip"] = startip + if startip, ok := d.GetOk("startip"); ok { + m["startip"] = startip.(string) } else { m["startip"] = fmt.Sprintf("%d.%d.%d.%d", sub[0], sub[1], sub[2], sub[3]+2) } - if endip, ok := m_in["endip"]; ok { - m["endip"] = endip + if endip, ok := d.GetOk("endip"); ok { + m["endip"] = endip.(string) } else { m["endip"] = fmt.Sprintf("%d.%d.%d.%d", sub[0]+(0xff-msk[0]), sub[1]+(0xff-msk[1]), sub[2]+(0xff-msk[2]), sub[3]+(0xff-msk[3]-1)) From 2d0d67de1c82941c77a5c050e0f581eb3bfe3a83 Mon Sep 17 00:00:00 2001 From: Carles Figuerola Date: Fri, 15 Jan 2016 14:26:26 -0600 Subject: [PATCH 3/4] Fix wording on the docs for resource_cloudstack_network --- .../docs/providers/cloudstack/r/network.html.markdown | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/website/source/docs/providers/cloudstack/r/network.html.markdown b/website/source/docs/providers/cloudstack/r/network.html.markdown index 91b90f86e..d2a96699c 100644 --- a/website/source/docs/providers/cloudstack/r/network.html.markdown +++ b/website/source/docs/providers/cloudstack/r/network.html.markdown @@ -35,15 +35,13 @@ The following arguments are supported: resource to be created. * `startip` - (Optional) Start of the IP block that will be available on the - network. It will be autocalculated to the second available IP in the range - if it's left out. + network. Defaults to the second available IP in the range. * `endip` - (Optional) End of the IP block that will be available on the - network. It will be autocalculated to the last available IP in the range - if it's left out. + network. Defaults to the last available IP in the range. * `gateway` - (Optional) Gateway that will be provided to the instances in this - network. It defaults to the first usable IP if it's left empty. + network. Defaults to the first usable IP in the range. * `network_offering` - (Required) The name or ID of the network offering to use for this network. From e2d6f7c5e991215a166974a928f0db2f53282029 Mon Sep 17 00:00:00 2001 From: Carles Figuerola Date: Thu, 21 Jan 2016 09:52:27 -0600 Subject: [PATCH 4/4] Specify that the vlan attribute in cloudstack is only usable for ROOT admins and stop reading it back --- builtin/providers/cloudstack/resource_cloudstack_network.go | 1 - .../source/docs/providers/cloudstack/r/network.html.markdown | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/builtin/providers/cloudstack/resource_cloudstack_network.go b/builtin/providers/cloudstack/resource_cloudstack_network.go index bde4c4dc2..98a4ebb9a 100644 --- a/builtin/providers/cloudstack/resource_cloudstack_network.go +++ b/builtin/providers/cloudstack/resource_cloudstack_network.go @@ -197,7 +197,6 @@ func resourceCloudStackNetworkRead(d *schema.ResourceData, meta interface{}) err d.Set("display_text", n.Displaytext) d.Set("cidr", n.Cidr) d.Set("gateway", n.Gateway) - d.Set("vlan", n.Vlan) setValueOrID(d, "network_offering", n.Networkofferingname, n.Networkofferingid) setValueOrID(d, "project", n.Project, n.Projectid) diff --git a/website/source/docs/providers/cloudstack/r/network.html.markdown b/website/source/docs/providers/cloudstack/r/network.html.markdown index d2a96699c..21c6f2fee 100644 --- a/website/source/docs/providers/cloudstack/r/network.html.markdown +++ b/website/source/docs/providers/cloudstack/r/network.html.markdown @@ -47,7 +47,8 @@ The following arguments are supported: for this network. * `vlan` - (Optional) The VLAN number (1-4095) the network will use. This might be - required by the Network Offering if specifyVlan=true is set. + required by the Network Offering if specifyVlan=true is set. Only the ROOT + admin can set this value. * `vpc` - (Optional) The name or ID of the VPC to create this network for. Changing this forces a new resource to be created.