Merge pull request #67 from bcornec/devel

Request to merge 0.3 version from devel to master
This commit is contained in:
Bruno Cornec 2016-04-07 15:41:19 +02:00
commit 7b22e23d66
109 changed files with 4470 additions and 1148 deletions

View File

@ -1,7 +1,8 @@
[run]
branch = True
source = redfish
omit = redfish/tests/*,redfish/openstack/*
redfish-client
omit = redfish/tests/*,redfish-client/tests/*
[report]
ignore-errors = True
#ignore-errors = True

8
.gitignore vendored
View File

@ -27,7 +27,7 @@ var/
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
#*.spec
# Installer logs
pip-log.txt
@ -41,6 +41,8 @@ htmlcov/
.cache
nosetests.xml
coverage.xml
redfish-client/tests/Dockerfile
redfish-client/tests/python-redfish.src.tar.gz
# Translations
*.mo
@ -55,6 +57,10 @@ docs/_build/
# PyBuilder
target/
# Project-Builder.org
delivery/
build/
# Pydev
.project
.pydevproject

View File

@ -1,4 +0,0 @@
[gerrit]
host=review.openstack.org
port=29418
project=stackforge/python-redfish.git

View File

@ -1,16 +1,5 @@
If you would like to contribute to the development of OpenStack,
you must follow the steps in this page:
If you would like to contribute to the development of this project.
http://docs.openstack.org/infra/manual/developers.html
Submit your pull request and issues to https://github.com/bcornec/python-redfish.
Once those steps have been completed, changes to OpenStack
should be submitted for review via the Gerrit tool, following
the workflow documented at:
http://docs.openstack.org/infra/manual/developers.html#development-workflow
Pull requests submitted through GitHub will be ignored.
Bugs should be filed on Launchpad, not GitHub:
https://bugs.launchpad.net/python-redfish
You can also share and discuss on the mailing list as well at http://mondorescue.org/sympa/arc/python-redfish.

View File

@ -1,38 +1,46 @@
python-redfish
==============
The python-redfish project
==========================
This repository will be used to house the Redfish python library, a reference
This repository will be used to house the python-redfish library, a reference
implementation to enable Python developers to communicate with the Redfish API
(http://www.dmtf.org/standards/redfish).
NOTE::
DRAFT - WORK IN PROGRESS
STATUS: Work in progress, ready for proof of concept.
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
-------------------
-----------------
This project follows the same convention as OpenStack projects, eg. using pbr
for build and test automation::
doc/ # documentation
doc/source # the doc source files live here
doc/build/html # output of building any docs will go here
doc/ # Documentation
doc/source # The doc source files live here
doc/build/html # Output of building any docs will go here
dmtf # Reference documents and mockup provided by the DMTF
examples/ # any sample code using this library, eg. for education
examples/ # Any sample code using this library, eg. for education
# should be put here
redfish/ # the redfish library
redfish/tests/ # python unit test suite
pbconf # Project builder file to build rpm/deb packages for
# distributions
redfish/ # The redfish library itself
redfish/tests/ # python-redfish unit test suite
redfish-client # Client tool to manage redfish devices
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
@ -41,24 +49,36 @@ 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.
Developer setup
---------------
Note: Running tests requires Docker engine.
To initialize a local development environment (eg, so you can run unit tests)
you should run the following commands::
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 source code
-------------------
The source code is available on github and can be retrieved using::
git clone https://github.com/bcornec/python-redfish
As python-redfish is currently in heavy development we recommend to checkout the devel branch using::
cd python-redfish
git checkout devel
Installation
------------
Please refer to the following link.
http://pythonhosted.org/python-redfish/installation.html
Contacts
--------
Distribution list : python-redfish@mondorescue.org
Distribution list: python-redfish@mondorescue.org
Further References
------------------
The data model documentation can be found here:
http://www.redfishspecification.org/redfish-data-model-and-schema/
The overall protocol documentation can be found here:
http://www.redfishspecification.org/
Please look at `dmtf/README.rst <further_ref.html>`_ file.

BIN
dmtf/DSP0266_1.0.1.pdf Normal file

Binary file not shown.

465
dmtf/DSP8011_1.0.0a.json Normal file
View File

@ -0,0 +1,465 @@
{
"@Redfish.Copyright": "Copyright © 2014-2015 Distributed Management Task Force, Inc. (DMTF). All rights reserved.",
"@odata.type": "#MessageRegistry.1.0.0.MessageRegistry",
"Id": "Base.1.0.0",
"Name": "Base Message Registry",
"Language": "en",
"Description": "This registry defines the base messages for Redfish",
"RegistryPrefix": "Base",
"RegistryVersion": "1.0.0",
"OwningEntity": "DMTF",
"Messages": {
"Success": {
"Description": "Indicates that all conditions of a successful operation have been met.",
"Message": "Successfully Completed Request",
"Severity": "OK",
"NumberOfArgs": 0,
"Resolution": "None"
},
"GeneralError": {
"Description": "Indicates that a general error has occurred.",
"Message": "A general error has occurred. See ExtendedInfo for more information.",
"Severity": "Critical",
"NumberOfArgs": 0,
"Resolution": "See ExtendedInfo for more information."
},
"Created": {
"Description": "Indicates that all conditions of a successful creation operation have been met.",
"Message": "The resource has been created successfully",
"Severity": "OK",
"NumberOfArgs": 0,
"Resolution": "None"
},
"PropertyDuplicate": {
"Description": "Indicates that a duplicate property was included in the request body.",
"Message": "The property %1 was duplicated in the request.",
"Severity": "Warning",
"NumberOfArgs": 1,
"ParamTypes": [
"string"
],
"Resolution": "Remove the duplicate property from the request body and resubmit the request if the operation failed."
},
"PropertyUnknown": {
"Description": "Indicates that an unknown property was included in the request body.",
"Message": "The property %1 is not in the list of valid properties for the resource.",
"Severity": "Warning",
"NumberOfArgs": 1,
"ParamTypes": [
"string"
],
"Resolution": "Remove the unknown property from the request body and resubmit the request if the operation failed."
},
"PropertyValueTypeError": {
"Description": "Indicates that a property was given the wrong value type, such as when a number is supplied for a property that requires a string.",
"Message": "The value %1 for the property %2 is of a different type than the property can accept.",
"Severity": "Warning",
"NumberOfArgs": 2,
"ParamTypes": [
"string",
"string"
],
"Resolution": "Correct the value for the property in the request body and resubmit the request if the operation failed."
},
"PropertyValueFormatError": {
"Description": "Indicates that a property was given the correct value type but the value of that property was not supported. This includes value size/length exceeded.",
"Message": "The value %1 for the property %2 is of a different format than the property can accept.",
"Severity": "Warning",
"NumberOfArgs": 2,
"ParamTypes": [
"string",
"string"
],
"Resolution": "Correct the value for the property in the request body and resubmit the request if the operation failed."
},
"PropertyValueNotInList": {
"Description": "Indicates that a property was given the correct value type but the value of that property was not supported. This values not in an enumeration",
"Message": "The value %1 for the property %2 is not in the list of acceptable values.",
"Severity": "Warning",
"NumberOfArgs": 2,
"ParamTypes": [
"string",
"string"
],
"Resolution": "Choose a value from the enumeration list that the implementation can support and resubmit the request if the operation failed."
},
"PropertyNotWritable": {
"Description": "Indicates that a property was given a value in the request body, but the property is a readonly property.",
"Message": "The property %1 is a read only property and cannot be assigned a value.",
"Severity": "Warning",
"NumberOfArgs": 1,
"ParamTypes": [
"string"
],
"Resolution": "Remove the property from the request body and resubmit the request if the operation failed."
},
"PropertyMissing": {
"Description": "Indicates that a required property was not supplied as part of the request.",
"Message": "The property %1 is a required property and must be included in the request.",
"Severity": "Warning",
"NumberOfArgs": 1,
"ParamTypes": [
"string"
],
"Resolution": "Ensure that the property is in the request body and has a valid value and resubmit the request if the operation failed."
},
"MalformedJSON": {
"Description": "Indicates that the request body was malformed JSON. Could be duplicate, syntax error,etc.",
"Message": "The request body submitted was malformed JSON and could not be parsed by the receiving service.",
"Severity": "Critical",
"NumberOfArgs": 0,
"Resolution": "Ensure that the request body is valid JSON and resubmit the request."
},
"ActionNotSupported": {
"Description": "Indicates that the action supplied with the POST operation is not supported by the resource.",
"Message": "The action %1 is not supported by the resource.",
"Severity": "Critical",
"NumberOfArgs": 1,
"ParamTypes": [
"string"
],
"Resolution": "The action supplied cannot be resubmitted to the implementation. Perhaps the action was invalid, the wrong resource was the target or the implementation documentation may be of assistance."
},
"ActionParameterMissing": {
"Description": "Indicates that the action requested was missing a parameter that is required to process the action.",
"Message": "The action %1 requires the parameter %2 to be present in the request body.",
"Severity": "Critical",
"NumberOfArgs": 2,
"ParamTypes": [
"string",
"string"
],
"Resolution": "Supply the action with the required parameter in the request body when the request is resubmitted."
},
"ActionParameterDuplicate": {
"Description": "Indicates that the action was supplied with a duplicated parameter in the request body.",
"Message": "The action %1 was submitted with more than one value for the parameter %2.",
"Severity": "Warning",
"NumberOfArgs": 2,
"ParamTypes": [
"string",
"string"
],
"Resolution": "Resubmit the action with only one instance of the parameter in the request body if the operation failed."
},
"ActionParameterUnknown": {
"Description": "Indicates that an action was submitted but a parameter supplied did not match any of the known parameters.",
"Message": "The action %1 was submitted with with the invalid parameter %2.",
"Severity": "Warning",
"NumberOfArgs": 2,
"ParamTypes": [
"string",
"string"
],
"Resolution": "Correct the invalid parameter and resubmit the request if the operation failed."
},
"ActionParameterValueTypeError": {
"Description": "Indicates that a parameter was given the wrong value type, such as when a number is supplied for a parameter that requires a string.",
"Message": "The value %1 for the parameter %2 in the action %3 is of a different type than the parameter can accept.",
"Severity": "Warning",
"NumberOfArgs": 3,
"ParamTypes": [
"string",
"string",
"string"
],
"Resolution": "Correct the value for the parameter in the request body and resubmit the request if the operation failed."
},
"ActionParameterValueFormatError": {
"Description": "Indicates that a parameter was given the correct value type but the value of that parameter was not supported. This includes value size/length exceeded.",
"Message": "The value %1 for the parameter %2 in the action %3 is of a different format than the parameter can accept.",
"Severity": "Warning",
"NumberOfArgs": 3,
"ParamTypes": [
"string",
"string",
"string"
],
"Resolution": "Correct the value for the parameter in the request body and resubmit the request if the operation failed."
},
"ActionParameterNotSupported": {
"Description": "Indicates that the parameter supplied for the action is not supported on the resource.",
"Message": "The parameter %1 for the action %2 is not supported on the target resource.",
"Severity": "Warning",
"NumberOfArgs": 2,
"ParamTypes": [
"string",
"string"
],
"Resolution": "Remove the parameter supplied and resubmit the request if the operation failed."
},
"QueryParameterValueTypeError": {
"Description": "Indicates that a query parameter was given the wrong value type, such as when a number is supplied for a query parameter that requires a string.",
"Message": "The value %1 for the query parameter %2 is of a different type than the parameter can accept.",
"Severity": "Warning",
"NumberOfArgs": 2,
"ParamTypes": [
"string",
"string"
],
"Resolution": "Correct the value for the query parameter in the request and resubmit the request if the operation failed."
},
"QueryParameterValueFormatError": {
"Description": "Indicates that a query parameter was given the correct value type but the value of that parameter was not supported. This includes value size/length exceeded.",
"Message": "The value %1 for the parameter %2 is of a different format than the parameter can accept.",
"Severity": "Warning",
"NumberOfArgs": 2,
"ParamTypes": [
"string",
"string"
],
"Resolution": "Correct the value for the query parameter in the request and resubmit the request if the operation failed."
},
"QueryParameterOutOfRange": {
"Description": "Indicates that a query parameter was supplied that is out of range for the given resource. This can happen with values that are too low or beyond that possible for the supplied resource, such as when a page is requested that is beyond the last page.",
"Message": "The value %1 for the query parameter %2 is out of range %3.",
"Severity": "Warning",
"NumberOfArgs": 3,
"ParamTypes": [
"string",
"string",
"string"
],
"Resolution": "Reduce the value for the query parameter to a value that is within range, such as a start or count value that is within bounds of the number of resources in a collection or a page that is within the range of valid pages."
},
"QueryNotSupportedOnResource": {
"Description": "Indicates that query is not supported on the given resource, such as when a start/count query is attempted on a resource that is not a collection.",
"Message": "Querying is not supported on the requested resource.",
"Severity": "Warning",
"NumberOfArgs": 0,
"Resolution": "Remove the query parameters and resubmit the request if the operation failed."
},
"QueryNotSupported": {
"Description": "Indicates that query is not supported on the implementation.",
"Message": "Querying is not supported by the implementation.",
"Severity": "Warning",
"NumberOfArgs": 0,
"Resolution": "Remove the query parameters and resubmit the request if the operation failed."
},
"SessionLimitExceeded": {
"Description": "Indicates that a session establishment has been requested but the operation failed due to the number of simultaneous sessions exceeding the limit of the implementation.",
"Message": "The session establishment failed due to the number of simultaneous sessions exceeding the limit of the implementation.",
"Severity": "Critical",
"NumberOfArgs": 0,
"Resolution": "Reduce the number of other sessions before trying to establish the session or increase the limit of simultaneous sessions (if supported)."
},
"EventSubscriptionLimitExceeded": {
"Description": "Indicates that a event subscription establishment has been requested but the operation failed due to the number of simultaneous connection exceeding the limit of the implementation.",
"Message": "The event subscription failed due to the number of simultaneous subscriptions exceeding the limit of the implementation.",
"Severity": "Critical",
"NumberOfArgs": 0,
"Resolution": "Reduce the number of other subscriptions before trying to establish the event subscription or increase the limit of simultaneous subscriptions (if supported)."
},
"ResourceCannotBeDeleted": {
"Description": "Indicates that a delete operation was attempted on a resource that cannot be deleted.",
"Message": "The delete request failed because the resource requested cannot be deleted.",
"Severity": "Critical",
"NumberOfArgs": 0,
"Resolution": "Do not attempt to delete a non-deletable resource."
},
"ResourceInUse": {
"Description": "Indicates that a change was requested to a resource but the change was rejected due to the resource being in use or transition.",
"Message": "The change to the requested resource failed because the resource is in use or in transition.",
"Severity": "Warning",
"NumberOfArgs": 0,
"Resolution": "Remove the condition and resubmit the request if the operation failed."
},
"ResourceAlreadyExists": {
"Description": "Indicates that a resource change or creation was attempted but that the operation cannot proceed because the resource already exists.",
"Message": "The requested resource already exists.",
"Severity": "Critical",
"NumberOfArgs": 0,
"Resolution": "Do not repeat the create operation as the resource has already been created."
},
"CreateFailedMissingReqProperties": {
"Description": "Indicates that a create was attempted on a resource but that properties that are required for the create operation were missing from the request.",
"Message": "The create operation failed because the required property %1 was missing from the request.",
"Severity": "Critical",
"NumberOfArgs": 1,
"ParamTypes": [
"string"
],
"Resolution": "Correct the body to include the required property with a valid value and resubmit the request if the operation failed."
},
"CreateLimitReachedForResource": {
"Description": "Indicates that no more resources can be created on the resource as it has reached its create limit.",
"Message": "The create operation failed because the resource has reached the limit of possible resources.",
"Severity": "Critical",
"NumberOfArgs": 0,
"Resolution": "Either delete resources and resubmit the request if the operation failed or do not resubmit the request."
},
"ServiceShuttingDown": {
"Description": "Indicates that the operation failed as the service is shutting down, such as when the service reboots.",
"Message": "The operation failed because the service is shutting down and can no longer take incoming requests.",
"Severity": "Critical",
"NumberOfArgs": 0,
"Resolution": "When the service becomes available, resubmit the request if the operation failed."
},
"ServiceInUnknownState": {
"Description": "Indicates that the operation failed because the service is in an unknown state and cannot accept additional requests.",
"Message": "The operation failed because the service is in an unknown state and can no longer take incoming requests.",
"Severity": "Critical",
"NumberOfArgs": 0,
"Resolution": "Restart the service and resubmit the request if the operation failed."
},
"NoValidSession": {
"Description": "Indicates that the operation failed because a valid session is required in order to access any resources.",
"Message": "There is no valid session established with the implementation.",
"Severity": "Critical",
"NumberOfArgs": 0,
"Resolution": "Establish as session before attempting any operations."
},
"InsufficientPrivilege": {
"Description": "Indicates that the credentials associated with the established session do not have sufficient privileges for the requested operation",
"Message": "There are insufficient privileges for the account or credentials associated with the current session to perform the requested operation.",
"Severity": "Critical",
"NumberOfArgs": 0,
"Resolution": "Either abandon the operation or change the associated access rights and resubmit the request if the operation failed."
},
"AccountModified": {
"Description": "Indicates that the account was successfully modified.",
"Message": "The account was successfully modifed.",
"Severity": "OK",
"NumberOfArgs": 0,
"Resolution": "No resolution is required."
},
"AccountNotModified": {
"Description": "Indicates that the modification requested for the account was not successful.",
"Message": "The account modification request failed.",
"Severity": "Warning",
"NumberOfArgs": 0,
"Resolution": "The modification may have failed due to permission issues or issues with the request body."
},
"AccountRemoved": {
"Description": "Indicates that the account was successfully removed.",
"Message": "The account was successfully removed.",
"Severity": "OK",
"NumberOfArgs": 0,
"Resolution": "No resolution is required."
},
"AccountForSessionNoLongerExists": {
"Description": "Indicates that the account for the session has been removed, thus the session has been removed as well.",
"Message": "The account for the current session has been removed, thus the current session has been removed as well.",
"Severity": "OK",
"NumberOfArgs": 0,
"Resolution": "Attempt to connect with a valid account."
},
"InvalidObject": {
"Description": "Indicates that the object in question is invalid according to the implementation. Examples include a firmware update malformed URI.",
"Message": "The object at %1 is invalid.",
"Severity": "Critical",
"NumberOfArgs": 1,
"ParamTypes": [
"string"
],
"Resolution": "Either the object is malformed or the URI is not correct. Correct the condition and resubmit the request if it failed."
},
"InternalError": {
"Description": "Indicates that the request failed for an unknown internal error but that the service is still operational.",
"Message": "The request failed due to an internal service error. The service is still operational.",
"Severity": "Critical",
"NumberOfArgs": 0,
"Resolution": "Resubmit the request. If the problem persists, consider resetting the service."
},
"UnrecognizedRequestBody": {
"Description": "Indicates that the service encountered an unrecognizable request body that could not even be interpreted as malformed JSON.",
"Message": "The service detected a malformed request body that it was unable to interpret.",
"Severity": "Warning",
"NumberOfArgs": 0,
"Resolution": "Correct the request body and resubmit the request if it failed."
},
"ResourceMissingAtURI": {
"Description": "Indicates that the operation expected an image or other resource at the provided URI but none was found. Examples of this are in requests that require URIs like Firmware Update.",
"Message": "The resource at the URI %1 was not found.",
"Severity": "Critical",
"NumberOfArgs": 1,
"ParamTypes": [
"string"
],
"Resolution": "Place a valid resource at thr URI or correct the URI and resubmit the request."
},
"ResourceAtUriInUnknownFormat": {
"Description": "Indicates that the URI was valid but the resource or image at that URI was in a format not supported by the service.",
"Message": "The resource at %1 is in a format not recognized by the service.",
"Severity": "Critical",
"NumberOfArgs": 1,
"ParamTypes": [
"string"
],
"Resolution": "Place an image or resource or file that is recognized by the service at the URI."
},
"ResourceAtUriUnauthorized": {
"Description": "Indicates that the attempt to access the resource/file/image at the URI was unauthorized.",
"Message": "While accessing the resource at %1, the service received an authorization error %2.",
"Severity": "Critical",
"NumberOfArgs": 2,
"ParamTypes": [
"string",
"string"
],
"Resolution": "Ensure that the appropriate access is provided for the service in order for it to access the URI."
},
"CouldNotEstablishConnection": {
"Description": "Indicates that the attempt to access the resource/file/image at the URI was unsuccessful because a session could not be established.",
"Message": "The service failed to establish a connection with the URI %1.",
"Severity": "Critical",
"NumberOfArgs": 1,
"ParamTypes": [
"string"
],
"Resolution": "Ensure that the URI contains a valid and reachable node name, protocol information and other URI components."
},
"SourceDoesNotSupportProtocol": {
"Description": "Indicates that while attempting to access, connect to or transfer a resource/file/image from another location that the other end of the connection did not support the protocol",
"Message": "The other end of the connection at %1 does not support the specified protocol %2.",
"Severity": "Critical",
"NumberOfArgs": 2,
"ParamTypes": [
"string",
"string"
],
"Resolution": "Change protocols or URIs. "
},
"AccessDenied": {
"Description": "Indicates that while attempting to access, connect to or transfer to/from another resource, the service was denied access.",
"Message": "While attempting to establish a connection to %1, the service was denied access.",
"Severity": "Critical",
"NumberOfArgs": 1,
"ParamTypes": [
"string"
],
"Resolution": "Attempt to ensure that the URI is correct and that the service has the appropriate credentials."
},
"ServiceTemporarilyUnavailable": {
"Description": "Indicates the service is temporarily unavailable.",
"Message": "The service is temporarily unavailable. Retry in %1 seconds.",
"Severity": "Critical",
"NumberOfArgs": 1,
"ParamTypes": [
"string"
],
"Resolution": "Wait for the indicated retry duration and retry the operation."
},
"InvalidIndex": {
"Description": "The Index is not valid.",
"Message": "The Index %1 is not a valid offset into the array.",
"Severity": "Warning",
"NumberOfArgs": 1,
"ParamTypes": [
"number"
],
"Resolution": "Verify the index value provided is within the bounds of the array."
},
"PropertyValueModified": {
"Description": "Indicates that a property was given the correct value type but the value of that property was modified. Examples are truncated or rounded values.",
"Message": "The property %1 was assigned the value %2 due to modification by the service.",
"Severity": "Warning",
"NumberOfArgs": 2,
"ParamTypes": [
"string",
"string"
],
"Resolution": "No resolution is required."
}
}
}

View File

@ -1,7 +1,7 @@
# Invoke with docker run -p 8000:80 <dockerimageid>
# Then use by browsing http://localhost:8000
FROM ubuntu:15.04
MAINTAINER bruno.cornec@hp.com
FROM ubuntu:15.10
MAINTAINER bruno.cornec@hpe.com
ENV DEBIAN_FRONTEND noninterative
# Install deps for Redfish mockup
RUN apt-get update

View File

@ -1,12 +1,26 @@
DMTF Redfish specification
--------------------------
This directory contains the current references from the DMTF on the Redfish
specification (1.0.0 at the time of the writing)
In order to ease test, the DMTF has published a mockup environment to simulate
a Redfish based system so it is possible to write programs without real Redfish
This directory contains the current references from the DMTF on the Redfish
specification (1.0.1 at the time of the writing)
The overall protocol documentation can be found online at:
http://www.dmtf.org/standards/redfish
The specification can be found locally in DSP0266_1.0.1.pdf or online at:
http://www.dmtf.org/sites/default/files/standards/documents/DSP0266_1.0.1.pdf
The data model documentation can be found locally in DSP8010_1.0.0.zip or online at:
http://redfish.dmtf.org/schemas/
In order to ease test, the DMTF has published a mockup environment to simulate
a Redfish based system so it is possible to write programs without real Redfish
compliant hardware platform.
Note: Mockup release is still 0.99.0a and so not aligned with specification realease
number.
Docker container
----------------

View File

@ -3,4 +3,3 @@
# Build and tag images
docker rmi redfish-simulator
docker build -t "redfish-simulator" .
docker tag -f redfish-simulator:latest localhost:5000/redfish-simulator

View File

@ -1,6 +1,7 @@
#!/bin/bash
function start_apache {
[ -f "/run/apache2/apache2.pid" ] && rm -f "/run/apache2/apache2.pid"
echo "Launching apache2 in foreground with /usr/sbin/apache2ctl -DFOREGROUND -k start"
/usr/sbin/apache2ctl -DFOREGROUND -k start
}

View File

@ -1,8 +1,9 @@
#!/bin/bash
# Build the docker container first
docker build -t localhost:5000/redfish-simulator:latest .
# Th -p option needs to be after the run command. No warning is given if before but doesn't work
docker rm "redfish-simulator"
docker run -d -p 8000:80 --name "redfish-simulator" localhost:5000/redfish-simulator:latest
docker ps -a | grep -q "redfish-simulator:latest"
if [ "$?" -eq 0 ]; then
docker rm "redfish-simulator"
fi
# The -p option needs to be after the run command. No warning is given if before but doesn't work
docker run -d -p 8000:80 --name "redfish-simulator" redfish-simulator:latest
echo "Launch your browser and load http://localhost:8000/redfish/v1"

177
doc/Makefile Normal file
View File

@ -0,0 +1,177 @@
# Makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = build
# User-friendly check for sphinx-build
ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
endif
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
# the i18n builder cannot share the environment and doctrees with the others
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " singlehtml to make a single large HTML file"
@echo " pickle to make pickle files"
@echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " qthelp to make HTML files and a qthelp project"
@echo " devhelp to make HTML files and a Devhelp project"
@echo " epub to make an epub"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " latexpdf to make LaTeX files and run them through pdflatex"
@echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
@echo " text to make text files"
@echo " man to make manual pages"
@echo " texinfo to make Texinfo files"
@echo " info to make Texinfo files and run them through makeinfo"
@echo " gettext to make PO message catalogs"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " xml to make Docutils-native XML files"
@echo " pseudoxml to make pseudoxml-XML files for display purposes"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
clean:
rm -rf $(BUILDDIR)/*
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
singlehtml:
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
@echo
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/python-redfish.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/python-redfish.qhc"
devhelp:
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo
@echo "Build finished."
@echo "To view the help file:"
@echo "# mkdir -p $$HOME/.local/share/devhelp/python-redfish"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/python-redfish"
@echo "# devhelp"
epub:
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make' in that directory to run these through (pdf)latex" \
"(use \`make latexpdf' here to do that automatically)."
latexpdf:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through pdflatex..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
latexpdfja:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through platex and dvipdfmx..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
text:
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "Build finished. The text files are in $(BUILDDIR)/text."
man:
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
texinfo:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
@echo "Run \`make' in that directory to run these through makeinfo" \
"(use \`make info' here to do that automatically)."
info:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo "Running Texinfo files through makeinfo..."
make -C $(BUILDDIR)/texinfo info
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
gettext:
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
@echo
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."
xml:
$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
@echo
@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
pseudoxml:
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
@echo
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."

19
doc/README.rst Normal file
View File

@ -0,0 +1,19 @@
python-redfish documentation
============================
This repository will be used to house the python Redfish documentation,
Contacts
--------
Distribution list : python-redfish@mondorescue.org
References documents
--------------------
On top of the DMTF official documentation, you can find some useful documents at the following URLs:
Firmware in the DC: Goodbye PXE/IPMI, welcome HTTP Boot and Redfish (Samer El-Haj-Mahmoud)
http://www.uefi.org/sites/default/files/resources/UEFI_Plugfest_May_2015_HTTP_Boot_Redfish_Samer_El-Haj_ver1.2.pdf

View File

@ -0,0 +1,9 @@
=====================
Classes documentation
=====================
.. toctree::
:maxdepth: 2
python-redfish_lib
redfish-client

329
doc/source/conf.py Executable file → Normal file
View File

@ -1,75 +1,332 @@
# -*- coding: utf-8 -*-
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
# python-redfish documentation build configuration file, created by
# sphinx-quickstart on Wed Feb 10 19:41:20 2016.
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# This file is execfile()d with the current directory set to its
# containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
import os
import sys
import os
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
sys.path.insert(0, os.path.abspath('../..'))
# -- General configuration ----------------------------------------------------
sys.path.insert(0, os.path.abspath('../../redfish-client'))
# -- General configuration ------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinx.ext.autodoc',
#'sphinx.ext.intersphinx',
'oslosphinx'
'sphinx.ext.viewcode',
]
# autodoc generation is a bit aggressive and a nuisance when doing heavy
# text edit cycles.
# execute "export SPHINX_DEBUG=1" in your terminal to disable
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix of source filenames.
source_suffix = '.rst'
# The encoding of source files.
#source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'python-redfish'
copyright = u'2013, OpenStack Foundation'
copyright = u'2015-2016, Bruno Cornec, Vincent Misson, René Ribaud'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = 'PBVER'
# The full version, including alpha/beta/rc tags.
release = 'PBVER'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = []
# The reST default role (used for this markup: `text`) to use for all
# documents.
#default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
add_function_parentheses = True
#add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
add_module_names = True
#add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# -- Options for HTML output --------------------------------------------------
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# The theme to use for HTML and HTML Help pages. Major themes that come with
# Sphinx are currently 'default' and 'sphinxdoc'.
# html_theme_path = ["."]
# html_theme = '_theme'
# html_static_path = ['static']
# If true, keep warnings as "system message" paragraphs in the built documents.
#keep_warnings = False
# -- Options for HTML output ----------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
html_theme = 'default'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied
# directly to the root of the documentation.
#html_extra_path = []
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# If false, no module index is generated.
#html_domain_indices = True
# If false, no index is generated.
#html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None
# Output file base name for HTML help builder.
htmlhelp_basename = '%sdoc' % project
htmlhelp_basename = 'python-redfishdoc'
# -- Options for LaTeX output ---------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#'preamble': '',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass
# [howto/manual]).
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
('index',
'%s.tex' % project,
u'%s Documentation' % project,
u'OpenStack Foundation', 'manual'),
('index', 'python-redfish.tex', u'python-redfish Documentation',
u'Bruno Cornec, Vincent Misson, René Ribaud', 'manual'),
]
# Example configuration for intersphinx: refer to the Python standard library.
#intersphinx_mapping = {'http://docs.python.org/': None}
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# If true, show page references after internal links.
#latex_show_pagerefs = False
# If true, show URL addresses after external links.
#latex_show_urls = False
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# If false, no module index is generated.
#latex_domain_indices = True
# -- Options for manual page output ---------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
('index', 'python-redfish', u'python-redfish Documentation',
[u'Bruno Cornec, Vincent Misson, René Ribaud'], 1)
]
# If true, show URL addresses after external links.
#man_show_urls = False
# -- Options for Texinfo output -------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
('index', 'python-redfish', u'python-redfish Documentation',
u'Bruno Cornec, Vincent Misson, René Ribaud', 'python-redfish', 'One line description of project.',
'Miscellaneous'),
]
# Documents to append as an appendix to all manuals.
#texinfo_appendices = []
# If false, no module index is generated.
#texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote'
# If true, do not generate a @detailmenu in the "Top" node's menu.
#texinfo_no_detailmenu = False
# -- Options for Epub output ----------------------------------------------
# Bibliographic Dublin Core info.
epub_title = u'python-redfish'
epub_author = u'Bruno Cornec, Vincent Misson, René Ribaud'
epub_publisher = u'Bruno Cornec, Vincent Misson, René Ribaud'
epub_copyright = u'2016, Bruno Cornec, Vincent Misson, René Ribaud'
# The basename for the epub file. It defaults to the project name.
#epub_basename = u'python-redfish'
# The HTML theme for the epub output. Since the default themes are not optimized
# for small screen space, using the same theme for HTML and epub output is
# usually not wise. This defaults to 'epub', a theme designed to save visual
# space.
#epub_theme = 'epub'
# The language of the text. It defaults to the language option
# or en if the language is not set.
#epub_language = ''
# The scheme of the identifier. Typical schemes are ISBN or URL.
#epub_scheme = ''
# The unique identifier of the text. This can be a ISBN number
# or the project homepage.
#epub_identifier = ''
# A unique identification for the text.
#epub_uid = ''
# A tuple containing the cover image and cover page html template filenames.
#epub_cover = ()
# A sequence of (type, uri, title) tuples for the guide element of content.opf.
#epub_guide = ()
# HTML files that should be inserted before the pages created by sphinx.
# The format is a list of tuples containing the path and title.
#epub_pre_files = []
# HTML files shat should be inserted after the pages created by sphinx.
# The format is a list of tuples containing the path and title.
#epub_post_files = []
# A list of files that should not be packed into the epub file.
epub_exclude_files = ['search.html']
# The depth of the table of contents in toc.ncx.
#epub_tocdepth = 3
# Allow duplicate toc entries.
#epub_tocdup = True
# Choose between 'default' and 'includehidden'.
#epub_tocscope = 'default'
# Fix unsupported image types using the PIL.
#epub_fix_images = False
# Scale large images.
#epub_max_image_width = 0
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#epub_show_urls = 'inline'
# If false, no index is generated.
#epub_use_index = True

View File

@ -0,0 +1,8 @@
===============
Developer setup
===============
#. Follow `get the source code <http://pythonhosted.org/python-redfish/readme.html#get-the-source-code>`_ section to retrieve the sources.
#. Follow `using pip and virtualenv <http://pythonhosted.org/python-redfish/installation.html#using-pip-and-virtualenv>`_ section to create your environment.
You can start hacking the code now.

11
doc/source/faq.rst Normal file
View File

@ -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

View File

@ -0,0 +1,3 @@
:orphan:
.. include:: ../../dmtf/README.rst

11
doc/source/help.rst Normal file
View File

@ -0,0 +1,11 @@
=============
Help required
=============
We need help on the following topic:
- debian/ubuntu dependencies packaging.
- installation on distributions which are not Fedora or Mageia.
- documentation.
Any contribution will be welcomed.

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 KiB

View File

@ -14,7 +14,12 @@ Contents:
readme
installation
usage
develsetup
testing
classesdoc
contributing
faq
help
Indices and tables
==================

View File

@ -2,11 +2,254 @@
Installation
============
At the command line::
The following instructions are ordered by ease of use, and our project recommendations.
$ pip install python-redfish
Or, if you have virtualenvwrapper installed::
Using rpm packages
------------------
There is currently no official Linux distribution packages.
The upstream project provides packages for a limited set of Linux distributions.
There are available at ftp://ftp.project-builder.org
As an example for Fedora 23 use the following:
1. As root get the repo file::
cd /etc/yum.repos.d && wget ftp://ftp.project-builder.org/fedora/23/x86_64/python-redfish.repo
2. Install using dnf::
dnf install python-redfish
..
Using deb package
-----------------
This installation in not yet possible due to missing deb package dependencies. We are working on it.
In the meantime we recommend to use `Using pip`_ or `Using pip and virtualenv`_.
Using pip and virtualenv
------------------------
1. Install virtualenv and virtualenvwrapper:
Fedora 22::
dnf install python-virtualenv python-virtualenvwrapper
Ubuntu 15.04::
apt-get install python-virtualenv virtualenvwrapper
2. Source virtualenvwrapper.sh::
. /usr/bin/virtualenvwrapper.sh
or::
. /usr/share/virtualenvwrapper/virtualenvwrapper.sh
3. Create a redfish virtual environement::
mkvirtualenv redfish
4. Install using pip::
pip install python-redfish
All files are installed under your virtualenv.
Using pip
---------
Use::
sudo pip install python-redfish
Pip will install :
1. The library and all dependencies into prefix/lib/pythonX.Y/site-packages directory
2. redfish-client conf file into prefix/etc/redfish-client.conf.
If prefix = '/usr' then force the configuration file to be in /etc
3. Data files (templates) into prefix/share/redfish-client/templates
Point 2 and 3 above need root access to your system. If you don't have root
access on your system, please follow `Using pip and virtualenv`_ section.
Using source code
-----------------
#. Follow `get the source code <http://pythonhosted.org/python-redfish/readme.html#get-the-source-code>`_ section to retrieve it.
#. Install from the source code using::
python setup.py install --prefix="/usr/local"
Building your own rpm packages
------------------------------
Inside the project tree there is a mechanism to build rpm packages for distributions.
The mechanism is based on `project builder <http://www.project-builder.org/>`_ tool.
#. Follow `get the source code <http://pythonhosted.org/python-redfish/readme.html#get-the-source-code>`_ section to retrieve it.
#. Download project builder for your distribution from ftp://ftp.project-builder.org.
#. Clone the project to your own github account.
#. Create a .pbrc with the following content, replace "/workspace/python/redfish" and "uggla" with your own directory and account::
$ cat .pbrc
pbdefdir python-redfish = $ENV{'HOME'}/workspace
pbconfdir python-redfish = $ENV{'HOME'}/workspace/python-redfish/pbconf
pbconfurl python-redfish = git+ssh://git@github.com:uggla/python-redfish.git
pburl python-redfish = git+ssh://git@github.com:uggla/python-redfish.git
#. Build the project::
pb -p python-redfish sbx2pkg
or::
pb -p python-redfish sbx2pkg2ins
#. All packages (srpm/rpm) should be available into the build directory, then install the package using rpm::
rpm -Uvh python-redfish/build/RPMS/python-redfish-devel20160213182552.rpm
============================
Inventory file configuration
============================
#. Verify redfish-client is working correclty::
redfish-client -h
#. Create a default entry to use the mockup::
redfish-client config add default default http://localhost:8000/redfish/v1
#. Verify the entry is correctly registered::
redfish-client config showall
Note: The inventory file is created in $HOME/.redfish
===================
Mockup installation
===================
#. Follow `get the source code <http://pythonhosted.org/python-redfish/readme.html#get-the-source-code>`_ section to retrieve it.
#. Install docker using your distribution packages or the docker `procedure <https://docs.docker.com/engine/installation/>`_ (docker provides more recent packages):
As an example for Fedora 23 use the following::
dnf install docker
systemctl enable docker.service
systemctl start docker.service
systemctl status docker.service
#. Jump into the dmtf directory.
#. Run ./buildImage.sh and ./run-redfish-simulator.sh
#. Check that a container is running and listening on port 8000::
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9943ff1d4d93 redfish-simulator:latest "/bin/sh -c /tmp/redf" 3 weeks ago Up 2 days 0.0.0.0:8000->80/tcp redfish-simulator
#. Try to connect using a navigator to http://localhost:8000 the following screen should apear.
.. image:: images/simulator.jpg
Note : in the above screenshot, firefox JSON-handle extension is used. If you want the same presentation install the extension and refresh the page.
==========================
Testing against the mockup
==========================
#. Follow `Inventory file configuration`_ and `Mockup installation`_ section.
#. Run the following command::
redfish-client manager getinfo
The result should be like this::
$ redfish-client manager getinfo
Gathering data from manager, please wait...
Redfish API version : 1.00
Root Service
Managers information :
======================
Manager id 1:
UUID : 00000000-0000-0000-0000-000000000000
Type : BMC
Firmware version : 1.00
State : Enabled
Ethernet Interface :
This manager has no ethernet interface
Managed Chassis :
1
Managed System :
1
----------------------------
Manager id 2:
UUID : 00000000-0000-0000-0000-000000000000
Type : EnclosureManager
Firmware version : Not available
State : Enabled
Ethernet Interface :
This manager has no ethernet interface
Managed Chassis :
Enc1
Managed System :
2
----------------------------
Manager id 3:
UUID : 00000000-0000-0000-0000-000000000000
Type : EnclosureManager
Firmware version : Not available
State : Enabled
Ethernet Interface :
This manager has no ethernet interface
Managed Chassis :
Enc1
Managed System :
2
----------------------------
============================
Building local documentation
============================
Building the html documentation locally.
#. Follow `get the source code <http://pythonhosted.org/python-redfish/readme.html#get-the-source-code>`_ section to retrieve it.
#. Jump in the doc directory::
cd doc
#. Build the html documentation::
make html
If you want to build the documentation in pdf.
#. Get texlive full distribution, e.g. on Fedora 23::
dnf install texlive-scheme-full
#. Build the documentation::
make latexpdf
$ mkvirtualenv python-redfish
$ pip install python-redfish

View File

@ -0,0 +1,6 @@
============
config class
============
.. automodule:: redfish.config
:members:

View File

@ -0,0 +1,6 @@
===============
exception class
===============
.. automodule:: redfish.exception
:members:

View File

@ -0,0 +1,6 @@
==========
main class
==========
.. automodule:: redfish.main
:members:

View File

@ -0,0 +1,6 @@
=============
mapping class
=============
.. automodule:: redfish.mapping
:members:

View File

@ -0,0 +1,6 @@
===========
types class
===========
.. automodule:: redfish.types
:members:

View File

@ -0,0 +1,8 @@
======================
python-redfish classes
======================
.. toctree::
:glob:
python-redfish_classes/*

View File

@ -0,0 +1,7 @@
======================
redfish-client classes
======================
.. automodule:: rfclient
:members:

33
doc/source/testing.rst Normal file
View File

@ -0,0 +1,33 @@
=============
Running tests
=============
redfish module tests
--------------------
Tests are not functional for the redfish module yet.
redfish-client tests
--------------------
#. Create your development environment following `Developer setup <develsetup.html>`_.
#. Install docker using the `procedure <https://docs.docker.com/engine/installation/>`_.
#. Ensure you can use docker with your current user.
#. Jump into the python-redfish directory containing the source code.
#. 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
#. Run the test::
tox
or::
py.test redfish-client

View File

@ -2,6 +2,25 @@
Usage
========
To use python-redfish in a project::
Example using the mockup
------------------------
example/simple-simulator.py provide a simple library usage to interact with the
redfish mockup.
Example using a proliant
------------------------
example/simple-proliant.py provide a simple library usage to interact with a HPE
ProLiant BL460C G9 server. However this example should work on any server supplier following redfish
standard.
redfish-client usage
--------------------
The client usage can be display using::
redfish-client -h
This is also available at http://pythonhosted.org/python-redfish/redfish-client.html.
import redfish

View File

@ -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'

View File

@ -1,5 +1,5 @@
{
"Nodes": {
"Managers": {
"default": {
"url": "",
"login": "",

View File

@ -1,12 +1,19 @@
# 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
from builtins import str
import os
import sys
import json
import redfish
from time import sleep
standard_library.install_aliases()
# Get $HOME environment.
HOME = os.getenv('HOME')
@ -16,7 +23,7 @@ if HOME == '':
sys.exit(1)
try:
with open(HOME + "/.redfish.conf") as json_data:
with open(HOME + "/.redfish/inventory") as json_data:
config = json.load(json_data)
json_data.close()
except IOError as e:
@ -24,58 +31,78 @@ except IOError as e:
print(e)
sys.exit(1)
URL = config["Nodes"]["default"]["url"]
USER_NAME = config["Nodes"]["default"]["login"]
PASSWORD = config["Nodes"]["default"]["password"]
URL = config["Managers"]["default"]["url"]
USER_NAME = config["Managers"]["default"]["login"]
PASSWORD = config["Managers"]["default"]["password"]
''' remote_mgmt is a redfish.RedfishConnection object '''
remote_mgmt = redfish.connect(URL, USER_NAME, PASSWORD, verify_cert=False)
try:
remote_mgmt = redfish.connect(URL,
USER_NAME,
PASSWORD,
simulator=False,
verify_cert=False)
except redfish.exception.RedfishException as e:
sys.stderr.write(str(e.message))
sys.stderr.write(str(e.advices))
sys.exit(1)
print ("Redfish API version : %s \n" % remote_mgmt.get_api_version())
# Uncomment following line to reset the blade !!!
#remote_mgmt.Systems.systems_list[0].reset_system()
# remote_mgmt.Systems.systems_dict["1"].reset_system()
# TODO : create an attribute to link the managed system directly
# and avoid systems_list[0]
# --> will be something like :
# remote_mgmt.Systems.systems_list[0] = remote_mgmt.Systems.managed_system
print("Bios version : {}\n".format(
remote_mgmt.Systems.systems_dict["1"].get_bios_version()))
print("Serial Number : {}\n".format(
remote_mgmt.Systems.systems_dict["1"].get_serial_number()))
print("Power State : {}\n".format(
remote_mgmt.Systems.systems_dict["1"].get_power()))
print("Parameter 'SystemType' : {}\n".format(
remote_mgmt.Systems.systems_dict["1"].get_parameter("SystemType")))
print("Bios version : {}\n".format(remote_mgmt.Systems.systems_list[0].get_bios_version()))
print("Serial Number : {}\n".format(remote_mgmt.Systems.systems_list[0].get_serial_number()))
print("Power State : {}\n".format(remote_mgmt.Systems.systems_list[0].get_power()))
print("Parameter 'SystemType' : {}\n".format(remote_mgmt.Systems.systems_list[0].get_parameter("SystemType")))
print("Get bios parameters : {}\n".format(
remote_mgmt.Systems.systems_dict["1"].bios.get_parameters()))
print("Get boot parameters : {}\n".format(
remote_mgmt.Systems.systems_dict["1"].bios.boot.get_parameters()))
print("Get bios parameters : {}\n".format(remote_mgmt.Systems.systems_list[0].bios.get_parameters()))
print("Get boot parameters : {}\n".format(remote_mgmt.Systems.systems_list[0].bios.boot.get_parameters()))
# print("Get bios parameter 'AdminPhone' : {}\n".format(
# remote_mgmt.Systems.systems_dict["1"].bios.get_parameter("AdminPhone")))
# print("Set bios parameter 'AdminPhone' to '' : {}\n".format(
# remote_mgmt.Systems.systems_dict["1"].bios.set_parameter("AdminPhone","")))
#print("Get bios parameter 'AdminPhone' : {}\n".format(remote_mgmt.Systems.systems_list[0].bios.get_parameter("AdminPhone")))
#print("Set bios parameter 'AdminPhone' to '' : {}\n".format(remote_mgmt.Systems.systems_list[0].bios.set_parameter("AdminPhone","")))
# Boot server with script
# remote_mgmt.Systems.systems_dict["1"].bios.set_parameter("Dhcpv4","Enabled")
remote_mgmt.Systems.systems_dict["1"].bios.set_parameter(
"PreBootNetwork", "Auto")
remote_mgmt.Systems.systems_dict["1"].bios.set_parameter(
"UefiShellStartup", "Enabled")
remote_mgmt.Systems.systems_dict["1"].bios.set_parameter(
"UefiShellStartupLocation", "NetworkLocation")
remote_mgmt.Systems.systems_dict["1"].bios.set_parameter(
"UefiShellStartupUrl", "http://10.3.222.88/deploy/startup.nsh")
# remote_mgmt.Systems.systems_dict["1"].set_parameter_json(
# '{"Boot": {"BootSourceOverrideTarget": "UefiShell"}}')
# remote_mgmt.Systems.systems_dict["1"].set_parameter_json(
# '{"Boot": {"BootSourceOverrideEnabled" : "Continuous"}}')
# remote_mgmt.Systems.systems_dict["1"].set_parameter_json(
# '{"Boot": {"BootSourceOverrideEnabled" : "Once"}}')
mySystem = remote_mgmt.Systems.systems_dict["1"]
mySystem.set_boot_source_override("None", "Disabled")
# Uncomment the next line to reset the server
# mySystem.reset_system()
#Boot server with script
#remote_mgmt.Systems.systems_list[0].bios.set_parameter("Dhcpv4","Enabled")
print("Get manager firmware version : {}\n".format(
remote_mgmt.Managers.managers_dict["1"].get_firmware_version()))
print("Get system Bios version : {}\n".format(
remote_mgmt.Systems.systems_dict["1"].get_bios_version()))
remote_mgmt.Systems.systems_list[0].bios.set_parameter("PreBootNetwork", "Auto")
remote_mgmt.Systems.systems_list[0].bios.set_parameter("UefiShellStartup", "Enabled")
remote_mgmt.Systems.systems_list[0].bios.set_parameter("UefiShellStartupLocation", "NetworkLocation")
remote_mgmt.Systems.systems_list[0].bios.set_parameter("UefiShellStartupUrl", "http://10.3.222.88/deploy/startup.nsh")
#remote_mgmt.Systems.systems_list[0].set_parameter_json('{"Boot": {"BootSourceOverrideTarget": "UefiShell"}}')
# remote_mgmt.Systems.systems_list[0].set_parameter_json('{"Boot": {"BootSourceOverrideEnabled" : "Continuous"}}')
#remote_mgmt.Systems.systems_list[0].set_parameter_json('{"Boot": {"BootSourceOverrideEnabled" : "Once"}}')
mySystem = remote_mgmt.Systems.systems_list[0]
mySystem.set_boot_source_override("None","Disabled")
#Uncomment the next line to reset the server
#mySystem.reset_system()
print("Get manager firmware version : {}\n".format(remote_mgmt.Managers.managers_list[0].get_firmware_version()))
print("Get system Bios version : {}\n".format(remote_mgmt.Systems.systems_list[0].get_bios_version()))
#Reset of the system is required to apply the changes
#remote_mgmt.Systems.systems_list[0].reset_system()
# Reset of the system is required to apply the changes
# remote_mgmt.Systems.systems_dict["1"].reset_system()
remote_mgmt.logout()

View File

@ -1,11 +1,17 @@
# 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
import os
import sys
import json
import redfish
standard_library.install_aliases()
# Get $HOME environment.
HOME = os.getenv('HOME')
@ -15,7 +21,7 @@ if HOME == '':
sys.exit(1)
try:
with open(HOME + "/.redfish.conf") as json_data:
with open(HOME + "/.redfish/inventory") as json_data:
config = json.load(json_data)
json_data.close()
except IOError as e:
@ -23,18 +29,28 @@ except IOError as e:
print(e)
sys.exit(1)
URL = config["Nodes"]["default"]["url"]
USER_NAME = config["Nodes"]["default"]["login"]
PASSWORD = config["Nodes"]["default"]["password"]
URL = config["Managers"]["default"]["url"]
USER_NAME = config["Managers"]["default"]["login"]
PASSWORD = config["Managers"]["default"]["password"]
''' remoteMgmt is a redfish.RedfishConnection object '''
remote_mgmt = redfish.connect(URL, USER_NAME, PASSWORD,
simulator=True, enforceSSL=False)
try:
remote_mgmt = redfish.connect(URL,
USER_NAME,
PASSWORD,
simulator=True,
enforceSSL=False)
except redfish.exception.RedfishException as e:
sys.stderr.write(e.message)
sys.stderr.write(e.advices)
sys.exit(1)
print("Redfish API version : {} \n".format(remote_mgmt.get_api_version()))
print("UUID : {} \n".format(remote_mgmt.Root.get_api_UUID()))
print("System 1 :\n")
print("Bios version : {}\n".format(remote_mgmt.Systems.systems_list[0].get_bios_version()))
print("Bios version : {}\n".format(
remote_mgmt.Systems.systems_dict["1"].get_bios_version()))
print("System 2 :\n")
print("Bios version : {}\n".format(remote_mgmt.Systems.systems_list[1].get_parameter("SerialNumber")))
#print remoteMgmt.get_api_link_to_server()
print("Bios version : {}\n".format(
remote_mgmt.Systems.systems_dict["2"].get_parameter("SerialNumber")))

View File

@ -1,58 +0,0 @@
#!/usr/bin/env python
#import logging
import sys
#from oslo_config import cfg
#from oslo_log import log as logging
import redfish
# Sets up basic logging for this module
#log_root = logging.getLogger('redfish')
#log_root.addHandler(logging.StreamHandler(sys.stdout))
#log_root.setLevel(logging.DEBUG)
#CONF = cfg.CONF
#logging.set_defaults(['redfish=DEBUG'])
#logging.register_options(CONF)
#logging.setup(CONF, "redfish")
# Connect to a redfish API endpoint
host = 'http://localhost'
user_name = ''
password = ''
# This returns a RedfishConnection object, which implements
# the low-level HTTP methods like GET, PUT, etc
connection = redfish.server.connect(host, user_name, password)
# From this connection, we can get the Root resource.
# Note that the root resource is somewhat special - you create it from
# the connection, but you create other resources from the root resource.
# (You don't strictly have to do this, but it's simpler.)
root = connection.get_root()
print("\n")
print("ROOT CONTROLLER")
print("===============")
print(root)
# The Root class has well-defined top-level resources, such as
# chassis, systems, managers, sessions, etc...
chassis = root.get_chassis()
print("\n")
print("CHASSIS DATA")
print("============")
print(chassis)
print("\n")
print("WALKING CHASSIS")
print("\n")
print("CHASSIS contains %d items" % len(chassis))
print("\n")
for item in chassis:
print("SYSTEM")
print("======")
print(item)
print("\n")

37
install.sh Executable file
View File

@ -0,0 +1,37 @@
#!/bin/bash
# Syntax: install.sh <Python> <Root Dir> <Python SiteLib> <Prefix> <PkgName>
set -x
export python=$1
export rootdir=$2
export sitelib=$3
export prefix=$4
export pkg=$5
# Documentation installation only
if [ $python = "doc" ]; then
install -d 755 $rootdir/$prefix/share/doc/$5/html/_static
install -m 644 doc/build/singlehtml/*.html $rootdir/$prefix/share/doc/$5/html
install -m 644 doc/build/singlehtml/_static/* $rootdir/$prefix/share/doc/$5/html/_static
install -m 644 doc/build/latex/*.pdf $rootdir/$prefix/share/doc/$5/
exit 0
fi
pyver=`$python --version 2>&1 | perl -p -e 's|.* ([2-3])\..*|$1|'`
$python setup.py install --skip-build --root=$rootdir --prefix=$prefix
rm -rf $rootdir/$sitelib/redfish/old
# Hardcoded for now to solve the delivery of the conf file still not correct with setup.py
mkdir -p $rootdir/etc
mv $rootdir/$prefix/etc/redfish-client.conf $rootdir/etc/redfish-client.conf
# Man pages installation
for i in 1; do
mkdir -p $rootdir/$prefix/share/man/man$i
for e in `ls doc/build/man/*.$i`; do
ne=`echo $e | perl -p -e 's|.*/([^/]*)\.'$i'|$1-py'$pyver.$i'|'`
install -m 644 $e $rootdir/$prefix/share/man/man$i/$ne
done
done

