Add support for route tables

This commit is contained in:
Alexandru Coman 2017-01-30 22:20:00 +02:00
parent 2db4520598
commit b6336231bd
No known key found for this signature in database
GPG Key ID: A7B6A9021F704507
5 changed files with 225 additions and 0 deletions

View File

@ -1096,3 +1096,93 @@ class VirtualSwitchManager(_BaseHNVModel):
"""Delete the required resource."""
raise exception.NotSupported(feature="DELETE",
context="VirtualSwitchManager")
class Routes(_BaseHNVModel):
"""Routes Model.
A routes resource is used to create routes under a tenant's Route Table.
The tenant can specify the addressPrefix of the route, the type of next
hop, and the next hop customer IP address.
"""
_endpoint = "/networking/v1/routeTables/{parent_id}/routes/{resource_id}"
parent_id = model.Field(name="parent_id",
key="parentResourceID",
is_property=False, is_required=False,
is_read_only=True)
"""The parent resource ID field contains the resource ID that is
associated with network objects that are ancestors of the necessary
resource.
"""
address_prefix = model.Field(name="address_prefix", key="addressPrefix",
is_required=True)
"""The destination CIDR to which the route applies, such as 10.1.0.0/16"""
next_hop_type = model.Field(name="next_hop_type", key="nextHopType",
is_required=True)
"""The type of hop to which the packet is sent.
Valid values are:
* `constant.VIRTUAL_APPLIANCE` represents a virtual appliance VM
within the tenant virtual network.
* `constant.VNET_LOCAL` represents the local virtual network.
* `constant.VIRTUAL_NETWORK_GATEWAY` represents a virtual network
gateway.
* `constant.INTERNET` represents the default internet gateway.
* `None` represents a black hole.
"""
next_hop_ip_address = model.Field(name="next_hop_ip_address",
key="nextHopIpAddress",
is_required=False)
"""Indicates the next hop to which IP address packets are forwarded,
such as 11.0.0.23."""
class RouteTables(_BaseHNVModel):
"""Route Table Model.
The RouteTable resource contains a list of routes. RouteTable resources
can be applied to subnets of a tenant virtual network to control routing
within virtual network. Once routeTables has been associated to a virtual
subnet, all tenant VMs created within that subnet will inherit the
RouteTable and will have their traffic routed per the routes contained
in the table.
"""
_endpoint = "/networking/v1/routeTables/{resource_id}"
routes = model.Field(name="routes", key="routes", is_required=False,
default=[])
"""Indicates the routes in a route table, see routes resource for full
details on this element."""
subnetworks = model.Field(name="subnetworks", key="subnets",
is_read_only=True)
"""Indicates an array of references to subnets resources this route
table is associated with."""
@classmethod
def from_raw_data(cls, raw_data):
"""Create a new model using raw API response."""
properties = raw_data["properties"]
routes = []
raw_routes = properties.get("routes", [])
for raw_route in raw_routes:
raw_route["parentResourceID"] = raw_data["resourceId"]
routes.append(Routes.from_raw_data(raw_route))
properties["routes"] = routes
subnets = []
raw_subnets = properties.get("subnets", [])
for raw_subnet in raw_subnets:
subnets.append(Resource.from_raw_data(raw_subnet))
properties["subnets"] = subnets
return super(RouteTables, cls).from_raw_data(raw_data)

View File

@ -73,3 +73,11 @@ class FakeResponse(object):
def virtual_switch_manager(self):
"""Fake GET response for virtual switch manager."""
return self._load_resource("virtual_switch_manager.json")
def routes(self):
"""Fake GET(all) response for routes."""
return self._load_resource("routes.json")
def route_tables(self):
"""Fake GET(all) response for route tables."""
return self._load_resource("route_tables.json")

View File

