1800 lines
57 KiB
Python
1800 lines
57 KiB
Python
# Licensed to the Apache Software Foundation (ASF) under one or more
|
|
# contributor license agreements. See the NOTICE file distributed with
|
|
# this work for additional information regarding copyright ownership.
|
|
# The ASF licenses this file to You 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.
|
|
"""
|
|
Dimension Data Common Components
|
|
"""
|
|
from base64 import b64encode
|
|
from time import sleep
|
|
# TODO: use disutils.version when Travis CI fixed the pylint issue with version
|
|
# from distutils.version import LooseVersion
|
|
from libcloud.utils.py3 import httplib
|
|
from libcloud.utils.py3 import b
|
|
from libcloud.common.base import ConnectionUserAndKey, XmlResponse, RawResponse
|
|
from libcloud.compute.base import Node
|
|
from libcloud.utils.py3 import basestring
|
|
from libcloud.utils.xml import findtext
|
|
from libcloud.compute.types import LibcloudError, InvalidCredsError
|
|
|
|
# Roadmap / TODO:
|
|
#
|
|
# 1.0 - Copied from OpSource API, named provider details.
|
|
|
|
# setup a few variables to represent all of the DimensionData cloud namespaces
|
|
NAMESPACE_BASE = "http://oec.api.opsource.net/schemas"
|
|
ORGANIZATION_NS = NAMESPACE_BASE + "/organization"
|
|
SERVER_NS = NAMESPACE_BASE + "/server"
|
|
NETWORK_NS = NAMESPACE_BASE + "/network"
|
|
DIRECTORY_NS = NAMESPACE_BASE + "/directory"
|
|
GENERAL_NS = NAMESPACE_BASE + "/general"
|
|
BACKUP_NS = NAMESPACE_BASE + "/backup"
|
|
|
|
# API 2.0 Namespaces and URNs
|
|
TYPES_URN = "urn:didata.com:api:cloud:types"
|
|
|
|
# API end-points
|
|
API_ENDPOINTS = {
|
|
'dd-na': {
|
|
'name': 'North America (NA)',
|
|
'host': 'api-na.dimensiondata.com',
|
|
'vendor': 'DimensionData'
|
|
},
|
|
'dd-eu': {
|
|
'name': 'Europe (EU)',
|
|
'host': 'api-eu.dimensiondata.com',
|
|
'vendor': 'DimensionData'
|
|
},
|
|
'dd-au': {
|
|
'name': 'Australia (AU)',
|
|
'host': 'api-au.dimensiondata.com',
|
|
'vendor': 'DimensionData'
|
|
},
|
|
'dd-au-gov': {
|
|
'name': 'Australia Canberra ACT (AU)',
|
|
'host': 'api-canberra.dimensiondata.com',
|
|
'vendor': 'DimensionData'
|
|
},
|
|
'dd-af': {
|
|
'name': 'Africa (AF)',
|
|
'host': 'api-mea.dimensiondata.com',
|
|
'vendor': 'DimensionData'
|
|
},
|
|
'dd-ap': {
|
|
'name': 'Asia Pacific (AP)',
|
|
'host': 'api-ap.dimensiondata.com',
|
|
'vendor': 'DimensionData'
|
|
},
|
|
'dd-latam': {
|
|
'name': 'South America (LATAM)',
|
|
'host': 'api-latam.dimensiondata.com',
|
|
'vendor': 'DimensionData'
|
|
},
|
|
'dd-canada': {
|
|
'name': 'Canada (CA)',
|
|
'host': 'api-canada.dimensiondata.com',
|
|
'vendor': 'DimensionData'
|
|
},
|
|
'is-na': {
|
|
'name': 'North America (NA)',
|
|
'host': 'usapi.cloud.is.co.za',
|
|
'vendor': 'InternetSolutions'
|
|
},
|
|
'is-eu': {
|
|
'name': 'Europe (EU)',
|
|
'host': 'euapi.cloud.is.co.za',
|
|
'vendor': 'InternetSolutions'
|
|
},
|
|
'is-au': {
|
|
'name': 'Australia (AU)',
|
|
'host': 'auapi.cloud.is.co.za',
|
|
'vendor': 'InternetSolutions'
|
|
},
|
|
'is-af': {
|
|
'name': 'Africa (AF)',
|
|
'host': 'meaapi.cloud.is.co.za',
|
|
'vendor': 'InternetSolutions'
|
|
},
|
|
'is-ap': {
|
|
'name': 'Asia Pacific (AP)',
|
|
'host': 'apapi.cloud.is.co.za',
|
|
'vendor': 'InternetSolutions'
|
|
},
|
|
'is-latam': {
|
|
'name': 'South America (LATAM)',
|
|
'host': 'latamapi.cloud.is.co.za',
|
|
'vendor': 'InternetSolutions'
|
|
},
|
|
'is-canada': {
|
|
'name': 'Canada (CA)',
|
|
'host': 'canadaapi.cloud.is.co.za',
|
|
'vendor': 'InternetSolutions'
|
|
},
|
|
'ntta-na': {
|
|
'name': 'North America (NA)',
|
|
'host': 'cloudapi.nttamerica.com',
|
|
'vendor': 'NTTNorthAmerica'
|
|
},
|
|
'ntta-eu': {
|
|
'name': 'Europe (EU)',
|
|
'host': 'eucloudapi.nttamerica.com',
|
|
'vendor': 'NTTNorthAmerica'
|
|
},
|
|
'ntta-au': {
|
|
'name': 'Australia (AU)',
|
|
'host': 'aucloudapi.nttamerica.com',
|
|
'vendor': 'NTTNorthAmerica'
|
|
},
|
|
'ntta-af': {
|
|
'name': 'Africa (AF)',
|
|
'host': 'sacloudapi.nttamerica.com',
|
|
'vendor': 'NTTNorthAmerica'
|
|
},
|
|
'ntta-ap': {
|
|
'name': 'Asia Pacific (AP)',
|
|
'host': 'hkcloudapi.nttamerica.com',
|
|
'vendor': 'NTTNorthAmerica'
|
|
},
|
|
'cisco-na': {
|
|
'name': 'North America (NA)',
|
|
'host': 'iaas-api-na.cisco-ccs.com',
|
|
'vendor': 'Cisco'
|
|
},
|
|
'cisco-eu': {
|
|
'name': 'Europe (EU)',
|
|
'host': 'iaas-api-eu.cisco-ccs.com',
|
|
'vendor': 'Cisco'
|
|
},
|
|
'cisco-au': {
|
|
'name': 'Australia (AU)',
|
|
'host': 'iaas-api-au.cisco-ccs.com',
|
|
'vendor': 'Cisco'
|
|
},
|
|
'cisco-af': {
|
|
'name': 'Africa (AF)',
|
|
'host': 'iaas-api-mea.cisco-ccs.com',
|
|
'vendor': 'Cisco'
|
|
},
|
|
'cisco-ap': {
|
|
'name': 'Asia Pacific (AP)',
|
|
'host': 'iaas-api-ap.cisco-ccs.com',
|
|
'vendor': 'Cisco'
|
|
},
|
|
'cisco-latam': {
|
|
'name': 'South America (LATAM)',
|
|
'host': 'iaas-api-sa.cisco-ccs.com',
|
|
'vendor': 'Cisco'
|
|
},
|
|
'cisco-canada': {
|
|
'name': 'Canada (CA)',
|
|
'host': 'iaas-api-ca.cisco-ccs.com',
|
|
'vendor': 'Cisco'
|
|
},
|
|
'med1-il': {
|
|
'name': 'Israel (IL)',
|
|
'host': 'api.cloud.med-1.com',
|
|
'vendor': 'Med-1'
|
|
},
|
|
'med1-na': {
|
|
'name': 'North America (NA)',
|
|
'host': 'api-na.cloud.med-1.com',
|
|
'vendor': 'Med-1'
|
|
},
|
|
'med1-eu': {
|
|
'name': 'Europe (EU)',
|
|
'host': 'api-eu.cloud.med-1.com',
|
|
'vendor': 'Med-1'
|
|
},
|
|
'med1-au': {
|
|
'name': 'Australia (AU)',
|
|
'host': 'api-au.cloud.med-1.com',
|
|
'vendor': 'Med-1'
|
|
},
|
|
'med1-af': {
|
|
'name': 'Africa (AF)',
|
|
'host': 'api-af.cloud.med-1.com',
|
|
'vendor': 'Med-1'
|
|
},
|
|
'med1-ap': {
|
|
'name': 'Asia Pacific (AP)',
|
|
'host': 'api-ap.cloud.med-1.com',
|
|
'vendor': 'Med-1'
|
|
},
|
|
'med1-latam': {
|
|
'name': 'South America (LATAM)',
|
|
'host': 'api-sa.cloud.med-1.com',
|
|
'vendor': 'Med-1'
|
|
},
|
|
'med1-canada': {
|
|
'name': 'Canada (CA)',
|
|
'host': 'api-ca.cloud.med-1.com',
|
|
'vendor': 'Med-1'
|
|
},
|
|
'indosat-id': {
|
|
'name': 'Indonesia (ID)',
|
|
'host': 'iaas-api.indosat.com',
|
|
'vendor': 'Indosat'
|
|
},
|
|
'indosat-na': {
|
|
'name': 'North America (NA)',
|
|
'host': 'iaas-usapi.indosat.com',
|
|
'vendor': 'Indosat'
|
|
},
|
|
'indosat-eu': {
|
|
'name': 'Europe (EU)',
|
|
'host': 'iaas-euapi.indosat.com',
|
|
'vendor': 'Indosat'
|
|
},
|
|
'indosat-au': {
|
|
'name': 'Australia (AU)',
|
|
'host': 'iaas-auapi.indosat.com',
|
|
'vendor': 'Indosat'
|
|
},
|
|
'indosat-af': {
|
|
'name': 'Africa (AF)',
|
|
'host': 'iaas-afapi.indosat.com',
|
|
'vendor': 'Indosat'
|
|
},
|
|
'bsnl-in': {
|
|
'name': 'India (IN)',
|
|
'host': 'api.bsnlcloud.com',
|
|
'vendor': 'BSNL'
|
|
},
|
|
'bsnl-na': {
|
|
'name': 'North America (NA)',
|
|
'host': 'usapi.bsnlcloud.com',
|
|
'vendor': 'BSNL'
|
|
},
|
|
'bsnl-eu': {
|
|
'name': 'Europe (EU)',
|
|
'host': 'euapi.bsnlcloud.com',
|
|
'vendor': 'BSNL'
|
|
},
|
|
'bsnl-au': {
|
|
'name': 'Australia (AU)',
|
|
'host': 'auapi.bsnlcloud.com',
|
|
'vendor': 'BSNL'
|
|
},
|
|
'bsnl-af': {
|
|
'name': 'Africa (AF)',
|
|
'host': 'afapi.bsnlcloud.com',
|
|
'vendor': 'BSNL'
|
|
}
|
|
}
|
|
|
|
# Default API end-point for the base connection class.
|
|
DEFAULT_REGION = 'dd-na'
|
|
|
|
BAD_CODE_XML_ELEMENTS = (
|
|
('responseCode', SERVER_NS),
|
|
('responseCode', TYPES_URN),
|
|
('result', GENERAL_NS)
|
|
)
|
|
|
|
BAD_MESSAGE_XML_ELEMENTS = (
|
|
('message', SERVER_NS),
|
|
('message', TYPES_URN),
|
|
('resultDetail', GENERAL_NS)
|
|
)
|
|
|
|
|
|
def dd_object_to_id(obj, obj_type, id_value='id'):
|
|
"""
|
|
Takes in a DD object or string and prints out it's id
|
|
This is a helper method, as many of our functions can take either an object
|
|
or a string, and we need an easy way of converting them
|
|
|
|
:param obj: The object to get the id for
|
|
:type obj: ``object``
|
|
|
|
:param func: The function to call, e.g. ex_get_vlan. Note: This
|
|
function needs to return an object which has ``status``
|
|
attribute.
|
|
:type func: ``function``
|
|
|
|
:rtype: ``str``
|
|
"""
|
|
if isinstance(obj, obj_type):
|
|
return getattr(obj, id_value)
|
|
elif isinstance(obj, (basestring)):
|
|
return obj
|
|
else:
|
|
raise TypeError(
|
|
"Invalid type %s looking for basestring or %s"
|
|
% (type(obj).__name__, obj_type.__name__)
|
|
)
|
|
|
|
|
|
# TODO: use disutils.version when Travis CI fixed the pylint issue with version
|
|
# This is a temporary workaround.
|
|
def LooseVersion(version):
|
|
return float(version)
|
|
|
|
|
|
class NetworkDomainServicePlan(object):
|
|
ESSENTIALS = "ESSENTIALS"
|
|
ADVANCED = "ADVANCED"
|
|
|
|
|
|
class DimensionDataRawResponse(RawResponse):
|
|
pass
|
|
|
|
|
|
class DimensionDataResponse(XmlResponse):
|
|
def parse_error(self):
|
|
if self.status == httplib.UNAUTHORIZED:
|
|
raise InvalidCredsError(self.body)
|
|
elif self.status == httplib.FORBIDDEN:
|
|
raise InvalidCredsError(self.body)
|
|
|
|
body = self.parse_body()
|
|
|
|
if self.status == httplib.BAD_REQUEST:
|
|
for response_code in BAD_CODE_XML_ELEMENTS:
|
|
code = findtext(body, response_code[0], response_code[1])
|
|
if code is not None:
|
|
break
|
|
for message in BAD_MESSAGE_XML_ELEMENTS:
|
|
message = findtext(body, message[0], message[1])
|
|
if message is not None:
|
|
break
|
|
raise DimensionDataAPIException(code=code,
|
|
msg=message,
|
|
driver=self.connection.driver)
|
|
if self.status is not httplib.OK:
|
|
raise DimensionDataAPIException(code=self.status,
|
|
msg=body,
|
|
driver=self.connection.driver)
|
|
|
|
return self.body
|
|
|
|
|
|
class DimensionDataAPIException(LibcloudError):
|
|
def __init__(self, code, msg, driver):
|
|
self.code = code
|
|
self.msg = msg
|
|
self.driver = driver
|
|
|
|
def __str__(self):
|
|
return "%s: %s" % (self.code, self.msg)
|
|
|
|
def __repr__(self):
|
|
return ("<DimensionDataAPIException: code='%s', msg='%s'>" %
|
|
(self.code, self.msg))
|
|
|
|
|
|
class DimensionDataConnection(ConnectionUserAndKey):
|
|
"""
|
|
Connection class for the DimensionData driver
|
|
"""
|
|
|
|
api_path_version_1 = '/oec'
|
|
api_path_version_2 = '/caas'
|
|
api_version_1 = 0.9
|
|
|
|
# Earliest version supported
|
|
oldest_api_version = '2.2'
|
|
|
|
# Latest version supported
|
|
latest_api_version = '2.4'
|
|
|
|
# Default api version
|
|
active_api_version = '2.4'
|
|
|
|
_orgId = None
|
|
responseCls = DimensionDataResponse
|
|
rawResponseCls = DimensionDataRawResponse
|
|
|
|
allow_insecure = False
|
|
|
|
def __init__(self, user_id, key, secure=True, host=None, port=None,
|
|
url=None, timeout=None, proxy_url=None,
|
|
api_version=None, **conn_kwargs):
|
|
super(DimensionDataConnection, self).__init__(
|
|
user_id=user_id,
|
|
key=key,
|
|
secure=secure,
|
|
host=host, port=port,
|
|
url=url, timeout=timeout,
|
|
proxy_url=proxy_url)
|
|
|
|
if conn_kwargs['region']:
|
|
self.host = conn_kwargs['region']['host']
|
|
|
|
if api_version:
|
|
if LooseVersion(api_version) < LooseVersion(
|
|
self.oldest_api_version):
|
|
msg = 'API Version specified is too old. No longer ' \
|
|
'supported. Please upgrade to the latest version {}' \
|
|
.format(self.active_api_version)
|
|
|
|
raise DimensionDataAPIException(code=None,
|
|
msg=msg,
|
|
driver=self.driver)
|
|
elif LooseVersion(api_version) > LooseVersion(
|
|
self.latest_api_version):
|
|
msg = 'Unsupported API Version. The version specified is ' \
|
|
'not release yet. Please use the latest supported ' \
|
|
'version {}' \
|
|
.format(self.active_api_version)
|
|
|
|
raise DimensionDataAPIException(code=None,
|
|
msg=msg,
|
|
driver=self.driver)
|
|
|
|
else:
|
|
# Overwrite default version using the version user specified
|
|
self.active_api_version = api_version
|
|
|
|
def add_default_headers(self, headers):
|
|
headers['Authorization'] = \
|
|
('Basic %s' % b64encode(b('%s:%s' % (self.user_id,
|
|
self.key))).decode('utf-8'))
|
|
headers['Content-Type'] = 'application/xml'
|
|
return headers
|
|
|
|
def request_api_1(self, action, params=None, data='',
|
|
headers=None, method='GET'):
|
|
action = "%s/%s/%s" % (self.api_path_version_1,
|
|
self.api_version_1, action)
|
|
|
|
return super(DimensionDataConnection, self).request(
|
|
action=action,
|
|
params=params, data=data,
|
|
method=method, headers=headers)
|
|
|
|
def request_api_2(self, path, action, params=None, data='',
|
|
headers=None, method='GET'):
|
|
action = "%s/%s/%s/%s" % (self.api_path_version_2,
|
|
self.active_api_version, path, action)
|
|
|
|
return super(DimensionDataConnection, self).request(
|
|
action=action,
|
|
params=params, data=data,
|
|
method=method, headers=headers)
|
|
|
|
def raw_request_with_orgId_api_1(self, action, params=None, data='',
|
|
headers=None, method='GET'):
|
|
action = "%s/%s" % (self.get_resource_path_api_1(), action)
|
|
return super(DimensionDataConnection, self).request(
|
|
action=action,
|
|
params=params, data=data,
|
|
method=method, headers=headers, raw=True)
|
|
|
|
def request_with_orgId_api_1(self, action, params=None, data='',
|
|
headers=None, method='GET'):
|
|
action = "%s/%s" % (self.get_resource_path_api_1(), action)
|
|
|
|
return super(DimensionDataConnection, self).request(
|
|
action=action,
|
|
params=params, data=data,
|
|
method=method, headers=headers)
|
|
|
|
def request_with_orgId_api_2(self, action, params=None, data='',
|
|
headers=None, method='GET'):
|
|
action = "%s/%s" % (self.get_resource_path_api_2(), action)
|
|
|
|
return super(DimensionDataConnection, self).request(
|
|
action=action,
|
|
params=params, data=data,
|
|
method=method, headers=headers)
|
|
|
|
def paginated_request_with_orgId_api_2(self, action, params=None, data='',
|
|
headers=None, method='GET',
|
|
page_size=250):
|
|
"""
|
|
A paginated request to the MCP2.0 API
|
|
This essentially calls out to request_with_orgId_api_2 for each page
|
|
and yields the response to make a generator
|
|
This generator can be looped through to grab all the pages.
|
|
|
|
:param action: The resource to access (i.e. 'network/vlan')
|
|
:type action: ``str``
|
|
|
|
:param params: Parameters to give to the action
|
|
:type params: ``dict`` or ``None``
|
|
|
|
:param data: The data payload to be added to the request
|
|
:type data: ``str``
|
|
|
|
:param headers: Additional header to be added to the request
|
|
:type headers: ``str`` or ``dict`` or ``None``
|
|
|
|
:param method: HTTP Method for the request (i.e. 'GET', 'POST')
|
|
:type method: ``str``
|
|
|
|
:param page_size: The size of each page to be returned
|
|
Note: Max page size in MCP2.0 is currently 250
|
|
:type page_size: ``int``
|
|
"""
|
|
if params is None:
|
|
params = {}
|
|
params['pageSize'] = page_size
|
|
|
|
resp = self.request_with_orgId_api_2(action, params,
|
|
data, headers,
|
|
method).object
|
|
yield resp
|
|
if len(resp) <= 0:
|
|
return
|
|
|
|
pcount = resp.get('pageCount') # pylint: disable=no-member
|
|
psize = resp.get('pageSize') # pylint: disable=no-member
|
|
pnumber = resp.get('pageNumber') # pylint: disable=no-member
|
|
|
|
while int(pcount) >= int(psize):
|
|
params['pageNumber'] = int(pnumber) + 1
|
|
resp = self.request_with_orgId_api_2(action, params,
|
|
data, headers,
|
|
method).object
|
|
pcount = resp.get('pageCount') # pylint: disable=no-member
|
|
psize = resp.get('pageSize') # pylint: disable=no-member
|
|
pnumber = resp.get('pageNumber') # pylint: disable=no-member
|
|
yield resp
|
|
|
|
def get_resource_path_api_1(self):
|
|
"""
|
|
This method returns a resource path which is necessary for referencing
|
|
resources that require a full path instead of just an ID, such as
|
|
networks, and customer snapshots.
|
|
"""
|
|
return ("%s/%s/%s" % (self.api_path_version_1, self.api_version_1,
|
|
self._get_orgId()))
|
|
|
|
def get_resource_path_api_2(self):
|
|
"""
|
|
This method returns a resource path which is necessary for referencing
|
|
resources that require a full path instead of just an ID, such as
|
|
networks, and customer snapshots.
|
|
"""
|
|
return ("%s/%s/%s" % (self.api_path_version_2, self.active_api_version,
|
|
self._get_orgId()))
|
|
|
|
def wait_for_state(self, state, func, poll_interval=2, timeout=60, *args,
|
|
**kwargs):
|
|
"""
|
|
Wait for the function which returns a instance with field status/state
|
|
to match.
|
|
|
|
Keep polling func until one of the desired states is matched
|
|
|
|
:param state: Either the desired state (`str`) or a `list` of states
|
|
:type state: ``str`` or ``list``
|
|
|
|
:param func: The function to call, e.g. ex_get_vlan. Note: This
|
|
function needs to return an object which has ``status``
|
|
attribute.
|
|
:type func: ``function``
|
|
|
|
:param poll_interval: The number of seconds to wait between checks
|
|
:type poll_interval: `int`
|
|
|
|
:param timeout: The total number of seconds to wait to reach a state
|
|
:type timeout: `int`
|
|
|
|
:param args: The arguments for func
|
|
:type args: Positional arguments
|
|
|
|
:param kwargs: The arguments for func
|
|
:type kwargs: Keyword arguments
|
|
|
|
:return: Result from the calling function.
|
|
"""
|
|
cnt = 0
|
|
result = None
|
|
object_state = None
|
|
while cnt < timeout / poll_interval:
|
|
result = func(*args, **kwargs)
|
|
if isinstance(result, Node):
|
|
object_state = result.state
|
|
else:
|
|
object_state = result.status
|
|
|
|
if object_state is state or str(object_state) in state:
|
|
return result
|
|
|
|
sleep(poll_interval)
|
|
cnt += 1
|
|
|
|
msg = 'Status check for object %s timed out' % (result)
|
|
raise DimensionDataAPIException(code=object_state,
|
|
msg=msg,
|
|
driver=self.driver)
|
|
|
|
def _get_orgId(self):
|
|
"""
|
|
Send the /myaccount API request to DimensionData cloud and parse the
|
|
'orgId' from the XML response object. We need the orgId to use most
|
|
of the other API functions
|
|
"""
|
|
if self._orgId is None:
|
|
body = self.request_api_1('myaccount').object
|
|
self._orgId = findtext(body, 'orgId', DIRECTORY_NS)
|
|
return self._orgId
|
|
|
|
def get_account_details(self):
|
|
"""
|
|
Get the details of this account
|
|
|
|
:rtype: :class:`DimensionDataAccountDetails`
|
|
"""
|
|
body = self.request_api_1('myaccount').object
|
|
return DimensionDataAccountDetails(
|
|
user_name=findtext(body, 'userName', DIRECTORY_NS),
|
|
full_name=findtext(body, 'fullName', DIRECTORY_NS),
|
|
first_name=findtext(body, 'firstName', DIRECTORY_NS),
|
|
last_name=findtext(body, 'lastName', DIRECTORY_NS),
|
|
email=findtext(body, 'emailAddress', DIRECTORY_NS))
|
|
|
|
|
|
class DimensionDataAccountDetails(object):
|
|
"""
|
|
Dimension Data account class details
|
|
"""
|
|
def __init__(self, user_name, full_name, first_name, last_name, email):
|
|
self.user_name = user_name
|
|
self.full_name = full_name
|
|
self.first_name = first_name
|
|
self.last_name = last_name
|
|
self.email = email
|
|
|
|
|
|
class DimensionDataStatus(object):
|
|
"""
|
|
DimensionData API pending operation status class
|
|
action, request_time, user_name, number_of_steps, update_time,
|
|
step.name, step.number, step.percent_complete, failure_reason,
|
|
"""
|
|
def __init__(self, action=None, request_time=None, user_name=None,
|
|
number_of_steps=None, update_time=None, step_name=None,
|
|
step_number=None, step_percent_complete=None,
|
|
failure_reason=None):
|
|
self.action = action
|
|
self.request_time = request_time
|
|
self.user_name = user_name
|
|
self.number_of_steps = number_of_steps
|
|
self.update_time = update_time
|
|
self.step_name = step_name
|
|
self.step_number = step_number
|
|
self.step_percent_complete = step_percent_complete
|
|
self.failure_reason = failure_reason
|
|
|
|
def __repr__(self):
|
|
return (('<DimensionDataStatus: action=%s, request_time=%s, '
|
|
'user_name=%s, number_of_steps=%s, update_time=%s, '
|
|
'step_name=%s, step_number=%s, '
|
|
'step_percent_complete=%s, failure_reason=%s>')
|
|
% (self.action, self.request_time, self.user_name,
|
|
self.number_of_steps, self.update_time, self.step_name,
|
|
self.step_number, self.step_percent_complete,
|
|
self.failure_reason))
|
|
|
|
|
|
class DimensionDataNetwork(object):
|
|
"""
|
|
DimensionData network with location.
|
|
"""
|
|
|
|
def __init__(self, id, name, description, location, private_net,
|
|
multicast, status):
|
|
self.id = str(id)
|
|
self.name = name
|
|
self.description = description
|
|
self.location = location
|
|
self.private_net = private_net
|
|
self.multicast = multicast
|
|
self.status = status
|
|
|
|
def __repr__(self):
|
|
return (('<DimensionDataNetwork: id=%s, name=%s, description=%s, '
|
|
'location=%s, private_net=%s, multicast=%s>')
|
|
% (self.id, self.name, self.description, self.location,
|
|
self.private_net, self.multicast))
|
|
|
|
|
|
class DimensionDataNetworkDomain(object):
|
|
"""
|
|
DimensionData network domain with location.
|
|
"""
|
|
|
|
def __init__(self, id, name, description, location, status, plan):
|
|
self.id = str(id)
|
|
self.name = name
|
|
self.description = description
|
|
self.location = location
|
|
self.status = status
|
|
self.plan = plan
|
|
|
|
def __repr__(self):
|
|
return (('<DimensionDataNetworkDomain: id=%s, name=%s, '
|
|
'description=%s, location=%s, status=%s, plan=%s>')
|
|
% (self.id, self.name, self.description, self.location,
|
|
self.status, self.plan))
|
|
|
|
|
|
class DimensionDataPublicIpBlock(object):
|
|
"""
|
|
DimensionData Public IP Block with location.
|
|
"""
|
|
|
|
def __init__(self, id, base_ip, size, location, network_domain,
|
|
status):
|
|
self.id = str(id)
|
|
self.base_ip = base_ip
|
|
self.size = size
|
|
self.location = location
|
|
self.network_domain = network_domain
|
|
self.status = status
|
|
|
|
def __repr__(self):
|
|
return (('<DimensionDataNetworkDomain: id=%s, base_ip=%s, '
|
|
'size=%s, location=%s, status=%s>')
|
|
% (self.id, self.base_ip, self.size, self.location,
|
|
self.status))
|
|
|
|
|
|
class DimensionDataServerCpuSpecification(object):
|
|
"""
|
|
A class that represents the specification of the CPU(s) for a
|
|
node
|
|
"""
|
|
def __init__(self, cpu_count, cores_per_socket, performance):
|
|
"""
|
|
Instantiate a new :class:`DimensionDataServerCpuSpecification`
|
|
|
|
:param cpu_count: The number of CPUs
|
|
:type cpu_count: ``int``
|
|
|
|
:param cores_per_socket: The number of cores per socket, the
|
|
recommendation is 1
|
|
:type cores_per_socket: ``int``
|
|
|
|
:param performance: The performance type, e.g. HIGHPERFORMANCE
|
|
:type performance: ``str``
|
|
"""
|
|
self.cpu_count = cpu_count
|
|
self.cores_per_socket = cores_per_socket
|
|
self.performance = performance
|
|
|
|
def __repr__(self):
|
|
return (('<DimensionDataServerCpuSpecification: '
|
|
'cpu_count=%s, cores_per_socket=%s, '
|
|
'performance=%s>')
|
|
% (self.cpu_count, self.cores_per_socket, self.performance))
|
|
|
|
|
|
class DimensionDataServerDisk(object):
|
|
"""
|
|
A class that represents the disk on a server
|
|
"""
|
|
def __init__(self, id=None, scsi_id=None, size_gb=None, speed=None,
|
|
state=None):
|
|
"""
|
|
Instantiate a new :class:`DimensionDataServerDisk`
|
|
|
|
:param id: The id of the disk
|
|
:type id: ``str``
|
|
|
|
:param scsi_id: Representation for scsi
|
|
:type scsi_id: ``int``
|
|
|
|
:param size_gb: Size of the disk
|
|
:type size_gb: ``int``
|
|
|
|
:param speed: Speed of the disk (i.e. STANDARD)
|
|
:type speed: ``str``
|
|
|
|
:param state: State of the disk (i.e. PENDING)
|
|
:type state: ``str``
|
|
"""
|
|
self.id = id
|
|
self.scsi_id = scsi_id
|
|
self.size_gb = size_gb
|
|
self.speed = speed
|
|
self.state = state
|
|
|
|
def __repr__(self):
|
|
return (('<DimensionDataServerDisk: '
|
|
'id=%s, size_gb=%s')
|
|
% (self.id, self.size_gb))
|
|
|
|
|
|
class DimensionDataServerVMWareTools(object):
|
|
"""
|
|
A class that represents the VMWareTools for a node
|
|
"""
|
|
def __init__(self, status, version_status, api_version):
|
|
"""
|
|
Instantiate a new :class:`DimensionDataServerVMWareTools` object
|
|
|
|
:param status: The status of VMWare Tools
|
|
:type status: ``str``
|
|
|
|
:param version_status: The status for the version of VMWare Tools
|
|
(i.e NEEDS_UPGRADE)
|
|
:type version_status: ``str``
|
|
|
|
:param api_version: The API version of VMWare Tools
|
|
:type api_version: ``str``
|
|
"""
|
|
self.status = status
|
|
self.version_status = version_status
|
|
self.api_version = api_version
|
|
|
|
def __repr__(self):
|
|
return (('<DimensionDataServerVMWareTools '
|
|
'status=%s, version_status=%s, '
|
|
'api_version=%s>')
|
|
% (self.status, self.version_status, self.api_version))
|
|
|
|
|
|
class DimensionDataFirewallRule(object):
|
|
"""
|
|
DimensionData Firewall Rule for a network domain
|
|
"""
|
|
|
|
def __init__(self, id, name, action, location, network_domain,
|
|
status, ip_version, protocol, source, destination,
|
|
enabled):
|
|
self.id = str(id)
|
|
self.name = name
|
|
self.action = action
|
|
self.location = location
|
|
self.network_domain = network_domain
|
|
self.status = status
|
|
self.ip_version = ip_version
|
|
self.protocol = protocol
|
|
self.source = source
|
|
self.destination = destination
|
|
self.enabled = enabled
|
|
|
|
def __repr__(self):
|
|
return (('<DimensionDataFirewallRule: id=%s, name=%s, '
|
|
'action=%s, location=%s, network_domain=%s, '
|
|
'status=%s, ip_version=%s, protocol=%s, source=%s, '
|
|
'destination=%s, enabled=%s>')
|
|
% (self.id, self.name, self.action, self.location,
|
|
self.network_domain, self.status, self.ip_version,
|
|
self.protocol, self.source, self.destination,
|
|
self.enabled))
|
|
|
|
|
|
class DimensionDataFirewallAddress(object):
|
|
"""
|
|
The source or destination model in a firewall rule
|
|
"""
|
|
def __init__(self, any_ip, ip_address, ip_prefix_size,
|
|
port_begin, port_end, address_list_id,
|
|
port_list_id):
|
|
self.any_ip = any_ip
|
|
self.ip_address = ip_address
|
|
self.ip_prefix_size = ip_prefix_size
|
|
self.port_list_id = port_list_id
|
|
self.port_begin = port_begin
|
|
self.port_end = port_end
|
|
self.address_list_id = address_list_id
|
|
self.port_list_id = port_list_id
|
|
|
|
def __repr__(self):
|
|
return (
|
|
'<DimensionDataFirewallAddress: any_ip=%s, ip_address=%s, '
|
|
'ip_prefix_size=%s, port_begin=%s, port_end=%s, '
|
|
'address_list_id=%s, port_list_id=%s>'
|
|
% (self.any_ip, self.ip_address, self.ip_prefix_size,
|
|
self.port_begin, self.port_end, self.address_list_id,
|
|
self.port_list_id))
|
|
|
|
|
|
class DimensionDataNatRule(object):
|
|
"""
|
|
An IP NAT rule in a network domain
|
|
"""
|
|
def __init__(self, id, network_domain, internal_ip, external_ip, status):
|
|
self.id = id
|
|
self.network_domain = network_domain
|
|
self.internal_ip = internal_ip
|
|
self.external_ip = external_ip
|
|
self.status = status
|
|
|
|
def __repr__(self):
|
|
return (('<DimensionDataNatRule: id=%s, status=%s>')
|
|
% (self.id, self.status))
|
|
|
|
|
|
class DimensionDataAntiAffinityRule(object):
|
|
"""
|
|
Anti-Affinity rule for DimensionData
|
|
|
|
An Anti-Affinity rule ensures that servers in the rule will
|
|
not reside on the same VMware ESX host.
|
|
"""
|
|
def __init__(self, id, node_list):
|
|
"""
|
|
Instantiate a new :class:`DimensionDataAntiAffinityRule`
|
|
|
|
:param id: The ID of the Anti-Affinity rule
|
|
:type id: ``str``
|
|
|
|
:param node_list: List of node ids that belong in this rule
|
|
:type node_list: ``list`` of ``str``
|
|
"""
|
|
self.id = id
|
|
self.node_list = node_list
|
|
|
|
def __repr__(self):
|
|
return (('<DimensionDataAntiAffinityRule: id=%s>')
|
|
% (self.id))
|
|
|
|
|
|
class DimensionDataVlan(object):
|
|
"""
|
|
DimensionData VLAN.
|
|
"""
|
|
|
|
def __init__(self, id, name, description, location, network_domain,
|
|
status, private_ipv4_range_address, private_ipv4_range_size,
|
|
ipv6_range_address, ipv6_range_size, ipv4_gateway,
|
|
ipv6_gateway):
|
|
"""
|
|
Initialize an instance of ``DimensionDataVlan``
|
|
|
|
:param id: The ID of the VLAN
|
|
:type id: ``str``
|
|
|
|
:param name: The name of the VLAN
|
|
:type name: ``str``
|
|
|
|
:param description: Plan text description of the VLAN
|
|
:type description: ``str``
|
|
|
|
:param location: The location (data center) of the VLAN
|
|
:type location: ``NodeLocation``
|
|
|
|
:param network_domain: The Network Domain that owns this VLAN
|
|
:type network_domain: :class:`DimensionDataNetworkDomain`
|
|
|
|
:param status: The status of the VLAN
|
|
:type status: :class:`DimensionDataStatus`
|
|
|
|
:param private_ipv4_range_address: The host address of the VLAN
|
|
IP space
|
|
:type private_ipv4_range_address: ``str``
|
|
|
|
:param private_ipv4_range_size: The size (e.g. '24') of the VLAN
|
|
as a CIDR range size
|
|
:type private_ipv4_range_size: ``int``
|
|
|
|
:param ipv6_range_address: The host address of the VLAN
|
|
IP space
|
|
:type ipv6_range_address: ``str``
|
|
|
|
:param ipv6_range_size: The size (e.g. '32') of the VLAN
|
|
as a CIDR range size
|
|
:type ipv6_range_size: ``int``
|
|
|
|
:param ipv4_gateway: The IPv4 default gateway address
|
|
:type ipv4_gateway: ``str``
|
|
|
|
:param ipv6_gateway: The IPv6 default gateway address
|
|
:type ipv6_gateway: ``str``
|
|
"""
|
|
self.id = str(id)
|
|
self.name = name
|
|
self.location = location
|
|
self.description = description
|
|
self.network_domain = network_domain
|
|
self.status = status
|
|
self.private_ipv4_range_address = private_ipv4_range_address
|
|
self.private_ipv4_range_size = private_ipv4_range_size
|
|
self.ipv6_range_address = ipv6_range_address
|
|
self.ipv6_range_size = ipv6_range_size
|
|
self.ipv4_gateway = ipv4_gateway
|
|
self.ipv6_gateway = ipv6_gateway
|
|
|
|
def __repr__(self):
|
|
return (('<DimensionDataVlan: id=%s, name=%s, '
|
|
'description=%s, location=%s, status=%s>')
|
|
% (self.id, self.name, self.description,
|
|
self.location, self.status))
|
|
|
|
|
|
class DimensionDataPool(object):
|
|
"""
|
|
DimensionData VIP Pool.
|
|
"""
|
|
|
|
def __init__(self, id, name, description, status, load_balance_method,
|
|
health_monitor_id, service_down_action, slow_ramp_time):
|
|
"""
|
|
Initialize an instance of ``DimensionDataPool``
|
|
|
|
:param id: The ID of the pool
|
|
:type id: ``str``
|
|
|
|
:param name: The name of the pool
|
|
:type name: ``str``
|
|
|
|
:param description: Plan text description of the pool
|
|
:type description: ``str``
|
|
|
|
:param status: The status of the pool
|
|
:type status: :class:`DimensionDataStatus`
|
|
|
|
:param load_balance_method: The load balancer method
|
|
:type load_balance_method: ``str``
|
|
|
|
:param health_monitor_id: The ID of the health monitor
|
|
:type health_monitor_id: ``str``
|
|
|
|
:param service_down_action: Action to take when pool is down
|
|
:type service_down_action: ``str``
|
|
|
|
:param slow_ramp_time: The ramp-up time for service recovery
|
|
:type slow_ramp_time: ``int``
|
|
"""
|
|
self.id = str(id)
|
|
self.name = name
|
|
self.description = description
|
|
self.status = status
|
|
self.load_balance_method = load_balance_method
|
|
self.health_monitor_id = health_monitor_id
|
|
self.service_down_action = service_down_action
|
|
self.slow_ramp_time = slow_ramp_time
|
|
|
|
def __repr__(self):
|
|
return (('<DimensionDataPool: id=%s, name=%s, '
|
|
'description=%s, status=%s>')
|
|
% (self.id, self.name, self.description,
|
|
self.status))
|
|
|
|
|
|
class DimensionDataPoolMember(object):
|
|
"""
|
|
DimensionData VIP Pool Member.
|
|
"""
|
|
|
|
def __init__(self, id, name, status, ip, port, node_id):
|
|
"""
|
|
Initialize an instance of ``DimensionDataPoolMember``
|
|
|
|
:param id: The ID of the pool member
|
|
:type id: ``str``
|
|
|
|
:param name: The name of the pool member
|
|
:type name: ``str``
|
|
|
|
:param status: The status of the pool
|
|
:type status: :class:`DimensionDataStatus`
|
|
|
|
:param ip: The IP of the pool member
|
|
:type ip: ``str``
|
|
|
|
:param port: The port of the pool member
|
|
:type port: ``int``
|
|
|
|
:param node_id: The ID of the associated node
|
|
:type node_id: ``str``
|
|
"""
|
|
self.id = str(id)
|
|
self.name = name
|
|
self.status = status
|
|
self.ip = ip
|
|
self.port = port
|
|
self.node_id = node_id
|
|
|
|
def __repr__(self):
|
|
return (('<DimensionDataPoolMember: id=%s, name=%s, '
|
|
'ip=%s, status=%s, port=%s, node_id=%s>')
|
|
% (self.id, self.name,
|
|
self.ip, self.status, self.port,
|
|
self.node_id))
|
|
|
|
|
|
class DimensionDataVIPNode(object):
|
|
def __init__(self, id, name, status, ip, connection_limit='10000',
|
|
connection_rate_limit='10000'):
|
|
"""
|
|
Initialize an instance of :class:`DimensionDataVIPNode`
|
|
|
|
:param id: The ID of the node
|
|
:type id: ``str``
|
|
|
|
:param name: The name of the node
|
|
:type name: ``str``
|
|
|
|
:param status: The status of the node
|
|
:type status: :class:`DimensionDataStatus`
|
|
|
|
:param ip: The IP of the node
|
|
:type ip: ``str``
|
|
|
|
:param connection_limit: The total connection limit for the node
|
|
:type connection_limit: ``int``
|
|
|
|
:param connection_rate_limit: The rate limit for the node
|
|
:type connection_rate_limit: ``int``
|
|
"""
|
|
self.id = str(id)
|
|
self.name = name
|
|
self.status = status
|
|
self.ip = ip
|
|
self.connection_limit = connection_limit
|
|
self.connection_rate_limit = connection_rate_limit
|
|
|
|
def __repr__(self):
|
|
return (('<DimensionDataVIPNode: id=%s, name=%s, '
|
|
'status=%s, ip=%s>')
|
|
% (self.id, self.name,
|
|
self.status, self.ip))
|
|
|
|
|
|
class DimensionDataVirtualListener(object):
|
|
"""
|
|
DimensionData Virtual Listener.
|
|
"""
|
|
|
|
def __init__(self, id, name, status, ip):
|
|
"""
|
|
Initialize an instance of :class:`DimensionDataVirtualListener`
|
|
|
|
:param id: The ID of the listener
|
|
:type id: ``str``
|
|
|
|
:param name: The name of the listener
|
|
:type name: ``str``
|
|
|
|
:param status: The status of the listener
|
|
:type status: :class:`DimensionDataStatus`
|
|
|
|
:param ip: The IP of the listener
|
|
:type ip: ``str``
|
|
"""
|
|
self.id = str(id)
|
|
self.name = name
|
|
self.status = status
|
|
self.ip = ip
|
|
|
|
def __repr__(self):
|
|
return (('<DimensionDataVirtualListener: id=%s, name=%s, '
|
|
'status=%s, ip=%s>')
|
|
% (self.id, self.name,
|
|
self.status, self.ip))
|
|
|
|
|
|
class DimensionDataDefaultHealthMonitor(object):
|
|
"""
|
|
A default health monitor for a VIP (node, pool or listener)
|
|
"""
|
|
def __init__(self, id, name, node_compatible, pool_compatible):
|
|
"""
|
|
Initialize an instance of :class:`DimensionDataDefaultHealthMonitor`
|
|
|
|
:param id: The ID of the monitor
|
|
:type id: ``str``
|
|
|
|
:param name: The name of the monitor
|
|
:type name: ``str``
|
|
|
|
:param node_compatible: Is a monitor capable of monitoring nodes
|
|
:type node_compatible: ``bool``
|
|
|
|
:param pool_compatible: Is a monitor capable of monitoring pools
|
|
:type pool_compatible: ``bool``
|
|
"""
|
|
self.id = id
|
|
self.name = name
|
|
self.node_compatible = node_compatible
|
|
self.pool_compatible = pool_compatible
|
|
|
|
def __repr__(self):
|
|
return (('<DimensionDataDefaultHealthMonitor: id=%s, name=%s>')
|
|
% (self.id, self.name))
|
|
|
|
|
|
class DimensionDataPersistenceProfile(object):
|
|
"""
|
|
Each Persistence Profile declares the combination of Virtual Listener
|
|
type and protocol with which it is
|
|
compatible and whether or not it is compatible as a
|
|
Fallback Persistence Profile.
|
|
"""
|
|
def __init__(self, id, name, compatible_listeners, fallback_compatible):
|
|
"""
|
|
Initialize an instance of :class:`DimensionDataPersistenceProfile`
|
|
|
|
:param id: The ID of the profile
|
|
:type id: ``str``
|
|
|
|
:param name: The name of the profile
|
|
:type name: ``str``
|
|
|
|
:param compatible_listeners: List of compatible Virtual Listener types
|
|
:type compatible_listeners: ``list`` of
|
|
:class:`DimensionDataVirtualListenerCompatibility`
|
|
|
|
:param fallback_compatible: Is capable as a fallback profile
|
|
:type fallback_compatible: ``bool``
|
|
"""
|
|
self.id = id
|
|
self.name = name
|
|
self.compatible_listeners = compatible_listeners
|
|
self.fallback_compatible = fallback_compatible
|
|
|
|
def __repr__(self):
|
|
return (('<DimensionDataPersistenceProfile: id=%s, name=%s>')
|
|
% (self.id, self.name))
|
|
|
|
|
|
class DimensionDataDefaultiRule(object):
|
|
"""
|
|
A default iRule for a network domain, can be applied to a listener
|
|
"""
|
|
def __init__(self, id, name, compatible_listeners):
|
|
"""
|
|
Initialize an instance of :class:`DimensionDataDefaultiRule`
|
|
|
|
:param id: The ID of the iRule
|
|
:type id: ``str``
|
|
|
|
:param name: The name of the iRule
|
|
:type name: ``str``
|
|
|
|
:param compatible_listeners: List of compatible Virtual Listener types
|
|
:type compatible_listeners: ``list`` of
|
|
:class:`DimensionDataVirtualListenerCompatibility`
|
|
"""
|
|
self.id = id
|
|
self.name = name
|
|
self.compatible_listeners = compatible_listeners
|
|
|
|
def __repr__(self):
|
|
return (('<DimensionDataDefaultiRule: id=%s, name=%s>')
|
|
% (self.id, self.name))
|
|
|
|
|
|
class DimensionDataVirtualListenerCompatibility(object):
|
|
"""
|
|
A compatibility preference for a persistence profile or iRule
|
|
specifies which virtual listener types this profile or iRule can be
|
|
applied to.
|
|
"""
|
|
def __init__(self, type, protocol):
|
|
self.type = type
|
|
self.protocol = protocol
|
|
|
|
def __repr__(self):
|
|
return (('<DimensionDataVirtualListenerCompatibility: '
|
|
'type=%s, protocol=%s>')
|
|
% (self.type, self.protocol))
|
|
|
|
|
|
class DimensionDataBackupDetails(object):
|
|
"""
|
|
Dimension Data Backup Details represents information about
|
|
a targets backups configuration
|
|
"""
|
|
|
|
def __init__(self, asset_id, service_plan, status, clients=None):
|
|
"""
|
|
Initialize an instance of :class:`DimensionDataBackupDetails`
|
|
|
|
:param asset_id: Asset identification for backups
|
|
:type asset_id: ``str``
|
|
|
|
:param service_plan: The service plan for backups. i.e (Essentials)
|
|
:type service_plan: ``str``
|
|
|
|
:param status: The overall status this backup target.
|
|
i.e. (unregistered)
|
|
:type status: ``str``
|
|
|
|
:param clients: Backup clients attached to this target
|
|
:type clients: ``list`` of :class:`DimensionDataBackupClient`
|
|
"""
|
|
self.asset_id = asset_id
|
|
self.service_plan = service_plan
|
|
self.status = status
|
|
self.clients = clients
|
|
|
|
def __repr__(self):
|
|
return (('<DimensionDataBackupDetails: id=%s>')
|
|
% (self.asset_id))
|
|
|
|
|
|
class DimensionDataBackupClient(object):
|
|
"""
|
|
An object that represents a backup client
|
|
"""
|
|
def __init__(self, id, type, status,
|
|
schedule_policy, storage_policy, download_url,
|
|
alert=None, running_job=None):
|
|
"""
|
|
Initialize an instance of :class:`DimensionDataBackupClient`
|
|
|
|
:param id: Unique ID for the client
|
|
:type id: ``str``
|
|
|
|
:param type: The type of client that this client is
|
|
:type type: :class:`DimensionDataBackupClientType`
|
|
|
|
:param status: The states of this particular backup client.
|
|
i.e. (Unregistered)
|
|
:type status: ``str``
|
|
|
|
:param schedule_policy: The schedule policy for this client
|
|
NOTE: Dimension Data only sends back the name
|
|
of the schedule policy, no further details
|
|
:type schedule_policy: ``str``
|
|
|
|
:param storage_policy: The storage policy for this client
|
|
NOTE: Dimension Data only sends back the name
|
|
of the storage policy, no further details
|
|
:type storage_policy: ``str``
|
|
|
|
:param download_url: The download url for this client
|
|
:type download_url: ``str``
|
|
|
|
:param alert: The alert configured for this backup client (optional)
|
|
:type alert: :class:`DimensionDataBackupClientAlert`
|
|
|
|
:param alert: The running job for the client (optional)
|
|
:type alert: :class:`DimensionDataBackupClientRunningJob`
|
|
"""
|
|
self.id = id
|
|
self.type = type
|
|
self.status = status
|
|
self.schedule_policy = schedule_policy
|
|
self.storage_policy = storage_policy
|
|
self.download_url = download_url
|
|
self.alert = alert
|
|
self.running_job = running_job
|
|
|
|
def __repr__(self):
|
|
return (('<DimensionDataBackupClient: id=%s>')
|
|
% (self.id))
|
|
|
|
|
|
class DimensionDataBackupClientAlert(object):
|
|
"""
|
|
An alert for a backup client
|
|
"""
|
|
def __init__(self, trigger, notify_list=[]):
|
|
"""
|
|
Initialize an instance of :class:`DimensionDataBackupClientAlert`
|
|
|
|
:param trigger: Trigger type for the client i.e. ON_FAILURE
|
|
:type trigger: ``str``
|
|
|
|
:param notify_list: List of email addresses that are notified
|
|
when the alert is fired
|
|
:type notify_list: ``list`` of ``str``
|
|
"""
|
|
self.trigger = trigger
|
|
self.notify_list = notify_list
|
|
|
|
def __repr__(self):
|
|
return (('<DimensionDataBackupClientAlert: trigger=%s>')
|
|
% (self.trigger))
|
|
|
|
|
|
class DimensionDataBackupClientRunningJob(object):
|
|
"""
|
|
A running job for a given backup client
|
|
"""
|
|
def __init__(self, id, status, percentage=0):
|
|
"""
|
|
Initialize an instance of :class:`DimensionDataBackupClientRunningJob`
|
|
|
|
:param id: The unqiue ID of the job
|
|
:type id: ``str``
|
|
|
|
:param status: The status of the job i.e. Waiting
|
|
:type status: ``str``
|
|
|
|
:param percentage: The percentage completion of the job
|
|
:type percentage: ``int``
|
|
"""
|
|
self.id = id
|
|
self.percentage = percentage
|
|
self.status = status
|
|
|
|
def __repr__(self):
|
|
return (('<DimensionDataBackupClientRunningJob: id=%s>')
|
|
% (self.id))
|
|
|
|
|
|
class DimensionDataBackupClientType(object):
|
|
"""
|
|
A client type object for backups
|
|
"""
|
|
def __init__(self, type, is_file_system, description):
|
|
"""
|
|
Initialize an instance of :class:`DimensionDataBackupClientType`
|
|
|
|
:param type: The type of client i.e. (FA.Linux, MySQL, ect.)
|
|
:type type: ``str``
|
|
|
|
:param is_file_system: The name of the iRule
|
|
:type is_file_system: ``bool``
|
|
|
|
:param description: Description of the client
|
|
:type description: ``str``
|
|
"""
|
|
self.type = type
|
|
self.is_file_system = is_file_system
|
|
self.description = description
|
|
|
|
def __repr__(self):
|
|
return (('<DimensionDataBackupClientType: type=%s>')
|
|
% (self.type))
|
|
|
|
|
|
class DimensionDataBackupStoragePolicy(object):
|
|
"""
|
|
A representation of a storage policy
|
|
"""
|
|
def __init__(self, name, retention_period, secondary_location):
|
|
"""
|
|
Initialize an instance of :class:`DimensionDataBackupStoragePolicy`
|
|
|
|
:param name: The name of the storage policy i.e. 14 Day Storage Policy
|
|
:type name: ``str``
|
|
|
|
:param retention_period: How long to keep the backup in days
|
|
:type retention_period: ``int``
|
|
|
|
:param secondary_location: The secondary location i.e. Primary
|
|
:type secondary_location: ``str``
|
|
"""
|
|
self.name = name
|
|
self.retention_period = retention_period
|
|
self.secondary_location = secondary_location
|
|
|
|
def __repr__(self):
|
|
return (('<DimensionDataBackupStoragePolicy: name=%s>')
|
|
% (self.name))
|
|
|
|
|
|
class DimensionDataBackupSchedulePolicy(object):
|
|
"""
|
|
A representation of a schedule policy
|
|
"""
|
|
def __init__(self, name, description):
|
|
"""
|
|
Initialize an instance of :class:`DimensionDataBackupSchedulePolicy`
|
|
|
|
:param name: The name of the policy i.e 12AM - 6AM
|
|
:type name: ``str``
|
|
|
|
:param description: Short summary of the details of the policy
|
|
:type description: ``str``
|
|
"""
|
|
self.name = name
|
|
self.description = description
|
|
|
|
def __repr__(self):
|
|
return (('<DimensionDataBackupSchedulePolicy: name=%s>')
|
|
% (self.name))
|
|
|
|
|
|
class DimensionDataTag(object):
|
|
"""
|
|
A representation of a Tag in Dimension Data
|
|
A Tag first must have a Tag Key, then an asset is tag with
|
|
a key and an option value. Tags can be queried later to filter assets
|
|
and also show up on usage report if so desired.
|
|
"""
|
|
def __init__(self, asset_type, asset_id, asset_name,
|
|
datacenter, key, value):
|
|
"""
|
|
Initialize an instance of :class:`DimensionDataTag`
|
|
|
|
:param asset_type: The type of asset. Current asset types:
|
|
SERVER, VLAN, NETWORK_DOMAIN, CUSTOMER_IMAGE,
|
|
PUBLIC_IP_BLOCK, ACCOUNT
|
|
:type asset_type: ``str``
|
|
|
|
:param asset_id: The GUID of the asset that is tagged
|
|
:type asset_id: ``str``
|
|
|
|
:param asset_name: The name of the asset that is tagged
|
|
:type asset_name: ``str``
|
|
|
|
:param datacenter: The short datacenter name of the tagged asset
|
|
:type datacenter: ``str``
|
|
|
|
:param key: The tagged key
|
|
:type key: :class:`DimensionDataTagKey`
|
|
|
|
:param value: The tagged value
|
|
:type value: ``None`` or ``str``
|
|
"""
|
|
self.asset_type = asset_type
|
|
self.asset_id = asset_id
|
|
self.asset_name = asset_name
|
|
self.datacenter = datacenter
|
|
self.key = key
|
|
self.value = value
|
|
|
|
def __repr__(self):
|
|
return (('<DimensionDataTag: asset_name=%s, tag_name=%s, value=%s>')
|
|
% (self.asset_name, self.key.name, self.value))
|
|
|
|
|
|
class DimensionDataTagKey(object):
|
|
"""
|
|
A representation of a Tag Key in Dimension Data
|
|
A tag key is required to tag an asset
|
|
"""
|
|
def __init__(self, id, name, description,
|
|
value_required, display_on_report):
|
|
"""
|
|
Initialize an instance of :class:`DimensionDataTagKey`
|
|
|
|
:param id: GUID of the tag key
|
|
:type id: ``str``
|
|
|
|
:param name: Name of the tag key
|
|
:type name: ``str``
|
|
|
|
:param description: Description of the tag key
|
|
:type description: ``str``
|
|
|
|
:param value_required: If a value is required for this tag key
|
|
:type value_required: ``bool``
|
|
|
|
:param display_on_report: If this tag key should be displayed on
|
|
usage reports
|
|
:type display_on_report: ``bool``
|
|
"""
|
|
self.id = id
|
|
self.name = name
|
|
self.description = description
|
|
self.value_required = value_required
|
|
self.display_on_report = display_on_report
|
|
|
|
def __repr__(self):
|
|
return (('<DimensionDataTagKey: name=%s>')
|
|
% (self.name))
|
|
|
|
|
|
class DimensionDataIpAddressList(object):
|
|
"""
|
|
DimensionData IP Address list
|
|
"""
|
|
|
|
def __init__(self, id, name, description, ip_version,
|
|
ip_address_collection,
|
|
state, create_time, child_ip_address_lists=None):
|
|
""""
|
|
Initialize an instance of :class:`DimensionDataIpAddressList`
|
|
|
|
:param id: GUID of the IP Address List key
|
|
:type id: ``str``
|
|
|
|
:param name: Name of the IP Address List
|
|
:type name: ``str``
|
|
|
|
:param description: Description of the IP Address List
|
|
:type description: ``str``
|
|
|
|
:param ip_version: IP version. E.g. IPV4, IPV6
|
|
:type ip_version: ``str``
|
|
|
|
:param ip_address_collection: Collection of DimensionDataIpAddress
|
|
:type ip_address_collection: ``List``
|
|
|
|
:param state: IP Address list state
|
|
:type state: ``str``
|
|
|
|
:param create_time: IP Address List created time
|
|
:type create_time: ``date time``
|
|
|
|
:param child_ip_address_lists: List of IP address list to be included
|
|
:type child_ip_address_lists: List \
|
|
of :class:'DimensionDataIpAddressList'
|
|
"""
|
|
self.id = id
|
|
self.name = name
|
|
self.description = description
|
|
self.ip_version = ip_version
|
|
self.ip_address_collection = ip_address_collection
|
|
self.state = state
|
|
self.create_time = create_time
|
|
self.child_ip_address_lists = child_ip_address_lists
|
|
|
|
def __repr__(self):
|
|
return ('<DimensionDataIpAddressList: id=%s, name=%s, description=%s, '
|
|
'ip_version=%s, ip_address_collection=%s, state=%s, '
|
|
'create_time=%s, child_ip_address_lists=%s>'
|
|
% (self.id, self.name, self.description, self.ip_version,
|
|
self.ip_address_collection, self.state, self.create_time,
|
|
self.child_ip_address_lists))
|
|
|
|
|
|
class DimensionDataChildIpAddressList(object):
|
|
"""
|
|
DimensionData Child IP Address list
|
|
"""
|
|
|
|
def __init__(self, id, name):
|
|
""""
|
|
Initialize an instance of :class:`DimensionDataChildIpAddressList`
|
|
|
|
:param id: GUID of the IP Address List key
|
|
:type id: ``str``
|
|
|
|
:param name: Name of the IP Address List
|
|
:type name: ``str``
|
|
|
|
"""
|
|
self.id = id
|
|
self.name = name
|
|
|
|
def __repr__(self):
|
|
return ('<DimensionDataChildIpAddressList: id=%s, name=%s>'
|
|
% (self.id, self.name))
|
|
|
|
|
|
class DimensionDataIpAddress(object):
|
|
"""
|
|
A representation of IP Address in Dimension Data
|
|
"""
|
|
|
|
def __init__(self, begin, end=None, prefix_size=None):
|
|
"""
|
|
Initialize an instance of :class:`DimensionDataIpAddress`
|
|
|
|
:param begin: IP Address Begin
|
|
:type begin: ``str``
|
|
|
|
:param end: IP Address end
|
|
:type end: ``str``
|
|
|
|
:param prefixSize: IP Address prefix size
|
|
:type prefixSize: ``int``
|
|
"""
|
|
self.begin = begin
|
|
self.end = end
|
|
self.prefix_size = prefix_size
|
|
|
|
def __repr__(self):
|
|
return ('<DimensionDataIpAddress: begin=%s, end=%s, prefix_size=%s>'
|
|
% (self.begin, self.end, self.prefix_size))
|
|
|
|
|
|
class DimensionDataPortList(object):
|
|
"""
|
|
DimensionData Port list
|
|
"""
|
|
|
|
def __init__(self, id, name, description, port_collection,
|
|
child_portlist_list,
|
|
state, create_time):
|
|
""""
|
|
Initialize an instance of :class:`DimensionDataPortList`
|
|
|
|
:param id: GUID of the Port List key
|
|
:type id: ``str``
|
|
|
|
:param name: Name of the Port List
|
|
:type name: ``str``
|
|
|
|
:param description: Description of the Port List
|
|
:type description: ``str``
|
|
|
|
:param port_collection: Collection of DimensionDataPort
|
|
:type port_collection: ``List``
|
|
|
|
:param child_portlist_list: Collection of DimensionDataChildPort
|
|
:type child_portlist_list: ``List``
|
|
|
|
:param state: Port list state
|
|
:type state: ``str``
|
|
|
|
:param create_time: Port List created time
|
|
:type create_time: ``date time``
|
|
"""
|
|
self.id = id
|
|
self.name = name
|
|
self.description = description
|
|
self.port_collection = port_collection
|
|
self.child_portlist_list = child_portlist_list
|
|
self.state = state
|
|
self.create_time = create_time
|
|
|
|
def __repr__(self):
|
|
return (
|
|
"<DimensionDataPortList: id=%s, name=%s, description=%s, "
|
|
"port_collection=%s, child_portlist_list=%s, state=%s, "
|
|
"create_time=%s>"
|
|
% (self.id, self.name, self.description,
|
|
self.port_collection, self.child_portlist_list, self.state,
|
|
self.create_time))
|
|
|
|
|
|
class DimensionDataChildPortList(object):
|
|
"""
|
|
DimensionData Child Port list
|
|
"""
|
|
|
|
def __init__(self, id, name):
|
|
""""
|
|
Initialize an instance of :class:`DimensionDataChildIpAddressList`
|
|
|
|
:param id: GUID of the child port list key
|
|
:type id: ``str``
|
|
|
|
:param name: Name of the child port List
|
|
:type name: ``str``
|
|
|
|
"""
|
|
self.id = id
|
|
self.name = name
|
|
|
|
def __repr__(self):
|
|
return ('<DimensionDataChildPortList: id=%s, name=%s>'
|
|
% (self.id, self.name))
|
|
|
|
|
|
class DimensionDataPort(object):
|
|
"""
|
|
A representation of Port in Dimension Data
|
|
"""
|
|
|
|
def __init__(self, begin, end=None):
|
|
"""
|
|
Initialize an instance of :class:`DimensionDataPort`
|
|
|
|
:param begin: Port Number Begin
|
|
:type begin: ``str``
|
|
|
|
:param end: Port Number end
|
|
:type end: ``str``
|
|
"""
|
|
self.begin = begin
|
|
self.end = end
|
|
|
|
def __repr__(self):
|
|
return ('<DimensionDataPort: begin=%s, end=%s>'
|
|
% (self.begin, self.end))
|
|
|
|
|
|
class DimensionDataNic(object):
|
|
"""
|
|
A representation of Network Adapter in Dimension Data
|
|
"""
|
|
|
|
def __init__(self, private_ip_v4=None, vlan=None,
|
|
network_adapter_name=None):
|
|
"""
|
|
Initialize an instance of :class:`DimensionDataNic`
|
|
|
|
:param private_ip_v4: IPv4
|
|
:type private_ip_v4: ``str``
|
|
|
|
:param vlan: Network VLAN
|
|
:type vlan: class: DimensionDataVlan or ``str``
|
|
|
|
:param network_adapter_name: Network Adapter Name
|
|
:type network_adapter_name: ``str``
|
|
"""
|
|
self.private_ip_v4 = private_ip_v4
|
|
self.vlan = vlan
|
|
self.network_adapter_name = network_adapter_name
|
|
|
|
def __repr__(self):
|
|
return ('<DimensionDataNic: private_ip_v4=%s, vlan=%s,'
|
|
'network_adapter_name=%s>'
|
|
% (self.private_ip_v4, self.vlan, self.network_adapter_name))
|