View Javadoc

1   package org.apache.helix.manager.zk;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.util.ArrayList;
23  import java.util.Date;
24  import java.util.HashMap;
25  import java.util.List;
26  import java.util.Map;
27  
28  import org.apache.helix.*;
29  import org.apache.helix.model.ClusterConstraints;
30  import org.apache.helix.model.ClusterConstraints.ConstraintAttribute;
31  import org.apache.helix.model.ClusterConstraints.ConstraintType;
32  import org.apache.helix.model.HelixConfigScope.ConfigScopeProperty;
33  import org.apache.helix.model.ConfigScope;
34  import org.apache.helix.model.ConstraintItem;
35  import org.apache.helix.model.ExternalView;
36  import org.apache.helix.model.HelixConfigScope;
37  import org.apache.helix.model.InstanceConfig;
38  import org.apache.helix.model.StateModelDefinition;
39  import org.apache.helix.model.builder.ConfigScopeBuilder;
40  import org.apache.helix.model.builder.ConstraintItemBuilder;
41  import org.apache.helix.model.builder.HelixConfigScopeBuilder;
42  import org.apache.helix.tools.StateModelConfigGenerator;
43  import org.apache.zookeeper.data.Stat;
44  import org.testng.Assert;
45  import org.testng.AssertJUnit;
46  import org.testng.annotations.Test;
47  
48  
49  public class TestZkHelixAdmin extends ZkUnitTestBase
50  {
51    @Test()
52    public void testZkHelixAdmin()
53    {
54      System.out.println("START testZkHelixAdmin at " + new Date(System.currentTimeMillis()));
55  
56      final String clusterName = getShortClassName();
57      String rootPath = "/" + clusterName;
58      if (_gZkClient.exists(rootPath))
59      {
60        _gZkClient.deleteRecursive(rootPath);
61      }
62  
63      ZKHelixAdmin tool = new ZKHelixAdmin(_gZkClient);
64      tool.addCluster(clusterName, true);
65      Assert.assertTrue(ZKUtil.isClusterSetup(clusterName, _gZkClient));
66      tool.addCluster(clusterName, true);
67      Assert.assertTrue(ZKUtil.isClusterSetup(clusterName, _gZkClient));
68  
69      List<String> list = tool.getClusters();
70      AssertJUnit.assertTrue(list.size() > 0);
71  
72      try
73      {
74        Stat oldstat = _gZkClient.getStat(rootPath);
75        Assert.assertNotNull(oldstat);
76        boolean success = tool.addCluster(clusterName, false);
77        //Even though it exists, it should return true but it should not make any changes in zk
78        Assert.assertTrue(success);
79        Stat newstat = _gZkClient.getStat(rootPath);
80        Assert.assertEquals(oldstat, newstat);
81      } catch (HelixException e)
82      {
83        // OK
84      }
85  
86      InstanceConfig config = new InstanceConfig("host1_9999");
87      config.setHostName("host1");
88      config.setPort("9999");
89      tool.addInstance(clusterName, config);
90      tool.enableInstance(clusterName, "host1_9999", true);
91      String path = PropertyPathConfig.getPath(PropertyType.INSTANCES,
92          clusterName, "host1_9999");
93      AssertJUnit.assertTrue(_gZkClient.exists(path));
94  
95      try
96      {
97        tool.addInstance(clusterName, config);
98        Assert.fail("should fail if add an alredy-existing instance");
99      } catch (HelixException e)
100     {
101       // OK
102     }
103     config = tool.getInstanceConfig(clusterName, "host1_9999");
104     AssertJUnit.assertEquals(config.getId(), "host1_9999");
105 
106     tool.dropInstance(clusterName, config);
107     try
108     {
109       tool.getInstanceConfig(clusterName, "host1_9999");
110       Assert.fail("should fail if get a non-existent instance");
111     } catch (HelixException e)
112     {
113       // OK
114     }
115     try
116     {
117       tool.dropInstance(clusterName, config);
118       Assert.fail("should fail if drop on a non-existent instance");
119     } catch (HelixException e)
120     {
121       // OK
122     }
123     try
124     {
125       tool.enableInstance(clusterName, "host1_9999", false);
126       Assert.fail("should fail if enable a non-existent instance");
127     } catch (HelixException e)
128     {
129       // OK
130     }
131     ZNRecord stateModelRecord = new ZNRecord("id1");
132     try
133     {
134       tool.addStateModelDef(clusterName, "id1", new StateModelDefinition(
135           stateModelRecord));
136       path = PropertyPathConfig.getPath(PropertyType.STATEMODELDEFS,
137           clusterName, "id1");
138       AssertJUnit.assertTrue(_gZkClient.exists(path));
139       Assert.fail("should fail");
140     } catch (HelixException e)
141     {
142       // OK
143     }
144     catch(IllegalArgumentException ex)
145     {
146       // OK
147     }
148     
149     tool.addStateModelDef(clusterName,
150         "MasterSlave",
151         new StateModelDefinition(StateModelConfigGenerator.generateConfigForMasterSlave()));
152     stateModelRecord = StateModelConfigGenerator.generateConfigForMasterSlave();
153     try
154     {
155       tool.addStateModelDef(clusterName, stateModelRecord.getId(), new StateModelDefinition(
156           stateModelRecord));
157       Assert.fail("should fail if add an already-existing state model");
158     } catch (HelixException e)
159     {
160       // OK
161     }
162     list = tool.getStateModelDefs(clusterName);
163     AssertJUnit.assertEquals(list.size(), 1);
164 
165     try
166     {
167       tool.addResource(clusterName, "resource", 10,
168           "nonexistStateModelDef");
169       Assert
170           .fail("should fail if add a resource without an existing state model");
171     } catch (HelixException e)
172     {
173       // OK
174     }
175     try
176     {
177       tool.addResource(clusterName, "resource", 10, "id1");
178       Assert.fail("should fail");
179     } catch (HelixException e)
180     {
181       // OK
182     }
183     list = tool.getResourcesInCluster(clusterName);
184     AssertJUnit.assertEquals(list.size(), 0);
185     try
186     {
187       tool.addResource(clusterName, "resource", 10, "id1");
188       Assert.fail("should fail");
189     } catch (HelixException e)
190     {
191       // OK
192     }
193     list = tool.getResourcesInCluster(clusterName);
194     AssertJUnit.assertEquals(list.size(), 0);
195 
196     ExternalView resourceExternalView = tool.getResourceExternalView(
197         clusterName, "resource");
198     AssertJUnit.assertNull(resourceExternalView);
199 
200     // test config support
201 //    ConfigScope scope = new ConfigScopeBuilder().forCluster(clusterName)
202 //        .forResource("testResource").forPartition("testPartition").build();
203     HelixConfigScope scope = new HelixConfigScopeBuilder(ConfigScopeProperty.PARTITION)
204                                   .forCluster(clusterName)
205                                   .forResource("testResource")
206                                   .forPartition("testPartition")
207                                   .build();
208   
209     Map<String, String> properties = new HashMap<String, String>();
210     properties.put("pKey1", "pValue1");
211     properties.put("pKey2", "pValue2");
212     
213     // make sure calling set/getConfig() many times will not drain zkClient resources
214     // int nbOfZkClients = ZkClient.getNumberOfConnections();
215     for (int i = 0; i < 100; i++)
216     {
217       tool.setConfig(scope, properties);
218       Map<String, String> newProperties = tool.getConfig(scope, new ArrayList<String>(properties.keySet()));
219       Assert.assertEquals(newProperties.size(), 2);
220       Assert.assertEquals(newProperties.get("pKey1"), "pValue1");
221       Assert.assertEquals(newProperties.get("pKey2"), "pValue2");
222     }
223     // Assert.assertTrue(ZkClient.getNumberOfConnections() - nbOfZkClients < 5);
224 
225     System.out.println("END testZkHelixAdmin at " + new Date(System.currentTimeMillis()));
226   }
227 
228     // drop resource should drop corresponding resource-level config also
229     @Test
230     public void testDropResource() {
231         String className = TestHelper.getTestClassName();
232         String methodName = TestHelper.getTestMethodName();
233         String clusterName = className + "_" + methodName;
234 
235         System.out.println("START " + clusterName + " at "
236                 + new Date(System.currentTimeMillis()));
237 
238         ZKHelixAdmin tool = new ZKHelixAdmin(_gZkClient);
239         tool.addCluster(clusterName, true);
240         Assert.assertTrue(ZKUtil.isClusterSetup(clusterName, _gZkClient), "Cluster should be setup");
241 
242         tool.addStateModelDef(clusterName, "MasterSlave", new StateModelDefinition(StateModelConfigGenerator.generateConfigForMasterSlave()));
243         tool.addResource(clusterName, "test-db", 4, "MasterSlave");
244         Map<String, String> resourceConfig = new HashMap<String, String>();
245         resourceConfig.put("key1", "value1");
246         tool.setConfig(new HelixConfigScopeBuilder(ConfigScopeProperty.RESOURCE)
247                                 .forCluster(clusterName)
248                                 .forResource("test-db")
249                                 .build(), 
250                        resourceConfig);
251 
252         PropertyKey.Builder keyBuilder = new PropertyKey.Builder(clusterName);
253         Assert.assertTrue(_gZkClient.exists(keyBuilder.idealStates("test-db").getPath()), "test-db ideal-state should exist");
254         Assert.assertTrue(_gZkClient.exists(keyBuilder.resourceConfig("test-db").getPath()), "test-db resource config should exist");
255 
256         tool.dropResource(clusterName, "test-db");
257         Assert.assertFalse(_gZkClient.exists(keyBuilder.idealStates("test-db").getPath()), "test-db ideal-state should be dropped");
258         Assert.assertFalse(_gZkClient.exists(keyBuilder.resourceConfig("test-db").getPath()), "test-db resource config should be dropped");
259 
260         System.out.println("END " + clusterName + " at "
261                 + new Date(System.currentTimeMillis()));
262     }
263     
264     // test add/remove message constraint
265     @Test
266     public void testAddRemoveMsgConstraint() {
267       String className = TestHelper.getTestClassName();
268       String methodName = TestHelper.getTestMethodName();
269       String clusterName = className + "_" + methodName;
270 
271       System.out.println("START " + clusterName + " at "
272               + new Date(System.currentTimeMillis()));
273 
274       ZKHelixAdmin tool = new ZKHelixAdmin(_gZkClient);
275       tool.addCluster(clusterName, true);
276       Assert.assertTrue(ZKUtil.isClusterSetup(clusterName, _gZkClient), "Cluster should be setup");
277 
278       // test admin.getMessageConstraints()
279       ClusterConstraints constraints = tool.getConstraints(clusterName, ConstraintType.MESSAGE_CONSTRAINT);
280       Assert.assertNull(constraints, "message-constraint should NOT exist for cluster: " + className);
281 
282       // remove non-exist constraint
283       try {
284         tool.removeConstraint(clusterName, ConstraintType.MESSAGE_CONSTRAINT, "constraint1");
285         // will leave a null message-constraint znode on zk
286       } catch (Exception e) {
287         Assert.fail("Should not throw exception when remove a non-exist constraint.");
288       }
289 
290       // add a message constraint
291       ConstraintItemBuilder builder = new ConstraintItemBuilder();
292       builder.addConstraintAttribute(ConstraintAttribute.RESOURCE.toString(), "MyDB")
293              .addConstraintAttribute(ConstraintAttribute.CONSTRAINT_VALUE.toString(), "1");
294       tool.setConstraint(clusterName, ConstraintType.MESSAGE_CONSTRAINT, "constraint1", builder.build());
295 
296       HelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor<ZNRecord>(_gZkClient));
297       PropertyKey.Builder keyBuilder = new PropertyKey.Builder(clusterName);
298       constraints = accessor.getProperty(keyBuilder.constraint(ConstraintType.MESSAGE_CONSTRAINT.toString()));
299       Assert.assertNotNull(constraints, "message-constraint should exist");
300       ConstraintItem item = constraints.getConstraintItem("constraint1");
301       Assert.assertNotNull(item, "message-constraint for constraint1 should exist");
302       Assert.assertEquals(item.getConstraintValue(), "1");
303       Assert.assertEquals(item.getAttributeValue(ConstraintAttribute.RESOURCE), "MyDB");
304       
305       // test admin.getMessageConstraints()
306       constraints = tool.getConstraints(clusterName, ConstraintType.MESSAGE_CONSTRAINT);
307       Assert.assertNotNull(constraints, "message-constraint should exist");
308       item = constraints.getConstraintItem("constraint1");
309       Assert.assertNotNull(item, "message-constraint for constraint1 should exist");
310       Assert.assertEquals(item.getConstraintValue(), "1");
311       Assert.assertEquals(item.getAttributeValue(ConstraintAttribute.RESOURCE), "MyDB");
312       
313 
314       // remove a exist message-constraint
315       tool.removeConstraint(clusterName, ConstraintType.MESSAGE_CONSTRAINT, "constraint1");
316       constraints = accessor.getProperty(keyBuilder.constraint(ConstraintType.MESSAGE_CONSTRAINT.toString()));
317       Assert.assertNotNull(constraints, "message-constraint should exist");
318       item = constraints.getConstraintItem("constraint1");
319       Assert.assertNull(item, "message-constraint for constraint1 should NOT exist");
320 
321       System.out.println("END " + clusterName + " at "
322               + new Date(System.currentTimeMillis()));
323     }
324 }