View File

@ -1,6 +0,0 @@
[DEFAULT]
# The list of modules to copy from oslo-incubator.git
# The base module to hold the copy of openstack.common
base=redfish

72
pbconf/pbfilter/all.pbf Normal file
View File

@ -0,0 +1,72 @@
#
# $Id$
#
# Filter for all files
#
#
# PBREPO is replaced by the root URL to access the repository
filter PBREPO = $pb->{'repo'}
# PBSRC is replaced by the source package location after the repo
filter PBSRC = src/%{name}-%{version}.tar.gz
# Used if virtual name != real name (perl, ...)
#filter PBSRC = src/%{srcname}-%{version}.tar.gz
# PBVER is replaced by the version ($pb->{'ver'} in code)
filter PBVER = $pb->{'ver'}$pb->{'extdir'}
# PBDATE is replaced by the date ($pb->{'date'} in code)
filter PBDATE = $pb->{'date'}
# PBEXTDIR is replaced by the testdir extension if needed ($pb->{'extdir'} in code)
filter PBEXTDIR = $pb->{'extdir'}
# PBPATCHSRC is replaced by the patches names if value is yes. Patches are located under the pbpatch dir of the pkg.
#filter PBPATCHSRC = yes
# PBPATCHCMD is replaced by the patches commands if value is yes
#filter PBPATCHCMD = yes
# PBMULTISRC is replaced by the sources names if value is yes. Sources are located under the pbsrc dir of the pkg.
#filter PBMULTISRC = yes
# PBTAG is replaced by the tag ($pb->{'tag'} in code)
filter PBTAG = $pb->{'tag'}
# PBREV is replaced by the revision ($pb->{'rev'} in code)
filter PBREV = $pb->{'rev'}
# PBREALPKG is replaced by the package name ($pb->{'realpkg'} in code)
filter PBREALPKG = $pb->{'realpkg'}
# PBPKG is replaced by the package name ($pb->{'pkg'} in code)
filter PBPKG = $pb->{'pkg'}
# PBPROJ is replaced by the project name ($pb->{'proj'} in code)
filter PBPROJ = $pb->{'proj'}
# PBPACKAGER is replaced by the packager name ($pb->{'packager'} in code)
filter PBPACKAGER = $pb->{'packager'}
# PBDESC contains the description of the package
filter PBDESC = The Redfish API supports dialoging with a Redfish compliant$/system such as defined by http://www.redfishcertification.org
# with a trailing , the variable can be multi-line.
# only the trailing 's will be removed, the leading spaces,
# trailing spaces, and newlines will remain except on the
# last line. You can use dollar slash as a way to introduce carriage
# return (perl syntax).
# You can use transform e.g. in rpm.pbf to adjust spaces
# PBSUMMARY contains a short single line description of the package
filter PBSUMMARY = Redfish python library
# PBURL contains the URL of the Web site of the project
filter PBURL = http://github.com/bcornec/python-redfish
# PBLOG is replaced by the changelog if value is yes
# and should be last as when used we need the %pb hash filled
filter PBLOG = yes
filter PBCONFFILE = /etc/redfish-client.conf
filter PBTEMPLATEPATH = /usr/share/redfish-client/templates
filter PBPYTHON3FILTER = perl -pi -e "s|configparser>=3.3.0; python_version < '3'|configparser>=3.3.0|" requirements.txt

