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  }