You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@libcloud.apache.org by an...@apache.org on 2016/11/14 23:51:27 UTC
[40/56] [abbrv] libcloud git commit: Removed sdist
http://git-wip-us.apache.org/repos/asf/libcloud/blob/8afcda91/apache-libcloud-1.0.0rc2/libcloud/common/cloudstack.py
----------------------------------------------------------------------
diff --git a/apache-libcloud-1.0.0rc2/libcloud/common/cloudstack.py b/apache-libcloud-1.0.0rc2/libcloud/common/cloudstack.py
deleted file mode 100644
index c40ed0f..0000000
--- a/apache-libcloud-1.0.0rc2/libcloud/common/cloudstack.py
+++ /dev/null
@@ -1,199 +0,0 @@
-# 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.
-
-import base64
-import hashlib
-import copy
-import hmac
-
-from libcloud.utils.py3 import httplib
-from libcloud.utils.py3 import urlencode
-from libcloud.utils.py3 import urlquote
-from libcloud.utils.py3 import b
-
-from libcloud.common.types import ProviderError
-from libcloud.common.base import ConnectionUserAndKey, PollingConnection
-from libcloud.common.base import JsonResponse
-from libcloud.common.types import MalformedResponseError
-from libcloud.compute.types import InvalidCredsError
-
-
-class CloudStackResponse(JsonResponse):
- def parse_error(self):
- if self.status == httplib.UNAUTHORIZED:
- raise InvalidCredsError('Invalid provider credentials')
-
- value = None
- body = self.parse_body()
- if hasattr(body, 'values'):
- values = list(body.values())[0]
- if 'errortext' in values:
- value = values['errortext']
- if value is None:
- value = self.body
-
- if not value:
- value = 'WARNING: error message text sent by provider was empty.'
-
- error = ProviderError(value=value, http_code=self.status,
- driver=self.connection.driver)
- raise error
-
-
-class CloudStackConnection(ConnectionUserAndKey, PollingConnection):
- responseCls = CloudStackResponse
- poll_interval = 1
- request_method = '_sync_request'
- timeout = 600
-
- ASYNC_PENDING = 0
- ASYNC_SUCCESS = 1
- ASYNC_FAILURE = 2
-
- def encode_data(self, data):
- """
- Must of the data is sent as part of query params (eeww),
- but in newer versions, userdata argument can be sent as a
- urlencoded data in the request body.
- """
- if data:
- data = urlencode(data)
-
- return data
-
- def _make_signature(self, params):
- signature = [(k.lower(), v) for k, v in list(params.items())]
- signature.sort(key=lambda x: x[0])
-
- pairs = []
- for pair in signature:
- key = urlquote(str(pair[0]), safe='[]')
- value = urlquote(str(pair[1]), safe='[]')
- item = '%s=%s' % (key, value)
- pairs .append(item)
-
- signature = '&'.join(pairs)
-
- signature = signature.lower().replace('+', '%20')
- signature = hmac.new(b(self.key), msg=b(signature),
- digestmod=hashlib.sha1)
- return base64.b64encode(b(signature.digest()))
-
- def add_default_params(self, params):
- params['apiKey'] = self.user_id
- params['response'] = 'json'
-
- return params
-
- def pre_connect_hook(self, params, headers):
- params['signature'] = self._make_signature(params)
-
- return params, headers
-
- def _async_request(self, command, action=None, params=None, data=None,
- headers=None, method='GET', context=None):
- if params:
- context = copy.deepcopy(params)
- else:
- context = {}
-
- # Command is specified as part of GET call
- context['command'] = command
- result = super(CloudStackConnection, self).async_request(
- action=action, params=params, data=data, headers=headers,
- method=method, context=context)
- return result['jobresult']
-
- def get_request_kwargs(self, action, params=None, data='', headers=None,
- method='GET', context=None):
- command = context['command']
- request_kwargs = {'command': command, 'action': action,
- 'params': params, 'data': data,
- 'headers': headers, 'method': method}
- return request_kwargs
-
- def get_poll_request_kwargs(self, response, context, request_kwargs):
- job_id = response['jobid']
- params = {'jobid': job_id}
- kwargs = {'command': 'queryAsyncJobResult', 'params': params}
- return kwargs
-
- def has_completed(self, response):
- status = response.get('jobstatus', self.ASYNC_PENDING)
-
- if status == self.ASYNC_FAILURE:
- msg = response.get('jobresult', {}).get('errortext', status)
- raise Exception(msg)
-
- return status == self.ASYNC_SUCCESS
-
- def _sync_request(self, command, action=None, params=None, data=None,
- headers=None, method='GET'):
- """
- This method handles synchronous calls which are generally fast
- information retrieval requests and thus return 'quickly'.
- """
- # command is always sent as part of "command" query parameter
- if params:
- params = copy.deepcopy(params)
- else:
- params = {}
-
- params['command'] = command
- result = self.request(action=self.driver.path, params=params,
- data=data, headers=headers, method=method)
-
- command = command.lower()
-
- # Work around for older verions which don't return "response" suffix
- # in delete ingress rule response command name
- if (command == 'revokesecuritygroupingress' and
- 'revokesecuritygroupingressresponse' not in result.object):
- command = command
- else:
- command = command + 'response'
-
- if command not in result.object:
- raise MalformedResponseError(
- "Unknown response format",
- body=result.body,
- driver=self.driver)
- result = result.object[command]
- return result
-
-
-class CloudStackDriverMixIn(object):
- host = None
- path = None
-
- connectionCls = CloudStackConnection
-
- def __init__(self, key, secret=None, secure=True, host=None, port=None):
- host = host or self.host
- super(CloudStackDriverMixIn, self).__init__(key, secret, secure, host,
- port)
-
- def _sync_request(self, command, action=None, params=None, data=None,
- headers=None, method='GET'):
- return self.connection._sync_request(command=command, action=action,
- params=params, data=data,
- headers=headers, method=method)
-
- def _async_request(self, command, action=None, params=None, data=None,
- headers=None, method='GET', context=None):
- return self.connection._async_request(command=command, action=action,
- params=params, data=data,
- headers=headers, method=method,
- context=context)
http://git-wip-us.apache.org/repos/asf/libcloud/blob/8afcda91/apache-libcloud-1.0.0rc2/libcloud/common/digitalocean.py
----------------------------------------------------------------------
diff --git a/apache-libcloud-1.0.0rc2/libcloud/common/digitalocean.py b/apache-libcloud-1.0.0rc2/libcloud/common/digitalocean.py
deleted file mode 100644
index 2e6f329..0000000
--- a/apache-libcloud-1.0.0rc2/libcloud/common/digitalocean.py
+++ /dev/null
@@ -1,250 +0,0 @@
-# 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.
-
-"""
-Common settings and connection objects for DigitalOcean Cloud
-"""
-import warnings
-
-from libcloud.utils.py3 import httplib, parse_qs, urlparse
-
-from libcloud.common.base import BaseDriver
-from libcloud.common.base import ConnectionUserAndKey, ConnectionKey
-from libcloud.common.base import JsonResponse
-from libcloud.common.types import InvalidCredsError
-
-__all__ = [
- 'DigitalOcean_v1_Response',
- 'DigitalOcean_v1_Connection',
- 'DigitalOcean_v2_Response',
- 'DigitalOcean_v2_Connection',
- 'DigitalOceanBaseDriver'
-]
-
-
-class DigitalOcean_v1_Response(JsonResponse):
- def parse_error(self):
- if self.status == httplib.FOUND and '/api/error' in self.body:
- # Hacky, but DigitalOcean error responses are awful
- raise InvalidCredsError(self.body)
- elif self.status == httplib.UNAUTHORIZED:
- body = self.parse_body()
- raise InvalidCredsError(body['message'])
- else:
- body = self.parse_body()
-
- if 'error_message' in body:
- error = '%s (code: %s)' % (body['error_message'], self.status)
- else:
- error = body
- return error
-
-
-class DigitalOcean_v1_Connection(ConnectionUserAndKey):
- """
- Connection class for the DigitalOcean (v1) driver.
- """
-
- host = 'api.digitalocean.com'
- responseCls = DigitalOcean_v1_Response
-
- def add_default_params(self, params):
- """
- Add parameters that are necessary for every request
-
- This method adds ``client_id`` and ``api_key`` to
- the request.
- """
- params['client_id'] = self.user_id
- params['api_key'] = self.key
- return params
-
-
-class DigitalOcean_v2_Response(JsonResponse):
- valid_response_codes = [httplib.OK, httplib.ACCEPTED, httplib.CREATED,
- httplib.NO_CONTENT]
-
- def parse_error(self):
- if self.status == httplib.UNAUTHORIZED:
- body = self.parse_body()
- raise InvalidCredsError(body['message'])
- else:
- body = self.parse_body()
- if 'message' in body:
- error = '%s (code: %s)' % (body['message'], self.status)
- else:
- error = body
- return error
-
- def success(self):
- return self.status in self.valid_response_codes
-
-
-class DigitalOcean_v2_Connection(ConnectionKey):
- """
- Connection class for the DigitalOcean (v2) driver.
- """
-
- host = 'api.digitalocean.com'
- responseCls = DigitalOcean_v2_Response
-
- def add_default_headers(self, headers):
- """
- Add headers that are necessary for every request
-
- This method adds ``token`` to the request.
- """
- headers['Authorization'] = 'Bearer %s' % (self.key)
- headers['Content-Type'] = 'application/json'
- return headers
-
- def add_default_params(self, params):
- """
- Add parameters that are necessary for every request
-
- This method adds ``per_page`` to the request to reduce the total
- number of paginated requests to the API.
- """
- params['per_page'] = self.driver.ex_per_page
- return params
-
-
-class DigitalOceanConnection(DigitalOcean_v2_Connection):
- """
- Connection class for the DigitalOcean driver.
- """
- pass
-
-
-class DigitalOceanResponse(DigitalOcean_v2_Response):
- pass
-
-
-class DigitalOceanBaseDriver(BaseDriver):
- """
- DigitalOcean BaseDriver
- """
- name = 'DigitalOcean'
- website = 'https://www.digitalocean.com'
-
- def __new__(cls, key, secret=None, api_version='v2', **kwargs):
- if cls is DigitalOceanBaseDriver:
- if api_version == 'v1' or secret is not None:
- cls = DigitalOcean_v1_BaseDriver
- warnings.warn("The v1 API has become deprecated. Please "
- "consider utilizing the v2 API.")
- elif api_version == 'v2':
- cls = DigitalOcean_v2_BaseDriver
- else:
- raise NotImplementedError('Unsupported API version: %s' %
- (api_version))
- return super(DigitalOceanBaseDriver, cls).__new__(cls, **kwargs)
-
- def ex_account_info(self):
- raise NotImplementedError(
- 'ex_account_info not implemented for this driver')
-
- def ex_list_events(self):
- raise NotImplementedError(
- 'ex_list_events not implemented for this driver')
-
- def ex_get_event(self, event_id):
- raise NotImplementedError(
- 'ex_get_event not implemented for this driver')
-
- def _paginated_request(self, url, obj):
- raise NotImplementedError(
- '_paginated_requests not implemented for this driver')
-
-
-class DigitalOcean_v1_BaseDriver(DigitalOceanBaseDriver):
- """
- DigitalOcean BaseDriver using v1 of the API.
- """
- connectionCls = DigitalOcean_v1_Connection
-
- def ex_get_event(self, event_id):
- """
- Get an event object
-
- :param event_id: Event id (required)
- :type event_id: ``str``
- """
- return self.connection.request('/v1/events/%s' % event_id).object
-
-
-class DigitalOcean_v2_BaseDriver(DigitalOceanBaseDriver):
- """
- DigitalOcean BaseDriver using v2 of the API.
-
- Supports `ex_per_page` ``int`` value keyword parameter to adjust per page
- requests against the API.
- """
- connectionCls = DigitalOcean_v2_Connection
-
- def __init__(self, key, secret=None, secure=True, host=None, port=None,
- api_version=None, region=None, ex_per_page=200, **kwargs):
- self.ex_per_page = ex_per_page
- super(DigitalOcean_v2_BaseDriver, self).__init__(key, **kwargs)
-
- def ex_account_info(self):
- return self.connection.request('/v2/account').object['account']
-
- def ex_list_events(self):
- return self._paginated_request('/v2/actions', 'actions')
-
- def ex_get_event(self, event_id):
- """
- Get an event object
-
- :param event_id: Event id (required)
- :type event_id: ``str``
- """
- params = {}
- return self.connection.request('/v2/actions/%s' % event_id,
- params=params).object['action']
-
- def _paginated_request(self, url, obj):
- """
- Perform multiple calls in order to have a full list of elements when
- the API responses are paginated.
-
- :param url: API endpoint
- :type url: ``str``
-
- :param obj: Result object key
- :type obj: ``str``
-
- :return: ``list`` of API response objects
- :rtype: ``list``
- """
- params = {}
- data = self.connection.request(url)
- try:
- query = urlparse.urlparse(data.object['links']['pages']['last'])
- # The query[4] references the query parameters from the url
- pages = parse_qs(query[4])['page'][0]
- values = data.object[obj]
- for page in range(2, int(pages) + 1):
- params.update({'page': page})
- new_data = self.connection.request(url, params=params)
-
- more_values = new_data.object[obj]
- for value in more_values:
- values.append(value)
- data = values
- except KeyError: # No pages.
- data = data.object[obj]
- return data
http://git-wip-us.apache.org/repos/asf/libcloud/blob/8afcda91/apache-libcloud-1.0.0rc2/libcloud/common/dimensiondata.py
----------------------------------------------------------------------
diff --git a/apache-libcloud-1.0.0rc2/libcloud/common/dimensiondata.py b/apache-libcloud-1.0.0rc2/libcloud/common/dimensiondata.py
deleted file mode 100644
index 40319a2..0000000
--- a/apache-libcloud-1.0.0rc2/libcloud/common/dimensiondata.py
+++ /dev/null
@@ -1,1406 +0,0 @@
-# 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
-from libcloud.utils.py3 import httplib
-from libcloud.utils.py3 import b
-from libcloud.common.base import ConnectionUserAndKey, XmlResponse
-from libcloud.common.types import LibcloudError, InvalidCredsError
-from libcloud.compute.base import Node
-from libcloud.utils.py3 import basestring
-from libcloud.utils.xml import findtext
-
-# 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__)
- )
-
-
-class NetworkDomainServicePlan(object):
- ESSENTIALS = "ESSENTIALS"
- ADVANCED = "ADVANCED"
-
-
-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'
- api_version_2 = '2.1'
-
- _orgId = None
- responseCls = DimensionDataResponse
-
- allow_insecure = False
-
- def __init__(self, user_id, key, secure=True, host=None, port=None,
- url=None, timeout=None, proxy_url=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']
-
- 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.api_version_2, path, action)
-
- return super(DimensionDataConnection, self).request(
- action=action,
- params=params, data=data,
- method=method, headers=headers)
-
- 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
-
- paged_resp = self.request_with_orgId_api_2(action, params,
- data, headers,
- method).object
- yield paged_resp
-
- while paged_resp.get('pageCount') >= paged_resp.get('pageSize'):
- params['pageNumber'] = int(paged_resp.get('pageNumber')) + 1
- paged_resp = self.request_with_orgId_api_2(action, params,
- data, headers,
- method).object
- yield paged_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.api_version_2,
- 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
- 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 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>')
- % (self.id, self.name, self.description, self.location,
- self.status))
-
-
-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, scsi_id, size_gb, speed, state):
- """
- 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):
- self.any_ip = any_ip
- self.ip_address = ip_address
- self.ip_prefix_size = ip_prefix_size
- self.port_begin = port_begin
- self.port_end = port_end
-
-
-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))
http://git-wip-us.apache.org/repos/asf/libcloud/blob/8afcda91/apache-libcloud-1.0.0rc2/libcloud/common/dnsimple.py
----------------------------------------------------------------------
diff --git a/apache-libcloud-1.0.0rc2/libcloud/common/dnsimple.py b/apache-libcloud-1.0.0rc2/libcloud/common/dnsimple.py
deleted file mode 100644
index 6a5da41..0000000
--- a/apache-libcloud-1.0.0rc2/libcloud/common/dnsimple.py
+++ /dev/null
@@ -1,53 +0,0 @@
-# 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.
-
-from libcloud.utils.py3 import httplib
-from libcloud.common.base import ConnectionUserAndKey
-from libcloud.common.base import JsonResponse
-
-
-class DNSimpleDNSResponse(JsonResponse):
-
- def success(self):
- """
- Determine if our request was successful.
-
- The meaning of this can be arbitrary; did we receive OK status? Did
- the node get created? Were we authenticated?
-
- :rtype: ``bool``
- :return: ``True`` or ``False``
- """
- # response.success() only checks for 200 and 201 codes. Should we
- # add 204?
- return self.status in [httplib.OK, httplib.CREATED, httplib.NO_CONTENT]
-
-
-class DNSimpleDNSConnection(ConnectionUserAndKey):
- host = 'api.dnsimple.com'
- responseCls = DNSimpleDNSResponse
-
- def add_default_headers(self, headers):
- """
- Add headers that are necessary for every request
-
- This method adds ``token`` to the request.
- """
- # TODO: fijarse sobre que info se paso como parametro y en base
- # a esto, fijar el header
- headers['X-DNSimple-Token'] = '%s:%s' % (self.user_id, self.key)
- headers['Accept'] = 'application/json'
- headers['Content-Type'] = 'application/json'
- return headers
http://git-wip-us.apache.org/repos/asf/libcloud/blob/8afcda91/apache-libcloud-1.0.0rc2/libcloud/common/durabledns.py
----------------------------------------------------------------------
diff --git a/apache-libcloud-1.0.0rc2/libcloud/common/durabledns.py b/apache-libcloud-1.0.0rc2/libcloud/common/durabledns.py
deleted file mode 100644
index 5859f6e..0000000
--- a/apache-libcloud-1.0.0rc2/libcloud/common/durabledns.py
+++ /dev/null
@@ -1,285 +0,0 @@
-# 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.
-
-import re
-from xml.etree import ElementTree as ET # noqa
-
-from libcloud.common.base import ConnectionUserAndKey
-from libcloud.common.base import XmlResponse
-
-
-# API HOST to connect
-API_HOST = 'durabledns.com'
-
-
-def _schema_builder(urn_nid, method, attributes):
- """
- Return a xml schema used to do an API request.
-
- :param urn_nid: API urn namespace id.
- :type urn_nid: type: ``str``
-
- :param method: API method.
- :type method: type: ``str``
-
- :param attributes: List of attributes to include.
- :type attributes: ``list`` of ``str``
-
- rtype: :class:`Element`
- """
- soap = ET.Element(
- 'soap:Body',
- {'xmlns:m': "https://durabledns.com/services/dns/%s" % method}
- )
- urn = ET.SubElement(soap, 'urn:%s:%s' % (urn_nid, method))
- # Attributes specification
- for attribute in attributes:
- ET.SubElement(urn, 'urn:%s:%s' % (urn_nid, attribute))
- return soap
-
-
-SCHEMA_BUILDER_MAP = {
- 'list_zones': {
- 'urn_nid': 'listZoneswsdl',
- 'method': 'listZones',
- 'attributes': ['apiuser', 'apikey']
- },
- 'list_records': {
- 'urn_nid': 'listRecordswsdl',
- 'method': 'listRecords',
- 'attributes': ['apiuser', 'apikey', 'zonename']
- },
- 'get_zone': {
- 'urn_nid': 'getZonewsdl',
- 'method': 'getZone',
- 'attributes': ['apiuser', 'apikey', 'zonename']
- },
- 'get_record': {
- 'urn_nid': 'getRecordwsdl',
- 'method': 'getRecord',
- 'attributes': ['apiuser', 'apikey', 'zonename', 'recordid']
- },
- 'create_zone': {
- 'urn_nid': 'createZonewsdl',
- 'method': 'createZone',
- 'attributes': ['apiuser', 'apikey', 'zonename', 'ns', 'mbox',
- 'refresh', 'retry', 'expire', 'minimum', 'ttl',
- 'xfer', 'update_acl']
- },
- 'create_record': {
- 'urn_nid': 'createRecordwsdl',
- 'method': 'createRecord',
- 'attributes': ['apiuser', 'apikey', 'zonename', 'name', 'type',
- 'data', 'aux', 'ttl', 'ddns_enabled']
- },
- 'update_zone': {
- 'urn_nid': 'updateZonewsdl',
- 'method': 'updateZone',
- 'attributes': ['apiuser', 'apikey', 'zonename', 'ns', 'mbox',
- 'refresh', 'retry', 'expire', 'minimum', 'ttl',
- 'xfer', 'update_acl']
- },
- 'update_record': {
- 'urn_nid': 'updateRecordwsdl',
- 'method': 'updateRecord',
- 'attributes': ['apiuser', 'apikey', 'zonename', 'id', 'name', 'aux',
- 'data', 'ttl', 'ddns_enabled']
- },
- 'delete_zone': {
- 'urn_nid': 'deleteZonewsdl',
- 'method': 'deleteZone',
- 'attributes': ['apiuser', 'apikey', 'zonename']
- },
- 'delete_record': {
- 'urn_nid': 'deleteRecordwsdl',
- 'method': 'deleteRecord',
- 'attributes': ['apiuser', 'apikey', 'zonename', 'id']
- }
-}
-
-
-class DurableDNSException(Exception):
-
- def __init__(self, code, message):
- self.code = code
- self.message = message
- self.args = (code, message)
-
- def __str__(self):
- return "%s %s" % (self.code, self.message)
-
- def __repr__(self):
- return "DurableDNSException %s %s" % (self.code, self.message)
-
-
-class DurableResponse(XmlResponse):
-
- errors = []
- objects = []
-
- def __init__(self, response, connection):
- super(DurableResponse, self).__init__(response=response,
- connection=connection)
-
- self.objects, self.errors = self.parse_body_and_error()
- if self.errors:
- raise self._make_excp(self.errors[0])
-
- def parse_body_and_error(self):
- """
- Used to parse body from httplib.HttpResponse object.
- """
- objects = []
- errors = []
- error_dict = {}
- extra = {}
- zone_dict = {}
- record_dict = {}
- xml_obj = self.parse_body()
- envelop_body = xml_obj.getchildren()[0]
- method_resp = envelop_body.getchildren()[0]
- # parse the xml_obj
- # handle errors
- if 'Fault' in method_resp.tag:
- fault = [fault for fault in method_resp.getchildren()
- if fault.tag == 'faultstring'][0]
- error_dict['ERRORMESSAGE'] = fault.text.strip()
- error_dict['ERRORCODE'] = self.status
- errors.append(error_dict)
-
- # parsing response from listZonesResponse
- if 'listZonesResponse' in method_resp.tag:
- answer = method_resp.getchildren()[0]
- for element in answer:
- zone_dict['id'] = element.getchildren()[0].text
- objects.append(zone_dict)
- # reset the zone_dict
- zone_dict = {}
- # parse response from listRecordsResponse
- if 'listRecordsResponse' in method_resp.tag:
- answer = method_resp.getchildren()[0]
- for element in answer:
- for child in element.getchildren():
- if child.tag == 'id':
- record_dict['id'] = child.text.strip()
- objects.append(record_dict)
- # reset the record_dict for later usage
- record_dict = {}
- # parse response from getZoneResponse
- if 'getZoneResponse' in method_resp.tag:
- for child in method_resp.getchildren():
- if child.tag == 'origin':
- zone_dict['id'] = child.text.strip()
- zone_dict['domain'] = child.text.strip()
- elif child.tag == 'ttl':
- zone_dict['ttl'] = int(child.text.strip())
- elif child.tag == 'retry':
- extra['retry'] = int(child.text.strip())
- elif child.tag == 'expire':
- extra['expire'] = int(child.text.strip())
- elif child.tag == 'minimum':
- extra['minimum'] = int(child.text.strip())
- else:
- if child.text:
- extra[child.tag] = child.text.strip()
- else:
- extra[child.tag] = ''
- zone_dict['extra'] = extra
- objects.append(zone_dict)
- # parse response from getRecordResponse
- if 'getRecordResponse' in method_resp.tag:
- answer = method_resp.getchildren()[0]
- for child in method_resp.getchildren():
- if child.tag == 'id' and child.text:
- record_dict['id'] = child.text.strip()
- elif child.tag == 'name' and child.text:
- record_dict['name'] = child.text.strip()
- elif child.tag == 'type' and child.text:
- record_dict['type'] = child.text.strip()
- elif child.tag == 'data' and child.text:
- record_dict['data'] = child.text.strip()
- elif child.tag == 'aux' and child.text:
- record_dict['aux'] = child.text.strip()
- elif child.tag == 'ttl' and child.text:
- record_dict['ttl'] = child.text.strip()
- if not record_dict:
- error_dict['ERRORMESSAGE'] = 'Record does not exist'
- error_dict['ERRORCODE'] = 404
- errors.append(error_dict)
- objects.append(record_dict)
- record_dict = {}
- if 'createZoneResponse' in method_resp.tag:
- answer = method_resp.getchildren()[0]
- if answer.tag == 'return' and answer.text:
- record_dict['id'] = answer.text.strip()
- objects.append(record_dict)
- # catch Record does not exists error when deleting record
- if 'deleteRecordResponse' in method_resp.tag:
- answer = method_resp.getchildren()[0]
- if 'Record does not exists' in answer.text.strip():
- errors.append({'ERRORMESSAGE': answer.text.strip(),
- 'ERRORCODE': self.status})
- # parse response in createRecordResponse
- if 'createRecordResponse' in method_resp.tag:
- answer = method_resp.getchildren()[0]
- record_dict['id'] = answer.text.strip()
- objects.append(record_dict)
- record_dict = {}
-
- return (objects, errors)
-
- def parse_body(self):
- # A problem arise in the api response because there are undeclared
- # xml namespaces. In order to fix that at the moment, we use the
- # _fix_response method to clean up since we won't always have lxml
- # library.
- self._fix_response()
- body = super(DurableResponse, self).parse_body()
- return body
-
- def success(self):
- """
- Used to determine if the request was successful.
- """
- return len(self.errors) == 0
-
- def _make_excp(self, error):
- return DurableDNSException(error['ERRORCODE'], error['ERRORMESSAGE'])
-
- def _fix_response(self):
- items = re.findall('<ns1:.+ xmlns:ns1="">', self.body, flags=0)
- for item in items:
- parts = item.split(' ')
- prefix = parts[0].replace('<', '').split(':')[1]
- new_item = "<" + prefix + ">"
- close_tag = "</" + parts[0].replace('<', '') + ">"
- new_close_tag = "</" + prefix + ">"
- self.body = self.body.replace(item, new_item)
- self.body = self.body.replace(close_tag, new_close_tag)
-
-
-class DurableConnection(ConnectionUserAndKey):
- host = API_HOST
- responseCls = DurableResponse
-
- def add_default_params(self, params):
- params['user_id'] = self.user_id
- params['key'] = self.key
- return params
-
- def add_default_headers(self, headers):
- headers['Content-Type'] = 'text/xml'
- headers['Content-Encoding'] = 'gzip; charset=ISO-8859-1'
- return headers
http://git-wip-us.apache.org/repos/asf/libcloud/blob/8afcda91/apache-libcloud-1.0.0rc2/libcloud/common/exceptions.py
----------------------------------------------------------------------
diff --git a/apache-libcloud-1.0.0rc2/libcloud/common/exceptions.py b/apache-libcloud-1.0.0rc2/libcloud/common/exceptions.py
deleted file mode 100644
index 14dcea8..0000000
--- a/apache-libcloud-1.0.0rc2/libcloud/common/exceptions.py
+++ /dev/null
@@ -1,75 +0,0 @@
-# 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.
-
-__all__ = [
- 'BaseHTTPError',
- 'RateLimitReachedError',
-
- 'exception_from_message'
-]
-
-
-class BaseHTTPError(Exception):
-
- """
- The base exception class for all HTTP related exceptions.
- """
-
- def __init__(self, code, message, headers=None):
- self.code = code
- self.message = message
- self.headers = headers
- # preserve old exception behavior for tests that
- # look for e.args[0]
- super(BaseHTTPError, self).__init__(message)
-
- def __str__(self):
- return self.message
-
-
-class RateLimitReachedError(BaseHTTPError):
- """
- HTTP 429 - Rate limit: you've sent too many requests for this time period.
- """
- code = 429
- message = '%s Rate limit exceeded' % (code)
-
- def __init__(self, *args, **kwargs):
- self.retry_after = int(kwargs.pop('retry_after', 0))
-
-
-_error_classes = [RateLimitReachedError]
-_code_map = dict((c.code, c) for c in _error_classes)
-
-
-def exception_from_message(code, message, headers=None):
- """
- Return an instance of BaseHTTPException or subclass based on response code.
-
- Usage::
- raise exception_from_message(code=self.status,
- message=self.parse_error())
- """
- kwargs = {
- 'code': code,
- 'message': message,
- 'headers': headers
- }
-
- if headers and 'retry_after' in headers:
- kwargs['retry_after'] = headers['retry_after']
-
- cls = _code_map.get(code, BaseHTTPError)
- return cls(**kwargs)
http://git-wip-us.apache.org/repos/asf/libcloud/blob/8afcda91/apache-libcloud-1.0.0rc2/libcloud/common/gandi.py
----------------------------------------------------------------------
diff --git a/apache-libcloud-1.0.0rc2/libcloud/common/gandi.py b/apache-libcloud-1.0.0rc2/libcloud/common/gandi.py
deleted file mode 100644
index be326f3..0000000
--- a/apache-libcloud-1.0.0rc2/libcloud/common/gandi.py
+++ /dev/null
@@ -1,194 +0,0 @@
-# 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.
-"""
-Gandi driver base classes
-"""
-
-import time
-import hashlib
-import sys
-
-from libcloud.utils.py3 import b
-
-from libcloud.common.base import ConnectionKey
-from libcloud.common.xmlrpc import XMLRPCResponse, XMLRPCConnection
-
-# Global constants
-
-DEFAULT_TIMEOUT = 600 # operation pooling max seconds
-DEFAULT_INTERVAL = 20 # seconds between 2 operation.info
-
-
-class GandiException(Exception):
- """
- Exception class for Gandi driver
- """
- def __str__(self):
- return '(%u) %s' % (self.args[0], self.args[1])
-
- def __repr__(self):
- return '<GandiException code %u "%s">' % (self.args[0], self.args[1])
-
-
-class GandiResponse(XMLRPCResponse):
- """
- A Base Gandi Response class to derive from.
- """
-
-
-class GandiConnection(XMLRPCConnection, ConnectionKey):
- """
- Connection class for the Gandi driver
- """
-
- responseCls = GandiResponse
- host = 'rpc.gandi.net'
- endpoint = '/xmlrpc/'
-
- def __init__(self, key, secure=True, timeout=None,
- retry_delay=None, backoff=None, proxy_url=None):
- # Note: Method resolution order in this case is
- # XMLRPCConnection -> Connection and Connection doesn't take key as the
- # first argument so we specify a keyword argument instead.
- # Previously it was GandiConnection -> ConnectionKey so it worked fine.
- super(GandiConnection, self).__init__(key=key, secure=secure,
- timeout=timeout,
- retry_delay=retry_delay,
- backoff=backoff,
- proxy_url=proxy_url)
- self.driver = BaseGandiDriver
-
- def request(self, method, *args):
- args = (self.key, ) + args
- return super(GandiConnection, self).request(method, *args)
-
-
-class BaseGandiDriver(object):
- """
- Gandi base driver
-
- """
- connectionCls = GandiConnection
- name = 'Gandi'
-
- # Specific methods for gandi
- def _wait_operation(self, id, timeout=DEFAULT_TIMEOUT,
- check_interval=DEFAULT_INTERVAL):
- """ Wait for an operation to succeed"""
-
- for i in range(0, timeout, check_interval):
- try:
- op = self.connection.request('operation.info', int(id)).object
-
- if op['step'] == 'DONE':
- return True
- if op['step'] in ['ERROR', 'CANCEL']:
- return False
- except (KeyError, IndexError):
- pass
- except Exception:
- e = sys.exc_info()[1]
- raise GandiException(1002, e)
-
- time.sleep(check_interval)
- return False
-
-
-class BaseObject(object):
- """Base class for objects not conventional"""
-
- uuid_prefix = ''
-
- def __init__(self, id, state, driver):
- self.id = str(id) if id else None
- self.state = state
- self.driver = driver
- self.uuid = self.get_uuid()
-
- def get_uuid(self):
- """Unique hash for this object
-
- :return: ``str``
-
- The hash is a function of an SHA1 hash of prefix, the object's ID and
- its driver which means that it should be unique between all
- interfaces.
- TODO : to review
- >>> from libcloud.compute.drivers.dummy import DummyNodeDriver
- >>> driver = DummyNodeDriver(0)
- >>> vif = driver.create_interface()
- >>> vif.get_uuid()
- 'd3748461511d8b9b0e0bfa0d4d3383a619a2bb9f'
-
- Note, for example, that this example will always produce the
- same UUID!
- """
- hashstring = '%s:%s:%s' % \
- (self.uuid_prefix, self.id, self.driver.type)
- return hashlib.sha1(b(hashstring)).hexdigest()
-
-
-class IPAddress(BaseObject):
- """
- Provide a common interface for ip addresses
- """
-
- uuid_prefix = 'inet:'
-
- def __init__(self, id, state, inet, driver, version=4, extra=None):
- super(IPAddress, self).__init__(id, state, driver)
- self.inet = inet
- self.version = version
- self.extra = extra or {}
-
- def __repr__(self):
- return (('<IPAddress: id=%s, address=%s, state=%s, driver=%s ...>')
- % (self.id, self.inet, self.state, self.driver.name))
-
-
-class NetworkInterface(BaseObject):
- """
- Provide a common interface for network interfaces
- """
-
- uuid_prefix = 'if:'
-
- def __init__(self, id, state, mac_address, driver,
- ips=None, node_id=None, extra=None):
- super(NetworkInterface, self).__init__(id, state, driver)
- self.mac = mac_address
- self.ips = ips or {}
- self.node_id = node_id
- self.extra = extra or {}
-
- def __repr__(self):
- return (('<Interface: id=%s, mac=%s, state=%s, driver=%s ...>')
- % (self.id, self.mac, self.state, self.driver.name))
-
-
-class Disk(BaseObject):
- """
- Gandi disk component
- """
- def __init__(self, id, state, name, driver, size, extra=None):
- super(Disk, self).__init__(id, state, driver)
- self.name = name
- self.size = size
- self.extra = extra or {}
-
- def __repr__(self):
- return (
- ('<Disk: id=%s, name=%s, state=%s, size=%s, driver=%s ...>')
- % (self.id, self.name, self.state, self.size, self.driver.name))