package org.apache.helix.ui.resource; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import org.apache.helix.manager.zk.ZKUtil; import org.apache.helix.model.IdealState; import org.apache.helix.model.InstanceConfig; import org.apache.helix.tools.ClusterSetup; import org.apache.helix.ui.api.ClusterConnection; import org.apache.helix.ui.util.ClientCache; import org.apache.helix.ui.util.DataCache; import javax.ws.rs.*; import javax.ws.rs.core.Response; import java.util.List; @Path("/admin") public class AdminResource { private final ClientCache clientCache; private final DataCache dataCache; public AdminResource(ClientCache clientCache, DataCache dataCache) { this.clientCache = clientCache; this.dataCache = dataCache; } @Path("/{zkAddress}/{clusterName}") @POST public Response addCluster(@PathParam("zkAddress") String zkAddress, @PathParam("clusterName") String clusterName) throws Exception { dataCache.invalidate(); ClusterSetup clusterSetup = clientCache.get(zkAddress).getClusterSetup(); if (clusterSetup.getClusterManagementTool().getClusters().contains(clusterName)) { return Response.status(Response.Status.CONFLICT).build(); } clusterSetup.addCluster(clusterName, false); dataCache.invalidate(); return Response.ok().build(); } @Path("/{zkAddress}/{clusterName}") @DELETE public Response dropCluster(@PathParam("zkAddress") String zkAddress, @PathParam("clusterName") String clusterName) throws Exception { dataCache.invalidate(); ClusterSetup clusterSetup = clientCache.get(zkAddress).getClusterSetup(); if (!clusterSetup.getClusterManagementTool().getClusters().contains(clusterName)) { throw new NotFoundException(); } clusterSetup.getClusterManagementTool().dropCluster(clusterName); return Response.noContent().build(); } @Path("/{zkAddress}/{clusterName}/instances/{instanceName}") @POST public Response addInstance(@PathParam("zkAddress") String zkAddress, @PathParam("clusterName") String clusterName, @PathParam("instanceName") String instanceName, @QueryParam("disable") boolean disable, @QueryParam("failIfNoInstance") boolean failIfNoInstance) throws Exception { dataCache.invalidate(); ClusterSetup clusterSetup = clientCache.get(zkAddress).getClusterSetup(); List<String> instances = clusterSetup.getClusterManagementTool().getInstancesInCluster(clusterName); Response response; if (instances.contains(instanceName)) { response = Response.notModified().build(); } else if (failIfNoInstance) { return Response.status(Response.Status.BAD_REQUEST).build(); } else { clusterSetup.addInstanceToCluster(clusterName, instanceName); response = Response.ok().build(); } clusterSetup.getClusterManagementTool().enableInstance(clusterName, instanceName, !disable); return response; } @Path("/{zkAddress}/{clusterName}/instances/{instanceName}") @DELETE public Response dropInstance(@PathParam("zkAddress") String zkAddress, @PathParam("clusterName") String clusterName, @PathParam("instanceName") String instanceName) throws Exception { dataCache.invalidate(); ClusterSetup clusterSetup = clientCache.get(zkAddress).getClusterSetup(); InstanceConfig instanceConfig = clusterSetup.getClusterManagementTool().getInstanceConfig(clusterName, instanceName); if (instanceConfig == null) { throw new NotFoundException(); } else if (instanceConfig.getInstanceEnabled()) { return Response.status(Response.Status.BAD_REQUEST) .header("X-Error-Message", "Cannot drop instance that is enabled") .build(); } clusterSetup.dropInstanceFromCluster(clusterName, instanceName); return Response.noContent().build(); } @Path("/{zkAddress}/{clusterName}/resources/{resourceName}/{partitions}/{replicas}") @POST public Response addResource(@PathParam("zkAddress") String zkAddress, @PathParam("clusterName") String clusterName, @PathParam("resourceName") String resourceName, @PathParam("partitions") int partitions, @PathParam("replicas") String replicas, @QueryParam("rebalance") boolean rebalance, @QueryParam("stateModel") String stateModel, @QueryParam("rebalanceMode") String rebalanceMode) throws Exception { dataCache.invalidate(); ClusterConnection conn = clientCache.get(zkAddress); ClusterSetup clusterSetup = conn.getClusterSetup(); if (!ZKUtil.isClusterSetup(clusterName, conn.getZkClient())) { return Response.status(Response.Status.BAD_REQUEST).build(); } IdealState existingIdealState = clusterSetup.getClusterManagementTool().getResourceIdealState(clusterName, resourceName); IdealState idealState = new IdealState(resourceName); idealState.setNumPartitions(partitions); idealState.setReplicas(replicas); idealState.setStateModelDefRef(stateModel == null ? "OnlineOffline" : stateModel); idealState.setRebalanceMode(rebalanceMode == null ? IdealState.RebalanceMode.FULL_AUTO : IdealState.RebalanceMode.valueOf(rebalanceMode)); Response response; if (existingIdealState == null) { clusterSetup.getClusterManagementTool().addResource(clusterName, resourceName, idealState); response = Response.ok().build(); } else if (!existingIdealState.equals(idealState)) { return Response.status(Response.Status.CONFLICT).build(); } else { response = Response.notModified().build(); } if (rebalance) { // TODO this will break if replicas is not integer (e.g. N) clusterSetup.rebalanceResource(clusterName, resourceName, Integer.valueOf(replicas)); } return response; } @Path("/{zkAddress}/{clusterName}/resources/{resourceName}") @DELETE public Response dropResource(@PathParam("zkAddress") String zkAddress, @PathParam("clusterName") String clusterName, @PathParam("resourceName") String resourceName) throws Exception { dataCache.invalidate(); ClusterSetup clusterSetup = clientCache.get(zkAddress).getClusterSetup(); List<String> resources = clusterSetup.getClusterManagementTool().getResourcesInCluster(clusterName); if (!resources.contains(resourceName)) { throw new NotFoundException(); } clusterSetup.dropResourceFromCluster(clusterName, resourceName); return Response.noContent().build(); } }