Since our code will only support py3. So remove six is necessary. Change-Id: I3738118b1898421ee41e9e2902c255ead73f3915
165 lines
4.6 KiB
Python
165 lines
4.6 KiB
Python
# -*- encoding: utf-8 -*-
|
|
# Copyright (c) 2015 b<>com
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
# implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
"""Utilities and helper functions."""
|
|
|
|
import datetime
|
|
import random
|
|
import re
|
|
import string
|
|
|
|
from croniter import croniter
|
|
|
|
from jsonschema import validators
|
|
from oslo_config import cfg
|
|
from oslo_log import log
|
|
from oslo_utils import strutils
|
|
from oslo_utils import uuidutils
|
|
|
|
from watcher.common import exception
|
|
|
|
CONF = cfg.CONF
|
|
|
|
LOG = log.getLogger(__name__)
|
|
|
|
|
|
class Struct(dict):
|
|
"""Specialized dict where you access an item like an attribute
|
|
|
|
>>> struct = Struct()
|
|
>>> struct['a'] = 1
|
|
>>> struct.b = 2
|
|
>>> assert struct.a == 1
|
|
>>> assert struct['b'] == 2
|
|
"""
|
|
|
|
def __getattr__(self, name):
|
|
try:
|
|
return self[name]
|
|
except KeyError:
|
|
raise AttributeError(name)
|
|
|
|
def __setattr__(self, name, value):
|
|
try:
|
|
self[name] = value
|
|
except KeyError:
|
|
raise AttributeError(name)
|
|
|
|
|
|
generate_uuid = uuidutils.generate_uuid
|
|
is_uuid_like = uuidutils.is_uuid_like
|
|
is_int_like = strutils.is_int_like
|
|
|
|
|
|
def is_cron_like(value):
|
|
"""Return True is submitted value is like cron syntax"""
|
|
try:
|
|
croniter(value, datetime.datetime.now())
|
|
except Exception as e:
|
|
raise exception.CronFormatIsInvalid(message=str(e))
|
|
return True
|
|
|
|
|
|
def safe_rstrip(value, chars=None):
|
|
"""Removes trailing characters from a string if that does not make it empty
|
|
|
|
:param value: A string value that will be stripped.
|
|
:param chars: Characters to remove.
|
|
:return: Stripped value.
|
|
|
|
"""
|
|
if not isinstance(value, str):
|
|
LOG.warning(
|
|
"Failed to remove trailing character. Returning original object."
|
|
"Supplied object is not a string: %s,", value)
|
|
return value
|
|
|
|
return value.rstrip(chars) or value
|
|
|
|
|
|
def is_hostname_safe(hostname):
|
|
"""Determine if the supplied hostname is RFC compliant.
|
|
|
|
Check that the supplied hostname conforms to:
|
|
* http://en.wikipedia.org/wiki/Hostname
|
|
* http://tools.ietf.org/html/rfc952
|
|
* http://tools.ietf.org/html/rfc1123
|
|
|
|
:param hostname: The hostname to be validated.
|
|
:returns: True if valid. False if not.
|
|
|
|
"""
|
|
m = r'^[a-z0-9]([a-z0-9\-]{0,61}[a-z0-9])?$'
|
|
return (isinstance(hostname, str) and
|
|
(re.match(m, hostname) is not None))
|
|
|
|
|
|
def get_cls_import_path(cls):
|
|
"""Return the import path of a given class"""
|
|
module = cls.__module__
|
|
if module is None or module == str.__module__:
|
|
return cls.__name__
|
|
return module + '.' + cls.__name__
|
|
|
|
|
|
# Default value feedback extension as jsonschema doesn't support it
|
|
def extend_with_default(validator_class):
|
|
validate_properties = validator_class.VALIDATORS["properties"]
|
|
|
|
def set_defaults(validator, properties, instance, schema):
|
|
for prop, subschema in properties.items():
|
|
if "default" in subschema and instance is not None:
|
|
instance.setdefault(prop, subschema["default"])
|
|
|
|
for error in validate_properties(
|
|
validator, properties, instance, schema
|
|
):
|
|
yield error
|
|
|
|
return validators.extend(validator_class,
|
|
{"properties": set_defaults})
|
|
|
|
|
|
# Parameter strict check extension as jsonschema doesn't support it
|
|
def extend_with_strict_schema(validator_class):
|
|
validate_properties = validator_class.VALIDATORS["properties"]
|
|
|
|
def strict_schema(validator, properties, instance, schema):
|
|
if instance is None:
|
|
return
|
|
|
|
for para in instance.keys():
|
|
if para not in properties.keys():
|
|
raise exception.AuditParameterNotAllowed(parameter=para)
|
|
|
|
for error in validate_properties(
|
|
validator, properties, instance, schema
|
|
):
|
|
yield error
|
|
|
|
return validators.extend(validator_class, {"properties": strict_schema})
|
|
|
|
|
|
StrictDefaultValidatingDraft4Validator = extend_with_default(
|
|
extend_with_strict_schema(validators.Draft4Validator))
|
|
|
|
Draft4Validator = validators.Draft4Validator
|
|
|
|
|
|
def random_string(n):
|
|
return ''.join([random.choice(
|
|
string.ascii_letters + string.digits) for i in range(n)])
|