vlove.virt.VirtBuilder.java Source code

Java tutorial

Introduction

Here is the source code for vlove.virt.VirtBuilder.java

Source

/**
 * vlove - web based virtual machine management
 * Copyright (C) 2010 Limone Fresco Limited
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
package vlove.virt;

import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.codehaus.plexus.util.cli.CommandLineException;
import org.codehaus.plexus.util.cli.CommandLineUtils;
import org.codehaus.plexus.util.cli.Commandline;
import org.codehaus.plexus.util.cli.StreamConsumer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import vlove.VirtException;
import vlove.model.NewVmWizardModel;

/**
 * Service to create VMs.
 * 
 * @author Michael Laccetti
 */
@Service
public class VirtBuilder {
    transient final Logger log = LoggerFactory.getLogger(getClass());

    /*@Autowired
    private ConfigDao      cd;*/

    private List<String> createVirtMachineCommand(NewVmWizardModel newVm) {
        // TODO Validate that the model is configured properly

        List<String> command = new ArrayList<>();
        command.add("sudo");
        command.add("vmbuilder");
        command.add("kvm");
        command.add("ubuntu");
        command.add("-v");
        // command.add(String.format("--libvirt=%s", cd.getConfigItem("libvirt.url").getValue()));
        command.add(String.format("--hostname=%s", newVm.getVmName()));
        command.add(String.format("--rootsize=%d", newVm.getDiskSize() * 1024));
        command.add(String.format("--swapsize=%d", newVm.getMemSize()));
        command.add(String.format("--suite=%s", newVm.getSuite()));
        command.add("--flavour=virtual");
        command.add(String.format("--arch=%s", newVm.getArch()));

        if (newVm.getNetworks().equalsIgnoreCase("manual")) {
            command.add(String.format("--bridge=%s", newVm.getBridge()));
        } else {
            command.add(String.format("--network=%s", newVm.getNetworks()));
        }

        command.add(String.format("--cpus=%d", newVm.getNumProcs()));
        command.add(String.format("--mem=%d", newVm.getMemSize()));

        log.debug("Command: {}", command);
        return command;
    }

    /**
     * Returns the exit value of the process.
     * 
     * @param out
     * @param err
     * @return
     * @throws VirtException
     */
    public int createVirtualMachine(NewVmWizardModel newVm, StreamConsumer out, StreamConsumer err)
            throws VirtException {
        List<String> command = createVirtMachineCommand(newVm);
        if (command == null || command.size() < 1) {
            throw new VirtException("Command needs to be provided.");
        }

        try {
            Commandline cs = new Commandline();
            cs.setExecutable(command.get(0));
            if (command.size() > 1) {
                cs.addArguments(command.subList(1, command.size()).toArray(new String[] {}));
            }
            PipedOutputStream pOut = new PipedOutputStream();
            PipedInputStream pIs = new PipedInputStream(pOut);

            List<ConsumerListener> listeners = new ArrayList<>();
            listeners.add(new ConsumerListener(pOut, Pattern.compile("\\[sudo\\] password for \\w+:"), "password"));

            NestedStreamConsumer nOut = new NestedStreamConsumer(listeners, out);
            return CommandLineUtils.executeCommandLine(cs, pIs, nOut, err);
        } catch (CommandLineException ce) {
            throw new VirtException("Could not execute command.", ce);
        } catch (IOException ie) {
            throw new VirtException("Could not execute command.", ie);
        }
    }

    private class NestedStreamConsumer implements StreamConsumer {
        private final List<ConsumerListener> listeners;
        private final StreamConsumer upstream;

        public NestedStreamConsumer(List<ConsumerListener> listeners, StreamConsumer upstream) {
            this.listeners = listeners;
            this.upstream = upstream;
        }

        @Override
        public void consumeLine(String line) {
            for (ConsumerListener cl : listeners) {
                cl.consumeLine(line);
            }
            upstream.consumeLine(line);
        }
    }

    private class ConsumerListener {
        private final PipedOutputStream pOut;
        private final Pattern p;
        private final String action;

        public ConsumerListener(PipedOutputStream pOut, Pattern p, String action) {
            this.pOut = pOut;
            this.p = p;
            this.action = action;
        }

        public void consumeLine(String line) {
            Matcher m = p.matcher(line);
            if (m.matches()) {
                try {
                    pOut.write(action.getBytes());
                } catch (IOException ie) {
                    log.warn("Could not write to piped output stream.", ie);
                }
            }
        }
    }
}