DimensionData: Adding in server filters to list nodes to help filter down results
Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/47e214fd Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/47e214fd Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/47e214fd Branch: refs/heads/trunk Commit: 47e214fd570dc370183b241b422977b5cd09bc6f Parents: e14dbf2 Author: Jeffrey Dunham <jeffrey.a.dun...@gmail.com> Authored: Mon Feb 8 13:29:18 2016 -0500 Committer: anthony-shaw <anthony.p.s...@gmail.com> Committed: Wed Feb 10 12:01:54 2016 +1100 ---------------------------------------------------------------------- libcloud/compute/drivers/dimensiondata.py | 123 ++++++++++++++++++++++- libcloud/test/compute/test_dimensiondata.py | 48 +++++++++ 2 files changed, 166 insertions(+), 5 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/libcloud/blob/47e214fd/libcloud/compute/drivers/dimensiondata.py ---------------------------------------------------------------------- diff --git a/libcloud/compute/drivers/dimensiondata.py b/libcloud/compute/drivers/dimensiondata.py index 5955058..3da09b2 100644 --- a/libcloud/compute/drivers/dimensiondata.py +++ b/libcloud/compute/drivers/dimensiondata.py @@ -247,19 +247,61 @@ class DimensionDataNodeDriver(NodeDriver): response_code = findtext(body, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] - def list_nodes(self, ex_location=None): + def list_nodes(self, ex_location=None, ex_name=None, + ex_ipv6=None, ex_ipv4=None, ex_vlan=None, + ex_image=None, ex_deployed=None, + ex_started=None, ex_state=None, + ex_network=None, ex_network_domain=None): """ List nodes deployed for your organization. :keyword ex_location: The location filter - :type location: :class:`NodeLocation` or ``str`` + :type ex_location: :class:`NodeLocation` or ``str`` + + :keyword ex_name: The name filter + :type ex_name ``str`` + + :keyword ex_ipv6: The ipv6 filter + :type ex_ipv6: ``str`` + + :keyword ex_ipv4: The ipv4 filter + :type ex_ipv4: ``str`` + + :keyword ex_vlan: The vlan filter + :type ex_vlan: :class:`DimensionDataVlan` or ``str`` + + :keyword ex_image: The image filter + :type ex_image: :class:`NodeImage` or ``str`` + + :keyword ex_deployed: The deployed filter + :type ex_deployed: ``bool`` + + :keyword ex_started: The started filter + :type ex_started: ``bool`` + + :keyword ex_state: The state filter + :type ex_state: ``str`` + + :keyword ex_network: The network filter + :type ex_notwork: :class:`DimensionDataNetwork` or ``str`` + + :keyword ex_network_domain: The network domain filter + :type ex_notwork_domain: :class:`DimensionDataNetworkDomain` + or ``str`` :return: a list of `Node` objects :rtype: ``list`` of :class:`Node` """ node_list = [] - for nodes in self.ex_list_nodes_paginated(location=ex_location): + for nodes in self.ex_list_nodes_paginated( + location=ex_location, + name=ex_name, ipv6=ex_ipv6, + ipv4=ex_ipv4, vlan=ex_vlan, + image=ex_image, deployed=ex_deployed, + started=ex_started, state=ex_state, + network=ex_network, + network_domain=ex_network_domain): node_list.extend(nodes) return node_list @@ -332,13 +374,46 @@ class DimensionDataNodeDriver(NodeDriver): .request_with_orgId_api_1('networkWithLocation%s' % url_ext) .object) - def ex_list_nodes_paginated(self, location=None): + def ex_list_nodes_paginated(self, name=None, location=None, + ipv6=None, ipv4=None, vlan=None, + image=None, deployed=None, started=None, + state=None, network=None, network_domain=None): """ Return a generator which yields node lists in pages - :keyword ex_location: The location filter + :keyword location: The location filter :type location: :class:`NodeLocation` or ``str`` + :keyword name: The name filter + :type name ``str`` + + :keyword ipv6: The ipv6 filter + :type ipv6: ``str`` + + :keyword ipv4: The ipv4 filter + :type ipv4: ``str`` + + :keyword vlan: The vlan filter + :type vlan: :class:`DimensionDataVlan` or ``str`` + + :keyword image: The image filter + :type image: :class:`NodeImage` or ``str`` + + :keyword deployed: The deployed filter + :type deployed: ``bool`` + + :keyword started: The started filter + :type started: ``bool`` + + :keyword state: The state filter + :type state: ``str`` + + :keyword network: The network filter + :type notwork: :class:`DimensionDataNetwork` or ``str`` + + :keyword network_domain: The network domain filter + :type notwork_domain: :class:`DimensionDataNetworkDomain` or ``str`` + :return: a list of `Node` objects :rtype: ``generator`` of `list` of :class:`Node` """ @@ -350,8 +425,46 @@ class DimensionDataNodeDriver(NodeDriver): else: params['datacenterId'] = location + if ipv6 is not None: + params['ipv6'] = ipv6 + if ipv4 is not None: + params['privateIpv4'] = ipv4 + if state is not None: + params['state'] = state + if started is not None: + params['started'] = started + if deployed is not None: + params['deployed'] = deployed + if name is not None: + params['name'] = name + + if network_domain is not None: + if isinstance(network_domain, DimensionDataNetworkDomain): + params['networkDomainId'] = network_domain.id + else: + params['networkDomainId'] = network_domain + + if network is not None: + if isinstance(network, DimensionDataNetwork): + params['networkId'] = network.id + else: + params['networkId'] = network + + if vlan is not None: + if isinstance(vlan, DimensionDataVlan): + params['vlanId'] = vlan.id + else: + params['vlanId'] = vlan + + if image is not None: + if isinstance(image, NodeImage): + params['sourceImageId'] = image.id + else: + params['sourceImageId'] = image + nodes_obj = self._list_nodes_single_page(params) yield self._to_nodes(nodes_obj) + while nodes_obj.get('pageCount') >= nodes_obj.get('pageSize'): params['pageNumber'] = int(nodes_obj.get('pageNumber')) + 1 nodes_obj = self._list_nodes_single_page(params) http://git-wip-us.apache.org/repos/asf/libcloud/blob/47e214fd/libcloud/test/compute/test_dimensiondata.py ---------------------------------------------------------------------- diff --git a/libcloud/test/compute/test_dimensiondata.py b/libcloud/test/compute/test_dimensiondata.py index 4986183..30cecd9 100644 --- a/libcloud/test/compute/test_dimensiondata.py +++ b/libcloud/test/compute/test_dimensiondata.py @@ -68,6 +68,17 @@ class DimensionDataTests(unittest.TestCase, TestCaseMixin): ret = self.driver.list_nodes() self.assertEqual(len(ret), 4) + # We're making sure here the filters make it to the URL + # See _caas_2_1_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_ALLFILTERS for asserts + def test_list_nodes_response_strings_ALLFILTERS(self): + DimensionDataMockHttp.type = 'ALLFILTERS' + ret = self.driver.list_nodes(ex_location='fake_loc', ex_name='fake_name', + ex_ipv6='fake_ipv6', ex_ipv4='fake_ipv4', ex_vlan='fake_vlan', + ex_image='fake_image', ex_deployed=True, + ex_started=True, ex_state='fake_state', + ex_network='fake_network', ex_network_domain='fake_network_domain') + self.assertTrue(isinstance(ret, list)) + def test_list_nodes_response_LOCATION(self): DimensionDataMockHttp.type = None ret = self.driver.list_locations() @@ -534,6 +545,10 @@ class DimensionDataMockHttp(MockHttp): body = self.fixtures.load('oec_0_9_myaccount.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) + def _oec_0_9_myaccount_ALLFILTERS(self, method, url, body, headers): + body = self.fixtures.load('oec_0_9_myaccount.xml') + return (httplib.OK, body, {}, httplib.responses[httplib.OK]) + def _oec_0_9_base_image(self, method, url, body, headers): body = self.fixtures.load('oec_0_9_base_image.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) @@ -705,6 +720,39 @@ class DimensionDataMockHttp(MockHttp): 'caas_2_1_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_paginated.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) + def _caas_2_1_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_ALLFILTERS(self, method, url, body, headers): + (_, params) = url.split('?') + parameters = params.split('&') + for parameter in parameters: + (key, value) = parameter.split('=') + if key == 'datacenterId': + assert value == 'fake_loc' + elif key == 'networkId': + assert value == 'fake_network' + elif key == 'networkDomainId': + assert value == 'fake_network_domain' + elif key == 'vlanId': + assert value == 'fake_vlan' + elif key == 'ipv6': + assert value == 'fake_ipv6' + elif key == 'privateIpv4': + assert value == 'fake_ipv4' + elif key == 'name': + assert value == 'fake_name' + elif key == 'state': + assert value == 'fake_state' + elif key == 'started': + assert value == 'True' + elif key == 'deployed': + assert value == 'True' + elif key == 'sourceImageId': + assert value == 'fake_image' + else: + raise ValueError("Could not find in url parameters {0}:{1}".format(key, value)) + body = self.fixtures.load( + 'caas_2_1_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server.xml') + return (httplib.OK, body, {}, httplib.responses[httplib.OK]) + def _caas_2_1_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_infrastructure_datacenter(self, method, url, body, headers): body = self.fixtures.load( 'caas_2_1_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_infrastructure_datacenter.xml')