Fix #16, use standard redfish headers

- Manager header into ConnectionParameters class.
- Fix all header requests into main.
- Fix all header requests into types.py.
- PEP8 fixes.
This commit is contained in:
Uggla 2016-04-04 22:30:46 +02:00
parent 846952810a
commit 844b2e898b
2 changed files with 72 additions and 52 deletions

View File

@ -124,10 +124,9 @@ from future import standard_library
standard_library.install_aliases() standard_library.install_aliases()
from builtins import object from builtins import object
import json import json
from urllib.parse import urlparse, urljoin import socket
from urllib.parse import urlparse, urljoin, urlunparse
import requests import requests
from . import config from . import config
from . import types from . import types
@ -207,13 +206,13 @@ class RedfishConnection(object):
"this is insecure and can allow" + "this is insecure and can allow" +
" a man in the middle attack") " a man in the middle attack")
# Show redfish standard headers
config.logger.debug(self.connection_parameters.headers)
config.logger.debug("Root url : %s", config.logger.debug("Root url : %s",
self.connection_parameters.rooturl) self.connection_parameters.rooturl)
self.Root = types.Root(self.connection_parameters.rooturl, self.Root = types.Root(self.connection_parameters.rooturl,
self.connection_parameters) self.connection_parameters)
#self.api_url = tortilla.wrap(self.connection_parameters.rooturl,
# debug=TORTILLADEBUG)
#self.root = self.api_url.get(verify=self.connection_parameters.verify_cert)
config.logger.info("API Version : %s", self.get_api_version()) config.logger.info("API Version : %s", self.get_api_version())
mapping.redfish_version = self.get_api_version() mapping.redfish_version = self.get_api_version()
@ -292,9 +291,10 @@ class RedfishConnection(object):
url = urljoin(url, "Sessions") url = urljoin(url, "Sessions")
# Craft request body and header # Craft request body and header
requestBody = {"UserName": self.connection_parameters.user_name , "Password": self.connection_parameters.password} requestBody = {"UserName": self.connection_parameters.user_name,
"Password": self.connection_parameters.password}
config.logger.debug(requestBody) config.logger.debug(requestBody)
header = {'Content-type': 'application/json'} headers = self.connection_parameters.headers
# ======================================================================= # =======================================================================
# Tortilla seems not able to provide the header of a post request answer. # 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. # However this is required by redfish standard to get X-Auth-Token.
@ -305,24 +305,28 @@ class RedfishConnection(object):
# sessions = sessionsUrl.post(verify=self.verify_cert, data=requestBody) # sessions = sessionsUrl.post(verify=self.verify_cert, data=requestBody)
auth = requests.post(url, auth = requests.post(url,
data=json.dumps(requestBody), data=json.dumps(requestBody),
headers=header, headers=headers,
verify=self.connection_parameters.verify_cert verify=self.connection_parameters.verify_cert)
)
# ======================================================================= # =======================================================================
# TODO : Manage exception with a class. # TODO : Manage exception with a class.
# ======================================================================= # =======================================================================
if auth.status_code != 201: if auth.status_code != 201:
try: try:
answer=auth.json() answer = auth.json()
except ValueError as e: except ValueError:
answer = "" answer = ""
raise exception.AuthenticationFailureException("Login request return an invalid status code ", code=auth.status_code, queryAnswer=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") self.connection_parameters.user_uri = auth.headers.get("location")
config.logger.debug("x-auth-token : %s", self.connection_parameters.auth_token) config.logger.debug("x-auth-token : %s",
config.logger.debug("user session : %s", self.connection_parameters.user_uri) self.connection_parameters.auth_token)
config.logger.debug("user session : %s",
self.connection_parameters.user_uri)
return True return True
def logout(self): def logout(self):
@ -330,13 +334,11 @@ class RedfishConnection(object):
url = self.connection_parameters.user_uri url = self.connection_parameters.user_uri
# Craft request header # Craft request header
header = {"Content-type": "application/json", headers = self.connection_parameters.headers
"x-auth-token": self.connection_parameters.auth_token
}
logout = requests.delete(url, headers=header, logout = requests.delete(url,
verify=self.connection_parameters.verify_cert headers=headers,
) verify=self.connection_parameters.verify_cert)
if logout.status_code == 200: if logout.status_code == 200:
config.logger.info("Logout successful") config.logger.info("Logout successful")
@ -406,3 +408,17 @@ class ConnectionParameters(object):
@user_uri.setter @user_uri.setter
def user_uri(self, user_uri): def user_uri(self, user_uri):
self.__user_uri = 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

@ -4,7 +4,6 @@ from __future__ import print_function
from __future__ import division from __future__ import division
from __future__ import absolute_import from __future__ import absolute_import
from future import standard_library from future import standard_library
standard_library.install_aliases()
from builtins import object from builtins import object
import pprint import pprint
@ -17,6 +16,7 @@ import ssl
from . import config from . import config
from . import mapping from . import mapping
from . import exception from . import exception
standard_library.install_aliases()
# Global variable # Global variable
@ -30,15 +30,12 @@ class Base(object):
self.url = url self.url = url
self.api_url = tortilla.wrap(url, debug=config.TORTILLADEBUG) self.api_url = tortilla.wrap(url, debug=config.TORTILLADEBUG)
config.logger.debug(connection_parameters.headers)
try: try:
if connection_parameters.auth_token is None: self.data = self.api_url.get(
self.data = self.api_url.get( verify=connection_parameters.verify_cert,
verify=connection_parameters.verify_cert) headers=connection_parameters.headers)
else:
self.data = self.api_url.get(
verify=connection_parameters.verify_cert,
headers={
'x-auth-token': connection_parameters.auth_token})
except (requests.ConnectionError, ssl.SSLError) as e: except (requests.ConnectionError, ssl.SSLError) as e:
# Log and transmit the exception. # Log and transmit the exception.
config.logger.info('Raise a RedfishException to upper level') config.logger.info('Raise a RedfishException to upper level')
@ -119,7 +116,7 @@ class Base(object):
config.logger.debug(self.api_url) config.logger.debug(self.api_url)
response = self.api_url.patch( response = self.api_url.patch(
verify=self.connection_parameters.verify_cert, verify=self.connection_parameters.verify_cert,
headers={'x-auth-token': self.connection_parameters.auth_token}, headers=self.connection_parameters.headers,
data=action) data=action)
return response return response
@ -317,8 +314,7 @@ class Managers(Base):
response = requests.post( response = requests.post(
reset_url, reset_url,
verify=self.connection_parameters.verify_cert, verify=self.connection_parameters.verify_cert,
headers={'x-auth-token': self.connection_parameters.auth_token, headers=self.connection_parameters.headers)
'Content-type': 'application/json'})
# TODO : treat response. # TODO : treat response.
return response return response
@ -357,13 +353,13 @@ class Systems(Base):
action['Action'] = 'Reset' action['Action'] = 'Reset'
action['ResetType'] = 'ForceRestart' action['ResetType'] = 'ForceRestart'
#Debug the url and perform the POST action # Debug the url and perform the POST action
#print self.api_url # print self.api_url
response = self.api_url.post(verify=self.connection_parameters.verify_cert, response = self.api_url.post(
headers={'x-auth-token': self.connection_parameters.auth_token}, verify=self.connection_parameters.verify_cert,
data=action headers=self.connection_parameters.headers,
) data=action)
#TODO : treat response. # TODO : treat response.
return response return response
def get_bios_version(self): def get_bios_version(self):
@ -377,7 +373,8 @@ class Systems(Base):
return self.data.Bios.Current.VersionString return self.data.Bios.Current.VersionString
except: except:
# Returned by mockup. # Returned by mockup.
# Hopefully this kind of discrepencies will be fixed with Redfish 1.0 (August) # Hopefully this kind of discrepencies will be fixed with
# Redfish 1.0 (August)
return self.data.BiosVersion return self.data.BiosVersion
def get_serial_number(self): def get_serial_number(self):
@ -391,7 +388,8 @@ class Systems(Base):
return self.data.SerialNumber return self.data.SerialNumber
except: except:
# Returned by mockup. # Returned by mockup.
# Hopefully this kind of discrepencies will be fixed with Redfish 1.0 (August) # Hopefully this kind of discrepencies will be fixed with
# Redfish 1.0 (August)
return '' return ''
def get_power(self): def get_power(self):
@ -413,11 +411,12 @@ class Systems(Base):
''' '''
# perform the POST action # perform the POST action
#print self.api_url.url() # print self.api_url.url()
response = requests.patch(self.api_url.url(), response = requests.patch(
verify=self.connection_parameters.verify_cert, self.api_url.url(),
headers={'x-auth-token': self.connection_parameters.auth_token, 'Content-type': 'application/json'}, verify=self.connection_parameters.verify_cert,
data=value) headers=self.connection_parameters.headers,
data=value)
return response.reason return response.reason
def set_boot_source_override(self, target, enabled): def set_boot_source_override(self, target, enabled):
@ -441,7 +440,9 @@ class Systems(Base):
"Continuous" "Continuous"
:returns: string -- http response of PATCH request :returns: string -- http response of PATCH request
''' '''
return self.set_parameter_json('{"Boot": {"BootSourceOverrideTarget": "'+target+'"},{"BootSourceOverrideEnabled" : "'+enabled+'"}}') return self.set_parameter_json(
'{"Boot": {"BootSourceOverrideTarget": "' +
target + '"},{"BootSourceOverrideEnabled" : "' + enabled + '"}}')
class SystemsCollection(BaseCollection): class SystemsCollection(BaseCollection):
@ -477,8 +478,11 @@ class EthernetInterfacesCollection(BaseCollection):
self.ethernet_interfaces_dict = {} self.ethernet_interfaces_dict = {}
# Url returned by the mock up is wrong /redfish/v1/Managers/EthernetInterfaces/1 returns a 404. --> this is not true anymore (2016/01/03) # Url returned by the mock up is wrong
# The correct one should be /redfish/v1/Managers/1/EthernetInterfaces/1 --> correct by mockup return invalid content (not json) # /redfish/v1/Managers/EthernetInterfaces/1 returns a 404.
# --> this is not true anymore (2016/01/03)
# The correct one should be /redfish/v1/Managers/1/EthernetInterfaces/1
# --> correct by mockup return invalid content (not json)
# 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)