Add new driver for Exoscale driver based on the CloudStack one. Also refactor CloudStack test cases so they can be more easily reused with other provider drivers.
Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/47927179 Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/47927179 Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/47927179 Branch: refs/heads/trunk Commit: 4792717965671b8d976745edf436e8a58edd1919 Parents: 194aca7 Author: Tomaz Muraus <[email protected]> Authored: Wed Nov 20 16:34:23 2013 +0100 Committer: Tomaz Muraus <[email protected]> Committed: Wed Nov 20 16:59:25 2013 +0100 ---------------------------------------------------------------------- CHANGES | 3 + libcloud/compute/drivers/cloudstack.py | 3 +- libcloud/compute/drivers/exoscale.py | 31 ++++++++ libcloud/compute/providers.py | 2 + libcloud/compute/types.py | 4 +- libcloud/test/compute/test_cloudstack.py | 103 +++++++++++++------------- libcloud/test/compute/test_exoscale.py | 28 +++++++ 7 files changed, 122 insertions(+), 52 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/libcloud/blob/47927179/CHANGES ---------------------------------------------------------------------- diff --git a/CHANGES b/CHANGES index 6613941..1244152 100644 --- a/CHANGES +++ b/CHANGES @@ -43,6 +43,9 @@ Changes with Apache Libcloud in development request. [Tomaz Muraus, Philipp Strube] + - Add a new driver for Exoscale (https://www.exoscale.ch/) provider. + [Tomaz Muraus] + Changes with Apache Libcloud 0.14.0-beta3 *) General http://git-wip-us.apache.org/repos/asf/libcloud/blob/47927179/libcloud/compute/drivers/cloudstack.py ---------------------------------------------------------------------- diff --git a/libcloud/compute/drivers/cloudstack.py b/libcloud/compute/drivers/cloudstack.py index f3cc884..1b0338c 100644 --- a/libcloud/compute/drivers/cloudstack.py +++ b/libcloud/compute/drivers/cloudstack.py @@ -195,7 +195,7 @@ class CloudStackNodeDriver(CloudStackDriverMixIn, NodeDriver): website = 'http://cloudstack.org/' type = Provider.CLOUDSTACK - features = {"create_node": ["generates_password", ]} + features = {'create_node': ['generates_password']} NODE_STATE_MAP = { 'Running': NodeState.RUNNING, @@ -239,6 +239,7 @@ class CloudStackNodeDriver(CloudStackDriverMixIn, NodeDriver): port = int(split[1]) else: host = host if host else self.host + path = path if path else self.path if path is not None: self.path = path http://git-wip-us.apache.org/repos/asf/libcloud/blob/47927179/libcloud/compute/drivers/exoscale.py ---------------------------------------------------------------------- diff --git a/libcloud/compute/drivers/exoscale.py b/libcloud/compute/drivers/exoscale.py new file mode 100644 index 0000000..9f883e0 --- /dev/null +++ b/libcloud/compute/drivers/exoscale.py @@ -0,0 +1,31 @@ +# 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.compute.providers import Provider +from libcloud.compute.drivers.cloudstack import CloudStackNodeDriver + +__all__ = [ + 'ExoscaleNodeDriver' +] + + +class ExoscaleNodeDriver(CloudStackNodeDriver): + type = Provider.EXOSCALE + name = 'Exoscale' + website = 'https://www.exoscale.ch/' + + # API endpoint info + host = 'api.exoscale.ch' + path = '/compute' http://git-wip-us.apache.org/repos/asf/libcloud/blob/47927179/libcloud/compute/providers.py ---------------------------------------------------------------------- diff --git a/libcloud/compute/providers.py b/libcloud/compute/providers.py index e78fe18..55c2abf 100644 --- a/libcloud/compute/providers.py +++ b/libcloud/compute/providers.py @@ -137,6 +137,8 @@ DRIVERS = { ('libcloud.compute.drivers.nephoscale', 'NephoscaleNodeDriver'), Provider.CLOUDFRAMES: ('libcloud.compute.drivers.cloudframes', 'CloudFramesNodeDriver'), + Provider.EXOSCALE: + ('libcloud.compute.drivers.exoscale', 'ExoscaleNodeDriver'), } http://git-wip-us.apache.org/repos/asf/libcloud/blob/47927179/libcloud/compute/types.py ---------------------------------------------------------------------- diff --git a/libcloud/compute/types.py b/libcloud/compute/types.py index 7dd7b74..a421bab 100644 --- a/libcloud/compute/types.py +++ b/libcloud/compute/types.py @@ -71,7 +71,8 @@ class Provider(object): :cvar KTUCLOUD: kt ucloud driver :cvar GRIDSPOT: Gridspot driver :cvar ABIQUO: Abiquo driver - @cvar NEPHOSCALE: NephoScale driver + :cvar NEPHOSCALE: NephoScale driver + :cvar EXOSCALE: Exoscale driver. """ DUMMY = 'dummy' EC2 = 'ec2_us_east' @@ -114,6 +115,7 @@ class Provider(object): DIGITAL_OCEAN = 'digitalocean' NEPHOSCALE = 'nephoscale' CLOUDFRAMES = 'cloudframes' + EXOSCALE = 'exoscale' # Deprecated constants which are still supported EC2_US_EAST = 'ec2_us_east' http://git-wip-us.apache.org/repos/asf/libcloud/blob/47927179/libcloud/test/compute/test_cloudstack.py ---------------------------------------------------------------------- diff --git a/libcloud/test/compute/test_cloudstack.py b/libcloud/test/compute/test_cloudstack.py index c3721dc..e950582 100644 --- a/libcloud/test/compute/test_cloudstack.py +++ b/libcloud/test/compute/test_cloudstack.py @@ -35,64 +35,20 @@ from libcloud.test.compute import TestCaseMixin from libcloud.test.file_fixtures import ComputeFileFixtures -class CloudStackNodeDriverTest(unittest.TestCase, TestCaseMixin): +class CloudStackCommonTestCase(TestCaseMixin): + driver_klass = CloudStackNodeDriver def setUp(self): - CloudStackNodeDriver.connectionCls.conn_classes = \ + self.driver_klass.connectionCls.conn_classes = \ (None, CloudStackMockHttp) - self.driver = CloudStackNodeDriver('apikey', 'secret', - path='/test/path', - host='api.dummy.com') + self.driver = self.driver_klass('apikey', 'secret', + path='/test/path', + host='api.dummy.com') self.driver.path = '/test/path' self.driver.type = -1 CloudStackMockHttp.fixture_tag = 'default' self.driver.connection.poll_interval = 0.0 - def test_driver_instantiation(self): - urls = [ - 'http://api.exoscale.ch/compute1', # http, default port - 'https://api.exoscale.ch/compute2', # https, default port - 'http://api.exoscale.ch:8888/compute3', # https, custom port - 'https://api.exoscale.ch:8787/compute4', # https, custom port - 'https://api.test.com/compute/endpoint' # https, default port - ] - - expected_values = [ - {'host': 'api.exoscale.ch', 'port': 80, 'path': '/compute1'}, - {'host': 'api.exoscale.ch', 'port': 443, 'path': '/compute2'}, - {'host': 'api.exoscale.ch', 'port': 8888, 'path': '/compute3'}, - {'host': 'api.exoscale.ch', 'port': 8787, 'path': '/compute4'}, - {'host': 'api.test.com', 'port': 443, 'path': '/compute/endpoint'} - ] - - cls = get_driver(Provider.CLOUDSTACK) - - for url, expected in zip(urls, expected_values): - driver = cls('key', 'secret', url=url) - - self.assertEqual(driver.host, expected['host']) - self.assertEqual(driver.path, expected['path']) - self.assertEqual(driver.connection.port, expected['port']) - - def test_user_must_provide_host_and_path_or_url(self): - expected_msg = ('When instantiating CloudStack driver directly ' - 'you also need to provide url or host and path ' - 'argument') - cls = get_driver(Provider.CLOUDSTACK) - - self.assertRaisesRegexp(Exception, expected_msg, cls, - 'key', 'secret') - - try: - cls('key', 'secret', True, 'localhost', '/path') - except Exception: - self.fail('host and path provided but driver raised an exception') - - try: - cls('key', 'secret', url='https://api.exoscale.ch/compute') - except Exception: - self.fail('url provided but driver raised an exception') - def test_create_node_immediate_failure(self): size = self.driver.list_sizes()[0] image = self.driver.list_images()[0] @@ -438,6 +394,53 @@ class CloudStackNodeDriverTest(unittest.TestCase, TestCaseMixin): self.assertTrue(res) +class CloudStackTestCase(CloudStackCommonTestCase, unittest.TestCase): + def test_driver_instantiation(self): + urls = [ + 'http://api.exoscale.ch/compute1', # http, default port + 'https://api.exoscale.ch/compute2', # https, default port + 'http://api.exoscale.ch:8888/compute3', # https, custom port + 'https://api.exoscale.ch:8787/compute4', # https, custom port + 'https://api.test.com/compute/endpoint' # https, default port + ] + + expected_values = [ + {'host': 'api.exoscale.ch', 'port': 80, 'path': '/compute1'}, + {'host': 'api.exoscale.ch', 'port': 443, 'path': '/compute2'}, + {'host': 'api.exoscale.ch', 'port': 8888, 'path': '/compute3'}, + {'host': 'api.exoscale.ch', 'port': 8787, 'path': '/compute4'}, + {'host': 'api.test.com', 'port': 443, 'path': '/compute/endpoint'} + ] + + cls = get_driver(Provider.CLOUDSTACK) + + for url, expected in zip(urls, expected_values): + driver = cls('key', 'secret', url=url) + + self.assertEqual(driver.host, expected['host']) + self.assertEqual(driver.path, expected['path']) + self.assertEqual(driver.connection.port, expected['port']) + + def test_user_must_provide_host_and_path_or_url(self): + expected_msg = ('When instantiating CloudStack driver directly ' + 'you also need to provide url or host and path ' + 'argument') + cls = get_driver(Provider.CLOUDSTACK) + + self.assertRaisesRegexp(Exception, expected_msg, cls, + 'key', 'secret') + + try: + cls('key', 'secret', True, 'localhost', '/path') + except Exception: + self.fail('host and path provided but driver raised an exception') + + try: + cls('key', 'secret', url='https://api.exoscale.ch/compute') + except Exception: + self.fail('url provided but driver raised an exception') + + class CloudStackMockHttp(MockHttpTestCase): fixtures = ComputeFileFixtures('cloudstack') fixture_tag = 'default' http://git-wip-us.apache.org/repos/asf/libcloud/blob/47927179/libcloud/test/compute/test_exoscale.py ---------------------------------------------------------------------- diff --git a/libcloud/test/compute/test_exoscale.py b/libcloud/test/compute/test_exoscale.py new file mode 100644 index 0000000..1a4cbec --- /dev/null +++ b/libcloud/test/compute/test_exoscale.py @@ -0,0 +1,28 @@ +# 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 sys + +from libcloud.compute.drivers.exoscale import ExoscaleNodeDriver +from libcloud.test.compute.test_cloudstack import CloudStackCommonTestCase + +from libcloud.test import unittest + + +class ExoscaleNodeDriverTestCase(CloudStackCommonTestCase, unittest.TestCase): + driver_klass = ExoscaleNodeDriver + +if __name__ == '__main__': + sys.exit(unittest.main())
