From b5ad930c913eb2eeaaa88e19e40f7c176b81d090 Mon Sep 17 00:00:00 2001 From: wegotthekeys Date: Fri, 25 Jan 2019 11:40:16 -0500 Subject: [PATCH 1/7] Python 3 modifications --- pyxcli/client.py | 20 ++++++++++++++------ pyxcli/helpers/xml_util.py | 6 +++--- pyxcli/response.py | 19 ++++++++++--------- pyxcli/transports.py | 9 +++++---- requirements.txt | 2 +- 5 files changed, 33 insertions(+), 23 deletions(-) diff --git a/pyxcli/client.py b/pyxcli/client.py index e656da4..b9034d2 100644 --- a/pyxcli/client.py +++ b/pyxcli/client.py @@ -203,7 +203,7 @@ def connect_ssl(cls, user, password, endpoints, Creates an SSL transport to the first endpoint (aserver) to which we successfully connect """ - if isinstance(endpoints, basestring): + if isinstance(endpoints, str): endpoints = [endpoints] transport = SingleEndpointTransport( SocketTransport.connect_ssl, endpoints, ca_certs=ca_certs, @@ -223,7 +223,7 @@ def connect_multiendpoint_ssl(cls, user, password, endpoints, on the system to discover all management IP interfaces and add them to the list of endpoints """ - if isinstance(endpoints, basestring): + if isinstance(endpoints, str): endpoints = [endpoints] client, transport = cls._initiate_client_for_multi_endpoint(user, password, @@ -261,7 +261,7 @@ def _dump_xcli(self, obj): return str(obj) def _build_command(self, cmd, params, options, remote_target=None): - root = etree.Element("command", id=str(self._cmdindex.next()), + root = etree.Element("command", id=str(next(self._cmdindex)), type=cmd, close_on_return="no") if remote_target: root.attrib["remote_target"] = remote_target @@ -273,8 +273,16 @@ def _build_command(self, cmd, params, options, remote_target=None): root.append(etree.Element("argument", name=self._dump_xcli(k), value=self._dump_xcli(v))) data = etree.tostring(root) - anon = data.replace(options["password"], - "XXX") if "password" in options else data + + if("password" in options): + data = data.decode() + data.replace(options["password"], "XXX") + data.encode() + + anon = data + + # anon = data.replace(options["password"], + # "XXX") if "password" in options else data xlog.debug("SEND %s" % (anon)) return data @@ -418,4 +426,4 @@ def execute(self, cmd, **kwargs): def execute_remote(self, *args, **kwargs): # you can't chain clients, a limitation of the XIV machine - raise NotImplementedError() + raise NotImplementedError() \ No newline at end of file diff --git a/pyxcli/helpers/xml_util.py b/pyxcli/helpers/xml_util.py index 534bb90..a28955e 100644 --- a/pyxcli/helpers/xml_util.py +++ b/pyxcli/helpers/xml_util.py @@ -49,7 +49,7 @@ def str_brief(obj, lim=20, dots='...', use_repr=True): >>> str_brief(2 ** 50, lim=10, dots='0') '11258999060' """ - if isinstance(obj, basestring) or not use_repr: + if isinstance(obj, str) or not use_repr: full = str(obj) else: full = repr(obj) @@ -189,7 +189,7 @@ class TerminationDetectingXMLParser(object): def __init__(self): self.tree_builder = _TerminationDetectingTreeBuilder() - self.xml_tree_builder = et.XMLTreeBuilder(target=self.tree_builder) + self.xml_tree_builder = et.XMLParser(target=self.tree_builder) def feed(self, chunk): with _translateExceptions(chunk): @@ -202,4 +202,4 @@ def close(self): @property def root_element_closed(self): - return self.tree_builder.root_element_closed + return self.tree_builder.root_element_closed \ No newline at end of file diff --git a/pyxcli/response.py b/pyxcli/response.py index 17f407d..c982a71 100644 --- a/pyxcli/response.py +++ b/pyxcli/response.py @@ -23,9 +23,10 @@ """ -from bunch import Bunch +from munch import Munch from pyxcli.helpers import xml_util as etree - +import base64 +import codecs class XCLIResponse(object): RETURN_PATH = "return" @@ -38,7 +39,8 @@ def instantiate(cls, cmdroot, encoding): compressed = cmdroot.find("compressed_return") if compressed is not None: text = compressed.attrib["value"] - raw = text.decode(encoding).decode("zlib") + raw = base64.b64decode(text) + raw = (codecs.decode(raw, "zlib")).decode('ascii') cmdroot.append(etree.fromstring("%s" % (raw,))) cmdroot.remove(compressed) @@ -103,9 +105,9 @@ def __len__(self): return len(self.as_list) def __getitem__(self, item): - if isinstance(item, basestring): + if isinstance(item, str): return self.all(item) - elif isinstance(item, (int, long)): + elif isinstance(item, int): return list(self.all())[item] else: @@ -128,11 +130,10 @@ def _populate_bunch_with_element(element): """ if 'value' in element.attrib: return element.get('value') - current_bunch = Bunch() + current_bunch = Munch() if element.get('id'): current_bunch['nextra_element_id'] = element.get('id') for subelement in element.getchildren(): - current_bunch[subelement.tag] = _populate_bunch_with_element( - subelement) - return current_bunch + current_bunch[subelement.tag] = _populate_bunch_with_element(subelement) + return current_bunch \ No newline at end of file diff --git a/pyxcli/transports.py b/pyxcli/transports.py index 1b2c562..d8a43ae 100644 --- a/pyxcli/transports.py +++ b/pyxcli/transports.py @@ -223,7 +223,8 @@ def send(self, data, timeout=None): while data: chunk = data[:self.MAX_IO_CHUNK] - sent = self.sock.send(chunk) + byte_chunk = chunk.encode() + sent = self.sock.send(byte_chunk) data = data[sent:] parser = TerminationDetectingXMLParser() @@ -233,7 +234,7 @@ def send(self, data, timeout=None): chunk = self.sock.recv(self.MAX_IO_CHUNK) if not chunk: break - raw += chunk + raw += chunk.decode() parser.feed(chunk) return parser.close() except XMLException as ex: @@ -307,7 +308,7 @@ def close(self): self.connector = None def add_endpoints(self, endpoints): - if isinstance(endpoints, basestring): + if isinstance(endpoints, str): endpoints = [endpoints] self.available_endpoints.extend(endpoints) @@ -353,4 +354,4 @@ def send(self, *args): self.transport.close() self.transport = ClosedTransport xlog.debug("MultiEndpointTransport: sending over %s failed", - self.transport) + self.transport) \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 4f454c3..3d7d7ec 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ -bunch +munch From fc872dc75bd05ae92483cb57f920c258836709df Mon Sep 17 00:00:00 2001 From: wegotthekeys Date: Fri, 25 Jan 2019 13:12:30 -0500 Subject: [PATCH 2/7] Travis --- .travis.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100755 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100755 index 0000000..b34d47c --- /dev/null +++ b/.travis.yml @@ -0,0 +1,15 @@ +language: python +dist: xenial +python: +  - "2.6" +  - "2.7" +  - "3.4" +  - "3.5" +  - "3.6" +  - "3.7" +sudo: true +install: +  - pip install -r test-requirements.txt +  - pip install -r requirements.txt +script: +  - nosetest -v \ No newline at end of file From 51b4c0496e7cd590a9ff5bb736149f8c0a20f26a Mon Sep 17 00:00:00 2001 From: wegotthekeys Date: Fri, 25 Jan 2019 13:16:33 -0500 Subject: [PATCH 3/7] Travis command fix --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b34d47c..403ae8f 100755 --- a/.travis.yml +++ b/.travis.yml @@ -12,4 +12,4 @@ install:   - pip install -r test-requirements.txt   - pip install -r requirements.txt script: -  - nosetest -v \ No newline at end of file +  - nosetests -v \ No newline at end of file From f310ad46c756cf42cc544f0223b85f2b90ee2121 Mon Sep 17 00:00:00 2001 From: wegotthekeys Date: Fri, 25 Jan 2019 13:19:04 -0500 Subject: [PATCH 4/7] travis tests fix --- pyxcli/events/events.py | 2 +- pyxcli/mirroring/mirrored_entities.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyxcli/events/events.py b/pyxcli/events/events.py index 7f92a1e..c31fb4e 100644 --- a/pyxcli/events/events.py +++ b/pyxcli/events/events.py @@ -24,7 +24,7 @@ import json from socket import getfqdn -from bunch import Bunch +from munch import Munch as Bunch from logging import getLogger from pyxcli import XCLI_DEFAULT_LOGGER from pyxcli.events.platform_info import get_platform_details diff --git a/pyxcli/mirroring/mirrored_entities.py b/pyxcli/mirroring/mirrored_entities.py index e67f49a..14a5105 100644 --- a/pyxcli/mirroring/mirrored_entities.py +++ b/pyxcli/mirroring/mirrored_entities.py @@ -15,7 +15,7 @@ ############################################################################## from logging import getLogger -from bunch import Bunch +from munch import Munch as Bunch from pyxcli import XCLI_DEFAULT_LOGGER CG = "cg" From b816cc2733a9a8353fbad01242124ee1644ccfea Mon Sep 17 00:00:00 2001 From: wegotthekeys Date: Fri, 25 Jan 2019 13:23:46 -0500 Subject: [PATCH 5/7] remove 2.6 from travis --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 403ae8f..d85d314 100755 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,6 @@ language: python dist: xenial python: -  - "2.6"   - "2.7"   - "3.4"   - "3.5" From 5e25f05180df6a42d4b0335f745301691165975a Mon Sep 17 00:00:00 2001 From: wegotthekeys Date: Fri, 25 Jan 2019 14:13:17 -0500 Subject: [PATCH 6/7] python 2 break fixes --- pyxcli/client.py | 9 +++++++-- pyxcli/helpers/xml_util.py | 7 ++++++- pyxcli/response.py | 14 ++++++++++++-- pyxcli/transports.py | 7 ++++++- 4 files changed, 31 insertions(+), 6 deletions(-) diff --git a/pyxcli/client.py b/pyxcli/client.py index b9034d2..bef194f 100644 --- a/pyxcli/client.py +++ b/pyxcli/client.py @@ -40,6 +40,11 @@ from pyxcli.response import XCLIResponse from pyxcli.helpers.exceptool import chained +try: + basestring +except NameError: + basestring = str + xlog = getLogger(XCLI_DEFAULT_LOGGER) @@ -203,7 +208,7 @@ def connect_ssl(cls, user, password, endpoints, Creates an SSL transport to the first endpoint (aserver) to which we successfully connect """ - if isinstance(endpoints, str): + if isinstance(endpoints, basestring): endpoints = [endpoints] transport = SingleEndpointTransport( SocketTransport.connect_ssl, endpoints, ca_certs=ca_certs, @@ -223,7 +228,7 @@ def connect_multiendpoint_ssl(cls, user, password, endpoints, on the system to discover all management IP interfaces and add them to the list of endpoints """ - if isinstance(endpoints, str): + if isinstance(endpoints, basestring): endpoints = [endpoints] client, transport = cls._initiate_client_for_multi_endpoint(user, password, diff --git a/pyxcli/helpers/xml_util.py b/pyxcli/helpers/xml_util.py index a28955e..b45f5fe 100644 --- a/pyxcli/helpers/xml_util.py +++ b/pyxcli/helpers/xml_util.py @@ -19,6 +19,11 @@ from contextlib import contextmanager from xml.parsers.expat import ExpatError +try: + basestring +except NameError: + basestring = str + Element = cet.Element tostring = cet.tostring @@ -49,7 +54,7 @@ def str_brief(obj, lim=20, dots='...', use_repr=True): >>> str_brief(2 ** 50, lim=10, dots='0') '11258999060' """ - if isinstance(obj, str) or not use_repr: + if isinstance(obj, basestring) or not use_repr: full = str(obj) else: full = repr(obj) diff --git a/pyxcli/response.py b/pyxcli/response.py index c982a71..11915f5 100644 --- a/pyxcli/response.py +++ b/pyxcli/response.py @@ -28,6 +28,16 @@ import base64 import codecs +try: + basestring +except NameError: + basestring = str + +try: + long +except NameError: + long = int + class XCLIResponse(object): RETURN_PATH = "return" @@ -105,9 +115,9 @@ def __len__(self): return len(self.as_list) def __getitem__(self, item): - if isinstance(item, str): + if isinstance(item, basestring): return self.all(item) - elif isinstance(item, int): + elif isinstance(item, (int,long)): return list(self.all())[item] else: diff --git a/pyxcli/transports.py b/pyxcli/transports.py index d8a43ae..c415a4a 100644 --- a/pyxcli/transports.py +++ b/pyxcli/transports.py @@ -34,6 +34,11 @@ from pyxcli.errors import CorruptResponse from pyxcli.errors import BaseScsiException +try: + basestring +except NameError: + basestring = str + xlog = getLogger(XCLI_DEFAULT_LOGGER) @@ -308,7 +313,7 @@ def close(self): self.connector = None def add_endpoints(self, endpoints): - if isinstance(endpoints, str): + if isinstance(endpoints, basestring): endpoints = [endpoints] self.available_endpoints.extend(endpoints) From afee5cbf0c37124dd3b22c03c610b5467eb38f7b Mon Sep 17 00:00:00 2001 From: "Slapelis, Daniel" Date: Tue, 29 Jan 2019 21:17:44 -0500 Subject: [PATCH 7/7] Cleaning up tests and removing commented code. --- pyxcli/client.py | 5 +---- pyxcli/events/events.py | 4 ++-- pyxcli/mirroring/mirrored_entities.py | 4 ++-- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/pyxcli/client.py b/pyxcli/client.py index bef194f..dd296db 100644 --- a/pyxcli/client.py +++ b/pyxcli/client.py @@ -285,9 +285,6 @@ def _build_command(self, cmd, params, options, remote_target=None): data.encode() anon = data - - # anon = data.replace(options["password"], - # "XXX") if "password" in options else data xlog.debug("SEND %s" % (anon)) return data @@ -431,4 +428,4 @@ def execute(self, cmd, **kwargs): def execute_remote(self, *args, **kwargs): # you can't chain clients, a limitation of the XIV machine - raise NotImplementedError() \ No newline at end of file + raise NotImplementedError() diff --git a/pyxcli/events/events.py b/pyxcli/events/events.py index c31fb4e..da4474d 100644 --- a/pyxcli/events/events.py +++ b/pyxcli/events/events.py @@ -24,7 +24,7 @@ import json from socket import getfqdn -from munch import Munch as Bunch +from munch import Munch from logging import getLogger from pyxcli import XCLI_DEFAULT_LOGGER from pyxcli.events.platform_info import get_platform_details @@ -86,7 +86,7 @@ def send_event(self, action, properties, event_severity=EVENT_SEVERITY): raise TypeError('properties is not dict') # prepare event - event_bunch = Bunch( + event_bunch = Munch( Product=self.product_name, Version=self.product_version, Server=self.server_name, diff --git a/pyxcli/mirroring/mirrored_entities.py b/pyxcli/mirroring/mirrored_entities.py index 14a5105..8cd35a1 100644 --- a/pyxcli/mirroring/mirrored_entities.py +++ b/pyxcli/mirroring/mirrored_entities.py @@ -15,7 +15,7 @@ ############################################################################## from logging import getLogger -from munch import Munch as Bunch +from munch import Munch from pyxcli import XCLI_DEFAULT_LOGGER CG = "cg" @@ -60,7 +60,7 @@ def get_mirror_resources_by_name_map(self, scope=None): for xcli_mirror in self.xcli_client.cmd.mirror_list(scope='CG'): name = MirroredEntities.get_mirrored_object_name(xcli_mirror) cgs_mirrors_by_name[name] = xcli_mirror - res = Bunch(volumes=volumes_mirrors_by_name, cgs=cgs_mirrors_by_name) + res = Munch(volumes=volumes_mirrors_by_name, cgs=cgs_mirrors_by_name) return res def get_cg_mirrors(self):