python-redfish/redfish-client/redfish-check-cartridge
Bruno Cornec b40437d19c Fix wrong delivery for usage files
- usage files are now placed under /usr/share (PBSHAREPATH variable) and not
  /usr/bin with the binary.
- PBTEMPLATEPATH replaced by PBSHAREPATH/templates

Change-Id: I757c679bf03e4e93028e019086ad665e2d43b35b
2017-02-15 18:52:07 +01:00

383 lines
13 KiB
Python
Executable File

#!/usr/bin/python
# coding=utf-8
'''
redfish-check_cartridge ::
This is a small program to check cartridge changes in HEP moonshot chassis.
'''
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 docopt
import logging
import configparser
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 check_cartridge'''
# 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)
#################################################################
# Main program
#################################################################
check_cartridge_version = "check_cartridge PBVER"
# Parse and manage arguments
try:
usagefp = 'PBSHAREPATH' + "/redfish-check-cartridge_usage.txt"
with open(usagefp) as usagefile:
usage = usagefile.read()
usagefile.close()
except (ValueError, IOError):
print("Usage file {} cannot be found.".format(usagefp))
sys.exit(1)
arguments = docopt.docopt(usage, version=check_cartridge_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 ***" % check_cartridge_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'])
# Check cmd line parameters
# 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')
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)
print('Get cartridge list\n')
cartridge_file = os.path.join(os.path.dirname(arguments['--inventory']),
'cartridge.json')
current_cartridge = redfish_data.Systems.systems_dict.keys()
previous_cartridge = []
if os.path.isfile(cartridge_file):
with open(cartridge_file, 'r') as f:
previous_cartridge = json.load(f)
f.close()
print('Writing cartridge list to file')
with open(cartridge_file, 'w') as f:
if len(current_cartridge) > 0:
json.dump(current_cartridge, f)
else:
f.write('{}')
f.close()
print("Current cartridges:")
print("{}\n".format(", ".join(current_cartridge)))
if not previous_cartridge:
print("First run, changes can not be evaluated")
sys.exit(0)
current_cartridge = set(current_cartridge)
previous_cartridge = set(previous_cartridge)
print("Computing changes...\n")
# Check if we have added a cartridge
diff = current_cartridge - previous_cartridge
print("Cartridges added:")
if diff:
print("{}".format(", ".join(diff)))
for item in diff:
system = redfish_data.Systems.systems_dict[item]
print(system.get_name())
print(system.get_model())
print(system.get_uuid())
print("Memory: {}".format(
system.data.Memory.TotalSystemMemoryGB))
print("MAC@: {}".format(
system.data.HostCorrelation.HostMACAddress))
print("------------------")
else:
print("None")
# Check if we have removed a cartridge
diff = previous_cartridge - current_cartridge
print("Cartridges removed:")
if diff:
print("{}\n".format(", ".join(diff)))
else:
print("None")
logger.info("Client session terminated")
sys.exit(0)