/** * * 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.testsuite.multitenantedairavata; import org.apache.airavata.api.Airavata; import org.apache.airavata.common.logging.MDCConstants; import org.apache.airavata.common.utils.ThriftUtils; import org.apache.airavata.messaging.core.*; import org.apache.airavata.model.application.io.InputDataObjectType; import org.apache.airavata.model.application.io.OutputDataObjectType; import org.apache.airavata.model.commons.ErrorModel; import org.apache.airavata.model.error.AiravataClientException; import org.apache.airavata.model.error.AiravataSystemException; import org.apache.airavata.model.error.InvalidRequestException; import org.apache.airavata.model.experiment.ExperimentModel; import org.apache.airavata.model.experiment.UserConfigurationDataModel; import org.apache.airavata.model.messaging.event.ExperimentStatusChangeEvent; import org.apache.airavata.model.messaging.event.JobStatusChangeEvent; import org.apache.airavata.model.messaging.event.MessageType; import org.apache.airavata.model.scheduling.ComputationalResourceSchedulingModel; import org.apache.airavata.model.security.AuthzToken; import org.apache.airavata.model.status.ExperimentState; import org.apache.airavata.model.status.ExperimentStatus; import org.apache.airavata.model.util.ExperimentModelUtil; import org.apache.airavata.model.workspace.Project; import org.apache.airavata.testsuite.multitenantedairavata.utils.FrameworkUtils; import org.apache.airavata.testsuite.multitenantedairavata.utils.PropertyFileType; import org.apache.airavata.testsuite.multitenantedairavata.utils.PropertyReader; import org.apache.airavata.testsuite.multitenantedairavata.utils.TestFrameworkConstants; import org.apache.thrift.TBase; import org.apache.thrift.TException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC; import java.io.File; import java.io.PrintWriter; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.*; import static org.apache.airavata.testsuite.multitenantedairavata.utils.TestFrameworkConstants.LocalEchoProperties.LOCAL_ECHO_EXPERIMENT_INPUT; import static org.apache.airavata.testsuite.multitenantedairavata.utils.TestFrameworkConstants.LocalEchoProperties.LocalApplication.INPUT_NAME; public class ExperimentExecution { private Airavata.Client airavata; private final static Logger logger = LoggerFactory.getLogger(ExperimentExecution.class); private Map<String, String> experimentsWithTokens; private Map<String, String> experimentsWithGateway; private Map<String, String> csTokens; private Map<String, Map<String, String>> appInterfaceMap; private Map<String, List<Project>> projectsMap; private PropertyReader propertyReader; private PrintWriter resultWriter; private String testUser; private TestFrameworkProps properties; private AuthzToken authzToken; public ExperimentExecution(Airavata.Client airavata, Map<String, String> tokenMap, TestFrameworkProps props) throws Exception { this.airavata = airavata; this.csTokens = tokenMap; authzToken = new AuthzToken("emptyToken"); authzToken.setClaimsMap(new HashMap<>()); this.appInterfaceMap = getApplicationMap(tokenMap); this.propertyReader = new PropertyReader(); this.properties = props; authzToken.getClaimsMap().put(org.apache.airavata.common.utils.Constants.USER_NAME, props.getTestUserName()); authzToken.getClaimsMap().put(org.apache.airavata.common.utils.Constants.GATEWAY_ID, props.getGname()); FrameworkUtils frameworkUtils = FrameworkUtils.getInstance(); testUser = props.getTestUserName(); this.projectsMap = getProjects(tokenMap); this.experimentsWithTokens = new HashMap<String, String>(); this.experimentsWithGateway = new HashMap<String, String>(); String resultFileLocation = properties.getResultFileLoc(); String resultFileName = resultFileLocation + getResultFileName(); File resultFolder = new File(resultFileLocation); if (!resultFolder.exists()) { resultFolder.mkdir(); } File resultFile = new File(resultFileName); resultWriter = new PrintWriter(resultFile, "UTF-8"); resultWriter.println("Test Framework Results"); resultWriter.println("========================================"); } public PrintWriter getResultWriter() { return resultWriter; } public void setResultWriter(PrintWriter resultWriter) { this.resultWriter = resultWriter; } protected Map<String, Map<String, String>> getApplicationMap(Map<String, String> tokenMap) throws Exception { appInterfaceMap = new HashMap<String, Map<String, String>>(); try { if (tokenMap != null && !tokenMap.isEmpty()) { for (String gatewayId : tokenMap.keySet()) { Map<String, String> allApplicationInterfaceNames = airavata.getAllApplicationInterfaceNames(authzToken, gatewayId); appInterfaceMap.put(gatewayId, allApplicationInterfaceNames); } } } catch (AiravataSystemException e) { logger.error("Error while getting application interfaces", e); throw new Exception("Error while getting application interfaces", e); } catch (InvalidRequestException e) { logger.error("Error while getting application interfaces", e); throw new Exception("Error while getting application interfaces", e); } catch (AiravataClientException e) { logger.error("Error while getting application interfaces", e); throw new Exception("Error while getting application interfaces", e); } catch (TException e) { logger.error("Error while getting application interfaces", e); throw new Exception("Error while getting application interfaces", e); } return appInterfaceMap; } protected Map<String, List<Project>> getProjects(Map<String, String> tokenMap) throws Exception { projectsMap = new HashMap<String, List<Project>>(); try { if (tokenMap != null && !tokenMap.isEmpty()) { for (String gatewayId : tokenMap.keySet()) { List<Project> allUserProjects = airavata.getUserProjects(authzToken, gatewayId, testUser, 5, 0); projectsMap.put(gatewayId, allUserProjects); } } } catch (AiravataSystemException e) { logger.error("Error while getting all user projects", e); throw new Exception("Error while getting all user projects", e); } catch (InvalidRequestException e) { logger.error("Error while getting all user projects", e); throw new Exception("Error while getting all user projects", e); } catch (AiravataClientException e) { logger.error("Error while getting all user projects", e); throw new Exception("Error while getting all user projects", e); } catch (TException e) { logger.error("Error while getting all user projects", e); throw new Exception("Error while getting all user projects", e); } return projectsMap; } public void launchExperiments(String gatewayId, String experimentId) throws Exception { try { airavata.launchExperiment(authzToken, experimentId, gatewayId); } catch (Exception e) { logger.error("Error while launching experiment", e); throw new Exception("Error while launching experiment", e); } } public void monitorExperiments() throws Exception { String brokerUrl = propertyReader.readProperty(TestFrameworkConstants.AiravataClientConstants.RABBIT_BROKER_URL, PropertyFileType.AIRAVATA_SERVER); System.out.println("broker url " + brokerUrl); final String exchangeName = propertyReader.readProperty(TestFrameworkConstants.AiravataClientConstants.RABBIT_EXCHANGE_NAME, PropertyFileType.AIRAVATA_SERVER); //Subscriber statusSubscriber = MessagingFactory.getSubscriber(this::processMessage, getRoutingKeys(), Type.STATUS); Subscriber statusSubscriber = MessagingFactory.getSubscriber(new ExperimentHandler(), getRoutingKeys(), Type.STATUS); } private List<String> getRoutingKeys() { List<String> routingKeys = new ArrayList<String>(); for (String expId : experimentsWithGateway.keySet()) { String gatewayId = experimentsWithGateway.get(expId); System.out.println("experiment Id : " + expId + " gateway Id : " + gatewayId); routingKeys.add(gatewayId); routingKeys.add(gatewayId + "." + expId); routingKeys.add(gatewayId + "." + expId + ".*"); routingKeys.add(gatewayId + "." + expId + ".*.*"); routingKeys.add(gatewayId + "." + expId + ".*.*.*"); } return routingKeys; } private class ExperimentHandler implements MessageHandler { @Override public void onMessage(MessageContext messageContext) { MDC.put(MDCConstants.GATEWAY_ID, messageContext.getGatewayId()); if (messageContext.getType().equals(MessageType.EXPERIMENT)) { try { ExperimentStatusChangeEvent event = new ExperimentStatusChangeEvent(); TBase messageEvent = messageContext.getEvent(); byte[] bytes = ThriftUtils.serializeThriftObject(messageEvent); ThriftUtils.createThriftFromBytes(bytes, event); ExperimentState expState = event.getState(); String expId = event.getExperimentId(); String gatewayId = event.getGatewayId(); if (expState.equals(ExperimentState.COMPLETED)) { resultWriter.println("Results for experiment : " + expId + " of gateway Id : " + gatewayId); resultWriter.println("====================================================================="); resultWriter.println("Status : " + ExperimentState.COMPLETED.toString()); // check file transfers List<OutputDataObjectType> experimentOutputs = airavata.getExperimentOutputs(authzToken, expId); int i = 1; for (OutputDataObjectType output : experimentOutputs) { System.out.println("################ Experiment : " + expId + " COMPLETES ###################"); System.out.println("Output " + i + " : " + output.getValue()); resultWriter.println("Output " + i + " : " + output.getValue()); i++; } resultWriter.println("End of Results for Experiment : " + expId); resultWriter.println("====================================================================="); } else if (expState.equals(ExperimentState.FAILED)) { resultWriter.println("Results for experiment : " + expId + " of gateway Id : " + gatewayId); resultWriter.println("====================================================================="); int j = 1; resultWriter.println("Status : " + ExperimentState.FAILED.toString()); System.out.println("################ Experiment : " + expId + " FAILED ###################"); ExperimentModel experiment = airavata.getExperiment(authzToken, expId); List<ErrorModel> errors = experiment.getErrors(); if (errors != null && !errors.isEmpty()) { for (ErrorModel errorDetails : errors) { System.out.println(errorDetails.getActualErrorMessage()); resultWriter.println("Actual Error : " + j + " : " + errorDetails.getActualErrorMessage()); resultWriter.println("User Friendly Message : " + j + " : " + errorDetails.getUserFriendlyMessage()); } } resultWriter.println("End of Results for Experiment : " + expId); resultWriter.println("====================================================================="); } } catch (TException e) { logger.error(e.getMessage(), e); } } resultWriter.flush(); MDC.clear(); } private void cancelExperiment(MessageContext messageContext) { // try { // byte[] bytes = ThriftUtils.serializeThriftObject(messageContext.getEvent()); // ExperimentSubmitEvent expEvent = new ExperimentSubmitEvent(); // ThriftUtils.createThriftFromBytes(bytes, expEvent); // log.info("Cancelling experiment with experimentId: {} gateway Id: {}", expEvent.getExperimentId(), expEvent.getGatewayId()); // terminateExperiment(expEvent.getExperimentId(), expEvent.getGatewayId()); // } catch (TException e) { // log.error("Experiment cancellation failed due to Thrift conversion error", e); // }finally { // experimentSubscriber.sendAck(messageContext.getDeliveryTag()); // } } } private void processMessage(MessageContext message) { if (message.getType().equals(MessageType.EXPERIMENT)) { try { ExperimentStatusChangeEvent event = new ExperimentStatusChangeEvent(); TBase messageEvent = message.getEvent(); byte[] bytes = ThriftUtils.serializeThriftObject(messageEvent); ThriftUtils.createThriftFromBytes(bytes, event); ExperimentState expState = event.getState(); String expId = event.getExperimentId(); String gatewayId = event.getGatewayId(); if (expState.equals(ExperimentState.COMPLETED)) { resultWriter.println("Results for experiment : " + expId + " of gateway Id : " + gatewayId); resultWriter.println("====================================================================="); resultWriter.println("Status : " + ExperimentState.COMPLETED.toString()); // check file transfers List<OutputDataObjectType> experimentOutputs = airavata.getExperimentOutputs(authzToken, expId); int i = 1; for (OutputDataObjectType output : experimentOutputs) { System.out.println("################ Experiment : " + expId + " COMPLETES ###################"); System.out.println("Output " + i + " : " + output.getValue()); resultWriter.println("Output " + i + " : " + output.getValue()); i++; } resultWriter.println("End of Results for Experiment : " + expId); resultWriter.println("====================================================================="); } else if (expState.equals(ExperimentState.FAILED)) { resultWriter.println("Results for experiment : " + expId + " of gateway Id : " + gatewayId); resultWriter.println("====================================================================="); int j = 1; resultWriter.println("Status : " + ExperimentState.FAILED.toString()); System.out.println("################ Experiment : " + expId + " FAILED ###################"); ExperimentModel experiment = airavata.getExperiment(authzToken, expId); List<ErrorModel> errors = experiment.getErrors(); if (errors != null && !errors.isEmpty()) { for (ErrorModel errorDetails : errors) { System.out.println(errorDetails.getActualErrorMessage()); resultWriter.println("Actual Error : " + j + " : " + errorDetails.getActualErrorMessage()); resultWriter.println("User Friendly Message : " + j + " : " + errorDetails.getUserFriendlyMessage()); } } resultWriter.println("End of Results for Experiment : " + expId); resultWriter.println("====================================================================="); } } catch (TException e) { logger.error(e.getMessage(), e); } } else if (message.getType().equals(MessageType.JOB)) { try { JobStatusChangeEvent event = new JobStatusChangeEvent(); TBase messageEvent = message.getEvent(); byte[] bytes = ThriftUtils.serializeThriftObject(messageEvent); ThriftUtils.createThriftFromBytes(bytes, event); } catch (TException e) { logger.error(e.getMessage(), e); } } resultWriter.flush(); } private String getResultFileName() { DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd_HHmmss"); Calendar cal = Calendar.getInstance(); return dateFormat.format(cal.getTime()); } public String createLocalEchoExperiment(String gatewayId, String applicationInterfaceId, String storageId, String computeResourceId) throws Exception { String experimentId = null; try { List<InputDataObjectType> applicationInputs = airavata.getApplicationInputs(authzToken, applicationInterfaceId); List<OutputDataObjectType> appOutputs = airavata.getApplicationOutputs(authzToken, applicationInterfaceId); for (InputDataObjectType inputDataObjectType : applicationInputs) { if (inputDataObjectType.getName().equalsIgnoreCase(INPUT_NAME)) { inputDataObjectType.setValue(LOCAL_ECHO_EXPERIMENT_INPUT); } } List<Project> projectsPerGateway = projectsMap.get(gatewayId); String projectID = null; if (projectsPerGateway != null && !projectsPerGateway.isEmpty()) { projectID = projectsPerGateway.get(0).getProjectID(); } ExperimentModel simpleExperiment = ExperimentModelUtil.createSimpleExperiment(gatewayId, projectID, properties.getTestUserName(), "Local Echo Experiment", "Local Echo Experiment run", applicationInterfaceId, applicationInputs); simpleExperiment.setExperimentOutputs(appOutputs); ComputationalResourceSchedulingModel scheduling = ExperimentModelUtil.createComputationResourceScheduling(computeResourceId, 4, 1, 1, "cpu", 20, 0); UserConfigurationDataModel userConfigurationData = new UserConfigurationDataModel(); userConfigurationData.setAiravataAutoSchedule(false); userConfigurationData.setOverrideManualScheduledParams(false); userConfigurationData.setComputationalResourceScheduling(scheduling); userConfigurationData.setStorageId(storageId); userConfigurationData.setExperimentDataDir(TestFrameworkConstants.STORAGE_LOCATION); simpleExperiment.setUserConfigurationData(userConfigurationData); experimentId = airavata.createExperiment(authzToken, gatewayId, simpleExperiment); experimentsWithGateway.put(experimentId, gatewayId); } catch (Exception e) { logger.error("Error while creating Echo experiment", e); throw new Exception("Error while creating Echo experiment", e); } return experimentId; } public ExperimentModel getExperimentModel(String experimentId){ ExperimentModel experimentModel = null; try { experimentModel = airavata.getExperiment(authzToken, experimentId); } catch (TException e) { logger.error("Error fetching experiment model", e); } return experimentModel; } public ExperimentStatus getExperimentStatus(String experimentId){ ExperimentStatus experimentStatus = null; try { experimentStatus = airavata.getExperimentStatus(authzToken, experimentId); } catch (TException e) { logger.error("Error fetching experiment status", e); } return experimentStatus; } }