summaryrefslogblamecommitdiffstats
path: root/src/main/java/org/openslx/virtualization/configuration/container/ContainerDefinition.java
blob: 825d0c36b18a47f3e52df6fb75d1aeb87a982ad5 (plain) (tree)
1
2
3
4
5
6
7
8




                                                           


                                           


                                                        




                                         



                                                                            

                                                                                                                     
 
                                                                                               



























                                                                                                        










                                                                                                                       
                                                                                                                            
 




                                                                                                      
                         
                                          







                                                                                                        


























                                                                                                                                        







                                                                                                           






                                                                                             

                                                                           






















                                                                                                     
 













                                                                                      
                                                                    














                                                                                   

                                                                                               














                                                                                                                
package org.openslx.virtualization.configuration.container;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.stream.JsonReader;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.openslx.util.Util;
import org.openslx.util.TarArchiveUtil.TarArchiveReader;
import org.openslx.util.TarArchiveUtil.TarArchiveWriter;

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Objects;

public class ContainerDefinition {

	//	TODO database needs a refactoring to store container details
	//  TODO refatoring: tar.gz of this object is not useful, for smaller dockerfiles it makes the package lager.
	//		 remove the containerRecipe, ContainerMeta holds in build_context the dockerfile.

	protected static final Logger LOGGER = LogManager.getLogger(ContainerDefinition.class);

	protected static final String CONTAINER_FILE = "dockerfile";
	protected static final String CONTAINER_META_FILE = "container_meta.json";

	/**
	 * The file to construct a real container image, could be an dockerfile or a singularity recipe.
	 */
	public String containerRecipe = "";

	/**
	 * Further container information, see {@link ContainerMeta}.
	 */
	public ContainerMeta containerMeta;

	public ContainerDefinition() {
		containerMeta = new ContainerMeta();
	}

	/**
	 * Copy Constructor
	 *
	 * @param containerDef {@link ContainerDefinition} from which to make a deep copy.
	 */
	public ContainerDefinition(ContainerDefinition containerDef) {
		containerRecipe = String.valueOf(containerDef.getContainerRecipe());
		containerMeta = new ContainerMeta(containerDef.getContainerMeta());
	}

	/**
	 * Utility function to create a {@link ContainerDefinition} object for a byte array downloaded from the server.
	 *
	 * @param rawTarData Downloaded tar.gz file from the server as a byte array.
	 * @return New object of ContainerDefinition.
	 */
	public static ContainerDefinition fromByteArray(byte[] rawTarData) {

		ContainerDefinition containerDef = new ContainerDefinition();

		try {
			TarArchiveReader tarReader = new TarArchiveReader(new ByteArrayInputStream(rawTarData), true, true);

			while (tarReader.hasNextEntry()) {
				if (tarReader.getEntryName().equals(CONTAINER_FILE))
					containerDef.setContainerRecipe(tarReader.readCurrentEntry());
				if (tarReader.getEntryName().equals(CONTAINER_META_FILE))
					containerDef.setContainerMeta(tarReader.readCurrentEntry());
			}
			tarReader.close();

		} catch (IOException e) {
			LOGGER.error("Could not create a ContainerDefinition Object for rawTarData", e);
		}

		return containerDef;
	}

	public String getContainerRecipe() {
		return containerRecipe;
	}

	public void setContainerRecipe(String containerRecipe) {
		this.containerRecipe = containerRecipe;
	}

	public void setContainerRecipe(File containerRecipeFile) {
		this.containerRecipe = readContainerRecipe(containerRecipeFile);
	}

	public void setContainerRecipe(byte[] rawContainerRecipe) {
		this.containerRecipe = new String(rawContainerRecipe, StandardCharsets.UTF_8);
	}

	public ContainerMeta getContainerMeta() {
		return containerMeta;
	}

	public void setContainerMeta(byte[] containerMeta) {
		Gson gson = new GsonBuilder().create();
		this.containerMeta = gson.fromJson(new JsonReader(
						new InputStreamReader(new ByteArrayInputStream(containerMeta), StandardCharsets.UTF_8)),
				ContainerMeta.class);
	}

	/**
	 * Serializes the ContainerMeta and Container Description (e.g. dockerfile) into an tar.gz archive.
	 *
	 * @return A ByteBuffer object of the container definition. Can be uploaded so satellite server.
	 */
	public ByteBuffer toByteBuffer() {

		ByteBuffer containerDef = null;
		Gson gson = new GsonBuilder().setPrettyPrinting().create();
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		try {			
			TarArchiveWriter tarWriter = new TarArchiveWriter(baos);
			tarWriter.writeFile(CONTAINER_META_FILE, gson.toJson(containerMeta));
			tarWriter.writeFile(CONTAINER_FILE, containerRecipe);
			Util.safeClose(tarWriter);

			containerDef = ByteBuffer.wrap(baos.toByteArray());
		} catch (IOException e) {
			LOGGER.warn("Could not create a tar file", e);
		}

		return containerDef;
	}

	private String readContainerRecipe(File file) {
		String recipe = null;
		try {

			BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
			ByteArrayOutputStream rawFile = new ByteArrayOutputStream();
			int count;
			byte[] data = new byte[1024];
			while ((count = bis.read(data)) != -1) {
				rawFile.write(data, 0, count);
			}

			String rawRecipe = new String(rawFile.toByteArray(), StandardCharsets.UTF_8);

			// replace windows by unix EOL
			recipe = rawRecipe.replaceAll("\\r\\n", "\n");

			bis.close();

		} catch (IOException e) {
			LOGGER.error("Could not read Container Recipe", e);
		}
		return recipe;
	}

	/**
	 * Saves containerRecipe and containerMeta at the provided location.
	 *
	 * @param destDir destination directory for containerRecipe and containerMeta.
	 */
	public void saveLocal(File destDir) {
		writeFile(destDir, containerRecipe, CONTAINER_FILE);
	}

	private void writeFile(File destDir, String fileContent, String filename) {
		File output = new File(destDir, filename);
		try {
			FileWriter fw = new FileWriter(output);
			fw.write(fileContent);
			fw.flush();
			fw.close();
		} catch (IOException e) {
			e.printStackTrace();
			LOGGER.error("Could not write File", e);
		}
	}

	public ContainerImageContext getContainerImageContext() {
		return ContainerImageContext.fromInt(containerMeta.getContainerImageContext());
	}

	@Override public boolean equals(Object o) {
		if (this == o)
			return true;
		if (o == null || getClass() != o.getClass())
			return false;
		ContainerDefinition that = (ContainerDefinition) o;
		return containerRecipe.equals(that.containerRecipe) && containerMeta.equals(that.containerMeta);
	}

	@Override public int hashCode() {
		return Objects.hash(containerRecipe, containerMeta);
	}
}