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