github.com/joshgarnett/terraform@v0.5.4-0.20160219181435-92dc20bb3594/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/rackspace/gophercloud" 12 "github.com/rackspace/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: envDefaultFuncAllowMissing("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 }, 58 } 59 } 60 61 func resourceNetworkingRouterV2Create(d *schema.ResourceData, meta interface{}) error { 62 config := meta.(*Config) 63 networkingClient, err := config.networkingV2Client(d.Get("region").(string)) 64 if err != nil { 65 return fmt.Errorf("Error creating OpenStack networking client: %s", err) 66 } 67 68 createOpts := routers.CreateOpts{ 69 Name: d.Get("name").(string), 70 TenantID: d.Get("tenant_id").(string), 71 } 72 73 if asuRaw, ok := d.GetOk("admin_state_up"); ok { 74 asu := asuRaw.(bool) 75 createOpts.AdminStateUp = &asu 76 } 77 78 if dRaw, ok := d.GetOk("distributed"); ok { 79 d := dRaw.(bool) 80 createOpts.Distributed = &d 81 } 82 83 externalGateway := d.Get("external_gateway").(string) 84 if externalGateway != "" { 85 gatewayInfo := routers.GatewayInfo{ 86 NetworkID: externalGateway, 87 } 88 createOpts.GatewayInfo = &gatewayInfo 89 } 90 91 log.Printf("[DEBUG] Create Options: %#v", createOpts) 92 n, err := routers.Create(networkingClient, createOpts).Extract() 93 if err != nil { 94 return fmt.Errorf("Error creating OpenStack Neutron router: %s", err) 95 } 96 log.Printf("[INFO] Router ID: %s", n.ID) 97 98 log.Printf("[DEBUG] Waiting for OpenStack Neutron Router (%s) to become available", n.ID) 99 stateConf := &resource.StateChangeConf{ 100 Pending: []string{"BUILD", "PENDING_CREATE", "PENDING_UPDATE"}, 101 Target: []string{"ACTIVE"}, 102 Refresh: waitForRouterActive(networkingClient, n.ID), 103 Timeout: 2 * time.Minute, 104 Delay: 5 * time.Second, 105 MinTimeout: 3 * time.Second, 106 } 107 108 _, err = stateConf.WaitForState() 109 110 d.SetId(n.ID) 111 112 return resourceNetworkingRouterV2Read(d, meta) 113 } 114 115 func resourceNetworkingRouterV2Read(d *schema.ResourceData, meta interface{}) error { 116 config := meta.(*Config) 117 networkingClient, err := config.networkingV2Client(d.Get("region").(string)) 118 if err != nil { 119 return fmt.Errorf("Error creating OpenStack networking client: %s", err) 120 } 121 122 n, err := routers.Get(networkingClient, d.Id()).Extract() 123 if err != nil { 124 httpError, ok := err.(*gophercloud.UnexpectedResponseCodeError) 125 if !ok { 126 return fmt.Errorf("Error retrieving OpenStack Neutron Router: %s", err) 127 } 128 129 if httpError.Actual == 404 { 130 d.SetId("") 131 return nil 132 } 133 return fmt.Errorf("Error retrieving OpenStack Neutron Router: %s", err) 134 } 135 136 log.Printf("[DEBUG] Retreived Router %s: %+v", d.Id(), n) 137 138 d.Set("name", n.Name) 139 d.Set("admin_state_up", n.AdminStateUp) 140 d.Set("distributed", n.Distributed) 141 d.Set("tenant_id", n.TenantID) 142 d.Set("external_gateway", n.GatewayInfo.NetworkID) 143 144 return nil 145 } 146 147 func resourceNetworkingRouterV2Update(d *schema.ResourceData, meta interface{}) error { 148 config := meta.(*Config) 149 networkingClient, err := config.networkingV2Client(d.Get("region").(string)) 150 if err != nil { 151 return fmt.Errorf("Error creating OpenStack networking client: %s", err) 152 } 153 154 var updateOpts routers.UpdateOpts 155 if d.HasChange("name") { 156 updateOpts.Name = d.Get("name").(string) 157 } 158 if d.HasChange("admin_state_up") { 159 asu := d.Get("admin_state_up").(bool) 160 updateOpts.AdminStateUp = &asu 161 } 162 163 log.Printf("[DEBUG] Updating Router %s with options: %+v", d.Id(), updateOpts) 164 165 _, err = routers.Update(networkingClient, d.Id(), updateOpts).Extract() 166 if err != nil { 167 return fmt.Errorf("Error updating OpenStack Neutron Router: %s", err) 168 } 169 170 return resourceNetworkingRouterV2Read(d, meta) 171 } 172 173 func resourceNetworkingRouterV2Delete(d *schema.ResourceData, meta interface{}) error { 174 config := meta.(*Config) 175 networkingClient, err := config.networkingV2Client(d.Get("region").(string)) 176 if err != nil { 177 return fmt.Errorf("Error creating OpenStack networking client: %s", err) 178 } 179 180 stateConf := &resource.StateChangeConf{ 181 Pending: []string{"ACTIVE"}, 182 Target: []string{"DELETED"}, 183 Refresh: waitForRouterDelete(networkingClient, d.Id()), 184 Timeout: 2 * time.Minute, 185 Delay: 5 * time.Second, 186 MinTimeout: 3 * time.Second, 187 } 188 189 _, err = stateConf.WaitForState() 190 if err != nil { 191 return fmt.Errorf("Error deleting OpenStack Neutron Router: %s", err) 192 } 193 194 d.SetId("") 195 return nil 196 } 197 198 func waitForRouterActive(networkingClient *gophercloud.ServiceClient, routerId string) resource.StateRefreshFunc { 199 return func() (interface{}, string, error) { 200 r, err := routers.Get(networkingClient, routerId).Extract() 201 if err != nil { 202 return nil, r.Status, err 203 } 204 205 log.Printf("[DEBUG] OpenStack Neutron Router: %+v", r) 206 return r, r.Status, nil 207 } 208 } 209 210 func waitForRouterDelete(networkingClient *gophercloud.ServiceClient, routerId string) resource.StateRefreshFunc { 211 return func() (interface{}, string, error) { 212 log.Printf("[DEBUG] Attempting to delete OpenStack Router %s.\n", routerId) 213 214 r, err := routers.Get(networkingClient, routerId).Extract() 215 if err != nil { 216 errCode, ok := err.(*gophercloud.UnexpectedResponseCodeError) 217 if !ok { 218 return r, "ACTIVE", err 219 } 220 if errCode.Actual == 404 { 221 log.Printf("[DEBUG] Successfully deleted OpenStack Router %s", routerId) 222 return r, "DELETED", nil 223 } 224 } 225 226 err = routers.Delete(networkingClient, routerId).ExtractErr() 227 if err != nil { 228 errCode, ok := err.(*gophercloud.UnexpectedResponseCodeError) 229 if !ok { 230 return r, "ACTIVE", err 231 } 232 if errCode.Actual == 404 { 233 log.Printf("[DEBUG] Successfully deleted OpenStack Router %s", routerId) 234 return r, "DELETED", nil 235 } 236 } 237 238 log.Printf("[DEBUG] OpenStack Router %s still active.\n", routerId) 239 return r, "ACTIVE", nil 240 } 241 }