Make fakeldap use redis
This commit is contained in:
		| @@ -21,37 +21,31 @@ | |||||||
|   Fake LDAP server for test harnesses. |   Fake LDAP server for test harnesses. | ||||||
| """ | """ | ||||||
|  |  | ||||||
| import logging | import json | ||||||
|  |  | ||||||
| from nova import datastore | from nova import datastore | ||||||
|  |  | ||||||
| SCOPE_SUBTREE  = 1 | SCOPE_SUBTREE  = 2 | ||||||
| MOD_ADD = 0 | MOD_ADD = 0 | ||||||
| MOD_DELETE = 1 | MOD_DELETE = 1 | ||||||
|  |  | ||||||
| SUBS = { |  | ||||||
|     'groupOfNames': ['novaProject'] |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class NO_SUCH_OBJECT(Exception): | class NO_SUCH_OBJECT(Exception): | ||||||
|     pass |     pass | ||||||
|  |  | ||||||
|  |  | ||||||
| def initialize(uri): | def initialize(uri): | ||||||
|     return FakeLDAP(uri) |     return FakeLDAP() | ||||||
|  |  | ||||||
|  |  | ||||||
| class FakeLDAP(object): | class FakeLDAP(object): | ||||||
|     def __init__(self, _uri): |  | ||||||
|         self.keeper = datastore.Keeper('fakeldap') |  | ||||||
|         if self.keeper['objects'] is None: |  | ||||||
|             self.keeper['objects'] = {} |  | ||||||
|  |  | ||||||
|     def simple_bind_s(self, dn, password): |     def simple_bind_s(self, dn, password): | ||||||
|  |         """This method is ignored, but provided for compatibility""" | ||||||
|         pass |         pass | ||||||
|  |  | ||||||
|     def unbind_s(self): |     def unbind_s(self): | ||||||
|  |         """This method is ignored, but provided for compatibility""" | ||||||
|         pass |         pass | ||||||
|  |  | ||||||
|     def _paren_groups(self, source): |     def _paren_groups(self, source): | ||||||
| @@ -67,6 +61,7 @@ class FakeLDAP(object): | |||||||
|                 count -= 1 |                 count -= 1 | ||||||
|                 if count == 0: |                 if count == 0: | ||||||
|                     result.append(source[start:pos+1]) |                     result.append(source[start:pos+1]) | ||||||
|  |         return result | ||||||
|  |  | ||||||
|     def _match_query(self, query, attrs): |     def _match_query(self, query, attrs): | ||||||
|         inner = query[1:-1] |         inner = query[1:-1] | ||||||
| @@ -83,63 +78,84 @@ class FakeLDAP(object): | |||||||
|         return self._match(k, v, attrs) |         return self._match(k, v, attrs) | ||||||
|  |  | ||||||
|     def _subs(self, v): |     def _subs(self, v): | ||||||
|         if v in SUBS: |         subs = { | ||||||
|             return [v] + SUBS[v] |             'groupOfNames': ['novaProject'] | ||||||
|  |         } | ||||||
|  |         if v in subs: | ||||||
|  |             return [v] + subs[v] | ||||||
|         return [v] |         return [v] | ||||||
|  |  | ||||||
|     def _match(self, k, v, attrs): |     def _match(self, k, v, attrs): | ||||||
|         if attrs.has_key(k): |         if attrs.has_key(k): | ||||||
|             for v in self._subs(v): |             for v in self._subs(v): | ||||||
|                 if (v in attrs[k]): |                 if v in attrs[k]: | ||||||
|                     return True |                     return True | ||||||
|         return False |         return False | ||||||
|  |  | ||||||
|  |  | ||||||
|     def search_s(self, dn, scope, query=None, fields=None): |     def search_s(self, dn, scope, query=None, fields=None): | ||||||
|         #logging.debug("searching for %s" % dn) |         """search for all matching objects under dn using the query | ||||||
|         filtered = {} |         only SCOPE_SUBTREE is supported. | ||||||
|         d = self.keeper['objects'] or {} |         """ | ||||||
|         for cn, attrs in d.iteritems(): |         if scope != SCOPE_SUBTREE: | ||||||
|             if cn[-len(dn):] == dn: |             raise NotImplementedError(str(scope)) | ||||||
|                 filtered[cn] = attrs |         redis = datastore.Redis.instance() | ||||||
|         objects = filtered |         keys = redis.keys(self._redis_prefix + '*' + dn) | ||||||
|         if query: |         objects = [] | ||||||
|             objects = {} |         for key in keys: | ||||||
|             for cn, attrs in filtered.iteritems(): |             # get the attributes from redis | ||||||
|                 if self._match_query(query, attrs): |             attrs = redis.hgetall(key) | ||||||
|                     objects[cn] = attrs |             # turn the values from redis into lists | ||||||
|         if objects == {}: |             attrs = dict([(k, self._from_json(v)) | ||||||
|  |                           for k, v in attrs.iteritems()]) | ||||||
|  |             # filter the objects by query | ||||||
|  |             if not query or self._match_query(query, attrs): | ||||||
|  |                 # filter the attributes by fields | ||||||
|  |                 attrs = dict([(k, v) for k, v in attrs.iteritems() | ||||||
|  |                               if not fields or k in fields]) | ||||||
|  |                 objects.append((key[len(self._redis_prefix):], attrs)) | ||||||
|  |         if objects == []: | ||||||
|             raise NO_SUCH_OBJECT() |             raise NO_SUCH_OBJECT() | ||||||
|         return objects.items() |         return objects | ||||||
|  |  | ||||||
|     def add_s(self, cn, attr): |     @property | ||||||
|         #logging.debug("adding %s" % cn) |     def _redis_prefix(self): | ||||||
|         stored = {} |         return 'ldap:' | ||||||
|         for k, v in attr: |  | ||||||
|             if type(v) is list: |  | ||||||
|                 stored[k] = v |  | ||||||
|             else: |  | ||||||
|                 stored[k] = [v] |  | ||||||
|         d = self.keeper['objects'] |  | ||||||
|         d[cn] = stored |  | ||||||
|         self.keeper['objects'] = d |  | ||||||
|  |  | ||||||
|     def delete_s(self, cn): |     def _from_json(self, encoded): | ||||||
|         logging.debug("deleting %s" % cn) |         """Convert attribute values from json representation.""" | ||||||
|         d = self.keeper['objects'] |         # return as simple strings instead of unicode strings | ||||||
|         del d[cn] |         return [str(x) for x in json.loads(encoded)] | ||||||
|         self.keeper['objects'] = d |  | ||||||
|  |  | ||||||
|     def modify_s(self, cn, attr): |     def _to_json(self, unencoded): | ||||||
|         logging.debug("modifying %s" % cn) |         """Convert attribute values into json representation.""" | ||||||
|         d = self.keeper['objects'] |         # all values are returned as lists from ldap | ||||||
|         for cmd, k, v in attr: |         return json.dumps(list(unencoded)) | ||||||
|             logging.debug("command %s" % cmd) |  | ||||||
|  |     def add_s(self, dn, attr): | ||||||
|  |         """Add an object with the specified attributes at dn.""" | ||||||
|  |         key = self._redis_prefix + dn | ||||||
|  |  | ||||||
|  |         value_dict = dict([(k, self._to_json(v)) for k, v in attr]) | ||||||
|  |         datastore.Redis.instance().hmset(key, value_dict) | ||||||
|  |  | ||||||
|  |     def delete_s(self, dn): | ||||||
|  |         """Remove the ldap object at specified dn.""" | ||||||
|  |         datastore.Redis.instance().delete(self._redis_prefix + dn) | ||||||
|  |  | ||||||
|  |     def modify_s(self, dn, attrs): | ||||||
|  |         """Modify the object at dn using the attribute list. | ||||||
|  |         attr is a list of tuples in the following form: | ||||||
|  |             ([MOD_ADD | MOD_DELETE], attribute, value) | ||||||
|  |         """ | ||||||
|  |         redis = datastore.Redis.instance() | ||||||
|  |         key = self._redis_prefix + dn | ||||||
|  |  | ||||||
|  |         for cmd, k, v in attrs: | ||||||
|  |             values = self._from_json(redis.hget(key, k)) | ||||||
|             if cmd == MOD_ADD: |             if cmd == MOD_ADD: | ||||||
|                 d[cn][k].append(v) |                 values.append(v) | ||||||
|             else: |             else: | ||||||
|                 d[cn][k].remove(v) |                 values.remove(v) | ||||||
|         self.keeper['objects'] = d |             values = redis.hset(key, k, self._to_json(values)) | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Vishvananda Ishaya
					Vishvananda Ishaya