/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
* Copyright (c) Ericsson AB, 2004-2008. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can obtain
* a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
* or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
* Sun designates this particular file as subject to the "Classpath" exception
* as provided by Sun in the GPL Version 2 section of the License file that
* accompanied this code. If applicable, add the following below the License
* Header, with the fields enclosed by brackets [] replaced by your own
* identifying information: "Portions Copyrighted [year]
* [name of copyright owner]"
*
* Contributor(s):
*
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package org.jvnet.glassfish.comms.admin.gui.extensions.util;
import com.sun.appserv.management.config.AMXConfig;
import com.sun.enterprise.admin.config.MBeanConfigInstanceNotFoundException;
import com.sun.enterprise.tools.admingui.handlers.ConfigurationHandlers;
import com.sun.enterprise.tools.admingui.util.AMXUtil;
import com.sun.enterprise.tools.admingui.util.GuiUtil;
import com.sun.enterprise.tools.admingui.util.JMXUtil;
import com.sun.enterprise.tools.admingui.util.TargetUtil;
import com.sun.jsftemplating.layout.descriptors.handler.HandlerContext;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import javax.management.Attribute;
import javax.management.AttributeList;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
public class CLBHelper {
public static final String CLB_OBJECT_NAME = "com.sun.appserv:type=converged-load-balancer,category=config";
public static final String CLB_CONFIG_OBJECT_NAME = "com.sun.appserv:type=converged-lb-config,category=config";
public static final String CLB_CONFIGS_OBJECT_NAME = "com.sun.appserv:type=converged-lb-configs,category=config";
public static final String CLB_CONFIG_NAME_SUFFIX = "_CLB_CONFIG";
public static final String CLB_CONFIG_FILE_NAME_SUFFIX = "_CLB.xml";
/** The function is called to unet the DCR file. This happens when the users select
* the http/sip policy radio button on the CLB config settings page.
*
* @param clbName Name of the CLB
*/
public static void unsetDCRFile(String clbName) throws Exception {
// Call the undetDCRFile on the backend
JMXUtil.invoke(CLB_CONFIGS_OBJECT_NAME,
"unsetDcrFile", new Object[]{clbName}, new String[]{"java.lang.String"});
}
public static interface CLB_KEYS {
public static final String CONFIG_FILE = "config-file";
public static final String AUTO_COMMIT = "auto-commit";
public static final String NAME = "name";
public static final String CLB_CONFIG_NAME = "converged-lb-config-name";
public static final String ELEMENT_NAME = "converged-load-balancer";
}
public static interface CLB_PROXY_KEYS {
public static final String REQUEST_POOL_SIZE = "request-pool-size";
public static final String SEND_RETRY_COUNT = "send-retry-count";
public static final String READ_TIMEOUT_IN_MILLIS = "read-timeout-in-millis";
public static final String ELEMENT_NAME = "proxy";
}
public static interface CLB_CLUSTER_REF_KEYS {
public static final String ELEMENT_NAME = "converged-lb-cluster-ref";
public static final String SELF_LOADBALANCE = "self-loadbalance";
}
public static interface SERVER_REF_KEYS {
public static final String DISABLE_TIMEOUT_IN_MINUTES = "disable-timeout-in-minutes";
public static final String ENABLED = "enabled";
public static final String LB_ENABLED = "lb-enabled";
public static final String ELEMENT_NAME = "server-ref";
}
public interface HEALTH_CHECKER_KEYS {
public static final String INTERVAL_IN_SECONDS = "interval-in-seconds";
public static final String TIMEOUT_IN_SECONDS = "timeout-in-seconds";
public static final String URL = "url";
public static final String ELEMENT_NAME = "health-checker";
}
public interface CLB_POLICY_KEYS {
public static final String HTTP = "http";
public static final String SIP = "sip";
public static final String DCR_FILE = "dcr-file";
public static final String ELEMENT_NAME = "converged-lb-policy";
}
/** The function returns the list of CLB created in each config
*/
public static ArrayList getConvergedLoadBalancers() {
ArrayList clbs = new ArrayList();
try {
String[] names = (String[]) JMXUtil.invoke(CLB_CONFIGS_OBJECT_NAME, "listConvergedLoadBalancers",
null, null);
if ((names != null) && (names.length > 0)) {
clbs = new ArrayList(Arrays.asList(names));
}
} catch (Exception ex) {
ex.printStackTrace();
}
return clbs;
}
public static ObjectName getCLBConfigsObject() throws Exception{
try {
return new ObjectName(CLB_CONFIGS_OBJECT_NAME);
} catch (Exception ex) {
if (!(ex instanceof MBeanConfigInstanceNotFoundException)) {
throw ex;
}
}
return null;
}
/** The funtion gets the CLB config associated with a CLB
*/
public static ObjectName getCLBConfig(String clbName) {
ObjectName clbConfig = null;
try {
Map configs = AMXUtil.getDomainConfig().getConfigConfigMap();
Iterator<String> configIt = configs.keySet().iterator();
while (configIt.hasNext()) {
String configName = configIt.next();
String objectName = CLB_OBJECT_NAME + ",config=" + configName;
try {
String name = (String) JMXUtil.getAttribute(objectName, "name");
if(clbName.equals(name)) {
String clbConfigName = (String) JMXUtil.getAttribute(objectName, "converged-lb-config-name");
return new ObjectName(CLB_CONFIG_OBJECT_NAME + ",name=" + clbConfigName);
}
} catch (Exception ex) {
if (!(ex instanceof MBeanConfigInstanceNotFoundException)){
throw ex;
}
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
return clbConfig;
}
/** The function gets the target instance/cluster associated with a CLB name
*/
public static ArrayList getCLBHostingTargets(String clbName) {
ArrayList targets = new ArrayList();
HashSet<String> serversList = new HashSet<String>(AMXUtil.getDomainConfig().getClusterConfigMap().keySet());
serversList.addAll(AMXUtil.getDomainConfig().getStandaloneServerConfigMap().keySet());
for (String targetName: serversList) {
//String configName = AMXUtil.getConfigName(targetName);
try {
if(existsCLB(targetName)) {
String objectName = CLB_OBJECT_NAME + ",config=" + AMXUtil.getConfigName(targetName);
String targetCLBName = (String) JMXUtil.getAttribute(objectName, "name");
if(clbName.equals(targetCLBName)) {
targets.add(targetName);
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
return targets;
}
public static Boolean deleteCLB(String clbName) {
Boolean success = (Boolean) JMXUtil.invoke(CLB_CONFIGS_OBJECT_NAME,
"deleteConvergedLoadBalancer", new Object[]{clbName},
new String[]{"java.lang.String"});
return success;
}
public static void createCLB(String clbName, HandlerContext handlerContext)
throws Exception {
String clbConfigFileName = (String) handlerContext.getInputValue("configFileName");
if (GuiUtil.isEmpty(clbConfigFileName)) {
clbConfigFileName = clbName + CLB_CONFIG_FILE_NAME_SUFFIX;
}
Boolean autoApply = (Boolean) handlerContext.getInputValue("autoApply");
if (autoApply == null) {
autoApply = false;
}
ArrayList<String> targets = new ArrayList();
String[] list = (String[]) handlerContext.getInputValue("targets");
if(list != null) {
targets = new ArrayList(Arrays.asList(list));
// need to check for empty string in case none of the targets are selected
if ((targets.size() == 1) && (((String)targets.get(0)).trim().length() == 0))
targets.remove(0);
}
if(targets.size() == 0) {
GuiUtil.handleError(handlerContext, "Please select atleast one target for hosting the CLB");
return;
} else {
Boolean isCluster = TargetUtil.isCluster(targets.get(0));
for(String sel: targets){
AMXConfig sc = null;
if(isCluster)
sc = AMXUtil.getDomainConfig().getClusterConfigMap().get(sel);
else
sc = AMXUtil.getDomainConfig().getStandaloneServerConfigMap().get(sel);
if (sc == null){
GuiUtil.handleError(handlerContext, GuiUtil.getMessage("loadBalancer.targetHelp"));
return;
}
}
}
AttributeList attrList = new AttributeList();
Boolean selfLB = (Boolean) handlerContext.getInputValue("selfLB");
if (selfLB == null) {
selfLB = false;
}
Attribute selfLBAttr = new Attribute("selfloadbalance", selfLB.toString());
attrList.add(selfLBAttr);
//Need to add lbenableallInstances defaulted to true
attrList.add(new Attribute("lbenableallinstances", "true"));
for(String targetName: targets) {
Object params[] = {null, attrList, clbConfigFileName, autoApply, targetName, null, clbName};
String types[] = {"java.lang.String", "javax.management.AttributeList", "java.lang.String",
"java.lang.Boolean","java.lang.String","java.util.Properties", "java.lang.String"};
JMXUtil.invoke(CLB_CONFIGS_OBJECT_NAME, "createConvergedLoadBalancer",
params, types);
}
}
/** The function checks to see if a CLB exists on the given target name
*
* @param targetName The name of the target
* @return True if CLB exists
*/
public static boolean existsCLB(String targetName) {
String configName = AMXUtil.getConfigName(targetName);
String objectName = CLB_OBJECT_NAME + ",config=" + configName;
return JMXUtil.isValidMBean(objectName);
}
/** The function checks to see if a CLB Config exists with the given config name
*
* @param clbConfigName The name of the CLB config
* @return returns True if CLB config exists
*/
public static boolean existsCLBConfig(String clbConfigName) {
String objectName = CLB_CONFIG_OBJECT_NAME + ",name=" + clbConfigName;
return JMXUtil.isValidMBean(objectName);
}
/** The function returns true if the config name is not being used as the config for any of the
* available CLBs
*/
public static Boolean isOrphanCLBConfig(String clbConfigName) {
ArrayList<String> clbs = getConvergedLoadBalancers();
for (String clbName : clbs) {
String targetCLBConfigName = getCLBConfig(clbName).getKeyProperty("name");
if (clbConfigName.equals(targetCLBConfigName)) {
// this config is used by another CLB
return false;
}
}
return true;
}
public static ObjectName getCLB(String targetName) throws MalformedObjectNameException {
if(existsCLB(targetName)) {
return new ObjectName(CLB_OBJECT_NAME + ",config=" + AMXUtil.getConfigName(targetName));
}
return null;
}
public static ArrayList getTargetsWithoutCLB() {
ArrayList targets = new ArrayList();
ArrayList<String> serverList = SipTargetUtil.getAllTargets();
for (String targetName: serverList) {
try {
if(!CLBHelper.existsCLB(targetName)) {
targets.add(targetName);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
return targets;
}
public static HashMap getCLBInfo(String targetName) throws Exception {
HashMap clbInfoMap = new HashMap();
Boolean autoApply = false;
ObjectName clb = getCLB(targetName);
if (clb != null) {
clbInfoMap.put("clbName", (String) JMXUtil.getAttribute(clb, CLB_KEYS.NAME));
clbInfoMap.put("configFile", (String) JMXUtil.getAttribute(clb, CLB_KEYS.CONFIG_FILE));
autoApply = Boolean.parseBoolean((String)JMXUtil.getAttribute(clb, CLB_KEYS.AUTO_COMMIT));
if (autoApply == null) {
autoApply = false;
}
clbInfoMap.put("configName", (String)JMXUtil.getAttribute(clb, CLB_KEYS.CLB_CONFIG_NAME));
ObjectName proxy = (ObjectName)SipUtil.getChildByFunction(clb, "getProxy");
clbInfoMap.put("reqPoolSize", (String)JMXUtil.getAttribute(proxy, CLB_PROXY_KEYS.REQUEST_POOL_SIZE));
clbInfoMap.put("sendRetryCount", (String)JMXUtil.getAttribute(proxy,
CLB_PROXY_KEYS.SEND_RETRY_COUNT));
clbInfoMap.put("readTimeout", (String)JMXUtil.getAttribute(proxy,
CLB_PROXY_KEYS.READ_TIMEOUT_IN_MILLIS));
HashMap props = SipUtil.getProperties(proxy);
clbInfoMap.put("props", props);
}
clbInfoMap.put("autoApply", autoApply);
return clbInfoMap;
}
public static HashMap getCLBConfigInfoMap(String clbName)throws Exception {
HashMap clbConfigInfoMap = new HashMap();
ObjectName clbConfig = getCLBConfig(clbName);
clbConfigInfoMap.put("configName", clbConfig.getKeyProperty("name"));
clbConfigInfoMap.put("clbConfigProps", SipUtil.getProperties(clbConfig));
ObjectName clbPolicy = (ObjectName) SipUtil.getChildByFunction(clbConfig, "getConvergedLbPolicy");
clbConfigInfoMap.put("selectedSipPolicies", new String[]{""});
clbConfigInfoMap.put("dcrFile", "none");
if (clbPolicy != null) {
// Get the DCR file properties
String dcrFile = (String) JMXUtil.getAttribute(clbPolicy, CLB_POLICY_KEYS.DCR_FILE);
if ((dcrFile != null) && (dcrFile.trim().length() > 0)) {
if (dcrFile.indexOf(".v") != -1) {
dcrFile = dcrFile.substring(0, dcrFile.indexOf(".v"));
}
clbConfigInfoMap.put("dcrFile", dcrFile);
clbConfigInfoMap.put("showDCRRemoveButton", Boolean.TRUE);
} else {
clbConfigInfoMap.put("showDCRRemoveButton", Boolean.FALSE);
}
//Get HTTP/SIP Policy properties
String httpPolicy = (String) JMXUtil.getAttribute(clbPolicy, CLB_POLICY_KEYS.HTTP);
clbConfigInfoMap.put("httpPolicy", httpPolicy);
String sipPolicy = (String) JMXUtil.getAttribute(clbPolicy, CLB_POLICY_KEYS.SIP);
clbConfigInfoMap.put("selectedSipPolicies", GuiUtil.stringToArray(sipPolicy, ","));
clbConfigInfoMap.put("policyProps", SipUtil.getProperties(clbPolicy));
}
String defSipPolicies = (String)SipUtil.getDefaultAttributeValues("converged-lb-policy").get("sip");
clbConfigInfoMap.put("sipPolicies", ConfigurationHandlers.getOptions(
GuiUtil.stringToArray(defSipPolicies, ",")));
List<String> refTargets = getCLBRefTargets(clbName);
Boolean selfLB = false;
if (refTargets.size() > 0) {
// All targets will have the same self LB value
HashMap refInfo = getCLBRefInfo(clbName, (String) refTargets.get(0));
selfLB = (Boolean) refInfo.get("selfLoadBalancing");
}
clbConfigInfoMap.put("selfLoadBalancing", selfLB);
if(selfLB) {
clbConfigInfoMap.put("topology", SipUtil.getMessage("clb.selfLB.label"));
} else {
clbConfigInfoMap.put("topology", SipUtil.getMessage("clb.non-selfLB.label"));
}
return clbConfigInfoMap;
}
public static void copyCLB(HashMap clbInfo, String targetName) throws Exception{
Properties proxyProps = new Properties();
proxyProps.putAll((HashMap)clbInfo.get("props"));
Object params[] = {(String)clbInfo.get("configFile"),
(String)clbInfo.get("configName"), (Boolean)clbInfo.get("autoApply"),
targetName, proxyProps, (String)clbInfo.get("clbName")};
String types[] = {"java.lang.String","java.lang.String",
"java.lang.Boolean","java.lang.String","java.util.Properties",
"java.lang.String"};
JMXUtil.invoke(CLB_CONFIGS_OBJECT_NAME, "createConvergedLoadBalancer",
params, types);
ObjectName clb = getCLB(targetName);
ObjectName proxy = (ObjectName) SipUtil.getChildByFunction(clb, "getProxy");
HashMap attrs = new HashMap();
attrs.put(CLB_PROXY_KEYS.REQUEST_POOL_SIZE, clbInfo.get("reqPoolSize"));
attrs.put(CLB_PROXY_KEYS.SEND_RETRY_COUNT, clbInfo.get("sendRetryCount"));
attrs.put(CLB_PROXY_KEYS.READ_TIMEOUT_IN_MILLIS, clbInfo.get("readTimeout"));
SipUtil.setAttributeValues(proxy, attrs);
SipUtil.setProperties(proxy, (HashMap) clbInfo.get("props"), null);
}
public static HashMap getCLBRefInfo(String clbName, String targetName) throws Exception {
HashMap clbRefInfoMap = new HashMap();
Boolean isCluster = TargetUtil.isCluster(targetName);
ObjectName clbConfig = getCLBConfig(clbName);
if (isCluster) {
// this is a cluster ref
ObjectName clusterRef = (ObjectName) SipUtil.getChildByFunction(clbConfig,
"getConvergedLbClusterRefByRef",
new Object[]{targetName}, new String[]{"java.lang.String"});
Boolean selfLoadBalance = Boolean.parseBoolean((String)
JMXUtil.getAttribute(clusterRef, CLB_CLUSTER_REF_KEYS.SELF_LOADBALANCE));
clbRefInfoMap.put("selfLoadBalancing", selfLoadBalance);
} else {
ObjectName serverRef = (ObjectName) SipUtil.getChildByFunction(clbConfig,
"getServerRefByRef",
new Object[]{targetName}, new String[]{"java.lang.String"});
clbRefInfoMap.put("disableTimeoutInMinutes",
JMXUtil.getAttribute(serverRef, SERVER_REF_KEYS.DISABLE_TIMEOUT_IN_MINUTES));
/*clbRefInfoMap.put("enabled",
JMXUtil.getAttribute(serverRef, SERVER_REF_KEYS.ENABLED));
clbRefInfoMap.put("lbEnabled",
JMXUtil.getAttribute(serverRef, SERVER_REF_KEYS.LB_ENABLED));*/
ObjectName healthChecker = (ObjectName) SipUtil.getChildByFunction(serverRef, "getHealthChecker");
if (healthChecker != null) {
clbRefInfoMap.put("intervalInSeconds",
JMXUtil.getAttribute(healthChecker, HEALTH_CHECKER_KEYS.INTERVAL_IN_SECONDS));
clbRefInfoMap.put("timeoutInSeconds",
JMXUtil.getAttribute(healthChecker, HEALTH_CHECKER_KEYS.TIMEOUT_IN_SECONDS));
clbRefInfoMap.put("url",
JMXUtil.getAttribute(healthChecker, HEALTH_CHECKER_KEYS.URL));
}
clbRefInfoMap.put("selfLoadBalancing", false);
}
clbRefInfoMap.put("isCluster", isCluster);
clbRefInfoMap.put("targetName", targetName);
return clbRefInfoMap;
}
public static ArrayList getCLBRefTargets(String clbName) throws Exception{
ObjectName clbConfig = CLBHelper.getCLBConfig(clbName);
ArrayList<String> targets = new ArrayList();
if (existsCLBConfig(clbConfig.getKeyProperty("name"))) {
String[] serverRefs = (String[]) JMXUtil.invoke(clbConfig, "getServerRefNamesList",
null, null);
String[] clusterRefs = (String[]) JMXUtil.invoke(clbConfig, "getConvergedLbClusterRefNamesList",
null, null);
if ((serverRefs != null) && (serverRefs.length > 0)) {
targets = new ArrayList(Arrays.asList(serverRefs));
} else if ((clusterRefs != null) && (clusterRefs.length > 0)) {
targets = new ArrayList(Arrays.asList(clusterRefs));
}
}
return targets;
}
public static void deleteCLBRef(String clbName, String targetName) throws Exception {
Object params[] = {null, clbName, Boolean.TRUE, targetName};
JMXUtil.invoke(CLB_CONFIGS_OBJECT_NAME, "deleteConvergedLbRef", params,
new String[] {"java.lang.String", "java.lang.String", "java.lang.Boolean", "java.lang.String"});
}
public static void createCLBRef(String clbName, String targetName, HashMap refInfoMap) throws Exception {
String clbConfigName = getCLBConfig(clbName).getKeyProperty("name");
Boolean selfLB = (Boolean) refInfoMap.get("selfLoadBalancing");
if(selfLB == null) {
selfLB = false;
}
// TODO provide enabling apps and instances functionality
Boolean lbEnableAllInstances = false; //Boolean.parseBoolean((String) refInfoMap.get("lbEnabledAllInstances"));
Object params[] = {null, clbConfigName, selfLB, lbEnableAllInstances, targetName};
JMXUtil.invoke(CLB_CONFIGS_OBJECT_NAME, "createConvergedLbRef", params,
new String[] {"java.lang.String", "java.lang.String", "java.lang.Boolean",
"java.lang.Boolean", "java.lang.String"});
}
/** The function is used to figure out if a CLB is self load balancing
* The criteria for selfLB is targets.size()==1 && (self-lb==true) for clusters
* If the LB target is a standalone instance then the criteria is
* targets.size == 1 && (server-ref-name==clb-target)
* @param clbName
* @return
* @throws java.lang.Exception
*/
public static boolean isSelfLB(String clbName) throws Exception {
boolean isSelfLB = false;
ArrayList<String> targets = getCLBRefTargets(clbName);
// Self LB criteria is target + cluster-ref== + self-lb==true
if (targets.size() == 1) {
//check that the target ref is a cluster
String targetName = targets.get(0);
ObjectName clbConfig = getCLBConfig(clbName);
boolean isCluster = TargetUtil.isCluster(targetName);
if (isCluster) {
ObjectName clusterRef = (ObjectName) SipUtil.getChildByFunction(clbConfig,
"getConvergedLbClusterRefByRef",
new Object[]{targetName}, new String[]{"java.lang.String"});
if(clusterRef != null) {
isSelfLB = Boolean.parseBoolean((String)
JMXUtil.getAttribute(clusterRef, CLB_CLUSTER_REF_KEYS.SELF_LOADBALANCE));
}
} else {
String hostingTarget = getCLBHostingTarget(clbName);
isSelfLB = (targetName.equals(hostingTarget));
}
}
return isSelfLB;
}
public static void setDCRFile(String filePath, String clbConfigName, String clbName) throws Exception{
Object[] params = new Object[]{filePath, clbConfigName, clbName};
String[] types = SipUtil.getSignatureArray(params);
JMXUtil.invoke(CLB_CONFIGS_OBJECT_NAME, "setDcrFile",
params, types);
}
/** This function is used to get the first target defined for a CLB
*
* @param clbName The CLB name
* @return the first available target for the CLB
*/
public static String getCLBHostingTarget(String clbName) {
HashSet<String> serversList = new HashSet<String>(AMXUtil.getDomainConfig().getClusterConfigMap().keySet());
serversList.addAll(AMXUtil.getDomainConfig().getStandaloneServerConfigMap().keySet());
for (String targetName: serversList) {
try {
if(existsCLB(targetName)) {
String objectName = CLB_OBJECT_NAME + ",config=" + AMXUtil.getConfigName(targetName);
String targetCLBName = (String) JMXUtil.getAttribute(objectName, "name");
if(clbName.equals(targetCLBName)) {
return targetName;
}
}
} catch (Exception ex) {
}
}
return null;
}
}