Add programatic introspection of drivers characteristic(s)

Change-Id: Icf187db9ba7d076b1a0f3cc9343acb0eaa1862cb
This commit is contained in:
Joshua Harlow 2015-10-31 14:32:44 -07:00
parent 9f5290ea9c
commit a3f22fe90c
11 changed files with 191 additions and 1 deletions

View File

@ -4,13 +4,17 @@ Drivers
Tooz is provided with several drivers implementing the provided coordination
API. While all drivers provides the same set of features with respect to the
API, some of them have different properties.
API, some of them have different characteristics:
Zookeeper
---------
**Driver:** :py:class:`tooz.drivers.zookeeper.KazooDriver`
**Characteristics:**
:py:attr:`tooz.drivers.zookeeper.KazooDriver.CHARACTERISTICS`
**Entrypoint name:** ``zookeeper`` or ``kazoo``
**Summary:**
@ -21,6 +25,10 @@ resilient towards network partitions for example.
**Test driver:** :py:class:`tooz.drivers.zake.ZakeDriver`
**Characteristics:**
:py:attr:`tooz.drivers.zake.ZakeDriver.CHARACTERISTICS`
**Test driver entrypoint name:** ``zake``
Considerations
@ -35,6 +43,10 @@ Memcached
**Driver:** :py:class:`tooz.drivers.memcached.MemcachedDriver`
**Characteristics:**
:py:attr:`tooz.drivers.memcached.MemcachedDriver.CHARACTERISTICS`
**Entrypoint name:** ``memcached``
**Summary:**
@ -58,6 +70,10 @@ Redis
**Driver:** :py:class:`tooz.drivers.redis.RedisDriver`
**Characteristics:**
:py:attr:`tooz.drivers.redis.RedisDriver.CHARACTERISTICS`
**Entrypoint name:** ``redis``
**Summary:**
@ -79,6 +95,8 @@ IPC
**Driver:** :py:class:`tooz.drivers.ipc.IPCDriver`
**Characteristics:** :py:attr:`tooz.drivers.ipc.IPCDriver.CHARACTERISTICS`
**Entrypoint name:** ``ipc``
**Summary:**
@ -98,6 +116,8 @@ File
**Driver:** :py:class:`tooz.drivers.file.FileDriver`
**Characteristics:** :py:attr:`tooz.drivers.file.FileDriver.CHARACTERISTICS`
**Entrypoint name:** ``file``
**Summary:**
@ -118,6 +138,10 @@ PostgreSQL
**Driver:** :py:class:`tooz.drivers.pgsql.PostgresDriver`
**Characteristics:**
:py:attr:`tooz.drivers.pgsql.PostgresDriver.CHARACTERISTICS`
**Entrypoint name:** ``postgresql``
**Summary:**
@ -140,6 +164,8 @@ MySQL
**Driver:** :py:class:`tooz.drivers.mysql.MySQLDriver`
**Characteristics:** :py:attr:`tooz.drivers.mysql.MySQLDriver.CHARACTERISTICS`
**Entrypoint name:** ``mysql``
**Summary:**
@ -157,6 +183,11 @@ Considerations
- Does **not** work when MySQL replicates from one server to another (locks
are local to the server that they were created from).
Characteristics
---------------
.. autoclass:: tooz.coordination.Characteristics
.. _advisory locks: http://www.postgresql.org/docs/8.2/interactive/\
explicit-locking.html#ADVISORY-LOCKS
.. _get_lock: http://dev.mysql.com/doc/refman/5.5/en/\

View File

@ -5,6 +5,7 @@ pbr>=1.6
Babel>=1.3
stevedore>=1.5.0 # Apache-2.0
six>=1.9.0
enum34;python_version=='2.7' or python_version=='2.6' or python_version=='3.3'
iso8601>=0.1.9
zake>=0.1.6 # Apache-2.0
jsonschema!=2.5.0,<3.0.0,>=2.0.0

View File

@ -16,6 +16,7 @@
import abc
import collections
import enum
from oslo_utils import excutils
from oslo_utils import netutils
@ -28,6 +29,74 @@ import tooz
TOOZ_BACKENDS_NAMESPACE = "tooz.backends"
class Characteristics(enum.Enum):
"""Attempts to describe the characteristic that a driver supports."""
DISTRIBUTED_ACROSS_THREADS = 'DISTRIBUTED_ACROSS_THREADS'
"""Coordinator components when used by multiple **threads** work
the same as if those components were only used by a single thread."""
DISTRIBUTED_ACROSS_PROCESSES = 'DISTRIBUTED_ACROSS_PROCESSES'
"""Coordinator components when used by multiple **processes** work
the same as if those components were only used by a single thread."""
DISTRIBUTED_ACROSS_HOSTS = 'DISTRIBUTED_ACROSS_HOSTS'
"""Coordinator components when used by multiple **hosts** work
the same as if those components were only used by a single thread."""
LINEARIZABLE = 'LINEARIZABLE'
"""The driver has the following properties:
* Ensures each operation must take place before its
completion time.
* Any operation invoked subsequently must take place
after the invocation and by extension, after the original operation
itself.
"""
SEQUENTIAL = 'SEQUENTIAL'
"""The driver has the following properties:
* Operations can take effect before or after completion but all
operations retain the constraint that operations from any given process
must take place in that processes order.
"""
CAUSAL = 'CAUSAL'
"""The driver has the following properties:
* Does **not** have to enforce the order of every
operation from a process, perhaps, only causally related operations
must occur in order.
"""
SERIALIZABLE = 'SERIALIZABLE'
"""The driver has the following properties:
* The history of **all** operations is equivalent to
one that took place in some single atomic order but with unknown
invocation and completion times - it places no bounds on
time or order.
"""
SAME_VIEW_UNDER_PARTITIONS = 'SAME_VIEW_UNDER_PARTITIONS'
"""When a client is connected to a server and that server is partitioned
from a group of other servers it will (somehow) have the same view of
data as a client connected to a server on the other side of the
partition (typically this is accomplished by write availability being
lost and therefore nothing can change).
"""
SAME_VIEW_ACROSS_CLIENTS = 'SAME_VIEW_ACROSS_CLIENTS'
"""A client connected to one server will *always* have the same view
every other client will have (no matter what server those other
clients are connected to). Typically this is a sacrifice in
write availability because before a write can be acknowledged it must
be acknowledged by *all* servers in a cluster (so that all clients
that are connected to those servers read the exact *same* thing).
"""
class Hooks(list):
def run(self, *args, **kwargs):
return list(map(lambda cb: cb(*args, **kwargs), self))
@ -72,6 +141,12 @@ class CoordinationDriver(object):
backing store.
"""
CHARACTERISTICS = ()
"""
Tuple of :py:class:`~tooz.coordination.Characteristics` introspectable
enum member(s) that can be used to interogate how this driver works.
"""
def __init__(self):
self._started = False
self._hooks_join_group = collections.defaultdict(Hooks)

View File

@ -193,6 +193,15 @@ class FileDriver(coordination._RunWatchersMixin,
account when applying this driver in there app).
"""
CHARACTERISTICS = (
coordination.Characteristics.DISTRIBUTED_ACROSS_THREADS,
coordination.Characteristics.DISTRIBUTED_ACROSS_PROCESSES,
)
"""
Tuple of :py:class:`~tooz.coordination.Characteristics` introspectable
enum member(s) that can be used to interogate how this driver works.
"""
HASH_ROUTINE = 'sha1'
"""This routine is used to hash a member (or group) id into a filesystem
safe name that can be used for member lookup and group joining."""

View File

@ -133,6 +133,15 @@ class IPCDriver(coordination.CoordinationDriver):
.. _IPC: http://en.wikipedia.org/wiki/Inter-process_communication
"""
CHARACTERISTICS = (
coordination.Characteristics.DISTRIBUTED_ACROSS_THREADS,
coordination.Characteristics.DISTRIBUTED_ACROSS_PROCESSES,
)
"""
Tuple of :py:class:`~tooz.coordination.Characteristics` introspectable
enum member(s) that can be used to interogate how this driver works.
"""
_SEGMENT_SIZE = 1024
_GROUP_LIST_KEY = "GROUP_LIST"
_GROUP_PROJECT = "_TOOZ_INTERNAL"

View File

@ -173,6 +173,17 @@ class MemcachedDriver(coordination._RunWatchersMixin,
.. _msgpack: http://msgpack.org/
"""
CHARACTERISTICS = (
coordination.Characteristics.DISTRIBUTED_ACROSS_THREADS,
coordination.Characteristics.DISTRIBUTED_ACROSS_PROCESSES,
coordination.Characteristics.DISTRIBUTED_ACROSS_HOSTS,
coordination.Characteristics.CAUSAL,
)
"""
Tuple of :py:class:`~tooz.coordination.Characteristics` introspectable
enum member(s) that can be used to interogate how this driver works.
"""
#: Key prefix attached to groups (used in name-spacing keys)
GROUP_PREFIX = b'_TOOZ_GROUP_'

