This is an automated email from the ASF dual-hosted git repository. dimuthuupe pushed a commit to branch helix-integration in repository https://gitbox.apache.org/repos/asf/airavata.git
commit 4e1c1b0f1156f6453b81b7a58a30a196545e2489 Author: dimuthu <[email protected]> AuthorDate: Fri Mar 2 16:58:42 2018 -0500 Standalone email monitor initial implementation --- modules/job-monitor/pom.xml | 38 +++ .../airavata/job/monitor/EmailBasedMonitor.java | 309 +++++++++++++++++++ .../monitor/parser/AiravataCustomMailParser.java | 77 +++++ .../airavata/job/monitor/parser/EmailParser.java | 34 +++ .../job/monitor/parser/JobStatusResult.java | 63 ++++ .../job/monitor/parser/LSFEmailParser.java | 78 +++++ .../job/monitor/parser/PBSEmailParser.java | 105 +++++++ .../job/monitor/parser/ResourceConfig.java | 54 ++++ .../job/monitor/parser/SLURMEmailParser.java | 83 +++++ .../job/monitor/parser/UGEEmailParser.java | 109 +++++++ .../src/main/resources/airavata-server.properties | 334 +++++++++++++++++++++ .../src/main/resources/email-config.yaml | 20 ++ .../src/main/resources/log4j.properties | 9 + pom.xml | 3 + 14 files changed, 1316 insertions(+) diff --git a/modules/job-monitor/pom.xml b/modules/job-monitor/pom.xml new file mode 100644 index 0000000..c536a14 --- /dev/null +++ b/modules/job-monitor/pom.xml @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <parent> + <artifactId>airavata</artifactId> + <groupId>org.apache.airavata</groupId> + <version>0.17-SNAPSHOT</version> + <relativePath>../../pom.xml</relativePath> + </parent> + <modelVersion>4.0.0</modelVersion> + + <artifactId>job-monitor</artifactId> + + <dependencies> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + <version>1.7.25</version> + </dependency> + <dependency> + <groupId>javax.mail</groupId> + <artifactId>mail</artifactId> + <version>1.4.5</version> + </dependency> + <dependency> + <groupId>org.apache.airavata</groupId> + <artifactId>airavata-commons</artifactId> + <version>0.17-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.yaml</groupId> + <artifactId>snakeyaml</artifactId> + <version>1.15</version> + </dependency> + </dependencies> + +</project> \ No newline at end of file diff --git a/modules/job-monitor/src/main/java/org/apache/airavata/job/monitor/EmailBasedMonitor.java b/modules/job-monitor/src/main/java/org/apache/airavata/job/monitor/EmailBasedMonitor.java new file mode 100644 index 0000000..7b13354 --- /dev/null +++ b/modules/job-monitor/src/main/java/org/apache/airavata/job/monitor/EmailBasedMonitor.java @@ -0,0 +1,309 @@ +package org.apache.airavata.job.monitor; + +import org.apache.airavata.common.exception.AiravataException; +import org.apache.airavata.common.utils.ServerSettings; +import org.apache.airavata.job.monitor.parser.EmailParser; +import org.apache.airavata.job.monitor.parser.JobStatusResult; +import org.apache.airavata.job.monitor.parser.ResourceConfig; +import org.apache.airavata.model.appcatalog.computeresource.JobSubmissionProtocol; +import org.apache.airavata.model.appcatalog.computeresource.ResourceJobManagerType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.yaml.snakeyaml.Yaml; + +import javax.mail.Address; +import javax.mail.Flags; +import javax.mail.Folder; +import javax.mail.Message; +import javax.mail.MessagingException; +import javax.mail.Session; +import javax.mail.Store; +import javax.mail.search.FlagTerm; +import javax.mail.search.SearchTerm; +import java.io.FileReader; +import java.io.InputStream; +import java.io.Reader; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + +public class EmailBasedMonitor implements Runnable { + + private static final Logger log = LoggerFactory.getLogger(EmailBasedMonitor.class); + + public static final int COMPARISON = 6; // after and equal + public static final String IMAPS = "imaps"; + public static final String POP3 = "pop3"; + private boolean stopMonitoring = false; + + private Session session ; + private Store store; + private Folder emailFolder; + private Properties properties; + //private Map<String, TaskContext> jobMonitorMap = new ConcurrentHashMap<>(); + private String host, emailAddress, password, storeProtocol, folderName ; + private Date monitorStartDate; + private Map<ResourceJobManagerType, EmailParser> emailParserMap = new HashMap<ResourceJobManagerType, EmailParser>(); + private Map<String, ResourceJobManagerType> addressMap = new HashMap<>(); + private Message[] flushUnseenMessages; + private Map<String, Boolean> canceledJobs = new ConcurrentHashMap<>(); + private Timer timer; + private Map<ResourceJobManagerType, ResourceConfig> resourceConfigs = new HashMap<>(); + + + public EmailBasedMonitor() throws Exception { + init(); + populateAddressAndParserMap(resourceConfigs); + } + + private void init() throws Exception { + loadContext(); + host = ServerSettings.getEmailBasedMonitorHost(); + emailAddress = ServerSettings.getEmailBasedMonitorAddress(); + password = ServerSettings.getEmailBasedMonitorPassword(); + storeProtocol = ServerSettings.getEmailBasedMonitorStoreProtocol(); + folderName = ServerSettings.getEmailBasedMonitorFolderName(); + if (!(storeProtocol.equals(IMAPS) || storeProtocol.equals(POP3))) { + throw new AiravataException("Unsupported store protocol , expected " + + IMAPS + " or " + POP3 + " but found " + storeProtocol); + } + properties = new Properties(); + properties.put("mail.store.protocol", storeProtocol); + timer = new Timer("CancelJobHandler", true); + long period = 1000 * 60 * 5; // five minute delay between successive task executions. + } + + private void loadContext() throws Exception { + Yaml yaml = new Yaml(); + InputStream emailConfigStream = EmailBasedMonitor.class.getClassLoader().getResourceAsStream("email-config.yaml"); + Object load = yaml.load(emailConfigStream); + + if (load == null) { + throw new Exception("Could not load the configuration"); + } + + if (load instanceof Map) { + Map<String, Object> loadMap = (Map<String, Object>) load; + Map<String, Object> configMap = (Map<String, Object>) loadMap.get("config"); + List<Map<String,Object >> resourceObjs = (List<Map<String, Object>>) configMap.get("resources"); + if (resourceObjs != null) { + resourceObjs.forEach(resource -> { + ResourceConfig resourceConfig = new ResourceConfig(); + String identifier = resource.get("jobManagerType").toString(); + resourceConfig.setJobManagerType(ResourceJobManagerType.valueOf(identifier)); + Object emailParser = resource.get("emailParser"); + if (emailParser != null){ + resourceConfig.setEmailParser(emailParser.toString()); + } + List<String> emailAddressList = (List<String>) resource.get("resourceEmailAddresses"); + resourceConfig.setResourceEmailAddresses(emailAddressList); + resourceConfigs.put(resourceConfig.getJobManagerType(), resourceConfig); + }); + } + } + populateAddressAndParserMap(resourceConfigs); + } + + private void populateAddressAndParserMap(Map<ResourceJobManagerType, ResourceConfig> resourceConfigs) throws AiravataException { + for (Map.Entry<ResourceJobManagerType, ResourceConfig> resourceConfigEntry : resourceConfigs.entrySet()) { + ResourceJobManagerType type = resourceConfigEntry.getKey(); + ResourceConfig config = resourceConfigEntry.getValue(); + List<String> resourceEmailAddresses = config.getResourceEmailAddresses(); + if (resourceEmailAddresses != null && !resourceEmailAddresses.isEmpty()){ + for (String resourceEmailAddress : resourceEmailAddresses) { + addressMap.put(resourceEmailAddress, type); + } + try { + Class<? extends EmailParser> emailParserClass = Class.forName(config.getEmailParser()).asSubclass(EmailParser.class); + EmailParser emailParser = emailParserClass.getConstructor().newInstance(); + emailParserMap.put(type, emailParser); + } catch (Exception e) { + throw new AiravataException("Error while instantiation email parsers", e); + } + } + } + + } + + public void monitor(String jobId) { + log.info("[EJM]: Added monitor Id : {} to email based monitor map", jobId); + } + + public void stopMonitor(String jobId, boolean runOutflow) { + + } + + public boolean isMonitoring(String jobId) { + return true; + } + + public void canceledJob(String jobId) { + + } + + private JobStatusResult parse(Message message) throws MessagingException, AiravataException { + Address fromAddress = message.getFrom()[0]; + String addressStr = fromAddress.toString(); + ResourceJobManagerType jobMonitorType = getJobMonitorType(addressStr); + EmailParser emailParser = emailParserMap.get(jobMonitorType); + if (emailParser == null) { + throw new AiravataException("[EJM]: Un-handle resource job manager type: " + jobMonitorType + .toString() + " for email monitoring --> " + addressStr); + } + return emailParser.parseEmail(message); + } + + private ResourceJobManagerType getJobMonitorType(String addressStr) throws AiravataException { +// System.out.println("*********** address ******** : " + addressStr); + for (Map.Entry<String, ResourceJobManagerType> addressEntry : addressMap.entrySet()) { + if (addressStr.contains(addressEntry.getKey())) { + return addressEntry.getValue(); + } + } + throw new AiravataException("[EJM]: Couldn't identify Resource job manager type from address " + addressStr); + } + + @Override + public void run() { + boolean quite = false; + + while (!stopMonitoring && !ServerSettings.isStopAllThreads()) { + try { + session = Session.getDefaultInstance(properties); + store = session.getStore(storeProtocol); + store.connect(host, emailAddress, password); + emailFolder = store.getFolder(folderName); + // first time we search for all unread messages. + SearchTerm unseenBefore = new FlagTerm(new Flags(Flags.Flag.SEEN), false); + while (!(stopMonitoring || ServerSettings.isStopAllThreads())) { + Thread.sleep(ServerSettings.getEmailMonitorPeriod());// sleep a bit - get a rest till job finishes + if (!store.isConnected()) { + store.connect(); + emailFolder = store.getFolder(folderName); + } + log.info("[EJM]: Retrieving unseen emails"); + emailFolder.open(Folder.READ_WRITE); + if (emailFolder.isOpen()) { + // flush if any message left in flushUnseenMessage + if (flushUnseenMessages != null && flushUnseenMessages.length > 0) { + try { + emailFolder.setFlags(flushUnseenMessages, new Flags(Flags.Flag.SEEN), false); + flushUnseenMessages = null; + } catch (MessagingException e) { + if (!store.isConnected()) { + store.connect(); + emailFolder.setFlags(flushUnseenMessages, new Flags(Flags.Flag.SEEN), false); + flushUnseenMessages = null; + } + } + } + Message[] searchMessages = emailFolder.search(unseenBefore); + if (searchMessages == null || searchMessages.length == 0) { + log.info("[EJM]: No new email messages"); + } else { + log.info("[EJM]: " + searchMessages.length + " new email/s received"); + } + processMessages(searchMessages); + emailFolder.close(false); + } + } + } catch (MessagingException e) { + log.error("[EJM]: Couldn't connect to the store ", e); + } catch (InterruptedException e) { + log.error("[EJM]: Interrupt exception while sleep ", e); + } catch (AiravataException e) { + log.error("[EJM]: UnHandled arguments ", e); + } catch (Throwable e) { + log.error("[EJM]: Caught a throwable ", e); + } finally { + try { + emailFolder.close(false); + store.close(); + } catch (MessagingException e) { + log.error("[EJM]: Store close operation failed, couldn't close store", e); + } catch (Throwable e) { + log.error("[EJM]: Caught a throwable while closing email store ", e); + } + } + } + log.info("[EJM]: Email monitoring daemon stopped"); + } + + private void processMessages(Message[] searchMessages) throws MessagingException { + List<Message> processedMessages = new ArrayList<>(); + List<Message> unreadMessages = new ArrayList<>(); + for (Message message : searchMessages) { + try { + JobStatusResult jobStatusResult = parse(message); + log.info(jobStatusResult.getJobId() + ", " + jobStatusResult.getJobName() + ", " + jobStatusResult.getState().getValue()); + //processedMessages.add(message); + unreadMessages.add(message); + } catch (Exception e) { + unreadMessages.add(message); + } + } + if (!processedMessages.isEmpty()) { + Message[] seenMessages = new Message[processedMessages.size()]; + processedMessages.toArray(seenMessages); + try { + emailFolder.setFlags(seenMessages, new Flags(Flags.Flag.SEEN), true); + } catch (MessagingException e) { + if (!store.isConnected()) { + store.connect(); + emailFolder.setFlags(seenMessages, new Flags(Flags.Flag.SEEN), true); + } + } + + } + if (!unreadMessages.isEmpty()) { + Message[] unseenMessages = new Message[unreadMessages.size()]; + unreadMessages.toArray(unseenMessages); + try { + emailFolder.setFlags(unseenMessages, new Flags(Flags.Flag.SEEN), false); + } catch (MessagingException e) { + if (!store.isConnected()) { + store.connect(); + emailFolder.setFlags(unseenMessages, new Flags(Flags.Flag.SEEN), false); + flushUnseenMessages = unseenMessages; // anyway we need to push this update. + } else { + flushUnseenMessages = unseenMessages; // anyway we need to push this update. + } + } + } + } + + private void process(JobStatusResult jobStatusResult){ + + } + + private void writeEnvelopeOnError(Message m) throws MessagingException { + Address[] a; + // FROM + if ((a = m.getFrom()) != null) { + for (int j = 0; j < a.length; j++) + log.error("FROM: " + a[j].toString()); + } + // TO + if ((a = m.getRecipients(Message.RecipientType.TO)) != null) { + for (int j = 0; j < a.length; j++) + log.error("TO: " + a[j].toString()); + } + // SUBJECT + if (m.getSubject() != null) + log.error("SUBJECT: " + m.getSubject()); + } + + public void stopMonitoring() { + stopMonitoring = true; + } + + public void setDate(Date date) { + this.monitorStartDate = date; + } + + public static void main(String args[]) throws Exception { + EmailBasedMonitor monitor = new EmailBasedMonitor(); + Thread t = new Thread(monitor); + t.start(); + t.join(); + } +} diff --git a/modules/job-monitor/src/main/java/org/apache/airavata/job/monitor/parser/AiravataCustomMailParser.java b/modules/job-monitor/src/main/java/org/apache/airavata/job/monitor/parser/AiravataCustomMailParser.java new file mode 100644 index 0000000..871c956 --- /dev/null +++ b/modules/job-monitor/src/main/java/org/apache/airavata/job/monitor/parser/AiravataCustomMailParser.java @@ -0,0 +1,77 @@ +/** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.airavata.job.monitor.parser; + +import org.apache.airavata.common.exception.AiravataException; +import org.apache.airavata.model.status.JobState; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.mail.Message; +import javax.mail.MessagingException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class AiravataCustomMailParser implements EmailParser { + + private static final Logger log = LoggerFactory.getLogger(SLURMEmailParser.class); + + private static final String REGEX = "[a-zA-Z]*_[a-z]*=(?<" + JOBID + ">\\d*)[ ]*[a-zA-Z]*=(?<" + + JOBNAME + ">[a-zA-Z0-9-]*)[ ]*[a-zA-Z]*=(?<" + STATUS + ">[a-zA-Z]*).*"; + + public static final String COMPLETED = "COMPLETED"; + private static final Pattern pattern = Pattern.compile(REGEX); + + @Override + public JobStatusResult parseEmail(Message message) throws MessagingException, AiravataException { + JobStatusResult jobStatusResult = new JobStatusResult(); + parseSubject(message.getSubject(), jobStatusResult); + return jobStatusResult; + } + + private void parseSubject(String subject, JobStatusResult jobStatusResult) throws MessagingException { + Matcher matcher = pattern.matcher(subject); + if (matcher.find()) { + jobStatusResult.setJobId(matcher.group(JOBID)); + jobStatusResult.setJobName(matcher.group(JOBNAME)); + jobStatusResult.setState(getJobState(matcher.group(STATUS))); + jobStatusResult.setAuthoritative(false); + + try { + //Waiting some time for the scheduler to move the job from completing to completed. + Thread.sleep(5000); + } catch (Exception ex) { + } + + } else { + log.error("[EJM]: No matched found for subject -> " + subject); + } + } + + private JobState getJobState(String state) { + switch (state.trim()) { + case COMPLETED: + return JobState.COMPLETE; + default: + log.error("[EJM]: Job State " + state + " isn't handle by Airavata custom parser"); + return JobState.UNKNOWN; + } + } +} \ No newline at end of file diff --git a/modules/job-monitor/src/main/java/org/apache/airavata/job/monitor/parser/EmailParser.java b/modules/job-monitor/src/main/java/org/apache/airavata/job/monitor/parser/EmailParser.java new file mode 100644 index 0000000..2bb3cc0 --- /dev/null +++ b/modules/job-monitor/src/main/java/org/apache/airavata/job/monitor/parser/EmailParser.java @@ -0,0 +1,34 @@ +/** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.airavata.job.monitor.parser; + +import org.apache.airavata.common.exception.AiravataException; + +import javax.mail.Message; +import javax.mail.MessagingException; + +public interface EmailParser { + static final String STATUS = "status"; + static final String JOBID = "jobId"; + static final String JOBNAME = "jobName"; + static final String EXIT_STATUS = "exitStatus"; + + JobStatusResult parseEmail(Message message) throws MessagingException, AiravataException; +} diff --git a/modules/job-monitor/src/main/java/org/apache/airavata/job/monitor/parser/JobStatusResult.java b/modules/job-monitor/src/main/java/org/apache/airavata/job/monitor/parser/JobStatusResult.java new file mode 100644 index 0000000..6019ae6 --- /dev/null +++ b/modules/job-monitor/src/main/java/org/apache/airavata/job/monitor/parser/JobStatusResult.java @@ -0,0 +1,63 @@ +/** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.airavata.job.monitor.parser; + + +import org.apache.airavata.model.status.JobState; + +public class JobStatusResult { + private JobState state; + private String jobId; + private String jobName; + private boolean authoritative = true; + + public String getJobName() { + return jobName; + } + + public void setJobName(String jobName) { + this.jobName = jobName; + } + + public JobState getState() { + return state; + } + + public void setState(JobState state) { + this.state = state; + } + + public String getJobId() { + return jobId; + } + + public void setJobId(String jobId) { + this.jobId = jobId; + } + + public boolean isAuthoritative() { + return authoritative; + } + + public void setAuthoritative(boolean authoritative) { + this.authoritative = authoritative; + } +} + diff --git a/modules/job-monitor/src/main/java/org/apache/airavata/job/monitor/parser/LSFEmailParser.java b/modules/job-monitor/src/main/java/org/apache/airavata/job/monitor/parser/LSFEmailParser.java new file mode 100644 index 0000000..70d6f9d --- /dev/null +++ b/modules/job-monitor/src/main/java/org/apache/airavata/job/monitor/parser/LSFEmailParser.java @@ -0,0 +1,78 @@ +/** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.airavata.job.monitor.parser; + +import org.apache.airavata.common.exception.AiravataException; +import org.apache.airavata.model.status.JobState; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.mail.Message; +import javax.mail.MessagingException; +import java.io.IOException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class LSFEmailParser implements EmailParser { + private static final Logger log = LoggerFactory.getLogger(LSFEmailParser.class); + private static final String REGEX = "[a-zA-Z]+\\s+(?<" + JOBID + ">[\\d]+):\\s+<(?<" + JOBNAME + ">[a-zA-Z0-9]+)>\\s+(?<" + STATUS + ">[a-zA-Z]+)"; + public static final String STARTED = "started"; + public static final String COMPLETE = "Done"; + public static final String FAILED = "Exited"; + + @Override + public JobStatusResult parseEmail(Message message) throws MessagingException, AiravataException { + JobStatusResult jobStatusResult = new JobStatusResult(); + + parseContent(message, jobStatusResult); + return jobStatusResult; + } + + private void parseContent(Message message, JobStatusResult jobStatusResult) throws MessagingException, AiravataException { + String subject = message.getSubject(); + Pattern pattern = Pattern.compile(REGEX); + Matcher matcher = pattern.matcher(subject); + try { + if (matcher.find()) { + jobStatusResult.setJobId(matcher.group(JOBID)); + jobStatusResult.setJobName(matcher.group(JOBNAME)); + String content = (String) message.getContent(); + jobStatusResult.setState(getJobState(matcher.group(STATUS), content)); + } else { + log.error("[EJM]: No matched found for subject => \n" + subject); + } + } catch (IOException e) { + throw new AiravataException("[EJM]: Error while reading content of the email message"); + } + } + + private JobState getJobState(String status, String content) { + switch (status) { + case STARTED: + return JobState.ACTIVE; + case COMPLETE: + return JobState.COMPLETE; + case FAILED: + return JobState.FAILED; + default: + return JobState.UNKNOWN; + } + } +} diff --git a/modules/job-monitor/src/main/java/org/apache/airavata/job/monitor/parser/PBSEmailParser.java b/modules/job-monitor/src/main/java/org/apache/airavata/job/monitor/parser/PBSEmailParser.java new file mode 100644 index 0000000..12fd5cb --- /dev/null +++ b/modules/job-monitor/src/main/java/org/apache/airavata/job/monitor/parser/PBSEmailParser.java @@ -0,0 +1,105 @@ +/** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.airavata.job.monitor.parser; + +import org.apache.airavata.common.exception.AiravataException; +import org.apache.airavata.model.status.JobState; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.mail.Message; +import javax.mail.MessagingException; +import java.io.IOException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class PBSEmailParser implements EmailParser { + private static final Logger log = LoggerFactory.getLogger(PBSEmailParser.class); + public static final String BEGUN_EXECUTION = "Begun execution"; + public static final String EXECUTION_TERMINATED = "Execution terminated"; + public static final String ABORTED_BY_PBS_SERVER = "Aborted by PBS Server"; + + static final String REGEX = "[a-zA-Z ]*:[ ]*(?<" + JOBID + ">[a-zA-Z0-9-_\\.]*)\\s+[a-zA-Z ]*:[ ]*(?<" + + JOBNAME + ">[a-zA-Z0-9-\\.]*)\\s[\\S|\\s]*(?<" + STATUS + ">" + BEGUN_EXECUTION + "|" + + EXECUTION_TERMINATED + "|" + ABORTED_BY_PBS_SERVER + ")"; + + private static final String REGEX_EXIT_STATUS = "Exit_status=(?<" + EXIT_STATUS + ">[\\d]+)"; + + @Override + public JobStatusResult parseEmail(Message message) throws MessagingException, AiravataException { + JobStatusResult jobStatusResult = new JobStatusResult(); +// log.info("Parsing -> " + message.getSubject()); + try { + String content = ((String) message.getContent()); + parseContent(content, jobStatusResult); + } catch (IOException e) { + throw new AiravataException("[EJM]: Error while reading content of the email message"); + } + return jobStatusResult; + } + + void parseContent(String content, JobStatusResult jobStatusResult) throws MessagingException, AiravataException { + content = content.replaceAll("[^\\x00-\\x7F]", ""); + Pattern pattern = Pattern.compile(REGEX); + Matcher matcher = pattern.matcher(content); + if (matcher.find()) { + jobStatusResult.setJobId(matcher.group(JOBID)); + jobStatusResult.setJobName(matcher.group(JOBNAME)); + String statusLine = matcher.group(STATUS); + jobStatusResult.setState(getJobState(statusLine, content)); + } else { + log.error("[EJM]: No matched found for content => \n" + content); + } + } + + private JobState getJobState(String statusLine, String content) { + switch (statusLine) { + case BEGUN_EXECUTION: + return JobState.ACTIVE; + case EXECUTION_TERMINATED: + int exitStatus = getExitStatus(content); + if (exitStatus == 0) { + // TODO - Remove rabbitmq client script line from the script. + return JobState.COMPLETE; + } else if (exitStatus == 271) { + return JobState.CANCELED; + } else { + return JobState.FAILED; + } + case ABORTED_BY_PBS_SERVER: + return JobState.FAILED; + default: + return JobState.UNKNOWN; + } + } + + private int getExitStatus(String content) { + Pattern pattern = Pattern.compile(REGEX_EXIT_STATUS); + Matcher matcher = pattern.matcher(content); + if (matcher.find()) { + String group = matcher.group(EXIT_STATUS); + if (group != null && !group.trim().isEmpty()) { + return Integer.valueOf(group.trim()); + } + } + return -1; + } + +} diff --git a/modules/job-monitor/src/main/java/org/apache/airavata/job/monitor/parser/ResourceConfig.java b/modules/job-monitor/src/main/java/org/apache/airavata/job/monitor/parser/ResourceConfig.java new file mode 100644 index 0000000..aacbc2d --- /dev/null +++ b/modules/job-monitor/src/main/java/org/apache/airavata/job/monitor/parser/ResourceConfig.java @@ -0,0 +1,54 @@ +/** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.airavata.job.monitor.parser; + +import org.apache.airavata.model.appcatalog.computeresource.ResourceJobManagerType; + +import java.util.List; + +public class ResourceConfig { + private ResourceJobManagerType jobManagerType; + private String emailParser; + private List<String> resourceEmailAddresses; + + public ResourceJobManagerType getJobManagerType() { + return jobManagerType; + } + + public void setJobManagerType(ResourceJobManagerType jobManagerType) { + this.jobManagerType = jobManagerType; + } + + public String getEmailParser() { + return emailParser; + } + + public void setEmailParser(String emailParser) { + this.emailParser = emailParser; + } + + public List<String> getResourceEmailAddresses() { + return resourceEmailAddresses; + } + + public void setResourceEmailAddresses(List<String> resourceEmailAddresses) { + this.resourceEmailAddresses = resourceEmailAddresses; + } +} diff --git a/modules/job-monitor/src/main/java/org/apache/airavata/job/monitor/parser/SLURMEmailParser.java b/modules/job-monitor/src/main/java/org/apache/airavata/job/monitor/parser/SLURMEmailParser.java new file mode 100644 index 0000000..d06c8b1 --- /dev/null +++ b/modules/job-monitor/src/main/java/org/apache/airavata/job/monitor/parser/SLURMEmailParser.java @@ -0,0 +1,83 @@ +/** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.airavata.job.monitor.parser; + +import org.apache.airavata.common.exception.AiravataException; +import org.apache.airavata.model.status.JobState; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.mail.Message; +import javax.mail.MessagingException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class SLURMEmailParser implements EmailParser { + + private static final Logger log = LoggerFactory.getLogger(SLURMEmailParser.class); + + private static final String REGEX = "[A-Z]*\\s[a-zA-Z]*_[a-z]*=(?<" + JOBID + ">\\d*)[ ]*[a-zA-Z]*=(?<"+ + JOBNAME + ">[a-zA-Z0-9-]*)[ ]*(?<" + STATUS + ">[]a-zA-Z ]*),.*"; + + public static final String BEGAN = "Began"; + public static final String STAGE_OUT = "Staged Out"; + public static final String ENDED = "Ended"; + public static final String FAILED = "Failed"; + private static final Pattern cancelledStatePattern = Pattern.compile("CANCELLED"); + private static final Pattern pattern = Pattern.compile(REGEX); + + @Override + public JobStatusResult parseEmail(Message message) throws MessagingException, AiravataException{ + JobStatusResult jobStatusResult = new JobStatusResult(); + parseSubject(message.getSubject(), jobStatusResult); + return jobStatusResult; + } + + private void parseSubject(String subject, JobStatusResult jobStatusResult) throws MessagingException { + Matcher matcher = pattern.matcher(subject); + if (matcher.find()) { + jobStatusResult.setJobId(matcher.group(JOBID)); + jobStatusResult.setJobName(matcher.group(JOBNAME)); + jobStatusResult.setState(getJobState(matcher.group(STATUS), subject)); + } else { + log.error("[EJM]: No matched found for subject -> " + subject); + } + } + + private JobState getJobState(String state, String subject) { + switch (state.trim()) { + case BEGAN: case STAGE_OUT: + return JobState.ACTIVE; + case ENDED: + Matcher matcher = cancelledStatePattern.matcher(subject); + if (matcher.find()) { + return JobState.CANCELED; + } + return JobState.COMPLETE; + case FAILED: + return JobState.FAILED; + default: + log.error("[EJM]: Job State " + state + " isn't handle by SLURM parser"); + return JobState.UNKNOWN; + + } + } + +} diff --git a/modules/job-monitor/src/main/java/org/apache/airavata/job/monitor/parser/UGEEmailParser.java b/modules/job-monitor/src/main/java/org/apache/airavata/job/monitor/parser/UGEEmailParser.java new file mode 100644 index 0000000..da2866f --- /dev/null +++ b/modules/job-monitor/src/main/java/org/apache/airavata/job/monitor/parser/UGEEmailParser.java @@ -0,0 +1,109 @@ +/** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.airavata.job.monitor.parser; + +import org.apache.airavata.common.exception.AiravataException; +import org.apache.airavata.model.status.JobState; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.mail.Message; +import javax.mail.MessagingException; +import java.io.IOException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class UGEEmailParser implements EmailParser { + + private static final Logger log = LoggerFactory.getLogger(UGEEmailParser.class); + private static final String REGEX = "[\\w]*[ ]*(?<"+ JOBID + ">[\\d]*)[ ]*\\((?<" + JOBNAME + + ">[a-zA-Z0-9]*)\\)[ ]*(?<" + STATUS + ">[a-zA-Z]*)"; + public static final String STARTED = "Started"; + public static final String COMPLETE = "Complete"; + public static final String FAILED = "Failed"; + public static final String KILLED = "Killed"; + private static final String REGEX_EXIT_STATUS = "Exit Status[ ]*=[ ]*(?<" + EXIT_STATUS + ">[\\d]+)"; + public static final String ABORTED = "Aborted"; + + + @Override + public JobStatusResult parseEmail(Message message) throws MessagingException, AiravataException { + JobStatusResult jobStatusResult = new JobStatusResult(); + + parseContent(message, jobStatusResult); + return jobStatusResult; + } + + private void parseContent(Message message, JobStatusResult jobStatusResult) throws MessagingException, AiravataException { + String subject = message.getSubject(); + + //FIXME - HACK to handle Little Dog email issue from SIU + subject = subject.replace("Set in error state", "Failed"); + + Pattern pattern = Pattern.compile(REGEX); + Matcher matcher = pattern.matcher(subject); + try { + if (matcher.find()) { + jobStatusResult.setJobId(matcher.group(JOBID)); + jobStatusResult.setJobName(matcher.group(JOBNAME)); + String content = (String) message.getContent(); + jobStatusResult.setState(getJobState(matcher.group(STATUS), content)); + } else { + log.error("[EJM]: No matched found for subject => \n" + subject); + } + } catch (IOException e) { + throw new AiravataException("[EJM]: Error while reading content of the email message"); + } + } + + private JobState getJobState(String status, String content) { + switch (status) { + case STARTED: + return JobState.ACTIVE; + case COMPLETE: + int exitStatus = getExitStatus(content); + if (exitStatus == 0) { + return JobState.COMPLETE; + } else { + log.info("[EJM]: Job returns with Exit Status = " + exitStatus + " , Marked as Failed"); + return JobState.FAILED; + } + case FAILED: + return JobState.FAILED; + case ABORTED: + return JobState.CANCELED; + default: + return JobState.UNKNOWN; + + } + } + + private int getExitStatus(String content) { + Pattern statusPattern = Pattern.compile(REGEX_EXIT_STATUS); + Matcher statusMatcher = statusPattern.matcher(content); + if (statusMatcher.find()) { + String group = statusMatcher.group(EXIT_STATUS); + if (group != null && !group.trim().isEmpty()) { + return Integer.valueOf(group.trim()); + } + } + return -1; + } +} diff --git a/modules/job-monitor/src/main/resources/airavata-server.properties b/modules/job-monitor/src/main/resources/airavata-server.properties new file mode 100644 index 0000000..b54b28c --- /dev/null +++ b/modules/job-monitor/src/main/resources/airavata-server.properties @@ -0,0 +1,334 @@ +# +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +########################################################################### +# +# This properties file provides configuration for all Airavata Services: +# API Server, Registry, Workflow Interpreter, GFac, Orchestrator +# +########################################################################### + +########################################################################### +# API Server Registry Configuration +########################################################################### + +#for derby [AiravataJPARegistry] +#registry.jdbc.driver=org.apache.derby.jdbc.ClientDriver +#registry.jdbc.url=jdbc:derby://localhost:1527/experiment_catalog;create=true;user=airavata;password=airavata +# MariaDB database configuration +registry.jdbc.driver=org.mariadb.jdbc.Driver +registry.jdbc.url=jdbc:mariadb://149.165.168.248:3306/experiment_catalog +registry.jdbc.user=eroma +registry.jdbc.password=eroma123456 +#FIXME: Probably the following property should be removed. +start.derby.server.mode=false +validationQuery=SELECT 1 from CONFIGURATION +cache.enable=false +jpa.cache.size=-1 +#jpa.connection.properties=MaxActive=10,MaxIdle=5,MinIdle=2,MaxWait=60000,testWhileIdle=true,testOnBorrow=true +enable.sharing=true + +# Properties for default user mode +default.registry.user=default-admin +default.registry.password=123456 +default.registry.password.hash.method=SHA +default.registry.gateway=default +super.tenant.gatewayId=default + +# Properties for cluster status monitoring +# cluster status monitoring job repeat time in seconds +cluster.status.monitoring.enable=false +cluster.status.monitoring.repeat.time=18000 + +########################################################################### +# Application Catalog DB Configuration +########################################################################### +#for derby [AiravataJPARegistry] +#appcatalog.jdbc.driver=org.apache.derby.jdbc.ClientDriver +#appcatalog.jdbc.url=jdbc:derby://localhost:1527/app_catalog;create=true;user=airavata;password=airavata +# MariaDB database configuration +appcatalog.jdbc.driver=org.mariadb.jdbc.Driver +appcatalog.jdbc.url=jdbc:mariadb://149.165.168.248:3306/app_catalog +appcatalog.jdbc.user=eroma +appcatalog.jdbc.password=eroma123456 +appcatalog.validationQuery=SELECT 1 from CONFIGURATION + +########################################################################## +# Replica Catalog DB Configuration +########################################################################### +#for derby [AiravataJPARegistry] +#replicacatalog.jdbc.driver=org.apache.derby.jdbc.ClientDriver +#replicacatalog.jdbc.url=jdbc:derby://localhost:1527/replica_catalog;create=true;user=airavata;password=airavata +# MariaDB database configuration +replicacatalog.jdbc.driver=org.mariadb.jdbc.Driver +replicacatalog.jdbc.url=jdbc:mariadb://149.165.168.248:3306/replica_catalog +replicacatalog.jdbc.user=eroma +replicacatalog.jdbc.password=eroma123456 +replicacatalog.validationQuery=SELECT 1 from CONFIGURATION + +########################################################################### +# Workflow Catalog DB Configuration +########################################################################### +#for derby [AiravataJPARegistry] +#workflowcatalog.jdbc.driver=org.apache.derby.jdbc.ClientDriver +#workflowcatalog.jdbc.url=jdbc:derby://localhost:1527/workflow_catalog;create=true;user=airavata;password=airavata +# MariaDB database configuration +workflowcatalog.jdbc.driver=org.mariadb.jdbc.Driver +workflowcatalog.jdbc.url=jdbc:mariadb://149.165.168.248:3306/replica_catalog +workflowcatalog.jdbc.user=eroma +workflowcatalog.jdbc.password=eroma123456 +workflowcatalog.validationQuery=SELECT 1 from CONFIGURATION + +########################################################################### +# Sharing Catalog DB Configuration +########################################################################### +#for derby [AiravataJPARegistry] +#sharingcatalog.jdbc.driver=org.apache.derby.jdbc.ClientDriver +#sharingcatalog.jdbc.url=jdbc:derby://localhost:1527/sharing_catalog;create=true;user=airavata;password=airavata +# MariaDB database configuration +sharingcatalog.jdbc.driver=org.mariadb.jdbc.Driver +sharingcatalog.jdbc.url=jdbc:mariadb://149.165.168.248:3306/sharing_catalog +sharingcatalog.jdbc.user=eroma +sharingcatalog.jdbc.password=eroma123456 +sharingcatalog.validationQuery=SELECT 1 from CONFIGURATION + +########################################################################### +# Sharing Registry Server Configuration +########################################################################### +sharing_server=org.apache.airavata.sharing.registry.server.SharingRegistryServer +sharing.registry.server.host=192.168.99.102 +sharing.registry.server.port=7878 + +########################################################################### +# User Profile MongoDB Configuration +########################################################################### +userprofile.mongodb.host=localhost +userprofile.mongodb.port=27017 + + +########################################################################### +# Server module Configuration +########################################################################### +#credential store server should be started before API server +#This is obsolete property with new script files. +#servers=credentialstore,apiserver,orchestrator + + +########################################################################### +# API Server Configurations +########################################################################### +apiserver=org.apache.airavata.api.server.AiravataAPIServer +apiserver.name=apiserver-node0 +apiserver.host=192.168.99.102 +apiserver.port=8930 +apiserver.min.threads=50 + +########################################################################### +# Orchestrator Server Configurations +########################################################################### +orchestrator=org.apache.airavata.orchestrator.server.OrchestratorServer +orchestrator.server.name=orchestrator-node0 +orchestrator.server.host=192.168.99.102 +orchestrator.server.port=8940 +orchestrator.server.min.threads=50 +job.validators=org.apache.airavata.orchestrator.core.validator.impl.BatchQueueValidator,org.apache.airavata.orchestrator.core.validator.impl.ExperimentStatusValidator +submitter.interval=10000 +threadpool.size=10 +start.submitter=true +embedded.mode=true +enable.validation=true + +########################################################################### +# Registry Server Configurations +########################################################################### +regserver=org.apache.airavata.registry.api.service.RegistryAPIServer +regserver.server.name=regserver-node0 +regserver.server.host=192.168.99.102 +regserver.server.port=8970 +regserver.server.min.threads=50 + +########################################################################### +# GFac Server Configurations +########################################################################### +gfac=org.apache.airavata.gfac.server.GfacServer +gfac.server.name=gfac-node0 +gfac.server.host=10.0.2.15 +gfac.server.port=8950 +gfac.thread.pool.size=50 +host.scheduler=org.apache.airavata.gfac.impl.DefaultHostScheduler + + + +########################################################################### +# Airavata Workflow Interpreter Configurations +########################################################################### +workflowserver=org.apache.airavata.api.server.WorkflowServer +enactment.thread.pool.size=10 + +#to define custom workflow parser user following property +#workflow.parser=org.apache.airavata.workflow.core.parser.AiravataWorkflowBuilder + + + +########################################################################### +# Job Scheduler can send informative email messages to you about the status of your job. +# Specify a string which consists of either the single character "n" (no mail), or one or more +# of the characters "a" (send mail when job is aborted), "b" (send mail when job begins), +# and "e" (send mail when job terminates). The default is "a" if not specified. +########################################################################### + +job.notification.enable=true +#Provide comma separated email ids as a string if more than one +job.notification.emailids= +job.notification.flags=abe + +########################################################################### +# Credential Store module Configuration +########################################################################### +credential.store.keystore.url=/Users/dimuthu/code/fork/airavata/modules/helix-spectator/src/main/resources/cred_store.jks +credential.store.keystore.alias=seckey +credential.store.keystore.password=credstore123 +credential.store.jdbc.url=jdbc:mariadb://149.165.168.248:3306/credential_store +credential.store.jdbc.user=eroma +credential.store.jdbc.password=eroma123456 +credential.store.jdbc.driver=org.mariadb.jdbc.Driver +credential.store.server.host=192.168.99.102 +credential.store.server.port=8960 +credentialstore=org.apache.airavata.credential.store.server.CredentialStoreServer +credential.stroe.jdbc.validationQuery=SELECT 1 from CONFIGURATION + +# these properties used by credential store email notifications +email.server=smtp.googlemail.com +email.server.port=465 +email.user=airavata +email.password=xxx +email.ssl=true [email protected] + +# SSH PKI key pair or ssh password can be used SSH based sshKeyAuthentication is used. +# if user specify both password sshKeyAuthentication gets the higher preference + +################# ---------- For ssh key pair sshKeyAuthentication ------------------- ################ +#ssh.public.key=/path to public key for ssh +#ssh.private.key=/path to private key file for ssh +#ssh.keypass=passphrase for the private key +#ssh.username=username for ssh connection +## If you set "yes" for ssh.strict.hostKey.checking, then you must provide known hosts file path +#ssh.strict.hostKey.checking=yes/no +#ssh.known.hosts.file=/path to known hosts file +### Incase of password sshKeyAuthentication. +#ssh.password=Password for ssh connection + +################ ---------- BES Properties ------------------- ############### +#bes.ca.cert.path=<location>/certificates/cacert.pem +#bes.ca.key.path=<location>/certificates/cakey.pem +#bes.ca.key.pass=passphrase + +########################################################################### +# Monitoring module Configuration +########################################################################### + +#This will be the primary monitoring tool which runs in airavata, in future there will be multiple monitoring +#mechanisms and one would be able to start a monitor +monitors=org.apache.airavata.gfac.monitor.impl.pull.qstat.QstatMonitor,org.apache.airavata.gfac.monitor.impl.LocalJobMonitor + +#These properties will used to enable email base monitoring +email.based.monitor.host=imap.gmail.com [email protected] +email.based.monitor.password=ansibletestairavata123 +email.based.monitor.folder.name=INBOX +# either imaps or pop3 +email.based.monitor.store.protocol=imaps +#These property will be used to query the email server periodically. value in milliseconds(ms). +email.based.monitoring.period=10000 + +########################################################################### +# AMQP Notification Configuration +########################################################################### +#for simple scenarios we can use the guest user +#rabbitmq.broker.url=amqp://localhost:5672 +#for production scenarios, give url as amqp://userName:password@hostName:portNumber/virtualHost, create user, virtualhost +# and give permissions, refer: http://blog.dtzq.com/2012/06/rabbitmq-users-and-virtual-hosts.html +rabbitmq.broker.url=amqp://airavata:[email protected]:5672/master +rabbitmq.status.exchange.name=status_exchange +rabbitmq.process.exchange.name=process_exchange +rabbitmq.experiment.exchange.name=experiment_exchange +durable.queue=false +prefetch.count=200 +process.launch.queue.name=process.launch.queue +experiment.launch..queue.name=experiment.launch.queue + +########################################################################### +# Zookeeper Server Configuration +########################################################################### +embedded.zk=false +zookeeper.server.connection=192.168.99.102:2181 +zookeeper.timeout=30000 + +######################################################################## +## API Security Configuration +######################################################################## +api.secured=false +security.manager.class=org.apache.airavata.service.security.KeyCloakSecurityManager +### TLS related configuration #### +TLS.enabled=true +TLS.api.server.port=9930 +TLS.client.timeout=10000 +#### keystore configuration #### +keystore.path=/home/pga/master-deployment/keystores/airavata.jks +keystore.password=password +#### trust store configuration #### +trust.store=/home/pga/master-deployment/keystores/client_truststore.jks +trust.store.password=password +#### authorization cache related configuration #### +authz.cache.enabled=true +authz.cache.manager.class=org.apache.airavata.service.security.authzcache.DefaultAuthzCacheManager +in.memory.cache.size=1000 + +# Kafka Logging related configuration +isRunningOnAws=false +kafka.broker.list=localhost:9092 +kafka.topic.prefix=local +enable.kafka.logging=false + +########################################################################### +# Profile Service Configuration +########################################################################### +profile.service.server.host=192.168.99.102 +profile.service.server.port=8962 +profile_service=org.apache.airavata.service.profile.server.ProfileServiceServer +# MariaDB properties +profile.service.jdbc.url=jdbc:mariadb://149.165.168.248:3306/profile_service +profile.service.jdbc.user=eroma +profile.service.jdbc.password=eroma123456 +profile.service.jdbc.driver=org.mariadb.jdbc.Driver +profile.service.validationQuery=SELECT 1 + +########################################################################### +# Iam Admin services Configuration +########################################################################### +iam.server.url=https://192.168.99.102/auth +iam.server.super.admin.username=admin +iam.server.super.admin.password=123456 + +########################################################################### +# DB Event Manager Runner +########################################################################### +db_event_manager=org.apache.airavata.db.event.manager.DBEventManagerRunner diff --git a/modules/job-monitor/src/main/resources/email-config.yaml b/modules/job-monitor/src/main/resources/email-config.yaml new file mode 100644 index 0000000..9f0c38f --- /dev/null +++ b/modules/job-monitor/src/main/resources/email-config.yaml @@ -0,0 +1,20 @@ +config: + resources: + - jobManagerType: PBS + emailParser: org.apache.airavata.job.monitor.parser.PBSEmailParser + resourceEmailAddresses: + - [email protected] # gordon + - [email protected] # Bigred2 + - root <[email protected]> # Bigred2 + - root <[email protected]> # alamo + + - jobManagerType: SLURM + emailParser: org.apache.airavata.job.monitor.parser.SLURMEmailParser + resourceEmailAddresses: + - SDSC Admin <[email protected]> # comet + - [email protected] # stampede + + - jobManagerType: UGE + emailParser: org.apache.airavata.job.monitor.parser.UGEEmailParser + resourceEmailAddresses: + - ls4.tacc.utexas.edu # contain Lonestar \ No newline at end of file diff --git a/modules/job-monitor/src/main/resources/log4j.properties b/modules/job-monitor/src/main/resources/log4j.properties new file mode 100644 index 0000000..5e31e3c --- /dev/null +++ b/modules/job-monitor/src/main/resources/log4j.properties @@ -0,0 +1,9 @@ +# Set root logger level to DEBUG and its only appender to A1. +log4j.rootLogger=INFO, A1 + +# A1 is set to be a ConsoleAppender. +log4j.appender.A1=org.apache.log4j.ConsoleAppender + +# A1 uses PatternLayout. +log4j.appender.A1.layout=org.apache.log4j.PatternLayout +log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n \ No newline at end of file diff --git a/pom.xml b/pom.xml index bd99a2d..c8e72db 100644 --- a/pom.xml +++ b/pom.xml @@ -28,6 +28,9 @@ <prerequisites> <maven>3.0</maven> </prerequisites> + <modules> + <module>modules/job-monitor</module> + </modules> <parent> <groupId>org.apache</groupId> -- To stop receiving notification emails like this one, please contact [email protected].
