123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325 |
- # -*- coding: utf-8 -*-
- """
- Test utility methods that communicate with SMB shares.
- """
- from __future__ import absolute_import
- import getpass
- import logging
- import os
- import signal
- import subprocess
- import tempfile
- import time
- import salt.utils.files
- import salt.utils.network
- import salt.utils.path
- import salt.utils.smb
- from tests.support.case import TestCase
- from tests.support.unit import skipIf
- log = logging.getLogger(__name__)
- CONFIG = (
- "[global]\n"
- "realm = saltstack.com\n"
- "interfaces = lo 127.0.0.0/8\n"
- "smb ports = 1445\n"
- "log level = 2\n"
- "map to guest = Bad User\n"
- "enable core files = no\n"
- "passdb backend = smbpasswd\n"
- "smb passwd file = {passwdb}\n"
- "lock directory = {samba_dir}\n"
- "state directory = {samba_dir}\n"
- "cache directory = {samba_dir}\n"
- "pid directory = {samba_dir}\n"
- "private dir = {samba_dir}\n"
- "ncalrpc dir = {samba_dir}\n"
- "socket options = IPTOS_LOWDELAY TCP_NODELAY\n"
- "min receivefile size = 0\n"
- "write cache size = 0\n"
- "client ntlmv2 auth = no\n"
- "client min protocol = SMB3_11\n"
- "client plaintext auth = no\n"
- "\n"
- "[public]\n"
- "path = {public_dir}\n"
- "read only = no\n"
- "guest ok = no\n"
- "writeable = yes\n"
- "force user = {user}\n"
- )
- TBE = (
- "{}:0:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:AC8E657F8"
- "3DF82BEEA5D43BDAF7800CC:[U ]:LCT-507C14C7:"
- )
- IPV6_ENABLED = bool(salt.utils.network.ip_addrs6(include_loopback=True))
- def which_smbd():
- """
- Find the smbd executable and cache the result if it exits.
- """
- if hasattr(which_smbd, "cached_result"):
- return which_smbd.cached_result
- smbd = salt.utils.path.which("smbd")
- if smbd:
- which_smbd.cached_result = smbd
- return smbd
- @skipIf(not which_smbd(), reason="smbd binary not found")
- @skipIf(
- not salt.utils.smb.HAS_SMBPROTOCOL, '"smbprotocol" needs to be installed.',
- )
- class TestSmb(TestCase):
- _smbd = None
- @staticmethod
- def check_pid(pid):
- try:
- os.kill(pid, 0)
- except OSError:
- return False
- else:
- return True
- @classmethod
- def setUpClass(cls):
- tmpdir = tempfile.mkdtemp()
- cls.samba_dir = os.path.join(tmpdir, "samba")
- cls.public_dir = os.path.join(tmpdir, "public")
- os.makedirs(cls.samba_dir)
- os.makedirs(cls.public_dir)
- os.chmod(cls.samba_dir, 0o775)
- os.chmod(cls.public_dir, 0o775)
- passwdb = os.path.join(tmpdir, "passwdb")
- cls.username = getpass.getuser()
- with salt.utils.files.fopen(passwdb, "w") as fp:
- fp.write(TBE.format(cls.username))
- samba_conf = os.path.join(tmpdir, "smb.conf")
- with salt.utils.files.fopen(samba_conf, "w") as fp:
- fp.write(
- CONFIG.format(
- samba_dir=cls.samba_dir,
- public_dir=cls.public_dir,
- passwdb=passwdb,
- user=cls.username,
- )
- )
- cls._smbd = subprocess.Popen(
- "{0} -FS -P0 -s {1}".format(which_smbd(), samba_conf), shell=True
- )
- time.sleep(1)
- pidfile = os.path.join(cls.samba_dir, "smbd.pid")
- with salt.utils.files.fopen(pidfile, "r") as fp:
- cls._pid = int(fp.read().strip())
- if not cls.check_pid(cls._pid):
- raise Exception("Unable to locate smbd's pid file")
- @classmethod
- def tearDownClass(cls):
- log.warning("teardown")
- os.kill(cls._pid, signal.SIGTERM)
- def test_write_file_ipv4(self):
- """
- Transfer a file over SMB
- """
- name = "test_write_file_v4.txt"
- content = "write test file content ipv4"
- share_path = os.path.join(self.public_dir, name)
- assert not os.path.exists(share_path)
- local_path = tempfile.mktemp()
- with salt.utils.files.fopen(local_path, "w") as fp:
- fp.write(content)
- conn = salt.utils.smb.get_conn("127.0.0.1", self.username, "foo", port=1445)
- salt.utils.smb.put_file(local_path, name, "public", conn=conn)
- conn.close()
- assert os.path.exists(share_path)
- with salt.utils.files.fopen(share_path, "r") as fp:
- result = fp.read()
- assert result == content
- @skipIf(not IPV6_ENABLED, "IPv6 not enabled")
- def test_write_file_ipv6(self):
- """
- Transfer a file over SMB
- """
- name = "test_write_file_v6.txt"
- content = "write test file content ipv6"
- share_path = os.path.join(self.public_dir, name)
- assert not os.path.exists(share_path)
- local_path = tempfile.mktemp()
- with salt.utils.files.fopen(local_path, "w") as fp:
- fp.write(content)
- conn = salt.utils.smb.get_conn("::1", self.username, "foo", port=1445)
- salt.utils.smb.put_file(local_path, name, "public", conn=conn)
- conn.close()
- assert os.path.exists(share_path)
- with salt.utils.files.fopen(share_path, "r") as fp:
- result = fp.read()
- assert result == content
- def test_write_str_v4(self):
- """
- Write a string to a file over SMB
- """
- name = "test_write_str.txt"
- content = "write test file content"
- share_path = os.path.join(self.public_dir, name)
- assert not os.path.exists(share_path)
- conn = salt.utils.smb.get_conn("127.0.0.1", self.username, "foo", port=1445)
- salt.utils.smb.put_str(content, name, "public", conn=conn)
- conn.close()
- assert os.path.exists(share_path)
- with salt.utils.files.fopen(share_path, "r") as fp:
- result = fp.read()
- assert result == content
- @skipIf(not IPV6_ENABLED, "IPv6 not enabled")
- def test_write_str_v6(self):
- """
- Write a string to a file over SMB
- """
- name = "test_write_str_v6.txt"
- content = "write test file content"
- share_path = os.path.join(self.public_dir, name)
- assert not os.path.exists(share_path)
- conn = salt.utils.smb.get_conn("::1", self.username, "foo", port=1445)
- salt.utils.smb.put_str(content, name, "public", conn=conn)
- conn.close()
- assert os.path.exists(share_path)
- with salt.utils.files.fopen(share_path, "r") as fp:
- result = fp.read()
- assert result == content
- def test_delete_file_v4(self):
- """
- Validate deletion of files over SMB
- """
- name = "test_delete_file.txt"
- content = "read test file content"
- share_path = os.path.join(self.public_dir, name)
- with salt.utils.files.fopen(share_path, "w") as fp:
- fp.write(content)
- assert os.path.exists(share_path)
- conn = salt.utils.smb.get_conn("127.0.0.1", self.username, "foo", port=1445)
- salt.utils.smb.delete_file(name, "public", conn=conn)
- conn.close()
- assert not os.path.exists(share_path)
- @skipIf(not IPV6_ENABLED, "IPv6 not enabled")
- def test_delete_file_v6(self):
- """
- Validate deletion of files over SMB
- """
- name = "test_delete_file_v6.txt"
- content = "read test file content"
- share_path = os.path.join(self.public_dir, name)
- with salt.utils.files.fopen(share_path, "w") as fp:
- fp.write(content)
- assert os.path.exists(share_path)
- conn = salt.utils.smb.get_conn("::1", self.username, "foo", port=1445)
- salt.utils.smb.delete_file(name, "public", conn=conn)
- conn.close()
- assert not os.path.exists(share_path)
- def test_mkdirs_v4(self):
- """
- Create directories over SMB
- """
- dir_name = "mkdirs/test"
- share_path = os.path.join(self.public_dir, dir_name)
- assert not os.path.exists(share_path)
- conn = salt.utils.smb.get_conn("127.0.0.1", self.username, "foo", port=1445)
- salt.utils.smb.mkdirs(dir_name, "public", conn=conn)
- conn.close()
- assert os.path.exists(share_path)
- @skipIf(not IPV6_ENABLED, "IPv6 not enabled")
- def test_mkdirs_v6(self):
- """
- Create directories over SMB
- """
- dir_name = "mkdirs/testv6"
- share_path = os.path.join(self.public_dir, dir_name)
- assert not os.path.exists(share_path)
- conn = salt.utils.smb.get_conn("::1", self.username, "foo", port=1445)
- salt.utils.smb.mkdirs(dir_name, "public", conn=conn)
- conn.close()
- assert os.path.exists(share_path)
- def test_delete_dirs_v4(self):
- """
- Validate deletion of directoreies over SMB
- """
- dir_name = "deldirs"
- subdir_name = "deldirs/test"
- local_path = os.path.join(self.public_dir, subdir_name)
- os.makedirs(local_path)
- assert os.path.exists(local_path)
- conn = salt.utils.smb.get_conn("127.0.0.1", self.username, "foo", port=1445)
- salt.utils.smb.delete_directory(subdir_name, "public", conn=conn)
- conn.close()
- conn = salt.utils.smb.get_conn("127.0.0.1", self.username, "foo", port=1445)
- salt.utils.smb.delete_directory(dir_name, "public", conn=conn)
- conn.close()
- assert not os.path.exists(local_path)
- assert not os.path.exists(os.path.join(self.public_dir, dir_name))
- @skipIf(not IPV6_ENABLED, "IPv6 not enabled")
- def test_delete_dirs_v6(self):
- """
- Validate deletion of directoreies over SMB
- """
- dir_name = "deldirsv6"
- subdir_name = "deldirsv6/test"
- local_path = os.path.join(self.public_dir, subdir_name)
- os.makedirs(local_path)
- assert os.path.exists(local_path)
- conn = salt.utils.smb.get_conn("::1", self.username, "foo", port=1445)
- salt.utils.smb.delete_directory(subdir_name, "public", conn=conn)
- conn.close()
- conn = salt.utils.smb.get_conn("::1", self.username, "foo", port=1445)
- salt.utils.smb.delete_directory(dir_name, "public", conn=conn)
- conn.close()
- assert not os.path.exists(local_path)
- assert not os.path.exists(os.path.join(self.public_dir, dir_name))
- def test_connection(self):
- """
- Validate creation of an SMB connection
- """
- conn = salt.utils.smb.get_conn("127.0.0.1", self.username, "foo", port=1445)
- conn.close()
- @skipIf(not IPV6_ENABLED, "IPv6 not enabled")
- def test_connection_v6(self):
- """
- Validate creation of an SMB connection
- """
- conn = salt.utils.smb.get_conn("::1", self.username, "foo", port=1445)
- conn.close()
|