From 773cd3d1541ae364eb9d88f7590c1e4b56579508 Mon Sep 17 00:00:00 2001 From: Chris DeRamus Date: Sun, 9 Feb 2014 15:57:56 -0500 Subject: [PATCH] LIBCLOUD-516: Add list_size() support into Eucalyptus for cluster versions >= 3.3.0. In this version Eucalyptus introduced the DescribeInstanceTypes call which is specific to EUCA and is not AWS compatible. This call requires a different XML namespace. Closes #249. Signed-off-by: Tomaz Muraus --- libcloud/compute/drivers/ec2.py | 56 ++++++++++++++++++- .../fixtures/ec2/describe_instance_types.xml | 1 + libcloud/test/compute/test_ec2.py | 15 ++++- 3 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 libcloud/test/compute/fixtures/ec2/describe_instance_types.xml diff --git a/libcloud/compute/drivers/ec2.py b/libcloud/compute/drivers/ec2.py index cade2ece5a..622265779b 100644 --- a/libcloud/compute/drivers/ec2.py +++ b/libcloud/compute/drivers/ec2.py @@ -44,6 +44,8 @@ 'API_VERSION', 'NAMESPACE', 'INSTANCE_TYPES', + 'DEFAULT_EUCA_API_VERSION', + 'EUCA_NAMESPACE', 'EC2NodeDriver', 'BaseEC2NodeDriver', @@ -64,6 +66,10 @@ API_VERSION = '2013-10-15' NAMESPACE = 'http://ec2.amazonaws.com/doc/%s/' % (API_VERSION) +# Eucalyptus Constants +DEFAULT_EUCA_API_VERSION = '3.3.0' +EUCA_NAMESPACE = 'http://msgs.eucalyptus.com/%s' % (DEFAULT_EUCA_API_VERSION) + """ Sizes must be hardcoded, because Amazon doesn't provide an API to fetch them. From http://aws.amazon.com/ec2/instance-types/ @@ -3875,22 +3881,70 @@ class EucNodeDriver(BaseEC2NodeDriver): connectionCls = EucConnection def __init__(self, key, secret=None, secure=True, host=None, - path=None, port=None): + path=None, port=None, api_version=DEFAULT_EUCA_API_VERSION): """ @inherits: :class:`EC2NodeDriver.__init__` :param path: The host where the API can be reached. :type path: ``str`` + + :param api_version: The API version to extend support for + Eucalyptus proprietary API calls + :type api_version: ``str`` """ super(EucNodeDriver, self).__init__(key, secret, secure, host, port) + if path is None: path = '/services/Eucalyptus' + self.path = path + self.EUCA_NAMESPACE = 'http://msgs.eucalyptus.com/%s' % (api_version) def list_locations(self): raise NotImplementedError( 'list_locations not implemented for this driver') + def _to_sizes(self, response): + return [self._to_size(el) for el in response.findall( + fixxpath(xpath='instanceTypeDetails/item', + namespace=self.EUCA_NAMESPACE))] + + def _to_size(self, el): + name = findtext(element=el, + xpath='name', + namespace=self.EUCA_NAMESPACE) + cpu = findtext(element=el, + xpath='cpu', + namespace=self.EUCA_NAMESPACE) + disk = findtext(element=el, + xpath='disk', + namespace=self.EUCA_NAMESPACE) + memory = findtext(element=el, + xpath='memory', + namespace=self.EUCA_NAMESPACE) + + return NodeSize(id=name, + name=name, + ram=int(memory), + disk=int(disk), + bandwidth=None, + price=None, + driver=EucNodeDriver, + extra={ + 'cpu': int(cpu) + }) + + def list_sizes(self): + """ + List available instance flavors/sizes + + :rtype: ``list`` of :class:`NodeSize` + """ + params = {'Action': 'DescribeInstanceTypes'} + response = self.connection.request(self.path, params=params).object + + return self._to_sizes(response) + def _add_instance_filter(self, params, node): """ Eucalyptus driver doesn't support filtering on instance id so this is a diff --git a/libcloud/test/compute/fixtures/ec2/describe_instance_types.xml b/libcloud/test/compute/fixtures/ec2/describe_instance_types.xml new file mode 100644 index 0000000000..3fff98b77f --- /dev/null +++ b/libcloud/test/compute/fixtures/ec2/describe_instance_types.xml @@ -0,0 +1 @@ +truem1.small15256t1.micro15256m1.medium110512c1.medium210512m1.large1101024c1.xlarge2101024m1.xlarge1102048m2.xlarge2102048m3.xlarge16152048m2.2xlarge16304096m3.2xlarge16304096cc1.4xlarge16603072m2.4xlarge16604096cc2.8xlarge161206144hi1.4xlarge161206144cg1.4xlarge1620012288cr1.8xlarge1624016384hs1.8xlarge1624000119808 \ No newline at end of file diff --git a/libcloud/test/compute/test_ec2.py b/libcloud/test/compute/test_ec2.py index ceacdbdd27..63f15aa359 100644 --- a/libcloud/test/compute/test_ec2.py +++ b/libcloud/test/compute/test_ec2.py @@ -1378,6 +1378,11 @@ def _services_Eucalyptus_CreateTags(self, method, url, body, headers): return self._CreateTags(method, url, body, headers) + def _services_Eucalyptus_DescribeInstanceTypes(self, method, url, body, + headers): + body = self.fixtures.load('describe_instance_types.xml') + return (httplib.OK, body, {}, httplib.responses[httplib.OK]) + class NimbusTests(EC2Tests): @@ -1444,7 +1449,7 @@ def setUp(self): EC2MockHttp.use_param = 'Action' EC2MockHttp.type = None self.driver = EucNodeDriver(key=EC2_PARAMS[0], secret=EC2_PARAMS[1], - host='some.eucalyptus.com') + host='some.eucalyptus.com', api_version='3.4.1') def test_list_locations_response(self): try: @@ -1457,6 +1462,14 @@ def test_list_locations_response(self): def test_list_location(self): pass + def test_list_sizes(self): + sizes = self.driver.list_sizes() + ids = [s.id for s in sizes] + self.assertEqual(len(ids), 18) + self.assertTrue('t1.micro' in ids) + self.assertTrue('m1.medium' in ids) + self.assertTrue('m3.xlarge' in ids) + if __name__ == '__main__': sys.exit(unittest.main())