summaryrefslogtreecommitdiffstats
path: root/dozentenmodul/src/main/java/org/openslx/dozmod/model/ContainerDefinition.java
blob: e29d8d9cbda060bcfc05c0f5046fb54cd3e633f8 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
package org.openslx.dozmod.model;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.stream.JsonReader;
import org.apache.log4j.Logger;
import org.kamranzafar.jtar.TarEntry;
import org.kamranzafar.jtar.TarInputStream;
import org.kamranzafar.jtar.TarOutputStream;
import org.openslx.dozmod.thrift.cache.MetaDataCache;
import org.openslx.dozmod.util.TarArchiveUtil;
import org.openslx.util.vm.DockerMetaDataDummy;

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

public class ContainerDefinition {

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

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

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

	/**
	 * Further container information.
	 */
	public ContainerMeta containerMeta;

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

	public ContainerDefinition(ContainerMeta containerMeta) {
		this.containerMeta = containerMeta;
	}

	/**
	 * Constructor to create a temporal ContainerDefinition object, to construct DockerMetaDataDummy
	 * TODO i think this is a temp. solution and could be changed in a later cleanup.
	 *
	 * @param file          container recipe file
	 * @param containerMeta container meta object
	 */
	public ContainerDefinition(File file, ContainerMeta containerMeta) {
		this.containerDescription = readContainerRecipe(file);
		this.containerMeta = containerMeta;
	}

	public String getDescription() {
		return containerDescription;
	}

	public void setDescription(String description) {
		containerDescription = description;
	}

	public void setContainerDescription(byte[] containerDescription) {
		this.containerDescription = new String(containerDescription, StandardCharsets.UTF_8);
	}

	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);
	}

	public ContainerMeta getContainerMeta() {
		return containerMeta;
	}

	public DockerMetaDataDummy createVmMeta() {

		byte[] rawContainerDefinition = toByteBuffer().array();
		return new DockerMetaDataDummy(MetaDataCache.getOperatingSystems(), rawContainerDefinition,
				rawContainerDefinition.length);
	}

	public static ContainerDefinition fromByteArray(byte[] rawTarData) {

		ContainerDefinition containerDef = new ContainerDefinition();

		try {
			TarInputStream tis = new TarInputStream(
					new GZIPInputStream(new BufferedInputStream(new ByteArrayInputStream(rawTarData))));

			TarEntry entry;

			while ((entry = tis.getNextEntry()) != null) {
				int size = (int) entry.getSize();
				byte[] rawData = new byte[size];
				tis.read(rawData, 0, size);

				if (entry.getName().equals(CONTAINER_FILE))
					containerDef.setContainerDescription(rawData);
				if (entry.getName().equals(CONTAINER_META_FILE))
					containerDef.setContainerMeta(rawData);
			}

		} catch (IOException e) {
			e.printStackTrace();
		}

		return containerDef;
	}

	/**
	 * 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;

		try {
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			TarOutputStream output = new TarOutputStream(new GZIPOutputStream(baos));

			Gson gson = new GsonBuilder().setPrettyPrinting().create();
			TarArchiveUtil.tarPutFile(output, CONTAINER_META_FILE, gson.toJson(containerMeta));
			TarArchiveUtil.tarPutFile(output, CONTAINER_FILE, containerDescription);
			output.close();

			containerDef = ByteBuffer.wrap(baos.toByteArray());

		} catch (IOException e) {
			LOGGER.warn("Could not create a tar file", e);
		}

		return containerDef;
	}

	private String readContainerRecipe(File file) {
		byte[] rawFile = null;
		try {
			BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
			rawFile = new byte[(int) file.length()];
			bis.read(rawFile);

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

	private String byteArrayToString(byte[] containerRecipe) {
		return new String(containerRecipe, StandardCharsets.UTF_8);
	}

	public void saveLocal(File destDir) {

		writeFile(destDir, containerDescription, CONTAINER_FILE);

		Gson gson = new GsonBuilder().setPrettyPrinting().create();
		writeFile(destDir, gson.toJson(containerMeta), CONTAINER_META_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);
		}
	}

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

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