diff --git a/README.rst b/README.rst index 4b4cf50..cb69f58 100644 --- a/README.rst +++ b/README.rst @@ -9,10 +9,15 @@ NOTE:: DRAFT - WORK IN PROGRESS - The current Redfish specification revision is 1.0.0 - Note that the mockup - is still at version 0.99.0a and may not reflect what the standard provides + The current Redfish specification revision is 1.0.0 - Note that the mockup + is still at version 0.99.0a and may not reflect what the standard provides fully +Documentation +------------- + +The full documentation is available at +http://pythonhosted.org/python-redfish/installation.html Project Structure ------------------- @@ -35,7 +40,7 @@ for build and test automation:: Requirements ------------ -To use the enclosed examples, you will need Python 2.7 +To use the enclosed examples, you will need Python 2.7 or Python 3.4 (https://www.python.org/downloads/). Note that Python 2.7.9 enforces greater SSL verification requiring server certificates be installed. Parameters to relax the requirements are available in the library, but these configurations @@ -44,6 +49,9 @@ are discouraged due to security. Python requirements are listed in requirements.txt; additional requirements for running the unit test suite are listed in test-requirements.txt. +Note: The program was tested with Python 2.7.10 and 3.4.2 however it might work +as well with all Python 3 releases. + Get the sources --------------- diff --git a/doc/source/faq.rst b/doc/source/faq.rst new file mode 100644 index 0000000..8e53b2a --- /dev/null +++ b/doc/source/faq.rst @@ -0,0 +1,11 @@ +=== +FAQ +=== + +- Q1 : error in setup command: Invalid environment marker: (python_version < '3') + + This error is caused by old setuptools revisions that do not understant "python_version < '3'". + Upgrade setuptools using:: + + pip install --upgrade setuptools + diff --git a/doc/source/index.rst b/doc/source/index.rst index 15abfa7..2de689e 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -18,6 +18,7 @@ Contents: testing classesdoc contributing + faq help Indices and tables diff --git a/doc/source/testing.rst b/doc/source/testing.rst index ac94b45..dd0d90c 100644 --- a/doc/source/testing.rst +++ b/doc/source/testing.rst @@ -15,6 +15,10 @@ refish-client tests #. Install docker using the `procedure `_. #. Ensure you can use docker with your current user. #. Jump into redfish-python directory containing the sources. +#. Depending of your distribution, you may have to upgrade setuptools:: + + pip install --upgrade setuptools + #. Install required modules for testings:: pip install -t test-requirements.txt diff --git a/examples/__init__.py b/examples/__init__.py index acef755..13c5e6a 100644 --- a/examples/__init__.py +++ b/examples/__init__.py @@ -1 +1,8 @@ -__author__ = 'deva' +# coding=utf-8 +from __future__ import unicode_literals +from __future__ import print_function +from __future__ import division +from __future__ import absolute_import +from future import standard_library +standard_library.install_aliases() +__author__ = 'uggla' diff --git a/examples/simple-proliant.py b/examples/simple-proliant.py index 451b7a1..a2f2a54 100644 --- a/examples/simple-proliant.py +++ b/examples/simple-proliant.py @@ -1,6 +1,13 @@ # coding=utf-8 """ Simple example to use python-redfish on HP Proliant servers """ +from __future__ import unicode_literals +from __future__ import print_function +from __future__ import division +from __future__ import absolute_import +from future import standard_library +standard_library.install_aliases() +from builtins import str import os import sys diff --git a/examples/simple-simulator.py b/examples/simple-simulator.py index df44ca5..3e73387 100644 --- a/examples/simple-simulator.py +++ b/examples/simple-simulator.py @@ -1,6 +1,12 @@ # coding=utf-8 """ Simple example to use python-redfish with DMTF simulator """ +from __future__ import unicode_literals +from __future__ import print_function +from __future__ import division +from __future__ import absolute_import +from future import standard_library +standard_library.install_aliases() import os import sys diff --git a/redfish-client/redfish-client b/redfish-client/redfish-client index 917892e..c6d1ddb 100755 --- a/redfish-client/redfish-client +++ b/redfish-client/redfish-client @@ -28,9 +28,17 @@ redfish-client :: --libdebugfile FILE Specify python-redfish library log file [default: /var/log/python-redfish/python-redfish.log] config commands : manage the configuration file. - manager commands : manage the manager (Ligh out management). If + manager commands : manage the manager (Light out management). If is not provided use the 'default' entry ''' +from __future__ import unicode_literals +from __future__ import print_function +from __future__ import division +from __future__ import absolute_import +from future import standard_library +standard_library.install_aliases() +from builtins import str +from builtins import object import os import sys @@ -38,7 +46,7 @@ import json import pprint import docopt import logging -import ConfigParser +import configparser import jinja2 import requests.packages.urllib3 import redfish @@ -268,7 +276,7 @@ if __name__ == '__main__': % (e.message, jinja2_env.loader.searchpath[0])) sys.exit(1) - print template.render(r=remote_mgmt) + print(template.render(r=remote_mgmt)) ################################################################# # Main program @@ -340,7 +348,7 @@ if __name__ == '__main__': logger.debug("Home directory : %s" % HOME) # Load config - config = ConfigParser.ConfigParser(allow_no_value=True) + config = configparser.ConfigParser(allow_no_value=True) logger.debug("Read configuration file") configfile = 'PBCONFFILE' diff --git a/redfish-client/tests/Dockerfile.debian b/redfish-client/tests/Dockerfile.debian index bb09658..e5c01fc 100644 --- a/redfish-client/tests/Dockerfile.debian +++ b/redfish-client/tests/Dockerfile.debian @@ -6,6 +6,9 @@ apt-get install -y python-pip COPY python-redfish.src.tar.gz /python-redfish.src.tar.gz RUN mkdir /var/log/python-redfish RUN tar xvvf python-redfish.src.tar.gz +# Need a really recent version of setuptools to support +# configparser>=3.3.0; python_version < '3' in requirements.txt +RUN pip install --upgrade setuptools RUN cd python-redfish* && \ pip install -r requirements.txt && \ python setup.py install diff --git a/redfish-client/tests/Dockerfile.fedora b/redfish-client/tests/Dockerfile.fedora index 4770d9f..b28b8dd 100644 --- a/redfish-client/tests/Dockerfile.fedora +++ b/redfish-client/tests/Dockerfile.fedora @@ -1,6 +1,5 @@ FROM fedora:23 RUN dnf install -y python-pip && \ -dnf install -y git && \ dnf install -y tar COPY python-redfish.src.tar.gz /python-redfish.src.tar.gz RUN mkdir /var/log/python-redfish diff --git a/redfish-client/tests/Dockerfile.fedorap3 b/redfish-client/tests/Dockerfile.fedorap3 new file mode 100644 index 0000000..f2fbc89 --- /dev/null +++ b/redfish-client/tests/Dockerfile.fedorap3 @@ -0,0 +1,11 @@ +FROM fedora:23 +RUN dnf install -y python3-pip && \ +dnf install -y tar +COPY python-redfish.src.tar.gz /python-redfish.src.tar.gz +RUN mkdir /var/log/python-redfish +RUN tar xvvf python-redfish.src.tar.gz +RUN cd python-redfish* && \ +pip3 install -r requirements.txt && \ +python3 setup.py install +CMD ["/bin/bash"] + diff --git a/redfish-client/tests/Dockerfile.fedorapip b/redfish-client/tests/Dockerfile.fedorapip index dfb0cad..4d29b63 100644 --- a/redfish-client/tests/Dockerfile.fedorapip +++ b/redfish-client/tests/Dockerfile.fedorapip @@ -1,6 +1,5 @@ FROM fedora:23 -RUN dnf install -y python-pip && \ -dnf install -y git +RUN dnf install -y python-pip RUN mkdir /var/log/python-redfish RUN pip install python-redfish CMD ["/bin/bash"] diff --git a/redfish-client/tests/Dockerfile.ubuntu b/redfish-client/tests/Dockerfile.ubuntu index c77091c..1b9e542 100644 --- a/redfish-client/tests/Dockerfile.ubuntu +++ b/redfish-client/tests/Dockerfile.ubuntu @@ -6,6 +6,9 @@ apt-get install -y python-pip COPY python-redfish.src.tar.gz /python-redfish.src.tar.gz RUN mkdir /var/log/python-redfish RUN tar xvvf python-redfish.src.tar.gz +# Need a really recent version of setuptools to support +# configparser>=3.3.0; python_version < '3' in requirements.txt +RUN pip install --upgrade setuptools RUN cd python-redfish* && \ pip install -r requirements.txt && \ python setup.py install diff --git a/redfish-client/tests/test_client.py b/redfish-client/tests/test_client.py index 7cd157d..1f41752 100644 --- a/redfish-client/tests/test_client.py +++ b/redfish-client/tests/test_client.py @@ -1,3 +1,10 @@ +from __future__ import unicode_literals +from __future__ import print_function +from __future__ import division +from __future__ import absolute_import +from future import standard_library +standard_library.install_aliases() +from builtins import object # coding=utf-8 import os import stat @@ -7,7 +14,7 @@ from docker import Client from path import Path -class DockerTest(): +class DockerTest(object): def __init__(self): self.cli = Client(base_url='unix://var/run/docker.sock') @@ -30,7 +37,7 @@ class DockerTest(): self.cli.wait(container=container.get('Id')) response = self.cli.logs(container=container.get('Id'), stdout=True) - return(response) + return(response.decode('utf8')) def test_dockersocket(): @@ -49,7 +56,7 @@ def test_docker(): def test_sources(): output = subprocess.check_output(["python", "setup.py", "sdist"]) - search = re.search(r"removing '(\S+)'", output) + search = re.search(r"removing '(\S+)'", str(output)) filename = Path('dist/' + search.group(1) + '.tar.gz') filename.copy('redfish-client/tests/python-redfish.src.tar.gz') assert Path('redfish-client/tests/python-redfish.src.tar.gz').isfile() @@ -57,20 +64,23 @@ def test_sources(): def test_dockerbuild(): docker = DockerTest() + # Warning : Image tag is derived from file name, do not use uppercase !!! dockerfiles = ('redfish-client/tests/Dockerfile.ubuntu', 'redfish-client/tests/Dockerfile.debian', 'redfish-client/tests/Dockerfile.fedora', + 'redfish-client/tests/Dockerfile.fedorap3', 'redfish-client/tests/Dockerfile.fedorapip') for dockerfile in dockerfiles: print('Testing : {}'.format(dockerfile)) response = docker.build(dockerfile) - status = response.pop() + status = str(response.pop()) assert 'Successfully built' in status def test_install(): docker = DockerTest() - images = ('rfubuntu', 'rfdebian', 'rffedora', 'rffedorapip') + images = ('rfubuntu', 'rfdebian', + 'rffedora', 'rffedorap3', 'rffedorapip') for img in images: print('Testing : {}'.format(img)) response = docker.run(img, 'redfish-client config showall') @@ -80,10 +90,11 @@ def test_install(): def test_versionformat(): docker = DockerTest() - images = ('rfubuntu', 'rfdebian', 'rffedora', 'rffedorapip') + images = ('rfubuntu', 'rfdebian', + 'rffedora', 'rffedorap3', 'rffedorapip') for img in images: print('Testing : {}'.format(img)) response = docker.run(img, 'redfish-client --version') print(response) - assert (re.match('redfish-client \d+\.\d+', response)) + assert (re.match(r'redfish-client \d+\.\d+', response)) diff --git a/redfish/__init__.py b/redfish/__init__.py index 0a6657b..2b57f55 100644 --- a/redfish/__init__.py +++ b/redfish/__init__.py @@ -12,15 +12,21 @@ # License for the specific language governing permissions and limitations # under the License. +from __future__ import unicode_literals +from __future__ import print_function +from __future__ import division +from __future__ import absolute_import +from future import standard_library +standard_library.install_aliases() import pbr.version from redfish.main import * -#import redfish.types try: __version__ = pbr.version.VersionInfo('redfish').release_string() -except Exception, e: - if "Versioning for this project requires either an sdist tarball" in e.message: +except Exception as e: + if "Versioning for this project requires either an sdist tarball" \ + in e.args[0]: pass else: raise diff --git a/redfish/config.py b/redfish/config.py index b4429ed..9f2b7f1 100644 --- a/redfish/config.py +++ b/redfish/config.py @@ -1,5 +1,11 @@ # coding=utf-8 +from __future__ import unicode_literals +from __future__ import print_function +from __future__ import division +from __future__ import absolute_import +from future import standard_library +standard_library.install_aliases() import logging import sys import os diff --git a/redfish/exception.py b/redfish/exception.py index d54feff..84b67cf 100644 --- a/redfish/exception.py +++ b/redfish/exception.py @@ -1,6 +1,13 @@ # -*- coding: utf-8 -*- -import config +from __future__ import unicode_literals +from __future__ import print_function +from __future__ import division +from __future__ import absolute_import +from future import standard_library +standard_library.install_aliases() +from builtins import str +from . import config class RedfishException(Exception): @@ -32,16 +39,6 @@ class InvalidRedfishContentException(RedfishException): ' Most of the time you are not pointing to the rest API\n' -class NonTrustedCertificatException(RedfishException): - def __init__(self, message, **kwargs): - super(NonTrustedCertificatException, self).__init__(message, **kwargs) - self.advices = \ - '1- Check if the url is the correct one\n' + \ - '2- Check if your device has a valid trusted certificat\n' + \ - ' You can use openssl to validate it using the command :\n' + \ - ' openssl s_client -showcerts -connect :443\n' - - class AuthenticationFailureException(RedfishException): def __init__(self, message, **kwargs): super(AuthenticationFailureException, self).__init__(message, **kwargs) diff --git a/redfish/main.py b/redfish/main.py index 98c0205..bf96712 100644 --- a/redfish/main.py +++ b/redfish/main.py @@ -1,3 +1,5 @@ +# coding=utf-8 +# # Copyright 2014 Hewlett-Packard Development Company, L.P. # # Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -114,17 +116,23 @@ Clients should always be prepared for: * headers the service returns """ +from __future__ import unicode_literals +from __future__ import print_function +from __future__ import division +from __future__ import absolute_import +from future import standard_library +standard_library.install_aliases() +from builtins import object -# coding=utf-8 import json -from urlparse import urlparse +from urllib.parse import urlparse import requests -import config -import types -import mapping -import exception +from . import config +from . import types +from . import mapping +from . import exception """Function to wrap RedfishConnection""" @@ -196,13 +204,13 @@ class RedfishConnection(object): # Verify cert if self.connection_parameters.verify_cert is False: config.logger.info("Certificat is not checked, " + - "this is insecure and can allow" + - " a man in the middle attack") + "this is insecure and can allow" + + " a man in the middle attack") - config.logger.debug("Root url : %s", self.connection_parameters.rooturl) + config.logger.debug("Root url : %s", + self.connection_parameters.rooturl) self.Root = types.Root(self.connection_parameters.rooturl, - self.connection_parameters - ) + self.connection_parameters) #self.api_url = tortilla.wrap(self.connection_parameters.rooturl, # debug=TORTILLADEBUG) #self.root = self.api_url.get(verify=self.connection_parameters.verify_cert) diff --git a/redfish/mapping.py b/redfish/mapping.py index f999cd2..db116ab 100644 --- a/redfish/mapping.py +++ b/redfish/mapping.py @@ -1,4 +1,11 @@ # coding=utf-8 +from __future__ import unicode_literals +from __future__ import print_function +from __future__ import division +from __future__ import absolute_import +from future import standard_library +standard_library.install_aliases() +from builtins import object redfish_mapper = None redfish_version = None diff --git a/redfish/types.py b/redfish/types.py index babc5d0..478ab53 100644 --- a/redfish/types.py +++ b/redfish/types.py @@ -1,14 +1,22 @@ # coding=utf-8 +from __future__ import unicode_literals +from __future__ import print_function +from __future__ import division +from __future__ import absolute_import +from future import standard_library +standard_library.install_aliases() +from builtins import object import pprint import re -from urlparse import urljoin +from urllib.parse import urljoin import requests import simplejson import tortilla -import config -import mapping -import exception +import ssl +from . import config +from . import mapping +from . import exception # Global variable @@ -24,15 +32,17 @@ class Base(object): try: if connection_parameters.auth_token is None: - self.data = self.api_url.get(verify=connection_parameters.verify_cert) + self.data = self.api_url.get( + verify=connection_parameters.verify_cert) else: - self.data = self.api_url.get(verify=connection_parameters.verify_cert, - headers={'x-auth-token': connection_parameters.auth_token} - ) - except requests.ConnectionError as e: + self.data = self.api_url.get( + verify=connection_parameters.verify_cert, + headers={ + 'x-auth-token': connection_parameters.auth_token}) + except (requests.ConnectionError, ssl.SSLError) as e: # Log and transmit the exception. config.logger.info('Raise a RedfishException to upper level') - msg = 'Connection error : {}\n'.format(e.message) + msg = 'Connection error : {}\n'.format(e) raise exception.ConnectionFailureException(msg) except simplejson.scanner.JSONDecodeError as e: # Log and transmit the exception. @@ -41,14 +51,6 @@ class Base(object): 'Ivalid content : Content does not appear to be a valid ' + \ 'Redfish json\n' raise exception.InvalidRedfishContentException(msg) - except TypeError as e: - # This happen connecting to a manager using non trusted - # SSL certificats. - # The exception is not what could be expected in such case but this - # is the one provided by Tortilla. - config.logger.info('Raise a RedfishException to upper level') - msg = 'Connection error\n' - raise exception.NonTrustedCertificatException(msg) config.logger.debug(self.data) def get_link_url(self, link_type): diff --git a/requirements.txt b/requirements.txt index fec375e..14b281f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,3 +8,7 @@ Jinja2>=2.7.3 Sphinx>=1.2.3 docopt>=0.6.2 simplejson>=3.8.1 + +# Python3 compat +future>=0.15.2 +configparser>=3.3.0; python_version < '3' diff --git a/setup.py b/setup.py index cc591e5..94994dd 100755 --- a/setup.py +++ b/setup.py @@ -1,3 +1,10 @@ +from __future__ import unicode_literals +from __future__ import print_function +from __future__ import division +from __future__ import absolute_import +from future import standard_library +standard_library.install_aliases() +from builtins import object #!/usr/bin/env python # Licensed under the Apache License, Version 2.0 (the 'License'); # you may not use this file except in compliance with the License. @@ -19,7 +26,7 @@ import fileinput import re import pprint import distutils -import ConfigParser +import configparser import setuptools from setuptools import Distribution from setuptools.command.install import install @@ -42,13 +49,13 @@ class OnlyGetScriptPath(install): self.distribution.install_scripts = self.install_scripts -class DataFilesHelper(): +class DataFilesHelper(object): '''Class to help manage data files''' def __init__(self): '''Read setup.cfg and build the required data''' self.data = {} self.setupstruc = [] - config = ConfigParser.ConfigParser() + config = configparser.ConfigParser() config.read('setup.cfg') for datafile in config.options('data_files_helper'): src, dst = config.get('data_files_helper', datafile).split(',') @@ -65,7 +72,7 @@ class DataFilesHelper(): self.data['script'] = {'src': src, 'dst': 'bin', 'fdst': self.calculatedst(src, 'bin')} - except ConfigParser.NoOptionError: + except configparser.NoOptionError: pass pp = pprint.PrettyPrinter(indent=4) pp.pprint(self.data)