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 9eec3019d9fcfcf8a783e5f6f2e72d135e1f1384..e5fa6791bf98df45eeb792ba67c3fccdd0b42917 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 @@ -829,9 +829,10 @@ public class PAGateway { public Boolean deleteByonNode(String byonId) { EntityManagerHelper.begin(); ByonNode byonNode = EntityManagerHelper.find(ByonNode.class, byonId); + if (byonNode == null) { LOGGER.error("The passed BYON ID is not Found in the database"); - return false; + throw new IllegalArgumentException("The passed BYON ID \"" + byonId + "\" is not Found in the database"); } LOGGER.info("Deleting the corresponding PACloud from the database ..."); @@ -848,56 +849,16 @@ public class PAGateway { LOGGER.warn("The PACloud related to the byonNode {} is not found.", byonNode.getName()); } - if(!undeployByonNs(byonNode, false, true)) { + if(!ByonUtils.undeployByonNs(byonNode, false, true)) { LOGGER.warn("The BYON node source undeploy finished with errors!"); } - - LOGGER.info("Deleting the BYON node " + byonNode.getId() +" from the database..."); - byonNode.setNodeCandidate(null); - EntityManagerHelper.remove(byonNode); - EntityManagerHelper.commit(); + ByonUtils.deleteByonNode(byonNode); return true; /*TODO: * change the hardcoding for preempt and remove variables * */ } - /** - * Undeploy or remove the node source of a BYON node - * @param byonNode an object of class ByonNode to be undeployed or removed. - * @param preempt If true undeploy or remove node source immediately without waiting for nodes to be freed - * @param remove If true completely remove the node source, if false only undeply the node source - * @return true if the resourceManagerGateway return no errors, false otherwise - */ - private Boolean undeployByonNs(ByonNode byonNode, Boolean preempt, Boolean remove) { - assert byonNode!= null : "A null value was passed for byonNode, A node source must have a BYON ID"; - String nodeSourceName = "BYON_NS_" + byonNode.getId(); - if (remove) { - try { - LOGGER.info("Removing BYON node source " + nodeSourceName + " from the ProActive server"); - resourceManagerGateway.removeNodeSource(nodeSourceName, preempt); - } catch (NotConnectedException | PermissionRestException e) { - LOGGER.error(Arrays.toString(e.getStackTrace())); - return false; - } - } - else { - try { - LOGGER.info("Undeploying BYON node source " + nodeSourceName + " from the ProActive server"); - resourceManagerGateway.undeployNodeSource(nodeSourceName, preempt); - } catch (NotConnectedException | PermissionRestException e) { - LOGGER.error(Arrays.toString(e.getStackTrace())); - return false; - } - } - LOGGER.info("BYON node source was removed with no errors"); - return true; - - /*TODO: - * Check if the nodes source is present before calling the resourceManagerGateway - */ - } - /** * Kill all active jobs in ProActive Scheduler */ 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 a48a835e71b8a29af1d7191651e1313828b7ef92..cc22fa9b99421affee083fc29afcb795ecc9a60d 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 @@ -13,6 +13,7 @@ import org.apache.http.conn.ConnectTimeoutException; import org.apache.http.conn.util.InetAddressUtils; import org.ow2.proactive.resourcemanager.common.NSState; import org.ow2.proactive.resourcemanager.common.event.RMNodeEvent; +import org.ow2.proactive.resourcemanager.common.event.RMNodeSourceEvent; import org.ow2.proactive.resourcemanager.common.event.dto.RMStateFull; import org.ow2.proactive.resourcemanager.exception.RMException; import org.ow2.proactive.resourcemanager.exception.RMNodeException; @@ -29,6 +30,7 @@ import javax.security.auth.login.LoginException; import java.security.KeyException; import java.util.*; import java.util.concurrent.*; +import java.util.stream.Collectors; @Slf4j public class PAResourceManagerGateway { @@ -166,6 +168,9 @@ public class PAResourceManagerGateway { if (option.equals("hostname")) { nodeInfo = rmNodeEvent.getHostName(); } + if (option.equals("state")) { + nodeInfo = rmNodeEvent.getNodeState().toString(); + } if (nodeInfo.equals("none")) { LOGGER.error("A wrong option was passed and the nodeInfo was now changed"); throw new IllegalArgumentException("The option passed \"" + option+ "\" is not found!"); @@ -462,4 +467,68 @@ public class PAResourceManagerGateway { }); EntityManagerHelper.commit(); } + /** + * Get a list of node source names in a given status from the ProActive Resource Manager + * @param status defines the status of node sources to be returned, can take ["deployed", "undeployed", "all"] + * @return listNodeSourceNames a string list of names of the deployed node sources + * @throws NotConnectedException In case the user is not connected + * @throws PermissionRestException In case the user does not have valid permissions + */ + public List getNodeSourceNames(String status) throws NotConnectedException, PermissionRestException { + LOGGER.info("Getting the node sources names from the resource manager"); + if (!Arrays.asList("deployed","undeployed","all").contains(status)){ + LOGGER.error("The passed status \"" + status + "\" is incorrect"); + throw new IllegalArgumentException("The passed status \"" + status + "\" is incorrect"); + } + return getFullMonitoring().getNodeSource().stream() + .filter(nodeSourceEvent -> nodeSourceEvent.getNodeSourceStatus().equals(status) || status.equals("all")) + .map(RMNodeSourceEvent::getNodeSourceName).collect(Collectors.toList()); + } + + + /** + * Get a list of deployed nodes hostnames from the ProActive Resource Manager + * @param nsName a String of the node source name + * @return nodeHostNames a string list of names of the deployed nodes hostnames + */ + public List getNodeHostNames(String nsName){ + List nodeHostNames = new LinkedList<>(); + try { + nodeHostNames = getAsyncDeployedNodesInformation(nsName, "hostname"); + } + catch(Exception e) { + LOGGER.error(" resourceManagerGateway threw an exception: " + e); + } + return nodeHostNames; + } + + /** + * Get a list of deployed nodes states from the ProActive Resource Manager + * @param nsName a String of the node source name + * @return nodeStates a string list of names of the deployed node states + */ + public List getNodeStates(String nsName){ + List nodeStates = new LinkedList<>(); + try { + nodeStates = getAsyncDeployedNodesInformation(nsName, "state"); + } + catch(Exception e) { + LOGGER.error(" resourceManagerGateway threw an exception: " + e); + } + return nodeStates; + } + + /** + * Get a list of deployed nodes sources from the ProActive Resource Manager + * @return nodeSourcesNames a string list of names of the deployed node sources + */ + public List getDeployedNodeSourcesNames() { + List nodeSourcesNames = new LinkedList<>(); + try { + nodeSourcesNames = getNodeSourceNames("deployed"); + } catch (NotConnectedException | PermissionRestException e) { + LOGGER.error(Arrays.toString(e.getStackTrace())); + } + return nodeSourcesNames; + } } 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 4ced1c52fd9fcad13e0ae86a14992463667c1350..fc79d30027d6b3be7bca24a050349a15c3ffffd6 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 @@ -4,7 +4,10 @@ import lombok.extern.slf4j.Slf4j; import org.activeeon.morphemic.infrastructure.deployment.PAResourceManagerGateway; import org.activeeon.morphemic.model.*; import org.apache.commons.lang3.RandomStringUtils; +import org.ow2.proactive.scheduler.common.exception.NotConnectedException; +import org.ow2.proactive_grid_cloud_portal.scheduler.exception.PermissionRestException; +import java.util.Arrays; import java.util.LinkedList; import java.util.List; import java.util.Optional; @@ -16,9 +19,9 @@ public class ByonUtils { private ByonUtils() {} - static final int MAX_CONNECTION_RETRIES = 5; + static final int MAX_CONNECTION_RETRIES = 10; - static final int INTERVAL = 5000; + static final int INTERVAL = 20000; public static void init(String paURL) { resourceManagerGateway = new PAResourceManagerGateway(paURL); @@ -106,47 +109,130 @@ public class ByonUtils { */ public static String getBYONHostname(String nsName) { LOGGER.info("Getting the byon node host name for: " + nsName); - List nodeHostnames = new LinkedList<>(); - int retries=0; - try { - nodeHostnames = resourceManagerGateway.getAsyncDeployedNodesInformation(nsName, "hostname"); - } - catch(Exception e) { - LOGGER.error(" resourceManagerGateway threw an exception: " + e); - } - if (nodeHostnames == null) { - LOGGER.error("The node Source "+ nsName + " Does not have any nodes"); - throw new IllegalStateException("Node source is empty no hostname can be retrieved"); - } - else { - if (nodeHostnames.size() != 1) { - if (nodeHostnames.size() == 0) { - LOGGER.error("The node Source " + nsName + " Does not have any nodes"); - throw new IllegalStateException("Node source is empty no hostname can be retrieved"); - } else { - LOGGER.error("The node Source " + nsName + " has more than one node"); - throw new IllegalStateException("Node source has multiple nodes"); + List nodeSourcesNames= new LinkedList<>(); + List nodeHostNames = new LinkedList<>(); + List nodeStates = new LinkedList<>(); + int retries =0; + while (retries host name is empty, retrying to get node information"); + } + else + { + return nodeHostNames.get(0); + } + } } } - } - while (nodeHostnames.get(0).equals("")) - { - LOGGER.warn("The node host name is empty, retrying to get node information"); try { Thread.sleep(INTERVAL); - nodeHostnames = resourceManagerGateway.getAsyncDeployedNodesInformation(nsName, "hostname"); - } - catch(Exception e) { - LOGGER.error(" resourceManagerGateway threw an exception: " + e); + } + catch (InterruptedException e){ + LOGGER.error("The sleep thread was interrupted"); + } + } + LOGGER.error("The node host name is not retrieved after " + retries+ " retries" ); + throw new IllegalStateException("Node hostname is empty"); + + /* TODO + * change the get getNodeStates and getNodeHostNames to getNodeEvents + * to limit the number of connections to the RM + * nodeStates.get(0) may lead to IndexOutOfRangeException => to be changed + */ + } + + /** + * Undeploy or remove the node source of a BYON node + * @param byonNode an object of class ByonNode to be undeployed or removed. + * @param preempt If true undeploy or remove node source immediately without waiting for nodes to be freed + * @param remove If true completely remove the node source, if false only undeply the node source + * @return true if the resourceManagerGateway return no errors, false otherwise + */ + public static Boolean undeployByonNs(ByonNode byonNode, Boolean preempt, Boolean remove) { + assert byonNode!= null : "A null value was passed for byonNode, A node source must have a BYON ID"; + String nodeSourceName = "BYON_NS_" + byonNode.getId(); + if (remove) { + try { + LOGGER.info("Removing BYON node source " + nodeSourceName + " from the ProActive server"); + if(resourceManagerGateway.getNodeSourceNames("all").contains(nodeSourceName)) { + resourceManagerGateway.removeNodeSource(nodeSourceName, preempt); + } + else{ + LOGGER.warn("The node source \""+ nodeSourceName+"\" does not exist in the RM"); + } + } catch (NotConnectedException | PermissionRestException e) { + LOGGER.error(Arrays.toString(e.getStackTrace())); + return false; } - if (retries > MAX_CONNECTION_RETRIES) { - LOGGER.error("The node host name is empty after " + retries+ " retries" ); - throw new IllegalStateException("Node hostname is empty"); + } + else { + try { + LOGGER.info("Undeploying BYON node source " + nodeSourceName + " from the ProActive server"); + if(resourceManagerGateway.getNodeSourceNames("deployed").contains(nodeSourceName)) { + resourceManagerGateway.undeployNodeSource(nodeSourceName, preempt); + } + else{ + LOGGER.warn("The node source \""+ nodeSourceName+"\" is not deployed in the RM"); + } + } catch (NotConnectedException | PermissionRestException e) { + LOGGER.error(Arrays.toString(e.getStackTrace())); + return false; } - retries++; } + LOGGER.info("BYON node source was removed with no errors"); + return true; + } + + /** + * Deleting the BYON node and its Node candidate from the data base + * @param byonNode an object of class ByonNode to be removed. + */ + public static void deleteByonNode(ByonNode byonNode) { + EntityManagerHelper.begin(); + LOGGER.info("Removing the BYON node " + byonNode.getId() +" from the database..."); + + Location byonLocation = byonNode.getNodeCandidate().getLocation(); + Hardware byonHardware = byonNode.getNodeCandidate().getHardware(); + Image byonImage = byonNode.getNodeCandidate().getImage(); - LOGGER.info("The hostname is retrieved successfully: " + nodeHostnames.get(0)); - return nodeHostnames.get(0); + LOGGER.info("Removing the BYON Location " + byonLocation.getId() +" from the database..."); + EntityManagerHelper.remove(byonLocation); + LOGGER.info("Removing the BYON Hardware " + byonHardware.getId() +" from the database..."); + EntityManagerHelper.remove(byonHardware); + LOGGER.info("Removing the BYON Image " + byonImage.getId() +" from the database..."); + EntityManagerHelper.remove(byonImage); + + byonNode.setNodeCandidate(null); + EntityManagerHelper.remove(byonNode); + EntityManagerHelper.commit(); } } 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 bd0753f757f55f34b27bd5701f49cb5d85fd86f7..f8a3805ceb6dd426651c3e6542ca9e99b3d760bd 100644 --- a/scheduling-abstraction-layer/src/main/resources/Define_NS_BYON.xml +++ b/scheduling-abstraction-layer/src/main/resources/Define_NS_BYON.xml @@ -66,7 +66,7 @@ println " OK!" //Getting NS configuration settings def infrastructureType = "org.ow2.proactive.resourcemanager.nodesource.infrastructure.SSHInfrastructureV2" -def infrastructureParameters = ["60000", //Node Time out +def infrastructureParameters = ["300000", //Node Time out "5", //Max deployment failure "5000", //wait between Deployment sshPort,//port, //SSH port