blob: 874a2435ee978a8f2c96771e2f1e18b10f2a97fa (
plain) (
tree)
|
|
package org.openslx.dozmod.gui.wizard.page;
import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;
import org.openslx.bwlp.thrift.iface.ImageDetailsRead;
import org.openslx.dozmod.Config;
import org.openslx.dozmod.gui.helper.QFileChooser;
import org.openslx.dozmod.gui.helper.TextChangeListener;
import org.openslx.dozmod.gui.wizard.Wizard;
import org.openslx.dozmod.gui.wizard.layout.ContainerUploadPageLayout;
import org.openslx.dozmod.model.ContainerBuildContextMethod;
import org.openslx.dozmod.model.ContainerDefinition;
import org.openslx.dozmod.model.ContainerMeta;
import org.openslx.dozmod.state.UploadWizardState;
import org.openslx.dozmod.thrift.cache.MetaDataCache;
import org.openslx.util.vm.DockerMetaDataDummy;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.filechooser.FileFilter;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ContainerUploadPage extends ContainerUploadPageLayout {
// TODO: Add a Instruction for the new Container-Feature in bwLehrpool.
// TODO: Add link to instructions for Docker-Intetragtion at https://www.bwlehrpool.de/doku.php
private final Logger LOGGER = Logger.getLogger(ContainerUploadPage.class);
/**
* Page for uploading an imagefile
*
* @param wizard
*/
private final UploadWizardState state;
private final ImageDetailsRead existingImage;
private final ContainerDefinition containerDefinition;
public ContainerUploadPage(Wizard wizard, final UploadWizardState state,
ContainerDefinition containerDefinition) {
super(wizard);
this.containerDefinition = containerDefinition;
this.state = state;
canComeBack = false;
existingImage = null;
// HACK set dummy os
state.selectedOs = MetaDataCache.getOsById(18);
init();
}
// TODO this constructor is currently used in case if user wants do upload a new version.
// This makes no currently no sens in context of docker container and this is used.
public ContainerUploadPage(Wizard wizard, UploadWizardState uploadWizardState,
ImageDetailsRead imageDetailsRead) {
super(wizard);
state = uploadWizardState;
existingImage = imageDetailsRead;
// TODO fix this!
containerDefinition = null;
lblImageName.setEnabled(existingImage == null);
txtImageName.setEnabled(existingImage == null);
txtInfoText.setVisible(existingImage == null);
state.name = imageDetailsRead.imageName;
state.defaultPermissions = imageDetailsRead.getDefaultPermissions();
state.description = imageDetailsRead.getDescription();
state.detectedOs = MetaDataCache.getOsById(imageDetailsRead.getOsId());
state.selectedOs = MetaDataCache.getOsById(imageDetailsRead.getOsId());
state.tags = imageDetailsRead.getTags();
state.defaultPermissions = imageDetailsRead.getUserPermissions();
state.uuid = imageDetailsRead.getImageBaseId();
init();
}
private void init() {
this.txtImageFile.addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent e) {
browseFile();
}
});
this.btnBrowseForImage.addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent e) {
browseFile();
}
});
txtImageName.getDocument().addDocumentListener(new TextChangeListener() {
@Override public void changed() {
reactOnUserInput();
}
});
txtContainerRun.getDocument().addDocumentListener(new TextChangeListener() {
@Override public void changed() {
reactOnUserInput();
}
});
tpInput.addChangeListener(new ChangeListener() {
@Override public void stateChanged(ChangeEvent e) {
reactOnUserInput();
}
});
txtGitRepo.getDocument().addDocumentListener(new TextChangeListener() {
@Override public void changed() {
reactOnUserInput();
}
});
btnBrowseForImage.requestFocus();
}
private void browseFile() {
QFileChooser fc = new QFileChooser(Config.getUploadPath(), false);
fc.setAcceptAllFileFilterUsed(false);
fc.addChoosableFileFilter(new DockerfileFilter());
int action = fc.showOpenDialog(getDialog());
File file = fc.getSelectedFile();
if (action != JFileChooser.APPROVE_OPTION || file == null)
return;
txtImageFile.setText(file.getAbsolutePath());
if (existingImage == null)
txtImageName.setText(file.getParentFile().getName());
else
txtImageName.setText(existingImage.getImageName());
state.descriptionFile = file;
// TESTING: Upload also a prematurely created image (tar)
String imageName = file.getParentFile().getName();
File imageTarFile = new File(file.getParentFile(), imageName.concat(".tar"));
if (imageTarFile.exists()) {
LOGGER.info("Upload also an created Image");
state.diskFile = imageTarFile;
} else {
state.diskFile = getDummyFile();
}
Config.setUploadPath(file.getParent());
reactOnUserInput();
}
private File getDummyFile() {
String configDir = Config.getPath();
File zeroFile = new File(configDir, "ZERO-FILE");
// create a temp file with dummy content,
// because vmchooser relies on an existing image after choosing a lecture.
// TODO change behavior in vmchooser to allow start lectures without images.
try {
if (!zeroFile.exists()) {
zeroFile.createNewFile();
FileUtils.writeStringToFile(zeroFile, "ZERO\n", "UTF-8");
}
} catch (IOException e) {
e.printStackTrace();
LOGGER.error("Could not create a dummy file.", e);
}
LOGGER.info("Use dummy file");
return zeroFile;
}
private void reactOnUserInput() {
boolean completed = checkUserInput();
if (completed)
setDescription("Container definition finished");
setPageComplete(completed);
}
private boolean checkUserInput() {
ContainerBuildContextMethod method = getBuildContextMethod();
switch (method) {
case FILE:
if (txtImageFile.getText() == null || txtImageFile.getText().isEmpty()) {
setWarningMessage("No Container Recipe provided!");
return false;
}
break;
case GIT_REPOSITORY:
if (txtGitRepo.getText() == null || txtGitRepo.getText().isEmpty()) {
setWarningMessage("No Git Repository provided!");
return false;
}
break;
}
if (txtImageName.getText() == null || txtImageName.getText().isEmpty()) {
setWarningMessage("Set proper Image Name");
return false;
}
if (txtContainerRun.getText() == null || txtContainerRun.getText().isEmpty()) {
setWarningMessage("set container run options");
return false;
}
return true;
}
private DockerMetaDataDummy createVmMeta() {
ContainerMeta containerMeta = containerDefinition.getContainerMeta();
containerMeta.setBuildContextMethod(getBuildContextMethod().ordinal());
containerMeta.setImageName(txtImageName.getText());
containerMeta.setRunOptions(txtContainerRun.getText());
switch (containerDefinition.getBuildContextMethod()) {
case FILE:
containerDefinition.setContainerRecipe(state.descriptionFile);
break;
case GIT_REPOSITORY:
containerMeta.setBuildContextUrl(txtGitRepo.getText());
state.diskFile = getDummyFile();
state.descriptionFile = getDummyFile();
break;
}
return containerDefinition.createVmMeta();
}
@Override protected boolean wantNextOrFinish() {
state.name = existingImage != null ? existingImage.getImageName() : txtImageName.getText();
state.meta = createVmMeta();
return true;
}
private static class DockerfileFilter extends FileFilter {
@Override public boolean accept(File f) {
Pattern p = Pattern.compile("[Dd]ockerfile");
Matcher m = p.matcher(f.getName());
boolean accept = false;
if (f.isFile() && m.matches())
accept = true;
return accept;
}
@Override public String getDescription() {
return "Dockerfile";
}
}
}
|