/** * Copyright 2012 Comcast Corporation * * Licensed 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. */ package com.comcast.cns.controller; import java.util.ArrayList; import java.util.List; import javax.management.JMX; import javax.management.MBeanServerConnection; import javax.management.ObjectName; import javax.management.remote.JMXConnector; import javax.management.remote.JMXConnectorFactory; import javax.management.remote.JMXServiceURL; import javax.servlet.AsyncContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.log4j.Logger; import com.comcast.cmb.common.controller.CMBControllerServlet; import com.comcast.cmb.common.model.CMBPolicy; import com.comcast.cmb.common.model.User; import com.comcast.cmb.common.persistence.AbstractDurablePersistence; import com.comcast.cmb.common.persistence.AbstractDurablePersistence.CmbRow; import com.comcast.cmb.common.persistence.DurablePersistenceFactory; import com.comcast.cmb.common.persistence.AbstractDurablePersistence.CMB_SERIALIZER; import com.comcast.cmb.common.util.CMBErrorCodes; import com.comcast.cmb.common.util.CMBException; import com.comcast.cns.io.CNSPopulator; import com.comcast.cns.io.CNSWorkerStatsPopulator; import com.comcast.cns.model.CNSWorkerStats; import com.comcast.cns.tools.CNSWorkerMonitorMBean; import com.comcast.cns.util.CNSErrorCodes; import com.comcast.cns.util.CNSWorkerStatWrapper; /** * Subscribe action * @author bwolf * */ public class CNSManageServiceAction extends CNSAction { private static Logger logger = Logger.getLogger(CNSManageServiceAction.class); public static final String CNS_API_SERVERS = "CNSAPIServers"; public static final String CNS_WORKERS = "CNSWorkers"; public CNSManageServiceAction() { super("ManageService"); } @Override public boolean isActionAllowed(User user, HttpServletRequest request, String service, CMBPolicy policy) throws Exception { return true; } /** * Manage cns service and workers * @param user the user for whom we are subscribing. * @param asyncContext */ @Override public boolean doAction(User user, AsyncContext asyncContext) throws Exception { HttpServletRequest request = (HttpServletRequest)asyncContext.getRequest(); HttpServletResponse response = (HttpServletResponse)asyncContext.getResponse(); String task = request.getParameter("Task"); if (task == null || task.equals("")) { logger.error("event=cns_manage_service error_code=missing_parameter_task"); throw new CMBException(CNSErrorCodes.MissingParameter,"Request parameter Task missing."); } String host = request.getParameter("Host"); //for some task, Host is mandatory. Check it. if (!task.equals("ClearAPIStats") && (!task.equals("StartWorker")) && (!task.equals("StopWorker")) && (host == null || host.equals(""))) { logger.error("event=cns_manage_service error_code=missing_parameter_host"); throw new CMBException(CNSErrorCodes.MissingParameter,"Request parameter Host missing."); } AbstractDurablePersistence cassandraHandler = DurablePersistenceFactory.getInstance(); if (task.equals("ClearWorkerQueues")) { List<CmbRow<String, String, String>> rows = cassandraHandler.readAllRows(AbstractDurablePersistence.CNS_KEYSPACE, CNS_WORKERS, 1000, 10, CMB_SERIALIZER.STRING_SERIALIZER, CMB_SERIALIZER.STRING_SERIALIZER, CMB_SERIALIZER.STRING_SERIALIZER); List<CNSWorkerStats> statsList = new ArrayList<CNSWorkerStats>(); if (rows != null) { for (CmbRow<String, String, String> row : rows) { CNSWorkerStats stats = new CNSWorkerStats(); stats.setIpAddress(row.getKey()); if (row.getColumnSlice().getColumnByName("producerTimestamp") != null) { stats.setProducerTimestamp(Long.parseLong(row.getColumnSlice().getColumnByName("producerTimestamp").getValue())); } if (row.getColumnSlice().getColumnByName("consumerTimestamp") != null) { stats.setConsumerTimestamp(Long.parseLong(row.getColumnSlice().getColumnByName("consumerTimestamp").getValue())); } if (row.getColumnSlice().getColumnByName("jmxport") != null) { stats.setJmxPort(Long.parseLong(row.getColumnSlice().getColumnByName("jmxport").getValue())); } if (row.getColumnSlice().getColumnByName("mode") != null) { stats.setMode(row.getColumnSlice().getColumnByName("mode").getValue()); } statsList.add(stats); } } for (CNSWorkerStats stats : statsList) { if (stats.getIpAddress().equals(host) && stats.getJmxPort() > 0) { JMXConnector jmxConnector = null; String url = null; try { long port = stats.getJmxPort(); url = "service:jmx:rmi:///jndi/rmi://" + host + ":" + port + "/jmxrmi"; JMXServiceURL serviceUrl = new JMXServiceURL(url); jmxConnector = JMXConnectorFactory.connect(serviceUrl, null); MBeanServerConnection mbeanConn = jmxConnector.getMBeanServerConnection(); ObjectName cnsWorkerMonitor = new ObjectName("com.comcast.cns.tools:type=CNSWorkerMonitorMBean"); CNSWorkerMonitorMBean mbeanProxy = JMX.newMBeanProxy(mbeanConn, cnsWorkerMonitor, CNSWorkerMonitorMBean.class, false); mbeanProxy.clearWorkerQueues(); String res = CNSWorkerStatsPopulator.getGetManageWorkerResponse(); response.getWriter().println(res); return true; } finally { if (jmxConnector != null) { jmxConnector.close(); } } } } throw new CMBException(CMBErrorCodes.NotFound, "Cannot clear worker queues: Host " + host + " not found."); } else if (task.equals("RemoveWorkerRecord")) { cassandraHandler.delete(AbstractDurablePersistence.CNS_KEYSPACE, CNS_WORKERS, host, null, CMB_SERIALIZER.STRING_SERIALIZER, CMB_SERIALIZER.STRING_SERIALIZER); String out = CNSPopulator.getResponseMetadata(); writeResponse(out, response); return true; } else if (task.equals("ClearAPIStats")) { CMBControllerServlet.initStats(); String out = CNSPopulator.getResponseMetadata(); writeResponse(out, response); return true; } else if (task.equals("RemoveRecord")) { cassandraHandler.delete(AbstractDurablePersistence.CNS_KEYSPACE, CNS_API_SERVERS, host, null, CMB_SERIALIZER.STRING_SERIALIZER, CMB_SERIALIZER.STRING_SERIALIZER); String out = CNSPopulator.getResponseMetadata(); writeResponse(out, response); return true; } else if (task.equals("StartWorker")||task.equals("StopWorker")) { String dataCenter = request.getParameter("DataCenter"); if(task.equals("StartWorker")){ CNSWorkerStatWrapper.startWorkers(dataCenter); } else { CNSWorkerStatWrapper.stopWorkers(dataCenter); } String out = CNSPopulator.getResponseMetadata(); writeResponse(out, response); return true; } else { logger.error("event=cns_manage_service error_code=invalid_task_parameter valid_values=ClearWorkerQueues,RemoveWorkerRecord,RemoveRecord,ClearAPIStats"); throw new CMBException(CNSErrorCodes.InvalidParameterValue,"Request parameter Task missing is invalid. Valid values are ClearWorkerQueues, RemoveWorkerRecord, RemoveRecord, ClearAPIStats."); } } }