summaryrefslogtreecommitdiffstats
path: root/dozentenmodulserver/src/main/java
diff options
context:
space:
mode:
authorSimon Rettberg2016-01-14 17:43:02 +0100
committerSimon Rettberg2016-01-14 17:43:02 +0100
commit3578c2cdf4bba9a73d57a64941ebc2e4c931e555 (patch)
tree622e50e698663f288f6b7d9d51a610f23218a831 /dozentenmodulserver/src/main/java
parent[server] Remove stupid debug output (diff)
downloadtutor-module-3578c2cdf4bba9a73d57a64941ebc2e4c931e555.tar.gz
tutor-module-3578c2cdf4bba9a73d57a64941ebc2e4c931e555.tar.xz
tutor-module-3578c2cdf4bba9a73d57a64941ebc2e4c931e555.zip
[server] Add location support/filtering
Diffstat (limited to 'dozentenmodulserver/src/main/java')
-rw-r--r--dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/App.java15
-rw-r--r--dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbLecture.java71
-rw-r--r--dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/ServerHandler.java9
-rw-r--r--dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/util/Configuration.java6
-rw-r--r--dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/web/WebServer.java66
5 files changed, 154 insertions, 13 deletions
diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/App.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/App.java
index 2d9e73c9..8e615ef1 100644
--- a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/App.java
+++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/App.java
@@ -3,6 +3,7 @@ package org.openslx.bwlp.sat;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
+import java.sql.SQLException;
import java.util.HashSet;
import java.util.Set;
@@ -13,6 +14,7 @@ import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;
import org.apache.thrift.transport.TTransportException;
+import org.openslx.bwlp.sat.database.Updater;
import org.openslx.bwlp.sat.database.mappers.DbUser;
import org.openslx.bwlp.sat.fileserv.FileServer;
import org.openslx.bwlp.sat.maintenance.DeleteOldImages;
@@ -40,8 +42,9 @@ public class App {
public static void main(String[] args) throws TTransportException, NoSuchAlgorithmException, IOException,
KeyManagementException {
- //get going and show basic information in log file
- BasicConfigurator.configure(new ConsoleAppender(new PatternLayout("%d %-5p [%t] %C{1} - %m%n")));
+ // get going and show basic information in log file
+ // don't add date/time to log output - will be done by syslog
+ BasicConfigurator.configure(new ConsoleAppender(new PatternLayout("%-5p [%t] %C{1} - %m%n")));
if (args.length != 0 && args[0].equals("debug")) {
DEBUG = true;
}
@@ -58,6 +61,14 @@ public class App {
System.exit(1);
}
+ // Update database schema if applicable
+ try {
+ Updater.updateDatabase();
+ } catch (SQLException e1) {
+ LOGGER.fatal("Updating/checking the database layout failed.");
+ return;
+ }
+
if (Identity.loadCertificate() == null) {
LOGGER.error("Could not set up TLS/SSL requirements, exiting");
System.exit(1);
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 0ed62770..1f0daf66 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
@@ -63,6 +63,8 @@ public class DbLecture {
stmt.setString("imageversionid", lecture.imageVersionId);
stmt.setBoolean("autoupdate", lecture.autoUpdate);
stmt.setBoolean("isenabled", lecture.isEnabled);
+ stmt.setBoolean("isprivate", lecture.limitToAllowedUsers);
+ stmt.setBoolean("islocationprivate", lecture.limitToLocations);
stmt.setLong("starttime", lecture.startTime);
stmt.setLong("endtime", lecture.endTime);
stmt.setString("updaterid", updatingUser.userId);
@@ -75,22 +77,41 @@ public class DbLecture {
stmt.setBoolean("canadmindefault", lecture.defaultPermissions.admin);
}
+ private static void writeLocations(MysqlConnection connection, String lectureId, List<Integer> locationIds)
+ throws SQLException {
+ MysqlStatement delStmt = connection.prepareStatement("DELETE FROM lecture_x_location WHERE lectureid = :lectureid");
+ delStmt.setString("lectureid", lectureId);
+ delStmt.executeUpdate();
+ if (locationIds == null || locationIds.isEmpty())
+ return;
+ MysqlStatement addStmt = connection.prepareStatement("INSERT IGNORE INTO lecture_x_location (lectureid, locationid)"
+ + " VALUES (:lectureid, :locationid)");
+ addStmt.setString("lectureid", lectureId);
+ for (Integer locationId : locationIds) {
+ addStmt.setInt("locationid", locationId);
+ addStmt.executeUpdate();
+ }
+ }
+
public static String create(UserInfo user, LectureWrite lecture) throws SQLException {
try (MysqlConnection connection = Database.getConnection()) {
MysqlStatement stmt = connection.prepareStatement("INSERT INTO lecture"
+ " (lectureid, displayname, description, imageversionid, autoupdate,"
+ " isenabled, starttime, endtime, createtime, updatetime,"
+ + " isprivate, islocationprivate,"
+ " ownerid, updaterid, runscript, nics, netrules, isexam,"
+ " hasinternetaccess, caneditdefault, canadmindefault)"
+ " VALUES "
+ " (:lectureid, :displayname, :description, :imageversionid, :autoupdate,"
+ " :isenabled, :starttime, :endtime, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(),"
+ + " :isprivate, :islocationprivate,"
+ " :ownerid, :updaterid, :runscript, :nics, :netrules, :isexam,"
+ " :hasinternetaccess, :caneditdefault, :canadmindefault)");
String lectureId = UUID.randomUUID().toString();
setWriteFields(stmt, lectureId, lecture, user);
stmt.setString("ownerid", user.userId);
stmt.executeUpdate();
+ writeLocations(connection, lectureId, lecture.locationIds);
connection.commit();
return lectureId;
} catch (SQLException e) {
@@ -105,11 +126,13 @@ public class DbLecture {
+ " displayname = :displayname, description = :description, imageversionid = :imageversionid,"
+ " autoupdate = :autoupdate, isenabled = :isenabled, starttime = :starttime,"
+ " endtime = :endtime, updatetime = UNIX_TIMESTAMP(),"
+ + " isprivate = :isprivate, islocationprivate = :islocationprivate,"
+ " updaterid = :updaterid, runscript = :runscript, nics = :nics,"
+ " netrules = :netrules, isexam = :isexam, hasinternetaccess = :hasinternetaccess,"
+ " caneditdefault = :caneditdefault, canadmindefault = :canadmindefault"
+ " WHERE lectureid = :lectureid");
setWriteFields(stmt, lectureId, lecture, user);
+ writeLocations(connection, lectureId, lecture.locationIds);
stmt.executeUpdate();
}
@@ -241,6 +264,7 @@ public class DbLecture {
+ " l.lectureid, l.displayname AS lecturename, l.description, l.imageversionid, i.imagebaseid,"
+ " l.autoupdate, l.isenabled, l.starttime, l.endtime, l.lastused, l.usecount, l.createtime,"
+ " l.updatetime, l.ownerid, l.updaterid, l.runscript, l.nics, l.netrules, l.isexam,"
+ + " l.isprivate, l.islocationprivate,"
+ " l.hasinternetaccess, l.caneditdefault, l.canadmindefault, p.canedit, p.canadmin"
+ " FROM lecture l "
+ " LEFT JOIN imageversion i USING (imageversionid)"
@@ -259,6 +283,8 @@ public class DbLecture {
lecture.setImageBaseId(rs.getString("imagebaseid"));
lecture.setAutoUpdate(rs.getBoolean("autoupdate"));
lecture.setIsEnabled(rs.getBoolean("isenabled"));
+ //lecture.setLimitToAllowedUsers(rs.getBoolean("isprivate"));
+ //lecture.setLimitToLocations(rs.getBoolean("islocationprivate")); TODO
lecture.setStartTime(rs.getLong("starttime"));
lecture.setEndTime(rs.getLong("endtime"));
lecture.setLastUsed(rs.getLong("lastused"));
@@ -286,6 +312,7 @@ public class DbLecture {
lecture.setDefaultPermissions(DbLecturePermissions.fromResultSetDefault(rs));
lecture.setUserPermissions(DbLecturePermissions.fromResultSetUser(rs));
User.setCombinedUserPermissions(lecture, user);
+ // TODO: Query locations
return lecture;
} catch (SQLException e) {
LOGGER.error("Query failed in DbLecture.getLectureDetails()", e);
@@ -407,10 +434,37 @@ public class DbLecture {
}
}
- public static VmChooserListXml getUsableListXml(boolean exams) throws SQLException {
+ public static VmChooserListXml getUsableListXml(boolean exams, String locationsString) throws SQLException {
+ // Sanitize and clean locations string
+ // Input is in the form of "1 2 3 4" or "1" or " 1 4 5"
+ // We want "1,2,3,4" or "1" or "1,4,5"
+ // Do this since we embed this directly into the query
+ String cleanLocations = null;
+ if (Util.isEmptyString(locationsString)) {
+ cleanLocations = "0";
+ } else if (locationsString.indexOf(' ') == -1) {
+ cleanLocations = Integer.toString(org.openslx.util.Util.parseInt(locationsString, 0));
+ } else {
+ String[] array = locationsString.split(" +");
+ for (String loc : array) {
+ int val = org.openslx.util.Util.parseInt(loc, -1);
+ if (val == -1)
+ continue;
+ if (cleanLocations == null) {
+ cleanLocations = Integer.toString(val);
+ } else {
+ cleanLocations += "," + Integer.toString(val);
+ }
+ }
+ if (cleanLocations == null) {
+ cleanLocations = "0";
+ }
+ }
+ // Query
try (MysqlConnection connection = Database.getConnection()) {
MysqlStatement stmt = connection.prepareStatement("SELECT"
+ " l.lectureid, l.displayname AS lecturename, l.description,"
+ + " l.islocationprivate, loc.lectureid AS loctest,"
+ " l.endtime, l.usecount, o.displayname AS osname, v.virtname, b.istemplate,"
+ " v.virtid, ov.virtoskeyword, i.filepath"
+ " FROM lecture l "
@@ -419,13 +473,26 @@ public class DbLecture {
+ " INNER JOIN operatingsystem o USING (osid)"
+ " INNER JOIN virtualizer v USING (virtid)"
+ " LEFT JOIN os_x_virt ov USING (osid, virtid)"
+ + " LEFT JOIN ("
+ + " SELECT DISTINCT lectureid FROM lecture_x_location WHERE locationid IN (" + cleanLocations + ")"
+ + " ) loc USING (lectureid)"
+ " WHERE l.isenabled = 1 AND l.isprivate = 0 AND l.isexam = :isexam"
+ " AND l.starttime < UNIX_TIMESTAMP() AND l.endtime > UNIX_TIMESTAMP() AND i.isvalid = 1");
stmt.setBoolean("isexam", exams);
ResultSet rs = stmt.executeQuery();
VmChooserListXml list = new VmChooserListXml(true);
while (rs.next()) {
- String prio = rs.getBoolean("istemplate") ? "10" : "100";
+ boolean isForThisLocation = rs.getString("loctest") != null;
+ if (!isForThisLocation && rs.getBoolean("islocationprivate"))
+ continue; // Is limited to location, and we're not in one of the required locations
+ String prio;
+ if (isForThisLocation) {
+ prio = "40";
+ } else if (rs.getBoolean("istemplate")) {
+ prio = "60";
+ } else {
+ prio = "80";
+ }
list.add(new VmChooserEntryXml(rs.getString("filepath"), prio, "-",
rs.getString("lecturename"), rs.getString("description"), rs.getString("lectureid"),
rs.getString("virtid"), rs.getString("virtname"), rs.getString("virtoskeyword"),
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 a1a9dacf..d24bb912 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
@@ -14,6 +14,7 @@ import org.openslx.bwlp.sat.database.mappers.DbImage.DeleteState;
import org.openslx.bwlp.sat.database.mappers.DbImagePermissions;
import org.openslx.bwlp.sat.database.mappers.DbLecture;
import org.openslx.bwlp.sat.database.mappers.DbLecturePermissions;
+import org.openslx.bwlp.sat.database.mappers.DbLocation;
import org.openslx.bwlp.sat.database.mappers.DbUser;
import org.openslx.bwlp.sat.database.models.ImageVersionMeta;
import org.openslx.bwlp.sat.database.models.LocalImageVersion;
@@ -635,8 +636,12 @@ public class ServerHandler implements SatelliteServer.Iface {
@Override
public List<Location> getLocations() throws TException {
- // TODO Auto-generated method stub
- return null;
+ try {
+ return DbLocation.getLocations();
+ } catch (SQLException e) {
+ throw new TInvocationException(InvocationError.INTERNAL_SERVER_ERROR,
+ "Database failure when retrieving list");
+ }
}
}
diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/util/Configuration.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/util/Configuration.java
index c8208338..5dd9b8ec 100644
--- a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/util/Configuration.java
+++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/util/Configuration.java
@@ -23,6 +23,7 @@ public class Configuration {
private static String masterAddress;
private static boolean masterSsl = true;
private static int masterPort = 9091;
+ private static String dbLocationTable;
public static boolean load() throws IOException {
// Load configuration from java properties file
@@ -39,6 +40,7 @@ public class Configuration {
dbUri = prop.getProperty("db.uri");
dbUsername = prop.getProperty("db.username");
dbPassword = prop.getProperty("db.password");
+ dbLocationTable = prop.getProperty("db.location-table");
masterAddress = prop.getProperty("master.address");
if (!Util.isEmptyString(prop.getProperty("master.ssl"))) {
masterSsl = Boolean.getBoolean(prop.getProperty("master.ssl"));
@@ -75,6 +77,10 @@ public class Configuration {
public static String getDbPassword() {
return dbPassword;
}
+
+ public static String getDbLocationTable() {
+ return dbLocationTable;
+ }
public static File getVmStoreProdPath() {
return vmStoreProdPath;
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 37a64ee8..5f82bac1 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
@@ -3,6 +3,9 @@ package org.openslx.bwlp.sat.web;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.sql.SQLException;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Map;
import org.apache.commons.io.output.ByteArrayOutputStream;
import org.apache.log4j.Logger;
@@ -21,23 +24,66 @@ public class WebServer extends NanoHTTPD {
private static final Logger LOGGER = Logger.getLogger(WebServer.class);
- private static final GenericDataCache<byte[]> lectureListCache = new GenericDataCache<byte[]>(15000) {
- Serializer serializer = new Persister();
+ private static final int LIST_CACHE_MS = 15000;
+ private static final int LIST_CACHE_MAX_ENTRIES = 16;
+
+ private static final Map<String, XmlDataCache> lectureListCache = Collections.synchronizedMap(new LinkedHashMap<String, XmlDataCache>() {
+ private static final long serialVersionUID = -8461839969909678055L;
+
+ @Override
+ protected boolean removeEldestEntry(Map.Entry<String, XmlDataCache> eldest) {
+ return size() > LIST_CACHE_MAX_ENTRIES;
+ }
+ });
+
+ private static final Serializer serializer = new Persister();
+
+ private class XmlDataCache extends GenericDataCache<byte[]> {
+
+ private final String locationId;
+
+ public XmlDataCache(String locations) {
+ super(LIST_CACHE_MS);
+ this.locationId = locations;
+ }
@Override
protected byte[] update() throws Exception {
- VmChooserListXml listXml = DbLecture.getUsableListXml(false);
+ VmChooserListXml listXml = DbLecture.getUsableListXml(false, locationId);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
serializer.write(listXml, baos);
return baos.toByteArray();
}
- };
+
+ }
public WebServer(int port) {
super("127.0.0.1", port);
super.maxRequestSize = 65535;
}
+ /**
+ * Extract request source ip address. Honors the x-forwarded-for header.
+ *
+ * @param headers map of headers as supplied by nanohttpd
+ * @return IP address, or empty string if unknown
+ */
+ private String extractIp(Map<String, String> headers) {
+ String ip;
+ ip = headers.get("remote-addr");
+ if (ip != null && !ip.equals("127.0.0.1"))
+ return ip;
+ if (headers == null || headers.isEmpty())
+ return "";
+ ip = headers.get("x-forwarded-for");
+ if (ip == null || ip.isEmpty())
+ return "";
+ final int i = ip.lastIndexOf(',');
+ if (i == -1)
+ return ip.trim();
+ return ip.substring(i + 1).trim();
+ }
+
@Override
public Response serve(IHTTPSession session) {
String uri = session.getUri();
@@ -61,7 +107,7 @@ public class WebServer extends NanoHTTPD {
private Response handle(IHTTPSession session, String uri) {
// Our special stuff
if (uri.startsWith("/vmchooser/list")) {
- return serveVmChooserList();
+ return serveVmChooserList(session.getParms());
}
if (uri.startsWith("/vmchooser/lecture/")) {
return serveLectureStart(uri.substring(19));
@@ -106,9 +152,15 @@ public class WebServer extends NanoHTTPD {
new ByteArrayInputStream(meta.getFilteredDefinitionArray()));
}
- private Response serveVmChooserList() {
+ private Response serveVmChooserList(Map<String, String> params) {
+ String locations = params.get("locations");
+ XmlDataCache cache = lectureListCache.get(locations);
+ if (cache == null) {
+ cache = new XmlDataCache(locations);
+ lectureListCache.put(locations, cache);
+ }
return new NanoHTTPD.Response(NanoHTTPD.Response.Status.OK, "text/xml; charset=utf-8",
- new ByteArrayInputStream(lectureListCache.get()));
+ new ByteArrayInputStream(cache.get()));
}
public static Response internalServerError() {