diff --git a/builtin/providers/cloudstack/resource_cloudstack_network.go b/builtin/providers/cloudstack/resource_cloudstack_network.go index a76beae325..98a4ebb9ab 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, @@ -89,22 +117,24 @@ 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, err := parseCIDR(d.Get("cidr").(string)) + m, err := parseCIDR(d) 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 != "" { @@ -166,6 +196,7 @@ 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) setValueOrID(d, "network_offering", n.Networkofferingname, n.Networkofferingid) setValueOrID(d, "project", n.Project, n.Projectid) @@ -240,9 +271,10 @@ func resourceCloudStackNetworkDelete(d *schema.ResourceData, meta interface{}) e return nil } -func parseCIDR(cidr string) (map[string]string, error) { +func parseCIDR(d *schema.ResourceData) (map[string]string, error) { m := make(map[string]string, 4) + cidr := d.Get("cidr").(string) ip, ipnet, err := net.ParseCIDR(cidr) if err != nil { return nil, fmt.Errorf("Unable to parse cidr %s: %s", cidr, err) @@ -252,10 +284,25 @@ func parseCIDR(cidr string) (map[string]string, error) { 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 := 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 := 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 := 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)) + } 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 4feb566b9b..21c6f2fee1 100644 --- a/website/source/docs/providers/cloudstack/r/network.html.markdown +++ b/website/source/docs/providers/cloudstack/r/network.html.markdown @@ -34,9 +34,22 @@ 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. Defaults to the second available IP in the range. + +* `endip` - (Optional) End of the IP block that will be available on the + network. Defaults to the last available IP in the range. + +* `gateway` - (Optional) Gateway that will be provided to the instances in this + 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. +* `vlan` - (Optional) The VLAN number (1-4095) the network will use. This might be + 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.