org.uoa.eolus.template.Nest.java Source code

Java tutorial

Introduction

Here is the source code for org.uoa.eolus.template.Nest.java

Source

/*
* Copyright 2010 Konstantinos Tsakalozos
*
* Licensed under the EUPL, Version 1.1 or  as soon they will be
* approved by the European Commission - subsequent versions of the EUPL (the Licence);
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at:
*
* http://ec.europa.eu/idabc/eupl
*
* Unless required by applicable law or agreed to in  writing, software
* distributed under the Licence is distributed on an AS IS basis,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the Licence for the specific language governing permissions and limitations under the Licence.
*/

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.uoa.eolus.template;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Map.Entry;

import org.apache.commons.io.FileUtils;
import org.uoa.eolus.DirectoryException;
import org.uoa.eolus.InternalErrorException;
import org.uoa.nefeli.utils.HostInfo;

public class Nest {

    private String repo;
    private String tempDir;
    private String kernel;
    private String initrd;
    private Map<String, List<HostInfo>> sitesinfo = new HashMap<String, List<HostInfo>>();
    private Random rand = new Random();

    public Nest(String repo, String tempDir, String kernel, String initrd) {
        this.repo = repo;
        // Creating directories just in case....
        (new File(repo)).mkdirs();
        this.tempDir = tempDir;
        this.kernel = kernel;
        this.initrd = initrd;
    }

    public List<String> getSiteConfigurations(String vMtemplateOwner, String vMclass) {
        System.out.println("Looking for Site depoyment description templates");
        File dir = new File(repo + "/" + vMtemplateOwner + "/" + vMclass);
        System.out.println("Looking in directory: " + repo + "/" + vMtemplateOwner + "/" + vMclass);
        FilenameFilter filter = new FilenameFilter() {
            public boolean accept(File dir, String name) {
                return name.startsWith("Site-");
            }
        };
        return Arrays.asList(dir.list(filter));
    }

    public File scheduleVM() {

        return null;
    }

    /**
     * Build up a OpenNebula specific template description File
     * @param VMTemplateClass The VM class to be used (currently this ignored)
     * @param ID The ID of the VM to be created
     * @param CPU CPU requirements
     * @param memSize Memory requirements
     * @param hostName The hostname of the physical system where we want the VM to be deployed 
     * @return The file containing the OpenNebula template description 
     * @throws DirectoryException 
     */
    public File matchVM(String user, String VMTemplateClass, String VMname, String hostName, int cores, int memSize,
            String[] nets) throws DirectoryException {
        File template = new File(tempDir + "/templateVM-" + VMname);

        String imagesPath = repo + "/" + VMTemplateClass;
        File dir = new File(imagesPath);
        FilenameFilter filter = new FilenameFilter() {
            public boolean accept(File dir, String name) {
                return name.endsWith(".img") && !name.startsWith("swap") && !name.equalsIgnoreCase("disk.img");
            }
        };
        String[] extraImages = dir.list(filter);

        try {
            FileWriter fstream = new FileWriter(template);
            BufferedWriter out = new BufferedWriter(fstream);

            out.write("" + "NAME   = " + VMname + " \n" + "CPU    = " + "0.1" + " \n" + "MEMORY = " + memSize
                    + " \n" + "OS     = [ \n" + " kernel   = \"/boot/" + kernel + "\", \n" + " initrd   = \"/boot/"
                    + initrd + "\", \n" + " root     = \"xvda2 ro\" ] \n" + "DISK   = [ \n"
                    + " type     = \"swap\", \n" + " size     = " + memSize + ", \n" + " target   = \"xvda1\"] \n"
                    + "DISK   = [" + " source   = \"" + repo + "/" + user + "/" + VMTemplateClass
                    + "/disk.img\", \n" + " target   = \"xvda2\", \n " + " readonly = \"no\" ] \n");
            out.write("RAW = [ type=\"xen\", data=\"vcpus=" + cores + "\" ]");
            if (extraImages != null) {
                for (int i = 0; i < extraImages.length; i++) {
                    try {
                        int j = getCounter(extraImages[i]);
                        out.write("DISK   = [" + " source   = \"" + repo + "/" + user + "/" + VMTemplateClass + "/"
                                + extraImages[i] + "\", \n" + " target   = \"xvda" + j + "\", \n "
                                + " readonly = \"no\" ] \n");
                    } catch (Exception x) {
                        System.out.println("No disk index number extracted from " + extraImages[i]);
                    }
                }
            }
            if (hostName != null) {
                String host = hostName.substring(0, hostName.indexOf('.'));
                out.write("REQUIREMENTS = \"HOSTNAME = \\\"" + host + "*\\\"\" \n");
            }
            for (int i = 0; i < nets.length; i++) {
                out.write("NIC    = [ NETWORK = \"" + nets[i] + "\" ] \n");
            }
            out.close();
            fstream.close();
            return template;
        } catch (Exception x) {
            throw new DirectoryException("Connot write ONE template file.", x);
        }
    }

