]> git.proxmox.com Git - ceph.git/blob - ceph/qa/tasks/samba.py
update sources to v12.1.4
[ceph.git] / ceph / qa / tasks / samba.py
1 """
2 Samba
3 """
4 import contextlib
5 import logging
6 import sys
7 import time
8
9 from teuthology import misc as teuthology
10 from teuthology.orchestra import run
11 from teuthology.orchestra.daemon import DaemonGroup
12
13 log = logging.getLogger(__name__)
14
15
16 def get_sambas(ctx, roles):
17 """
18 Scan for roles that are samba. Yield the id of the the samba role
19 (samba.0, samba.1...) and the associated remote site
20
21 :param ctx: Context
22 :param roles: roles for this test (extracted from yaml files)
23 """
24 for role in roles:
25 assert isinstance(role, basestring)
26 PREFIX = 'samba.'
27 assert role.startswith(PREFIX)
28 id_ = role[len(PREFIX):]
29 (remote,) = ctx.cluster.only(role).remotes.iterkeys()
30 yield (id_, remote)
31
32
33 @contextlib.contextmanager
34 def task(ctx, config):
35 """
36 Setup samba smbd with ceph vfs module. This task assumes the samba
37 package has already been installed via the install task.
38
39 The config is optional and defaults to starting samba on all nodes.
40 If a config is given, it is expected to be a list of
41 samba nodes to start smbd servers on.
42
43 Example that starts smbd on all samba nodes::
44
45 tasks:
46 - install:
47 - install:
48 project: samba
49 extra_packages: ['samba']
50 - ceph:
51 - samba:
52 - interactive:
53
54 Example that starts smbd on just one of the samba nodes and cifs on the other::
55
56 tasks:
57 - samba: [samba.0]
58 - cifs: [samba.1]
59
60 An optional backend can be specified, and requires a path which smbd will
61 use as the backend storage location:
62
63 roles:
64 - [osd.0, osd.1, osd.2, mon.0, mon.1, mon.2, mds.a]
65 - [client.0, samba.0]
66
67 tasks:
68 - ceph:
69 - ceph-fuse: [client.0]
70 - samba:
71 samba.0:
72 cephfuse: "{testdir}/mnt.0"
73
74 This mounts ceph to {testdir}/mnt.0 using fuse, and starts smbd with
75 a UNC of //localhost/cephfuse. Access through that UNC will be on
76 the ceph fuse mount point.
77
78 If no arguments are specified in the samba
79 role, the default behavior is to enable the ceph UNC //localhost/ceph
80 and use the ceph vfs module as the smbd backend.
81
82 :param ctx: Context
83 :param config: Configuration
84 """
85 log.info("Setting up smbd with ceph vfs...")
86 assert config is None or isinstance(config, list) or isinstance(config, dict), \
87 "task samba got invalid config"
88
89 if config is None:
90 config = dict(('samba.{id}'.format(id=id_), None)
91 for id_ in teuthology.all_roles_of_type(ctx.cluster, 'samba'))
92 elif isinstance(config, list):
93 config = dict((name, None) for name in config)
94
95 samba_servers = list(get_sambas(ctx=ctx, roles=config.keys()))
96
97 testdir = teuthology.get_testdir(ctx)
98
99 if not hasattr(ctx, 'daemons'):
100 ctx.daemons = DaemonGroup()
101
102 for id_, remote in samba_servers:
103
104 rolestr = "samba.{id_}".format(id_=id_)
105
106 confextras = """vfs objects = ceph
107 ceph:config_file = /etc/ceph/ceph.conf"""
108
109 unc = "ceph"
110 backend = "/"
111
112 if config[rolestr] is not None:
113 # verify that there's just one parameter in role
114 if len(config[rolestr]) != 1:
115 log.error("samba config for role samba.{id_} must have only one parameter".format(id_=id_))
116 raise Exception('invalid config')
117 confextras = ""
118 (unc, backendstr) = config[rolestr].items()[0]
119 backend = backendstr.format(testdir=testdir)
120
121 # on first samba role, set ownership and permissions of ceph root
122 # so that samba tests succeed
123 if config[rolestr] is None and id_ == samba_servers[0][0]:
124 remote.run(
125 args=[
126 'mkdir', '-p', '/tmp/cmnt', run.Raw('&&'),
127 'sudo', 'ceph-fuse', '/tmp/cmnt', run.Raw('&&'),
128 'sudo', 'chown', 'ubuntu:ubuntu', '/tmp/cmnt/', run.Raw('&&'),
129 'sudo', 'chmod', '1777', '/tmp/cmnt/', run.Raw('&&'),
130 'sudo', 'umount', '/tmp/cmnt/', run.Raw('&&'),
131 'rm', '-rf', '/tmp/cmnt',
132 ],
133 )
134 else:
135 remote.run(
136 args=[
137 'sudo', 'chown', 'ubuntu:ubuntu', backend, run.Raw('&&'),
138 'sudo', 'chmod', '1777', backend,
139 ],
140 )
141
142 teuthology.sudo_write_file(remote, "/usr/local/samba/etc/smb.conf", """
143 [global]
144 workgroup = WORKGROUP
145 netbios name = DOMAIN
146
147 [{unc}]
148 path = {backend}
149 {extras}
150 writeable = yes
151 valid users = ubuntu
152 """.format(extras=confextras, unc=unc, backend=backend))
153
154 # create ubuntu user
155 remote.run(
156 args=[
157 'sudo', '/usr/local/samba/bin/smbpasswd', '-e', 'ubuntu',
158 run.Raw('||'),
159 'printf', run.Raw('"ubuntu\nubuntu\n"'),
160 run.Raw('|'),
161 'sudo', '/usr/local/samba/bin/smbpasswd', '-s', '-a', 'ubuntu'
162 ])
163
164 smbd_cmd = [
165 'sudo',
166 'daemon-helper',
167 'term',
168 'nostdin',
169 '/usr/local/samba/sbin/smbd',
170 '-F',
171 ]
172 ctx.daemons.add_daemon(remote, 'smbd', id_,
173 args=smbd_cmd,
174 logger=log.getChild("smbd.{id_}".format(id_=id_)),
175 stdin=run.PIPE,
176 wait=False,
177 )
178
179 # let smbd initialize, probably a better way...
180 seconds_to_sleep = 100
181 log.info('Sleeping for %s seconds...' % seconds_to_sleep)
182 time.sleep(seconds_to_sleep)
183 log.info('Sleeping stopped...')
184
185 try:
186 yield
187 finally:
188 log.info('Stopping smbd processes...')
189 exc_info = (None, None, None)
190 for d in ctx.daemons.iter_daemons_of_role('smbd'):
191 try:
192 d.stop()
193 except (run.CommandFailedError,
194 run.CommandCrashedError,
195 run.ConnectionLostError):
196 exc_info = sys.exc_info()
197 log.exception('Saw exception from %s.%s', d.role, d.id_)
198 if exc_info != (None, None, None):
199 raise exc_info[0], exc_info[1], exc_info[2]
200
201 for id_, remote in samba_servers:
202 remote.run(
203 args=[
204 'sudo',
205 'rm', '-rf',
206 '/usr/local/samba/etc/smb.conf',
207 '/usr/local/samba/private/*',
208 '/usr/local/samba/var/run/',
209 '/usr/local/samba/var/locks',
210 '/usr/local/samba/var/lock',
211 ],
212 )
213 # make sure daemons are gone
214 try:
215 remote.run(
216 args=[
217 'while',
218 'sudo', 'killall', '-9', 'smbd',
219 run.Raw(';'),
220 'do', 'sleep', '1',
221 run.Raw(';'),
222 'done',
223 ],
224 )
225
226 remote.run(
227 args=[
228 'sudo',
229 'lsof',
230 backend,
231 ],
232 check_status=False
233 )
234 remote.run(
235 args=[
236 'sudo',
237 'fuser',
238 '-M',
239 backend,
240 ],
241 check_status=False
242 )
243 except Exception:
244 log.exception("Saw exception")
245 pass