"Fossies" - the Fresh Open Source Software Archive

Member "opensaf-5.21.09/python/pyosaf/utils/__init__.py" (14 Sep 2021, 9782 Bytes) of package /linux/misc/opensaf-5.21.09.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file.

    1 ############################################################################
    2 #
    3 # (C) Copyright 2014 The OpenSAF Foundation
    4 # (C) Copyright 2017 Ericsson AB. All rights reserved.
    5 #
    6 # This program is distributed in the hope that it will be useful, but
    7 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    8 # or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
    9 # under the GNU Lesser General Public License Version 2.1, February 1999.
   10 # The complete license can be accessed from the following location:
   11 # http://opensource.org/licenses/lgpl-license.php
   12 # See the Copying file included with the OpenSAF distribution for full
   13 # licensing terms.
   14 #
   15 # Author(s): Oracle, Ericsson
   16 #
   17 ############################################################################
   18 """ pyosaf common utils """
   19 import os
   20 import syslog
   21 import time
   22 import warnings
   23 from copy import deepcopy
   24 from ctypes import POINTER
   25 
   26 from pyosaf import saImmOm
   27 from pyosaf.saAis import eSaAisErrorT, SaStringT, unmarshalNullArray
   28 
   29 # Version for pyosaf utils
   30 __version__ = "1.0.1"
   31 
   32 # The 'MAX_RETRY_TIME' and 'RETRY_INTERVAL' environment variables shall be set
   33 # with user-defined values BEFORE importing the pyosaf 'utils' module;
   34 # Otherwise, the default values for MAX_RETRY_TIME(60s) and RETRY_INTERVAL(1s)
   35 # will be used throughout.
   36 MAX_RETRY_TIME = int(os.environ.get("MAX_RETRY_TIME")) \
   37     if "MAX_RETRY_TIME" in os.environ else 60
   38 RETRY_INTERVAL = int(os.environ.get("RETRY_INTERVAL")) \
   39     if "RETRY_INTERVAL" in os.environ else 1
   40 
   41 
   42 class SafException(Exception):
   43     """ SAF Exception for error during executing SAF functions """
   44     def __init__(self, value, msg=None):
   45         Exception.__init__(self)
   46         self.value = value
   47         self.msg = msg
   48 
   49     def __str__(self):
   50         return eSaAisErrorT.whatis(self.value)
   51 
   52 
   53 def raise_saf_exception(func, error):
   54     """ Raise an exception for a given SAF function, based on the given
   55     error code
   56     """
   57     error_string = "%s: %s" % (func.__name__, eSaAisErrorT.whatis(error))
   58     raise SafException(error, error_string)
   59 
   60 
   61 def check_resource_abort(ccb_handle):
   62     """ Get error strings from IMM and check if it is a resource abort case
   63 
   64     Args:
   65         ccb_handle (SaImmCcbHandleT): CCB handle
   66 
   67     Returns:
   68         bool: 'True' if it is a resource abort case. 'False', otherwise.
   69     """
   70     c_error_strings = POINTER(SaStringT)()
   71     saImmOmCcbGetErrorStrings = decorate(saImmOm.saImmOmCcbGetErrorStrings)
   72 
   73     # Get error strings
   74     # As soon as the ccb_handle is finalized, the strings are freed
   75     rc = saImmOmCcbGetErrorStrings(ccb_handle, c_error_strings)
   76     if rc == eSaAisErrorT.SA_AIS_OK:
   77         if c_error_strings:
   78             list_err_strings = unmarshalNullArray(c_error_strings)
   79             for c_error_string in list_err_strings:
   80                 if c_error_string.startswith("IMM: Resource abort: "):
   81                     if "CCB is in an error state" not in c_error_string:
   82                         return True
   83 
   84     return False
   85 
   86 
   87 def decorate(func):
   88     """ Decorate the given SAF function so that it retries a fixed number of
   89     times for certain returned error codes during execution
   90 
   91     Args:
   92         func (function): The decorated SAF function
   93 
   94     Returns:
   95         SaAisErrorT: Return code of the decorated SAF function
   96     """
   97 
   98     def inner(*args):
   99         """ Call the decorated function in the lexical scope in a retry loop
  100 
  101         Args:
  102             args (tuple): Arguments of the decorated SAF function
  103         """
  104         count_sec_sleeps = 0
  105 
  106         rc = func(*args)
  107 
  108         while rc != eSaAisErrorT.SA_AIS_OK:
  109 
  110             if count_sec_sleeps >= MAX_RETRY_TIME:
  111                 break
  112 
  113             if rc == eSaAisErrorT.SA_AIS_ERR_TRY_AGAIN:
  114                 sleep_time_interval = RETRY_INTERVAL
  115             elif rc == eSaAisErrorT.SA_AIS_ERR_NO_RESOURCES:
  116                 sleep_time_interval = RETRY_INTERVAL
  117             elif rc == eSaAisErrorT.SA_AIS_ERR_BUSY:
  118                 sleep_time_interval = 3 * RETRY_INTERVAL
  119             elif rc == eSaAisErrorT.SA_AIS_ERR_FAILED_OPERATION:
  120                 # Retry on getting FAILED_OPERATION only applies to IMM
  121                 # CCB-related operations in case of a resource abort
  122                 # and CCB not in error state.
  123                 ccb_handle = args[0]
  124                 resource_abort = check_resource_abort(ccb_handle)
  125                 if not resource_abort:
  126                     break
  127                 sleep_time_interval = RETRY_INTERVAL
  128             else:
  129                 break  # Break out of the retry loop
  130 
  131             # Check sleep_time_interval to sleep and retry the function
  132             time.sleep(sleep_time_interval)
  133             count_sec_sleeps += sleep_time_interval
  134             rc = func(*args)
  135 
  136         return rc
  137 
  138     return inner
  139 
  140 
  141 def initialize_decorate(init_func):
  142     """ Decorate the given SAF sa<Service>Initialize() function so that it
  143     retries a fixed number of times with the same arguments for certain
  144     returned error codes during execution
  145     """
  146 
  147     def inner(*args):
  148         """ Call the decorated Initialize() function in the lexical scope in a
  149         retry loop
  150 
  151         Args:
  152             args (tuple): Arguments of the SAF Initialize() function with
  153                 format (handle, callbacks, version)
  154         """
  155         count_sec_sleeps = 0
  156 
  157         # Backup the current version
  158         backup_version = deepcopy(args[2])
  159 
  160         rc = init_func(*args)
  161         while rc != eSaAisErrorT.SA_AIS_OK:
  162 
  163             if count_sec_sleeps >= MAX_RETRY_TIME:
  164                 break
  165 
  166             if rc == eSaAisErrorT.SA_AIS_ERR_TRY_AGAIN:
  167                 sleep_time_interval = RETRY_INTERVAL
  168             elif rc == eSaAisErrorT.SA_AIS_ERR_NO_RESOURCES:
  169                 sleep_time_interval = RETRY_INTERVAL
  170             elif rc == eSaAisErrorT.SA_AIS_ERR_BUSY:
  171                 sleep_time_interval = 3 * RETRY_INTERVAL
  172             else:
  173                 break  # Break out of the retry loop
  174 
  175             # Check sleep_time_interval to sleep and retry the function
  176             time.sleep(sleep_time_interval)
  177             count_sec_sleeps += sleep_time_interval
  178             # If the SAF Initialize() function returns ERR_TRY_AGAIN, the
  179             # version (as output argument) will still get updated to the
  180             # latest supported service API version; thus we need to restore
  181             # the original backed-up version before the next retry of
  182             # initialization.
  183             version = deepcopy(backup_version)
  184             args = args[:2] + (version,)
  185             rc = init_func(*args)
  186 
  187         return rc
  188 
  189     return inner
  190 
  191 
  192 def bad_handle_retry(func):
  193     """ Decorate the given function so that it retries a fixed number of times
  194     if getting the error code SA_AIS_ERR_BAD_HANDLE during execution
  195 
  196     Args:
  197         func (function): The decorated function
  198 
  199     Returns:
  200         Return code/output of the decorated function
  201     """
  202     def inner(*args, **kwargs):
  203         """ Call the decorated function in the lexical scope in a retry loop
  204         if it gets the returned error code SA_AIS_ERR_BAD_HANDLE
  205 
  206         Args:
  207             args (tuple): Arguments of the decorated function
  208         """
  209         count_sec_sleeps = 0
  210         sleep_time_interval = 10 * RETRY_INTERVAL
  211 
  212         result = func(*args, **kwargs)
  213         rc = result[0] if isinstance(result, tuple) else result
  214         while rc == eSaAisErrorT.SA_AIS_ERR_BAD_HANDLE:
  215             if count_sec_sleeps >= MAX_RETRY_TIME:
  216                 break
  217 
  218             time.sleep(sleep_time_interval)
  219             count_sec_sleeps += sleep_time_interval
  220             result = func(*args, **kwargs)
  221             rc = result[0] if isinstance(result, tuple) else result
  222 
  223         return result
  224 
  225     return inner
  226 
  227 
  228 def deprecate(func):
  229     """ Decorate the given function as deprecated
  230 
  231     A warning message to notify the users about the function deprecation will
  232     be displayed if the users have enabled the filter for this kind of warning
  233 
  234     Args:
  235         func (function): The deprecated function
  236 
  237     Returns:
  238         Return code/output of the decorated function
  239     """
  240     def inner(*args, **kwargs):
  241         """ Call the deprecated function in the lexical scope """
  242         warnings.warn("This function will be deprecated in future release. "
  243                       "Please consider using its OOP counterpart.",
  244                       PendingDeprecationWarning)
  245         return func(*args, **kwargs)
  246 
  247     return inner
  248 
  249 
  250 ###############################
  251 # Common system logging utils #
  252 ###############################
  253 def log_err(message):
  254     """ Print a message to syslog at ERROR level
  255 
  256     Args:
  257         message (str): Message to be printed to syslog
  258     """
  259     syslog.syslog(syslog.LOG_ERR, "ER " + message)
  260 
  261 
  262 def log_warn(message):
  263     """ Print a message to syslog at WARNING level
  264 
  265     Args:
  266         message (str): Message to be printed to syslog
  267     """
  268     syslog.syslog(syslog.LOG_WARNING, "WA " + message)
  269 
  270 
  271 def log_notice(message):
  272     """ Print a message to syslog at NOTICE level
  273     Args:
  274         message (str): Message to be printed to syslog
  275     """
  276     syslog.syslog(syslog.LOG_NOTICE, "NO " + message)
  277 
  278 
  279 def log_info(message):
  280     """ Print a message to syslog at INFO level
  281 
  282     Args:
  283         message (str): Message to be printed to syslog
  284     """
  285     syslog.syslog(syslog.LOG_INFO, "IN " + message)
  286 
  287 
  288 def log_debug(message):
  289     """ Print a message to syslog at DEBUG level
  290 
  291     Args:
  292         message (str): Message to be printed to syslog
  293     """
  294     syslog.syslog(syslog.LOG_DEBUG, "DB " + message)
  295 
  296 
  297 def log_init(ident):
  298     """ Initialize system logging function
  299 
  300     Args:
  301         ident(str): A string to be prepended to each message
  302     """
  303     syslog.openlog(ident, syslog.LOG_PID, syslog.LOG_USER)