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  }