Skip to content

Commit 03af8fe

Browse files
committed
testhelper: introduce class SMBClient
We use the python module pysmbc to access the SMB server. The helper class hides the complexities and helps us bypass the smbclient binary to connect to the remote samba server giving us more flexibility in the python tests. Signed-off-by: Sachin Prabhu <sprabhu@redhat.com>
1 parent 62170d1 commit 03af8fe

File tree

5 files changed

+89
-84
lines changed

5 files changed

+89
-84
lines changed

testcases/consistency/test_consistency.py

Lines changed: 35 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -7,72 +7,52 @@
77
# ip addresses).
88

99
import testhelper
10+
from testhelper import SMBClient
1011
import os
1112
import pytest
1213
import typing
13-
from pathlib import Path
14-
1514

1615
test_string = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
1716
test_info_file = os.getenv("TEST_INFO_FILE")
1817
test_info = testhelper.read_yaml(test_info_file)
1918

2019

21-
def file_content_check(f: typing.IO, comp_str: str) -> bool:
22-
read_data = f.read()
23-
return read_data == comp_str
24-
25-
26-
def consistency_check(mount_point: Path, ipaddr: str, share_name: str) -> None:
20+
def consistency_check(hostname: str, share_name: str) -> None:
2721
mount_params = testhelper.get_mount_parameters(test_info, share_name)
28-
mount_params["host"] = ipaddr
29-
try:
30-
test_file = testhelper.get_tmp_file(mount_point)
31-
test_file_resp = test_file.with_suffix(".resp")
32-
test_file_remote = "test-" + ipaddr + "." + share_name
33-
with open(test_file, "w") as f:
34-
f.write(test_string)
35-
put_cmds = "put %s %s" % (test_file, test_file_remote)
36-
(ret, output) = testhelper.smbclient(mount_params, put_cmds)
37-
assert ret == 0, "Failed to copy file to server"
38-
39-
# The file read cycle
40-
get_cmds = "get %s %s; rm %s" % (
41-
test_file_remote,
42-
test_file_resp,
43-
test_file_remote,
44-
)
45-
(ret, output) = testhelper.smbclient(mount_params, get_cmds)
46-
assert ret == 0, "Failed to copy file from server"
47-
with open(test_file_resp, "r") as f:
48-
assert file_content_check(
49-
f, test_string
50-
), "File content does not match"
51-
finally:
52-
if test_file.exists():
53-
test_file.unlink()
54-
if test_file_resp.exists():
55-
test_file_resp.unlink()
56-
57-
58-
def generate_consistency_check(
59-
test_info_file: dict,
60-
) -> typing.List[typing.Tuple[str, str]]:
61-
if not test_info_file:
62-
return []
22+
test_filename = "/test_consistency"
23+
24+
# file write cycle
25+
scon = SMBClient(
26+
hostname,
27+
share_name,
28+
mount_params["username"],
29+
mount_params["password"],
30+
)
31+
scon.simple_write(test_filename, test_string)
32+
del scon
33+
34+
# file read cycle
35+
scon = SMBClient(
36+
hostname,
37+
share_name,
38+
mount_params["username"],
39+
mount_params["password"],
40+
)
41+
retstr = scon.simple_read(test_filename)
42+
scon.unlink(test_filename)
43+
del scon
44+
45+
assert retstr == test_string, "File content does not match"
46+
47+
48+
def generate_consistency_check() -> typing.List[typing.Tuple[str, str]]:
6349
arr = []
64-
for share in testhelper.get_exported_shares(test_info):
65-
s = testhelper.get_share(test_info, share)
66-
arr.append((s["server"], s["name"]))
50+
for sharename in testhelper.get_exported_shares(test_info):
51+
share = testhelper.get_share(test_info, sharename)
52+
arr.append((share["server"], share["name"]))
6753
return arr
6854

6955

70-
@pytest.mark.parametrize(
71-
"ipaddr,share_name", generate_consistency_check(test_info)
72-
)
73-
def test_consistency(ipaddr: str, share_name: str) -> None:
74-
tmp_root = testhelper.get_tmp_root()
75-
mount_point = testhelper.get_tmp_mount_point(tmp_root)
76-
consistency_check(mount_point, ipaddr, share_name)
77-
os.rmdir(mount_point)
78-
os.rmdir(tmp_root)
56+
@pytest.mark.parametrize("hostname,share_name", generate_consistency_check())
57+
def test_consistency(hostname: str, share_name: str) -> None:
58+
consistency_check(hostname, share_name)

