package pt.ist.fenix.task;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import org.fenixedu.academic.FenixEduAcademicConfiguration;
import org.fenixedu.bennu.core.domain.Bennu;
import org.fenixedu.bennu.io.domain.FileStorage;
import org.fenixedu.bennu.io.domain.FileSupport;
import org.fenixedu.bennu.io.domain.LocalFileSystemStorage;
import org.fenixedu.bennu.portal.domain.PortalConfiguration;
import org.fenixedu.bennu.scheduler.CronTask;
import org.fenixedu.bennu.scheduler.annotation.Task;
import pt.ist.fenix.FenixIstConfiguration;
import com.google.common.base.Objects;
import com.google.common.io.ByteStreams;
@Task(englishTitle = "Checks the AFS store's quota", readOnly = true)
public class CheckStoreQuota extends CronTask {
@Override
public void runTask() throws Exception {
List<String> messages = new ArrayList<>();
for (FileStorage store : FileSupport.getInstance().getFileStorageSet().stream()
.filter(store -> store instanceof LocalFileSystemStorage).collect(Collectors.toList())) {
LocalFileSystemStorage localStore = (LocalFileSystemStorage) store;
String path = localStore.getAbsolutePath();
taskLog("Path: %s\n", path);
if (path.startsWith("/tmp/")) {
continue;
}
Process process = Runtime.getRuntime().exec("fs listquota " + path);
String[] lines = new String(ByteStreams.toByteArray(process.getInputStream())).split("\n");
List<String> fragments =
Stream.of(lines[1].split(" ")).filter(str -> !str.trim().isEmpty()).collect(Collectors.toList());
long total = Integer.parseInt(fragments.get(1));
long current = Integer.parseInt(fragments.get(2));
BigDecimal occupation =
BigDecimal.valueOf(current).divide(BigDecimal.valueOf(total)).multiply(BigDecimal.valueOf(100));
taskLog("\tTotal: %s Current: %s, Occupied: %s\n", total, current, occupation);
if (occupation.longValue() > 90 && hasConfigurations(store)) {
messages.add("- " + store.getName() + ". Total: " + total + ", Current: " + current + ". Occupation: "
+ occupation);
}
}
if (!messages.isEmpty()) {
String subject =
"[" + PortalConfiguration.getInstance().getApplicationTitle().getContent() + "] File storage space alert";
String body = "File Storage Space alert!\n\n" + messages.stream().collect(Collectors.joining("\n"));
sendEmail(subject, body, FenixIstConfiguration.getConfiguration().getStoreQuotaWarningEmail());
taskLog("Notification sent!");
} else {
taskLog("Everything is ok!");
}
}
private void sendEmail(String subject, String body, String to) throws Exception {
Properties props = new Properties();
props.put("mail.smtp.host",
Objects.firstNonNull(FenixEduAcademicConfiguration.getConfiguration().getMailSmtpHost(), "localhost"));
Session session = Session.getDefaultInstance(props, null);
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(Bennu.getInstance().getSystemSender().getFromAddress()));
message.addRecipient(Message.RecipientType.TO, new InternetAddress(to));
message.setSubject(subject);
message.setText(body);
Multipart multipart = new MimeMultipart();
{
BodyPart messageBodyPart = new MimeBodyPart();
messageBodyPart.setText(body);
multipart.addBodyPart(messageBodyPart);
}
message.setContent(multipart);
Transport.send(message);
}
private boolean hasConfigurations(FileStorage store) {
return FileSupport.getInstance().getConfigurationSet().stream().anyMatch(config -> config.getStorage().equals(store));
}
}