Skip to content

Commit 9d25a1a

Browse files
Merge pull request #115 from NethServer/bug-7537-1
Refs NethServer/dev#7537
2 parents 38daf7a + bfd2cd3 commit 9d25a1a

File tree

5 files changed

+71
-13
lines changed

5 files changed

+71
-13
lines changed

README.md

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -256,16 +256,27 @@ container scans for files and directories whose filesystem change time
256256
exceeds the configured retention period and removes them. If a retention
257257
value of `0` is set, the automatic cleanup procedure is disabled.
258258

259-
When the recycle bin is enabled, the Samba share parameter
260-
`recycle:repository = .recycle` is set in the share registry
261-
configuration. Review the current share configuration with:
259+
When the recycle bin is enabled on a share, its the Samba parameter
260+
`recycle:repository = .recycle/%U` is set in the share registry
261+
configuration.
262+
263+
Review the current share configuration with:
262264

263265
podman exec samba-dc net conf list
264266

265-
The default repository value `.recycle` assigned to enable the recycle bin
266-
can be adjusted by executing a command like this:
267+
The default base path for the recycle bin is `.recycle`. It is created by
268+
the add-share and alter-share actions if it does not exist, to properly
269+
set its permissions. It can be changed with the following command:
270+
271+
python3 -magent -c 'agent.set_env("RECYCLE_REPOSITORY", ".myrecycle")'
272+
273+
The path is relative to the share root directory. This change does not
274+
affect shares that have already been configured.
275+
276+
The full recycle bin path is private for each user. For this reason, the
277+
`/%U` suffix is always automatically appended when generating the
278+
corresponding Samba configuration parameter.
267279

268-
python3 -magent -c 'agent.set_env("RECYCLE_REPOSITORY", ".myrecycle")'
269280

270281
## Known log messages
271282

