]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | """ |
2 | Run rados gateway agent in test mode | |
3 | """ | |
4 | import contextlib | |
5 | import logging | |
6 | import argparse | |
7 | ||
8 | from teuthology.orchestra import run | |
9 | from teuthology import misc as teuthology | |
10 | import util.rgw as rgw_utils | |
11 | ||
12 | log = logging.getLogger(__name__) | |
13 | ||
14 | def run_radosgw_agent(ctx, config): | |
15 | """ | |
16 | Run a single radosgw-agent. See task() for config format. | |
17 | """ | |
18 | return_list = list() | |
19 | for (client, cconf) in config.items(): | |
20 | # don't process entries that are not clients | |
21 | log.debug("client is %r", client) | |
22 | if not 'client.' in client: | |
23 | log.debug('key {data} does not contain \'client.\', moving on'.format( | |
24 | data=client)) | |
25 | continue | |
26 | ||
27 | src_client = cconf['src'] | |
28 | dest_client = cconf['dest'] | |
29 | ||
30 | src_zone = rgw_utils.zone_for_client(ctx, src_client) | |
31 | dest_zone = rgw_utils.zone_for_client(ctx, dest_client) | |
32 | ||
33 | log.info("source is %s", src_zone) | |
34 | log.info("dest is %s", dest_zone) | |
35 | ||
36 | testdir = teuthology.get_testdir(ctx) | |
37 | (remote,) = ctx.cluster.only(client).remotes.keys() | |
38 | # figure out which branch to pull from | |
39 | branch = cconf.get('force-branch', None) | |
40 | if not branch: | |
41 | branch = cconf.get('branch', 'master') | |
42 | sha1 = cconf.get('sha1') | |
43 | remote.run( | |
44 | args=[ | |
45 | 'cd', testdir, run.Raw('&&'), | |
46 | 'git', 'clone', | |
47 | '-b', branch, | |
48 | # 'https://github.com/ceph/radosgw-agent.git', | |
49 | 'git://git.ceph.com/radosgw-agent.git', | |
50 | 'radosgw-agent.{client}'.format(client=client), | |
51 | ] | |
52 | ) | |
53 | if sha1 is not None: | |
54 | remote.run( | |
55 | args=[ | |
56 | 'cd', testdir, run.Raw('&&'), | |
57 | run.Raw('&&'), | |
58 | 'git', 'reset', '--hard', sha1, | |
59 | ] | |
60 | ) | |
61 | remote.run( | |
62 | args=[ | |
63 | 'cd', testdir, run.Raw('&&'), | |
64 | 'cd', 'radosgw-agent.{client}'.format(client=client), | |
65 | run.Raw('&&'), | |
66 | './bootstrap', | |
67 | ] | |
68 | ) | |
69 | ||
70 | src_host, src_port = rgw_utils.get_zone_host_and_port(ctx, src_client, | |
71 | src_zone) | |
72 | dest_host, dest_port = rgw_utils.get_zone_host_and_port(ctx, dest_client, | |
73 | dest_zone) | |
74 | src_access, src_secret = rgw_utils.get_zone_system_keys(ctx, src_client, | |
75 | src_zone) | |
76 | dest_access, dest_secret = rgw_utils.get_zone_system_keys(ctx, dest_client, | |
77 | dest_zone) | |
78 | sync_scope = cconf.get('sync-scope', None) | |
79 | port = cconf.get('port', 8000) | |
80 | daemon_name = '{host}.{port}.syncdaemon'.format(host=remote.name, port=port) | |
81 | in_args=[ | |
82 | 'daemon-helper', | |
83 | 'kill', | |
84 | '{tdir}/radosgw-agent.{client}/radosgw-agent'.format(tdir=testdir, | |
85 | client=client), | |
86 | '-v', | |
87 | '--src-access-key', src_access, | |
88 | '--src-secret-key', src_secret, | |
89 | '--source', "http://{addr}:{port}".format(addr=src_host, port=src_port), | |
90 | '--dest-access-key', dest_access, | |
91 | '--dest-secret-key', dest_secret, | |
92 | '--max-entries', str(cconf.get('max-entries', 1000)), | |
93 | '--log-file', '{tdir}/archive/rgw_sync_agent.{client}.log'.format( | |
94 | tdir=testdir, | |
95 | client=client), | |
96 | '--object-sync-timeout', '30', | |
97 | ] | |
98 | ||
99 | if cconf.get('metadata-only', False): | |
100 | in_args.append('--metadata-only') | |
101 | ||
102 | # the test server and full/incremental flags are mutually exclusive | |
103 | if sync_scope is None: | |
104 | in_args.append('--test-server-host') | |
105 | in_args.append('0.0.0.0') | |
106 | in_args.append('--test-server-port') | |
107 | in_args.append(str(port)) | |
108 | log.debug('Starting a sync test server on {client}'.format(client=client)) | |
109 | # Stash the radosgw-agent server / port # for use by subsequent tasks | |
110 | ctx.radosgw_agent.endpoint = (client, str(port)) | |
111 | else: | |
112 | in_args.append('--sync-scope') | |
113 | in_args.append(sync_scope) | |
114 | log.debug('Starting a {scope} sync on {client}'.format(scope=sync_scope,client=client)) | |
115 | ||
116 | # positional arg for destination must come last | |
117 | in_args.append("http://{addr}:{port}".format(addr=dest_host, | |
118 | port=dest_port)) | |
119 | ||
120 | return_list.append((client, remote.run( | |
121 | args=in_args, | |
122 | wait=False, | |
123 | stdin=run.PIPE, | |
124 | logger=log.getChild(daemon_name), | |
125 | ))) | |
126 | return return_list | |
127 | ||
128 | ||
129 | @contextlib.contextmanager | |
130 | def task(ctx, config): | |
131 | """ | |
132 | Run radosgw-agents in test mode. | |
133 | ||
134 | Configuration is clients to run the agents on, with settings for | |
135 | source client, destination client, and port to listen on. Binds | |
136 | to 0.0.0.0. Port defaults to 8000. This must be run on clients | |
137 | that have the correct zone root pools and rgw zone set in | |
138 | ceph.conf, or the task cannot read the region information from the | |
139 | cluster. | |
140 | ||
141 | By default, this task will start an HTTP server that will trigger full | |
142 | or incremental syncs based on requests made to it. | |
143 | Alternatively, a single full sync can be triggered by | |
144 | specifying 'sync-scope: full' or a loop of incremental syncs can be triggered | |
145 | by specifying 'sync-scope: incremental' (the loop will sleep | |
146 | '--incremental-sync-delay' seconds between each sync, default is 30 seconds). | |
147 | ||
148 | By default, both data and metadata are synced. To only sync | |
149 | metadata, for example because you want to sync between regions, | |
150 | set metadata-only: true. | |
151 | ||
152 | An example:: | |
153 | ||
154 | tasks: | |
155 | - ceph: | |
156 | conf: | |
157 | client.0: | |
158 | rgw zone = foo | |
159 | rgw zone root pool = .root.pool | |
160 | client.1: | |
161 | rgw zone = bar | |
162 | rgw zone root pool = .root.pool2 | |
163 | - rgw: # region configuration omitted for brevity | |
164 | - radosgw-agent: | |
165 | client.0: | |
166 | branch: wip-next-feature-branch | |
167 | src: client.0 | |
168 | dest: client.1 | |
169 | sync-scope: full | |
170 | metadata-only: true | |
171 | # port: 8000 (default) | |
172 | client.1: | |
173 | src: client.1 | |
174 | dest: client.0 | |
175 | port: 8001 | |
176 | """ | |
177 | assert isinstance(config, dict), 'rgw_sync_agent requires a dictionary config' | |
178 | log.debug("config is %s", config) | |
179 | ||
180 | overrides = ctx.config.get('overrides', {}) | |
181 | # merge each client section, but only if it exists in config since there isn't | |
182 | # a sensible default action for this task | |
183 | for client in config.iterkeys(): | |
184 | if config[client]: | |
185 | log.debug('config[{client}]: {data}'.format(client=client, data=config[client])) | |
186 | teuthology.deep_merge(config[client], overrides.get('radosgw-agent', {})) | |
187 | ||
188 | ctx.radosgw_agent = argparse.Namespace() | |
189 | ctx.radosgw_agent.config = config | |
190 | ||
191 | procs = run_radosgw_agent(ctx, config) | |
192 | ||
193 | ctx.radosgw_agent.procs = procs | |
194 | ||
195 | try: | |
196 | yield | |
197 | finally: | |
198 | testdir = teuthology.get_testdir(ctx) | |
199 | try: | |
200 | for client, proc in procs: | |
201 | log.info("shutting down sync agent on %s", client) | |
202 | proc.stdin.close() | |
203 | proc.wait() | |
204 | finally: | |
205 | for client, proc in procs: | |
206 | ctx.cluster.only(client).run( | |
207 | args=[ | |
208 | 'rm', '-rf', | |
209 | '{tdir}/radosgw-agent.{client}'.format(tdir=testdir, | |
210 | client=client) | |
211 | ] | |
212 | ) |