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.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.util.Util;
import org.openslx.util.TarArchiveUtil.TarArchiveReader;
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.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<LectureSummary> 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 boolean isDataContainer(ImageSummaryRead image) {
ContainerDefinition containerDefinition = getContainerDefinition(Session.getSatelliteToken(), image.getImageName(), image.getLatestVersionId());
if (containerDefinition.getContainerMeta().getImageType() == ContainerMeta.ContainerImageType.DATA) {
return true;
}
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)) {
ContainerDefinition containerDefinition = getContainerDefinition(satelliteToken, image.getImageName(), image.getLatestVersionId());
if (containerDefinition != null && containerDefinition.getContainerMeta().getImageType() == ContainerMeta.ContainerImageType.DATA)
dataContainerImages.add(image);
}
}
return dataContainerImages;
}
public static void showWarning(Component c, String message, Logger logger) {
Gui.showMessageBox(c, message,
MessageType.WARNING, logger, null);
}
public static ContainerDefinition getContainerDefinition(String satelliteToken, String imageName, String latestVersionId) {
byte[] rawVirtConfig = null;
if (latestVersionId == null) {
LOGGER.warn(String.format("LatestVersionID is null, cannot retrieve virtualizer config for image '%s'",imageName));
return null;
}
try {
ByteBuffer byteBuffer = ThriftManager.getSatClient().getImageVersionVirtConfig(satelliteToken,
latestVersionId);
rawVirtConfig = ThriftUtil.unwrapByteBuffer(byteBuffer);
} catch (TException e) {
LOGGER.error(String.format(" Failed to retrieve virtualizer config for image '%s' with image version '%s', see trace:",
imageName, latestVersionId), 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 {
TarArchiveReader tarReader = new TarArchiveReader(new FileInputStream(tarFile));
while (tarReader.hasNextEntry()) {
if (tarReader.getEntryName().equals("manifest.json")) {
containsManifest = true;
manifestJson = JsonParser.parseString(new String(tarReader.readCurrentEntry(), StandardCharsets.UTF_8))
.getAsJsonArray();
}
if (tarReader.getEntryName().equals("repositories")) {
containsRepositories = true;
// just check if the file exists
}
if (containsManifest && containsRepositories)
break;
}
Util.safeClose(tarReader);
} catch (IOException e) {
LOGGER.error("IOError while processing tar file", e);
}
// check the json files inside the tar file
try {
if (containsManifest && containsRepositories && manifestJson.isJsonArray() && manifestJson.size() == 1) {
isValid = true;
JsonArray jRepoTags = manifestJson.get(0).getAsJsonObject().getAsJsonArray("RepoTags");
if (jRepoTags.isEmpty())
LOGGER.info("Valid Docker-Archive with no repoTags recognized");
else
LOGGER.info(String.format("Valid Docker-Archive with repoTag=%s recognized", jRepoTags.get(0).toString()));
} 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 (IllegalStateException e) {
Gui.showMessageBox("An error occurred while checking the Docker archive!", MessageType.ERROR, LOGGER, null);
isValid=false;
}
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) {
if (image.imageBaseId.equals(imageBaseId))
return image.getImageName();
}
return imageBaseId;
}
}