org.xenmaster.setup.debian.Bootstrapper.java Source code

Java tutorial

Introduction

Here is the source code for org.xenmaster.setup.debian.Bootstrapper.java

Source

/*
 * Bootstrapper.java
 * Copyright (C) 2011,2012 Wannes De Smet
 * 
 * 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 3 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, see <http://www.gnu.org/licenses/>.
 */
package org.xenmaster.setup.debian;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.GZIPInputStream;

import net.wgr.settings.Settings;
import net.wgr.utility.Network;

import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.io.IOUtils;
import org.apache.commons.net.tftp.TFTPOptionReadRequestPacket;
import org.apache.log4j.Logger;
import org.xenmaster.connectivity.tftp.TFTPServer;
import org.xenmaster.site.XenMasterSite;

/**
 * 
 * @created Oct 27, 2011
 * @author double-u
 */
public class Bootstrapper {

    protected TFTPServer tftpd;
    protected HashMap<String, String> preseedValues;
    protected long lastChecked;

    public Bootstrapper() {
        tftpd = new TFTPServer();
        preseedValues = new HashMap<>();
        lastChecked = 0;
    }

    public void boot() {
        tftpd.addListener(new PXEListener());
        tftpd.boot();

        preseedValues.put("menuItemLabel", "^Install Debian");
    }

    public void waitForServerToQuit() throws InterruptedException {
        tftpd.waitTillQuit();
    }

    protected class PXEListener implements TFTPServer.ActivityListener {

        @Override
        public InputStream pathRequest(TFTPOptionReadRequestPacket packet) {
            try {
                if (downloadNetbootFiles())
                    return null;

                File path = new File(
                        Settings.getInstance().getString("StorePath") + "/netboot/" + packet.getFilename());
                if (!path.exists()) {
                    return null;
                }
                File f = path.getAbsoluteFile();
                if (f.exists()) {
                    FileInputStream fis = new FileInputStream(f);
                    if (f.getName().equals("txt.cfg")) {
                        preseedValues
                                .put("preseedUrl",
                                        "http://"
                                                + Network
                                                        .getHostAddressInSubnet(
                                                                packet.getAddress().getHostAddress(), "255.255.0.0")
                                                        .getHostAddress()
                                                + ":" + Settings.getInstance().get("WebApplicationPort")
                                                + "/setup/xapi");

                        String txt = IOUtils.toString(fis);
                        for (Map.Entry<String, String> entry : preseedValues.entrySet()) {
                            // todo regex
                            txt = txt.replace("#{" + entry.getKey() + "}", entry.getValue());
                        }

                        return new ByteArrayInputStream(txt.getBytes("UTF-8"));
                    }
                    return fis;
                }
            } catch (IOException ex) {
                Logger.getLogger(getClass()).error("File not found", ex);
            }
            return null;
        }
    }

    protected boolean downloadNetbootFiles() {
        if (System.currentTimeMillis() - lastChecked < 50 * 60 * 1000) {
            return false;
        }

        File localVersionFile = new File(Settings.getInstance().getString("StorePath") + "/netboot/version");
        int localVersion = -1;
        try (FileInputStream fis = new FileInputStream(localVersionFile)) {
            localVersion = Integer.parseInt(IOUtils.toString(fis));
        } catch (IOException | NumberFormatException ex) {
            Logger.getLogger(getClass()).error("Failed to retrieve local version file", ex);
        }

        int remoteVersion = -1;
        try {
            remoteVersion = Integer.parseInt(IOUtils.toString(XenMasterSite.getFileAsStream("/netboot/version")));
        } catch (IOException | NumberFormatException ex) {
            Logger.getLogger(getClass()).error("Failed to retrieve remote version file", ex);
        }

        lastChecked = System.currentTimeMillis();

        if (localVersion < remoteVersion) {
            Logger.getLogger(getClass())
                    .info("New version " + remoteVersion + " found. Please hold while downloading netboot data");
            try {
                TarArchiveInputStream tais = new TarArchiveInputStream(
                        new GZIPInputStream(XenMasterSite.getFileAsStream("/netboot/netboot.tar.gz")));
                TarArchiveEntry tae = null;
                FileOutputStream fos = null;
                while ((tae = tais.getNextTarEntry()) != null) {
                    if (tais.canReadEntryData(tae)) {
                        String target = Settings.getInstance().getString("StorePath") + "/" + tae.getName();

                        if (tae.isSymbolicLink()) {
                            Path targetFile = FileSystems.getDefault().getPath(tae.getLinkName());
                            Path linkName = FileSystems.getDefault().getPath(target);

                            // Link might already have been written as null file
                            if (targetFile.toFile().exists()) {
                                targetFile.toFile().delete();
                            }

                            Files.createSymbolicLink(linkName, targetFile);
                            Logger.getLogger(getClass()).info(
                                    "Created sym link " + linkName.toString() + " -> " + targetFile.toString());
                        } else if (tae.isDirectory()) {
                            new File(target).mkdir();

                            Logger.getLogger(getClass()).info("Created dir " + target);
                        } else if (tae.isFile()) {
                            fos = new FileOutputStream(target);
                            byte[] b = new byte[1024];
                            int curPos = 0;
                            while (tais.available() > 0) {
                                tais.read(b, curPos, 1024);
                                fos.write(b, curPos, 1024);
                            }

                            fos.flush();
                            fos.close();

                            Logger.getLogger(getClass()).info("Wrote file " + target);
                        }
                    }
                }

                tais.close();
                // Write local version
                IOUtils.write("" + remoteVersion, new FileOutputStream(localVersionFile));
            } catch (IOException ex) {
                Logger.getLogger(getClass()).error("Failed to download netboot files", ex);
            }
        } else {
            return false;
        }

        return true;
    }
}