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