View Javadoc

1   package org.apache.helix.webapp.resources;
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.io.IOException;
23  import java.util.LinkedList;
24  import java.util.List;
25  import java.util.Map;
26  import java.util.TreeMap;
27  
28  import org.apache.helix.HelixDataAccessor;
29  import org.apache.helix.HelixException;
30  import org.apache.helix.manager.zk.ZkClient;
31  import org.apache.helix.model.InstanceConfig;
32  import org.apache.helix.model.LiveInstance;
33  import org.apache.helix.tools.ClusterSetup;
34  import org.apache.helix.webapp.RestAdminApplication;
35  import org.apache.log4j.Logger;
36  import org.codehaus.jackson.JsonGenerationException;
37  import org.codehaus.jackson.map.JsonMappingException;
38  import org.restlet.Context;
39  import org.restlet.data.MediaType;
40  import org.restlet.data.Request;
41  import org.restlet.data.Response;
42  import org.restlet.data.Status;
43  import org.restlet.resource.Representation;
44  import org.restlet.resource.Resource;
45  import org.restlet.resource.StringRepresentation;
46  import org.restlet.resource.Variant;
47  
48  
49  public class InstancesResource extends Resource
50  {
51    private final static Logger LOG = Logger.getLogger(InstancesResource.class);
52  
53    public InstancesResource(Context context, Request request, Response response)
54    {
55      super(context, request, response);
56      getVariants().add(new Variant(MediaType.TEXT_PLAIN));
57      getVariants().add(new Variant(MediaType.APPLICATION_JSON));
58    }
59  
60    @Override
61    public boolean allowGet()
62    {
63      return true;
64    }
65  
66    @Override
67    public boolean allowPost()
68    {
69      return true;
70    }
71  
72    @Override
73    public boolean allowPut()
74    {
75      return false;
76    }
77  
78    @Override
79    public boolean allowDelete()
80    {
81      return false;
82    }
83  
84    @Override
85    public Representation represent(Variant variant)
86    {
87      StringRepresentation presentation = null;
88      try
89      {
90        String clusterName = (String) getRequest().getAttributes().get("clusterName");
91        presentation = getInstancesRepresentation(clusterName);
92      }
93  
94      catch (Exception e)
95      {
96        String error = ClusterRepresentationUtil.getErrorAsJsonStringFromException(e);
97        presentation = new StringRepresentation(error, MediaType.APPLICATION_JSON);
98  
99        LOG.error("", e);
100     }
101     return presentation;
102   }
103 
104   StringRepresentation getInstancesRepresentation(String clusterName) throws JsonGenerationException,
105       JsonMappingException,
106       IOException
107   {
108     ZkClient zkClient =
109         (ZkClient) getContext().getAttributes().get(RestAdminApplication.ZKCLIENT);
110 
111     HelixDataAccessor accessor =
112         ClusterRepresentationUtil.getClusterDataAccessor(zkClient, clusterName);
113     Map<String, LiveInstance> liveInstancesMap =
114         accessor.getChildValuesMap(accessor.keyBuilder().liveInstances());
115     Map<String, InstanceConfig> instanceConfigsMap =
116         accessor.getChildValuesMap(accessor.keyBuilder().instanceConfigs());
117     
118     Map<String, List<String>> tagInstanceLists = new TreeMap<String, List<String>>();
119     
120     for (String instanceName : instanceConfigsMap.keySet())
121     {
122       boolean isAlive = liveInstancesMap.containsKey(instanceName);
123       instanceConfigsMap.get(instanceName)
124                         .getRecord()
125                         .setSimpleField("Alive", isAlive + "");
126       InstanceConfig config = instanceConfigsMap.get(instanceName);
127       for(String tag : config.getTags())
128       {
129         if(!tagInstanceLists.containsKey(tag))
130         {
131           tagInstanceLists.put(tag, new LinkedList<String>());
132         }
133         if(!tagInstanceLists.get(tag).contains(instanceName))
134         {
135           tagInstanceLists.get(tag).add(instanceName);
136         }
137       }
138     }
139 
140     StringRepresentation representation =
141         new StringRepresentation(ClusterRepresentationUtil.ObjectToJson(instanceConfigsMap.values()) + ClusterRepresentationUtil.ObjectToJson(tagInstanceLists),
142                                  MediaType.APPLICATION_JSON);
143 
144     return representation;
145   }
146 
147   @Override
148   public void acceptRepresentation(Representation entity)
149   {
150     try
151     {
152       String clusterName = (String) getRequest().getAttributes().get("clusterName");
153       JsonParameters jsonParameters = new JsonParameters(entity);
154       String command = jsonParameters.getCommand();
155 
156       ZkClient zkClient =
157           (ZkClient) getContext().getAttributes().get(RestAdminApplication.ZKCLIENT);
158       ClusterSetup setupTool = new ClusterSetup(zkClient);
159 
160       if (command.equalsIgnoreCase(ClusterSetup.addInstance)
161           || JsonParameters.CLUSTERSETUP_COMMAND_ALIASES.get(ClusterSetup.addInstance)
162                                                         .contains(command))
163       {
164         if (jsonParameters.getParameter(JsonParameters.INSTANCE_NAME) != null)
165         {
166           setupTool.addInstanceToCluster(clusterName,
167                                          jsonParameters.getParameter(JsonParameters.INSTANCE_NAME));
168         }
169         else if (jsonParameters.getParameter(JsonParameters.INSTANCE_NAMES) != null)
170         {
171           setupTool.addInstancesToCluster(clusterName,
172                                           jsonParameters.getParameter(JsonParameters.INSTANCE_NAMES)
173                                                         .split(";"));
174         }
175         else
176         {
177           throw new HelixException("Missing Json paramaters: '"
178               + JsonParameters.INSTANCE_NAME + "' or '" + JsonParameters.INSTANCE_NAMES
179               + "' ");
180         }
181       }
182       else if (command.equalsIgnoreCase(ClusterSetup.swapInstance))
183       {
184         if (jsonParameters.getParameter(JsonParameters.NEW_INSTANCE) == null
185             || jsonParameters.getParameter(JsonParameters.OLD_INSTANCE) == null)
186         {
187           throw new HelixException("Missing Json paramaters: '"
188               + JsonParameters.NEW_INSTANCE + "' or '" + JsonParameters.OLD_INSTANCE
189               + "' ");
190         }
191         setupTool.swapInstance(clusterName,
192                                jsonParameters.getParameter(JsonParameters.OLD_INSTANCE),
193                                jsonParameters.getParameter(JsonParameters.NEW_INSTANCE));
194       }
195       else
196       {
197         throw new HelixException("Unsupported command: " + command
198             + ". Should be one of [" + ClusterSetup.addInstance + ", "
199             + ClusterSetup.swapInstance + "]");
200       }
201 
202       getResponse().setEntity(getInstancesRepresentation(clusterName));
203       getResponse().setStatus(Status.SUCCESS_OK);
204     }
205     catch (Exception e)
206     {
207       getResponse().setEntity(ClusterRepresentationUtil.getErrorAsJsonStringFromException(e),
208                               MediaType.APPLICATION_JSON);
209       getResponse().setStatus(Status.SUCCESS_OK);
210       LOG.error("", e);
211     }
212   }
213 }