3212 lines
129 KiB
Python
3212 lines
129 KiB
Python
# Copyright 2017 Cloudbase Solutions Srl
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
"""This module contains all the available HNV resources."""
|
|
|
|
import re
|
|
import time
|
|
import uuid
|
|
|
|
from oslo_log import log as logging
|
|
|
|
from hnvclient.common import constant
|
|
from hnvclient.common import exception
|
|
from hnvclient.common import model
|
|
from hnvclient.common import utils
|
|
from hnvclient import CONFIG
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
class _BaseHNVModel(model.Model):
|
|
|
|
_endpoint = CONFIG["url"]
|
|
|
|
resource_ref = model.Field(name="resource_ref", key="resourceRef",
|
|
is_property=False)
|
|
"""A relative URI to an associated resource."""
|
|
|
|
resource_id = model.Field(name="resource_id", key="resourceId",
|
|
is_property=False,
|
|
default=lambda: str(uuid.uuid1()))
|
|
"""The resource ID for the resource. The value MUST be unique in
|
|
the context of the resource if it is a top-level resource, or in the
|
|
context of the direct parent resource if it is a child resource."""
|
|
|
|
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.
|
|
"""
|
|
|
|
grandparent_id = model.Field(
|
|
name="grandparent_id", key="grandParentResourceID",
|
|
is_property=False, is_required=False, is_read_only=True)
|
|
"""The grand parent resource ID field contains the resource ID that
|
|
is associated with network objects that are ancestors of the parent
|
|
of the necessary resource."""
|
|
|
|
operation_id = model.Field(name="operation_id", key="operation-id",
|
|
is_property=False, is_required=False,
|
|
is_read_only=True)
|
|
"""The value of the x-ms-request-id header returned by the resource
|
|
provider."""
|
|
|
|
instance_id = model.Field(name="instance_id", key="instanceId",
|
|
is_property=False)
|
|
"""The globally unique Id generated and used internally by the Network
|
|
Controller. The mapping resource that enables the client to map between
|
|
the instanceId and the resourceId."""
|
|
|
|
resource_metadata = model.Field(name="resource_metadata",
|
|
key="resourceMetadata",
|
|
is_property=False, is_required=False)
|
|
"""Structured data that the client provides to the server. This is an
|
|
optional element but it is suggested that all clients fill in the data
|
|
that is applicable to them."""
|
|
|
|
etag = model.Field(name="etag", key="etag", is_property=False,
|
|
is_read_only=True)
|
|
"""An opaque string representing the state of the resource at the
|
|
time the response was generated. This header is returned for
|
|
requests that target a single entity. The Network Controller will
|
|
also always return an etag in the response body. The etag is
|
|
updated every time the resource is updated."""
|
|
|
|
tags = model.Field(name="tags", key="tags", is_property=False,
|
|
is_required=False)
|
|
|
|
provisioning_state = model.Field(name="provisioning_state",
|
|
key="provisioningState",
|
|
is_read_only=True, is_required=False)
|
|
"""Indicates the various states of the resource. Valid values are
|
|
Deleting, Failed, Succeeded, and Updating."""
|
|
|
|
configuration_state = model.Field(name="configuration_state",
|
|
key="configurationState",
|
|
is_read_only=True, is_required=False)
|
|
""""Configuration state indicates any failures in processing state
|
|
corresponding to the resource it is contained in."""
|
|
|
|
def _reset_model(self, response):
|
|
"""Update the fields value with the received information."""
|
|
|
|
# pylint: disable=no-member
|
|
|
|
# Reset the model to the initial state
|
|
self._provision_done = False # Set back the provision flag
|
|
self._changes.clear() # Clear the changes
|
|
|
|
# Process the raw data from the update response
|
|
fields = self.process_raw_data(response)
|
|
# Update the current model representation
|
|
self._set_fields(fields)
|
|
|
|
# Lock the current model
|
|
self._provision_done = True
|
|
|
|
def is_ready(self):
|
|
"""Check if the current model is ready to be used."""
|
|
if not self.provisioning_state:
|
|
raise exception.ServiceException("The object doesn't contain "
|
|
"`provisioningState`.")
|
|
elif self.provisioning_state == constant.FAILED:
|
|
raise exception.ServiceException(
|
|
"Failed to complete the required operation.")
|
|
elif self.provisioning_state == constant.SUCCEEDED:
|
|
LOG.debug("The model %s: %s was successfully updated "
|
|
"(or created).",
|
|
self.__class__.__name__, self.resource_id)
|
|
return True
|
|
|
|
return False
|
|
|
|
@staticmethod
|
|
def _get_client():
|
|
"""Create a new client for the HNV REST API."""
|
|
return utils.get_client(
|
|
url=CONFIG["url"],
|
|
username=CONFIG["username"],
|
|
password=CONFIG["password"],
|
|
allow_insecure=CONFIG["https_allow_insecure"],
|
|
ca_bundle=CONFIG["https_ca_bundle"]
|
|
)
|
|
|
|
@classmethod
|
|
def _get_all(cls, parent_id=None, grandparent_id=None):
|
|
"""Retrives all the required resources."""
|
|
client = cls._get_client()
|
|
endpoint = cls._endpoint.format(resource_id="",
|
|
parent_id=parent_id or "",
|
|
grandparent_id=grandparent_id or "")
|
|
resources = []
|
|
while True:
|
|
response = client.get_resource(endpoint)
|
|
for raw_data in response.get("value", []):
|
|
raw_data["parentResourceID"] = parent_id
|
|
raw_data["grandParentResourceID"] = grandparent_id
|
|
resources.append(cls.from_raw_data(raw_data))
|
|
endpoint = response.get("nextLink")
|
|
if not endpoint:
|
|
break
|
|
return resources
|
|
|
|
@classmethod
|
|
def _get(cls, resource_id, parent_id, grandparent_id):
|
|
""""Retrieves the required resource."""
|
|
client = cls._get_client()
|
|
endpoint = cls._endpoint.format(resource_id=resource_id or "",
|
|
parent_id=parent_id or "",
|
|
grandparent_id=grandparent_id or "")
|
|
raw_data = client.get_resource(endpoint)
|
|
raw_data["parentResourceID"] = parent_id
|
|
raw_data["grandParentResourceID"] = grandparent_id
|
|
return cls.from_raw_data(raw_data)
|
|
|
|
@classmethod
|
|
def get(cls, resource_id=None, parent_id=None, grandparent_id=None):
|
|
"""Retrieves the required resources.
|
|
|
|
:param resource_id: The identifier for the specific resource
|
|
within the resource type.
|
|
:param parent_id: The identifier for the specific ancestor
|
|
resource within the resource type.
|
|
:param grandparent_id: The identifier that is associated with
|
|
network objects that are ancestors of the
|
|
parent of the necessary resource.
|
|
"""
|
|
|
|
if not resource_id:
|
|
return cls._get_all(parent_id, grandparent_id)
|
|
else:
|
|
return cls._get(resource_id, parent_id, grandparent_id)
|
|
|
|
@classmethod
|
|
def remove(cls, resource_id, parent_id=None, grandparent_id=None,
|
|
wait=True, timeout=None):
|
|
"""Delete the required resource.
|
|
|
|
:param resource_id: The identifier for the specific resource
|
|
within the resource type.
|
|
:param parent_id: The identifier for the specific ancestor
|
|
resource within the resource type.
|
|
:param grandparent_id: The identifier that is associated with
|
|
network objects that are ancestors of the
|
|
parent of the necessary resource.
|
|
:param wait: Whether to wait until the operation is
|
|
completed
|
|
:param timeout: The maximum amount of time required for this
|
|
operation to be completed.
|
|
|
|
If optional :param wait: is True and timeout is None (the default),
|
|
block if necessary until the resource is available. If timeout is a
|
|
positive number, it blocks at most timeout seconds and raises the
|
|
`TimeOut` exception if no item was available within that time.
|
|
|
|
Otherwise (block is false), return a resource if one is immediately
|
|
available, else raise the `NotFound` exception (timeout is ignored
|
|
in that case).
|
|
"""
|
|
client = cls._get_client()
|
|
endpoint = cls._endpoint.format(resource_id=resource_id or "",
|
|
parent_id=parent_id or "",
|
|
grandparent_id=grandparent_id or "")
|
|
client.remove_resource(endpoint)
|
|
|
|
elapsed_time = 0
|
|
while wait:
|
|
try:
|
|
resource = cls._get(resource_id=resource_id,
|
|
parent_id=parent_id,
|
|
grandparent_id=grandparent_id)
|
|
resource.is_ready()
|
|
LOG.debug("The resource is still available. %r", resource)
|
|
except exception.NotFound:
|
|
LOG.debug("The resource was successfully removed.")
|
|
break
|
|
|
|
elapsed_time += CONFIG["retry_interval"]
|
|
if timeout and elapsed_time > timeout:
|
|
raise exception.TimeOut("The request timed out.")
|
|
time.sleep(CONFIG["retry_interval"])
|
|
|
|
def refresh(self):
|
|
"""Get the latest representation of the current model."""
|
|
client = self._get_client()
|
|
endpoint = self._endpoint.format(
|
|
resource_id=self.resource_id or "",
|
|
parent_id=self.parent_id or "",
|
|
grandparent_id=self.grandparent_id or "")
|
|
response = client.get_resource(endpoint)
|
|
self._reset_model(response)
|
|
|
|
def commit(self, if_match=None, wait=True, timeout=None):
|
|
"""Apply all the changes on the current model.
|
|
|
|
:param wait: Whether to wait until the operation is completed
|
|
:param timeout: The maximum amount of time required for this
|
|
operation to be completed.
|
|
|
|
If optional :param wait: is True and timeout is None (the default),
|
|
block if necessary until the resource is available. If timeout is a
|
|
positive number, it blocks at most timeout seconds and raises the
|
|
`TimeOut` exception if no item was available within that time.
|
|
|
|
Otherwise (block is false), return a resource if one is immediately
|
|
available, else raise the `NotFound` exception (timeout is ignored
|
|
in that case).
|
|
"""
|
|
if not self._changes:
|
|
LOG.debug("No changes available for %s: %s",
|
|
self.__class__.__name__, self.resource_id)
|
|
return
|
|
|
|
LOG.debug("Apply all the changes on the current %s: %s",
|
|
self.__class__.__name__, self.resource_id)
|
|
client = self._get_client()
|
|
endpoint = self._endpoint.format(
|
|
resource_id=self.resource_id or "",
|
|
parent_id=self.parent_id or "",
|
|
grandparent_id=self.grandparent_id or "")
|
|
request_body = self.dump(include_read_only=False)
|
|
response = client.update_resource(endpoint, data=request_body,
|
|
if_match=if_match)
|
|
|
|
elapsed_time = 0
|
|
while wait:
|
|
self.refresh() # Update the representation of the current model
|
|
if self.is_ready():
|
|
break
|
|
elapsed_time += CONFIG["retry_interval"]
|
|
if timeout and elapsed_time > timeout:
|
|
raise exception.TimeOut("The request timed out.")
|
|
time.sleep(CONFIG["retry_interval"])
|
|
else:
|
|
self._reset_model(response)
|
|
|
|
# NOTE(alexcoman): In order to keep backwards compatibility the
|
|
# `method: commit` will return a reference to itself.
|
|
# An example for that can be the following use case:
|
|
# label = client.Model().commit()
|
|
return self
|
|
|
|
@classmethod
|
|
def process_raw_data(cls, raw_data):
|
|
"""Create a new model using raw API response."""
|
|
properties = raw_data.get("properties", {})
|
|
|
|
raw_metadata = raw_data.get("resourceMetadata", None)
|
|
if raw_metadata is not None:
|
|
metadata = ResourceMetadata.from_raw_data(raw_metadata)
|
|
raw_data["resourceMetadata"] = metadata
|
|
|
|
raw_state = properties.get("configurationState", None)
|
|
if raw_state is not None:
|
|
configuration = ConfigurationState.from_raw_data(raw_state)
|
|
properties["configurationState"] = configuration
|
|
|
|
return super(_BaseHNVModel, cls).process_raw_data(raw_data)
|
|
|
|
def _set_fields(self, fields):
|
|
"""Set or update the fields value."""
|
|
super(_BaseHNVModel, self)._set_fields(fields)
|
|
if not self.resource_ref:
|
|
endpoint = self._endpoint.format(
|
|
resource_id=self.resource_id, parent_id=self.parent_id,
|
|
grandparent_id=self.grandparent_id)
|
|
self.resource_ref = re.sub("(/networking/v[0-9]+)", "", endpoint)
|
|
|
|
|
|
class Resource(model.Model):
|
|
|
|
"""Model for the resource references."""
|
|
|
|
_regexp = {}
|
|
|
|
resource_ref = model.Field(name="resource_ref", key="resourceRef",
|
|
is_property=False, is_required=True)
|
|
"""A relative URI to an associated resource."""
|
|
|
|
def __init__(self, **fields):
|
|
super(Resource, self).__init__(**fields)
|
|
if not self._regexp:
|
|
self._load_models()
|
|
|
|
def _load_models(self):
|
|
models = globals().copy()
|
|
for _, model_cls in models.items():
|
|
endpoint = getattr(model_cls, "_endpoint", None)
|
|
if endpoint is not None:
|
|
regexp = endpoint.format(
|
|
resource_id="(?P<resource_id>[^/]+)",
|
|
parent_id="(?P<parent_id>[^/]+)",
|
|
grandparent_id="(?P<grandparent_id>[^/]+)")
|
|
regexp = re.sub("(/networking/v[0-9]+)", "", regexp)
|
|
# Note(alexcoman): In order to avoid any false positives
|
|
# we will force the regexp to match the entire resource
|
|
# reference.
|
|
regexp = "^{regexp}$".format(regexp=regexp)
|
|
self._regexp[model_cls] = re.compile(regexp,
|
|
flags=re.IGNORECASE)
|
|
|
|
def get_resource(self):
|
|
"""Return the associated resource."""
|
|
references = {"resource_id": None, "parent_id": None,
|
|
"grandparent_id": None}
|
|
for model_cls, regexp in self._regexp.items():
|
|
match = regexp.search(self.resource_ref)
|
|
if match is not None:
|
|
references.update(match.groupdict())
|
|
return model_cls.get(**references)
|
|
|
|
raise exception.NotFound("No model available for %(resource_ref)r",
|
|
resource_ref=self.resource_ref)
|
|
|
|
|
|
class ResourceMetadata(model.Model):
|
|
|
|
"""Model for Resource Metadata.
|
|
|
|
Structured data that the client provides to the server. This is an
|
|
optional element but it is suggested that all clients fill in the
|
|
data that is applicable to them.
|
|
"""
|
|
|
|
client = model.Field(name="client", key="client",
|
|
is_property=False, is_required=False)
|
|
"""Indicates the client that creates or updates the resource.
|
|
Although this element is optional, it is strongly recommended that it
|
|
contain an appropriate value."""
|
|
|
|
tenant_id = model.Field(name="tenant_id", key="tenantId",
|
|
is_property=False, is_required=False)
|
|
"""The identifier of the tenant in the client environment.
|
|
Provides linkage between the resource in the Network Controller
|
|
and the tenant in the client network."""
|
|
|
|
group_id = model.Field(name="group_id", key="groupId",
|
|
is_property=False, is_required=False)
|
|
"""The identifier of the group that the tenant belongs to within
|
|
the client environment. This is usually used in environments that
|
|
contain multiple tenants that are aggregated into groups that the
|
|
client manages. This provides linkage between the resource in the
|
|
Network Controller and the group that the tenant belongs to in the
|
|
client network."""
|
|
|
|
resource_name = model.Field(name="resource_name", key="resourceName",
|
|
is_property=False, is_required=False)
|
|
"""Indicates the globally unique name of the resource. If it
|
|
is not assigned a value then it will be blank."""
|
|
|
|
name = model.Field(name="name", key="name",
|
|
is_property=False, is_required=False)
|
|
"""Indicates the globally unique name of the resource. If it
|
|
is not assigned a value then it will be blank."""
|
|
|
|
original_href = model.Field(name="original_href", key="originalHref",
|
|
is_property=False, is_required=False)
|
|
"""The original URI of the resource if the client uses a URI based
|
|
system to organize resources."""
|
|
|
|
|
|
class IPPools(_BaseHNVModel):
|
|
|
|
"""Model for IP Pools.
|
|
|
|
The ipPools resource represents the range of IP addresses from which IP
|
|
addresses will be allocated for nodes within a subnet. The subnet is a
|
|
logical or physical subnet inside a logical network.
|
|
|
|
The ipPools for a virtual subnet are implicit. The start and end IP
|
|
addresses of the pool of the virtual subnet is based on the IP prefix
|
|
of the virtual subnet.
|
|
"""
|
|
|
|
_endpoint = ("/networking/v1/logicalNetworks/{grandparent_id}"
|
|
"/subnets/{parent_id}/ipPools/{resource_id}")
|
|
|
|
parent_id = model.Field(
|
|
name="parent_id", key="parentResourceID",
|
|
is_property=False, is_required=True, 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.
|
|
"""
|
|
|
|
grandparent_id = model.Field(
|
|
name="grandparent_id", key="grandParentResourceID",
|
|
is_property=False, is_required=True, is_read_only=True)
|
|
"""The grand parent resource ID field contains the resource ID that
|
|
is associated with network objects that are ancestors of the parent
|
|
of the necessary resource."""
|
|
|
|
start_ip_address = model.Field(name="start_ip_address",
|
|
key="startIpAddress",
|
|
is_required=True, is_read_only=False)
|
|
"""Start IP address of the pool.
|
|
Note: This is an inclusive value so it is a valid IP address from
|
|
this pool."""
|
|
|
|
end_ip_address = model.Field(name="end_ip_address", key="endIpAddress",
|
|
is_required=True, is_read_only=False)
|
|
"""End IP address of the pool.
|
|
Note: This is an inclusive value so it is a valid IP address from
|
|
this pool."""
|
|
|
|
usage = model.Field(name="usage", key="usage",
|
|
is_required=False, is_read_only=True)
|
|
"""Statistics of the usage of the IP pool."""
|
|
|
|
|
|
class LogicalSubnetworks(_BaseHNVModel):
|
|
|
|
"""Logical subnetworks model.
|
|
|
|
The logicalSubnets resource consists of a subnet/VLAN pair.
|
|
The vlan resource is required; however it MAY contain a value of zero
|
|
if the subnet is not associated with a vlan.
|
|
"""
|
|
|
|
# Note(alexcoman): The endpoint from the Northbound API (NBI) definition
|
|
# of the Microsoft Network Controller is not valid. The valid endpoint
|
|
# it's `subnets` not `logicalSubnetworks`.
|
|
_endpoint = ("/networking/v1/logicalNetworks/{parent_id}"
|
|
"/subnets/{resource_id}")
|
|
|
|
parent_id = model.Field(
|
|
name="parent_id", key="parentResourceID",
|
|
is_property=False, is_required=True, 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")
|
|
"""Identifies the subnet id in form of ipAddresss/prefixlength."""
|
|
|
|
vlan_id = model.Field(name="vlan_id", key="vlanID", is_required=True,
|
|
default=0)
|
|
"""Indicates the VLAN ID associated with the logical subnet."""
|
|
|
|
routes = model.Field(name="routes", key="routes", is_required=False)
|
|
"""Indicates the routes that are contained in the logical subnet."""
|
|
|
|
ip_pools = model.Field(name="ip_pools", key="ipPools",
|
|
is_required=False)
|
|
"""Indicates the IP Pools that are contained in the logical subnet."""
|
|
|
|
dns_servers = model.Field(name="dns_servers", key="dnsServers",
|
|
is_required=False, default=list)
|
|
"""Indicates one or more DNS servers that are used for resolving DNS
|
|
queries by devices or host connected to this logical subnet."""
|
|
|
|
ip_configurations = model.Field(name="ip_configurations",
|
|
key="ipConfigurations")
|
|
"""Indicates an array of IP configurations that are contained
|
|
in the network interface."""
|
|
|
|
network_interfaces = model.Field(name="network_interfaces",
|
|
key="networkInterfaces",
|
|
is_read_only=True)
|
|
"""Indicates an array of references to networkInterfaces resources
|
|
that are attached to the logical subnet."""
|
|
|
|
is_public = model.Field(name="is_public", key="isPublic")
|
|
"""Boolean flag specifying whether the logical subnet is a
|
|
public subnet."""
|
|
|
|
default_gateways = model.Field(name="default_gateways",
|
|
key="defaultGateways")
|
|
"""A collection of one or more gateways for the subnet."""
|
|
|
|
gateway_pools = model.Field(name="gateway_pools", key="gatewayPools",
|
|
is_required=False, is_read_only=True)
|
|
"""Indicates a collection of references to gatewayPools resources
|
|
in which connections can be created. This information is populated
|
|
at the time of subscription and can be changed only via the Service
|
|
administrator portal."""
|
|
|
|
@classmethod
|
|
def process_raw_data(cls, raw_data):
|
|
"""Create a new model using raw API response."""
|
|
properties = raw_data["properties"]
|
|
|
|
ip_pools = []
|
|
for raw_content in properties.get("ipPools", []):
|
|
raw_content["parentResourceID"] = raw_data["resourceId"]
|
|
raw_content["grandParentResourceID"] = raw_data["parentResourceID"]
|
|
ip_pools.append(IPPools.from_raw_data(raw_content))
|
|
properties["ipPools"] = ip_pools
|
|
|
|
ip_configurations = []
|
|
for raw_content in properties.get("ipConfigurations", []):
|
|
resource = Resource.from_raw_data(raw_content)
|
|
ip_configurations.append(resource)
|
|
properties["ipConfigurations"] = ip_configurations
|
|
|
|
network_interfaces = []
|
|
for raw_content in properties.get("networkInterfaces", []):
|
|
resource = Resource.from_raw_data(raw_content)
|
|
network_interfaces.append(resource)
|
|
properties["networkInterfaces"] = network_interfaces
|
|
|
|
return super(LogicalSubnetworks, cls).process_raw_data(raw_data)
|
|
|
|
|
|
class LogicalNetworks(_BaseHNVModel):
|
|
|
|
"""Logical networks model.
|
|
|
|
The logicalNetworks resource represents a logical partition of physical
|
|
network that is dedicated for a specific purpose.
|
|
A logical network comprises of a collection of logical subnets.
|
|
"""
|
|
|
|
_endpoint = "/networking/v1/logicalNetworks/{resource_id}"
|
|
|
|
subnetworks = model.Field(name="subnetworks", key="subnets",
|
|
is_required=False, default=list)
|
|
"""Indicates the subnets that are contained in the logical network."""
|
|
|
|
network_virtualization_enabled = model.Field(
|
|
name="network_virtualization_enabled",
|
|
key="networkVirtualizationEnabled", default=False, is_required=False)
|
|
"""Indicates if the network is enabled to be the Provider Address network
|
|
for one or more virtual networks. Valid values are `True` or `False`.
|
|
The default is `False`."""
|
|
|
|
virtual_networks = model.Field(
|
|
name="virtual_networks", key="virtualNetworks",
|
|
is_read_only=True, default=list)
|
|
"""Indicates an array of virtualNetwork resources that are using
|
|
the network."""
|
|
|
|
@classmethod
|
|
def process_raw_data(cls, raw_data):
|
|
"""Create a new model using raw API response."""
|
|
properties = raw_data["properties"]
|
|
|
|
subnetworks = []
|
|
for raw_subnet in properties.get("subnets", []):
|
|
raw_subnet["parentResourceID"] = raw_data["resourceId"]
|
|
subnetworks.append(LogicalSubnetworks.from_raw_data(raw_subnet))
|
|
properties["subnets"] = subnetworks
|
|
|
|
virtual_networks = []
|
|
for raw_network in properties.get("virtualNetworks", []):
|
|
virtual_networks.append(Resource.from_raw_data(raw_network))
|
|
properties["virtualNetworks"] = virtual_networks
|
|
|
|
return super(LogicalNetworks, cls).process_raw_data(raw_data)
|
|
|
|
|
|
class IPConfiguration(_BaseHNVModel):
|
|
|
|
"""IP Configuration Model.
|
|
|
|
This resource represents configuration information for IP addresses:
|
|
allocation method, actual IP address, membership of a logical or virtual
|
|
subnet, load balancing and access control information.
|
|
"""
|
|
|
|
_endpoint = ("/networking/v1/networkInterfaces/{parent_id}"
|
|
"/ipConfigurations/{resource_id}")
|
|
|
|
parent_id = model.Field(
|
|
name="parent_id", key="parentResourceID",
|
|
is_property=False, is_required=True, 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.
|
|
"""
|
|
|
|
access_control_list = model.Field(name="access_control_list",
|
|
key="accessControlList",
|
|
is_required=False)
|
|
"""Indicates a reference to an accessControlList resource that defines
|
|
the ACLs in and out of the IP Configuration."""
|
|
|
|
backend_address_pools = model.Field(
|
|
name="backend_address_pools", key="loadBalancerBackendAddressPools",
|
|
is_required=False, is_read_only=False)
|
|
"""Reference to backendAddressPools child resource of loadBalancers
|
|
resource."""
|
|
|
|
inbound_nat_rules = model.Field(
|
|
name="loadBalancerInboundNatRules", key="loadBalancerInboundNatRules",
|
|
is_required=False)
|
|
"""Reference to inboundNatRules child resource of loadBalancers
|
|
resource."""
|
|
|
|
private_ip_address = model.Field(
|
|
name="private_ip_address", key="privateIPAddress",
|
|
is_required=False)
|
|
"""Indicates the private IP address of the IP Configuration."""
|
|
|
|
private_ip_allocation_method = model.Field(
|
|
name="private_ip_allocation_method", key="privateIPAllocationMethod",
|
|
is_required=False)
|
|
"""Indicates the allocation method (Static or Dynamic)."""
|
|
|
|
public_ip_address = model.Field(
|
|
name="public_ip_address", key="publicIPAddress",
|
|
is_required=False)
|
|
"""Indicates the public IP address of the IP Configuration."""
|
|
|
|
service_insertion = model.Field(
|
|
name="service_insertion", key="serviceInsertion",
|
|
is_required=False)
|
|
"""Indicates a reference to a serviceInsertion resource that defines
|
|
the service insertion in and out of the IP Configuration."""
|
|
|
|
subnet = model.Field(name="subnet", key="subnet", is_read_only=True)
|
|
"""Indicates a reference to the subnet resource that the IP Configuration
|
|
is connected to."""
|
|
|
|
@classmethod
|
|
def process_raw_data(cls, raw_data):
|
|
"""Create a new model using raw API response."""
|
|
properties = raw_data["properties"]
|
|
|
|
address_pools = []
|
|
for content in properties.get("loadBalancerBackendAddressPools", []):
|
|
resource = Resource.from_raw_data(content)
|
|
address_pools.append(resource)
|
|
properties["loadBalancerBackendAddressPools"] = address_pools
|
|
|
|
nat_rules = []
|
|
for content in properties.get("loadBalancerInboundNatRules", None):
|
|
resource = Resource.from_raw_data(content)
|
|
nat_rules.append(resource)
|
|
properties["loadBalancerInboundNatRules"] = nat_rules
|
|
|
|
raw_content = properties.get("publicIPAddress", None)
|
|
if raw_content is not None:
|
|
resource = Resource.from_raw_data(raw_content)
|
|
properties["publicIPAddress"] = resource
|
|
|
|
raw_content = properties.get("serviceInsertion", None)
|
|
if raw_content is not None:
|
|
resource = Resource.from_raw_data(raw_content)
|
|
properties["serviceInsertion"] = resource
|
|
|
|
raw_content = properties.get("subnet", None)
|
|
if raw_content is not None:
|
|
resource = Resource.from_raw_data(raw_content)
|
|
properties["subnet"] = resource
|
|
|
|
return super(IPConfiguration, cls).process_raw_data(raw_data)
|
|
|
|
|
|
class DNSSettings(model.Model):
|
|
|
|
"""Model for DNS Setting for Network Interfaces."""
|
|
|
|
dns_servers = model.Field(name="dns_servers", key="dnsServers",
|
|
is_property=False, is_required=False)
|
|
"""Indicates an array of IP Addresses that the network interface
|
|
resource will use for the DNS servers."""
|
|
|
|
|
|
class QosSettings(model.Model):
|
|
|
|
"""Qos Settings Model."""
|
|
|
|
outbound_reserved_value = model.Field(name="outbound_reserved_value",
|
|
key="outboundReservedValue",
|
|
is_required=False,
|
|
is_property=False)
|
|
"""If outboundReservedMode is "absolute" then the value indicates the
|
|
bandwidth, in Mbps, guaranteed to the virtual port for transmission
|
|
(egress)."""
|
|
|
|
outbound_maximum_mbps = model.Field(name="outbound_maximum_mbps",
|
|
key="outboundMaximumMbps",
|
|
is_required=False,
|
|
is_property=False)
|
|
"""Indicates the maximum permitted send-side bandwidth, in Mbps,
|
|
for the virtual port (egress)."""
|
|
|
|
inbound_maximum_mbps = model.Field(name="inbound_maximum_mbps",
|
|
key="inboundMaximumMbps",
|
|
is_required=False,
|
|
is_property=False)
|
|
"""Indicates the maximum permitted receive-side bandwidth for the
|
|
virtual port (ingress) in Mbps."""
|
|
|
|
|
|
class PortSettings(model.Model):
|
|
|
|
"""Port Settings Model."""
|
|
|
|
mac_spoofing = model.Field(name="mac_spoofing", key="macSpoofingEnabled",
|
|
is_required=False, is_property=False)
|
|
"""Specifies whether virtual machines can change the source MAC
|
|
address in outgoing packets to one not assigned to them."""
|
|
|
|
arp_guard = model.Field(name="arp_guard", key="arpGuardEnabled",
|
|
is_required=False, is_property=False)
|
|
"""Specifies whether ARP guard is enabled or not. ARP guard
|
|
will allow only addresses specified in ArpFilter to pass through
|
|
the port."""
|
|
|
|
dhcp_guard = model.Field(name="dhcp_guard", key="dhcpGuardEnabled",
|
|
is_required=False, is_property=False)
|
|
"""Specifies the number of broadcast, multicast, and unknown
|
|
unicast packets per second a virtual machine is allowed to
|
|
send through the specified virtual network adapter."""
|
|
|
|
storm_limit = model.Field(name="storm_limit", key="stormLimit",
|
|
is_required=False, is_property=False)
|
|
"""Specifies the number of broadcast, multicast, and unknown
|
|
unicast packets per second a virtual machine is allowed to
|
|
send through the specified virtual network adapter."""
|
|
|
|
port_flow_limit = model.Field(name="port_flow_limit",
|
|
key="portFlowLimit",
|
|
is_required=False, is_property=False)
|
|
"""Specifies the maximum number of flows that can be executed
|
|
for the port."""
|
|
|
|
vmq_weight = model.Field(name="vmq_weight", key="vmqWeight",
|
|
is_required=False, is_property=False)
|
|
"""Specifies whether virtual machine queue (VMQ) is to be
|
|
enabled on the virtual network adapter."""
|
|
|
|
iov_weight = model.Field(name="iov_weight", key="iovWeight",
|
|
is_required=False, is_property=False)
|
|
"""Specifies whether single-root I/O virtualization (SR-IOV) is to
|
|
be enabled on this virtual network adapter."""
|
|
|
|
iov_interrupt_moderation = model.Field(name="iov_interrupt_moderation",
|
|
key="iovInterruptModeration",
|
|
is_required=False,
|
|
is_property=False)
|
|
"""Specifies the interrupt moderation value for a single-root I/O
|
|
virtualization (SR-IOV) virtual function assigned to a virtual
|
|
network adapter."""
|
|
|
|
iov_queue_pairs = model.Field(name="iov_queue_pairs",
|
|
key="iovQueuePairsRequested",
|
|
is_required=False, is_property=False)
|
|
"""Specifies the number of hardware queue pairs to be allocated
|
|
to an SR-IOV virtual function."""
|
|
|
|
qos_settings = model.Field(name="qos_settings", key="qosSettings",
|
|
is_required=False, is_property=False)
|
|
|
|
@classmethod
|
|
def process_raw_data(cls, raw_data):
|
|
"""Create a new model using raw API response."""
|
|
raw_settings = raw_data.get("qosSettings", {})
|
|
qos_settings = QosSettings.from_raw_data(raw_settings)
|
|
raw_data["qosSettings"] = qos_settings
|
|
return super(PortSettings, cls).process_raw_data(raw_data)
|
|
|
|
|
|
class ConfigurationState(model.Model):
|
|
|
|
"""Model for configuration state."""
|
|
|
|
uuid = model.Field(name="uuid", key="id",
|
|
is_property=False, is_required=False)
|
|
status = model.Field(name="status", key="status",
|
|
is_property=False, is_required=False)
|
|
last_update = model.Field(name="last_update", key="lastUpdatedTime",
|
|
is_property=False, is_required=False)
|
|
detailed_info = model.Field(name="detailed_info", key="detailedInfo",
|
|
is_property=False, is_required=False)
|
|
interface_errors = model.Field(name="interface_errors",
|
|
key="virtualNetworkInterfaceErrors",
|
|
is_property=False, is_required=False)
|
|
host_errors = model.Field(name="host_erros", key="hostErrors",
|
|
is_property=False, is_required=False)
|
|
|
|
|
|
class NetworkInterfaces(_BaseHNVModel):
|
|
|
|
"""Network Interface Model.
|
|
|
|
The networkInterfaces resource specifies the configuration of either
|
|
a host virtual interface (host vNIC) or a virtual server NIC (VMNIC).
|
|
"""
|
|
|
|
_endpoint = "/networking/v1/networkInterfaces/{resource_id}"
|
|
|
|
dns_settings = model.Field(name="dns_settings", key="dnsSettings",
|
|
is_read_only=False)
|
|
"""Indicates the DNS settings of this network interface."""
|
|
|
|
ip_configurations = model.Field(name="ip_configurations",
|
|
key="ipConfigurations")
|
|
"""Indicates an array of IP configurations that are contained
|
|
in the network interface."""
|
|
|
|
is_host = model.Field(name="is_host",
|
|
key="isHostVirtualNetworkInterface")
|
|
"""True if this is a host virtual interface (host vNIC)
|
|
False if this is a virtual server NIC (VMNIC)."""
|
|
|
|
is_primary = model.Field(name="is_primary", key="isPrimary",
|
|
default=True, is_static=True)
|
|
"""`True` if this is the primary interface and the default
|
|
value if the property is not set or `False` if this is a
|
|
secondary interface."""
|
|
|
|
is_multitenant_stack = model.Field(name="is_multitenant_stack",
|
|
key="isMultitenantStack",
|
|
default=False)
|
|
"""`True` if allows the NIC to be part of multiple virtual networks
|
|
or `False` if the opposite."""
|
|
|
|
internal_dns_name = model.Field(name="internal_dns_name",
|
|
key="internalDnsNameLabel")
|
|
"""Determines the name that will be registered in iDNS
|
|
when the iDnsServer resource is configured."""
|
|
|
|
server = model.Field(name="server", key="server",
|
|
is_read_only=True)
|
|
"""Indicates a reference to the servers resource for the
|
|
machine that is currently hosting the virtual machine to
|
|
which this network interface belongs."""
|
|
|
|
port_settings = model.Field(name="port_settings", key="portSettings")
|
|
"""A PortSettings object."""
|
|
|
|
mac_address = model.Field(name="mac_address", key="privateMacAddress")
|
|
"""Indicates the private MAC address of this network interface."""
|
|
|
|
mac_allocation_method = model.Field(name="mac_allocation_method",
|
|
key="privateMacAllocationMethod")
|
|
"""Indicates the allocation scheme of the MAC for this
|
|
network interface."""
|
|
|
|
service_insertion_elements = model.Field(
|
|
name="service_insertion_elements", key="serviceInsertionElements",
|
|
is_read_only=True)
|
|
"""Indicates an array of serviceInsertions resources that
|
|
this networkInterfaces resource is part of."""
|
|
|
|
@classmethod
|
|
def process_raw_data(cls, raw_data):
|
|
"""Create a new model using raw API response."""
|
|
properties = raw_data["properties"]
|
|
|
|
ip_configurations = []
|
|
raw_settings = properties.get("ipConfigurations", [])
|
|
for raw_configuration in raw_settings:
|
|
raw_configuration["parentResourceID"] = raw_data["resourceId"]
|
|
ip_configuration = IPConfiguration.from_raw_data(raw_configuration)
|
|
ip_configurations.append(ip_configuration)
|
|
properties["ipConfigurations"] = ip_configurations
|
|
|
|
raw_settings = properties.get("dnsSettings", {})
|
|
dns_settings = DNSSettings.from_raw_data(raw_settings)
|
|
properties["dnsSettings"] = dns_settings
|
|
|
|
raw_settings = properties.get("portSettings", {})
|
|
port_settings = PortSettings.from_raw_data(raw_settings)
|
|
properties["portSettings"] = port_settings
|
|
|
|
return super(NetworkInterfaces, cls).process_raw_data(raw_data)
|
|
|
|
|
|
class SubNetworks(_BaseHNVModel):
|
|
|
|
"""SubNetwork Model.
|
|
|
|
The subnets resource is used to create Virtual Subnets (VSIDs) under
|
|
a tenant's virtual network (RDID). The user can specify the addressPrefix
|
|
to use for the subnets, the accessControl Lists to protect the subnets,
|
|
the routeTable to be applied to the subnet, and optionally the service
|
|
insertion to use within the subnet.
|
|
"""
|
|
|
|
_endpoint = ("/networking/v1/virtualNetworks/{parent_id}"
|
|
"/subnets/{resource_id}")
|
|
|
|
parent_id = model.Field(
|
|
name="parent_id", key="parentResourceID",
|
|
is_property=False, is_required=True, 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)
|
|
"""Indicates the address prefix that defines the subnet. The value is
|
|
in the format of 0.0.0.0/0. This value must not overlap with other
|
|
subnets in the virtual network and must fall in the addressPrefix defined
|
|
in the virtual network."""
|
|
|
|
access_control_list = model.Field(name="access_control_list",
|
|
key="accessControlList",
|
|
is_required=False)
|
|
"""Indicates a reference to an accessControlLists resource that defines
|
|
the ACLs in and out of the subnet."""
|
|
|
|
service_insertion = model.Field(name="service_insertion",
|
|
key="serviceInsertion",
|
|
is_required=False)
|
|
"""Indicates a reference to a serviceInsertions resource that defines the
|
|
service insertion to be applied to the subnet."""
|
|
|
|
route_table = model.Field(name="route_table", key="routeTable",
|
|
is_required=False)
|
|
"""Indicates a reference to a routeTable resource that defines the tenant
|
|
routes to be applied to the subnet."""
|
|
|
|
ip_configuration = model.Field(name="ip_configuration",
|
|
key="ipConfigurations",
|
|
is_read_only=False)
|
|
"""Indicates an array of references of networkInterfaces resources that
|
|
are connected to the subnet."""
|
|
|
|
@classmethod
|
|
def process_raw_data(cls, raw_data):
|
|
"""Create a new model using raw API response."""
|
|
properties = raw_data["properties"]
|
|
|
|
raw_content = properties.get("accessControlList", None)
|
|
if raw_content is not None:
|
|
resource = Resource.from_raw_data(raw_content)
|
|
properties["accessControlList"] = resource
|
|
|
|
# TODO(alexcoman): Add model for ServiceInsertion
|
|
raw_content = properties.get("serviceInsertion", None)
|
|
if raw_content is not None:
|
|
resource = Resource.from_raw_data(raw_content)
|
|
properties["serviceInsertion"] = resource
|
|
|
|
raw_content = properties.get("routeTable", None)
|
|
if raw_content is not None:
|
|
resource = Resource.from_raw_data(raw_content)
|
|
properties["routeTable"] = resource
|
|
|
|
ip_configurations = []
|
|
for raw_config in properties.get("ipConfigurations", []):
|
|
ip_configurations.append(Resource.from_raw_data(raw_config))
|
|
properties["ipConfigurations"] = ip_configurations
|
|
|
|
return super(SubNetworks, cls).process_raw_data(raw_data)
|
|
|
|
|
|
class DHCPOptions(model.Model):
|
|
|
|
"""Model for DHCP options.
|
|
|
|
Indicates the DHCP options used by servers in the virtual network.
|
|
"""
|
|
|
|
dns_servers = model.Field(
|
|
name="dns_servers", key="dnsServers",
|
|
is_property=False, is_required=True, is_read_only=False)
|
|
"""Indicates an array of DNS servers that are being used by
|
|
the virtual network."""
|
|
|
|
|
|
class AddressSpace(model.Model):
|
|
|
|
"""Indicates the address space of the virtual network."""
|
|
|
|
address_prefixes = model.Field(
|
|
name="address_prefixes", key="addressPrefixes",
|
|
is_property=False, is_required=True, is_read_only=False)
|
|
"""Indicates the valid list of address prefixes that
|
|
can make up this virtual network. The value is an array
|
|
of address prefixes in the format of 0.0.0.0/0.
|
|
The space cannot be shrunk if addresses are in use in a
|
|
subnet belonging to the virtual network.
|
|
"""
|
|
|
|
|
|
class VirtualNetworks(_BaseHNVModel):
|
|
|
|
"""Virtual Network Model.
|
|
|
|
This resource is used to create a virtual network using HNV for tenant
|
|
overlays. The default encapsulation for virtualNetworks is Virtual
|
|
Extensible LAN but this can be changed by updating the virtual
|
|
NetworkManager resource. Similarly, the HNV Distributed Router is enabled
|
|
by default but this can be overridden using the virtualNetworkManager
|
|
resource.
|
|
"""
|
|
|
|
_endpoint = "/networking/v1/virtualNetworks/{resource_id}"
|
|
|
|
address_space = model.Field(name="address_space",
|
|
key="addressSpace",
|
|
is_required=True)
|
|
"""Indicates the address space of the virtual network."""
|
|
|
|
dhcp_options = model.Field(name="dhcp_options", key="dhcpOptions",
|
|
is_required=False)
|
|
"""Indicates the DHCP options used by servers in the virtual
|
|
network."""
|
|
|
|
subnetworks = model.Field(name="subnetworks", key="subnets",
|
|
is_required=False, default=list)
|
|
"""Indicates the subnets that are on the virtual network."""
|
|
|
|
logical_network = model.Field(name="logical_network",
|
|
key="logicalNetwork",
|
|
is_required=True)
|
|
"""Indicates a reference to the networks resource that is the
|
|
underlay network which the virtual network runs on."""
|
|
|
|
@classmethod
|
|
def process_raw_data(cls, raw_data):
|
|
"""Create a new model using raw API response."""
|
|
properties = raw_data["properties"]
|
|
|
|
raw_content = properties.get("addressSpace", None)
|
|
if raw_content is not None:
|
|
address_space = AddressSpace.from_raw_data(raw_content)
|
|
properties["addressSpace"] = address_space
|
|
|
|
raw_content = properties.get("dhcpOptions")
|
|
if raw_content is not None:
|
|
dhcp_options = DHCPOptions.from_raw_data(raw_content)
|
|
properties["dhcpOptions"] = dhcp_options
|
|
|
|
raw_content = properties.get("logicalNetwork", None)
|
|
if raw_content is not None:
|
|
properties["logicalNetwork"] = Resource.from_raw_data(raw_content)
|
|
|
|
subnetworks = []
|
|
for raw_subnet in properties.get("subnets", []):
|
|
raw_subnet["parentResourceID"] = raw_data["resourceId"]
|
|
subnetworks.append(SubNetworks.from_raw_data(raw_subnet))
|
|
properties["subnets"] = subnetworks
|
|
|
|
return super(VirtualNetworks, cls).process_raw_data(raw_data)
|
|
|
|
|
|
class ACLRules(_BaseHNVModel):
|
|
|
|
"""ACL Rules Model.
|
|
|
|
The aclRules resource describes the network traffic that is allowed
|
|
or denied for a network interface of a virtual machine. Currently,
|
|
only inbound rules are expressed.
|
|
"""
|
|
|
|
_endpoint = ("/networking/v1/accessControlLists/{parent_id}"
|
|
"/aclRules/{resource_id}")
|
|
|
|
parent_id = model.Field(
|
|
name="parent_id", key="parentResourceID",
|
|
is_property=False, is_required=True, 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.
|
|
"""
|
|
|
|
action = model.Field(name="action", key="action")
|
|
"""Indicates the action the ACL Rule will take. Valid values
|
|
are: `Allow` and `Deny`."""
|
|
|
|
destination_prefix = model.Field(name="destination_prefix",
|
|
key="destinationAddressPrefix")
|
|
"""Indicates the CIDR value of destination IP or a pre-defined tag
|
|
to which traffic is destined. You can specify 0.0.0.0/0 for IPv4
|
|
all and ::/0 for IPv6 all traffic."""
|
|
|
|
destination_port_range = model.Field(name="destination_port_range",
|
|
key="destinationPortRange")
|
|
"""Indicates the destination port(s) that will trigger this ACL
|
|
rule. Valid values include a single port, port range (separated by "-"),
|
|
or "*" for all ports. All numbers are inclusive."""
|
|
|
|
source_prefix = model.Field(name="source_prefix",
|
|
key="sourceAddressPrefix")
|
|
"""Indicates the CIDR value of source IP or a pre-defined TAG from
|
|
which traffic is originating. You can specify 0.0.0.0/0 for IPv4 all
|
|
and ::/0 forIPv6 all traffic."""
|
|
|
|
source_port_range = model.Field(name="source_port_range",
|
|
key="sourcePortRange")
|
|
"""Indicates the source port(s) that will trigger this ACL rule.
|
|
Valid values include a single port, port range (separated by "-"),
|
|
or "*" for all ports. All numbers are inclusive."""
|
|
|
|
description = model.Field(name="description", key="description")
|
|
"""Indicates a description of the ACL rule."""
|
|
|
|
logging = model.Field(name="logging", key="logging",
|
|
default="Enabled")
|
|
"""Indicates whether logging will be turned on for when this
|
|
rule gets triggered. Valid values are `Enabled` or `Disabled`."""
|
|
|
|
priority = model.Field(name="priority", key="priority")
|
|
"""Indicates the priority of the rule relative to the priority of
|
|
other ACL rules. This is a unique numeric value in the context of
|
|
an accessControlLists resource. Value from 101 - 65000 are user
|
|
defined. Values 1 - 100 and 65001 - 65535 are reserved."""
|
|
|
|
protocol = model.Field(name="protocol", key="protocol")
|
|
"""Indicates the protocol to which the ACL rule will apply.
|
|
Valid values are `TCP` or `UDP`."""
|
|
|
|
rule_type = model.Field(name="rule_type", key="type")
|
|
"""Indicates whether the rule is to be evaluated against ingress
|
|
traffic (Inbound) or egress traffic (Outbound). Valid values are
|
|
`Inbound` or `Outbound`."""
|
|
|
|
|
|
class AccessControlLists(_BaseHNVModel):
|
|
|
|
"""Access Constrol List Model.
|
|
|
|
An accessControlLists resource contains a list of ACL rules.
|
|
Access control list resources can be assigned to virtual subnets
|
|
or IP configurations.
|
|
|
|
An ACL can be associated with:
|
|
* Subnets of a virtual or logical network. This means that all
|
|
network interfaces (NICs) with IP configurations created in the
|
|
subnet inherit the ACL rules in the Access Control List. Often,
|
|
subnets are used for a specific architectural tier (frontend,
|
|
middle tier, backend) in more complex applications. Assigning
|
|
an ACL to subnets can thus be used to control the network flow
|
|
between the different tiers.
|
|
*IP configuration of a NIC. This means that the ACL will be
|
|
applied to the parent network interface of the specified IP
|
|
configuration.
|
|
"""
|
|
|
|
_endpoint = "/networking/v1/accessControlLists/{resource_id}"
|
|
|
|
acl_rules = model.Field(name="acl_rules", key="aclRules")
|
|
"""Indicates the rules in an access control list."""
|
|
|
|
inbound_action = model.Field(name="inbound_action",
|
|
key="inboundDefaultAction",
|
|
default="Permit")
|
|
"""Indicates the default action for Inbound Rules. Valid values are
|
|
`Permit` and `Deny`. The default value is `Permit`."""
|
|
|
|
outbound_action = model.Field(name="outbound_action",
|
|
key="outboundDefaultAction",
|
|
default="Permit")
|
|
"""Indicates the default action for Outbound Rules. Valid values are
|
|
`Permit` and `Deny`. The default value is `Permit`."""
|
|
|
|
ip_configuration = model.Field(name="ip_configuration",
|
|
key="ipConfigurations")
|
|
"""Indicates references to IP addresses of network interfaces
|
|
resources this access control list is associated with."""
|
|
|
|
subnets = model.Field(name="subnets", key="subnets")
|
|
"""Indicates an array of references to subnets resources this access
|
|
control list is associated with."""
|
|
|
|
@classmethod
|
|
def process_raw_data(cls, raw_data):
|
|
"""Create a new model using raw API response."""
|
|
properties = raw_data["properties"]
|
|
|
|
ip_configurations = []
|
|
for raw_content in properties.get("ipConfigurations", []):
|
|
resource = Resource.from_raw_data(raw_content)
|
|
ip_configurations.append(resource)
|
|
properties["ipConfigurations"] = ip_configurations
|
|
|
|
subnetworks = []
|
|
for raw_subnet in properties.get("subnets", []):
|
|
subnetworks.append(Resource.from_raw_data(raw_subnet))
|
|
properties["subnets"] = subnetworks
|
|
|
|
acl_rules = []
|
|
for raw_rule in properties.get("aclRules", []):
|
|
raw_rule["parentResourceID"] = raw_data["resourceId"]
|
|
acl_rules.append(ACLRules.from_raw_data(raw_rule))
|
|
properties["aclRules"] = acl_rules
|
|
|
|
return super(AccessControlLists, cls).process_raw_data(raw_data)
|
|
|
|
|
|
class VirtualSwtichQosSettings(model.Model):
|
|
|
|
"""Model for virtual switch QoS settings."""
|
|
|
|
reservation_mode = model.Field(
|
|
name="reservation_mode", key="reservationMode",
|
|
is_required=False, is_property=False)
|
|
"""Specifies whether outboundReservedValue is applied as the absolute
|
|
bandwidth (Mbps) or as a weighted value.
|
|
Allowed values are `constant.ABSOLUTE` or `constant.WEIGHT`.
|
|
"""
|
|
|
|
enable_software_revervations = model.Field(
|
|
name="enable_software_revervations", key="enableSoftwareReservations",
|
|
is_required=False, is_property=False)
|
|
"""True to enable software qos reservation."""
|
|
|
|
enable_hardware_limits = model.Field(
|
|
name="enable_hardware_limits", key="enableHardwareLimits",
|
|
is_required=False, is_property=False)
|
|
"""Offloads Tx and Rx cap to hardware."""
|
|
|
|
enable_hardware_reservations = model.Field(
|
|
name="enable_hardware_reservations", key="enableHardwareReservations",
|
|
is_required=False, is_property=False)
|
|
"""Offloads bandwith reservation to hardware."""
|
|
|
|
link_speed_percentage = model.Field(
|
|
name="link_speed_percentage", key="linkSpeedPercentage",
|
|
is_required=False, is_property=False)
|
|
"""The percentage of the link speed to be used for calculating reservable
|
|
bandwidth."""
|
|
|
|
default_reservation = model.Field(
|
|
name="default_reservation", key="defaultReservation",
|
|
is_required=False, is_property=False, default=0)
|
|
"""The default value of the reservation to be used for Nics that do not
|
|
have any reservation specified (0)."""
|
|
|
|
|
|
class VirtualSwitchManager(_BaseHNVModel):
|
|
|
|
"""Virtual switch manager model.
|
|
|
|
The virtualSwitchManager resource is a singleton resource that
|
|
configures the virtual switch properties on every server managed
|
|
by the Network Controller (meaning that the NC has server resources for
|
|
those machines).
|
|
"""
|
|
|
|
_endpoint = "/networking/v1/virtualSwitchManager/configuration"
|
|
|
|
qos_settings = model.Field(name="qos_settings", key="qosSettings",
|
|
is_required=False)
|
|
|
|
def __init__(self, **fields):
|
|
qos_settings = fields.get("qos_settings", {})
|
|
if not isinstance(qos_settings, VirtualSwtichQosSettings):
|
|
fields["qos_settings"] = VirtualSwtichQosSettings.from_raw_data(
|
|
raw_data=qos_settings)
|
|
super(VirtualSwitchManager, self).__init__(**fields)
|
|
|
|
@classmethod
|
|
def get(cls, resource_id=None, parent_id=None, grandparent_id=None):
|
|
""""Retrieves the required resource."""
|
|
return cls._get(resource_id, parent_id, grandparent_id)
|
|
|
|
@classmethod
|
|
def process_raw_data(cls, raw_data):
|
|
"""Create a new model using raw API response."""
|
|
properties = raw_data["properties"]
|
|
qos_settings = properties.get("qosSettings", {})
|
|
properties["qosSettings"] = VirtualSwtichQosSettings.from_raw_data(
|
|
raw_data=qos_settings)
|
|
return super(VirtualSwitchManager, cls).process_raw_data(raw_data)
|
|
|
|
@classmethod
|
|
def remove(cls, resource_id, parent_id=None, grandparent_id=None,
|
|
wait=True, timeout=None):
|
|
"""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=True, 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=list)
|
|
"""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 process_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).process_raw_data(raw_data)
|
|
|
|
|
|
class MainMode(model.Model):
|
|
|
|
"""Main mode IPsec configuration details."""
|
|
|
|
diffie_hellman_group = model.Field(
|
|
name="diffie_hellman_group", key="diffieHellmanGroup",
|
|
is_required=False, is_read_only=False, is_property=False)
|
|
"""Indicates Diffie Hellman group used during main mode IKE negotiation.
|
|
Values: `Group1`, `Group2`, `Group14`, `ECP256`, `ECP384` or `Group24`."""
|
|
|
|
integrity_algorithm = model.Field(
|
|
name="integrity_algorithm", key="integrityAlgorithm",
|
|
is_required=False, is_read_only=False, is_property=False)
|
|
"""Indicates Integrity algorithm used during main mode IKE negotiation.
|
|
Values: `MD5`, `SHA196`, `SHA256` or `SHA384`."""
|
|
|
|
encryption_algorithm = model.Field(
|
|
name="encryption_algorithm", key="encryptionAlgorithm",
|
|
is_required=False, is_read_only=False, is_property=False)
|
|
"""Indicates cipher algorithm used during main mode IKE negotiation.
|
|
Values: `DES`, `DES3`, `AES128`, `AES192` or `AES256`."""
|
|
|
|
sa_life_time_seconds = model.Field(
|
|
name="sa_life_time_seconds", key="saLifeTimeSeconds",
|
|
is_required=False, is_read_only=False, is_property=False)
|
|
"""Indicates life time of SA in seconds."""
|
|
|
|
sa_life_time_kb = model.Field(
|
|
name="sa_life_time_kb", key="saLifeTimeKiloBytes",
|
|
is_required=False, is_read_only=False, is_property=False)
|
|
"""Indicates life time of SA in Kilobytes. Ignored by IPsec."""
|
|
|
|
|
|
class QuickMode(model.Model):
|
|
|
|
"""Quick mode IPsec configuration"""
|
|
|
|
perfect_forward_secrecy = model.Field(
|
|
name="perfect_forward_secrecy", key="perfectForwardSecrecy",
|
|
is_required=False, is_read_only=False, is_property=False)
|
|
"""Indicates whether Perfect Forward Secrecy is enabled or not. If enabled
|
|
specifies the algorithm.
|
|
Values: `None`, `PFS1`, `PFS2`, `PFS2048`, `PFS14`, `ECP256`, `ECP384`,
|
|
`PFSMM` or `PFS24`."""
|
|
|
|
cipher_tc = model.Field(
|
|
name="cipher_tc", key="cipherTransformationConstant",
|
|
is_required=False, is_read_only=False, is_property=False)
|
|
"""Indicates the encryption algorithm used for data traffic.
|
|
Values:
|
|
None, `constant.AES128`, `constant.AES128CBC`, `constant.AES192`,
|
|
`constant.AES192CBC`, `constant.AES256`, `constant.AES256`,
|
|
`constant.CBCDES`, `constant.CBCDES3`, `constant.DES`, `constant.DES3`,
|
|
`constant.GCMAES128`, `constant.GCMAES192` or `constant.GCMAES256`.
|
|
"""
|
|
|
|
authentication_tc = model.Field(
|
|
name="authentication_tc", key="authenticationTransformationConstant",
|
|
is_required=False, is_read_only=False, is_property=False)
|
|
"""Indicates the authentication transform used for data traffic.
|
|
Values: `constant.MD596`, `constant.SHA196`, `constant.SHA256`,
|
|
`constant.GCMAES128`, `constant.GCMAES192` or `constant.GCMAES256`."""
|
|
|
|
sa_life_time_seconds = model.Field(
|
|
name="sa_life_time_seconds", key="saLifeTimeSeconds",
|
|
is_required=False, is_read_only=False, is_property=False)
|
|
"""Indicates life time of SA in seconds."""
|
|
|
|
sa_life_time_kb = model.Field(
|
|
name="sa_life_time_kb", key="saLifeTimeKiloBytes",
|
|
is_required=False, is_read_only=False, is_property=False)
|
|
"""Indicates life time of SA in Kilobytes."""
|
|
|
|
idle_disconnect = model.Field(
|
|
name="idle_disconnect", key="idleDisconnectSeconds",
|
|
is_required=False, is_read_only=False, is_property=False)
|
|
"""Indicates idle time after which SA is disconnected."""
|
|
|
|
|
|
class _VpnTrafficSelector(model.Model):
|
|
|
|
"""Model for VPN traffice selector."""
|
|
|
|
ts_type = model.Field(
|
|
name="ts_type", key="type",
|
|
is_required=False, is_read_only=False, is_property=False)
|
|
"""Indicates whether traffic is `IPv4` or `IPv6`."""
|
|
|
|
protocol_id = model.Field(
|
|
name="protocol_id", key="protocolId",
|
|
is_required=False, is_read_only=False, is_property=False)
|
|
"""Indicates IP protocol ID (such as UDP, TCP, and ICMP)."""
|
|
|
|
port_start = model.Field(
|
|
name="port_start", key="portStart",
|
|
is_required=False, is_read_only=False, is_property=False)
|
|
"""Indicates start of port range."""
|
|
|
|
port_end = model.Field(
|
|
name="port_end", key="portEnd",
|
|
is_required=False, is_read_only=False, is_property=False)
|
|
"""Indicates end of port range."""
|
|
|
|
ip_address_start = model.Field(
|
|
name="ip_address_start", key="ipAddressStart",
|
|
is_required=False, is_read_only=False, is_property=False)
|
|
"""Indicates start of IP addresses."""
|
|
|
|
ip_address_end = model.Field(
|
|
name="ip_address_end", key="ipAddressEnd",
|
|
is_required=False, is_read_only=False, is_property=False)
|
|
"""Indicates end of IP addresses."""
|
|
|
|
ts_payload_id = model.Field(
|
|
name="ts_payload_id", key="tsPayloadId",
|
|
is_required=False, is_read_only=False, is_property=False)
|
|
"""No information available for this field."""
|
|
|
|
|
|
class LocalVpnTrafficSelector(_VpnTrafficSelector):
|
|
|
|
"""Model for local VPN traffic selector.
|
|
|
|
Indicates collection of IPsec TrafficSelectors on the hoster side.
|
|
"""
|
|
|
|
pass
|
|
|
|
|
|
class RemoteVpnTrafficSelector(_VpnTrafficSelector):
|
|
|
|
"""Model for remote VPN traffic selector.
|
|
|
|
Indicates collection of IPsec TrafficSelectors on the tenant side.
|
|
"""
|
|
|
|
pass
|
|
|
|
|
|
class IPSecConfiguration(model.Model):
|
|
|
|
"""Details of IPsec configuration."""
|
|
|
|
authentication_method = model.Field(
|
|
name="authentication_method", key="authenticationMethod",
|
|
is_required=False, is_read_only=False, is_property=False,
|
|
default="PSK")
|
|
"""Indicates authentication method. PSK is the only valid value."""
|
|
|
|
shared_secret = model.Field(
|
|
name="shared_secret", key="sharedsecret",
|
|
is_required=False, is_read_only=False, is_property=False)
|
|
"""The shared secret used for this NetworkConnection.
|
|
Note this is write-only property and the value of this field is not
|
|
shown in the GET of Networkconnection."""
|
|
|
|
main_mode = model.Field(
|
|
name="main_mode", key="mainMode",
|
|
is_required=False, is_read_only=False, is_property=False)
|
|
"""Main mode IPsec configuration details."""
|
|
|
|
quick_mode = model.Field(
|
|
name="quick_mode", key="quickMode",
|
|
is_required=False, is_read_only=False, is_property=False)
|
|
"""Quick mode IPsec configuration."""
|
|
|
|
local_vpn_ts = model.Field(
|
|
name="local_vpn_ts", key="localVpnTrafficSelector",
|
|
is_required=False, is_read_only=False, is_property=False)
|
|
"""Indicates collection of IPsec TrafficSelectors on the hoster side."""
|
|
|
|
remote_vpn_ts = model.Field(
|
|
name="remote_vpn_ts", key="remoteVpnTrafficSelector",
|
|
is_required=False, is_read_only=False, is_property=False)
|
|
"""Indicates collection of IPsec TrafficSelectors on the tenant side."""
|
|
|
|
@classmethod
|
|
def process_raw_data(cls, raw_data):
|
|
"""Create a new model using raw API response."""
|
|
raw_main = raw_data.get("mainMode", None)
|
|
if raw_main is not None:
|
|
main_mode = MainMode.from_raw_data(raw_main)
|
|
raw_data["mainMode"] = main_mode
|
|
|
|
raw_quick = raw_data.get("quickMode", None)
|
|
if raw_quick is not None:
|
|
quick_mode = QuickMode.from_raw_data(raw_quick)
|
|
raw_data["quickMode"] = quick_mode
|
|
|
|
local_vpn_ts = []
|
|
for raw_local_vpn in raw_data.get("localVpnTrafficSelector", []):
|
|
local_vpn_ts.append(LocalVpnTrafficSelector.from_raw_data(
|
|
raw_local_vpn))
|
|
raw_data["localVpnTrafficSelector"] = local_vpn_ts
|
|
|
|
remote_vpn_ts = []
|
|
for raw_remote_vpn in raw_data.get("remoteVpnTrafficSelector", []):
|
|
remote_vpn_ts.append(RemoteVpnTrafficSelector.from_raw_data(
|
|
raw_remote_vpn))
|
|
raw_data["remoteVpnTrafficSelector"] = remote_vpn_ts
|
|
|
|
return super(IPSecConfiguration, cls).process_raw_data(raw_data)
|
|
|
|
|
|
class IPAddress(model.Model):
|
|
|
|
"""IP assigned in the tenant compartment for L3 interface."""
|
|
|
|
ip_address = model.Field(
|
|
name="ip_address", key="ipAddress",
|
|
is_required=False, is_read_only=False, is_property=False)
|
|
"""IP address for L3 interface in tenant compartment."""
|
|
|
|
prefix_length = model.Field(
|
|
name="prefix_length", key="prefixLength",
|
|
is_required=False, is_read_only=False, is_property=False)
|
|
"""Prefix length of the IP address."""
|
|
|
|
|
|
class NetworkInterfaceRoute(model.Model):
|
|
|
|
"""Model for network interface route."""
|
|
|
|
destination_prefix = model.Field(
|
|
name="destination_prefix", key="destinationPrefix",
|
|
is_required=True, is_read_only=False, is_property=False)
|
|
"""Prefix with subnet of the routes."""
|
|
|
|
next_hop = model.Field(
|
|
name="next_hop", key="nextHop",
|
|
is_required=False, is_read_only=False, is_property=False)
|
|
"""Next Hop of the routes. Is significant only for L3 connections.
|
|
Has no significance for point to point connections such as IPsec & GRE."""
|
|
|
|
metric = model.Field(
|
|
name="metric", key="metric",
|
|
is_required=False, is_read_only=False, is_property=False)
|
|
"""Indicates Metric of the route."""
|
|
|
|
protocol = model.Field(
|
|
name="protocol", key="protocol",
|
|
is_required=False, is_read_only=False, is_property=False)
|
|
"""Indicates how the route is learnt/added (`static` or `BGP`)."""
|
|
|
|
|
|
class NetworkInterfaceStatistics(model.Model):
|
|
|
|
"""Model for network interface statistics."""
|
|
|
|
outbound_bytes = model.Field(
|
|
name="outbound_bytes", key="outboundBytes",
|
|
is_required=False, is_read_only=True, is_property=False)
|
|
"""Indicates number of bytes transmitted."""
|
|
|
|
inbound_bytes = model.Field(
|
|
name="inbound_bytes", key="inboundBytes",
|
|
is_required=False, is_read_only=True, is_property=False)
|
|
"""Indicates number of bytes received."""
|
|
|
|
rx_total_packets_dropped = model.Field(
|
|
name="rx_total_packets_dropped", key="rxTotalPacketsDropped",
|
|
is_required=False, is_read_only=True, is_property=False)
|
|
"""Indicates number of packets dropped in ingress direction."""
|
|
|
|
tx_total_packets_dropped = model.Field(
|
|
name="tx_total_packets_dropped", key="txTotalPacketsDropped",
|
|
is_required=False, is_read_only=True, is_property=False)
|
|
"""Indicates number of packets dropped in egress direction."""
|
|
|
|
tx_rate_kbps = model.Field(
|
|
name="tx_rate_kbps", key="txRateKbps",
|
|
is_required=False, is_read_only=True, is_property=False)
|
|
"""Indicates rate at which traffic is going out in Kbps."""
|
|
|
|
rx_rate_kbps = model.Field(
|
|
name="rx_rate_kbps", key="rxRateKbps",
|
|
is_required=False, is_read_only=True, is_property=False)
|
|
"""Indicates rate at which traffic is coming in in Kbps."""
|
|
|
|
tx_rate_limited_packets_dropped = model.Field(
|
|
name="tx_rate_limited_packets_dropped",
|
|
key="txRateLimitedPacketsDropped",
|
|
is_required=False, is_read_only=True, is_property=False)
|
|
"""Indicates number of packets dropped in egress direction due to
|
|
rate limiting."""
|
|
|
|
rx_rate_limited_packets_dropped = model.Field(
|
|
name="rx_rate_limited_packets_dropped",
|
|
key="rxRateLimitedPacketsDropped",
|
|
is_required=False, is_read_only=True, is_property=False)
|
|
"""Indicates number of packets dropped in ingress direction due to
|
|
rate limiting."""
|
|
|
|
last_updated = model.Field(
|
|
name="last_updated", key="lastUpdated",
|
|
is_required=False, is_read_only=True, is_property=False)
|
|
"""Indicates the time the statistics were last updated."""
|
|
|
|
|
|
class GREConfiguration(model.Model):
|
|
|
|
"""Model for GRE configuration.
|
|
|
|
Indicates details of GRE configuration.
|
|
"""
|
|
|
|
gre_key = model.Field(
|
|
name="gre_key", key="greKey",
|
|
is_required=False, is_read_only=False, is_property=False)
|
|
"""Indicates GRE key."""
|
|
|
|
|
|
class L3Configuration(model.Model):
|
|
|
|
"""Model for L3 configuration.
|
|
|
|
Indicates details of L3 configuration.
|
|
"""
|
|
|
|
vlan_subnet = model.Field(
|
|
name="vlan_subnet", key="vlanSubnet",
|
|
is_required=False, is_read_only=False, is_property=False)
|
|
"""Reference to a logical subnet of L3 connection."""
|
|
|
|
|
|
class NetworkConnections(_BaseHNVModel):
|
|
|
|
"""Model for network connections.
|
|
|
|
The networkConnections resource specifies a connection from virtual
|
|
network to external networks.
|
|
Multiple connections can exist for a given virtual network and there
|
|
are different types of connections.
|
|
"""
|
|
|
|
_endpoint = ("/networking/v1/virtualGateways/{parent_id}"
|
|
"/networkConnections/{resource_id}")
|
|
|
|
parent_id = model.Field(
|
|
name="parent_id", key="parentResourceID",
|
|
is_property=False, is_required=True, 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.
|
|
"""
|
|
|
|
connection_type = model.Field(name="connection_type", key="connectionType",
|
|
is_required=False, is_read_only=False)
|
|
"""Indicates type of connection. Valid keys are `constant.IPSSEC`,
|
|
`constant.GRE` and `constant.L3`."""
|
|
outbound_kbps = model.Field(name="outbound_kbps",
|
|
key="outboundKiloBitsPerSecond",
|
|
is_required=False, is_read_only=False)
|
|
"""Indicates maximum allowed outbound bandwidth in Kbps."""
|
|
|
|
inbound_bbps = model.Field(name="inbound_bbps",
|
|
key="inboundKiloBitsPerSecond",
|
|
is_required=False, is_read_only=False)
|
|
"""Indicates maximum allowed outbound bandwidth in Kbps."""
|
|
|
|
ipsec_configuration = model.Field(name="ipsec_configuration",
|
|
key="ipSecConfiguration",
|
|
is_required=False, is_read_only=False)
|
|
"""Details of IPsec configuration."""
|
|
|
|
ip_address = model.Field(name="ip_address", key="IpAddress",
|
|
is_required=False, is_read_only=False)
|
|
"""Indicates ConnecTo Address to which peers connect to and which is
|
|
the source IP address in egress direction. This would be the VIP."""
|
|
|
|
ip_addresses = model.Field(name="ip_addresses", key="ipAddresses",
|
|
is_required=False, is_read_only=False)
|
|
"""IP assigned in the tenant compartment for L3 interface."""
|
|
|
|
peer_ip_address = model.Field(name="peer_ip_address",
|
|
key="peerIPAddresses",
|
|
is_required=False, is_read_only=False)
|
|
"""Indicates peer IP address to which connection is made."""
|
|
|
|
source_ip_address = model.Field(name="source_ip_address",
|
|
key="sourceIPAddress",
|
|
is_required=False, is_read_only=False)
|
|
"""Indicates sourceIPAddress used by the tunnel. Applicable to
|
|
IKEv2 and GRE."""
|
|
|
|
destination_ip_address = model.Field(name="destination_ip_address",
|
|
key="destinationIPAddress",
|
|
is_required=False, is_read_only=False)
|
|
"""Indicates destination ip address of the tunnel. Applicable to
|
|
IKEv2 and GRE."""
|
|
|
|
routes = model.Field(name="routes", key="routes",
|
|
is_required=False, is_read_only=False)
|
|
"""List of all the routes (static and those learned via BGP) on the
|
|
network interface. Traffic matching the routes is transmitted on the
|
|
network interface.
|
|
"""
|
|
|
|
connection_status = model.Field(name="connection_status",
|
|
key="connectionStatus",
|
|
is_required=False, is_read_only=False)
|
|
"""Indicates administrative status of connection.
|
|
Values: `enabled` or `disabled`."""
|
|
|
|
connection_state = model.Field(name="connection_state",
|
|
key="connectionState",
|
|
is_required=False, is_read_only=False)
|
|
"""Indicates operational status of connection.
|
|
Values: `Connected` or `Disconnected`.
|
|
"""
|
|
|
|
statistics = model.Field(name="statistics", key="statistics",
|
|
is_required=False, is_read_only=False)
|
|
"""Statistics of the connection."""
|
|
|
|
connection_uptime = model.Field(name="connection_uptime",
|
|
key="connectionUpTime",
|
|
is_required=False, is_read_only=True)
|
|
"""Indicates operations up time of the connection in seconds."""
|
|
|
|
connection_error_reason = model.Field(name="connection_error_reason",
|
|
key="connectionErrorReason",
|
|
is_required=False,
|
|
is_read_only=True)
|
|
"""Indicates the reason for not being able to connect after dialling
|
|
in the previous attempt."""
|
|
|
|
unreachability_reason = model.Field(name="unreachability_reason",
|
|
key="unreachabilityReason",
|
|
is_required=False, is_read_only=True)
|
|
"""Indicates the reason for not being able to connect/dial in the
|
|
previous attempt."""
|
|
|
|
gre_configuration = model.Field(name="gre_configuration",
|
|
key="greConfiguration",
|
|
is_required=False, is_read_only=False)
|
|
"""Indicates details of GRE configuration."""
|
|
|
|
l3_configuration = model.Field(name="l3_configuration",
|
|
key="l3Configuration",
|
|
is_required=False, is_read_only=False)
|
|
"""Indicates details of L3 configuration."""
|
|
|
|
gateway = model.Field(name="gateway", key="gateway",
|
|
is_required=False, is_read_only=False)
|
|
|
|
@classmethod
|
|
def process_raw_data(cls, raw_data):
|
|
"""Create a new model using raw API response."""
|
|
properties = raw_data.get("properties", {})
|
|
|
|
raw_content = properties.get("ipSecConfiguration", None)
|
|
if raw_content is not None:
|
|
ip_sec = IPSecConfiguration.from_raw_data(raw_content)
|
|
properties["ipSecConfiguration"] = ip_sec
|
|
|
|
ip_addresses = []
|
|
for raw_content in properties.get("ipAddresses", []):
|
|
ip_addresses.append(IPAddress.from_raw_data(raw_content))
|
|
properties["ipAddresses"] = ip_addresses
|
|
|
|
routes = []
|
|
for raw_content in properties.get("routes", []):
|
|
routes.append(NetworkInterfaceRoute.from_raw_data(raw_content))
|
|
properties["routes"] = routes
|
|
|
|
raw_content = properties.get("statistics", None)
|
|
if raw_content is not None:
|
|
statistics = NetworkInterfaceStatistics.from_raw_data(
|
|
raw_content)
|
|
properties["statistics"] = statistics
|
|
|
|
raw_content = properties.get("greConfiguration", None)
|
|
if raw_content is not None:
|
|
gre_configuration = GREConfiguration.from_raw_data(raw_content)
|
|
properties["greConfiguration"] = gre_configuration
|
|
|
|
raw_content = properties.get("l3Configuration", None)
|
|
if raw_content is not None:
|
|
l3_configuration = L3Configuration.from_raw_data(raw_content)
|
|
properties["l3Configuration"] = l3_configuration
|
|
|
|
raw_content = properties.get("gateway", None)
|
|
if raw_content is not None:
|
|
gateway = Resource.from_raw_data(raw_content)
|
|
properties["gateway"] = gateway
|
|
|
|
return super(NetworkConnections, cls).process_raw_data(raw_data)
|
|
|
|
|
|
class PublicIPAddresses(_BaseHNVModel):
|
|
|
|
"""Model for public IP addresses.
|
|
|
|
The PublicIPAddresses resource specifies an IP address which is publically
|
|
available. This PublicIPAddresses resource is used by the VirtualGateways
|
|
resource and the loadBalancers resource to indicate the IP address that
|
|
can be used to communicate with the virtual network from outside it.
|
|
"""
|
|
|
|
_endpoint = "/networking/v1/publicIPAddresses/{resource_id}"
|
|
|
|
ip_address = model.Field(name="ip_address", key="ipAddress",
|
|
is_required=False, is_read_only=False)
|
|
"""IP address which is allocated.
|
|
|
|
The caller can pass in a specific public IP address to be allocated or
|
|
leave it empty.
|
|
"""
|
|
|
|
allocation_method = model.Field(name="allocation_method",
|
|
key="publicIPAllocationMethod",
|
|
is_required=False, is_read_only=False)
|
|
"""`Dynamic` or `Static`
|
|
|
|
In case of static publicIpAllocationMethod, ipAddress property
|
|
needs to be passed indicating the specific public IP address which
|
|
needs to be allocated.
|
|
In case of Dynamic publicIpAllocationMethod, the ipAddress
|
|
property is not meaningful in a PUT (allocation request). In case
|
|
of Dynamic, any free public IP address will be allocated to the
|
|
caller.
|
|
"""
|
|
|
|
dns_record = model.Field(name="dns_record", key="dnsRecord",
|
|
is_required=False, is_read_only=False)
|
|
"""Properties of a DNS record associated with this public IP address."""
|
|
|
|
idle_timeout = model.Field(name="idle_timeout",
|
|
key="idleTimeoutInMinutes",
|
|
is_required=False, is_read_only=False)
|
|
"""Specifies the timeout for the TCP idle connection.
|
|
|
|
The value can be set between 4 and 30 minutes. The default is 4
|
|
minutes. If public IP is used as a frontend IP of a Load Balancer
|
|
this value is ignored.
|
|
"""
|
|
|
|
ip_configuration = model.Field(name="ip_configuration",
|
|
key="ipConfiguration",
|
|
is_required=False, is_read_only=True)
|
|
"""Reference to an ipConfigurations resource.
|
|
|
|
Relative URI of the private IP address with which this public IP is
|
|
associated. Private ip can be defined on NIC, loadBalancers, or
|
|
gateways.
|
|
"""
|
|
|
|
@classmethod
|
|
def process_raw_data(cls, raw_data):
|
|
"""Create a new model using raw API response."""
|
|
properties = raw_data.get("properties", {})
|
|
|
|
raw_content = properties.get("ipConfiguration", None)
|
|
if raw_content is not None:
|
|
resource = Resource.from_raw_data(raw_content)
|
|
properties["ipConfiguration"] = resource
|
|
|
|
return super(PublicIPAddresses, cls).process_raw_data(raw_data)
|
|
|
|
|
|
class BackendAddressPools(_BaseHNVModel):
|
|
|
|
"""Model for backend address pools.
|
|
|
|
This resource represents the list of IPs that can receive network traffic
|
|
that comes via the front-end IPs. The Load Balancing MUX handles incoming
|
|
traffic via the front-end IPs and distributes them to backend IPs based
|
|
on load balancing configuration.
|
|
"""
|
|
|
|
_endpoint = ("/networking/v1/loadBalancers/{parent_id}"
|
|
"/backendAddressPools/{resource_id}")
|
|
|
|
parent_id = model.Field(
|
|
name="parent_id", key="parentResourceID",
|
|
is_property=False, is_required=True, 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.
|
|
"""
|
|
|
|
backend_ip_configurations = model.Field(
|
|
name="backend_ip_configurations", key="backendIPConfigurations",
|
|
is_required=False, is_read_only=False)
|
|
"""Indicates an array of references to ipConfiguration Resources.
|
|
|
|
There is no restriction on having the same IP configurations in multiple
|
|
backendAddressPools. An IpConfiguration can become a part of a
|
|
backendAddressPool by setting a reference to a backendAddressPool resource
|
|
in the loadBalancerBackendAddressPools array field on the IpConfiguration
|
|
resource.
|
|
"""
|
|
|
|
load_balancing_rules = model.Field(name="load_balancing_rules",
|
|
key="loadBalancingRules",
|
|
is_required=False, is_read_only=False)
|
|
"""Indicates an array of references to the set of loadBalancingRules
|
|
resources that use this backend address pool.
|
|
"""
|
|
|
|
outbound_nat_rules = model.Field(name="outbound_nat_rules",
|
|
key="outboundNatRules",
|
|
is_required=False, is_read_only=False)
|
|
"""Indicates an array of references to the set of outboundNatRules
|
|
resources that use this backend address pool."""
|
|
|
|
@classmethod
|
|
def process_raw_data(cls, raw_data):
|
|
"""Create a new model using raw API response."""
|
|
properties = raw_data.get("properties", {})
|
|
|
|
backend_ip_configurations = []
|
|
for raw_content in properties.get("backendIPConfigurations", []):
|
|
resource = Resource.from_raw_data(raw_content)
|
|
backend_ip_configurations.append(resource)
|
|
properties["backendIPConfigurations"] = backend_ip_configurations
|
|
|
|
load_balancing_rules = []
|
|
for raw_content in properties.get("loadBalancingRules", []):
|
|
resource = Resource.from_raw_data(raw_content)
|
|
load_balancing_rules.append(resource)
|
|
properties["loadBalancingRules"] = load_balancing_rules
|
|
|
|
outbound_nat_rules = []
|
|
for raw_content in properties.get("outboundNatRules", []):
|
|
resource = Resource.from_raw_data(raw_content)
|
|
outbound_nat_rules.append(resource)
|
|
properties["outboundNatRules"] = outbound_nat_rules
|
|
|
|
return super(BackendAddressPools, cls).process_raw_data(raw_data)
|
|
|
|
|
|
class FrontendIPConfigurations(_BaseHNVModel):
|
|
|
|
"""Model for frontend ip configurations.
|
|
|
|
This resource represents the frontend IP addresses of the load balancer.
|
|
Either a publicIPAddress or a privateIPAddress and subnet must
|
|
be configured.
|
|
"""
|
|
|
|
_endpoint = ("/networking/v1/loadBalancers/{parent_id}"
|
|
"/frontendIpConfigurations/{resource_id}")
|
|
|
|
parent_id = model.Field(
|
|
name="parent_id", key="parentResourceID",
|
|
is_property=False, is_required=True, 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.
|
|
"""
|
|
|
|
inbound_nat_rules = model.Field(
|
|
name="inbound_nat_rules", key="inboundNatRules",
|
|
is_required=False, is_read_only=True)
|
|
"""Indicates a reference to the inboundNatRules resource used by
|
|
the frontEndIpConfiguration."""
|
|
|
|
load_balancing_rules = model.Field(
|
|
name="load_balancing_rules", key="loadBalancingRules",
|
|
is_required=False, is_read_only=False)
|
|
"""Indicates a reference to the loadBalancingRules resource used
|
|
by the frontEndIpConfiguration."""
|
|
|
|
outbound_nat_rules = model.Field(
|
|
name="outbound_nat_rules", key="outboundNatRules",
|
|
is_required=False, is_read_only=True)
|
|
"""Indicates a reference to the outboundNatRules resource used by
|
|
the frontEndIpConfiguration."""
|
|
|
|
public_ip_address = model.Field(
|
|
name="public_ip_address", key="publicIPAddress",
|
|
is_required=False, is_read_only=False)
|
|
"""Indicates a reference to the publicIPAddresses resource used by
|
|
the frontEndIpConfiguration. If a publicIPAddress is specified,
|
|
then a privateIPaddress is not specified. When a
|
|
publicIPAddress is specified, the privateIpAllocationMethod is
|
|
set to Dynamic.
|
|
"""
|
|
|
|
private_ip_address = model.Field(name="private_ip_address",
|
|
key="privateIPAddress",
|
|
is_required=False, is_read_only=False)
|
|
"""This is only specified if a specific private IP address identifies an
|
|
IP address which is statically configured for use with this
|
|
frontendIpConfiguration.
|
|
|
|
PrivateIPAllocation method MUST be allocated static for this case.
|
|
If a privateIPAddress is specified, a reference to a publicIPaddress
|
|
cannot be specified at the same time. privateIPAddresses can be either
|
|
from the infrastructure address space or from a tenant address space,
|
|
in either case they MUST be accompanied with a valid subnet specified in
|
|
subnet element reference.
|
|
"""
|
|
|
|
private_ip_allocation_method = model.Field(
|
|
name="private_ip_allocation_method", key="privateIPAllocationMethod",
|
|
is_required=False, is_read_only=False)
|
|
"""Static or Dynamic."""
|
|
|
|
subnet = model.Field(name="subnet", key="subnet",
|
|
is_required=False, is_read_only=False)
|
|
"""Indicates a references to the subnet resource used by the
|
|
frontendIpConfiguration resource. MUST be specified if a
|
|
privateIPaddress is specified.
|
|
A subnet reference to a logical network subnet is needed if the
|
|
privateIpAddress is from the infrastructure address space. A
|
|
subnet reference to a virtual network subnet is needed if the
|
|
privateIpAddress is from a tenant address space.
|
|
The subnet MUST include the IP address specified in
|
|
privateIpAddress.
|
|
"""
|
|
|
|
@classmethod
|
|
def process_raw_data(cls, raw_data):
|
|
"""Create a new model using raw API response."""
|
|
properties = raw_data.get("properties", {})
|
|
|
|
load_balancing_rules = []
|
|
for raw_content in properties.get("loadBalancingRules", []):
|
|
resource = Resource.from_raw_data(raw_content)
|
|
load_balancing_rules.append(resource)
|
|
properties["loadBalancingRules"] = load_balancing_rules
|
|
|
|
inbound_nat_rules = []
|
|
for raw_content in properties.get("inboundNatRules", []):
|
|
resource = Resource.from_raw_data(raw_content)
|
|
inbound_nat_rules.append(resource)
|
|
properties["inboundNatRules"] = inbound_nat_rules
|
|
|
|
outbound_nat_rules = []
|
|
for raw_content in properties.get("outboundNatRules", []):
|
|
resource = Resource.from_raw_data(raw_content)
|
|
outbound_nat_rules.append(resource)
|
|
properties["outboundNatRules"] = outbound_nat_rules
|
|
|
|
raw_content = properties.get("subnet", None)
|
|
if raw_content is not None:
|
|
resource = Resource.from_raw_data(raw_content)
|
|
properties["subnet"] = resource
|
|
|
|
return super(FrontendIPConfigurations, cls).process_raw_data(raw_data)
|
|
|
|
|
|
class InboundNATRules(_BaseHNVModel):
|
|
|
|
"""Model for inbound nat rules.
|
|
|
|
This resource is used to configure the load balancer to apply
|
|
Network Address Translation of inbound traffic.
|
|
"""
|
|
|
|
_endpoint = ("/networking/v1/loadBalancers/{parent_id}"
|
|
"/inboundNatRules/{resource_id}")
|
|
|
|
parent_id = model.Field(
|
|
name="parent_id", key="parentResourceID",
|
|
is_property=False, is_required=True, 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.
|
|
"""
|
|
|
|
backend_ip_configuration = model.Field(
|
|
name="backend_ip_configuration", key="backendIPConfiguration",
|
|
is_required=False, is_read_only=False)
|
|
"""Indicates a references to backendAddressPool resource. Traffic
|
|
sent to frontendPort of each of the frontendIPConfigurations is
|
|
forwarded to the backend IP.
|
|
"""
|
|
|
|
backend_port = model.Field(name="backend_port", key="backendPort",
|
|
is_required=False, is_read_only=False)
|
|
"""Indicates a port used for internal connections on the endpoint.
|
|
The localPort attribute maps the external port on the endpoint
|
|
to an internal port on a role. This is useful in scenarios where a
|
|
role has to communicate to an internal component on a port
|
|
that different from the one that is exposed externally.
|
|
Possible values range between 1 and 65535, inclusive.
|
|
This parameter is required if the protocol is TCP or UDP.
|
|
"""
|
|
|
|
frontend_ip_configurations = model.Field(
|
|
name="frontend_ip_configurations", key="frontendIPConfigurations",
|
|
is_required=True, is_read_only=False)
|
|
"""Indicates an array of references to frontendIPConfigurations
|
|
resources."""
|
|
|
|
frontend_port = model.Field(name="frontend_port", key="frontendPort",
|
|
is_required=False, is_read_only=False)
|
|
"""The port for the external endpoint. Any port number can be
|
|
specified, but the port numbers specified for each role in the
|
|
service MUST be unique. Possible values range between 1 and
|
|
65535, inclusive.
|
|
This parameter must be specified if protocol is TCP or UDP.
|
|
"""
|
|
|
|
protocol = model.Field(name="protocol", key="protocol",
|
|
is_required=True, is_read_only=False)
|
|
"""Indicates the inbound transport protocol for the external
|
|
endpoint. Valid values include `UDP`, `TCP`, `GRE`, `ESP` or `ALL`.
|
|
`ALL` indicates a wildcard.
|
|
"""
|
|
|
|
idle_timeout = model.Field(name="idle_timeout",
|
|
key="idleTimeoutInMinutes",
|
|
is_required=False, is_read_only=False)
|
|
"""Specifies the timeout for the TCP idle connection.
|
|
|
|
The value can be set between 4 and 30 minutes. The default is 4
|
|
minutes. If public IP is used as a frontend IP of a Load Balancer
|
|
this value is ignored.
|
|
"""
|
|
|
|
floating_ip = model.Field(name="floating_ip", key="enableFloatingIP",
|
|
is_required=False, is_read_only=False)
|
|
"""
|
|
This specifies that a floating IP will be used on the available servers
|
|
behind a load balancer. Floating IP (VIP) will be forwarded by the load
|
|
balancer to the backend server. The back-end server will be configured
|
|
with that VIP, a datacenter IP and weakhost forwarding.
|
|
|
|
Floating IP configuration is required if you are using the SQL AlwaysOn
|
|
Availability Group feature. This setting can't be changed after you create
|
|
the endpoint.
|
|
"""
|
|
|
|
@classmethod
|
|
def process_raw_data(cls, raw_data):
|
|
"""Create a new model using raw API response."""
|
|
properties = raw_data.get("properties", {})
|
|
|
|
raw_ip_configuration = properties.get("backendIPConfiguration", [])
|
|
if isinstance(raw_ip_configuration, dict):
|
|
raw_ip_configuration = [raw_ip_configuration]
|
|
|
|
for raw_content in raw_ip_configuration:
|
|
backend_ip_configuration = Resource.from_raw_data(raw_content)
|
|
properties["backendIPConfiguration"] = backend_ip_configuration
|
|
|
|
frontend_ip_configurations = []
|
|
for raw_content in properties.get("frontendIPConfigurations", []):
|
|
resource = Resource.from_raw_data(raw_content)
|
|
frontend_ip_configurations.append(resource)
|
|
properties["frontendIPConfigurations"] = frontend_ip_configurations
|
|
|
|
return super(InboundNATRules, cls).process_raw_data(raw_data)
|
|
|
|
|
|
class LoadBalancingRules(_BaseHNVModel):
|
|
|
|
"""Model for load balancing rules.
|
|
|
|
This resource is used to configure load balancing policies. The policies
|
|
dictate the kind of traffic that is load-balanced, and port mapping
|
|
between frontend IPs and backend IPs.
|
|
"""
|
|
|
|
_endpoint = ("/networking/v1/loadBalancers/{parent_id}"
|
|
"/loadBalancingRules/{resource_id}")
|
|
|
|
parent_id = model.Field(
|
|
name="parent_id", key="parentResourceID",
|
|
is_property=False, is_required=True, 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.
|
|
"""
|
|
|
|
backend_address_pool = model.Field(
|
|
name="backend_address_pool", key="backendAddressPool",
|
|
is_required=False, is_read_only=False)
|
|
"""Indicates an array of references to a BackendAddressPool resource.
|
|
|
|
Inbound traffic is randomly load balanced across IPs in the backend pool.
|
|
"""
|
|
|
|
backend_port = model.Field(name="backend_port", key="backendPort",
|
|
is_required=False, is_read_only=False)
|
|
"""Indicates the port used for internal connections on the endpoint.
|
|
|
|
The localPort attribute maps the external port on the endpoint to an
|
|
internal port on a role. This is useful in scenarios where a role has
|
|
to communicate to an internal component on a port that different from
|
|
the one that is exposed externally. If not specified, the value of
|
|
localPort is the same as the port attribute. Set the value of localPort
|
|
to "*" to automatically assign an unallocated port that is discoverable
|
|
using the runtime API.
|
|
Possible values range between 1 and 65535, inclusive.
|
|
This parameter is required if the protocol is TCP or UDP.
|
|
"""
|
|
|
|
frontend_ip_configurations = model.Field(
|
|
name="frontend_ip_configurations", key="frontendIPConfigurations",
|
|
is_required=True, is_read_only=False)
|
|
"""Indicates an array of references to FrontendIPAddress resources."""
|
|
|
|
frontend_port = model.Field(name="frontend_port", key="frontendPort",
|
|
is_required=False, is_read_only=False)
|
|
"""Indicates the port for the external endpoint.
|
|
|
|
Possible values range between 1 and 65535, inclusive. This value MUST
|
|
be unique for the loadbalancer resource.
|
|
This parameter is required if the protocol is TCP or UDP.
|
|
"""
|
|
|
|
idle_timeout = model.Field(
|
|
name="idle_timeout", key="idleTimeoutInMinutes",
|
|
is_required=False, is_read_only=False)
|
|
"""Indicates the timeout for the Tcp idle connection in the inbound
|
|
direction, i.e. a connection initiated by an internet client to a VIP.
|
|
The value can be set between 4 and 30 minutes. The default value is
|
|
4 minutes.
|
|
"""
|
|
|
|
protocol = model.Field(name="protocol", key="protocol",
|
|
is_required=True, is_read_only=False)
|
|
"""Indicates the inbound transport protocol for the external endpoint.
|
|
Valid values include `UDP`, `TCP`, `GRE`, `ESP` or `ALL`.
|
|
"""
|
|
|
|
probe = model.Field(name="probe", key="probe",
|
|
is_required=False, is_read_only=False)
|
|
"""Indicates a reference to the probe resource used by this
|
|
LoadBalancingRule.
|
|
"""
|
|
|
|
floating_ip = model.Field(name="floating_ip", key="enableFloatingIP",
|
|
is_required=False, is_read_only=False)
|
|
"""
|
|
This specifies that a floating IP will be used on the available servers
|
|
behind a load balancer. Floating IP (VIP) will be forwarded by the load
|
|
balancer to the backend server. The back-end server will be configured
|
|
with that VIP, a datacenter IP and weakhost forwarding.
|
|
|
|
Floating IP configuration is required if you are using the SQL AlwaysOn
|
|
Availability Group feature. This setting can't be changed after you create
|
|
the endpoint.
|
|
"""
|
|
|
|
load_distribution = model.Field(
|
|
name="load_distribution", key="loadDistribution",
|
|
is_required=False, is_read_only=False)
|
|
"""This specifies the load balancing distribution type to be used by
|
|
the load balancer. The loadBalancer uses a distribution algorithm which
|
|
is a 5 tuple (source IP, source port, destination IP, destination port,
|
|
protocol type) hash to map traffic to available servers. It provides
|
|
stickiness only within a transport session, which is a feature that routes
|
|
the requests for a particular session to the same physical machine that
|
|
serviced the first request for that session. Packets in the same TCP or
|
|
UDP session will be directed to the same datacenter IP instance behind the
|
|
load balanced endpoint. When the client closes and re-opens the connection
|
|
or starts a new session from the same source IP, the source port changes
|
|
and causes the traffic to go to a different datacenter IP endpoint.
|
|
|
|
The loadBalancer can be configured to use a 2 tuple (Source IP,
|
|
Destination IP) or 3 tuple (Source IP, Destination IP, Protocol) to map
|
|
traffic to the available servers. By using SourceIPProtocol, connections
|
|
initiated from the same client computer goes to the same datacenter IP
|
|
endpoint.
|
|
* Default - The load balancer is configured to use a 5 tuple hash
|
|
to map traffic to available servers
|
|
* SourceIP - The load balancer is configured to use a 2 tuple hash
|
|
to map traffic to available servers
|
|
* SourceIPProtocol - The load balancer is configured to use a 3 tuple
|
|
hash to map traffic to available servers
|
|
"""
|
|
|
|
@classmethod
|
|
def process_raw_data(cls, raw_data):
|
|
"""Create a new model using raw API response."""
|
|
properties = raw_data.get("properties", {})
|
|
|
|
frontend_ip_configurations = []
|
|
for raw_content in properties.get("frontendIPConfigurations", []):
|
|
resource = Resource.from_raw_data(raw_content)
|
|
frontend_ip_configurations.append(resource)
|
|
properties["frontendIPConfigurations"] = frontend_ip_configurations
|
|
|
|
raw_content = properties.get("backendAddressPool", None)
|
|
if raw_content is not None:
|
|
resource = Resource.from_raw_data(raw_content)
|
|
properties["backendAddressPool"] = resource
|
|
|
|
raw_content = properties.get("probe", None)
|
|
if raw_content is not None:
|
|
resource = Resource.from_raw_data(raw_content)
|
|
properties["probe"] = resource
|
|
|
|
return super(LoadBalancingRules, cls).process_raw_data(raw_data)
|
|
|
|
|
|
class OutboundNATRules(_BaseHNVModel):
|
|
|
|
"""Model for outbound NAT rules.
|
|
|
|
This resource is used to configure the load balancer to apply
|
|
Network Address Translation of outbound traffic.
|
|
"""
|
|
|
|
_endpoint = ("/networking/v1/loadBalancers/{parent_id}"
|
|
"/outboundNatRules/{resource_id}")
|
|
|
|
parent_id = model.Field(
|
|
name="parent_id", key="parentResourceID",
|
|
is_property=False, is_required=True, 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.
|
|
"""
|
|
|
|
frontend_ip_configurations = model.Field(
|
|
name="frontend_ip_configurations", key="frontendIPConfigurations",
|
|
is_required=True, is_read_only=False)
|
|
"""Indicates an array of frontendIpConfigurations resources.
|
|
|
|
Indicates an array of references to frontendIpAddress resources.
|
|
"""
|
|
|
|
backend_address_pool = model.Field(
|
|
name="backend_address_pool", key="backendAddressPool",
|
|
is_required=True, is_read_only=False)
|
|
"""Indicates a reference to the backendAddressPool resource.
|
|
|
|
This is the pool of IP addresses where outbound traffic originates.
|
|
"""
|
|
|
|
protocol = model.Field(
|
|
name="protocol", key="protocol",
|
|
is_required=True, is_read_only=False)
|
|
"""Protocol for outbound traffic. For transparent outbound NAT
|
|
specify "all".
|
|
Valid values include `TCP`, `UDP`, `GRE`, `ESP` or `All`.
|
|
"""
|
|
|
|
@classmethod
|
|
def process_raw_data(cls, raw_data):
|
|
"""Create a new model using raw API response."""
|
|
properties = raw_data.get("properties", {})
|
|
|
|
frontend_ip_configurations = []
|
|
for raw_content in properties.get("frontendIPConfigurations", []):
|
|
resource = Resource.from_raw_data(raw_content)
|
|
frontend_ip_configurations.append(resource)
|
|
properties["frontendIPConfigurations"] = frontend_ip_configurations
|
|
|
|
raw_content = properties.get("backendAddressPool", None)
|
|
if raw_content is not None:
|
|
resource = Resource.from_raw_data(raw_content)
|
|
properties["backendAddressPool"] = resource
|
|
|
|
return super(OutboundNATRules, cls).process_raw_data(raw_data)
|
|
|
|
|
|
class Probes(_BaseHNVModel):
|
|
|
|
"""Model for probes."""
|
|
|
|
_endpoint = ("/networking/v1/loadBalancers/{parent_id}"
|
|
"/probes/{resource_id}")
|
|
|
|
parent_id = model.Field(
|
|
name="parent_id", key="parentResourceID",
|
|
is_property=False, is_required=True, 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.
|
|
"""
|
|
|
|
interval = model.Field(name="interval", key="intervalInSeconds",
|
|
is_required=False, is_read_only=False)
|
|
"""Indicates the interval, in seconds, for how frequently to probe the
|
|
endpoint for health status. Typically, the interval is slightly less than
|
|
half the allocated timeout period (in seconds) which allows two full
|
|
probes before taking the instance out of rotation. The default value is
|
|
15, the minimum value is 5.
|
|
"""
|
|
|
|
load_balancing_rules = model.Field(
|
|
name="load_balancing_rules", key="loadBalancingRules",
|
|
is_required=False, is_read_only=True)
|
|
"""Indicates an array of references to loadBalancingRule resources that
|
|
use this probe.
|
|
"""
|
|
|
|
number_of_probes = model.Field(
|
|
name="number_of_probes", key="numberOfProbes",
|
|
is_required=False, is_read_only=False)
|
|
"""Indicates the timeout period, in seconds, applied to the probe where
|
|
no response will result in stopping further traffic from being delivered
|
|
to the endpoint. This value allows endpoints to be taken out of rotation
|
|
faster or slower than the typical times (which are the defaults).
|
|
The default value is 31, the minimum value is 11.
|
|
"""
|
|
|
|
protocol = model.Field(name="protocol", key="protocol",
|
|
is_required=True, is_read_only=False)
|
|
"""Indicates the protocol of the end point.
|
|
|
|
Valid values are `HTTP` or `TCP`. If `TCP` is specified, a received ACK
|
|
is required for the probe to be successful. If `HTTP` is specified,
|
|
a 200 OK response from the specified URI is required for the probe to
|
|
be successful.
|
|
"""
|
|
|
|
port = model.Field(name="port", key="port",
|
|
is_required=True, is_read_only=False)
|
|
"""Indicates the port for communicating the probe. Possible values range
|
|
from 1 to 65535, inclusive.
|
|
"""
|
|
|
|
request_path = model.Field(name="request_path", key="requestPath",
|
|
is_required=True, is_read_only=False)
|
|
"""Indicates the URI used for requesting health status from the VM.
|
|
|
|
The path is required if protocol is set to HTTP. Otherwise, it is not
|
|
allowed. There is no default value.
|
|
"""
|
|
|
|
@classmethod
|
|
def process_raw_data(cls, raw_data):
|
|
"""Create a new model using raw API response."""
|
|
properties = raw_data.get("properties", {})
|
|
|
|
load_balancing_rules = []
|
|
for raw_content in properties.get("loadBalancingRules", []):
|
|
resource = Resource.from_raw_data(raw_content)
|
|
load_balancing_rules.append(resource)
|
|
properties["loadBalancingRules"] = load_balancing_rules
|
|
|
|
return super(Probes, cls).process_raw_data(raw_data)
|
|
|
|
|
|
class LoadBalancers(_BaseHNVModel):
|
|
|
|
"""Model for load balancers.
|
|
|
|
The loadBalancers resource allows fine-grained configuration of the
|
|
distribution of incoming traffic across VM instances that are hosted
|
|
in a Windows Server and System Center cloud. This resource has two
|
|
main parts: a frontend and a backend configuration.
|
|
|
|
The frontend configuration exposes the IP address of the load balancer.
|
|
For example, this address can be a reserved public or private IP address
|
|
previously provided to the client, or it can be an IP address that is
|
|
dynamically allocated from a subnet of a virtual network.
|
|
"""
|
|
|
|
_endpoint = "/networking/v1/loadBalancers/{resource_id}"
|
|
|
|
backend_address_pools = model.Field(name="backend_address_pools",
|
|
key="backendAddressPools",
|
|
is_required=False, is_read_only=False)
|
|
"""Indicates the backend Address Pool of the load balancer."""
|
|
|
|
frontend_ip_configurations = model.Field(
|
|
name="frontend_ip_configurations", key="frontendIPConfigurations",
|
|
is_required=True, is_read_only=False)
|
|
"""Indicates the frontend IP addresses of the load balancer."""
|
|
|
|
load_balancing_rules = model.Field(name="load_balancing_rules",
|
|
key="loadBalancingRules",
|
|
is_required=False, is_read_only=False)
|
|
"""A list of load balancing configurations.
|
|
|
|
Each configuration describes what traffic and how it gets load balanced
|
|
between backend IPs.
|
|
"""
|
|
|
|
inbound_nat_rules = model.Field(name="inbound_nat_rules",
|
|
key="inboundNatRules",
|
|
is_required=False, is_read_only=False)
|
|
"""Indicates an array of inbound NAT rules configured for the
|
|
load balancer.
|
|
"""
|
|
|
|
outbound_nat_rules = model.Field(name="outbound_nat_rules",
|
|
key="outboundNatRules",
|
|
is_required=False, is_read_only=False)
|
|
"""Indicates an array of outbound NAT rules configured for the
|
|
load balancer.
|
|
"""
|
|
|
|
probes = model.Field(name="probes", key="probes",
|
|
is_required=False, is_read_only=False)
|
|
"""Indicates an array of probes configured for the
|
|
load balancer.
|
|
"""
|
|
|
|
@classmethod
|
|
def process_raw_data(cls, raw_data):
|
|
properties = raw_data.get("properties", {})
|
|
|
|
backend_address_pools = []
|
|
for raw_content in properties.get("backendAddressPools", []):
|
|
raw_content["parentResourceID"] = raw_data["resourceId"]
|
|
address_pool = BackendAddressPools.from_raw_data(raw_content)
|
|
backend_address_pools.append(address_pool)
|
|
properties["backendAddressPools"] = backend_address_pools
|
|
|
|
frontend_ip_configurations = []
|
|
for raw_content in properties.get("frontendIPConfigurations", []):
|
|
raw_content["parentResourceID"] = raw_data["resourceId"]
|
|
ip_configurations = FrontendIPConfigurations.from_raw_data(
|
|
raw_content)
|
|
frontend_ip_configurations.append(ip_configurations)
|
|
properties["frontendIPConfigurations"] = frontend_ip_configurations
|
|
|
|
inbound_nat_rules = []
|
|
for raw_content in properties.get("inboundNatRules", []):
|
|
raw_content["parentResourceID"] = raw_data["resourceId"]
|
|
inbound_nat_rule = InboundNATRules.from_raw_data(raw_content)
|
|
inbound_nat_rules.append(inbound_nat_rule)
|
|
properties["inboundNatRules"] = inbound_nat_rules
|
|
|
|
outbound_nat_rules = []
|
|
for raw_content in properties.get("outboundNatRules", []):
|
|
raw_content["parentResourceID"] = raw_data["resourceId"]
|
|
outbound_nat_rule = OutboundNATRules.from_raw_data(raw_content)
|
|
outbound_nat_rules.append(outbound_nat_rule)
|
|
properties["outboundNatRules"] = outbound_nat_rules
|
|
|
|
load_balancing_rules = []
|
|
for raw_content in properties.get("loadBalancingRules", []):
|
|
raw_content["parentResourceID"] = raw_data["resourceId"]
|
|
balancing_rule = LoadBalancingRules.from_raw_data(raw_content)
|
|
load_balancing_rules.append(balancing_rule)
|
|
properties["loadBalancingRules"] = load_balancing_rules
|
|
|
|
probes = []
|
|
for raw_content in properties.get("probes", []):
|
|
raw_content["parentResourceID"] = raw_data["resourceId"]
|
|
probe = Probes.from_raw_data(raw_content)
|
|
probes.append(probe)
|
|
properties["probes"] = probes
|
|
|
|
return super(LoadBalancers, cls).process_raw_data(raw_data)
|
|
|
|
|
|
class _BGPPeersStatistics(model.Model):
|
|
|
|
"""Base model for BGP peers statistics submodels."""
|
|
|
|
last_sent = model.Field(
|
|
name="last_sent", key="lastsent",
|
|
is_property=False, is_required=False, is_read_only=True)
|
|
"""Last sent timestamp."""
|
|
|
|
last_received = model.Field(
|
|
name="last_received", key="lastReceived",
|
|
is_property=False, is_required=False, is_read_only=True)
|
|
"""Last received timestamp."""
|
|
|
|
sent_count = model.Field(
|
|
name="sent_count", key="sentCount",
|
|
is_property=False, is_required=False, is_read_only=True)
|
|
"""Sent count."""
|
|
|
|
received_count = model.Field(
|
|
name="received_count", key="receivedCount",
|
|
is_property=False, is_required=False, is_read_only=True)
|
|
"""Received count."""
|
|
|
|
|
|
class OpenMessageStatistics(_BGPPeersStatistics):
|
|
|
|
"""Model for open message statistics."""
|
|
|
|
pass
|
|
|
|
|
|
class NotificationMessageStatistics(_BGPPeersStatistics):
|
|
|
|
"""Model for notification message statistics."""
|
|
|
|
pass
|
|
|
|
|
|
class KeepAliveMessageStatistics(_BGPPeersStatistics):
|
|
|
|
"""Model for keep alive message statistics."""
|
|
|
|
pass
|
|
|
|
|
|
class RouteRefreshMessageStatistics(_BGPPeersStatistics):
|
|
|
|
"""Model for route regresh message statistics."""
|
|
|
|
pass
|
|
|
|
|
|
class UpdateMessageStatistics(_BGPPeersStatistics):
|
|
|
|
"""Model for update message statistics."""
|
|
|
|
pass
|
|
|
|
|
|
class _StatisticsRoute(model.Model):
|
|
|
|
"""Base model for IPV4 and IPV6 route statistics."""
|
|
|
|
update_sent_count = model.Field(
|
|
name="update_sent_count", key="updateSentCount",
|
|
is_property=False, is_required=False, is_read_only=True)
|
|
"""Route update sent count."""
|
|
|
|
update_received_count = model.Field(
|
|
name="update_received_count", key="updateReceivedCount",
|
|
is_property=False, is_required=False, is_read_only=True)
|
|
"""Route update received count."""
|
|
|
|
withdrawl_sent_count = model.Field(
|
|
name="withdraw_sent_count", key="withdrawlSentCount",
|
|
is_property=False, is_required=False, is_read_only=True)
|
|
"""Route withdrawal sent count."""
|
|
|
|
withdrawl_received_count = model.Field(
|
|
name="withdraw_received_count", key="withdrawlReceivedCount",
|
|
is_property=False, is_required=False, is_read_only=True)
|
|
"""Route withdrawal received count."""
|
|
|
|
|
|
class IPV4Route(_StatisticsRoute):
|
|
|
|
"""Stats for IPv4 routes."""
|
|
|
|
pass
|
|
|
|
|
|
class IPV6Route(_StatisticsRoute):
|
|
|
|
"""Stats for IPv6 routes."""
|
|
|
|
pass
|
|
|
|
|
|
class BGPPeersStatistics(model.Model):
|
|
|
|
"""Provides statistics for this peer."""
|
|
|
|
tcp_connection_established = model.Field(
|
|
name="tcp_connection_established", key="tcpConnectionEstablished",
|
|
is_property=False, is_required=False, is_read_only=True)
|
|
"""Timestamp of TCP connection establishment for BGP."""
|
|
|
|
tcp_connection_closed = model.Field(
|
|
name="tcp_connection_closed", key="tcpConnectionClosed",
|
|
is_property=False, is_required=False, is_read_only=True)
|
|
"""Timestamp of TCP connection closed for BGP."""
|
|
|
|
open_message_stats = model.Field(
|
|
name="open_message_stats", key="openMessageStats",
|
|
is_property=False, is_required=False, is_read_only=True)
|
|
"""Instance of OpenMessageStatistics."""
|
|
|
|
notification_message_stats = model.Field(
|
|
name="notification_message_stats", key="notificationMessageStats",
|
|
is_property=False, is_required=False, is_read_only=True)
|
|
"""Instance of NotificationMessageStatistics."""
|
|
|
|
keep_alive_message_stats = model.Field(
|
|
name="keep_alive_message_stats", key="keepAliveMessageStats",
|
|
is_property=False, is_required=False, is_read_only=True)
|
|
"""Instance of KeepAliveMessageStatistics."""
|
|
|
|
route_refresh_message_stats = model.Field(
|
|
name="route_refresh_message_stats", key="routeRefreshMessageStats",
|
|
is_property=False, is_required=False, is_read_only=True)
|
|
"""Instance of RouteRefreshMessageStatistics."""
|
|
|
|
update_message_stats = model.Field(
|
|
name="update_message_stats", key="updateMessageStats",
|
|
is_property=False, is_required=False, is_read_only=True)
|
|
"""Instance of UpdateMessageStatistics."""
|
|
|
|
ipv4_route_stats = model.Field(
|
|
name="ipv4_route_stats", key="ipv4Route",
|
|
is_property=False, is_required=False, is_read_only=True)
|
|
"""Stats for IPv4 routes."""
|
|
|
|
ipv6_route_stats = model.Field(
|
|
name="ipv6_route_stats", key="ipv6Route",
|
|
is_property=False, is_required=False, is_read_only=True)
|
|
"""Stats for IPv6 routes."""
|
|
|
|
last_updated = model.Field(
|
|
name="last_updated", key="lastUpdated",
|
|
is_property=False, is_required=False, is_read_only=True)
|
|
"""Time stamp when the stats were last updated."""
|
|
|
|
@classmethod
|
|
def process_raw_data(cls, raw_data):
|
|
"""Create a new model using raw API response."""
|
|
raw_content = raw_data.get("updateMessageStats", None)
|
|
if raw_content is not None:
|
|
statistics = UpdateMessageStatistics.from_raw_data(raw_content)
|
|
raw_data["updateMessageStats"] = statistics
|
|
|
|
raw_content = raw_data.get("routeRefreshMessageStats", None)
|
|
if raw_content is not None:
|
|
statistics = RouteRefreshMessageStatistics.from_raw_data(
|
|
raw_content)
|
|
raw_data["routeRefreshMessageStats"] = statistics
|
|
|
|
raw_content = raw_data.get("keepAliveMessageStats", None)
|
|
if raw_content is not None:
|
|
statistics = KeepAliveMessageStatistics.from_raw_data(raw_content)
|
|
raw_data["keepAliveMessageStats"] = statistics
|
|
|
|
raw_content = raw_data.get("notificationMessageStats", None)
|
|
if raw_content is not None:
|
|
statistics = NotificationMessageStatistics.from_raw_data(
|
|
raw_content)
|
|
raw_data["notificationMessageStats"] = statistics
|
|
|
|
raw_content = raw_data.get("openMessageStats", None)
|
|
if raw_content is not None:
|
|
statistics = OpenMessageStatistics.from_raw_data(raw_content)
|
|
raw_data["openMessageStats"] = statistics
|
|
|
|
raw_content = raw_data.get("ipv4Route", None)
|
|
if raw_content is not None:
|
|
statistics = IPV4Route.from_raw_data(raw_content)
|
|
raw_data["ipv4Route"] = statistics
|
|
|
|
raw_content = raw_data.get("ipv6Route", None)
|
|
if raw_content is not None:
|
|
statistics = IPV6Route.from_raw_data(raw_content)
|
|
raw_data["ipv6Route"] = statistics
|
|
|
|
return super(BGPPeersStatistics, cls).process_raw_data(raw_data)
|
|
|
|
|
|
class BGPPeers(_BaseHNVModel):
|
|
|
|
"""Model for BGP peers.
|
|
|
|
This resource configures BGP peers of the virtualGateways resource.
|
|
The peer is identified by remoteRouterId and asNumber. A VRF context
|
|
can be specified on devices that support VRF. The routeMapIn and
|
|
routeMapOut properties can specify a policy map that controls the
|
|
route updates that are associated with the BGP peer.
|
|
"""
|
|
|
|
_endpoint = ("/networking/v1/virtualGateways/{grandparent_id}"
|
|
"/bgpRouters/{parent_id}/bgpPeers/{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.
|
|
"""
|
|
|
|
grandparent_id = model.Field(
|
|
name="grandparent_id", key="grandParentResourceID",
|
|
is_property=False, is_required=False, is_read_only=True)
|
|
"""The grand parent resource ID field contains the resource ID that
|
|
is associated with network objects that are ancestors of the parent
|
|
of the necessary resource."""
|
|
|
|
connection_state = model.Field(
|
|
name="connection_state", key="connectionState",
|
|
is_required=False, is_read_only=True)
|
|
"""Status of BGP peering for this peer. Possible values are `Connected` and
|
|
`Disconnected`."""
|
|
|
|
asn_number = model.Field(name="asn_number", key="asNumber",
|
|
is_required=False, is_read_only=True)
|
|
"""Indicates the ASN number of the BGP Peer."""
|
|
|
|
ext_asn_number = model.Field(name="ext_asn_number", key="extAsNumber",
|
|
is_required=False, is_read_only=False)
|
|
"""Indicates Extended ASN number of the BGP Peer in XX.YY format."""
|
|
|
|
peer_ip_address = model.Field(name="peer_ip_address", key="peerIpAddress",
|
|
is_required=False, is_read_only=False)
|
|
"""IP address of the peer."""
|
|
|
|
statistics = model.Field(name="statistics", key="statistics",
|
|
is_required=False, is_read_only=True)
|
|
"""Provides statistics for this peer."""
|
|
|
|
policy_map_out = model.Field(name="policy_map_out", key="policyMapOut",
|
|
is_required=False, is_read_only=False)
|
|
"""Reference to the policy map object that is used to filter
|
|
the routing updates sent to the peer."""
|
|
|
|
policy_map_in = model.Field(name="policy_map_in", key="policyMapIn",
|
|
is_required=False, is_read_only=False)
|
|
"""Reference to the policy map object that is used to filter
|
|
routing updates received from the peer."""
|
|
|
|
is_generated = model.Field(name="is_generated", key="isGenerated",
|
|
is_required=False, is_read_only=True)
|
|
"""This flag is set to `True` for iBGP peers."""
|
|
|
|
@classmethod
|
|
def process_raw_data(cls, raw_data):
|
|
"""Create a new model using raw API response."""
|
|
properties = raw_data.get("properties", {})
|
|
|
|
raw_content = properties.get("statistics", None)
|
|
if raw_content is not None:
|
|
statistics = BGPPeersStatistics.from_raw_data(raw_content)
|
|
properties["statistics"] = statistics
|
|
|
|
return super(BGPPeers, cls).process_raw_data(raw_data)
|
|
|
|
|
|
class BGPRouters(_BaseHNVModel):
|
|
|
|
"""Model for BGP routers.
|
|
|
|
The BGP Router resource contains the configuration needed for the Border
|
|
Gateway Protocol (BGP) router in the virtual gateway to connect to BGP
|
|
routers outside the virtual network in order to exchange routing
|
|
information.
|
|
"""
|
|
|
|
_endpoint = ("/networking/v1/virtualGateways/{parent_id}"
|
|
"/bgpRouters/{resource_id}")
|
|
|
|
parent_id = model.Field(
|
|
name="parent_id", key="parentResourceID",
|
|
is_property=False, is_required=True, 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.
|
|
"""
|
|
|
|
require_igp_sync = model.Field(
|
|
name="require_igp_sync", key="requireIgpSync",
|
|
is_required=True, is_read_only=False)
|
|
|
|
is_enabled = model.Field(name="is_enabled", key="isEnabled",
|
|
is_required=True, is_read_only=False)
|
|
|
|
is_generated = model.Field(name="is_generated", key="isGenerated",
|
|
is_required=False, is_read_only=True)
|
|
"""If this BGP router is automatically enabled, without making any REST
|
|
calls then isGenerated is set to `True`."""
|
|
|
|
ext_as_number = model.Field(name="ext_as_number", key="extAsNumber",
|
|
is_required=False, is_read_only=False)
|
|
"""Extended (4-byte) ASN of the local BGP Router in XX.YY format."""
|
|
|
|
router_id = model.Field(name="router_id", key="routerId",
|
|
is_required=False, is_read_only=False)
|
|
"""Indicates Router ID."""
|
|
|
|
router_ip = model.Field(
|
|
name="router_ip", key="routerIP",
|
|
is_required=False, is_read_only=False)
|
|
"""Indicates IP addresses to which BGP peering can be established."""
|
|
|
|
bgp_peers = model.Field(name="bgp_peers", key="bgpPeers",
|
|
is_required=False, is_read_only=False)
|
|
"""Collection of BGP peers associated with the BGP Routers resource."""
|
|
|
|
@classmethod
|
|
def process_raw_data(cls, raw_data):
|
|
"""Create a new model using raw API response."""
|
|
properties = raw_data.get("properties", {})
|
|
|
|
bgp_peers = []
|
|
for raw_content in properties.get("bgpPeers", []):
|
|
raw_content["parentResourceID"] = raw_data["resourceId"]
|
|
raw_content["grandParentResourceID"] = raw_data["parentResourceID"]
|
|
bgp_peers.append(BGPPeers.from_raw_data(raw_content))
|
|
properties["bgpPeers"] = bgp_peers
|
|
|
|
return super(BGPRouters, cls).process_raw_data(raw_data)
|
|
|
|
|
|
class LoadBalancerManager(_BaseHNVModel):
|
|
|
|
"""Model for load balancer manager.
|
|
|
|
The LoadBalancerManager resource is a singleton resource that configures
|
|
the load balancing service of the Network Controller.
|
|
"""
|
|
|
|
_endpoint = "/networking/v1/loadBalancerManager/config"
|
|
|
|
manager_ip_address = model.Field(
|
|
name="manager_ip_address", key="loadBalancerManagerIPAddress",
|
|
is_property=True, is_required=True, is_read_only=False)
|
|
"""The IP address of the load balancer service. This is part of one of
|
|
the FrontendIPPools as specified in the FrontendIPPool element in this
|
|
resource."""
|
|
|
|
outbound_nat_ip = model.Field(
|
|
name="outbound_nat_ip", key="outboundNatIPExemptions",
|
|
is_property=True, is_required=True, is_read_only=False)
|
|
"""An array of v4 or v6 subnets masks with prefixes that will not have
|
|
the source IP and Port changed by being NAT-ed. This is typically used
|
|
for datacenter services that will communicated with other services within
|
|
the same datacenter or cluster. Array of strings in the following format:
|
|
0.0.0.0/0.
|
|
|
|
NOTE: There is no validation that these IP addresses are known by the
|
|
Network Controller."""
|
|
|
|
vip_ip_pools = model.Field(
|
|
name="vip_ip_pools", key="vipIpPools",
|
|
is_property=True, is_required=True, is_read_only=False)
|
|
"""An array of references to ipPool resource that will be used for the
|
|
frontend IP Addresses.
|
|
"""
|
|
@classmethod
|
|
def get(cls, resource_id=None, parent_id=None, grandparent_id=None):
|
|
""""Retrieves the required resource."""
|
|
return cls._get(resource_id, parent_id, grandparent_id)
|
|
|
|
@classmethod
|
|
def process_raw_data(cls, raw_data):
|
|
"""Create a new model using raw API response."""
|
|
properties = raw_data.get("properties", {})
|
|
|
|
vip_ip_pools = []
|
|
for raw_content in properties.get("vipIpPools", []):
|
|
resource = Resource.from_raw_data(raw_content)
|
|
vip_ip_pools.append(resource)
|
|
properties["vipIpPools"] = vip_ip_pools
|
|
|
|
return super(LoadBalancerManager, cls).process_raw_data(raw_data)
|
|
|
|
|
|
class _Connections(model.Model):
|
|
|
|
"""Model for connections LoadBalancerMux's sub-model."""
|
|
|
|
credential = model.Field(
|
|
name="credential", key="credential",
|
|
is_property=False, is_required=False)
|
|
"""Indicates a reference to a credential resource that can be used to
|
|
connect to the device for management purposes.
|
|
"""
|
|
|
|
credential_type = model.Field(
|
|
name="credential_type", key="credentialType",
|
|
is_property=False, is_required=False)
|
|
"""Indicates the type of credential, e.g. X509Certificate or
|
|
UsernamePassword.
|
|
"""
|
|
|
|
management_addresses = model.Field(
|
|
name="management_addresses", key="managementAddresses",
|
|
is_property=False, is_required=False)
|
|
"""Indicates the management address used to connect to the server. This is
|
|
in the form of an IPv4 IP address, an IPv6 IP address, a DNS name or a flat
|
|
(NetBIOS) name.
|
|
"""
|
|
|
|
protocol = model.Field(name="protocol", key="protocol",
|
|
is_property=False, is_required=False)
|
|
|
|
port = model.Field(name="port", key="port",
|
|
is_property=False, is_required=False)
|
|
|
|
@classmethod
|
|
def process_raw_data(cls, raw_data):
|
|
raw_content = raw_data.get("credential")
|
|
if raw_content is not None:
|
|
credential_ref = Resource.from_raw_data(raw_content)
|
|
raw_data["credential"] = credential_ref
|
|
|
|
return super(_Connections, cls).process_raw_data(raw_data)
|
|
|
|
|
|
class _PeerRouterConfiguration(model.Model):
|
|
|
|
"""Model for peer router configuration _RouterConfiguration sub-model."""
|
|
|
|
peer_id = model.Field(name="peer_id", key="id",
|
|
is_property=False, is_required=True)
|
|
|
|
name = model.Field(name="name", key="routerName",
|
|
is_property=False, is_required=True)
|
|
"""The friendly name of the peer router."""
|
|
|
|
peer_asn = model.Field(name="peer_asn", key="peerASN",
|
|
is_property=False, is_required=True)
|
|
"""The BGP autonomous system number of the peer."""
|
|
|
|
ip_address = model.Field(name="ip_address", key="routerIPAddress",
|
|
is_property=False, is_required=False)
|
|
"""The IPv4 address of the local interface on the Mux from which peering
|
|
to BGP will be established."""
|
|
|
|
|
|
class _RouterConfiguration(model.Model):
|
|
|
|
"""Model for router configuration LoadBalancerMux's sub-model."""
|
|
|
|
local_asn = model.Field(
|
|
name="local_asn", key="localASN",
|
|
is_property=False, is_required=True, is_read_only=False)
|
|
"""Is the BGP autonomous system number of the MUX."""
|
|
|
|
peer_router_configurations = model.Field(
|
|
name="peer_router_configurations",
|
|
key="peerRouterConfigurations",
|
|
is_property=False, is_required=True, is_read_only=False)
|
|
"""The BGP settings the MUX uses to establish and maintain BGP peering
|
|
with one or more peers."""
|
|
|
|
@classmethod
|
|
def process_raw_data(cls, raw_data):
|
|
router_configurations = []
|
|
for raw_content in raw_data.get("peerRouterConfigurations", []):
|
|
configuration = _PeerRouterConfiguration.from_raw_data(raw_content)
|
|
router_configurations.append(configuration)
|
|
raw_data["peerRouterConfigurations"] = router_configurations
|
|
|
|
return super(_RouterConfiguration, cls).process_raw_data(raw_data)
|
|
|
|
|
|
class LoadBalancerMux(_BaseHNVModel):
|
|
|
|
"""Model for load balancer mux resource.
|
|
|
|
The LoadBalancerMux resource represents a MUX VM deployed in the
|
|
Network Controller's stamp.
|
|
"""
|
|
|
|
connections = model.Field(
|
|
name="connections", key="connections",
|
|
is_property=True, is_required=False, is_read_only=False)
|
|
"""Indicates an array of connections that specifies the information
|
|
needed to connect to the specific device for the purposes of managing
|
|
and controlling the device.
|
|
"""
|
|
|
|
router_configuration = model.Field(
|
|
name="router_configuration", key="routerConfiguration",
|
|
is_property=True, is_required=True, is_read_only=False)
|
|
"""Provides the BGP router configuration to the MUX to ensure it peers
|
|
with the datacenter routing infrastructure and properly advertises routes.
|
|
"""
|
|
|
|
virtual_server = model.Field(
|
|
name="virtual_server", key="virtualServer",
|
|
is_property=True, is_required=True, is_read_only=False)
|
|
"""Indicates a reference to the virtualServer resource that
|
|
the loadbalancer mux runs on."""
|
|
|
|
@classmethod
|
|
def process_raw_data(cls, raw_data):
|
|
properties = raw_data.get("properties", {})
|
|
|
|
connections = []
|
|
for connection in properties.get("connections", []):
|
|
connection = _Connections.from_raw_data(connection)
|
|
connections.append(connection)
|
|
properties["connections"] = connections
|
|
|
|
raw_content = properties.get("routerConfiguration")
|
|
if raw_content is not None:
|
|
configuration = _RouterConfiguration.from_raw_data(raw_content)
|
|
properties["routerConfiguration"] = configuration
|
|
|
|
raw_content = properties.get("virtualServer")
|
|
if raw_content is not None:
|
|
resource = Resource.from_raw_data(raw_content)
|
|
properties["virtualServer"] = resource
|
|
|
|
return super(LoadBalancerMux, cls).process_raw_data(raw_data)
|
|
|
|
|
|
def setup(**config):
|
|
"""Update the global configurations for the HNV client.
|
|
|
|
:param url: The base URL where the agent looks for Network
|
|
Controller API.
|
|
:param username: The username required for connecting to the
|
|
Network Controller API.
|
|
:param password: The password required for connecting to the
|
|
Network Controller API.
|
|
:param https_allow_insecure: Whether to disable the validation
|
|
of HTTPS certificates.
|
|
:param https_ca_bundle: The path to a CA_BUNDLE file or directory
|
|
with certificates of trusted CAs.
|
|
:param retry_count: Max. number of attempts for fetching content in
|
|
case of transient errors.
|
|
:param retry_interval: Interval between attempts in case of transient
|
|
errors, expressed in seconds.
|
|
:param http_request_timeout: Number of seconds until network requests
|
|
stop waiting for a response.
|
|
"""
|
|
CONFIG.update(config)
|