github.com/hobbeswalsh/terraform@v0.3.7-0.20150619183303-ad17cf55a0fa/builtin/providers/cloudstack/resource_cloudstack_network.go (about) 1 package cloudstack 2 3 import ( 4 "fmt" 5 "log" 6 "net" 7 "strings" 8 9 "github.com/hashicorp/terraform/helper/schema" 10 "github.com/xanzy/go-cloudstack/cloudstack" 11 ) 12 13 func resourceCloudStackNetwork() *schema.Resource { 14 return &schema.Resource{ 15 Create: resourceCloudStackNetworkCreate, 16 Read: resourceCloudStackNetworkRead, 17 Update: resourceCloudStackNetworkUpdate, 18 Delete: resourceCloudStackNetworkDelete, 19 20 Schema: map[string]*schema.Schema{ 21 "name": &schema.Schema{ 22 Type: schema.TypeString, 23 Required: true, 24 }, 25 26 "display_text": &schema.Schema{ 27 Type: schema.TypeString, 28 Optional: true, 29 Computed: true, 30 }, 31 32 "cidr": &schema.Schema{ 33 Type: schema.TypeString, 34 Required: true, 35 ForceNew: true, 36 }, 37 38 "network_offering": &schema.Schema{ 39 Type: schema.TypeString, 40 Required: true, 41 }, 42 43 "vpc": &schema.Schema{ 44 Type: schema.TypeString, 45 Optional: true, 46 ForceNew: true, 47 }, 48 49 "aclid": &schema.Schema{ 50 Type: schema.TypeString, 51 Optional: true, 52 ForceNew: true, 53 }, 54 55 "zone": &schema.Schema{ 56 Type: schema.TypeString, 57 Required: true, 58 ForceNew: true, 59 }, 60 }, 61 } 62 } 63 64 func resourceCloudStackNetworkCreate(d *schema.ResourceData, meta interface{}) error { 65 cs := meta.(*cloudstack.CloudStackClient) 66 67 name := d.Get("name").(string) 68 69 // Retrieve the network_offering UUID 70 networkofferingid, e := retrieveUUID(cs, "network_offering", d.Get("network_offering").(string)) 71 if e != nil { 72 return e.Error() 73 } 74 75 // Retrieve the zone UUID 76 zoneid, e := retrieveUUID(cs, "zone", d.Get("zone").(string)) 77 if e != nil { 78 return e.Error() 79 } 80 81 // Compute/set the display text 82 displaytext, ok := d.GetOk("display_text") 83 if !ok { 84 displaytext = name 85 } 86 87 // Create a new parameter struct 88 p := cs.Network.NewCreateNetworkParams(displaytext.(string), name, networkofferingid, zoneid) 89 90 // Get the network details from the CIDR 91 m, err := parseCIDR(d.Get("cidr").(string)) 92 if err != nil { 93 return err 94 } 95 96 // Set the needed IP config 97 p.SetStartip(m["start"]) 98 p.SetGateway(m["gateway"]) 99 p.SetEndip(m["end"]) 100 p.SetNetmask(m["netmask"]) 101 102 // Check is this network needs to be created in a VPC 103 vpc := d.Get("vpc").(string) 104 if vpc != "" { 105 // Retrieve the vpc UUID 106 vpcid, e := retrieveUUID(cs, "vpc", vpc) 107 if e != nil { 108 return e.Error() 109 } 110 111 // Set the vpc UUID 112 p.SetVpcid(vpcid) 113 114 // Since we're in a VPC, check if we want to assiciate an ACL list 115 aclid := d.Get("aclid").(string) 116 if aclid != "" { 117 // Set the acl UUID 118 p.SetAclid(aclid) 119 } 120 } 121 122 // Create the new network 123 r, err := cs.Network.CreateNetwork(p) 124 if err != nil { 125 return fmt.Errorf("Error creating network %s: %s", name, err) 126 } 127 128 d.SetId(r.Id) 129 130 return resourceCloudStackNetworkRead(d, meta) 131 } 132 133 func resourceCloudStackNetworkRead(d *schema.ResourceData, meta interface{}) error { 134 cs := meta.(*cloudstack.CloudStackClient) 135 136 // Get the virtual machine details 137 n, count, err := cs.Network.GetNetworkByID(d.Id()) 138 if err != nil { 139 if count == 0 { 140 log.Printf( 141 "[DEBUG] Network %s does no longer exist", d.Get("name").(string)) 142 d.SetId("") 143 return nil 144 } 145 146 return err 147 } 148 149 d.Set("name", n.Name) 150 d.Set("display_text", n.Displaytext) 151 d.Set("cidr", n.Cidr) 152 153 setValueOrUUID(d, "network_offering", n.Networkofferingname, n.Networkofferingid) 154 setValueOrUUID(d, "zone", n.Zonename, n.Zoneid) 155 156 return nil 157 } 158 159 func resourceCloudStackNetworkUpdate(d *schema.ResourceData, meta interface{}) error { 160 cs := meta.(*cloudstack.CloudStackClient) 161 name := d.Get("name").(string) 162 163 // Create a new parameter struct 164 p := cs.Network.NewUpdateNetworkParams(d.Id()) 165 166 // Check if the name or display text is changed 167 if d.HasChange("name") || d.HasChange("display_text") { 168 p.SetName(name) 169 170 // Compute/set the display text 171 displaytext := d.Get("display_text").(string) 172 if displaytext == "" { 173 displaytext = name 174 } 175 p.SetDisplaytext(displaytext) 176 } 177 178 // Check if the cidr is changed 179 if d.HasChange("cidr") { 180 p.SetGuestvmcidr(d.Get("cidr").(string)) 181 } 182 183 // Check if the network offering is changed 184 if d.HasChange("network_offering") { 185 // Retrieve the network_offering UUID 186 networkofferingid, e := retrieveUUID(cs, "network_offering", d.Get("network_offering").(string)) 187 if e != nil { 188 return e.Error() 189 } 190 // Set the new network offering 191 p.SetNetworkofferingid(networkofferingid) 192 } 193 194 // Update the network 195 _, err := cs.Network.UpdateNetwork(p) 196 if err != nil { 197 return fmt.Errorf( 198 "Error updating network %s: %s", name, err) 199 } 200 201 return resourceCloudStackNetworkRead(d, meta) 202 } 203 204 func resourceCloudStackNetworkDelete(d *schema.ResourceData, meta interface{}) error { 205 cs := meta.(*cloudstack.CloudStackClient) 206 207 // Create a new parameter struct 208 p := cs.Network.NewDeleteNetworkParams(d.Id()) 209 210 // Delete the network 211 _, err := cs.Network.DeleteNetwork(p) 212 if err != nil { 213 // This is a very poor way to be told the UUID does no longer exist :( 214 if strings.Contains(err.Error(), fmt.Sprintf( 215 "Invalid parameter id value=%s due to incorrect long value format, "+ 216 "or entity does not exist", d.Id())) { 217 return nil 218 } 219 220 return fmt.Errorf("Error deleting network %s: %s", d.Get("name").(string), err) 221 } 222 return nil 223 } 224 225 func parseCIDR(cidr string) (map[string]string, error) { 226 m := make(map[string]string, 4) 227 228 ip, ipnet, err := net.ParseCIDR(cidr) 229 if err != nil { 230 return nil, fmt.Errorf("Unable to parse cidr %s: %s", cidr, err) 231 } 232 233 msk := ipnet.Mask 234 sub := ip.Mask(msk) 235 236 m["netmask"] = fmt.Sprintf("%d.%d.%d.%d", msk[0], msk[1], msk[2], msk[3]) 237 m["gateway"] = fmt.Sprintf("%d.%d.%d.%d", sub[0], sub[1], sub[2], sub[3]+1) 238 m["start"] = fmt.Sprintf("%d.%d.%d.%d", sub[0], sub[1], sub[2], sub[3]+2) 239 m["end"] = fmt.Sprintf("%d.%d.%d.%d", 240 sub[0]+(0xff-msk[0]), sub[1]+(0xff-msk[1]), sub[2]+(0xff-msk[2]), sub[3]+(0xff-msk[3]-1)) 241 242 return m, nil 243 }