Package org.wso2.carbon.mediator.autoscale.ec2autoscale

Source Code of org.wso2.carbon.mediator.autoscale.ec2autoscale.EC2LoadAnalyzerTask

/*
* Copyright 2004,2005 The Apache Software Foundation.
*
* 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 org.wso2.carbon.mediator.autoscale.ec2autoscale;

import org.apache.axis2.AxisFault;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.context.ConfigurationContextFactory;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.synapse.core.SynapseEnvironment;
import org.wso2.carbon.base.ServerConfiguration;
import org.wso2.carbon.ec2client.EC2Client;
import org.wso2.carbon.ec2client.EC2Exception;
import org.wso2.carbon.ec2client.data.*;
import org.wso2.carbon.mediator.autoscale.AutoscaleUtil;
import org.wso2.carbon.mediator.autoscale.LoadAnalyzerTask;
import org.wso2.carbon.utils.ServerConstants;
import sun.misc.BASE64Encoder;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class EC2LoadAnalyzerTask extends LoadAnalyzerTask {

    private static final Log                log             = LogFactory.getLog(EC2LoadAnalyzerTask.class);
    private static       EC2InstanceManager instanceManager = new EC2InstanceManager();

    private static final String CLIENT_REPOSITORY_LOCATION = "Axis2Config.ClientRepositoryLocation";
    private static final String CLIENT_AXIS2_XML_LOCATION  = "Axis2Config.clientAxis2XmlLocation";
    private static final String INSTANCE_MGT_WS_ENDPOINT   = "InstanceMgtWSEndpoint";

    private static boolean wasAddressAssignedToMe = false;

    private String pEc2PrivateKey;
    private String pEc2Cert;
    private String pElasticIP = System.getenv("ELASTIC_IP");
    private ConfigurationContext clientConfigContext;


    /*
      Load Balanced Service and the load balancer instance types
     */
    private String pInstanceType             = InstanceType.LARGE.getType();
    private String pLoadBalancerInstanceType = InstanceType.SMALL.getType();

    private String pInstanceAdditionalInfo;
    private String pKey;
    private String pImageId = System.getenv("ami_id");
    private String pApplicationPayload;
    private String pLoadBalancerPayload;

    private List<Instance> runningApplicationInstances = new ArrayList<Instance>();
    private List<Instance> pendingApplicationInstances = new ArrayList<Instance>();
    private List<Instance> runningLBInstances          = new ArrayList<Instance>();
    private List<Instance> pendingLBInstances          = new ArrayList<Instance>();

    public void setApplicationPayload(String pApplicationPayload) {
        this.pApplicationPayload = pApplicationPayload;
    }

    public void setLoadBalancerPayload(String pLoadBalancerPayload) {
        this.pLoadBalancerPayload = pLoadBalancerPayload;
    }

    public void init(SynapseEnvironment synEnv) {
        super.init(synEnv);
        try {
            createClientConfigContext();
        } catch (EC2Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void execute() {

        applicationGroupIds = extractGroupIds(pApplicationGroup);
        loadBalancerGroupIds = extractGroupIds(getPLoadBalancerGroup());

        if (!instanceManager.isEC2Client()) {
            try {
                createEC2Client();
                setInstanceManager(instanceManager);

                /*pick the current information and put in to Map and parse it to EC2InstanceManager methods*/
                setRunInstanceDataforEC2();
                calculateRunningAndPendingInstances();
            } catch (EC2Exception e) {
                autoscaleUtil.handleException(e.getMessage(), e);
            }
        } else {
            try {
                createEC2Client();
            } catch (EC2Exception e) {
                autoscaleUtil.handleException(e.getMessage(), e);
            }
            setInstanceManager(instanceManager);
            try {
                calculateRunningAndPendingInstances();
            } catch (EC2Exception e) {
                autoscaleUtil.handleException(e.getMessage(), e);
            }
        }
        super.execute();
    }

    private void createClientConfigContext() throws EC2Exception {
        // we can not use the same synapse configuration context object here.
        // synapse configuration context uses its nhttp transport which can not
        // use with the axis2 client
        //TODO Use the clienSide ConfigContext from the OSGi service
        ServerConfiguration serverConfig = ServerConfiguration.getInstance();
        String clientRepositoryLocation =
            serverConfig.getFirstProperty(CLIENT_REPOSITORY_LOCATION);
        String clientAxis2XmlLocation =
            serverConfig.getFirstProperty(CLIENT_AXIS2_XML_LOCATION);
        try {
            clientConfigContext =
                ConfigurationContextFactory.createConfigurationContextFromFileSystem(
                    clientRepositoryLocation, clientAxis2XmlLocation);
        } catch (AxisFault e) {
            throw new EC2Exception("Cannot create new client ConfigurationContext for EC2 client", e);
        }
        clientConfigContext.setProperty(ServerConstants.WORK_DIR,
                                        System.getProperty("axis2.work.dir"));
    }

    private void createEC2Client() throws EC2Exception {
        ServerConfiguration serverConfig = ServerConfiguration.getInstance();
        String instanceMgtWSEndpoint =
            serverConfig.getFirstProperty(INSTANCE_MGT_WS_ENDPOINT);

        instanceManager.setNonReplicapableProperty(getConfigCtx())// TODO FIXME: Why is this needed
        EC2Client ec2Client = new EC2Client(clientConfigContext, pEc2PrivateKey, pEc2Cert);
        if (instanceMgtWSEndpoint == null || instanceMgtWSEndpoint.length() == 0) {
            instanceManager.setEc2Client(ec2Client);
        } else {
            instanceManager.setEc2Client(ec2Client);
        }
    }

    private void calculateRunningAndPendingInstances() throws EC2Exception {
        //Calculate running and pending instances
        List<Instance> instances = instanceManager.describeInstances();
        for (Instance instance : instances) {
            if (instance.getImage().getImageId().equals(pImageId)) {
                //Calculating Application instances
                if (containGroupIds(applicationGroupIds, instance.getGroupIds())) {
                    if (instance.getCurrentState().equals(InstanceState.RUNNING)) {
                        runningApplicationInstances.add(instance);
                    } else if (instance.getCurrentState().equals(InstanceState.PENDING)) {
                        pendingApplicationInstances.add(instance);
                    }
                }
                //Calculating LB instances
                if (containGroupIds(loadBalancerGroupIds, instance.getGroupIds())) {
                    if (instance.getCurrentState().equals(InstanceState.RUNNING)) {
                        runningLBInstances.add(instance);
                    } else if (instance.getCurrentState().equals(InstanceState.PENDING)) {
                        pendingLBInstances.add(instance);
                    }
                }
            }
        }
    }

    /**
     * Carry out a sanity check. Checks whether the system meets the minimum requirements
     *
     * @return whether the caller has to continue execution or not.
     *         true - continue execution, false - abort execution
     * @throws EC2Exception IF an error occurs while communicating with EC2
     */
    public boolean doSanityCheck() throws EC2Exception {

        // Assign the elastic IP to itself, if not already assigned
        if (!wasAddressAssignedToMe) {
            List<Address> addressList = instanceManager.describeAddresses(new String[]{pElasticIP});
            String localInstanceId = System.getenv("instance_id");

            // Associate this address with this instance only if any other instance has not assigned it to itself
            Instance instance = null;
            if (addressList.size() > 0) {
                instance = addressList.get(0).getInstance();
            } else {
                autoscaleUtil.handleException("Elastic IP address " + pElasticIP + " has  not been reserved");
            }
            if ((instance == null) ||
                !(instance.getCurrentState().equals(InstanceState.RUNNING) ||
                    instance.getCurrentState().equals(InstanceState.PENDING))) {
                // if the instance is not running or pending we assume that the instance has die
                instanceManager.associateAddress(localInstanceId, pElasticIP);
                wasAddressAssignedToMe = true;
                // if a new IPAddress was assigned to this instance,
                // it needs to create a new client since the IP address has changed
                createEC2Client();
                log.info("Associated Elastic IP " + pElasticIP + " with local instance " + localInstanceId);
            } else if (!instance.getInstanceId().equals(localInstanceId)) {  // Address assigned to a running instance
                return false// This is not the primary load balancer. Hence, need not continue
            }
        }

        // Recheck whether this instance is still the primary LB, if it assigned the address to itself
//        if (wasAddressAssignedToMe) {
//            addressList = imanager.describeAddresses(new String[]{pElasticIP});
//            if (!addressList.get(0).getInstance().getInstanceId().equals(localInstanceId)) {
//                return false;
//            }
//        }

        //TODO LB instance is 1 for this stratos release
        // Check the min number of load balancer instances
        int currentLoadBalancerInstances = runningLBInstances.size() + pendingLBInstances.size();
//        if (log.isDebugEnabled()) {
//            log.info("Current LB instances=" + currentLoadBalancerInstances);
//            log.info("Min LB instances=" + getPMinLoadBalancerInstances());
//        }

        if (currentLoadBalancerInstances < getMinLoadBalancerInstances()) {
            log.warn("Sanity check failed. Min LB instances is: " + currentLoadBalancerInstances +
                         ". Specified min LB instances is: " + getMinLoadBalancerInstances());
            int diff = getMinLoadBalancerInstances() - currentLoadBalancerInstances;

            // Launch diff number of LB instances
            log.info("Launching " + diff + " LB instances");
            instanceManager.runInstances(pImageId,
                                         diff,
                                         InstanceType.getTypeFromString(pLoadBalancerInstanceType),
                                         pKey,
                                         loadBalancerGroupIds,
                                         pInstanceAdditionalInfo,
                                         getLoadBalancerUserData(),
                                         new AvailabilityZone(getAvailabilityZone(), ""));
            return false;
        }

        // Check the min number of Axis2 instances
        int currentAxis2Instances = runningApplicationInstances.size() + pendingApplicationInstances.size();
//        if (log.isDebugEnabled()) {
//            log.info("Current Axis2 instances=" + currentAxis2Instances);
//            log.info("Min Axis2 instances=" + getPMinAppInstances());
//        }

        if (currentAxis2Instances < getPMinAppInstances()) {
            log.warn("Sanity check failed. Min Axis2 instances is: " + currentAxis2Instances +
                         ". Specified min Axis2 instances is: " + getPMinAppInstances());
            int diff = getPMinAppInstances() - currentAxis2Instances;

            // Launch diff number of axis2 instances
            log.info("Launching " + diff + " Axis2 instances");
            instanceManager.runInstances(pImageId,
                                         diff,
                                         InstanceType.getTypeFromString(pInstanceType),
                                         pKey,
                                         applicationGroupIds,
                                         pInstanceAdditionalInfo,
                                         getAppUserData(),
                                         new AvailabilityZone(getAvailabilityZone(), ""));
        }
        //TODO: Even if an instance is running, Axis2 may not be running, handle that situ

        return true;
    }

    public void setEc2PrivateKey(String ec2PrivateKey) {
        this.pEc2PrivateKey = ec2PrivateKey;
    }

    public void setEc2Cert(String ec2Cert) {
        this.pEc2Cert = ec2Cert;
    }

    public void setInstanceType(String pInstanceType) {
        this.pInstanceType = pInstanceType;
    }

    public void setLoadBalancerInstanceType(String pLoadBalancerInstanceType) {
        this.pLoadBalancerInstanceType = pLoadBalancerInstanceType;
    }

    public void setInstanceAdditionalInfo(String instanceAdditionalInfo) {
        this.pInstanceAdditionalInfo = instanceAdditionalInfo;
    }

    public void setKey(String key) {
        this.pKey = key;
    }

    public void setElasticIP(String elasticIP) {
        if (this.pElasticIP == null) {
            this.pElasticIP = autoscaleUtil.replaceVariables(elasticIP);
        }
    }

    public List<Instance> getRunningApplicationInstances() throws Exception {
//        List applicationInstances = new ArrayList<Instance>();
//        List<Instance> instances = getInstanceManager().describeInstances();
//
//        for (Instance instance : instances) {
//            if (instance.getImage().getImageId().equals(pImageId) &&
//                    instance.getCurrentState().equals(InstanceState.RUNNING) &&
//                    containGroupIds(applicationGroupIds, instance.getGroupIds())) {
//                applicationInstances.add(instance);
//            }
//        }
//        return applicationInstances;
        return runningApplicationInstances;
    }

    public List<Instance> getPendingApplicationInstances() throws Exception {
//        List<Instance> applicationInstances = new ArrayList<Instance>();
//        List<Instance> instances = getInstanceManager().describeInstances();
//        for (Instance instance : instances) {
//            if (instance.getImage().getImageId().equals(pImageId) &&
//                    instance.getCurrentState().equals(InstanceState.PENDING) &&
//                    containGroupIds(applicationGroupIds, instance.getGroupIds())) {
//                applicationInstances.add(instance);
//            }
//        }
//        return applicationInstances;
        return pendingApplicationInstances;
    }

//    private List<Instance> getRunningAndPendingInstances(String[] groupIds) throws EC2Exception {
//        List<Instance> applicationInstances = new ArrayList<Instance>();
//            List<Instance> instances = imanager.describeInstances();
//        for (Instance instance : instances) {
//            if (instance.getImage().getImageId().equals(pImageId) &&
//                    (instance.getCurrentState().equals(InstanceState.RUNNING) ||
//                    instance.getCurrentState().equals(InstanceState.PENDING))  &&
//                    containGroupIds(groupIds, instance.getGroupIds())) {
//                applicationInstances.add(instance);
//            }
//        }
//        return applicationInstances;
//    }

    private void setRunInstanceDataforEC2() throws EC2Exception {
        if (runInstanceData == null) {
            runInstanceData = new HashMap();
            runInstanceData.put("ImageId", pImageId);
            runInstanceData.put("InstancesPerScaleUp", getPInstancesPerScaleUp());
            runInstanceData.put("InstanceType", InstanceType.getTypeFromString(pInstanceType));
            runInstanceData.put("Key", pKey);
            runInstanceData.put("ApplicationGroupIds", applicationGroupIds);
            runInstanceData.put("InstanceAdditionalInfo", pInstanceAdditionalInfo);
            runInstanceData.put("UserData", getAppUserData());
            runInstanceData.put("AvailabilityZone", new AvailabilityZone(getAvailabilityZone(), ""));
        }
    }

    public UserData getAppUserData() throws EC2Exception {
        UserData userData = new UserData();
        try {
            byte[] bytes = AutoscaleUtil.getBytesFromFile(new File(pApplicationPayload));
            BASE64Encoder encoder = new BASE64Encoder();
            String userDataStr = encoder.encode(bytes);
            userData.setData(userDataStr);
        } catch (IOException e) {
            autoscaleUtil.handleException("Cannot read data from payload file", e);
        }
        return userData;
    }

    public UserData getLoadBalancerUserData() throws EC2Exception {
        UserData userData = new UserData();
        try {
            byte[] bytes = AutoscaleUtil.getBytesFromFile(new File(pLoadBalancerPayload));
            BASE64Encoder encoder = new BASE64Encoder();
            String userDataStr = encoder.encode(bytes);
            userData.setData(userDataStr);
        } catch (IOException e) {
            autoscaleUtil.handleException("Cannot read data from payload file", e);
        }
        return userData;
    }

}
TOP

Related Classes of org.wso2.carbon.mediator.autoscale.ec2autoscale.EC2LoadAnalyzerTask

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.