]> git.proxmox.com Git - ceph.git/blame - ceph/qa/tasks/admin_socket.py
buildsys: switch source download to quincy
[ceph.git] / ceph / qa / tasks / admin_socket.py
CommitLineData
7c673cae
FG
1"""
2Admin Socket task -- used in rados, powercycle, and smoke testing
3"""
7c673cae
FG
4
5import json
6import logging
7import os
8import time
9
9f95a23c 10from teuthology.exceptions import CommandFailedError
7c673cae
FG
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:
9f95a23c 71 for client, tests in config.items():
7c673cae
FG
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 """
7c673cae
FG
87 testdir = teuthology.get_testdir(ctx)
88 max_tries = 120
89 while True:
9f95a23c
TL
90 try:
91 out = remote.sh([
7c673cae
FG
92 'sudo',
93 'adjust-ulimits',
94 'ceph-coverage',
95 '{tdir}/archive/coverage'.format(tdir=testdir),
96 'ceph',
97 '--admin-daemon', socket_path,
9f95a23c
TL
98 ] + command.split(' ') + args)
99 except CommandFailedError:
100 assert max_tries > 0
101 max_tries -= 1
102 log.info('ceph cli returned an error, command not registered yet?')
103 log.info('sleeping and retrying ...')
104 time.sleep(1)
105 continue
106 break
7c673cae
FG
107 log.debug('admin socket command %s returned %s', command, out)
108 return json.loads(out)
109
110def _run_tests(ctx, client, tests):
111 """
112 Create a temp directory and wait for a client socket to be created.
113 For each test, copy the executable locally and run the test.
114 Remove temp directory when finished.
115
116 :param ctx: Context
117 :param client: client machine to run the test
118 :param tests: list of tests to run
119 """
120 testdir = teuthology.get_testdir(ctx)
121 log.debug('Running admin socket tests on %s', client)
9f95a23c 122 (remote,) = ctx.cluster.only(client).remotes.keys()
7c673cae
FG
123 socket_path = '/var/run/ceph/ceph-{name}.asok'.format(name=client)
124 overrides = ctx.config.get('overrides', {}).get('admin_socket', {})
125
126 try:
127 tmp_dir = os.path.join(
128 testdir,
129 'admin_socket_{client}'.format(client=client),
130 )
131 remote.run(
132 args=[
133 'mkdir',
134 '--',
135 tmp_dir,
136 run.Raw('&&'),
137 # wait for client process to create the socket
138 'while', 'test', '!', '-e', socket_path, run.Raw(';'),
139 'do', 'sleep', '1', run.Raw(';'), 'done',
140 ],
141 )
142
9f95a23c 143 for command, config in tests.items():
7c673cae
FG
144 if config is None:
145 config = {}
146 teuthology.deep_merge(config, overrides)
147 log.debug('Testing %s with config %s', command, str(config))
148
149 test_path = None
150 if 'test' in config:
151 # hack: the git_url is always ceph-ci or ceph
152 git_url = teuth_config.get_ceph_git_url()
153 repo_name = 'ceph.git'
154 if git_url.count('ceph-ci'):
155 repo_name = 'ceph-ci.git'
156 url = config['test'].format(
157 branch=config.get('branch', 'master'),
158 repo=repo_name,
159 )
160 test_path = os.path.join(tmp_dir, command)
161 remote.run(
162 args=[
163 'wget',
164 '-q',
165 '-O',
166 test_path,
167 '--',
168 url,
169 run.Raw('&&'),
170 'chmod',
171 'u=rx',
172 '--',
173 test_path,
174 ],
175 )
176
177 args = config.get('args', [])
178 assert isinstance(args, list), \
179 'admin socket command args must be a list'
180 sock_out = _socket_command(ctx, remote, socket_path, command, args)
181 if test_path is not None:
182 remote.run(
183 args=[
184 test_path,
185 ],
186 stdin=json.dumps(sock_out),
187 )
188
189 finally:
190 remote.run(
191 args=[
192 'rm', '-rf', '--', tmp_dir,
193 ],
194 )