commit
1cf02e1aa1
@ -1,16 +1,5 @@
|
|||||||
If you would like to contribute to the development of OpenStack,
|
If you would like to contribute to the development of this project.
|
||||||
you must follow the steps in this page:
|
|
||||||
|
|
||||||
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
|
You can also share and discuss on the mailing list as well.
|
||||||
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
|
|
||||||
|
43
README.rst
43
README.rst
@ -20,14 +20,17 @@ Project Structure
|
|||||||
This project follows the same convention as OpenStack projects, eg. using pbr
|
This project follows the same convention as OpenStack projects, eg. using pbr
|
||||||
for build and test automation::
|
for build and test automation::
|
||||||
|
|
||||||
doc/ # documentation
|
doc/ # Documentation
|
||||||
doc/source # the doc source files live here
|
doc/source # The doc source files live here
|
||||||
doc/build/html # output of building any docs will go here
|
doc/build/html # Output of building any docs will go here
|
||||||
dmtf # Reference documents and mockup provided by the DMTF
|
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
|
# should be put here
|
||||||
redfish/ # the redfish library
|
pbconf # Project builder file to build rpm/deb packages for
|
||||||
redfish/tests/ # python unit test suite
|
# distributions
|
||||||
|
redfish/ # The redfish library itself
|
||||||
|
redfish/tests/ # Python redfish unit test suite
|
||||||
|
redfish-client # Client tool to manage redfish devices
|
||||||
|
|
||||||
Requirements
|
Requirements
|
||||||
------------
|
------------
|
||||||
@ -41,23 +44,31 @@ are discouraged due to security.
|
|||||||
Python requirements are listed in requirements.txt; additional requirements for
|
Python requirements are listed in requirements.txt; additional requirements for
|
||||||
running the unit test suite are listed in test-requirements.txt.
|
running the unit test suite are listed in test-requirements.txt.
|
||||||
|
|
||||||
Developer setup
|
Get the sources
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
To initialize a local development environment (eg, so you can run unit tests)
|
The sources are available on github and can be retrieved using::
|
||||||
you should run the following commands
|
|
||||||
|
git clone https://github.com/uggla/python-redfish
|
||||||
|
|
||||||
|
As python redefish 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
|
Contacts
|
||||||
--------
|
--------
|
||||||
|
|
||||||
Distribution list : python-redfish@mondorescue.org
|
Distribution list: python-redfish@mondorescue.org
|
||||||
|
|
||||||
Further References
|
Further References
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
The data model documentation can be found here:
|
Please look at `dmtf/README.rst <further_ref.html>`_ file.
|
||||||
http://www.redfishspecification.org/redfish-data-model-and-schema/
|
|
||||||
|
|
||||||
The overall protocol documentation can be found here:
|
|
||||||
http://www.redfishspecification.org/
|
|
||||||
|
|
||||||
|
@ -2,11 +2,25 @@ DMTF Redfish specification
|
|||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
This directory contains the current references from the DMTF on the Redfish
|
This directory contains the current references from the DMTF on the Redfish
|
||||||
specification (1.0.0 at the time of the writing)
|
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
|
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
|
a Redfish based system so it is possible to write programs without real Redfish
|
||||||
compliant hardware platform.
|
compliant hardware platform.
|
||||||
|
|
||||||
|
Note: Mockup release is still 0.99.0a and so not aligned with specification realease
|
||||||
|
number.
|
||||||
|
|
||||||
Docker container
|
Docker container
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
|
@ -48,16 +48,16 @@ master_doc = 'index'
|
|||||||
|
|
||||||
# General information about the project.
|
# General information about the project.
|
||||||
project = u'python-redfish'
|
project = u'python-redfish'
|
||||||
copyright = u'2016, Bruno Cornec, Vincent Misson, René Ribaud'
|
copyright = u'2015-2016, Bruno Cornec, Vincent Misson, René Ribaud'
|
||||||
|
|
||||||
# The version info for the project you're documenting, acts as replacement for
|
# The version info for the project you're documenting, acts as replacement for
|
||||||
# |version| and |release|, also used in various other places throughout the
|
# |version| and |release|, also used in various other places throughout the
|
||||||
# built documents.
|
# built documents.
|
||||||
#
|
#
|
||||||
# The short X.Y version.
|
# The short X.Y version.
|
||||||
version = '0.4'
|
version = 'PBVER'
|
||||||
# The full version, including alpha/beta/rc tags.
|
# The full version, including alpha/beta/rc tags.
|
||||||
release = '0.4'
|
release = 'PBVER'
|
||||||
|
|
||||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||||
# for a list of supported languages.
|
# for a list of supported languages.
|
||||||
|
8
doc/source/develsetup.rst
Normal file
8
doc/source/develsetup.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
===============
|
||||||
|
Developer setup
|
||||||
|
===============
|
||||||
|
|
||||||
|
#. Follow `get the sources <http://pythonhosted.org/python-redfish/readme.html#get-the-sources>`_ 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.
|
3
doc/source/further_ref.rst
Normal file
3
doc/source/further_ref.rst
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
:orphan:
|
||||||
|
|
||||||
|
.. include:: ../../dmtf/README.rst
|
12
doc/source/help.rst
Normal file
12
doc/source/help.rst
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
=============
|
||||||
|
Help required
|
||||||
|
=============
|
||||||
|
|
||||||
|
We need help on the following topic:
|
||||||
|
|
||||||
|
- debian/ubuntu dependencies packaging.
|
||||||
|
- python3 testing.
|
||||||
|
- installation on distributions which are not Fedora or Mageia.
|
||||||
|
- documentation.
|
||||||
|
|
||||||
|
Any contribution will be welcomed.
|
BIN
doc/source/images/simulator.jpg
Normal file
BIN
doc/source/images/simulator.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 159 KiB |
@ -14,8 +14,10 @@ Contents:
|
|||||||
readme
|
readme
|
||||||
installation
|
installation
|
||||||
usage
|
usage
|
||||||
contributing
|
develsetup
|
||||||
classesdoc
|
classesdoc
|
||||||
|
contributing
|
||||||
|
help
|
||||||
|
|
||||||
Indices and tables
|
Indices and tables
|
||||||
==================
|
==================
|
||||||
|
@ -2,11 +2,226 @@
|
|||||||
Installation
|
Installation
|
||||||
============
|
============
|
||||||
|
|
||||||
At the command line::
|
Using pip
|
||||||
|
---------
|
||||||
|
Use::
|
||||||
|
|
||||||
$ pip install python-redfish
|
sudo pip install python-redfish
|
||||||
|
|
||||||
Or, if you have virtualenvwrapper installed::
|
Pip will install :
|
||||||
|
|
||||||
|
1. The library and all dependencies into your site-packages directory
|
||||||
|
2. Redfish client master conf file into /etc/redfish_client.conf
|
||||||
|
3. Data file (templates) into /usr/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 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-virtualenv
|
||||||
|
|
||||||
|
All files are installed under your virtualenv.
|
||||||
|
|
||||||
|
Using the sources
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
#. Follow `get the sources <http://pythonhosted.org/python-redfish/readme.html#get-the-sources>`_ section to retrieve the sources.
|
||||||
|
#. Install from the source using::
|
||||||
|
|
||||||
|
python setup.py install
|
||||||
|
|
||||||
|
|
||||||
|
Using rpm package
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
There is currently no oficial packages for distributions.
|
||||||
|
However part of the sources there is a mechanism to buil rpm or deb packages for distributions.
|
||||||
|
|
||||||
|
The mechanism is based on `project builder <http://www.project-builder.org/>`_ tool.
|
||||||
|
|
||||||
|
#. Follow `get the sources <http://pythonhosted.org/python-redfish/readme.html#get-the-sources>`_ section to retrieve the sources.
|
||||||
|
#. 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 "/wokspace/python/redfish" and "uggla" with your own directory and account::
|
||||||
|
|
||||||
|
[uggla@ugglalaptop ~]$ 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
|
||||||
|
|
||||||
|
|
||||||
|
#. Follow `get the sources <http://pythonhosted.org/python-redfish/readme.html#get-the-sources>`_ section to retrieve the sources.
|
||||||
|
|
||||||
|
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`_.
|
||||||
|
|
||||||
|
=====================================
|
||||||
|
Host configuration file configuration
|
||||||
|
=====================================
|
||||||
|
|
||||||
|
#. Verify redfish-client is working correclty::
|
||||||
|
|
||||||
|
redfish-client.py -h
|
||||||
|
|
||||||
|
#. Create a default entry to use the mockup::
|
||||||
|
|
||||||
|
redfish-client.py config add default default http://localhost:8000/redfish/v1
|
||||||
|
|
||||||
|
#. Verify the entry is correctly registered::
|
||||||
|
|
||||||
|
redfish-client.py config showall
|
||||||
|
|
||||||
|
===================
|
||||||
|
Mockup installation
|
||||||
|
===================
|
||||||
|
|
||||||
|
#. Follow `get the sources <http://pythonhosted.org/python-redfish/readme.html#get-the-sources>`_ section to retrieve the sources.
|
||||||
|
#. Install docker using your distribution packages or the docker `procedure <https://docs.docker.com/engine/installation/>`_ (docker provide more recent packages for ubuntu)::
|
||||||
|
|
||||||
|
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::
|
||||||
|
|
||||||
|
(pypi)[uggla@ugglalaptop dmtf]$ 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 `Host configuration file configuration`_ and `Mockup installation`_ section.
|
||||||
|
#. Run the following command::
|
||||||
|
|
||||||
|
redfish-client.py manager getinfo
|
||||||
|
|
||||||
|
The result should be like this::
|
||||||
|
|
||||||
|
(pypi)[uggla@ugglalaptop dmtf]$ redfish-client.py 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 sources <http://pythonhosted.org/python-redfish/readme.html#get-the-sources>`_ section to retrieve the sources.
|
||||||
|
#. 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, ex on Fedora::
|
||||||
|
|
||||||
|
dnf install texlive-scheme-full
|
||||||
|
#. Build the documentation::
|
||||||
|
|
||||||
|
make latexpdf
|
||||||
|
|
||||||
$ mkvirtualenv python-redfish
|
|
||||||
$ pip install python-redfish
|
|
||||||
|
@ -2,6 +2,25 @@
|
|||||||
Usage
|
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 HP
|
||||||
|
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.py -h
|
||||||
|
|
||||||
|
This is also available at http://pythonhosted.org/python-redfish/redfish-client.html .
|
||||||
|
|
||||||
import redfish
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"Nodes": {
|
"Managers": {
|
||||||
"default": {
|
"default": {
|
||||||
"url": "",
|
"url": "",
|
||||||
"login": "",
|
"login": "",
|
||||||
|
@ -43,48 +43,48 @@ except redfish.exception.RedfishException as e:
|
|||||||
print ("Redfish API version : %s \n" % remote_mgmt.get_api_version())
|
print ("Redfish API version : %s \n" % remote_mgmt.get_api_version())
|
||||||
|
|
||||||
# Uncomment following line to reset the blade !!!
|
# 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
|
# TODO : create an attribute to link the managed system directly
|
||||||
# and avoid systems_list[0]
|
# and avoid systems_dict["1"]
|
||||||
# --> will be something like :
|
# --> will be something like :
|
||||||
# remote_mgmt.Systems.systems_list[0] = remote_mgmt.Systems.managed_system
|
# remote_mgmt.Systems.systems_dict["1"] = remote_mgmt.Systems.managed_system
|
||||||
|
|
||||||
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("Serial Number : {}\n".format(remote_mgmt.Systems.systems_list[0].get_serial_number()))
|
print("Serial Number : {}\n".format(remote_mgmt.Systems.systems_dict["1"].get_serial_number()))
|
||||||
print("Power State : {}\n".format(remote_mgmt.Systems.systems_list[0].get_power()))
|
print("Power State : {}\n".format(remote_mgmt.Systems.systems_dict["1"].get_power()))
|
||||||
print("Parameter 'SystemType' : {}\n".format(remote_mgmt.Systems.systems_list[0].get_parameter("SystemType")))
|
print("Parameter 'SystemType' : {}\n".format(remote_mgmt.Systems.systems_dict["1"].get_parameter("SystemType")))
|
||||||
|
|
||||||
print("Get bios parameters : {}\n".format(remote_mgmt.Systems.systems_list[0].bios.get_parameters()))
|
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_list[0].bios.boot.get_parameters()))
|
print("Get boot parameters : {}\n".format(remote_mgmt.Systems.systems_dict["1"].bios.boot.get_parameters()))
|
||||||
|
|
||||||
|
|
||||||
#print("Get bios parameter 'AdminPhone' : {}\n".format(remote_mgmt.Systems.systems_list[0].bios.get_parameter("AdminPhone")))
|
#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_list[0].bios.set_parameter("AdminPhone","")))
|
#print("Set bios parameter 'AdminPhone' to '' : {}\n".format(remote_mgmt.Systems.systems_dict["1"].bios.set_parameter("AdminPhone","")))
|
||||||
|
|
||||||
|
|
||||||
#Boot server with script
|
#Boot server with script
|
||||||
#remote_mgmt.Systems.systems_list[0].bios.set_parameter("Dhcpv4","Enabled")
|
#remote_mgmt.Systems.systems_dict["1"].bios.set_parameter("Dhcpv4","Enabled")
|
||||||
|
|
||||||
remote_mgmt.Systems.systems_list[0].bios.set_parameter("PreBootNetwork", "Auto")
|
remote_mgmt.Systems.systems_dict["1"].bios.set_parameter("PreBootNetwork", "Auto")
|
||||||
remote_mgmt.Systems.systems_list[0].bios.set_parameter("UefiShellStartup", "Enabled")
|
remote_mgmt.Systems.systems_dict["1"].bios.set_parameter("UefiShellStartup", "Enabled")
|
||||||
remote_mgmt.Systems.systems_list[0].bios.set_parameter("UefiShellStartupLocation", "NetworkLocation")
|
remote_mgmt.Systems.systems_dict["1"].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_dict["1"].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_dict["1"].set_parameter_json('{"Boot": {"BootSourceOverrideTarget": "UefiShell"}}')
|
||||||
# remote_mgmt.Systems.systems_list[0].set_parameter_json('{"Boot": {"BootSourceOverrideEnabled" : "Continuous"}}')
|
# remote_mgmt.Systems.systems_dict["1"].set_parameter_json('{"Boot": {"BootSourceOverrideEnabled" : "Continuous"}}')
|
||||||
#remote_mgmt.Systems.systems_list[0].set_parameter_json('{"Boot": {"BootSourceOverrideEnabled" : "Once"}}')
|
#remote_mgmt.Systems.systems_dict["1"].set_parameter_json('{"Boot": {"BootSourceOverrideEnabled" : "Once"}}')
|
||||||
|
|
||||||
mySystem = remote_mgmt.Systems.systems_list[0]
|
mySystem = remote_mgmt.Systems.systems_dict["1"]
|
||||||
mySystem.set_boot_source_override("None","Disabled")
|
mySystem.set_boot_source_override("None","Disabled")
|
||||||
#Uncomment the next line to reset the server
|
#Uncomment the next line to reset the server
|
||||||
#mySystem.reset_system()
|
#mySystem.reset_system()
|
||||||
|
|
||||||
|
|
||||||
print("Get manager firmware version : {}\n".format(remote_mgmt.Managers.managers_list[0].get_firmware_version()))
|
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_list[0].get_bios_version()))
|
print("Get system Bios version : {}\n".format(remote_mgmt.Systems.systems_dict["1"].get_bios_version()))
|
||||||
|
|
||||||
#Reset of the system is required to apply the changes
|
#Reset of the system is required to apply the changes
|
||||||
#remote_mgmt.Systems.systems_list[0].reset_system()
|
#remote_mgmt.Systems.systems_dict["1"].reset_system()
|
||||||
|
|
||||||
remote_mgmt.logout()
|
remote_mgmt.logout()
|
||||||
|
@ -43,7 +43,7 @@ except redfish.exception.RedfishException as e:
|
|||||||
print("Redfish API version : {} \n".format(remote_mgmt.get_api_version()))
|
print("Redfish API version : {} \n".format(remote_mgmt.get_api_version()))
|
||||||
print("UUID : {} \n".format(remote_mgmt.Root.get_api_UUID()))
|
print("UUID : {} \n".format(remote_mgmt.Root.get_api_UUID()))
|
||||||
print("System 1 :\n")
|
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("System 2 :\n")
|
||||||
print("Bios version : {}\n".format(remote_mgmt.Systems.systems_list[1].get_parameter("SerialNumber")))
|
print("Bios version : {}\n".format(remote_mgmt.Systems.systems_dict["2"].get_parameter("SerialNumber")))
|
||||||
#print remoteMgmt.get_api_link_to_server()
|
#print remoteMgmt.get_api_link_to_server()
|
||||||
|
@ -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")
|
|
@ -130,7 +130,7 @@ defpkgdir python-redfish = .
|
|||||||
|
|
||||||
# List of files per pkg on which to apply filters
|
# List of files per pkg on which to apply filters
|
||||||
# Files are mentioned relatively to pbroot/defpkgdir
|
# Files are mentioned relatively to pbroot/defpkgdir
|
||||||
filteredfiles python-redfish = redfish-client/redfish-client.py
|
filteredfiles python-redfish = redfish-client/redfish-client.py,doc/source/conf.py
|
||||||
#supfiles python-redfish = python-redfish.init
|
#supfiles python-redfish = python-redfish.init
|
||||||
|
|
||||||
# For perl modules, names are different depending on distro
|
# For perl modules, names are different depending on distro
|
||||||
|
2
redfish-client/etc/redfish-client.conf
Normal file
2
redfish-client/etc/redfish-client.conf
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
[redfish-client]
|
||||||
|
templates_path = /usr/share/redfish-client/templates
|
@ -37,10 +37,10 @@ import json
|
|||||||
import pprint
|
import pprint
|
||||||
import docopt
|
import docopt
|
||||||
import logging
|
import logging
|
||||||
import redfish
|
import ConfigParser
|
||||||
import requests.packages.urllib3
|
|
||||||
import jinja2
|
import jinja2
|
||||||
|
import requests.packages.urllib3
|
||||||
|
import redfish
|
||||||
|
|
||||||
class ConfigFile(object):
|
class ConfigFile(object):
|
||||||
'''redfisht-client configuration file management'''
|
'''redfisht-client configuration file management'''
|
||||||
@ -253,7 +253,13 @@ if __name__ == '__main__':
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# Display manager information using jinja2 template
|
# Display manager information using jinja2 template
|
||||||
|
try:
|
||||||
template = jinja2_env.get_template("manager_info.template")
|
template = jinja2_env.get_template("manager_info.template")
|
||||||
|
except jinja2.exceptions.TemplateNotFound as e:
|
||||||
|
print('Template "{}" not found in {}.'.format(e.message, jinja2_env.loader.searchpath[0]))
|
||||||
|
logger.debug('Template "%s" not found in %s.' % (e.message, jinja2_env.loader.searchpath[0]))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
print template.render(r=remote_mgmt)
|
print template.render(r=remote_mgmt)
|
||||||
|
|
||||||
|
|
||||||
@ -314,8 +320,9 @@ if __name__ == '__main__':
|
|||||||
logger.info("Arguments parsed")
|
logger.info("Arguments parsed")
|
||||||
logger.debug(arguments)
|
logger.debug(arguments)
|
||||||
|
|
||||||
# Get $HOME environment.
|
# Get $HOME and $VIRTUAL_ENV environment variables.
|
||||||
HOME = os.getenv('HOME')
|
HOME = os.getenv('HOME')
|
||||||
|
VIRTUAL_ENV = os.getenv('VIRTUAL_ENV')
|
||||||
|
|
||||||
if not HOME:
|
if not HOME:
|
||||||
print('$HOME environment variable not set, please check your system')
|
print('$HOME environment variable not set, please check your system')
|
||||||
@ -323,14 +330,38 @@ if __name__ == '__main__':
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
logger.debug("Home directory : %s" % HOME)
|
logger.debug("Home directory : %s" % HOME)
|
||||||
|
|
||||||
|
if VIRTUAL_ENV:
|
||||||
|
logger.debug("Virtual env : %s" % VIRTUAL_ENV)
|
||||||
|
|
||||||
|
# Load master conf file
|
||||||
|
config = ConfigParser.ConfigParser(allow_no_value=True)
|
||||||
|
logger.debug("Read master configuration file")
|
||||||
|
master_conf_file_path = "/etc/redfish-client.conf"
|
||||||
|
|
||||||
|
if VIRTUAL_ENV:
|
||||||
|
logger.debug("Read master configuration file from virtual environment")
|
||||||
|
master_conf_file_path = VIRTUAL_ENV + master_conf_file_path
|
||||||
|
|
||||||
|
if not os.path.isfile(master_conf_file_path):
|
||||||
|
print('Master configuration file not found at {}.'.format(master_conf_file_path))
|
||||||
|
logger.error('Master configuration file not found at %s.' % master_conf_file_path)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
config.read(master_conf_file_path)
|
||||||
|
|
||||||
arguments['--conf_file'] = arguments['--conf_file'].replace('~', HOME)
|
arguments['--conf_file'] = arguments['--conf_file'].replace('~', HOME)
|
||||||
conf_file = ConfigFile(arguments['--conf_file'])
|
conf_file = ConfigFile(arguments['--conf_file'])
|
||||||
|
|
||||||
# Initialize Template system (jinja2)
|
# Initialize Template system (jinja2)
|
||||||
# TODO : set the template file location into cmd line default to /usr/share/python-redfish/templates ?
|
# TODO : set the template file location into cmd line default to /usr/share/python-redfish/templates ?
|
||||||
|
templates_path = config.get("redfish-client", "templates_path")
|
||||||
logger.debug("Initialize template system")
|
logger.debug("Initialize template system")
|
||||||
jinja2_env = jinja2.Environment(loader=jinja2.FileSystemLoader("templates"))
|
if VIRTUAL_ENV:
|
||||||
|
logger.debug("Read templates file from virtual environment")
|
||||||
|
templates_path = VIRTUAL_ENV + templates_path
|
||||||
|
jinja2_env = jinja2.Environment(loader=jinja2.FileSystemLoader(templates_path))
|
||||||
|
|
||||||
|
# Check cmd line parameters
|
||||||
if arguments['config'] is True:
|
if arguments['config'] is True:
|
||||||
logger.debug("Config commands")
|
logger.debug("Config commands")
|
||||||
if arguments['show'] is True:
|
if arguments['show'] is True:
|
||||||
|
@ -1,32 +0,0 @@
|
|||||||
#=======================================================================
|
|
||||||
# print('Redfish API version : %s' % remote_mgmt.get_api_version())
|
|
||||||
# print(remote_mgmt.Root.get_name())
|
|
||||||
# print('\n')
|
|
||||||
# print('Managers information :')
|
|
||||||
# print('----------------------')
|
|
||||||
# for manager_index in sorted(remote_mgmt.Managers.managers_dict):
|
|
||||||
# manager = remote_mgmt.Managers.managers_dict[manager_index]
|
|
||||||
# print('\nManager id {} :').format(manager_index)
|
|
||||||
# print('UUID : {}').format(manager.get_uuid())
|
|
||||||
# print('Type : {}').format(manager.get_type())
|
|
||||||
# print('Firmware version : {}').format(manager.get_firmware_version())
|
|
||||||
# print('State : {}').format(manager.get_status())
|
|
||||||
# print manager.get_managed_chassis()
|
|
||||||
# print manager.get_managed_systems()
|
|
||||||
# print('Ethernet interfaces :')
|
|
||||||
# try :
|
|
||||||
# for ethernetinterface_index in sorted(manager.ethernet_interfaces_collection.ethernet_interfaces_dict):
|
|
||||||
# ei = manager.ethernet_interfaces_collection.ethernet_interfaces_dict[ethernetinterface_index]
|
|
||||||
# print('\nEthernet Interface id {} :').format(ethernetinterface_index)
|
|
||||||
# print(ei.get_name())
|
|
||||||
# print(ei.get_parameter('FQDN'))
|
|
||||||
# print ei.get_ipv4()
|
|
||||||
# print ei.get_ipv6()
|
|
||||||
# except AttributeError:
|
|
||||||
# # We don't have ethernet interfaces
|
|
||||||
# pass
|
|
||||||
#=======================================================================
|
|
||||||
|
|
||||||
|
|
||||||
Redfish API version : remote_mgmt.get_api_version()
|
|
||||||
remote_mgmt.Root.get_name()
|
|
@ -17,6 +17,7 @@ Ethernet Interface :
|
|||||||
Ethernet Interface id {{ ethernetinterface_index }} :
|
Ethernet Interface id {{ ethernetinterface_index }} :
|
||||||
{{ ei.get_name() }}
|
{{ ei.get_name() }}
|
||||||
FQDN : {{ ei.get_fqdn() }}
|
FQDN : {{ ei.get_fqdn() }}
|
||||||
|
Mac address : {{ ei.get_mac() }}
|
||||||
Address ipv4 : {{ ei.get_ipv4() | join(', ') }}
|
Address ipv4 : {{ ei.get_ipv4() | join(', ') }}
|
||||||
Address ipv6 : {{ ei.get_ipv6() | join(', ') }}
|
Address ipv6 : {{ ei.get_ipv6() | join(', ') }}
|
||||||
{%- endfor %}
|
{%- endfor %}
|
||||||
|
@ -12,11 +12,15 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
#import pbr.version
|
import pbr.version
|
||||||
|
|
||||||
from redfish.main import *
|
from redfish.main import *
|
||||||
#import redfish.types
|
#import redfish.types
|
||||||
|
|
||||||
|
try:
|
||||||
#__version__ = pbr.version.VersionInfo(
|
__version__ = pbr.version.VersionInfo('redfish').version_string()
|
||||||
# 'redfish').version_string()
|
except Exception, e:
|
||||||
|
if "Versioning for this project requires either an sdist tarball" in e.message:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
@ -15,8 +15,13 @@ class RedfishException(Exception):
|
|||||||
class ConnectionFailureException(RedfishException):
|
class ConnectionFailureException(RedfishException):
|
||||||
def __init__(self, message, **kwargs):
|
def __init__(self, message, **kwargs):
|
||||||
super(ConnectionFailureException, self).__init__(message, **kwargs)
|
super(ConnectionFailureException, self).__init__(message, **kwargs)
|
||||||
self.advices = '1- Check if the url is the correct one\n' + \
|
self.advices = \
|
||||||
'2- Check if your device is answering on the network\n'
|
'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):
|
class InvalidRedfishContentException(RedfishException):
|
||||||
|
@ -247,8 +247,6 @@ class RedfishConnection(object):
|
|||||||
self.connection_parameters
|
self.connection_parameters
|
||||||
)
|
)
|
||||||
|
|
||||||
#for system in self.Systems.systems_list:
|
|
||||||
#config.logger.debug(system.data.links.ManagedBy)
|
|
||||||
# self.Chassis
|
# self.Chassis
|
||||||
|
|
||||||
# self.EventService
|
# self.EventService
|
||||||
|
@ -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)
|
|
@ -1,197 +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.
|
|
||||||
|
|
||||||
|
|
||||||
"""
|
|
||||||
Redfish Resource Types
|
|
||||||
"""
|
|
||||||
|
|
||||||
import base64
|
|
||||||
import gzip
|
|
||||||
import hashlib
|
|
||||||
import httplib
|
|
||||||
import json
|
|
||||||
import ssl
|
|
||||||
import StringIO
|
|
||||||
import sys
|
|
||||||
import urllib2
|
|
||||||
from urlparse import urlparse
|
|
||||||
|
|
||||||
#from oslo_log import log as logging
|
|
||||||
from redfish import exception
|
|
||||||
|
|
||||||
#LOG = logging.getLogger('redfish')
|
|
||||||
|
|
||||||
|
|
||||||
class Base(object):
|
|
||||||
def __init__(self, obj, connection=None):
|
|
||||||
self._conn = connection
|
|
||||||
"""handle to the redfish connection"""
|
|
||||||
|
|
||||||
self._attrs = []
|
|
||||||
"""list of discovered attributes"""
|
|
||||||
|
|
||||||
self._links = []
|
|
||||||
"""list of linked resources"""
|
|
||||||
|
|
||||||
# parse the individual resources, appending them to
|
|
||||||
# the list of object attributes
|
|
||||||
for k in obj.keys():
|
|
||||||
ref = k.lower()
|
|
||||||
if ref in ["links", "oem", "items"]:
|
|
||||||
continue
|
|
||||||
setattr(self, ref, obj[k])
|
|
||||||
self._attrs.append(ref)
|
|
||||||
|
|
||||||
# make sure the required attributes are present
|
|
||||||
if not getattr(self, 'name', False):
|
|
||||||
raise ObjectLoadException(
|
|
||||||
"Failed to load object. Reason: could not determine name.")
|
|
||||||
if not getattr(self, 'type', False):
|
|
||||||
raise ObjectLoadException(
|
|
||||||
"Failed to load object. Reason: could not determine type.")
|
|
||||||
|
|
||||||
if getattr(self, 'serviceversion', False):
|
|
||||||
self.type = self.type.replace('.' + self.serviceversion, '')
|
|
||||||
else:
|
|
||||||
# TODO: use a regex here to strip and store the version
|
|
||||||
# instead of assuming it is 7 chars long
|
|
||||||
self.type = self.type[:-7]
|
|
||||||
|
|
||||||
# Lastly, parse the 'links' resource.
|
|
||||||
# Note that this may have different nested structure, depending on
|
|
||||||
# what type of resource this is, or what vendor it is.
|
|
||||||
# subclasses may follow this by parsing other resources / collections
|
|
||||||
self._parse_links(obj)
|
|
||||||
|
|
||||||
def _parse_links(self, obj):
|
|
||||||
"""Map linked resources to getter functions
|
|
||||||
|
|
||||||
The root resource returns a dict of links to top-level resources
|
|
||||||
"""
|
|
||||||
def getter(connection, href):
|
|
||||||
def _get():
|
|
||||||
return connection.rest_get(href, {})
|
|
||||||
return _get
|
|
||||||
|
|
||||||
for k in obj['links']:
|
|
||||||
ref = "get_" + k.lower()
|
|
||||||
self._links.append(ref)
|
|
||||||
href = obj['links'][k]['href']
|
|
||||||
setattr(self, ref, getter(self._conn, href))
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
"""Return this object's _attrs as a dict"""
|
|
||||||
res = {}
|
|
||||||
for a in self._attrs:
|
|
||||||
res[a] = getattr(self, a)
|
|
||||||
return res
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
"""Return the string representation of this object's _attrs"""
|
|
||||||
return json.dumps(self.__repr__())
|
|
||||||
|
|
||||||
|
|
||||||
class BaseCollection(Base):
|
|
||||||
"""Base class for collection types"""
|
|
||||||
def __init__(self, obj, connection=None):
|
|
||||||
super(BaseCollection, self).__init__(obj, connection=connection)
|
|
||||||
self._parse_items(obj)
|
|
||||||
self._attrs.append('items')
|
|
||||||
|
|
||||||
def _parse_links(self, obj):
|
|
||||||
"""links are special on a chassis; dont parse them"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def _parse_items(self, obj):
|
|
||||||
"""Map linked items to getter methods
|
|
||||||
|
|
||||||
The chassis resource returns a list of items and corresponding
|
|
||||||
link data in a separate entity.
|
|
||||||
"""
|
|
||||||
def getter(connection, href):
|
|
||||||
def _get():
|
|
||||||
return connection.rest_get(href, {})
|
|
||||||
return _get
|
|
||||||
|
|
||||||
self.items = []
|
|
||||||
self._item_getters = []
|
|
||||||
|
|
||||||
if 'links' in obj and 'Member' in obj['links']:
|
|
||||||
# NOTE: this assumes the lists are ordered the same
|
|
||||||
counter = 0
|
|
||||||
for item in obj['links']['Member']:
|
|
||||||
self.items.append(obj['Items'][counter])
|
|
||||||
self._item_getters.append(
|
|
||||||
getter(self._conn, item['href']))
|
|
||||||
counter+=1
|
|
||||||
elif 'Items' in obj:
|
|
||||||
# TODO: find an example of this format and make sure it works
|
|
||||||
for item in obj['Items']:
|
|
||||||
if 'links' in item and 'self' in item['links']:
|
|
||||||
href = item['links']['self']['href']
|
|
||||||
self.items.append(item)
|
|
||||||
|
|
||||||
# TODO: implement paging support
|
|
||||||
# if 'links' in obj and 'NextPage' in obj['links']:
|
|
||||||
# next_page = THIS_URI + '?page=' + str(obj['links']['NextPage']['page'])
|
|
||||||
# do something with next_page URI
|
|
||||||
|
|
||||||
def __iter__(self):
|
|
||||||
for getter in self._item_getters:
|
|
||||||
yield getter()
|
|
||||||
|
|
||||||
|
|
||||||
class Root(Base):
|
|
||||||
"""Root '/' resource class"""
|
|
||||||
def _parse_links(self, obj):
|
|
||||||
"""Map linked resources to getter functions
|
|
||||||
|
|
||||||
The root resource returns a dict of links to top-level resources
|
|
||||||
|
|
||||||
TODO: continue implementing customizations for top-level resources
|
|
||||||
|
|
||||||
"""
|
|
||||||
mapping = {
|
|
||||||
'Systems': Systems,
|
|
||||||
'Chassis': Chassis,
|
|
||||||
'Managers': Base,
|
|
||||||
'Schemas': Base,
|
|
||||||
'Registries': Base,
|
|
||||||
'Tasks': Base,
|
|
||||||
'AccountService': Base,
|
|
||||||
'Sessions': Base,
|
|
||||||
'EventService': Base,
|
|
||||||
}
|
|
||||||
|
|
||||||
def getter(connection, href, type):
|
|
||||||
def _get():
|
|
||||||
return mapping[type](connection.rest_get(href, {}), self._conn)
|
|
||||||
return _get
|
|
||||||
|
|
||||||
for k in obj['links']:
|
|
||||||
ref = "get_" + k.lower()
|
|
||||||
self._links.append(ref)
|
|
||||||
href = obj['links'][k]['href']
|
|
||||||
setattr(self, ref, getter(self._conn, href, k))
|
|
||||||
|
|
||||||
|
|
||||||
class Chassis(BaseCollection):
|
|
||||||
"""Chassis resource class"""
|
|
||||||
def __len__(self):
|
|
||||||
return len(self.items)
|
|
||||||
|
|
||||||
|
|
||||||
class Systems(Base):
|
|
||||||
pass
|
|
@ -23,7 +23,7 @@ class Base(object):
|
|||||||
self.api_url = tortilla.wrap(url, debug=config.TORTILLADEBUG)
|
self.api_url = tortilla.wrap(url, debug=config.TORTILLADEBUG)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if connection_parameters.auth_token == None:
|
if connection_parameters.auth_token is None:
|
||||||
self.data = self.api_url.get(verify=connection_parameters.verify_cert)
|
self.data = self.api_url.get(verify=connection_parameters.verify_cert)
|
||||||
else:
|
else:
|
||||||
self.data = self.api_url.get(verify=connection_parameters.verify_cert,
|
self.data = self.api_url.get(verify=connection_parameters.verify_cert,
|
||||||
@ -138,8 +138,7 @@ class BaseCollection(Base):
|
|||||||
def __init__(self, url, connection_parameters):
|
def __init__(self, url, connection_parameters):
|
||||||
super(BaseCollection, self).__init__(url, connection_parameters)
|
super(BaseCollection, self).__init__(url, connection_parameters)
|
||||||
|
|
||||||
self.links=[]
|
self.links = []
|
||||||
|
|
||||||
|
|
||||||
#linksmembers = self.data.Links.Members
|
#linksmembers = self.data.Links.Members
|
||||||
#linksmembers = self.data.links.Member
|
#linksmembers = self.data.links.Member
|
||||||
@ -153,7 +152,6 @@ class BaseCollection(Base):
|
|||||||
#self.links.append(getattr(link,'href'))
|
#self.links.append(getattr(link,'href'))
|
||||||
self.links.append(urljoin(self.url, getattr(link, mapping.redfish_mapper.map_links_ref())))
|
self.links.append(urljoin(self.url, getattr(link, mapping.redfish_mapper.map_links_ref())))
|
||||||
|
|
||||||
|
|
||||||
config.logger.debug(self.links)
|
config.logger.debug(self.links)
|
||||||
|
|
||||||
|
|
||||||
@ -204,10 +202,10 @@ class Managers(Base):
|
|||||||
try:
|
try:
|
||||||
# New proliant firmware now respects Redfish v1.00, so seems to correct below statement
|
# New proliant firmware now respects Redfish v1.00, so seems to correct below statement
|
||||||
# TODO : better handle exception and if possible support old firmware ?
|
# TODO : better handle exception and if possible support old firmware ?
|
||||||
self.ethernet_interfaces_collection = EthernetInterfacesCollection(
|
self.ethernet_interfaces_collection = \
|
||||||
|
EthernetInterfacesCollection(
|
||||||
self.get_link_url('EthernetInterfaces'),
|
self.get_link_url('EthernetInterfaces'),
|
||||||
connection_parameters
|
connection_parameters)
|
||||||
)
|
|
||||||
|
|
||||||
# Works on proliant, need to treat 095 vs 0.96 differences
|
# Works on proliant, need to treat 095 vs 0.96 differences
|
||||||
#self.ethernet_interfaces_collection = EthernetInterfacesCollection(
|
#self.ethernet_interfaces_collection = EthernetInterfacesCollection(
|
||||||
@ -222,7 +220,6 @@ class Managers(Base):
|
|||||||
# This means we don't have EthernetInterfaces
|
# This means we don't have EthernetInterfaces
|
||||||
self.ethernet_interfaces_collection = None
|
self.ethernet_interfaces_collection = None
|
||||||
|
|
||||||
|
|
||||||
def get_firmware_version(self):
|
def get_firmware_version(self):
|
||||||
'''Get firmware version of the manager
|
'''Get firmware version of the manager
|
||||||
|
|
||||||
@ -303,6 +300,27 @@ class Managers(Base):
|
|||||||
except AttributeError:
|
except AttributeError:
|
||||||
return "Not available"
|
return "Not available"
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
'''Reset the manager.
|
||||||
|
|
||||||
|
:returns: string -- http response of POST request
|
||||||
|
|
||||||
|
'''
|
||||||
|
# Craft the request
|
||||||
|
link = getattr(self.data.Actions, "#Manager.Reset")
|
||||||
|
link = link.target
|
||||||
|
|
||||||
|
reset_url = urljoin(self.url, link)
|
||||||
|
|
||||||
|
response = requests.post(
|
||||||
|
reset_url,
|
||||||
|
verify=self.connection_parameters.verify_cert,
|
||||||
|
headers={'x-auth-token': self.connection_parameters.auth_token,
|
||||||
|
'Content-type': 'application/json'})
|
||||||
|
# TODO : treat response.
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
class ManagersCollection(BaseCollection):
|
class ManagersCollection(BaseCollection):
|
||||||
'''Class to manage redfish ManagersCollection data.'''
|
'''Class to manage redfish ManagersCollection data.'''
|
||||||
def __init__(self, url, connection_parameters):
|
def __init__(self, url, connection_parameters):
|
||||||
@ -429,10 +447,11 @@ class SystemsCollection(BaseCollection):
|
|||||||
def __init__(self, url, connection_parameters):
|
def __init__(self, url, connection_parameters):
|
||||||
super(SystemsCollection, self).__init__(url, connection_parameters)
|
super(SystemsCollection, self).__init__(url, connection_parameters)
|
||||||
|
|
||||||
self.systems_list = []
|
self.systems_dict = {}
|
||||||
|
|
||||||
for link in self.links:
|
for link in self.links:
|
||||||
self.systems_list.append(Systems(link, connection_parameters))
|
index = re.search(r'Systems/(\w+)', link)
|
||||||
|
self.systems_dict[index.group(1)] = Systems(link, connection_parameters)
|
||||||
|
|
||||||
|
|
||||||
class Bios(Base):
|
class Bios(Base):
|
||||||
@ -451,7 +470,8 @@ class Boot(Base):
|
|||||||
class EthernetInterfacesCollection(BaseCollection):
|
class EthernetInterfacesCollection(BaseCollection):
|
||||||
'''Class to manage redfish EthernetInterfacesColkection data.'''
|
'''Class to manage redfish EthernetInterfacesColkection data.'''
|
||||||
def __init__(self, url, connection_parameters):
|
def __init__(self, url, connection_parameters):
|
||||||
super(EthernetInterfacesCollection, self).__init__(url, connection_parameters)
|
super(EthernetInterfacesCollection,
|
||||||
|
self).__init__(url, connection_parameters)
|
||||||
|
|
||||||
self.ethernet_interfaces_dict = {}
|
self.ethernet_interfaces_dict = {}
|
||||||
|
|
||||||
@ -460,7 +480,8 @@ class EthernetInterfacesCollection(BaseCollection):
|
|||||||
# Check more than 1 hour for this bug.... grrr....
|
# Check more than 1 hour for this bug.... grrr....
|
||||||
for link in self.links:
|
for link in self.links:
|
||||||
index = re.search(r'EthernetInterfaces/(\w+)', link)
|
index = re.search(r'EthernetInterfaces/(\w+)', link)
|
||||||
self.ethernet_interfaces_dict[index.group(1)] = EthernetInterfaces(link, connection_parameters)
|
self.ethernet_interfaces_dict[index.group(1)] = \
|
||||||
|
EthernetInterfaces(link, connection_parameters)
|
||||||
|
|
||||||
|
|
||||||
class EthernetInterfaces(Base):
|
class EthernetInterfaces(Base):
|
||||||
@ -487,7 +508,6 @@ class EthernetInterfaces(Base):
|
|||||||
except AttributeError:
|
except AttributeError:
|
||||||
return "Not available"
|
return "Not available"
|
||||||
|
|
||||||
|
|
||||||
def get_ipv4(self):
|
def get_ipv4(self):
|
||||||
'''Get EthernetInterface ipv4 address
|
'''Get EthernetInterface ipv4 address
|
||||||
|
|
||||||
|
@ -8,3 +8,5 @@ Babel>=1.3
|
|||||||
tortilla>=0.4.1
|
tortilla>=0.4.1
|
||||||
Jinja2>=2.7.3
|
Jinja2>=2.7.3
|
||||||
Sphinx>=1.2.3
|
Sphinx>=1.2.3
|
||||||
|
docopt>=0.6.2
|
||||||
|
simplejson>=3.8.1
|
||||||
|
16
setup.cfg
16
setup.cfg
@ -5,9 +5,11 @@ description-file =
|
|||||||
README.rst
|
README.rst
|
||||||
author = Redfish dev team
|
author = Redfish dev team
|
||||||
author-email = python-redfish@mondorescue.org
|
author-email = python-redfish@mondorescue.org
|
||||||
home-page = http://github.com/bcornec/python-redfish
|
home-page = https://github.com/uggla/python-redfish/tree/devel
|
||||||
|
license = Apache-2
|
||||||
classifier =
|
classifier =
|
||||||
#Environment :: OpenStack
|
Development Status :: 4 - Beta
|
||||||
|
Environment :: Console
|
||||||
Intended Audience :: Information Technology
|
Intended Audience :: Information Technology
|
||||||
Intended Audience :: System Administrators
|
Intended Audience :: System Administrators
|
||||||
License :: OSI Approved :: Apache Software License
|
License :: OSI Approved :: Apache Software License
|
||||||
@ -15,15 +17,21 @@ classifier =
|
|||||||
Programming Language :: Python
|
Programming Language :: Python
|
||||||
Programming Language :: Python :: 2
|
Programming Language :: Python :: 2
|
||||||
Programming Language :: Python :: 2.7
|
Programming Language :: Python :: 2.7
|
||||||
Programming Language :: Python :: 2.6
|
|
||||||
Programming Language :: Python :: 3
|
Programming Language :: Python :: 3
|
||||||
Programming Language :: Python :: 3.3
|
|
||||||
Programming Language :: Python :: 3.4
|
Programming Language :: Python :: 3.4
|
||||||
|
|
||||||
[files]
|
[files]
|
||||||
packages =
|
packages =
|
||||||
redfish
|
redfish
|
||||||
|
|
||||||
|
scripts =
|
||||||
|
redfish-client/redfish-client.py
|
||||||
|
|
||||||
|
data_files =
|
||||||
|
usr/share/redfish-client/templates = redfish-client/templates/*
|
||||||
|
etc/ = redfish-client/etc/*
|
||||||
|
|
||||||
|
|
||||||
[build_sphinx]
|
[build_sphinx]
|
||||||
source-dir = doc/source
|
source-dir = doc/source
|
||||||
build-dir = doc/build
|
build-dir = doc/build
|
||||||
|
Loading…
Reference in New Issue
Block a user