1from __future__ import print_function
2
3import sys
4import os
5import random
6import string
7import time
8
9from .tarantool_admin import TarantoolAdmin
10
11
12# a time during which try to acquire a lock
13AWAIT_TIME = 60  # seconds
14
15# on which port bind a socket for binary protocol
16BINARY_PORT = 3301
17
18
19def get_random_string():
20    return ''.join(random.choice(string.ascii_lowercase) for _ in range(16))
21
22
23class RemoteTarantoolServer(object):
24    def __init__(self):
25        self.host = os.environ['REMOTE_TARANTOOL_HOST']
26
27        self.args = {}
28        self.args['primary'] = BINARY_PORT
29        self.args['admin'] = os.environ['REMOTE_TARANTOOL_CONSOLE_PORT']
30
31        assert(self.args['primary'] != self.args['admin'])
32
33        # a name to using for a lock
34        self.whoami = get_random_string()
35
36        self.admin = TarantoolAdmin(self.host, self.args['admin'])
37        self.lock_is_acquired = False
38
39        # emulate stopped server
40        self.acquire_lock()
41        self.admin.execute('box.cfg{listen = box.NULL}')
42
43    def acquire_lock(self):
44        deadline = time.time() + AWAIT_TIME
45        while True:
46            res = self.admin.execute('return acquire_lock("%s")' % self.whoami)
47            ok = res[0]
48            err = res[1] if not ok else None
49            if ok:
50                break
51            if time.time() > deadline:
52                raise RuntimeError('can not acquire "%s" lock: %s' % (
53                    self.whoami, str(err)))
54            print('waiting to acquire "%s" lock' % self.whoami,
55                  file=sys.stderr)
56            time.sleep(1)
57        self.lock_is_acquired = True
58
59    def touch_lock(self):
60        assert(self.lock_is_acquired)
61        res = self.admin.execute('return touch_lock("%s")' % self.whoami)
62        ok = res[0]
63        err = res[1] if not ok else None
64        if not ok:
65            raise RuntimeError('can not update "%s" lock: %s' % (
66                self.whoami, str(err)))
67
68    def release_lock(self):
69        res = self.admin.execute('return release_lock("%s")' % self.whoami)
70        ok = res[0]
71        err = res[1] if not ok else None
72        if not ok:
73            raise RuntimeError('can not release "%s" lock: %s' % (
74                self.whoami, str(err)))
75        self.lock_is_acquired = False
76
77    def start(self):
78        if not self.lock_is_acquired:
79            self.acquire_lock()
80        self.admin.execute('box.cfg{listen = "0.0.0.0:%s"}' %
81                           self.args['primary'])
82
83    def stop(self):
84        self.admin.execute('box.cfg{listen = box.NULL}')
85        self.release_lock()
86
87    def is_started(self):
88        return self.lock_is_acquired
89
90    def clean(self):
91        pass
92
93    def __del__(self):
94        self.admin.disconnect()
95