github.com/nicgrayson/terraform@v0.4.3-0.20150415203910-c4de50829380/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 d.Set("network_offering", n.Networkofferingname) 153 d.Set("zone", n.Zonename) 154 155 return nil 156 } 157 158 func resourceCloudStackNetworkUpdate(d *schema.ResourceData, meta interface{}) error { 159 cs := meta.(*cloudstack.CloudStackClient) 160 name := d.Get("name").(string) 161 162 // Create a new parameter struct 163 p := cs.Network.NewUpdateNetworkParams(d.Id()) 164 165 // Check if the name or display text is changed 166 if d.HasChange("name") || d.HasChange("display_text") { 167 p.SetName(name) 168 169 // Compute/set the display text 170 displaytext := d.Get("display_text").(string) 171 if displaytext == "" { 172 displaytext = name 173 } 174 p.SetDisplaytext(displaytext) 175 } 176 177 // Check if the cidr is changed 178 if d.HasChange("cidr") { 179 p.SetGuestvmcidr(d.Get("cidr").(string)) 180 } 181 182 // Check if the network offering is changed 183 if d.HasChange("network_offering") { 184 // Retrieve the network_offering UUID 185 networkofferingid, e := retrieveUUID(cs, "network_offering", d.Get("network_offering").(string)) 186 if e != nil { 187 return e.Error() 188 } 189 // Set the new network offering 190 p.SetNetworkofferingid(networkofferingid) 191 } 192 193 // Update the network 194 _, err := cs.Network.UpdateNetwork(p) 195 if err != nil { 196 return fmt.Errorf( 197 "Error updating network %s: %s", name, err) 198 } 199 200 return resourceCloudStackNetworkRead(d, meta) 201 } 202 203 func resourceCloudStackNetworkDelete(d *schema.ResourceData, meta interface{}) error { 204 cs := meta.(*cloudstack.CloudStackClient) 205 206 // Create a new parameter struct 207 p := cs.Network.NewDeleteNetworkParams(d.Id()) 208 209 // Delete the network 210 _, err := cs.Network.DeleteNetwork(p) 211 if err != nil { 212 // This is a very poor way to be told the UUID does no longer exist :( 213 if strings.Contains(err.Error(), fmt.Sprintf( 214 "Invalid parameter id value=%s due to incorrect long value format, "+ 215 "or entity does not exist", d.Id())) { 216 return nil 217 } 218 219 return fmt.Errorf("Error deleting network %s: %s", d.Get("name").(string), err) 220 } 221 return nil 222 } 223 224 func parseCIDR(cidr string) (map[string]string, error) { 225 m := make(map[string]string, 4) 226 227 ip, ipnet, err := net.ParseCIDR(cidr) 228 if err != nil { 229 return nil, fmt.Errorf("Unable to parse cidr %s: %s", cidr, err) 230 } 231 232 msk := ipnet.Mask 233 sub := ip.Mask(msk) 234 235 m["netmask"] = fmt.Sprintf("%d.%d.%d.%d", msk[0], msk[1], msk[2], msk[3]) 236 m["gateway"] = fmt.Sprintf("%d.%d.%d.%d", sub[0], sub[1], sub[2], sub[3]+1) 237 m["start"] = fmt.Sprintf("%d.%d.%d.%d", sub[0], sub[1], sub[2], sub[3]+2) 238 m["end"] = fmt.Sprintf("%d.%d.%d.%d", 239 sub[0]+(0xff-msk[0]), sub[1]+(0xff-msk[1]), sub[2]+(0xff-msk[2]), sub[3]+(0xff-msk[3]-1)) 240 241 return m, nil 242 }