Skip to content

Commit 2c2d2c5

Browse files
author
v.shepard
committed
PBCKP-588 test fix test_restore_after_failover
1 parent 72e6d5d commit 2c2d2c5

File tree

5 files changed

+74
-61
lines changed

5 files changed

+74
-61
lines changed

testgres/node.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -625,9 +625,11 @@ def status(self):
625625
"-D", self.data_dir,
626626
"status"
627627
] # yapf: disable
628-
out = execute_utility(_params, self.utils_log_file)
629-
if 'no server running' in out:
628+
status_code, out, err = execute_utility(_params, self.utils_log_file, verbose=True)
629+
if 'does not exist' in err:
630630
return NodeStatus.Uninitialized
631+
elif'no server running' in out:
632+
return NodeStatus.Stopped
631633
return NodeStatus.Running
632634

633635
except ExecUtilException as e:
@@ -712,14 +714,17 @@ def start(self, params=[], wait=True):
712714
] + params # yapf: disable
713715

714716
try:
715-
execute_utility(_params, self.utils_log_file)
717+
exit_status, out, error = execute_utility(_params, self.utils_log_file, verbose=True)
718+
if 'does not exist' in error:
719+
raise Exception
720+
if 'server started' in out:
721+
self.is_started = True
716722
except Exception as e:
717723
msg = 'Cannot start node'
718724
files = self._collect_special_files()
719725
raise_from(StartNodeException(msg, files), e)
720726

721727
self._maybe_start_logger()
722-
self.is_started = True
723728
return self
724729

725730
def stop(self, params=[], wait=True):