View File

@ -102,6 +102,16 @@ class MySQLDriver(coordination.CoordinationDriver):
.. _MySQL: http://dev.mysql.com/
"""
CHARACTERISTICS = (
coordination.Characteristics.DISTRIBUTED_ACROSS_THREADS,
coordination.Characteristics.DISTRIBUTED_ACROSS_PROCESSES,
coordination.Characteristics.DISTRIBUTED_ACROSS_HOSTS,
)
"""
Tuple of :py:class:`~tooz.coordination.Characteristics` introspectable
enum member(s) that can be used to interogate how this driver works.
"""
def __init__(self, member_id, parsed_url, options):
"""Initialize the MySQL driver."""
super(MySQLDriver, self).__init__()

View File

@ -158,6 +158,16 @@ class PostgresDriver(coordination.CoordinationDriver):
.. _PostgreSQL: http://www.postgresql.org/
"""
CHARACTERISTICS = (
coordination.Characteristics.DISTRIBUTED_ACROSS_THREADS,
coordination.Characteristics.DISTRIBUTED_ACROSS_PROCESSES,
coordination.Characteristics.DISTRIBUTED_ACROSS_HOSTS,
)
"""
Tuple of :py:class:`~tooz.coordination.Characteristics` introspectable
enum member(s) that can be used to interogate how this driver works.
"""
def __init__(self, member_id, parsed_url, options):
"""Initialize the PostgreSQL driver."""
super(PostgresDriver, self).__init__()

View File

@ -160,6 +160,17 @@ class RedisDriver(coordination._RunWatchersMixin,
.. _AOF: http://redis.io/topics/persistence
"""
CHARACTERISTICS = (
coordination.Characteristics.DISTRIBUTED_ACROSS_THREADS,
coordination.Characteristics.DISTRIBUTED_ACROSS_PROCESSES,
coordination.Characteristics.DISTRIBUTED_ACROSS_HOSTS,
coordination.Characteristics.CAUSAL,
)
"""
Tuple of :py:class:`~tooz.coordination.Characteristics` introspectable
enum member(s) that can be used to interogate how this driver works.
"""
MIN_VERSION = version.LooseVersion("2.6.0")
"""
The min redis version that this driver requires to operate with...

View File

@ -17,6 +17,7 @@ from __future__ import absolute_import
from zake import fake_client
from zake import fake_storage
from tooz import coordination
from tooz.drivers import zookeeper
@ -31,6 +32,14 @@ class ZakeDriver(zookeeper.KazooDriver):
.. _zookeeper: http://zookeeper.apache.org/
"""
CHARACTERISTICS = (
coordination.Characteristics.DISTRIBUTED_ACROSS_THREADS,
)
"""
Tuple of :py:class:`~tooz.coordination.Characteristics` introspectable
enum member(s) that can be used to interogate how this driver works.
"""
# NOTE(harlowja): this creates a shared backend 'storage' layer that
# would typically exist inside a zookeeper server, but since zake has
# no concept of a 'real' zookeeper server we create a fake one and share

View File

@ -407,6 +407,20 @@ class KazooDriver(BaseZooKeeperDriver):
this option is one of the keys in this dictionary).
"""
CHARACTERISTICS = (
coordination.Characteristics.DISTRIBUTED_ACROSS_THREADS,
coordination.Characteristics.DISTRIBUTED_ACROSS_PROCESSES,
coordination.Characteristics.DISTRIBUTED_ACROSS_HOSTS,
# Writes *always* go through a single leader process, but it may
# take a while for those writes to propagate to followers (and =
# during this time clients can read older values)...
coordination.Characteristics.SEQUENTIAL,
)
"""
Tuple of :py:class:`~tooz.coordination.Characteristics` introspectable
enum member(s) that can be used to interogate how this driver works.
"""
def __init__(self, member_id, parsed_url, options):
super(KazooDriver, self).__init__(member_id, parsed_url, options)
self._coord = self._make_client(parsed_url, self._options)