io.subutai.plugin.appscale.impl.AppScaleImpl.java Source code

Java tutorial

Introduction

Here is the source code for io.subutai.plugin.appscale.impl.AppScaleImpl.java

Source

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package io.subutai.plugin.appscale.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;

import javax.net.ssl.TrustManager;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.codehaus.jackson.jaxrs.JacksonJsonProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.apache.cxf.configuration.jsse.TLSClientParameters;
import org.apache.cxf.jaxrs.client.WebClient;
import org.apache.cxf.transport.http.HTTPConduit;

import com.google.common.base.Preconditions;
import com.google.common.base.Strings;

import io.subutai.common.command.CommandException;
import io.subutai.common.command.CommandResult;
import io.subutai.common.command.RequestBuilder;
import io.subutai.common.environment.Blueprint;
import io.subutai.common.environment.ContainerHostNotFoundException;
import io.subutai.common.environment.Environment;
import io.subutai.common.environment.EnvironmentNotFoundException;
import io.subutai.common.environment.EnvironmentStatus;
import io.subutai.common.environment.NodeSchema;
import io.subutai.common.environment.Topology;
import io.subutai.common.mdc.SubutaiExecutors;
import io.subutai.common.peer.ContainerSize;
import io.subutai.common.peer.EnvironmentContainerHost;
import io.subutai.common.peer.EnvironmentId;
import io.subutai.common.peer.HostNotFoundException;
import io.subutai.common.peer.LocalPeer;
import io.subutai.common.peer.ResourceHost;
import io.subutai.common.tracker.TrackerOperation;
import io.subutai.core.environment.api.EnvironmentEventListener;
import io.subutai.core.environment.api.EnvironmentManager;
import io.subutai.core.identity.api.IdentityManager;
import io.subutai.core.lxc.quota.api.QuotaManager;
import io.subutai.core.metric.api.Monitor;
import io.subutai.core.network.api.NetworkManager;
import io.subutai.core.peer.api.PeerManager;
import io.subutai.core.plugincommon.api.AbstractOperationHandler;
import io.subutai.core.plugincommon.api.ClusterException;
import io.subutai.core.plugincommon.api.ClusterOperationType;
import io.subutai.core.plugincommon.api.ClusterSetupStrategy;
import io.subutai.core.plugincommon.api.PluginDAO;
import io.subutai.core.tracker.api.Tracker;
import io.subutai.plugin.appscale.api.AppScaleConfig;
import io.subutai.plugin.appscale.api.AppScaleInterface;
import io.subutai.plugin.appscale.impl.handler.AppscaleAlertHandler;
import io.subutai.plugin.appscale.impl.handler.ClusterOperationHandler;

import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;

/**
 *
 * @author caveman
 * @author Beyazt Keleolu
 */
public class AppScaleImpl implements AppScaleInterface, EnvironmentEventListener {

    private static final Logger LOG = LoggerFactory.getLogger(AppScaleImpl.class.getName());
    private ExecutorService executor;
    private final Monitor monitor;
    private final PluginDAO pluginDAO;
    private Tracker tracker;
    private EnvironmentManager environmentManager;
    private NetworkManager networkManager;
    private QuotaManager quotaManager;
    private PeerManager peerManager;
    private IdentityManager identityManager;
    private Environment environment;
    private AppScaleConfig appScaleConfig;
    private static final String BUILD_TOPOLOGY_URL = "https://localhost:8443/rest/v1/strategy/ROUND-ROBIN-STRATEGY";
    private static final String ENVIRONMENT_URL = "https://localhost:8443/rest/v1/environments/";

    private static String GET_TOKEN_URL = "https://localhost:8443/rest/v1/identity/gettoken?username=%s&password=%s";

    private String token;

    public AppScaleImpl(Monitor monitor, PluginDAO pluginDAO, IdentityManager identityManager) {
        this.monitor = monitor;
        this.pluginDAO = pluginDAO;
        this.identityManager = identityManager;
    }

    public void init() {
        executor = SubutaiExecutors.newCachedThreadPool();
    }

    public void destroy() {

    }

    /**
     *
     * @param appScaleConfig
     * @return
     *
     * setup -> install
     *
     */
    @Override
    public UUID installCluster(AppScaleConfig appScaleConfig) {
        LOG.info("install cluster started");

        Preconditions.checkNotNull(appScaleConfig, "Configuration is null");
        Preconditions.checkArgument(!Strings.isNullOrEmpty(appScaleConfig.getClusterName()),
                "clusterName is empty or null");

        AbstractOperationHandler abstractOperationHandler = new ClusterOperationHandler(this, appScaleConfig,
                ClusterOperationType.INSTALL, this.identityManager);
        LOG.info("install cluster " + abstractOperationHandler);
        executor.execute(abstractOperationHandler);
        LOG.info("install executor " + " tracker id: " + abstractOperationHandler.getTrackerId());
        getPluginDAO().saveInfo(AppScaleConfig.PRODUCT_KEY, appScaleConfig.getClusterName(), appScaleConfig);
        return abstractOperationHandler.getTrackerId();
    }

    @Override
    /**
     * returns true if container installed
     */
    public Boolean checkIfContainerInstalled(AppScaleConfig appScaleConfig) {
        Boolean ret = true;

        Preconditions.checkNotNull(appScaleConfig, "Configuration is null");
        Preconditions.checkArgument(!Strings.isNullOrEmpty(appScaleConfig.getClusterName()),
                "clusterName is empty or null");

        try {
            EnvironmentContainerHost containerHostByHostname = environment
                    .getContainerHostByHostname(appScaleConfig.getClusterName());
            CommandResult commandResult = containerHostByHostname.execute(new RequestBuilder(Commands.getPsAUX()));
            if (commandResult.getStdOut().contains("No such file or directory")) {
                ret = false;
            }
        } catch (ContainerHostNotFoundException | CommandException ex) {
            java.util.logging.Logger.getLogger(AppScaleImpl.class.getName()).log(Level.SEVERE, null, ex);
        }
        return ret;
    }

    @Override
    public UUID uninstallCluster(AppScaleConfig appScaleConfig) {
        Preconditions.checkNotNull(appScaleConfig, "Configuration is null");
        Preconditions.checkArgument(!Strings.isNullOrEmpty(appScaleConfig.getClusterName()),
                "clusterName is empty");
        AbstractOperationHandler abstractOperationHandler = new ClusterOperationHandler(this, appScaleConfig,
                ClusterOperationType.UNINSTALL, this.identityManager);
        executor.execute(abstractOperationHandler);
        return abstractOperationHandler.getTrackerId();
    }

    @Override
    public void configureSsh(AppScaleConfig appScaleConfig) {
        try {
            EnvironmentContainerHost containerHost = environment
                    .getContainerHostByHostname(appScaleConfig.getClusterName());
            String ipAddress = this.getIPAddress(containerHost);
            String command1443 = "ssh -f -N -R 1443:" + ipAddress + ":1443 ubuntu@localhost";
            String command5555 = "ssh -f -N -R 5555:" + ipAddress + ":5555 ubuntu@localhost";
            String command8081 = "ssh -f -N -R 8081:" + ipAddress + ":8081 ubuntu@localhost";

            LocalPeer localPeer = peerManager.getLocalPeer();
            ResourceHost resourceHostByContainerId = localPeer.getResourceHostByContainerId(containerHost.getId());
            resourceHostByContainerId.execute(new RequestBuilder(command8081));
            resourceHostByContainerId.execute(new RequestBuilder(command1443));
            resourceHostByContainerId.execute(new RequestBuilder(command5555));

        } catch (ContainerHostNotFoundException | HostNotFoundException | CommandException ex) {
            java.util.logging.Logger.getLogger(AppScaleImpl.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public AppScaleConfig getAppScaleConfig() {
        return appScaleConfig;
    }

    public void setAppScaleConfig(AppScaleConfig appScaleConfig) {
        this.appScaleConfig = appScaleConfig;
    }

    private String getIPAddress(EnvironmentContainerHost ch) {
        String ipaddr = null;
        try {

            String localCommand = "ip addr | grep eth0 | grep \"inet\" | cut -d\" \" -f6 | cut -d\"/\" -f1";
            CommandResult resultAddr = ch.execute(new RequestBuilder(localCommand));
            ipaddr = resultAddr.getStdOut();
            ipaddr = ipaddr.replace("\n", "");
            LOG.info("Container IP: " + ipaddr);
        } catch (CommandException ex) {
            LOG.error("ip address command error : " + ex);
        }
        return ipaddr;

    }

    @Override
    public UUID configureSSH(AppScaleConfig appScaleConfig) {

        AbstractOperationHandler abstractOperationHandler = new ClusterOperationHandler(this, appScaleConfig,
                ClusterOperationType.CUSTOM, this.identityManager);
        executor.execute(abstractOperationHandler);
        return abstractOperationHandler.getTrackerId();

    }

    @Override
    public List<String> getClusterList(Environment name) {
        List<String> c = new ArrayList();
        Set<EnvironmentContainerHost> containerHosts = name.getContainerHosts();
        containerHosts.stream().forEach((ech) -> {
            c.add(ech.toString());
        });
        return c;
    }

    @Override
    public UUID uninstallCluster(String string) {
        return uninstallCluster(getConfig(string));
    }

    @Override
    public UUID startCluster(String clusterName) {

        UUID uuid = null;
        try {
            EnvironmentContainerHost masterContainerHost = environment.getContainerHostByHostname(clusterName);
            AbstractOperationHandler a = (AbstractOperationHandler) masterContainerHost
                    .execute(new RequestBuilder(Commands.getAppScaleStartCommand()));
            uuid = a.getTrackerId();
        } catch (ContainerHostNotFoundException | CommandException ex) {
            java.util.logging.Logger.getLogger(AppScaleImpl.class.getName()).log(Level.SEVERE, null, ex);
        }
        return uuid;

    }

    @Override
    public UUID stopCluster(String clusterName) {
        UUID uuid = null;
        try {
            EnvironmentContainerHost masterContainerHost = environment.getContainerHostByHostname(clusterName);
            AbstractOperationHandler a = (AbstractOperationHandler) masterContainerHost
                    .execute(new RequestBuilder(Commands.getAppScaleStopCommand()));
            uuid = a.getTrackerId();
        } catch (ContainerHostNotFoundException | CommandException ex) {
            java.util.logging.Logger.getLogger(AppScaleImpl.class.getName()).log(Level.SEVERE, null, ex);
        }
        return uuid;
    }

    @Override
    public UUID growEnvironment(AppScaleConfig appScaleConfig) {

        Boolean createAppEngineInstance = new AppscaleAlertHandler(this).createAppEngineInstance(environment,
                appScaleConfig);
        if (createAppEngineInstance) {
            return UUID.randomUUID();
        } else {
            return null;
        }

    }

    @Override
    public UUID restartCluster(String clusterName) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public UUID statusCluster(String clusterName) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public UUID startService(String clusterName, String hostName) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public UUID stopService(String clusterName, String hostName) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public UUID statusService(String clusterName, String hostName) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public UUID addNode(String clusterName) {
        LOG.info("**** Adding Node****");
        List<String> info = getPluginDAO().getInfo(AppScaleConfig.PRODUCT_KEY);
        List<String> appenList = appScaleConfig.getAppenList();
        appenList.add(clusterName);
        appScaleConfig.setAppenList(appenList); // new node added as appengine
        AbstractOperationHandler abstractOperationHandler = new ClusterOperationHandler(this, appScaleConfig,
                ClusterOperationType.CUSTOM, this.identityManager);
        // CUSTOM is to scale 1 node up
        executor.execute(abstractOperationHandler);
        return abstractOperationHandler.getTrackerId();
    }

    public UUID addNode(AppScaleConfig localConfig) {
        LOG.info("**** Adding Node****");
        AbstractOperationHandler abstractOperationHandler = new ClusterOperationHandler(this, localConfig,
                ClusterOperationType.CUSTOM, this.identityManager);
        executor.execute(abstractOperationHandler);
        return abstractOperationHandler.getTrackerId();
    }

    private WebClient createWebClient(String url, Boolean trustCerts) {
        JacksonJsonProvider jsonProvider = new JacksonJsonProvider();
        WebClient webClient = WebClient.create(url, Collections.singletonList(jsonProvider));
        if (trustCerts) {
            HTTPConduit conduit = WebClient.getConfig(webClient).getHttpConduit();
            TLSClientParameters params = conduit.getTlsClientParameters();
            if (params == null) {
                params = new TLSClientParameters();
                conduit.setTlsClientParameters(params);
            }
            params.setTrustManagers(new TrustManager[] { new io.subutai.plugin.appscale.impl.NTM()
                    // new NaiveTrustManager ()
            });
            params.setDisableCNCheck(true);
        }
        return webClient;
    }

    @Override
    public UUID oneClickInstall(AppScaleConfig localConfig) {
        UUID uuid = null;
        token = localConfig.getPermanentToken();
        AppScaleConfig newAppScaleConfig = buildEnvironment(localConfig);
        if (newAppScaleConfig.getClusterName() != null) {
            AbstractOperationHandler abstractOperationHandler = new ClusterOperationHandler(this, newAppScaleConfig,
                    ClusterOperationType.INSTALL, this.identityManager);
            executor.execute(abstractOperationHandler);
            uuid = abstractOperationHandler.getTrackerId();
        }
        return uuid;
    }

    private AppScaleConfig buildEnvironment(AppScaleConfig ac) {
        Random rand = new Random();
        String additionString = randomAlphabetic(10).toLowerCase();
        String containerName = "appscale" + additionString;
        String environmentName = ac.getUserEnvironmentName();
        NodeSchema node = new NodeSchema(containerName, ContainerSize.HUGE, "appscale", 0, 0);
        List<NodeSchema> nodes = new ArrayList<>();
        nodes.add(node);
        Blueprint blueprint = new Blueprint(environmentName, nodes);
        Topology topology = buildTopology(blueprint);
        EnvironmentId envID = createEnvironment(topology);
        Boolean healt = false;
        while (!healt) // possible infinite loop here...
        {
            try {
                TimeUnit.SECONDS.sleep(10);
                Environment env = environmentManager.loadEnvironment(envID.getId());
                if (env != null && env.getStatus().equals(EnvironmentStatus.HEALTHY)) {
                    LOG.info("Environment loaded and healty...");
                    List<String> l = new ArrayList(); // this is necessary for ConfigureCluster method
                    Set<EnvironmentContainerHost> containerHosts = env.getContainerHosts();
                    for (EnvironmentContainerHost e : containerHosts) {
                        l.add(e.getHostname());
                        ac.setClusterName(e.getHostname());
                    }
                    ac.setCassList(l);
                    ac.setZooList(l);
                    ac.setAppenList(l);
                    ac.setScaleOption("static"); // subutai scaling for now until we figrue out the Appscale scaling
                    ac.setEnvironmentId(env.getId());
                    healt = true;
                }
            } catch (EnvironmentNotFoundException | InterruptedException ex) {

                LOG.error("environment can not loaded yet..." + ex);
            }

        }
        return ac;
    }

    private Topology buildTopology(Blueprint blueprint) {
        WebClient webClient = createWebClient(BUILD_TOPOLOGY_URL, true);
        webClient.type(MediaType.APPLICATION_JSON);
        webClient.accept(MediaType.APPLICATION_JSON);
        webClient.replaceHeader("sptoken", token);
        LOG.info(webClient.getHeaders().toString());
        Response response = webClient.post(blueprint);
        LOG.info(String.valueOf(response.getStatus()));
        if (response.getStatus() == 200) {
            return response.readEntity(Topology.class);
        } else {
            return null;
        }
    }

    private EnvironmentId createEnvironment(Topology topology) {

        WebClient webClient = createWebClient(ENVIRONMENT_URL, true);
        webClient.type(MediaType.APPLICATION_JSON);
        webClient.accept(MediaType.APPLICATION_JSON);
        webClient.replaceHeader("sptoken", token);
        LOG.info(webClient.getHeaders().toString());
        Response response = webClient.post(topology);
        LOG.info(String.valueOf(response.getStatus()));
        if (response.getStatus() == 200) {
            return response.readEntity(EnvironmentId.class);
        } else {
            return null;
        }
    }

    @Override
    public UUID destroyNode(String clusterName, String hostName) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public UUID removeCluster(String clusterName) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public ClusterSetupStrategy getClusterSetupStrategy(Environment e, TrackerOperation t, AppScaleConfig ac) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public void saveConfig(AppScaleConfig ac) throws ClusterException {
        Preconditions.checkNotNull(ac);

        if (!getPluginDAO().saveInfo(AppScaleConfig.PRODUCT_KEY, ac.getClusterName(), ac)) {
            throw new ClusterException("Could not save cluster info");
        }
    }

    @Override
    public void deleteConfig(AppScaleConfig ac) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public AppScaleConfig getConfig(String clusterName) {
        return this.getAppScaleConfig();
    }

    @Override
    public List<AppScaleConfig> getClusters() {
        List<AppScaleConfig> returnConfig = new ArrayList();
        List<AppScaleConfig> info = pluginDAO.getInfo(AppScaleConfig.PRODUCT_KEY, AppScaleConfig.class);
        for (AppScaleConfig c : info) {
            try {
                Environment loadEnvironment = environmentManager.loadEnvironment(c.getEnvironmentId());
                if (EnvironmentStatus.HEALTHY == loadEnvironment.getStatus()) {
                    returnConfig.add(c);
                }
            } catch (EnvironmentNotFoundException ex) {

            }
        }
        return returnConfig;
    }

    @Override
    public AppScaleConfig getCluster(String string) {
        return pluginDAO.getInfo(AppScaleConfig.PRODUCT_KEY, string, AppScaleConfig.class);
    }

    @Override
    public UUID addNode(String string, String string1) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public void onEnvironmentCreated(Environment e) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public void onEnvironmentGrown(Environment e, Set<EnvironmentContainerHost> set) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public void onContainerDestroyed(Environment e, String string) {

    }

    @Override
    public void onEnvironmentDestroyed(String envID) {
        List<AppScaleConfig> c = getClusters();
        for (AppScaleConfig a : c) {
            if (a.getEnvironmentId().equals(envID)) {
                getPluginDAO().deleteInfo(AppScaleConfig.getPRODUCT_KEY(), a.getClusterName());
            }
        }
    }

    public ExecutorService getExecutor() {
        return executor;
    }

    public void setExecutor(ExecutorService executor) {
        this.executor = executor;
    }

    public Monitor getMonitor() {
        return monitor;
    }

    public PluginDAO getPluginDAO() {
        return pluginDAO;
    }

    public EnvironmentManager getEnvironmentManager() {
        return environmentManager;
    }

    public void setEnvironmentManager(EnvironmentManager environmentManager) {
        this.environmentManager = environmentManager;
    }

    public NetworkManager getNetworkManager() {
        return networkManager;
    }

    public void setNetworkManager(NetworkManager networkManager) {
        this.networkManager = networkManager;
    }

    public QuotaManager getQuotaManager() {
        return quotaManager;
    }

    public void setQuotaManager(QuotaManager quotaManager) {
        this.quotaManager = quotaManager;
    }

    public IdentityManager getIdentityManager() {
        return identityManager;
    }

    public void setIdentityManager(final IdentityManager identityManager) {
        this.identityManager = identityManager;
    }

    public PeerManager getPeerManager() {
        return peerManager;
    }

    public void setPeerManager(PeerManager peerManager) {
        this.peerManager = peerManager;
    }

    public Environment getEnvironment() {
        return environment;
    }

    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }

    public static Logger getLOG() {
        return LOG;
    }

    public Tracker getTracker() {
        return tracker;
    }

    public void setTracker(Tracker tracker) {
        this.tracker = tracker;
    }

}