def acquire(self): basedir = os.path.dirname(self.fname) if not os.path.exists(basedir): fileutils.ensure_tree(basedir) LOG.info(_('Created lock path: %s'), basedir) self.lockfile = open(self.fname, 'w') while True: try: # Using non-blocking locks since green threads are not # patched to deal with blocking locking calls. # Also upon reading the MSDN docs for locking(), it seems # to have a laughable 10 attempts "blocking" mechanism. self.trylock() LOG.debug(_('Got file lock "%s"'), self.fname) return True except IOError as e: if e.errno in (errno.EACCES, errno.EAGAIN): # external locks synchronise things like iptables # updates - give it some time to prevent busy spinning time.sleep(0.01) else: raise threading.ThreadError(_("Unable to acquire lock on" " `%(filename)s` due to" " %(exception)s") % { 'filename': self.fname, 'exception': e, })
def to_bytes(text, default=0): """Converts a string into an integer of bytes. Looks at the last characters of the text to determine what conversion is needed to turn the input text into a byte number. Supports "B, K(B), M(B), G(B), and T(B)". (case insensitive) :param text: String input for bytes size conversion. :param default: Default return value when text is blank. """ match = BYTE_REGEX.search(text) if match: magnitude = int(match.group(1)) mult_key_org = match.group(2) if not mult_key_org: return magnitude elif text: msg = _('Invalid string format: %s') % text raise TypeError(msg) else: return default mult_key = mult_key_org.lower().replace('b', '', 1) multiplier = BYTE_MULTIPLIERS.get(mult_key) if multiplier is None: msg = _('Unknown byte multiplier: %s') % mult_key_org raise TypeError(msg) return magnitude * multiplier
def to_bytes(text, default=0): """Converts a string into an integer of bytes. Looks at the last characters of the text to determine what conversion is needed to turn the input text into a byte number. Supports "B, K(B), M(B), G(B), and T(B)". (case insensitive) :param text: String input for bytes size conversion. :param default: Default return value when text is blank. """ match = BYTE_REGEX.search(text) if match: magnitude = int(match.group(1)) mult_key_org = match.group(2) if not mult_key_org: return magnitude elif text: msg = _('Invalid string format: %s') % text raise TypeError(msg) else: return default mult_key = mult_key_org.lower().replace('b', '', 1) multiplier = BYTE_MULTIPLIERS.get(mult_key) if multiplier is None: msg = _('Unknown byte multiplier: %s') % mult_key_org raise TypeError(msg) return magnitude * multiplier
def acquire(self): basedir = os.path.dirname(self.fname) if not os.path.exists(basedir): fileutils.ensure_tree(basedir) LOG.info(_('Created lock path: %s'), basedir) self.lockfile = open(self.fname, 'w') while True: try: # Using non-blocking locks since green threads are not # patched to deal with blocking locking calls. # Also upon reading the MSDN docs for locking(), it seems # to have a laughable 10 attempts "blocking" mechanism. self.trylock() LOG.debug(_('Got file lock "%s"'), self.fname) return True except IOError as e: if e.errno in (errno.EACCES, errno.EAGAIN): # external locks synchronise things like iptables # updates - give it some time to prevent busy spinning time.sleep(0.01) else: raise threading.ThreadError( _("Unable to acquire lock on" " `%(filename)s` due to" " %(exception)s") % { 'filename': self.fname, 'exception': e, })
def release(self): try: self.unlock() self.lockfile.close() LOG.debug(_('Released file lock "%s"'), self.fname) except IOError: LOG.exception(_("Could not release the acquired lock `%s`"), self.fname)
def release(self): try: self.unlock() self.lockfile.close() LOG.debug(_('Released file lock "%s"'), self.fname) except IOError: LOG.exception(_("Could not release the acquired lock `%s`"), self.fname)
def inner(*args, **kwargs): try: with lock(name, lock_file_prefix, external): LOG.debug(_('Got semaphore / lock "%(function)s"'), {'function': f.__name__}) return f(*args, **kwargs) finally: LOG.debug(_('Semaphore / lock released "%(function)s"'), {'function': f.__name__})
def inner(*args, **kwargs): try: with lock(name, lock_file_prefix, external): LOG.debug(_('Got semaphore / lock "%(function)s"'), {'function': f.__name__}) return f(*args, **kwargs) finally: LOG.debug(_('Semaphore / lock released "%(function)s"'), {'function': f.__name__})
def deprecated(self, msg, *args, **kwargs): """Call this method when a deprecated feature is used. If the system is configured for fatal deprecations then the message is logged at the 'critical' level and :class:`DeprecatedConfig` will be raised. Otherwise, the message will be logged (once) at the 'warn' level. :raises: :class:`DeprecatedConfig` if the system is configured for fatal deprecations. """ stdmsg = _("Deprecated: %s") % msg if CONF.fatal_deprecations: self.critical(stdmsg, *args, **kwargs) raise DeprecatedConfig(msg=stdmsg) # Using a list because a tuple with dict can't be stored in a set. sent_args = self._deprecated_messages_sent.setdefault(msg, list()) if args in sent_args: # Already logged this message, so don't log it again. return sent_args.append(args) self.warn(stdmsg, *args, **kwargs)
def bool_from_string(subject, strict=False): """Interpret a string as a boolean. A case-insensitive match is performed such that strings matching 't', 'true', 'on', 'y', 'yes', or '1' are considered True and, when `strict=False`, anything else is considered False. Useful for JSON-decoded stuff and config file parsing. If `strict=True`, unrecognized values, including None, will raise a ValueError which is useful when parsing values passed in from an API call. Strings yielding False are 'f', 'false', 'off', 'n', 'no', or '0'. """ if not isinstance(subject, six.string_types): subject = str(subject) lowered = subject.strip().lower() if lowered in TRUE_STRINGS: return True elif lowered in FALSE_STRINGS: return False elif strict: acceptable = ', '.join("'%s'" % s for s in sorted(TRUE_STRINGS + FALSE_STRINGS)) msg = _("Unrecognized value '%(val)s', acceptable values are:" " %(acceptable)s") % { 'val': subject, 'acceptable': acceptable } raise ValueError(msg) else: return False
def inner_func(*args, **kwargs): last_log_time = 0 last_exc_message = None exc_count = 0 while True: try: return infunc(*args, **kwargs) except Exception as exc: this_exc_message = six.u(str(exc)) if this_exc_message == last_exc_message: exc_count += 1 else: exc_count = 1 # Do not log any more frequently than once a minute unless # the exception message changes cur_time = int(time.time()) if (cur_time - last_log_time > 60 or this_exc_message != last_exc_message): logging.exception( _('Unexpected exception occurred %d time(s)... ' 'retrying.') % exc_count) last_log_time = cur_time last_exc_message = this_exc_message exc_count = 0 # This should be a very rare event. In case it isn't, do # a sleep. time.sleep(1)
def bool_from_string(subject, strict=False): """Interpret a string as a boolean. A case-insensitive match is performed such that strings matching 't', 'true', 'on', 'y', 'yes', or '1' are considered True and, when `strict=False`, anything else is considered False. Useful for JSON-decoded stuff and config file parsing. If `strict=True`, unrecognized values, including None, will raise a ValueError which is useful when parsing values passed in from an API call. Strings yielding False are 'f', 'false', 'off', 'n', 'no', or '0'. """ if not isinstance(subject, six.string_types): subject = str(subject) lowered = subject.strip().lower() if lowered in TRUE_STRINGS: return True elif lowered in FALSE_STRINGS: return False elif strict: acceptable = ', '.join( "'%s'" % s for s in sorted(TRUE_STRINGS + FALSE_STRINGS)) msg = _("Unrecognized value '%(val)s', acceptable values are:" " %(acceptable)s") % {'val': subject, 'acceptable': acceptable} raise ValueError(msg) else: return False
class NotAuthorized(KwstandbyClientException): """HTTP 401 - Not authorized. User have no enough rights to perform action. """ code = 401 message = _("Not authorized request.")
def __exit__(self, exc_type, exc_val, exc_tb): if exc_type is not None: logging.error( _('Original exception being dropped: %s'), traceback.format_exception(self.type_, self.value, self.tb)) return False if self.reraise: six.reraise(self.type_, self.value, self.tb)
def internal_lock(name): with _semaphores_lock: try: sem = _semaphores[name] except KeyError: sem = threading.Semaphore() _semaphores[name] = sem LOG.debug(_('Got semaphore "%(lock)s"'), {'lock': name}) return sem
def internal_lock(name): with _semaphores_lock: try: sem = _semaphores[name] except KeyError: sem = threading.Semaphore() _semaphores[name] = sem LOG.debug(_('Got semaphore "%(lock)s"'), {'lock': name}) return sem
class LogConfigError(Exception): message = _('Error loading logging config %(log_config)s: %(err_msg)s') def __init__(self, log_config, err_msg): self.log_config = log_config self.err_msg = err_msg def __str__(self): return self.message % dict(log_config=self.log_config, err_msg=self.err_msg)
def Client(version=1, *args, **kwargs): version_map = { '1': 'kwstandbyclient.v1.client.Client', '1a0': 'kwstandbyclient.v1.client.Client', } try: client_path = version_map[str(version)] except (KeyError, ValueError): msg = _("Invalid client version '%(version)s'. " "Must be one of: %(available_version)s") % ( { 'version': version, 'available_version': ', '.join(version_map.keys()) }) raise exception.UnsupportedVersion(msg) return importutils.import_object(client_path, *args, **kwargs)
def external_lock(name, lock_file_prefix=None): with internal_lock(name): LOG.debug(_('Attempting to grab external lock "%(lock)s"'), {'lock': name}) # NOTE(mikal): the lock name cannot contain directory # separators name = name.replace(os.sep, '_') if lock_file_prefix: sep = '' if lock_file_prefix.endswith('-') else '-' name = '%s%s%s' % (lock_file_prefix, sep, name) if not CONF.lock_path: raise cfg.RequiredOptError('lock_path') lock_file_path = os.path.join(CONF.lock_path, name) return InterProcessLock(lock_file_path)
class KwstandbyClientException(Exception): """Base exception class.""" message = _("An unknown exception occurred %s.") code = 500 def __init__(self, message=None, **kwargs): self.kwargs = kwargs if 'code' not in self.kwargs: try: self.kwargs['code'] = self.code except AttributeError: pass if not message: message = self.message % kwargs super(KwstandbyClientException, self).__init__(message)
def external_lock(name, lock_file_prefix=None): with internal_lock(name): LOG.debug(_('Attempting to grab external lock "%(lock)s"'), {'lock': name}) # NOTE(mikal): the lock name cannot contain directory # separators name = name.replace(os.sep, '_') if lock_file_prefix: sep = '' if lock_file_prefix.endswith('-') else '-' name = '%s%s%s' % (lock_file_prefix, sep, name) if not CONF.lock_path: raise cfg.RequiredOptError('lock_path') lock_file_path = os.path.join(CONF.lock_path, name) return InterProcessLock(lock_file_path)
def from_elapsed_time_to_seconds(elapsed_time): """Return the amount of seconds based on the time_option parameter :param: time_option: a string that matches ELAPSED_TIME_REGEX """ is_elapsed_time = re.match(ELAPSED_TIME_REGEX, elapsed_time) if is_elapsed_time is None: raise exception.KwstandbyClientException( _("Invalid time " "format for option.")) elapsed_time_value = int(is_elapsed_time.group(1)) elapsed_time_option = is_elapsed_time.group(2) seconds = { 's': lambda x: timeutils.total_seconds(datetime.timedelta(seconds=x)), 'm': lambda x: timeutils.total_seconds(datetime.timedelta(minutes=x)), 'h': lambda x: timeutils.total_seconds(datetime.timedelta(hours=x)), 'd': lambda x: timeutils.total_seconds(datetime.timedelta(days=x)), }[elapsed_time_option](elapsed_time_value) # the above code returns a "float" return int(seconds)
def request(self, url, method, **kwargs): """Base request method. Adds specific headers and URL prefix to the request. :param url: Resource URL. :type url: str :param method: Method to be called (GET, POST, PUT, DELETE). :type method: str :returns: Response and body. :rtype: tuple """ kwargs.setdefault('headers', kwargs.get('headers', {})) kwargs['headers']['User-Agent'] = self.USER_AGENT kwargs['headers']['Accept'] = 'application/json' kwargs['headers']['x-auth-token'] = self.auth_token if 'body' in kwargs: kwargs['headers']['Content-Type'] = 'application/json' kwargs['data'] = json.dumps(kwargs['body']) del kwargs['body'] resp = requests.request(method, self.kwstandby_url + url, **kwargs) try: body = json.loads(resp.text) except ValueError: body = None if resp.status_code >= 400: if body is not None: error_message = body.get('error_message', body) else: error_message = resp.text body = _("ERROR: {0}").format(error_message) raise exception.KwstandbyClientException(body, code=resp.status_code) return resp, body
def _find_facility_from_conf(): facility_names = logging.handlers.SysLogHandler.facility_names facility = getattr(logging.handlers.SysLogHandler, CONF.syslog_log_facility, None) if facility is None and CONF.syslog_log_facility in facility_names: facility = facility_names.get(CONF.syslog_log_facility) if facility is None: valid_facilities = facility_names.keys() consts = ['LOG_AUTH', 'LOG_AUTHPRIV', 'LOG_CRON', 'LOG_DAEMON', 'LOG_FTP', 'LOG_KERN', 'LOG_LPR', 'LOG_MAIL', 'LOG_NEWS', 'LOG_AUTH', 'LOG_SYSLOG', 'LOG_USER', 'LOG_UUCP', 'LOG_LOCAL0', 'LOG_LOCAL1', 'LOG_LOCAL2', 'LOG_LOCAL3', 'LOG_LOCAL4', 'LOG_LOCAL5', 'LOG_LOCAL6', 'LOG_LOCAL7'] valid_facilities.extend(consts) raise TypeError(_('syslog facility must be one of: %s') % ', '.join("'%s'" % fac for fac in valid_facilities)) return facility
def from_elapsed_time_to_seconds(elapsed_time): """Return the amount of seconds based on the time_option parameter :param: time_option: a string that matches ELAPSED_TIME_REGEX """ is_elapsed_time = re.match(ELAPSED_TIME_REGEX, elapsed_time) if is_elapsed_time is None: raise exception.KwstandbyClientException(_("Invalid time " "format for option.")) elapsed_time_value = int(is_elapsed_time.group(1)) elapsed_time_option = is_elapsed_time.group(2) seconds = { 's': lambda x: timeutils.total_seconds(datetime.timedelta(seconds=x)), 'm': lambda x: timeutils.total_seconds(datetime.timedelta(minutes=x)), 'h': lambda x: timeutils.total_seconds(datetime.timedelta(hours=x)), 'd': lambda x: timeutils.total_seconds(datetime.timedelta(days=x)), }[elapsed_time_option](elapsed_time_value) # the above code returns a "float" return int(seconds)
def read_cached_file(filename, force_reload=False): """Read from a file if it has been modified. :param force_reload: Whether to reload the file. :returns: A tuple with a boolean specifying if the data is fresh or not. """ global _FILE_CACHE if force_reload and filename in _FILE_CACHE: del _FILE_CACHE[filename] reloaded = False mtime = os.path.getmtime(filename) cache_info = _FILE_CACHE.setdefault(filename, {}) if not cache_info or mtime > cache_info.get('mtime', 0): LOG.debug(_("Reloading cached file %s") % filename) with open(filename) as fap: cache_info['data'] = fap.read() cache_info['mtime'] = mtime reloaded = True return (reloaded, cache_info['data'])
class NoKwstandbyEndpoint(KwstandbyClientException): """Occurs if no endpoint for Kwstandby set in the Keystone.""" message = _("No publicURL endpoint for Kwstandby found. Set endpoint " "for Kwstandby in the Keystone.") code = 404
class NoUniqueMatch(KwstandbyClientException): """Occurs if there are more than one appropriate resources.""" message = _("There is no unique requested resource.") code = 409
class UnsupportedVersion(KwstandbyClientException): """Occurs if unsupported client version was requested.""" message = _("Unsupported client version requested.") code = 406
class IncorrectLease(KwstandbyClientException): """Occurs if lease parameters are incorrect.""" message = _("The lease parameters are incorrect.") code = 409
class DeprecatedConfig(Exception): message = _("Fatal call to deprecated config: %(msg)s") def __init__(self, msg): super(Exception, self).__init__(self.message % dict(msg=msg))
def update(self, node_id, status): """Update node status.""" if not status: return _('No status to update passed.') return self._update('/status/%s/' % node_id, {'status': status}, response_key='nodes_status')
def update(self, node_id, status): """Update node status.""" if not status: return _('No status to update passed.') return self._update('/status/%s/' % node_id, {'status': status}, response_key='nodes_status')
class CommandError(KwstandbyClientException): """Occurs if not all authentication vital options are set.""" message = _("You have to provide all options like user name or tenant " "id to make authentication possible.") code = 401