23
pbconf/pbfilter/deb.pbf Normal file
View File

@ -0,0 +1,23 @@
#
# $Id$
#
# Filter for debian build
#
# PBGRP is replaced by the group of apps
filter PBGRP = utils
# PBLIC is replaced by the license of the application
# Cf: http://www.debian.org/legal/licenses/
filter PBLIC = ASL 2.0
# PBDEP is replaced by the list of dependencies
filter PBDEP = python-docopt, python-tortilla, python-jinja2, python-pbr, python-docopt, python-simplejson
# PBBDEP is replaced by the list of build dependencies
filter PBBDEP = python-dev, python-setuptools, python-pbr, python-tortilla, python-jinja2, python-sphinx
# PBSUG is replaced by the list of suggestions
#filter PBSUG =
# PBREC is replaced by the list of recommandations
#filter PBREC =

View File

@ -0,0 +1,11 @@
#
# $Id$
#
# Filter for debian build
#
# PBDEBSTD is replaced by the Debian standard version
filter PBDEBSTD = 3.6.1
# PBDEBCOMP is replaced by the Debian Compatibility value
filter PBDEBCOMP = 4

View File

@ -0,0 +1,11 @@
#
# $Id$
#
# Filter for debian build
#
# PBDEBSTD is replaced by the Debian standard version
filter PBDEBSTD = 3.6.1
# PBDEBCOMP is replaced by the Debian Compatibility value
filter PBDEBCOMP = 5