testhelper/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
from .testhelper import * # noqa: F401, F403
22
from .cmdhelper import * # noqa: F401, F403
33
from .fshelper import * # noqa: F401, F403
4+
from .smbclient import * # noqa: F401, F403

testhelper/cmdhelper.py

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -63,35 +63,6 @@ def cifs_umount(mount_point: Path) -> int:
6363
return ret
6464

6565

66-
def smbclient(
67-
mount_params: typing.Dict[str, str], cmds: str
68-
) -> typing.Tuple[int, str]:
69-
"""Run the following command on smbclient and return the output.
70-
71-
Parameters:
72-
mount_params: Dict containing the mount parameters.
73-
cmds: String containg the ';' separated commands to run.
74-
75-
Returns:
76-
int: Return value from the shell execution
77-
string: stdout
78-
"""
79-
smbclient_cmd = [
80-
"smbclient",
81-
"--user=%s%%%s" % (mount_params["username"], mount_params["password"]),
82-
"//%s/%s" % (mount_params["host"], mount_params["share"]),
83-
"-c",
84-
cmds,
85-
]
86-
ret = subprocess.run(
87-
smbclient_cmd,
88-
universal_newlines=True,
89-
stdout=subprocess.PIPE,
90-
stderr=subprocess.STDOUT,
91-
)
92-
return (ret.returncode, ret.stdout)
93-
94-
9566
def check_cmds(cmds: typing.List[str]) -> Path:
9667
"""Return first file path which exists.
9768

testhelper/smbclient.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import smbc # type: ignore
2+
import typing
3+
import os
4+
5+
6+
class SMBClient:
7+
"""Use pysmbc to access the SMB server"""
8+
9+
def __init__(self, hostname: str, share: str, username: str, passwd: str):
10+
self.server = hostname
11+
self.share = share
12+
self.username = username
13+
self.password = passwd
14+
self.rooturi = f"smb://{self.server}/{self.share}"
15+
16+
def auth_cb(se, sh, w, u, p):
17+
return (w, self.username, self.password)
18+
19+
self.ctx = smbc.Context(auth_fn=auth_cb)
20+
21+
def readdir(self, path: str = "/") -> typing.List:
22+
uri = self.rooturi + path
23+
d = self.ctx.opendir(uri)
24+
return d.getdents()
25+
26+
def open(
27+
self, path: str, flags: int = os.O_RDWR, mode: int = 0o644
28+
) -> typing.Any:
29+
uri = self.rooturi + path
30+
return self.ctx.open(uri, flags)
31+
32+
def mkdir(self, dpath: str) -> None:
33+
self.ctx.mkdir(self.rooturi + dpath)
34+
35+
def rmdir(self, dpath: str) -> None:
36+
self.ctx.rmdir(self.rooturi + dpath)
37+
38+
def unlink(self, fpath: str) -> None:
39+
self.ctx.unlink(self.rooturi + fpath)
40+
41+
def simple_write(self, fpath: str, teststr: str) -> None:
42+
f = self.open(fpath, os.O_WRONLY | os.O_CREAT)
43+
f.write(teststr)
44+
f.close()
45+
46+
def simple_read(self, fpath: str) -> str:
47+
f = self.open(fpath)
48+
str = f.read()
49+
f.close()
50+
return str.decode("ascii")

tox.ini

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ deps =
1313
pyyaml
1414
pytest-randomly
1515
iso8601
16+
pysmbc
1617
commands = pytest -vrfEsxXpP testcases/
1718

1819
[testenv:pytest-unprivileged]
@@ -21,6 +22,7 @@ deps =
2122
pyyaml
2223
pytest-randomly
2324
iso8601
25+
pysmbc
2426
commands = pytest -vrfEsxXpP -k 'not privileged' testcases/
2527

2628
[testenv:sanity]
@@ -29,6 +31,7 @@ deps =
2931
pyyaml
3032
pytest-randomly
3133
iso8601
34+
pysmbc
3235
changedir = {toxinidir}
3336
commands = pytest -vrfEsxXpP testcases/consistency
3437

0 commit comments

Comments
 (0)