X-Git-Url: https://gerrit.akraino.org/r/gitweb?a=blobdiff_plain;f=cmframework%2Fsrc%2Fcmframework%2Fredisbackend%2Fcmredisdb.py;fp=cmframework%2Fsrc%2Fcmframework%2Fredisbackend%2Fcmredisdb.py;h=deb9b7780503e757d49aae17add2e9b083ef50a5;hb=c389bdee7b3845b55f443dbf04c0ce4083a55886;hp=0000000000000000000000000000000000000000;hpb=5030f0c004701dd422c78c71c014ef60f48139fc;p=ta%2Fconfig-manager.git diff --git a/cmframework/src/cmframework/redisbackend/cmredisdb.py b/cmframework/src/cmframework/redisbackend/cmredisdb.py new file mode 100644 index 0000000..deb9b77 --- /dev/null +++ b/cmframework/src/cmframework/redisbackend/cmredisdb.py @@ -0,0 +1,190 @@ +# Copyright 2019 Nokia + +# 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. +# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 +from __future__ import print_function +from urlparse import urlparse +import re +import time +import functools +import redis + +from cmframework.apis import cmerror +from cmframework.apis import cmbackend + + +def retry(func): + @functools.wraps(func) + def wrapper(*args, **kwargs): + for _ in xrange(20): + try: + return func(*args, **kwargs) + except Exception, e: # pylint: disable=broad-except + time.sleep(1) + retExc = e + raise retExc + + return wrapper + + +class CMRedisDB(cmbackend.CMBackend): + + def __init__(self, **kw): + dburl = kw['uri'] + urldata = urlparse(dburl) + self.vip = urldata.hostname + self.port = urldata.port + self.password = urldata.password + self.client = redis.StrictRedis(host=self.vip, port=self.port, password=self.password) + + @retry + def set_property(self, prop_name, prop_value): + self.client.set(prop_name, prop_value) + + def get_property(self, prop_name): + return self.client.get(prop_name) + + @retry + def delete_property(self, prop_name): + self.client.delete(prop_name) + + @retry + def set_properties(self, properties): + pipe = self.client.pipeline() + for name, value in properties.iteritems(): + pipe.set(name, value) + pipe.execute() + + def get_properties(self, prop_filter): + # seems redis does not understand regex, it understands only glob + # patterns, thus we need to handle the matching by ourselves :/ + keys = self.client.keys() + pattern = re.compile(prop_filter) + props = {} + for key in keys: + if pattern.match(key): + value = self.client.get(key) + props[key] = value + return props + + @retry + def delete_properties(self, arg): + if not isinstance(arg, list): + raise cmerror.CMError('Deleting with filter is not supported by the backend') + pipe = self.client.pipeline() + for prop in arg: + pipe.delete(prop) + pipe.execute() + + +def main(): + import argparse + import sys + import traceback + + parser = argparse.ArgumentParser(description='Test redis db plugin', prog=sys.argv[0]) + + parser.add_argument('--uri', + required=True, + dest='uri', + metavar='URI', + help='The redis db uri format redis://:password@:port', + type=str, + action='store') + + parser.add_argument('--api', + required=True, + dest='api', + metavar='API', + help=('The api name, can be set_property, get_property, delete_property, ' + 'set_properties, get_properties, delete_properties'), + type=str, + action='store') + + parser.add_argument('--property', + required=False, + dest='properties', + metavar='PROPERTY', + help='The property in the format name[=value]', + type=str, + action='append') + + parser.add_argument('--filter', + required=False, + dest='filter', + metavar='FILTER', + help='The regular expression matching the property names', + type=str, + action='store') + + args = parser.parse_args(sys.argv[1:]) + + try: + uri = args.uri + api = args.api + p = {} + p['uri'] = uri + db = CMRedisDB(**p) + print('Involing %s' % api) + func = getattr(db, api) + if api == 'set_property': + if not args.properties: + raise Exception('Missing --properties argument') + for prop in args.properties: + i = prop.index('=') + name = prop[:i] + value = prop[(i + 1):] + print("Setting %s to %s" % (name, value)) + func(name, value) + elif api == 'get_property': + if not args.properties: + raise Exception('Missing --properties argument') + for prop in args.properties: + value = func(prop) + print('%s=%s' % (prop, value)) + elif api == 'delete_property': + if not args.properties: + raise Exception('Missing --properties argument') + for prop in args.properties: + print('Deleting %s' % prop) + func(prop) + elif api == 'set_properties': + if not args.properties: + raise Exception('Missing --properties argument') + props = {} + for prop in args.properties: + i = prop.index('=') + name = prop[:i] + value = prop[(i + 1):] + props[name] = value + func(props) + elif api == 'get_properties': + if not args.filter: + raise Exception('Missing --filter argument') + print('Getting properties matching %s' % args.filter) + props = func(args.filter) + for key, value in props.iteritems(): + print('%s=%s' % (key, value)) + elif api == 'delete_properties': + if not args.properties: + raise Exception('Missing --properties argument') + func(args.properties) + except Exception as exp: # pylint: disable=broad-except + print('Failed with error %s', exp) + traceback.print_exc() + sys.exit(1) + sys.exit(0) + + +if __name__ == '__main__': + main()