summaryrefslogtreecommitdiff
path: root/client/utils/cluster.py
blob: 0efdb8b1a30d5078b1549860f2535bbfd7c6c762 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
import os
import shutil
import time

from multiprocessing import cpu_count, Process, Queue
from subprocess import call, STDOUT
from tempfile import TemporaryFile
from utils.logging import log


class PgCluster(object):
    'basic manipulation of postgres cluster (init, start, stop, destroy)'

    def __init__(self, outdir, bin_path, data_path):
        self._outdir = outdir
        self._bin = bin_path
        self._data = data_path

        self._env = os.environ
        self._env['PATH'] = ':'.join([bin_path, self._env['PATH']])

        self._options = ""

    def _initdb(self):
        'initialize the data directory'

        with TemporaryFile() as strout:
            log("initializing cluster into '%s'" % (self._data,))
            call(['pg_ctl', '-D', self._data, 'init'], env=self._env,
                 stdout=strout, stderr=STDOUT)

    def _configure(self, config):
        'build options list to use with pg_ctl'

        for k in config:
            self._options += ''.join([" -c ", k, "='", str(config[k]), "'"])

    def _destroy(self):
        """
        forced cleanup of possibly existing cluster processes and data
        directory
        """

        with TemporaryFile() as strout:
            log("killing all existing postgres processes")
            call(['killall', 'postgres'], stdout=strout, stderr=STDOUT)

        # remove the data directory
        if os.path.exists(self._data):
            shutil.rmtree(self._data)

    def start(self, config, destroy=True):
        'init, configure and start the cluster'

        # cleanup any previous cluster running, remove data dir if it exists
        if destroy:
            self._destroy()

        self._initdb()
        self._configure(config)

        with TemporaryFile() as strout:
            log("starting cluster in '%s' using '%s' binaries" %
                (self._data, self._bin))
            cmd = ['pg_ctl', '-D', self._data, '-l',
                   ''.join([self._outdir, '/pg.log']), '-w']
            if len(self._options) > 0:
                cmd.extend(['-o', self._options])
            cmd.append('start')
            call(cmd, env=self._env, stdout=strout, stderr=STDOUT)

    def stop(self, destroy=True):
        'stop the cluster'

        with TemporaryFile() as strout:
            log("stopping cluster in '%s' using '%s' binaries" %
                (self._data, self._bin))
            call(['pg_ctl', '-D', self._data, '-w', '-t', '60', 'stop'],
                 env=self._env, stdout=strout, stderr=STDOUT)

        # kill any remaining processes, remove the data dir
        if destroy:
            self._destroy()