summaryrefslogtreecommitdiffstats
path: root/src/main/java/org/openslx/taskmanager/tasks/CompileIPxeNew.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/org/openslx/taskmanager/tasks/CompileIPxeNew.java')
-rw-r--r--src/main/java/org/openslx/taskmanager/tasks/CompileIPxeNew.java194
1 files changed, 194 insertions, 0 deletions
diff --git a/src/main/java/org/openslx/taskmanager/tasks/CompileIPxeNew.java b/src/main/java/org/openslx/taskmanager/tasks/CompileIPxeNew.java
new file mode 100644
index 0000000..2afa636
--- /dev/null
+++ b/src/main/java/org/openslx/taskmanager/tasks/CompileIPxeNew.java
@@ -0,0 +1,194 @@
+package org.openslx.taskmanager.tasks;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.log4j.Logger;
+import org.openslx.satserver.util.Exec;
+import org.openslx.satserver.util.Exec.ExecCallback;
+import org.openslx.taskmanager.api.AbstractTask;
+import org.openslx.taskmanager.api.BoundedLog;
+
+import com.google.gson.annotations.Expose;
+
+public class CompileIPxeNew extends AbstractTask
+{
+ private static final Logger LOG = Logger.getLogger( CompileIPxeNew.class );
+
+ @Expose
+ private String ipaddress = null;
+
+ private Output status = new Output();
+
+ private static AtomicBoolean isRunning = new AtomicBoolean();
+
+ /**
+ * Files which should be copied to the TFTP dir so they're available for netboot
+ */
+ private static final String[] FILES_NET = { "bin-i386-pcbios/undionly.kpxe", "bin-i386-pcbios/undionly.kkpxe",
+ "bin-i386-pcbios/undionly.kkkpxe", "bin-x86_64-efi/ipxe.efi", "bin-x86_64-efi/snponly.efi" };
+
+ /**
+ * Files which should be moved to the websrv so they're available for download
+ */
+ private static final String[] FILES_DL = { "bin-i386-pcbios/ipxe.usb", "bin-i386-pcbios/ipxe.hd",
+ "bin-i386-pcbios/ipxe.lkrn", "bin-x86_64-efi/ipxe.usb", "bin-x86_64-efi/ipxe.efi",
+ "bin-x86_64-efi/snp.usb", "bin-x86_64-efi/snp.efi" };
+
+ /**
+ * Combination of the two, mapping each file to false.
+ * Will be used for status object.
+ */
+ private static final Map<String, Boolean> FILES_MAP;
+
+ private static final String[] FILES_ALL;
+
+ static
+ {
+ Map<String, Boolean> map = new HashMap<>();
+ for ( String s : FILES_NET ) {
+ map.put( s, false );
+ }
+ for ( String s : FILES_DL ) {
+ map.put( s, false );
+ }
+ FILES_MAP = Collections.unmodifiableMap( map );
+ FILES_ALL = map.keySet().toArray( new String[ map.size() ] );
+ }
+
+ @Override
+ protected boolean initTask()
+ {
+ this.setStatusObject( this.status );
+ if ( this.ipaddress == null || this.ipaddress.isEmpty() ) {
+ status.addError( "No IP address given!" );
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ protected boolean execute()
+ {
+ if ( !isRunning.compareAndSet( false, true ) ) {
+ status.addError( "Another operation is already in progress." );
+ return false;
+ }
+ try {
+ boolean ret = true;
+ if ( !updateIpxe() )
+ ret = false;
+ return ret;
+ } finally {
+ isRunning.set( false );
+ }
+ }
+
+ private boolean updateIpxe()
+ {
+ // Prepare menu
+ String template;
+ try {
+ template = FileUtils.readFileToString( new File( "./data/ipxe-embed.template" ), StandardCharsets.UTF_8 );
+ } catch ( IOException e ) {
+ status.addError( e.toString() );
+ return false;
+ }
+ // Substitution
+ template = template.replace( "%ipaddress%", this.ipaddress );
+ String hybridEmbed = template.replace( "%mode%", "PXE" );
+ String usbEmbed = template.replace( "%mode%", "USB" );
+ // Write out
+ try {
+ FileUtils.writeStringToFile( new File( "/opt/openslx/ipxe/ipxelinux.ipxe" ), hybridEmbed, StandardCharsets.UTF_8 );
+ FileUtils.writeStringToFile( new File( "/opt/openslx/ipxe/usb.ipxe" ), usbEmbed, StandardCharsets.UTF_8 );
+ } catch ( IOException e ) {
+ status.addError( e.toString() );
+ return false;
+ }
+ // Compile
+ ProcLogger pl = new ProcLogger();
+ if ( 0 != Exec.syncAt( 600, pl, "/opt/openslx/ipxe/src", join( "make", "EMBED=../ipxelinux.ipxe", FILES_ALL ) ) ) {
+ status.addError( "Compiling ipxe targets failed" );
+ return false;
+ }
+ // NETBOOT
+ for ( String f : FILES_NET ) {
+ try {
+ FileUtils.copyFile( new File( "/opt/openslx/ipxe/src", f ),
+ new File( "/srv/openslx/tftp", new File( f ).getName() ) );
+ } catch ( Exception e ) {
+ status.addError( "Cannot copy " + f + " to TFTP dir: " + e.toString() );
+ }
+ }
+ // DOWNLOAD
+ for ( String f : FILES_DL ) {
+ try {
+ FileUtils.copyFile( new File( "/opt/openslx/ipxe/src/", f ),
+ new File( "/srv/openslx/www/boot/download", f.replace( '/', '-' ) ) );
+ } catch ( Exception e ) {
+ status.addError( "Cannot copy " + f + " to www-download dir: " + e.toString() );
+ }
+ }
+ return true;
+ }
+
+ private String[] join(String a, String b, String... rest)
+ {
+ String[] r = new String[rest.length + 2];
+ r[0] = a;
+ r[1] = b;
+ System.arraycopy( rest, 0, r, 2, rest.length );
+ return r;
+ }
+
+ class Output
+ {
+ protected Map<String, Boolean> files = new ConcurrentHashMap<>( FILES_MAP );
+ protected final BoundedLog log = new BoundedLog( 20, true );
+ protected String errors = "";
+
+ protected void addLog( String data )
+ {
+ log.addLog( data );
+ }
+
+ protected synchronized void addError( String err )
+ {
+ errors = errors + err + "\n";
+ }
+ }
+
+ private static final Pattern RE_FINISH = Pattern.compile( "^\\s*\\[(?:FINISH|GENEFIDSK)\\]\\s*(.*?)\\s*$" );
+
+ private class ProcLogger implements ExecCallback
+ {
+
+ @Override
+ public void processStdOut( String line )
+ {
+ status.addLog( line );
+ Matcher m = RE_FINISH.matcher( line );
+ if ( m.matches() ) {
+ status.files.put( m.group( 1 ), true );
+ }
+ }
+
+ @Override
+ public void processStdErr( String line )
+ {
+ status.addLog( line );
+ }
+
+ }
+
+}