Commit e7a6e354 authored by Mohamed Khalil Labidi's avatar Mohamed Khalil Labidi
Browse files

Merge branch 'byon-ns' into proactive-dev

parents a0926ee0 3ed89bc5
......@@ -2,7 +2,9 @@ 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.hibernate.annotations.GenericGenerator;
import javax.persistence.*;
......@@ -17,6 +19,8 @@ import java.util.Objects;
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Getter
@Setter
@Table(name = "BYON_NODE")
public class ByonNode implements Serializable {
@Id
......@@ -49,9 +53,8 @@ public class ByonNode implements Serializable {
@JsonProperty("diagnostic")
private String diagnostic = null;
@Column(name = "NODE_CANDIDATE")
@JsonProperty("nodeCandidate")
private String nodeCandidate = null;
@OneToOne(fetch = FetchType.EAGER, orphanRemoval = true, cascade = CascadeType.REFRESH)
private NodeCandidate nodeCandidate = null;
@Column(name = "USER_ID")
@JsonProperty("userId")
......@@ -61,6 +64,9 @@ public class ByonNode implements Serializable {
@JsonProperty("allocated")
private Boolean allocated = null;
@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.REFRESH)
private Job job;
public ByonNode name(String name) {
this.name = name;
return this;
......@@ -142,85 +148,24 @@ public class ByonNode implements Serializable {
return this;
}
/**
* Reason this node was created
* @return reason
**/
public String getReason() {
return reason;
}
public void setReason(String reason) {
this.reason = reason;
}
public ByonNode diagnostic(String diagnostic) {
this.diagnostic = diagnostic;
return this;
}
/**
* Diagnostic information about the node state
* @return diagnostic
**/
public String getDiagnostic() {
return diagnostic;
}
public void setDiagnostic(String diagnostic) {
this.diagnostic = diagnostic;
}
public ByonNode nodeCandidate(String nodeCandidate) {
this.nodeCandidate = nodeCandidate;
return this;
}
/**
* The node candidate this node was created from if applicable.
* @return nodeCandidate
**/
public String getNodeCandidate() {
return nodeCandidate;
}
public void setNodeCandidate(String nodeCandidate) {
this.nodeCandidate = nodeCandidate;
}
public ByonNode id(String id) {
this.id = id;
return this;
}
/**
* Unique identifier of this BYON.
* @return id
**/
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public ByonNode userId(String userId) {
this.userId = userId;
return this;
}
/**
* User id of the owner of this node.
* @return userId
**/
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public ByonNode allocated(Boolean allocated) {
this.allocated = allocated;
......@@ -235,11 +180,6 @@ public class ByonNode implements Serializable {
return allocated;
}
public void setAllocated(Boolean allocated) {
this.allocated = allocated;
}
@Override
public boolean equals(java.lang.Object o) {
if (this == o) {
......
......@@ -14,6 +14,8 @@ public enum CloudType {
PUBLIC("PUBLIC"),
BYON("BYON"),
SIMULATION("SIMULATION");
private String value;
......
......@@ -53,20 +53,48 @@ public class Deployment implements Serializable {
@Embedded
private IpAddress ipAddress = null;
@Column(name = "NODE_TYPE")
@Enumerated(EnumType.STRING)
private NodeType deploymentType;
@OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.REFRESH)
private ByonNode byonNode;
@Override
public String toString() {
return "Deployment{" +
"nodeName='" + nodeName + '\'' +
", locationName='" + locationName + '\'' +
", imageProviderId='" + imageProviderId + '\'' +
", hardwareProviderId='" + hardwareProviderId + '\'' +
", isDeployed='" + isDeployed.toString() + '\'' +
", instanceId='" + instanceId + '\'' +
", ipAddress='" + ipAddress + '\'' +
", nodeAccessToken='" + nodeAccessToken + '\'' +
", number='" + number + '\'' +
", paCloud='" + paCloud.getNodeSourceNamePrefix() + '\'' +
", task='" + task.getName() + '\'' +
'}';
switch (deploymentType) {
case IAAS:
return "Deployment{" +
"nodeName='" + nodeName + '\'' +
", locationName='" + locationName + '\'' +
", imageProviderId='" + imageProviderId + '\'' +
", hardwareProviderId='" + hardwareProviderId + '\'' +
", isDeployed='" + isDeployed.toString() + '\'' +
", instanceId='" + instanceId + '\'' +
", ipAddress='" + ipAddress + '\'' +
", nodeAccessToken='" + nodeAccessToken + '\'' +
", number='" + number + '\'' +
", paCloud='" + paCloud.getNodeSourceNamePrefix() + '\'' +
", task='" + task.getName() + '\'' +
", byonNode='" + byonNode + '\'' +
'}';
case BYON:
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() + '\'' +
", byonNode='" + byonNode.getName() + '\'' +
'}';
default:
return "Deployment{nodeName='" + nodeName + '}';
}
}
}
......@@ -71,7 +71,7 @@ public class NodeCandidate implements Serializable {
private NodeCandidateTypeEnum nodeCandidateType = null;
@Column(name = "JOB_ID_FOR_BYON")
@JsonProperty("nodeType")
@JsonProperty("jobIdForByon")
private String jobIdForBYON;
@Column(name = "PRICE")
......@@ -288,6 +288,13 @@ public class NodeCandidate implements Serializable {
this.environment = environment;
}
/**
* Check if a node candidate is of BYON type
* @return true if yes, false if not
*/
public boolean isByonNodeCandidate() {
return nodeCandidateType.value.equals("BYON");
}
@Override
public boolean equals(java.lang.Object o) {
......
......@@ -16,7 +16,7 @@ public class NodeTypeRequirement extends Requirement {
@JsonProperty("nodeType")
private List<NodeType> nodeTypes;
@JsonProperty("nodeType")
@JsonProperty("jobIdForByon")
private String jobIdForBYON;
/**
......
package org.activeeon.morphemic.service;
import lombok.extern.slf4j.Slf4j;
import org.activeeon.morphemic.model.*;
import org.apache.commons.lang3.RandomStringUtils;
import java.util.Optional;
@Slf4j
public class ByonUtils {
private ByonUtils() {}
/**
* @param byonDef an Object of class ByonDefinition that contains all the nodes Definition
* @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();
EntityManagerHelper.begin();
//set the image
Image image = new Image();
image.setId("byon-image-" + RandomStringUtils.randomAlphanumeric(16));
image.setOperatingSystem(byonDef.getNodeProperties().getOperatingSystem());
//set 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
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;
}
/**
* 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 ...");
EntityManagerHelper.begin();
//Check if the Byon cloud already exists
Optional<Cloud> optCloud = Optional.ofNullable(EntityManagerHelper.find(Cloud.class, "byon"));
if (optCloud.isPresent()) {
LOGGER.info("Dummy BYON cloud found!");
return optCloud.get();
}
LOGGER.debug("Creating the dummy BYON cloud ...");
//else, Byon cloud will be created
Cloud byonCloud = new Cloud();
byonCloud.setCloudType(CloudType.BYON);
byonCloud.setOwner("BYON");
byonCloud.setId("byon");
//Add the Byon cloud to the database
EntityManagerHelper.persist(byonCloud);
EntityManagerHelper.commit();
LOGGER.info("Dummy BYON cloud created.");
return byonCloud;
/* TODO :
* Check if we have to add other variables to the new cloud
*/
}
}
<?xml version="1.0" encoding="UTF-8"?>
<job
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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.xml" priority="normal" onTaskError="continueJobExecution" maxNumberOfExecution="2" >
<variables>
<variable name="pa_port" value="8080" model="PA:Integer"/>
<variable name="NS_name" value="SSH_INFRA" model="PA:NOT_EMPTY_STRING"/>
<variable name="pa_protocol" value="http" model="PA:NOT_EMPTY_STRING"/>
<variable name="rm_host_name" value="example.com" model="PA:NOT_EMPTY_STRING"/>
<variable name="ssh_username" value="node" model="PA:NOT_EMPTY_STRING"/>
<variable name="ssh_password" value="" model="PA:HIDDEN"/>
<variable name="ssh_key" value="" model="PA:HIDDEN"/>
<variable name="ssh_port" value="22" model="PA:Integer"/>
<variable name="list_of_ips" value="127.0.0.1" model="PA:NOT_EMPTY_STRING"/>
<variable name="tokens" value="" model=""/>
</variables>
<description>
<![CDATA[ A workflow that executes Groovy in JVM. ]]>
</description>
<taskFlow>
<task name="Create_NodeSource"
fork="true">
<description>
<![CDATA[ The simplest task, ran by a Groovy engine. ]]>
</description>
<scriptExecutable>
<script>
<code language="groovy">
<![CDATA[
// Connecting to the Scheduler
import java.io.File
def retCode = 0;
def tokens= variables.get("tokens")
def nodeSourceName = variables.get("NS_name")
def protocol = variables.get("pa_protocol")
def host = variables.get("rm_host_name")
def port = variables.get("pa_port")
def sshUsername = variables.get("ssh_username")
def sshPassword = variables.get("ssh_password")
def sshKey = variables.get("ssh_key")
def sshPort = variables.get("ssh_port")
def ips= variables.get("list_of_ips")
def javaOptions = "-Dproactive.net.nolocal=true -Dproactive.communication.protocol=pamr -Dproactive.useIPaddress=true -Dproactive.pamr.router.address=" + host
ips = ips.split(",")
def hosts = ""
for (ip in ips) {
hosts = hosts + ip + " 1\n"
}
if (tokens=="") {
tokens="ALL"
}
else {
tokens="tokens="+tokens
}
println "[+] Preparation of NodeSoure " + nodeSourceName
print "(1/4) Connecting to the RM at "+protocol+"://"+host+":"+port+"/ ..."
rmapi.connect()
println " OK!"
//Getting NS configuration settings
def infrastructureType = "org.ow2.proactive.resourcemanager.nodesource.infrastructure.SSHInfrastructureV2"
def infrastructureParameters = ["60000", //Node Time out
"5", //Max deployment failure
"5000", //wait between Deployment
sshPort,//port, //SSH port
sshUsername, //SSH Username
sshPassword, //SSH Password
"/opt/activeeon_enterprise-node-linux-x64-12.1.0-SNAPSHOT/jre/bin/java", //JavaPath on the remote host
"/opt/activeeon_enterprise-node-linux-x64-12.1.0-SNAPSHOT", //ScheduligPath on the remote hosts
"Linux", //targetOs
javaOptions]//Java options
def infrastructureFileParameters = [hosts, //hostsList file content
"", //SSH Private Key
"" //SSH Options
]
def policyType = "org.ow2.proactive.resourcemanager.nodesource.policy.StaticPolicy"
def poliyParameters = [tokens,"ALL"]
def policyFileParameters = [""]
def nodesRecoverable = "true"
print "(2/4) Creating NodeSource ..."
rmapi.defineNodeSource(nodeSourceName,infrastructureType,(String[]) infrastructureParameters.toArray(),(String[]) infrastructureFileParameters.toArray(), policyType, (String[]) poliyParameters.toArray(), (String[]) policyFileParameters.toArray(),nodesRecoverable)
println " ... OK !"
print "(3/4) Deploying the NodeSource ..."
rmapi.deployNodeSource(nodeSourceName)
println " ... OK !"
print "(4/4) Done"
return retCode;
]]>
</code>
</script>
</scriptExecutable>
<metadata>
<positionTop>
511
</positionTop>
<positionLeft>
514.5
</positionLeft>
</metadata>
</task>
</taskFlow>
<metadata>
<visualization>
<![CDATA[ <html>
<head>
<link rel="stylesheet" href="/studio/styles/studio-standalone.css">
<style>
#workflow-designer {
left:0 !important;
top:0 !important;
width:2726px;
height:3360px;
}
</style>
</head>
<body>
<div id="workflow-visualization-view"><div id="workflow-visualization" style="position:relative;top:-506px;left:-509.5px"><div class="task _jsPlumb_endpoint_anchor_ ui-draggable" id="jsPlumb_1_19" style="top: 511px; left: 514.5px; z-index: 24;"><a class="task-name" data-toggle="tooltip" data-placement="right" title="The simplest task, ran by a Groovy engine."><img src="/studio/images/Groovy.png" width="20px">&nbsp;<span class="name">Create_NodeSource</span></a></div><div class="_jsPlumb_endpoint source-endpoint dependency-source-endpoint connected _jsPlumb_endpoint_anchor_ ui-draggable ui-droppable" style="position: absolute; height: 20px; width: 20px; left: 567px; top: 541px;"><svg style="position:absolute;left:0px;top:0px" width="20" height="20" pointer-events="all" position="absolute" version="1.1" xmlns="http://www.w3.org/1999/xhtml"><circle cx="10" cy="10" r="10" version="1.1" xmlns="http://www.w3.org/1999/xhtml" fill="#666" stroke="none" style=""></circle></svg></div></div></div>
</body>
</html>
]]>
</visualization>
</metadata>
</job>
\ No newline at end of file
import org.ow2.proactive.resourcemanager.common.event.RMNodeEvent
// Conncting to the Scheduler
println "[+] Preparation of Nodes ... "
print "(1/4) Connecting to the RM ..."
rmapi.connect()
println " ... OK !"
// Getting NS configuration settings
def retCode = 0;
def nodeSourceName = variables.get("NS_name")
def nodeToken = variables.get("token")
def hostName = variables.get("host_name")
// Enforcing ....
print "(2/4) Searching for nodes ..."
def nodeURLs = rmapi.getRMStateFull().getNodesEvents().findAll { nodeEvent ->
return (nodeSourceName == nodeEvent.getNodeSource() && hostName == nodeEvent.getHostName());
}.collect { nodeEvent ->
return (nodeEvent.getNodeUrl());
}
println " ... OK !"
println "Found node URLs : " + nodeURLs.toString()
print "(3/4) Acquiring nodes ..."
nodeURLs.each { nodeURL ->
rmapi.addNodeToken(nodeURL, nodeToken)
}
println " ... OK !"
print "(4/4) Logging out ..."
rmapi.disconnect();
println " ... OK !"
return retCode;
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment