Add a PostgreSQL driver
Change-Id: Id6a6ef4c1ec11c1f8cf5aa440c4f425213837ffc
This commit is contained in:
parent
b6242610fc
commit
b5f87e4fc5
|
@ -0,0 +1,25 @@
|
|||
#!/bin/bash
|
||||
set -x -e
|
||||
|
||||
. functions.sh
|
||||
|
||||
function clean_exit() {
|
||||
local error_code="$?"
|
||||
${PGSQL_PATH}/pg_ctl -w -D ${PGSQL_DATA} -o "-p $PGSQL_PORT" stop
|
||||
rm -rf ${PGSQL_DATA}
|
||||
return $error_code
|
||||
}
|
||||
|
||||
trap "clean_exit" EXIT
|
||||
|
||||
# Start PostgreSQL process for tests
|
||||
PGSQL_DATA=`mktemp -d /tmp/tooz-pgsql-XXXXX`
|
||||
PGSQL_PATH=`pg_config --bindir`
|
||||
PGSQL_PORT=9825
|
||||
${PGSQL_PATH}/initdb ${PGSQL_DATA}
|
||||
${PGSQL_PATH}/pg_ctl -w -D ${PGSQL_DATA} -o "-k ${PGSQL_DATA} -p ${PGSQL_PORT}" start
|
||||
# Wait for PostgreSQL to start listening to connections
|
||||
export TOOZ_TEST_PGSQL_URL="postgresql:///?host=${PGSQL_DATA}&port=${PGSQL_PORT}&dbname=template1"
|
||||
|
||||
# Yield execution to venv command
|
||||
$*
|
|
@ -30,6 +30,7 @@ tooz.backends =
|
|||
memcached = tooz.drivers.memcached:MemcachedDriver
|
||||
ipc = tooz.drivers.ipc:IPCDriver
|
||||
redis = tooz.drivers.redis:RedisDriver
|
||||
postgresql = tooz.drivers.pgsql:PostgresDriver
|
||||
|
||||
[build_sphinx]
|
||||
all_files = 1
|
||||
|
|
|
@ -9,3 +9,4 @@ testtools>=0.9.32
|
|||
testscenarios>=0.4
|
||||
coverage>=3.6
|
||||
sysv_ipc>=0.6.8
|
||||
psycopg2
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright © 2014 eNovance
|
||||
#
|
||||
# Author: Julien Danjou <julien@danjou.info>
|
||||
#
|
||||
# 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.
|
||||
import hashlib
|
||||
|
||||
import psycopg2
|
||||
import six
|
||||
|
||||
import tooz
|
||||
from tooz import coordination
|
||||
from tooz import locking
|
||||
|
||||
|
||||
class PostgresLock(locking.Lock):
|
||||
"""A PostgreSQL based lock."""
|
||||
|
||||
def __init__(self, name, connection):
|
||||
super(PostgresLock, self).__init__(name)
|
||||
self._conn = connection
|
||||
h = hashlib.md5()
|
||||
h.update(name)
|
||||
if six.PY2:
|
||||
self.key = list(map(ord, h.digest()[0:2]))
|
||||
else:
|
||||
self.key = h.digest()[0:2]
|
||||
|
||||
def acquire(self, blocking=True):
|
||||
if blocking is not True:
|
||||
raise tooz.NotImplemented(
|
||||
"This driver does not support non blocking locks")
|
||||
with self._conn.cursor() as cur:
|
||||
cur.execute("SELECT pg_advisory_lock(%s, %s);", self.key)
|
||||
return True
|
||||
|
||||
def release(self):
|
||||
with self._conn.cursor() as cur:
|
||||
cur.execute("SELECT pg_advisory_unlock(%s, %s);", self.key)
|
||||
return cur.fetchone()[0]
|
||||
|
||||
|
||||
class PostgresDriver(coordination.CoordinationDriver):
|
||||
|
||||
def __init__(self, member_id, parsed_url, options):
|
||||
"""Initialize the PostgreSQL driver."""
|
||||
super(PostgresDriver, self).__init__()
|
||||
self._host = options.get("host", [None])[-1]
|
||||
self._port = parsed_url.port or options.get("port", [None])[-1]
|
||||
self._dbname = parsed_url.path[1:] or options.get("dbname", [None])[-1]
|
||||
self._username = parsed_url.username
|
||||
self._password = parsed_url.password
|
||||
|
||||
def _start(self):
|
||||
self._conn = psycopg2.connect(host=self._host,
|
||||
port=self._port,
|
||||
user=self._username,
|
||||
password=self._password,
|
||||
database=self._dbname)
|
||||
|
||||
def _stop(self):
|
||||
self._conn.close()
|
||||
|
||||
def get_lock(self, name):
|
||||
return PostgresLock(name, self._conn)
|
||||
|
||||
@staticmethod
|
||||
def watch_join_group(group_id, callback):
|
||||
raise tooz.NotImplemented
|
||||
|
||||
@staticmethod
|
||||
def unwatch_join_group(group_id, callback):
|
||||
raise tooz.NotImplemented
|
||||
|
||||
@staticmethod
|
||||
def watch_leave_group(group_id, callback):
|
||||
raise tooz.NotImplemented
|
||||
|
||||
@staticmethod
|
||||
def unwatch_leave_group(group_id, callback):
|
||||
raise tooz.NotImplemented
|
||||
|
||||
@staticmethod
|
||||
def watch_elected_as_leader(group_id, callback):
|
||||
raise tooz.NotImplemented
|
||||
|
||||
@staticmethod
|
||||
def unwatch_elected_as_leader(group_id, callback):
|
||||
raise tooz.NotImplemented
|
|
@ -13,6 +13,7 @@
|
|||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
import os
|
||||
import time
|
||||
import uuid
|
||||
|
||||
|
@ -33,6 +34,7 @@ class TestAPI(testscenarios.TestWithScenarios,
|
|||
('memcached', {'url': 'memcached://?timeout=5'}),
|
||||
('ipc', {'url': 'ipc://'}),
|
||||
('redis', {'url': 'redis://localhost:6379?timeout=5'}),
|
||||
('postgresql', {'url': os.getenv("TOOZ_TEST_PGSQL_URL")}),
|
||||
]
|
||||
|
||||
# Only certain drivers have the tested support for timeouts that we test
|
||||
|
@ -61,6 +63,8 @@ class TestAPI(testscenarios.TestWithScenarios,
|
|||
|
||||
def setUp(self):
|
||||
super(TestAPI, self).setUp()
|
||||
if self.url is None:
|
||||
self.skipTest("No URL set for this driver")
|
||||
self.group_id = self._get_random_uuid()
|
||||
self.member_id = self._get_random_uuid()
|
||||
self._coord = tooz.coordination.get_coordinator(self.url,
|
||||
|
|
13
tox.ini
13
tox.ini
|
@ -69,6 +69,19 @@ deps = {[testenv:py34]deps}
|
|||
basepython = python3.4
|
||||
commands = {toxinidir}/setup-memcached-env.sh python setup.py testr --slowest --testr-args="{posargs}"
|
||||
|
||||
[testenv:py27-postgresql]
|
||||
commands = {toxinidir}/setup-postgresql-env.sh python setup.py testr --slowest --testr-args="{posargs}"
|
||||
|
||||
[testenv:py33-postgresql]
|
||||
deps = {[testenv:py33]deps}
|
||||
basepython = python3.3
|
||||
commands = {toxinidir}/setup-postgresql-env.sh python setup.py testr --slowest --testr-args="{posargs}"
|
||||
|
||||
[testenv:py34-postgresql]
|
||||
deps = {[testenv:py34]deps}
|
||||
basepython = python3.4
|
||||
commands = {toxinidir}/setup-postgresql-env.sh python setup.py testr --slowest --testr-args="{posargs}"
|
||||
|
||||
[testenv:cover]
|
||||
commands = python setup.py testr --slowest --coverage --testr-args="{posargs}"
|
||||
|
||||
|
|
Loading…
Reference in New Issue