View File

@ -0,0 +1,11 @@
#
# $Id$
#
# Filter for debian build
#
# PBDEBSTD is replaced by the Debian standard version
filter PBDEBSTD = 3.8.0
# PBDEBCOMP is replaced by the Debian Compatibility value
filter PBDEBCOMP = 7

View File

@ -0,0 +1,11 @@
#
# $Id$
#
# Filter for debian build
#
# PBDEBSTD is replaced by the Debian standard version
filter PBDEBSTD = 3.8.0
# PBDEBCOMP is replaced by the Debian Compatibility value
filter PBDEBCOMP = 7

View File

@ -0,0 +1,11 @@
#
# $Id$
#
# Filter for debian build
#
# PBDEBSTD is replaced by the Debian standard version
filter PBDEBSTD = 3.9.4
# PBDEBCOMP is replaced by the Debian Compatibility value
filter PBDEBCOMP = 9

View File

@ -0,0 +1,11 @@
#
# $Id$
#
# Filter for debian build
#
# PBDEBSTD is replaced by the Debian standard version
filter PBDEBSTD = 3.8.0
# PBDEBCOMP is replaced by the Debian Compatibility value
filter PBDEBCOMP = 7

View File

@ -0,0 +1,9 @@
#
# $Id$
#
# Filter for old fedora build
#
# PBSUF is replaced by the package suffix ($pb->{'suf'} in code)
filter PBSUF = $pb->{'suf'}

View File

@ -0,0 +1,9 @@
#
# $Id$
#
# Filter for old fedora build
#
# PBSUF is replaced by the package suffix ($pb->{'suf'} in code)
filter PBSUF = $pb->{'suf'}

View File

@ -0,0 +1,9 @@
#
# $Id$
#
# Filter for old fedora build
#
# PBSUF is replaced by the package suffix ($pb->{'suf'} in code)
filter PBSUF = $pb->{'suf'}

View File

@ -0,0 +1,9 @@
#
# $Id$
#
# Filter for old fedora build
#
# PBSUF is replaced by the package suffix ($pb->{'suf'} in code)
filter PBSUF = $pb->{'suf'}

View File

@ -0,0 +1,9 @@
#
# $Id$
#
# Filter for old fedora build
#
# PBSUF is replaced by the package suffix ($pb->{'suf'} in code)
filter PBSUF = $pb->{'suf'}

View File

@ -0,0 +1,9 @@
#
# $Id$
#
# Filter for old fedora build
#
# PBSUF is replaced by the package suffix ($pb->{'suf'} in code)
filter PBSUF = $pb->{'suf'}

View File

@ -0,0 +1,9 @@
#
# $Id$
#
# Filter for old fedora build
#
# PBSUF is replaced by the package suffix ($pb->{'suf'} in code)
filter PBSUF = $pb->{'suf'}

View File

@ -0,0 +1,26 @@
#
# $Id$
#
# Filter for rpm build
#
# PBGRP is replaced by the RPM group of apps
# Cf: http://fedoraproject.org/wiki/RPMGroups
#filter PBGRP = Applications/Archiving
# PBLIC is replaced by the license of the application
# Cf: http://fedoraproject.org/wiki/Licensing
#filter PBLIC = GPLv2+
# PBDEP is replaced by the list of dependencies
#filter PBDEP =
# PBBDEP is replaced by the list of build dependencies
#filter PBBDEP =
# PBSUF is replaced by the package suffix ($pb->{'suf'} in code)
filter PBSUF = %{dist}
# PBOBS is replaced by the Obsolete line
#filter PBOBS =

8
pbconf/pbfilter/md.pbf Normal file
View File

@ -0,0 +1,8 @@
# Specific group for Mandriva for python-redfish
# Cf: http://wiki.mandriva.com/en/Development/Packaging/Groups
filter PBGRP = Development/Python
# PBLIC is replaced by the license of the application
# Cf: http://wiki.mandriva.com/en/Development/Packaging/Licenses
#filter PBLIC = GPL

View File

