github.com/recobe182/terraform@v0.8.5-0.20170117231232-49ab22a935b7/builtin/providers/openstack/resource_openstack_networking_network_v2.go (about) 1 package openstack 2 3 import ( 4 "fmt" 5 "log" 6 "strconv" 7 "time" 8 9 "github.com/hashicorp/terraform/helper/resource" 10 "github.com/hashicorp/terraform/helper/schema" 11 12 "github.com/gophercloud/gophercloud" 13 "github.com/gophercloud/gophercloud/openstack/networking/v2/networks" 14 ) 15 16 func resourceNetworkingNetworkV2() *schema.Resource { 17 return &schema.Resource{ 18 Create: resourceNetworkingNetworkV2Create, 19 Read: resourceNetworkingNetworkV2Read, 20 Update: resourceNetworkingNetworkV2Update, 21 Delete: resourceNetworkingNetworkV2Delete, 22 Importer: &schema.ResourceImporter{ 23 State: schema.ImportStatePassthrough, 24 }, 25 26 Schema: map[string]*schema.Schema{ 27 "region": &schema.Schema{ 28 Type: schema.TypeString, 29 Required: true, 30 ForceNew: true, 31 DefaultFunc: schema.EnvDefaultFunc("OS_REGION_NAME", ""), 32 }, 33 "name": &schema.Schema{ 34 Type: schema.TypeString, 35 Optional: true, 36 ForceNew: false, 37 }, 38 "admin_state_up": &schema.Schema{ 39 Type: schema.TypeString, 40 Optional: true, 41 ForceNew: false, 42 Computed: true, 43 }, 44 "shared": &schema.Schema{ 45 Type: schema.TypeString, 46 Optional: true, 47 ForceNew: false, 48 Computed: true, 49 }, 50 "tenant_id": &schema.Schema{ 51 Type: schema.TypeString, 52 Optional: true, 53 ForceNew: true, 54 Computed: true, 55 }, 56 "value_specs": &schema.Schema{ 57 Type: schema.TypeMap, 58 Optional: true, 59 ForceNew: true, 60 }, 61 }, 62 } 63 } 64 65 func resourceNetworkingNetworkV2Create(d *schema.ResourceData, meta interface{}) error { 66 config := meta.(*Config) 67 networkingClient, err := config.networkingV2Client(GetRegion(d)) 68 if err != nil { 69 return fmt.Errorf("Error creating OpenStack networking client: %s", err) 70 } 71 72 createOpts := NetworkCreateOpts{ 73 networks.CreateOpts{ 74 Name: d.Get("name").(string), 75 TenantID: d.Get("tenant_id").(string), 76 }, 77 MapValueSpecs(d), 78 } 79 80 asuRaw := d.Get("admin_state_up").(string) 81 if asuRaw != "" { 82 asu, err := strconv.ParseBool(asuRaw) 83 if err != nil { 84 return fmt.Errorf("admin_state_up, if provided, must be either 'true' or 'false'") 85 } 86 createOpts.AdminStateUp = &asu 87 } 88 89 sharedRaw := d.Get("shared").(string) 90 if sharedRaw != "" { 91 shared, err := strconv.ParseBool(sharedRaw) 92 if err != nil { 93 return fmt.Errorf("shared, if provided, must be either 'true' or 'false': %v", err) 94 } 95 createOpts.Shared = &shared 96 } 97 98 log.Printf("[DEBUG] Create Options: %#v", createOpts) 99 n, err := networks.Create(networkingClient, createOpts).Extract() 100 if err != nil { 101 return fmt.Errorf("Error creating OpenStack Neutron network: %s", err) 102 } 103 log.Printf("[INFO] Network ID: %s", n.ID) 104 105 log.Printf("[DEBUG] Waiting for Network (%s) to become available", n.ID) 106 107 stateConf := &resource.StateChangeConf{ 108 Pending: []string{"BUILD"}, 109 Target: []string{"ACTIVE"}, 110 Refresh: waitForNetworkActive(networkingClient, n.ID), 111 Timeout: 2 * time.Minute, 112 Delay: 5 * time.Second, 113 MinTimeout: 3 * time.Second, 114 } 115 116 _, err = stateConf.WaitForState() 117 118 d.SetId(n.ID) 119 120 return resourceNetworkingNetworkV2Read(d, meta) 121 } 122 123 func resourceNetworkingNetworkV2Read(d *schema.ResourceData, meta interface{}) error { 124 config := meta.(*Config) 125 networkingClient, err := config.networkingV2Client(GetRegion(d)) 126 if err != nil { 127 return fmt.Errorf("Error creating OpenStack networking client: %s", err) 128 } 129 130 n, err := networks.Get(networkingClient, d.Id()).Extract() 131 if err != nil { 132 return CheckDeleted(d, err, "network") 133 } 134 135 log.Printf("[DEBUG] Retrieved Network %s: %+v", d.Id(), n) 136 137 d.Set("name", n.Name) 138 d.Set("admin_state_up", strconv.FormatBool(n.AdminStateUp)) 139 d.Set("shared", strconv.FormatBool(n.Shared)) 140 d.Set("tenant_id", n.TenantID) 141 d.Set("region", GetRegion(d)) 142 143 return nil 144 } 145 146 func resourceNetworkingNetworkV2Update(d *schema.ResourceData, meta interface{}) error { 147 config := meta.(*Config) 148 networkingClient, err := config.networkingV2Client(GetRegion(d)) 149 if err != nil { 150 return fmt.Errorf("Error creating OpenStack networking client: %s", err) 151 } 152 153 var updateOpts networks.UpdateOpts 154 if d.HasChange("name") { 155 updateOpts.Name = d.Get("name").(string) 156 } 157 if d.HasChange("admin_state_up") { 158 asuRaw := d.Get("admin_state_up").(string) 159 if asuRaw != "" { 160 asu, err := strconv.ParseBool(asuRaw) 161 if err != nil { 162 return fmt.Errorf("admin_state_up, if provided, must be either 'true' or 'false'") 163 } 164 updateOpts.AdminStateUp = &asu 165 } 166 } 167 if d.HasChange("shared") { 168 sharedRaw := d.Get("shared").(string) 169 if sharedRaw != "" { 170 shared, err := strconv.ParseBool(sharedRaw) 171 if err != nil { 172 return fmt.Errorf("shared, if provided, must be either 'true' or 'false': %v", err) 173 } 174 updateOpts.Shared = &shared 175 } 176 } 177 178 log.Printf("[DEBUG] Updating Network %s with options: %+v", d.Id(), updateOpts) 179 180 _, err = networks.Update(networkingClient, d.Id(), updateOpts).Extract() 181 if err != nil { 182 return fmt.Errorf("Error updating OpenStack Neutron Network: %s", err) 183 } 184 185 return resourceNetworkingNetworkV2Read(d, meta) 186 } 187 188 func resourceNetworkingNetworkV2Delete(d *schema.ResourceData, meta interface{}) error { 189 config := meta.(*Config) 190 networkingClient, err := config.networkingV2Client(GetRegion(d)) 191 if err != nil { 192 return fmt.Errorf("Error creating OpenStack networking client: %s", err) 193 } 194 195 stateConf := &resource.StateChangeConf{ 196 Pending: []string{"ACTIVE"}, 197 Target: []string{"DELETED"}, 198 Refresh: waitForNetworkDelete(networkingClient, d.Id()), 199 Timeout: 2 * time.Minute, 200 Delay: 5 * time.Second, 201 MinTimeout: 3 * time.Second, 202 } 203 204 _, err = stateConf.WaitForState() 205 if err != nil { 206 return fmt.Errorf("Error deleting OpenStack Neutron Network: %s", err) 207 } 208 209 d.SetId("") 210 return nil 211 } 212 213 func waitForNetworkActive(networkingClient *gophercloud.ServiceClient, networkId string) resource.StateRefreshFunc { 214 return func() (interface{}, string, error) { 215 n, err := networks.Get(networkingClient, networkId).Extract() 216 if err != nil { 217 return nil, "", err 218 } 219 220 log.Printf("[DEBUG] OpenStack Neutron Network: %+v", n) 221 if n.Status == "DOWN" || n.Status == "ACTIVE" { 222 return n, "ACTIVE", nil 223 } 224 225 return n, n.Status, nil 226 } 227 } 228 229 func waitForNetworkDelete(networkingClient *gophercloud.ServiceClient, networkId string) resource.StateRefreshFunc { 230 return func() (interface{}, string, error) { 231 log.Printf("[DEBUG] Attempting to delete OpenStack Network %s.\n", networkId) 232 233 n, err := networks.Get(networkingClient, networkId).Extract() 234 if err != nil { 235 if _, ok := err.(gophercloud.ErrDefault404); ok { 236 log.Printf("[DEBUG] Successfully deleted OpenStack Network %s", networkId) 237 return n, "DELETED", nil 238 } 239 return n, "ACTIVE", err 240 } 241 242 err = networks.Delete(networkingClient, networkId).ExtractErr() 243 if err != nil { 244 if _, ok := err.(gophercloud.ErrDefault404); ok { 245 log.Printf("[DEBUG] Successfully deleted OpenStack Network %s", networkId) 246 return n, "DELETED", nil 247 } 248 if errCode, ok := err.(gophercloud.ErrUnexpectedResponseCode); ok { 249 if errCode.Actual == 409 { 250 return n, "ACTIVE", nil 251 } 252 } 253 return n, "ACTIVE", err 254 } 255 256 log.Printf("[DEBUG] OpenStack Network %s still active.\n", networkId) 257 return n, "ACTIVE", nil 258 } 259 }