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