summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dozentenmodul/src/main/java/org/openslx/dozmod/gui/panel/ContainerPanel.java85
-rw-r--r--dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/ImageDetailsWindow.java1
-rw-r--r--dozentenmodul/src/main/java/org/openslx/dozmod/gui/wizard/ImageCreationWizard.java1
-rw-r--r--dozentenmodul/src/main/java/org/openslx/dozmod/gui/wizard/layout/ContainerUploadPageLayout.java127
-rw-r--r--dozentenmodul/src/main/java/org/openslx/dozmod/gui/wizard/layout/ImageTypePageLayout.java19
-rw-r--r--dozentenmodul/src/main/java/org/openslx/dozmod/gui/wizard/page/ContainerUploadPage.java142
-rw-r--r--dozentenmodul/src/main/java/org/openslx/dozmod/gui/wizard/page/ImageTypePage.java12
-rw-r--r--dozentenmodul/src/main/java/org/openslx/dozmod/model/ContainerDefinition.java26
-rw-r--r--dozentenmodul/src/main/java/org/openslx/dozmod/util/ContainerUtils.java141
-rw-r--r--dozentenmodul/src/main/java/org/openslx/dozmod/util/ContainerWrapper.java79
-rw-r--r--dozentenmodul/src/main/java/org/openslx/dozmod/util/ImageWrapper.java25
-rw-r--r--dozentenmodul/src/main/properties/i18n/page.properties1
-rw-r--r--dozentenmodul/src/main/properties/i18n/page_de_DE.properties3
-rw-r--r--dozentenmodul/src/main/properties/i18n/page_layout.properties11
-rw-r--r--dozentenmodul/src/main/properties/i18n/page_layout_de_DE.properties13
-rw-r--r--dozentenmodul/src/main/properties/i18n/panel.properties2
-rw-r--r--dozentenmodul/src/main/properties/i18n/panel_de_DE.properties2
-rw-r--r--dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbImage.java2
-rw-r--r--dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/web/WebServer.java44
19 files changed, 495 insertions, 241 deletions
diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/panel/ContainerPanel.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/panel/ContainerPanel.java
index 1cb861ee..42a50418 100644
--- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/panel/ContainerPanel.java
+++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/panel/ContainerPanel.java
@@ -26,7 +26,7 @@ public class ContainerPanel extends JPanel {
*/
private static final long serialVersionUID = -3335320345960410582L;
- // TODO Set the height of txtContainerRecipe to a proper Value
+ // TODO Set the height of txtContainerRecipe to a proper Value
public static final String IMAGE_CONTEXT = "IMAGE";
public static final String CONTAINER_CONTEXT = "CONTAINER";
@@ -53,19 +53,15 @@ public class ContainerPanel extends JPanel {
pnlContainerMeta = new JPanel();
GridManager grdContainerMeta = new GridManager(pnlContainerMeta, 3);
- QLabel lblContainerRunOpt = new QLabel(
- I18n.PANEL.getString("ContainerPanel.ContainerStartOptions.label"));
- lblContainerRunOpt.setToolTipText(
- I18n.PANEL.getString("ContainerPanel.ContainerStartOptions.tooltip"));
+ QLabel lblContainerRunOpt = new QLabel(I18n.PANEL.getString("ContainerPanel.ContainerStartOptions.label"));
+ lblContainerRunOpt.setToolTipText(I18n.PANEL.getString("ContainerPanel.ContainerStartOptions.tooltip"));
txtContainerRun = new JTextField();
grdContainerMeta.add(lblContainerRunOpt);
grdContainerMeta.add(txtContainerRun, 2).fill(true, false).expand(true, false);
grdContainerMeta.nextRow();
- QLabel lblContainerRunCommand = new QLabel(
- I18n.PANEL.getString("ContainerPanel.ContainerRunCommand.label"));
- lblContainerRunCommand.setToolTipText(
- I18n.PANEL.getString("ContainerPanel.ContainerRunCommand.tooltip"));
+ QLabel lblContainerRunCommand = new QLabel(I18n.PANEL.getString("ContainerPanel.ContainerRunCommand.label"));
+ lblContainerRunCommand.setToolTipText(I18n.PANEL.getString("ContainerPanel.ContainerRunCommand.tooltip"));
txtContainerRunCommand = new JTextField();
grdContainerMeta.add(lblContainerRunCommand);
grdContainerMeta.add(txtContainerRunCommand, 2).fill(true, false).expand(true, false);
@@ -77,8 +73,7 @@ public class ContainerPanel extends JPanel {
GridManager grdContainer = new GridManager(this, 2, false, new Insets(8, 2, 8, 2));
- QLabel lblContainerImageName = new QLabel(
- I18n.PANEL.getString("ContainerPanel.Label.ImageName.text"));
+ QLabel lblContainerImageName = new QLabel(I18n.PANEL.getString("ContainerPanel.Label.ImageName.text"));
grdContainer.add(lblContainerImageName);
txtContainerImageName = new JTextField();
grdContainer.add(txtContainerImageName, 1).fill(true, false).expand(true, false);
@@ -90,8 +85,7 @@ public class ContainerPanel extends JPanel {
scrollableTextArea.setPreferredSize(Gui.getScaledDimension(0, 200));
grdContainer.add(scrollableTextArea, 2).fill(true, true).expand(true, true);
- lblContainerImageType = new QLabel(
- I18n.PANEL.getString("ContainerPanel.Label.ContainerImageType.text"));
+ lblContainerImageType = new QLabel(I18n.PANEL.getString("ContainerPanel.Label.ContainerImageType.text"));
cboContainerImageType = ContainerPanel.createContainerImageTypeCBO();
grdContainer.add(lblContainerImageType);
grdContainer.add(cboContainerImageType).fill(true, false).expand(true, false);
@@ -102,39 +96,44 @@ public class ContainerPanel extends JPanel {
}
/**
- * Retrieves Container specific details for the currently displayed lecture and disables gui elements for
- * the specific context.
+ * Retrieves Container specific details for the currently displayed lecture and
+ * disables gui elements for the specific context.
*
- * @param satelliteToken The satelliteToken from which the information are retrieved.
- * @param image The ImageDetailsRead which has general information about Image (name, type, version, etc.)
+ * @param satelliteToken The satelliteToken from which the information are
+ * retrieved.
+ * @param image The ImageDetailsRead which has general information
+ * about Image (name, type, version, etc.)
* @param context In which context this Panel ist used (Image or Lecture)
*/
public void init(String satelliteToken, ImageDetailsRead image, String context) {
try {
byte[] rawVirtConfig;
- ByteBuffer byteBuffer = ThriftManager.getSatClient()
- .getImageVersionVirtConfig(satelliteToken, image.getLatestVersionId());
+ ByteBuffer byteBuffer = ThriftManager.getSatClient().getImageVersionVirtConfig(satelliteToken,
+ image.getLatestVersionId());
rawVirtConfig = ThriftUtil.unwrapByteBuffer(byteBuffer);
containerDefinition = ContainerDefinition.fromByteArray(rawVirtConfig);
} catch (TException e) {
- LOGGER.error("Failed to retrieve virtualizer config for image version " + "'"
- + image.getLatestVersionId() + ", see trace: ", e);
+ LOGGER.error("Failed to retrieve virtualizer config for image version " + "'" + image.getLatestVersionId()
+ + ", see trace: ", e);
}
txtContainerImageName.setText(image.imageName);
txtContainerImageName.setEnabled(false);
// TODO simplify this mess. ContainerBuildContextMethod is to complex or useless
- switch (containerDefinition.getBuildContextMethod()) {
- case FILE:
+ switch (containerDefinition.getContainerImageContext()) {
+ case DOCKERFILE:
txtContainerRecipe.setText(containerDefinition.getContainerRecipe());
break;
- case IMAGE_REPO:
+ case IMAGE_REPOSITORY:
txtContainerRecipe.setText(containerDefinition.getContainerMeta().getImageRepo());
break;
case GIT_REPOSITORY:
txtContainerRecipe.setText(containerDefinition.getContainerMeta().getBuildContextUrl());
break;
+ case DOCKER_ARCHIVE:
+ txtContainerRecipe.setText(containerDefinition.getContainerMeta().getImageName());
+ break;
default:
LOGGER.error("Unknown Build Context");
break;
@@ -153,17 +152,22 @@ public class ContainerPanel extends JPanel {
private void initImageDetails() {
+ // TODO currently no support for different containerImageType
+ lblContainerImageType.setVisible(false);
+ cboContainerImageType.setEditable(false);
+ cboContainerImageType.setVisible(false);
+
cboContainerImageType.setSelectedItem(containerDefinition.getContainerMeta().getImageType());
if (containerDefinition.getContainerMeta().getImageType() == ContainerMeta.ContainerImageType.DATA) {
- // do not allowed to change type if it is data
+ // do not allow changing type if it is data
cboContainerImageType.setEnabled(false);
- }
- else {
- // do not allow to switch type to data after creation
+ } else {
+ // do not allow switching type to data after creation
cboContainerImageType.removeItem(ContainerMeta.ContainerImageType.DATA);
}
- // currently do not allow user to change the Image Repository or Dockerfile in the suite.
+ // currently, do not allow user to change the Image Repository or Dockerfile in
+ // the suite.
txtContainerRecipe.setEnabled(false);
// do not show container specific input options
@@ -184,9 +188,8 @@ public class ContainerPanel extends JPanel {
public void addToChangeMonitor(DialogChangeMonitor changeMonitor) {
if (isFirstTime) {
- changeMonitor.add(txtContainerRecipe)
- .addConstraint(new DialogChangeMonitor.TextNotEmptyConstraint(
- I18n.PANEL.getString("ContainerPanel.Constraint.NoEmptyDockerfile.text")));
+ changeMonitor.add(txtContainerRecipe).addConstraint(new DialogChangeMonitor.TextNotEmptyConstraint(
+ I18n.PANEL.getString("ContainerPanel.Constraint.NoEmptyDockerfile.text")));
changeMonitor.add(txtContainerRun);
changeMonitor.add(txtContainerRunCommand);
changeMonitor.add(bindMountConfigurator);
@@ -200,7 +203,8 @@ public class ContainerPanel extends JPanel {
*
* @param satelliteToken for current session to communicate with Sat.
* @param image of the image version, which will be updated.
- * @return Returns true uf upload successfully finished, false if error occurred.
+ * @return Returns true uf upload successfully finished, false if error
+ * occurred.
*/
public boolean saveChanges(String satelliteToken, ImageDetailsRead image) {
@@ -216,9 +220,8 @@ public class ContainerPanel extends JPanel {
if (!newConDev.equals(containerDefinition)) {
LOGGER.info("Update Container Definition");
try {
- ThriftManager.getSatClient()
- .setImageVersionVirtConfig(satelliteToken, image.getLatestVersionId(),
- newConDev.toByteBuffer());
+ ThriftManager.getSatClient().setImageVersionVirtConfig(satelliteToken, image.getLatestVersionId(),
+ newConDev.toByteBuffer());
} catch (TException e) {
LOGGER.error("Upload new ContainerDefinition failed", e);
return false;
@@ -227,17 +230,18 @@ public class ContainerPanel extends JPanel {
return true;
}
- public static ComboBox<ContainerMeta.ContainerImageType> createContainerImageTypeCBO (){
+ public static ComboBox<ContainerMeta.ContainerImageType> createContainerImageTypeCBO() {
ComboBox<ContainerMeta.ContainerImageType> cbo = new ComboBox<>(
new ComboBox.ComboBoxRenderer<ContainerMeta.ContainerImageType>() {
- @Override public String renderItem(ContainerMeta.ContainerImageType item) {
- switch (item){
+ @Override
+ public String renderItem(ContainerMeta.ContainerImageType item) {
+ switch (item) {
case LECTURE:
return "Pool";
case BATCH:
return "Pool/Cluster";
case DATA:
- return "Daten";
+ return I18n.PANEL.getString("ContainerPanel.ContainerImageType.Item.label");
default:
return "";
}
@@ -250,4 +254,3 @@ public class ContainerPanel extends JPanel {
return cbo;
}
}
-
diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/ImageDetailsWindow.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/ImageDetailsWindow.java
index 3fc632b8..8d31798f 100644
--- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/ImageDetailsWindow.java
+++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/ImageDetailsWindow.java
@@ -827,7 +827,6 @@ public class ImageDetailsWindow extends ImageDetailsWindowLayout
showContainerTab();
// TODO Currently, do not allow user to upload a new version or share an Container Image.
- btnUpdateImage.setEnabled(false);
btnUploadToMaster.setEnabled(false);
}
}
diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/wizard/ImageCreationWizard.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/wizard/ImageCreationWizard.java
index 33ed8800..885e40f7 100644
--- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/wizard/ImageCreationWizard.java
+++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/wizard/ImageCreationWizard.java
@@ -108,6 +108,7 @@ public class ImageCreationWizard extends Wizard implements UiFeedback, QuitNotif
@Override public boolean wantFinish() {
+ // TODO copy/paste from ContainerUploadPage.wantNextOrFinish()
// In order for settings for a container to be recorded in the ImageMetaDataPage for the ContainerDefinition,
// the UploadInitiator was only allowed to be created here.
// TODO maybe also for VM-Images this is suitable
diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/wizard/layout/ContainerUploadPageLayout.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/wizard/layout/ContainerUploadPageLayout.java
index b0201e47..2bc4c768 100644
--- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/wizard/layout/ContainerUploadPageLayout.java
+++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/wizard/layout/ContainerUploadPageLayout.java
@@ -5,7 +5,7 @@ import org.openslx.dozmod.gui.helper.GridManager;
import org.openslx.dozmod.gui.helper.I18n;
import org.openslx.dozmod.gui.wizard.Wizard;
import org.openslx.dozmod.gui.wizard.WizardPage;
-import org.openslx.virtualization.configuration.container.ContainerBuildContextMethod;
+import org.openslx.virtualization.configuration.container.ContainerImageContext;
import javax.swing.*;
import java.awt.*;
@@ -29,7 +29,8 @@ public class ContainerUploadPageLayout extends WizardPage {
protected final JTabbedPane tpInput;
protected final JTextField txtGitRepo;
- protected final JTextField txtContainerImageFile;
+ protected final JTextField txtImageTar;
+ protected final JButton btnBrowseImageTar;
/**
* Constructor to define the Layout
@@ -39,75 +40,97 @@ public class ContainerUploadPageLayout extends WizardPage {
super(wizard, I18n.PAGE_LAYOUT.getString("ContainerUploadPage.title"));
setDescription(I18n.PAGE_LAYOUT.getString("ContainerUploadPage.description"));
GridManager grid = new GridManager(this, 3, false);
+ GridManager tmpGrid;
- JPanel imageRepoPanel = new JPanel();
- imageRepoPanel.setVisible(true);
- GridManager tmpGrid = new GridManager(imageRepoPanel, 2, true, new Insets(0, 5, 0, 5));
- QLabel lblImageRepo = new QLabel(I18n.PAGE_LAYOUT.getString("ContainerUploadPage.ImageRepo.label"));
- lblImageRepo.setToolTipText(
- I18n.PAGE_LAYOUT.getString("ContainerUploadPage.ImageRepository.ToolTipText"));
- txtImageRepo = new JTextField();
- txtImageRepo.setEditable(true);
- txtImageRepo.setToolTipText(
- I18n.PAGE_LAYOUT.getString("ContainerUploadPage.ImageRepository.ToolTipText"));
- tmpGrid.add(lblImageRepo);
- tmpGrid.add(txtImageRepo).fill(true, false).expand(true, false);
- tmpGrid.finish(false);
-
- JPanel p1 = new JPanel();
- p1.setVisible(false);
- GridManager g1 = new GridManager(p1, 3, true, new Insets(0, 5, 0, 5));
+ // ####################################
+ // Dockerfile Input Panel -- UNUSED --
+ JPanel pnlDockerfileInput = new ContainerTabPanel(ContainerImageContext.DOCKERFILE);
+ pnlDockerfileInput.setVisible(false);
+ tmpGrid = new GridManager(pnlDockerfileInput, 3, true, new Insets(0, 5, 0, 5));
QLabel imageFileCaption = new QLabel(
I18n.PAGE_LAYOUT.getString("ContainerUploadPage.DockerFile.label"));
txtImageFile = new JTextField();
txtImageFile.setEditable(false);
btnBrowseForImage = new JButton(I18n.PAGE_LAYOUT.getString("ImageUpload.Button.browseForImage.text"));
btnBrowseForImage.setMnemonic(KeyEvent.VK_B);
- g1.add(imageFileCaption);
- g1.add(txtImageFile).fill(true, false).expand(true, false);
- g1.add(btnBrowseForImage);
- g1.finish(false);
-
- JPanel p2 = new JPanel();
- p2.setVisible(false);
- GridManager g2 = new GridManager(p2, 2, true, new Insets(0, 5, 0, 5));
+ tmpGrid.add(imageFileCaption);
+ tmpGrid.add(txtImageFile).fill(true, false).expand(true, false);
+ tmpGrid.add(btnBrowseForImage);
+ tmpGrid.finish(false);
+
+ // ####################################
+ // Git Repository Input Panel -- UNUSED --
+ JPanel pnlGitRepositoryInput = new ContainerTabPanel(ContainerImageContext.GIT_REPOSITORY);
+ pnlGitRepositoryInput.setVisible(false);
+ tmpGrid = new GridManager(pnlGitRepositoryInput, 2, true, new Insets(0, 5, 0, 5));
QLabel lblGitRepo = new QLabel(I18n.PAGE_LAYOUT.getString("ContainerUploadPage.GitRepository.label"));
lblGitRepo.setToolTipText(
I18n.PAGE_LAYOUT.getString("ContainerUploadPage.GitRepository.toolTipText"));
txtGitRepo = new JTextField();
txtGitRepo.setToolTipText(
I18n.PAGE_LAYOUT.getString("ContainerUploadPage.GitRepository.toolTipText"));
- g2.add(lblGitRepo);
- g2.add(txtGitRepo).fill(true, false).expand(true, false);
- g2.finish(false);
+ tmpGrid.add(lblGitRepo);
+ tmpGrid.add(txtGitRepo).fill(true, false).expand(true, false);
+ tmpGrid.finish(false);
+
+ // ####################################
+ // Container Archive Input Panel
+ JPanel pnlContainerImage = new ContainerTabPanel(ContainerImageContext.DOCKER_ARCHIVE);
+ pnlGitRepositoryInput.setVisible(false);
+ tmpGrid = new GridManager(pnlContainerImage, 3, true, new Insets(0, 5, 0, 5));
+
+ QLabel lblImageTarFile = new QLabel(
+ I18n.PAGE_LAYOUT.getString("ContainerUploadPage.ContainerImageFile.label"));
+ lblImageTarFile.setToolTipText(
+ I18n.PAGE_LAYOUT.getString("ContainerUploadPage.ContainerImageFile.ToolTipText"));
+
+ txtImageTar = new JTextField();
+ txtImageTar.setEnabled(false);
+ btnBrowseImageTar = new JButton(I18n.PAGE_LAYOUT.getString("ImageUpload.Button.browseForImage.text"));
+ btnBrowseImageTar.setMnemonic(KeyEvent.VK_B);
+ tmpGrid.add(lblImageTarFile);
+ tmpGrid.add(txtImageTar).fill(true, false).expand(true, false);
+ tmpGrid.add(btnBrowseImageTar);
+ tmpGrid.finish(false);
+ // ####################################
+ // Image Repository Input Panel
+ JPanel pnlImageRepo = new ContainerTabPanel(ContainerImageContext.IMAGE_REPOSITORY);
+ pnlImageRepo.setVisible(true);
+ tmpGrid = new GridManager(pnlImageRepo, 2, true, new Insets(0, 5, 0, 5));
+ QLabel lblImageRepo = new QLabel(I18n.PAGE_LAYOUT.getString("ContainerUploadPage.ImageRepo.label"));
+ lblImageRepo.setToolTipText(
+ I18n.PAGE_LAYOUT.getString("ContainerUploadPage.ImageRepository.ToolTipText"));
+ txtImageRepo = new JTextField();
+ txtImageRepo.setEditable(true);
+ txtImageRepo.setToolTipText(
+ I18n.PAGE_LAYOUT.getString("ContainerUploadPage.ImageRepository.ToolTipText"));
+ tmpGrid.add(lblImageRepo);
+ tmpGrid.add(txtImageRepo).fill(true, false).expand(true, false);
+ tmpGrid.finish(false);
+
+ // ####################################
+ // Tabbed Input Pane
tpInput = new JTabbedPane();
- tpInput.addTab("Dockerfile", p1);
- tpInput.addTab("Git-Repository", p2);
- tpInput.addTab("Image-Repository", imageRepoPanel);
+ // TODO we need first a proper backend in bwlp-sat to build container
+ //tpInput.addTab("Dockerfile", pnlDockerfileInput);
+ //tpInput.addTab("Git-Repository", pnlGitRepositoryInput);
+ tpInput.addTab("Docker-Archive", pnlContainerImage);
+ tpInput.addTab("Image-Repository", pnlImageRepo);
tpInput.setSelectedIndex(0);
-
grid.add(tpInput, 3).fill(true, false);
grid.nextRow();
+ // ####################################
+ // Image Name
lblImageName = new QLabel(I18n.PANEL.getString("ContainerPanel.Label.ImageName.text"));
txtImageName = new JTextField();
grid.add(lblImageName);
grid.add(txtImageName, 2, 1).fill(true, false).expand(true, false);
grid.nextRow();
- QLabel lblContainerImageFile = new QLabel(
- I18n.PAGE_LAYOUT.getString("ContainerUploadPage.ContainerImageFile.label"));
- lblContainerImageFile.setToolTipText(
- I18n.PAGE_LAYOUT.getString("ContainerUploadPage.ContainerImageFile.ToolTipText"));
- txtContainerImageFile = new JTextField();
- txtContainerImageFile.setEnabled(false);
- txtContainerImageFile.setToolTipText(
- I18n.PAGE_LAYOUT.getString("ContainerUploadPage.ContainerImageFile.ToolTipText"));
- grid.add(lblContainerImageFile);
- grid.add(txtContainerImageFile, 2).fill(true, false).expand(true, false);
- grid.nextRow();
-
+ // ####################################
+ // Info Box
grid.add(Box.createVerticalGlue(), 3).expand(true, true);
txtInfoText = new JTextArea();
txtInfoText.setBorder(BorderFactory.createTitledBorder(
@@ -125,7 +148,15 @@ public class ContainerUploadPageLayout extends WizardPage {
grid.finish(true);
}
- protected ContainerBuildContextMethod getBuildContextMethod() {
- return ContainerBuildContextMethod.fromInt(tpInput.getSelectedIndex());
+ protected ContainerImageContext getCurrentContext() {
+ return ((ContainerTabPanel) tpInput.getSelectedComponent()).containerImageContext;
+ }
+
+ static class ContainerTabPanel extends JPanel {
+ public final ContainerImageContext containerImageContext;
+
+ ContainerTabPanel(ContainerImageContext imageContext) {
+ this.containerImageContext = imageContext;
+ }
}
}
diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/wizard/layout/ImageTypePageLayout.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/wizard/layout/ImageTypePageLayout.java
index 8999e880..d858882a 100644
--- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/wizard/layout/ImageTypePageLayout.java
+++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/wizard/layout/ImageTypePageLayout.java
@@ -15,8 +15,9 @@ public abstract class ImageTypePageLayout extends WizardPage {
private static final long serialVersionUID = 2548125409461846482L;
protected final JTextArea txtInfoText;
- protected final JButton btnNewVmImage;
- protected final JButton btnNewDockerImage;
+ protected final JRadioButton rbtnNewVmImage;
+ protected final JRadioButton rbtnNewDockerImage;
+ protected final ButtonGroup btgrpImageTyp;
/**
* Page to choose between new VM-Image or Docker Image
@@ -40,12 +41,14 @@ public abstract class ImageTypePageLayout extends WizardPage {
grid.nextRow();
grid.nextRow();
- // -- New VM Pick--
- btnNewVmImage = new JButton(I18n.PAGE_LAYOUT.getString("ImageTypePageLayout.button.newVM"));
- grid.add(btnNewVmImage, 2, 2).fill(true, true).expand(true, true);
- // -- New Docker-Image Pick--
- btnNewDockerImage = new JButton(I18n.PAGE_LAYOUT.getString("ImageTypePageLayout.button.newDocker"));
- grid.add(btnNewDockerImage, 2, 2).fill(true, true).expand(true, true);
+ rbtnNewVmImage = new JRadioButton(I18n.PAGE_LAYOUT.getString("ImageTypePageLayout.button.newVM"));
+ grid.add(rbtnNewVmImage, 2, 2).fill(true, true).expand(true, true);
+ rbtnNewDockerImage = new JRadioButton(I18n.PAGE_LAYOUT.getString("ImageTypePageLayout.button.newDocker"));
+ grid.add(rbtnNewDockerImage, 2, 2).fill(true, true).expand(true, true);
+
+ btgrpImageTyp = new ButtonGroup();
+ btgrpImageTyp.add(rbtnNewVmImage);
+ btgrpImageTyp.add(rbtnNewDockerImage);
grid.finish(false);
diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/wizard/page/ContainerUploadPage.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/wizard/page/ContainerUploadPage.java
index b21564a6..283019b6 100644
--- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/wizard/page/ContainerUploadPage.java
+++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/wizard/page/ContainerUploadPage.java
@@ -4,18 +4,19 @@ 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.Gui;
import org.openslx.dozmod.gui.helper.I18n;
+import org.openslx.dozmod.gui.helper.MessageType;
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.ContainerDefinition;
import org.openslx.dozmod.state.UploadWizardState;
-import org.openslx.dozmod.thrift.ThriftActions;
+import org.openslx.dozmod.thrift.*;
import org.openslx.dozmod.thrift.cache.MetaDataCache;
+import org.openslx.dozmod.util.ContainerUtils;
import org.openslx.virtualization.configuration.VirtualizationConfigurationDocker;
-import org.openslx.virtualization.configuration.container.ContainerBuildContextMethod;
-import org.openslx.virtualization.configuration.container.ContainerMeta;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
@@ -23,10 +24,9 @@ import javax.swing.event.ChangeListener;
import javax.swing.filechooser.FileFilter;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
-import java.awt.event.MouseEvent;
-import java.awt.event.MouseListener;
import java.io.File;
import java.io.IOException;
+import java.nio.ByteBuffer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -65,8 +65,7 @@ public class ContainerUploadPage extends ContainerUploadPageLayout {
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.
+ // This constructor is used in case the user wants do upload a new version.
public ContainerUploadPage(Wizard wizard, UploadWizardState uploadWizardState,
ImageDetailsRead imageDetailsRead) {
super(wizard);
@@ -74,13 +73,16 @@ public class ContainerUploadPage extends ContainerUploadPageLayout {
state = uploadWizardState;
existingImage = imageDetailsRead;
- // TODO fix this!
- containerDefinition = null;
+ containerDefinition = ContainerUtils.getContainerDefinition(
+ Session.getSatelliteToken(),
+ imageDetailsRead.getLatestVersionId());
lblImageName.setEnabled(existingImage == null);
txtImageName.setEnabled(existingImage == null);
+ txtImageName.setText(existingImage.getImageName());
txtInfoText.setVisible(existingImage == null);
+
state.name = imageDetailsRead.imageName;
state.defaultPermissions = imageDetailsRead.getDefaultPermissions();
state.description = imageDetailsRead.getDescription();
@@ -129,45 +131,37 @@ public class ContainerUploadPage extends ContainerUploadPageLayout {
}
});
- txtContainerImageFile.addMouseListener(new MouseListener() {
- @Override public void mouseClicked(MouseEvent e) {
- if (e.getClickCount() >= 2)
- browseContainerImageFile();
- }
-
- @Override public void mousePressed(MouseEvent e) {
-
- }
-
- @Override public void mouseReleased(MouseEvent e) {
-
- }
-
- @Override public void mouseEntered(MouseEvent e) {
-
+ this.btnBrowseImageTar.addActionListener(new ActionListener() {
+ @Override public void actionPerformed(ActionEvent e) {
+ browseImageTarFile();
}
+ });
- @Override public void mouseExited(MouseEvent e) {
-
+ this.txtImageTar.addActionListener(new ActionListener() {
+ @Override public void actionPerformed(ActionEvent e) {
+ browseImageTarFile();
}
});
btnBrowseForImage.requestFocus();
}
- private void browseContainerImageFile() {
+ private void browseImageTarFile() {
QFileChooser fc = new QFileChooser(Config.getUploadPath(), false);
fc.setAcceptAllFileFilterUsed(false);
fc.addChoosableFileFilter(new ContainerImageFileFiler());
int action = fc.showOpenDialog(getDialog());
File file = fc.getSelectedFile();
- if (action != JFileChooser.APPROVE_OPTION || file == null) {
- txtContainerImageFile.setText("");
+
+ if (action != JFileChooser.APPROVE_OPTION || file == null || !ContainerUtils.isValidTar(file)) {
+ txtImageTar.setText("");
return;
}
- txtContainerImageFile.setText(file.getAbsolutePath());
+ txtImageTar.setText(file.getAbsolutePath());
+ Config.setUploadPath(file.getParent());
+ reactOnUserInput();
LOGGER.info("Tar File selected");
}
@@ -191,13 +185,6 @@ public class ContainerUploadPage extends ContainerUploadPageLayout {
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()) {
- txtContainerImageFile.setText(imageTarFile.getAbsolutePath());
- LOGGER.info("Prebuild Container Image found");
- }
Config.setUploadPath(file.getParent());
reactOnUserInput();
@@ -230,21 +217,20 @@ public class ContainerUploadPage extends ContainerUploadPageLayout {
}
private boolean checkUserInput() {
- ContainerBuildContextMethod method = getBuildContextMethod();
- switch (method) {
- case IMAGE_REPO:
+ switch (getCurrentContext()) {
+ case IMAGE_REPOSITORY:
if (txtImageRepo.getText() == null || txtImageRepo.getText().isEmpty()) {
setWarningMessage(I18n.PAGE.getString("ContainerUploadPage.Warning.NoImageRepo"));
return false;
}
break;
- case FILE:
+ case DOCKERFILE:
if (txtImageFile.getText() == null || txtImageFile.getText().isEmpty()) {
setWarningMessage(I18n.PAGE.getString("ContainerUploadPage.Warning.NoReceipt"));
return false;
}
- if (! ContainerDefinition.isValidDockerfile(txtImageFile.getText())) {
+ if (!ContainerDefinition.isValidDockerfile(txtImageFile.getText())) {
setWarningMessage(I18n.PAGE.getString("ContainerUploadPage.Warning.NoValidDockerfiler"));
return false;
}
@@ -255,6 +241,16 @@ public class ContainerUploadPage extends ContainerUploadPageLayout {
return false;
}
break;
+ case DOCKER_ARCHIVE:
+ if (txtImageTar.getText() == null || txtImageTar.getText().isEmpty()) {
+ setWarningMessage(I18n.PAGE.getString("ContainerUploadPage.Warning.NoDockerArchive"));
+ return false;
+ }
+ break;
+
+ default:
+ // The case is not provided
+ return false;
}
if (txtImageName.getText() == null || txtImageName.getText().isEmpty()) {
@@ -266,27 +262,26 @@ public class ContainerUploadPage extends ContainerUploadPageLayout {
private VirtualizationConfigurationDocker createVirtualizationConfig() {
- ContainerMeta containerMeta = containerDefinition.getContainerMeta();
- containerMeta.setBuildContextMethod(getBuildContextMethod().ordinal());
- containerMeta.setImageName(txtImageName.getText());
+ containerDefinition.getContainerMeta().setContainerImageContext(getCurrentContext().ordinal());
+ containerDefinition.getContainerMeta().setImageName(txtImageName.getText());
- File containerImageFile = new File(txtContainerImageFile.getText());
- if (containerImageFile.exists())
- state.diskFile = containerImageFile;
- else
- state.diskFile = getDummyFile();
-
- switch (containerDefinition.getBuildContextMethod()) {
- case FILE:
+ switch (containerDefinition.getContainerImageContext()) {
+ case DOCKERFILE:
containerDefinition.setContainerRecipe(state.descriptionFile);
+ state.diskFile = getDummyFile();
break;
- case IMAGE_REPO:
- containerMeta.setImageRepo(txtImageRepo.getText());
+ case IMAGE_REPOSITORY:
+ containerDefinition.getContainerMeta().setImageRepo(txtImageRepo.getText());
+ state.diskFile = getDummyFile();
state.descriptionFile = getDummyFile();
case GIT_REPOSITORY:
- containerMeta.setBuildContextUrl(txtGitRepo.getText());
+ containerDefinition.getContainerMeta().setBuildContextUrl(txtGitRepo.getText());
+ state.diskFile = getDummyFile();
state.descriptionFile = getDummyFile();
break;
+ case DOCKER_ARCHIVE:
+ state.diskFile = new File(txtImageTar.getText());
+ state.descriptionFile = getDummyFile();
}
return containerDefinition.createVirtualizationConfig();
}
@@ -321,6 +316,29 @@ public class ContainerUploadPage extends ContainerUploadPageLayout {
state.uuid = existingImage.getImageBaseId();
state.name = existingImage.getImageName();
}
+
+ // TODO copy/paste from ImageCreationWizard.wantFinish()
+ // Do this only if the user wants to upload a new image version!
+ if (existingImage != null) {
+ // Create upload initiator that will manage requesting a token, hashing the
+ // file, connecting for upload...
+ if (state.upload == null) {
+ try {
+ state.upload = new UploadInitiator(state.uuid, state.diskFile,
+ ByteBuffer.wrap(state.virtualizationConfig.getConfigurationAsByteArray()));
+ } catch (WrappedException e) {
+ ThriftError.showMessage(this, LOGGER, e.exception, e.displayMessage);
+ return false;
+ } catch (IOException e) {
+ Gui.showMessageBox(this,
+ I18n.PAGE.getString("ImageUpload.Message.error.uploadInitiatorFailed"),
+ MessageType.ERROR, LOGGER, e);
+ return false;
+ }
+ }
+ // Start the hash check now
+ state.upload.startHashing();
+ }
return true;
}
@@ -331,10 +349,7 @@ public class ContainerUploadPage extends ContainerUploadPageLayout {
Pattern p = Pattern.compile("[Dd]ockerfile");
Matcher m = p.matcher(f.getName());
- boolean accept = false;
- if ((f.isFile() && m.matches()) || f.isDirectory())
- accept = true;
- return accept;
+ return (f.isFile() && m.matches()) || f.isDirectory();
}
@Override public String getDescription() {
@@ -346,10 +361,7 @@ public class ContainerUploadPage extends ContainerUploadPageLayout {
@Override public boolean accept(File f) {
- boolean accept = false;
- if ((f.isFile() && f.toString().endsWith(".tar")) || f.isDirectory())
- accept = true;
- return accept;
+ return (f.isFile() && f.toString().endsWith(".tar")) || f.isDirectory();
}
@Override public String getDescription() {
diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/wizard/page/ImageTypePage.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/wizard/page/ImageTypePage.java
index cd80a41e..d839559e 100644
--- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/wizard/page/ImageTypePage.java
+++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/wizard/page/ImageTypePage.java
@@ -16,25 +16,25 @@ public class ImageTypePage extends ImageTypePageLayout {
public ImageTypePage(final ImageCreationWizard wizard) {
super(wizard);
- btnNewVmImage.addActionListener(new ActionListener() {
+ rbtnNewVmImage.addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent e) {
+ setPageComplete(false);
wizard.doVmCreation();
setPageComplete(true);
- wizard.doNext();
}
});
- btnNewDockerImage.addActionListener(new ActionListener() {
+ rbtnNewDockerImage.addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent e) {
+ setPageComplete(false);
wizard.doDockerCreation();
setPageComplete(true);
- wizard.doNext();
}
});
}
@Override protected void onPageEnter() {
- // set onPageEnter to disable Next and Finish button
- setPageComplete(false);
+ if(btgrpImageTyp.getSelection() == null)
+ rbtnNewVmImage.doClick();
}
}
diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/model/ContainerDefinition.java b/dozentenmodul/src/main/java/org/openslx/dozmod/model/ContainerDefinition.java
index 99d73c23..9724ce61 100644
--- a/dozentenmodul/src/main/java/org/openslx/dozmod/model/ContainerDefinition.java
+++ b/dozentenmodul/src/main/java/org/openslx/dozmod/model/ContainerDefinition.java
@@ -3,9 +3,9 @@ package org.openslx.dozmod.model;
import org.openslx.dozmod.thrift.cache.MetaDataCache;
import org.openslx.virtualization.configuration.VirtualizationConfigurationDocker;
import org.openslx.virtualization.configuration.VirtualizationConfigurationException;
+import org.openslx.virtualization.configuration.container.ContainerMeta;
-import java.io.File;
-import java.io.FileNotFoundException;
+import java.io.*;
import java.util.Scanner;
public class ContainerDefinition extends
@@ -31,6 +31,28 @@ public class ContainerDefinition extends
return null;
}
+ private void setContainerMeta(ContainerMeta containerMeta){
+ this.containerMeta = containerMeta;
+ }
+
+ /**
+ * Masks the fromByteArray Method in org.openslx.virtualization.configuration.container.ContainerDefinition.
+ * Prevents ClassCastExceptions while casting from parent to child!
+ * @param rawTarData
+ * @return
+ */
+ public static ContainerDefinition fromByteArray(byte[] rawTarData) {
+
+ ContainerDefinition conDef = new ContainerDefinition();
+
+ org.openslx.virtualization.configuration.container.ContainerDefinition pConDef = org.openslx.virtualization.configuration.container.ContainerDefinition.fromByteArray(rawTarData);
+
+ conDef.setContainerRecipe(pConDef.getContainerRecipe());
+ conDef.setContainerMeta(pConDef.getContainerMeta());
+
+ return conDef;
+ }
+
public static boolean isValidDockerfile(String dockerfile) {
try {
File file = new File(dockerfile);
diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/util/ContainerUtils.java b/dozentenmodul/src/main/java/org/openslx/dozmod/util/ContainerUtils.java
index ca57a265..87f87131 100644
--- a/dozentenmodul/src/main/java/org/openslx/dozmod/util/ContainerUtils.java
+++ b/dozentenmodul/src/main/java/org/openslx/dozmod/util/ContainerUtils.java
@@ -1,23 +1,33 @@
package org.openslx.dozmod.util;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonParser;
import org.apache.log4j.Logger;
import org.apache.thrift.TException;
+import org.kamranzafar.jtar.TarEntry;
+import org.kamranzafar.jtar.TarHeader;
+import org.kamranzafar.jtar.TarInputStream;
import org.openslx.bwlp.thrift.iface.ImageSummaryRead;
import org.openslx.bwlp.thrift.iface.LectureSummary;
import org.openslx.dozmod.gui.Gui;
+import org.openslx.dozmod.gui.helper.GridManager;
import org.openslx.dozmod.gui.helper.I18n;
import org.openslx.dozmod.gui.helper.MessageType;
+import org.openslx.dozmod.model.ContainerDefinition;
import org.openslx.dozmod.thrift.Session;
import org.openslx.dozmod.thrift.cache.ImageCache;
import org.openslx.dozmod.thrift.cache.LectureCache;
import org.openslx.thrifthelper.TConst;
import org.openslx.thrifthelper.ThriftManager;
import org.openslx.util.ThriftUtil;
-import org.openslx.virtualization.configuration.container.ContainerDefinition;
import org.openslx.virtualization.configuration.container.ContainerMeta;
+import javax.swing.*;
import java.awt.*;
+import java.io.*;
import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
@@ -26,8 +36,11 @@ import java.util.List;
*/
public class ContainerUtils {
+ private static final Logger LOGGER = Logger.getLogger(ContainerUtils.class);
+
/**
- * Checks ImageBaseId of image if already linked with existing Lectures in LectureCache.
+ * Checks ImageBaseId of image if already linked with existing Lectures in
+ * LectureCache.
*
* @param image The image to check.
* @return true if the images imageBaseId is already linked with a lecture.
@@ -36,7 +49,8 @@ public class ContainerUtils {
if (image != null && image.getVirtId().equals(TConst.VIRT_DOCKER)) {
List<LectureSummary> lectureSummaries = LectureCache.get(true);
for (LectureSummary lecture : lectureSummaries) {
- // lecture.imageBaseId is null when no image linked to it -> NullPointer on equals
+ // lecture.imageBaseId is null when no image linked to it -> NullPointer on
+ // equals
if (image.imageBaseId.equals(lecture.imageBaseId)) {
return true;
}
@@ -49,21 +63,20 @@ public class ContainerUtils {
String satelliteToken = Session.getSatelliteToken();
List<ImageSummaryRead> images = ImageCache.get(true);
List<ImageSummaryRead> dataContainerImages = new ArrayList<>();
- for (ImageSummaryRead image: images) {
- if (image.getVirtId().equals(TConst.VIRT_DOCKER))
- {
+ for (ImageSummaryRead image : images) {
+ if (image.getVirtId().equals(TConst.VIRT_DOCKER)) {
try {
byte[] rawVirtConfig;
- ByteBuffer byteBuffer = ThriftManager.getSatClient()
- .getImageVersionVirtConfig(satelliteToken, image.getLatestVersionId());
+ ByteBuffer byteBuffer = ThriftManager.getSatClient().getImageVersionVirtConfig(satelliteToken,
+ image.getLatestVersionId());
rawVirtConfig = ThriftUtil.unwrapByteBuffer(byteBuffer);
ContainerDefinition containerDefinition = ContainerDefinition.fromByteArray(rawVirtConfig);
if (containerDefinition.getContainerMeta().getImageType() == ContainerMeta.ContainerImageType.DATA)
dataContainerImages.add(image);
} catch (TException e) {
-// LOGGER.error("Failed to retrieve virtualizer config for image version " + "'"
-// + image.getLatestVersionId() + ", see trace: ", e);
+ // LOGGER.error("Failed to retrieve virtualizer config for image version " + "'"
+ // + image.getLatestVersionId() + ", see trace: ", e);
}
}
}
@@ -75,9 +88,115 @@ public class ContainerUtils {
MessageType.WARNING, logger, null);
}
+ public static ContainerDefinition getContainerDefinition(String satelliteToken, String latestVersionId) {
+ byte[] rawVirtConfig = null;
+ try {
+ ByteBuffer byteBuffer = ThriftManager.getSatClient().getImageVersionVirtConfig(satelliteToken,
+ latestVersionId);
+ rawVirtConfig = ThriftUtil.unwrapByteBuffer(byteBuffer);
+ } catch (TException e) {
+ LOGGER.error("Failed to retrieve virtualizer config for image version " + "'" + latestVersionId
+ + ", see trace: ", e);
+ return null;
+ }
+ return ContainerDefinition.fromByteArray(rawVirtConfig);
+ }
+
+ /**
+ * Check if a provided tar file contains information about a single docker
+ * image. To check the validity of the file, the existence of two JSON files is
+ * checked and one of the files must only contain information for one image.
+ *
+ * The tar file have to be created by the 'docker save ...' command.
+ *
+ * @param tarFile the user selected tar file.
+ * @return true if the images imageBaseId is already linked with a lecture.
+ */
+ public static boolean isValidTar(File tarFile) {
+
+ boolean isValid = false;
+ boolean containsManifest = false;
+ boolean containsRepositories = false;
+ JsonArray manifestJson = null;
+
+ try {
+ TarInputStream tis = new TarInputStream(new FileInputStream(tarFile));
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ byte[] rawData = new byte[1024];
+ TarEntry entry;
+
+ // setDefaultSkip seems to fasten things up while processing the file,
+ // because we want only to check manifest.json and repositories file
+ tis.setDefaultSkip(true);
+ while ((entry = tis.getNextEntry()) != null) {
+ if (!TarHeader.USTAR_MAGIC.equals(entry.getHeader().magic.toString()))
+ break;
+ Arrays.fill(rawData, (byte) 0);
+ output.reset();
+ int count = 0;
+
+ if (entry.getName().equals("manifest.json")) {
+ containsManifest = true;
+ while ((count = tis.read(rawData)) != -1) {
+ output.write(rawData, 0, count);
+ }
+ manifestJson = new JsonParser().parse(new String(output.toByteArray(), StandardCharsets.UTF_8))
+ .getAsJsonArray();
+ }
+
+ if (entry.getName().equals("repositories")) {
+ containsRepositories = true;
+ // dont read the file, no checks for the Content
+ }
+
+ if (containsManifest && containsRepositories)
+ break;
+ }
+ tis.close();
+ // check the json files inside the tar file
+ if (containsManifest && containsRepositories && manifestJson.isJsonArray() && manifestJson.size() == 1) {
+ isValid = true;
+ String repoTag = manifestJson.get(0).getAsJsonObject().get("RepoTags").getAsString();
+ LOGGER.info(String.format("Tar File contains Docker Image with repoTag=%s", repoTag));
+ } else if (containsManifest && containsRepositories && manifestJson.isJsonArray()
+ && manifestJson.size() > 1) {
+ Gui.showMessageBox("Tar File container more then one Images!", MessageType.ERROR, LOGGER, null);
+ } else {
+ Gui.showMessageBox("No valid Tar File with Images provided!", MessageType.ERROR, LOGGER, null);
+ }
+
+ } catch (IOException e) {
+ LOGGER.error("IOError while processing tar file", e);
+ }
+ return isValid;
+ }
+
+ public static JPanel createDownloadContainerInfo(String imageRepo, String infoText) {
+ JPanel pnlUserInfo = new JPanel();
+ GridManager grid = new GridManager(pnlUserInfo, 1, true);
+
+ JTextArea txtInfoText = new JTextArea();
+ txtInfoText.setBorder(BorderFactory.createTitledBorder(I18n.PAGE_LAYOUT.getString("Info")));
+ txtInfoText.setLineWrap(true);
+ txtInfoText.setWrapStyleWord(true);
+ txtInfoText.setEditable(false);
+ txtInfoText.setFocusable(false);
+ txtInfoText.setOpaque(false);
+ txtInfoText.setText(infoText);
+ grid.add(txtInfoText).fill(true, true);
+ grid.nextRow();
+
+ JTextField txtUserInfo = new JTextField();
+ txtUserInfo.setText(imageRepo);
+ grid.add(txtUserInfo).fill(true, true);
+ grid.finish(true);
+
+ return pnlUserInfo;
+ }
+
public static String getImageNameByBaseId(String imageBaseId) {
List<ImageSummaryRead> images = ImageCache.get(true);
- for (ImageSummaryRead image: images) {
+ for (ImageSummaryRead image : images) {
if (image.imageBaseId.equals(imageBaseId))
return image.getImageName();
}
diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/util/ContainerWrapper.java b/dozentenmodul/src/main/java/org/openslx/dozmod/util/ContainerWrapper.java
new file mode 100644
index 00000000..38ca2477
--- /dev/null
+++ b/dozentenmodul/src/main/java/org/openslx/dozmod/util/ContainerWrapper.java
@@ -0,0 +1,79 @@
+package org.openslx.dozmod.util;
+
+import org.apache.log4j.Logger;
+import org.openslx.dozmod.gui.Gui;
+import org.openslx.dozmod.gui.helper.MessageType;
+import org.openslx.virtualization.configuration.container.ContainerDefinition;
+
+import javax.swing.*;
+import java.awt.*;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+
+public class ContainerWrapper {
+
+ private static final Logger LOGGER = Logger.getLogger(ContainerWrapper.class);
+
+
+ public static void unwrapContainer(File tmpDiskFile, String imageName, File destDir,
+ byte[] virtualizerConfig) {
+ ContainerDefinition conDef = ContainerDefinition.fromByteArray(virtualizerConfig);
+ try {
+ switch (conDef.getContainerImageContext()) {
+ case DOCKERFILE:
+ conDef.saveLocal(destDir);
+ showImageMessageInfo(destDir.getPath(),
+ "Dieses Image wird durch ein Dockerfile gebaut. Wechseln Sie in das Verzeichnis und bauen Sie das Image lokal (docker build).");
+
+ break;
+ case GIT_REPOSITORY:
+ Files.delete(tmpDiskFile.toPath());
+ Files.delete(destDir.toPath());
+
+ showImageMessageInfo(conDef.getContainerMeta().getBuildContextUrl(),
+ "Dieses Image wird durch ein öffentliches Git-Repository gebaut. Das Image kann mit dem angezeigten Link lokal gebaut werden (docker build), zudem können die Image-Quellen über diesen betrachtet werden.");
+ break;
+ case IMAGE_REPOSITORY:
+ Files.delete(tmpDiskFile.toPath());
+ Files.delete(destDir.toPath());
+
+ showImageMessageInfo(
+ conDef.getContainerMeta().getImageRepo(),
+ "Dieses Image ist lediglich eine Referenz auf ein öffentliches Image. Das Image kann mittels des angezeigten Links gepullt werden."
+ );
+ break;
+ case DOCKER_ARCHIVE:
+ File destImage = new File(destDir.getAbsolutePath(),
+ VmWrapper.generateFilename(imageName, "tar"));
+ if (destImage.exists())
+ Files.delete(destImage.toPath());
+ Files.move(tmpDiskFile.toPath(),destImage.toPath());
+ break;
+ }
+
+ if (tmpDiskFile.exists())
+ Files.delete(tmpDiskFile.toPath());
+ } catch (IOException e) {
+ Gui.asyncMessageBox("Konnte temporäre Download Datei nicht löschen", MessageType.WARNING,
+ LOGGER, e);
+ }
+ }
+
+ private static void showImageMessageInfo(String imageSourceUrl, String infoText) {
+ Gui.asyncExec(new Runnable() {
+ @Override public void run() {
+ Object oldDimension = UIManager.get("OptionPane.minimumSize");
+ UIManager.put("OptionPane.minimumSize",new Dimension(400,200));
+ JOptionPane.showMessageDialog(null,
+ ContainerUtils.createDownloadContainerInfo(
+ imageSourceUrl,
+ infoText
+ ),
+ "Container-Image Info",
+ JOptionPane.INFORMATION_MESSAGE);
+ UIManager.put("OptionPane.minimumSize",oldDimension);
+ }
+ });
+ }
+}
diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/util/ImageWrapper.java b/dozentenmodul/src/main/java/org/openslx/dozmod/util/ImageWrapper.java
index fe884a15..3c3a5f1c 100644
--- a/dozentenmodul/src/main/java/org/openslx/dozmod/util/ImageWrapper.java
+++ b/dozentenmodul/src/main/java/org/openslx/dozmod/util/ImageWrapper.java
@@ -7,22 +7,16 @@ import org.openslx.dozmod.gui.helper.I18n;
import org.openslx.dozmod.gui.helper.MessageType;
import org.openslx.thrifthelper.TConst;
import org.openslx.virtualization.configuration.VirtualizationConfigurationException;
-import org.openslx.virtualization.configuration.container.ContainerDefinition;
import org.openslx.virtualization.disk.DiskImage;
import org.openslx.virtualization.disk.DiskImage.ImageFormat;
import org.openslx.virtualization.disk.DiskImageException;
import java.io.File;
import java.io.IOException;
-import java.nio.file.Files;
/**
* This Class handle the unpacking of Images downloaded from
* the server individually (VM-Images, Docker-Images (Container Images)).
- *
- * In case of Container-Images the Image-Blob is not important because it can be recreated with the
- * recipe (e.g. dockerfile).
- * TODO Do not download the Image-Blob of a Container-Image.
*/
public class ImageWrapper {
@@ -47,20 +41,10 @@ public class ImageWrapper {
boolean imageIsCompressed = false;
ImageFormat imageFormat = null;
- // unwrap each image individually
- // TODO In future maybe this is a check to distinguish between VM-Image and Container Image
+ // unwrap container image individually
if (virtualizerId.equals(TConst.VIRT_DOCKER)) {
- ContainerDefinition conDef = ContainerDefinition.fromByteArray(virtualizerConfig);
- conDef.saveLocal(destDir);
-
- try {
- // delete image file, unused in container Context.
- Files.delete(tmpDiskFile.toPath());
- } catch (IOException e) {
- Gui.asyncMessageBox("Konnte temporäre Download Datei nicht löschen", MessageType.WARNING,
- LOGGER, e);
- }
+ ContainerWrapper.unwrapContainer(tmpDiskFile, imageName, destDir, virtualizerConfig);
} else {
@@ -73,8 +57,9 @@ public class ImageWrapper {
}
if (imageIsCompressed && imageFormat != ImageFormat.QCOW2) {
- Gui.asyncMessageBox(I18n.THRIFT.getString("ThriftActions.Message.warning.diskImageCompressed",
- imageName, Branding.getServiceFAQWebsite()), MessageType.WARNING, null, null);
+ Gui.asyncMessageBox(
+ I18n.THRIFT.getString("ThriftActions.Message.warning.diskImageCompressed", imageName,
+ Branding.getServiceFAQWebsite()), MessageType.WARNING, null, null);
}
File destImage = new File(destDir.getAbsolutePath(), VmWrapper.generateFilename(imageName, ext));
destImage.delete();
diff --git a/dozentenmodul/src/main/properties/i18n/page.properties b/dozentenmodul/src/main/properties/i18n/page.properties
index eef4b242..1c096ad5 100644
--- a/dozentenmodul/src/main/properties/i18n/page.properties
+++ b/dozentenmodul/src/main/properties/i18n/page.properties
@@ -73,6 +73,7 @@ ContainerUploadPage.Warning.NoImageRepo=No Image Repository provided
ContainerUploadPage.Warning.NoReceipt=No Container Recipe provided!
ContainerUploadPage.Warning.NoValidDockerfiler=No valid Dockerfile provided!
ContainerUploadPage.Warning.NoGitRepository=No Git Repository provided!
+ContainerUploadPage.Warning.NoDockerArchive=No Docker Archive provided!
ContainerUploadPage.Warning.NoProperName=Set proper Image Name
ContainerUploadPage.Warning.NoRunOptions=Set container run options
diff --git a/dozentenmodul/src/main/properties/i18n/page_de_DE.properties b/dozentenmodul/src/main/properties/i18n/page_de_DE.properties
index 67c3662a..8a7efd04 100644
--- a/dozentenmodul/src/main/properties/i18n/page_de_DE.properties
+++ b/dozentenmodul/src/main/properties/i18n/page_de_DE.properties
@@ -21,7 +21,7 @@ ImageUpload.Message.warning.diskImageSnapshot=Von der ausgewählten VM wurde ein
In diesem Zustand kann\n die VM leider nicht ins {0}-System geladen werden. Bitte konsolidieren Sie zunächst\n\
den Snapshot und versuchen Sie es erneut.
ImageUpload.Message.warning.diskImageNotSupportedByHypervisor=Das Format der zu dieser VM gehörigen virtuellen \
- Festplatte\n wird vom aktuellen aktuellen Hypervisor nicht unterstützt.
+ Festplatte\n wird vom aktuellen Hypervisor nicht unterstützt.
ImageUpload.WizardPage.errorMessage.diskImageNotSupportedByHypervisor=Das Format der virtuellen Festplatte dieser VM \
wird vom aktuellen Hypervisor nicht unterstützt
ImageUpload.WizardPage.errorMessage.diskImageStandalone=Die virtuelle Festplatte der VM hat ein inkompatibles Format
@@ -69,6 +69,7 @@ ContainerUploadPage.Description.ContainerDefFinished=Container Definition vollst
ContainerUploadPage.Warning.NoReceipt=Keine Containeranweisungen angegeben!
ContainerUploadPage.Warning.NoValidDockerfiler=Kein valides Dockerfile angegeben!
ContainerUploadPage.Warning.NoGitRepository=Kein Git Repository angegeben!
+ContainerUploadPage.Warning.NoDockerArchive=Kein Docker Archive angegeben!
ContainerUploadPage.Warning.NoProperName=Bitte Imagenamen setzen
ContainerUploadPage.Warning.NoRunOptions=Bitte Container Start Optionen setzen
ContainerUploadPage.Warning.NoImageRepo=Kein Image Repository angegeben
diff --git a/dozentenmodul/src/main/properties/i18n/page_layout.properties b/dozentenmodul/src/main/properties/i18n/page_layout.properties
index b14eae34..7b2f3b13 100644
--- a/dozentenmodul/src/main/properties/i18n/page_layout.properties
+++ b/dozentenmodul/src/main/properties/i18n/page_layout.properties
@@ -65,14 +65,13 @@ ContainerUploadPage.GitRepository.label=Git Repository
ContainerUploadPage.GitRepository.toolTipText=Set clone address of Git Repository [git@ | http://] [.git]. Currently no Validation Checks!
ContainerUploadPage.ImageRepository.ToolTipText=Specify the Container Image by his Repository Name (e.g python:3.7 or tensorflow/tensorflow)
ContainerUploadPage.CheckBox.ContainsLicenseRestricted.text=Contains license restricted software
-ContainerUploadPage.ContainerImageFile.label=Pre-build Container Image
-ContainerUploadPage.ContainerImageFile.ToolTipText=<html>Optionally attach a tar archive of a container image to the upload.<br>\
-Open dialogue with double click<html>
+ContainerUploadPage.ContainerImageFile.label=Container Image
+ContainerUploadPage.ContainerImageFile.ToolTipText=<html>Attach a container image archived as tarball<br>\
+For example: docker save IMAGE --output image_name.tar<html>
ContainerUploadPage.Infobox.label=Information
ContainerUploadPage.Infobox.text=Enter the information necessary for creating a container image here.\n\n\
-Container images are currently built and run on clients. \
-If the build takes too much time, you can optionally add a pre-built \
-container image as a tar archive to the upload (docker save).
+It is possible to reference an image directly from a public registry or to add a self-created \
+image to the upload. For more information on creating an image, see the bwLehrpool documentation.
# ImageUploadSummaryPageLayout
ImageUploadSummary.WizardPage.title=Done!
diff --git a/dozentenmodul/src/main/properties/i18n/page_layout_de_DE.properties b/dozentenmodul/src/main/properties/i18n/page_layout_de_DE.properties
index de385d68..4972b451 100644
--- a/dozentenmodul/src/main/properties/i18n/page_layout_de_DE.properties
+++ b/dozentenmodul/src/main/properties/i18n/page_layout_de_DE.properties
@@ -64,16 +64,13 @@ ContainerUploadPage.GitRepository.label=Git Repository
ContainerUploadPage.GitRepository.toolTipText=Clone Addresse des Git Repositories setzen. [git@ | http://] [.git]. Derzeit keine Validierungsprüfungen!
ContainerUploadPage.ImageRepository.ToolTipText=Geben Sie das Container-Image durch seinen Repository-Namen an (z.B. python:3.7 oder tensorflow/tensorflow)
ContainerUploadPage.CheckBox.ContainsLicenseRestricted.text=Enthält lizenzpflichtige Software
-ContainerUploadPage.ContainerImageFile.label=Vorgebautes Container-Image\
-
-ContainerUploadPage.ContainerImageFile.ToolTipText=<html>Fügen Sie dem Upload optional ein ein als tar archiviertes Container-Image an.<br>\
-Öffne Dialog mit Doppelklick<html>
+ContainerUploadPage.ContainerImageFile.label=Container-Image
+ContainerUploadPage.ContainerImageFile.ToolTipText=<html>Fügen Sie ein archiviertes Container-Image als tar-Datei an.<br>\
+Zum Beispiel: docker save IMAGE --output image_name.tar.<html>
ContainerUploadPage.Infobox.label=Hinweis
ContainerUploadPage.Infobox.text=Geben Sie hier die zur Erstellung eines Container-Images nötigen Informationen an.\n\n\
-Container-Images werden derzeit auf Clients gebaut und ausgeführt. \
-Sollte der Bau zu viel Zeit benötigen, können Sie optional dem \
-Upload ein vorgebautes Container-Image als tar-Archive hinzufügen\
-(docker save).
+Es ist möglich ein Image direkt von einer öffentlichen Registry zu referenzieren oder ein selbsterstelltes \
+Image dem Upload hinzuzufügen. Weiter Informationen zur Erstellung entnehmen Sie der bwLehrpool-Dokumentation.
# ImageUploadSummaryPageLayout
ImageUploadSummary.WizardPage.title=Fertig!
diff --git a/dozentenmodul/src/main/properties/i18n/panel.properties b/dozentenmodul/src/main/properties/i18n/panel.properties
index 8770f86f..44fbee3b 100644
--- a/dozentenmodul/src/main/properties/i18n/panel.properties
+++ b/dozentenmodul/src/main/properties/i18n/panel.properties
@@ -8,3 +8,5 @@ ContainerPanel.ContainerRunCommand.label=Container Run Command
ContainerPanel.ContainerRunCommand.tooltip=Specify the programme and arguments for the Docker Run command.
ContainerPanel.Label.ContainerImageType.text=Container Image Type
+
+ContainerPanel.ContainerImageType.Item.label=Data
diff --git a/dozentenmodul/src/main/properties/i18n/panel_de_DE.properties b/dozentenmodul/src/main/properties/i18n/panel_de_DE.properties
index e3f47cba..9b5b06bb 100644
--- a/dozentenmodul/src/main/properties/i18n/panel_de_DE.properties
+++ b/dozentenmodul/src/main/properties/i18n/panel_de_DE.properties
@@ -8,3 +8,5 @@ ContainerPanel.ContainerRunCommand.label=Container-Startbefehl
ContainerPanel.ContainerRunCommand.tooltip=Geben Sie das Programm und Argumente für docker run an.
ContainerPanel.Label.ContainerImageType.text=Container-Image-Typ
+
+ContainerPanel.ContainerImageType.Item.label=Daten
diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbImage.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbImage.java
index 62041952..9c39078c 100644
--- a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbImage.java
+++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbImage.java
@@ -1173,7 +1173,7 @@ public class DbImage {
resultJson.addProperty("image_recipe", condev.getContainerRecipe());
resultJson.addProperty("image_repo", condev.getContainerMeta().getImageRepo());
resultJson.addProperty("build_context_method",
- condev.getContainerMeta().getBuildContextMethod());
+ condev.getContainerMeta().getContainerImageContext());
resultJson.addProperty("build_context_url", condev.getContainerMeta().getBuildContextUrl());
break;
}
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 cc9f8b72..43e56137 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
@@ -41,9 +41,9 @@ import fi.iki.elonen.NanoHTTPD;
public class WebServer extends NanoHTTPD {
private static final Logger LOGGER = Logger.getLogger(WebServer.class);
-
- private static final ThreadPoolExecutor tpe =
- new GrowingThreadPoolExecutor(1, 8, 1, TimeUnit.MINUTES, new LinkedBlockingQueue<Runnable>(16));
+
+ private static final ThreadPoolExecutor tpe = new GrowingThreadPoolExecutor(1, 8, 1, TimeUnit.MINUTES,
+ new LinkedBlockingQueue<Runnable>(16));
private static final Serializer serializer = new Persister();
@@ -93,6 +93,8 @@ public class WebServer extends NanoHTTPD {
return serveMetaData(parts[2]);
if (parts[3].equals("netrules"))
return serveLectureNetRules(parts[2]);
+ if (parts[3].equals("imagemeta"))
+ return serveContainerImageMetaData(parts[2]);
}
return notFound();
}
@@ -126,16 +128,14 @@ public class WebServer extends NanoHTTPD {
return new NanoHTTPD.Response(NanoHTTPD.Response.Status.OK, "application/json; charset=utf-8",
Json.serialize(FileServer.instance().getStatus()));
}
-
- private static void tarPutFile(TarOutputStream output, String fileName, String data) throws IOException
- {
+
+ private static void tarPutFile(TarOutputStream output, String fileName, String data) throws IOException {
if (data == null)
return;
tarPutFile(output, fileName, data.getBytes(StandardCharsets.UTF_8));
}
-
- private static void tarPutFile(TarOutputStream output, String fileName, byte[] data) throws IOException
- {
+
+ private static void tarPutFile(TarOutputStream output, String fileName, byte[] data) throws IOException {
if (data == null)
return;
output.putNextEntry(new TarEntry(TarHeader.createHeader(fileName, data.length, Util.unixTime(), false, 0644)));
@@ -172,8 +172,7 @@ public class WebServer extends NanoHTTPD {
if (ld.runScript != null) {
int cnt = 0;
for (RunScript rs : ld.runScript) {
- tarPutFile(output, String.format("adminrun/%04d-%d-%d.%s",
- cnt++, rs.visibility,
+ tarPutFile(output, String.format("adminrun/%04d-%d-%d.%s", cnt++, rs.visibility,
rs.passCreds ? 1 : 0, rs.extension), rs.content);
}
}
@@ -191,10 +190,9 @@ public class WebServer extends NanoHTTPD {
LOGGER.warn("Server overloaded; rejecting VM Metadata request", e2);
return internalServerError();
}
- return new NanoHTTPD.Response(NanoHTTPD.Response.Status.OK, "application/gzip",
- sink);
+ return new NanoHTTPD.Response(NanoHTTPD.Response.Status.OK, "application/gzip", sink);
}
-
+
private Response serveLectureNetRules(String lectureId) {
List<NetRule> list = new ArrayList<>();
boolean defaultAllowed;
@@ -223,13 +221,12 @@ public class WebServer extends NanoHTTPD {
sb.append("IN * 0 REJECT\n");
sb.append("OUT * 0 REJECT\n");
}
- return new NanoHTTPD.Response(NanoHTTPD.Response.Status.OK, "text/plain; charset=utf-8",
- sb.toString());
+ return new NanoHTTPD.Response(NanoHTTPD.Response.Status.OK, "text/plain; charset=utf-8", sb.toString());
}
private String serializeNetShares(List<NetShare> list) {
// openslx.exe expects shares in the following format
- // <path> <letter> <shortcut> <username> <password>
+ // <path> <letter> <shortcut> <username> <password>
// letter is either a drive letter for Windows VMs,
// or a mount point for Linux VMs.
StringBuilder sb = new StringBuilder();
@@ -276,13 +273,13 @@ public class WebServer extends NanoHTTPD {
/**
* Helper for returning "Internal Server Error" Status
- * @param body Message
+ *
+ * @param body Message
*/
public static Response internalServerError(String body) {
- return new NanoHTTPD.Response(NanoHTTPD.Response.Status.INTERNAL_ERROR, "text/plain",
- body);
+ return new NanoHTTPD.Response(NanoHTTPD.Response.Status.INTERNAL_ERROR, "text/plain", body);
}
-
+
public static Response internalServerError() {
return internalServerError("Internal Server Error");
}
@@ -305,9 +302,10 @@ public class WebServer extends NanoHTTPD {
}
/**
- * create a json response with information about existing container images in bwlehrpool
+ * create a json response with information about existing container images in
+ * bwlehrpool
*/
- private Response serverContainerImages () {
+ private Response serverContainerImages() {
try {
return new Response(Response.Status.OK, "application/json; charset=utf-8",
Json.serialize(DbImage.getContainerImageCluster()));