package org.openslx.dozmod.util; import com.google.gson.JsonArray; import com.google.gson.JsonParser; import org.apache.logging.log4j.LogManager; import org.apache.logging.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.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; /** * Class with some temporally Helper Functions. */ public class ContainerUtils { private static final Logger LOGGER = LogManager.getLogger(ContainerUtils.class); /** * 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. */ public static boolean isContainerImageLinked(ImageSummaryRead image) { if (image != null && image.getVirtId().equals(TConst.VIRT_DOCKER)) { List lectureSummaries = LectureCache.get(true); for (LectureSummary lecture : lectureSummaries) { // lecture.imageBaseId is null when no image linked to it -> NullPointer on // equals if (image.imageBaseId.equals(lecture.imageBaseId)) { return true; } } } return false; } public static List getDataContainerImages() { String satelliteToken = Session.getSatelliteToken(); List images = ImageCache.get(true); List 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); } 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 = JsonParser.parseString(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 images = ImageCache.get(true); for (ImageSummaryRead image : images) { if (image.imageBaseId.equals(imageBaseId)) return image.getImageName(); } return imageBaseId; } }