@ -0,0 +1,71 @@
{
"value": [
{
"resourceRef": "/routeTables/rt",
"resourceId": "rt",
"resourceMetadata": {},
"etag": "W/\"153bce9f-1830-4f13-b90d-a7017119ac24\"",
"instanceId": "0cbeadb5-6bc8-41b6-9bba-6b96ca010eba",
"properties": {
"provisioningState": "Succeeded",
"routes": [
{
"resourceRef": "/routeTables/rt/routes/4f7b9b29-6744-436d-af0e-779fa7093f29",
"resourceId": "4f7b9b29-6744-436d-af0e-779fa7093f29",
"resourceMetadata": {},
"etag": "W/\"153bce9f-1830-4f13-b90d-a7017119ac24\"",
"instanceId": "cdbf5edf-d288-4d8e-89b9-f45a2a1d59ec",
"properties": {
"provisioningState": "Succeeded",
"addressPrefix": "11.0.0.0/24",
"nextHopType": "VirtualAppliance",
"nextHopIpAddress": "12.0.0.21"
}
}
],
"subnets": []
}
},
{
"resourceRef": "/routeTables/d81c27bd-4be4-438a-8b88-31ca717cfe75",
"resourceId": "d81c27bd-4be4-438a-8b88-31ca717cfe75",
"etag": "W/\"7a107f52-a9b3-486e-b8a0-cb85426c1400\"",
"instanceId": "a6070cef-9db4-439a-a095-1cc5e5b9ed8c",
"properties": {
"provisioningState": "Succeeded",
"routes": [
{
"resourceRef": "/routeTables/d81c27bd-4be4-438a-8b88-31ca717cfe75/routes/4f7b9b29-6744-436d-af0e-779fa7093f29",
"resourceId": "4f7b9b29-6744-436d-af0e-779fa7093f29",
"etag": "W/\"7a107f52-a9b3-486e-b8a0-cb85426c1400\"",
"instanceId": "94428b30-47fa-4ba3-b5c5-0fa949eb0ccc",
"properties": {
"provisioningState": "Succeeded",
"addressPrefix": "11.0.0.0/24",
"nextHopType": "VirtualAppliance",
"nextHopIpAddress": "12.0.0.21"
}
},
{
"resourceRef": "/routeTables/d81c27bd-4be4-438a-8b88-31ca717cfe75/routes/4e65fd4c-51bd-4ac5-bbec-c9fad8d66a24",
"resourceId": "4e65fd4c-51bd-4ac5-bbec-c9fad8d66a24",
"etag": "W/\"7a107f52-a9b3-486e-b8a0-cb85426c1400\"",
"instanceId": "1dcd588f-56b9-4807-b818-b1325831684b",
"properties": {
"provisioningState": "Succeeded",
"addressPrefix": "11.0.0.22/32",
"nextHopType": "VnetLocal",
"nextHopIpAddress": ""
}
}
],
"subnets": [
{
"resourceRef": "/virtualNetworks/13b0d711-6db5-4309-b454-595625165034/subnets/4e577d52-e7be-4c45-a369-f0f941f3555a"
}
]
}
}
],
"nextLink": ""
}

View File

@ -0,0 +1,44 @@
{
"value": [
{
"resourceId": "{uniqueString}",
"instanceId": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
"tags": {
"key": "value"
},
"resourceMetadata": {
"client": "WAP Network Resource Provider",
"tenantId": "{subscriptionid}",
"groupId": "{groupname}",
"name": "{name}",
"originalHref": "https://..."
},
"properties": {
"provisioningState": "Updating|Deleting|Failed|Succeeded",
"addressPrefix": "10.0.0.0/24",
"nextHopType": "VirtualAppliance",
"nextHopIpAddress": "11.0.0.5"
}
},
{
"resourceId": "{uniqueString}",
"instanceId": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
"tags": {
"key": "value"
},
"resourceMetadata": {
"client": "WAP Network Resource Provider",
"tenantId": "{subscriptionid}",
"groupId": "{groupname}",
"name": "{name}",
"originalHref": "https://..."
},
"properties": {
"provisioningState": "Updating|Deleting|Failed|Succeeded",
"addressPrefix": "11.11.0.0/16",
"nextHopType": "VirtualAppliance",
"nextHopIpAddress": "11.12.5.5"
}
}
]
}

View File

@ -275,3 +275,15 @@ class TestClient(unittest.TestCase):
raw_data = self._response.virtual_switch_manager()
self._test_get_resource(model=client.VirtualSwitchManager,
raw_data=raw_data)
def test_routes(self):
resources = self._response.routes()
for raw_data in resources.get("value", []):
self._test_get_resource(model=client.Routes,
raw_data=raw_data)
def test_route_tables(self):
resources = self._response.route_tables()
for raw_data in resources.get("value", []):
self._test_get_resource(model=client.RouteTables,
raw_data=raw_data)