Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ These tests are run regularly against our public infrastructure as well as our i
| **Router** | [test_internet_gateway](./test_router.py#L17) | default |
| | [test_reverse_ptr_record_of_router](./test_router.py#L73) | default |
| | [test_router_connected_private_networks](./test_router.py#L101) | default |
| | [test_peering_connected_private_networks](./test_router.py#L161) | default |
| **Server** | [test_change_flavor_from_flex_to_flex](./test_server.py#L21) | default |
| | [test_change_flavor_from_flex_to_plus](./test_server.py#L43) | default |
| | [test_change_flavor_from_plus_to_flex](./test_server.py#L65) | default |
Expand Down
8 changes: 6 additions & 2 deletions api.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,8 @@ def on_response(self, response, *args, **kwargs):
try:
response.raise_for_status()
except requests.exceptions.HTTPError as e:
ignore = e.request.method == 'DELETE' \
and e.response.status_code == 404
ignore = (e.request.method == 'DELETE'
and e.response.status_code == 404)

if not ignore:
raise e
Expand Down Expand Up @@ -190,6 +190,10 @@ def cleanup(self, limit_to_scope=True, limit_to_process=True):

# will be removed when interfaces become a toplevel resource
if 'routers' in r['href']:
try:
self.patch(r['href'], json={"extra_routes": []})
except Exception as e:
exceptions.append(e)
for iface in r['interfaces']:
href = f'routers/{r["uuid"]}/interfaces/{iface["uuid"]}'
try:
Expand Down
18 changes: 9 additions & 9 deletions resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ def factory(cls, **defaults):
server = new_focal_server(flavor='flex-4-1')

"""

def create_resource_factory(**parameters):
resource = cls(**{**defaults, **parameters})
resource.create()
Expand Down Expand Up @@ -1133,13 +1134,13 @@ def network(self):
class Volume(CloudscaleResource):

def __init__(
self,
request,
api,
size=None,
zone=None,
volume_type='ssd',
volume_snapshot_uuid=None,
self,
request,
api,
size=None,
zone=None,
volume_type='ssd',
volume_snapshot_uuid=None,
):
super().__init__(request, api)

Expand Down Expand Up @@ -1348,7 +1349,6 @@ def wait_for_completion(self, seconds=120):

continue
if current_status == 'success':

return

raise RuntimeError(f"Custom Image Import has unexpected status: "
Expand Down Expand Up @@ -1509,7 +1509,6 @@ def verify_backend(self, prober, backend, count=1, port=None):
class Router(CloudscaleResource):

def __init__(self, request, api, name, zone, internet_gateway):

super().__init__(request, api)
self.spec = {
'name': generate_server_name(request, name),
Expand Down Expand Up @@ -1546,6 +1545,7 @@ def remove_interface(self, interface):

# will be removed when interfaces become a toplevel resource
def delete(self):
self.update(extra_routes=[])
for interface in self.interfaces:
self.remove_interface(interface)
self.api.delete(self.href)
Expand Down
93 changes: 93 additions & 0 deletions test_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,3 +156,96 @@ def test_router_connected_private_networks(
# Each server can ping the other over private IPv4
s1.ping(s2.ip("private", 4), tries=5, wait=1)
s2.ping(s1.ip("private", 4), tries=5, wait=1)


def test_peering_connected_private_networks(
create_router,
create_server,
create_jumphost,
create_private_network,
image,
):
""" Test to create two routers between three private networks. """

# Create a pair of routers
router_a = create_router(name='router-a')
router_b = create_router(name='router-b')

# Create three private networks
private_network_a = create_private_network()
private_network_b = create_private_network()
private_network_c = create_private_network() # Peering Network

subnet_a = private_network_a.add_subnet(
cidr="10.10.10.0/24",
gateway_address="10.10.10.1",
)
subnet_b = private_network_b.add_subnet(
cidr="10.10.20.0/24",
gateway_address="10.10.20.1",
)
subnet_c = private_network_c.add_subnet(
cidr="10.10.0.0/24",
)

# Attach the routers to their respective private and peering subnets
router_a.add_interface(
network=private_network_a.uuid,
subnet=subnet_a.uuid,
address="10.10.10.1"
)
router_a.add_interface(
network=private_network_c.uuid,
subnet=subnet_c.uuid,
address="10.10.0.10"
)
router_b.add_interface(
network=private_network_b.uuid,
subnet=subnet_b.uuid,
address="10.10.20.1"
)
router_b.add_interface(
network=private_network_c.uuid,
subnet=subnet_c.uuid,
address="10.10.0.20"
)

# Add extra routes to correctly forward traffic
router_a.update(extra_routes=[
{
"destination": "10.10.20.0/24",
"next_hop": "10.10.0.20"
}
])
router_b.update(extra_routes=[
{
"destination": "10.10.10.0/24",
"next_hop": "10.10.0.10"
}
])

# Create jumpost
jumphost = create_jumphost(private_networks=[
private_network_a,
private_network_b
])

# Create servers each connected only to its own private network
server_a, server_b = in_parallel(create_server, instances=(
{
"name": "s1",
"image": image,
"interfaces": [{"network": private_network_a.uuid}],
"jump_host": jumphost,
},
{
"name": "s2",
"image": image,
"interfaces": [{"network": private_network_b.uuid}],
"jump_host": jumphost,
},
))

# Each server can ping the other over private IPv4
server_a.ping(server_b.ip("private", 4), tries=5, wait=1)
server_b.ping(server_a.ip("private", 4), tries=5, wait=1)
Loading