{"id":350972,"date":"2023-07-29T15:02:06","date_gmt":"2023-07-29T15:02:06","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=350972"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=350972","title":{"rendered":"<span>\u0422\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e NAS. \u0427\u0430\u0441\u0442\u044c 2. \u0411\u0430\u0437\u0430<\/span>"},"content":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0412 <a href=\"https:\/\/habr.com\/ru\/companies\/3rdman\/articles\/746178\/\">\u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0435<\/a> \u043c\u044b \u0444\u043e\u0440\u043c\u0443\u043b\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u0446\u0435\u043b\u0438 \u0438 \u0441\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u043b\u0438 \u0441\u043f\u0438\u0441\u043e\u043a \u0442\u0435\u0441\u0442\u043e\u0432 \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438. \u0414\u0430\u043b\u0435\u0435 \u0432 \u0440\u0430\u0431\u043e\u0442\u0435 QA \u043e\u0431\u044b\u0447\u043d\u043e \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0431\u0430\u0437\u043e\u0432\u044b\u0445 \u0442\u0435\u0441\u0442\u043e\u0432 \u0438 \u043e\u0431\u0432\u044f\u0437\u043a\u0438 \u0434\u043b\u044f \u043d\u0438\u0445, \u0447\u0435\u043c \u043c\u044b \u0432 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0438 \u0437\u0430\u0439\u043c\u0451\u043c\u0441\u044f. \u041f\u043e\u043b\u043d\u044b\u0439 \u043a\u043e\u0434 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043b\u0435\u0436\u0438\u0442 \u043d\u0430 <a href=\"https:\/\/github.com\/ThirdManTeam\/regular_nas_tests\">\u0433\u0438\u0442\u0445\u0430\u0431 <\/a>\u0438 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442\u044c \u0435\u0433\u043e \u0432 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u043d\u0435 \u0431\u0443\u0434\u0435\u043c. <\/p>\n<h2>\u041d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0442\u0435\u0441\u0442\u044b<\/h2>\n<p>\u041d\u0443 \u0447\u0442\u043e \u0436\u0435, \u043f\u0440\u0438\u0448\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430. \u0417\u0434\u0435\u0441\u044c \u044f \u043e\u043f\u0438\u0448\u0443 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0442\u0435\u0441\u0442\u043e\u0432 \u0434\u043b\u044f FTP.\u00a0 \u0418 \u0442\u0430\u043a &#8212; \u0432\u043e\u0442 \u043a\u043e\u0434 \u0442\u0435\u0441\u0442\u0430:<\/p>\n<pre><code>class TestFTP:      def test_ftp_10MB_file_upload(self, ftp, perfmeter, test_name, ssh, target_dir):         file_data = get_file_with_size_mb(10)         md5sum_source = get_md5sum(file_data)          file_name = PurePath('test_ftp_file_10MB.bin')         source_file = PurePath('\/tmp') \/ file_name          with open(source_file, 'wb') as fh:             fh.write(file_data)             fh.close()          with open(source_file, 'rb') as fh:             ftp.cwd(CFG['FTP']['PATH'])             logging.info(f\"Current path: {ftp.pwd()}\")             logging.info(f\"List before operation: {list(ftp.mlsd())}\")             perfmeter.estimate_func(test_name, ftp.storbinary, f\"STOR {file_name}\", fh)             logging.info(f\"List after operation: {list(ftp.mlsd())}\")          md5sum_target = ssh.md5sum(target_dir \/ file_name)         assert md5sum_source == md5sum_target<\/code><\/pre>\n<p>\u041e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043d\u0430 \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u0438 \u0442\u0435\u0441\u0442\u0430 \u0438 \u0432\u044b\u0437\u043e\u0432\u0430\u0445 \u0444\u0438\u043a\u0441\u0442\u0443\u0440 \u043c\u044b \u043d\u0435 \u0431\u0443\u0434\u0435\u043c, \u0440\u0430\u0437\u0431\u0435\u0440\u0451\u043c \u0438\u0445 \u043f\u043e \u043c\u0435\u0440\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u0442\u0435\u0441\u0442\u0435.<\/p>\n<p>\u0421\u043f\u0435\u0440\u0432\u0430 \u043c\u044b \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u0444\u0430\u0439\u043b \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u043c\u0435\u0440\u0430:<\/p>\n<pre><code>file_data = get_file_with_size_mb(10) md5sum_source = get_md5sum(file_data)<\/code><\/pre>\n<p>\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u201c<em>os.urandom(size*1024*1024)<\/em>\u201d, \u0438 \u0442\u0443\u0442 \u0436\u0435 \u0441\u0447\u0438\u0442\u0430\u0435\u043c md5 \u0441\u0443\u043c\u043c\u0443, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u043f\u043e\u0437\u0436\u0435 \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0441\u0442\u0438 \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<p>\u0414\u043b\u044f \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0447\u0435\u0440\u0435\u0437 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0443\u044e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 ftplib \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0444\u0430\u0439\u043b \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e:<\/p>\n<pre><code>file_name = PurePath('test_ftp_file_10MB.bin') source_file = PurePath('\/tmp') \/ file_name  with open(source_file, 'wb') as fh:     fh.write(file_data)     fh.close()<\/code><\/pre>\n<p>\u0418 \u0437\u0430\u0442\u0435\u043c \u043a\u043b\u0430\u0434\u0451\u043c \u044d\u0442\u043e\u0442 \u0444\u0430\u0439\u043b \u043d\u0430 NAS \u043f\u043e FTP:<\/p>\n<pre><code>with open(source_file, 'rb') as fh:     ftp.cwd(CFG['FTP']['PATH'])     logging.info(f\"Current path: {ftp.pwd()}\")     logging.info(f\"List before operation: {list(ftp.mlsd())}\")     perfmeter.estimate_func(test_name, ftp.storbinary, f\"STOR {file_name}\", fh)     logging.info(f\"List after operation: {list(ftp.mlsd())}\") <\/code><\/pre>\n<p>\u0418 \u044d\u0442\u043e, \u043f\u043e \u0441\u0443\u0442\u0438, \u0433\u043b\u0430\u0432\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u0442\u0435\u0441\u0442\u0430.<\/p>\n<p>\u041e\u0431\u044a\u0435\u043a\u0442 <em>ftp<\/em> \u0438\u0437 \u201c<em>ftp.cwd(CFG[&#8216;FTP&#8217;][&#8216;PATH&#8217;])<\/em>\u201d \u0441\u043e\u0437\u0434\u0430\u0451\u0442\u0441\u044f \u0444\u0438\u043a\u0441\u0442\u0443\u0440\u043e\u0439 <em>ftp<\/em>:<\/p>\n<pre><code>@pytest.fixture(scope=\"session\") def ftp():     ftpcon = FTP(CFG['FTP']['ADDRESS'])     ftpcon.login(user=CFG['FTP']['LOGIN'], passwd=CFG['FTP']['PASSWD'])     logging.info(\"FTP Welcome message:\" + ftpcon.getwelcome())     yield ftpcon     ftpcon.quit()<\/code><\/pre>\n<p>\u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f scope=&#187;session&#187; ftp \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u0436\u0438\u0442\u044c \u0432\u0435\u0441\u044c \u043f\u0440\u043e\u0433\u043e\u043d \u0442\u0435\u0441\u0442\u043e\u0432, \u0430 \u043f\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0438 \u0442\u0435\u0441\u0442\u043e\u0432 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u0437\u0430\u043a\u0440\u043e\u0435\u0442 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435.<\/p>\n<p>\u0414\u043b\u044f \u0438\u0437\u043c\u0435\u0440\u0435\u043d\u0438\u044f \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c <em>perfmeter<\/em> \u0432 \u0441\u0442\u0440\u043e\u043a\u0435 \u201c<em>perfmeter.estimate_func(test_name, ftp.storbinary, f&#187;STOR {file_name}&#187;, fh)<\/em>\u201d. <\/p>\n<pre><code>class PerformaceMeter:     def __init__(self):         self._init_db_connection(CFG['DIAGNOSTIC']['PERF_STAT_DB']) \u2026     def estimate_func(self, test_name, func, *args):         start_time = time.time()         func(*args)         end_time = time.time()         func_time = end_time - start_time         logging.info(f\"Test {test_name} - {func_time}\")          self._db_cur.execute(\"insert into OperationTime values (?, ?, ?, ?)\",             (test_name, start_time, end_time, 0))         self._db_con.commit()<\/code><\/pre>\n<p>\u041e\u0431\u044a\u0435\u043a\u0442 <em>perfmeter<\/em> \u043a\u043b\u0430\u0441\u0441\u0430 <em>PerformasnceMeter<\/em> \u0441\u043e\u0437\u0434\u0430\u0451\u0442\u0441\u044f \u0442\u043e\u0436\u0435 \u0444\u0438\u043a\u0441\u0442\u0443\u0440\u043e\u0439 \u0434\u043b\u044f \u0441\u043a\u043e\u0443\u043f\u0430 session. \u0412\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u043c\u044b \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u043c \u043a\u0430\u043a \u0440\u0430\u0437\u043d\u0438\u0446\u0443 \u043c\u0435\u0436\u0434\u0443 end_time \u0438 start_time, \u0442\u0430\u043a \u043a\u0430\u043a \u0432\u044b\u0441\u043e\u043a\u043e\u0439 \u0442\u043e\u0447\u043d\u043e\u0441\u0442\u0438 \u043d\u0430\u043c \u0442\u0443\u0442 \u0438 \u043d\u0435 \u043d\u0443\u0436\u043d\u043e. \u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0441\u0440\u0430\u0437\u0443 \u043f\u0438\u0448\u0435\u043c \u0432 \u0431\u0430\u0437\u0443.<\/p>\n<p>\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u0448\u0430\u0433\u043e\u043c \u043c\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0441\u0442\u044c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<pre><code>md5sum_target = ssh.md5sum(target_dir \/ file_name) assert md5sum_source == md5sum_target<\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c \u043e\u0431\u044a\u0435\u043a\u0442 <em>ssh<\/em> \u043a\u043b\u0430\u0441\u0441\u0430 <em>SSH_Client<\/em> &#8212; \u044d\u0442\u043e \u043e\u0431\u0451\u0440\u0442\u043a\u0430 \u043d\u0430\u0434 <em>paramiko.SSHClient<\/em>. \u0412 \u043d\u0451\u043c \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f ssh \u0441\u0435\u0441\u0441\u0438\u044f:<\/p>\n<pre><code>class SSH_Client:      def __init__(self):         self._client = paramiko.SSHClient()         self._client.set_missing_host_key_policy(paramiko.AutoAddPolicy())      def connect(self, hostname, username, password=None):         if password:             logging.info(f\"ssh {username}@{hostname} with password {password}\") # security :)             self._client.connect(                 hostname=hostname, username=username, password=password)         else:             logging.info(f\"ssh {username}@{hostname} without password\")             self._client.connect(hostname=hostname, username=username)          self._sftp = self._client.open_sftp()<\/code><\/pre>\n<p>\u0438 \u0441\u0434\u0435\u043b\u0430\u043d\u044b \u043c\u0435\u0442\u043e\u0434\u044b \u0434\u043b\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0445 \u043a\u043e\u043c\u0430\u043d\u0434 \u0438 \u043f\u0430\u0440\u0441\u0438\u043d\u0433\u0430 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430:<\/p>\n<pre><code>    def exec(self, cmd):         logging.debug(f\"exec$ {cmd}\")         stdin, stdout, stderr = self._client.exec_command(cmd, get_pty=True)         stdin.close()          out = stdout.readlines()         out_text = ''.join(out)         logging.debug(f\"STDOUT:\\n{out_text}\")         err = stderr.readlines()         err_text = ''.join(err)         logging.debug(f\"STDERR:\\n{err_text}\")          return out, err      def md5sum(self, path):         out, err = self.exec(f\"md5sum {path}\")         for l in out:             if re.match(r\"\\S{32} \", l):                 md5sum = l[:32]                 break         return md5sum<\/code><\/pre>\n<p>\u0422\u0430\u043a \u0447\u0442\u043e, \u0443\u043f\u0440\u043e\u0449\u0451\u043d\u043d\u043e \u0433\u043e\u0432\u043e\u0440\u044f, \u043c\u044b \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 \u0442\u0435\u0441\u0442\u0430 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u043c\u0435\u0440\u0430 \u0438 \u0441\u043d\u0438\u043c\u0430\u0435\u043c \u0441 \u043d\u0435\u0433\u043e md5 \u0441\u0443\u043c\u043c\u0443, \u043a\u043e\u043f\u0438\u0440\u0443\u0435\u043c \u0444\u0430\u0439\u043b \u043d\u0430 \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440, \u0437\u0430\u0441\u0435\u043a\u0430\u044f \u0432\u0440\u0435\u043c\u044f \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c\u0441\u044f \u0442\u0443\u0434\u0430 \u043f\u043e ssh, \u0441\u043d\u0438\u043c\u0430\u0435\u043c md5 \u0441\u0443\u043c\u043c\u0443 \u0434\u043b\u044f \u0444\u0430\u0439\u043b\u0430 \u0438 \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0435\u043c \u0438\u0445.<\/p>\n<p>\u041f\u043e\u0434\u043e\u0431\u043d\u044b\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043c\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c \u0438 \u0441 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430\u043c\u0438. \u041f\u043e \u0438\u0442\u043e\u0433\u0443 \u043c\u044b \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0432 \u0431\u0430\u0437\u0443 \u0432\u043d\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0441\u0442\u0438 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 (\u0438 \u044d\u0442\u043e \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u043e), \u043d\u043e \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u043e\u0432\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0441 \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u043c\u044b \u0441\u043c\u043e\u0436\u0435\u043c \u043f\u0440\u043e\u0432\u0435\u0441\u0442\u0438 \u0434\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u043a\u0443.<\/p>\n<h2>\u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0442\u0435\u0441\u0442\u044b<\/h2>\n<p>\u041f\u0440\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0442\u0435\u0441\u0442\u043e\u0432 \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u043f\u0435\u0440\u0435\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u044b. \u0410 \u0438\u043c\u0435\u043d\u043d\u043e &#8212; \u043c\u044b \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u0432 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0434\u0438\u0441\u043a\u043e\u0432, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 WebDAV.<\/p>\n<h3>\u0422\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0434\u0438\u0441\u043a\u043e\u0432<\/h3>\n<p>\u041f\u0440\u043e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0434\u0438\u0441\u043a\u043e\u0432 \u0435\u0441\u0442\u044c \u043e\u0442\u043b\u0438\u0447\u043d\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f \u043d\u0430 \u0425\u0430\u0431\u0440\u0435: <a href=\"https:\/\/habr.com\/ru\/articles\/154235\/\"><u>https:\/\/habr.com\/ru\/articles\/154235\/<\/u><\/a>. \u041c\u044b \u0436\u0435, \u043f\u0440\u043e\u0430\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0432 \u0437\u0430\u0434\u0430\u0447\u0443, \u0440\u0435\u0448\u0438\u043b\u0438 \u0432\u044b\u043d\u0435\u0441\u0442\u0438 \u0434\u0430\u043d\u043d\u044b\u0439 \u0432\u0438\u0434 \u0442\u0435\u0441\u0442\u043e\u0432 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u043a. \u0421\u0442\u0440\u043e\u0433\u043e \u0433\u043e\u0432\u043e\u0440\u044f, \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0431\u043e\u0440 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0439 \u0434\u043b\u044f fio. \u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0442\u0435\u0441\u0442\u043e\u0432 \u0431\u0443\u0434\u0443\u0442 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u0432\u0440\u0443\u0447\u043d\u0443\u044e. \u041f\u0440\u0438\u0447\u0438\u043d \u0434\u043b\u044f \u0442\u0430\u043a\u043e\u0433\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e:<\/p>\n<ol>\n<li>\n<p>\u041c\u0435\u043d\u044f\u0442\u044c \u043c\u0435\u0442\u043e\u0434\u044b \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0434\u0438\u0441\u043a\u043e\u0432 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043d\u0435 \u0447\u0430\u0441\u0442\u043e. \u0410 \u0437\u043d\u0430\u0447\u0438\u0442 \u0438 fio \u0433\u043e\u043d\u044f\u0442\u044c \u0447\u0430\u0441\u0442\u043e \u043d\u0435 \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f.<\/p>\n<\/li>\n<li>\n<p>\u0421\u0430\u043c\u0438 \u0442\u0435\u0441\u0442\u044b \u0438\u0434\u0443\u0442 \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f. \u041c\u0435\u0448\u0430\u0442\u044c \u0438\u0445 \u0441 \u043d\u0430\u0448\u0438\u043c\u0438 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0448\u0443\u0441\u0442\u0440\u044b\u043c\u0438 \u0442\u0435\u0441\u0442\u0430\u043c\u0438 \u043d\u0435 \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0431\u044b. \u0414\u0430 \u0438 \u0441\u043c\u044b\u0441\u043b\u0430 \u0432 \u044d\u0442\u043e\u043c \u043d\u0435 \u043c\u043d\u043e\u0433\u043e.<\/p>\n<\/li>\n<\/ol>\n<p>\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u044d\u0442\u0443 \u0442\u0435\u043c\u0443 \u043f\u043e\u0441\u0442\u0430\u0440\u0430\u0435\u043c\u0441\u044f \u0440\u0430\u0441\u043a\u0440\u044b\u0442\u044c \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0441\u0442\u0430\u0442\u044c\u044f\u0445.<\/p>\n<h3>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 WebDAV<\/h3>\n<p>\u041f\u043e \u0437\u0430\u044f\u0432\u043a\u0430\u043c \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0445 \u043a \u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u0440\u0435\u0448\u0438\u043b\u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 \u0441\u043f\u0438\u0441\u043e\u043a \u0442\u0435\u0441\u0442\u043e\u0432 \u0438 WebDAV. \u0412 \u043a\u043e\u043d\u0446\u0435 \u043a\u043e\u043d\u0446\u043e\u0432 \u044d\u0442\u043e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435, \u0445\u043e\u0442\u044f \u0438 \u043d\u0435 \u0441\u0440\u0435\u0434\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 OMV. \u0412\u0435\u0434\u044c \u043f\u043b\u0430\u0433\u0438\u043d\u0430 \u0434\u043b\u044f \u043d\u0435\u0433\u043e \u043d\u0435\u0442\u0443 \u0434\u0430\u0436\u0435 \u0432 omv-extras (\u0442\u043e\u0447\u043d\u0435\u0435 \u0431\u044b\u043b, \u043d\u043e \u043f\u0440\u043e\u0442\u0443\u0445). \u041f\u043e\u0447\u0438\u0442\u0430\u0432 <a href=\"https:\/\/forum.openmediavault.org\/index.php?thread\/43001-webdav\/\"><u>\u0444\u043e\u0440\u0443\u043c<\/u><\/a> \u043f\u0440\u0438\u043d\u044f\u043b\u0438 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043d\u0435 \u0441\u0432\u044f\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u0441 \u043f\u043b\u0430\u0433\u0438\u043d\u0430\u043c\u0438. \u0423 \u043d\u0430\u0441 \u043e\u0441\u0442\u0430\u0451\u0442\u0441\u044f 2 \u043f\u0443\u0442\u0438:<\/p>\n<ol>\n<li>\n<p>\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c WebDAV \u0432 Docker, \u0447\u0442\u043e \u0438 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e\u0442 \u043d\u0430 \u0444\u043e\u0440\u0443\u043c\u0435. \u0420\u0435\u0448\u0435\u043d\u0438\u0435 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0440\u0430\u0437\u0443\u043c\u043d\u044b\u043c \u0438 \u0443\u0434\u043e\u0431\u043d\u044b\u043c, \u043d\u043e \u201c\u0437\u0430\u0433\u0440\u044f\u0437\u043d\u044f\u0435\u0442\u201d \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0442\u0435\u0441\u0442\u043e\u0432. \u0412\u0435\u0434\u044c \u043f\u043e\u043c\u0438\u043c\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0435\u0449\u0451 \u0438 Docker. \u0414\u0430, \u0443 \u043d\u0435\u0433\u043e \u043e\u0432\u0435\u0440\u0445\u0435\u0434 \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u0431\u043e\u043b\u044c\u0448\u043e\u0439, \u043d\u043e \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442.<\/p>\n<\/li>\n<li>\n<p>\u0421\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c WebDAV \u043d\u0430\u0442\u0438\u0432\u043d\u043e \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0435. \u042d\u0442\u043e\u0442 \u043f\u0443\u0442\u044c \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f \u043c\u043d\u0435 \u0435\u0449\u0451 \u043c\u0435\u043d\u044c\u0448\u0435, \u0442\u0430\u043a \u043a\u0430\u043a \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f \u0432\u043c\u0435\u0448\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0438, \u043e\u0442\u043b\u0430\u0436\u0435\u043d\u043d\u044b\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430\u043c\u0438 OMV. \u041f\u043e\u0441\u043b\u0435\u0434\u0441\u0442\u0432\u0438\u044f \u0442\u0430\u043a\u043e\u0433\u043e \u0432\u043c\u0435\u0448\u0430\u0442\u0435\u043b\u044c\u0441\u0442\u0432\u0430 \u0434\u043b\u044f \u043c\u0435\u043d\u044f \u043b\u0438\u0447\u043d\u043e \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u044b. \u0414\u0430 \u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c \u044d\u0442\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u0441\u043b\u043e\u0436\u043d\u0435\u0435.<\/p>\n<\/li>\n<\/ol>\n<p>\u0418\u0437 \u0434\u0432\u0443\u0445 \u0437\u043e\u043b \u0432\u044b\u0431\u0440\u0430\u043b\u0438 \u043c\u0435\u043d\u044c\u0448\u0435\u0435 \u0438 \u0431\u043e\u043b\u0435\u0435 \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u043e\u0435. \u0422\u043e \u0435\u0441\u0442\u044c \u0414\u043e\u043a\u0435\u0440.<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u0430\u043a \u043c\u044b \u043d\u0435 \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u043b\u0438 \u0434\u043e\u043a\u0435\u0440 \u043d\u0430 OMV \u0447\u0435\u0440\u0435\u0437 \u043f\u043b\u0430\u0433\u0438\u043d\u044b<\/summary>\n<div class=\"spoiler__content\">\n<p>\u041f\u043e\u043f\u044b\u0442\u043a\u0430 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043d\u043e\u0432\u044b\u0439 \u043f\u043b\u0430\u0433\u0438\u043d \u0434\u043b\u044f \u0434\u043e\u043a\u0435\u0440\u0430 \u043f\u043e <a href=\"https:\/\/forum.openmediavault.org\/index.php?thread\/48003-guide-using-the-new-docker-plugin\/\"><u>\u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438 \u0441 \u0444\u043e\u0440\u0443\u043c\u0430<\/u><\/a> \u0443\u0432\u0435\u043d\u0447\u0430\u043b\u0430\u0441\u044c \u043f\u043e\u043b\u043d\u044b\u043c \u043f\u0440\u043e\u0432\u0430\u043b\u043e\u043c:<\/p>\n<pre><code>Failed to execute command 'export PATH=\/bin:\/sbin:\/usr\/bin:\/usr\/sbin:\/usr\/local\/bin:\/usr\/local\/sbin; export LANG=C.UTF-8; export LANGUAGE=; export DEBIAN_FRONTEND=noninteractive; apt-get --yes --allow-downgrades --allow-change-held-packages --fix-missing --allow-unauthenticated --reinstall install openmediavault-compose 2>&amp;1' with exit code '100': Reading package lists...  Building dependency tree...  Reading state information...  Some packages could not be installed. This may mean that you have requested an impossible situation or if you are using the unstable distribution that some required packages have not yet been created or been moved out of Incoming. The following information may help to resolve the situation:  The following packages have unmet dependencies:  openmediavault-compose : Depends: openmediavault-sharerootfs but it is not installable E: Unable to correct problems, you have held broken packages.  OMV\\ExecException: Failed to execute command 'export PATH=\/bin:\/sbin:\/usr\/bin:\/usr\/sbin:\/usr\/local\/bin:\/usr\/local\/sbin; export LANG=C.UTF-8; export LANGUAGE=; export DEBIAN_FRONTEND=noninteractive; apt-get --yes --allow-downgrades --allow-change-held-packages --fix-missing --allow-unauthenticated --reinstall install openmediavault-compose 2>&amp;1' with exit code '100': Reading package lists...  Building dependency tree...  Reading state information...  Some packages could not be installed. This may mean that you have requested an impossible situation or if you are using the unstable distribution that some required packages have not yet been created or been moved out of Incoming. The following information may help to resolve the situation:  The following packages have unmet dependencies:  openmediavault-compose : Depends: openmediavault-sharerootfs but it is not installable E: Unable to correct problems, you have held broken packages. in \/usr\/share\/openmediavault\/engined\/rpc\/pluginmgmt.inc:247 Stack trace: #0 \/usr\/share\/php\/openmediavault\/rpc\/serviceabstract.inc(619): Engined\\Rpc\\PluginMgmt->Engined\\Rpc\\{closure}('\/tmp\/bgstatusfo...', '\/tmp\/bgoutputNb...') #1 \/usr\/share\/openmediavault\/engined\/rpc\/pluginmgmt.inc(251): OMV\\Rpc\\ServiceAbstract->execBgProc(Object(Closure)) #2 [internal function]: Engined\\Rpc\\PluginMgmt->install(Array, Array) #3 \/usr\/share\/php\/openmediavault\/rpc\/serviceabstract.inc(123): call_user_func_array(Array, Array) #4 \/usr\/share\/php\/openmediavault\/rpc\/rpc.inc(86): OMV\\Rpc\\ServiceAbstract->callMethod('install', Array, Array) #5 \/usr\/sbin\/omv-engined(537): OMV\\Rpc\\Rpc::call('Plugin', 'install', Array, Array, 1) #6 {main}<\/code><\/pre>\n<p>\u041a\u0430\u043a\u043e\u0439-\u0442\u043e \u0431\u0430\u0440\u0434\u0430\u043a \u0441 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044f\u043c\u0438. \u041d\u0430 \u0444\u043e\u0440\u0443\u043c\u0435 \u043f\u0440\u043e \u0442\u0430\u043a\u043e\u0435 <a href=\"https:\/\/forum.openmediavault.org\/index.php?thread\/48600-500-internal-sertver-error-installing-plugins\/&amp;postID=356370&amp;highlight=Depends%253A%2Bopenmediavault-sharerootfs%2Bbut%2Bit%2Bis%2Bnot%2Binstallable#post356370\"><u>\u0442\u043e\u0436\u0435 \u0441\u043b\u044b\u0448\u0430\u043b\u0438<\/u><\/a> \u0438 \u0440\u0435\u0448\u0438\u043b\u0438 \u201c\u043f\u0435\u0440\u0435\u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b\u201d. \u0412\u043e\u043e\u0431\u0449\u0435 \u0447\u0435\u043c \u043f\u043b\u043e\u0442\u043d\u0435\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u044e \u0441 OMV, \u0442\u0435\u043c \u0431\u043e\u043b\u044c\u0448\u0435 \u043f\u043e\u043d\u0438\u043c\u0430\u044e \u043f\u043e\u0437\u0438\u0446\u0438\u044e \u0442\u0435\u0445, \u043a\u0442\u043e \u0445\u043e\u0447\u0435\u0442 \u043a\u0443\u043f\u0438\u0442\u044c \u0443\u0441\u043b\u043e\u0432\u043d\u044b\u0439 Synology, \u0438 \u0447\u0442\u043e\u0431\u044b \u0443 \u043d\u0438\u0445 \u0432\u0441\u0451 \u201c\u043f\u0440\u043e\u0441\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u043b\u043e\u201d.<\/p>\n<\/div>\n<\/details>\n<p>\u041d\u0430\u0448\u0430 \u0446\u0435\u043b\u044c &#8212; \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0435, \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u043e\u0435 \u0438 \u043b\u0435\u0433\u043a\u043e \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u043c\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435. \u0412\u0437\u044f\u043b\u0438 \u0443\u0436\u0435 \u0433\u043e\u0442\u043e\u0432\u044b\u0439 \u043e\u0431\u0440\u0430\u0437 \u0441 Docker Hub: <a href=\"https:\/\/hub.docker.com\/r\/bytemark\/webdav\"><u>https:\/\/hub.docker.com\/r\/bytemark\/webdav<\/u><\/a>.\u00a0<\/p>\n<p>\u041a\u0430\u0447\u0430\u0435\u043c \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0435\u0433\u043e:<\/p>\n<pre><code>sudo docker run --restart always \\ -v \/srv\/dev-disk-by-uuid-5c2aebc7-baad-45ca-a418-703fda90f8db\/webdav:\/var\/lib\/dav \\ -e AUTH_TYPE=Digest -e USERNAME=test -e PASSWORD=test \\ --publish 8079:80 -d bytemark\/webdav<\/code><\/pre>\n<p>\u0418 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0432 \u0435\u0433\u043e \u043a\u0430\u043a \u0441\u0435\u0442\u0435\u0432\u043e\u0439 \u0434\u0438\u0441\u043a \u0432 \u041f\u0440\u043e\u0432\u043e\u0434\u043d\u0438\u043a. \u0421\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u0430\u043f\u043a\u0443 \u044f \u0432 \u043d\u0451\u043c \u043c\u043e\u0433\u0443:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/4bd\/ae3\/346\/4bdae3346602cef5c72805a95a440226.png\" width=\"830\" height=\"151\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/4bd\/ae3\/346\/4bdae3346602cef5c72805a95a440226.png\"\/><\/figure>\n<p>\u041f\u0430\u043f\u043a\u0430 \u043f\u043e\u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435:<\/p>\n<pre><code>test@ubernas-x86:\/srv\/dev-disk-by-uuid-5c2aebc7-baad-45ca-a418-703fda90f8db\/webdav\/data$ ls -l total 4 drwxrwsr-x+ 3 82 82 4096 Jul 20 05:12 webdavtestvk<\/code><\/pre>\n<p>\u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043a \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438!<\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u043d\u0435 \u0442\u0440\u0430\u0442\u0438\u0442\u044c \u0441\u0438\u043b\u044b \u043d\u0430 \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u0438\u0442\u043e\u043d\u043e\u0432\u0441\u043a\u0438\u0445 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a \u0434\u043b\u044f WebDAV, \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f \u0443\u0442\u0438\u043b\u0438\u0442\u043e\u0439 mount, \u0438 \u0431\u0443\u0434\u0435\u043c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u043e\u0439 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0435\u0439, \u043a\u0430\u043a \u0441 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0439. \u041c\u043e\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043c\u043e\u0436\u043d\u043e \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0438\u0442\u044c \u043f\u043e \u043a\u043e\u043c\u0430\u043d\u0434\u0435:<\/p>\n<pre><code>sudo mount -t davfs http:\/\/192.168.10.20:8079 \/home\/vkovalev\/webdavtest<\/code><\/pre>\n<p>\u041b\u0438\u0431\u043e \u043f\u0440\u043e\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0443\u044e \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044e \u0432 fstab \u0438 \u043f\u043e\u043b\u043e\u0436\u0438\u0442\u044c \u043a\u0440\u0435\u0434\u044b \u0432 ~\/.davfs2\/secrets.<\/p>\n<p>\u041a\u043e\u0434 \u0442\u0435\u0441\u0442\u0430 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0441\u044f \u043f\u0440\u043e\u0441\u0442\u044b\u043c \u0438 \u043b\u0430\u043a\u043e\u043d\u0438\u0447\u043d\u044b\u043c. \u0421\u043f\u0435\u0440\u0432\u0430.<\/p>\n<pre><code>def test_webdav_10MB_file_upload(self, perfmeter, test_name, target_dir_webdav, file_path_webdav, ssh):     file_data = get_file_with_size_mb(10)     md5sum_source = get_md5sum(file_data)     put_file_to_directory(file_data, file_path_webdav)     perfmeter.estimate_func(test_name, put_file_to_directory, file_data, file_path_webdav)          file_name = file_path_webdav.name     target_file = target_dir_webdav \/ file_name          md5sum_target = ssh.md5sum(target_file)     assert md5sum_source == md5sum_target<\/code><\/pre>\n<p>\u0411\u0435\u0440\u0451\u043c \u0444\u0430\u0439\u043b, \u043a\u043b\u0430\u0434\u0451\u043c \u0435\u0433\u043e \u0432 \u043f\u0440\u0438\u043c\u043e\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u0443\u044e \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e. \u041a\u0430\u043a \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0433\u043e \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0430 &#8212; \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0441\u0442\u044c \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 NAS. \u041d\u043e, \u0434\u043b\u044f \u043c\u0435\u043d\u044f \u0432\u043d\u0435\u0437\u0430\u043f\u043d\u043e, \u0442\u0435\u0441\u0442 \u043f\u0430\u0434\u0430\u0435\u0442. \u0424\u0430\u0439\u043b\u0430 \u043d\u0430 \u0442\u043e\u043c \u043a\u043e\u043d\u0446\u0435 \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u043e. \u041e\u0442\u043a\u043b\u044e\u0447\u0438\u043b \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432 \u043f\u043e\u0441\u043b\u0435 \u0442\u0435\u0441\u0442\u0430 \u0438 \u0443\u0431\u0435\u0434\u0438\u043b\u0441\u044f, \u0447\u0442\u043e \u0434\u0435\u043b\u043e \u0432\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0438 \u043e\u0442 NFS, \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0437\u0430\u043f\u0438\u0441\u0438 \u0444\u0430\u0439\u043b\u0430 \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e \u0437\u0430\u0432\u0435\u0440\u0448\u0430\u0435\u0442\u0441\u044f \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u0440\u0430\u043d\u044c\u0448\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u044d\u0442\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430 \u043d\u0430 \u0434\u0438\u0441\u043a \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 NAS. \u0418\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e, \u0430 \u0433\u0434\u0435 \u0438\u043c\u0435\u043d\u043d\u043e \u044d\u0442\u043e\u0442 \u0444\u0430\u0439\u043b \u201c\u0437\u0430\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f\u201d? \u041d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0435, \u0438\u043b\u0438 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435? \u0410 \u0435\u0449\u0451 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u043d\u0435\u0443\u0434\u043e\u0431\u043d\u044b\u0439 \u0432\u043e\u043f\u0440\u043e\u0441 &#8212; \u0430 \u0447\u0442\u043e \u0438\u043c\u0435\u043d\u043d\u043e \u043c\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043f\u043e\u0434\u043e\u0431\u043d\u044b\u043c\u0438 \u0442\u0435\u0441\u0442\u0430\u043c\u0438?<\/p>\n<p>\u0421 \u043d\u0435\u0443\u0434\u043e\u0431\u043d\u044b\u043c\u0438 \u0432\u043e\u043f\u0440\u043e\u0441\u0430\u043c\u0438 \u043f\u043e\u0437\u0436\u0435, \u0430 \u043f\u043e\u043a\u0430 \u0432\u043a\u0430\u0440\u044f\u0447\u0438\u043c \u043a\u043e\u0441\u0442\u044b\u043b\u044c, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0438\u0439 \u0442\u043e\u0447\u043d\u0435\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c \u043c\u043e\u043c\u0435\u043d\u0442 \u043f\u043e\u044f\u0432\u043b\u0435\u043d\u0438\u044f \u0444\u0430\u0439\u043b\u0430 \u043d\u0430 NAS.<\/p>\n<h3>\u041a\u043e\u0441\u0442\u044b\u043b\u0435\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0435<\/h3>\n<p>\u0421\u0443\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b &#8212; \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u0444\u0430\u0439\u043b \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u043b\u0441\u044f \u043d\u0430 NAS, \u043f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c \u0441\u0435\u043a\u0443\u043d\u0434\u043e\u043c\u0435\u0440. \u0410 \u0437\u043d\u0430\u0447\u0438\u0442 \u0432 estimate_func \u0431\u0443\u0434\u0435\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u0444\u0430\u0439\u043b\u0430 \u043d\u0430 NAS \u0447\u0435\u0440\u0435\u0437 ssh \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435. \u0414\u0430, \u044d\u0442\u043e, \u0432\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u0437\u0430\u043c\u0435\u0442\u043d\u044b\u0439 \u043e\u0432\u0435\u0440\u0445\u0435\u0434, \u0430 \u0432\u043e-\u0432\u0442\u043e\u0440\u044b\u0445 \u043f\u043e\u0440\u0442\u0438\u0442 \u043a\u043e\u043d\u0446\u0435\u043f\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043c\u0435\u0442\u043e\u0434\u0430 estimate_func. \u041d\u043e \u043d\u0430 \u0442\u043e \u043e\u043d \u0438 \u043a\u043e\u0441\u0442\u044b\u043b\u044c.<\/p>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043e\u0432\u0430\u043d\u0438\u044f \u0444\u0430\u0439\u043b\u0430 \u0441\u0434\u0435\u043b\u0430\u043b \u0442\u0430\u043a:<\/p>\n<pre><code>def is_file_exists(self, path):     cmd = f\"if [ -f {path} ]; then echo 'True'; fi\"     out, err = self.exec(cmd)     return len(out) > 0 and out[0].strip() == \"True\"<\/code><\/pre>\n<p>\u041c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u0432 \u0446\u0438\u043a\u043b\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u0444\u0430\u0439\u043b\u0430, \u043f\u043e\u043a\u0430 \u043e\u043d \u043d\u0435 \u043f\u043e\u044f\u0432\u0438\u0442\u0441\u044f, \u0438\u043b\u0438 \u043f\u043e\u043a\u0430 \u043d\u0435 \u043f\u0440\u0435\u0440\u0432\u0451\u0442\u0441\u044f \u043f\u043e \u0442\u0430\u0439\u043c\u0430\u0443\u0442\u0443:<\/p>\n<pre><code>def wait_for_file(ssh_client, file_path, timeout=150):     logging.debug(f\"Wait for file {file_path} with timeout {timeout} seconds.\")      time_start = time.time()     while not ssh_client.is_file_exists(file_path):         if time.time() - time_start > timeout:             return False         time.sleep(0.05)     logging.debug(f\"File {file_path} is appears in {time.time() - time_start} seconds.\")     return True<\/code><\/pre>\n<p>\u041f\u0440\u0438 \u0432\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u043d\u0438\u0438 \u043a\u043e\u0441\u0442\u044b\u043b\u044f \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0441\u0442\u0438 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0445 \u0442\u0435\u0441\u0442\u043e\u0432. \u041d\u043e \u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u0431\u043e\u043b\u0435\u0435 \u0447\u0435\u0441\u0442\u043d\u043e\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043c\u043e\u043c\u0435\u043d\u0442\u0430, \u043a\u043e\u0433\u0434\u0430 \u0444\u0430\u0439\u043b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u043e\u044f\u0432\u0438\u043b\u0441\u044f \u043d\u0430 NAS. \u0425\u043e\u0442\u044f \u0434\u043e \u0438\u0434\u0435\u0430\u043b\u0430 \u0442\u0443\u0442 \u0435\u0449\u0451 \u0434\u0430\u043b\u0435\u043a\u043e.<\/p>\n<h2>\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0442\u0435\u0441\u0442\u043e\u0432<\/h2>\n<p>\u041d\u0443 \u0438 \u043f\u0440\u0438\u043c\u0435\u0440 \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0433\u043e \u043f\u0440\u043e\u0433\u043e\u043d\u0430:<\/p>\n<pre><code>(venv) vkovalev@VK-UBER-LAPTOP:~\/dev\/regular_tests$ NAS_TEST_CONFIG=x86nas_conf.ini pytest src\/test_simple.py --log-cli-level=INFO --count=50 -k ftp ======================================== test session starts ========================================= platform linux -- Python 3.10.6, pytest-7.3.1, pluggy-1.2.0 rootdir: \/home\/vkovalev\/dev\/regular_tests plugins: repeat-0.9.1 collected 400 items \/ 300 deselected \/ 100 selected  src\/test_simple.py::TestFTP::test_ftp_10MB_file_upload[1-50] ------------------------------------------- live log setup ------------------------------------------- INFO     root:ssh_client.py:15 ssh test@192.168.10.20 with password test INFO     paramiko.transport:transport.py:1873 Connected (version 2.0, client OpenSSH_8.4p1) INFO     paramiko.transport:transport.py:1873 Authentication (publickey) failed. INFO     paramiko.transport:transport.py:1873 Authentication (password) successful! INFO     paramiko.transport.sftp:sftp.py:169 [chan 0] Opened sftp connection (server version 3) INFO     root:conftest.py:58 FTP Welcome message:220 ProFTPD Server (Debian) [::ffff:192.168.10.20] ------------------------------------------- live log call -------------------------------------------- INFO     root:test_simple.py:74 Current path: \/home\/test INFO     root:test_simple.py:75 List before operation: [('.', {'modify': '20230724121427', 'perm': 'flcdmpe', 'type': 'cdir', 'unique': '10302U20008', 'unix.group': '0', 'unix.groupname': 'users', 'unix.mode': '0755', 'unix.owner': '1001', 'unix.ownername': 'test'}), ('.bash_history', {'modify': '20230724142057', 'perm': 'adfrw', 'size': '1056', 'type': 'file', 'unique': '10302U20009', 'unix.group': '100', 'unix.groupname': 'users', 'unix.mode': '0600', 'unix.owner': '1001', 'unix.ownername': 'test'}), ('findmevk', {'modify': '20230724120730', 'perm': 'flcdmpe', 'type': 'dir', 'unique': '10302U2000A', 'unix.group': '100', 'unix.groupname': 'users', 'unix.mode': '0755', 'unix.owner': '1001', 'unix.ownername': 'test'}), ('test_ftp_file_500MB.bin', {'modify': '20230724121441', 'perm': 'adfrw', 'size': '524288000', 'type': 'file', 'unique': '10302U2000C', 'unix.group': '100', 'unix.groupname': 'users', 'unix.mode': '0644', 'unix.owner': '1001', 'unix.ownername': 'test'}), ('..', {'modify': '20230721085135', 'perm': 'fle', 'type': 'pdir', 'unique': '10302U20001', 'unix.group': '0', 'unix.groupname': 'users', 'unix.mode': '0755', 'unix.owner': '0', 'unix.ownername': 'test'}), ('test_ftp_file_10MB.bin', {'modify': '20230724121206', 'perm': 'adfrw', 'size': '10485760', 'type': 'file', 'unique': '10302U2000B', 'unix.group': '100', 'unix.groupname': 'users', 'unix.mode': '0644', 'unix.owner': '1001', 'unix.ownername': 'test'})] INFO     root:utils.py:89 Test test_ftp_10MB_file_upload - 7.1594085693359375 INFO     root:test_simple.py:77 List after operation: [('.', {'modify': '20230724121427', 'perm': 'flcdmpe', 'type': 'cdir', 'unique': '10302U20008', 'unix.group': '0', 'unix.groupname': 'users', 'unix.mode': '0755', 'unix.owner': '1001', 'unix.ownername': 'test'}), ('.bash_history', {'modify': '20230724142057', 'perm': 'adfrw', 'size': '1056', 'type': 'file', 'unique': '10302U20009', 'unix.group': '100', 'unix.groupname': 'users', 'unix.mode': '0600', 'unix.owner': '1001', 'unix.ownername': 'test'}), ('findmevk', {'modify': '20230724120730', 'perm': 'flcdmpe', 'type': 'dir', 'unique': '10302U2000A', 'unix.group': '100', 'unix.groupname': 'users', 'unix.mode': '0755', 'unix.owner': '1001', 'unix.ownername': 'test'}), ('test_ftp_file_500MB.bin', {'modify': '20230724121441', 'perm': 'adfrw', 'size': '524288000', 'type': 'file', 'unique': '10302U2000C', 'unix.group': '100', 'unix.groupname': 'users', 'unix.mode': '0644', 'unix.owner': '1001', 'unix.ownername': 'test'}), ('..', {'modify': '20230721085135', 'perm': 'fle', 'type': 'pdir', 'unique': '10302U20001', 'unix.group': '0', 'unix.groupname': 'users', 'unix.mode': '0755', 'unix.owner': '0', 'unix.ownername': 'test'}), ('test_ftp_file_10MB.bin', {'modify': '20230727080632', 'perm': 'adfrw', 'size': '10485760', 'type': 'file', 'unique': '10302U2000B', 'unix.group': '100', 'unix.groupname': 'users', 'unix.mode': '0644', 'unix.owner': '1001', 'unix.ownername': 'test'})] PASSED                                                                                         [  1%] src\/test_simple.py::TestFTP::test_ftp_10MB_file_upload[2-50] ... src\/test_simple.py::TestFTP::test_ftp_500MB_file_upload[50-50] ------------------------------------------- live log call -------------------------------------------- INFO     root:test_simple.py:96 Current path: \/home\/test INFO     root:test_simple.py:97 List before operation: [('.', {'modify': '20230724121427', 'perm': 'flcdmpe', 'type': 'cdir', 'unique': '10302U20008', 'unix.group': '0', 'unix.groupname': 'users', 'unix.mode': '0755', 'unix.owner': '1001', 'unix.ownername': 'test'}), ('.bash_history', {'modify': '20230724142057', 'perm': 'adfrw', 'size': '1056', 'type': 'file', 'unique': '10302U20009', 'unix.group': '100', 'unix.groupname': 'users', 'unix.mode': '0600', 'unix.owner': '1001', 'unix.ownername': 'test'}), ('findmevk', {'modify': '20230724120730', 'perm': 'flcdmpe', 'type': 'dir', 'unique': '10302U2000A', 'unix.group': '100', 'unix.groupname': 'users', 'unix.mode': '0755', 'unix.owner': '1001', 'unix.ownername': 'test'}), ('test_ftp_file_500MB.bin', {'modify': '20230727091558', 'perm': 'adfrw', 'size': '524288000', 'type': 'file', 'unique': '10302U2000C', 'unix.group': '100', 'unix.groupname': 'users', 'unix.mode': '0644', 'unix.owner': '1001', 'unix.ownername': 'test'}), ('..', {'modify': '20230721085135', 'perm': 'fle', 'type': 'pdir', 'unique': '10302U20001', 'unix.group': '0', 'unix.groupname': 'users', 'unix.mode': '0755', 'unix.owner': '0', 'unix.ownername': 'test'}), ('test_ftp_file_10MB.bin', {'modify': '20230727080940', 'perm': 'adfrw', 'size': '10485760', 'type': 'file', 'unique': '10302U2000B', 'unix.group': '100', 'unix.groupname': 'users', 'unix.mode': '0644', 'unix.owner': '1001', 'unix.ownername': 'test'})] INFO     root:utils.py:89 Test test_ftp_500MB_file_upload - 82.15386939048767 INFO     root:test_simple.py:99 List after operation: [('.', {'modify': '20230724121427', 'perm': 'flcdmpe', 'type': 'cdir', 'unique': '10302U20008', 'unix.group': '0', 'unix.groupname': 'users', 'unix.mode': '0755', 'unix.owner': '1001', 'unix.ownername': 'test'}), ('.bash_history', {'modify': '20230724142057', 'perm': 'adfrw', 'size': '1056', 'type': 'file', 'unique': '10302U20009', 'unix.group': '100', 'unix.groupname': 'users', 'unix.mode': '0600', 'unix.owner': '1001', 'unix.ownername': 'test'}), ('findmevk', {'modify': '20230724120730', 'perm': 'flcdmpe', 'type': 'dir', 'unique': '10302U2000A', 'unix.group': '100', 'unix.groupname': 'users', 'unix.mode': '0755', 'unix.owner': '1001', 'unix.ownername': 'test'}), ('test_ftp_file_500MB.bin', {'modify': '20230727091719', 'perm': 'adfrw', 'size': '524288000', 'type': 'file', 'unique': '10302U2000C', 'unix.group': '100', 'unix.groupname': 'users', 'unix.mode': '0644', 'unix.owner': '1001', 'unix.ownername': 'test'}), ('..', {'modify': '20230721085135', 'perm': 'fle', 'type': 'pdir', 'unique': '10302U20001', 'unix.group': '0', 'unix.groupname': 'users', 'unix.mode': '0755', 'unix.owner': '0', 'unix.ownername': 'test'}), ('test_ftp_file_10MB.bin', {'modify': '20230727080940', 'perm': 'adfrw', 'size': '10485760', 'type': 'file', 'unique': '10302U2000B', 'unix.group': '100', 'unix.groupname': 'users', 'unix.mode': '0644', 'unix.owner': '1001', 'unix.ownername': 'test'})] PASSED                                                                                         [100%] ----------------------------------------- live log teardown ------------------------------------------ INFO     paramiko.transport.sftp:sftp.py:169 [chan 0] sftp session closed. <\/code><\/pre>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 \u0432 \u0431\u0430\u0437\u0443 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f:<\/p>\n<pre><code>(venv) vkovalev@VK-UBER-LAPTOP:~\/dev\/regular_tests\/test_logs$ sqlite3 perf_stat.db SQLite version 3.37.2 2022-01-06 13:25:41 Enter \".help\" for usage hints. sqlite> SELECT * FROM OperationTime; test_ftp_10MB_file_upload|1690408346.56921|1690408348.23682|0 test_ftp_10MB_file_upload|1690408348.45588|1690408350.45754|0 test_ftp_10MB_file_upload|1690408350.6777|1690408352.87904|0 ... test_ftp_500MB_file_upload|1690412608.31712|1690412712.00417|0 test_ftp_500MB_file_upload|1690412718.02048|1690412804.01584|0 test_ftp_500MB_file_upload|1690412809.94036|1690412892.09423|0<\/code><\/pre>\n<p>\u041e\u0442\u043b\u0438\u0447\u043d\u043e, \u0437\u043d\u0430\u0447\u0438\u0442 \u043f\u043e\u0434\u0445\u043e\u0434 \u0440\u0430\u0431\u043e\u0447\u0438\u0439, \u0438 \u043d\u0430 \u044d\u0442\u043e\u0439 \u0431\u0430\u0437\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0442\u044c \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0443\u044e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443.<\/p>\n<h2>\u0417\u0430\u0447\u0435\u043c \u044d\u0442\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043e?<\/h2>\n<p>\u041f\u043e\u0434 \u043a\u043e\u043d\u0435\u0446 \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0431\u044b \u043e\u0431\u044a\u044f\u0441\u043d\u0438\u0442\u044c, \u0437\u0430\u0447\u0435\u043c \u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442 \u0432\u043e\u043e\u0431\u0449\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d \u0438 \u0447\u0442\u043e \u043e\u043d \u0434\u0435\u043b\u0430\u0435\u0442 \u043d\u0430 \u0425\u0430\u0431\u0440\u0435. \u042d\u0442\u043e \u043d\u0435 \u043d\u043e\u0432\u043e\u0441\u0442\u044c, \u043d\u0435 \u0442\u0443\u0442\u043e\u0440\u0438\u0430\u043b \u0438 \u043d\u0435 \u044d\u043d\u0446\u0438\u043a\u043b\u043e\u043f\u0435\u0434\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0437\u0430\u043c\u0435\u0442\u043a\u0430, \u043d\u0435 \u0430\u043a\u043a\u0443\u0440\u0430\u0442\u043d\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f \u0441\u043e \u0441\u0445\u0435\u043c\u0430\u043c\u0438, \u0433\u0440\u0430\u0444\u0438\u043a\u0430\u043c\u0438 \u0438 \u0432\u044b\u0432\u0435\u0440\u0435\u043d\u043d\u043e\u0439 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043e\u0439. \u0414\u0435\u043b\u043e \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043f\u0440\u043e\u0435\u043a\u0442 NAS \u043c\u044b \u0434\u0435\u043b\u0430\u0435\u043c \u043f\u043e \u0444\u0430\u043d\u0443 \u0438 \u0432 \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u043e\u0435 \u043e\u0442 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u0432\u0440\u0435\u043c\u044f. \u041a\u0430\u043a \u0441\u043b\u0435\u0434\u0441\u0442\u0432\u0438\u0435, \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u043d\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043d\u0435 \u043c\u043d\u043e\u0433\u043e, \u0430 \u044d\u043d\u0442\u0443\u0437\u0438\u0430\u0437\u043c \u0438 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u044f\u044f \u0434\u0438\u0441\u0446\u0438\u043f\u043b\u0438\u043d\u0430 \u043d\u0435 \u0432\u0441\u0435\u0441\u0438\u043b\u044c\u043d\u044b. \u041e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0441\u0442\u044c \u043f\u0435\u0440\u0435\u0434 \u0430\u0443\u0434\u0438\u0442\u043e\u0440\u0438\u0435\u0439 \u0425\u0430\u0431\u0440\u0430 \u043f\u043e\u0434\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u0435\u0442 \u0447\u0442\u043e-\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c, \u043f\u0435\u0440\u0435\u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u0441\u0432\u043e\u0438 \u0438\u0434\u0435\u0438, \u0438\u0437\u0431\u0435\u0433\u0430\u0442\u044c \u0445\u0430\u043b\u0442\u0443\u0440\u044b, \u043f\u0440\u043e\u0432\u043e\u0434\u0438\u0442\u044c \u0440\u0435\u0432\u044c\u044e \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 \u0440\u0430\u0431\u043e\u0442\u044b, \u0434\u0430 \u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u0433\u043b\u0443\u0431\u0436\u0435 \u0432\u043d\u0438\u043a\u0430\u0442\u044c \u0432 \u0441\u0443\u0442\u044c. <\/p>\n<p>\u041f\u043e \u044d\u0442\u0438\u043c \u043f\u0440\u0438\u0447\u0438\u043d\u0430\u043c \u043c\u044b \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0432\u0435\u0441\u0442\u0438 \u043d\u0430 \u0425\u0430\u0431\u0440\u0435 \u0434\u043d\u0435\u0432\u043d\u0438\u043a \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438. \u041c\u043e\u0436\u0435\u0442 \u043a\u0442\u043e-\u0442\u043e \u043f\u043e\u0447\u0435\u0440\u043f\u043d\u0451\u0442 \u0442\u0443\u0442 \u0438\u0434\u0435\u0438 \u0434\u043b\u044f \u0441\u0432\u043e\u0438\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432, \u0430 \u043c\u044b \u0432 \u0441\u0432\u043e\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0441\u0443\u043c\u0435\u0435\u043c \u0440\u0430\u043d\u044c\u0448\u0435 \u043f\u0440\u0438\u0441\u043b\u0443\u0448\u0430\u0442\u044c\u0441\u044f \u043a \u043c\u043d\u0435\u043d\u0438\u044e \u0430\u0443\u0434\u0438\u0442\u043e\u0440\u0438\u0438 \u0438 \u0443\u043b\u0443\u0447\u0448\u0438\u043c \u0441\u0432\u043e\u0438 \u0440\u0435\u0448\u0435\u043d\u0438\u044f.<\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0437\u0434\u0435\u0441\u044c \u043c\u043d\u0435 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e, \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0443\u043b\u0443\u0447\u0448\u0438\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u0435 \u0442\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c\u043e\u0433\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e? \u0415\u0441\u0442\u044c \u043b\u0438 \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u043d\u044b\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f, \u0447\u0435\u043c \u043f\u0430\u0440\u0441\u0438\u043d\u0433 \u0432\u044b\u0432\u043e\u0434\u0430 \u043a\u043e\u043d\u0441\u043e\u043b\u0438 \u043b\u0438\u043d\u0443\u043a\u0441 \u043f\u043e ssh? \u0411\u0443\u0434\u0443 \u043a\u0440\u0430\u0439\u043d\u0435 \u043f\u0440\u0438\u0437\u043d\u0430\u0442\u0435\u043b\u0435\u043d \u0437\u0430 \u0441\u043e\u0432\u0435\u0442\u044b!<\/p>\n<p>\u0412 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0441\u0442\u0430\u0442\u044c\u044f\u0445 \u043e\u043f\u0438\u0448\u0435\u043c \u043d\u0430\u0448\u0438 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0435 \u0441\u0442\u0435\u043d\u0434\u044b \u0438 \u0441\u0445\u0435\u043c\u044b \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f\u043e\u0432, \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u0440\u0430\u0437\u0431\u0435\u0440\u0451\u043c\u0441\u044f \u0441 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0441\u0442\u044c\u044e \u043d\u0430\u0448\u0438\u0445 \u0442\u0435\u0441\u0442\u043e\u0432, \u043f\u0440\u043e\u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0438\u0437\u043c\u0435\u0440\u0435\u043d\u0438\u0439.<\/p>\n<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p> <!----> <!----><\/div>\n<p> <!----> <!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/companies\/3rdman\/articles\/751004\/\"> https:\/\/habr.com\/ru\/companies\/3rdman\/articles\/751004\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0412 <a href=\"https:\/\/habr.com\/ru\/companies\/3rdman\/articles\/746178\/\">\u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0435<\/a> \u043c\u044b \u0444\u043e\u0440\u043c\u0443\u043b\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u0446\u0435\u043b\u0438 \u0438 \u0441\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u043b\u0438 \u0441\u043f\u0438\u0441\u043e\u043a \u0442\u0435\u0441\u0442\u043e\u0432 \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438. \u0414\u0430\u043b\u0435\u0435 \u0432 \u0440\u0430\u0431\u043e\u0442\u0435 QA \u043e\u0431\u044b\u0447\u043d\u043e \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0431\u0430\u0437\u043e\u0432\u044b\u0445 \u0442\u0435\u0441\u0442\u043e\u0432 \u0438 \u043e\u0431\u0432\u044f\u0437\u043a\u0438 \u0434\u043b\u044f \u043d\u0438\u0445, \u0447\u0435\u043c \u043c\u044b \u0432 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0438 \u0437\u0430\u0439\u043c\u0451\u043c\u0441\u044f. \u041f\u043e\u043b\u043d\u044b\u0439 \u043a\u043e\u0434 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043b\u0435\u0436\u0438\u0442 \u043d\u0430 <a href=\"https:\/\/github.com\/ThirdManTeam\/regular_nas_tests\">\u0433\u0438\u0442\u0445\u0430\u0431 <\/a>\u0438 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442\u044c \u0435\u0433\u043e \u0432 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u043d\u0435 \u0431\u0443\u0434\u0435\u043c. <\/p>\n<h2>\u041d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0442\u0435\u0441\u0442\u044b<\/h2>\n<p>\u041d\u0443 \u0447\u0442\u043e \u0436\u0435, \u043f\u0440\u0438\u0448\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430. \u0417\u0434\u0435\u0441\u044c \u044f \u043e\u043f\u0438\u0448\u0443 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0442\u0435\u0441\u0442\u043e\u0432 \u0434\u043b\u044f FTP.\u00a0 \u0418 \u0442\u0430\u043a &#8212; \u0432\u043e\u0442 \u043a\u043e\u0434 \u0442\u0435\u0441\u0442\u0430:<\/p>\n<pre><code>class TestFTP:      def test_ftp_10MB_file_upload(self, ftp, perfmeter, test_name, ssh, target_dir):         file_data = get_file_with_size_mb(10)         md5sum_source = get_md5sum(file_data)          file_name = PurePath('test_ftp_file_10MB.bin')         source_file = PurePath('\/tmp') \/ file_name          with open(source_file, 'wb') as fh:             fh.write(file_data)             fh.close()          with open(source_file, 'rb') as fh:             ftp.cwd(CFG['FTP']['PATH'])             logging.info(f\"Current path: {ftp.pwd()}\")             logging.info(f\"List before operation: {list(ftp.mlsd())}\")             perfmeter.estimate_func(test_name, ftp.storbinary, f\"STOR {file_name}\", fh)             logging.info(f\"List after operation: {list(ftp.mlsd())}\")          md5sum_target = ssh.md5sum(target_dir \/ file_name)         assert md5sum_source == md5sum_target<\/code><\/pre>\n<p>\u041e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043d\u0430 \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u0438 \u0442\u0435\u0441\u0442\u0430 \u0438 \u0432\u044b\u0437\u043e\u0432\u0430\u0445 \u0444\u0438\u043a\u0441\u0442\u0443\u0440 \u043c\u044b \u043d\u0435 \u0431\u0443\u0434\u0435\u043c, \u0440\u0430\u0437\u0431\u0435\u0440\u0451\u043c \u0438\u0445 \u043f\u043e \u043c\u0435\u0440\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u0442\u0435\u0441\u0442\u0435.<\/p>\n<p>\u0421\u043f\u0435\u0440\u0432\u0430 \u043c\u044b \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u0444\u0430\u0439\u043b \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u043c\u0435\u0440\u0430:<\/p>\n<pre><code>file_data = get_file_with_size_mb(10) md5sum_source = get_md5sum(file_data)<\/code><\/pre>\n<p>\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u201c<em>os.urandom(size*1024*1024)<\/em>\u201d, \u0438 \u0442\u0443\u0442 \u0436\u0435 \u0441\u0447\u0438\u0442\u0430\u0435\u043c md5 \u0441\u0443\u043c\u043c\u0443, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u043f\u043e\u0437\u0436\u0435 \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0441\u0442\u0438 \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<p>\u0414\u043b\u044f \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0447\u0435\u0440\u0435\u0437 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0443\u044e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 ftplib \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0444\u0430\u0439\u043b \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e:<\/p>\n<pre><code>file_name = PurePath('test_ftp_file_10MB.bin') source_file = PurePath('\/tmp') \/ file_name  with open(source_file, 'wb') as fh:     fh.write(file_data)     fh.close()<\/code><\/pre>\n<p>\u0418 \u0437\u0430\u0442\u0435\u043c \u043a\u043b\u0430\u0434\u0451\u043c \u044d\u0442\u043e\u0442 \u0444\u0430\u0439\u043b \u043d\u0430 NAS \u043f\u043e FTP:<\/p>\n<pre><code>with open(source_file, 'rb') as fh:     ftp.cwd(CFG['FTP']['PATH'])     logging.info(f\"Current path: {ftp.pwd()}\")     logging.info(f\"List before operation: {list(ftp.mlsd())}\")     perfmeter.estimate_func(test_name, ftp.storbinary, f\"STOR {file_name}\", fh)     logging.info(f\"List after operation: {list(ftp.mlsd())}\") <\/code><\/pre>\n<p>\u0418 \u044d\u0442\u043e, \u043f\u043e \u0441\u0443\u0442\u0438, \u0433\u043b\u0430\u0432\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u0442\u0435\u0441\u0442\u0430.<\/p>\n<p>\u041e\u0431\u044a\u0435\u043a\u0442 <em>ftp<\/em> \u0438\u0437 \u201c<em>ftp.cwd(CFG[&#8216;FTP&#8217;][&#8216;PATH&#8217;])<\/em>\u201d \u0441\u043e\u0437\u0434\u0430\u0451\u0442\u0441\u044f \u0444\u0438\u043a\u0441\u0442\u0443\u0440\u043e\u0439 <em>ftp<\/em>:<\/p>\n<pre><code>@pytest.fixture(scope=\"session\") def ftp():     ftpcon = FTP(CFG['FTP']['ADDRESS'])     ftpcon.login(user=CFG['FTP']['LOGIN'], passwd=CFG['FTP']['PASSWD'])     logging.info(\"FTP Welcome message:\" + ftpcon.getwelcome())     yield ftpcon     ftpcon.quit()<\/code><\/pre>\n<p>\u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f scope=&#187;session&#187; ftp \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u0436\u0438\u0442\u044c \u0432\u0435\u0441\u044c \u043f\u0440\u043e\u0433\u043e\u043d \u0442\u0435\u0441\u0442\u043e\u0432, \u0430 \u043f\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0438 \u0442\u0435\u0441\u0442\u043e\u0432 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u0437\u0430\u043a\u0440\u043e\u0435\u0442 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435.<\/p>\n<p>\u0414\u043b\u044f \u0438\u0437\u043c\u0435\u0440\u0435\u043d\u0438\u044f \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c <em>perfmeter<\/em> \u0432 \u0441\u0442\u0440\u043e\u043a\u0435 \u201c<em>perfmeter.estimate_func(test_name, ftp.storbinary, f&#187;STOR {file_name}&#187;, fh)<\/em>\u201d. <\/p>\n<pre><code>class PerformaceMeter:     def __init__(self):         self._init_db_connection(CFG['DIAGNOSTIC']['PERF_STAT_DB']) \u2026     def estimate_func(self, test_name, func, *args):         start_time = time.time()         func(*args)         end_time = time.time()         func_time = end_time - start_time         logging.info(f\"Test {test_name} - {func_time}\")          self._db_cur.execute(\"insert into OperationTime values (?, ?, ?, ?)\",             (test_name, start_time, end_time, 0))         self._db_con.commit()<\/code><\/pre>\n<p>\u041e\u0431\u044a\u0435\u043a\u0442 <em>perfmeter<\/em> \u043a\u043b\u0430\u0441\u0441\u0430 <em>PerformasnceMeter<\/em> \u0441\u043e\u0437\u0434\u0430\u0451\u0442\u0441\u044f \u0442\u043e\u0436\u0435 \u0444\u0438\u043a\u0441\u0442\u0443\u0440\u043e\u0439 \u0434\u043b\u044f \u0441\u043a\u043e\u0443\u043f\u0430 session. \u0412\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u043c\u044b \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u043c \u043a\u0430\u043a \u0440\u0430\u0437\u043d\u0438\u0446\u0443 \u043c\u0435\u0436\u0434\u0443 end_time \u0438 start_time, \u0442\u0430\u043a \u043a\u0430\u043a \u0432\u044b\u0441\u043e\u043a\u043e\u0439 \u0442\u043e\u0447\u043d\u043e\u0441\u0442\u0438 \u043d\u0430\u043c \u0442\u0443\u0442 \u0438 \u043d\u0435 \u043d\u0443\u0436\u043d\u043e. \u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0441\u0440\u0430\u0437\u0443 \u043f\u0438\u0448\u0435\u043c \u0432 \u0431\u0430\u0437\u0443.<\/p>\n<p>\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u0448\u0430\u0433\u043e\u043c \u043c\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0441\u0442\u044c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<pre><code>md5sum_target = ssh.md5sum(target_dir \/ file_name) assert md5sum_source == md5sum_target<\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c \u043e\u0431\u044a\u0435\u043a\u0442 <em>ssh<\/em> \u043a\u043b\u0430\u0441\u0441\u0430 <em>SSH_Client<\/em> &#8212; \u044d\u0442\u043e \u043e\u0431\u0451\u0440\u0442\u043a\u0430 \u043d\u0430\u0434 <em>paramiko.SSHClient<\/em>. \u0412 \u043d\u0451\u043c \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f ssh \u0441\u0435\u0441\u0441\u0438\u044f:<\/p>\n<pre><code>class SSH_Client:      def __init__(self):         self._client = paramiko.SSHClient()         self._client.set_missing_host_key_policy(paramiko.AutoAddPolicy())      def connect(self, hostname, username, password=None):         if password:             logging.info(f\"ssh {username}@{hostname} with password {password}\") # security :)             self._client.connect(                 hostname=hostname, username=username, password=password)         else:             logging.info(f\"ssh {username}@{hostname} without password\")             self._client.connect(hostname=hostname, username=username)          self._sftp = self._client.open_sftp()<\/code><\/pre>\n<p>\u0438 \u0441\u0434\u0435\u043b\u0430\u043d\u044b \u043c\u0435\u0442\u043e\u0434\u044b \u0434\u043b\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0445 \u043a\u043e\u043c\u0430\u043d\u0434 \u0438 \u043f\u0430\u0440\u0441\u0438\u043d\u0433\u0430 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430:<\/p>\n<pre><code>    def exec(self, cmd):         logging.debug(f\"exec$ {cmd}\")         stdin, stdout, stderr = self._client.exec_command(cmd, get_pty=True)         stdin.close()          out = stdout.readlines()         out_text = ''.join(out)         logging.debug(f\"STDOUT:\\n{out_text}\")         err = stderr.readlines()         err_text = ''.join(err)         logging.debug(f\"STDERR:\\n{err_text}\")          return out, err      def md5sum(self, path):         out, err = self.exec(f\"md5sum {path}\")         for l in out:             if re.match(r\"\\S{32} \", l):                 md5sum = l[:32]                 break         return md5sum<\/code><\/pre>\n<p>\u0422\u0430\u043a \u0447\u0442\u043e, \u0443\u043f\u0440\u043e\u0449\u0451\u043d\u043d\u043e \u0433\u043e\u0432\u043e\u0440\u044f, \u043c\u044b \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 \u0442\u0435\u0441\u0442\u0430 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u043c\u0435\u0440\u0430 \u0438 \u0441\u043d\u0438\u043c\u0430\u0435\u043c \u0441 \u043d\u0435\u0433\u043e md5 \u0441\u0443\u043c\u043c\u0443, \u043a\u043e\u043f\u0438\u0440\u0443\u0435\u043c \u0444\u0430\u0439\u043b \u043d\u0430 \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440, \u0437\u0430\u0441\u0435\u043a\u0430\u044f \u0432\u0440\u0435\u043c\u044f \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c\u0441\u044f \u0442\u0443\u0434\u0430 \u043f\u043e ssh, \u0441\u043d\u0438\u043c\u0430\u0435\u043c md5 \u0441\u0443\u043c\u043c\u0443 \u0434\u043b\u044f \u0444\u0430\u0439\u043b\u0430 \u0438 \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0435\u043c \u0438\u0445.<\/p>\n<p>\u041f\u043e\u0434\u043e\u0431\u043d\u044b\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043c\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c \u0438 \u0441 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430\u043c\u0438. \u041f\u043e \u0438\u0442\u043e\u0433\u0443 \u043c\u044b \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0432 \u0431\u0430\u0437\u0443 \u0432\u043d\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0441\u0442\u0438 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 (\u0438 \u044d\u0442\u043e \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u043e), \u043d\u043e \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u043e\u0432\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0441 \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u043c\u044b \u0441\u043c\u043e\u0436\u0435\u043c \u043f\u0440\u043e\u0432\u0435\u0441\u0442\u0438 \u0434\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u043a\u0443.<\/p>\n<h2>\u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0442\u0435\u0441\u0442\u044b<\/h2>\n<p>\u041f\u0440\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0442\u0435\u0441\u0442\u043e\u0432 \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u043f\u0435\u0440\u0435\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u044b. \u0410 \u0438\u043c\u0435\u043d\u043d\u043e &#8212; \u043c\u044b \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u0432 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0434\u0438\u0441\u043a\u043e\u0432, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 WebDAV.<\/p>\n<h3>\u0422\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0434\u0438\u0441\u043a\u043e\u0432<\/h3>\n<p>\u041f\u0440\u043e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0434\u0438\u0441\u043a\u043e\u0432 \u0435\u0441\u0442\u044c \u043e\u0442\u043b\u0438\u0447\u043d\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f \u043d\u0430 \u0425\u0430\u0431\u0440\u0435: <a href=\"https:\/\/habr.com\/ru\/articles\/154235\/\"><u>https:\/\/habr.com\/ru\/articles\/154235\/<\/u><\/a>. \u041c\u044b \u0436\u0435, \u043f\u0440\u043e\u0430\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0432 \u0437\u0430\u0434\u0430\u0447\u0443, \u0440\u0435\u0448\u0438\u043b\u0438 \u0432\u044b\u043d\u0435\u0441\u0442\u0438 \u0434\u0430\u043d\u043d\u044b\u0439 \u0432\u0438\u0434 \u0442\u0435\u0441\u0442\u043e\u0432 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u043a. \u0421\u0442\u0440\u043e\u0433\u043e \u0433\u043e\u0432\u043e\u0440\u044f, \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0431\u043e\u0440 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0439 \u0434\u043b\u044f fio. \u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0442\u0435\u0441\u0442\u043e\u0432 \u0431\u0443\u0434\u0443\u0442 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u0432\u0440\u0443\u0447\u043d\u0443\u044e. \u041f\u0440\u0438\u0447\u0438\u043d \u0434\u043b\u044f \u0442\u0430\u043a\u043e\u0433\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e:<\/p>\n<ol>\n<li>\n<p>\u041c\u0435\u043d\u044f\u0442\u044c \u043c\u0435\u0442\u043e\u0434\u044b \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0434\u0438\u0441\u043a\u043e\u0432 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043d\u0435 \u0447\u0430\u0441\u0442\u043e. \u0410 \u0437\u043d\u0430\u0447\u0438\u0442 \u0438 fio \u0433\u043e\u043d\u044f\u0442\u044c \u0447\u0430\u0441\u0442\u043e \u043d\u0435 \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f.<\/p>\n<\/li>\n<li>\n<p>\u0421\u0430\u043c\u0438 \u0442\u0435\u0441\u0442\u044b \u0438\u0434\u0443\u0442 \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f. \u041c\u0435\u0448\u0430\u0442\u044c \u0438\u0445 \u0441 \u043d\u0430\u0448\u0438\u043c\u0438 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0448\u0443\u0441\u0442\u0440\u044b\u043c\u0438 \u0442\u0435\u0441\u0442\u0430\u043c\u0438 \u043d\u0435 \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0431\u044b. \u0414\u0430 \u0438 \u0441\u043c\u044b\u0441\u043b\u0430 \u0432 \u044d\u0442\u043e\u043c \u043d\u0435 \u043c\u043d\u043e\u0433\u043e.<\/p>\n<\/li>\n<\/ol>\n<p>\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u044d\u0442\u0443 \u0442\u0435\u043c\u0443 \u043f\u043e\u0441\u0442\u0430\u0440\u0430\u0435\u043c\u0441\u044f \u0440\u0430\u0441\u043a\u0440\u044b\u0442\u044c \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0441\u0442\u0430\u0442\u044c\u044f\u0445.<\/p>\n<h3>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 WebDAV<\/h3>\n<p>\u041f\u043e \u0437\u0430\u044f\u0432\u043a\u0430\u043c \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0445 \u043a \u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u0440\u0435\u0448\u0438\u043b\u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 \u0441\u043f\u0438\u0441\u043e\u043a \u0442\u0435\u0441\u0442\u043e\u0432 \u0438 WebDAV. \u0412 \u043a\u043e\u043d\u0446\u0435 \u043a\u043e\u043d\u0446\u043e\u0432 \u044d\u0442\u043e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435, \u0445\u043e\u0442\u044f \u0438 \u043d\u0435 \u0441\u0440\u0435\u0434\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 OMV. \u0412\u0435\u0434\u044c \u043f\u043b\u0430\u0433\u0438\u043d\u0430 \u0434\u043b\u044f \u043d\u0435\u0433\u043e \u043d\u0435\u0442\u0443 \u0434\u0430\u0436\u0435 \u0432 omv-extras (\u0442\u043e\u0447\u043d\u0435\u0435 \u0431\u044b\u043b, \u043d\u043e \u043f\u0440\u043e\u0442\u0443\u0445). \u041f\u043e\u0447\u0438\u0442\u0430\u0432 <a href=\"https:\/\/forum.openmediavault.org\/index.php?thread\/43001-webdav\/\"><u>\u0444\u043e\u0440\u0443\u043c<\/u><\/a> \u043f\u0440\u0438\u043d\u044f\u043b\u0438 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043d\u0435 \u0441\u0432\u044f\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u0441 \u043f\u043b\u0430\u0433\u0438\u043d\u0430\u043c\u0438. \u0423 \u043d\u0430\u0441 \u043e\u0441\u0442\u0430\u0451\u0442\u0441\u044f 2 \u043f\u0443\u0442\u0438:<\/p>\n<ol>\n<li>\n<p>\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c WebDAV \u0432 Docker, \u0447\u0442\u043e \u0438 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e\u0442 \u043d\u0430 \u0444\u043e\u0440\u0443\u043c\u0435. \u0420\u0435\u0448\u0435\u043d\u0438\u0435 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0440\u0430\u0437\u0443\u043c\u043d\u044b\u043c \u0438 \u0443\u0434\u043e\u0431\u043d\u044b\u043c, \u043d\u043e \u201c\u0437\u0430\u0433\u0440\u044f\u0437\u043d\u044f\u0435\u0442\u201d \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0442\u0435\u0441\u0442\u043e\u0432. \u0412\u0435\u0434\u044c \u043f\u043e\u043c\u0438\u043c\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0435\u0449\u0451 \u0438 Docker. \u0414\u0430, \u0443 \u043d\u0435\u0433\u043e \u043e\u0432\u0435\u0440\u0445\u0435\u0434 \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u0431\u043e\u043b\u044c\u0448\u043e\u0439, \u043d\u043e \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442.<\/p>\n<\/li>\n<li>\n<p>\u0421\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c WebDAV \u043d\u0430\u0442\u0438\u0432\u043d\u043e \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0435. \u042d\u0442\u043e\u0442 \u043f\u0443\u0442\u044c \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f \u043c\u043d\u0435 \u0435\u0449\u0451 \u043c\u0435\u043d\u044c\u0448\u0435, \u0442\u0430\u043a \u043a\u0430\u043a \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f \u0432\u043c\u0435\u0448\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0438, \u043e\u0442\u043b\u0430\u0436\u0435\u043d\u043d\u044b\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430\u043c\u0438 OMV. \u041f\u043e\u0441\u043b\u0435\u0434\u0441\u0442\u0432\u0438\u044f \u0442\u0430\u043a\u043e\u0433\u043e \u0432\u043c\u0435\u0448\u0430\u0442\u0435\u043b\u044c\u0441\u0442\u0432\u0430 \u0434\u043b\u044f \u043c\u0435\u043d\u044f \u043b\u0438\u0447\u043d\u043e \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u044b. \u0414\u0430 \u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c \u044d\u0442\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u0441\u043b\u043e\u0436\u043d\u0435\u0435.<\/p>\n<\/li>\n<\/ol>\n<p>\u0418\u0437 \u0434\u0432\u0443\u0445 \u0437\u043e\u043b \u0432\u044b\u0431\u0440\u0430\u043b\u0438 \u043c\u0435\u043d\u044c\u0448\u0435\u0435 \u0438 \u0431\u043e\u043b\u0435\u0435 \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u043e\u0435. \u0422\u043e \u0435\u0441\u0442\u044c \u0414\u043e\u043a\u0435\u0440.<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u0430\u043a \u043c\u044b \u043d\u0435 \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u043b\u0438 \u0434\u043e\u043a\u0435\u0440 \u043d\u0430 OMV \u0447\u0435\u0440\u0435\u0437 \u043f\u043b\u0430\u0433\u0438\u043d\u044b<\/summary>\n<div class=\"spoiler__content\">\n<p>\u041f\u043e\u043f\u044b\u0442\u043a\u0430 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043d\u043e\u0432\u044b\u0439 \u043f\u043b\u0430\u0433\u0438\u043d \u0434\u043b\u044f \u0434\u043e\u043a\u0435\u0440\u0430 \u043f\u043e <a href=\"https:\/\/forum.openmediavault.org\/index.php?thread\/48003-guide-using-the-new-docker-plugin\/\"><u>\u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438 \u0441 \u0444\u043e\u0440\u0443\u043c\u0430<\/u><\/a> \u0443\u0432\u0435\u043d\u0447\u0430\u043b\u0430\u0441\u044c \u043f\u043e\u043b\u043d\u044b\u043c \u043f\u0440\u043e\u0432\u0430\u043b\u043e\u043c:<\/p>\n<pre><code>Failed to execute command 'export PATH=\/bin:\/sbin:\/usr\/bin:\/usr\/sbin:\/usr\/local\/bin:\/usr\/local\/sbin; export LANG=C.UTF-8; export LANGUAGE=; export DEBIAN_FRONTEND=noninteractive; apt-get --yes --allow-downgrades --allow-change-held-packages --fix-missing --allow-unauthenticated --reinstall install openmediavault-compose 2>&amp;1' with exit code '100': Reading package lists...  Building dependency tree...  Reading state information...  Some packages could not be installed. This may mean that you have requested an impossible situation or if you are using the unstable distribution that some required packages have not yet been created or been moved out of Incoming. The following information may help to resolve the situation:  The following packages have unmet dependencies:  openmediavault-compose : Depends: openmediavault-sharerootfs but it is not installable E: Unable to correct problems, you have held broken packages.  OMV\\ExecException: Failed to execute command 'export PATH=\/bin:\/sbin:\/usr\/bin:\/usr\/sbin:\/usr\/local\/bin:\/usr\/local\/sbin; export LANG=C.UTF-8; export LANGUAGE=; export DEBIAN_FRONTEND=noninteractive; apt-get --yes --allow-downgrades --allow-change-held-packages --fix-missing --allow-unauthenticated --reinstall install openmediavault-compose 2>&amp;1' with exit code '100': Reading package lists...  Building dependency tree...  Reading state information...  Some packages could not be installed. This may mean that you have requested an impossible situation or if you are using the unstable distribution that some required packages have not yet been created or been moved out of Incoming. The following information may help to resolve the situation:  The following packages have unmet dependencies:  openmediavault-compose : Depends: openmediavault-sharerootfs but it is not installable E: Unable to correct problems, you have held broken packages. in \/usr\/share\/openmediavault\/engined\/rpc\/pluginmgmt.inc:247 Stack trace: #0 \/usr\/share\/php\/openmediavault\/rpc\/serviceabstract.inc(619): Engined\\Rpc\\PluginMgmt->Engined\\Rpc\\{closure}('\/tmp\/bgstatusfo...', '\/tmp\/bgoutputNb...') #1 \/usr\/share\/openmediavault\/engined\/rpc\/pluginmgmt.inc(251): OMV\\Rpc\\ServiceAbstract->execBgProc(Object(Closure)) #2 [internal function]: Engined\\Rpc\\PluginMgmt->install(Array, Array) #3 \/usr\/share\/php\/openmediavault\/rpc\/serviceabstract.inc(123):<\/code><\/pre>\n<\/div>\n<\/details>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-350972","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/350972","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=350972"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/350972\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=350972"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=350972"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=350972"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}