From b7c764e33206b44a5831d335573a45fe4c424231 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Sat, 8 Dec 2018 16:43:45 +0100 Subject: [server] Support downloading and querying preset runscripts --- .../org/openslx/bwlp/sat/database/Updater.java | 73 ++++++++++++++++++++++ .../bwlp/sat/database/mappers/DbLecture.java | 21 ++++++- .../org/openslx/bwlp/sat/thrift/ServerHandler.java | 10 ++- .../java/org/openslx/bwlp/sat/web/WebServer.java | 11 +++- 4 files changed, 110 insertions(+), 5 deletions(-) diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/Updater.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/Updater.java index 8fcd70a9..26bb1856 100644 --- a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/Updater.java +++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/Updater.java @@ -19,6 +19,7 @@ public class Updater { addLectureFilter(); addPredefinedFilters(); addPredefinedNetworkShares(); + addPredefinedRunScripts(); } private static void addLectureLocationMapTable() throws SQLException { @@ -246,6 +247,78 @@ public class Updater { throw e; } } + + /** + * Add tables for predefined runscripts. There's the main table for the + * scripts, then we need an n:m table to connect lectures to runscripts, and + * finally another n:m table to define which operating systems a script is + * suitable for. + */ + private static void addPredefinedRunScripts() throws SQLException { + try (MysqlConnection connection = Database.getConnection()) { + if (!tableExists(connection, "presetrunscript")) { + connection.prepareStatement("CREATE TABLE presetrunscript (" + + " runscriptid int(11) NOT NULL AUTO_INCREMENT," + + " scriptname varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL," + + " content text COLLATE utf8mb4_unicode_ci NOT NULL," + + " extension varchar(10) COLLATE utf8mb4_unicode_ci NOT NULL," + + " visibility tinyint(1) NOT NULL COMMENT '0 = hidden, 1 = normal, 2 = minimized'," + + " passcreds tinyint(1) NOT NULL," + + " isglobal tinyint(1) NOT NULL COMMENT 'Whether to apply this script to all lectures'," + + " PRIMARY KEY (runscriptid)," + + " KEY isglobal (isglobal)" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci") + .executeUpdate(); + LOGGER.info("Updated database: Created table presetrunscript"); + } + if (!tableExists(connection, "presetrunscript_x_operatingsystem")) { + connection.prepareStatement("CREATE TABLE presetrunscript_x_operatingsystem (" + + " runscriptid int(11) NOT NULL," + + " osid int(11) NOT NULL," + + " PRIMARY KEY (runscriptid, osid)," + + " KEY osid (osid)" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci") + .executeUpdate(); + connection.prepareStatement( + "ALTER TABLE presetrunscript_x_operatingsystem" + + " ADD CONSTRAINT osid FOREIGN KEY (osid)" + + " REFERENCES operatingsystem (osid)" + + " ON DELETE CASCADE ON UPDATE CASCADE," + + " ADD CONSTRAINT runscriptid FOREIGN KEY (runscriptid)" + + " REFERENCES presetrunscript (runscriptid)" + + " ON DELETE CASCADE ON UPDATE CASCADE") + .executeUpdate(); + LOGGER.info("Updated database: Created presetrunscript_x_operatingsystem table + constraint"); + } + if (!tableExists(connection, "lecture_x_runscript")) { + connection.prepareStatement("CREATE TABLE lecture_x_runscript (" + + " lectureid char(36) CHARACTER SET ascii COLLATE ascii_bin NOT NULL," + + " runscriptid int(11) NOT NULL," + + " PRIMARY KEY (lectureid,runscriptid)," + + " KEY runscriptid (runscriptid)" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci") + .executeUpdate(); + connection.prepareStatement( + "ALTER TABLE lecture_x_runscript" + + " ADD CONSTRAINT lecture_runscript FOREIGN KEY (lectureid)" + + " REFERENCES lecture (lectureid)" + + " ON DELETE CASCADE ON UPDATE CASCADE," + + " ADD CONSTRAINT lecture_x_runscript_ibfk_1 FOREIGN KEY (runscriptid)" + + " REFERENCES presetrunscript (runscriptid)" + + " ON DELETE CASCADE ON UPDATE CASCADE") + .executeUpdate(); + LOGGER.info("Updated database: Created lecture_x_runscript table + constraint"); + } + connection.commit(); + } catch (SQLException e) { + LOGGER.error("Query failed in addPredefinedRunScripts()", e); + throw e; + } + } + + /* + * Helper methods + */ /** * Check whether given table exists. diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbLecture.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbLecture.java index 603b72fe..a8889d78 100644 --- a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbLecture.java +++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbLecture.java @@ -547,7 +547,7 @@ public class DbLecture { // Get required data about lecture and used image MysqlStatement stmt = connection.prepareStatement("SELECT" + " l.displayname AS lecturename, l.starttime, l.endtime, l.isenabled, l.hasusbaccess," - + " l.runscript, o.virtoskeyword, i.virtualizerconfig" + + " l.runscript, b.osid, o.virtoskeyword, i.virtualizerconfig" + " FROM lecture l " + " INNER JOIN imageversion i USING (imageversionid)" + " INNER JOIN imagebase b USING (imagebaseid)" @@ -573,8 +573,9 @@ public class DbLecture { osKeyword = rs.getString("virtoskeyword"); usbAccess = rs.getBoolean("hasusbaccess"); retval.vmx = meta; - retval.runScript = rs.getString("runscript"); + retval.legacyRunScript = rs.getString("runscript"); retval.netShares = DbLectureNetshare.getLectureNetshares(connection, lectureId); + retval.runScript = DbRunScript.getRunScriptsForLaunch(connection, lectureId, rs.getInt("osid")); // Everything worked so far, update statistics counters MysqlStatement upStmt = connection.prepareStatement("UPDATE" + " lecture SET lastused = UNIX_TIMESTAMP(), usecount = usecount + 1" @@ -653,10 +654,24 @@ public class DbLecture { MailGenerator.lectureDeactivated(lectures); } + public static class RunScript { + public final String content; + public final String extension; + public final int visibility; + public final boolean passCreds; + RunScript(String content, String extension, int visibility, boolean passCreds) { + this.content = content; + this.extension = extension; + this.visibility = visibility; + this.passCreds = passCreds; + } + } + public static class LaunchData { public VmMetaData vmx; public List netShares; - public String runScript; + public String legacyRunScript; + public List runScript; } } diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/ServerHandler.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/ServerHandler.java index 8e1ed59e..f97766ed 100644 --- a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/ServerHandler.java +++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/ServerHandler.java @@ -20,6 +20,7 @@ import org.openslx.bwlp.sat.database.mappers.DbLectureNetshare; import org.openslx.bwlp.sat.database.mappers.DbLecturePermissions; import org.openslx.bwlp.sat.database.mappers.DbLocation; import org.openslx.bwlp.sat.database.mappers.DbLog; +import org.openslx.bwlp.sat.database.mappers.DbRunScript; import org.openslx.bwlp.sat.database.mappers.DbUser; import org.openslx.bwlp.sat.database.models.ImageVersionMeta; import org.openslx.bwlp.sat.database.models.LocalImageVersion; @@ -56,6 +57,7 @@ import org.openslx.bwlp.thrift.iface.NetShare; import org.openslx.bwlp.thrift.iface.OperatingSystem; import org.openslx.bwlp.thrift.iface.Organization; import org.openslx.bwlp.thrift.iface.PredefinedData; +import org.openslx.bwlp.thrift.iface.PresetRunScript; import org.openslx.bwlp.thrift.iface.SatelliteConfig; import org.openslx.bwlp.thrift.iface.SatelliteServer; import org.openslx.bwlp.thrift.iface.SatelliteStatus; @@ -790,7 +792,7 @@ public class ServerHandler implements SatelliteServer.Iface { public PredefinedData getPredefinedData(String userToken) throws TAuthorizationException, TInvocationException, TException { SessionManager.ensureAuthenticated(userToken); // Only logged in users - PredefinedData data = new PredefinedData(new ArrayList(), new ArrayList()); + PredefinedData data = new PredefinedData(); try { data.ldapFilter = DbLectureFilter.getPredefinedLdapFilters(); } catch (SQLException e) { @@ -803,6 +805,12 @@ public class ServerHandler implements SatelliteServer.Iface { throw new TInvocationException(InvocationError.INTERNAL_SERVER_ERROR, "Database failure when querying predefined network shares."); } + try { + data.runScripts = DbRunScript.getPredefinedRunScripts(); + } catch (SQLException e) { + throw new TInvocationException(InvocationError.INTERNAL_SERVER_ERROR, + "Database failure when querying predefined run scripts."); + } return data; } diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/web/WebServer.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/web/WebServer.java index e1823bf8..8d10271d 100644 --- a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/web/WebServer.java +++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/web/WebServer.java @@ -21,6 +21,7 @@ import org.kamranzafar.jtar.TarHeader; import org.kamranzafar.jtar.TarOutputStream; import org.openslx.bwlp.sat.database.mappers.DbLecture; import org.openslx.bwlp.sat.database.mappers.DbLecture.LaunchData; +import org.openslx.bwlp.sat.database.mappers.DbLecture.RunScript; import org.openslx.bwlp.sat.fileserv.FileServer; import org.openslx.bwlp.thrift.iface.LectureRead; import org.openslx.bwlp.thrift.iface.NetRule; @@ -178,8 +179,16 @@ public class WebServer extends NanoHTTPD { public void run() { try { tarPutFile(output, "vmx", ld.vmx.getFilteredDefinitionArray()); - tarPutFile(output, "runscript", ld.runScript); + tarPutFile(output, "runscript", ld.legacyRunScript); tarPutFile(output, "netshares", serializeNetShares(ld.netShares)); + if (ld.runScript != null) { + int cnt = 0; + for (RunScript rs : ld.runScript) { + tarPutFile(output, String.format("adminrun/%04d-%d-%d.%s", + cnt++, rs.visibility, + rs.passCreds ? 1 : 0, rs.extension), rs.content); + } + } } catch (IOException e) { LOGGER.warn("Error writing to tar stream", e); } finally { -- cgit v1.2.3-55-g7522