From 7923c863c7fe2abe6a944c2a0fa8122995fa0560 Mon Sep 17 00:00:00 2001 From: alijawadfahs Date: Thu, 1 Sep 2022 16:26:58 +0200 Subject: [PATCH] all the changes on SAL from proactive-dev-2.5 --- scheduling-abstraction-layer/pom.xml | 7 +- .../org/activeeon/morphemic/PAGateway.java | 236 +++++++++++++++- .../deployment/PAResourceManagerGateway.java | 2 +- .../activeeon/morphemic/model/CloudType.java | 2 + .../morphemic/model/Credentials.java | 4 +- .../activeeon/morphemic/model/Deployment.java | 20 ++ .../morphemic/model/EdgeDefinition.java | 37 +++ .../activeeon/morphemic/model/EdgeNode.java | 258 ++++++++++++++++++ .../morphemic/model/NodeCandidate.java | 41 ++- .../activeeon/morphemic/model/NodeType.java | 30 +- .../morphemic/model/NodeTypeRequirement.java | 7 +- .../activeeon/morphemic/model/PACloud.java | 5 + .../morphemic/model/SSHCredentials.java | 44 +++ .../morphemic/nc/NodeCandidateUtils.java | 42 ++- .../nc/WhiteListedInstanceTypesUtils.java | 11 +- .../morphemic/service/ByonUtils.java | 123 +++++---- .../service/JCloudsInstancesUtils.java | 9 +- .../morphemic/service/TaskBuilder.java | 15 +- .../workflow/analyser/WfAnalyser.java | 116 ++++++++ .../analyser/WfAnalyserCamelUtils.java | 137 ++++++++++ .../analyser/WfAnalyserXmiElementUtils.java | 50 ++++ .../src/main/resources/Define_NS_AWS.xml | 9 +- .../resources/Define_NS_AWS_AutoScale.xml | 5 +- .../src/main/resources/Define_NS_BYON.xml | 8 +- .../src/main/resources/Define_NS_EDGE.xml | 152 +++++++++++ .../src/main/resources/Define_NS_OS.xml | 3 +- .../main/resources/META-INF/persistence.xml | 1 + .../main/resources/prepare_infra_script.sh | 16 +- 28 files changed, 1299 insertions(+), 91 deletions(-) create mode 100644 scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/model/EdgeDefinition.java create mode 100644 scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/model/EdgeNode.java create mode 100644 scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/model/SSHCredentials.java create mode 100644 scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/workflow/analyser/WfAnalyser.java create mode 100644 scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/workflow/analyser/WfAnalyserCamelUtils.java create mode 100644 scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/workflow/analyser/WfAnalyserXmiElementUtils.java create mode 100644 scheduling-abstraction-layer/src/main/resources/Define_NS_EDGE.xml diff --git a/scheduling-abstraction-layer/pom.xml b/scheduling-abstraction-layer/pom.xml index dae1307f..b00ebcc0 100644 --- a/scheduling-abstraction-layer/pom.xml +++ b/scheduling-abstraction-layer/pom.xml @@ -4,7 +4,7 @@ 4.0.0 org.activeeon scheduling-abstraction-layer - 4.5-SNAPSHOT + 4.6-SNAPSHOT org.projectlombok @@ -79,6 +79,11 @@ 5.4.22.Final compile + + org.jdom + jdom2 + 2.0.6.1 + org.mariadb.jdbc mariadb-java-client diff --git a/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/PAGateway.java b/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/PAGateway.java index 269054a7..60134262 100644 --- a/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/PAGateway.java +++ b/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/PAGateway.java @@ -345,11 +345,15 @@ public class PAGateway { List allNodeCandidates = EntityManagerHelper.createQuery("SELECT nc FROM NodeCandidate nc", NodeCandidate.class).getResultList(); allNodeCandidates.forEach(nodeCandidate -> { + LOGGER.info("Checking node candidate with type: {}", nodeCandidate.getHardware().getName()); if (nodeCandidate.isByonNodeCandidate() || + nodeCandidate.isEdgeNodeCandidate() || JCloudsInstancesUtils.isHandledHardwareInstanceType(nodeCandidate.getCloud().getApi().getProviderName(), nodeCandidate.getHardware().getName()) || WhiteListedInstanceTypesUtils.isHandledHardwareInstanceType(nodeCandidate.getHardware().getName())) { + LOGGER.info(" Checking filters for node candidate with type: {} ...", nodeCandidate.getHardware().getName()); if (NodeCandidateUtils.verifyAllFilters(requirements, nodeCandidate)) { + LOGGER.info(" Requirements answered. Success!"); filteredNodeCandidates.add(nodeCandidate); } } @@ -415,6 +419,9 @@ public class PAGateway { Map variables = new HashMap<>(); variables.put("NS_name", nodeSourceName); variables.put("security_group", cloud.getSecurityGroup()); + variables.put("sshUsername", cloud.getSshCredentials().getUsername()); + variables.put("sshKeyPairName", cloud.getSshCredentials().getKeyPairName()); + variables.put("sshPrivateKey", cloud.getSshCredentials().getPrivateKey()); try { URL endpointPa = (new URL(this.paURL)); variables.put("rm_host_name", endpointPa.getHost()); @@ -444,10 +451,7 @@ public class PAGateway { filename = File.separator + "Define_NS_AWS.xml"; variables.put("aws_username", cloud.getCredentials().getUserName()); variables.put("aws_secret", cloud.getCredentials().getPrivateKey()); - // This was temporarily disabled because of a bug in connector-iaas related - // to a scenario where an EC2 infra is deployed with a specific subnet AND a - // node is requested with a specific security group OR ports to be opened. -// variables.put("subnet", cloud.getSubnet()); + variables.put("subnet", cloud.getSubnet()); break; case "openstack": filename = File.separator + "Define_NS_OS.xml"; @@ -485,7 +489,7 @@ public class PAGateway { * @param byonNodeList a list of BYON nodes to be connected to the server. * @param nodeSourceName The name of the node source */ - public void defineByonNodeSource(List byonNodeList, String nodeSourceName) { + private void defineByonNodeSource(List byonNodeList, String nodeSourceName) { Map variables = new HashMap<>(); String filename; String byonIPs = ""; @@ -536,6 +540,81 @@ public class PAGateway { TemporaryFilesHelper.delete(fXmlFile); } + /** + * Define an EDGE node source + * @param edgeNodeList a list of EDGE nodes to be connected to the server. + * @param nodeSourceName The name of the node source + */ + private void defineEdgeNodeSource(List edgeNodeList, String nodeSourceName) { + Map variables = new HashMap<>(); + String filename; + String edgeIPs = ""; + // Prepare the ip addresses for all the nodes to be added + for(EdgeNode edgeNode: edgeNodeList){ + List tempListIP=edgeNode.getIpAddresses(); + assert !tempListIP.isEmpty(); + edgeIPs= edgeIPs + tempListIP.get(0).getValue().replace(" ", "") + ","; + } + // Collect the pamr router address and port number + try { + URL endpointPa = (new URL(this.paURL)); + variables.put("rm_host_name", endpointPa.getHost()); + variables.put("pa_port", "" + endpointPa.getPort()); + } catch (MalformedURLException e) { + LOGGER.error(String.valueOf(e.getStackTrace())); + } + + assert !edgeNodeList.isEmpty(); + EdgeNode edgeNode = edgeNodeList.get(0); + filename = File.separator + "Define_NS_EDGE.xml"; + variables.put("NS_name", nodeSourceName); + variables.put("pa_protocol", "http"); + variables.put("tokens", "EDGE_" + edgeNode.getJobId()); + variables.put("ssh_username", edgeNode.getLoginCredential().getUsername()); + variables.put("ssh_password", edgeNode.getLoginCredential().getPassword()); + /* IMPORTANT: Later we should relay only on the ssh_key. For now all the nodes must have the same login + credentials. later by automating the node deployment process we can add the server key automatically. + TODO */ + variables.put("ssh_key", ""); + variables.put("ssh_port", "22"); + variables.put("list_of_ips", edgeIPs); + switch (edgeNode.getSystemArch()) { + case "AMD": + variables.put("deployment_mode", "useStartupScript"); + variables.put("script_url", edgeNode.getScriptURL()); + variables.put("script_path", "/tmp/proactive-agent.sh"); + break; + case "ARMv7": + variables.put("deployment_mode", "useNodeJarStartupScript"); + variables.put("jar_url", edgeNode.getJarURL()); + variables.put("jre_url", "https://ci-materials.s3.amazonaws.com/Latest_jre/jre-8u322b06-linux-arm.tar.gz"); + break; + case "ARMv8": + variables.put("deployment_mode", "useNodeJarStartupScript"); + variables.put("jar_url", edgeNode.getJarURL()); + variables.put("jre_url", "https://ci-materials.s3.amazonaws.com/Latest_jre/jre-8u322b06-linux-aarch64.tar.gz"); + break; + default: + LOGGER.error("The Edge node system architecture {} is not supported!", edgeNode.getSystemArch()); + throw new IllegalArgumentException("The Edge node system architecture " + edgeNode.getSystemArch() + " is not supported!"); + } + + // Create the xml file + File fXmlFile = null; + LOGGER.info("NodeSource deployment workflow filename: " + filename); + try { + fXmlFile = TemporaryFilesHelper.createTempFileFromResource(filename); + } catch (IOException ioe) { + LOGGER.error("Opening the NS deployment workflow file failed due to : " + Arrays.toString(ioe.getStackTrace())); + } + assert fXmlFile != null; + LOGGER.info("Submitting the file: " + fXmlFile.toString()); + LOGGER.info("Trying to deploy the NS: " + nodeSourceName); + JobId jobId = schedulerGateway.submit(fXmlFile, variables); + LOGGER.info("Job submitted with ID: " + jobId); + TemporaryFilesHelper.delete(fXmlFile); + } + /** * Add an EMS deployment to a defined job * @param nodeNames Names of the nodes to which to add EMS deployment @@ -656,14 +735,14 @@ public class PAGateway { * @param byonNodeDefinition objects of class ByonDefinition that contains the detials of the nodes to be registered. * @param jobId A constructed job identifier * @param Automate the Byon agent will be deployed automatically if the value is set to True - * @return ByonNodeList objects of class ByonNode that contains information about the registered Node + * @return newByonNode ByonNode object that contains information about the registered Node */ public ByonNode registerNewByonNode(ByonDefinition byonNodeDefinition, String jobId, boolean Automate) { Validate.notNull(byonNodeDefinition, "The received Byon node definition is empty. Nothing to be registered."); Validate.notNull(jobId, "The received jobId is empty. Nothing to be registered."); LOGGER.info("registerNewByonNode endpoint is called with Automate set to " + Automate + ", Registering a new BYON definition related to job " + jobId + " ..."); - NodeCandidate byonNC = ByonUtils.createByonNodeCandidate(byonNodeDefinition, jobId); + NodeCandidate byonNC = ByonUtils.createNodeCandidate(byonNodeDefinition.getNodeProperties(), jobId, "byon"); EntityManagerHelper.begin(); ByonNode newByonNode = new ByonNode(); newByonNode.setName(byonNodeDefinition.getName()); @@ -687,6 +766,42 @@ public class PAGateway { } + /** + * Register new Edge nodes passed as EdgeDefinition object + * + * @param edgeNodeDefinition objects of class ByonDefinition that contains the detials of the nodes to be registered. + * @param jobId A constructed job identifier + * @return newEdgeNode EdgeNode object that contains information about the registered Node + */ + public EdgeNode registerNewEdgeNode(EdgeDefinition edgeNodeDefinition, String jobId) { + Validate.notNull(edgeNodeDefinition, "The received EDGE node definition is empty. Nothing to be registered."); + Validate.notNull(jobId, "The received jobId is empty. Nothing to be registered."); + LOGGER.info("registerNewEdgeNode endpoint is called, Registering a new EDGE definition related to job " + jobId + " ..."); + + EntityManagerHelper.begin(); + EdgeNode newEdgeNode = new EdgeNode(); + newEdgeNode.setName(edgeNodeDefinition.getName()); + newEdgeNode.setLoginCredential(edgeNodeDefinition.getLoginCredential()); + newEdgeNode.setIpAddresses(edgeNodeDefinition.getIpAddresses()); + newEdgeNode.setNodeProperties(edgeNodeDefinition.getNodeProperties()); + newEdgeNode.setJobId(jobId); + newEdgeNode.setSystemArch(edgeNodeDefinition.getSystemArch()); + newEdgeNode.setScriptURL(edgeNodeDefinition.getScriptURL()); + newEdgeNode.setJarURL(edgeNodeDefinition.getJarURL()); + + NodeCandidate edgeNC = ByonUtils.createNodeCandidate(edgeNodeDefinition.getNodeProperties(), jobId, "edge"); + newEdgeNode.setNodeCandidate(edgeNC); + + EntityManagerHelper.persist(newEdgeNode); + EntityManagerHelper.commit(); + LOGGER.info("EDGE node registered."); + + return newEdgeNode; + /* TODO: + * Avoid duplicate nodes in the database + */ + } + /** * Return the List of registered BYON nodes @@ -711,6 +826,31 @@ public class PAGateway { */ } + + /** + * Return the List of registered EDGE nodes + * @param jobId A constructed job identifier, If "0" is passed as the JobId all the Edge Nodes will be returned + * @return List of EdgeNode objects that contains information about the registered Nodes + */ + public List getEdgeNodeList(String jobId) { + List filteredEdgeNodes = new LinkedList<>(); + List listEdgeNodes = EntityManagerHelper.createQuery("SELECT edge FROM EdgeNode edge", EdgeNode.class).getResultList(); + if (jobId.equals("0")) { + return listEdgeNodes; + } else { + for (EdgeNode edgeNode : listEdgeNodes) { + if (jobId.equals(edgeNode.getJobId())) { + filteredEdgeNodes.add(edgeNode); + } + } + return filteredEdgeNodes; + } + /*TODO: + * Add Logging info + */ + } + + /** * Adding BYON nodes to a job component * @param byonIdPerComponent a mapping between byon nodes and job components @@ -733,11 +873,17 @@ public class PAGateway { newDeployment.setDeploymentType(NodeType.BYON); newDeployment.setByonNode(byonNode); + SSHCredentials sshCred = new SSHCredentials(); + sshCred.setUsername(byonNode.getLoginCredential().getUsername()); + sshCred.setUsername(byonNode.getLoginCredential().getPassword()); + sshCred.setUsername(byonNode.getLoginCredential().getPrivateKey()); + PACloud cloud = new PACloud(); String nodeSourceName = "BYON_NS_" + byonNode.getId(); cloud.setCloudID(nodeSourceName); cloud.setNodeSourceNamePrefix(nodeSourceName); cloud.setCloudType(CloudType.BYON); + cloud.setSshCredentials(sshCred); cloud.addDeployment(newDeployment); newDeployment.setPaCloud(cloud); EntityManagerHelper.persist(cloud); @@ -763,6 +909,65 @@ public class PAGateway { return 0; } + + /** + * Adding EDGE nodes to a job component + * @param edgeIdPerComponent a mapping between byon nodes and job components + * @param jobId A constructed job identifier + * @return 0 if nodes has been added properly. A greater than 0 value otherwise. + */ + public int addEdgeNodes(Map edgeIdPerComponent, String jobId) { + Validate.notNull(edgeIdPerComponent, "The received byonIdPerComponent structure is empty. Nothing to be added."); + + EntityManagerHelper.begin(); + edgeIdPerComponent.forEach((edgeNodeId, componentName) -> { + EdgeNode edgeNode = EntityManagerHelper.find(EdgeNode.class, edgeNodeId); + Task task = EntityManagerHelper.find(Task.class, jobId + componentName); + + assert edgeNode!=null : "The EDGE ID passed in the mapping does not exist in the database"; + assert task!=null : "The componentId passed in the mapping does not exist in the database"; + + Deployment newDeployment = new Deployment(); + newDeployment.setNodeName(edgeNode.getName()); + newDeployment.setDeploymentType(NodeType.EDGE); + newDeployment.setEdgeNode(edgeNode); + + SSHCredentials sshCred = new SSHCredentials(); + sshCred.setUsername(edgeNode.getLoginCredential().getUsername()); + sshCred.setUsername(edgeNode.getLoginCredential().getPassword()); + sshCred.setUsername(edgeNode.getLoginCredential().getPrivateKey()); + + PACloud cloud = new PACloud(); + String nodeSourceName = "EDGE_"+edgeNode.getSystemArch()+"_NS_" + edgeNode.getId(); + cloud.setCloudID(nodeSourceName); + cloud.setNodeSourceNamePrefix(nodeSourceName); + cloud.setCloudType(CloudType.EDGE); + cloud.setSshCredentials(sshCred); + cloud.addDeployment(newDeployment); + newDeployment.setPaCloud(cloud); + EntityManagerHelper.persist(cloud); + + List edgeNodeList = new LinkedList<>(); + edgeNodeList.add(edgeNode); + LOGGER.info("EDGE node Added: " + edgeNode.getName() + " Ip: " + edgeNode.getIpAddresses().get(0).getValue()); + defineEdgeNodeSource(edgeNodeList, nodeSourceName); + LOGGER.info("EDGE node source EDGE_NS_" + edgeNode.getId() + " is defined"); + + newDeployment.setTask(task); + newDeployment.setNumber(task.getNextDeploymentID()); + EntityManagerHelper.persist(newDeployment); + LOGGER.debug("Deployment created: " + newDeployment.toString()); + + task.addDeployment(newDeployment); + EntityManagerHelper.persist(task); + }); + + EntityManagerHelper.commit(); + + LOGGER.info("EDGE nodes added properly."); + return 0; + } + /** * Undeploy clouds * @param cloudIDs List of cloud IDs to remove @@ -816,8 +1021,8 @@ public class PAGateway { String nodeSourceName = cloud.getNodeSourceNamePrefix() + entry.getKey(); LOGGER.info("Removing node source " + nodeSourceName + " from the ProActive server."); resourceManagerGateway.removeNodeSource(nodeSourceName, preempt); - } catch (NotConnectedException | PermissionRestException e) { - LOGGER.error(Arrays.toString(e.getStackTrace())); + } catch (NotConnectedException | PermissionRestException | IllegalArgumentException e) { + LOGGER.error("Removing cloud crashed. Error: ", e); } } for (Map.Entry entry : cloud.getDeployedWhiteListedRegions().entrySet()) { @@ -825,8 +1030,8 @@ public class PAGateway { String nodeSourceName = PACloud.WHITE_LISTED_NAME_PREFIX + cloud.getNodeSourceNamePrefix() + entry.getKey(); LOGGER.info("Removing node source " + nodeSourceName + " from the ProActive server."); resourceManagerGateway.removeNodeSource(nodeSourceName, preempt); - } catch (NotConnectedException | PermissionRestException e) { - LOGGER.error(Arrays.toString(e.getStackTrace())); + } catch (NotConnectedException | PermissionRestException | IllegalArgumentException e) { + LOGGER.error("Removing WL cloud crashed. Error: ", e); } } if (cloud.getDeployments() != null) { @@ -1044,6 +1249,12 @@ public class PAGateway { newCloud.setDefaultNetwork(cloud.optString("defaultNetwork")); newCloud.setBlacklist(cloud.optString("blacklist")); + SSHCredentials sshCredentials = new SSHCredentials(); + sshCredentials.setUsername(cloud.optJSONObject("sshCredentials").optString("username")); + sshCredentials.setKeyPairName(cloud.optJSONObject("sshCredentials").optString("keyPairName")); + sshCredentials.setPrivateKey(cloud.optJSONObject("sshCredentials").optString("privateKey")); + newCloud.setSshCredentials(sshCredentials); + Credentials credentials = new Credentials(); credentials.setUserName(cloud.optJSONObject("credentials").optString("user")); credentials.setPrivateKey(cloud.optJSONObject("credentials").optString("secret")); @@ -1127,6 +1338,7 @@ public class PAGateway { null, null, NodeType.IAAS, + null, null ); }) @@ -1525,6 +1737,8 @@ public class PAGateway { Location.clean(); LOGGER.info("Cleaning ByonNodes ..."); ByonNode.clean(); + LOGGER.info("Cleaning EdgeNodes ..."); + EdgeNode.clean(); EntityManagerHelper.commit(); LOGGER.info("Done."); } diff --git a/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/infrastructure/deployment/PAResourceManagerGateway.java b/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/infrastructure/deployment/PAResourceManagerGateway.java index 477e34c6..abbc24cf 100644 --- a/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/infrastructure/deployment/PAResourceManagerGateway.java +++ b/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/infrastructure/deployment/PAResourceManagerGateway.java @@ -287,7 +287,7 @@ public class PAResourceManagerGateway { * @throws NotConnectedException In case the user is not connected * @throws PermissionRestException In case the user does not have valid permissions */ - public Boolean removeNodeSource(String nodeSourceName, Boolean preempt) throws NotConnectedException, PermissionRestException { + public Boolean removeNodeSource(String nodeSourceName, Boolean preempt) throws NotConnectedException, PermissionRestException, IllegalArgumentException { reconnectIfDisconnected(); LOGGER.debug("Removing node source ..."); Boolean result = rmRestInterface.removeNodeSource(RMConnectionHelper.getSessionId(), nodeSourceName, preempt); diff --git a/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/model/CloudType.java b/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/model/CloudType.java index f9fafdeb..56dffb2d 100644 --- a/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/model/CloudType.java +++ b/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/model/CloudType.java @@ -16,6 +16,8 @@ public enum CloudType { BYON("BYON"), + EDGE("EDGE"), + SIMULATION("SIMULATION"); private String value; diff --git a/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/model/Credentials.java b/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/model/Credentials.java index 2c786bd6..17c17bb2 100644 --- a/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/model/Credentials.java +++ b/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/model/Credentials.java @@ -26,10 +26,10 @@ public class Credentials implements Serializable { @Column(name = "PASSWORD") private String password; - @Column(name = "PRIVATE_KEY") + @Column(name = "PRIVATE_KEY", columnDefinition = "TEXT") private String privateKey; - @Column(name = "PUBLIC_KEY") + @Column(name = "PUBLIC_KEY", columnDefinition = "TEXT") private String publicKey; @Column(name = "DOMAIN") diff --git a/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/model/Deployment.java b/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/model/Deployment.java index cdbdacab..3fd99a2a 100644 --- a/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/model/Deployment.java +++ b/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/model/Deployment.java @@ -62,6 +62,10 @@ public class Deployment implements Serializable { @OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.REFRESH) private ByonNode byonNode; + @OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.REFRESH) + private EdgeNode edgeNode; + + public static void clean() { List allDeployments = EntityManagerHelper.createQuery("SELECT d FROM Deployment d", Deployment.class).getResultList(); allDeployments.forEach(EntityManagerHelper::remove); @@ -101,6 +105,22 @@ public class Deployment implements Serializable { ", task='" + task.getName() + '\'' + ", byonNode='" + byonNode.getName() + '\'' + '}'; + + case EDGE: + return "Deployment{" + + "nodeName='" + nodeName + '\'' + + ", locationName='" + locationName + '\'' + + ", imageProviderId='" + imageProviderId + '\'' + + ", hardwareProviderId='" + hardwareProviderId + '\'' + + ", isDeployed='" + isDeployed.toString() + '\'' + + ", instanceId='" + instanceId + '\'' + + ", ipAddress='" + ipAddress + '\'' + + ", nodeAccessToken='" + nodeAccessToken + '\'' + + ", number='" + number + '\'' + + ", paCloud='" + paCloud + '\'' + + ", task='" + task.getName() + '\'' + + ", edgeNode='" + edgeNode.getName() + '\'' + + '}'; default: return "Deployment{nodeName='" + nodeName + '}'; } diff --git a/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/model/EdgeDefinition.java b/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/model/EdgeDefinition.java new file mode 100644 index 00000000..f2b2b93b --- /dev/null +++ b/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/model/EdgeDefinition.java @@ -0,0 +1,37 @@ +package org.activeeon.morphemic.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.*; + +import java.util.List; + +/** + * Attributes defining a BYON node + */ +@AllArgsConstructor +@NoArgsConstructor +@Getter +@Setter +@ToString(callSuper = true) +public class EdgeDefinition { + @JsonProperty("name") + private String name = null; + + @JsonProperty("systemArch") + private String systemArch = null; + + @JsonProperty("scriptURL") + private String scriptURL = null; + + @JsonProperty("jarURL") + private String jarURL = null; + + @JsonProperty("loginCredential") + private LoginCredential loginCredential = null; + + @JsonProperty("ipAddresses") + private List ipAddresses = null; + + @JsonProperty("nodeProperties") + private NodeProperties nodeProperties = null; +} diff --git a/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/model/EdgeNode.java b/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/model/EdgeNode.java new file mode 100644 index 00000000..f641922b --- /dev/null +++ b/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/model/EdgeNode.java @@ -0,0 +1,258 @@ +package org.activeeon.morphemic.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.activeeon.morphemic.service.EntityManagerHelper; +import org.hibernate.annotations.GenericGenerator; + +import javax.persistence.*; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +/** + * Representation of an Edge used by ProActive + * This class is a clone of the Byon Node Class with some modifications + */ +@AllArgsConstructor +@NoArgsConstructor +@Entity +@Getter +@Setter +@Table(name = "EDGE_NODE") +public class EdgeNode implements Serializable { + @Id + @GeneratedValue(generator = "system-uuid") + @GenericGenerator(name = "system-uuid", strategy = "uuid") + @Column(name = "ID") + @JsonProperty("id") + private String id = null; + + @Column(name = "NAME") + @JsonProperty("name") + private String name = null; + + @Column(name = "SYSTEM_ARCH") + @JsonProperty("systemArch") + private String systemArch = null; + + @JsonProperty("scriptURL") + private String scriptURL = null; + + @JsonProperty("scriptURL") + private String jarURL = null; + + @Embedded + @JsonProperty("loginCredential") + private LoginCredential loginCredential = null; + + @ElementCollection(targetClass=IpAddress.class) + private List ipAddresses = null; + + @Embedded + @JsonProperty("nodeProperties") + private NodeProperties nodeProperties = null; + + @Column(name = "REASON") + @JsonProperty("reason") + private String reason = null; + + @Column(name = "DIAGNOSTIC") + @JsonProperty("diagnostic") + private String diagnostic = null; + + @OneToOne(fetch = FetchType.EAGER, orphanRemoval = true, cascade = CascadeType.REFRESH) + private NodeCandidate nodeCandidate = null; + + @Column(name = "USER_ID") + @JsonProperty("userId") + private String userId = null; + + @Column(name = "ALLOCATED") + @JsonProperty("allocated") + private Boolean allocated = null; + + @Column(name = "JOB_ID") + @JsonProperty("jobId") + private String jobId; + + public static void clean() { + List allEdgeNodes = EntityManagerHelper.createQuery("SELECT en FROM EdgeNode en", EdgeNode.class).getResultList(); + allEdgeNodes.forEach(EntityManagerHelper::remove); + } + + public EdgeNode name(String name) { + this.name = name; + return this; + } + + /** + * Human-readable name for the node. + * @return name + **/ + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public EdgeNode loginCredential(LoginCredential loginCredential) { + this.loginCredential = loginCredential; + return this; + } + + /** + * Get loginCredential + * @return loginCredential + **/ + public LoginCredential getLoginCredential() { + return loginCredential; + } + + public void setLoginCredential(LoginCredential loginCredential) { + this.loginCredential = loginCredential; + } + + public EdgeNode ipAddresses(List ipAddresses) { + this.ipAddresses = ipAddresses; + return this; + } + + public EdgeNode addIpAddressesItem(IpAddress ipAddressesItem) { + if (this.ipAddresses == null) { + this.ipAddresses = new ArrayList(); + } + this.ipAddresses.add(ipAddressesItem); + return this; + } + + /** + * The public/private ip addresses under which this node is reachable. + * @return ipAddresses + **/ + public List getIpAddresses() { + return ipAddresses; + } + + public void setIpAddresses(List ipAddresses) { + this.ipAddresses = ipAddresses; + } + + public EdgeNode nodeProperties(NodeProperties nodeProperties) { + this.nodeProperties = nodeProperties; + return this; + } + + /** + * Further properties of this node. + * @return nodeProperties + **/ + public NodeProperties getNodeProperties() { + return nodeProperties; + } + + public void setNodeProperties(NodeProperties nodeProperties) { + this.nodeProperties = nodeProperties; + } + + public EdgeNode reason(String reason) { + this.reason = reason; + return this; + } + + + + public EdgeNode diagnostic(String diagnostic) { + this.diagnostic = diagnostic; + return this; + } + + + public EdgeNode id(String id) { + this.id = id; + return this; + } + + public EdgeNode userId(String userId) { + this.userId = userId; + return this; + } + + + public EdgeNode allocated(Boolean allocated) { + this.allocated = allocated; + return this; + } + + /** + * Signals if the node was allocated by cloudiator + * @return allocated + **/ + public Boolean isAllocated() { + return allocated; + } + + @Override + public boolean equals(java.lang.Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + EdgeNode edgeNode = (EdgeNode) o; + return Objects.equals(this.name, edgeNode.name) && + Objects.equals(this.loginCredential, edgeNode.loginCredential) && + Objects.equals(this.ipAddresses, edgeNode.ipAddresses) && + Objects.equals(this.nodeProperties, edgeNode.nodeProperties) && + Objects.equals(this.reason, edgeNode.reason) && + Objects.equals(this.diagnostic, edgeNode.diagnostic) && + Objects.equals(this.nodeCandidate, edgeNode.nodeCandidate) && + Objects.equals(this.id, edgeNode.id) && + Objects.equals(this.userId, edgeNode.userId) && + Objects.equals(this.allocated, edgeNode.allocated) && + Objects.equals(this.jobId, edgeNode.jobId); + } + + @Override + public int hashCode() { + return Objects.hash(name, loginCredential, ipAddresses, nodeProperties, reason, diagnostic, nodeCandidate, id, userId, allocated); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class EdgeNode {\n"); + + sb.append(" name: ").append(toIndentedString(name)).append("\n"); + sb.append(" loginCredential: ").append(toIndentedString(loginCredential)).append("\n"); + sb.append(" ipAddresses: ").append(toIndentedString(ipAddresses)).append("\n"); + sb.append(" nodeProperties: ").append(toIndentedString(nodeProperties)).append("\n"); + sb.append(" reason: ").append(toIndentedString(reason)).append("\n"); + sb.append(" diagnostic: ").append(toIndentedString(diagnostic)).append("\n"); + sb.append(" nodeCandidate: ").append(toIndentedString(nodeCandidate)).append("\n"); + sb.append(" id: ").append(toIndentedString(id)).append("\n"); + sb.append(" userId: ").append(toIndentedString(userId)).append("\n"); + sb.append(" allocated: ").append(toIndentedString(allocated)).append("\n"); + sb.append(" jobId: ").append(toIndentedString(jobId)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} diff --git a/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/model/NodeCandidate.java b/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/model/NodeCandidate.java index abe81c48..6b824a23 100644 --- a/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/model/NodeCandidate.java +++ b/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/model/NodeCandidate.java @@ -5,6 +5,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonValue; import lombok.AllArgsConstructor; import lombok.NoArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.activeeon.morphemic.service.EntityManagerHelper; import org.hibernate.annotations.GenericGenerator; @@ -19,6 +20,7 @@ import java.util.Optional; /** * A node creatable by the system */ +@Slf4j @AllArgsConstructor @NoArgsConstructor @Entity @@ -48,6 +50,8 @@ public class NodeCandidate implements Serializable { BYON("BYON"), + EDGE("EDGE"), + SIMULATION("SIMULATION"); private String value; @@ -82,6 +86,10 @@ public class NodeCandidate implements Serializable { @JsonProperty("jobIdForByon") private String jobIdForBYON; + @Column(name = "JOB_ID_FOR_EDGE") + @JsonProperty("jobIdForEdge") + private String jobIdForEDGE; + @Column(name = "PRICE") @JsonProperty("price") private Double price = null; @@ -156,10 +164,16 @@ public class NodeCandidate implements Serializable { return jobIdForBYON; } + public String getJobIdForEDGE() { + return jobIdForEDGE; + } + public void setJobIdForBYON(String jobIdForBYON) { this.jobIdForBYON = jobIdForBYON; } + public void setJobIdForEDGE(String jobIdForEDGE) { this.jobIdForEDGE = jobIdForEDGE; } + public NodeCandidate price(Double price) { this.price = price; return this; @@ -301,9 +315,30 @@ public class NodeCandidate implements Serializable { * @return true if yes, false if not */ public boolean isByonNodeCandidate() { - return nodeCandidateType.value.equals("BYON"); + if (nodeCandidateType.equals(NodeCandidateTypeEnum.BYON)) { + LOGGER.info(" Is BYON: YES"); + return true; + } else { + LOGGER.info(" Is BYON: NO"); + return false; + } + } + + /** + * Check if a node candidate is of BYON type + * @return true if yes, false if not + */ + public boolean isEdgeNodeCandidate() { + if (nodeCandidateType.equals(NodeCandidateTypeEnum.EDGE)) { + LOGGER.info(" Is EDGE: YES"); + return true; + } else { + LOGGER.info(" Is EDGE: NO"); + return false; + } } + /** * Find the first node candidate that * @param hardware A given stored hardware @@ -329,6 +364,7 @@ public class NodeCandidate implements Serializable { return Objects.equals(this.id, nodeCandidate.id) && Objects.equals(this.nodeCandidateType, nodeCandidate.nodeCandidateType) && Objects.equals(this.jobIdForBYON, nodeCandidate.jobIdForBYON) && + Objects.equals(this.jobIdForEDGE, nodeCandidate.jobIdForEDGE) && Objects.equals(this.price, nodeCandidate.price) && Objects.equals(this.cloud, nodeCandidate.cloud) && Objects.equals(this.image, nodeCandidate.image) && @@ -341,7 +377,7 @@ public class NodeCandidate implements Serializable { @Override public int hashCode() { - return Objects.hash(id, nodeCandidateType, jobIdForBYON, price, cloud, image, hardware, location, pricePerInvocation, memoryPrice, environment); + return Objects.hash(id, nodeCandidateType, jobIdForBYON, jobIdForEDGE, price, cloud, image, hardware, location, pricePerInvocation, memoryPrice, environment); } @Override @@ -352,6 +388,7 @@ public class NodeCandidate implements Serializable { sb.append(" id: ").append(toIndentedString(id)).append("\n"); sb.append(" nodeCandidateType: ").append(toIndentedString(nodeCandidateType)).append("\n"); sb.append(" jobIdForBYON: ").append(toIndentedString(jobIdForBYON)).append("\n"); + sb.append(" jobIdForEDGE: ").append(toIndentedString(jobIdForEDGE)).append("\n"); sb.append(" price: ").append(toIndentedString(price)).append("\n"); sb.append(" cloud: ").append(toIndentedString(cloud)).append("\n"); sb.append(" image: ").append(toIndentedString(image)).append("\n"); diff --git a/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/model/NodeType.java b/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/model/NodeType.java index c3899c47..971bc1b5 100644 --- a/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/model/NodeType.java +++ b/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/model/NodeType.java @@ -43,13 +43,23 @@ public enum NodeType implements Enumerator { * * @see #BYON_VALUE */ - BYON(3, "BYON", "BYON"), /** + BYON(3, "BYON", "BYON"), + + /** + * The 'EDGE' literal object. + * + * + * @see #EDGE_VALUE + */ + EDGE(4, "EDGE", "EDGE"), /** + + /** * The 'SIMULATION' literal object. * * * @see #SIMULATION_VALUE */ - SIMULATION(4, "SIMULATION", "SIMULATION"); + SIMULATION(5, "SIMULATION", "SIMULATION"); /** * The 'IAAS' literal value. @@ -99,6 +109,18 @@ public enum NodeType implements Enumerator { */ public static final int BYON_VALUE = 3; + /** + * The 'EDGE' literal value. + * + *

+ * If the meaning of 'EDGE' literal object isn't clear, + * there really should be more of a description here... + *

+ * + * @see #EDGE + */ + public static final int EDGE_VALUE = 4; + /** * The 'SIMULATION' literal value. * @@ -109,7 +131,7 @@ public enum NodeType implements Enumerator { * * @see #SIMULATION */ - public static final int SIMULATION_VALUE = 4; + public static final int SIMULATION_VALUE = 5; /** * An array of all the 'Node Type' enumerators. @@ -122,6 +144,7 @@ public enum NodeType implements Enumerator { PAAS, FAAS, BYON, + EDGE, SIMULATION, }; @@ -179,6 +202,7 @@ public enum NodeType implements Enumerator { case PAAS_VALUE: return PAAS; case FAAS_VALUE: return FAAS; case BYON_VALUE: return BYON; + case EDGE_VALUE: return EDGE; case SIMULATION_VALUE: return SIMULATION; } return null; diff --git a/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/model/NodeTypeRequirement.java b/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/model/NodeTypeRequirement.java index a9355cb1..6dd8b3c4 100644 --- a/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/model/NodeTypeRequirement.java +++ b/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/model/NodeTypeRequirement.java @@ -19,6 +19,9 @@ public class NodeTypeRequirement extends Requirement { @JsonProperty("jobIdForByon") private String jobIdForBYON; + @JsonProperty("jobIdForEDGE") + private String jobIdForEDGE; + /** * Get nodeType * @return nodeType @@ -36,12 +39,13 @@ public class NodeTypeRequirement extends Requirement { NodeTypeRequirement nodeTypeRequirement = (NodeTypeRequirement) o; return Objects.equals(this.nodeTypes, nodeTypeRequirement.nodeTypes) && Objects.equals(this.jobIdForBYON, nodeTypeRequirement.jobIdForBYON) && + Objects.equals(this.jobIdForEDGE, nodeTypeRequirement.jobIdForEDGE) && super.equals(o); } @Override public int hashCode() { - return Objects.hash(nodeTypes, jobIdForBYON, super.hashCode()); + return Objects.hash(nodeTypes, jobIdForBYON, jobIdForEDGE, super.hashCode()); } @Override @@ -51,6 +55,7 @@ public class NodeTypeRequirement extends Requirement { sb.append(" ").append(toIndentedString(super.toString())).append("\n"); sb.append(" nodeType: ").append(toIndentedString(nodeTypes)).append("\n"); sb.append(" jobIdForBYON: ").append(toIndentedString(jobIdForBYON)).append("\n"); + sb.append(" jobIdForEDGE: ").append(toIndentedString(jobIdForEDGE)).append("\n"); sb.append("}"); return sb.toString(); } diff --git a/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/model/PACloud.java b/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/model/PACloud.java index eb5f3d4b..43e748f9 100644 --- a/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/model/PACloud.java +++ b/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/model/PACloud.java @@ -44,6 +44,10 @@ public class PACloud implements Serializable { @Column(name = "SECURITY_GROUP") private String securityGroup; + @Embedded + @Column(name = "SSH_CREDENTIALS") + private SSHCredentials sshCredentials; + @Column(name = "ENDPOINT") private String endpoint; @@ -134,6 +138,7 @@ public class PACloud implements Serializable { ", cloudType='" + cloudType.toString() + '\'' + ", subnet='" + subnet + '\'' + ", securityGroup='" + securityGroup + '\'' + + ", sshCredentials='" + sshCredentials.toString() + '\'' + ", endpoint='" + endpoint + '\'' + ", scopePrefix='" + scopePrefix + '\'' + ", scopeValue='" + scopeValue + '\'' + diff --git a/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/model/SSHCredentials.java b/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/model/SSHCredentials.java new file mode 100644 index 00000000..a81d2ef9 --- /dev/null +++ b/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/model/SSHCredentials.java @@ -0,0 +1,44 @@ +package org.activeeon.morphemic.model; + +import lombok.*; + +import javax.persistence.Column; +import javax.persistence.Embeddable; +import java.util.Objects; + +@AllArgsConstructor +@NoArgsConstructor +@Getter +@Setter +@ToString +@Embeddable +public class SSHCredentials { + + @Column(name = "USERNAME") + private String username = null; + + @Column(name = "KEY_PAIR_NAME") + private String keyPairName = null; + + @Column(name = "PRIVATE_KEY", columnDefinition = "TEXT") + private String privateKey = null; + + @Override + public boolean equals(java.lang.Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + SSHCredentials sshCredentials = (SSHCredentials) o; + return Objects.equals(this.username, sshCredentials.username) && + Objects.equals(this.keyPairName, sshCredentials.keyPairName) && + Objects.equals(this.privateKey, sshCredentials.privateKey); + } + + @Override + public int hashCode() { + return Objects.hash(username, keyPairName, privateKey); + } +} diff --git a/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/nc/NodeCandidateUtils.java b/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/nc/NodeCandidateUtils.java index 0ac1b248..080c2d09 100644 --- a/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/nc/NodeCandidateUtils.java +++ b/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/nc/NodeCandidateUtils.java @@ -50,18 +50,23 @@ public class NodeCandidateUtils { public static boolean verifyAllFilters(List requirements, NodeCandidate nodeCandidate) { if (requirements == null || requirements.isEmpty()) { + LOGGER.info(" Satisfy all requirements!!!"); return true; } if (requirements.get(0) instanceof NodeTypeRequirement) { if (satisfyNodeTypeRequirement((NodeTypeRequirement) requirements.get(0), nodeCandidate)) { + LOGGER.info(" satisfyNodeTypeRequirement: YES"); return verifyAllFilters(requirements.subList(1, requirements.size()), nodeCandidate); } + LOGGER.info(" satisfyNodeTypeRequirement: NO"); return false; } if (requirements.get(0) instanceof AttributeRequirement) { if (satisfyAttributeRequirement((AttributeRequirement) requirements.get(0), nodeCandidate)) { + LOGGER.info(" satisfyAttributeRequirement: YES"); return verifyAllFilters(requirements.subList(1, requirements.size()), nodeCandidate); } + LOGGER.info(" satisfyAttributeRequirement: NO"); return false; } LOGGER.warn("Unknown requirement type. It could not be applied: " + requirements.get(0).toString()); @@ -69,6 +74,10 @@ public class NodeCandidateUtils { } private static boolean satisfyAttributeRequirement(AttributeRequirement attributeRequirement, NodeCandidate nodeCandidate) { + // THIS LOG IS ADDED FOR TESTING,TO BE IMPROVED LATER + LOGGER.info("Checking the attribute requirement: \n {} \n for node candidate \"{}\" ", + attributeRequirement.toString(), nodeCandidate.getId()); + // THIS LOG IS ADDED FOR TESTING,TO BE IMPROVED LATER if (attributeRequirement.getRequirementClass().equals("hardware")) { switch (attributeRequirement.getRequirementAttribute()) { case "ram": @@ -121,15 +130,40 @@ public class NodeCandidateUtils { private static boolean satisfyNodeTypeRequirement(NodeTypeRequirement requirement, NodeCandidate nodeCandidate) { return (requirement.getNodeTypes().stream().anyMatch(nodeType -> { - if (nodeType.getLiteral().equals(nodeCandidate.getNodeCandidateType().name()) && + if (nodeType.getLiteral().equals(nodeCandidate.getNodeCandidateType().name()) && (( nodeType.equals(NodeType.BYON) && - requirement.getJobIdForBYON().equals(nodeCandidate.getJobIdForBYON())) { + requirement.getJobIdForBYON().equals(nodeCandidate.getJobIdForBYON())) || + ( nodeType.equals(NodeType.EDGE) && + requirement.getJobIdForEDGE().equals(nodeCandidate.getJobIdForEDGE())))) { return true; - } else return nodeType.getLiteral().equals(nodeCandidate.getNodeCandidateType().name()) && - !nodeType.equals(NodeType.BYON); + } + // THIS LOG IS ADDED FOR TESTING,TO BE IMPROVED LATER + else { + if( !nodeType.equals(NodeType.BYON) && !nodeType.equals(NodeType.EDGE)) + { + if (nodeType.getLiteral().equals(nodeCandidate.getNodeCandidateType().name())) { + return true; + } + else { + LOGGER.info("the nodeType in the requirement \"{}\" is mismatched with the node candidate \"{}\" nodeType \"{}\"", + nodeType.getLiteral(), nodeCandidate.getId(),nodeCandidate.getNodeCandidateType().name()); + return false; + } + } + else { + LOGGER.info("nodeType or jobId mismatch, \n " + + "Required: nodeType \"{}\", jobID for BYON and EDGE: \"{}\", \"{}\" \n" + + "Node candidate: nodeType \"{}\", jobID for BYON and EDGE: \"{}\", \"{}\" \n", + nodeType.getLiteral(),requirement.getJobIdForBYON(),requirement.getJobIdForEDGE(), + nodeCandidate.getNodeCandidateType().name(),nodeCandidate.getJobIdForBYON(),nodeCandidate.getJobIdForEDGE()); + return false; + } + + } // THIS LOG IS ADDED FOR TESTING,TO BE IMPROVED LATER })); } + private Hardware createHardware(JSONObject nodeCandidateJSON, PACloud paCloud) { JSONObject hardwareJSON = nodeCandidateJSON.optJSONObject("hw"); String hardwareId = paCloud.getCloudID() + "/" + diff --git a/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/nc/WhiteListedInstanceTypesUtils.java b/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/nc/WhiteListedInstanceTypesUtils.java index d0e95c71..60188a79 100644 --- a/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/nc/WhiteListedInstanceTypesUtils.java +++ b/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/nc/WhiteListedInstanceTypesUtils.java @@ -1,5 +1,8 @@ package org.activeeon.morphemic.nc; +import lombok.extern.slf4j.Slf4j; + +@Slf4j public class WhiteListedInstanceTypesUtils { /** @@ -8,6 +11,12 @@ public class WhiteListedInstanceTypesUtils { * @return True if the instance type family is while listed, false otherwise */ public static boolean isHandledHardwareInstanceType(String instanceType) { - return AwsWhiteListedInstanceTypes.isAwsWhiteListedHardwareInstanceType(instanceType); + if (AwsWhiteListedInstanceTypes.isAwsWhiteListedHardwareInstanceType(instanceType)) { + LOGGER.info(" Is aws white list family: YES"); + return true; + } else { + LOGGER.info(" Is aws white list family: NO"); + return false; + } } } diff --git a/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/service/ByonUtils.java b/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/service/ByonUtils.java index fc79d300..59b54130 100644 --- a/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/service/ByonUtils.java +++ b/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/service/ByonUtils.java @@ -28,75 +28,102 @@ public class ByonUtils { } /** - * @param byonDef an Object of class ByonDefinition that contains all the nodes Definition + * @param np an Object of class NodeProperties that contains all the nodes properties needed for the candidate declaration + * @param jobId a String identifier of the node candidate job + * @param nodeType a String of the node type (byon or edge) * @return an object of class NodeCandidate */ - public static NodeCandidate createByonNodeCandidate(ByonDefinition byonDef, String jobId) { - LOGGER.debug("Creating the BYON node candidate ..."); - //create a dummy cloud - Cloud byonCloud = ByonUtils.getOrCreateDummyByonCloud(); + public static NodeCandidate createNodeCandidate(NodeProperties np, String jobId, String nodeType) { EntityManagerHelper.begin(); - //set the image - Image image = new Image(); - image.setId("byon-image-" + RandomStringUtils.randomAlphanumeric(16)); - image.setOperatingSystem(byonDef.getNodeProperties().getOperatingSystem()); + LOGGER.debug("Creating the {} node candidate ...", nodeType.toUpperCase()); + //Start by setting the universal nodes properties + NodeCandidate nc = new NodeCandidate(); + nc.setPrice(0.0); + nc.setMemoryPrice(0.0); + nc.setPricePerInvocation(0.0); - //set the hardware + //create a dummy cloud definition for BYON nodes + Cloud dummyCloud = new Cloud(); + dummyCloud = ByonUtils.getOrCreateDummyCloud(nodeType); + //Create a dummy image + Image image = new Image(); + image.setOperatingSystem(np.getOperatingSystem()); + //Define the hardware Hardware hardware = new Hardware(); - hardware.setId("byon-hardware-" + RandomStringUtils.randomAlphanumeric(16)); - hardware.setCores(byonDef.getNodeProperties().getNumberOfCores()); - hardware.setDisk((double) byonDef.getNodeProperties().getDisk()); - hardware.setRam(byonDef.getNodeProperties().getMemory()); - - //set the location + hardware.setCores(np.getNumberOfCores()); + hardware.setDisk((double) np.getDisk()); + hardware.setRam(np.getMemory()); + //Define the location Location location = new Location(); - location.setId("byon-location-" + RandomStringUtils.randomAlphanumeric(16)); - location.setGeoLocation(byonDef.getNodeProperties().getGeoLocation()); - - //define a dummy NC - NodeCandidate byonNC = new NodeCandidate(); - byonNC.setNodeCandidateType(NodeCandidate.NodeCandidateTypeEnum.BYON); - byonNC.setJobIdForBYON(jobId); - byonNC.setPrice(0.0); - byonNC.setMemoryPrice(0.0); - byonNC.setPricePerInvocation(0.0); - byonNC.setCloud(byonCloud); - byonNC.setImage(image); - byonNC.setHardware(hardware); - byonNC.setLocation(location); - - EntityManagerHelper.persist(byonNC); - EntityManagerHelper.commit(); - LOGGER.info("BYON node candidate created."); - return byonNC; + location.setGeoLocation(np.getGeoLocation()); + + //Define the properties that depend on the node type + + if (nodeType.equals("byon")) { + + //set the image name + image.setId("byon-image-" + RandomStringUtils.randomAlphanumeric(16)); + //set the hardware + hardware.setId("byon-hardware-" + RandomStringUtils.randomAlphanumeric(16)); + //set the location + location.setId("byon-location-" + RandomStringUtils.randomAlphanumeric(16)); + //set the nc parameters + nc.setNodeCandidateType(NodeCandidate.NodeCandidateTypeEnum.BYON); + // set the nc jobIdForBYON + nc.setJobIdForBYON(jobId); + // set the nc jobIdForEDGE + nc.setJobIdForEDGE(null); + } + else { //the node type is EDGE + + //set the image name + image.setId("edge-image-" + RandomStringUtils.randomAlphanumeric(16)); + //set the hardware + hardware.setId("edge-hardware-" + RandomStringUtils.randomAlphanumeric(16)); + //set the location + location.setId("edge-location-" + RandomStringUtils.randomAlphanumeric(16)); + //set the nc parameters + nc.setNodeCandidateType(NodeCandidate.NodeCandidateTypeEnum.EDGE); + // set the nc jobIdForBYON + nc.setJobIdForBYON(null); + // set the nc jobIdForEDGE + nc.setJobIdForEDGE(jobId); + } + + nc.setCloud(dummyCloud); + nc.setImage(image); + nc.setHardware(hardware); + nc.setLocation(location); + EntityManagerHelper.persist(nc); + LOGGER.info("{} node candidate created.", nodeType.toUpperCase()); + return nc; } /** * Create a dummy object of class Cloud to be used for the node candidates * @return the created byonCloud object */ - public static Cloud getOrCreateDummyByonCloud() { - LOGGER.debug("Searching for the dummy BYON cloud ..."); + public static Cloud getOrCreateDummyCloud(String nodeType) { + LOGGER.debug("Searching for the dummy cloud ..."); EntityManagerHelper.begin(); //Check if the Byon cloud already exists - Optional optCloud = Optional.ofNullable(EntityManagerHelper.find(Cloud.class, "byon")); + Optional optCloud = Optional.ofNullable(EntityManagerHelper.find(Cloud.class, nodeType)); if (optCloud.isPresent()) { - LOGGER.info("Dummy BYON cloud found!"); + LOGGER.info("Dummy cloud for {} was found!", nodeType); return optCloud.get(); } - LOGGER.debug("Creating the dummy BYON cloud ..."); + LOGGER.debug("Creating the dummy cloud for {} Nodes ...", nodeType); //else, Byon cloud will be created - Cloud byonCloud = new Cloud(); - byonCloud.setCloudType(CloudType.BYON); - byonCloud.setOwner("BYON"); - byonCloud.setId("byon"); + Cloud newCloud = new Cloud(); + newCloud.setCloudType((nodeType.equals("byon")) ? CloudType.BYON : CloudType.EDGE); + newCloud.setOwner((nodeType.equals("byon")) ? "BYON" : "EDGE"); + newCloud.setId(nodeType); //Add the Byon cloud to the database - EntityManagerHelper.persist(byonCloud); - EntityManagerHelper.commit(); - LOGGER.info("Dummy BYON cloud created."); - return byonCloud; + EntityManagerHelper.persist(newCloud); + LOGGER.info("Dummy {} cloud created.", nodeType.toUpperCase()); + return newCloud; /* TODO : * Check if we have to add other variables to the new cloud diff --git a/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/service/JCloudsInstancesUtils.java b/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/service/JCloudsInstancesUtils.java index 7aa53126..4bbe6196 100644 --- a/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/service/JCloudsInstancesUtils.java +++ b/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/service/JCloudsInstancesUtils.java @@ -35,8 +35,15 @@ public class JCloudsInstancesUtils { */ public static boolean isHandledHardwareInstanceType(String providerName, String instanceType) { if ("aws-ec2".equals(providerName)) - return handledAWSInstanceTypes.contains(instanceType); + if (handledAWSInstanceTypes.contains(instanceType)) { + LOGGER.info(" Is aws handled by JClouds: YES"); + return true; + } else { + LOGGER.info(" Is aws handled by JClouds: NO"); + return false; + } // TODO: To check if for other cloud providers all instance types are handled by JClouds + LOGGER.info(" Is handled by JClouds: YES"); return true; } } diff --git a/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/service/TaskBuilder.java b/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/service/TaskBuilder.java index bc66c211..73b65f2a 100644 --- a/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/service/TaskBuilder.java +++ b/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/service/TaskBuilder.java @@ -148,7 +148,8 @@ public class TaskBuilder { case IAAS: return createInfraIAASTask(task, deployment, taskNameSuffix, nodeToken); case BYON: - return createInfraBYONTask(task, deployment, taskNameSuffix, nodeToken); + case EDGE: + return createInfraBYONandEDGETask(task, deployment, taskNameSuffix, nodeToken); } return new ScriptTask(); @@ -157,7 +158,7 @@ public class TaskBuilder { private void addLocalDefaultNSRegexSelectionScript(ScriptTask scriptTask) { try { String selectionScriptFileName = "check_node_source_regexp.groovy"; - String[] nodeSourceNameRegex = {"^local$|^Default$"}; + String[] nodeSourceNameRegex = {"^local$|^Default$|^LocalNodes$"}; SelectionScript selectionScript = new SelectionScript(Utils.getContentWithFileName(selectionScriptFileName), "groovy", nodeSourceNameRegex, @@ -268,10 +269,12 @@ public class TaskBuilder { return new ScriptTask(); } - private ScriptTask createInfraBYONTask(Task task, Deployment deployment, String taskNameSuffix, String nodeToken) { - LOGGER.debug("Acquiring node BYON script file: " + getClass().getResource(File.separator + "acquire_node_BYON_script.groovy").toString()); - ScriptTask deployNodeTask = PAFactory.createGroovyScriptTaskFromFile("acquireBYONNode_" + task.getName() + taskNameSuffix, - "acquire_node_BYON_script.groovy"); + private ScriptTask createInfraBYONandEDGETask(Task task, Deployment deployment, String taskNameSuffix, String nodeToken) { + String nodeType = deployment.getDeploymentType().getName(); + System.out.println("the nodeType name is: "+ nodeType); + LOGGER.debug("Acquiring node " + nodeType + " script file: " + getClass().getResource(File.separator + "acquire_node_BYON_script.groovy").toString()); + ScriptTask deployNodeTask = PAFactory.createGroovyScriptTaskFromFile("acquire"+nodeType+"Node_" + task.getName() + taskNameSuffix, + "acquire_node_BYON_script.groovy"); deployNodeTask.setPreScript(PAFactory.createSimpleScriptFromFIle("pre_acquire_node_script.groovy", "groovy")); diff --git a/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/workflow/analyser/WfAnalyser.java b/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/workflow/analyser/WfAnalyser.java new file mode 100644 index 00000000..322ff401 --- /dev/null +++ b/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/workflow/analyser/WfAnalyser.java @@ -0,0 +1,116 @@ +package org.activeeon.morphemic.workflow.analyser; + +import org.jdom2.Document; +import org.jdom2.Element; +import org.jdom2.JDOMException; +import org.jdom2.input.SAXBuilder; +import org.json.JSONArray; +import org.json.JSONObject; + +import java.io.File; +import java.io.IOException; +import java.util.List; + +/* + * This class contains the java endpoints that build from a Camel model the component grouping JSON + * and the dot graph syntax of the application. + * + * Developed by Activeeon in the context of H2020 MORPHEMIC project. + * @author Activeeon R&D Department + */ + +public class WfAnalyser { + + // Environment Variable Name for the camel xmi model path = CAMEL_XMI_DIR, e.g. CAMEL_XMI_DIR = "/users/user1/Documents/camel.xmi" + private static final String PROPERTIES_FILE_ENVIRONMENT_VARIABLE_NAME = "CAMEL_XMI_DIR"; + + Element camelModelRoot; + + WfAnalyserCamelUtils wfAnalyserCamelUtils; + + public WfAnalyser() throws IOException, JDOMException { + SAXBuilder builder = new SAXBuilder(); + String path = System.getenv(PROPERTIES_FILE_ENVIRONMENT_VARIABLE_NAME); + File xmiFile = new File(path); + Document document = builder.build(xmiFile); + this.camelModelRoot = document.getRootElement(); + wfAnalyserCamelUtils = new WfAnalyserCamelUtils(this.camelModelRoot); + } + + public WfAnalyser(String path) throws IOException, JDOMException { + SAXBuilder builder = new SAXBuilder(); + File xmiFile = new File(path); + Document document = builder.build(xmiFile); + this.camelModelRoot = document.getRootElement(); + wfAnalyserCamelUtils = new WfAnalyserCamelUtils(this.camelModelRoot); + } + + public JSONObject getJsonGrouping() { + JSONObject result = new JSONObject(); + JSONArray applicationComponents = new JSONArray(); + + // Get application name + Element applicationElement = camelModelRoot.getChild("application"); + result.put("Application_name", applicationElement.getAttributeValue("name")); + + // Get number of components + List components = camelModelRoot.getChild("deploymentModels").getChildren("softwareComponents"); + result.put("Number_of_components", components.size()); + + // App Requirements + result.put("General_requirements", wfAnalyserCamelUtils.getAppRequirements(components.size())); + + // Get components metadata: name, requirements, long_lived, ... + for(Element component: components){ + JSONObject componentMetaData = new JSONObject(); + + // Get component name + componentMetaData.put("name", component.getAttributeValue("name")); + + // Get component long_lived value if it exists + componentMetaData.put("Long_lived", component.getAttributeValue("longLived")); + + // Get resource requirements + String resourceReqValue = component.getAttributeValue("requirementSet"); + int reqIndex = Integer.parseInt(resourceReqValue.split("@requirementSets.")[1]); + JSONArray resourceRequirements = wfAnalyserCamelUtils.getResourceRequirements(reqIndex); + componentMetaData.put("Resources", resourceRequirements); + + // Get component variants + componentMetaData.put("Variants", WfAnalyserXmiElementUtils.getVariants(component)); + + applicationComponents.put(componentMetaData); + } + result.put("Application_components", applicationComponents); + result.put("Application_graph", wfAnalyserCamelUtils.getWorkflowArchitecture()); + return result; + } + + public String generateDotGraph() { + StringBuilder dotGraphSyntax = new StringBuilder(); + + // Write the dot file header + dotGraphSyntax.append("digraph g {\n"); + + // Add components to the do graph + List components = camelModelRoot.getChild("deploymentModels").getChildren("softwareComponents"); + for(Element component: components) { + dotGraphSyntax.append(component.getAttributeValue("name")).append("[fontcolor=black, color=orange];\n"); + } + // Add required communication + for(Element component: components) { + List requiredCommunications = component.getChildren("requiredCommunications"); + for(Element requiredCommunication: requiredCommunications) { + dotGraphSyntax.append(WfAnalyserXmiElementUtils.findRequiredComponent(components, requiredCommunication.getAttributeValue("portNumber"))) + .append("->") + .append(component.getAttributeValue("name")) + .append(" [fillcolor=grey, fontcolor=blue, color=grey, fontsize=6]").append(";"); + dotGraphSyntax.append("\n"); + } + } + // Write the dot file end character + dotGraphSyntax.append("}\n"); + return dotGraphSyntax.toString(); + } + +} \ No newline at end of file diff --git a/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/workflow/analyser/WfAnalyserCamelUtils.java b/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/workflow/analyser/WfAnalyserCamelUtils.java new file mode 100644 index 00000000..cd81ca84 --- /dev/null +++ b/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/workflow/analyser/WfAnalyserCamelUtils.java @@ -0,0 +1,137 @@ +package org.activeeon.morphemic.workflow.analyser; + +import lombok.AllArgsConstructor; +import org.jdom2.Element; +import org.json.JSONArray; +import org.json.JSONObject; + +import java.util.List; + +/* + * This class contains the methods that handle an XMI model to generate the corresponding JSON objects. + * + * Developed by Activeeon in the context of H2020 MORPHEMIC project. + * @author Activeeon R&D Department + */ + +@AllArgsConstructor +public class WfAnalyserCamelUtils { + + Element camelModelRoot; + + public JSONArray getResourceRequirements(int reqIndex) { + JSONArray resourceRequirement = new JSONArray(); + Element requirementModels = camelModelRoot.getChild("requirementModels"); + // Get component Req by index + Element compRequirement = requirementModels.getChildren("requirements").get(reqIndex); + // Get component req features + List subFeatures = compRequirement.getChildren("subFeatures"); + // Get list of attributes per component feature + for(Element feature: subFeatures) { + JSONObject requirement = new JSONObject(); + String reqName = feature.getAttributeValue("annotations"); + // Get list of attributes per requirement element + List attributes = feature.getChildren("attributes"); + JSONArray listOfRequirements = new JSONArray(); + for(Element attribute: attributes) { + // Get attribute name + String attributeName = attribute.getAttributeValue("name"); + // Get attribute value + String value = attribute.getChild("value").getAttributeValue("value"); + JSONObject attributeValue = new JSONObject(); + // Create json object with attribute name and value + attributeValue.put(attributeName, value); + // Add the attribute object to the list + listOfRequirements.put(attributeValue); + } + requirement.put(reqName, listOfRequirements); + resourceRequirement.put(requirement); + } + return resourceRequirement; + } + + + public JSONArray getAppRequirements(int startIndex) { + JSONArray appRequirements = new JSONArray(); + Element requirementModels = camelModelRoot.getChild("requirementModels"); + // Get component Req + List compRequirements = requirementModels.getChildren("requirements"); + for(int i=startIndex; i images = requirement.getChildren("images"); + JSONArray imagesValue = new JSONArray(); + for(Element image: images) { + imagesValue.put(image.getValue()); + } + + if(imagesValue.length()>0) { + instancesRequirementObject.put("Images for: " + reqName, imagesValue); + } + + if(!instancesReq.isEmpty()) { + instancesRequirementObject.put(reqName, instancesReq); + } + + //instancesRequirementObject.get() + + if(!instancesRequirementObject.isEmpty()) { + appRequirements.put(instancesRequirementObject); + } + } + return appRequirements; + } + + + public JSONArray getWorkflowArchitecture() { + JSONArray results = new JSONArray(); + List components = camelModelRoot.getChild("deploymentModels").getChildren("softwareComponents"); + for(Element component: components) { + JSONArray cnx = new JSONArray(); + List requiredCommunications = component.getChildren("requiredCommunications"); + List providedCommunications = component.getChildren("providedCommunications"); + for(Element requiredCommunication: requiredCommunications) { + String connectionName = WfAnalyserXmiElementUtils.findProvidedComponent(components, requiredCommunication.getAttributeValue("portNumber")); + if(!connectionName.isEmpty()) { + cnx.put(connectionName); + } + } + for(Element providedCommunication: providedCommunications) { + String connectionName = WfAnalyserXmiElementUtils.findProvidedComponent(components, providedCommunication.getAttributeValue("portNumber")); + if(!connectionName.isEmpty()) { + cnx.put(connectionName); + } + } + JSONObject compConnections = new JSONObject(); + compConnections.put(component.getAttributeValue("name"), cnx); + results.put(compConnections); + } + return results; + } + + +} diff --git a/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/workflow/analyser/WfAnalyserXmiElementUtils.java b/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/workflow/analyser/WfAnalyserXmiElementUtils.java new file mode 100644 index 00000000..6ca625eb --- /dev/null +++ b/scheduling-abstraction-layer/src/main/java/org/activeeon/morphemic/workflow/analyser/WfAnalyserXmiElementUtils.java @@ -0,0 +1,50 @@ +package org.activeeon.morphemic.workflow.analyser; + +import org.jdom2.Element; +import org.json.JSONArray; + +import java.util.List; + +/* + * This class contains the methods that handle XMI elements to generate the corresponding JSON objects. + * + * Developed by Activeeon in the context of H2020 MORPHEMIC project. + * @author Activeeon R&D Department + */ + +public class WfAnalyserXmiElementUtils { + + + public static String findRequiredComponent(List components, String portNumber) { + for(Element component: components) { + if(component.getChildren("providedCommunications").stream().anyMatch(provComm -> provComm.getAttributeValue("portNumber").equals(portNumber))) { + return component.getAttributeValue("name"); + } + } + return ""; + } + + public static String findProvidedComponent(List components, String portNumber) { + for(Element component: components) { + if(component.getChildren("requiredCommunications").stream().anyMatch(provComm -> provComm.getAttributeValue("portNumber").equals(portNumber))) { + return component.getAttributeValue("name"); + } + } + return ""; + } + + public static JSONArray getVariants(Element component) { + JSONArray variants = new JSONArray(); + List attributes = component.getChildren("attributes"); + for(Element element: attributes) { + String value = element.getChild("value").getAttributeValue("value"); + if(value.contains("VM") || value.contains("DOCKER") || value.contains("SERVERLESS") || value.contains("HPC")) { + variants.put(value); + } + } + return variants; + } + + private WfAnalyserXmiElementUtils() {} + +} diff --git a/scheduling-abstraction-layer/src/main/resources/Define_NS_AWS.xml b/scheduling-abstraction-layer/src/main/resources/Define_NS_AWS.xml index 597fc3de..a0fbf7fc 100644 --- a/scheduling-abstraction-layer/src/main/resources/Define_NS_AWS.xml +++ b/scheduling-abstraction-layer/src/main/resources/Define_NS_AWS.xml @@ -8,6 +8,9 @@ + + + @@ -46,8 +49,8 @@ def infrastructureParameters = [variables.get("aws_username"), //username variables.get("NS_nVMs"), //N of VMs "1", //N VMs per node variables.get("image"), //image - "", //OS - "", //awsKeyPair + variables.get("sshUsername"), //sshUsername + variables.get("sshKeyPairName"), //sshKeyPair "", //ram "", //Ncore variables.get("security_group"), //sg @@ -59,7 +62,7 @@ def infrastructureParameters = [variables.get("aws_username"), //username "300000", //timeout "", ""] -def infrastructureFileParameters = [""] +def infrastructureFileParameters = [variables.get("sshPrivateKey")] def policyType = "org.ow2.proactive.resourcemanager.nodesource.policy.EmptyPolicy" def poliyParameters = ["ALL","ME"] def policyFileParameters = [] diff --git a/scheduling-abstraction-layer/src/main/resources/Define_NS_AWS_AutoScale.xml b/scheduling-abstraction-layer/src/main/resources/Define_NS_AWS_AutoScale.xml index 4c24f0b9..1bc0f752 100644 --- a/scheduling-abstraction-layer/src/main/resources/Define_NS_AWS_AutoScale.xml +++ b/scheduling-abstraction-layer/src/main/resources/Define_NS_AWS_AutoScale.xml @@ -10,6 +10,7 @@ + @@ -48,12 +49,12 @@ def infrastructureParameters = ["proactive-nodesource-", //vmGroupTagPrefix "100", //maxVms variables.get("instance_type"), //defaultInstanceType variables.get("image"), //image - "", //awsKeyPair + variables.get("sshKeyPairName"), //awsKeyPair "", //vpc variables.get("subnet"), //subnet variables.get("security_group"), //sg variables.get("region"), //region - "pamr://0/", //rmUrl + "pamr://0/", //rmUrl //use pamr://4096/ for trydevs testing variables.get("rm_host_name"), //host protocol + "://" + variables.get("rm_host_name") + ":"+ variables.get("pa_port") + "/rest/node.jar", //node jar url "-Dproactive.useIPaddress=true", //additionalProperties" diff --git a/scheduling-abstraction-layer/src/main/resources/Define_NS_BYON.xml b/scheduling-abstraction-layer/src/main/resources/Define_NS_BYON.xml index 5dec694c..463f71ff 100644 --- a/scheduling-abstraction-layer/src/main/resources/Define_NS_BYON.xml +++ b/scheduling-abstraction-layer/src/main/resources/Define_NS_BYON.xml @@ -1,7 +1,7 @@ + xmlns="urn:proactive:jobdescriptor:3.12" xsi:schemaLocation="urn:proactive:jobdescriptor:3.12 http://www.activeeon.com/public_content/schemas/proactive/jobdescriptor/3.12/schedulerjob.xsd" name="Define_NS_BYON" priority="normal" onTaskError="continueJobExecution" maxNumberOfExecution="2" > @@ -75,7 +75,11 @@ def infrastructureParameters = ["300000", //Node Time out "/opt/ProActive_node_agent/jre/bin/java", //JavaPath on the remote host "/opt/ProActive_node_agent", //ScheduligPath on the remote hosts "Linux", //targetOs - javaOptions]//Java options + javaOptions, //Java options + "autoGenerated", //deploymentMode + "", //nodeJarUrl + "", //startupScriptStandard + ""] //startupScriptWithNodeJarDownload def infrastructureFileParameters = [hosts, //hostsList file content "", //SSH Private Key diff --git a/scheduling-abstraction-layer/src/main/resources/Define_NS_EDGE.xml b/scheduling-abstraction-layer/src/main/resources/Define_NS_EDGE.xml new file mode 100644 index 00000000..fd6d7f57 --- /dev/null +++ b/scheduling-abstraction-layer/src/main/resources/Define_NS_EDGE.xml @@ -0,0 +1,152 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 508.96875 + + + 515.5 + + + + + + + + + + + + + + + + ]]> + + + \ No newline at end of file diff --git a/scheduling-abstraction-layer/src/main/resources/Define_NS_OS.xml b/scheduling-abstraction-layer/src/main/resources/Define_NS_OS.xml index 9c56d9d1..33769756 100644 --- a/scheduling-abstraction-layer/src/main/resources/Define_NS_OS.xml +++ b/scheduling-abstraction-layer/src/main/resources/Define_NS_OS.xml @@ -11,6 +11,7 @@ + @@ -57,7 +58,7 @@ def infrastructureParameters = [variables.get("os_username"), //username "irrelevant_image", //image "irrelevant_flavor", //flavor variables.get("os_networkId"), // networkId - "", //publicKeyName + variables.get("sshKeyPairName"), //keyPairName variables.get("NS_nVMs"), //numberOfInstance "1", //N VMs per node protocol + "://" + variables.get("rm_host_name") + ":"+ variables.get("pa_port") + "/connector-iaas", //connector-iaas url diff --git a/scheduling-abstraction-layer/src/main/resources/META-INF/persistence.xml b/scheduling-abstraction-layer/src/main/resources/META-INF/persistence.xml index e1bfee52..e31dde8f 100644 --- a/scheduling-abstraction-layer/src/main/resources/META-INF/persistence.xml +++ b/scheduling-abstraction-layer/src/main/resources/META-INF/persistence.xml @@ -19,6 +19,7 @@ org.activeeon.morphemic.model.Location org.activeeon.morphemic.model.Hardware org.activeeon.morphemic.model.ByonNode + org.activeeon.morphemic.model.EdgeNode diff --git a/scheduling-abstraction-layer/src/main/resources/prepare_infra_script.sh b/scheduling-abstraction-layer/src/main/resources/prepare_infra_script.sh index fa1ef652..7dae2c4a 100644 --- a/scheduling-abstraction-layer/src/main/resources/prepare_infra_script.sh +++ b/scheduling-abstraction-layer/src/main/resources/prepare_infra_script.sh @@ -1,8 +1,20 @@ PROVIDED_PORT_NAME=$variables_providedPortName if [[ ! -z $PROVIDED_PORT_NAME ]]; then - IP_ADDR=$(dig +short myip.opendns.com @resolver1.opendns.com) - echo Public adress: $IP_ADDR + + wget -q https://raw.githubusercontent.com/ow2-proactive/utility-scripts/main/network-scripts/Get_public_ip.sh && chmod +x Get_public_ip.sh || { echo "failed to download the IP script"; exit 1; } + IP_ADDR=`./Get_public_ip.sh` + CODE=$? + echo "The Public IP was retreived with code: $CODE" + + if [[ $CODE -lt 6 ]] + then + echo Public adress: $IP_ADDR + else + echo "Getting the Public IP failed!" + echo "The recieved IP: $IP_ADDR" + exit 1 + fi echo "$IP_ADDR" > $PROVIDED_PORT_NAME"_ip" fi \ No newline at end of file -- GitLab