@ -0,0 +1,8 @@
# Specific group for SuSE for python-redfish
# Cf: http://en.opensuse.org/SUSE_Package_Conventions/RPM_Groups
#filter PBGRP = Productivity/Archiving/Backup
# PBLIC is replaced by the license of the application
# Cf: http://en.opensuse.org/Packaging/SUSE_Package_Conventions/RPM_Style#1.6._License_Tag
#filter PBLIC = GPL

8
pbconf/pbfilter/pkg.pbf Normal file
View File

@ -0,0 +1,8 @@
#
# $Id$
#
# Filter for pkg build
#
# Solaris package name (VENDOR : 4 letters in uppercase, SOFT : 8 letters in lowercase)
filter PBSOLPKG = SUNWsoftware

33
pbconf/pbfilter/rpm.pbf Normal file
View File

@ -0,0 +1,33 @@
#
# $Id$
#
# Filter for rpm build
#
# PBGRP is replaced by the RPM group of apps
filter PBGRP = Applications/System
# PBLIC is replaced by the license of the application
filter PBLIC = ASL 2.0
# PBDEP is replaced by the list of dependencies
#filter PBDEP =
# PBBDEP is replaced by the list of build dependencies
filter PBPYTHON2BDEP = python-devel,python-setuptools,python-pbr >= 0.8,python-sphinx >= 1.2.3,python-future >= 0.15.2
filter PBPYTHON2DEP = python-docopt >= 0.6.2,python-tortilla >= 0.4.1,python-jinja2 >= 2.7.3,python-pbr >= 0.8,python-simplejson >= 3.8.1,python-requests >= 2.9.1,python-configparser >= 3.3.0
filter PBPYTHON3BDEP = python3-devel,python3-setuptools,python3-pbr >= 0.8,python3-sphinx >= 1.2.3,python3-future >= 0.15.2
filter PBPYTHON3DEP = python3-docopt >= 0.6.2,python3-tortilla >= 0.4.1,python3-jinja2 >= 2.7.3,python3-pbr >= 0.8,python3-simplejson >= 3.8.1,python3-requests >= 2.9.1
filter PBPYTHON3PKG = python3-redfish
# PBSUF is replaced by the package suffix ($pb->{'suf'} in code)
filter PBSUF = $pb->{'suf'}
# PBOBS is replaced by the Obsolete line
#filter PBOBS =
# transform a variable from the key on the right to the key on the left using the perl expression
# after the input key name. Useful for taking multi-line documentation and removing trailing spaces
# or leading spaces.
#transform PBDESC = PBDESC_raw s/\s+\n/\n/go;

View File

@ -0,0 +1,11 @@
#
# $Id$
#
# Filter for ubuntu build
#
# PBDEBSTD is replaced by the Debian standard version
filter PBDEBSTD = 3.6.2
# PBDEBCOMP is replaced by the Debian Compatibility value
filter PBDEBCOMP = 4

View File

@ -0,0 +1,11 @@
#
# $Id$
#
# Filter for ubuntu build
#
# PBDEBSTD is replaced by the Debian standard version
filter PBDEBSTD = 3.6.2
# PBDEBCOMP is replaced by the Debian Compatibility value
filter PBDEBCOMP = 4

View File

@ -0,0 +1,11 @@
#
# $Id$
#
# Filter for ubuntu build
#
# PBDEBSTD is replaced by the Debian standard version
filter PBDEBSTD = 3.6.2
# PBDEBCOMP is replaced by the Debian Compatibility value
filter PBDEBCOMP = 4

View File

@ -0,0 +1,11 @@
#
# $Id$
#
# Filter for ubuntu build
#
# PBDEBSTD is replaced by the Debian standard version
filter PBDEBSTD = 3.7.3
# PBDEBCOMP is replaced by the Debian Compatibility value
filter PBDEBCOMP = 4

View File

@ -0,0 +1,11 @@
#
# $Id$
#
# Filter for ubuntu build
#
# PBDEBSTD is replaced by the Debian standard version
filter PBDEBSTD = 3.7.3
# PBDEBCOMP is replaced by the Debian Compatibility value
filter PBDEBCOMP = 4

View File

@ -0,0 +1,11 @@
#
# $Id$
#
# Filter for ubuntu build
#
# PBDEBSTD is replaced by the Debian standard version
filter PBDEBSTD = 3.8.0
# PBDEBCOMP is replaced by the Debian Compatibility value
filter PBDEBCOMP = 4

View File

@ -0,0 +1,11 @@
#
# $Id$
#
# Filter for ubuntu build
#
# PBDEBSTD is replaced by the Debian standard version
filter PBDEBSTD = 3.8.3
# PBDEBCOMP is replaced by the Debian Compatibility value
filter PBDEBCOMP = 7

139
pbconf/python-redfish.pb Normal file
View File

@ -0,0 +1,139 @@
#
# Project Builder configuration file
# For project python-redfish
#
# $Id$
#
#
# What is the project URL
#
#pburl python-redfish = svn://svn.python-redfish.org/python-redfish/devel
#pburl python-redfish = svn://svn+ssh.python-redfish.org/python-redfish/devel
#pburl python-redfish = cvs://cvs.python-redfish.org/python-redfish/devel
#pburl python-redfish = http://www.python-redfish.org/src/python-redfish-devel.tar.gz
#pburl python-redfish = ftp://ftp.python-redfish.org/src/python-redfish-devel.tar.gz
#pburl python-redfish = file:///src/python-redfish-devel.tar.gz
#pburl python-redfish = dir:///src/python-redfish-devel
pburl python-redfish = git+ssh://git@github.com/bcornec/python-redfish.git
# Repository
pbrepo python-redfish = ftp://ftp.mondorescue.org
pbml python-redfish = python-redfish@mondorescue.org
#pbsmtp python-redfish = localhost
# For distro supporting it, which area is used
#projcomponent python-redfish = main
# Check whether project is well formed
# when downloading from ftp/http/...
# (containing already a directory with the project-version name)
pbwf python-redfish = 1
# Do we check GPG keys
pbgpgcheck python-redfish = 1
#
# Packager label
#
pbpackager python-redfish = Bruno Cornec <bruno@project-builder.org>
#
# For delivery to a machine by SSH (potentially the FTP server)
# Needs hostname, account and directory
#
sshhost python-redfish = www.mondorescue.org
sshlogin python-redfish = bruno
sshdir python-redfish = /prj/ftp
sshport python-redfish = 22
#
#
# For Virtual machines management
# Naming convention to follow: distribution name (as per ProjectBuilder::Distribution)
# followed by '-' and by release number
# followed by '-' and by architecture
# a .vmtype extension will be added to the resulting string
# a QEMU rhel-3-i286 here means that the VM will be named rhel-3-i386.qemu
#
vmlist python-redfish = rhel-6-i386,opensuse-12.3-i386,sles-11-i386,gentoo-nover-i386,debian-8-i386,ubuntu-14.04-i386,ubuntu-15.10-i386,mageia-4-i386,mageia-5-i386,mageia-4-x86_64,mageia-5-x86_64,fedora-22-x86_64,fedora-23-x86_64,rhel-6-x86_64,rhel-7-x86_64,opensuse-12.3-i386,sles-10-x86_64,sles-11-x86_64,sles-12-x86_64,gentoo-nover-x86_64,debian-8-x86_64,ubuntu-14.04-x86_64,ubuntu-15.10-x86_64
#
# Valid values for vmtype are
# qemu, (vmware, xen, ... TBD)
#vmtype python-redfish = qemu
# Hash for VM stuff on vmtype
#vmntp default = pool.ntp.org
# We suppose we can commmunicate with the VM through SSH
#vmhost python-redfish = localhost
#vmlogin python-redfish = pb
#vmport python-redfish = 2222
# Timeout to wait when VM is launched/stopped
#vmtmout default = 120
# per VMs needed paramaters
#vmopt python-redfish = -m 384 -daemonize
#vmpath python-redfish = /home/qemu
#vmsize python-redfish = 5G
#
# For Virtual environment management
# Naming convention to follow: distribution name (as per ProjectBuilder::Distribution)
# followed by '-' and by release number
# followed by '-' and by architecture
# a .vetype extension will be added to the resulting string
# a chroot rhel-3-i286 here means that the VE will be named rhel-3-i386.chroot
#
#velist python-redfish = fedora-7-i386
# VE params
vetype python-redfish = docker
#ventp default = pool.ntp.org
#velogin python-redfish = pb
#vepath python-redfish = /var/cache/rpmbootstrap
#rbsconf python-redfish = /etc/mock
#verebuild python-redfish = false
#
# Global version/tag for the project
#
projver python-redfish = devel
projtag python-redfish = 1
# Hash of valid version names
# Additional repository to add at build time
# addrepo centos-5-x86_64 = http://packages.sw.be/rpmforge-release/rpmforge-release-0.3.6-1.el5.rf.x86_64.rpm,ftp://ftp.project-builder.org/centos/5/pb.repo
# addrepo centos-5-x86_64 = http://packages.sw.be/rpmforge-release/rpmforge-release-0.3.6-1.el5.rf.x86_64.rpm,ftp://ftp.project-builder.org/centos/5/pb.repo
#version python-redfish = devel,stable
# Is it a test version or a production version
testver python-redfish = true
# Which upper target dir for delivery
delivery python-redfish = test
# Additional repository to add at build time
# addrepo centos-5-x86_64 = http://packages.sw.be/rpmforge-release/rpmforge-release-0.3.6-1.el5.rf.x86_64.rpm,ftp://ftp.project-builder.org/centos/5/pb.repo
# addrepo centos-4-x86_64 = http://packages.sw.be/rpmforge-release/rpmforge-release-0.3.6-1.el4.rf.x86_64.rpm,ftp://ftp.project-builder.org/centos/4/pb.repo
# Adapt to your needs:
# Optional if you need to overwrite the global values above
#
#pkgver python-redfish = stable
#pkgtag python-redfish = 3
# Hash of default package/package directory
defpkgdir python-redfish = .
# Hash of additional package/package directory
#extpkgdir minor-pkg = dir-minor-pkg
# List of files per pkg on which to apply filters
# Files are mentioned relatively to pbroot/defpkgdir
filteredfiles python-redfish = redfish-client/redfish-client,doc/source/conf.py,redfish-client/etc/redfish-client.conf,install.sh
#supfiles python-redfish = python-redfish.init
# For perl modules, names are different depending on distro
# Here perl-xxx for RPMs, libxxx-perl for debs, ...
# So the package name is indeed virtual
#namingtype python-redfish = perl

View File

@ -0,0 +1 @@
PBLOG

View File

@ -0,0 +1 @@
PBDEBCOMP

View File

@ -0,0 +1,24 @@
Source: PBPKG
# http://www.debian.org/doc/debian-policy/ch-archive.html#s-subsections
Section: PBGRP
Priority: optional
Maintainer: PBPACKAGER
Build-Depends: debhelper (>= 4.2.20), python-dev (>= 2.7), PBBDEP
X-Python-Version: >= 2.7
Standards-Version: PBDEBSTD
Vcs-Svn: https://github.com/bcornec/PBPROJ
Vcs-Browser: https://github.com/bcornec/PBPROJ
Homepage: PBURL
Package: PBPKG
Architecture: amd64 i386 ia64
# http://www.debian.org/doc/debian-policy/ch-archive.html#s-subsections
Section: PBGRP
Priority: optional
Depends: ${shlibs:Depends}, ${misc:Depends}, python (>= 2.7), PBDEP
Recommends: PBREC
Suggests: PBSUG
Description: PBSUMMARY
PBDESC
.

View File

@ -0,0 +1,27 @@
This package is debianized by PBPACKAGER
`date`
The current upstream source was downloaded from
PBREPO.
Upstream Authors: Put their name here
Copyright:
This package is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 dated June, 1991.
This package is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this package; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA 02110-1301, USA.
On Debian systems, the complete text of the GNU General
Public License can be found in /usr/share/common-licenses/GPL.

View File

@ -0,0 +1,5 @@
INSTALL
COPYING
AUTHORS
NEWS
README

View File

@ -0,0 +1,13 @@
#!/usr/bin/make -f
export PYBUILD_NAME=PBPKG
export PYBUILD_AFTER_INSTALL_python3=rm -rf {destdir}/usr/bin
%:
dh $@ --with python2,python3,sphinxdoc --buildsystem=pybuild
#dh $@ --with python2,python3 --buildsystem=python_distutils
PYPI_DESC = PBSUMMARY
DEB_UPSTREAM_VERSION=$(shell dpkg-parsechangelog | sed -rne 's,^Version: ([^-]+).*,\1,p')
help2man = PYTHONPATH=${CURDIR} help2man -N --version-string=${DEB_UPSTREAM_VERSION} \
-o $1 -n '$2' $(CURDIR)/debian/PBPKG/usr/bin/$(subst .1,,$1)

View File

@ -0,0 +1,30 @@
# $Id$
PYTHON-REDFISH CHANGES
devel (2050-01-01)
- TBD ()
v0.2 (2015-12-08)
- first rpm made using project-builder.org (Bruno Cornec)
- Update the simple-simulator example (René Ribaud)
- Update redfish-client (René Ribaud)
- Add both UEFI parameters "Continuous" and "Once" as an example (Vincent Misson)
- New function set_parameter and set_parameter_json on Systems Class (Vincent Misson)
- New classes in types.py: Bios & Boot (Vincent Misson)
- New function get_power() and generic function get_parameter(parameter_name) for class Systems (Vincent Misson)
- Create new function: get_serialnumber. Tested with Simulator (v1) + Redfish Proliant 0.9.5 and 1.0 (Vincent Misson)
- Various doc updates (Bruno COrnec, René Ribaud)
v0.1 (2015-09-09)
- Uses tortilla lib to wrap the REST API (René Ribaud)
- Uses python requests to manage login/logout (René Ribaud)
- Provides 2 functional working examples with Redfish simulator and ProLiant server or Moonshot Server (René Ribaud)
- Remove OpenStack deps as this code has to be usable outside of OpenStack (Bruno Cornec)
- Provides a configuration file to handle credentials and connection URL (René Ribaud)
- Provides a mapping class to handle multiple versions of Redfish (in this version, 0.95.0 for ProLiant and 1.0.0 for mockup) (René Ribaud)
- Provides a first action reset_server to ... reset system The action is commented into simple-proliant.py to not do unexpected reset. (René Ribaud)
- Provides a first retrieving function get_bios_version to get the BIOS version of a system. (René Ribaud)
- Add basic logging capability (René Ribaud)
- Change the documentation to reference Redfish specification. Remove HP and iLO specific references (Samer El-Haj-Mahmoud)
- Initial content and Clean up to meet pep8 and doc strings (Devenanda van der Veen)

View File

@ -0,0 +1,4 @@
#
# $Id$
#
#P SUNWperl584core Perl 5.8.4 (core)

View File

@ -0,0 +1,7 @@
#
# $Id$
#
#perl Makefile.PL INSTALLDIRS=vendor
./configure --prefix=/usr
make
make install DESTDIR=\$1

View File

@ -0,0 +1,13 @@
#
# $Id$
#
PKG="PBSOLPKG"
NAME="PBREALPKG"
VERSION="PBVER"
# all or i386
ARCH="all"
CATEGORY="application"
DESC="PBSUMMARY"
EMAIL="PBPACKAGER"
VENDOR="PBPACKAGER"
HOTLINE="PBURL"

View File

