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