Closed stvacs closed 2 years ago
At a guess the NetApp server might not support transacted operations that smbclient
is trying to do. Looking at the code it looks like the following operations are done
FSCTL_SRV_REQUEST_RESUME_KEY
FSCTL_SRV_COPYCHUNK_WRITE
The logs you sent unfortunately seem to include this operation in it so I can't tell with of the 2 failed. This isn't your fault, just a gap in the logging unfortunately.
My guess is the FSCTL_SRV_REQUEST_RESUME_KEY
is not implemented on the Netapp side so let's try and test out that assumption. Can you try to run the following:
import smbclient
from smbprotocol.ioctl import CtlCode, IOCTLFlags, SMB2IOCTLRequest, SMB2IOCTLResponse, SMB2SrvRequestResumeKey
path = r'\\server\share\test.txt'
with smbclient.open_file(path, mode='rb', share_access='r', buffering=0) as fd:
ioctl_req = SMB2IOCTLRequest()
ioctl_req['ctl_code'] = CtlCode.FSCTL_SRV_REQUEST_RESUME_KEY
ioctl_req['file_id'] = fd.fd.file_id
ioctl_req['max_output_response'] = 32
ioctl_req['flags'] = IOCTLFlags.SMB2_0_IOCTL_IS_FSCTL
ioctl_req['buffer'] = b""
sid = fd.fd.tree_connect.session.session_id
tid = fd.fd.tree_connect.tree_connect_id
req = fd.fd.connection.send(ioctl_req, sid, tid)
header_resp = fd.fd.connection.receive(req)
resp = SMB2IOCTLResponse()
resp.unpack(header_resp['data'].get_value())
resume_key = SMB2SrvRequestResumeKey()
resume_key.unpack(resp['buffer'].get_value())
print(header_resp)
print(resp)
print(resume_key)
This should print out the header response containing STATUS_SUCCESS
and the IOCTL response and the resume key information. If it fails with STATUS_NOT_SUPPORTED
we know this is the part that's failing and will have to potentially find some alternatives.
Thank you for your suggestion and some additional test code. Below you find the result. The exception is raised on execution of "header_resp = fd.fd.connection.receive(req)", e.g. all code below is never excuted. This indicates that FSCTL_SRV_REQUEST_RESUME_KEY is not implemented.
Is it possible to implement FSCTL_SRV_COPYCHUNK without FSCTL_SRV_REQUEST_RESUME_KEY request? Based on https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb/c82ff91d-28d8-4274-a2ab-c2f5ade26b98 I had the impression, that FSCTL_SRV_REQUEST_RESUME_KEY was mandatory.
Traceback (most recent call last): File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.496.0_x64qbz5n2kfra8p0\lib\runpy.py", line 196, in _run_module_as_main return _run_code(code, main_globals, None, File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.496.0_x64__qbz5n2kfra8p0\lib\runpy.py", line 86, in _run_code exec(code, run_globals) File "c:\Users\user.vscode\extensions\ms-python.python-2022.6.2\pythonFiles\lib\python\debugpy__main.py", line 45, in
cli.main() File "c:\Users\user.vscode\extensions\ms-python.python-2022.6.2\pythonFiles\lib\python\debugpy/..\debugpy\server\cli.py", line 444, in main run() File "c:\Users\user.vscode\extensions\ms-python.python-2022.6.2\pythonFiles\lib\python\debugpy/..\debugpy\server\cli.py", line 285, in run_file runpy.run_path(target_as_str, run_name=compat.force_str(" main")) File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.496.0_x64qbz5n2kfra8p0\lib\runpy.py", line 269, in run_path return _run_module_code(code, init_globals, run_name, File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.496.0_x64__qbz5n2kfra8p0\lib\runpy.py", line 96, in _run_module_code _run_code(code, mod_globals, init_globals, File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.496.0_x64qbz5n2kfra8p0\lib\runpy.py", line 86, in _run_code exec(code, run_globals) File "y:\pysmb-test\log_error.py", line 22, inheader_resp = fd.fd.connection.receive(req) File "c:\Users\user\pyrt\lib\site-packages\smbprotocol\connection.py", line 1006, in receive raise SMBResponseException(response) smbprotocol.exceptions.NotSupported: Received unexpected status from the server: The request is not supported. (3221225659) STATUS_NOT_SUPPORTED: 0xc00000bb
It seems to be a required IOCTL command as the docs for FSCTL_SRV_COPYCHUNK mention that the SourceFile
is set to
A key that represents the source file with the data to be copied. This key is obtained through FSCTL_SRV_REQUEST_RESUME_KEY.
In your case if server side copies are not supported you will have to use shutil.copyfileobj
to copy files. Theoretically it should be possible to do smbclient.shutil.copyfile
and force it to use the more inefficient copy by reading and writing manually but unfortunately the code doesn't have a fallback written and will always use smbclient.copyfile
if it shares the same root.
import smbclient
import shutil
with smbclient.open_file(src, mode='rc') as src_fd, smbclient.open_file(dst, mode='wb') as dst_fd:
shutil.copyfileobj(src_fd, dst_fd)
Closing as per the above, without supporting the required IOCTL commands the raw server side copy operation cannot be used. The workaround is to use shutil.copyfileobj
with an opened handle on both sides. This is unfortunately not as efficient but the only way around this problem.
Hi, I am using a simple program (see attached file) to test server-side copy with a NetApp Ontap server (v2.1 or higher). This program runs fine with other server as target eg. a Synology Samba server. But with NetApp following error is thrown:
Traceback (most recent call last): File "y:\pysmb-test\minimal_example.py", line 23, in
smbclient.copyfile( sf_name, tf_name )
File "C:\Users\user\pyrt\lib\site-packages\smbclient_os.py", line 158, in copyfile
with SMBFileTransaction(src_fd) as transaction_src:
File "C:\Users\user\pyrt\lib\site-packages\smbclient_io.py", line 277, in exit
self.commit()
File "C:\Users\user\pyrt\lib\site-packages\smbclient_io.py", line 364, in commit
raise failures[0]
smbprotocol.exceptions.SMBOSError: [Error 0] [NtStatus 0xc00000bb] Unknown NtStatus error returned 'STATUS_NOT_SUPPORTED'
To my knowledge both server-side copy (e.g. FSCTL_SRV_COPYCHUNK support) and ODX are enabled for the CIFS share in question. I have attached the debug log from the test program.
Is there anything I can do on the client side to make this work?
Thanks for helping.
_smb.log minimal_example.py.txt