1 package org.apache.helix.webapp.resources;
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.util.Map;
24
25 import org.apache.helix.HelixDataAccessor;
26 import org.apache.helix.HelixException;
27 import org.apache.helix.PropertyKey;
28 import org.apache.helix.ZNRecord;
29 import org.apache.helix.PropertyKey.Builder;
30 import org.apache.helix.manager.zk.ZkClient;
31 import org.apache.helix.model.IdealState;
32 import org.apache.helix.tools.ClusterSetup;
33 import org.apache.helix.webapp.RestAdminApplication;
34 import org.apache.log4j.Logger;
35 import org.codehaus.jackson.JsonGenerationException;
36 import org.codehaus.jackson.map.JsonMappingException;
37 import org.restlet.Context;
38 import org.restlet.data.MediaType;
39 import org.restlet.data.Request;
40 import org.restlet.data.Response;
41 import org.restlet.data.Status;
42 import org.restlet.resource.Representation;
43 import org.restlet.resource.Resource;
44 import org.restlet.resource.StringRepresentation;
45 import org.restlet.resource.Variant;
46
47
48 public class IdealStateResource extends Resource
49 {
50 private final static Logger LOG = Logger.getLogger(IdealStateResource.class);
51
52 public IdealStateResource(Context context, Request request, Response response)
53 {
54 super(context, request, response);
55 getVariants().add(new Variant(MediaType.TEXT_PLAIN));
56 getVariants().add(new Variant(MediaType.APPLICATION_JSON));
57 }
58
59 @Override
60 public boolean allowGet()
61 {
62 return true;
63 }
64
65 @Override
66 public boolean allowPost()
67 {
68 return true;
69 }
70
71 @Override
72 public boolean allowPut()
73 {
74 return false;
75 }
76
77 @Override
78 public boolean allowDelete()
79 {
80 return false;
81 }
82
83 @Override
84 public Representation represent(Variant variant)
85 {
86 StringRepresentation presentation = null;
87 try
88 {
89 String clusterName = (String) getRequest().getAttributes().get("clusterName");
90 String resourceName = (String) getRequest().getAttributes().get("resourceName");
91 presentation = getIdealStateRepresentation(clusterName, resourceName);
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 getIdealStateRepresentation(String clusterName, String resourceName) throws JsonGenerationException,
105 JsonMappingException,
106 IOException
107 {
108 Builder keyBuilder = new PropertyKey.Builder(clusterName);
109 ZkClient zkClient =
110 (ZkClient) getContext().getAttributes().get(RestAdminApplication.ZKCLIENT);
111
112 String message =
113 ClusterRepresentationUtil.getClusterPropertyAsString(zkClient,
114 clusterName,
115 keyBuilder.idealStates(resourceName),
116 MediaType.APPLICATION_JSON);
117
118 StringRepresentation representation =
119 new StringRepresentation(message, MediaType.APPLICATION_JSON);
120
121 return representation;
122 }
123
124 @Override
125 public void acceptRepresentation(Representation entity)
126 {
127 try
128 {
129 String clusterName = (String) getRequest().getAttributes().get("clusterName");
130 String resourceName = (String) getRequest().getAttributes().get("resourceName");
131 ZkClient zkClient =
132 (ZkClient) getContext().getAttributes().get(RestAdminApplication.ZKCLIENT);
133 ClusterSetup setupTool = new ClusterSetup(zkClient);
134
135 JsonParameters jsonParameters = new JsonParameters(entity);
136 String command = jsonParameters.getCommand();
137
138 if (command.equalsIgnoreCase(ClusterSetup.addIdealState))
139 {
140 ZNRecord newIdealState = jsonParameters.getExtraParameter(JsonParameters.NEW_IDEAL_STATE);
141 HelixDataAccessor accessor =
142 ClusterRepresentationUtil.getClusterDataAccessor(zkClient, clusterName);
143
144 accessor.setProperty(accessor.keyBuilder().idealStates(resourceName),
145 new IdealState(newIdealState));
146
147 }
148 else if (command.equalsIgnoreCase(ClusterSetup.rebalance))
149 {
150 int replicas =
151 Integer.parseInt(jsonParameters.getParameter(JsonParameters.REPLICAS));
152 String keyPrefix = jsonParameters.getParameter(JsonParameters.RESOURCE_KEY_PREFIX);
153 String groupTag = jsonParameters.getParameter(ClusterSetup.instanceGroupTag);
154
155 setupTool.rebalanceCluster(clusterName,
156 resourceName,
157 replicas,
158 keyPrefix,
159 groupTag);
160
161 }
162 else if (command.equalsIgnoreCase(ClusterSetup.expandResource))
163 {
164 setupTool.expandResource(clusterName, resourceName);
165 }
166 else if (command.equalsIgnoreCase(ClusterSetup.addResourceProperty))
167 {
168 Map<String, String> parameterMap = jsonParameters.cloneParameterMap();
169 parameterMap.remove(JsonParameters.MANAGEMENT_COMMAND);
170 for (String key : parameterMap.keySet())
171 {
172 setupTool.addResourceProperty(clusterName,
173 resourceName,
174 key,
175 parameterMap.get(key));
176 }
177 }
178 else
179 {
180 throw new HelixException("Unsupported command: " + command
181 + ". Should be one of [" + ClusterSetup.addIdealState + ", "
182 + ClusterSetup.rebalance + ", " + ClusterSetup.expandResource + ", "
183 + ClusterSetup.addResourceProperty + "]");
184 }
185
186 getResponse().setEntity(getIdealStateRepresentation(clusterName, resourceName));
187 getResponse().setStatus(Status.SUCCESS_OK);
188 }
189 catch (Exception e)
190 {
191 getResponse().setEntity(ClusterRepresentationUtil.getErrorAsJsonStringFromException(e),
192 MediaType.APPLICATION_JSON);
193 getResponse().setStatus(Status.SUCCESS_OK);
194 LOG.error("Error in posting " + entity, e);
195 }
196 }
197 }