/**
*
* Created : Feb 19, 2012
*
* @author pquiring
*/
import java.util.*;
import java.io.*;
import jfparted.*;
import javaforce.*;
import javaforce.linux.*;
public class Install extends IPanel implements ShellProcessListener {
/**
* Creates new form Install
*/
public Install() {
initComponents();
Data.getDevices();
Data.getPartitions();
Installer.disableButtons();
//create a Thread
Worker worker = new Worker();
worker.start();
}
private class Optional extends Exception {
public Optional(String msg) {
super(msg);
}
};
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
jScrollPane1 = new javax.swing.JScrollPane();
log = new javax.swing.JTextArea();
progress = new javax.swing.JProgressBar();
log.setColumns(20);
log.setEditable(false);
log.setRows(5);
jScrollPane1.setViewportView(log);
progress.setToolTipText("");
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE)
.addComponent(progress, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 274, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(progress, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE))
);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JTextArea log;
private javax.swing.JProgressBar progress;
// End of variables declaration//GEN-END:variables
private int totalFilesCopied = 0, filesToCopy = 0;
private boolean calcFilesToCopy = false;
private boolean fedoraMount = false;
public class Worker extends Thread {
public void run() {
ShellProcess sp;
ArrayList<String> cmd;
String output;
//disable all swaps (can prevent deleting old parts)
sp = new ShellProcess();
cmd = new ArrayList<String>();
cmd.add("sudo");
cmd.add("swapoff");
cmd.add("-a");
output = sp.run(cmd, false);
if ((output == null) || (sp.getErrorLevel() != 0)) {
addLog("Error:Failed to exec swapoff");
JFLog.log("ErrorLevel=" + sp.getErrorLevel());
abort();
return;
}
//umount any parts that startsWith(Data.root.device.dev)
sp = new ShellProcess();
cmd = new ArrayList<String>();
cmd.add("mount");
output = sp.run(cmd, false);
if ((output == null) || (sp.getErrorLevel() != 0)) {
addLog("Error:Failed to exec mount");
JFLog.log("ErrorLevel=" + sp.getErrorLevel());
abort();
return;
}
String lns[] = output.split("\n");
for(int a=0;a<lns.length;a++) {
if (lns[a].startsWith(Data.root.device.dev)) {
int idx = lns[a].indexOf(" ");
if (!Data.umount(lns[a].substring(0, idx))) {
addLog("Error:Failed to exec umount");
abort();
return;
}
}
}
if (Linux.distro == Linux.DistroTypes.Fedora) {
//need to mount CD under /mnt/src
Data.mount("/dev/mapper/live-osimg-min", "/mnt/src");
fedoraMount = true;
}
//do guided part stuff
if (Data.guidedTarget != null) {
//perform ops1 (removes)
addLog("Partitioning device...");
sp = new ShellProcess();
cmd = new ArrayList<String>();
cmd.add("sudo");
cmd.add("parted");
for(int a=0;a<Data.ops1.size();a++) sp.addResponse("(parted) ", Data.ops1.get(a), false);
output = sp.run(cmd, false);
if ((output == null) || (output.indexOf("Error:") != -1) || (sp.getErrorLevel() != 0)) {
addLog("Error:Failed to remove old partitions.\nAre they mounted?");
JFLog.log("ErrorLevel=" + sp.getErrorLevel());
abort();
return;
}
//perform ops2 (mkpart's)
sp = new ShellProcess();
cmd = new ArrayList<String>();
cmd.add("sudo");
cmd.add("parted");
for(int a=0;a<Data.ops2.size();a++) sp.addResponse("(parted) ", Data.ops2.get(a), false);
output = sp.run(cmd, false);
if ((output == null) || (output.indexOf("Error:") != -1) || (sp.getErrorLevel() != 0)) {
addLog("Error:Failed to create new partitions.");
JFLog.log("ErrorLevel=" + sp.getErrorLevel());
abort();
return;
}
//format / and swap
addLog("Formatting new partitions...");
Data.root.label = "OS";
if (!Data.format(Data.root)) {
addLog("Error:Failed to format root partition");
abort();
return;
}
addLog("...swap...");
Data.swap.label = "SWAP";
if (!Data.format(Data.swap)) {
addLog("Error:Failed to format swap partition");
abort();
return;
}
}
//refresh partition lists
Data.getDevices();
Data.getPartitions();
// confirm Data.root == ext4 & Data.swap == swap
String rootdev = Data.root.device.dev + Data.root.number;
String swapdev = "";
if (Data.swap != null) swapdev = Data.swap.device.dev + Data.swap.number;
boolean rootOk = false;
boolean swapOk = false;
if (Data.swap == null) swapOk = true;
for(int d=0;d<Data.devices.size();d++) {
Data.Device device = Data.devices.get(d);
for (int p=0;p<device.parts.size();p++) {
Data.Partition part = device.parts.get(p);
if (part.number == -1) continue;
String partdev = part.device.dev + part.number;
if (partdev.equals(rootdev)) {
if (part.filesys.startsWith("ext")) {
rootOk = true;
}
}
if ((Data.swap != null) && (partdev.equals(swapdev))) {
if (part.filesys.equals("swap")) {
swapOk = true;
}
}
}
}
if (!rootOk) {
addLog("Error:Unable to find root partition.");
abort();
return;
}
if (!swapOk) {
addLog("Error:Unable to find swap partition.");
abort();
return;
}
// mount Data.root
if (!Data.mount(Data.root, "/mnt/install")) {
addLog("Error:Failed to mount root partition.");
abort();
return;
}
//load filesToCopy from /etc/.live
try {
Properties props = new Properties();
FileInputStream etclive = new FileInputStream("/etc/.live");
props.load(etclive);
etclive.close();
filesToCopy = JF.atoi(props.getProperty("filesToCopy"));
} catch (Exception e) {
JFLog.log(e);
}
if (filesToCopy <= 0) {
addLog("Calculating files to copy...");
sp = new ShellProcess();
cmd = new ArrayList<String>();
cmd.add("sudo");
cmd.add("rsync");
cmd.add("-aHAXvn"); //archive + H A X + verbose + dry run
if (Linux.distro == Linux.DistroTypes.Ubuntu)
cmd.add("/rofs/.");
else
cmd.add("/mnt/src/.");
cmd.add("/mnt/install");
sp.addListener(Install.this);
sp.log = false; //too much
sp.keepOutput(false);
calcFilesToCopy = true;
output = sp.run(cmd, false);
calcFilesToCopy = false;
sp.log = true;
if ((output == null) || (sp.getErrorLevel() != 0)) {
addLog("Error:Failed to calculate files to copy.");
JFLog.log("ErrorLevel=" + sp.getErrorLevel());
abort();
return;
}
// addLog("filesToCopy=" + filesToCopy);
System.out.println("filesToCopy=" + filesToCopy);
}
sp = new ShellProcess();
cmd = new ArrayList<String>();
addLog("Copying files...");
cmd.add("sudo");
cmd.add("rsync");
cmd.add("-aHAXv"); //archive + H A X + verbose
if (Linux.distro == Linux.DistroTypes.Ubuntu)
cmd.add("/rofs/.");
else
cmd.add("/mnt/src/.");
cmd.add("/mnt/install");
sp.addListener(Install.this);
sp.log = false; //too much
sp.keepOutput(false);
output = sp.run(cmd, false);
sp.log = true;
sp.addListener(null);
if ((output == null) || (sp.getErrorLevel() != 0)) {
addLog("Error:Failed to copy files.");
JFLog.log("ErrorLevel=" + sp.getErrorLevel());
abort();
return;
}
ShellProcess.log = true;
//modify new installation
// : create skipped folders
/* Data.mkdir("/mnt/install/dev");
Data.mkdir("/mnt/install/proc");
Data.mkdir("/mnt/install/tmp");
Data.chmod("/mnt/install/tmp", "1777");
Data.mkdir("/mnt/install/sys");
Data.mkdir("/mnt/install/run");
Data.mkdir("/mnt/install/run/lock");
Data.chmod("/mnt/install/run/lock", "1777");*/
// : fstab
addLog("Generating fstab...");
try {
FileOutputStream fos = new FileOutputStream("/tmp/fstab");
fos.write("#fstab generated by jfinstall\n".getBytes());
for(int a=0;a<Data.fstab.size();a++) {
fos.write((Data.fstab.get(a) + "\n").getBytes());
}
fos.close();
sp = new ShellProcess();
cmd.clear();
cmd.add("sudo");
cmd.add("cp");
cmd.add("/tmp/fstab");
cmd.add("/mnt/install/etc/fstab");
output = sp.run(cmd, false);
if ((output == null) || (sp.getErrorLevel() != 0)) {
addLog("Error:Failed to setup fstab.");
JFLog.log("ErrorLevel=" + sp.getErrorLevel());
abort();
return;
}
} catch (Exception e) {
JFLog.log(e);
addLog("fstab creation failed");
abort();
return;
}
addLog("Creating new user...");
// : add new user
try {
sp = new ShellProcess();
cmd.clear();
cmd.add("sudo");
cmd.add("chroot");
cmd.add("/mnt/install");
cmd.add("useradd");
cmd.add("-s");
cmd.add("/bin/bash");
cmd.add("-m");
cmd.add("-G");
switch (Linux.distro) {
case Ubuntu: cmd.add("sudo"); break; //allows sudo (Ubuntu 12.04)
// cmd.add("admin"); //allows sudo (Ubuntu 11.10)
case Fedora: cmd.add("wheel"); break; //allows sudo (Fedora)
}
cmd.add("-c");
cmd.add("\"" + Data.fullName + "\"");
cmd.add(Data.loginName);
output = sp.run(cmd, false);
if ((output == null) || (sp.getErrorLevel() != 0)) {
addLog("Error:Failed to create new user.");
JFLog.log("ErrorLevel=" + sp.getErrorLevel());
abort();
return;
}
} catch (Exception e) {
JFLog.log(e);
addLog("Error:Failed to create new user.");
abort();
return;
}
// : set new user passwd
try {
sp = new ShellProcess();
cmd.clear();
cmd.add("sudo");
cmd.add("chroot");
cmd.add("/mnt/install");
cmd.add("passwd");
cmd.add(Data.loginName);
//ubuntu???
sp.addResponse("Enter new UNIX password:", Data.passwd + "\n", true);
sp.addResponse("Retype new UNIX password:", Data.passwd + "\n", true);
//fedora (f19)
sp.addResponse("New password:", Data.passwd + "\n", true);
sp.addResponse("Retype new password:", Data.passwd + "\n", true);
output = sp.run(cmd, true); //NOTE : prompts are sent to stderr
if ((output == null) || (sp.getErrorLevel() != 0)) {
addLog("Error:Failed to create new user passwd.");
JFLog.log("ErrorLevel=" + sp.getErrorLevel());
abort();
return;
}
} catch (Exception e) {
JFLog.log(e);
addLog("Error:Failed to create new user passwd.");
abort();
return;
}
// : delete /etc/.live
try {
sp = new ShellProcess();
cmd.clear();
cmd.add("sudo");
cmd.add("rm");
cmd.add("/mnt/install/etc/.live");
output = sp.run(cmd, false);
if ((output == null) || (sp.getErrorLevel() != 0)) {
addLog("Error:Failed to delete /etc/.live");
JFLog.log("ErrorLevel=" + sp.getErrorLevel());
abort();
return;
}
} catch (Exception e) {
JFLog.log(e);
addLog("Error:Failed to delete /etc/.live");
abort();
return;
}
// : assign hostname & domain
addLog("Assign computer name & domain...");
try {
File tmpFile1 = File.createTempFile("hostname", ".tmp");
FileOutputStream fos1 = new FileOutputStream(tmpFile1);
fos1.write(Data.localhost.getBytes());
fos1.close();
File tmpFile2 = File.createTempFile("hosts", ".tmp");
FileOutputStream fos2 = new FileOutputStream(tmpFile2);
FileInputStream fis2 = new FileInputStream("/mnt/install/etc/hosts");
BufferedReader br = new BufferedReader(new InputStreamReader(fis2));
String ln;
while ((ln = br.readLine()) != null) {
if (ln.startsWith("127.0.0.1")) {
ln = "127.0.0.1\tlocalhost " + Data.localhost;
}
fos2.write((ln + "\n").getBytes());
}
fos2.close();
fis2.close();
if (!Linux.runScript(new String[] {
"cp " + tmpFile1.getAbsolutePath() + " /mnt/install/etc/hostname",
"cp " + tmpFile2.getAbsolutePath() + " /mnt/install/etc/hosts",
})) {
tmpFile1.delete();
throw new Exception("file io error");
}
tmpFile1.delete();
} catch (Exception e) {
JFLog.log(e);
addLog("Error:Failed to set hostname.");
abort();
return;
}
try {
File tmpFile = File.createTempFile("network", ".xml");
FileOutputStream fos = new FileOutputStream(tmpFile);
fos.write(("<network>\n <hostname>" + Data.localhost + "</hostname>\n <domain>" + Data.localdomain + "</domain>\n</network>\n").getBytes());
fos.close();
if (!Linux.copyFile(tmpFile.getAbsolutePath(), "/mnt/install/etc/jconfig.d/network.xml")) {
throw new Exception("file io error");
}
tmpFile.delete();
} catch (Exception e) {
JFLog.log(e);
addLog("Error:Failed to save network config.");
abort();
return;
}
//set timezone
try {
sp = new ShellProcess();
cmd.clear();
cmd.add("sudo");
cmd.add("chroot");
cmd.add("/mnt/install");
cmd.add("rm");
cmd.add("/etc/localtime");
output = sp.run(cmd, false);
if ((output == null) || (sp.getErrorLevel() != 0)) {
addLog("Error:Failed to delete current timezone.");
JFLog.log("ErrorLevel=" + sp.getErrorLevel());
abort();
return;
}
} catch (Exception e) {
JFLog.log(e);
addLog("Error:Failed to delete current timezone.");
abort();
return;
}
try {
sp = new ShellProcess();
cmd.clear();
cmd.add("sudo");
cmd.add("chroot");
cmd.add("/mnt/install");
cmd.add("ln");
cmd.add("-s");
cmd.add("/usr/share/zoneinfo/" + Data.timezone);
cmd.add("/etc/localtime");
output = sp.run(cmd, false);
if ((output == null) || (sp.getErrorLevel() != 0)) {
addLog("Error:Failed to assign timezone.");
JFLog.log("ErrorLevel=" + sp.getErrorLevel());
abort();
return;
}
} catch (Exception e) {
JFLog.log(e);
addLog("Error:Failed to assign timezone.");
abort();
return;
}
try {
File file = new File("/tmp/timezone");
FileOutputStream fos = new FileOutputStream(file);
fos.write(Data.timezone.getBytes());
fos.close();
sp = new ShellProcess();
cmd.clear();
cmd.add("sudo");
cmd.add("cp");
cmd.add("/tmp/timezone");
cmd.add("/mnt/install/etc/timezone");
output = sp.run(cmd, false);
if ((output == null) || (sp.getErrorLevel() != 0)) {
addLog("Error:Failed to assign timezone.");
JFLog.log("ErrorLevel=" + sp.getErrorLevel());
abort();
return;
}
file.delete();
} catch (Exception e) {
JFLog.log(e);
addLog("Error:Failed to assign timezone.");
abort();
return;
}
// : set root part bootable (parted : set $Data.root.number boot on)
addLog("Setting boot partition...");
try {
sp = new ShellProcess();
cmd.clear();
cmd.add("sudo");
cmd.add("parted");
sp.addResponse("(parted) ", "select " + Data.root.device.dev + "\n", false);
sp.addResponse("(parted) ", "set " + Data.root.number + " boot on\n", false);
sp.addResponse("(parted) ", "quit\n", false);
output = sp.run(cmd, false);
if ((output == null) || (sp.getErrorLevel() != 0)) {
addLog("Error:Failed to set bootable partition.");
JFLog.log("ErrorLevel=" + sp.getErrorLevel());
abort();
return;
}
} catch (Exception e) {
JFLog.log(e);
addLog("Error:Failed to set bootable partition.");
abort();
return;
}
// : install grub
addLog("Installing boot loader...");
try {
sp = new ShellProcess();
cmd.clear();
cmd.add("sudo");
if (new File("/usr/sbin/grub2-install").exists())
cmd.add("grub2-install");
else if (new File("/usr/sbin/grub-install").exists())
cmd.add("grub-install");
else throw new Exception("grub tools not found");
cmd.add(Data.root.device.dev);
cmd.add("--boot-directory=/mnt/install/boot");
output = sp.run(cmd, false);
if ((output == null) || (sp.getErrorLevel() != 0)) {
addLog("Error:Failed to exec " + cmd.get(1));
JFLog.log("ErrorLevel=" + sp.getErrorLevel());
abort();
return;
}
} catch (Exception e) {
JFLog.log(e);
addLog("grub install failed");
abort();
return;
}
//get `uname -r`
sp = new ShellProcess();
//create initramfs
try {
sp = new ShellProcess();
cmd.clear();
cmd.add("sudo");
cmd.add("jfinstall-chroot.sh");
cmd.add("/mnt/install");
if (Linux.distro == Linux.DistroTypes.Fedora) {
//fedora way
cmd.add("dracut");
} else {
//ubuntu way
String uname = sp.run(new String[] {"uname", "-r"}, false).replaceAll("\n", "");
cmd.add("mkinitramfs");
cmd.add("-o");
cmd.add("/boot/initrd.img-" + uname);
}
output = sp.run(cmd, false);
if ((output == null) || (sp.getErrorLevel() != 0)) {
addLog("Error:Failed to exec " + cmd.get(3));
JFLog.log("ErrorLevel=" + sp.getErrorLevel());
abort();
return;
}
} catch (Exception e) {
JFLog.log(e);
addLog("create initramfs failed");
abort();
return;
}
//grub mkconfig
try {
sp = new ShellProcess();
cmd.clear();
cmd.add("sudo");
cmd.add("jfinstall-chroot.sh");
cmd.add("/mnt/install");
if (new File("/usr/sbin/grub2-mkconfig").exists()) {
cmd.add("grub2-mkconfig");
cmd.add("--output=/boot/grub2/grub.cfg");
} else if (new File("/usr/sbin/grub-mkconfig").exists()) {
cmd.add("grub-mkconfig");
cmd.add("--output=/boot/grub/grub.cfg");
} else {
throw new Exception("grub tools not found");
}
output = sp.run(cmd, false);
if ((output == null) || (sp.getErrorLevel() != 0)) {
addLog("Error:Failed to exec " + cmd.get(3) );
JFLog.log("ErrorLevel=" + sp.getErrorLevel());
abort();
return;
}
} catch (Exception e) {
JFLog.log(e);
addLog("grub mkconfig failed");
abort();
return;
}
//grub mkdevicemap (optional)
try {
sp = new ShellProcess();
cmd.clear();
cmd.add("sudo");
cmd.add("jfinstall-chroot.sh");
cmd.add("/mnt/install");
if (new File("/usr/sbin/grub2-mkdevicemap").exists())
cmd.add("grub2-mkdevicemap");
else if (new File("/usr/sbin/grub-mkdevicemap").exists())
cmd.add("grub-mkdevicemap");
else throw new Optional("device.map will not be created");
output = sp.run(cmd, false);
if ((output == null) || (sp.getErrorLevel() != 0)) {
addLog("Error:Failed to exec " + cmd.get(3));
JFLog.log("ErrorLevel=" + sp.getErrorLevel());
abort();
return;
}
} catch (Optional e) {
JFLog.log(e.toString());
} catch (Exception e) {
JFLog.log(e);
addLog("grub mkdevicemap failed");
abort();
return;
}
addLog("Removing unneeded packages...");
// : remove unneeded packages
try {
sp = new ShellProcess();
cmd.clear();
cmd.add("sudo");
cmd.add("chroot");
cmd.add("/mnt/install");
switch (Linux.distro) {
case Ubuntu:
cmd.add("apt-get");
cmd.add("--yes");
break;
case Fedora:
cmd.add("yum");
cmd.add("-y");
break;
}
cmd.add("remove");
switch (Linux.distro) {
case Ubuntu:
cmd.add("casper");
cmd.add("lupin-casper");
break;
}
cmd.add("jfinstall");
output = sp.run(cmd, false);
if ((output == null) || (sp.getErrorLevel() != 0)) {
addLog("Error:Failed to remove unneeded packages.");
JFLog.log("ErrorLevel=" + sp.getErrorLevel());
abort();
return;
}
} catch (Exception e) {
JFLog.log(e);
addLog("Error:Failed to remove unneeded packages.");
abort();
return;
}
/*
addLog("Installing 'extra' packages...");
//install restricted packages (ffmpeg, chrome)
try {
sp = new ShellProcess();
cmd.clear();
cmd.add("sudo");
cmd.add("chroot");
cmd.add("/mnt/install");
switch (Linux.distro) {
case Ubuntu:
cmd.add("apt-get");
cmd.add("--yes");
break;
case Fedora:
cmd.add("yum");
cmd.add("-y");
break;
}
cmd.add("install");
switch (Linux.distro) {
case Ubuntu:
cmd.add("libav-tools");
break;
case Fedora:
cmd.add("ffmpeg");
break;
}
cmd.add("google-chrome-stable");
output = sp.run(cmd, false);
if ((output == null) || (sp.getErrorLevel() != 0)) {
addLog("Warning:Failed to install extra packages.");
JFLog.log("ErrorLevel=" + sp.getErrorLevel());
}
} catch (Exception e) {
JFLog.log(e);
addLog("Warning:Failed to install extra packages.");
}
*/
//delete some fedora live files
/*
//even Fedora installers don't touch this stuff
if (Linux.distro == Linux.DistroTypes.Fedora) {
try {
new File("/etc/rc.d/init.d/livesys").delete();
new File("/etc/rc.d/init.d/livesys-late").delete();
new File("/sbin/halt.local").delete();
} catch (Exception e) {
JFLog.log(e);
}
}
*/
//unmount root part
Data.umount(Data.root.device.dev + Data.root.number);
if (Linux.distro == Linux.DistroTypes.Fedora) {
if (fedoraMount) {
Data.umount("/mnt/src");
fedoraMount = false;
}
}
//done!
addLog("Installation complete");
progress.setValue(100);
Installer.enableFinish();
}
}
private void addLog(String msg) {
log.setText(log.getText() + msg + "\n");
JFLog.log(msg);
}
private void abort() {
addLog("Installation aborted");
addLog("Please view /tmp/install.log for details");
if (Data.root != null) Data.umount(Data.root.device.dev + Data.root.number);
if (Linux.distro == Linux.DistroTypes.Fedora) {
if (fedoraMount) {
Data.umount("/mnt/src");
fedoraMount = false;
}
}
Installer.enableFinish();
}
public void shellProcessOutput(String str) {
int newFilesCopied = str.split("\n").length - 1;
if (calcFilesToCopy) {
filesToCopy += newFilesCopied;
} else {
totalFilesCopied += newFilesCopied;
progress.setValue(totalFilesCopied * 100 / filesToCopy);
}
}
public IPanel next() {return null;}
public IPanel prev() {return null;}
public IPanel getThis() {return this;}
}