github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/builtin/providers/openstack/resource_openstack_networking_router_v2.go (about) 1 package openstack 2 3 import ( 4 "fmt" 5 "log" 6 "time" 7 8 "github.com/hashicorp/terraform/helper/resource" 9 "github.com/hashicorp/terraform/helper/schema" 10 11 "github.com/gophercloud/gophercloud" 12 "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers" 13 ) 14 15 func resourceNetworkingRouterV2() *schema.Resource { 16 return &schema.Resource{ 17 Create: resourceNetworkingRouterV2Create, 18 Read: resourceNetworkingRouterV2Read, 19 Update: resourceNetworkingRouterV2Update, 20 Delete: resourceNetworkingRouterV2Delete, 21 22 Timeouts: &schema.ResourceTimeout{ 23 Create: schema.DefaultTimeout(10 * time.Minute), 24 Delete: schema.DefaultTimeout(10 * time.Minute), 25 }, 26 27 Schema: map[string]*schema.Schema{ 28 "region": &schema.Schema{ 29 Type: schema.TypeString, 30 Required: true, 31 ForceNew: true, 32 DefaultFunc: schema.EnvDefaultFunc("OS_REGION_NAME", ""), 33 }, 34 "name": &schema.Schema{ 35 Type: schema.TypeString, 36 Optional: true, 37 ForceNew: false, 38 }, 39 "admin_state_up": &schema.Schema{ 40 Type: schema.TypeBool, 41 Optional: true, 42 ForceNew: false, 43 Computed: true, 44 }, 45 "distributed": &schema.Schema{ 46 Type: schema.TypeBool, 47 Optional: true, 48 ForceNew: true, 49 Computed: true, 50 }, 51 "external_gateway": &schema.Schema{ 52 Type: schema.TypeString, 53 Optional: true, 54 ForceNew: false, 55 }, 56 "tenant_id": &schema.Schema{ 57 Type: schema.TypeString, 58 Optional: true, 59 ForceNew: true, 60 Computed: true, 61 }, 62 "value_specs": &schema.Schema{ 63 Type: schema.TypeMap, 64 Optional: true, 65 ForceNew: true, 66 }, 67 }, 68 } 69 } 70 71 func resourceNetworkingRouterV2Create(d *schema.ResourceData, meta interface{}) error { 72 config := meta.(*Config) 73 networkingClient, err := config.networkingV2Client(GetRegion(d)) 74 if err != nil { 75 return fmt.Errorf("Error creating OpenStack networking client: %s", err) 76 } 77 78 createOpts := RouterCreateOpts{ 79 routers.CreateOpts{ 80 Name: d.Get("name").(string), 81 TenantID: d.Get("tenant_id").(string), 82 }, 83 MapValueSpecs(d), 84 } 85 86 if asuRaw, ok := d.GetOk("admin_state_up"); ok { 87 asu := asuRaw.(bool) 88 createOpts.AdminStateUp = &asu 89 } 90 91 if dRaw, ok := d.GetOk("distributed"); ok { 92 d := dRaw.(bool) 93 createOpts.Distributed = &d 94 } 95 96 externalGateway := d.Get("external_gateway").(string) 97 if externalGateway != "" { 98 gatewayInfo := routers.GatewayInfo{ 99 NetworkID: externalGateway, 100 } 101 createOpts.GatewayInfo = &gatewayInfo 102 } 103 104 log.Printf("[DEBUG] Create Options: %#v", createOpts) 105 n, err := routers.Create(networkingClient, createOpts).Extract() 106 if err != nil { 107 return fmt.Errorf("Error creating OpenStack Neutron router: %s", err) 108 } 109 log.Printf("[INFO] Router ID: %s", n.ID) 110 111 log.Printf("[DEBUG] Waiting for OpenStack Neutron Router (%s) to become available", n.ID) 112 stateConf := &resource.StateChangeConf{ 113 Pending: []string{"BUILD", "PENDING_CREATE", "PENDING_UPDATE"}, 114 Target: []string{"ACTIVE"}, 115 Refresh: waitForRouterActive(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 resourceNetworkingRouterV2Read(d, meta) 126 } 127 128 func resourceNetworkingRouterV2Read(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 := routers.Get(networkingClient, d.Id()).Extract() 136 if err != nil { 137 if _, ok := err.(gophercloud.ErrDefault404); ok { 138 d.SetId("") 139 return nil 140 } 141 142 return fmt.Errorf("Error retrieving OpenStack Neutron Router: %s", err) 143 } 144 145 log.Printf("[DEBUG] Retrieved Router %s: %+v", d.Id(), n) 146 147 d.Set("name", n.Name) 148 d.Set("admin_state_up", n.AdminStateUp) 149 d.Set("distributed", n.Distributed) 150 d.Set("tenant_id", n.TenantID) 151 d.Set("external_gateway", n.GatewayInfo.NetworkID) 152 153 return nil 154 } 155 156 func resourceNetworkingRouterV2Update(d *schema.ResourceData, meta interface{}) error { 157 routerId := d.Id() 158 osMutexKV.Lock(routerId) 159 defer osMutexKV.Unlock(routerId) 160 161 config := meta.(*Config) 162 networkingClient, err := config.networkingV2Client(GetRegion(d)) 163 if err != nil { 164 return fmt.Errorf("Error creating OpenStack networking client: %s", err) 165 } 166 167 var updateOpts routers.UpdateOpts 168 if d.HasChange("name") { 169 updateOpts.Name = d.Get("name").(string) 170 } 171 if d.HasChange("admin_state_up") { 172 asu := d.Get("admin_state_up").(bool) 173 updateOpts.AdminStateUp = &asu 174 } 175 if d.HasChange("external_gateway") { 176 externalGateway := d.Get("external_gateway").(string) 177 if externalGateway != "" { 178 gatewayInfo := routers.GatewayInfo{ 179 NetworkID: externalGateway, 180 } 181 updateOpts.GatewayInfo = &gatewayInfo 182 } 183 } 184 185 log.Printf("[DEBUG] Updating Router %s with options: %+v", d.Id(), updateOpts) 186 187 _, err = routers.Update(networkingClient, d.Id(), updateOpts).Extract() 188 if err != nil { 189 return fmt.Errorf("Error updating OpenStack Neutron Router: %s", err) 190 } 191 192 return resourceNetworkingRouterV2Read(d, meta) 193 } 194 195 func resourceNetworkingRouterV2Delete(d *schema.ResourceData, meta interface{}) error { 196 config := meta.(*Config) 197 networkingClient, err := config.networkingV2Client(GetRegion(d)) 198 if err != nil { 199 return fmt.Errorf("Error creating OpenStack networking client: %s", err) 200 } 201 202 stateConf := &resource.StateChangeConf{ 203 Pending: []string{"ACTIVE"}, 204 Target: []string{"DELETED"}, 205 Refresh: waitForRouterDelete(networkingClient, d.Id()), 206 Timeout: d.Timeout(schema.TimeoutDelete), 207 Delay: 5 * time.Second, 208 MinTimeout: 3 * time.Second, 209 } 210 211 _, err = stateConf.WaitForState() 212 if err != nil { 213 return fmt.Errorf("Error deleting OpenStack Neutron Router: %s", err) 214 } 215 216 d.SetId("") 217 return nil 218 } 219 220 func waitForRouterActive(networkingClient *gophercloud.ServiceClient, routerId string) resource.StateRefreshFunc { 221 return func() (interface{}, string, error) { 222 r, err := routers.Get(networkingClient, routerId).Extract() 223 if err != nil { 224 return nil, r.Status, err 225 } 226 227 log.Printf("[DEBUG] OpenStack Neutron Router: %+v", r) 228 return r, r.Status, nil 229 } 230 } 231 232 func waitForRouterDelete(networkingClient *gophercloud.ServiceClient, routerId string) resource.StateRefreshFunc { 233 return func() (interface{}, string, error) { 234 log.Printf("[DEBUG] Attempting to delete OpenStack Router %s.\n", routerId) 235 236 r, err := routers.Get(networkingClient, routerId).Extract() 237 if err != nil { 238 if _, ok := err.(gophercloud.ErrDefault404); ok { 239 log.Printf("[DEBUG] Successfully deleted OpenStack Router %s", routerId) 240 return r, "DELETED", nil 241 } 242 return r, "ACTIVE", err 243 } 244 245 err = routers.Delete(networkingClient, routerId).ExtractErr() 246 if err != nil { 247 if _, ok := err.(gophercloud.ErrDefault404); ok { 248 log.Printf("[DEBUG] Successfully deleted OpenStack Router %s", routerId) 249 return r, "DELETED", nil 250 } 251 return r, "ACTIVE", err 252 } 253 254 log.Printf("[DEBUG] OpenStack Router %s still active.\n", routerId) 255 return r, "ACTIVE", nil 256 } 257 }