github.com/jmbataller/terraform@v0.6.8-0.20151125192640-b7a12e3a580c/builtin/providers/openstack/resource_openstack_lb_vip_v1.go (about)

     1  package openstack
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  
     7  	"github.com/hashicorp/terraform/helper/schema"
     8  	"github.com/rackspace/gophercloud"
     9  	"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/floatingips"
    10  	"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/vips"
    11  )
    12  
    13  func resourceLBVipV1() *schema.Resource {
    14  	return &schema.Resource{
    15  		Create: resourceLBVipV1Create,
    16  		Read:   resourceLBVipV1Read,
    17  		Update: resourceLBVipV1Update,
    18  		Delete: resourceLBVipV1Delete,
    19  
    20  		Schema: map[string]*schema.Schema{
    21  			"region": &schema.Schema{
    22  				Type:        schema.TypeString,
    23  				Required:    true,
    24  				ForceNew:    true,
    25  				DefaultFunc: envDefaultFuncAllowMissing("OS_REGION_NAME"),
    26  			},
    27  			"name": &schema.Schema{
    28  				Type:     schema.TypeString,
    29  				Required: true,
    30  				ForceNew: false,
    31  			},
    32  			"subnet_id": &schema.Schema{
    33  				Type:     schema.TypeString,
    34  				Required: true,
    35  				ForceNew: true,
    36  			},
    37  			"protocol": &schema.Schema{
    38  				Type:     schema.TypeString,
    39  				Required: true,
    40  				ForceNew: true,
    41  			},
    42  			"port": &schema.Schema{
    43  				Type:     schema.TypeInt,
    44  				Required: true,
    45  				ForceNew: true,
    46  			},
    47  			"pool_id": &schema.Schema{
    48  				Type:     schema.TypeString,
    49  				Required: true,
    50  				ForceNew: false,
    51  			},
    52  			"tenant_id": &schema.Schema{
    53  				Type:     schema.TypeString,
    54  				Optional: true,
    55  				Computed: true,
    56  				ForceNew: true,
    57  			},
    58  			"address": &schema.Schema{
    59  				Type:     schema.TypeString,
    60  				Optional: true,
    61  				Computed: true,
    62  				ForceNew: true,
    63  			},
    64  			"description": &schema.Schema{
    65  				Type:     schema.TypeString,
    66  				Optional: true,
    67  				Computed: true,
    68  				ForceNew: false,
    69  			},
    70  			"persistence": &schema.Schema{
    71  				Type:     schema.TypeMap,
    72  				Optional: true,
    73  				ForceNew: false,
    74  			},
    75  			"conn_limit": &schema.Schema{
    76  				Type:     schema.TypeInt,
    77  				Optional: true,
    78  				Computed: true,
    79  				ForceNew: false,
    80  			},
    81  			"port_id": &schema.Schema{
    82  				Type:     schema.TypeString,
    83  				Computed: true,
    84  				ForceNew: false,
    85  			},
    86  			"floating_ip": &schema.Schema{
    87  				Type:     schema.TypeString,
    88  				Optional: true,
    89  				ForceNew: false,
    90  			},
    91  			"admin_state_up": &schema.Schema{
    92  				Type:     schema.TypeBool,
    93  				Optional: true,
    94  				Computed: true,
    95  				ForceNew: false,
    96  			},
    97  		},
    98  	}
    99  }
   100  
   101  func resourceLBVipV1Create(d *schema.ResourceData, meta interface{}) error {
   102  	config := meta.(*Config)
   103  	networkingClient, err := config.networkingV2Client(d.Get("region").(string))
   104  	if err != nil {
   105  		return fmt.Errorf("Error creating OpenStack networking client: %s", err)
   106  	}
   107  
   108  	createOpts := vips.CreateOpts{
   109  		Name:         d.Get("name").(string),
   110  		SubnetID:     d.Get("subnet_id").(string),
   111  		Protocol:     d.Get("protocol").(string),
   112  		ProtocolPort: d.Get("port").(int),
   113  		PoolID:       d.Get("pool_id").(string),
   114  		TenantID:     d.Get("tenant_id").(string),
   115  		Address:      d.Get("address").(string),
   116  		Description:  d.Get("description").(string),
   117  		Persistence:  resourceVipPersistenceV1(d),
   118  		ConnLimit:    gophercloud.MaybeInt(d.Get("conn_limit").(int)),
   119  	}
   120  
   121  	asu := d.Get("admin_state_up").(bool)
   122  	createOpts.AdminStateUp = &asu
   123  
   124  	log.Printf("[DEBUG] Create Options: %#v", createOpts)
   125  	p, err := vips.Create(networkingClient, createOpts).Extract()
   126  	if err != nil {
   127  		return fmt.Errorf("Error creating OpenStack LB VIP: %s", err)
   128  	}
   129  	log.Printf("[INFO] LB VIP ID: %s", p.ID)
   130  
   131  	floatingIP := d.Get("floating_ip").(string)
   132  	if floatingIP != "" {
   133  		lbVipV1AssignFloatingIP(floatingIP, p.PortID, networkingClient)
   134  	}
   135  
   136  	d.SetId(p.ID)
   137  
   138  	return resourceLBVipV1Read(d, meta)
   139  }
   140  
   141  func resourceLBVipV1Read(d *schema.ResourceData, meta interface{}) error {
   142  	config := meta.(*Config)
   143  	networkingClient, err := config.networkingV2Client(d.Get("region").(string))
   144  	if err != nil {
   145  		return fmt.Errorf("Error creating OpenStack networking client: %s", err)
   146  	}
   147  
   148  	p, err := vips.Get(networkingClient, d.Id()).Extract()
   149  	if err != nil {
   150  		return CheckDeleted(d, err, "LB VIP")
   151  	}
   152  
   153  	log.Printf("[DEBUG] Retreived OpenStack LB VIP %s: %+v", d.Id(), p)
   154  
   155  	d.Set("name", p.Name)
   156  	d.Set("subnet_id", p.SubnetID)
   157  	d.Set("protocol", p.Protocol)
   158  	d.Set("port", p.ProtocolPort)
   159  	d.Set("pool_id", p.PoolID)
   160  	d.Set("port_id", p.PortID)
   161  	d.Set("tenant_id", p.TenantID)
   162  	d.Set("address", p.Address)
   163  	d.Set("description", p.Description)
   164  	d.Set("conn_limit", p.ConnLimit)
   165  	d.Set("admin_state_up", p.AdminStateUp)
   166  
   167  	return nil
   168  }
   169  
   170  func resourceLBVipV1Update(d *schema.ResourceData, meta interface{}) error {
   171  	config := meta.(*Config)
   172  	networkingClient, err := config.networkingV2Client(d.Get("region").(string))
   173  	if err != nil {
   174  		return fmt.Errorf("Error creating OpenStack networking client: %s", err)
   175  	}
   176  
   177  	var updateOpts vips.UpdateOpts
   178  	if d.HasChange("name") {
   179  		updateOpts.Name = d.Get("name").(string)
   180  	}
   181  	if d.HasChange("pool_id") {
   182  		updateOpts.PoolID = d.Get("pool_id").(string)
   183  	}
   184  	if d.HasChange("description") {
   185  		updateOpts.Description = d.Get("description").(string)
   186  	}
   187  	if d.HasChange("persistence") {
   188  		updateOpts.Persistence = resourceVipPersistenceV1(d)
   189  	}
   190  	if d.HasChange("conn_limit") {
   191  		updateOpts.ConnLimit = gophercloud.MaybeInt(d.Get("conn_limit").(int))
   192  	}
   193  	if d.HasChange("floating_ip") {
   194  		portID := d.Get("port_id").(string)
   195  
   196  		// Searching for a floating IP assigned to the VIP
   197  		listOpts := floatingips.ListOpts{
   198  			PortID: portID,
   199  		}
   200  		page, err := floatingips.List(networkingClient, listOpts).AllPages()
   201  		if err != nil {
   202  			return err
   203  		}
   204  
   205  		fips, err := floatingips.ExtractFloatingIPs(page)
   206  		if err != nil {
   207  			return err
   208  		}
   209  
   210  		// If a floating IP is found we unassign it
   211  		if len(fips) == 1 {
   212  			updateOpts := floatingips.UpdateOpts{
   213  				PortID: "",
   214  			}
   215  			if err = floatingips.Update(networkingClient, fips[0].ID, updateOpts).Err; err != nil {
   216  				return err
   217  			}
   218  		}
   219  
   220  		// Assign the updated floating IP
   221  		floatingIP := d.Get("floating_ip").(string)
   222  		if floatingIP != "" {
   223  			lbVipV1AssignFloatingIP(floatingIP, portID, networkingClient)
   224  		}
   225  	}
   226  	if d.HasChange("admin_state_up") {
   227  		asu := d.Get("admin_state_up").(bool)
   228  		updateOpts.AdminStateUp = &asu
   229  	}
   230  
   231  	log.Printf("[DEBUG] Updating OpenStack LB VIP %s with options: %+v", d.Id(), updateOpts)
   232  
   233  	_, err = vips.Update(networkingClient, d.Id(), updateOpts).Extract()
   234  	if err != nil {
   235  		return fmt.Errorf("Error updating OpenStack LB VIP: %s", err)
   236  	}
   237  
   238  	return resourceLBVipV1Read(d, meta)
   239  }
   240  
   241  func resourceLBVipV1Delete(d *schema.ResourceData, meta interface{}) error {
   242  	config := meta.(*Config)
   243  	networkingClient, err := config.networkingV2Client(d.Get("region").(string))
   244  	if err != nil {
   245  		return fmt.Errorf("Error creating OpenStack networking client: %s", err)
   246  	}
   247  
   248  	err = vips.Delete(networkingClient, d.Id()).ExtractErr()
   249  	if err != nil {
   250  		return fmt.Errorf("Error deleting OpenStack LB VIP: %s", err)
   251  	}
   252  
   253  	d.SetId("")
   254  	return nil
   255  }
   256  
   257  func resourceVipPersistenceV1(d *schema.ResourceData) *vips.SessionPersistence {
   258  	rawP := d.Get("persistence").(interface{})
   259  	rawMap := rawP.(map[string]interface{})
   260  	if len(rawMap) != 0 {
   261  		p := vips.SessionPersistence{}
   262  		if t, ok := rawMap["type"]; ok {
   263  			p.Type = t.(string)
   264  		}
   265  		if c, ok := rawMap["cookie_name"]; ok {
   266  			p.CookieName = c.(string)
   267  		}
   268  		return &p
   269  	}
   270  	return nil
   271  }
   272  
   273  func lbVipV1AssignFloatingIP(floatingIP, portID string, networkingClient *gophercloud.ServiceClient) error {
   274  	log.Printf("[DEBUG] Assigning floating IP %s to VIP %s", floatingIP, portID)
   275  
   276  	listOpts := floatingips.ListOpts{
   277  		FloatingIP: floatingIP,
   278  	}
   279  	page, err := floatingips.List(networkingClient, listOpts).AllPages()
   280  	if err != nil {
   281  		return err
   282  	}
   283  
   284  	fips, err := floatingips.ExtractFloatingIPs(page)
   285  	if err != nil {
   286  		return err
   287  	}
   288  	if len(fips) != 1 {
   289  		return fmt.Errorf("Unable to retrieve floating IP '%s'", floatingIP)
   290  	}
   291  
   292  	updateOpts := floatingips.UpdateOpts{
   293  		PortID: portID,
   294  	}
   295  	if err = floatingips.Update(networkingClient, fips[0].ID, updateOpts).Err; err != nil {
   296  		return err
   297  	}
   298  
   299  	return nil
   300  }