diff options
author | ralph isenmann | 2021-11-10 16:25:43 +0100 |
---|---|---|
committer | ralph isenmann | 2021-11-10 16:25:43 +0100 |
commit | 10f2c2f06fb37d20504f2baea280979f91635d55 (patch) | |
tree | ff90441c19aa6129f8950613a6a6706f7ab1b38b | |
parent | Merge branch 'master' of git.openslx.org:openslx-ng/tutor-module (diff) | |
parent | Merge branch 'feature/docker-data-container' of git.openslx.org:openslx-ng/tu... (diff) | |
download | tutor-module-10f2c2f06fb37d20504f2baea280979f91635d55.tar.gz tutor-module-10f2c2f06fb37d20504f2baea280979f91635d55.tar.xz tutor-module-10f2c2f06fb37d20504f2baea280979f91635d55.zip |
Merge branch 'feature/docker-data-container'
6 files changed, 222 insertions, 96 deletions
diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/control/table/ContainerBindMountTable.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/control/table/ContainerBindMountTable.java index 81c76303..28a5225f 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/control/table/ContainerBindMountTable.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/control/table/ContainerBindMountTable.java @@ -1,6 +1,7 @@ package org.openslx.dozmod.gui.control.table; import org.openslx.dozmod.gui.helper.I18n; +import org.openslx.dozmod.util.ContainerUtils; import org.openslx.virtualization.configuration.container.ContainerBindMount; import java.util.ArrayList; @@ -11,7 +12,7 @@ public class ContainerBindMountTable extends ListTable<ContainerBindMount> { * Version for serialization. */ private static final long serialVersionUID = -2908607335582645909L; - + public static final ListTableColumn COL_SOURCE = new ListTableColumn( I18n.CONFIGURATOR.getString("ContainerBindMount.BindMountTable.col.src")); public static final ListTableColumn COL_TARGET = new ListTableColumn( @@ -27,7 +28,13 @@ public class ContainerBindMountTable extends ListTable<ContainerBindMount> { @Override protected Object getValueAtInternal(ContainerBindMount item, ListTableColumn column) { if (COL_SOURCE == column) - return item.getSource(); + switch (item.getMountType()){ + case DEFAULT: + return item.getSource(); + case CONTAINER_IMAGE: + return ContainerUtils.getImageNameByBaseId(item.getSource()); + } + if (COL_TARGET == column) return item.getTarget(); if (COL_OPTIONS == column) diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/ContainerBindMountWindow.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/ContainerBindMountWindow.java index fa3cf920..f4f946e6 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/ContainerBindMountWindow.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/ContainerBindMountWindow.java @@ -12,6 +12,7 @@ import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.util.ArrayList; import java.util.List; +import java.util.Objects; public class ContainerBindMountWindow extends ContainerBindMountWindowLayout { @@ -38,7 +39,7 @@ public class ContainerBindMountWindow extends ContainerBindMountWindowLayout { dispose(); } }); - this.cboSourceMountPoint.addItemListener(new ItemListener() { + this.cboSourceMount.addItemListener(new ItemListener() { @Override public void itemStateChanged(ItemEvent e) { isInputComplete(); } @@ -54,7 +55,8 @@ public class ContainerBindMountWindow extends ContainerBindMountWindowLayout { private boolean isInputComplete() { btnSave.setEnabled(false); - if (cboSourceMountPoint == null || cboSourceMountPoint.getSelectedIndex() == 0) { + if (cboSourceMount == null || Objects.equals(cboSourceMount.getSelectedItem(), + ContainerMountChoice.getEmptyChoice())) { header.updateStatus("Source Path is Missing"); return false; } @@ -68,11 +70,14 @@ public class ContainerBindMountWindow extends ContainerBindMountWindowLayout { } private void saveEntry() { - ContainerBindMount bindMount = new ContainerBindMount(); - bindMount.setSource( - ContainerBindMountWindowLayout.SOURCE_MOUNT_POINTS[cboSourceMountPoint.getSelectedIndex()]); - bindMount.setTarget(this.txtBmTarget.getText()); - bindMount.setOptions(this.txtBmOptions.getText()); + + ContainerMountChoice mountChoice = (ContainerMountChoice) this.cboSourceMount.getSelectedItem(); + + ContainerBindMount.ContainerMountType mountType = mountChoice.type; + String source = mountChoice.value; + String target = this.txtBmTarget.getText(); + String option = this.txtBmOptions.getText(); + ContainerBindMount bindMount = new ContainerBindMount(mountType, source, target, option); List<ContainerBindMount> oldData = bindMountTable.getData(); List<ContainerBindMount> data = new ArrayList<>(oldData); diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/layout/ContainerBindMountWindowLayout.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/layout/ContainerBindMountWindowLayout.java index 6f6a3cfe..3b542a10 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/layout/ContainerBindMountWindowLayout.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/layout/ContainerBindMountWindowLayout.java @@ -1,13 +1,18 @@ package org.openslx.dozmod.gui.window.layout; +import org.openslx.bwlp.thrift.iface.ImageSummaryRead; import org.openslx.dozmod.gui.Gui; import org.openslx.dozmod.gui.control.ComboBox; import org.openslx.dozmod.gui.control.QLabel; import org.openslx.dozmod.gui.helper.GridManager; import org.openslx.dozmod.gui.helper.StatusHeader; +import org.openslx.dozmod.util.ContainerUtils; +import org.openslx.virtualization.configuration.container.ContainerBindMount; import javax.swing.*; import java.awt.*; +import java.util.ArrayList; +import java.util.List; public class ContainerBindMountWindowLayout extends JDialog { @@ -19,8 +24,7 @@ public class ContainerBindMountWindowLayout extends JDialog { private static final String title = "Add Bind Mount"; protected final StatusHeader header; - protected final QLabel lblBmSource; - protected final JTextField txtBmSource; + // protected final QLabel lblBmSource; protected final QLabel lblBmTarget; protected final JTextField txtBmTarget; protected final QLabel lblBmOptions; @@ -33,14 +37,14 @@ public class ContainerBindMountWindowLayout extends JDialog { protected static String[] SOURCE_MOUNT_POINTS = { EMPTY_MARKER, TAGS[0], TAGS[1], "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" }; - protected final ComboBox<String> cboSourceMountPoint = new ComboBox<String>( - new ComboBox.ComboBoxRenderer<String>() { - @Override public String renderItem(String letter) { - if (letter == null) - return null; - return letter; + protected final ComboBox<ContainerMountChoice> cboSourceMount = new ComboBox<>( + new ComboBox.ComboBoxRenderer<ContainerMountChoice>() { + @Override public String renderItem(ContainerMountChoice choice) { + if (choice == null) + return ""; + return choice.name; } - }, String.class); + }, ContainerMountChoice.class); public ContainerBindMountWindowLayout(Window modalParent) { super(modalParent, title, ModalityType.APPLICATION_MODAL); @@ -53,16 +57,17 @@ public class ContainerBindMountWindowLayout extends JDialog { add(contentPanel, BorderLayout.CENTER); GridManager grid = new GridManager(contentPanel, 2, true, new Insets(2, 2, 2, 2)); - lblBmSource = new QLabel("Source"); - - txtBmSource = new JTextField(); - cboSourceMountPoint.setModel(new DefaultComboBoxModel<>(SOURCE_MOUNT_POINTS)); - cboSourceMountPoint.setSelectedItem(SOURCE_MOUNT_POINTS[0]); - - grid.add(lblBmSource); - grid.add(cboSourceMountPoint).fill(true, false).expand(true, false); + cboSourceMount.setModel( + new DefaultComboBoxModel<>(generateMountChoices().toArray(new ContainerMountChoice[0]))); + cboSourceMount.setSelectedIndex(0); + grid.add(new QLabel("Source")); + grid.add(cboSourceMount).fill(true, false).expand(true, false); grid.nextRow(); + // grid.add(lblBmSource); + // grid.add(cboSourceMountPoint).fill(true, false).expand(true, false); + // grid.nextRow(); + lblBmTarget = new QLabel("Target"); txtBmTarget = new JTextField(); grid.add(lblBmTarget); @@ -87,10 +92,49 @@ public class ContainerBindMountWindowLayout extends JDialog { grid.add(buttonPane, 2).fill(true, false).expand(true, false); grid.finish(false); - setSize(350, 200); + setSize(350, 300); setResizable(false); if (modalParent != null) { Gui.centerShellOverShell(modalParent, this); } } + + private ArrayList<ContainerMountChoice> generateMountChoices() { + List<ImageSummaryRead> dataContainerImages = ContainerUtils.getDataContainerImages(); + ArrayList<ContainerMountChoice> mountChoices = new ArrayList<>(); + mountChoices.add(ContainerMountChoice.getEmptyChoice()); + + for (int i = 1; i < SOURCE_MOUNT_POINTS.length; i++) { + mountChoices.add(new ContainerMountChoice(ContainerBindMount.ContainerMountType.DEFAULT, + SOURCE_MOUNT_POINTS[i], SOURCE_MOUNT_POINTS[i])); + } + + for (ImageSummaryRead image : dataContainerImages) { + mountChoices.add(new ContainerMountChoice(ContainerBindMount.ContainerMountType.CONTAINER_IMAGE, + image.imageName, image.imageBaseId)); + } + return mountChoices; + } + + protected static class ContainerMountChoice { + + public final ContainerBindMount.ContainerMountType type; + public final String name; + public final String value; + + private static ContainerMountChoice emptyMountChoice = null; + + public ContainerMountChoice(ContainerBindMount.ContainerMountType type, String name, String value) { + this.type = type; + this.name = name; + this.value = value; + } + + public static ContainerMountChoice getEmptyChoice() { + if (emptyMountChoice == null) + emptyMountChoice = new ContainerMountChoice(ContainerBindMount.ContainerMountType.DEFAULT, + "-", "-"); + return emptyMountChoice; + } + } } 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 3d65ea5d..87f87131 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/util/ContainerUtils.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/util/ContainerUtils.java @@ -14,10 +14,13 @@ 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.ContainerMeta; import javax.swing.*; import java.awt.*; @@ -25,6 +28,7 @@ import java.io.*; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.util.Arrays; +import java.util.ArrayList; import java.util.List; /** @@ -33,8 +37,10 @@ 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. @@ -43,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; } @@ -52,6 +59,30 @@ public class ContainerUtils { return false; } + public static List<ImageSummaryRead> getDataContainerImages() { + 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)) { + try { + byte[] rawVirtConfig; + 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); + } + } + } + return dataContainerImages; + } + public static void showWarning(Component c, Logger logger) { Gui.showMessageBox(c, I18n.WINDOW.getString("LectureDetails.Message.error.containerLinkedWithLecture"), MessageType.WARNING, logger, null); @@ -60,21 +91,21 @@ public class ContainerUtils { public static ContainerDefinition getContainerDefinition(String satelliteToken, String latestVersionId) { byte[] rawVirtConfig = null; try { - ByteBuffer byteBuffer = ThriftManager.getSatClient() - .getImageVersionVirtConfig(satelliteToken, latestVersionId); + 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); + 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. + * 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. * @@ -98,7 +129,7 @@ public class ContainerUtils { // 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())) + if (!TarHeader.USTAR_MAGIC.equals(entry.getHeader().magic.toString())) break; Arrays.fill(rawData, (byte) 0); output.reset(); @@ -109,8 +140,8 @@ public class ContainerUtils { while ((count = tis.read(rawData)) != -1) { output.write(rawData, 0, count); } - manifestJson = new JsonParser().parse( - new String(output.toByteArray(), StandardCharsets.UTF_8)).getAsJsonArray(); + manifestJson = new JsonParser().parse(new String(output.toByteArray(), StandardCharsets.UTF_8)) + .getAsJsonArray(); } if (entry.getName().equals("repositories")) { @@ -123,20 +154,15 @@ public class ContainerUtils { } tis.close(); // check the json files inside the tar file - if (containsManifest && containsRepositories && manifestJson.isJsonArray() - && manifestJson.size() == 1) { + 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); + 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); + Gui.showMessageBox("No valid Tar File with Images provided!", MessageType.ERROR, LOGGER, null); } } catch (IOException e) { @@ -150,23 +176,30 @@ public class ContainerUtils { GridManager grid = new GridManager(pnlUserInfo, 1, true); JTextArea txtInfoText = new JTextArea(); - txtInfoText.setBorder(BorderFactory.createTitledBorder( - I18n.PAGE_LAYOUT.getString("Info"))); + 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.add(txtInfoText).fill(true, true); grid.nextRow(); JTextField txtUserInfo = new JTextField(); txtUserInfo.setText(imageRepo); - grid.add(txtUserInfo).fill(true,true); + 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) { + if (image.imageBaseId.equals(imageBaseId)) + return image.getImageName(); + } + return imageBaseId; + } } 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 bac3ad6c..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 @@ -1,14 +1,6 @@ package org.openslx.bwlp.sat.database.mappers; -import java.io.*; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.UUID; - +import com.google.gson.JsonObject; import org.apache.log4j.Logger; import org.openslx.bwlp.sat.RuntimeConfig; import org.openslx.bwlp.sat.database.Database; @@ -20,27 +12,20 @@ import org.openslx.bwlp.sat.database.models.LocalImageVersion; import org.openslx.bwlp.sat.mail.MailGenerator; import org.openslx.bwlp.sat.permissions.User; import org.openslx.bwlp.sat.util.FileSystem; -import org.openslx.bwlp.thrift.iface.ImageBaseWrite; -import org.openslx.bwlp.thrift.iface.ImageDetailsRead; -import org.openslx.bwlp.thrift.iface.ImagePermissions; -import org.openslx.bwlp.thrift.iface.ImagePublishData; -import org.openslx.bwlp.thrift.iface.ImageSummaryRead; -import org.openslx.bwlp.thrift.iface.ImageVersionDetails; -import org.openslx.bwlp.thrift.iface.ImageVersionWrite; -import org.openslx.bwlp.thrift.iface.Role; -import org.openslx.bwlp.thrift.iface.ShareMode; -import org.openslx.bwlp.thrift.iface.TNotFoundException; -import org.openslx.bwlp.thrift.iface.UserInfo; +import org.openslx.bwlp.thrift.iface.*; import org.openslx.filetransfer.util.ChunkList; import org.openslx.filetransfer.util.FileChunk; import org.openslx.util.QuickTimer; import org.openslx.util.QuickTimer.Task; import org.openslx.util.Util; - -// master-sync-shared import org.openslx.virtualization.configuration.container.ContainerDefinition; import org.openslx.virtualization.configuration.container.ContainerMeta; +import java.io.File; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.*; + public class DbImage { private static final Logger LOGGER = Logger.getLogger(DbImage.class); @@ -1162,6 +1147,44 @@ public class DbImage { } } + public static String getContainerImageMetadata(String imagebaseid) throws SQLException { + + try (MysqlConnection connection = Database.getConnection()) { + MysqlStatement stmt = connection.prepareStatement( + "SELECT ib.imagebaseid, ib.displayname, iv.filepath, iv.filesize, iv.virtualizerconfig" + + " FROM imagebase AS ib" + + " JOIN imageversion AS iv ON (ib.latestversionid=iv.imageversionid AND ib.virtid = 'docker' AND ib.latestversionid IS NOT NULL)" + + " WHERE ib.imagebaseid = :imagebaseid"); + stmt.setString("imagebaseid", imagebaseid); + ResultSet rs = stmt.executeQuery(); + + JsonObject resultJson = new JsonObject(); + while (rs.next()) { + ContainerDefinition condev = ContainerDefinition.fromByteArray( + rs.getBytes("iv.virtualizerconfig")); + // currently only data images are returned + if (condev.getContainerMeta().getImageType() != ContainerMeta.ContainerImageType.DATA) + break; + + resultJson.addProperty("displayname", rs.getString("ib.displayname")); + resultJson.addProperty("imagepath", rs.getString("iv.filepath")); + resultJson.addProperty("filesize", rs.getString("iv.filesize")); + + resultJson.addProperty("image_recipe", condev.getContainerRecipe()); + resultJson.addProperty("image_repo", condev.getContainerMeta().getImageRepo()); + resultJson.addProperty("build_context_method", + condev.getContainerMeta().getContainerImageContext()); + resultJson.addProperty("build_context_url", condev.getContainerMeta().getBuildContextUrl()); + break; + } + + return resultJson.toString(); + } catch (Exception e) { + LOGGER.error("Query failed in DbImage.getContainerImages()", e); + throw e; + } + } + static class ContainerImages { public final String owner_firstname; public final String owner_lastname; 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 a3d9d293..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,12 +93,20 @@ 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(); } if (uri.startsWith("/bwlp/container/clusterimages")) { return serverContainerImages(); } + if (uri.startsWith("/image/container/")) { + if (parts.length < 4) + return badRequest("Bad Request"); + if (parts[3].equals("metadata")) + return serveContainerImageMetaData(parts[2]); + } if (uri.startsWith("/status/fileserver")) { return serveStatus(); @@ -120,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))); @@ -166,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); } } @@ -185,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; @@ -217,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(); @@ -270,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"); } @@ -299,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())); @@ -310,4 +314,14 @@ public class WebServer extends NanoHTTPD { return internalServerError(); } } + + private Response serveContainerImageMetaData(String imageBaseId) { + try { + return new Response(Response.Status.OK, "application/json; charset=utf-8", + DbImage.getContainerImageMetadata(imageBaseId)); + } catch (SQLException e) { + LOGGER.error("error -- could not server container image", e); + return internalServerError(); + } + } } |