forked from tarantool/tarantool
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add test/lib/ for python modules. Create the first module that implements admin connection. Automatically read host and port and pidfile from tarantool configuration file, and thus remove them from suite.ini. Change .gitignore and remove a too broad ignore mask (it ignored __init__.py, which is mandatory file name for a module in python). Fix a bug in config reader for tarantool that would leave "box.pid" in quotes. Move TestSuite and Test to a lib/ module. Patch cmdline.py and ./admin.py to read input in line-buffered fashion (used to be block-buffered), regardless of whether input is a terminal or a pipe. This allows to work with these tools interactively.
- Loading branch information
Showing
10 changed files
with
422 additions
and
344 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,66 @@ | |||
__author__ = "Konstantin Osipov <kostja.osipov@gmail.com>" | |||
|
|||
# Redistribution and use in source and binary forms, with or without | |||
# modification, are permitted provided that the following conditions | |||
# are met: | |||
# 1. Redistributions of source code must retain the above copyright | |||
# notice, this list of conditions and the following disclaimer. | |||
# 2. Redistributions in binary form must reproduce the above copyright | |||
# notice, this list of conditions and the following disclaimer in the | |||
# documentation and/or other materials provided with the distribution. | |||
# | |||
# THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||
# ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE | |||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
# SUCH DAMAGE. | |||
|
|||
import socket | |||
import sys | |||
import string | |||
|
|||
class Connection: | |||
def __init__(self, host, port): | |||
self.host = host | |||
self.port = port | |||
self.is_connected = False | |||
|
|||
def connect(self): | |||
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | |||
self.socket.connect((self.host, self.port)) | |||
self.is_connected = True | |||
|
|||
def disconnect(self): | |||
if self.is_connected: | |||
self.socket.close() | |||
self.is_connected = False | |||
|
|||
def execute(self, command): | |||
self.socket.sendall(command) | |||
|
|||
bufsiz = 4096 | |||
res = "" | |||
|
|||
while True: | |||
buf = self.socket.recv(bufsiz) | |||
if not buf: | |||
break | |||
res+= buf; | |||
if res.rfind("---\n"): | |||
break | |||
|
|||
return res | |||
|
|||
def __enter__(self): | |||
self.connect() | |||
return self | |||
|
|||
def __exit__(self, type, value, tb): | |||
self.disconnect() | |||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,124 @@ | |||
import os | |||
import stat | |||
import shutil | |||
import subprocess | |||
import pexpect | |||
import sys | |||
import signal | |||
import time | |||
|
|||
class TarantoolSilverboxServer: | |||
"""Server represents a single server instance. Normally, the | |||
program operates with only one server, but in future we may add | |||
replication slaves. The server is started once at the beginning | |||
of each suite, and stopped at the end.""" | |||
|
|||
def __init__(self, args, config, pidfile): | |||
"""Set server options: path to configuration file, pid file, exe, etc.""" | |||
self.args = args | |||
self.path_to_config = config | |||
self.path_to_pidfile = os.path.join(args.vardir, pidfile) | |||
self.path_to_exe = None | |||
self.abspath_to_exe = None | |||
self.is_started = False | |||
|
|||
def start(self): | |||
"""Start server instance: check if the old one exists, kill it | |||
if necessary, create necessary directories and files, start | |||
the server. The server working directory is taken from 'vardir', | |||
specified in the prgoram options. | |||
Currently this is implemented for tarantool_silverbox only.""" | |||
|
|||
if not self.is_started: | |||
print "Starting the server..." | |||
|
|||
if self.path_to_exe == None: | |||
self.path_to_exe = self.find_exe() | |||
self.abspath_to_exe = os.path.abspath(self.path_to_exe) | |||
|
|||
print " Found executable at " + self.path_to_exe + "." | |||
|
|||
print " Creating and populating working directory in " +\ | |||
self.args.vardir + "..." | |||
|
|||
if os.access(self.args.vardir, os.F_OK): | |||
print " Found old vardir, deleting..." | |||
self.kill_old_server() | |||
shutil.rmtree(self.args.vardir, ignore_errors = True) | |||
|
|||
os.mkdir(self.args.vardir) | |||
shutil.copy(self.path_to_config, self.args.vardir) | |||
|
|||
subprocess.check_call([self.abspath_to_exe, "--init_storage"], | |||
cwd = self.args.vardir, | |||
# catch stdout/stderr to not clutter output | |||
stdout = subprocess.PIPE, | |||
stderr = subprocess.PIPE) | |||
|
|||
if self.args.start_and_exit: | |||
subprocess.check_call([self.abspath_to_exe, "--daemonize"], | |||
cwd = self.args.vardir, | |||
stdout = subprocess.PIPE, | |||
stderr = subprocess.PIPE) | |||
else: | |||
self.server = pexpect.spawn(self.abspath_to_exe, | |||
cwd = self.args.vardir) | |||
self.logfile_read = sys.stdout | |||
self.server.expect_exact("entering event loop") | |||
|
|||
version = subprocess.Popen([self.abspath_to_exe, "--version"], | |||
cwd = self.args.vardir, | |||
stdout = subprocess.PIPE).stdout.read().rstrip() | |||
|
|||
print "Started {0} {1}.".format(os.path.basename(self.abspath_to_exe), | |||
version) | |||
|
|||
# Set is_started flag, to nicely support cleanup during an exception. | |||
self.is_started = True | |||
else: | |||
print "The server is already started." | |||
|
|||
def stop(self): | |||
"""Stop server instance. Do nothing if the server is not started, | |||
to properly shut down the server in case of an exception during | |||
start up.""" | |||
if self.is_started: | |||
print "Stopping the server..." | |||
self.server.terminate() | |||
self.server.expect(pexpect.EOF) | |||
self.is_started = False | |||
else: | |||
print "The server is not started." | |||
|
|||
def find_exe(self): | |||
"""Locate server executable in the bindir. We just take | |||
the first thing looking like an exe in there.""" | |||
|
|||
if (os.access(self.args.bindir, os.F_OK) == False or | |||
stat.S_ISDIR(os.stat(self.args.bindir).st_mode) == False): | |||
raise TestRunException("Directory " + self.args.bindir + | |||
" doesn't exist") | |||
|
|||
for f in os.listdir(self.args.bindir): | |||
f = os.path.join(self.args.bindir, f) | |||
st_mode = os.stat(f).st_mode | |||
if stat.S_ISREG(st_mode) and st_mode & stat.S_IXUSR: | |||
return f | |||
raise TestRunException("Can't find server executable in " + | |||
self.args.bindir) | |||
|
|||
def kill_old_server(self): | |||
"""Kill old server instance if it exists.""" | |||
if os.access(self.path_to_pidfile, os.F_OK) == False: | |||
return # Nothing to do | |||
pid = 0 | |||
with open(self.path_to_pidfile) as f: | |||
pid = int(f.read()) | |||
print " Found old server, pid {0}, killing...".format(pid) | |||
try: | |||
os.kill(pid, signal.SIGTERM) | |||
while os.kill(pid, 0) != -1: | |||
time.sleep(0.01) | |||
except OSError: | |||
pass | |||
|
Oops, something went wrong.