Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit eb74ae0

Browse files
committed
network recovery tests infrastructure. #6
1 parent 29cc931 commit eb74ae0

10 files changed

+538
-0
lines changed

contrib/mmts/tests2/.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.blockade
2+
.vagrant
3+
*.swp
4+
*.pyc

contrib/mmts/tests2/Dockerfile

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# vim:set ft=dockerfile:
2+
FROM debian:jessie
3+
4+
# explicitly set user/group IDs
5+
RUN groupadd -r postgres --gid=999 && useradd -r -g postgres --uid=999 postgres
6+
7+
# make the "en_US.UTF-8" locale so postgres will be utf-8 enabled by default
8+
RUN apt-get update && apt-get install -y locales && rm -rf /var/lib/apt/lists/* \
9+
&& localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8
10+
ENV LANG en_US.utf8
11+
12+
# use git to fetch sources
13+
RUN apt-get update \
14+
&& apt-get install -y git \
15+
&& rm -rf /var/lib/apt/lists/*
16+
17+
# postgres build deps
18+
RUN apt-get update && apt-get install -y \
19+
make \
20+
gcc \
21+
libreadline-dev \
22+
bison \
23+
flex \
24+
zlib1g-dev \
25+
&& rm -rf /var/lib/apt/lists/*
26+
27+
RUN mkdir /pg
28+
RUN chown postgres:postgres /pg
29+
30+
USER postgres
31+
WORKDIR /pg
32+
ENV CFLAGS -O0
33+
RUN git clone https://github.com/postgrespro/postgres_cluster.git --depth 1
34+
WORKDIR /pg/postgres_cluster
35+
RUN ./configure --enable-cassert --enable-debug --prefix=/usr/local/
36+
RUN make -j 4
37+
38+
USER root
39+
RUN make install
40+
RUN cd /pg/postgres_cluster/contrib/pg_tsdtm && make install
41+
RUN cd /pg/postgres_cluster/contrib/raftable && make install
42+
RUN cd /pg/postgres_cluster/contrib/mmts && make install
43+
RUN cd /pg/postgres_cluster/contrib/postgres_fdw && make install
44+
RUN mkdir -p /var/lib/postgresql/data && chown -R postgres /var/lib/postgresql/data
45+
RUN mkdir -p /run/postgresql && chown -R postgres /run/postgresql
46+
47+
USER postgres
48+
ENV PATH /usr/local/bin:$PATH
49+
ENV PGDATA /var/lib/postgresql/data
50+
VOLUME /var/lib/postgresql/data
51+
52+
COPY docker-entrypoint.sh /
53+
54+
ENTRYPOINT ["/docker-entrypoint.sh"]
55+
56+
EXPOSE 5432
57+
CMD ["postgres"]
58+
59+
60+

contrib/mmts/tests2/Vagrantfile

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
script = <<SCRIPT
2+
#!/bin/bash -e
3+
4+
if [ ! -f /etc/default/docker ]; then
5+
echo "/etc/default/docker not found -- is docker installed?" >&2
6+
exit 1
7+
fi
8+
9+
apt-get -y install python-pip python-virtualenv
10+
apt-get -y install postgresql-server-dev-all python-dev
11+
12+
cd /vagrant
13+
14+
export PIP_DOWNLOAD_CACHE=/vagrant/.pip_download_cache
15+
16+
SCRIPT
17+
18+
Vagrant.configure(2) do |config|
19+
20+
config.vm.box = "ubuntu/trusty64"
21+
22+
if Vagrant.has_plugin?("vagrant-cachier")
23+
config.cache.scope = :box
24+
end
25+
26+
config.vm.provider :virtualbox do |vb, override|
27+
vb.memory = 2048
28+
end
29+
30+
# there are obviously vagrant versions with a
31+
# broken 'docker' provisioner that can be fixed
32+
# by invoking an 'apt-get update' *before* docker itself
33+
config.vm.provision "shell", inline: "apt-get update"
34+
35+
# fetch the ubuntu:latest image that is required for
36+
# the test suite
37+
config.vm.provision "docker", images: ["ubuntu:trusty"]
38+
39+
# kick off the tests automatically
40+
config.vm.provision "shell", inline: script
41+
end
42+

contrib/mmts/tests2/blockade.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
version: '2'
2+
3+
containers:
4+
5+
node1:
6+
container_name: node1
7+
image: pgmmts
8+
environment:
9+
POSTGRES_USER: 'postgres'
10+
NODE_ID: 1
11+
ports:
12+
5432: 5432
13+
14+
node2:
15+
container_name: node2
16+
image: pgmmts
17+
environment:
18+
POSTGRES_USER: 'postgres'
19+
NODE_ID: 2
20+
ports:
21+
5433: 5432
22+
23+
node3:
24+
container_name: node3
25+
image: pgmmts
26+
environment:
27+
POSTGRES_USER: 'postgres'
28+
NODE_ID: 3
29+
ports:
30+
5434: 5432
31+
32+
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
#!/bin/bash
2+
set -e
3+
4+
# wtf is that?
5+
if [ "${1:0:1}" = '-' ]; then
6+
set -- postgres "$@"
7+
fi
8+
9+
if [ "$1" = 'postgres' ]; then
10+
mkdir -p "$PGDATA"
11+
chmod 700 "$PGDATA"
12+
chown -R postgres "$PGDATA"
13+
14+
# look specifically for PG_VERSION, as it is expected in the DB dir
15+
if [ ! -s "$PGDATA/PG_VERSION" ]; then
16+
initdb
17+
18+
if [ "$POSTGRES_PASSWORD" ]; then
19+
pass="PASSWORD '$POSTGRES_PASSWORD'"
20+
authMethod=md5
21+
else
22+
pass=
23+
authMethod=trust
24+
fi
25+
26+
{ echo; echo "host all all 0.0.0.0/0 $authMethod"; } >> "$PGDATA/pg_hba.conf"
27+
{ echo; echo "host replication all 0.0.0.0/0 $authMethod"; } >> "$PGDATA/pg_hba.conf"
28+
29+
############################################################################
30+
31+
# internal start of server in order to allow set-up using psql-client
32+
# does not listen on TCP/IP and waits until start finishes
33+
pg_ctl -D "$PGDATA" \
34+
-o "-c listen_addresses=''" \
35+
-w start
36+
37+
: ${POSTGRES_USER:=postgres}
38+
: ${POSTGRES_DB:=$POSTGRES_USER}
39+
export POSTGRES_USER POSTGRES_DB
40+
41+
psql=( psql -v ON_ERROR_STOP=1 )
42+
43+
if [ "$POSTGRES_DB" != 'postgres' ]; then
44+
"${psql[@]}" --username postgres <<-EOSQL
45+
CREATE DATABASE "$POSTGRES_DB" ;
46+
EOSQL
47+
echo
48+
fi
49+
50+
if [ "$POSTGRES_USER" = 'postgres' ]; then
51+
op='ALTER'
52+
else
53+
op='CREATE'
54+
fi
55+
"${psql[@]}" --username postgres <<-EOSQL
56+
$op USER "$POSTGRES_USER" WITH SUPERUSER $pass ;
57+
EOSQL
58+
echo
59+
60+
############################################################################
61+
62+
CONNSTRS='dbname=postgres host=node1, dbname=postgres host=node2, dbname=postgres host=node3'
63+
RAFT_PEERS='1:172.18.0.2:6666, 2:172.18.0.4:6666, 3:172.18.0.3:6666'
64+
65+
cat <<-EOF >> $PGDATA/postgresql.conf
66+
listen_addresses='*'
67+
max_prepared_transactions = 100
68+
synchronous_commit = off
69+
wal_level = logical
70+
max_worker_processes = 15
71+
max_replication_slots = 10
72+
max_wal_senders = 10
73+
shared_preload_libraries = 'raftable,multimaster'
74+
raftable.id = $NODE_ID
75+
raftable.peers = '$RAFT_PEERS'
76+
multimaster.workers=4
77+
multimaster.use_raftable=true
78+
multimaster.queue_size=52857600
79+
multimaster.ignore_tables_without_pk=1
80+
multimaster.node_id = $NODE_ID
81+
multimaster.conn_strings = '$CONNSTRS'
82+
EOF
83+
84+
tail -n 20 $PGDATA/postgresql.conf
85+
86+
pg_ctl -D "$PGDATA" -m fast -w stop
87+
88+
echo
89+
echo 'PostgreSQL init process complete; ready for start up.'
90+
echo
91+
fi
92+
fi
93+
94+
exec "$@"
95+

contrib/mmts/tests2/lib/__init__.py

Whitespace-only changes.
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
import psycopg2
2+
import random
3+
from multiprocessing import Process, Value, Queue
4+
import time
5+
from event_history import *
6+
7+
class ClientCollection(object):
8+
def __init__(self, connstrs):
9+
self._clients = []
10+
11+
for cs in connstrs:
12+
b = BankClient(cs)
13+
self._clients.append(b)
14+
# glob_clients.append(b)
15+
16+
self._clients[0].initialize()
17+
18+
@property
19+
def clients(self):
20+
return self._clients
21+
22+
def __getitem__(self, index):
23+
return self._clients[index]
24+
25+
def start(self):
26+
for client in self._clients:
27+
client.start()
28+
29+
def stop(self):
30+
for client in self._clients:
31+
client.stop()
32+
# client.cleanup()
33+
34+
35+
class BankClient(object):
36+
37+
def __init__(self, connstr):
38+
self.connstr = connstr
39+
self.run = Value('b', True)
40+
self._history = EventHistory()
41+
self.accounts = 10000
42+
43+
def initialize(self):
44+
# initialize database
45+
conn = psycopg2.connect(self.connstr)
46+
cur = conn.cursor()
47+
cur.execute('create extension if not exists multimaster')
48+
conn.commit()
49+
50+
cur.execute('create table bank_test(uid int primary key, amount int)')
51+
52+
cur.execute('''
53+
insert into bank_test
54+
select *, 0 from generate_series(0, %s)''',
55+
(self.accounts,))
56+
conn.commit()
57+
cur.close()
58+
conn.close()
59+
60+
@property
61+
def history(self):
62+
return self._history
63+
64+
def check_total(self):
65+
conn = psycopg2.connect(self.connstr)
66+
cur = conn.cursor();
67+
while self.run.value:
68+
cur.execute('select sum(amount) from bank_test')
69+
res = cur.fetchone()
70+
if res[0] != 0:
71+
print("Isolation error, total = %d" % (res[0],))
72+
raise BaseException #
73+
74+
cur.close()
75+
conn.close()
76+
77+
def transfer_money(self):
78+
print(self.connstr)
79+
conn = psycopg2.connect(self.connstr)
80+
cur = conn.cursor()
81+
82+
i = 0
83+
while self.run.value:
84+
i += 1
85+
amount = 1
86+
from_uid = random.randrange(1, self.accounts + 1)
87+
to_uid = random.randrange(1, self.accounts + 1)
88+
89+
event_id = self.history.register_start('tx')
90+
91+
#cur.execute('begin')
92+
cur.execute('''update bank_test
93+
set amount = amount - %s
94+
where uid = %s''',
95+
(amount, from_uid))
96+
cur.execute('''update bank_test
97+
set amount = amount + %s
98+
where uid = %s''',
99+
(amount, to_uid))
100+
#cur.execute('commit')
101+
102+
try:
103+
conn.commit()
104+
except:
105+
self.history.register_finish(event_id, 'rollback')
106+
else:
107+
self.history.register_finish(event_id, 'commit')
108+
109+
#print("T", i)
110+
111+
cur.close()
112+
conn.close()
113+
114+
def watchdog(self):
115+
while self.run.value:
116+
time.sleep(1)
117+
print('watchdog: ', self.history.aggregate())
118+
119+
def start(self):
120+
self.transfer_process = Process(target=self.transfer_money, args=())
121+
self.transfer_process.start()
122+
123+
self.total_process = Process(target=self.check_total, args=())
124+
self.total_process.start()
125+
126+
self.total_process = Process(target=self.watchdog, args=())
127+
self.total_process.start()
128+
129+
130+
return
131+
132+
def stop(self):
133+
self.run.value = False
134+
# self.total_process.join()
135+
# self.transfer_process.join()
136+
return
137+
138+
def cleanup(self):
139+
conn = psycopg2.connect(self.connstr)
140+
cur = conn.cursor()
141+
cur.execute('drop table bank_test')
142+
conn.commit()
143+
cur.close()
144+
conn.close()
145+
146+
147+

0 commit comments

Comments
 (0)