    private int getCounter(String filename) throws Exception {
        int index = filename.lastIndexOf(".");
        index--;
        String strCounter = filename.substring(index, index + 1);
        return Integer.parseInt(strCounter);
    }

    public File matchVM(String user, String mclass, String mname, int cores, int memSize, String[] nets)
            throws DirectoryException {
        return matchVM(user, mclass, mname, null, cores, memSize, nets);
    }

    public void copyUserTemplate(String user, String template, String target, boolean move)
            throws DirectoryException {
        String cmd = "mv";
        if (move)
            cmd = "mv " + repo + "/" + user + "/" + template + " " + repo + "/" + user + "/" + target
                    + "; exit; \n";
        else
            cmd = "cp -r " + repo + "/" + user + "/" + template + " " + repo + "/" + user + "/." + target + "; mv "
                    + repo + "/" + user + "/." + target + " " + repo + "/" + user + "/" + target + "; exit; \n";

        System.out.println("CMD: " + cmd);

        Runtime run = Runtime.getRuntime();
        try {
            Process child = run.exec("/bin/bash");
            BufferedWriter outCommand = new BufferedWriter(new OutputStreamWriter(child.getOutputStream()));
            outCommand.write(cmd);
            outCommand.flush();
            //         InputStream out = child.getInputStream();
            //         InputStreamReader isr = new InputStreamReader(out);
            //         BufferedReader output = new BufferedReader(isr);
            //         InputStream err = child.getErrorStream();
            //         InputStreamReader eisr = new InputStreamReader(err);
            //         BufferedReader error = new BufferedReader(eisr);
            //         System.out.println("Waiting for");         
            child.waitFor();
            //         String o = "";
            //         String s;
            //         while ((s = output.readLine()) != null) {
            //            o += s + "\n";
            //         }
            //         System.out.println("stdout: " + o);
            //         String e = "";
            //         s = error.readLine(); // First line is a warning: Warning:
            //         // Permanently added 'XX.XX.XX.XX' (RSA) to
            //         // the list of known hosts.
            //         while ((s = error.readLine()) != null) {
            //            e += s + "\n";
            //         }
            //         System.out.println("stderr: " + e);

            if (child.exitValue() != 0)
                throw new InternalErrorException("Copy process failed.");
            else {
                System.out.println("Returning.");
            }
        } catch (Exception e) {
            throw new DirectoryException("Cannot execute rm command.", e);
        }
    }

    public void copyUserToUserTemplate(String fromuser, String touser, String template, String target, boolean move)
            throws DirectoryException {
        String cmd = "mv";
        if (move)
            cmd = "mv " + repo + "/" + fromuser + "/" + template + " " + repo + "/" + touser + "/" + target
                    + "; exit; \n";
        else
            cmd = "cp -r " + repo + "/" + fromuser + "/" + template + " " + repo + "/" + touser + "/." + target
                    + "; mv " + repo + "/" + touser + "/." + target + " " + repo + "/" + touser + "/" + target
                    + "; exit; \n";

        System.out.println("CMD: " + cmd);
        Runtime run = Runtime.getRuntime();
        try {
            Process child = run.exec("/bin/bash");
            BufferedWriter outCommand = new BufferedWriter(new OutputStreamWriter(child.getOutputStream()));
            outCommand.write(cmd);
            outCommand.flush();
            // child.waitFor();
            // if (child.exitValue() != 0)
            // return false;
            // else
        } catch (Exception e) {
            throw new DirectoryException("Cannot execute cp/mv command.", e);
        }
    }

    public void removeUserTemplate(String user, String template) throws DirectoryException {
        String cmd = "rm -rf " + repo + "/" + user + "/" + template;
        System.out.println("CMD: " + cmd);
        Runtime run = Runtime.getRuntime();
        try {
            Process child = run.exec(cmd);
        } catch (Exception e) {
            throw new DirectoryException("Cannot execute rm command.", e);
        }
    }

    public String[] getAllUserTemplates(String user) {
        File dir = new File(repo + "/" + user);
        System.out.println("Looking in directory: " + repo + "/" + user);
        FilenameFilter filter = new FilenameFilter() {
            public boolean accept(File dir, String name) {
                return !name.startsWith(".");
            }
        };
        return dir.list(filter);

    }

