/acceptance/openstack/networking/v2/extensions/layer3/layer3.go

https://github.com/gophercloud/gophercloud · Go · 387 lines · 270 code · 88 blank · 29 comment · 59 complexity · ce3005aaaf340e42753aaf3250db1049 MD5 · raw file

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