github.com/turtlemonvh/terraform@v0.6.9-0.20151204001754-8e40b6b855e8/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 "project": &schema.Schema{ 56 Type: schema.TypeString, 57 Optional: true, 58 ForceNew: true, 59 }, 60 61 "zone": &schema.Schema{ 62 Type: schema.TypeString, 63 Required: true, 64 ForceNew: true, 65 }, 66 }, 67 } 68 } 69 70 func resourceCloudStackNetworkCreate(d *schema.ResourceData, meta interface{}) error { 71 cs := meta.(*cloudstack.CloudStackClient) 72 73 name := d.Get("name").(string) 74 75 // Retrieve the network_offering ID 76 networkofferingid, e := retrieveID(cs, "network_offering", d.Get("network_offering").(string)) 77 if e != nil { 78 return e.Error() 79 } 80 81 // Retrieve the zone ID 82 zoneid, e := retrieveID(cs, "zone", d.Get("zone").(string)) 83 if e != nil { 84 return e.Error() 85 } 86 87 // Compute/set the display text 88 displaytext, ok := d.GetOk("display_text") 89 if !ok { 90 displaytext = name 91 } 92 93 // Create a new parameter struct 94 p := cs.Network.NewCreateNetworkParams(displaytext.(string), name, networkofferingid, zoneid) 95 96 // Get the network details from the CIDR 97 m, err := parseCIDR(d.Get("cidr").(string)) 98 if err != nil { 99 return err 100 } 101 102 // Set the needed IP config 103 p.SetStartip(m["start"]) 104 p.SetGateway(m["gateway"]) 105 p.SetEndip(m["end"]) 106 p.SetNetmask(m["netmask"]) 107 108 // Check is this network needs to be created in a VPC 109 vpc := d.Get("vpc").(string) 110 if vpc != "" { 111 // Retrieve the vpc ID 112 vpcid, e := retrieveID(cs, "vpc", vpc) 113 if e != nil { 114 return e.Error() 115 } 116 117 // Set the vpc ID 118 p.SetVpcid(vpcid) 119 120 // Since we're in a VPC, check if we want to assiciate an ACL list 121 aclid := d.Get("aclid").(string) 122 if aclid != "" { 123 // Set the acl ID 124 p.SetAclid(aclid) 125 } 126 } 127 128 // If there is a project supplied, we retrieve and set the project id 129 if project, ok := d.GetOk("project"); ok { 130 // Retrieve the project ID 131 projectid, e := retrieveID(cs, "project", project.(string)) 132 if e != nil { 133 return e.Error() 134 } 135 // Set the default project ID 136 p.SetProjectid(projectid) 137 } 138 139 // Create the new network 140 r, err := cs.Network.CreateNetwork(p) 141 if err != nil { 142 return fmt.Errorf("Error creating network %s: %s", name, err) 143 } 144 145 d.SetId(r.Id) 146 147 return resourceCloudStackNetworkRead(d, meta) 148 } 149 150 func resourceCloudStackNetworkRead(d *schema.ResourceData, meta interface{}) error { 151 cs := meta.(*cloudstack.CloudStackClient) 152 153 // Get the virtual machine details 154 n, count, err := cs.Network.GetNetworkByID(d.Id()) 155 if err != nil { 156 if count == 0 { 157 log.Printf( 158 "[DEBUG] Network %s does no longer exist", d.Get("name").(string)) 159 d.SetId("") 160 return nil 161 } 162 163 return err 164 } 165 166 d.Set("name", n.Name) 167 d.Set("display_text", n.Displaytext) 168 d.Set("cidr", n.Cidr) 169 170 setValueOrID(d, "network_offering", n.Networkofferingname, n.Networkofferingid) 171 setValueOrID(d, "project", n.Project, n.Projectid) 172 setValueOrID(d, "zone", n.Zonename, n.Zoneid) 173 174 return nil 175 } 176 177 func resourceCloudStackNetworkUpdate(d *schema.ResourceData, meta interface{}) error { 178 cs := meta.(*cloudstack.CloudStackClient) 179 name := d.Get("name").(string) 180 181 // Create a new parameter struct 182 p := cs.Network.NewUpdateNetworkParams(d.Id()) 183 184 // Check if the name or display text is changed 185 if d.HasChange("name") || d.HasChange("display_text") { 186 p.SetName(name) 187 188 // Compute/set the display text 189 displaytext := d.Get("display_text").(string) 190 if displaytext == "" { 191 displaytext = name 192 } 193 p.SetDisplaytext(displaytext) 194 } 195 196 // Check if the cidr is changed 197 if d.HasChange("cidr") { 198 p.SetGuestvmcidr(d.Get("cidr").(string)) 199 } 200 201 // Check if the network offering is changed 202 if d.HasChange("network_offering") { 203 // Retrieve the network_offering ID 204 networkofferingid, e := retrieveID(cs, "network_offering", d.Get("network_offering").(string)) 205 if e != nil { 206 return e.Error() 207 } 208 // Set the new network offering 209 p.SetNetworkofferingid(networkofferingid) 210 } 211 212 // Update the network 213 _, err := cs.Network.UpdateNetwork(p) 214 if err != nil { 215 return fmt.Errorf( 216 "Error updating network %s: %s", name, err) 217 } 218 219 return resourceCloudStackNetworkRead(d, meta) 220 } 221 222 func resourceCloudStackNetworkDelete(d *schema.ResourceData, meta interface{}) error { 223 cs := meta.(*cloudstack.CloudStackClient) 224 225 // Create a new parameter struct 226 p := cs.Network.NewDeleteNetworkParams(d.Id()) 227 228 // Delete the network 229 _, err := cs.Network.DeleteNetwork(p) 230 if err != nil { 231 // This is a very poor way to be told the ID does no longer exist :( 232 if strings.Contains(err.Error(), fmt.Sprintf( 233 "Invalid parameter id value=%s due to incorrect long value format, "+ 234 "or entity does not exist", d.Id())) { 235 return nil 236 } 237 238 return fmt.Errorf("Error deleting network %s: %s", d.Get("name").(string), err) 239 } 240 return nil 241 } 242 243 func parseCIDR(cidr string) (map[string]string, error) { 244 m := make(map[string]string, 4) 245 246 ip, ipnet, err := net.ParseCIDR(cidr) 247 if err != nil { 248 return nil, fmt.Errorf("Unable to parse cidr %s: %s", cidr, err) 249 } 250 251 msk := ipnet.Mask 252 sub := ip.Mask(msk) 253 254 m["netmask"] = fmt.Sprintf("%d.%d.%d.%d", msk[0], msk[1], msk[2], msk[3]) 255 m["gateway"] = fmt.Sprintf("%d.%d.%d.%d", sub[0], sub[1], sub[2], sub[3]+1) 256 m["start"] = fmt.Sprintf("%d.%d.%d.%d", sub[0], sub[1], sub[2], sub[3]+2) 257 m["end"] = fmt.Sprintf("%d.%d.%d.%d", 258 sub[0]+(0xff-msk[0]), sub[1]+(0xff-msk[1]), sub[2]+(0xff-msk[2]), sub[3]+(0xff-msk[3]-1)) 259 260 return m, nil 261 }