provider/openstack: State Changes for Networking Resources
This commit adds create and delete state change checks for the "core" networking resources.
This commit is contained in:
parent
21eb546f0c
commit
cc54d9e0fd
|
@ -3,8 +3,12 @@ package openstack
|
|||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/terraform/helper/resource"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/floatingips"
|
||||
"github.com/rackspace/gophercloud/openstack/networking/v2/networks"
|
||||
"github.com/rackspace/gophercloud/pagination"
|
||||
|
@ -45,7 +49,7 @@ func resourceNetworkingFloatingIPV2() *schema.Resource {
|
|||
|
||||
func resourceNetworkFloatingIPV2Create(d *schema.ResourceData, meta interface{}) error {
|
||||
config := meta.(*Config)
|
||||
networkClient, err := config.networkingV2Client(d.Get("region").(string))
|
||||
networkingClient, err := config.networkingV2Client(d.Get("region").(string))
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error creating OpenStack network client: %s", err)
|
||||
}
|
||||
|
@ -62,11 +66,23 @@ func resourceNetworkFloatingIPV2Create(d *schema.ResourceData, meta interface{})
|
|||
PortID: d.Get("port_id").(string),
|
||||
}
|
||||
log.Printf("[DEBUG] Create Options: %#v", createOpts)
|
||||
floatingIP, err := floatingips.Create(networkClient, createOpts).Extract()
|
||||
floatingIP, err := floatingips.Create(networkingClient, createOpts).Extract()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error allocating floating IP: %s", err)
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] Waiting for OpenStack Neutron Floating IP (%s) to become available.", floatingIP.ID)
|
||||
|
||||
stateConf := &resource.StateChangeConf{
|
||||
Target: "ACTIVE",
|
||||
Refresh: waitForFloatingIPActive(networkingClient, floatingIP.ID),
|
||||
Timeout: 2 * time.Minute,
|
||||
Delay: 5 * time.Second,
|
||||
MinTimeout: 3 * time.Second,
|
||||
}
|
||||
|
||||
_, err = stateConf.WaitForState()
|
||||
|
||||
d.SetId(floatingIP.ID)
|
||||
|
||||
return resourceNetworkFloatingIPV2Read(d, meta)
|
||||
|
@ -74,12 +90,12 @@ func resourceNetworkFloatingIPV2Create(d *schema.ResourceData, meta interface{})
|
|||
|
||||
func resourceNetworkFloatingIPV2Read(d *schema.ResourceData, meta interface{}) error {
|
||||
config := meta.(*Config)
|
||||
networkClient, err := config.networkingV2Client(d.Get("region").(string))
|
||||
networkingClient, err := config.networkingV2Client(d.Get("region").(string))
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error creating OpenStack network client: %s", err)
|
||||
}
|
||||
|
||||
floatingIP, err := floatingips.Get(networkClient, d.Id()).Extract()
|
||||
floatingIP, err := floatingips.Get(networkingClient, d.Id()).Extract()
|
||||
if err != nil {
|
||||
return CheckDeleted(d, err, "floating IP")
|
||||
}
|
||||
|
@ -97,7 +113,7 @@ func resourceNetworkFloatingIPV2Read(d *schema.ResourceData, meta interface{}) e
|
|||
|
||||
func resourceNetworkFloatingIPV2Update(d *schema.ResourceData, meta interface{}) error {
|
||||
config := meta.(*Config)
|
||||
networkClient, err := config.networkingV2Client(d.Get("region").(string))
|
||||
networkingClient, err := config.networkingV2Client(d.Get("region").(string))
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error creating OpenStack network client: %s", err)
|
||||
}
|
||||
|
@ -110,7 +126,7 @@ func resourceNetworkFloatingIPV2Update(d *schema.ResourceData, meta interface{})
|
|||
|
||||
log.Printf("[DEBUG] Update Options: %#v", updateOpts)
|
||||
|
||||
_, err = floatingips.Update(networkClient, d.Id(), updateOpts).Extract()
|
||||
_, err = floatingips.Update(networkingClient, d.Id(), updateOpts).Extract()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error updating floating IP: %s", err)
|
||||
}
|
||||
|
@ -120,28 +136,38 @@ func resourceNetworkFloatingIPV2Update(d *schema.ResourceData, meta interface{})
|
|||
|
||||
func resourceNetworkFloatingIPV2Delete(d *schema.ResourceData, meta interface{}) error {
|
||||
config := meta.(*Config)
|
||||
networkClient, err := config.networkingV2Client(d.Get("region").(string))
|
||||
networkingClient, err := config.networkingV2Client(d.Get("region").(string))
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error creating OpenStack network client: %s", err)
|
||||
}
|
||||
|
||||
err = floatingips.Delete(networkClient, d.Id()).ExtractErr()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error deleting floating IP: %s", err)
|
||||
stateConf := &resource.StateChangeConf{
|
||||
Pending: []string{"ACTIVE"},
|
||||
Target: "DELETED",
|
||||
Refresh: waitForFloatingIPDelete(networkingClient, d.Id()),
|
||||
Timeout: 2 * time.Minute,
|
||||
Delay: 5 * time.Second,
|
||||
MinTimeout: 3 * time.Second,
|
||||
}
|
||||
|
||||
_, err = stateConf.WaitForState()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error deleting OpenStack Neutron Floating IP: %s", err)
|
||||
}
|
||||
|
||||
d.SetId("")
|
||||
return nil
|
||||
}
|
||||
|
||||
func getNetworkID(d *schema.ResourceData, meta interface{}, networkName string) (string, error) {
|
||||
config := meta.(*Config)
|
||||
networkClient, err := config.networkingV2Client(d.Get("region").(string))
|
||||
networkingClient, err := config.networkingV2Client(d.Get("region").(string))
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Error creating OpenStack network client: %s", err)
|
||||
}
|
||||
|
||||
opts := networks.ListOpts{Name: networkName}
|
||||
pager := networks.List(networkClient, opts)
|
||||
pager := networks.List(networkingClient, opts)
|
||||
networkID := ""
|
||||
|
||||
err = pager.EachPage(func(page pagination.Page) (bool, error) {
|
||||
|
@ -165,13 +191,13 @@ func getNetworkID(d *schema.ResourceData, meta interface{}, networkName string)
|
|||
|
||||
func getNetworkName(d *schema.ResourceData, meta interface{}, networkID string) (string, error) {
|
||||
config := meta.(*Config)
|
||||
networkClient, err := config.networkingV2Client(d.Get("region").(string))
|
||||
networkingClient, err := config.networkingV2Client(d.Get("region").(string))
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Error creating OpenStack network client: %s", err)
|
||||
}
|
||||
|
||||
opts := networks.ListOpts{ID: networkID}
|
||||
pager := networks.List(networkClient, opts)
|
||||
pager := networks.List(networkingClient, opts)
|
||||
networkName := ""
|
||||
|
||||
err = pager.EachPage(func(page pagination.Page) (bool, error) {
|
||||
|
@ -192,3 +218,52 @@ func getNetworkName(d *schema.ResourceData, meta interface{}, networkID string)
|
|||
|
||||
return networkName, err
|
||||
}
|
||||
|
||||
func waitForFloatingIPActive(networkingClient *gophercloud.ServiceClient, fId string) resource.StateRefreshFunc {
|
||||
return func() (interface{}, string, error) {
|
||||
f, err := floatingips.Get(networkingClient, fId).Extract()
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] OpenStack Neutron Floating IP: %+v", f)
|
||||
if f.Status == "DOWN" || f.Status == "ACTIVE" {
|
||||
return f, "ACTIVE", nil
|
||||
}
|
||||
|
||||
return f, "", nil
|
||||
}
|
||||
}
|
||||
|
||||
func waitForFloatingIPDelete(networkingClient *gophercloud.ServiceClient, fId string) resource.StateRefreshFunc {
|
||||
return func() (interface{}, string, error) {
|
||||
log.Printf("[DEBUG] Attempting to delete OpenStack Floating IP %s.\n", fId)
|
||||
|
||||
f, err := floatingips.Get(networkingClient, fId).Extract()
|
||||
if err != nil {
|
||||
errCode, ok := err.(*gophercloud.UnexpectedResponseCodeError)
|
||||
if !ok {
|
||||
return f, "ACTIVE", err
|
||||
}
|
||||
if errCode.Actual == 404 {
|
||||
log.Printf("[DEBUG] Successfully deleted OpenStack Floating IP %s", fId)
|
||||
return f, "DELETED", nil
|
||||
}
|
||||
}
|
||||
|
||||
err = floatingips.Delete(networkingClient, fId).ExtractErr()
|
||||
if err != nil {
|
||||
errCode, ok := err.(*gophercloud.UnexpectedResponseCodeError)
|
||||
if !ok {
|
||||
return f, "ACTIVE", err
|
||||
}
|
||||
if errCode.Actual == 404 {
|
||||
log.Printf("[DEBUG] Successfully deleted OpenStack Floating IP %s", fId)
|
||||
return f, "DELETED", nil
|
||||
}
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] OpenStack Floating IP %s still active.\n", fId)
|
||||
return f, "ACTIVE", nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,8 +4,12 @@ import (
|
|||
"fmt"
|
||||
"log"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/terraform/helper/resource"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/openstack/networking/v2/networks"
|
||||
)
|
||||
|
||||
|
@ -87,6 +91,19 @@ func resourceNetworkingNetworkV2Create(d *schema.ResourceData, meta interface{})
|
|||
}
|
||||
log.Printf("[INFO] Network ID: %s", n.ID)
|
||||
|
||||
log.Printf("[DEBUG] Waiting for Network (%s) to become available", n.ID)
|
||||
|
||||
stateConf := &resource.StateChangeConf{
|
||||
Pending: []string{"BUILD"},
|
||||
Target: "ACTIVE",
|
||||
Refresh: waitForNetworkActive(networkingClient, n.ID),
|
||||
Timeout: 2 * time.Minute,
|
||||
Delay: 5 * time.Second,
|
||||
MinTimeout: 3 * time.Second,
|
||||
}
|
||||
|
||||
_, err = stateConf.WaitForState()
|
||||
|
||||
d.SetId(n.ID)
|
||||
|
||||
return resourceNetworkingNetworkV2Read(d, meta)
|
||||
|
@ -163,7 +180,16 @@ func resourceNetworkingNetworkV2Delete(d *schema.ResourceData, meta interface{})
|
|||
return fmt.Errorf("Error creating OpenStack networking client: %s", err)
|
||||
}
|
||||
|
||||
err = networks.Delete(networkingClient, d.Id()).ExtractErr()
|
||||
stateConf := &resource.StateChangeConf{
|
||||
Pending: []string{"ACTIVE"},
|
||||
Target: "DELETED",
|
||||
Refresh: waitForNetworkDelete(networkingClient, d.Id()),
|
||||
Timeout: 2 * time.Minute,
|
||||
Delay: 5 * time.Second,
|
||||
MinTimeout: 3 * time.Second,
|
||||
}
|
||||
|
||||
_, err = stateConf.WaitForState()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error deleting OpenStack Neutron Network: %s", err)
|
||||
}
|
||||
|
@ -171,3 +197,52 @@ func resourceNetworkingNetworkV2Delete(d *schema.ResourceData, meta interface{})
|
|||
d.SetId("")
|
||||
return nil
|
||||
}
|
||||
|
||||
func waitForNetworkActive(networkingClient *gophercloud.ServiceClient, networkId string) resource.StateRefreshFunc {
|
||||
return func() (interface{}, string, error) {
|
||||
n, err := networks.Get(networkingClient, networkId).Extract()
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] OpenStack Neutron Network: %+v", n)
|
||||
if n.Status == "DOWN" || n.Status == "ACTIVE" {
|
||||
return n, "ACTIVE", nil
|
||||
}
|
||||
|
||||
return n, n.Status, nil
|
||||
}
|
||||
}
|
||||
|
||||
func waitForNetworkDelete(networkingClient *gophercloud.ServiceClient, networkId string) resource.StateRefreshFunc {
|
||||
return func() (interface{}, string, error) {
|
||||
log.Printf("[DEBUG] Attempting to delete OpenStack Network %s.\n", networkId)
|
||||
|
||||
n, err := networks.Get(networkingClient, networkId).Extract()
|
||||
if err != nil {
|
||||
errCode, ok := err.(*gophercloud.UnexpectedResponseCodeError)
|
||||
if !ok {
|
||||
return n, "ACTIVE", err
|
||||
}
|
||||
if errCode.Actual == 404 {
|
||||
log.Printf("[DEBUG] Successfully deleted OpenStack Network %s", networkId)
|
||||
return n, "DELETED", nil
|
||||
}
|
||||
}
|
||||
|
||||
err = networks.Delete(networkingClient, networkId).ExtractErr()
|
||||
if err != nil {
|
||||
errCode, ok := err.(*gophercloud.UnexpectedResponseCodeError)
|
||||
if !ok {
|
||||
return n, "ACTIVE", err
|
||||
}
|
||||
if errCode.Actual == 404 {
|
||||
log.Printf("[DEBUG] Successfully deleted OpenStack Network %s", networkId)
|
||||
return n, "DELETED", nil
|
||||
}
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] OpenStack Network %s still active.\n", networkId)
|
||||
return n, "ACTIVE", nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,17 +2,36 @@ package openstack
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/terraform/helper/resource"
|
||||
"github.com/hashicorp/terraform/terraform"
|
||||
|
||||
"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/routers"
|
||||
"github.com/rackspace/gophercloud/openstack/networking/v2/networks"
|
||||
"github.com/rackspace/gophercloud/openstack/networking/v2/subnets"
|
||||
)
|
||||
|
||||
func TestAccNetworkingV2Network_basic(t *testing.T) {
|
||||
region := os.Getenv(OS_REGION_NAME)
|
||||
|
||||
var network networks.Network
|
||||
|
||||
var testAccNetworkingV2Network_basic = fmt.Sprintf(`
|
||||
resource "openstack_networking_network_v2" "foo" {
|
||||
region = "%s"
|
||||
name = "network_1"
|
||||
admin_state_up = "true"
|
||||
}`, region)
|
||||
|
||||
var testAccNetworkingV2Network_update = fmt.Sprintf(`
|
||||
resource "openstack_networking_network_v2" "foo" {
|
||||
region = "%s"
|
||||
name = "network_2"
|
||||
admin_state_up = "true"
|
||||
}`, region)
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
|
@ -34,6 +53,57 @@ func TestAccNetworkingV2Network_basic(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func TestAccNetworkingV2Network_netstack(t *testing.T) {
|
||||
region := os.Getenv(OS_REGION_NAME)
|
||||
|
||||
var network networks.Network
|
||||
var subnet subnets.Subnet
|
||||
var router routers.Router
|
||||
|
||||
var testAccNetworkingV2Network_netstack = fmt.Sprintf(`
|
||||
resource "openstack_networking_network_v2" "foo" {
|
||||
region = "%s"
|
||||
name = "network_1"
|
||||
admin_state_up = "true"
|
||||
}
|
||||
|
||||
resource "openstack_networking_subnet_v2" "foo" {
|
||||
region = "%s"
|
||||
name = "subnet_1"
|
||||
network_id = "${openstack_networking_network_v2.foo.id}"
|
||||
cidr = "192.168.10.0/24"
|
||||
ip_version = 4
|
||||
}
|
||||
|
||||
resource "openstack_networking_router_v2" "foo" {
|
||||
region = "%s"
|
||||
name = "router_1"
|
||||
}
|
||||
|
||||
resource "openstack_networking_router_interface_v2" "foo" {
|
||||
region = "%s"
|
||||
router_id = "${openstack_networking_router_v2.foo.id}"
|
||||
subnet_id = "${openstack_networking_subnet_v2.foo.id}"
|
||||
}`, region, region, region, region)
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckNetworkingV2NetworkDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
resource.TestStep{
|
||||
Config: testAccNetworkingV2Network_netstack,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckNetworkingV2NetworkExists(t, "openstack_networking_network_v2.foo", &network),
|
||||
testAccCheckNetworkingV2SubnetExists(t, "openstack_networking_subnet_v2.foo", &subnet),
|
||||
testAccCheckNetworkingV2RouterExists(t, "openstack_networking_router_v2.foo", &router),
|
||||
testAccCheckNetworkingV2RouterInterfaceExists(t, "openstack_networking_router_interface_v2.foo"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func testAccCheckNetworkingV2NetworkDestroy(s *terraform.State) error {
|
||||
config := testAccProvider.Meta().(*Config)
|
||||
networkingClient, err := config.networkingV2Client(OS_REGION_NAME)
|
||||
|
|
|
@ -3,8 +3,11 @@ package openstack
|
|||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/terraform/helper/resource"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/routers"
|
||||
"github.com/rackspace/gophercloud/openstack/networking/v2/ports"
|
||||
|
@ -55,6 +58,19 @@ func resourceNetworkingRouterInterfaceV2Create(d *schema.ResourceData, meta inte
|
|||
}
|
||||
log.Printf("[INFO] Router interface Port ID: %s", n.PortID)
|
||||
|
||||
log.Printf("[DEBUG] Waiting for Router Interface (%s) to become available", n.PortID)
|
||||
|
||||
stateConf := &resource.StateChangeConf{
|
||||
Pending: []string{"BUILD", "PENDING_CREATE", "PENDING_UPDATE"},
|
||||
Target: "ACTIVE",
|
||||
Refresh: waitForRouterInterfaceActive(networkingClient, n.PortID),
|
||||
Timeout: 2 * time.Minute,
|
||||
Delay: 5 * time.Second,
|
||||
MinTimeout: 3 * time.Second,
|
||||
}
|
||||
|
||||
_, err = stateConf.WaitForState()
|
||||
|
||||
d.SetId(n.PortID)
|
||||
|
||||
return resourceNetworkingRouterInterfaceV2Read(d, meta)
|
||||
|
@ -93,11 +109,16 @@ func resourceNetworkingRouterInterfaceV2Delete(d *schema.ResourceData, meta inte
|
|||
return fmt.Errorf("Error creating OpenStack networking client: %s", err)
|
||||
}
|
||||
|
||||
removeOpts := routers.InterfaceOpts{
|
||||
SubnetID: d.Get("subnet_id").(string),
|
||||
stateConf := &resource.StateChangeConf{
|
||||
Pending: []string{"ACTIVE"},
|
||||
Target: "DELETED",
|
||||
Refresh: waitForRouterInterfaceDelete(networkingClient, d),
|
||||
Timeout: 2 * time.Minute,
|
||||
Delay: 5 * time.Second,
|
||||
MinTimeout: 3 * time.Second,
|
||||
}
|
||||
|
||||
_, err = routers.RemoveInterface(networkingClient, d.Get("router_id").(string), removeOpts).Extract()
|
||||
_, err = stateConf.WaitForState()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error deleting OpenStack Neutron Router Interface: %s", err)
|
||||
}
|
||||
|
@ -105,3 +126,55 @@ func resourceNetworkingRouterInterfaceV2Delete(d *schema.ResourceData, meta inte
|
|||
d.SetId("")
|
||||
return nil
|
||||
}
|
||||
|
||||
func waitForRouterInterfaceActive(networkingClient *gophercloud.ServiceClient, rId string) resource.StateRefreshFunc {
|
||||
return func() (interface{}, string, error) {
|
||||
r, err := ports.Get(networkingClient, rId).Extract()
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] OpenStack Neutron Router Interface: %+v", r)
|
||||
return r, r.Status, nil
|
||||
}
|
||||
}
|
||||
|
||||
func waitForRouterInterfaceDelete(networkingClient *gophercloud.ServiceClient, d *schema.ResourceData) resource.StateRefreshFunc {
|
||||
return func() (interface{}, string, error) {
|
||||
routerId := d.Get("router_id").(string)
|
||||
routerInterfaceId := d.Id()
|
||||
|
||||
log.Printf("[DEBUG] Attempting to delete OpenStack Router Interface %s.\n", routerInterfaceId)
|
||||
|
||||
removeOpts := routers.InterfaceOpts{
|
||||
SubnetID: d.Get("subnet_id").(string),
|
||||
}
|
||||
|
||||
r, err := ports.Get(networkingClient, routerInterfaceId).Extract()
|
||||
if err != nil {
|
||||
errCode, ok := err.(*gophercloud.UnexpectedResponseCodeError)
|
||||
if !ok {
|
||||
return r, "ACTIVE", err
|
||||
}
|
||||
if errCode.Actual == 404 {
|
||||
log.Printf("[DEBUG] Successfully deleted OpenStack Router Interface %s", routerInterfaceId)
|
||||
return r, "DELETED", nil
|
||||
}
|
||||
}
|
||||
|
||||
_, err = routers.RemoveInterface(networkingClient, routerId, removeOpts).Extract()
|
||||
if err != nil {
|
||||
errCode, ok := err.(*gophercloud.UnexpectedResponseCodeError)
|
||||
if !ok {
|
||||
return r, "ACTIVE", err
|
||||
}
|
||||
if errCode.Actual == 404 {
|
||||
log.Printf("[DEBUG] Successfully deleted OpenStack Router Interface %s", routerInterfaceId)
|
||||
return r, "DELETED", nil
|
||||
}
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] OpenStack Router Interface %s still active.\n", routerInterfaceId)
|
||||
return r, "ACTIVE", nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,8 +3,11 @@ package openstack
|
|||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/terraform/helper/resource"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/routers"
|
||||
)
|
||||
|
@ -81,6 +84,18 @@ func resourceNetworkingRouterV2Create(d *schema.ResourceData, meta interface{})
|
|||
}
|
||||
log.Printf("[INFO] Router ID: %s", n.ID)
|
||||
|
||||
log.Printf("[DEBUG] Waiting for OpenStack Neutron Router (%s) to become available", n.ID)
|
||||
stateConf := &resource.StateChangeConf{
|
||||
Pending: []string{"BUILD", "PENDING_CREATE", "PENDING_UPDATE"},
|
||||
Target: "ACTIVE",
|
||||
Refresh: waitForRouterActive(networkingClient, n.ID),
|
||||
Timeout: 2 * time.Minute,
|
||||
Delay: 5 * time.Second,
|
||||
MinTimeout: 3 * time.Second,
|
||||
}
|
||||
|
||||
_, err = stateConf.WaitForState()
|
||||
|
||||
d.SetId(n.ID)
|
||||
|
||||
return resourceNetworkingRouterV2Read(d, meta)
|
||||
|
@ -150,7 +165,16 @@ func resourceNetworkingRouterV2Delete(d *schema.ResourceData, meta interface{})
|
|||
return fmt.Errorf("Error creating OpenStack networking client: %s", err)
|
||||
}
|
||||
|
||||
err = routers.Delete(networkingClient, d.Id()).ExtractErr()
|
||||
stateConf := &resource.StateChangeConf{
|
||||
Pending: []string{"ACTIVE"},
|
||||
Target: "DELETED",
|
||||
Refresh: waitForRouterDelete(networkingClient, d.Id()),
|
||||
Timeout: 2 * time.Minute,
|
||||
Delay: 5 * time.Second,
|
||||
MinTimeout: 3 * time.Second,
|
||||
}
|
||||
|
||||
_, err = stateConf.WaitForState()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error deleting OpenStack Neutron Router: %s", err)
|
||||
}
|
||||
|
@ -158,3 +182,48 @@ func resourceNetworkingRouterV2Delete(d *schema.ResourceData, meta interface{})
|
|||
d.SetId("")
|
||||
return nil
|
||||
}
|
||||
|
||||
func waitForRouterActive(networkingClient *gophercloud.ServiceClient, routerId string) resource.StateRefreshFunc {
|
||||
return func() (interface{}, string, error) {
|
||||
r, err := routers.Get(networkingClient, routerId).Extract()
|
||||
if err != nil {
|
||||
return nil, r.Status, err
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] OpenStack Neutron Router: %+v", r)
|
||||
return r, r.Status, nil
|
||||
}
|
||||
}
|
||||
|
||||
func waitForRouterDelete(networkingClient *gophercloud.ServiceClient, routerId string) resource.StateRefreshFunc {
|
||||
return func() (interface{}, string, error) {
|
||||
log.Printf("[DEBUG] Attempting to delete OpenStack Router %s.\n", routerId)
|
||||
|
||||
r, err := routers.Get(networkingClient, routerId).Extract()
|
||||
if err != nil {
|
||||
errCode, ok := err.(*gophercloud.UnexpectedResponseCodeError)
|
||||
if !ok {
|
||||
return r, "ACTIVE", err
|
||||
}
|
||||
if errCode.Actual == 404 {
|
||||
log.Printf("[DEBUG] Successfully deleted OpenStack Router %s", routerId)
|
||||
return r, "DELETED", nil
|
||||
}
|
||||
}
|
||||
|
||||
err = routers.Delete(networkingClient, routerId).ExtractErr()
|
||||
if err != nil {
|
||||
errCode, ok := err.(*gophercloud.UnexpectedResponseCodeError)
|
||||
if !ok {
|
||||
return r, "ACTIVE", err
|
||||
}
|
||||
if errCode.Actual == 404 {
|
||||
log.Printf("[DEBUG] Successfully deleted OpenStack Router %s", routerId)
|
||||
return r, "DELETED", nil
|
||||
}
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] OpenStack Router %s still active.\n", routerId)
|
||||
return r, "ACTIVE", nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,9 +3,13 @@ package openstack
|
|||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/terraform/helper/hashcode"
|
||||
"github.com/hashicorp/terraform/helper/resource"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/openstack/networking/v2/subnets"
|
||||
)
|
||||
|
||||
|
@ -140,6 +144,17 @@ func resourceNetworkingSubnetV2Create(d *schema.ResourceData, meta interface{})
|
|||
}
|
||||
log.Printf("[INFO] Subnet ID: %s", s.ID)
|
||||
|
||||
log.Printf("[DEBUG] Waiting for Subnet (%s) to become available", s.ID)
|
||||
stateConf := &resource.StateChangeConf{
|
||||
Target: "ACTIVE",
|
||||
Refresh: waitForSubnetActive(networkingClient, s.ID),
|
||||
Timeout: 2 * time.Minute,
|
||||
Delay: 5 * time.Second,
|
||||
MinTimeout: 3 * time.Second,
|
||||
}
|
||||
|
||||
_, err = stateConf.WaitForState()
|
||||
|
||||
d.SetId(s.ID)
|
||||
|
||||
return resourceNetworkingSubnetV2Read(d, meta)
|
||||
|
@ -220,7 +235,16 @@ func resourceNetworkingSubnetV2Delete(d *schema.ResourceData, meta interface{})
|
|||
return fmt.Errorf("Error creating OpenStack networking client: %s", err)
|
||||
}
|
||||
|
||||
err = subnets.Delete(networkingClient, d.Id()).ExtractErr()
|
||||
stateConf := &resource.StateChangeConf{
|
||||
Pending: []string{"ACTIVE"},
|
||||
Target: "DELETED",
|
||||
Refresh: waitForSubnetDelete(networkingClient, d.Id()),
|
||||
Timeout: 2 * time.Minute,
|
||||
Delay: 5 * time.Second,
|
||||
MinTimeout: 3 * time.Second,
|
||||
}
|
||||
|
||||
_, err = stateConf.WaitForState()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error deleting OpenStack Neutron Subnet: %s", err)
|
||||
}
|
||||
|
@ -263,3 +287,48 @@ func resourceSubnetHostRoutesV2(d *schema.ResourceData) []subnets.HostRoute {
|
|||
}
|
||||
return hr
|
||||
}
|
||||
|
||||
func waitForSubnetActive(networkingClient *gophercloud.ServiceClient, subnetId string) resource.StateRefreshFunc {
|
||||
return func() (interface{}, string, error) {
|
||||
s, err := subnets.Get(networkingClient, subnetId).Extract()
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] OpenStack Neutron Subnet: %+v", s)
|
||||
return s, "ACTIVE", nil
|
||||
}
|
||||
}
|
||||
|
||||
func waitForSubnetDelete(networkingClient *gophercloud.ServiceClient, subnetId string) resource.StateRefreshFunc {
|
||||
return func() (interface{}, string, error) {
|
||||
log.Printf("[DEBUG] Attempting to delete OpenStack Subnet %s.\n", subnetId)
|
||||
|
||||
s, err := subnets.Get(networkingClient, subnetId).Extract()
|
||||
if err != nil {
|
||||
errCode, ok := err.(*gophercloud.UnexpectedResponseCodeError)
|
||||
if !ok {
|
||||
return s, "ACTIVE", err
|
||||
}
|
||||
if errCode.Actual == 404 {
|
||||
log.Printf("[DEBUG] Successfully deleted OpenStack Subnet %s", subnetId)
|
||||
return s, "DELETED", nil
|
||||
}
|
||||
}
|
||||
|
||||
err = subnets.Delete(networkingClient, subnetId).ExtractErr()
|
||||
if err != nil {
|
||||
errCode, ok := err.(*gophercloud.UnexpectedResponseCodeError)
|
||||
if !ok {
|
||||
return s, "ACTIVE", err
|
||||
}
|
||||
if errCode.Actual == 404 {
|
||||
log.Printf("[DEBUG] Successfully deleted OpenStack Subnet %s", subnetId)
|
||||
return s, "DELETED", nil
|
||||
}
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] OpenStack Subnet %s still active.\n", subnetId)
|
||||
return s, "ACTIVE", nil
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue