controllers.GoogleComputeEngineApplication.java Source code

Java tutorial

Introduction

Here is the source code for controllers.GoogleComputeEngineApplication.java

Source

/*
 * Copyright 2014 Ricardo Lorenzo<unshakablespirit@gmail.com>
 *
 *    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 controllers;

import actors.GoogleComputeEngineConnection;
import akka.actor.ActorRef;
import akka.actor.Props;
import com.fasterxml.jackson.databind.JsonNode;
import org.springframework.beans.factory.annotation.Qualifier;
import play.data.Form;
import play.libs.Akka;
import play.libs.F;
import play.mvc.Controller;
import play.mvc.Result;
import play.mvc.WebSocket;
import scala.Option;
import services.ConfigurationService;
import services.GoogleAuthenticationService;
import services.GoogleComputeEngineService;
import utils.gce.GoogleComputeEngineException;
import utils.gce.auth.GoogleComputeEngineAuthImpl;
import utils.gce.storage.GoogleCloudStorageException;
import utils.play.BugWorkaroundForm;
import utils.puppet.PuppetConfiguration;
import utils.puppet.disk.PuppetDiskConfiguration;
import utils.security.SSHKey;
import utils.security.SSHKeyStore;
import views.data.ClusterCreationForm;
import views.data.ClusterDeletionForm;

import javax.inject.Inject;
import java.io.IOException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

@org.springframework.stereotype.Controller
public class GoogleComputeEngineApplication extends Controller {
    private static GoogleAuthenticationService googleAuth;
    private static GoogleComputeEngineService googleService;

    @Inject
    void setGoogleService(@Qualifier("gauth-service") GoogleAuthenticationService googleAuth) {
        GoogleComputeEngineApplication.googleAuth = googleAuth;
    }

    @Inject
    void setGoogleService(@Qualifier("gce-service") GoogleComputeEngineService googleService) {
        GoogleComputeEngineApplication.googleService = googleService;
    }

    public static Result gceIndex(Option<String> code) {
        String callBackUrl = GoogleComputeEngineAuthImpl.getCallBackURL(request());
        try {
            String result = GoogleAuthenticationService.authenticate(callBackUrl,
                    code.isDefined() ? code.get() : null);
            if (result != null) {
                return redirect(result);
            }
            return ok(views.html.index.render(request().path(), code));
        } catch (GoogleComputeEngineException e) {
            return ok(views.html.error.render(e.getMessage()));
        }
    }

    public static F.Promise<Result> gceDisks() {
        String callBackUrl = GoogleComputeEngineAuthImpl.getCallBackURL(request());
        try {
            String result = GoogleAuthenticationService.authenticate(callBackUrl, null);
            if (result != null) {
                return F.Promise.promise(() -> redirect(result));
            }
            return F.Promise.promise(() -> ok(GoogleComputeEngineService.listDisks()));
        } catch (GoogleComputeEngineException e) {
            return F.Promise.promise(() -> ok(views.html.error.render(e.getMessage())));
        }
    }

    public static F.Promise<Result> gceDiskTypes() {
        String callBackUrl = GoogleComputeEngineAuthImpl.getCallBackURL(request());
        try {
            String result = GoogleAuthenticationService.authenticate(callBackUrl, null);
            if (result != null) {
                return F.Promise.promise(() -> redirect(result));
            }
            return F.Promise.promise(() -> ok(GoogleComputeEngineService.listDiskTypes()));
        } catch (GoogleComputeEngineException e) {
            return F.Promise.promise(() -> ok(views.html.error.render(e.getMessage())));
        }
    }

    public static F.Promise<Result> gceInstances(Option<String> type) {
        String callBackUrl = GoogleComputeEngineAuthImpl.getCallBackURL(request());
        try {
            String result = GoogleAuthenticationService.authenticate(callBackUrl, null);
            if (result != null) {
                return F.Promise.promise(() -> redirect(result));
            }
            if (type.isDefined()) {
                return F.Promise.promise(() -> ok(
                        GoogleComputeEngineService.listInstances(Arrays.asList(new String[] { type.get() }))));
            } else {
                return F.Promise.promise(() -> ok(GoogleComputeEngineService.listInstances(null)));
            }
        } catch (GoogleComputeEngineException e) {
            return F.Promise.promise(() -> ok(views.html.error.render(e.getMessage())));
        }
    }

    public static F.Promise<Result> gceNetworks() {
        String callBackUrl = GoogleComputeEngineAuthImpl.getCallBackURL(request());
        try {
            String result = GoogleAuthenticationService.authenticate(callBackUrl, null);
            if (result != null) {
                return F.Promise.promise(() -> redirect(result));
            }
            return F.Promise.promise(() -> ok(GoogleComputeEngineService.listNetworks()));
        } catch (GoogleComputeEngineException e) {
            return F.Promise.promise(() -> ok(views.html.error.render(e.getMessage())));
        }
    }

    public static WebSocket<JsonNode> gceOperations() {
        return new WebSocket<JsonNode>() {
            public void onReady(final In<JsonNode> in, final Out<JsonNode> out) {
                final ActorRef computeActor = Akka.system()
                        .actorOf(Props.create(GoogleComputeEngineConnection.class, out));

                in.onMessage(new F.Callback<JsonNode>() {
                    @Override
                    public void invoke(JsonNode jsonNode) throws Throwable {
                        if (jsonNode.has("action") && "retrieve".equals(jsonNode.get("action").textValue())) {
                            Date lastOperationDate = null;
                            if (jsonNode.has("lastOperationDate")) {
                                DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX");
                                try {
                                    lastOperationDate = format.parse(jsonNode.get("lastOperationDate").textValue());
                                } catch (ParseException e) {
                                    System.out.println("Date parse error: " + e.getMessage());
                                }
                            }
                            final ActorRef computeActor = Akka.system()
                                    .actorOf(Props.create(GoogleComputeEngineConnection.class, out));
                            GoogleComputeEngineService.listOperations(computeActor, lastOperationDate);
                        }
                    }
                });

                in.onClose(new F.Callback0() {
                    @Override
                    public void invoke() throws Throwable {
                        Akka.system().stop(computeActor);
                    }
                });
            }
        };
    }

    public static F.Promise<Result> gceZones() {
        String callBackUrl = GoogleComputeEngineAuthImpl.getCallBackURL(request());
        try {
            String result = GoogleAuthenticationService.authenticate(callBackUrl, null);
            if (result != null) {
                return F.Promise.promise(() -> redirect(result));
            }
            return F.Promise.promise(() -> ok(GoogleComputeEngineService.listZones()));
        } catch (GoogleComputeEngineException e) {
            return F.Promise.promise(() -> ok(views.html.error.render(e.getMessage())));
        }
    }

    public static Result createClusterWizard() {
        String callBackUrl = GoogleComputeEngineAuthImpl.getCallBackURL(request());
        try {
            boolean option_chosen;
            String result = GoogleAuthenticationService.authenticate(callBackUrl, null);
            if (result != null) {
                return redirect(result);
            }
            Map<String, Boolean> machineTypes = new TreeMap<>(Comparator.<String>naturalOrder()),
                    images = new TreeMap<>(Comparator.<String>reverseOrder()),
                    networks = new TreeMap<>(Comparator.<String>reverseOrder()),
                    dataDiskTypes = new TreeMap<>(Comparator.<String>reverseOrder()),
                    dataDiskRaids = new TreeMap<>(Comparator.<String>naturalOrder()), filesystems = new HashMap<>();
            ClusterCreationForm clusterCreation = new ClusterCreationForm();
            Form<ClusterCreationForm> formData = Form.form(ClusterCreationForm.class).fill(clusterCreation);
            for (PuppetDiskConfiguration diskConfig : PuppetConfiguration.getSupportedDiskConfigurations()) {
                dataDiskRaids.put(diskConfig.getName(), "raid0".equals(diskConfig.getName()));
            }
            for (JsonNode n : GoogleComputeEngineService.listDiskTypes().findValues("name")) {
                dataDiskTypes.put(n.textValue(), "pd-ssd".equals(n.textValue()));
            }
            for (String fs : PuppetConfiguration.getSupportedDiskFileSystems()) {
                filesystems.put(fs, "ext4".equals(fs));
            }
            for (JsonNode n : GoogleComputeEngineService.listMachineTypes().findValues("name")) {
                machineTypes.put(n.textValue(), "n1-standard-4".equals(n.textValue()));
            }
            option_chosen = false;
            for (JsonNode n : GoogleComputeEngineService.listImages().findValues("name")) {
                if (!option_chosen && n.textValue().startsWith("debian-")) {
                    images.put(n.textValue(), true);
                    option_chosen = true;
                } else {
                    images.put(n.textValue(), false);
                }
            }
            option_chosen = false;
            for (JsonNode n : GoogleComputeEngineService.listNetworks().findValues("name")) {
                if (!option_chosen) {
                    networks.put(n.textValue(), true);
                    option_chosen = true;
                } else {
                    networks.put(n.textValue(), false);
                }
            }
            return ok(views.html.cluster_creation.render(formData, machineTypes, images, networks, dataDiskTypes,
                    dataDiskRaids, filesystems, Boolean.valueOf(clusterCreation.isCgroups())));
        } catch (GoogleComputeEngineException e) {
            return ok(views.html.error.render(e.getMessage()));
        }
    }

    public static Result createClusterWizardPost() {
        String callBackUrl = GoogleComputeEngineAuthImpl.getCallBackURL(request());
        try {
            String result = GoogleAuthenticationService.authenticate(callBackUrl, null);
            if (result != null) {
                return redirect(result);
            }
        } catch (GoogleComputeEngineException e) {
            return ok(views.html.error.render(e.getMessage()));
        }
        Form<ClusterCreationForm> formData = new BugWorkaroundForm<>(ClusterCreationForm.class).bindFromRequest();
        ClusterCreationForm clusterForm = formData.get();
        if (formData.hasErrors()) {
            Map<String, Boolean> machineTypes = new TreeMap<>(Comparator.<String>naturalOrder()),
                    images = new TreeMap<>(Comparator.<String>reverseOrder()),
                    networks = new TreeMap<>(Comparator.<String>reverseOrder()),
                    dataDiskTypes = new TreeMap<>(Comparator.<String>reverseOrder()),
                    dataDiskRaids = new TreeMap<>(Comparator.<String>naturalOrder()), filesystems = new HashMap<>();
            flash("error", "Please correct errors above.");
            try {
                for (PuppetDiskConfiguration diskConfig : PuppetConfiguration.getSupportedDiskConfigurations()) {
                    dataDiskRaids.put(diskConfig.getName(), (clusterForm.getDiskRaid() != null
                            && diskConfig.getName().equals(clusterForm.getDiskRaid())));
                }
                for (JsonNode n : GoogleComputeEngineService.listDiskTypes().findValues("name")) {
                    dataDiskTypes.put(n.textValue(), clusterForm.getDataDiskType() != null
                            && n.textValue().equals(clusterForm.getDataDiskType()));
                }
                for (String fs : PuppetConfiguration.getSupportedDiskFileSystems()) {
                    filesystems.put(fs,
                            (clusterForm.getFileSystem() != null && fs.equals(clusterForm.getFileSystem())));
                }
                for (JsonNode n : GoogleComputeEngineService.listMachineTypes().findValues("name")) {
                    machineTypes.put(n.textValue(), (clusterForm.getMachineType() != null
                            && n.textValue().equals(clusterForm.getMachineType())));
                }
                for (JsonNode n : GoogleComputeEngineService.listImages().findValues("name")) {
                    images.put(n.textValue(),
                            (clusterForm.getImage() != null && n.textValue().equals(clusterForm.getImage())));
                }
                for (JsonNode n : GoogleComputeEngineService.listNetworks().findValues("name")) {
                    networks.put(n.textValue(),
                            (clusterForm.getNetwork() != null && n.textValue().equals(clusterForm.getNetwork())));
                }
                return ok(views.html.cluster_creation.render(formData, machineTypes, images, networks,
                        dataDiskTypes, dataDiskRaids, filesystems, Boolean.valueOf(clusterForm.isCgroups())));
            } catch (GoogleComputeEngineException e) {
                return ok(views.html.error.render(e.getMessage()));
            }
        } else {
            try {
                googleService.createCluster(clusterForm.getClusterName(), clusterForm.getShardNodes(),
                        clusterForm.getProcesses(), clusterForm.getNodeDisks(), clusterForm.getMachineType(),
                        Arrays.asList(clusterForm.getNetwork()), clusterForm.getImage(),
                        clusterForm.getDataDiskType(), clusterForm.getDiskRaid(), clusterForm.getFileSystem(),
                        clusterForm.getDataDiskSizeGb(), clusterForm.getRootDiskSizeGb());
            } catch (GoogleComputeEngineException e) {
                return ok(views.html.error.render(e.getMessage()));
            } catch (GoogleCloudStorageException e) {
                return ok(views.html.error.render(e.getMessage()));
            }
            flash("success",
                    "Cluster creation launched! Please check the running operations in the cluster status page.");
            return ok(views.html.cluster_creation.render(formData, null, null, null, null, null, null, null));
        }
    }

    public static Result deleteClusterWizard() {
        String callBackUrl = GoogleComputeEngineAuthImpl.getCallBackURL(request());
        try {
            String result = GoogleAuthenticationService.authenticate(callBackUrl, null);
            if (result != null) {
                return redirect(result);
            }
            ClusterDeletionForm clusterDeletion = new ClusterDeletionForm();
            Form<ClusterDeletionForm> formData = Form.form(ClusterDeletionForm.class).fill(clusterDeletion);
            return ok(views.html.cluster_deletion.render(formData, clusterDeletion.getDelete()));
        } catch (GoogleComputeEngineException e) {
            return ok(views.html.error.render(e.getMessage()));
        }
    }

    public static Result deleteClusterWizardPost() {
        String callBackUrl = GoogleComputeEngineAuthImpl.getCallBackURL(request());
        try {
            String result = GoogleAuthenticationService.authenticate(callBackUrl, null);
            if (result != null) {
                return redirect(result);
            }
            Form<ClusterDeletionForm> formData = new BugWorkaroundForm<>(ClusterDeletionForm.class)
                    .bindFromRequest();
            ClusterDeletionForm clusterForm = formData.get();
            if (formData.hasErrors()) {
                flash("error", "Please correct errors above.");
                return ok(views.html.cluster_deletion.render(formData, clusterForm.getDelete()));
            } else {
                try {
                    googleService.deleteCluster();
                } catch (GoogleComputeEngineException e) {
                    return ok(views.html.error.render(e.getMessage()));
                }
                flash("success",
                        "Cluster deletion launched! Please check the running operations in the cluster status page.");
                return ok(views.html.cluster_deletion.render(formData, null));
            }
        } catch (GoogleComputeEngineException e) {
            return ok(views.html.error.render(e.getMessage()));
        }
    }

    public static Result getClusterPrivateKey() {
        try {
            SSHKeyStore store = new SSHKeyStore();
            SSHKey key = store.getKey(ConfigurationService.CLUSTER_USER);
            if (key == null) {
                return ok(views.html.error.render("no cluster key found"));
            }
            return ok(key.getSSHPrivateKey()).as("text/plain");
        } catch (ClassNotFoundException e) {
            return ok(views.html.error.render(e.getMessage()));
        } catch (IOException e) {
            return ok(views.html.error.render(e.getMessage()));
        }
    }
}