    public void createUser(String user) throws DirectoryException {
        boolean mkdir = (new File(repo + "/" + user)).mkdir();
        if (!mkdir) {
            System.out.println("Template directory creation failed.");
            File d = new File(repo + "/" + user);
            if ((d == null) || (!d.isDirectory())) {
                throw new DirectoryException("Template directory creation failed");
            }
        }
    }

    public void removeUser(String user) throws DirectoryException {
        deleteDir(new File(repo + "/" + user));
    }

    public void deleteDir(File dir) throws DirectoryException {
        if (dir.isDirectory()) {
            String[] children = dir.list();
            for (int i = 0; i < children.length; i++) {
                try {
                    deleteDir(new File(dir, children[i]));
                } catch (DirectoryException x) {
                    System.out.println("Cannot remove directory");
                }
            }
        }
        // The directory is now empty so delete it
        boolean rmdir = dir.delete();
        if (!rmdir)
            throw new DirectoryException("Cannot remove template directory " + dir.getName() + ".");
    }

    public String[] getAllUsersOfRepo() {
        File dir = new File(repo);
        FilenameFilter filter = new FilenameFilter() {
            public boolean accept(File dir, String name) {
                return !name.startsWith(".");
            }
        };
        return dir.list(filter);

    }

    public File scheduleVMtoHost(String vMtemplateOwner, String vMclass, String vMname, String sitedesc,
            String host, Integer cores, Integer memSize, String[] nets) throws IOException, DirectoryException {
        File desc = new File(repo + "/" + vMtemplateOwner + "/" + vMclass + "/" + sitedesc);
        String vmdepdesc = FileUtils.readFileToString(desc);

        File template = new File(tempDir + "/templateVM-" + vMname);

        try {
            FileWriter fstream = new FileWriter(template);
            BufferedWriter out = new BufferedWriter(fstream);

            vmdepdesc = vmdepdesc.replaceFirst("%%VMNAME%%", vMname);
            vmdepdesc = vmdepdesc.replace("%%MEMSIZE%%", "" + memSize);
            vmdepdesc = vmdepdesc.replace("%%REPOSITORY%%", repo + "/" + vMtemplateOwner + "/" + vMclass);
            vmdepdesc = vmdepdesc.replace("%%CORES%%", "" + cores);
            vmdepdesc += "\nREQUIREMENTS = \"HOSTNAME = \\\"" + host + "*\\\"\" \n";
            for (int i = 0; i < nets.length; i++) {
                vmdepdesc += "NIC    = [ NETWORK = \"" + nets[i] + "\" ] \n";
            }
            out.write(vmdepdesc);
            out.close();
            fstream.close();
            return template;
        } catch (Exception x) {
            throw new DirectoryException("Connot write ONE template file.", x);
        }
    }

    public void startNewVMScheduling() {
        sitesinfo.clear();
    }

    public void loadHostInfo(String s, List<HostInfo> hi) {
        System.out.println("Candidate site: " + s);
        sitesinfo.put(s, hi);
    }

    public File newVMScheduling(String vMtemplateOwner, String vMclass, String vMname, Integer cores,
            Integer memSize, String[] nets) throws IOException, DirectoryException, InternalErrorException {

        while (sitesinfo.size() != 0) {
            int siteindex = Math.abs(rand.nextInt()) % sitesinfo.size();
            Iterator<Entry<String, List<HostInfo>>> it = sitesinfo.entrySet().iterator();
            Entry<String, List<HostInfo>> currentsite = null;
            for (int i = 0; i < siteindex + 1; i++) {
                currentsite = it.next();
            }

            String sitename = currentsite.getKey();
            sitesinfo.remove(sitename);
            List<HostInfo> hostinfo = currentsite.getValue();

            while (hostinfo.size() != 0) {
                int hostindex = Math.abs(rand.nextInt()) % hostinfo.size();
                HostInfo hi = hostinfo.get(hostindex);
                if (isEnough(hi, cores, memSize)) {
                    return scheduleVMtoHost(vMtemplateOwner, vMclass, vMname, sitename, hi.name, cores, memSize,
                            nets);
                } else {
                    hostinfo.remove(hostindex);
                }
            }
        }
        throw new InternalErrorException("Connot schedule VM.");

    }

    private boolean isEnough(HostInfo hi, Integer cores, Integer memSize) {
        System.out.println("Comparing hi.Mem_free > memSize " + hi.Mem_free + " > " + memSize);
        if (hi.Mem_free > memSize * 1024)
            return true;
        return false;
    }

}