1 package org.apache.helix.webapp;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.IOException;
23 import java.io.StringReader;
24 import java.io.StringWriter;
25 import java.util.ArrayList;
26 import java.util.HashMap;
27 import java.util.List;
28 import java.util.Map;
29
30 import org.apache.helix.PropertyPathConfig;
31 import org.apache.helix.PropertyType;
32 import org.apache.helix.ZNRecord;
33 import org.apache.helix.model.StateModelDefinition;
34 import org.apache.helix.model.InstanceConfig.InstanceConfigProperty;
35 import org.apache.helix.tools.AdminTestBase;
36 import org.apache.helix.tools.ClusterSetup;
37 import org.apache.helix.webapp.resources.ClusterRepresentationUtil;
38 import org.apache.helix.webapp.resources.JsonParameters;
39 import org.codehaus.jackson.JsonGenerationException;
40 import org.codehaus.jackson.map.JsonMappingException;
41 import org.codehaus.jackson.map.ObjectMapper;
42 import org.codehaus.jackson.type.TypeReference;
43 import org.restlet.Client;
44 import org.restlet.data.MediaType;
45 import org.restlet.data.Method;
46 import org.restlet.data.Protocol;
47 import org.restlet.data.Reference;
48 import org.restlet.data.Request;
49 import org.restlet.data.Response;
50 import org.restlet.resource.Representation;
51 import org.testng.Assert;
52 import org.testng.AssertJUnit;
53 import org.testng.annotations.Test;
54
55
56 public class TestClusterManagementWebapp extends AdminTestBase
57 {
58 @Test
59 public void testInvocation() throws Exception
60 {
61 verifyAddCluster();
62 verifyAddStateModel();
63 verifyAddHostedEntity();
64 verifyAddInstance();
65 verifyRebalance();
66 verifyEnableInstance();
67 verifyAlterIdealState();
68 verifyConfigAccessor();
69
70 verifyEnableCluster();
71
72 System.out.println("Test passed!!");
73 }
74
75
76
77
78 String clusterName = "cluster-12345";
79 String resourceGroupName = "new-entity-12345";
80 String instance1 = "test-1";
81 String statemodel = "state_model";
82 int instancePort = 9999;
83 int partitions = 10;
84 int replicas = 3;
85
86 void verifyAddStateModel() throws JsonGenerationException,
87 JsonMappingException,
88 IOException
89 {
90 String httpUrlBase =
91 "http://localhost:" + ADMIN_PORT + "/clusters/" + clusterName
92 + "/StateModelDefs/MasterSlave";
93 Reference resourceRef = new Reference(httpUrlBase);
94 Request request = new Request(Method.GET, resourceRef);
95 Client client = new Client(Protocol.HTTP);
96 Response response = client.handle(request);
97 Representation result = response.getEntity();
98 StringWriter sw = new StringWriter();
99 result.write(sw);
100 ObjectMapper mapper = new ObjectMapper();
101 ZNRecord zn = mapper.readValue(new StringReader(sw.toString()), ZNRecord.class);
102
103 Map<String, String> paraMap = new HashMap<String, String>();
104
105 paraMap.put(JsonParameters.MANAGEMENT_COMMAND,
106 ClusterSetup.addStateModelDef);
107
108 ZNRecord r = new ZNRecord("Test");
109 r.merge(zn);
110 StateModelDefinition newStateModel = new StateModelDefinition(r);
111
112 httpUrlBase =
113 "http://localhost:" + ADMIN_PORT + "/clusters/" + clusterName + "/StateModelDefs";
114 resourceRef = new Reference(httpUrlBase);
115 request = new Request(Method.POST, resourceRef);
116 request.setEntity(JsonParameters.JSON_PARAMETERS + "="
117 + ClusterRepresentationUtil.ObjectToJson(paraMap) + "&"
118 + JsonParameters.NEW_STATE_MODEL_DEF + "="
119 + ClusterRepresentationUtil.ZNRecordToJson(r),
120 MediaType.APPLICATION_ALL);
121 client = new Client(Protocol.HTTP);
122 response = client.handle(request);
123
124 result = response.getEntity();
125 sw = new StringWriter();
126 result.write(sw);
127
128
129
130 AssertJUnit.assertTrue(sw.toString().contains("Test"));
131 }
132
133 void verifyAddCluster() throws IOException,
134 InterruptedException
135 {
136 String httpUrlBase = "http://localhost:" + ADMIN_PORT + "/clusters";
137 Map<String, String> paraMap = new HashMap<String, String>();
138
139 paraMap.put(JsonParameters.CLUSTER_NAME, clusterName);
140 paraMap.put(JsonParameters.MANAGEMENT_COMMAND, ClusterSetup.addCluster);
141
142 Reference resourceRef = new Reference(httpUrlBase);
143
144 Request request = new Request(Method.POST, resourceRef);
145
146 request.setEntity(JsonParameters.JSON_PARAMETERS + "="
147 + ClusterRepresentationUtil.ObjectToJson(paraMap), MediaType.APPLICATION_ALL);
148 Client client = new Client(Protocol.HTTP);
149 Response response = client.handle(request);
150
151 Representation result = response.getEntity();
152 StringWriter sw = new StringWriter();
153 result.write(sw);
154
155
156
157 ObjectMapper mapper = new ObjectMapper();
158 ZNRecord zn = mapper.readValue(new StringReader(sw.toString()), ZNRecord.class);
159 AssertJUnit.assertTrue(zn.getListField("clusters").contains(clusterName));
160
161 }
162
163 void verifyAddHostedEntity() throws JsonGenerationException,
164 JsonMappingException,
165 IOException
166 {
167 String httpUrlBase =
168 "http://localhost:" + ADMIN_PORT + "/clusters/" + clusterName + "/resourceGroups";
169 Map<String, String> paraMap = new HashMap<String, String>();
170
171 paraMap.put(JsonParameters.RESOURCE_GROUP_NAME, resourceGroupName);
172 paraMap.put(JsonParameters.PARTITIONS, "" + partitions);
173 paraMap.put(JsonParameters.STATE_MODEL_DEF_REF, "MasterSlave");
174 paraMap.put(JsonParameters.MANAGEMENT_COMMAND, ClusterSetup.addResource);
175
176 Reference resourceRef = new Reference(httpUrlBase);
177
178 Request request = new Request(Method.POST, resourceRef);
179
180 request.setEntity(JsonParameters.JSON_PARAMETERS + "="
181 + ClusterRepresentationUtil.ObjectToJson(paraMap), MediaType.APPLICATION_ALL);
182 Client client = new Client(Protocol.HTTP);
183 Response response = client.handle(request);
184
185 Representation result = response.getEntity();
186 StringWriter sw = new StringWriter();
187 result.write(sw);
188
189
190
191 ObjectMapper mapper = new ObjectMapper();
192 ZNRecord zn = mapper.readValue(new StringReader(sw.toString()), ZNRecord.class);
193 AssertJUnit.assertTrue(zn.getListField("ResourceGroups").contains(resourceGroupName));
194
195 httpUrlBase =
196 "http://localhost:" + ADMIN_PORT + "/clusters/" + clusterName + "/resourceGroups/"
197 + resourceGroupName;
198 resourceRef = new Reference(httpUrlBase);
199
200 request = new Request(Method.GET, resourceRef);
201
202 client = new Client(Protocol.HTTP);
203 response = client.handle(request);
204
205 result = response.getEntity();
206 sw = new StringWriter();
207 result.write(sw);
208
209
210 }
211
212 void verifyAddInstance() throws JsonGenerationException,
213 JsonMappingException,
214 IOException
215 {
216 String httpUrlBase =
217 "http://localhost:" + ADMIN_PORT + "/clusters/" + clusterName + "/instances";
218 Map<String, String> paraMap = new HashMap<String, String>();
219
220 paraMap.put(JsonParameters.INSTANCE_NAME, instance1 + ":" + instancePort);
221 paraMap.put(JsonParameters.MANAGEMENT_COMMAND, ClusterSetup.addInstance);
222
223 Reference resourceRef = new Reference(httpUrlBase);
224
225 Request request = new Request(Method.POST, resourceRef);
226
227 request.setEntity(JsonParameters.JSON_PARAMETERS + "="
228 + ClusterRepresentationUtil.ObjectToJson(paraMap), MediaType.APPLICATION_ALL);
229 Client client = new Client(Protocol.HTTP);
230 Response response = client.handle(request);
231
232 Representation result = response.getEntity();
233 StringWriter sw = new StringWriter();
234 result.write(sw);
235
236
237
238 ObjectMapper mapper = new ObjectMapper();
239
240 TypeReference<ArrayList<ZNRecord>> typeRef = new TypeReference<ArrayList<ZNRecord>>()
241 {
242 };
243 List<ZNRecord> znList = mapper.readValue(new StringReader(sw.toString()), typeRef);
244 AssertJUnit.assertTrue(znList.get(0).getId().equals(instance1 + "_" + instancePort));
245
246
247 paraMap.clear();
248 paraMap.put(JsonParameters.MANAGEMENT_COMMAND, ClusterSetup.addInstance);
249
250 String[] instances = { "test2", "test3", "test4", "test5" };
251
252 String instanceNames = "";
253 boolean first = true;
254 for (String instance : instances)
255 {
256 if (first == true)
257 {
258 first = false;
259 }
260 else
261 {
262 instanceNames += ";";
263 }
264 instanceNames += (instance + ":" + instancePort);
265 }
266 paraMap.put(JsonParameters.INSTANCE_NAMES, instanceNames);
267
268 request = new Request(Method.POST, resourceRef);
269
270 request.setEntity(JsonParameters.JSON_PARAMETERS + "="
271 + ClusterRepresentationUtil.ObjectToJson(paraMap), MediaType.APPLICATION_ALL);
272 client = new Client(Protocol.HTTP);
273 response = client.handle(request);
274
275 result = response.getEntity();
276 sw = new StringWriter();
277 result.write(sw);
278
279
280
281 mapper = new ObjectMapper();
282
283 znList = mapper.readValue(new StringReader(sw.toString()), typeRef);
284
285 for (String instance : instances)
286 {
287 boolean found = false;
288 for (ZNRecord r : znList)
289 {
290 String instanceId = instance + "_" + instancePort;
291 if (r.getId().equals(instanceId))
292 {
293 found = true;
294 break;
295 }
296 }
297 AssertJUnit.assertTrue(found);
298 }
299 }
300
301 void verifyRebalance() throws JsonGenerationException,
302 JsonMappingException,
303 IOException
304 {
305 String httpUrlBase =
306 "http://localhost:" + ADMIN_PORT + "/clusters/" + clusterName + "/resourceGroups/"
307 + resourceGroupName + "/idealState";
308 Map<String, String> paraMap = new HashMap<String, String>();
309
310 paraMap.put(JsonParameters.REPLICAS, "" + replicas);
311 paraMap.put(JsonParameters.MANAGEMENT_COMMAND, ClusterSetup.rebalance);
312
313 Reference resourceRef = new Reference(httpUrlBase);
314
315 Request request = new Request(Method.POST, resourceRef);
316
317 request.setEntity(JsonParameters.JSON_PARAMETERS + "="
318 + ClusterRepresentationUtil.ObjectToJson(paraMap), MediaType.APPLICATION_ALL);
319 Client client = new Client(Protocol.HTTP);
320 Response response = client.handle(request);
321
322 Representation result = response.getEntity();
323 StringWriter sw = new StringWriter();
324 result.write(sw);
325
326
327
328 ObjectMapper mapper = new ObjectMapper();
329 ZNRecord r = mapper.readValue(new StringReader(sw.toString()), ZNRecord.class);
330
331 for (int i = 0; i < partitions; i++)
332 {
333 String partitionName = resourceGroupName + "_" + i;
334 assert (r.getMapField(partitionName).size() == replicas);
335 }
336
337 httpUrlBase = "http://localhost:" + ADMIN_PORT + "/clusters/" + clusterName;
338 resourceRef = new Reference(httpUrlBase);
339 request = new Request(Method.GET, resourceRef);
340
341 client = new Client(Protocol.HTTP);
342 response = client.handle(request);
343
344 result = response.getEntity();
345 sw = new StringWriter();
346 result.write(sw);
347
348 }
349
350 void verifyEnableInstance() throws JsonGenerationException,
351 JsonMappingException,
352 IOException
353 {
354 String httpUrlBase =
355 "http://localhost:" + ADMIN_PORT + "/clusters/" + clusterName + "/instances/"
356 + instance1 + "_" + instancePort;
357 Map<String, String> paraMap = new HashMap<String, String>();
358
359 paraMap.put(JsonParameters.ENABLED, "" + false);
360 paraMap.put(JsonParameters.MANAGEMENT_COMMAND, ClusterSetup.enableInstance);
361
362 Reference resourceRef = new Reference(httpUrlBase);
363
364 Request request = new Request(Method.POST, resourceRef);
365
366 request.setEntity(JsonParameters.JSON_PARAMETERS + "="
367 + ClusterRepresentationUtil.ObjectToJson(paraMap), MediaType.APPLICATION_ALL);
368 Client client = new Client(Protocol.HTTP);
369 Response response = client.handle(request);
370
371 Representation result = response.getEntity();
372 StringWriter sw = new StringWriter();
373 result.write(sw);
374
375
376
377 ObjectMapper mapper = new ObjectMapper();
378 ZNRecord r = mapper.readValue(new StringReader(sw.toString()), ZNRecord.class);
379 AssertJUnit.assertTrue(r.getSimpleField(InstanceConfigProperty.HELIX_ENABLED.toString())
380 .equals("" + false));
381
382
383 paraMap.put(JsonParameters.ENABLED, "" + true);
384 request = new Request(Method.POST, resourceRef);
385
386 request.setEntity(JsonParameters.JSON_PARAMETERS + "="
387 + ClusterRepresentationUtil.ObjectToJson(paraMap), MediaType.APPLICATION_ALL);
388 client = new Client(Protocol.HTTP);
389 response = client.handle(request);
390
391 result = response.getEntity();
392 sw = new StringWriter();
393 result.write(sw);
394
395
396
397 mapper = new ObjectMapper();
398 r = mapper.readValue(new StringReader(sw.toString()), ZNRecord.class);
399 AssertJUnit.assertTrue(r.getSimpleField(InstanceConfigProperty.HELIX_ENABLED.toString())
400 .equals("" + true));
401 }
402
403 void verifyAlterIdealState() throws IOException
404 {
405 String httpUrlBase =
406 "http://localhost:" + ADMIN_PORT + "/clusters/" + clusterName + "/resourceGroups/"
407 + resourceGroupName + "/idealState";
408
409 Reference resourceRef = new Reference(httpUrlBase);
410 Request request = new Request(Method.GET, resourceRef);
411
412 Client client = new Client(Protocol.HTTP);
413 Response response = client.handle(request);
414
415 Representation result = response.getEntity();
416 StringWriter sw = new StringWriter();
417 result.write(sw);
418
419
420
421 ObjectMapper mapper = new ObjectMapper();
422 ZNRecord r = mapper.readValue(new StringReader(sw.toString()), ZNRecord.class);
423 String partitionName = "new-entity-12345_3";
424 r.getMapFields().remove(partitionName);
425
426 Map<String, String> paraMap = new HashMap<String, String>();
427
428 paraMap.put(JsonParameters.MANAGEMENT_COMMAND, ClusterSetup.addIdealState);
429
430 resourceRef = new Reference(httpUrlBase);
431
432 request = new Request(Method.POST, resourceRef);
433 request.setEntity(JsonParameters.JSON_PARAMETERS + "="
434 + ClusterRepresentationUtil.ObjectToJson(paraMap) + "&"
435 + JsonParameters.NEW_IDEAL_STATE + "="
436 + ClusterRepresentationUtil.ZNRecordToJson(r),
437 MediaType.APPLICATION_ALL);
438 client = new Client(Protocol.HTTP);
439 response = client.handle(request);
440
441 result = response.getEntity();
442 sw = new StringWriter();
443 result.write(sw);
444
445
446
447 mapper = new ObjectMapper();
448 ZNRecord r2 = mapper.readValue(new StringReader(sw.toString()), ZNRecord.class);
449 AssertJUnit.assertTrue(!r2.getMapFields().containsKey(partitionName));
450
451 for (String key : r2.getMapFields().keySet())
452 {
453 AssertJUnit.assertTrue(r.getMapFields().containsKey(key));
454 }
455 }
456
457
458 void verifyConfigAccessor() throws Exception
459 {
460 ObjectMapper mapper = new ObjectMapper();
461 Client client = new Client(Protocol.HTTP);
462
463
464 String url =
465 "http://localhost:" + ADMIN_PORT + "/clusters/" + clusterName + "/configs/cluster/"
466 + clusterName;
467
468 postConfig(client, url, mapper, ClusterSetup.setConfig, "key1=value1,key2=value2");
469
470 ZNRecord record = get(client, url, mapper);
471 Assert.assertEquals(record.getSimpleFields().size(), 2);
472 Assert.assertEquals(record.getSimpleField("key1"), "value1");
473 Assert.assertEquals(record.getSimpleField("key2"), "value2");
474
475
476 String participantName = "test2_9999";
477 url =
478 "http://localhost:" + ADMIN_PORT + "/clusters/" + clusterName
479 + "/configs/participant/" + participantName;
480
481 postConfig(client, url, mapper, ClusterSetup.setConfig, "key3=value3,key4=value4");
482
483 record = get(client, url, mapper);
484 Assert.assertTrue(record.getSimpleFields().size() >= 2, "Should at least contains 2 keys");
485 Assert.assertEquals(record.getSimpleField("key3"), "value3");
486 Assert.assertEquals(record.getSimpleField("key4"), "value4");
487
488
489 url =
490 "http://localhost:" + ADMIN_PORT + "/clusters/" + clusterName
491 + "/configs/resource/testResource";
492
493 postConfig(client, url, mapper, ClusterSetup.setConfig, "key5=value5,key6=value6");
494
495 record = get(client, url, mapper);
496 Assert.assertEquals(record.getSimpleFields().size(), 2);
497 Assert.assertEquals(record.getSimpleField("key5"), "value5");
498 Assert.assertEquals(record.getSimpleField("key6"), "value6");
499
500
501 url =
502 "http://localhost:" + ADMIN_PORT + "/clusters/" + clusterName
503 + "/configs/partition/testResource/testPartition";
504
505 postConfig(client, url, mapper, ClusterSetup.setConfig, "key7=value7,key8=value8");
506
507 record = get(client, url, mapper);
508 Assert.assertEquals(record.getSimpleFields().size(), 2);
509 Assert.assertEquals(record.getSimpleField("key7"), "value7");
510 Assert.assertEquals(record.getSimpleField("key8"), "value8");
511
512
513 url = "http://localhost:" + ADMIN_PORT + "/clusters/" + clusterName + "/configs";
514 record = get(client, url, mapper);
515 Assert.assertEquals(record.getListFields().size(), 1);
516 Assert.assertTrue(record.getListFields().containsKey("scopes"));
517 Assert.assertTrue(contains(record.getListField("scopes"),
518 "CLUSTER",
519 "PARTICIPANT",
520 "RESOURCE",
521 "PARTITION"));
522
523
524
525
526
527
528
529 url =
530 "http://localhost:" + ADMIN_PORT + "/clusters/" + clusterName + "/configs/participant";
531 record = get(client, url, mapper);
532 Assert.assertTrue(record.getListFields().containsKey("PARTICIPANT"));
533 Assert.assertTrue(contains(record.getListField("PARTICIPANT"), participantName));
534
535 url = "http://localhost:" + ADMIN_PORT + "/clusters/" + clusterName + "/configs/resource";
536 record = get(client, url, mapper);
537 Assert.assertEquals(record.getListFields().size(), 1);
538 Assert.assertTrue(record.getListFields().containsKey("RESOURCE"));
539 Assert.assertTrue(contains(record.getListField("RESOURCE"), "testResource"));
540
541 url =
542 "http://localhost:" + ADMIN_PORT + "/clusters/" + clusterName
543 + "/configs/partition/testResource";
544 record = get(client, url, mapper);
545 Assert.assertEquals(record.getListFields().size(), 1);
546 Assert.assertTrue(record.getListFields().containsKey("PARTITION"));
547 Assert.assertTrue(contains(record.getListField("PARTITION"), "testPartition"));
548
549 }
550
551 private ZNRecord get(Client client, String url, ObjectMapper mapper) throws Exception
552 {
553 Request request = new Request(Method.GET, new Reference(url));
554 Response response = client.handle(request);
555 Representation result = response.getEntity();
556 StringWriter sw = new StringWriter();
557 result.write(sw);
558 String responseStr = sw.toString();
559 Assert.assertTrue(responseStr.toLowerCase().indexOf("error") == -1);
560 Assert.assertTrue(responseStr.toLowerCase().indexOf("exception") == -1);
561
562 ZNRecord record = mapper.readValue(new StringReader(responseStr), ZNRecord.class);
563 return record;
564 }
565
566 private void postConfig(Client client,
567 String url,
568 ObjectMapper mapper,
569 String command,
570 String configs) throws Exception
571 {
572 Map<String, String> params = new HashMap<String, String>();
573
574 params.put(JsonParameters.MANAGEMENT_COMMAND, command);
575 params.put(JsonParameters.CONFIGS, configs);
576
577 Request request = new Request(Method.POST, new Reference(url));
578 request.setEntity(JsonParameters.JSON_PARAMETERS + "="
579 + ClusterRepresentationUtil.ObjectToJson(params), MediaType.APPLICATION_ALL);
580
581 Response response = client.handle(request);
582 Representation result = response.getEntity();
583 StringWriter sw = new StringWriter();
584 result.write(sw);
585 String responseStr = sw.toString();
586 Assert.assertTrue(responseStr.toLowerCase().indexOf("error") == -1);
587 Assert.assertTrue(responseStr.toLowerCase().indexOf("exception") == -1);
588 }
589
590 void verifyEnableCluster() throws Exception
591 {
592 System.out.println("START: verifyEnableCluster()");
593 String httpUrlBase =
594 "http://localhost:" + ADMIN_PORT + "/clusters/" + clusterName + "/Controller";
595 Map<String, String> paramMap = new HashMap<String, String>();
596
597 paramMap.put(JsonParameters.MANAGEMENT_COMMAND, ClusterSetup.enableCluster);
598 paramMap.put(JsonParameters.ENABLED, "" + false);
599
600 Reference resourceRef = new Reference(httpUrlBase);
601
602 Request request = new Request(Method.POST, resourceRef);
603
604 request.setEntity(JsonParameters.JSON_PARAMETERS + "="
605 + ClusterRepresentationUtil.ObjectToJson(paramMap), MediaType.APPLICATION_ALL);
606 Client client = new Client(Protocol.HTTP);
607 Response response = client.handle(request);
608
609 Representation result = response.getEntity();
610 StringWriter sw = new StringWriter();
611 result.write(sw);
612
613 System.out.println(sw.toString());
614
615
616 String pausePath = PropertyPathConfig.getPath(PropertyType.PAUSE, clusterName);
617 System.out.println("pausePath: " + pausePath);
618 boolean exists = _gZkClient.exists(pausePath);
619 Assert.assertTrue(exists, pausePath + " should exist");
620
621
622 paramMap.put(JsonParameters.ENABLED, "" + true);
623 request = new Request(Method.POST, resourceRef);
624
625 request.setEntity(JsonParameters.JSON_PARAMETERS + "="
626 + ClusterRepresentationUtil.ObjectToJson(paramMap), MediaType.APPLICATION_ALL);
627 client = new Client(Protocol.HTTP);
628 response = client.handle(request);
629
630 result = response.getEntity();
631 sw = new StringWriter();
632 result.write(sw);
633
634 System.out.println(sw.toString());
635
636
637 exists = _gZkClient.exists(pausePath);
638 Assert.assertFalse(exists, pausePath + " should be removed");
639
640 System.out.println("END: verifyEnableCluster()");
641 }
642
643 private boolean contains(List<String> list, String... items)
644 {
645 for (String item : items)
646 {
647 if (!list.contains(item))
648 {
649 return false;
650 }
651 }
652 return true;
653 }
654 }