2015-10-26 15:45:48 +01:00
|
|
|
package vcd
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"github.com/hashicorp/terraform/helper/schema"
|
|
|
|
)
|
|
|
|
|
|
|
|
func resourceVcdDNAT() *schema.Resource {
|
|
|
|
return &schema.Resource{
|
|
|
|
Create: resourceVcdDNATCreate,
|
|
|
|
Delete: resourceVcdDNATDelete,
|
|
|
|
Read: resourceVcdDNATRead,
|
|
|
|
|
|
|
|
Schema: map[string]*schema.Schema{
|
|
|
|
"edge_gateway": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Required: true,
|
|
|
|
ForceNew: true,
|
|
|
|
},
|
|
|
|
|
|
|
|
"external_ip": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Required: true,
|
2015-11-10 19:39:58 +01:00
|
|
|
ForceNew: true,
|
2015-10-26 15:45:48 +01:00
|
|
|
},
|
|
|
|
|
|
|
|
"port": &schema.Schema{
|
|
|
|
Type: schema.TypeInt,
|
|
|
|
Required: true,
|
2015-11-10 19:39:58 +01:00
|
|
|
ForceNew: true,
|
2015-10-26 15:45:48 +01:00
|
|
|
},
|
|
|
|
|
|
|
|
"internal_ip": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Required: true,
|
2015-11-10 19:39:58 +01:00
|
|
|
ForceNew: true,
|
2015-10-26 15:45:48 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func resourceVcdDNATCreate(d *schema.ResourceData, meta interface{}) error {
|
2015-11-19 00:56:17 +01:00
|
|
|
vcdClient := meta.(*VCDClient)
|
2015-10-26 15:45:48 +01:00
|
|
|
// Multiple VCD components need to run operations on the Edge Gateway, as
|
|
|
|
// the edge gatway will throw back an error if it is already performing an
|
|
|
|
// operation we must wait until we can aquire a lock on the client
|
2015-11-16 21:11:05 +01:00
|
|
|
vcdClient.Mutex.Lock()
|
|
|
|
defer vcdClient.Mutex.Unlock()
|
2015-10-26 15:45:48 +01:00
|
|
|
portString := getPortString(d.Get("port").(int))
|
|
|
|
|
2015-11-16 21:11:05 +01:00
|
|
|
edgeGateway, err := vcdClient.OrgVdc.FindEdgeGateway(d.Get("edge_gateway").(string))
|
2015-11-02 17:39:56 +01:00
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("Unable to find edge gateway: %#v", err)
|
|
|
|
}
|
|
|
|
|
2015-10-26 15:45:48 +01:00
|
|
|
// Creating a loop to offer further protection from the edge gateway erroring
|
|
|
|
// due to being busy eg another person is using another client so wouldn't be
|
|
|
|
// constrained by out lock. If the edge gateway reurns with a busy error, wait
|
|
|
|
// 3 seconds and then try again. Continue until a non-busy error or success
|
|
|
|
|
2015-11-19 00:56:17 +01:00
|
|
|
err = retryCall(vcdClient.MaxRetryTimeout, func() error {
|
2015-11-02 17:39:56 +01:00
|
|
|
task, err := edgeGateway.AddNATMapping("DNAT", d.Get("external_ip").(string),
|
2015-10-26 15:45:48 +01:00
|
|
|
d.Get("internal_ip").(string),
|
|
|
|
portString)
|
|
|
|
if err != nil {
|
2015-11-02 17:39:56 +01:00
|
|
|
return fmt.Errorf("Error setting DNAT rules: %#v", err)
|
2015-10-26 15:45:48 +01:00
|
|
|
}
|
|
|
|
|
2015-11-02 17:39:56 +01:00
|
|
|
return task.WaitTaskCompletion()
|
|
|
|
})
|
|
|
|
|
2015-10-26 15:45:48 +01:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("Error completing tasks: %#v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
d.SetId(d.Get("external_ip").(string) + "_" + portString)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func resourceVcdDNATRead(d *schema.ResourceData, meta interface{}) error {
|
2015-11-19 00:56:17 +01:00
|
|
|
vcdClient := meta.(*VCDClient)
|
2015-11-16 21:11:05 +01:00
|
|
|
e, err := vcdClient.OrgVdc.FindEdgeGateway(d.Get("edge_gateway").(string))
|
2015-10-26 15:45:48 +01:00
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("Unable to find edge gateway: %#v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
var found bool
|
|
|
|
|
|
|
|
for _, r := range e.EdgeGateway.Configuration.EdgeGatewayServiceConfiguration.NatService.NatRule {
|
|
|
|
if r.RuleType == "DNAT" &&
|
2015-11-10 19:39:58 +01:00
|
|
|
r.GatewayNatRule.OriginalIP == d.Get("external_ip").(string) &&
|
|
|
|
r.GatewayNatRule.OriginalPort == getPortString(d.Get("port").(int)) {
|
2015-10-26 15:45:48 +01:00
|
|
|
found = true
|
|
|
|
d.Set("internal_ip", r.GatewayNatRule.TranslatedIP)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if !found {
|
|
|
|
d.SetId("")
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func resourceVcdDNATDelete(d *schema.ResourceData, meta interface{}) error {
|
2015-11-19 00:56:17 +01:00
|
|
|
vcdClient := meta.(*VCDClient)
|
2015-10-26 15:45:48 +01:00
|
|
|
// Multiple VCD components need to run operations on the Edge Gateway, as
|
|
|
|
// the edge gatway will throw back an error if it is already performing an
|
|
|
|
// operation we must wait until we can aquire a lock on the client
|
2015-11-16 21:11:05 +01:00
|
|
|
vcdClient.Mutex.Lock()
|
|
|
|
defer vcdClient.Mutex.Unlock()
|
2015-10-26 15:45:48 +01:00
|
|
|
portString := getPortString(d.Get("port").(int))
|
|
|
|
|
2015-11-16 21:11:05 +01:00
|
|
|
edgeGateway, err := vcdClient.OrgVdc.FindEdgeGateway(d.Get("edge_gateway").(string))
|
2015-10-26 15:45:48 +01:00
|
|
|
|
2015-11-02 17:39:56 +01:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("Unable to find edge gateway: %#v", err)
|
|
|
|
}
|
2015-11-19 00:56:17 +01:00
|
|
|
err = retryCall(vcdClient.MaxRetryTimeout, func() error {
|
2015-11-02 17:39:56 +01:00
|
|
|
task, err := edgeGateway.RemoveNATMapping("DNAT", d.Get("external_ip").(string),
|
2015-10-26 15:45:48 +01:00
|
|
|
d.Get("internal_ip").(string),
|
|
|
|
portString)
|
|
|
|
if err != nil {
|
2015-11-02 17:39:56 +01:00
|
|
|
return fmt.Errorf("Error setting DNAT rules: %#v", err)
|
2015-10-26 15:45:48 +01:00
|
|
|
}
|
|
|
|
|
2015-11-02 17:39:56 +01:00
|
|
|
return task.WaitTaskCompletion()
|
|
|
|
})
|
2015-10-26 15:45:48 +01:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("Error completing tasks: %#v", err)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|