mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-20 11:48:24 -06:00
Needed to tweak a few things in order get all tests running OK and to be able to handle the latest changes in master. All is good again now…
242 lines
5.7 KiB
Go
242 lines
5.7 KiB
Go
package cloudstack
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"net"
|
|
"strings"
|
|
|
|
"github.com/hashicorp/terraform/helper/schema"
|
|
"github.com/xanzy/go-cloudstack/cloudstack"
|
|
)
|
|
|
|
func resourceCloudStackNetwork() *schema.Resource {
|
|
return &schema.Resource{
|
|
Create: resourceCloudStackNetworkCreate,
|
|
Read: resourceCloudStackNetworkRead,
|
|
Update: resourceCloudStackNetworkUpdate,
|
|
Delete: resourceCloudStackNetworkDelete,
|
|
|
|
Schema: map[string]*schema.Schema{
|
|
"name": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Required: true,
|
|
},
|
|
|
|
"display_text": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
Computed: true,
|
|
},
|
|
|
|
"cidr": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Required: true,
|
|
ForceNew: true,
|
|
},
|
|
|
|
"network_offering": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Required: true,
|
|
},
|
|
|
|
"vpc": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
ForceNew: true,
|
|
},
|
|
|
|
"aclid": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
ForceNew: true,
|
|
},
|
|
|
|
"zone": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Required: true,
|
|
ForceNew: true,
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
func resourceCloudStackNetworkCreate(d *schema.ResourceData, meta interface{}) error {
|
|
cs := meta.(*cloudstack.CloudStackClient)
|
|
|
|
name := d.Get("name").(string)
|
|
|
|
// Retrieve the network_offering UUID
|
|
networkofferingid, e := retrieveUUID(cs, "network_offering", d.Get("network_offering").(string))
|
|
if e != nil {
|
|
return e.Error()
|
|
}
|
|
|
|
// Retrieve the zone UUID
|
|
zoneid, e := retrieveUUID(cs, "zone", d.Get("zone").(string))
|
|
if e != nil {
|
|
return e.Error()
|
|
}
|
|
|
|
// Compute/set the display text
|
|
displaytext, ok := d.GetOk("display_text")
|
|
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))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Set the needed IP config
|
|
p.SetStartip(m["start"])
|
|
p.SetGateway(m["gateway"])
|
|
p.SetEndip(m["end"])
|
|
p.SetNetmask(m["netmask"])
|
|
|
|
// Check is this network needs to be created in a VPC
|
|
vpc := d.Get("vpc").(string)
|
|
if vpc != "" {
|
|
// Retrieve the vpc UUID
|
|
vpcid, e := retrieveUUID(cs, "vpc", vpc)
|
|
if e != nil {
|
|
return e.Error()
|
|
}
|
|
|
|
// Set the vpc UUID
|
|
p.SetVpcid(vpcid)
|
|
|
|
// Since we're in a VPC, check if we want to assiciate an ACL list
|
|
aclid := d.Get("aclid").(string)
|
|
if aclid != "" {
|
|
// Set the acl UUID
|
|
p.SetAclid(aclid)
|
|
}
|
|
}
|
|
|
|
// Create the new network
|
|
r, err := cs.Network.CreateNetwork(p)
|
|
if err != nil {
|
|
return fmt.Errorf("Error creating network %s: %s", name, err)
|
|
}
|
|
|
|
d.SetId(r.Id)
|
|
|
|
return resourceCloudStackNetworkRead(d, meta)
|
|
}
|
|
|
|
func resourceCloudStackNetworkRead(d *schema.ResourceData, meta interface{}) error {
|
|
cs := meta.(*cloudstack.CloudStackClient)
|
|
|
|
// Get the virtual machine details
|
|
n, count, err := cs.Network.GetNetworkByID(d.Id())
|
|
if err != nil {
|
|
if count == 0 {
|
|
log.Printf(
|
|
"[DEBUG] Network %s does no longer exist", d.Get("name").(string))
|
|
d.SetId("")
|
|
return nil
|
|
}
|
|
|
|
return err
|
|
}
|
|
|
|
d.Set("name", n.Name)
|
|
d.Set("display_text", n.Displaytext)
|
|
d.Set("cidr", n.Cidr)
|
|
d.Set("network_offering", n.Networkofferingname)
|
|
d.Set("zone", n.Zonename)
|
|
|
|
return nil
|
|
}
|
|
|
|
func resourceCloudStackNetworkUpdate(d *schema.ResourceData, meta interface{}) error {
|
|
cs := meta.(*cloudstack.CloudStackClient)
|
|
name := d.Get("name").(string)
|
|
|
|
// Create a new parameter struct
|
|
p := cs.Network.NewUpdateNetworkParams(d.Id())
|
|
|
|
// Check if the name or display text is changed
|
|
if d.HasChange("name") || d.HasChange("display_text") {
|
|
p.SetName(name)
|
|
|
|
// Compute/set the display text
|
|
displaytext := d.Get("display_text").(string)
|
|
if displaytext == "" {
|
|
displaytext = name
|
|
}
|
|
}
|
|
|
|
// Check if the cidr is changed
|
|
if d.HasChange("cidr") {
|
|
p.SetGuestvmcidr(d.Get("cidr").(string))
|
|
}
|
|
|
|
// Check if the network offering is changed
|
|
if d.HasChange("network_offering") {
|
|
// Retrieve the network_offering UUID
|
|
networkofferingid, e := retrieveUUID(cs, "network_offering", d.Get("network_offering").(string))
|
|
if e != nil {
|
|
return e.Error()
|
|
}
|
|
// Set the new network offering
|
|
p.SetNetworkofferingid(networkofferingid)
|
|
}
|
|
|
|
// Update the network
|
|
_, err := cs.Network.UpdateNetwork(p)
|
|
if err != nil {
|
|
return fmt.Errorf(
|
|
"Error updating network %s: %s", name, err)
|
|
}
|
|
|
|
return resourceCloudStackNetworkRead(d, meta)
|
|
}
|
|
|
|
func resourceCloudStackNetworkDelete(d *schema.ResourceData, meta interface{}) error {
|
|
cs := meta.(*cloudstack.CloudStackClient)
|
|
|
|
// Create a new parameter struct
|
|
p := cs.Network.NewDeleteNetworkParams(d.Id())
|
|
|
|
// Delete the network
|
|
_, err := cs.Network.DeleteNetwork(p)
|
|
if err != nil {
|
|
// This is a very poor way to be told the UUID does no longer exist :(
|
|
if strings.Contains(err.Error(), fmt.Sprintf(
|
|
"Invalid parameter id value=%s due to incorrect long value format, "+
|
|
"or entity does not exist", d.Id())) {
|
|
return nil
|
|
}
|
|
|
|
return fmt.Errorf("Error deleting network %s: %s", d.Get("name").(string), err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func parseCIDR(cidr string) (map[string]string, error) {
|
|
m := make(map[string]string, 4)
|
|
|
|
ip, ipnet, err := net.ParseCIDR(cidr)
|
|
if err != nil {
|
|
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])
|
|
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))
|
|
|
|
return m, nil
|
|
}
|