github.com/vnpaycloud-console/gophercloud/v2@v2.0.5/internal/acceptance/openstack/networking/v2/networking.go (about) 1 package v2 2 3 import ( 4 "context" 5 "fmt" 6 "testing" 7 8 "github.com/vnpaycloud-console/gophercloud/v2" 9 "github.com/vnpaycloud-console/gophercloud/v2/internal/acceptance/tools" 10 "github.com/vnpaycloud-console/gophercloud/v2/openstack/networking/v2/extensions/extradhcpopts" 11 "github.com/vnpaycloud-console/gophercloud/v2/openstack/networking/v2/extensions/portsecurity" 12 "github.com/vnpaycloud-console/gophercloud/v2/openstack/networking/v2/networks" 13 "github.com/vnpaycloud-console/gophercloud/v2/openstack/networking/v2/ports" 14 "github.com/vnpaycloud-console/gophercloud/v2/openstack/networking/v2/subnets" 15 th "github.com/vnpaycloud-console/gophercloud/v2/testhelper" 16 ) 17 18 // PortWithExtraDHCPOpts represents a port with extra DHCP options configuration. 19 type PortWithExtraDHCPOpts struct { 20 ports.Port 21 extradhcpopts.ExtraDHCPOptsExt 22 } 23 24 // CreateNetwork will create basic network. An error will be returned if the 25 // network could not be created. 26 func CreateNetwork(t *testing.T, client *gophercloud.ServiceClient) (*networks.Network, error) { 27 networkName := tools.RandomString("TESTACC-", 8) 28 networkDescription := tools.RandomString("TESTACC-DESC-", 8) 29 createOpts := networks.CreateOpts{ 30 Name: networkName, 31 Description: networkDescription, 32 AdminStateUp: gophercloud.Enabled, 33 } 34 35 t.Logf("Attempting to create network: %s", networkName) 36 37 network, err := networks.Create(context.TODO(), client, createOpts).Extract() 38 if err != nil { 39 return network, err 40 } 41 42 t.Logf("Successfully created network.") 43 44 th.AssertEquals(t, network.Name, networkName) 45 th.AssertEquals(t, network.Description, networkDescription) 46 47 return network, nil 48 } 49 50 // CreateNetworkWithoutPortSecurity will create a network without port security. 51 // An error will be returned if the network could not be created. 52 func CreateNetworkWithoutPortSecurity(t *testing.T, client *gophercloud.ServiceClient) (*networks.Network, error) { 53 networkName := tools.RandomString("TESTACC-", 8) 54 networkCreateOpts := networks.CreateOpts{ 55 Name: networkName, 56 AdminStateUp: gophercloud.Enabled, 57 } 58 59 iFalse := false 60 createOpts := portsecurity.NetworkCreateOptsExt{ 61 CreateOptsBuilder: networkCreateOpts, 62 PortSecurityEnabled: &iFalse, 63 } 64 65 t.Logf("Attempting to create network: %s", networkName) 66 67 network, err := networks.Create(context.TODO(), client, createOpts).Extract() 68 if err != nil { 69 return network, err 70 } 71 72 t.Logf("Successfully created network.") 73 74 th.AssertEquals(t, network.Name, networkName) 75 76 return network, nil 77 } 78 79 // CreatePort will create a port on the specified subnet. An error will be 80 // returned if the port could not be created. 81 func CreatePort(t *testing.T, client *gophercloud.ServiceClient, networkID, subnetID string) (*ports.Port, error) { 82 portName := tools.RandomString("TESTACC-", 8) 83 portDescription := tools.RandomString("TESTACC-DESC-", 8) 84 85 t.Logf("Attempting to create port: %s", portName) 86 87 createOpts := ports.CreateOpts{ 88 NetworkID: networkID, 89 Name: portName, 90 Description: portDescription, 91 AdminStateUp: gophercloud.Enabled, 92 FixedIPs: []ports.IP{{SubnetID: subnetID}}, 93 } 94 95 port, err := ports.Create(context.TODO(), client, createOpts).Extract() 96 if err != nil { 97 return port, err 98 } 99 100 if err := WaitForPortToCreate(client, port.ID); err != nil { 101 return port, err 102 } 103 104 newPort, err := ports.Get(context.TODO(), client, port.ID).Extract() 105 if err != nil { 106 return newPort, err 107 } 108 109 t.Logf("Successfully created port: %s", portName) 110 111 th.AssertEquals(t, port.Name, portName) 112 th.AssertEquals(t, port.Description, portDescription) 113 114 return newPort, nil 115 } 116 117 // CreatePortWithNoSecurityGroup will create a port with no security group 118 // attached. An error will be returned if the port could not be created. 119 func CreatePortWithNoSecurityGroup(t *testing.T, client *gophercloud.ServiceClient, networkID, subnetID string) (*ports.Port, error) { 120 portName := tools.RandomString("TESTACC-", 8) 121 iFalse := false 122 123 t.Logf("Attempting to create port: %s", portName) 124 125 createOpts := ports.CreateOpts{ 126 NetworkID: networkID, 127 Name: portName, 128 AdminStateUp: &iFalse, 129 FixedIPs: []ports.IP{{SubnetID: subnetID}}, 130 SecurityGroups: &[]string{}, 131 } 132 133 port, err := ports.Create(context.TODO(), client, createOpts).Extract() 134 if err != nil { 135 return port, err 136 } 137 138 if err := WaitForPortToCreate(client, port.ID); err != nil { 139 return port, err 140 } 141 142 newPort, err := ports.Get(context.TODO(), client, port.ID).Extract() 143 if err != nil { 144 return newPort, err 145 } 146 147 t.Logf("Successfully created port: %s", portName) 148 149 th.AssertEquals(t, port.Name, portName) 150 151 return newPort, nil 152 } 153 154 // CreatePortWithoutPortSecurity will create a port without port security on the 155 // specified subnet. An error will be returned if the port could not be created. 156 func CreatePortWithoutPortSecurity(t *testing.T, client *gophercloud.ServiceClient, networkID, subnetID string) (*ports.Port, error) { 157 portName := tools.RandomString("TESTACC-", 8) 158 159 t.Logf("Attempting to create port: %s", portName) 160 161 portCreateOpts := ports.CreateOpts{ 162 NetworkID: networkID, 163 Name: portName, 164 AdminStateUp: gophercloud.Enabled, 165 FixedIPs: []ports.IP{{SubnetID: subnetID}}, 166 } 167 168 iFalse := false 169 createOpts := portsecurity.PortCreateOptsExt{ 170 CreateOptsBuilder: portCreateOpts, 171 PortSecurityEnabled: &iFalse, 172 } 173 174 port, err := ports.Create(context.TODO(), client, createOpts).Extract() 175 if err != nil { 176 return port, err 177 } 178 179 if err := WaitForPortToCreate(client, port.ID); err != nil { 180 return port, err 181 } 182 183 newPort, err := ports.Get(context.TODO(), client, port.ID).Extract() 184 if err != nil { 185 return newPort, err 186 } 187 188 t.Logf("Successfully created port: %s", portName) 189 190 th.AssertEquals(t, port.Name, portName) 191 192 return newPort, nil 193 } 194 195 // CreatePortWithExtraDHCPOpts will create a port with DHCP options on the 196 // specified subnet. An error will be returned if the port could not be created. 197 func CreatePortWithExtraDHCPOpts(t *testing.T, client *gophercloud.ServiceClient, networkID, subnetID string) (*PortWithExtraDHCPOpts, error) { 198 portName := tools.RandomString("TESTACC-", 8) 199 200 t.Logf("Attempting to create port: %s", portName) 201 202 portCreateOpts := ports.CreateOpts{ 203 NetworkID: networkID, 204 Name: portName, 205 AdminStateUp: gophercloud.Enabled, 206 FixedIPs: []ports.IP{{SubnetID: subnetID}}, 207 } 208 209 createOpts := extradhcpopts.CreateOptsExt{ 210 CreateOptsBuilder: portCreateOpts, 211 ExtraDHCPOpts: []extradhcpopts.CreateExtraDHCPOpt{ 212 { 213 OptName: "test_option_1", 214 OptValue: "test_value_1", 215 }, 216 }, 217 } 218 port := &PortWithExtraDHCPOpts{} 219 220 err := ports.Create(context.TODO(), client, createOpts).ExtractInto(port) 221 if err != nil { 222 return nil, err 223 } 224 225 if err := WaitForPortToCreate(client, port.ID); err != nil { 226 return nil, err 227 } 228 229 err = ports.Get(context.TODO(), client, port.ID).ExtractInto(port) 230 if err != nil { 231 return port, err 232 } 233 234 t.Logf("Successfully created port: %s", portName) 235 236 return port, nil 237 } 238 239 // CreatePortWithMultipleFixedIPs will create a port with two FixedIPs on the 240 // specified subnet. An error will be returned if the port could not be created. 241 func CreatePortWithMultipleFixedIPs(t *testing.T, client *gophercloud.ServiceClient, networkID, subnetID string) (*ports.Port, error) { 242 portName := tools.RandomString("TESTACC-", 8) 243 portDescription := tools.RandomString("TESTACC-DESC-", 8) 244 245 t.Logf("Attempting to create port with two fixed IPs: %s", portName) 246 247 createOpts := ports.CreateOpts{ 248 NetworkID: networkID, 249 Name: portName, 250 Description: portDescription, 251 AdminStateUp: gophercloud.Enabled, 252 FixedIPs: []ports.IP{{SubnetID: subnetID}, {SubnetID: subnetID}}, 253 } 254 255 port, err := ports.Create(context.TODO(), client, createOpts).Extract() 256 if err != nil { 257 return port, err 258 } 259 260 if err := WaitForPortToCreate(client, port.ID); err != nil { 261 return port, err 262 } 263 264 newPort, err := ports.Get(context.TODO(), client, port.ID).Extract() 265 if err != nil { 266 return newPort, err 267 } 268 269 t.Logf("Successfully created port: %s", portName) 270 271 th.AssertEquals(t, port.Name, portName) 272 th.AssertEquals(t, port.Description, portDescription) 273 274 if len(port.FixedIPs) != 2 { 275 t.Fatalf("Failed to create a port with two fixed IPs: %s", portName) 276 } 277 278 return newPort, nil 279 } 280 281 // CreateSubnet will create a subnet on the specified Network ID. An error 282 // will be returned if the subnet could not be created. 283 func CreateSubnet(t *testing.T, client *gophercloud.ServiceClient, networkID string) (*subnets.Subnet, error) { 284 subnetOctet := tools.RandomInt(1, 250) 285 subnetCIDR := fmt.Sprintf("192.168.%d.0/24", subnetOctet) 286 subnetGateway := fmt.Sprintf("192.168.%d.1", subnetOctet) 287 return CreateSubnetWithCIDR(t, client, networkID, subnetCIDR, subnetGateway) 288 } 289 290 // CreateSubnetWithCIDR will create a subnet on the specified Network ID and CIDR. An error 291 // will be returned if the subnet could not be created. 292 func CreateSubnetWithCIDR(t *testing.T, client *gophercloud.ServiceClient, networkID, subnetCIDR, subnetGateway string) (*subnets.Subnet, error) { 293 subnetName := tools.RandomString("TESTACC-", 8) 294 subnetDescription := tools.RandomString("TESTACC-DESC-", 8) 295 createOpts := subnets.CreateOpts{ 296 NetworkID: networkID, 297 CIDR: subnetCIDR, 298 IPVersion: 4, 299 Name: subnetName, 300 Description: subnetDescription, 301 EnableDHCP: gophercloud.Disabled, 302 GatewayIP: &subnetGateway, 303 } 304 305 t.Logf("Attempting to create subnet: %s", subnetName) 306 307 subnet, err := subnets.Create(context.TODO(), client, createOpts).Extract() 308 if err != nil { 309 return subnet, err 310 } 311 312 t.Logf("Successfully created subnet.") 313 314 th.AssertEquals(t, subnet.Name, subnetName) 315 th.AssertEquals(t, subnet.Description, subnetDescription) 316 th.AssertEquals(t, subnet.GatewayIP, subnetGateway) 317 th.AssertEquals(t, subnet.CIDR, subnetCIDR) 318 319 return subnet, nil 320 } 321 322 // CreateSubnet will create a subnet on the specified Network ID and service types. 323 // 324 // An error will be returned if the subnet could not be created. 325 func CreateSubnetWithServiceTypes(t *testing.T, client *gophercloud.ServiceClient, networkID string) (*subnets.Subnet, error) { 326 subnetName := tools.RandomString("TESTACC-", 8) 327 subnetDescription := tools.RandomString("TESTACC-DESC-", 8) 328 subnetOctet := tools.RandomInt(1, 250) 329 subnetCIDR := fmt.Sprintf("192.168.%d.0/24", subnetOctet) 330 subnetGateway := fmt.Sprintf("192.168.%d.1", subnetOctet) 331 serviceTypes := []string{"network:routed"} 332 createOpts := subnets.CreateOpts{ 333 NetworkID: networkID, 334 CIDR: subnetCIDR, 335 IPVersion: 4, 336 Name: subnetName, 337 Description: subnetDescription, 338 EnableDHCP: gophercloud.Disabled, 339 GatewayIP: &subnetGateway, 340 ServiceTypes: serviceTypes, 341 } 342 343 t.Logf("Attempting to create subnet: %s", subnetName) 344 345 subnet, err := subnets.Create(context.TODO(), client, createOpts).Extract() 346 if err != nil { 347 return subnet, err 348 } 349 350 t.Logf("Successfully created subnet.") 351 352 th.AssertEquals(t, subnet.Name, subnetName) 353 th.AssertEquals(t, subnet.Description, subnetDescription) 354 th.AssertEquals(t, subnet.GatewayIP, subnetGateway) 355 th.AssertEquals(t, subnet.CIDR, subnetCIDR) 356 th.AssertDeepEquals(t, subnet.ServiceTypes, serviceTypes) 357 358 return subnet, nil 359 } 360 361 // CreateSubnetWithDefaultGateway will create a subnet on the specified Network 362 // ID and have Neutron set the gateway by default An error will be returned if 363 // the subnet could not be created. 364 func CreateSubnetWithDefaultGateway(t *testing.T, client *gophercloud.ServiceClient, networkID string) (*subnets.Subnet, error) { 365 subnetName := tools.RandomString("TESTACC-", 8) 366 subnetOctet := tools.RandomInt(1, 250) 367 subnetCIDR := fmt.Sprintf("192.168.%d.0/24", subnetOctet) 368 defaultGateway := fmt.Sprintf("192.168.%d.1", subnetOctet) 369 370 createOpts := subnets.CreateOpts{ 371 NetworkID: networkID, 372 CIDR: subnetCIDR, 373 IPVersion: 4, 374 Name: subnetName, 375 EnableDHCP: gophercloud.Disabled, 376 } 377 378 t.Logf("Attempting to create subnet: %s", subnetName) 379 380 subnet, err := subnets.Create(context.TODO(), client, createOpts).Extract() 381 if err != nil { 382 return subnet, err 383 } 384 385 t.Logf("Successfully created subnet.") 386 387 th.AssertEquals(t, subnet.Name, subnetName) 388 th.AssertEquals(t, subnet.GatewayIP, defaultGateway) 389 th.AssertEquals(t, subnet.CIDR, subnetCIDR) 390 391 return subnet, nil 392 } 393 394 // CreateSubnetWithNoGateway will create a subnet with no gateway on the 395 // specified Network ID. An error will be returned if the subnet could not be 396 // created. 397 func CreateSubnetWithNoGateway(t *testing.T, client *gophercloud.ServiceClient, networkID string) (*subnets.Subnet, error) { 398 noGateway := "" 399 subnetName := tools.RandomString("TESTACC-", 8) 400 subnetOctet := tools.RandomInt(1, 250) 401 subnetCIDR := fmt.Sprintf("192.168.%d.0/24", subnetOctet) 402 dhcpStart := fmt.Sprintf("192.168.%d.10", subnetOctet) 403 dhcpEnd := fmt.Sprintf("192.168.%d.200", subnetOctet) 404 createOpts := subnets.CreateOpts{ 405 NetworkID: networkID, 406 CIDR: subnetCIDR, 407 IPVersion: 4, 408 Name: subnetName, 409 EnableDHCP: gophercloud.Disabled, 410 GatewayIP: &noGateway, 411 AllocationPools: []subnets.AllocationPool{ 412 { 413 Start: dhcpStart, 414 End: dhcpEnd, 415 }, 416 }, 417 } 418 419 t.Logf("Attempting to create subnet: %s", subnetName) 420 421 subnet, err := subnets.Create(context.TODO(), client, createOpts).Extract() 422 if err != nil { 423 return subnet, err 424 } 425 426 t.Logf("Successfully created subnet.") 427 428 th.AssertEquals(t, subnet.Name, subnetName) 429 th.AssertEquals(t, subnet.GatewayIP, "") 430 th.AssertEquals(t, subnet.CIDR, subnetCIDR) 431 432 return subnet, nil 433 } 434 435 // CreateSubnetWithSubnetPool will create a subnet associated with the provided subnetpool on the specified Network ID. 436 // An error will be returned if the subnet or the subnetpool could not be created. 437 func CreateSubnetWithSubnetPool(t *testing.T, client *gophercloud.ServiceClient, networkID string, subnetPoolID string) (*subnets.Subnet, error) { 438 subnetName := tools.RandomString("TESTACC-", 8) 439 subnetOctet := tools.RandomInt(1, 250) 440 subnetCIDR := fmt.Sprintf("10.%d.0.0/24", subnetOctet) 441 createOpts := subnets.CreateOpts{ 442 NetworkID: networkID, 443 CIDR: subnetCIDR, 444 IPVersion: 4, 445 Name: subnetName, 446 EnableDHCP: gophercloud.Disabled, 447 SubnetPoolID: subnetPoolID, 448 } 449 450 t.Logf("Attempting to create subnet: %s", subnetName) 451 452 subnet, err := subnets.Create(context.TODO(), client, createOpts).Extract() 453 if err != nil { 454 return subnet, err 455 } 456 457 t.Logf("Successfully created subnet.") 458 459 th.AssertEquals(t, subnet.Name, subnetName) 460 th.AssertEquals(t, subnet.CIDR, subnetCIDR) 461 462 return subnet, nil 463 } 464 465 // CreateSubnetWithSubnetPoolNoCIDR will create a subnet associated with the 466 // provided subnetpool on the specified Network ID. 467 // An error will be returned if the subnet or the subnetpool could not be created. 468 func CreateSubnetWithSubnetPoolNoCIDR(t *testing.T, client *gophercloud.ServiceClient, networkID string, subnetPoolID string) (*subnets.Subnet, error) { 469 subnetName := tools.RandomString("TESTACC-", 8) 470 createOpts := subnets.CreateOpts{ 471 NetworkID: networkID, 472 IPVersion: 4, 473 Name: subnetName, 474 EnableDHCP: gophercloud.Disabled, 475 SubnetPoolID: subnetPoolID, 476 } 477 478 t.Logf("Attempting to create subnet: %s", subnetName) 479 480 subnet, err := subnets.Create(context.TODO(), client, createOpts).Extract() 481 if err != nil { 482 return subnet, err 483 } 484 485 t.Logf("Successfully created subnet.") 486 487 th.AssertEquals(t, subnet.Name, subnetName) 488 489 return subnet, nil 490 } 491 492 // CreateSubnetWithSubnetPoolPrefixlen will create a subnet associated with the 493 // provided subnetpool on the specified Network ID and with overwritten 494 // prefixlen instead of the default subnetpool prefixlen. 495 // An error will be returned if the subnet or the subnetpool could not be created. 496 func CreateSubnetWithSubnetPoolPrefixlen(t *testing.T, client *gophercloud.ServiceClient, networkID string, subnetPoolID string) (*subnets.Subnet, error) { 497 subnetName := tools.RandomString("TESTACC-", 8) 498 createOpts := subnets.CreateOpts{ 499 NetworkID: networkID, 500 IPVersion: 4, 501 Name: subnetName, 502 EnableDHCP: gophercloud.Disabled, 503 SubnetPoolID: subnetPoolID, 504 Prefixlen: 12, 505 } 506 507 t.Logf("Attempting to create subnet: %s", subnetName) 508 509 subnet, err := subnets.Create(context.TODO(), client, createOpts).Extract() 510 if err != nil { 511 return subnet, err 512 } 513 514 t.Logf("Successfully created subnet.") 515 516 th.AssertEquals(t, subnet.Name, subnetName) 517 518 return subnet, nil 519 } 520 521 // DeleteNetwork will delete a network with a specified ID. A fatal error will 522 // occur if the delete was not successful. This works best when used as a 523 // deferred function. 524 func DeleteNetwork(t *testing.T, client *gophercloud.ServiceClient, networkID string) { 525 t.Logf("Attempting to delete network: %s", networkID) 526 527 err := networks.Delete(context.TODO(), client, networkID).ExtractErr() 528 if err != nil { 529 t.Fatalf("Unable to delete network %s: %v", networkID, err) 530 } 531 532 t.Logf("Deleted network: %s", networkID) 533 } 534 535 // DeletePort will delete a port with a specified ID. A fatal error will 536 // occur if the delete was not successful. This works best when used as a 537 // deferred function. 538 func DeletePort(t *testing.T, client *gophercloud.ServiceClient, portID string) { 539 t.Logf("Attempting to delete port: %s", portID) 540 541 err := ports.Delete(context.TODO(), client, portID).ExtractErr() 542 if err != nil { 543 t.Fatalf("Unable to delete port %s: %v", portID, err) 544 } 545 546 t.Logf("Deleted port: %s", portID) 547 } 548 549 // DeleteSubnet will delete a subnet with a specified ID. A fatal error will 550 // occur if the delete was not successful. This works best when used as a 551 // deferred function. 552 func DeleteSubnet(t *testing.T, client *gophercloud.ServiceClient, subnetID string) { 553 t.Logf("Attempting to delete subnet: %s", subnetID) 554 555 err := subnets.Delete(context.TODO(), client, subnetID).ExtractErr() 556 if err != nil { 557 t.Fatalf("Unable to delete subnet %s: %v", subnetID, err) 558 } 559 560 t.Logf("Deleted subnet: %s", subnetID) 561 } 562 563 func WaitForPortToCreate(client *gophercloud.ServiceClient, portID string) error { 564 return tools.WaitFor(func(ctx context.Context) (bool, error) { 565 p, err := ports.Get(ctx, client, portID).Extract() 566 if err != nil { 567 return false, err 568 } 569 570 if p.Status == "ACTIVE" || p.Status == "DOWN" { 571 return true, nil 572 } 573 574 return false, nil 575 }) 576 } 577 578 // This is duplicated from https://github.com/gophercloud/utils 579 // so that Gophercloud "core" doesn't have a dependency on the 580 // complementary utils repository. 581 func IDFromName(client *gophercloud.ServiceClient, name string) (string, error) { 582 count := 0 583 id := "" 584 585 listOpts := networks.ListOpts{ 586 Name: name, 587 } 588 589 pages, err := networks.List(client, listOpts).AllPages(context.TODO()) 590 if err != nil { 591 return "", err 592 } 593 594 all, err := networks.ExtractNetworks(pages) 595 if err != nil { 596 return "", err 597 } 598 599 for _, s := range all { 600 if s.Name == name { 601 count++ 602 id = s.ID 603 } 604 } 605 606 switch count { 607 case 0: 608 return "", gophercloud.ErrResourceNotFound{Name: name, ResourceType: "network"} 609 case 1: 610 return id, nil 611 default: 612 return "", gophercloud.ErrMultipleResourcesFound{Name: name, Count: count, ResourceType: "network"} 613 } 614 }