[Python-modules-commits] [libcloud] 01/05: Imported Upstream version 1.5.0
Hans-Christoph Steiner
eighthave at moszumanska.debian.org
Fri Jan 6 22:18:52 UTC 2017
This is an automated email from the git hooks/post-receive script.
eighthave pushed a commit to branch master
in repository libcloud.
commit 3fcb2ab45e14dd0d59a847dd2a9f9147b031f762
Author: Hans-Christoph Steiner <hans at eds.org>
Date: Fri Jan 6 23:02:11 2017 +0100
Imported Upstream version 1.5.0
---
CHANGES.rst | 67 +
PKG-INFO | 2 +-
apache_libcloud.egg-info/PKG-INFO | 2 +-
apache_libcloud.egg-info/SOURCES.txt | 35 +-
libcloud/__init__.py | 2 +-
libcloud/common/dimensiondata.py | 56 +-
libcloud/common/openstack_identity.py | 140 +-
libcloud/compute/drivers/azure_arm.py | 34 +
libcloud/compute/drivers/cloudscale.py | 246 +
libcloud/compute/drivers/dimensiondata.py | 610 +-
libcloud/compute/drivers/ec2.py | 102 +-
libcloud/compute/drivers/ecs.py | 3 +
libcloud/compute/drivers/gce.py | 56 +-
libcloud/compute/providers.py | 2 +
libcloud/compute/types.py | 5 +
libcloud/container/drivers/rancher.py | 71 +-
libcloud/loadbalancer/drivers/gce.py | 5 +-
...dimensiondata.py => test_dimensiondata_v2_3.py} | 3 +-
...dimensiondata.py => test_dimensiondata_v2_4.py} | 17 +-
libcloud/test/common/test_openstack_identity.py | 47 +
...9999_providers_Microsoft_Commerce_RateCard.json | 84270 +++++++++++++++++++
.../compute/fixtures/cloudscale/create_node.json | 46 +
.../compute/fixtures/cloudscale/list_images.json | 1 +
.../compute/fixtures/cloudscale/list_nodes.json | 48 +
.../compute/fixtures/cloudscale/list_sizes.json | 2 +
.../2.4/change_nic_networkadapter_response.xml | 7 +
.../2.4/exchange_nic_vlans_response.xml | 8 +
.../dimensiondata/2.4/image_customerImage.xml | 57 +
...rImage_2ffa36c8_1848_49eb_b4fa_9d908775f68c.xml | 19 +
...rImage_5234e5c7_01de_4411_8b6e_baeb8d91cf5d.xml | 19 +
.../fixtures/dimensiondata/2.4/image_osImage.xml | 40 +
...sImage_6b4fb0c7_a57b_4f58_b59c_9958f94f971a.xml | 13 +
...sImage_c14b1a46_2428_44c1_9c1a_b20e6418d08c.xml | 14 +
.../dimensiondata/2.4/import_image_response.xml | 8 +
.../dimensiondata/2.4/server_GetServer.xml | 42 +
.../dimensiondata/2.4/server_cleanServer.xml | 9 +
.../dimensiondata/2.4/server_clone_response.xml | 9 +
.../fixtures/dimensiondata/2.4/server_server.xml | 192 +
.../dimensiondata/2.4/server_server_NA3.xml | 56 +
...server_e75ead52_692f_4314_8725_c8a4f4d13a87.xml | 30 +
.../dimensiondata/2.4/server_server_paginated.xml | 58 +
...x_describe_quota.xml => ex_describe_quotas.xml} | 4 +-
.../gce/projects_coreos-cloud_global_images.json | 3 +
...ntral1-b_instances_libcloud-lb-nopubip-001.json | 49 +
libcloud/test/compute/test_azure_arm.py | 9 +
libcloud/test/compute/test_cloudscale.py | 122 +
...dimensiondata.py => test_dimensiondata_v2_3.py} | 7 +-
...dimensiondata.py => test_dimensiondata_v2_4.py} | 326 +-
libcloud/test/compute/test_ec2.py | 22 +-
libcloud/test/compute/test_gce.py | 18 +-
libcloud/test/container/test_rancher.py | 218 +-
...dimensiondata.py => test_dimensiondata_v2_3.py} | 3 +-
...dimensiondata.py => test_dimensiondata_v2_4.py} | 47 +-
libcloud/test/loadbalancer/test_gce.py | 7 +
libcloud/test/secrets.py-dist | 3 +-
55 files changed, 86943 insertions(+), 348 deletions(-)
diff --git a/CHANGES.rst b/CHANGES.rst
index 8917d83..18df134 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -2,6 +2,69 @@
=========
+Changes in current version of Apache Libcloud
+---------------------------------------------
+
+Common
+~~~~~~
+
+- Set Dimension Data compute, backup and load balancer to default to 2.4 API
+ [GITHUB-961]
+ [Samuel Chong]
+
+Compute
+~~~~~~~
+
+- [azure] New method for accessing rate cards
+ [GITHUB-957]
+ (Soren L. Hansen)
+
+- [gce] Allow multiple preemptible instances to be created
+ [GITHUB-954]
+ (John Baublitz)
+
+- [openstack] Add new Connection class to support VOMS proxys to keystone servers
+ [GITHUB-959]
+ (micafer)
+
+- [outscale] Added support for changed API for describing quotas
+ [GITHUB-960]
+ (Javier M. Mellid)
+
+- [ec2] Added m4 instances to us-gov and brazil, added m4.16xlarge to all
+ [GITHUB-964]
+ (Matthew Tyas)
+
+- Added new CloudScale.ch driver
+
+- [google compute] Bug fix for ex_create_multiple_nodes Google Cloud disk auto delete
+ (GITHUB-955)
+ [John Baublitz]
+
+- [google compute] Add "MULTI_IP_SUBNET" guestOsFeatures option.
+ (GITHUB-956)
+ [Max Illfelder]
+
+- [dimensiondata] Added support for 2.4 API, added support for image import, cloning. Add feature for changing NIC VLANs, add feature for changing
+ NIC order for a server.
+ (GITHUB-953)
+ [Samuel Chong]
+
+- [ec2] Add US-EAST2 (Ohio)
+ (GITHUB-946)
+ [Matthew Harris]
+
+- [google compute] Fix to allow multiple node creation with subnets
+ (GITHUB-949)
+ [John Baublitz]
+
+Container
+~~~~~~~~~
+
+- [rancher] The scheme (secure) and port no longer need to be explicitly specified, allowing a user to simply copy in the string provided to them from Rancher.
+ [GITHUB-958]
+ (Matthew Ellison)
+
Changes in Apache Libcloud 1.4.0
--------------------------------
@@ -90,6 +153,10 @@ Load Balancing
(LIBCLOUD-869, GITHUB-936)
[Anton Kozyrev]
+- Fix bug where GCE Load balancer supposes that all VMs have public ips
+ (LIBCLOUD-879, GITHUB-952)
+ [Chris Walker]
+
Storage
~~~~~~~
diff --git a/PKG-INFO b/PKG-INFO
index 28d0d02..df9284a 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: apache-libcloud
-Version: 1.4.0
+Version: 1.5.0
Summary: A standard Python library that abstracts away differences among multiple cloud provider APIs. For more information and documentation, please see http://libcloud.apache.org
Home-page: http://libcloud.apache.org/
Author: Apache Software Foundation
diff --git a/apache_libcloud.egg-info/PKG-INFO b/apache_libcloud.egg-info/PKG-INFO
index 28d0d02..df9284a 100644
--- a/apache_libcloud.egg-info/PKG-INFO
+++ b/apache_libcloud.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: apache-libcloud
-Version: 1.4.0
+Version: 1.5.0
Summary: A standard Python library that abstracts away differences among multiple cloud provider APIs. For more information and documentation, please see http://libcloud.apache.org
Home-page: http://libcloud.apache.org/
Author: Apache Software Foundation
diff --git a/apache_libcloud.egg-info/SOURCES.txt b/apache_libcloud.egg-info/SOURCES.txt
index ec49ab4..0c576ce 100644
--- a/apache_libcloud.egg-info/SOURCES.txt
+++ b/apache_libcloud.egg-info/SOURCES.txt
@@ -92,6 +92,7 @@ libcloud/compute/drivers/azure_arm.py
libcloud/compute/drivers/bluebox.py
libcloud/compute/drivers/brightbox.py
libcloud/compute/drivers/bsnl.py
+libcloud/compute/drivers/cloudscale.py
libcloud/compute/drivers/cloudsigma.py
libcloud/compute/drivers/cloudstack.py
libcloud/compute/drivers/cloudwatt.py
@@ -231,7 +232,8 @@ libcloud/test/test_types.py
libcloud/test/test_utils.py
libcloud/test/backup/__init__.py
libcloud/test/backup/test_base.py
-libcloud/test/backup/test_dimensiondata.py
+libcloud/test/backup/test_dimensiondata_v2_3.py
+libcloud/test/backup/test_dimensiondata_v2_4.py
libcloud/test/backup/fixtures/dimensiondata/_backup_DISABLE.xml
libcloud/test/backup/fixtures/dimensiondata/_backup_ENABLE.xml
libcloud/test/backup/fixtures/dimensiondata/_backup_EXISTS.xml
@@ -285,12 +287,14 @@ libcloud/test/compute/test_azure_arm.py
libcloud/test/compute/test_base.py
libcloud/test/compute/test_bluebox.py
libcloud/test/compute/test_brightbox.py
+libcloud/test/compute/test_cloudscale.py
libcloud/test/compute/test_cloudsigma_v1_0.py
libcloud/test/compute/test_cloudsigma_v2_0.py
libcloud/test/compute/test_cloudstack.py
libcloud/test/compute/test_deployment.py
libcloud/test/compute/test_digitalocean_v2.py
-libcloud/test/compute/test_dimensiondata.py
+libcloud/test/compute/test_dimensiondata_v2_3.py
+libcloud/test/compute/test_dimensiondata_v2_4.py
libcloud/test/compute/test_ec2.py
libcloud/test/compute/test_ecp.py
libcloud/test/compute/test_ecs.py
@@ -383,6 +387,7 @@ libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_servi
libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_services_vmimages.xml
libcloud/test/compute/fixtures/azure/libcloud.pem
libcloud/test/compute/fixtures/azure_arm/_77777777_7777_7777_7777_777777777777_oauth2_token.json
+libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_9999_9999_9999_999999999999_providers_Microsoft_Commerce_RateCard.json
libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_9999_9999_9999_999999999999_providers_Microsoft_Compute.json
libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_9999_9999_9999_999999999999_providers_Microsoft_Compute_locations_eastus_vmSizes.json
libcloud/test/compute/fixtures/bluebox/api_block_products_json.json
@@ -402,6 +407,10 @@ libcloud/test/compute/fixtures/brightbox/list_server_types.json
libcloud/test/compute/fixtures/brightbox/list_servers.json
libcloud/test/compute/fixtures/brightbox/list_zones.json
libcloud/test/compute/fixtures/brightbox/token.json
+libcloud/test/compute/fixtures/cloudscale/create_node.json
+libcloud/test/compute/fixtures/cloudscale/list_images.json
+libcloud/test/compute/fixtures/cloudscale/list_nodes.json
+libcloud/test/compute/fixtures/cloudscale/list_sizes.json
libcloud/test/compute/fixtures/cloudsigma/drives_clone.txt
libcloud/test/compute/fixtures/cloudsigma/drives_info.txt
libcloud/test/compute/fixtures/cloudsigma/drives_single_info.txt
@@ -768,6 +777,22 @@ libcloud/test/compute/fixtures/dimensiondata/tag_tagKey_5ab77f5f_5aa9_426f_8459_
libcloud/test/compute/fixtures/dimensiondata/tag_tagKey_list.xml
libcloud/test/compute/fixtures/dimensiondata/tag_tagKey_list_SINGLE.xml
libcloud/test/compute/fixtures/dimensiondata/tag_tag_list.xml
+libcloud/test/compute/fixtures/dimensiondata/2.4/change_nic_networkadapter_response.xml
+libcloud/test/compute/fixtures/dimensiondata/2.4/exchange_nic_vlans_response.xml
+libcloud/test/compute/fixtures/dimensiondata/2.4/image_customerImage.xml
+libcloud/test/compute/fixtures/dimensiondata/2.4/image_customerImage_2ffa36c8_1848_49eb_b4fa_9d908775f68c.xml
+libcloud/test/compute/fixtures/dimensiondata/2.4/image_customerImage_5234e5c7_01de_4411_8b6e_baeb8d91cf5d.xml
+libcloud/test/compute/fixtures/dimensiondata/2.4/image_osImage.xml
+libcloud/test/compute/fixtures/dimensiondata/2.4/image_osImage_6b4fb0c7_a57b_4f58_b59c_9958f94f971a.xml
+libcloud/test/compute/fixtures/dimensiondata/2.4/image_osImage_c14b1a46_2428_44c1_9c1a_b20e6418d08c.xml
+libcloud/test/compute/fixtures/dimensiondata/2.4/import_image_response.xml
+libcloud/test/compute/fixtures/dimensiondata/2.4/server_GetServer.xml
+libcloud/test/compute/fixtures/dimensiondata/2.4/server_cleanServer.xml
+libcloud/test/compute/fixtures/dimensiondata/2.4/server_clone_response.xml
+libcloud/test/compute/fixtures/dimensiondata/2.4/server_server.xml
+libcloud/test/compute/fixtures/dimensiondata/2.4/server_server_NA3.xml
+libcloud/test/compute/fixtures/dimensiondata/2.4/server_server_e75ead52_692f_4314_8725_c8a4f4d13a87.xml
+libcloud/test/compute/fixtures/dimensiondata/2.4/server_server_paginated.xml
libcloud/test/compute/fixtures/ec2/allocate_address.xml
libcloud/test/compute/fixtures/ec2/allocate_vpc_address.xml
libcloud/test/compute/fixtures/ec2/associate_address.xml
@@ -895,7 +920,7 @@ libcloud/test/compute/fixtures/elastichosts/servers_create.json
libcloud/test/compute/fixtures/elastichosts/servers_info.json
libcloud/test/compute/fixtures/fcu/ex_describe_instance_types.xml
libcloud/test/compute/fixtures/fcu/ex_describe_product_types.xml
-libcloud/test/compute/fixtures/fcu/ex_describe_quota.xml
+libcloud/test/compute/fixtures/fcu/ex_describe_quotas.xml
libcloud/test/compute/fixtures/fcu/ex_get_product_type.xml
libcloud/test/compute/fixtures/fcu/ex_modify_instance_keypair.xml
libcloud/test/compute/fixtures/gandi/account_info.xml
@@ -1161,6 +1186,7 @@ libcloud/test/compute/fixtures/gce/zones_us-central1-b_instanceGroup_myinstanceg
libcloud/test/compute/fixtures/gce/zones_us-central1-b_instances_libcloud-lb-demo-www-000.json
libcloud/test/compute/fixtures/gce/zones_us-central1-b_instances_libcloud-lb-demo-www-001.json
libcloud/test/compute/fixtures/gce/zones_us-central1-b_instances_libcloud-lb-demo-www-002.json
+libcloud/test/compute/fixtures/gce/zones_us-central1-b_instances_libcloud-lb-nopubip-001.json
libcloud/test/compute/fixtures/gce/zones_us-east1-b.json
libcloud/test/compute/fixtures/gce/zones_us-east1-b_instanceGroupManagers.json
libcloud/test/compute/fixtures/gce/zones_us-east1-b_instanceGroup_myinstancegroup.json
@@ -1918,7 +1944,8 @@ libcloud/test/loadbalancer/__init__.py
libcloud/test/loadbalancer/test_alb.py
libcloud/test/loadbalancer/test_brightbox.py
libcloud/test/loadbalancer/test_cloudstack.py
-libcloud/test/loadbalancer/test_dimensiondata.py
+libcloud/test/loadbalancer/test_dimensiondata_v2_3.py
+libcloud/test/loadbalancer/test_dimensiondata_v2_4.py
libcloud/test/loadbalancer/test_elb.py
libcloud/test/loadbalancer/test_gce.py
libcloud/test/loadbalancer/test_gogrid.py
diff --git a/libcloud/__init__.py b/libcloud/__init__.py
index 9689bb8..ecb5319 100644
--- a/libcloud/__init__.py
+++ b/libcloud/__init__.py
@@ -36,7 +36,7 @@ __all__ = [
'__version__',
'enable_debug'
]
-__version__ = '1.4.0'
+__version__ = '1.5.0'
def enable_debug(fo):
diff --git a/libcloud/common/dimensiondata.py b/libcloud/common/dimensiondata.py
index bdcde5a..f76d52a 100644
--- a/libcloud/common/dimensiondata.py
+++ b/libcloud/common/dimensiondata.py
@@ -17,13 +17,15 @@ 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.common.types import LibcloudError, InvalidCredsError
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:
#
@@ -267,7 +269,7 @@ API_ENDPOINTS = {
'name': 'Africa (AF)',
'host': 'afapi.bsnlcloud.com',
'vendor': 'BSNL'
- },
+ }
}
# Default API end-point for the base connection class.
@@ -313,6 +315,12 @@ def dd_object_to_id(obj, obj_type, id_value='id'):
)
+# 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"
@@ -372,8 +380,16 @@ class DimensionDataConnection(ConnectionUserAndKey):
api_path_version_1 = '/oec'
api_path_version_2 = '/caas'
- api_version_1 = '0.9'
- api_version_2 = '2.3'
+ 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
@@ -382,7 +398,8 @@ class DimensionDataConnection(ConnectionUserAndKey):
allow_insecure = False
def __init__(self, user_id, key, secure=True, host=None, port=None,
- url=None, timeout=None, proxy_url=None, **conn_kwargs):
+ url=None, timeout=None, proxy_url=None,
+ api_version=None, **conn_kwargs):
super(DimensionDataConnection, self).__init__(
user_id=user_id,
key=key,
@@ -394,6 +411,31 @@ class DimensionDataConnection(ConnectionUserAndKey):
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,
@@ -414,7 +456,7 @@ class DimensionDataConnection(ConnectionUserAndKey):
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)
+ self.active_api_version, path, action)
return super(DimensionDataConnection, self).request(
action=action,
@@ -515,7 +557,7 @@ class DimensionDataConnection(ConnectionUserAndKey):
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,
+ 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,
diff --git a/libcloud/common/openstack_identity.py b/libcloud/common/openstack_identity.py
index 3a81219..da90f0b 100644
--- a/libcloud/common/openstack_identity.py
+++ b/libcloud/common/openstack_identity.py
@@ -24,7 +24,8 @@ import datetime
from libcloud.utils.py3 import httplib
from libcloud.utils.iso8601 import parse_date
-from libcloud.common.base import ConnectionUserAndKey, Response
+from libcloud.common.base import (ConnectionUserAndKey, Response,
+ CertificateConnection)
from libcloud.compute.types import (LibcloudError, InvalidCredsError,
MalformedResponseError)
@@ -41,6 +42,7 @@ AUTH_VERSIONS_WITH_EXPIRES = [
'2.0',
'2.0_apikey',
'2.0_password',
+ '2.0_voms',
'3.0',
'3.x_password',
'3.x_oidc_access_token'
@@ -69,6 +71,7 @@ __all__ = [
'OpenStackIdentity_1_0_Connection',
'OpenStackIdentity_1_1_Connection',
'OpenStackIdentity_2_0_Connection',
+ 'OpenStackIdentity_2_0_Connection_VOMS',
'OpenStackIdentity_3_0_Connection',
'OpenStackIdentity_3_0_Connection_OIDC_access_token',
@@ -1536,6 +1539,139 @@ class OpenStackIdentity_3_0_Connection_OIDC_access_token(
driver=self.driver)
+class OpenStackIdentity_2_0_Connection_VOMS(OpenStackIdentityConnection,
+ CertificateConnection):
+ """
+ Connection class for Keystone API v2.0. with VOMS proxy support
+ In this case the key parameter will be the path of the VOMS proxy file.
+ """
+
+ responseCls = OpenStackAuthResponse
+ name = 'OpenStack Identity API v2.0 VOMS support'
+ auth_version = '2.0'
+
+ def __init__(self, auth_url, user_id, key, tenant_name=None,
+ domain_name='Default',
+ token_scope=OpenStackIdentityTokenScope.PROJECT,
+ timeout=None, parent_conn=None):
+ CertificateConnection.__init__(self, cert_file=key,
+ url=auth_url,
+ timeout=timeout)
+
+ self.parent_conn = parent_conn
+
+ # enable tests to use the same mock connection classes.
+ if parent_conn:
+ self.conn_classes = parent_conn.conn_classes
+ self.driver = parent_conn.driver
+ else:
+ self.driver = None
+
+ self.auth_url = auth_url
+ self.tenant_name = tenant_name
+ self.domain_name = domain_name
+ self.token_scope = token_scope
+ self.timeout = timeout
+
+ self.urls = {}
+ self.auth_token = None
+ self.auth_token_expires = None
+ self.auth_user_info = None
+
+ def authenticate(self, force=False):
+ if not self._is_authentication_needed(force=force):
+ return self
+
+ tenant = self.tenant_name
+ if not tenant:
+ # if the tenant name is not specified look for it
+ token = self._get_unscoped_token()
+ tenant = self._get_tenant_name(token)
+
+ data = {'auth': {'voms': True, 'tenantName': tenant}}
+
+ reqbody = json.dumps(data)
+ return self._authenticate_2_0_with_body(reqbody)
+
+ def _get_unscoped_token(self):
+ """
+ Get unscoped token from VOMS proxy
+ """
+ data = {'auth': {'voms': True}}
+ reqbody = json.dumps(data)
+
+ response = self.request('/v2.0/tokens', data=reqbody,
+ headers={'Content-Type': 'application/json'},
+ method='POST')
+
+ if response.status == httplib.UNAUTHORIZED:
+ # Invalid credentials
+ raise InvalidCredsError()
+ elif response.status in [httplib.OK, httplib.CREATED]:
+ try:
+ body = json.loads(response.body)
+ return body['access']['token']['id']
+ except Exception:
+ e = sys.exc_info()[1]
+ raise MalformedResponseError('Failed to parse JSON', e)
+ else:
+ raise MalformedResponseError('Malformed response',
+ driver=self.driver)
+
+ def _get_tenant_name(self, token):
+ """
+ Get the first available tenant name (usually there are only one)
+ """
+ headers = {'Accept': 'application/json',
+ 'Content-Type': 'application/json',
+ 'X-Auth-Token': token}
+ response = self.request('/v2.0/tenants', headers=headers, method='GET')
+
+ if response.status == httplib.UNAUTHORIZED:
+ # Invalid credentials
+ raise InvalidCredsError()
+ elif response.status in [httplib.OK, httplib.CREATED]:
+ try:
+ body = json.loads(response.body)
+ return body["tenants"][0]["name"]
+ except Exception:
+ e = sys.exc_info()[1]
+ raise MalformedResponseError('Failed to parse JSON', e)
+ else:
+ raise MalformedResponseError('Malformed response',
+ driver=self.driver)
+
+ def _authenticate_2_0_with_body(self, reqbody):
+ resp = self.request('/v2.0/tokens', data=reqbody,
+ headers={'Content-Type': 'application/json'},
+ method='POST')
+
+ if resp.status == httplib.UNAUTHORIZED:
+ raise InvalidCredsError()
+ elif resp.status not in [httplib.OK,
+ httplib.NON_AUTHORITATIVE_INFORMATION]:
+ body = 'code: %s body: %s' % (resp.status, resp.body)
+ raise MalformedResponseError('Malformed response', body=body,
+ driver=self.driver)
+ else:
+ body = resp.object
+
+ try:
+ access = body['access']
+ expires = access['token']['expires']
+
+ self.auth_token = access['token']['id']
+ self.auth_token_expires = parse_date(expires)
+ self.urls = access['serviceCatalog']
+ self.auth_user_info = access.get('user', {})
+ except KeyError:
+ e = sys.exc_info()[1]
+ raise MalformedResponseError('Auth JSON response is \
+ missing required elements', e)
+
+ return self
+
+
def get_class_for_auth_version(auth_version):
"""
Retrieve class for the provided auth version.
@@ -1548,6 +1684,8 @@ def get_class_for_auth_version(auth_version):
cls = OpenStackIdentity_2_0_Connection
elif auth_version == '2.0_password':
cls = OpenStackIdentity_2_0_Connection
+ elif auth_version == '2.0_voms':
+ cls = OpenStackIdentity_2_0_Connection_VOMS
elif auth_version == '3.x_password':
cls = OpenStackIdentity_3_0_Connection
elif auth_version == '3.x_oidc_access_token':
diff --git a/libcloud/compute/drivers/azure_arm.py b/libcloud/compute/drivers/azure_arm.py
index c7d0441..44abcdb 100644
--- a/libcloud/compute/drivers/azure_arm.py
+++ b/libcloud/compute/drivers/azure_arm.py
@@ -709,6 +709,40 @@ class AzureNodeDriver(NodeDriver):
return True
+ def ex_get_ratecard(self, offer_durable_id, currency='USD',
+ locale='en-US', region='US'):
+ """
+ Get rate card
+
+ :param offer_durable_id: ID of the offer applicable for this
+ user account. (e.g. "0026P")
+ See http://azure.microsoft.com/en-us/support/legal/offer-details/
+ :type offer_durable_id: str
+
+ :param currency: Desired currency for the response (default: "USD")
+ :type currency: ``str``
+
+ :param locale: Locale (default: "en-US")
+ :type locale: ``str``
+
+ :param region: Region (two-letter code) (default: "US")
+ :type regions: ``str``
+
+ :return: A dictionary of rates whose ID's correspond to nothing at all
+ :rtype: ``dict``
+ """
+
+ action = "/subscriptions/%s/providers/Microsoft.Commerce/" \
+ "RateCard" % (self.subscription_id,)
+ params = {"api-version": "2016-08-31-preview",
+ "$filter": "OfferDurableId eq 'MS-AZR-%s' and "
+ "Currency eq '%s' and "
+ "Locale eq '%s' and "
+ "RegionInfo eq '%s'" %
+ (offer_durable_id, currency, locale, region)}
+ r = self.connection.request(action, params=params)
+ return r.object
+
def ex_list_publishers(self, location=None):
"""
List node image publishers.
diff --git a/libcloud/compute/drivers/cloudscale.py b/libcloud/compute/drivers/cloudscale.py
new file mode 100644
index 0000000..98034ec
--- /dev/null
+++ b/libcloud/compute/drivers/cloudscale.py
@@ -0,0 +1,246 @@
+# 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.
+"""
+A driver for cloudscale.ch.
+"""
+
+import json
+
+from libcloud.utils.py3 import httplib
+
+from libcloud.common.base import ConnectionKey, JsonResponse
+from libcloud.compute.types import Provider, NodeState
+from libcloud.common.types import InvalidCredsError
+from libcloud.compute.base import NodeDriver
+from libcloud.compute.base import Node, NodeImage, NodeSize
+
+
+class CloudscaleResponse(JsonResponse):
+ valid_response_codes = [httplib.OK, httplib.ACCEPTED, httplib.CREATED,
+ httplib.NO_CONTENT]
+
+ def parse_error(self):
+ body = self.parse_body()
+ if self.status == httplib.UNAUTHORIZED:
+ raise InvalidCredsError(body['detail'])
+ else:
+ # We are taking the first issue here. There might be multiple ones,
+ # but that doesn't really matter. It's nicer if the error is just
+ # one error (because it's a Python API and there's only one
+ # exception.
+ return next(iter(body.values()))
+
+ def success(self):
+ return self.status in self.valid_response_codes
+
+
+class CloudscaleConnection(ConnectionKey):
+ """
+ Connection class for the cloudscale.ch driver.
+ """
+ host = 'api.cloudscale.ch'
+ responseCls = CloudscaleResponse
+
+ 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
+
+
+class CloudscaleNodeDriver(NodeDriver):
+ """
+ Cloudscale's node driver.
+ """
+
+ connectionCls = CloudscaleConnection
+
+ type = Provider.CLOUDSCALE
+ name = 'Cloudscale'
+ website = 'https://www.cloudscale.ch'
+
+ NODE_STATE_MAP = dict(
+ changing=NodeState.PENDING,
+ running=NodeState.RUNNING,
+ stopped=NodeState.STOPPED,
+ paused=NodeState.PAUSED,
+ )
+
+ def __init__(self, key, **kwargs):
+ super(CloudscaleNodeDriver, self).__init__(key, **kwargs)
+
+ def list_nodes(self):
+ '''
+ List all your existing compute nodes.
+ '''
+ return self._list_resources('/v1/servers', self._to_node)
+
+ def list_sizes(self):
+ '''
+ Lists all available sizes. On cloudscale these are known as flavors.
+ '''
+ return self._list_resources('/v1/flavors', self._to_size)
+
+ def list_images(self):
+ '''
+ List all images.
+
+ Images are identified by slugs on cloudscale.ch. This means that minor
+ version upgrades (e.g. Ubuntu 16.04.1 to Ubuntu 16.04.2) will be
+ possible within the same id ``ubuntu-16.04``.
+ '''
+ return self._list_resources('/v1/images', self._to_image)
+
+ def create_node(self, name, size, image, location=None, ex_create_attr={}):
+ """
+ Create a node.
+
+ The `ex_create_attr` parameter can include the following dictionary
+ key and value pairs:
+
+ * `ssh_keys`: ``list`` of ``str`` ssh public keys
+ * `volume_size_gb`: ``int`` defaults to 10.
+ * `bulk_volume_size_gb`: defaults to None.
+ * `use_public_network`: ``bool`` defaults to True
+ * `use_private_network`: ``bool`` defaults to False
+ * `use_ipv6`: ``bool`` defaults to True
+ * `anti_affinity_with`: ``uuid`` of a server to create an anti-affinity
+ group with that server or add it to the same group as that server.
+ * `user_data`: ``str`` for optional cloud-config data
+
+ :keyword ex_create_attr: A dictionary of optional attributes for
+ droplet creation
+ :type ex_create_attr: ``dict``
+
+ :return: The newly created node.
+ :rtype: :class:`Node`
+ """
+ attr = dict(ex_create_attr)
+ attr.update(
+ name=name,
+ image=image.id,
+ flavor=size.id,
+ )
+ result = self.connection.request(
+ '/v1/servers',
+ data=json.dumps(attr),
+ method='POST'
+ )
+ return self._to_node(result.object)
+
+ def reboot_node(self, node):
+ '''
+ Reboot a node. It's also possible to use ``node.reboot()``.
+ '''
+ return self._action(node, 'reboot')
+
+ def ex_start_node(self, node):
+ '''
+ Start a node. This is only possible if the node is stopped.
+ '''
+ return self._action(node, 'start')
+
+ def ex_stop_node(self, node):
+ '''
+ Stop a specific node. Similar to ``shutdown -h now``. This is only
+ possible if the node is running.
+ '''
+ return self._action(node, 'stop')
+
+ def ex_node_by_uuid(self, uuid):
+ '''
+ :param str ex_user_data: A valid uuid that references your exisiting
+ cloudscale.ch server.
+ :type ex_user_data: ``str``
+
+ :return: The server node you asked for.
+ :rtype: :class:`Node`
+ '''
+ res = self.connection.request(self._get_server_url(uuid))
+ return self._to_node(res.object)
+
+ def destroy_node(self, node):
+ '''
+ Delete a node. It's also possible to use ``node.destroy()``.
+ This will irreversibly delete the cloudscale.ch server and all its
+ volumes. So please be cautious.
+ '''
+ res = self.connection.request(
+ self._get_server_url(node.id),
+ method='DELETE'
+ )
+ return res.status == httplib.NO_CONTENT
+
+ def _get_server_url(self, uuid):
+ return '/v1/servers/%s' % uuid
+
+ def _action(self, node, action_name):
+ response = self.connection.request(
+ self._get_server_url(node.id) + '/' + action_name,
+ method='POST'
+ )
+ return response.status == httplib.OK
+
+ def _list_resources(self, url, tranform_func):
+ data = self.connection.request(url, method='GET').object
+ return [tranform_func(obj) for obj in data]
+
+ def _to_node(self, data):
+ state = self.NODE_STATE_MAP.get(data['status'], NodeState.UNKNOWN)
+ extra_keys = ['volumes', 'interfaces', 'anti_affinity_with']
+ extra = {}
+ for key in extra_keys:
+ if key in data:
+ extra[key] = data[key]
+
+ public_ips = []
+ private_ips = []
+ for interface in data['interfaces']:
+ if interface['type'] == 'public':
+ ips = public_ips
+ else:
+ ips = private_ips
+ for address_obj in interface['addresses']:
+ ips.append(address_obj['address'])
+
+ return Node(
+ id=data['uuid'],
+ name=data['name'],
+ state=state,
+ public_ips=public_ips,
+ private_ips=private_ips,
+ extra=extra,
+ driver=self,
+ image=self._to_image(data['image']),
+ size=self._to_size(data['flavor']),
+ )
+
+ def _to_size(self, data):
+ extra = {'vcpu_count': data['vcpu_count']}
+ ram = data['memory_gb'] * 1024
+
+ return NodeSize(id=data['slug'], name=data['name'],
+ ram=ram, disk=10,
+ bandwidth=0, price=0,
+ extra=extra, driver=self)
+
+ def _to_image(self, data):
+ extra = {'operating_system': data['operating_system']}
+ return NodeImage(id=data['slug'], name=data['name'], extra=extra,
+ driver=self)
diff --git a/libcloud/compute/drivers/dimensiondata.py b/libcloud/compute/drivers/dimensiondata.py
index 76dfb55..c47eedd 100644
--- a/libcloud/compute/drivers/dimensiondata.py
+++ b/libcloud/compute/drivers/dimensiondata.py
@@ -21,6 +21,7 @@ try:
except ImportError:
from xml.etree import ElementTree as ET
+from libcloud.common.dimensiondata import LooseVersion
from libcloud.common.exceptions import BaseHTTPError
from libcloud.compute.base import NodeDriver, Node, NodeAuthPassword
from libcloud.compute.base import NodeSize, NodeImage, NodeLocation
@@ -56,15 +57,26 @@ from libcloud.utils.py3 import urlencode, ensure_string
from libcloud.utils.xml import fixxpath, findtext, findall
from libcloud.utils.py3 import basestring
from libcloud.compute.types import NodeState, Provider
+import sys
# Node state map is a dictionary with the keys as tuples
# These tuples represent:
# (<state_of_node_from_didata>, <is node started?>, <action happening>)
NODE_STATE_MAP = {
- ('NORMAL', 'true', None):
- NodeState.RUNNING,
('NORMAL', 'false', None):
NodeState.STOPPED,
+ ('PENDING_CHANGE', 'false', None):
+ NodeState.PENDING,
+ ('PENDING_CHANGE', 'false', 'CHANGE_NETWORK_ADAPTER'):
+ NodeState.PENDING,
+ ('PENDING_CHANGE', 'true', 'CHANGE_NETWORK_ADAPTER'):
+ NodeState.PENDING,
+ ('PENDING_CHANGE', 'false', 'EXCHANGE_NIC_VLANS'):
+ NodeState.PENDING,
+ ('PENDING_CHANGE', 'true', 'EXCHANGE_NIC_VLANS'):
+ NodeState.PENDING,
+ ('NORMAL', 'true', None):
+ NodeState.RUNNING,
('PENDING_CHANGE', 'true', 'START_SERVER'):
NodeState.STARTING,
('PENDING_ADD', 'true', 'DEPLOY_SERVER'):
@@ -95,6 +107,7 @@ OBJECT_TO_TAGGING_ASSET_TYPE_MAP = {
class DimensionDataNodeDriver(NodeDriver):
"""
DimensionData node driver.
+ Default api_version is used unless specified.
"""
selected_region = None
@@ -114,6 +127,9 @@ class DimensionDataNodeDriver(NodeDriver):
if region is not None:
self.selected_region = API_ENDPOINTS[region]
+ if api_version is not None:
+ self.api_version = api_version
+
super(DimensionDataNodeDriver, self).__init__(key=key, secret=secret,
secure=secure, host=host,
port=port,
@@ -129,6 +145,7 @@ class DimensionDataNodeDriver(NodeDriver):
kwargs = super(DimensionDataNodeDriver,
self)._ex_connection_class_kwargs()
kwargs['region'] = self.selected_region
+ kwargs['api_version'] = self.api_version
return kwargs
def _create_node_mcp1(self, name, image, auth, ex_description,
@@ -365,7 +382,6 @@ class DimensionDataNodeDriver(NodeDriver):
>>> # ex_primary_nic_network_adapter='E1000',
>>> # ex_is_started=False)
>>>
- >>> pprint(node)
:keyword name: (required) String with a name for this new node
:type name: ``str``
@@ -476,6 +492,10 @@ class DimensionDataNodeDriver(NodeDriver):
'ex_network_domain '
'for MCP2 or ex_network for legacy MCP1')
+ # Set ex_is_started to False by default if none bool data type provided
+ if not isinstance(ex_is_started, bool):
+ ex_is_started = True
+
# Handle MCP1 legacy
if 'ex_network' in kwargs:
new_node = self._create_node_mcp1(
@@ -783,7 +803,7 @@ class DimensionDataNodeDriver(NodeDriver):
Note: Currently only returns the default 'base OS images'
provided by DimensionData. Customer images (snapshots)
- are not yet supported.
+ use ex_list_customer_images
:keyword ex_location: Filters the node list to nodes that are
located in this location
@@ -864,6 +884,109 @@ class DimensionDataNodeDriver(NodeDriver):
.request_with_orgId_api_1('networkWithLocation%s' % url_ext)
.object)
+ def import_image(self, ovf_package_name, name,
+ cluster_id=None, datacenter_id=None, description=None,
+ is_guest_os_customization=None,
+ tagkey_name_value_dictionaries=None):
+ """
+ Import image
+
+ :param ovf_package_name: Image OVF package name
+ :type ovf_package_name: ``str``
+
+ :param name: Image name
... 88224 lines suppressed ...
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/libcloud.git
More information about the Python-modules-commits
mailing list