added more tests to tests and test directory. nttcis module for drs uses a decorator to list/filter consistency groups
Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/1935b5f2 Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/1935b5f2 Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/1935b5f2 Branch: refs/heads/trunk Commit: 1935b5f2cff2d8e1d44ead7ab0686dd70d00c93d Parents: 3d3289d Author: mitch <[email protected]> Authored: Mon Nov 5 17:21:30 2018 -0500 Committer: mitch <[email protected]> Committed: Mon Nov 5 17:21:30 2018 -0500 ---------------------------------------------------------------------- libcloud/common/nttcis.py | 31 +++--- libcloud/compute/drivers/nttcis.py | 109 ------------------- libcloud/drs/drivers/nttcis.py | 51 ++++++++- .../drs/fixtures/nttcis/list_cg_by_params.xml | 25 +++++ libcloud/test/drs/test_nttcis.py | 13 +++ tests/lib_list_test.py | 19 +++- 6 files changed, 115 insertions(+), 133 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/libcloud/blob/1935b5f2/libcloud/common/nttcis.py ---------------------------------------------------------------------- diff --git a/libcloud/common/nttcis.py b/libcloud/common/nttcis.py index a26695a..78dc73f 100644 --- a/libcloud/common/nttcis.py +++ b/libcloud/common/nttcis.py @@ -744,13 +744,13 @@ class NttCisPublicIpBlock(object): self.status)) -""" class NttCisServerCpuSpecification(object): - + """ A class that represents the specification of the CPU(s) for a node - + """ def __init__(self, cpu_count, cores_per_socket, performance): + """ Instantiate a new :class:`NttCisServerCpuSpecification` :param cpu_count: The number of CPUs @@ -762,7 +762,7 @@ class NttCisServerCpuSpecification(object): :param performance: The performance type, e.g. HIGHPERFORMANCE :type performance: ``str`` - + """ self.cpu_count = cpu_count self.cores_per_socket = cores_per_socket self.performance = performance @@ -772,13 +772,14 @@ class NttCisServerCpuSpecification(object): 'cpu_count=%s, cores_per_socket=%s, ' 'performance=%s>') % (self.cpu_count, self.cores_per_socket, self.performance)) -""" -""" + + class NttCisServerDisk(object): - + """ A class that represents the disk on a server - + """ def __init__(self, id=None, scsi_id=None, size_gb=None, speed=None, state=None): + """ Instantiate a new :class:`DimensionDataServerDisk` :param id: The id of the disk @@ -795,7 +796,7 @@ class NttCisServerDisk(object): :param state: State of the disk (i.e. PENDING) :type state: ``str`` - + """ self.id = id self.scsi_id = scsi_id self.size_gb = size_gb @@ -809,11 +810,11 @@ class NttCisServerDisk(object): class NttCisScsiController(object): - + """ A class that represents the disk on a server - + """ def __init__(self, id, adapter_type, bus_number, state): - + """ Instantiate a new :class:`DimensionDataServerDisk` :param id: The id of the controller @@ -830,7 +831,7 @@ class NttCisScsiController(object): :param state: State of the disk (i.e. PENDING) :type state: ``str`` - + """ self.id = id self.adapter_type = adapter_type self.bus_number = bus_number @@ -840,7 +841,6 @@ class NttCisScsiController(object): return (('<NttCisScsiController: ' 'id=%s, adapter_type=%s, bus_number=%s, state=%s') % (self.id, self.adapter_type, self.bus_number, self.state)) -""" class NttCisServerVMWareTools(object): @@ -2135,12 +2135,9 @@ class XmlDictConfig(dict): # good idea -- time will tell. It works for the way we are # currently doing XML configuration files... elif element.items(): - items = element.items() # It is possible to have duplicate element tags. If so, convert to a dict of lists - i = element.tag.split('}')[1] if element.tag.split('}')[1] in self: - t = type(self[element.tag.split('}')[1]]) if isinstance(self[element.tag.split('}')[1]], list): self[element.tag.split('}')[1]].append(dict(element.items())) #tmp_list.append(element.tag.split('}')[1]) http://git-wip-us.apache.org/repos/asf/libcloud/blob/1935b5f2/libcloud/compute/drivers/nttcis.py ---------------------------------------------------------------------- diff --git a/libcloud/compute/drivers/nttcis.py b/libcloud/compute/drivers/nttcis.py index d8b4aa3..18e2bdb 100644 --- a/libcloud/compute/drivers/nttcis.py +++ b/libcloud/compute/drivers/nttcis.py @@ -2224,115 +2224,6 @@ class NttCisNodeDriver(NodeDriver): params=params).object return self._to_firewall_rules(response, network_domain) - """ - def ex_create_firewall_rule(self, network_domain, rule, position, - position_relative_to_rule=None): - Creates a firewall rule - :param network_domain: The network domain in which to create - the firewall rule - :type network_domain: :class:`NttCisNetworkDomain` or ``str`` - :param rule: The rule in which to create - :type rule: :class:`NttCisFirewallRule` - :param position: The position in which to create the rule - There are two types of positions - with position_relative_to_rule arg and without it - With: 'BEFORE' or 'AFTER' - Without: 'FIRST' or 'LAST' - :type position: ``str`` - :param position_relative_to_rule: The rule or rule name in - which to decide positioning by - :type position_relative_to_rule: - :class:`NttCisFirewallRule` or ``str`` - :rtype: ``bool`` - positions_without_rule = ('FIRST', 'LAST') - positions_with_rule = ('BEFORE', 'AFTER') - create_node = ET.Element('createFirewallRule', {'xmlns': TYPES_URN}) - ET.SubElement(create_node, "networkDomainId").text = \ - self._network_domain_to_network_domain_id(network_domain) - ET.SubElement(create_node, "name").text = rule.name - ET.SubElement(create_node, "action").text = rule.action - ET.SubElement(create_node, "ipVersion").text = rule.ip_version - ET.SubElement(create_node, "protocol").text = rule.protocol - # Setup source port rule - source = ET.SubElement(create_node, "source") - if rule.source.address_list_id is not None: - source_ip = ET.SubElement(source, 'ipAddressListId') - source_ip.text = rule.source.address_list_id - else: - source_ip = ET.SubElement(source, 'ip') - if rule.source.any_ip: - source_ip.set('address', 'ANY') - else: - source_ip.set('address', rule.source.ip_address) - if rule.source.ip_prefix_size is not None: - source_ip.set('prefixSize', - str(rule.source.ip_prefix_size)) - if rule.source.port_list_id is not None: - source_port = ET.SubElement(source, 'portListId') - source_port.text = rule.source.port_list_id - else: - if rule.source.port_begin is not None: - source_port = ET.SubElement(source, 'port') - source_port.set('begin', rule.source.port_begin) - if rule.source.port_end is not None: - source_port.set('end', rule.source.port_end) - # Setup destination port rule - dest = ET.SubElement(create_node, "destination") - if rule.destination.address_list_id is not None: - dest_ip = ET.SubElement(dest, 'ipAddressListId') - dest_ip.text = rule.destination.address_list_id - else: - dest_ip = ET.SubElement(dest, 'ip') - if rule.destination.any_ip: - dest_ip.set('address', 'ANY') - else: - dest_ip.set('address', rule.destination.ip_address) - if rule.destination.ip_prefix_size is not None: - dest_ip.set('prefixSize', - rule.destination.ip_prefix_size) - if rule.destination.port_list_id is not None: - dest_port = ET.SubElement(dest, 'portListId') - dest_port.text = rule.destination.port_list_id - else: - if rule.destination.port_begin is not None: - dest_port = ET.SubElement(dest, 'port') - dest_port.set('begin', rule.destination.port_begin) - if rule.destination.port_end is not None: - dest_port.set('end', rule.destination.port_end) - # Set up positioning of rule - ET.SubElement(create_node, "enabled").text = str(rule.enabled).lower() - placement = ET.SubElement(create_node, "placement") - if position_relative_to_rule is not None: - if position not in positions_with_rule: - raise ValueError("When position_relative_to_rule is specified" - " position must be %s" - % ', '.join(positions_with_rule)) - if isinstance(position_relative_to_rule, - NttCisFirewallRule): - rule_name = position_relative_to_rule.name - else: - rule_name = position_relative_to_rule - placement.set('relativeToRule', rule_name) - else: - if position not in positions_without_rule: - raise ValueError("When position_relative_to_rule is not" - " specified position must be %s" - % ', '.join(positions_without_rule)) - placement.set('position', position) - - response = self.connection.request_with_orgId_api_2( - 'network/createFirewallRule', - method='POST', - data=ET.tostring(create_node)).object - - rule_id = None - for info in findall(response, 'info', TYPES_URN): - if info.get('name') == 'firewallRuleId': - rule_id = info.get('value') - rule.id = rule_id - return rule - """ - def ex_create_firewall_rule(self, network_domain, name, action, ip_version, protocol, source_addr, dest_addr, http://git-wip-us.apache.org/repos/asf/libcloud/blob/1935b5f2/libcloud/drs/drivers/nttcis.py ---------------------------------------------------------------------- diff --git a/libcloud/drs/drivers/nttcis.py b/libcloud/drs/drivers/nttcis.py index 49d1986..d97b632 100644 --- a/libcloud/drs/drivers/nttcis.py +++ b/libcloud/drs/drivers/nttcis.py @@ -1,3 +1,5 @@ +import re +import functools from libcloud.utils.py3 import ET from libcloud.common.nttcis import NttCisConnection from libcloud.common.nttcis import API_ENDPOINTS @@ -10,6 +12,26 @@ from libcloud.utils.xml import fixxpath, findtext, findall from libcloud.common.types import LibcloudError +def get_params(func): + @functools.wraps(func) + def paramed(*args, **kwargs): + + if kwargs: + for k, v in kwargs.items(): + old_key = k + matches = re.findall(r'_(\w)', k) + for match in matches: + k = k.replace('_'+match, match.upper()) + del kwargs[old_key] + kwargs[k] = v + params = kwargs + result = func(args[0], params) + else: + result = func(args[0]) + return result + return paramed + + class NttCisDRSDriver(Driver): """ NttCis node driver. @@ -90,14 +112,36 @@ class NttCisDRSDriver(Driver): response_code = findtext(response, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] - def list_consistency_groups(self): - #params = {'networkDomainId': ex_network_domain_id} + @get_params + def list_consistency_groups(self, params={}): + """ + Functions takes a named parameter that must be one of the following + :param params: A dictionary composed of one of the follwing keys and a value + target_data_center_id: + source_network_domain_id: + target_network_domain_id: + source_server_id: + target_server_id: + name: + state: + operation_status: + drs_infrastructure_status: + :return: `list` of :class: `NttCisConsistencyGroup` + """ + response = self.connection.request_with_orgId_api_2( - 'consistencyGroup/consistencyGroup').object + 'consistencyGroup/consistencyGroup', params=params).object cgs = self._to_consistency_groups(response) return cgs def get_consistency_group(self, consistency_group_id): + """ + Retrieves a Consistency by it's id and is more efficient thatn listing + all consistency groups and filtering that result. + :param consistency_group_id: An id of a consistency group + :type consistency_group_id: ``str`` + :return: :class: `NttCisConsistencygroup` + """ response = self.connection.request_with_orgId_api_2( "consistencyGroup/consistencyGroup/%s" % consistency_group_id ).object @@ -119,7 +163,6 @@ class NttCisDRSDriver(Driver): return [self._to_process(el) for el in cgs] def _to_snapshots(self, object): - elem = findall(object, "consistencyGroupSnapshots", TYPES_URN) snapshots = [] for element in object.findall(fixxpath("snapshot", TYPES_URN)): snapshots.append(self._to_process(element)) http://git-wip-us.apache.org/repos/asf/libcloud/blob/1935b5f2/libcloud/test/drs/fixtures/nttcis/list_cg_by_params.xml ---------------------------------------------------------------------- diff --git a/libcloud/test/drs/fixtures/nttcis/list_cg_by_params.xml b/libcloud/test/drs/fixtures/nttcis/list_cg_by_params.xml new file mode 100644 index 0000000..0115461 --- /dev/null +++ b/libcloud/test/drs/fixtures/nttcis/list_cg_by_params.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<consistencyGroups xmlns="urn:didata.com:api:cloud:types" pageNumber="1" pageCount="1" totalCount="1" pageSize="250"> + <consistencyGroup id="3710c093-7dcc-4a21-bd07-af9f4d93b6b5"><name>sdk_test2_cg</name> + <description>A test consistency group</description><journal sizeGb="100" extentCount="1"/> + <source datacenterId="NADRAASLAB01" networkDomainId="f9d6a249-c922-4fa1-9f0f-de5b452c4026"> + <networkDomainName>DRS-ProdEng-East-ND1</networkDomainName> + </source> + <target datacenterId="NADRAASLAB02" networkDomainId="e46c8815-193f-402d-b8a5-682eaa646fb2"> + <networkDomainName>DRS-ProdEng-West-ND1</networkDomainName> + </target> + <serverPair id="de9f0a6b-db84-4ffa-aacf-796f694c29f2" state="NORMAL"> + <sourceServer id="032f3967-00e4-4780-b4ef-8587460f9dd4" primaryNicIpv4="192.168.12.8" primaryNicIpv6="2607:f480:111:1426:3dc9:25dc:4985:81b2"> + <name>src-sdk-test</name> + </sourceServer> + <targetServer id="aee58575-38e2-495f-89d3-854e6a886411" primaryNicIpv4="192.168.22.7" primaryNicIpv6="2607:f480:211:1159:2dff:40ed:ee7c:4738"> + <name>tgt-sdk-test</name> + </targetServer> + </serverPair> + <createTime>2018-10-31T16:02:05.000Z</createTime> + <operationStatus>DRS_MODE</operationStatus> + <drsInfrastructure enabled="true" status="ACTIVE" updateTime="2018-11-05T16:35:01.000Z"/> + <drsStatusCheckFailureCount>0</drsStatusCheckFailureCount> + <state>NORMAL</state> + </consistencyGroup> +</consistencyGroups> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/libcloud/blob/1935b5f2/libcloud/test/drs/test_nttcis.py ---------------------------------------------------------------------- diff --git a/libcloud/test/drs/test_nttcis.py b/libcloud/test/drs/test_nttcis.py index 9e99d49..7431a25 100644 --- a/libcloud/test/drs/test_nttcis.py +++ b/libcloud/test/drs/test_nttcis.py @@ -48,6 +48,11 @@ def test_get_consistency_group(driver): assert cg.id == "3710c093-7dcc-4a21-bd07-af9f4d93b6b5" +def test_get_consistency_group_by_name(driver): + cgs = driver.list_consistency_groups(name="skd_test2_cg") + assert cgs[0].id == "3710c093-7dcc-4a21-bd07-af9f4d93b6b5" + + class NttCisMockHttp(MockHttp): fixtures = DRSFileFixtures('nttcis') @@ -85,3 +90,11 @@ class NttCisMockHttp(MockHttp): headers): body = self.fixtures.load("get_consistency_group.xml") return (httplib.OK, body, {}, httplib.responses[httplib.OK]) + + def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_consistencyGroup_consistencyGroup_name(self, + method, + url, + body, + headers): + body = self.fixtures.load("list_cg_by_params.xml") + return (httplib.OK, body, {}, httplib.responses[httplib.OK]) \ No newline at end of file http://git-wip-us.apache.org/repos/asf/libcloud/blob/1935b5f2/tests/lib_list_test.py ---------------------------------------------------------------------- diff --git a/tests/lib_list_test.py b/tests/lib_list_test.py index 0563f9a..81e88a5 100644 --- a/tests/lib_list_test.py +++ b/tests/lib_list_test.py @@ -394,10 +394,23 @@ def test_list_health_monitors(compute_driver, lbdriver): def test_list_consistency_groups(drsdriver): cgs = drsdriver.list_consistency_groups() - return cgs + for cg in cgs: + print(cg.name) -def test_get_consistency_group(drsdriver): +def test_list_cg_by_src_net_domain(drsdriver): + nd = "f9d6a249-c922-4fa1-9f0f-de5b452c4026" + cgs = drsdriver.list_consistency_groups(source_network_domain_id=nd) + assert cgs[0].name == "sdk_test2_cg" + + +def test_list_cg_by_name(drsdriver): + name = "sdk_test2_cg" + cg = drsdriver.list_consistency_groups(name=name) + assert cg[0].id == "3710c093-7dcc-4a21-bd07-af9f4d93b6b5" + + +def test_get_consistency_group_by_id(drsdriver): cgs = drsdriver.list_consistency_groups() cg_id = [i for i in cgs if i.name == "sdk_test2_cg"][0].id cg = drsdriver.get_consistency_group(cg_id) @@ -408,4 +421,4 @@ def test_get_snapshots(drsdriver): cgs = drsdriver.list_consistency_groups() cg_id = [i for i in cgs if i.name == "sdk_test2_cg"][0].id snaps = drsdriver.list_consistency_group_snapshots(cg_id) - print(cg_id) \ No newline at end of file + assert hasattr(snaps, 'journalUsageGb') \ No newline at end of file
