package io.fathom.cloud.compute.scheduler; import io.fathom.cloud.CloudException; import io.fathom.cloud.blobs.BlobData; import io.fathom.cloud.blobs.TempFile; import io.fathom.cloud.services.ImageKey; import io.fathom.cloud.sftp.RemoteFile; import io.fathom.cloud.sftp.Sftp; import io.fathom.cloud.ssh.SftpChannel; import io.fathom.cloud.ssh.SshConfig; import java.io.Closeable; import java.io.File; import java.io.IOException; import java.util.UUID; public abstract class HostFilesystem { protected final SshConfig sshConfig; public HostFilesystem(SshConfig sshConfig) { this.sshConfig = sshConfig; } public File getRootFs(UUID containerId) { return new File("/var/fathomcloud/rootfs/" + containerId + "/"); } protected Sftp buildSftp() throws CloudException { return buildSftp(getImageTmpdir()); } protected Sftp buildSftp(RemoteFile tempDir) throws CloudException { SftpChannel sftpChannel; try { sftpChannel = sshConfig.getSftpChannel(); } catch (IOException e) { throw new CloudException("Error connecting to host", e); } return new Sftp(sftpChannel, tempDir); } protected RemoteFile getImagePath(ImageKey imageId) { RemoteFile imageDir = getImageBaseDir(); String name = imageId.getKey() + getImageExtension(); RemoteFile imageFile = new RemoteFile(imageDir, name); return imageFile; } protected abstract String getImageExtension(); protected File getVolumePath(VolumeType volumeType, UUID volumeId) { return new File("/volumes/" + volumeType.name().toLowerCase() + "/" + volumeId + "/"); } private RemoteFile getImageBaseDir() { RemoteFile imageDir = new RemoteFile(new File("/var/fathomcloud/images")); return imageDir; } protected RemoteFile getImageTmpdir() { RemoteFile imageDir = getImageBaseDir(); return new RemoteFile(imageDir, "tmp"); } public abstract void uploadImage(ImageKey imageId, BlobData imageData) throws IOException, CloudException; public boolean hasImage(ImageKey imageId) throws IOException, CloudException { RemoteFile imageFile = getImagePath(imageId); try (SftpChannel sftp = buildSftp()) { return sftp.exists(imageFile.getSshPath()); } } public abstract void copyImageToRootfs(ImageKey imageId, File rootfsPath) throws IOException; public abstract File createVolume(VolumeType volumeType, UUID containerId) throws IOException; /** * This is called when the image is frozen. It should prepare a snapshot as quickly as possible. * * The actual copying of the snapshot data should be placed into Snapshot.copyToFile, if possible. * * Cleanup of the snapshot should be done in Snapshot.close * * @param containerId * @return * @throws IOException */ public abstract Snapshot snapshotImage(UUID containerId) throws IOException; public interface Snapshot extends Closeable { TempFile copyToFile() throws IOException, CloudException; } public abstract void purgeInstance(UUID containerId) throws IOException; }