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