]> git.proxmox.com Git - ceph.git/blame - ceph/qa/tasks/admin_socket.py
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / qa / tasks / admin_socket.py
CommitLineData
7c673cae
FG
1"""
2Admin Socket task -- used in rados, powercycle, and smoke testing
3"""
4from cStringIO import StringIO
5
6import json
7import logging
8import os
9import time
10
11from teuthology.orchestra import run
12from teuthology import misc as teuthology
13from teuthology.parallel import parallel
14from teuthology.config import config as teuth_config
15
16log = logging.getLogger(__name__)
17
18
19def task(ctx, config):
20 """
21 Run an admin socket command, make sure the output is json, and run
22 a test program on it. The test program should read json from
23 stdin. This task succeeds if the test program exits with status 0.
24
25 To run the same test on all clients::
26
27 tasks:
28 - ceph:
29 - rados:
30 - admin_socket:
31 all:
32 dump_requests:
33 test: http://example.com/script
34
35 To restrict it to certain clients::
36
37 tasks:
38 - ceph:
39 - rados: [client.1]
40 - admin_socket:
41 client.1:
42 dump_requests:
43 test: http://example.com/script
44
45 If an admin socket command has arguments, they can be specified as
46 a list::
47
48 tasks:
49 - ceph:
50 - rados: [client.0]
51 - admin_socket:
52 client.0:
53 dump_requests:
54 test: http://example.com/script
55 help:
56 test: http://example.com/test_help_version
57 args: [version]
58
59 Note that there must be a ceph client with an admin socket running
60 before this task is run. The tests are parallelized at the client
61 level. Tests for a single client are run serially.
62
63 :param ctx: Context
64 :param config: Configuration
65 """
66 assert isinstance(config, dict), \
67 'admin_socket task requires a dict for configuration'
68 teuthology.replace_all_with_clients(ctx.cluster, config)
69
70 with parallel() as ptask:
71 for client, tests in config.iteritems():
72 ptask.spawn(_run_tests, ctx, client, tests)
73
74
75def _socket_command(ctx, remote, socket_path, command, args):
76 """
77 Run an admin socket command and return the result as a string.
78
79 :param ctx: Context
80 :param remote: Remote site
81 :param socket_path: path to socket
82 :param command: command to be run remotely
83 :param args: command arguments
84
85 :returns: output of command in json format
86 """
87 json_fp = StringIO()
88 testdir = teuthology.get_testdir(ctx)
89 max_tries = 120
90 while True:
91 proc = remote.run(
92 args=[
93 'sudo',
94 'adjust-ulimits',
95 'ceph-coverage',
96 '{tdir}/archive/coverage'.format(tdir=testdir),
97 'ceph',
98 '--admin-daemon', socket_path,
99 ] + command.split(' ') + args,
100 stdout=json_fp,
101 check_status=False,
102 )
103 if proc.exitstatus == 0:
104 break
105 assert max_tries > 0
106 max_tries -= 1
107 log.info('ceph cli returned an error, command not registered yet?')
108 log.info('sleeping and retrying ...')
109 time.sleep(1)
110 out = json_fp.getvalue()
111 json_fp.close()
112 log.debug('admin socket command %s returned %s', command, out)
113 return json.loads(out)
114
115def _run_tests(ctx, client, tests):
116 """
117 Create a temp directory and wait for a client socket to be created.
118 For each test, copy the executable locally and run the test.
119 Remove temp directory when finished.
120
121 :param ctx: Context
122 :param client: client machine to run the test
123 :param tests: list of tests to run
124 """
125 testdir = teuthology.get_testdir(ctx)
126 log.debug('Running admin socket tests on %s', client)
127 (remote,) = ctx.cluster.only(client).remotes.iterkeys()
128 socket_path = '/var/run/ceph/ceph-{name}.asok'.format(name=client)
129 overrides = ctx.config.get('overrides', {}).get('admin_socket', {})
130
131 try:
132 tmp_dir = os.path.join(
133 testdir,
134 'admin_socket_{client}'.format(client=client),
135 )
136 remote.run(
137 args=[
138 'mkdir',
139 '--',
140 tmp_dir,
141 run.Raw('&&'),
142 # wait for client process to create the socket
143 'while', 'test', '!', '-e', socket_path, run.Raw(';'),
144 'do', 'sleep', '1', run.Raw(';'), 'done',
145 ],
146 )
147
148 for command, config in tests.iteritems():
149 if config is None:
150 config = {}
151 teuthology.deep_merge(config, overrides)
152 log.debug('Testing %s with config %s', command, str(config))
153
154 test_path = None
155 if 'test' in config:
156 # hack: the git_url is always ceph-ci or ceph
157 git_url = teuth_config.get_ceph_git_url()
158 repo_name = 'ceph.git'
159 if git_url.count('ceph-ci'):
160 repo_name = 'ceph-ci.git'
161 url = config['test'].format(
162 branch=config.get('branch', 'master'),
163 repo=repo_name,
164 )
165 test_path = os.path.join(tmp_dir, command)
166 remote.run(
167 args=[
168 'wget',
169 '-q',
170 '-O',
171 test_path,
172 '--',
173 url,
174 run.Raw('&&'),
175 'chmod',
176 'u=rx',
177 '--',
178 test_path,
179 ],
180 )
181
182 args = config.get('args', [])
183 assert isinstance(args, list), \
184 'admin socket command args must be a list'
185 sock_out = _socket_command(ctx, remote, socket_path, command, args)
186 if test_path is not None:
187 remote.run(
188 args=[
189 test_path,
190 ],
191 stdin=json.dumps(sock_out),
192 )
193
194 finally:
195 remote.run(
196 args=[
197 'rm', '-rf', '--', tmp_dir,
198 ],
199 )