github.com/vtorhonen/terraform@v0.9.0-beta2.0.20170307220345-5d894e4ffda7/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(GetRegion(d))
    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(GetRegion(d))
   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  	d.Set("region", GetRegion(d))
   142  
   143  	return nil
   144  }
   145  
   146  func resourceNetworkingNetworkV2Update(d *schema.ResourceData, meta interface{}) error {
   147  	config := meta.(*Config)
   148  	networkingClient, err := config.networkingV2Client(GetRegion(d))
   149  	if err != nil {
   150  		return fmt.Errorf("Error creating OpenStack networking client: %s", err)
   151  	}
   152  
   153  	var updateOpts networks.UpdateOpts
   154  	if d.HasChange("name") {
   155  		updateOpts.Name = d.Get("name").(string)
   156  	}
   157  	if d.HasChange("admin_state_up") {
   158  		asuRaw := d.Get("admin_state_up").(string)
   159  		if asuRaw != "" {
   160  			asu, err := strconv.ParseBool(asuRaw)
   161  			if err != nil {
   162  				return fmt.Errorf("admin_state_up, if provided, must be either 'true' or 'false'")
   163  			}
   164  			updateOpts.AdminStateUp = &asu
   165  		}
   166  	}
   167  	if d.HasChange("shared") {
   168  		sharedRaw := d.Get("shared").(string)
   169  		if sharedRaw != "" {
   170  			shared, err := strconv.ParseBool(sharedRaw)
   171  			if err != nil {
   172  				return fmt.Errorf("shared, if provided, must be either 'true' or 'false': %v", err)
   173  			}
   174  			updateOpts.Shared = &shared
   175  		}
   176  	}
   177  
   178  	log.Printf("[DEBUG] Updating Network %s with options: %+v", d.Id(), updateOpts)
   179  
   180  	_, err = networks.Update(networkingClient, d.Id(), updateOpts).Extract()
   181  	if err != nil {
   182  		return fmt.Errorf("Error updating OpenStack Neutron Network: %s", err)
   183  	}
   184  
   185  	return resourceNetworkingNetworkV2Read(d, meta)
   186  }
   187  
   188  func resourceNetworkingNetworkV2Delete(d *schema.ResourceData, meta interface{}) error {
   189  	config := meta.(*Config)
   190  	networkingClient, err := config.networkingV2Client(GetRegion(d))
   191  	if err != nil {
   192  		return fmt.Errorf("Error creating OpenStack networking client: %s", err)
   193  	}
   194  
   195  	stateConf := &resource.StateChangeConf{
   196  		Pending:    []string{"ACTIVE"},
   197  		Target:     []string{"DELETED"},
   198  		Refresh:    waitForNetworkDelete(networkingClient, d.Id()),
   199  		Timeout:    2 * time.Minute,
   200  		Delay:      5 * time.Second,
   201  		MinTimeout: 3 * time.Second,
   202  	}
   203  
   204  	_, err = stateConf.WaitForState()
   205  	if err != nil {
   206  		return fmt.Errorf("Error deleting OpenStack Neutron Network: %s", err)
   207  	}
   208  
   209  	d.SetId("")
   210  	return nil
   211  }
   212  
   213  func waitForNetworkActive(networkingClient *gophercloud.ServiceClient, networkId string) resource.StateRefreshFunc {
   214  	return func() (interface{}, string, error) {
   215  		n, err := networks.Get(networkingClient, networkId).Extract()
   216  		if err != nil {
   217  			return nil, "", err
   218  		}
   219  
   220  		log.Printf("[DEBUG] OpenStack Neutron Network: %+v", n)
   221  		if n.Status == "DOWN" || n.Status == "ACTIVE" {
   222  			return n, "ACTIVE", nil
   223  		}
   224  
   225  		return n, n.Status, nil
   226  	}
   227  }
   228  
   229  func waitForNetworkDelete(networkingClient *gophercloud.ServiceClient, networkId string) resource.StateRefreshFunc {
   230  	return func() (interface{}, string, error) {
   231  		log.Printf("[DEBUG] Attempting to delete OpenStack Network %s.\n", networkId)
   232  
   233  		n, err := networks.Get(networkingClient, networkId).Extract()
   234  		if err != nil {
   235  			if _, ok := err.(gophercloud.ErrDefault404); ok {
   236  				log.Printf("[DEBUG] Successfully deleted OpenStack Network %s", networkId)
   237  				return n, "DELETED", nil
   238  			}
   239  			return n, "ACTIVE", err
   240  		}
   241  
   242  		err = networks.Delete(networkingClient, networkId).ExtractErr()
   243  		if err != nil {
   244  			if _, ok := err.(gophercloud.ErrDefault404); ok {
   245  				log.Printf("[DEBUG] Successfully deleted OpenStack Network %s", networkId)
   246  				return n, "DELETED", nil
   247  			}
   248  			if errCode, ok := err.(gophercloud.ErrUnexpectedResponseCode); ok {
   249  				if errCode.Actual == 409 {
   250  					return n, "ACTIVE", nil
   251  				}
   252  			}
   253  			return n, "ACTIVE", err
   254  		}
   255  
   256  		log.Printf("[DEBUG] OpenStack Network %s still active.\n", networkId)
   257  		return n, "ACTIVE", nil
   258  	}
   259  }