testgres/operations/local_ops.py

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ def exec_command(self, cmd, wait_exit=False, verbose=False,
5252
:return: The output of the subprocess.
5353
"""
5454
if isinstance(cmd, list):
55-
cmd = " ".join(cmd)
55+
cmd = ' '.join(item.decode('utf-8') if isinstance(item, bytes) else item for item in cmd)
5656
log.debug(f"Executing command: `{cmd}`")
5757

5858
if os.name == 'nt':
@@ -98,8 +98,7 @@ def exec_command(self, cmd, wait_exit=False, verbose=False,
9898

9999
# Environment setup
100100
def environ(self, var_name):
101-
cmd = f"echo ${var_name}"
102-
return self.exec_command(cmd, encoding='utf-8').strip()
101+
return os.environ.get(var_name)
103102

104103
def find_executable(self, executable):
105104
return find_executable(executable)
@@ -108,17 +107,6 @@ def is_executable(self, file):
108107
# Check if the file is executable
109108
return os.access(file, os.X_OK)
110109

111-
def add_to_path(self, new_path):
112-
pathsep = self.pathsep
113-
# Check if the directory is already in PATH
114-
path = self.environ("PATH")
115-
if new_path not in path.split(pathsep):
116-
if self.remote:
117-
self.exec_command(f"export PATH={new_path}{pathsep}{path}")
118-
else:
119-
os.environ["PATH"] = f"{new_path}{pathsep}{path}"
120-
return pathsep
121-
122110
def set_env(self, var_name, var_val):
123111
# Check if the directory is already in PATH
124112
os.environ[var_name] = var_val
@@ -128,8 +116,7 @@ def get_user(self):
128116
return getpass.getuser()
129117

130118
def get_name(self):
131-
cmd = 'python3 -c "import os; print(os.name)"'
132-
return self.exec_command(cmd).strip()
119+
return os.name
133120

134121
# Work with dirs
135122
def makedirs(self, path, remove_existing=False):

testgres/operations/os_ops.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,6 @@ def is_executable(self, file):
2929
# Check if the file is executable
3030
raise NotImplementedError()
3131

32-
def add_to_path(self, new_path):
33-
raise NotImplementedError()
34-
3532
def set_env(self, var_name, var_val):
3633
# Check if the directory is already in PATH
3734
raise NotImplementedError()

testgres/operations/remote_ops.py

Lines changed: 52 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,22 @@
2020
error_markers = [b'error', b'Permission denied']
2121

2222

23+
class PsUtilProcessProxy:
24+
def __init__(self, ssh, pid):
25+
self.ssh = ssh
26+
self.pid = pid
27+
28+
def kill(self):
29+
command = f"kill {self.pid}"
30+
self.ssh.exec_command(command)
31+
32+
def cmdline(self):
33+
command = f"ps -p {self.pid} -o cmd --no-headers"
34+
stdin, stdout, stderr = self.ssh.exec_command(command)
35+
cmdline = stdout.read().decode('utf-8').strip()
36+
return cmdline.split()
37+
38+
2339
class RemoteOperations(OsOperations):
2440
def __init__(self, host="127.0.0.1", hostname='localhost', port=None, ssh_key=None, username=None):
2541
super().__init__(username)
@@ -71,7 +87,7 @@ def exec_command(self, cmd: str, wait_exit=False, verbose=False, expect_error=Fa
7187
self.ssh = self.ssh_connect()
7288

7389
if isinstance(cmd, list):
74-
cmd = " ".join(cmd)
90+
cmd = ' '.join(item.decode('utf-8') if isinstance(item, bytes) else item for item in cmd)
7591
if input:
7692
stdin, stdout, stderr = self.ssh.exec_command(cmd)
7793
stdin.write(input)
@@ -140,17 +156,6 @@ def is_executable(self, file):
140156
is_exec = self.exec_command(f"test -x {file} && echo OK")
141157
return is_exec == b"OK\n"
142158

143-
def add_to_path(self, new_path):
144-
pathsep = self.pathsep
145-
# Check if the directory is already in PATH
146-
path = self.environ("PATH")
147-
if new_path not in path.split(pathsep):
148-
if self.remote:
149-
self.exec_command(f"export PATH={new_path}{pathsep}{path}")
150-
else:
151-
os.environ["PATH"] = f"{new_path}{pathsep}{path}"
152-
return pathsep
153-
154159
def set_env(self, var_name: str, var_val: str):
155160
"""
156161
Set the value of an environment variable.
@@ -243,9 +248,17 @@ def mkdtemp(self, prefix=None):
243248
raise ExecUtilException("Could not create temporary directory.")
244249

245250
def mkstemp(self, prefix=None):
246-
cmd = f"mktemp {prefix}XXXXXX"
247-
filename = self.exec_command(cmd).strip()
248-
return filename
251+
if prefix:
252+
temp_dir = self.exec_command(f"mktemp {prefix}XXXXX", encoding='utf-8')
253+
else:
254+
temp_dir = self.exec_command("mktemp", encoding='utf-8')
255+
256+
if temp_dir:
257+
if not os.path.isabs(temp_dir):
258+
temp_dir = os.path.join('/home', self.username, temp_dir.strip())
259+
return temp_dir
260+
else:
261+
raise ExecUtilException("Could not create temporary directory.")
249262

250263
def copytree(self, src, dst):
251264
if not os.path.isabs(dst):
@@ -291,7 +304,7 @@ def write(self, filename, data, truncate=False, binary=False, read_and_write=Fal
291304
data = data.encode(encoding)
292305
if isinstance(data, list):
293306
# ensure each line ends with a newline
294-
data = [s if s.endswith('\n') else s + '\n' for s in data]
307+
data = [(s if isinstance(s, str) else s.decode('utf-8')).rstrip('\n') + '\n' for s in data]
295308
tmp_file.writelines(data)
296309
else:
297310
tmp_file.write(data)
@@ -351,8 +364,8 @@ def isfile(self, remote_file):
351364

352365
def isdir(self, dirname):
353366
cmd = f"if [ -d {dirname} ]; then echo True; else echo False; fi"
354-
response = self.exec_command(cmd, encoding='utf-8')
355-
return response.strip() == "True"
367+
response = self.exec_command(cmd)
368+
return response.strip() == b"True"
356369

357370
def remove_file(self, filename):
358371
cmd = f"rm {filename}"
@@ -366,16 +379,16 @@ def kill(self, pid, signal):
366379

367380
def get_pid(self):
368381
# Get current process id
369-
return self.exec_command("echo $$")
382+
return int(self.exec_command("echo $$", encoding='utf-8'))
370383

371384
def get_remote_children(self, pid):
372385
command = f"pgrep -P {pid}"
373386
stdin, stdout, stderr = self.ssh.exec_command(command)
374387
children = stdout.readlines()
375-
return [int(child_pid.strip()) for child_pid in children]
388+
return [PsUtilProcessProxy(self.ssh, int(child_pid.strip())) for child_pid in children]
376389

377390
# Database control
378-
def db_connect(self, dbname, user, password=None, host="127.0.0.1", port=5432):
391+
def db_connect(self, dbname, user, password=None, host="127.0.0.1", port=5432, ssh_key=None):
379392
"""
380393
Connects to a PostgreSQL database on the remote system.
381394
Args:
@@ -389,19 +402,26 @@ def db_connect(self, dbname, user, password=None, host="127.0.0.1", port=5432):
389402
This function establishes a connection to a PostgreSQL database on the remote system using the specified
390403
parameters. It returns a connection object that can be used to interact with the database.
391404
"""
392-
with sshtunnel.open_tunnel(
393-
(host, 22), # Remote server IP and SSH port
394-
ssh_username=self.username,
395-
ssh_pkey=self.ssh_key,
396-
remote_bind_address=(host, port), # PostgreSQL server IP and PostgreSQL port
397-
local_bind_address=('localhost', port), # Local machine IP and available port
398-
):
405+
tunnel = sshtunnel.open_tunnel(
406+
(host, 22), # Remote server IP and SSH port
407+
ssh_username=user or self.username,
408+
ssh_pkey=ssh_key or self.ssh_key,
409+
remote_bind_address=(host, port), # PostgreSQL server IP and PostgreSQL port
410+
local_bind_address=('localhost', port) # Local machine IP and available port
411+
)
412+
413+
tunnel.start()
414+
415+
try:
399416
conn = pglib.connect(
400-
host=host,
401-
port=port,
417+
host=host, # change to 'localhost' because we're connecting through a local ssh tunnel
418+
port=tunnel.local_bind_port, # use the local bind port set up by the tunnel
402419
dbname=dbname,
403-
user=user,
420+
user=user or self.username,
404421
password=password
405422
)
406423

407-
return conn
424+
return conn
425+
except Exception as e:
426+
tunnel.stop()
427+
raise e

testgres/utils.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ def release_port(port):
4545
bound_ports.discard(port)
4646

4747

48-
def execute_utility(args, logfile=None):
48+
def execute_utility(args, logfile=None, verbose=False):
4949
"""
5050
Execute utility (pg_ctl, pg_dump etc).
5151
@@ -56,24 +56,28 @@ def execute_utility(args, logfile=None):
5656
Returns:
5757
stdout of executed utility.
5858
"""
59-
command = u' '.join(args)
60-
exit_status, out, error = tconf.os_ops.exec_command(command, verbose=True)
59+
exit_status, out, error = tconf.os_ops.exec_command(args, verbose=True)
6160
# decode result
6261
out = '' if not out else out
6362
if isinstance(out, bytes):
6463
out = out.decode('utf-8')
64+
if isinstance(error, bytes):
65+
error = error.decode('utf-8')
6566

6667
# write new log entry if possible
6768
if logfile:
6869
try:
69-
tconf.os_ops.write(filename=logfile, data=command, truncate=True)
70+
tconf.os_ops.write(filename=logfile, data=args, truncate=True)
7071
if out:
7172
# comment-out lines
7273
lines = [u'\n'] + ['# ' + line for line in out.splitlines()] + [u'\n']
7374
tconf.os_ops.write(filename=logfile, data=lines)
7475
except IOError:
75-
log.warn(f"Problem with writing to logfile `{logfile}` during run command `{command}`")
76-
return out
76+
log.warn(f"Problem with writing to logfile `{logfile}` during run command `{args}`")
77+
if verbose:
78+
return exit_status, out, error
79+
else:
80+
return out
7781

7882

7983
def get_bin_path(filename):

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy