github.com/gophercloud/gophercloud@v1.14.1/internal/acceptance/openstack/networking/v2/extensions/layer3/layer3.go (about)

     1  package layer3
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/addressscopes"
     7  
     8  	"github.com/gophercloud/gophercloud"
     9  	"github.com/gophercloud/gophercloud/internal/acceptance/clients"
    10  	"github.com/gophercloud/gophercloud/internal/acceptance/tools"
    11  	"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips"
    12  	"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/portforwarding"
    13  
    14  	"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers"
    15  	"github.com/gophercloud/gophercloud/openstack/networking/v2/ports"
    16  	th "github.com/gophercloud/gophercloud/testhelper"
    17  )
    18  
    19  // CreateFloatingIP creates a floating IP on a given network and port. An error
    20  // will be returned if the creation failed.
    21  func CreateFloatingIP(t *testing.T, client *gophercloud.ServiceClient, networkID, portID string) (*floatingips.FloatingIP, error) {
    22  	t.Logf("Attempting to create floating IP on port: %s", portID)
    23  
    24  	fipDescription := "Test floating IP"
    25  	createOpts := &floatingips.CreateOpts{
    26  		Description:       fipDescription,
    27  		FloatingNetworkID: networkID,
    28  		PortID:            portID,
    29  	}
    30  
    31  	floatingIP, err := floatingips.Create(client, createOpts).Extract()
    32  	if err != nil {
    33  		return floatingIP, err
    34  	}
    35  
    36  	t.Logf("Created floating IP.")
    37  
    38  	th.AssertEquals(t, floatingIP.Description, fipDescription)
    39  
    40  	return floatingIP, err
    41  }
    42  
    43  // CreateFloatingIPWithFixedIP creates a floating IP on a given network and port with a
    44  // defined fixed IP. An error will be returned if the creation failed.
    45  func CreateFloatingIPWithFixedIP(t *testing.T, client *gophercloud.ServiceClient, networkID, portID, fixedIP string) (*floatingips.FloatingIP, error) {
    46  	t.Logf("Attempting to create floating IP on port: %s and address: %s", portID, fixedIP)
    47  
    48  	fipDescription := "Test floating IP"
    49  	createOpts := &floatingips.CreateOpts{
    50  		Description:       fipDescription,
    51  		FloatingNetworkID: networkID,
    52  		PortID:            portID,
    53  		FixedIP:           fixedIP,
    54  	}
    55  
    56  	floatingIP, err := floatingips.Create(client, createOpts).Extract()
    57  	if err != nil {
    58  		return floatingIP, err
    59  	}
    60  
    61  	t.Logf("Created floating IP.")
    62  
    63  	th.AssertEquals(t, floatingIP.Description, fipDescription)
    64  	th.AssertEquals(t, floatingIP.FixedIP, fixedIP)
    65  
    66  	return floatingIP, err
    67  }
    68  
    69  // CreatePortForwarding creates a port forwarding for a given floating IP
    70  // and port. An error will be returned if the creation failed.
    71  func CreatePortForwarding(t *testing.T, client *gophercloud.ServiceClient, fipID string, portID string, portFixedIPs []ports.IP) (*portforwarding.PortForwarding, error) {
    72  	t.Logf("Attempting to create Port forwarding for floating IP with ID: %s", fipID)
    73  
    74  	fixedIP := portFixedIPs[0]
    75  	internalIP := fixedIP.IPAddress
    76  	pfDescription := "Test description"
    77  	createOpts := &portforwarding.CreateOpts{
    78  		Description:       pfDescription,
    79  		Protocol:          "tcp",
    80  		InternalPort:      25,
    81  		ExternalPort:      2230,
    82  		InternalIPAddress: internalIP,
    83  		InternalPortID:    portID,
    84  	}
    85  
    86  	pf, err := portforwarding.Create(client, fipID, createOpts).Extract()
    87  	if err != nil {
    88  		return pf, err
    89  	}
    90  
    91  	t.Logf("Created Port Forwarding.")
    92  
    93  	th.AssertEquals(t, pf.Protocol, "tcp")
    94  
    95  	return pf, err
    96  }
    97  
    98  // DeletePortForwarding deletes a Port Forwarding with a given ID and a given floating IP ID.
    99  // A fatal error is returned if the deletion fails. Works best as a deferred function
   100  func DeletePortForwarding(t *testing.T, client *gophercloud.ServiceClient, fipID string, pfID string) {
   101  	t.Logf("Attempting to delete the port forwarding with ID %s for floating IP with ID %s", pfID, fipID)
   102  
   103  	err := portforwarding.Delete(client, fipID, pfID).ExtractErr()
   104  	if err != nil {
   105  		t.Fatalf("Failed to delete Port forwarding with ID %s for floating IP with ID %s", pfID, fipID)
   106  	}
   107  	t.Logf("Successfully deleted the port forwarding with ID %s for floating IP with ID %s", pfID, fipID)
   108  
   109  }
   110  
   111  // CreateExternalRouter creates a router on the external network. This requires
   112  // the OS_EXTGW_ID environment variable to be set. An error is returned if the
   113  // creation failed.
   114  func CreateExternalRouter(t *testing.T, client *gophercloud.ServiceClient) (*routers.Router, error) {
   115  	var router *routers.Router
   116  	choices, err := clients.AcceptanceTestChoicesFromEnv()
   117  	if err != nil {
   118  		return router, err
   119  	}
   120  
   121  	routerName := tools.RandomString("TESTACC-", 8)
   122  	routerDescription := tools.RandomString("TESTACC-DESC-", 8)
   123  
   124  	t.Logf("Attempting to create external router: %s", routerName)
   125  
   126  	adminStateUp := true
   127  	gatewayInfo := routers.GatewayInfo{
   128  		NetworkID: choices.ExternalNetworkID,
   129  	}
   130  
   131  	createOpts := routers.CreateOpts{
   132  		Name:         routerName,
   133  		Description:  routerDescription,
   134  		AdminStateUp: &adminStateUp,
   135  		GatewayInfo:  &gatewayInfo,
   136  	}
   137  
   138  	router, err = routers.Create(client, createOpts).Extract()
   139  	if err != nil {
   140  		return router, err
   141  	}
   142  
   143  	if err := WaitForRouterToCreate(client, router.ID); err != nil {
   144  		return router, err
   145  	}
   146  
   147  	t.Logf("Created router: %s", routerName)
   148  
   149  	th.AssertEquals(t, router.Name, routerName)
   150  	th.AssertEquals(t, router.Description, routerDescription)
   151  
   152  	return router, nil
   153  }
   154  
   155  // CreateRouter creates a router on a specified Network ID. An error will be
   156  // returned if the creation failed.
   157  func CreateRouter(t *testing.T, client *gophercloud.ServiceClient, networkID string) (*routers.Router, error) {
   158  	routerName := tools.RandomString("TESTACC-", 8)
   159  	routerDescription := tools.RandomString("TESTACC-DESC-", 8)
   160  
   161  	t.Logf("Attempting to create router: %s", routerName)
   162  
   163  	adminStateUp := true
   164  	createOpts := routers.CreateOpts{
   165  		Name:         routerName,
   166  		Description:  routerDescription,
   167  		AdminStateUp: &adminStateUp,
   168  	}
   169  
   170  	router, err := routers.Create(client, createOpts).Extract()
   171  	if err != nil {
   172  		return router, err
   173  	}
   174  
   175  	if err := WaitForRouterToCreate(client, router.ID); err != nil {
   176  		return router, err
   177  	}
   178  
   179  	t.Logf("Created router: %s", routerName)
   180  
   181  	th.AssertEquals(t, router.Name, routerName)
   182  	th.AssertEquals(t, router.Description, routerDescription)
   183  
   184  	return router, nil
   185  }
   186  
   187  // CreateRouterInterface will attach a subnet to a router. An error will be
   188  // returned if the operation fails.
   189  func CreateRouterInterface(t *testing.T, client *gophercloud.ServiceClient, portID, routerID string) (*routers.InterfaceInfo, error) {
   190  	t.Logf("Attempting to add port %s to router %s", portID, routerID)
   191  
   192  	aiOpts := routers.AddInterfaceOpts{
   193  		PortID: portID,
   194  	}
   195  
   196  	iface, err := routers.AddInterface(client, routerID, aiOpts).Extract()
   197  	if err != nil {
   198  		return iface, err
   199  	}
   200  
   201  	if err := WaitForRouterInterfaceToAttach(client, portID); err != nil {
   202  		return iface, err
   203  	}
   204  
   205  	t.Logf("Successfully added port %s to router %s", portID, routerID)
   206  	return iface, nil
   207  }
   208  
   209  // CreateRouterInterfaceOnSubnet will attach a subnet to a router. An error will be
   210  // returned if the operation fails.
   211  func CreateRouterInterfaceOnSubnet(t *testing.T, client *gophercloud.ServiceClient, subnetID, routerID string) (*routers.InterfaceInfo, error) {
   212  	t.Logf("Attempting to add subnet %s to router %s", subnetID, routerID)
   213  
   214  	aiOpts := routers.AddInterfaceOpts{
   215  		SubnetID: subnetID,
   216  	}
   217  
   218  	iface, err := routers.AddInterface(client, routerID, aiOpts).Extract()
   219  	if err != nil {
   220  		return iface, err
   221  	}
   222  
   223  	if err := WaitForRouterInterfaceToAttach(client, iface.PortID); err != nil {
   224  		return iface, err
   225  	}
   226  
   227  	t.Logf("Successfully added subnet %s to router %s", subnetID, routerID)
   228  	return iface, nil
   229  }
   230  
   231  // DeleteRouter deletes a router of a specified ID. A fatal error will occur
   232  // if the deletion failed. This works best when used as a deferred function.
   233  func DeleteRouter(t *testing.T, client *gophercloud.ServiceClient, routerID string) {
   234  	t.Logf("Attempting to delete router: %s", routerID)
   235  
   236  	err := routers.Delete(client, routerID).ExtractErr()
   237  	if err != nil {
   238  		t.Fatalf("Error deleting router: %v", err)
   239  	}
   240  
   241  	if err := WaitForRouterToDelete(client, routerID); err != nil {
   242  		t.Fatalf("Error waiting for router to delete: %v", err)
   243  	}
   244  
   245  	t.Logf("Deleted router: %s", routerID)
   246  }
   247  
   248  // DeleteRouterInterface will detach a subnet to a router. A fatal error will
   249  // occur if the deletion failed. This works best when used as a deferred
   250  // function.
   251  func DeleteRouterInterface(t *testing.T, client *gophercloud.ServiceClient, portID, routerID string) {
   252  	t.Logf("Attempting to detach port %s from router %s", portID, routerID)
   253  
   254  	riOpts := routers.RemoveInterfaceOpts{
   255  		PortID: portID,
   256  	}
   257  
   258  	_, err := routers.RemoveInterface(client, routerID, riOpts).Extract()
   259  	if err != nil {
   260  		t.Fatalf("Failed to detach port %s from router %s", portID, routerID)
   261  	}
   262  
   263  	if err := WaitForRouterInterfaceToDetach(client, portID); err != nil {
   264  		t.Fatalf("Failed to wait for port %s to detach from router %s", portID, routerID)
   265  	}
   266  
   267  	t.Logf("Successfully detached port %s from router %s", portID, routerID)
   268  }
   269  
   270  // DeleteFloatingIP deletes a floatingIP of a specified ID. A fatal error will
   271  // occur if the deletion failed. This works best when used as a deferred
   272  // function.
   273  func DeleteFloatingIP(t *testing.T, client *gophercloud.ServiceClient, floatingIPID string) {
   274  	t.Logf("Attempting to delete floating IP: %s", floatingIPID)
   275  
   276  	err := floatingips.Delete(client, floatingIPID).ExtractErr()
   277  	if err != nil {
   278  		t.Fatalf("Failed to delete floating IP: %v", err)
   279  	}
   280  
   281  	t.Logf("Deleted floating IP: %s", floatingIPID)
   282  }
   283  
   284  func WaitForRouterToCreate(client *gophercloud.ServiceClient, routerID string) error {
   285  	return tools.WaitFor(func() (bool, error) {
   286  		r, err := routers.Get(client, routerID).Extract()
   287  		if err != nil {
   288  			return false, err
   289  		}
   290  
   291  		if r.Status == "ACTIVE" {
   292  			return true, nil
   293  		}
   294  
   295  		return false, nil
   296  	})
   297  }
   298  
   299  func WaitForRouterToDelete(client *gophercloud.ServiceClient, routerID string) error {
   300  	return tools.WaitFor(func() (bool, error) {
   301  		_, err := routers.Get(client, routerID).Extract()
   302  		if err != nil {
   303  			if _, ok := err.(gophercloud.ErrDefault404); ok {
   304  				return true, nil
   305  			}
   306  
   307  			return false, err
   308  		}
   309  
   310  		return false, nil
   311  	})
   312  }
   313  
   314  func WaitForRouterInterfaceToAttach(client *gophercloud.ServiceClient, routerInterfaceID string) error {
   315  	return tools.WaitFor(func() (bool, error) {
   316  		r, err := ports.Get(client, routerInterfaceID).Extract()
   317  		if err != nil {
   318  			return false, err
   319  		}
   320  
   321  		if r.Status == "ACTIVE" {
   322  			return true, nil
   323  		}
   324  
   325  		return false, nil
   326  	})
   327  }
   328  
   329  func WaitForRouterInterfaceToDetach(client *gophercloud.ServiceClient, routerInterfaceID string) error {
   330  	return tools.WaitFor(func() (bool, error) {
   331  		r, err := ports.Get(client, routerInterfaceID).Extract()
   332  		if err != nil {
   333  			if _, ok := err.(gophercloud.ErrDefault404); ok {
   334  				return true, nil
   335  			}
   336  
   337  			if errCode, ok := err.(gophercloud.ErrUnexpectedResponseCode); ok {
   338  				if errCode.Actual == 409 {
   339  					return false, nil
   340  				}
   341  			}
   342  
   343  			return false, err
   344  		}
   345  
   346  		if r.Status == "ACTIVE" {
   347  			return true, nil
   348  		}
   349  
   350  		return false, nil
   351  	})
   352  }
   353  
   354  // CreateAddressScope will create an address-scope. An error will be returned if
   355  // the address-scope could not be created.
   356  func CreateAddressScope(t *testing.T, client *gophercloud.ServiceClient) (*addressscopes.AddressScope, error) {
   357  	addressScopeName := tools.RandomString("TESTACC-", 8)
   358  	createOpts := addressscopes.CreateOpts{
   359  		Name:      addressScopeName,
   360  		IPVersion: 4,
   361  	}
   362  
   363  	t.Logf("Attempting to create an address-scope: %s", addressScopeName)
   364  
   365  	addressScope, err := addressscopes.Create(client, createOpts).Extract()
   366  	if err != nil {
   367  		return nil, err
   368  	}
   369  
   370  	t.Logf("Successfully created the addressscopes.")
   371  
   372  	th.AssertEquals(t, addressScope.Name, addressScopeName)
   373  	th.AssertEquals(t, addressScope.IPVersion, int(gophercloud.IPv4))
   374  
   375  	return addressScope, nil
   376  }
   377  
   378  // DeleteAddressScope will delete an address-scope with the specified ID.
   379  // A fatal error will occur if the delete was not successful.
   380  func DeleteAddressScope(t *testing.T, client *gophercloud.ServiceClient, addressScopeID string) {
   381  	t.Logf("Attempting to delete the address-scope: %s", addressScopeID)
   382  
   383  	err := addressscopes.Delete(client, addressScopeID).ExtractErr()
   384  	if err != nil {
   385  		t.Fatalf("Unable to delete address-scope %s: %v", addressScopeID, err)
   386  	}
   387  
   388  	t.Logf("Deleted address-scope: %s", addressScopeID)
   389  }