Improve error management

- Better handle connection errors.
- Better handle login errors.
- Improve exception process.
- Update examples.
	- Make examples compatible with new configuration file.
	- Show exception handling.
- Validate trusted SSL connection.
- Various PEP8 corrections.
This commit is contained in:
Uggla 2016-01-02 11:33:58 +01:00
parent 4ef8d92da7
commit 466534359c
5 changed files with 131 additions and 61 deletions

View File

@ -6,7 +6,7 @@ import os
import sys import sys
import json import json
import redfish import redfish
from time import sleep
# Get $HOME environment. # Get $HOME environment.
HOME = os.getenv('HOME') HOME = os.getenv('HOME')
@ -24,17 +24,26 @@ except IOError as e:
print(e) print(e)
sys.exit(1) sys.exit(1)
URL = config["Nodes"]["default"]["url"] URL = config["Managers"]["default"]["url"]
USER_NAME = config["Nodes"]["default"]["login"] USER_NAME = config["Managers"]["default"]["login"]
PASSWORD = config["Nodes"]["default"]["password"] PASSWORD = config["Managers"]["default"]["password"]
''' remote_mgmt is a redfish.RedfishConnection object ''' ''' 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()) 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_list[0].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_list[0]

View File

@ -23,13 +23,22 @@ except IOError as e:
print(e) print(e)
sys.exit(1) sys.exit(1)
URL = config["Nodes"]["default"]["url"] URL = config["Managers"]["default"]["url"]
USER_NAME = config["Nodes"]["default"]["login"] USER_NAME = config["Managers"]["default"]["login"]
PASSWORD = config["Nodes"]["default"]["password"] PASSWORD = config["Managers"]["default"]["password"]
''' remoteMgmt is a redfish.RedfishConnection object ''' ''' remoteMgmt is a redfish.RedfishConnection object '''
remote_mgmt = redfish.connect(URL, USER_NAME, PASSWORD, try:
simulator=True, enforceSSL=False) 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("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()))

View File

@ -1,21 +1,52 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import sys
import config import config
class RedfishException(Exception): class RedfishException(Exception):
"""Base class for redfish exceptions""" """Base class for redfish exceptions"""
def __init__(self, message=None, **kwargs): def __init__(self, message, **kwargs):
self.kwargs = kwargs self.kwargs = kwargs
self.message = message 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'
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 NonTrustedCertificatException(RedfishException):
def __init__(self, message, **kwargs):
super(NonTrustedCertificatException, self).__init__(message, **kwargs)
self.advices = \
'1- Check if the url is the correct one\n' + \
'2- Check if your device has a valid trusted certificat\n' + \
' You can use openssl to validate it using the command :\n' + \
' openssl s_client -showcerts -connect <server>:443\n'
class AuthenticationFailureException(RedfishException): class AuthenticationFailureException(RedfishException):
def __init__(self, message=None, **kwargs): def __init__(self, message, **kwargs):
super(AuthenticationFailureException, self).__init__(message=None, **kwargs) super(AuthenticationFailureException, self).__init__(message, **kwargs)
config.logger.error(message) self.message += str(kwargs['code'])
# TODO self.queryAnswer = kwargs['queryAnswer']
# Give a bit more details about the failure (check login etc...) if kwargs['code'] == 400:
sys.exit(1) self.message += ': ' + self.queryAnswer['Messages'][0]['MessageID']
self.advices = '1- Check your credentials\n'
self.message += '\n'
class LogoutFailureException(RedfishException): class LogoutFailureException(RedfishException):
pass pass

View File

@ -294,6 +294,7 @@ class RedfishConnection(object):
# 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)
header = {'Content-type': 'application/json'} header = {'Content-type': 'application/json'}
# ======================================================================= # =======================================================================
# 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.
@ -313,8 +314,11 @@ class RedfishConnection(object):
# TODO : Manage exception with a class. # TODO : Manage exception with a class.
# ======================================================================= # =======================================================================
if auth.status_code != 201: if auth.status_code != 201:
raise exception.AuthenticationFailureException("Login request return an invalid status code") try:
#sysraise "Error getting token", auth.status_code answer=auth.json()
except ValueError as e:
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")

View File

@ -1,12 +1,14 @@
# coding=utf-8 # coding=utf-8
import pprint import pprint
import re
from urlparse import urljoin from urlparse import urljoin
import requests import requests
import simplejson
import tortilla import tortilla
import config import config
import mapping import mapping
import re import exception
# Global variable # Global variable
@ -28,10 +30,25 @@ class Base(object):
headers={'x-auth-token': connection_parameters.auth_token} headers={'x-auth-token': connection_parameters.auth_token}
) )
except requests.ConnectionError as e: except requests.ConnectionError as e:
print e
# Log and transmit the exception. # Log and transmit the exception.
config.logger.error("Connection error : %s", e) config.logger.info("Raise a RedfishException to upper level")
raise e msg = "Connection error : {}\n".format(e.message)
raise exception.ConnectionFailureException(msg)
except simplejson.scanner.JSONDecodeError as e:
# Log and transmit the exception.
config.logger.info("Raise a RedfishException to upper level")
msg = \
"Ivalid content : Content does not appear to be a valid " + \
"Redfish json\n"
raise exception.InvalidRedfishContentException(msg)
except TypeError as e:
# This happen connecting to a manager using non trusted
# SSL certificats.
# The exception is not what could be expected in such case but this
# is the one provided by Tortilla.
config.logger.info("Raise a RedfishException to upper level")
msg = "Connection error\n"
raise exception.NonTrustedCertificatException(msg)
print self.data print self.data
def get_link_url(self, link_type): def get_link_url(self, link_type):