diff options
author | Simon Rettberg | 2015-09-23 16:52:16 +0200 |
---|---|---|
committer | Simon Rettberg | 2015-09-23 16:52:16 +0200 |
commit | 8bb1ae726b5108d8ff58dbfd36378fb8319dfa98 (patch) | |
tree | 05e0b880c824673bc9d7e0d8bc2c33e8c3630b28 /dozentenmodul/src/main/java/org/openslx/dozmod | |
parent | [server] Fix race condition on delete; check for vmstore before up/download (diff) | |
download | tutor-module-8bb1ae726b5108d8ff58dbfd36378fb8319dfa98.tar.gz tutor-module-8bb1ae726b5108d8ff58dbfd36378fb8319dfa98.tar.xz tutor-module-8bb1ae726b5108d8ff58dbfd36378fb8319dfa98.zip |
[client] Disable login button while login is running; create legacy vmx if server doesn't supply one
Diffstat (limited to 'dozentenmodul/src/main/java/org/openslx/dozmod')
6 files changed, 73 insertions, 58 deletions
diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/App.java b/dozentenmodul/src/main/java/org/openslx/dozmod/App.java index d7c9539f..4a1f6fe3 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/App.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/App.java @@ -200,8 +200,8 @@ public class App { null, "Ungefangene Ausnahme in Faden " + t.getName() - + "\n" - + "Die Anwendung könnte instabil laufen. Zur Sicherheit sollten Sie sie neustarten.", + + "\n\n" + + "Die Anwendung könnte instabil laufen.\nZur Sicherheit sollten Sie sie neustarten.", MessageType.WARNING, LOGGER, e); } }); diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/filetransfer/DownloadTask.java b/dozentenmodul/src/main/java/org/openslx/dozmod/filetransfer/DownloadTask.java index 0cd77713..0aa48e8c 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/filetransfer/DownloadTask.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/filetransfer/DownloadTask.java @@ -103,12 +103,12 @@ public class DownloadTask extends TransferTask { if (chunk == null) return; // TODO: Hash check, async - chunks.markSuccessful(chunk); try { synchronized (fileHandle) { fileHandle.seek(chunk.range.startOffset); fileHandle.write(buffer, 0, chunk.range.getLength()); } + chunks.markSuccessful(chunk); } catch (Exception e) { LOGGER.error("Could not write to file at offset " + chunk.range.startOffset, e); fileWritable = false; @@ -166,7 +166,8 @@ public class DownloadTask extends TransferTask { if (consecutiveInitFails.get() > 20) { state = TransferState.ERROR; error = "Cannot talk to server after 20 tries..."; - } else if (chunks.isComplete()) { + } else if (chunks.isComplete() && getTransferCount() == 0) { + Util.safeClose(fileHandle); state = TransferState.FINISHED; error = null; } else { diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/MainWindow.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/MainWindow.java index 7a0c1b56..57c825f5 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/MainWindow.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/MainWindow.java @@ -236,7 +236,7 @@ public abstract class MainWindow { public void fire() { App.waitForInit(); // now try to init the session with the saved configuration (by giving it null) - if (ThriftActions.initSession(null, SwingUtilities.getWindowAncestor(mainWindow))) { + if (ThriftActions.initSession(null, false, SwingUtilities.getWindowAncestor(mainWindow))) { initWindow(); } else { // session resume failed, so do the normal login procedure diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/LoginWindow.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/LoginWindow.java index 8b16bd2b..342ce9eb 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/LoginWindow.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/LoginWindow.java @@ -73,18 +73,21 @@ public class LoginWindow extends LoginWindowLayout { private final String NO_USERNAME = "Kein Benutzername angegeben!"; private final String NO_PASSWORD = "Kein Passwort angegeben!"; - public static boolean forceCustomSatellite; + private boolean forceCustomSatellite = false; + private final KeyEventDispatcher satelliteShiftDispatcher = new KeyEventDispatcher() { @Override public boolean dispatchKeyEvent(KeyEvent event) { - int type = event.getID(); int code = event.getKeyCode(); if (code == KeyEvent.VK_SHIFT) { // shift key is pressed + int type = event.getID(); if (type == KeyEvent.KEY_PRESSED) { forceCustomSatellite = true; - } else if (type == KeyEvent.KEY_RELEASED) + event.consume(); + } else if (type == KeyEvent.KEY_RELEASED) { forceCustomSatellite = false; - event.consume(); + event.consume(); + } } return event.isConsumed(); } @@ -213,8 +216,7 @@ public class LoginWindow extends LoginWindowLayout { return; } - idpCombo.setModel( - new DefaultComboBoxModel<Organization>(orgs.toArray(new Organization[orgs.size()]))); + idpCombo.setModel(new DefaultComboBoxModel<Organization>(orgs.toArray(new Organization[orgs.size()]))); // now check if we had a saved identity provider String savedOrganizationId = Config.getIdentityProvider(); idpCombo.setSelectedItem(OrganizationCache.find(savedOrganizationId)); @@ -292,7 +294,8 @@ public class LoginWindow extends LoginWindowLayout { // username contains a known organization if (!selectedOrg.equals(orgInUsername)) { // but it does not match the one selected in the combobox - boolean ret = Gui.showMessageBox(this, + boolean ret = Gui.showMessageBox( + this, "Der angegebene Benutzername enthält eine Organisation, die nicht mit Ihrer IDP-Auswahl übereinstimmt." + "\nWollen Sie die in Ihrem Benutzername gefundene Organisation verwenden?", MessageType.QUESTION_YESNO, null, null); @@ -314,11 +317,16 @@ public class LoginWindow extends LoginWindowLayout { final LoginWindow me = this; final AuthenticatorCallback authenticatorCallback = new AuthenticatorCallback() { @Override - public void postLogin(ReturnCode returnCode, AuthenticationData data, Throwable t) { + public void postLogin(ReturnCode returnCode, final AuthenticationData data, Throwable t) { switch (returnCode) { case NO_ERROR: - postSuccessfulLogin(data); - break; + Gui.asyncExec(new Runnable() { + @Override + public void run() { + postSuccessfulLogin(data); + } + }); + return; case IDENTITY_PROVIDER_ERROR: Gui.showMessageBox(me, "IdP Error", MessageType.ERROR, LOGGER, null); break; @@ -329,10 +337,9 @@ public class LoginWindow extends LoginWindowLayout { LOGGER, t); break; case UNREGISTERED_ERROR: - Gui.showMessageBox(me, - "You are not registered to bwLehrpool. Please visit " - + ShibbolethEcp.getRegistrationUrl() + " and register first.", - MessageType.ERROR, LOGGER, t); + Gui.showMessageBox(me, "You are not registered to bwLehrpool. Please visit " + + ShibbolethEcp.getRegistrationUrl() + " and register first.", MessageType.ERROR, + LOGGER, t); break; case INVALID_URL_ERROR: Gui.showMessageBox(me, "ECP Authenticator says: Invalid URL.", MessageType.ERROR, LOGGER, @@ -343,6 +350,7 @@ public class LoginWindow extends LoginWindowLayout { Gui.showMessageBox(me, "Internal error!", MessageType.ERROR, LOGGER, null); break; } + loginButton.setEnabled(true); } }; @@ -363,20 +371,23 @@ public class LoginWindow extends LoginWindowLayout { return; } - // Execute login - App.waitForInit(); + loginButton.setEnabled(false); final String finalUsername = username; QuickTimer.scheduleOnce(new Task() { @Override public void fire() { + // Execute login + App.waitForInit(); try { authenticator.login(finalUsername, password, authenticatorCallback); + return; } catch (TException e) { ThriftError.showMessage(LoginWindow.this, LOGGER, e, "Anmeldung fehlgeschlagen"); } catch (Exception e) { Gui.showMessageBox(LoginWindow.this, "Anmeldung fehlgeschlagen", MessageType.ERROR, LOGGER, e); } + loginButton.setEnabled(true); } }); } @@ -391,18 +402,19 @@ public class LoginWindow extends LoginWindowLayout { // Update known suggested fingerprints importFingerprints(data.satellites); // now try to init the session with the data received - if (ThriftActions.initSession(data, SwingUtilities.getWindowAncestor(this))) { + if (ThriftActions.initSession(data, forceCustomSatellite, SwingUtilities.getWindowAncestor(this))) { if (saveUsernameCheck.isSelected()) { Config.saveCurrentSession(Session.getSatelliteAddress(), Session.getSatelliteToken(), Session.getMasterToken()); } // Remove the listener for the shift key. (For forcing the satellite selection) - KeyboardFocusManager.getCurrentKeyboardFocusManager() - .removeKeyEventDispatcher(satelliteShiftDispatcher); + KeyboardFocusManager.getCurrentKeyboardFocusManager().removeKeyEventDispatcher( + satelliteShiftDispatcher); dispose(); return; } + loginButton.setEnabled(true); } /** diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/thrift/ThriftActions.java b/dozentenmodul/src/main/java/org/openslx/dozmod/thrift/ThriftActions.java index 5a6f4566..fba3ed2a 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/thrift/ThriftActions.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/thrift/ThriftActions.java @@ -46,7 +46,6 @@ import org.openslx.dozmod.gui.Gui; import org.openslx.dozmod.gui.MainWindow; import org.openslx.dozmod.gui.helper.MessageType; import org.openslx.dozmod.gui.helper.QFileChooser; -import org.openslx.dozmod.gui.window.LoginWindow; import org.openslx.dozmod.gui.window.SatelliteListWindow; import org.openslx.dozmod.thrift.cache.ImageCache; import org.openslx.dozmod.thrift.cache.LectureCache; @@ -69,7 +68,6 @@ public class ThriftActions { private static final long SIZE_CHECK_EXTRA_DL = 50l * 1024l * 1024l; private static final long SIZE_CHECK_EXTRA_UL = 150l * 1024l * 1024l; - /* ******************************************************************************* * * LOGIN @@ -83,10 +81,12 @@ public class ThriftActions { * @param window the parentWindow * @param data AuthenticationData as received from a successful login, or * null if trying to resume a saved sessions - * @param loginWindow + * @param forceCustomSatellite show satellite selection dialog even if there + * is just one + * @param loginWindow * @return true if initialising the session worked, false otherwise */ - public static boolean initSession(AuthenticationData data, Window window) { + public static boolean initSession(AuthenticationData data, boolean forceCustomSatellite, Window window) { Client client = null; WhoamiInfo whoami = null; String address = null; @@ -102,35 +102,23 @@ public class ThriftActions { masterToken = session.masterToken; } else { // after login - if (data.satellites == null || data.satellites.isEmpty()) { - // TODO: Ask for manual IP address entry - Gui.asyncMessageBox( - "Login erfolgreich, aber für die gewählte Einrichtung ist kein Satellit registriert", - MessageType.ERROR, LOGGER, null); - return false; - } - // Satellite sat = data.satellites.get(0); Satellite sat = null; - if (data.satellites.size() == 1 && !LoginWindow.forceCustomSatellite) { + if (data.satellites != null && data.satellites.size() == 1 && !forceCustomSatellite) { sat = data.satellites.get(0); } else { - sat = SatelliteListWindow.open(window , data.satellites); + sat = SatelliteListWindow.open(window, data.satellites); } if (sat == null || sat.addressList == null) { // TODO: Ask for manual IP address entry - Gui.asyncMessageBox( - "Login erfolgreich, aber es wurde kein Satelliten-Server ausgewählt.\n" - + "Vorgang abgebrochen.", - MessageType.ERROR, LOGGER, null); + Gui.asyncMessageBox("Login erfolgreich, aber es wurde kein Satelliten-Server ausgewählt.\n" + + "Vorgang abgebrochen.", MessageType.ERROR, LOGGER, null); return false; } if (sat.addressList.isEmpty()) { // TODO: Ask for manual IP address entry - Gui.asyncMessageBox( - "Login erfolgreich, aber für den ausgewählten Satelliten-Server ist\n" - + "keine Adresse hinterlegt. Kann nicht verbinden.", - MessageType.ERROR, LOGGER, null); + Gui.asyncMessageBox("Login erfolgreich, aber für den ausgewählten Satelliten-Server ist\n" + + "keine Adresse hinterlegt. Kann nicht verbinden.", MessageType.ERROR, LOGGER, null); return false; } address = sat.addressList.get(0); @@ -141,8 +129,15 @@ public class ThriftActions { // try to get a new client client = ThriftManager.getNewSatelliteClient(GraphicalCertHandler.getSslContext(address), address, App.THRIFT_SSL_PORT, App.THRIFT_TIMEOUT_MS); - if (client == null) + if (client == null) { + if (data != null) { + Gui.asyncMessageBox( + "Authentifizierung erfolgreich, die Verbindung zum Satelliten-Server ist jedoch nicht möglich.\n\n" + + "Möglicherweise ist der Server nicht verfügbar, oder die Netzwerkverbindung gestört.", + MessageType.ERROR, null, null); + } return false; + } // check our version long remoteVersion = 0; @@ -169,7 +164,7 @@ public class ThriftActions { Gui.asyncMessageBox( "Authentifizierung erfolgreich, der Satellit verweigert jedoch die Verbindung.\n\n" + "Grund: " + e.number.toString() + " (" + e.message + ")", - MessageType.ERROR, null, null); + MessageType.ERROR, null, null); } return false; } catch (TInvocationException e) { @@ -371,7 +366,7 @@ public class ThriftActions { uploadThread.setDaemon(true); uploadThread.start(); do { // Even more ugly - block the GUI thread so we know whether the - // upload started, and only then switch to the next page + // upload started, and only then switch to the next page Util.sleep(5); } while (uploadTask.getFailCount() == 0 && uploadTask.getTransferCount() == 0 && !uploadTask.isCanceled()); @@ -545,12 +540,12 @@ public class ThriftActions { } try { VmWrapper.wrapVm(destImage, imageName, transInf.getMachineDescription(), - virtualizerId, osId); + virtualizerId, osId, diskImage); } catch (MetaDataMissingException | IOException e) { Gui.asyncMessageBox( "Zur heruntergeladenen VM konnte keine vmx-Datei angelegt werden." + "\nSie können versuchen, das Abbild manuell in den VMWare-Player zu importieren.", - MessageType.WARNING, LOGGER, e); + MessageType.WARNING, LOGGER, e); } } }); diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/util/VmWrapper.java b/dozentenmodul/src/main/java/org/openslx/dozmod/util/VmWrapper.java index 2a192171..37bbbc3d 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/util/VmWrapper.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/util/VmWrapper.java @@ -4,6 +4,7 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.lang.management.ManagementFactory; +import java.nio.charset.StandardCharsets; import javax.management.AttributeNotFoundException; import javax.management.InstanceNotFoundException; @@ -17,6 +18,7 @@ import org.apache.commons.io.FileUtils; import org.apache.log4j.Logger; import org.openslx.bwlp.thrift.iface.OperatingSystem; import org.openslx.dozmod.thrift.cache.MetaDataCache; +import org.openslx.util.vm.DiskImage; import org.openslx.util.vm.VmwareMetaData; public class VmWrapper { @@ -24,19 +26,18 @@ public class VmWrapper { private static final Logger LOGGER = Logger.getLogger(VmWrapper.class); public static void wrapVm(File diskFile, String imageName, byte[] machineDescription, - String virtualizerId, int osId) throws MetaDataMissingException, IOException { + String virtualizerId, int osId, DiskImage diskImageInfo) throws MetaDataMissingException, + IOException { // TODO This is very vmware specific, but should support others too some day if (!diskFile.exists()) throw new FileNotFoundException("Disk file " + diskFile.getAbsolutePath() + " does not exist"); // Handle machine description to generate *.vmx VmwareMetaData vmwareConfig = null; - if (machineDescription == null) { - // TODO: Generate fallback vmx - return; - } else { - vmwareConfig = new VmwareMetaData(MetaDataCache.getOperatingSystems(), machineDescription, - machineDescription.length); + if (machineDescription == null || machineDescription.length < 10) { + machineDescription = getFallbackVmx(diskImageInfo); } + vmwareConfig = new VmwareMetaData(MetaDataCache.getOperatingSystems(), machineDescription, + machineDescription.length); // Append disk & NAT if (!vmwareConfig.addDefaultNat() || !vmwareConfig.addHddTemplate(diskFile.getName(), null, null)) { throw new MetaDataMissingException(); @@ -71,6 +72,12 @@ public class VmWrapper { FileUtils.writeByteArrayToFile(vmxFile, vmwareConfig.getFilteredDefinitionArray()); } + private static byte[] getFallbackVmx(DiskImage diskImageInfo) throws IOException { + String vmx = ResourceLoader.getTextFile("/txt/vmx_template"); + return vmx.replace("%VM_HW_VERSION%", Integer.toString(diskImageInfo.hwVersion)).getBytes( + StandardCharsets.UTF_8); + } + /** * Generates a filename based on the given imageName and with the proper * extension depending on the virtualizer |