@@ -292,3 +303,24 @@ Migration is implemented in the `import-module` action.
292303
- `user.SAMBA_PAI` attribute is not copied to NS8 shares. It contains
293304
the ACL *protected/don't inherit* flag. See [map acl
294305
inherit](https://www.samba.org/samba/docs/current/man-html/smb.conf.5.html).
306+
307+
## Testing
308+
309+
Test the module using the `test-module.sh` script:
310+
311+
./test-module.sh <NODE_ADDR> ghcr.io/nethserver/samba:bug-7537
312+
313+
Additional arguments are forwarded to the `robot` command (see [Robot
314+
Framework](https://robotframework.org/)).
315+
316+
For instance, to speed up testing on a local machine:
317+
318+
1. Skip the instance removal
319+
320+
./test-module.sh 10.5.4.1 ghcr.io/nethserver/samba:bug-7537 --exclude remove
321+
322+
2. Continue to use the Samba instance, skipping the installation steps.
323+
The `--variable` option is required to find the existing Samba
324+
instance.
325+
326+
./test-module.sh 10.5.4.1 ghcr.io/nethserver/samba:bug-7537 --exclude createORremove --variable MID1:samba1

imageroot/actions/list-shares/50list_shares

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ list_shares = {
7070
"shares": []
7171
}
7272

73-
ocfg = configparser.ConfigParser(delimiters=("="))
73+
ocfg = configparser.ConfigParser(delimiters=("="), interpolation=None)
7474
with subprocess.Popen(podman_exec + ["net", "conf", "list"], stdout=subprocess.PIPE, text=True) as hconf:
7575
try:
7676
ocfg.read_file(hconf.stdout, 'samba-registry-conf')

imageroot/pypkg/samba.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,12 +227,13 @@ def configure_samba_audit(sharename, enable_audit=True, log_failed_events=False)
227227

228228
def configure_recycle(sharename, enable_recycle=True, recycle_retention=0, recycle_versions=False):
229229
if enable_recycle:
230-
agent.run_helper("podman", "exec", "samba-dc", "net", "conf", "setparm", sharename, "recycle:repository", os.getenv("RECYCLE_REPOSITORY", ".recycle"))
230+
agent.run_helper("podman", "exec", "samba-dc", "net", "conf", "setparm", sharename, "recycle:repository", os.getenv("RECYCLE_REPOSITORY", ".recycle") + "/%U")
231231
if recycle_versions:
232232
agent.run_helper("podman", "exec", "samba-dc", "net", "conf", "delparm", sharename, "recycle:versions")
233233
else:
234234
agent.run_helper("podman", "exec", "samba-dc", "net", "conf", "setparm", sharename, "recycle:versions", "no")
235235
agent.run_helper("podman", "exec", "samba-dc", "recycle", "set_retention", sharename, str(recycle_retention))
236+
agent.run_helper("podman", "exec", "samba-dc", "recycle", "init_repository", sharename)
236237
else:
237238
agent.run_helper("podman", "exec", "samba-dc", "net", "conf", "delparm", sharename, "recycle:repository")
238239
agent.run_helper("podman", "exec", "samba-dc", "net", "conf", "delparm", sharename, "recycle:versions")

samba-dc/usr/local/sbin/recycle

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import json
1010
import sys
1111
import time
1212
import os
13+
import shutil
1314
from pathlib import Path
1415
import argparse
1516
import configparser
@@ -70,7 +71,27 @@ def get_recycle_repository(share_name):
7071
stderr=subprocess.DEVNULL).strip()
7172
except subprocess.CalledProcessError as e:
7273
repodir = '' # recycle is disabled
73-
return repodir
74+
return repodir.removesuffix("/%U")
75+
76+
def init_recycle_directory(share_name):
77+
repository = get_recycle_repository(share_name)
78+
if not repository:
79+
return # recycle bin is disabled
80+
share_path = RECYCLE_BASE / share_name
81+
recycle_path = share_path / repository
82+
if recycle_path.exists():
83+
return
84+
print(f"Creating recycle repository: {recycle_path}", file=sys.stderr)
85+
cur = share_path
86+
share_meta = share_path.stat()
87+
# Create the recycle bin repository and its parent path components
88+
# like mkdir -p, copying on them the share root permissions and
89+
# extended attributes:
90+
for part in recycle_path.relative_to(share_path).parts:
91+
cur = cur / part
92+
cur.mkdir(exist_ok=True)
93+
os.chown(cur, share_meta.st_uid, share_meta.st_gid)
94+
shutil.copystat(share_path, cur)
7495

7596
def run_daemon():
7697
while True:
@@ -101,6 +122,8 @@ def main():
101122
set_parser.add_argument("num_days", type=int, help="Retention in days (0 means keep forever)")
102123
del_parser = subparsers.add_parser("del_retention", help="Delete retention for a share")
103124
del_parser.add_argument("share_name", help="Share name")
125+
init_parser = subparsers.add_parser("init_repository", help="Initialize the repository directory for a share")
126+
init_parser.add_argument("share_name", help="Share name")
104127
subparsers.add_parser("run_daemon", help="Run the daily cleanup loop continuosly")
105128
subparsers.add_parser("purge_shares", help="Run cleanup procedure immediately")
106129
args = parser.parse_args()
@@ -110,6 +133,8 @@ def main():
110133
set_retention(args.share_name, args.num_days)
111134
elif args.command == "del_retention":
112135
del_retention(args.share_name)
136+
elif args.command == "init_repository":
137+
init_recycle_directory(args.share_name)
113138
elif args.command == "run_daemon":
114139
run_daemon()
115140
elif args.command == "purge_shares":

tests/10__configure_domain.robot

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,19 @@ Retrieve defaults
1313
${response} = Run task module/${MID1}/get-defaults {"provision":"new-domain"}
1414
Set Global Variable ${IPADDR} ${response['ipaddress_list'][0]['ipaddress']}
1515
Should Not Be Empty ${IPADDR}
16+
Set Global Variable ${DOMAIN} ${MID1}.test
17+
Set Global Variable ${DOMSUFFIX} dc=${MID1},dc=test
1618

1719
Configure the domain
1820
[Tags] create instance
19-
Set Global Variable ${DOMAIN} ${MID1}.test
20-
Set Global Variable ${DOMSUFFIX} dc=${MID1},dc=test
2121
${out} ${err} ${rc} = Execute Command
2222
... api-cli run module/${MID1}/configure-module --data '{"provision":"new-domain","realm":"${DOMAIN}","nbdomain":"${nbdomain}","hostname":"${dc1_hostname}","ipaddress":"${IPADDR}","adminuser":"${admuser}","adminpass":"${admpass}"}'
2323
... return_rc=True return_stdout=True return_stderr=True
2424
Should Be Equal As Integers ${rc} 0
25+
26+
The server is reachable after restart
2527
${val} = Get server url ${MID1}
2628
Set Global Variable ${SURL} ${val}
2729
Wait Until Keyword Succeeds 10s 1s RootDSE is correct ${SURL}
28-
29-
The server is reachable after restart
3030
Execute Command systemctl restart ${MID1}
3131
Wait Until Keyword Succeeds 10s 1s RootDSE is correct ${SURL}

0 commit comments

Comments
 (0)