@ -0,0 +1,105 @@
#
# $Id$
#
Name: PBREALPKG
Version: PBVER
Release: PBTAGPBSUF
Summary: PBSUMMARY
License: PBLIC
Group: PBGRP
Url: PBURL
Source: PBREPO/PBSRC
Requires: PBPYTHON2DEP
BuildArch: noarch
BuildRequires: PBPYTHON2BDEP
%description
PBDESC
Python2 version.
%package -n PBPYTHON3PKG
Summary: %{summary} / Python 3 library
BuildRequires: PBPYTHON3BDEP
Requires: PBPYTHON3DEP
%package -n PBREALPKG-doc
Summary: %{summary} / Documentation
BuildRequires: PBPYTHON3BDEP
Requires: PBPYTHON3DEP
%description -n PBPYTHON3PKG
PBDESC
Python3 version.
%description -n PBREALPKG-doc
PBDESC
Documentation
%prep
%setup -q
# Fix for now as long as setuptools isn't more recent in distributions
PBPYTHON3FILTER
cp -a . %{py3dir}
%build
pushd %{py3dir}
%{__python3} setup.py build
# Build minimal documentation
cd doc
make man
popd
%{__python} setup.py build
# Build minimal documentation
cd doc
make man
make singlehtml
make latexpdf
%install
./install.sh %{__python} %{buildroot} %{python_sitelib} %{_prefix} PBPKG
./install.sh doc %{buildroot} %{python_sitelib} %{_prefix} PBPKG
for i in `ls %{buildroot}/%{_mandir}/man1/*-py2.1*`; do
j=`echo $i | perl -p -e 's|-py2||'`
cp -a $i $j
done
pushd %{py3dir}
./install.sh %{__python3} %{buildroot} %{python3_sitelib} %{_prefix} PBPYTHON3PKG
popd
%files
%doc README.rst examples/[a-z]*.py LICENSE
%{_bindir}/redfish-client
%dir %{_datadir}/redfish-client
%{_datadir}/redfish-client/templates/*
%config(noreplace) %{_sysconfdir}/redfish-client.conf
%dir %{python_sitelib}/redfish
%{python_sitelib}/redfish/*.py*
%{python_sitelib}/redfish/tests/*.py*
%{python_sitelib}/python_redfish*
# Needs improvement to host all .1 man pages but not the py3 ones
%{_mandir}/man1/PBREALPKG.1*
%{_mandir}/man1/*-py2.1*
%files -n PBPYTHON3PKG
%doc README.rst examples/[a-z]*.py LICENSE
%dir %{python3_sitelib}/redfish
%{python3_sitelib}/redfish/*.py*
%{python3_sitelib}/redfish/__pycache__/*.py*
%{python3_sitelib}/redfish/tests/*.py*
%{python3_sitelib}/redfish/tests/__pycache__/*.py*
%{python3_sitelib}/python_redfish*
%{_mandir}/man1/*-py3.1*
%files -n PBREALPKG-doc
%{_docdir}/PBREALPKG/html/_static/*
%{_docdir}/PBREALPKG/html/index.html
%{_docdir}/PBREALPKG/*.pdf
%changelog
PBLOG

View File

@ -1,36 +0,0 @@
%global srcname redfish
Name: python-%{srcname}
Version: 0.1
Release: %mkrel 1
Summary: Redfish python library
Group: Development/Python
License: Apache v2.0
URL: https://github.com/devananda/%{name}
Source0: %name-%version.tar.gz
BuildArch: noarch
BuildRequires: python-devel
BuildRequires: python-setuptools
%description
The Redfish API supports dialoging with a Redfish compliant
system such as defined by http://www.redfishcertification.org
%prep
%setup -q -n %{name}
#-%{version}
%build
%{__python} setup.py build
%install
%{__python} setup.py install -O1 --skip-build --root %{buildroot}
%files
%doc README.rst examples/*.py
%dir %{python_sitelib}/redfish
%{python_sitelib}/redfish/*.py*
%{python_sitelib}/redfish/tests/*.py*
%{python_sitelib}/python_redfish*

View File

@ -0,0 +1,2 @@
[redfish-client]
templates_path = PBTEMPLATEPATH

448
redfish-client/redfish-client Executable file
View File

@ -0,0 +1,448 @@
#!/usr/bin/python
# coding=utf-8
'''
redfish-client ::
Usage:
redfish-client [options] config add <manager_name> <manager_url> [<login>] [<password>]
redfish-client [options] config del <manager_name>
redfish-client [options] config modify <manager_name> (manager_name | url | login | password) <changed_value>
redfish-client [options] config show
redfish-client [options] config showall
redfish-client [options] manager getinfo [<manager_name>]
redfish-client [options] chassis getinfo [<manager_name>]
redfish-client [options] system getinfo [<manager_name>]
redfish-client (-h | --help)
redfish-client --version
Options:
-h --help Show this screen.
--version Show version.
-c --config FILE Configuration file
-i --inventory FILE Configuration file [default: $HOME/.redfish/inventory]
--insecure Ignore SSL certificates
--debug LEVEL Run in debug mode, LEVEL from 1 to 3 increase verbosity
Security warning LEVEL > 1 could reveal password into the logs
--debugfile FILE Specify the client debugfile [default: $HOME/.redfish/redfish-client.log]
--libdebugfile FILE Specify python-redfish library log file [default: $HOME/.redfish/python-redfish.log]
config commands : manage the configuration file.
manager commands : manage the manager (Light out management). If <manager_name>
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
from builtins import str
from builtins import object
import os
import sys
import json
import pprint
import docopt
import logging
import configparser
import jinja2
import requests.packages.urllib3
import redfish
standard_library.install_aliases()
class InventoryFile(object):
'''redfisht-client inventory file management'''
def __init__(self, inventory_file):
'''Initialize the inventory file
Open and load configuration file data.
If the file does not exist create an empty one ready to receive data
:param inventory_file: File name of the configuration file
default: ~/.redfish/inventory
:type config-file: str
:returns: Nothing
'''
self._inventory_file = inventory_file
# read json file
try:
with open(self._inventory_file) as json_data:
self.data = json.load(json_data)
json_data.close()
except (ValueError, IOError):
self.data = {'Managers': {}}
def save(self):
'''Save the configuration file data'''
try:
with open(self._inventory_file, 'w') as json_data:
json.dump(self.data, json_data)
json_data.close()
except IOError as e:
print(e.msg)
sys.exit(1)
def manager_incorect(self, exception):
''' Log and exit if manager name is incorect'''
logger.error('Incorrect manager name : %s' % exception.args)
sys.exit(1)
def check_manager(self, manager_name):
'''Check if the manager exists in configuration file
:param manager_name: Name of the manager
:type manager_name: str
'''
try:
if manager_name not in self.get_managers():
raise KeyError(manager_name)
except KeyError as e:
self.manager_incorect(e)
def add_manager(self, manager_name, url, login, password):
'''Add a manager to the configuration file
:param manager_name: Name of the manager
:type manager_name: str
:param url: Url of the manager
:type url: str
:param login: Login of the manager
:type login: str
:param password: Password of the manager
:type password: str
'''
self.data['Managers'][manager_name] = {}
self.data['Managers'][manager_name]['url'] = url
if login is None:
login = ''
if password is None:
password = ''
self.data['Managers'][manager_name]['login'] = login
self.data['Managers'][manager_name]['password'] = password
def modify_manager(self, manager_name, parameter, parameter_value):
'''Modify the manager settings
:param manager_name: Name of the manager
:type manager_name: str
:param parameter: url | login | password
:type url: str
:param parameter_value: Value of the parameter
:type parameter_value: str
:returns: Nothing
'''
if parameter == 'url':
try:
self.data['Managers'][manager_name]['url'] = parameter_value
except KeyError as e:
self.manager_incorect(e)
elif parameter == 'login':
try:
self.data['Managers'][manager_name]['login'] = parameter_value
except KeyError as e:
self.manager_incorect(e)
elif parameter == 'password':
try:
self.data['Managers'][manager_name]['password'] \
= parameter_value
except KeyError as e:
self.manager_incorect(e)
elif parameter == 'manager_name':
# Create a new entry with the new name
self.add_manager(parameter_value,
self.data['Managers'][manager_name]['url'],
self.data['Managers'][manager_name]['login'],
self.data['Managers'][manager_name]['password'],
)
# Remove the previous one
self.delete_manager(manager_name)
def delete_manager(self, manager_name):
'''Delete manager
:param manager_name: Name of the manager
:type manager_name: str
:returns: Nothing
'''
try:
del self.data['Managers'][manager_name]
except KeyError as e:
self.manager_incorect(e)
def get_managers(self):
'''Get manager configured
:returns: Managers
:type returns: list
'''
managers = []
for manager in self.data['Managers']:
managers += [manager]
return(managers)
def get_manager_info(self, manager):
'''Show manager info (url, login, password)
:param manager: Name of the manager
:type manager: str
:returns: info containing url, login, password
:type returns: dict
'''
info = {}
url = self.data['Managers'][manager]['url']
login = self.data['Managers'][manager]['login']
password = self.data['Managers'][manager]['password']
info = {'url': url, 'login': login, 'password': password}
return(info)
class RedfishClientException(Exception):
'''Base class for redfish client exceptions'''
def __init__(self, message=None, **kwargs):
self.kwargs = kwargs
self.message = message
if __name__ == '__main__':
'''Main application redfish-client'''
# Functions
def get_redfish_data(connection_parameters, check_SSL):
if not connection_parameters['login']:
simulator = True
enforceSSL = False
else:
simulator = False
enforceSSL = True
try:
redfish_data = redfish.connect(connection_parameters['url'],
connection_parameters['login'],
connection_parameters['password'],
verify_cert=check_SSL,
simulator=simulator,
enforceSSL=enforceSSL)
return(redfish_data)
except redfish.exception.RedfishException as e:
logger.error(str(e.message))
sys.stderr.write(str(e.message))
sys.stderr.write(str(e.advices))
sys.exit(1)
def show_manager(all=False):
'''Display manager info
:param all: Add login and password info
:type all: bool
:returns: Nothing
'''
print('Managers configured :')
if(not inventory.get_managers()):
print("None")
else:
for manager in sorted(inventory.get_managers()):
print(manager)
if all is True:
info = inventory.get_manager_info(manager)
print('\tUrl : {}'.format(info['url']))
print('\tLogin : {}'.format(info['login']))
print('\tPassword : {}'.format(info['password']))
def display_manager_info(redfish_data):
# Display manager information using jinja2 template
render_template("manager_info.template")
def display_chassis_info(redfish_data):
# Display system information using jinja2 template
render_template("chassis_info.template")
def display_system_info(redfish_data):
# Display system information using jinja2 template
render_template("system_info.template")
def render_template(template):
try:
template = jinja2_env.get_template(template)
except jinja2.exceptions.TemplateNotFound as e:
print('Template "{}" not found in {}.'
.format(e.message, jinja2_env.loader.searchpath[0]))
logger.error('Template "%s" not found in %s.'
% (e.message, jinja2_env.loader.searchpath[0]))
sys.exit(1)
print(template.render(r=redfish_data))
#################################################################
# Main program
#################################################################
redfishclient_version = "redfish-client PBVER"
# Parse and manage arguments
arguments = docopt.docopt(__doc__, version=redfishclient_version)
# Check debuging options
# Debugging LEVEL :
# 1- Only client
# 2- Client and lib
# 3- Client and lib + Tortilla
loglevel = {"console_logger_level": "nolog",
"file_logger_level": logging.INFO,
"tortilla": False,
"lib_console_logger_level": "nolog",
"lib_file_logger_level": logging.INFO,
"urllib3_disable_warning": True}
if arguments['--debug'] == '1':
loglevel['console_logger_level'] = logging.DEBUG
loglevel['file_logger_level'] = logging.DEBUG
elif arguments['--debug'] == '2':
loglevel['console_logger_level'] = logging.DEBUG
loglevel['file_logger_level'] = logging.DEBUG
loglevel['lib_console_logger_level'] = logging.DEBUG
loglevel['lib_file_logger_level'] = logging.DEBUG
loglevel['urllib3_disable_warning'] = False
elif arguments['--debug'] == '3':
loglevel['console_logger_level'] = logging.DEBUG
loglevel['file_logger_level'] = logging.DEBUG
loglevel['lib_console_logger_level'] = logging.DEBUG
loglevel['lib_file_logger_level'] = logging.DEBUG
loglevel['urllib3_disable_warning'] = False
loglevel['tortilla'] = True
# Initialize logger according to command line parameters
logger = redfish.config.initialize_logger(arguments['--debugfile'],
loglevel['console_logger_level'],
loglevel['file_logger_level'],
__name__)
redfish.config.REDFISH_LOGFILE = arguments['--libdebugfile']
redfish.config.TORTILLADEBUG = loglevel['tortilla']
redfish.config.CONSOLE_LOGGER_LEVEL = loglevel['lib_console_logger_level']
redfish.config.FILE_LOGGER_LEVEL = loglevel['lib_file_logger_level']
# Avoid warning messages from request / urllib3
# SecurityWarning: Certificate has no `subjectAltName`, falling back
# to check for a `commonName` for now. This feature is being removed
# by major browsers and deprecated by RFC 2818.
# (See https://github.com/shazow/urllib3/issues/497 for details.)
if loglevel['urllib3_disable_warning'] is True:
requests.packages.urllib3.disable_warnings()
logger.info("*** Starting %s ***" % redfishclient_version)
logger.info("Arguments parsed")
logger.debug(arguments)
# Load config
config = configparser.ConfigParser(allow_no_value=True)
logger.debug("Read configuration file")
configfile = 'PBCONFFILE'
if(arguments['--config']):
configfile = arguments['--config']
logger.debug("Overwrite configuration specified by user at %s"
% configfile)
if(os.path.isfile(configfile)):
logger.debug('Configuration found at %s.' % configfile)
config.read(configfile)
else:
print('Configuration file not found at {}.'.format(configfile))
logger.error('Configuration file not found at %s.' % configfile)
sys.exit(1)
arguments['--inventory'] = os.path.expandvars(arguments['--inventory'])
inventory = InventoryFile(arguments['--inventory'])
# Initialize Template system (jinja2)
templates_path = config.get("redfish-client", "templates_path")
logger.debug("Initialize template system")
jinja2_env = jinja2.Environment(
loader=jinja2.FileSystemLoader(templates_path))
# Check cmd line parameters
if arguments['config'] is True:
logger.debug("Config commands")
if arguments['show'] is True:
logger.debug('show command')
show_manager()
elif arguments['showall'] is True:
logger.debug('showall command')
show_manager(True)
elif arguments['add'] is True:
logger.debug('add command')
inventory.add_manager(arguments['<manager_name>'],
arguments['<manager_url>'],
arguments['<login>'],
arguments['<password>'])
logger.debug(inventory.data)
inventory.save()
elif arguments['del'] is True:
logger.debug('del command')
inventory.delete_manager(arguments['<manager_name>'])
logger.debug(inventory.data)
inventory.save()
elif arguments['modify'] is True:
logger.debug('modify command')
if arguments['url'] is not False:
inventory.modify_manager(arguments['<manager_name>'],
'url',
arguments['<changed_value>'])
elif arguments['login'] is not False:
inventory.modify_manager(arguments['<manager_name>'],
'login',
arguments['<changed_value>'])
elif arguments['password'] is not False:
inventory.modify_manager(arguments['<manager_name>'],
'password',
arguments['<changed_value>'])
elif arguments['manager_name'] is not False:
inventory.modify_manager(arguments['<manager_name>'],
'manager_name',
arguments['<changed_value>'])
logger.debug(inventory.data)
inventory.save()
elif arguments['getinfo'] is True:
logger.debug('getinfo command')
# If manager is not defined set it to 'default'
if not arguments['<manager_name>']:
manager_name = 'default'
else:
manager_name = arguments['<manager_name>']
# Check if the default section is available in our conf file
inventory.check_manager(manager_name)
connection_parameters = inventory.get_manager_info(manager_name)
print('Gathering data from manager, please wait...\n')
# TODO : Add a rotating star showing program is running ?
# Could be a nice exercice for learning python. :)
logger.info('Gathering data from manager')
if arguments['--insecure'] is True:
redfish_data = get_redfish_data(connection_parameters, False)
else:
redfish_data = get_redfish_data(connection_parameters, True)
if arguments['manager'] is True:
logger.debug("Manager commands")
display_manager_info(redfish_data)
elif arguments['system'] is True:
logger.debug("system commands")
display_system_info(redfish_data)
elif arguments['chassis'] is True:
logger.debug("chassis commands")
display_chassis_info(redfish_data)
logger.info("Client session terminated")
sys.exit(0)

View File

@ -1,126 +0,0 @@
#!/usr/bin/python
# coding=utf-8
"""
redfish-client
Usage:
redfish-client.py [options] config add <manager_name> <manager_url> [<login>] [<password>]
redfish-client.py [options] config del <manager_name>
redfish-client.py [options] config modify <manager_name> (url | login | password) <changed_value>
redfish-client.py [options] config show
redfish-client.py [options] config showall
redfish-client.py (-h | --help)
redfish-client.py --version
Options:
-h --help Show this screen.
--version Show version.
--conf_file FILE Configuration file [default: ~/.redfish.conf].
config commands manage the configuration file.
"""
import os
import sys
import json
import pprint
import docopt
class ConfigFile(object):
def __init__(self, config_file):
self._config_file = config_file
# read json file
try:
with open(self._config_file) as json_data:
self.data = json.load(json_data)
json_data.close()
except (ValueError, IOError):
self.data = {"Managers":{}}
def save(self):
try:
with open(self._config_file , 'w') as json_data:
json.dump(self.data, json_data)
json_data.close()
except IOError as e:
print(e.msg)
sys.exit(1)
def add_manager(self, manager_name, url, login, password):
self.data['Managers'][manager_name] = {}
self.data['Managers'][manager_name]['url'] = url
if login != None:
self.data['Managers'][manager_name]['login'] = login
if password != None:
self.data['Managers'][manager_name]['password'] = password
def get_managers(self):
managers = []
for manager in self.data['Managers']:
managers += [manager]
return(managers)
def get_manager_info(self, manager):
info = {}
url=self.data['Managers'][manager]['url']
login=self.data['Managers'][manager]['login']
password=self.data['Managers'][manager]['password']
info={'url':url, 'login':login, 'password':password}
return(info)
class RedfishClientException(Exception):
"""Base class for redfish client exceptions"""
def __init__(self, message=None, **kwargs):
self.kwargs = kwargs
self.message = message
if __name__ == '__main__':
# Functions
def show_manager(all=False):
print("Managers configured :")
for manager in conf_file.get_managers():
print(manager)
if all == True:
info = conf_file.get_manager_info(manager)
print("\tUrl : {}".format(info['url']))
print("\tLogin : {}".format(info['login']))
print("\tPassword : {}".format(info['password']))
# Get $HOME environment.
HOME = os.getenv('HOME')
if HOME == '':
print("$HOME environment variable not set, please check your system")
sys.exit(1)
arguments = docopt.docopt(__doc__, version='redfish-client 0.1')
print(arguments)
arguments['--conf_file'] = arguments['--conf_file'].replace('~', HOME)
conf_file = ConfigFile(arguments['--conf_file'])
if arguments['config'] == True:
if arguments['show'] == True:
show_manager()
elif arguments['showall'] == True:
show_manager(True)
elif arguments['add'] == True:
conf_file.add_manager(arguments['<manager_name>'],
arguments['<manager_url>'],
arguments['<login>'],
arguments['password'])
pprint.pprint(conf_file.data)
conf_file.save()
sys.exit(0)

1
redfish-client/rfclient.py Symbolic link
View File

@ -0,0 +1 @@
redfish-client

View File

@ -0,0 +1,91 @@
Redfish API version : {{ r.get_api_version() }}
{{ r.Root.get_name() }}
Chassis information :
=====================
{% for chassis_index in r.Chassis.chassis_dict | sort %}
{%- set chassis = r.Chassis.chassis_dict[chassis_index] %}
Chassis id {{ chassis_index }}:
Manufacturer : {{ chassis.get_manufacturer() }}
Model : {{ chassis.get_model() }}
Chassis Type : {{ chassis.get_type() }}
PartNumber : {{ chassis.get_part_number() }}
SKU : {{ chassis.get_sku() }}
Serial : {{ chassis.get_serial_number() }}
AssetTag : {{ chassis.get_asset_tag() }}
Status : State : {{ chassis.get_status().Health }} / Health : {{ chassis.get_status().Health }}
{%- if chassis.thermal %}
Temperatures :
{%- if chassis.thermal.get_temperatures() == 'Not available' %}
Not available
{%- else %}
{%- for sensor, temp in chassis.thermal.get_temperatures().items() | sort %}
{{ sensor }} : {{ temp }}
{%- endfor %}
{%- endif %}
Fans :
{%- if chassis.thermal.get_fans() == 'Not available' %}
Not available
{%- else %}
{%- for fan, rpm in chassis.thermal.get_fans().items() | sort %}
{{ fan }} : {{ rpm }}
{%- endfor %}
{%- endif %}
{%- endif %}
{#
Hostname : {{ system.get_hostname() }}
Bios version : {{ system.get_bios_version() }}
CPU number : {{ system.get_cpucount() }}
CPU model : {{ system.get_cpumodel() }}
{%- if system.processors_collection %}
CPU details :
{%- for cpu_index in system.processors_collection.processors_dict | sort %}
{%- set cpu = system.processors_collection.processors_dict[cpu_index] %}
Processor id {{ cpu_index }} :
Speed : {{ cpu.get_speed() }}
Cores : {{ cpu.get_cores() }}
Threads : {{ cpu.get_threads() }}
{% endfor %}
{%- endif %}
Available memory : {{ system.get_memory() }}
Status : State : {{ system.get_status().Health }} / Health : {{ system.get_status().Health }}
Power : {{ system.get_power() }}
Description : {{ system.get_description() }}
Chassis : {{ system.get_chassis() | join(', ') }}
Managers : {{ system.get_managers() | join(', ') }}
IndicatorLED : {{ system.get_indicatorled() }}
Ethernet Interface :
{%- if system.ethernet_interfaces_collection %}
{%- for ethernetinterface_index in system.ethernet_interfaces_collection.ethernet_interfaces_dict | sort %}
{%- set ei = system.ethernet_interfaces_collection.ethernet_interfaces_dict[ethernetinterface_index] %}
Ethernet Interface id {{ ethernetinterface_index }} :
{{ ei.get_name() }}
FQDN : {{ ei.get_fqdn() }}
Mac address : {{ ei.get_mac() }}
Address ipv4 : {{ ei.get_ipv4() | join(', ') }}
Address ipv6 : {{ ei.get_ipv6() | join(', ') }}
{%- endfor %}
{%- else %}
This system has no ethernet interface
{%- endif %}
Simple Storage :
{%- if system.simple_storage_collection %}
{%- for simplestorage_index in system.simple_storage_collection.simple_storage_dict | sort %}
{%- set ss = system.simple_storage_collection.simple_storage_dict[simplestorage_index] %}
Simple Storage id {{ simplestorage_index }} :
{{ ss.get_name() }}
Status : State : {{ system.get_status().Health }} / Health : {{ system.get_status().Health }}
{%- for dev in ss.get_devices() %}
Device id {{ loop.index }} : {{ dev.Name }} {{ dev.Manufacturer }} {{ dev.Model }}
{%- endfor %}
{%- endfor %}
{%- else %}
This system has no simple storage
{%- endif %}
--------------------------------------------------------------------------------
#}
{% endfor %}

View File

@ -0,0 +1,32 @@
Redfish API version : {{ r.get_api_version() }}
{{ r.Root.get_name() }}
Managers information :
======================
{% for manager_index in r.Managers.managers_dict | sort %}
{%- set manager = r.Managers.managers_dict[manager_index] %}
Manager id {{ manager_index }}:
UUID : {{ manager.get_uuid() }}
Type : {{ manager.get_type() }}
Firmware version : {{ manager.get_firmware_version() }}
Status : State : {{ manager.get_status().Health }} / Health : {{ manager.get_status().Health }}
Ethernet Interface :
{%- if manager.ethernet_interfaces_collection %}
{%- for ethernetinterface_index in manager.ethernet_interfaces_collection.ethernet_interfaces_dict | sort %}
{%- set ei = manager.ethernet_interfaces_collection.ethernet_interfaces_dict[ethernetinterface_index] %}
Ethernet Interface id {{ ethernetinterface_index }} :
{{ ei.get_name() }}
FQDN : {{ ei.get_fqdn() }}
Mac address : {{ ei.get_mac() }}
Address ipv4 : {{ ei.get_ipv4() | join(', ') }}
Address ipv6 : {{ ei.get_ipv6() | join(', ') }}
{%- endfor %}
{%- else %}
This manager has no ethernet interface
{%- endif %}
Managed Chassis :
{{ manager.get_managed_chassis() | join(', ') }}
Managed System :
{{ manager.get_managed_systems() | join(', ') }}
----------------------------
{% endfor %}

View File

@ -0,0 +1,68 @@
Redfish API version : {{ r.get_api_version() }}
{{ r.Root.get_name() }}
Systems information :
=====================
{% for system_index in r.Systems.systems_dict | sort %}
{%- set system = r.Systems.systems_dict[system_index] %}
System id {{ system_index }}:
UUID : {{ system.get_uuid() }}
Type : {{ system.get_type() }}
Manufacturer : {{ system.get_manufacturer() }}
Model : {{ system.get_model() }}
SKU : {{ system.get_sku() }}
Serial : {{ system.get_serial_number() }}
Hostname : {{ system.get_hostname() }}
Bios version : {{ system.get_bios_version() }}
CPU number : {{ system.get_cpucount() }}
CPU model : {{ system.get_cpumodel() }}
{%- if system.processors_collection %}
CPU details :
{%- for cpu_index in system.processors_collection.processors_dict | sort %}
{%- set cpu = system.processors_collection.processors_dict[cpu_index] %}
Processor id {{ cpu_index }} :
Speed : {{ cpu.get_speed() }}
Cores : {{ cpu.get_cores() }}
Threads : {{ cpu.get_threads() }}
{% endfor %}
{%- endif %}
Available memory : {{ system.get_memory() }} GB
Status : State : {{ system.get_status().Health }} / Health : {{ system.get_status().Health }}
Power : {{ system.get_power() }}
Description : {{ system.get_description() }}
Chassis : {{ system.get_chassis() | join(', ') }}
Managers : {{ system.get_managers() | join(', ') }}
IndicatorLED : {{ system.get_indicatorled() }}
Ethernet Interface :
{%- if system.ethernet_interfaces_collection %}
{%- for ethernetinterface_index in system.ethernet_interfaces_collection.ethernet_interfaces_dict | sort %}
{%- set ei = system.ethernet_interfaces_collection.ethernet_interfaces_dict[ethernetinterface_index] %}
Ethernet Interface id {{ ethernetinterface_index }} :
{{ ei.get_name() }}
FQDN : {{ ei.get_fqdn() }}
Mac address : {{ ei.get_mac() }}
Address ipv4 : {{ ei.get_ipv4() | join(', ') }}
Address ipv6 : {{ ei.get_ipv6() | join(', ') }}
{%- endfor %}
{%- else %}
This system has no ethernet interface
{%- endif %}
Simple Storage :
{%- if system.simple_storage_collection %}
{%- for simplestorage_index in system.simple_storage_collection.simple_storage_dict | sort %}
{%- set ss = system.simple_storage_collection.simple_storage_dict[simplestorage_index] %}
Simple Storage id {{ simplestorage_index }} :
{{ ss.get_name() }}
Status : State : {{ system.get_status().Health }} / Health : {{ system.get_status().Health }}
{%- for dev in ss.get_devices() %}
Device id {{ loop.index }} : {{ dev.Name }} {{ dev.Manufacturer }} {{ dev.Model }}
{%- endfor %}
{%- endfor %}
{%- else %}
This system has no simple storage
{%- endif %}
--------------------------------------------------------------------------------
{% endfor %}

View File

@ -0,0 +1,12 @@
FROM centos:7
RUN yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm && \
yum 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
RUN pip install --upgrade pip
RUN pip install --upgrade setuptools
RUN cd python-redfish* && \
pip install -r requirements.txt && \
python setup.py install
CMD ["/bin/bash"]

View File

@ -0,0 +1,16 @@
FROM debian:jessie
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update && \
apt-get install -y apt-utils && \
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
CMD ["/bin/bash"]

View File

@ -0,0 +1,10 @@
FROM fedora:23
RUN dnf install -y python-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* && \
pip install -r requirements.txt && \
python setup.py install
CMD ["/bin/bash"]

View File

@ -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"]

View File

@ -0,0 +1,6 @@
FROM fedora:23
RUN dnf install -y python-pip
RUN mkdir /var/log/python-redfish
RUN pip install python-redfish
CMD ["/bin/bash"]

View File

@ -0,0 +1,16 @@
FROM ubuntu:wily
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update && \
apt-get install -y apt-utils && \
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
CMD ["/bin/bash"]

View File

@ -0,0 +1,103 @@
# 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
from builtins import object
import os
import stat
import subprocess
import re
from docker import Client
from path import Path
standard_library.install_aliases()
class DockerTest(object):
def __init__(self):
self.cli = Client(base_url='unix://var/run/docker.sock')
def build(self, dockerfile):
dockerfile = Path(dockerfile)
tag = 'rf' + dockerfile.basename().replace('Dockerfile.', '')
dockerfile.copy('redfish-client/tests/Dockerfile')
response = [line for line in self.cli.build(
path='redfish-client/tests',
tag=tag,
rm=True)]
return(response)
def run(self, image, command):
container = self.cli.create_container(image=image,
command=command,
tty=True,
stdin_open=True)
self.cli.start(container=container.get('Id'))
self.cli.wait(container=container.get('Id'))
response = self.cli.logs(container=container.get('Id'),
stdout=True)
self.cli.remove_container(container=container.get('Id'))
return(response.decode('utf8'))
def test_dockersocket():
mode = os.stat('/var/run/docker.sock').st_mode
isSocket = stat.S_ISSOCK(mode)
assert isSocket, 'Make sure docker services are running'
def test_docker():
cli = Client(base_url='unix://var/run/docker.sock')
response = cli.containers()
assert isinstance(response, list), 'Ensure you have sufficiant' + \
'credentials to use docker with' + \
'your current user'
def test_sources():
output = subprocess.check_output(["python", "setup.py", "sdist"])
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()
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.centos',
'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 = str(response.pop())
assert 'Successfully built' in status
def test_install():
docker = DockerTest()
images = ('rfubuntu', 'rfdebian', 'rfcentos',
'rffedora', 'rffedorap3', 'rffedorapip')
for img in images:
print('Testing : {}'.format(img))
response = docker.run(img, 'redfish-client config showall')
print(response)
assert ('Managers configured' in response and 'None' in response)
def test_versionformat():
docker = DockerTest()
images = ('rfubuntu', 'rfdebian', 'rfcentos',
'rffedora', 'rffedorap3', 'rffedorapip')
for img in images:
print('Testing : {}'.format(img))
response = docker.run(img, 'redfish-client --version')
print(response)
assert (re.match(r'redfish-client \d+\.\d+', response))

View File

@ -12,11 +12,21 @@
# License for the specific language governing permissions and limitations
# under the License.
#import pbr.version
from __future__ import unicode_literals
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import
from future import standard_library
import pbr.version
from redfish.main import *
#import redfish.types
from redfish.main import connect
standard_library.install_aliases()
#__version__ = pbr.version.VersionInfo(
# 'redfish').version_string()
try:
__version__ = pbr.version.VersionInfo('redfish').release_string()
except Exception as e:
if "Versioning for this project requires either an sdist tarball" \
in e.args[0]:
pass
else:
raise

View File

@ -1,37 +1,85 @@
# 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
import logging
import sys
import os
from logging.handlers import RotatingFileHandler
standard_library.install_aliases()
# Global variable definition
TORTILLADEBUG = True
logger = None
TORTILLADEBUG = True
HOME = os.getenv('HOME')
if HOME is None:
print("$HOME environment variable not set, please check your system")
sys.exit(1)
if HOME == '':
print("$HOME environment is set, but empty, please check your system")
sys.exit(1)
REDFISH_HOME = os.path.join(HOME, ".redfish")
if not os.path.exists(REDFISH_HOME):
try:
os.mkdir(REDFISH_HOME)
except IOError:
print('ERROR: can\'t create {}.\n'.format(REDFISH_HOME))
print(' Try to create directory {}'.format(REDFISH_HOME))
print(' using: mkdir -p {}'.format(REDFISH_HOME))
sys.exit(1)
REDFISH_LOGFILE = os.path.join(REDFISH_HOME, "python-redfish.log")
CONSOLE_LOGGER_LEVEL = logging.DEBUG
FILE_LOGGER_LEVEL = logging.DEBUG
def initialize_logger(redfish_logfile):
"""Return api version.
def initialize_logger(REDFISH_LOGFILE,
CONSOLE_LOGGER_LEVEL,
FILE_LOGGER_LEVEL,
logger_name=None):
'''Initialize a global logger to track application behaviour
:param redfish_logfile: redfish log
:type str
:returns: True
:param redfish_logfile: Log filename
:type redfish_logfile: str
:param screen_logger_level: Console log level
(logging.DEBUG, logging.ERROR, ..) or nolog
:type screen_logger_level: logging constant or string
:param file_logger_level: File log level
:type file_logger_level: logging constant
:returns: logging object
"""
global logger
logger = logging.getLogger()
'''
logger = logging.getLogger(logger_name)
logger.setLevel(logging.DEBUG)
formatter = logging.Formatter(
'%(asctime)s :: %(levelname)s :: %(message)s'
)
file_handler = RotatingFileHandler(redfish_logfile, 'a', 1000000, 1)
'%(asctime)s :: %(levelname)s :: %(message)s')
try:
file_handler = RotatingFileHandler(
os.path.expandvars(REDFISH_LOGFILE), 'a', 1000000, 1)
except IOError:
print('ERROR: {} does not exist or is not writeable.\n'.format(
REDFISH_LOGFILE))
print(' Try to create directory {}'.format(os.path.dirname(
REDFISH_LOGFILE)))
print(' using: mkdir -p {}'.format(os.path.dirname(
REDFISH_LOGFILE)))
sys.exit(1)
# First logger to file
file_handler.setLevel(logging.DEBUG)
file_handler.setLevel(FILE_LOGGER_LEVEL)
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
# Second logger to console
steam_handler = logging.StreamHandler()
steam_handler.setLevel(logging.DEBUG)
logger.addHandler(steam_handler)
return True
if CONSOLE_LOGGER_LEVEL != "nolog":
steam_handler = logging.StreamHandler()
steam_handler.setLevel(CONSOLE_LOGGER_LEVEL)
logger.addHandler(steam_handler)
return logger

View File

@ -1,21 +1,55 @@
# -*- coding: utf-8 -*-
import sys
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
from builtins import str
from . import config
standard_library.install_aliases()
class RedfishException(Exception):
"""Base class for redfish exceptions"""
def __init__(self, message=None, **kwargs):
def __init__(self, message, **kwargs):
self.kwargs = kwargs
self.message = message
self.advices = None
config.logger.error(message)
class ConnectionFailureException(RedfishException):
def __init__(self, message, **kwargs):
super(ConnectionFailureException, self).__init__(message, **kwargs)
self.advices = \
'1- Check if the url is the correct one\n' + \
'2- Check if your device is answering on the network\n' + \
'3- 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 <server>:443\n' + \
'4- Use option "--insecure" to connect without checking' + \
' certificate\n'
class InvalidRedfishContentException(RedfishException):
def __init__(self, message, **kwargs):
super(InvalidRedfishContentException, self).__init__(message, **kwargs)
self.advices = \
'1- Check if the url is the correct one\n' + \
' Most of the time you are not pointing to the rest API\n'
class AuthenticationFailureException(RedfishException):
def __init__(self, message=None, **kwargs):
super(AuthenticationFailureException, self).__init__(message=None, **kwargs)
config.logger.error(message)
# TODO
# Give a bit more details about the failure (check login etc...)
sys.exit(1)
def __init__(self, message, **kwargs):
super(AuthenticationFailureException, self).__init__(message, **kwargs)
self.message += str(kwargs['code'])
self.queryAnswer = kwargs['queryAnswer']
if kwargs['code'] == 400:
self.message += ': ' + self.queryAnswer['Messages'][0]['MessageID']
self.advices = '1- Check your credentials\n'
self.message += '\n'
class LogoutFailureException(RedfishException):
pass

View File

@ -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
@ -27,8 +29,9 @@ resources.
A URI should be treated by the client as opaque, and thus should not be
attempted to be understood or deconstructed by the client. Only specific top
level URIs (any URI in this sample code) may be assumed, and even these may be
absent based upon the implementation (e.g. there might be no /redfish/v1/Systems
collection on something that doesn't have compute nodes.)
absent based upon the implementation
(e.g. there might be no /redfish/v1/Systems collection on something
that doesn't have compute nodes.)
The other URIs must be discovered dynamically by following href links. This is
because the API will eventually be implemented on a system that breaks any
@ -114,33 +117,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 sys
import json
from urlparse import urlparse
from urllib.parse import urlparse, urljoin, urlunparse
import requests
import config
import types
import mapping
import exception
from . import config
from . import types
from . import mapping
from . import exception
# Global variable definition
redfish_logfile = "/var/log/python-redfish/python-redfish.log"
# ===============================================================================
# TODO : create method to set logging level and TORTILLADEBUG.
# ===============================================================================
def set_log_file(logfile):
global redfish_logfile
redfish_logfile = logfile
return True
""" Function to wrap RedfishConnection """
"""Function to wrap RedfishConnection"""
def connect(
@ -149,10 +142,8 @@ def connect(
password,
simulator=False,
enforceSSL=True,
verify_cert=True
):
global redfish_logfile
config.initialize_logger(redfish_logfile)
verify_cert=True):
return RedfishConnection(
url,
user,
@ -173,9 +164,16 @@ class RedfishConnection(object):
simulator=False,
enforceSSL=True,
verify_cert=True
):
):
"""Initialize a connection to a Redfish service."""
super(RedfishConnection, self).__init__()
# Specify a name for the logger as recommended by the logging
# documentation. However for strange reason requests logs are not
# anymore capture in the log file.
# TODO : Check strange behavior about requests logs.
config.logger = config.initialize_logger(config.REDFISH_LOGFILE,
config.CONSOLE_LOGGER_LEVEL,
config.FILE_LOGGER_LEVEL,
__name__)
config.logger.info("Initialize python-redfish")
@ -204,22 +202,22 @@ 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.api_url = tortilla.wrap(self.connection_parameters.rooturl,
# debug=TORTILLADEBUG)
#self.root = self.api_url.get(verify=self.connection_parameters.verify_cert)
self.connection_parameters)
config.logger.info("API Version : %s", self.get_api_version())
mapping.redfish_version = self.get_api_version()
mapping.redfish_root_name = self.Root.get_name()
# Instanciate a global mapping object to handle Redfish version variation
mapping.redfish_mapper = mapping.RedfishVersionMapping(self.get_api_version())
# Instantiate a global mapping object to handle
# Redfish version variation
mapping.redfish_mapper = mapping.RedfishVersionMapping(
self.get_api_version(), self.Root.get_name())
# Now we need to login otherwise we are not allowed to extract data
if self.__simulator is False:
@ -229,11 +227,10 @@ class RedfishConnection(object):
config.logger.info("Login successful")
except "Error getting token":
config.logger.error("Login fail, fail to get auth token")
raise exception.AuthenticationFailureException("Fail to get an auth token.")
raise exception.AuthenticationFailureException(
"Fail to get an auth token.")
# Struture change with mockup 1.0.0, there is no links
# Structure change with mockup 1.0.0, there is no links
# section anymore.
# ===================================================================
# TODO : Add a switch to allow the both structure
@ -241,37 +238,32 @@ class RedfishConnection(object):
# Types
self.SessionService = types.SessionService(
self.Root.get_link_url(
mapping.redfish_mapper.map_sessionservice()),
self.connection_parameters
)
self.Root.get_link_url(
mapping.redfish_mapper.map_sessionservice()),
self.connection_parameters)
self.Managers = types.ManagersCollection(self.Root.get_link_url("Managers"),
self.connection_parameters
)
self.Managers = types.ManagersCollection(
self.Root.get_link_url("Managers"),
self.connection_parameters)
self.Systems = types.SystemsCollection(self.Root.get_link_url("Systems"),
self.connection_parameters
)
self.Systems = types.SystemsCollection(
self.Root.get_link_url("Systems"),
self.connection_parameters)
#for system in self.Systems.systems_list:
#config.logger.debug(system.data.links.ManagedBy)
# self.Chassis
self.Chassis = types.ChassisCollection(
self.Root.get_link_url("Chassis"), self.connection_parameters)
# self.EventService
# self.AccountService
# self.Tasks
# ========================================================================
# systemCollectionLink = getattr(self.root.Links.Systems,"@odata.id")
# self.systemCollection = self.apiUrl.redfish.v1.Systems.get()
#
# print self.systemCollection.Name
#
# ========================================================================
# ========================================================================
def get_api_version(self):
"""Return api version.
@ -284,42 +276,53 @@ class RedfishConnection(object):
def login(self):
# Craft full url
url = self.Root.get_link_url(
mapping.redfish_mapper.map_sessionservice()
)
# Handle login with redfish 1.00, url must be :
mapping.redfish_mapper.map_sessionservice())
# Handle login with redfish 1.00, url must be :
# /rest/v1/SessionService/Sessions as specified by the specification
if float(mapping.redfish_version) >= 1.00:
url += '/Sessions'
url = urljoin(url, "Sessions")
# Craft request body and header
requestBody = {"UserName": self.connection_parameters.user_name , "Password": self.connection_parameters.password}
header = {'Content-type': 'application/json'}
# =======================================================================
# Tortilla seems not able to provide the header of a post request answer.
requestBody = {"UserName": self.connection_parameters.user_name,
"Password": self.connection_parameters.password}
config.logger.debug(requestBody)
headers = self.connection_parameters.headers
# ====================================================================
# Tortilla seems not able to provide the header of a post request
# answer.
# However this is required by redfish standard to get X-Auth-Token.
# So jump to "requests" library to get the required token.
# TODO : Patch tortilla to handle this case.
# =======================================================================
# sessionsUrl = tortilla.wrap("https://10.3.222.104/rest/v1/Sessions", debug=TORTILLADEBUG)
# sessions = sessionsUrl.post(verify=self.verify_cert, data=requestBody)
# ====================================================================
# sessionsUrl = tortilla.wrap(
# "https://10.3.222.104/rest/v1/Sessions", debug=TORTILLADEBUG)
# sessions = sessionsUrl.post(
# verify=self.verify_cert, data=requestBody)
auth = requests.post(url,
data=json.dumps(requestBody),
headers=header,
verify=self.connection_parameters.verify_cert
)
headers=headers,
verify=self.connection_parameters.verify_cert)
# =======================================================================
# TODO : Manage exception with a class.
# =======================================================================
if auth.status_code != 201:
raise exception.AuthenticationFailureException("Login request return an invalid status code")
#sysraise "Error getting token", auth.status_code
try:
answer = auth.json()
except ValueError:
answer = ""
raise exception.AuthenticationFailureException(
"Login request return an invalid status code ",
code=auth.status_code, queryAnswer=answer)
self.connection_parameters.auth_token = auth.headers.get("x-auth-token")
self.connection_parameters.auth_token = auth.headers.get(
"x-auth-token")
self.connection_parameters.user_uri = auth.headers.get("location")
config.logger.debug("x-auth-token : %s", self.connection_parameters.auth_token)
config.logger.debug("user session : %s", self.connection_parameters.user_uri)
config.logger.debug("x-auth-token : %s",
self.connection_parameters.auth_token)
config.logger.debug("user session : %s",
self.connection_parameters.user_uri)
return True
def logout(self):
@ -327,13 +330,11 @@ class RedfishConnection(object):
url = self.connection_parameters.user_uri
# Craft request header
header = {"Content-type": "application/json",
"x-auth-token": self.connection_parameters.auth_token
}
headers = self.connection_parameters.headers
logout = requests.delete(url, headers=header,
verify=self.connection_parameters.verify_cert
)
logout = requests.delete(url,
headers=headers,
verify=self.connection_parameters.verify_cert)
if logout.status_code == 200:
config.logger.info("Logout successful")
@ -403,3 +404,17 @@ class ConnectionParameters(object):
@user_uri.setter
def user_uri(self, user_uri):
self.__user_uri = user_uri
@property
def headers(self):
# Host header is set by request or tortilla
url = urlparse(self.__rooturl)
origin = urlunparse((url.scheme, url.netloc, '', '', '', ''))
headers = {'OData-Version': '4.0',
'Content-type': 'application/json',
'Accept': 'application/json',
'Origin': origin,
'User-Agent': 'python-redfish'}
if self.auth_token:
headers.update({'x-auth-token': self.auth_token})
return headers

View File

@ -1,31 +1,60 @@
# 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
from builtins import object
standard_library.install_aliases()
redfish_mapper = None
redfish_version = None
redfish_root_name = None
class RedfishVersionMapping(object):
"""Implements basic url path mapping beetween Redfish versions."""
'''Implements basic url path mapping beetween Redfish versions.'''
def __init__(self, version):
def __init__(self, version, rootname):
self.__version = version
self.__rootname = rootname
def map_sessionservice(self):
if self.__version == "0.95":
return "Sessions"
return("SessionService")
if self.__version == '0.95':
return 'Sessions'
return 'SessionService'
def map_links(self):
if self.__version == "0.95":
return "links"
return("Links")
def map_links(self, data_dict=None):
if data_dict is None:
if self.__version == '0.95':
return 'links'
else:
# Checking if we have Links or links.
# This is to deal with proliant firmware 2.40 bug that reports
# incorrectly links instead of Links (Redfish standard)
try:
data_dict.links
return 'links'
except AttributeError:
pass
return 'Links'
def map_links_ref(self, data_dict=None):
if data_dict is None:
if self.__version == '0.95':
return 'href'
else:
# Checking if we have @odata.id or href.
# This is to deal with proliant firmware 2.40 bug that reports
# incorrectly href instead of @odata.id (Redfish standard)
try:
data_dict.href
return 'href'
except AttributeError:
pass
return '@odata.id'
def map_links_ref(self):
if self.__version == "0.95":
return "href"
return("@odata.id")
def map_members(self):
if self.__version == "0.95":
return "Member"
return("Members")
if self.__version == '0.95':
return 'Member'
return 'Members'

View File

@ -1,49 +0,0 @@
# Copyright 2014 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
Provides functions for using the Redfish RESTful API.
"""
import collections
import json
import sys
from redfish import connection
class RedfishOperation(connection.RedfishConnection):
def reset_server(self):
(status, headers, system) = self.rest_get('/redfish/v1/Systems', None)
memberuri = system['links']['Member'][0]['href']
# verify expected type
# hint: don't limit to version 0 here as we will rev to 1.0 at some point hopefully with minimal changes
# assert(connection.get_type(system) == 'ComputerSystem.0' or connection.get_type(system) == 'ComputerSystem.1')
# verify it supports POST
# assert(connection.operation_allowed(headers, 'POST'))
action = dict()
action['Action'] = 'Reset'
action['ResetType'] = 'ForceRestart'
# perform the POST action
print('POST ' + json.dumps(action) + ' to ' + memberuri)
(status, headers, response) = self.rest_post(memberuri, None, action)
print('POST response = ' + str(status))
connection.print_extended_error(response)

Some files were not shown because too many files have changed in this diff Show More