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)