Repository: libcloud Updated Branches: refs/heads/trunk 4d926bd3f -> a7dbbf37d
Adding docs and more coverage on tests Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/c06ddd64 Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/c06ddd64 Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/c06ddd64 Branch: refs/heads/trunk Commit: c06ddd640aa18837840488ef821a152455e9dc5b Parents: 8301b2c Author: Jeffrey Dunham <jeffrey.a.dun...@gmail.com> Authored: Wed Feb 10 18:15:15 2016 -0500 Committer: anthony-shaw <anthony.p.s...@gmail.com> Committed: Thu Feb 11 13:27:59 2016 +1100 ---------------------------------------------------------------------- libcloud/common/dimensiondata.py | 17 +++++- libcloud/compute/drivers/dimensiondata.py | 51 +++++++++--------- ...abe5a7d0e4_infrastructure_datacenter_NA9.xml | 54 ++++++++++++++++++++ libcloud/test/compute/test_dimensiondata.py | 42 +++++++++++++++ 4 files changed, 138 insertions(+), 26 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/libcloud/blob/c06ddd64/libcloud/common/dimensiondata.py ---------------------------------------------------------------------- diff --git a/libcloud/common/dimensiondata.py b/libcloud/common/dimensiondata.py index 37d4572..f78b056 100644 --- a/libcloud/common/dimensiondata.py +++ b/libcloud/common/dimensiondata.py @@ -94,14 +94,29 @@ BAD_MESSAGE_XML_ELEMENTS = ( ('resultDetail', GENERAL_NS) ) + def location_to_location_id(location): + """ + Helper function to get a location id from a location whether + it be a NodeLocation or a string + + :param location: The location to get an id from + :type location: :class:`NodeLocation` or ``str`` + + :return: The location id + :rtype: ``str`` or None (if no location passed in) + """ if location is not None: if isinstance(location, NodeLocation): return location.id elif isinstance(location, basestring): return location else: - raise TypeError("Invalid location type for location_to_location_id()") + raise TypeError( + "Invalid location type for location_to_location_id()" + ) + return None + class NetworkDomainServicePlan(object): ESSENTIALS = "ESSENTIALS" http://git-wip-us.apache.org/repos/asf/libcloud/blob/c06ddd64/libcloud/compute/drivers/dimensiondata.py ---------------------------------------------------------------------- diff --git a/libcloud/compute/drivers/dimensiondata.py b/libcloud/compute/drivers/dimensiondata.py index 6226af5..744577d 100644 --- a/libcloud/compute/drivers/dimensiondata.py +++ b/libcloud/compute/drivers/dimensiondata.py @@ -300,7 +300,6 @@ class DimensionDataNodeDriver(NodeDriver): :return: a list of `Node` objects :rtype: ``list`` of :class:`Node` """ - node_list = [] for nodes in self.ex_list_nodes_paginated( location=ex_location, @@ -316,11 +315,18 @@ class DimensionDataNodeDriver(NodeDriver): def list_images(self, location=None): """ - return a list of available images - Currently only returns the default 'base OS images' provided by - DimensionData. Customer images (snapshots) are not yet supported. + List images available + + Note: Currently only returns the default 'base OS images' + provided by DimensionData. Customer images (snapshots) + are not yet supported. - @inherits: :class:`NodeDriver.list_images` + :keyword ex_location: Filters the node list to nodes that are + located in this location + :type ex_location: :class:`NodeLocation` or ``str`` + + :return: List of images available + :rtype: ``list`` of :class:`NodeImage` """ params = {} if location is not None: @@ -350,17 +356,20 @@ class DimensionDataNodeDriver(NodeDriver): driver=self.connection.driver), ] - def list_locations(self, id=None): + def list_locations(self, ex_id=None): """ - list locations (datacenters) available for instantiating servers and + List locations (datacenters) available for instantiating servers and networks. - @inherits: :class:`NodeDriver.list_locations` - """ + :keyword ex_id: Filters the location list to this id + :type ex_id: ``str`` + :return: List of locations + :rtype: ``list`` of :class:`NodeLocation` + """ params = {} - if id is not None: - params['id'] = id + if ex_id is not None: + params['id'] = ex_id return self._to_locations( self.connection @@ -685,14 +694,7 @@ class DimensionDataNodeDriver(NodeDriver): :return: a list of DimensionDataNetwork objects :rtype: ``list`` of :class:`DimensionDataNetwork` or ``str`` """ - params = {} - if location is not None: - params['location'] = location_to_location_id(location) - - response = self.connection \ - .request_with_orgId_api_1('networkWithLocation', - params=params).object - return self._to_networks(response) + return self.list_networks(location) def ex_create_network(self, location, name, description=None): """ @@ -710,8 +712,7 @@ class DimensionDataNodeDriver(NodeDriver): :return: A new instance of `DimensionDataNetwork` :rtype: Instance of :class:`DimensionDataNetwork` """ - if location is not None: - network_location = location_to_location_id(location) + network_location = location_to_location_id(location) create_node = ET.Element('NewNetworkWithLocation', {'xmlns': NETWORK_NS}) @@ -807,7 +808,7 @@ class DimensionDataNodeDriver(NodeDriver): Deploy a new network domain to a data center :param location: The data center to list - :type location: :class:`NodeLocation` + :type location: :class:`NodeLocation` or ``str`` :param name: The name of the network domain to create :type name: ``str`` @@ -1036,7 +1037,7 @@ class DimensionDataNodeDriver(NodeDriver): List VLANs available, can filter by location and/or network domain :param location: Only VLANs in this location (optional) - :type location: :class:`NodeLocation` + :type location: :class:`NodeLocation` or ``str`` :param network_domain: Only VLANs in this domain (optional) :type network_domain: :class:`DimensionDataNetworkDomain` @@ -1313,7 +1314,7 @@ class DimensionDataNodeDriver(NodeDriver): """ location = None if id is not None: - location = self.list_locations(id=id)[0] + location = self.list_locations(ex_id=id)[0] return location def ex_wait_for_state(self, state, func, poll_interval=2, @@ -1572,7 +1573,7 @@ class DimensionDataNodeDriver(NodeDriver): Return a list of customer imported images :param location: The target location - :type location: :class:`NodeLocation` + :type location: :class:`NodeLocation` or ``str`` :rtype: ``list`` of :class:`NodeImage` """ http://git-wip-us.apache.org/repos/asf/libcloud/blob/c06ddd64/libcloud/test/compute/fixtures/dimensiondata/caas_2_1_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_infrastructure_datacenter_NA9.xml ---------------------------------------------------------------------- diff --git a/libcloud/test/compute/fixtures/dimensiondata/caas_2_1_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_infrastructure_datacenter_NA9.xml b/libcloud/test/compute/fixtures/dimensiondata/caas_2_1_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_infrastructure_datacenter_NA9.xml new file mode 100644 index 0000000..396ad10 --- /dev/null +++ b/libcloud/test/compute/fixtures/dimensiondata/caas_2_1_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_infrastructure_datacenter_NA9.xml @@ -0,0 +1,54 @@ +<?xml version="1.0" encoding="UTF-8"?> +<datacenters xmlns="urn:didata.com:api:cloud:types" pageNumber="1" pageCount="1" totalCount="1" pageSize="250"> + <datacenter id="NA9" type="MCP 2.0"> + <displayName>US - East 3 - MCP 2.0</displayName> + <city>Ashburn</city> + <state>Virginia</state> + <country>US</country> + <vpnUrl>https://na9.cloud-vpn.net</vpnUrl> + <ftpsHost>ftps-na.cloud-vpn.net</ftpsHost> + <networking type="2" maintenanceStatus="NORMAL"> + <property name="MAX_NODE_CONNECTION_LIMIT" value="100000"/> + <property name="MAX_NODE_CONNECTION_RATE_LIMIT" value="4000"/> + <property name="MAX_VIRTUAL_LISTENER_CONNECTION_LIMIT" value="100000"/> + <property name="MAX_VIRTUAL_LISTENER_CONNECTION_RATE_LIMIT" value="4000"/> + </networking> + <hypervisor type="VMWARE" maintenanceStatus="NORMAL"> + <diskSpeed id="STANDARD" default="true" available="true"> + <displayName>Standard</displayName> + <abbreviation>STD</abbreviation> + <description>Standard Disk Speed</description> + </diskSpeed> + <diskSpeed id="HIGHPERFORMANCE" default="false" available="true"> + <displayName>High Performance</displayName> + <abbreviation>HPF</abbreviation> + <description>Faster than Standard. Uses 15000 RPM disk with Fast Cache.</description> + </diskSpeed> + <diskSpeed id="ECONOMY" default="false" available="true"> + <displayName>Economy</displayName> + <abbreviation>ECN</abbreviation> + <description>Slower than Standard. Uses 7200 RPM disk without Fast Cache.</description> + </diskSpeed> + <cpuSpeed id="STANDARD" default="true" available="true"> + <displayName>Standard</displayName> + <description>Standard CPU Speed</description> + </cpuSpeed> + <cpuSpeed id="HIGHPERFORMANCE" default="false" available="true"> + <displayName>High Performance</displayName> + <description>Faster and more consistent than Standard. Suitable for applications that are more CPU intensive.</description> + </cpuSpeed> + <property name="MIN_DISK_SIZE_GB" value="10"/> + <property name="MAX_DISK_SIZE_GB" value="1000"/> + <property name="MAX_TOTAL_ADDITIONAL_STORAGE_GB" value="14000"/> + <property name="MAX_TOTAL_IMAGE_STORAGE_GB" value="2600"/> + <property name="MAX_CPU_COUNT" value="32"/> + <property name="MIN_MEMORY_GB" value="1"/> + <property name="MAX_MEMORY_GB" value="256"/> + <property name="VMWARE_HARDWARE_VERSION" value="vmx-10"/> + <property name="VLAN_SECURITY_GROUPS_ENABLED" value="false"/> + </hypervisor> + <backup type="COMMVAULT" maintenanceStatus="NORMAL"/> + <consoleAccess maintenanceStatius="NORMAL"/> + <monitoring maintenanceStatus="NORMAL"/> + </datacenter> +</datacenters> http://git-wip-us.apache.org/repos/asf/libcloud/blob/c06ddd64/libcloud/test/compute/test_dimensiondata.py ---------------------------------------------------------------------- diff --git a/libcloud/test/compute/test_dimensiondata.py b/libcloud/test/compute/test_dimensiondata.py index 30cecd9..4ddba15 100644 --- a/libcloud/test/compute/test_dimensiondata.py +++ b/libcloud/test/compute/test_dimensiondata.py @@ -287,6 +287,12 @@ class DimensionDataTests(unittest.TestCase, TestCaseMixin): self.assertEqual(net.id, "208e3a8e-9d2f-11e2-b29c-001517c4643e") self.assertEqual(net.name, "Test Network") + def test_ex_create_network_NO_DESCRIPTION(self): + location = self.driver.ex_get_location_by_id('NA9') + net = self.driver.ex_create_network(location, "Test Network") + self.assertEqual(net.id, "208e3a8e-9d2f-11e2-b29c-001517c4643e") + self.assertEqual(net.name, "Test Network") + def test_ex_delete_network(self): net = self.driver.ex_list_networks()[0] result = self.driver.ex_delete_network(net) @@ -307,6 +313,15 @@ class DimensionDataTests(unittest.TestCase, TestCaseMixin): self.assertEqual(net.name, 'test') self.assertTrue(net.id, 'f14a871f-9a25-470c-aef8-51e13202e1aa') + def test_ex_create_network_domain_NO_DESCRIPTION(self): + location = self.driver.ex_get_location_by_id('NA9') + plan = NetworkDomainServicePlan.ADVANCED + net = self.driver.ex_create_network_domain(location=location, + name='test', + service_plan=plan) + self.assertEqual(net.name, 'test') + self.assertTrue(net.id, 'f14a871f-9a25-470c-aef8-51e13202e1aa') + def test_ex_get_network_domain(self): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') self.assertEqual(net.id, '8cdfd607-f429-4df6-9352-162cfc0891be') @@ -343,6 +358,15 @@ class DimensionDataTests(unittest.TestCase, TestCaseMixin): vlan = self.driver.ex_create_vlan(network_domain=net, name='test', private_ipv4_base_address='10.3.4.0', + private_ipv4_prefix_size='24', + description='test vlan') + self.assertEqual(vlan.id, '0e56433f-d808-4669-821d-812769517ff8') + + def test_ex_create_vlan_NO_DESCRIPTION(self,): + net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') + vlan = self.driver.ex_create_vlan(network_domain=net, + name='test', + private_ipv4_base_address='10.3.4.0', private_ipv4_prefix_size='24') self.assertEqual(vlan.id, '0e56433f-d808-4669-821d-812769517ff8') @@ -520,6 +544,14 @@ class DimensionDataTests(unittest.TestCase, TestCaseMixin): result = self.driver.ex_reconfigure_node(node, 4, 4, 1, 'HIGHPERFORMANCE') self.assertTrue(result) + def test_ex_get_location_by_id(self): + location = self.driver.ex_get_location_by_id('NA9') + self.assertTrue(location.id, 'NA9') + + def test_ex_get_location_by_id_NO_LOCATION(self): + location = self.driver.ex_get_location_by_id(None) + self.assertIsNone(location) + class InvalidRequestError(Exception): def __init__(self, tag): @@ -630,6 +662,11 @@ class DimensionDataMockHttp(MockHttp): 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkWithLocation.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) + def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkWithLocation_NA9(self, method, url, body, headers): + body = self.fixtures.load( + 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkWithLocation.xml') + return (httplib.OK, body, {}, httplib.responses[httplib.OK]) + def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_4bba37be_506f_11e3_b29c_001517c4643e(self, method, url, body, headers): body = self.fixtures.load( @@ -754,6 +791,11 @@ class DimensionDataMockHttp(MockHttp): return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_1_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_infrastructure_datacenter(self, method, url, body, headers): + if url.endswith('id=NA9'): + body = self.fixtures.load( + 'caas_2_1_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_infrastructure_datacenter_NA9.xml') + return (httplib.OK, body, {}, httplib.responses[httplib.OK]) + body = self.fixtures.load( 'caas_2_1_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_infrastructure_datacenter.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK])