zuul update
Change-Id: I12e48440e6eb4dd37000e10e6ccd36fbe189e5df
This commit is contained in:
parent
d930c2af71
commit
73a63a390d
10
.gitignore
vendored
10
.gitignore
vendored
@ -1,2 +1,12 @@
|
||||
__pycache__/
|
||||
.nox/
|
||||
utility-evaluator/src/test/.DS_Store
|
||||
utility-evaluator/src/test/java/.DS_Store
|
||||
utility-evaluator/src/main/java/eu/nebulous/.DS_Store
|
||||
utility-evaluator/src/.DS_Store
|
||||
utility-evaluator/src/main/.DS_Store
|
||||
utility-evaluator/src/main/java/.DS_Store
|
||||
utility-evaluator/src/main/java/eu/.DS_Store
|
||||
utility-evaluator/.DS_Store
|
||||
.vscode/settings.json
|
||||
.DS_Store
|
||||
|
@ -1,15 +0,0 @@
|
||||
#
|
||||
# Build stage
|
||||
#
|
||||
FROM docker.io/library/maven:3.9.2-eclipse-temurin-17 AS build
|
||||
COPY src /home/app/src
|
||||
COPY pom.xml /home/app
|
||||
RUN mvn -f /home/app/pom.xml clean package
|
||||
|
||||
#
|
||||
# Package stage
|
||||
#
|
||||
FROM docker.io/library/eclipse-temurin:17-jre
|
||||
COPY --from=build /home/app/target/demo-0.0.1-SNAPSHOT.jar /usr/local/lib/demo.jar
|
||||
EXPOSE 8080
|
||||
ENTRYPOINT ["java","-jar","/usr/local/lib/demo.jar"]
|
@ -1,42 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
<groupId>com.example</groupId>
|
||||
<artifactId>demo</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>demo</name>
|
||||
<description>Demo project for Spring Boot</description>
|
||||
<properties>
|
||||
<java.version>17</java.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
@ -1,13 +0,0 @@
|
||||
package com.example.demo;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class DemoApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(DemoApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
package com.example.demo;
|
||||
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
public class DemoController {
|
||||
|
||||
@RequestMapping("/")
|
||||
public Object root() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
package com.example.demo;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
@SpringBootTest
|
||||
class DemoApplicationTests {
|
||||
|
||||
@Test
|
||||
void contextLoads() {
|
||||
//test
|
||||
}
|
||||
|
||||
}
|
12
utility-evaluator/.mvn/local-settings.xml
Normal file
12
utility-evaluator/.mvn/local-settings.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<settings xmlns="http://maven.apache.org/SETTINGS/1.2.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.2.0 http://maven.apache.org/xsd/settings-1.2.0.xsd">
|
||||
<mirrors>
|
||||
<mirror>
|
||||
<id>my-repository-http-unblocker</id>
|
||||
<mirrorOf>activeeon</mirrorOf>
|
||||
<name></name>
|
||||
<url>http://repository.activeeon.com/content/groups/proactive/</url>
|
||||
</mirror>
|
||||
</mirrors>
|
||||
</settings>
|
16
utility-evaluator/Dockerfile
Normal file
16
utility-evaluator/Dockerfile
Normal file
@ -0,0 +1,16 @@
|
||||
#
|
||||
# Build stage
|
||||
#
|
||||
FROM docker.io/library/maven:3.9.2-eclipse-temurin-17 AS build
|
||||
COPY src /home/app/src
|
||||
COPY local-settings.xml /home/local-settings.xml
|
||||
COPY pom.xml /home/app
|
||||
RUN mvn -f /home/app/pom.xml -s /home/local-settings.xml clean package
|
||||
|
||||
#
|
||||
# Package stage
|
||||
#
|
||||
FROM docker.io/library/eclipse-temurin:17-jre
|
||||
COPY --from=build /home/app/target/utilityevaluator-0.0.1-SNAPSHOT.jar /usr/local/lib/utilityevaluator.jar
|
||||
EXPOSE 8080
|
||||
ENTRYPOINT ["java","-jar","/usr/local/lib/utilityevaluator.jar"]
|
12
utility-evaluator/local-settings.xml
Normal file
12
utility-evaluator/local-settings.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<settings xmlns="http://maven.apache.org/SETTINGS/1.2.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.2.0 http://maven.apache.org/xsd/settings-1.2.0.xsd">
|
||||
<mirrors>
|
||||
<mirror>
|
||||
<id>my-repository-http-unblocker</id>
|
||||
<mirrorOf>activeeon</mirrorOf>
|
||||
<name></name>
|
||||
<url>http://repository.activeeon.com/content/groups/proactive/</url>
|
||||
</mirror>
|
||||
</mirrors>
|
||||
</settings>
|
137
utility-evaluator/pom.xml
Normal file
137
utility-evaluator/pom.xml
Normal file
@ -0,0 +1,137 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
<groupId>eu.nebulous</groupId>
|
||||
<artifactId>utilityevaluator</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>utilityevaluator</name>
|
||||
<description>First release of Utility Evaluator component</description>
|
||||
<properties>
|
||||
<java.version>17</java.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-activemq</artifactId>
|
||||
<version>3.1.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>3.12.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.ow2.proactive</groupId>
|
||||
<artifactId>sal-common</artifactId>
|
||||
<version>13.1.0-SNAPSHOT</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-annotations</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-core</artifactId>
|
||||
<version>2.16.1</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>2.16.1</version>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-annotations</artifactId>
|
||||
<version>2.16.0</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.30</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.projectreactor.netty</groupId>
|
||||
<artifactId>reactor-netty</artifactId>
|
||||
<version>1.1.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.json</groupId>
|
||||
<artifactId>json</artifactId>
|
||||
<version>20231013</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/jakarta.jms/jakarta.jms-api -->
|
||||
<!--<dependency>
|
||||
<groupId>jakarta.jms</groupId>
|
||||
<artifactId>jakarta.jms-api</artifactId>
|
||||
<version>3.1.0</version>
|
||||
</dependency> -->
|
||||
<dependency>
|
||||
<groupId>eu.nebulouscloud</groupId>
|
||||
<artifactId>exn-connector-java</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>maven-central</id>
|
||||
<url>https://repo1.maven.org/maven2/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>activeeon</id>
|
||||
<name>repository.activeeon</name>
|
||||
<url>http://repository.activeeon.com/content/groups/proactive/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>ossrh</id>
|
||||
<url>https://s01.oss.sonatype.org/content/repositories/snapshots/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
@ -0,0 +1,17 @@
|
||||
package eu.nebulous.utilityevaluator;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
|
||||
|
||||
|
||||
@SpringBootApplication
|
||||
public class UtilityEvaluatorApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(UtilityEvaluatorApplication.class, args);
|
||||
// The application is listening to messages and sav
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package eu.nebulous.utilityevaluator;
|
||||
|
||||
import org.ow2.proactive.sal.model.NodeCandidate;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import eu.nebulous.utilityevaluator.communication.activemq.message.FetchNodeCandidatesMessage;
|
||||
import eu.nebulous.utilityevaluator.communication.sal.NodeCandidatesFetchingService;
|
||||
import eu.nebulous.utilityevaluator.nodecandidates.NodeCandidateConverter;
|
||||
import eu.nebulous.utilityevaluator.nodecandidates.NodeCandidateDTO;
|
||||
import jline.internal.Log;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class UtilityEvaluatorController {
|
||||
|
||||
private final NodeCandidatesFetchingService nodeCandidatesService;
|
||||
|
||||
|
||||
//this is the main method of Utiliy Evaluator. It creates a .csv file with available Node Candidates
|
||||
public Optional<String> createNodeCandidatesTensor(FetchNodeCandidatesMessage message){
|
||||
|
||||
Log.info("Creating Node Candidates tensor...");
|
||||
List<NodeCandidate> nodeCandidates = nodeCandidatesService.getNodeCandidates(message.getCloudProviders());
|
||||
|
||||
//convert Node Candidates, possibly also filter (in the future)
|
||||
List<NodeCandidateDTO> convertedNodeCandidates = NodeCandidateConverter.convertToDtoList(nodeCandidates);
|
||||
String csv = NodeCandidateConverter.convertToCsv(convertedNodeCandidates);
|
||||
|
||||
return Optional.of(csv);
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,41 @@
|
||||
package eu.nebulous.utilityevaluator;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.json.JSONObject;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import eu.nebulous.utilityevaluator.communication.activemq.message.FetchNodeCandidatesMessage;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class UtilityEvaluatorListener {
|
||||
// This is an old component that is going to be removed after tests
|
||||
|
||||
private final UtilityEvaluatorController controller;
|
||||
|
||||
//@JmsListener(destination = "eu.nebulouscloud.dsl.general")
|
||||
//@JmsListener(destination = "TestTopic")
|
||||
public void handleGeneralApplicationMessage(JSONObject message) {
|
||||
// Process the received message
|
||||
log.info("Received message: {}", message.toString());
|
||||
|
||||
FetchNodeCandidatesMessage clearedMessage = new FetchNodeCandidatesMessage(message);
|
||||
log.info("Cleared message: {}", clearedMessage.toString());
|
||||
Optional<String> nodeCandidatesTensor = controller.createNodeCandidatesTensor(clearedMessage);
|
||||
if (nodeCandidatesTensor.isPresent()){
|
||||
log.info("Tensor successfully created");
|
||||
// If needed, you can also send a response back to another queue or topic
|
||||
//jmsTemplate.convertAndSend("eu.nebulouslcloud.optimizer.solver.tensor", new NodeCandidatesTensorMessage(clearedMessage.getApplicationID(), nodeCandidatesTensor.get()));
|
||||
log.info("Tensor was passed via ActiveMQ");
|
||||
}
|
||||
else {
|
||||
log.error("There was an error during creating the tensor");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
package eu.nebulous.utilityevaluator.communication.activemq;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.jms.core.JmsTemplate;
|
||||
import org.springframework.jms.support.converter.MappingJackson2MessageConverter;
|
||||
import org.springframework.jms.support.converter.MessageConverter;
|
||||
import org.springframework.jms.support.converter.MessageType;
|
||||
import org.springframework.jms.support.destination.DynamicDestinationResolver;
|
||||
|
||||
import jakarta.jms.Destination;
|
||||
import jakarta.jms.JMSException;
|
||||
import jakarta.jms.Session;
|
||||
|
||||
|
||||
public class Config {
|
||||
|
||||
@Value("${spring.activemq.broker-url}")
|
||||
String BROKER_URL;
|
||||
@Value("${spring.activemq.user}")
|
||||
String BROKER_USERNAME;
|
||||
@Value("${spring.activemq.password}")
|
||||
String BROKER_PASSWORD;
|
||||
|
||||
@Bean
|
||||
public ActiveMQConnectionFactory connectionFactory(){
|
||||
System.out.println("Connection factory being createdb for url, username and password:" + BROKER_URL + " " + BROKER_USERNAME + ", " + BROKER_PASSWORD);
|
||||
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory();
|
||||
connectionFactory.setTrustAllPackages(true);
|
||||
connectionFactory.setBrokerURL(BROKER_URL);
|
||||
connectionFactory.setPassword(BROKER_USERNAME);
|
||||
connectionFactory.setUserName(BROKER_PASSWORD);
|
||||
connectionFactory.setClientID("optimizer-utilityevaluator");
|
||||
return connectionFactory;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MessageConverter messageConverter() {
|
||||
MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
|
||||
converter.setTargetType(MessageType.TEXT);
|
||||
converter.setObjectMapper(objectMapper());
|
||||
return converter;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ObjectMapper objectMapper() {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
mapper.registerModule(new JavaTimeModule());
|
||||
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
|
||||
return mapper;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public JmsTemplate jmsTemplate(){
|
||||
JmsTemplate template = new JmsTemplate();
|
||||
template.setConnectionFactory(connectionFactory());
|
||||
template.setMessageConverter(messageConverter());
|
||||
template.setPubSubDomain(true);
|
||||
template.setDestinationResolver(destinationResolver());
|
||||
template.setDeliveryPersistent(true);
|
||||
return template;
|
||||
}
|
||||
|
||||
@Bean
|
||||
DynamicDestinationResolver destinationResolver() {
|
||||
return new DynamicDestinationResolver() {
|
||||
@Override
|
||||
public Destination resolveDestinationName(Session session, String destinationName, boolean pubSubDomain) throws JMSException {
|
||||
if(destinationName.endsWith("Topic")) {
|
||||
pubSubDomain = true;
|
||||
}
|
||||
else {
|
||||
pubSubDomain = false;
|
||||
}
|
||||
return super.resolveDestinationName(session,destinationName,pubSubDomain);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
package eu.nebulous.utilityevaluator.communication.activemq.message;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
import org.json.JSONPointer;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public class FetchNodeCandidatesMessage implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final JSONPointer APPLICATION_ID_POINTER = new JSONPointer("/application/name");
|
||||
private static final JSONPointer CLOUD_PROVIDERS_POINTER = new JSONPointer("/cloud_providers");
|
||||
|
||||
@NonNull
|
||||
private String applicationID;
|
||||
@NonNull
|
||||
private Map<String,String> cloudProviders;
|
||||
|
||||
|
||||
|
||||
public FetchNodeCandidatesMessage(JSONObject generalApplicationMessage){
|
||||
|
||||
this.applicationID = (@NonNull String) generalApplicationMessage.query(APPLICATION_ID_POINTER);
|
||||
JSONArray providersJSON = (JSONArray) generalApplicationMessage.query(CLOUD_PROVIDERS_POINTER);
|
||||
Map<String,String> cloudProviders = new HashMap<String,String>();
|
||||
|
||||
for (final Object p : providersJSON) {
|
||||
JSONObject provider = (JSONObject) p;
|
||||
cloudProviders.put(provider.optString("type"), provider.optString("sal_key"));
|
||||
}
|
||||
this.cloudProviders = cloudProviders;
|
||||
}
|
||||
|
||||
public FetchNodeCandidatesMessage(String appId, Map body, Map<String, Object> map){
|
||||
this.applicationID = appId;
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package eu.nebulous.utilityevaluator.communication.activemq.message;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.NonNull;
|
||||
|
||||
@AllArgsConstructor
|
||||
public class NodeCandidatesTensorMessage implements Serializable{
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@NonNull
|
||||
private String applicationID;
|
||||
@NonNull
|
||||
private String nodeCandidatesTensorCSV;
|
||||
|
||||
}
|
@ -0,0 +1,94 @@
|
||||
package eu.nebulous.utilityevaluator.communication.exnconnector;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import eu.nebulouscloud.exn.Connector;
|
||||
import eu.nebulouscloud.exn.core.Consumer;
|
||||
import eu.nebulouscloud.exn.handlers.ConnectorHandler;
|
||||
import eu.nebulouscloud.exn.settings.StaticExnConfig;
|
||||
|
||||
import eu.nebulouscloud.exn.core.Context;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
@Component
|
||||
public class ExnConnector {
|
||||
|
||||
@Value("${spring.activemq.broker-url}")
|
||||
String BROKER_URL;
|
||||
@Value("${spring.activemq.broker-port}")
|
||||
Integer BROKER_PORT;
|
||||
@Value("${spring.activemq.user}")
|
||||
String BROKER_USERNAME;
|
||||
@Value("${spring.activemq.password}")
|
||||
String BROKER_PASSWORD;
|
||||
|
||||
|
||||
public static final String GENERAL_APP_CREATION_MESSAGE_TOPIC = "eu.nebulouscloud.ui.dsl.generic.>";
|
||||
public final GeneralMessageHandler generalHandler;
|
||||
|
||||
public ExnConnector(GeneralMessageHandler handler) {
|
||||
super();
|
||||
this.generalHandler = handler;
|
||||
init();
|
||||
|
||||
|
||||
}
|
||||
private void init() {
|
||||
try {
|
||||
Connector c = new Connector(
|
||||
"utilityevaluator",
|
||||
new MyConnectorHandler(),
|
||||
List.of(),
|
||||
List.of(new Consumer("ui_all", GENERAL_APP_CREATION_MESSAGE_TOPIC, generalHandler ,true,true)),
|
||||
false,
|
||||
false,
|
||||
new StaticExnConfig(
|
||||
"localhost",
|
||||
5672,
|
||||
BROKER_USERNAME,
|
||||
BROKER_PASSWORD
|
||||
)
|
||||
);
|
||||
c.start();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class MyConnectorHandler extends ConnectorHandler {
|
||||
|
||||
Logger logger = LoggerFactory.getLogger(MyConnectorHandler.class);
|
||||
|
||||
@Override
|
||||
public void onReady(Context context) {
|
||||
logger.info ("Ready start working");
|
||||
//context.registerConsumer(new Consumer("ue_health","health", generalHandler, true));
|
||||
|
||||
|
||||
/**
|
||||
* We can then de-register the consumer
|
||||
*/
|
||||
new Thread(){
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
try {
|
||||
logger.debug("Waiting for 50 s to unregister consumer");
|
||||
Thread.sleep(30000);
|
||||
context.unregisterConsumer("ue_health");
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
package eu.nebulous.utilityevaluator.communication.exnconnector;
|
||||
|
||||
import eu.nebulouscloud.exn.Connector;
|
||||
import eu.nebulouscloud.exn.core.Consumer;
|
||||
import eu.nebulouscloud.exn.core.Context;
|
||||
import eu.nebulouscloud.exn.core.Handler;
|
||||
import eu.nebulouscloud.exn.handlers.ConnectorHandler;
|
||||
import eu.nebulouscloud.exn.settings.StaticExnConfig;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.apache.qpid.protonj2.client.Message;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Component
|
||||
public class ExnListener extends Handler {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(ExnListener.class);
|
||||
private String topicName;
|
||||
private String address;
|
||||
private Connector connector;
|
||||
|
||||
public ExnListener(String topicName, String address, String brokerHost, int brokerPort, String username, String password) {
|
||||
this.topicName = topicName;
|
||||
this.address = address;
|
||||
|
||||
ConnectorHandler connectorHandler = new ConnectorHandler() {
|
||||
@Override
|
||||
public void onReady(Context context) {
|
||||
log.info("Connector ready. Registering consumer for topic: {}", topicName);
|
||||
// Register this handler as a consumer for the specified topic and address
|
||||
context.registerConsumer(new Consumer(topicName, address, ExnListener.this, true));
|
||||
}
|
||||
};
|
||||
|
||||
// Initialize the connector with the connector handler and configuration
|
||||
this.connector = new Connector("ui", connectorHandler, List.of(), List.of(), false, false,
|
||||
new StaticExnConfig(brokerHost, brokerPort, username, password));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessage(String key, String address, Map body, Message message, Context context) {
|
||||
log.info("Received message on topic {}: key={}, address={}, body={}", topicName, key, address, body);
|
||||
// Implement custom message processing logic here
|
||||
processMessage(key, address, body, message, context);
|
||||
}
|
||||
|
||||
public void start() {
|
||||
try {
|
||||
connector.start();
|
||||
log.info("ExnListener started for topic: {}", topicName);
|
||||
} catch (Exception e) {
|
||||
log.error("Error starting ExnListener: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
try {
|
||||
connector.stop();
|
||||
log.info("ExnListener stopped for topic: {}", topicName);
|
||||
} catch (Exception e) {
|
||||
log.error("Error stopping ExnListener: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
protected void processMessage(String key, String address, Map body, Message message, Context context) {
|
||||
// This method can be overridden in subclasses for custom message processing
|
||||
}
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
package eu.nebulous.utilityevaluator.communication.exnconnector;
|
||||
|
||||
import eu.nebulous.utilityevaluator.UtilityEvaluatorController;
|
||||
import eu.nebulouscloud.exn.core.Context;
|
||||
import eu.nebulouscloud.exn.core.Handler;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.qpid.protonj2.client.Message;
|
||||
import org.apache.qpid.protonj2.client.exceptions.ClientException;
|
||||
import org.json.JSONObject;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class GeneralMessageHandler extends Handler {
|
||||
|
||||
public final UtilityEvaluatorController controller;
|
||||
|
||||
public GeneralMessageHandler(UtilityEvaluatorController controller){
|
||||
super();
|
||||
this.controller = controller;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessage(String key, String address, Map body, Message message, Context context) {
|
||||
log.info("Received by custom handler {} => {} = {}", key,address,String.valueOf(body));
|
||||
log.info("Received message: {}", message.toString());
|
||||
log.info("Body={}", body.toString());
|
||||
JSONObject jsonObject = new JSONObject(body);
|
||||
Map<String, Object> map = jsonObject.toMap();
|
||||
try {
|
||||
String applicationId = message.subject();
|
||||
//todo: transform the old code to get it in the right format
|
||||
} catch (ClientException e) {
|
||||
|
||||
e.printStackTrace();
|
||||
log.error(e.getMessage());
|
||||
}
|
||||
|
||||
|
||||
/*FetchNodeCandidatesMessage clearedMessage = new FetchNodeCandidatesMessage(message);
|
||||
log.info("Cleared message: {}", clearedMessage.toString());
|
||||
Optional<String> nodeCandidatesTensor = controller.createNodeCandidatesTensor(clearedMessage);
|
||||
if (nodeCandidatesTensor.isPresent()){
|
||||
log.info("Tensor successfully created");
|
||||
// If needed, you can also send a response back to another queue or topic
|
||||
//jmsTemplate.convertAndSend("eu.nebulouslcloud.optimizer.solver.tensor", new NodeCandidatesTensorMessage(clearedMessage.getApplicationID(), nodeCandidatesTensor.get()));
|
||||
log.info("Tensor was passed via ActiveMQ");
|
||||
}
|
||||
else {
|
||||
log.error("There was an error during creating the tensor");
|
||||
|
||||
}*/
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
package eu.nebulous.utilityevaluator.communication.sal;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.ow2.proactive.sal.model.NodeCandidate;
|
||||
import org.ow2.proactive.sal.model.Requirement;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import eu.nebulous.utilityevaluator.communication.sal.error.ProactiveClientException;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Component
|
||||
public class NodeCandidatesFetchingService {
|
||||
|
||||
private static final int NUMBER_OF_REPEATS_FOR_NODE_CANDIDATES = 120;
|
||||
private static final int DELAY_BETWEEN_REQUESTS = 5000;
|
||||
|
||||
private final ProactiveConnector proactiveClientConnectorService;
|
||||
|
||||
|
||||
/*public NodeCandidatesFetchingService(ProactiveClientProperties properties){
|
||||
ProactiveConnector connector = new ProactiveConnector(properties);
|
||||
this.proactiveClientConnectorService = connector;
|
||||
}*/
|
||||
|
||||
//https://gitlab.ow2.org/melodic/melodic-upperware/-/tree/morphemic-rc4.0/cp_generator/src/main/java/eu/paasage/upperware/profiler/generator/communication/impl
|
||||
|
||||
public List<NodeCandidate> getNodeCandidates(Map<String,String> cloudProviders){
|
||||
List<Requirement> providerRequirements = convertProviderRequirements(cloudProviders);
|
||||
return findNodeCandidates(providerRequirements);
|
||||
}
|
||||
|
||||
private List<Requirement> convertProviderRequirements(Map<String,String> cloudProviders){
|
||||
//todo: filter based on the chosen cloud providers
|
||||
return List.of();
|
||||
}
|
||||
|
||||
private List<NodeCandidate> findNodeCandidates(List<Requirement> requirements) {
|
||||
List<NodeCandidate> nodeCandidates = new LinkedList<>();
|
||||
boolean isAnyAsyncNodeCandidatesProcessesInProgress = true;
|
||||
int requestNo = 0;
|
||||
try {
|
||||
while (isAnyAsyncNodeCandidatesProcessesInProgress && (requestNo < NUMBER_OF_REPEATS_FOR_NODE_CANDIDATES)) {
|
||||
log.info("Checking if nodeCandidates downlaod process is finished. Trye: {}", requestNo);
|
||||
isAnyAsyncNodeCandidatesProcessesInProgress = proactiveClientConnectorService.isAnyAsyncNodeCandidatesProcessesInProgress();
|
||||
Thread.sleep(DELAY_BETWEEN_REQUESTS);
|
||||
requestNo++;
|
||||
}
|
||||
if (isAnyAsyncNodeCandidatesProcessesInProgress) {
|
||||
throw new RuntimeException("NodeCandidates are not yet present inside proactive scheduler");
|
||||
}
|
||||
nodeCandidates = proactiveClientConnectorService.fetchNodeCandidates(requirements);
|
||||
} catch (InterruptedException e1) {
|
||||
e1.printStackTrace();
|
||||
} catch (ProactiveClientException e2) {
|
||||
log.error("Error message body: {}", e2.getMessage());
|
||||
}
|
||||
return nodeCandidates;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package eu.nebulous.utilityevaluator.communication.sal;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@Getter
|
||||
public class ProactiveClientProperties {
|
||||
|
||||
@Value("${spring.pa-config.rest-url}")
|
||||
public String url;
|
||||
@Value("${spring.pa-config.login}")
|
||||
public String login;
|
||||
@Value("${spring.pa-config.password}")
|
||||
public String password;
|
||||
|
||||
|
||||
public ProactiveClientProperties(@Value("${spring.pa-config.rest-url}") String url,
|
||||
@Value("${spring.pa-config.login}") String login,
|
||||
@Value("${spring.pa-config.password}") String password) {
|
||||
this.url = url;
|
||||
this.login = login;
|
||||
this.password = password;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,142 @@
|
||||
package eu.nebulous.utilityevaluator.communication.sal;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonSetter;
|
||||
import com.fasterxml.jackson.annotation.Nulls;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import eu.nebulous.utilityevaluator.communication.sal.error.ProactiveClientException;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.handler.codec.http.HttpResponseStatus;
|
||||
import io.netty.handler.logging.LogLevel;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
import org.ow2.proactive.sal.model.*;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.netty.ByteBufMono;
|
||||
import reactor.netty.http.client.HttpClient;
|
||||
import reactor.netty.transport.logging.AdvancedByteBufFormat;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Duration;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class ProactiveConnector {
|
||||
|
||||
private static final String SESSION_HEADER = "sessionid";
|
||||
private static final int RETRIES_NUMBER = 20;
|
||||
private static final String PA_GATEWAY = "/pagateway";
|
||||
private static final String PA_GATEWAY_CONNECT = PA_GATEWAY + "/connect";
|
||||
private static final String NODECANDIDATES = "/nodecandidates";
|
||||
public static final String CLOUD = "/cloud";
|
||||
public static final String CLOUD_NODE_CANDIDATES_FETCH_CHECK = CLOUD + "/async";
|
||||
|
||||
private final HttpClient httpClient;
|
||||
private String sessionId;
|
||||
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
public ProactiveConnector(ProactiveClientProperties properties) {
|
||||
log.info("Properties: login: {}, pass: {}, url: {}", properties.getLogin(), properties.getPassword(), properties.getUrl());
|
||||
this.connect(properties.getLogin(), properties.getPassword(), properties.getUrl());
|
||||
//sessionId = "blablabla";
|
||||
this.httpClient = HttpClient.create()
|
||||
.baseUrl(properties.getUrl())
|
||||
.headers(headers -> headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE))
|
||||
.headers(headers -> headers.add(SESSION_HEADER, sessionId))
|
||||
.responseTimeout(Duration.of(80, ChronoUnit.SECONDS))
|
||||
.wiretap("reactor.netty.http.client.HttpClient", LogLevel.DEBUG, AdvancedByteBufFormat.TEXTUAL, StandardCharsets.UTF_8);
|
||||
this.httpClient.warmup().block();
|
||||
this.objectMapper = new ObjectMapper();
|
||||
this.objectMapper
|
||||
.configOverride(List.class)
|
||||
.setSetterInfo(JsonSetter.Value.forValueNulls(Nulls.AS_EMPTY))
|
||||
.setSetterInfo(JsonSetter.Value.forContentNulls(Nulls.AS_EMPTY));
|
||||
}
|
||||
|
||||
public void connect(String login, String password, String schedulerUrl) {
|
||||
log.info("Connecting to SAL as a service");
|
||||
|
||||
this.sessionId = HttpClient.create()
|
||||
.headers(headers -> headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED))
|
||||
.post()
|
||||
.uri(schedulerUrl + PA_GATEWAY_CONNECT)
|
||||
.sendForm((req, form) -> form
|
||||
//.attr("username", login)
|
||||
.attr("name", login)
|
||||
.attr("password", password))
|
||||
.responseContent()
|
||||
.aggregate()
|
||||
.asString()
|
||||
.retry(RETRIES_NUMBER)
|
||||
.block();
|
||||
log.info("Connected with sessionId: {}...", sessionId.substring(0,10));
|
||||
}
|
||||
|
||||
|
||||
//nodeCandidates
|
||||
public List<NodeCandidate> fetchNodeCandidates(List<Requirement> requirements) {
|
||||
return httpClient.post()
|
||||
.uri(NODECANDIDATES)
|
||||
.send(bodyMonoPublisher(requirements))
|
||||
.responseSingle((resp, bytes) -> {
|
||||
if (!resp.status().equals(HttpResponseStatus.OK)) {
|
||||
return bytes.asString().flatMap(body -> Mono.error(new ProactiveClientException(body)));
|
||||
} else {
|
||||
return bytes.asString().mapNotNull(s -> {
|
||||
try {
|
||||
log.info("Received message: {}", s);
|
||||
return objectMapper.readValue(s, NodeCandidate[].class);
|
||||
} catch (IOException e) {
|
||||
log.error(e.getMessage(), e);;
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
.doOnError(Throwable::printStackTrace)
|
||||
.blockOptional()
|
||||
.map(Arrays::asList)
|
||||
.orElseGet(Collections::emptyList);
|
||||
}
|
||||
|
||||
private Mono<ByteBuf> bodyMonoPublisher(Object body) {
|
||||
if ((body instanceof JSONArray) || (body instanceof JSONObject)) {
|
||||
return ByteBufMono.fromString(Mono.just(body.toString()));
|
||||
}
|
||||
String json = null;
|
||||
try {
|
||||
json = objectMapper.writeValueAsString(body);
|
||||
} catch (JsonProcessingException e) {
|
||||
log.error(e.getMessage(), e);;
|
||||
}
|
||||
log.info("Sending body json: {}", json);
|
||||
return ByteBufMono.fromString(Mono.just(json));
|
||||
}
|
||||
|
||||
|
||||
public Boolean isAnyAsyncNodeCandidatesProcessesInProgress() {
|
||||
return httpClient.get()
|
||||
.uri(CLOUD_NODE_CANDIDATES_FETCH_CHECK)
|
||||
.responseSingle((resp, bytes) -> {
|
||||
if (!resp.status().equals(HttpResponseStatus.OK)) {
|
||||
return bytes.asString().flatMap(body -> Mono.error(new ProactiveClientException(body)));
|
||||
} else {
|
||||
return bytes.asString().map(Boolean::new);
|
||||
}
|
||||
})
|
||||
.doOnError(Throwable::printStackTrace)
|
||||
.block();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package eu.nebulous.utilityevaluator.communication.sal.error;
|
||||
|
||||
import reactor.netty.http.client.HttpClientResponse;
|
||||
|
||||
public class ProactiveClientException extends RuntimeException {
|
||||
public ProactiveClientException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public ProactiveClientException(HttpClientResponse clientResponse) {
|
||||
super(clientResponse.status().toString());
|
||||
}
|
||||
|
||||
public ProactiveClientException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,64 @@
|
||||
package eu.nebulous.utilityevaluator.nodecandidates;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import org.ow2.proactive.sal.model.NodeCandidate;
|
||||
|
||||
|
||||
//static class that converts Node Candidates from SAL to NodeCandidatesDTO, which are then directly saved in node Candidates tensor
|
||||
public class NodeCandidateConverter {
|
||||
|
||||
public static final String CSV_HEADER = "id;gpu;cpu;ram;location;latitude;longitude;provider;type;price\n";
|
||||
|
||||
public static List<NodeCandidateDTO> convertToDtoList(List<NodeCandidate> nodeCandidates) {
|
||||
return nodeCandidates.stream()
|
||||
.map(NodeCandidateConverter::convertToDto)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private static NodeCandidateDTO convertToDto(NodeCandidate nodeCandidate) {
|
||||
NodeCandidateDTO dto = new NodeCandidateDTO(
|
||||
nodeCandidate.getNodeCandidateType(),
|
||||
nodeCandidate.getPrice(),
|
||||
nodeCandidate.getCloud().getId(),
|
||||
nodeCandidate.getHardware().getCores(),
|
||||
nodeCandidate.getHardware().getFpga(),
|
||||
nodeCandidate.getHardware().getRam(),
|
||||
nodeCandidate.getLocation().getGeoLocation().getCountry(),
|
||||
nodeCandidate.getLocation().getGeoLocation().getLatitude(),
|
||||
nodeCandidate.getLocation().getGeoLocation().getLongitude(),
|
||||
nodeCandidate.getId()
|
||||
);
|
||||
return dto;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static String convertToCsv(List<NodeCandidateDTO> nodeCandidates) {
|
||||
// Create CSV header
|
||||
String csv = CSV_HEADER;
|
||||
|
||||
// Append node candidates to CSV
|
||||
csv += nodeCandidates.stream()
|
||||
.map(nc->NodeCandidateConverter.convertNodeCandidateToCsv(nc))
|
||||
.collect(Collectors.joining("\n"));
|
||||
|
||||
return csv;
|
||||
}
|
||||
|
||||
private static String convertNodeCandidateToCsv(NodeCandidateDTO nodeCandidate) {
|
||||
// Convert a single NodeCandidate to CSV format
|
||||
return String.format("%s;%d;%d;%d;%s;%f;%f;%s;%s;%f",
|
||||
nodeCandidate.getId(),
|
||||
nodeCandidate.getGpu(),
|
||||
nodeCandidate.getCpu(),
|
||||
nodeCandidate.getRam(),
|
||||
nodeCandidate.getLocation(),
|
||||
nodeCandidate.getLatitude(),
|
||||
nodeCandidate.getLongitude(),
|
||||
nodeCandidate.getProvider(),
|
||||
nodeCandidate.getType(),
|
||||
nodeCandidate.getPrice());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package eu.nebulous.utilityevaluator.nodecandidates;
|
||||
|
||||
import org.ow2.proactive.sal.model.NodeCandidate;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class NodeCandidateDTO {
|
||||
@NonNull
|
||||
private NodeCandidate.NodeCandidateTypeEnum type;
|
||||
@NonNull
|
||||
private Double price;
|
||||
@NonNull
|
||||
private String provider;
|
||||
@NonNull
|
||||
private Integer cpu;
|
||||
@NonNull
|
||||
private Integer gpu;
|
||||
@NonNull
|
||||
private Long ram;
|
||||
@NonNull
|
||||
private String location;
|
||||
@NonNull
|
||||
private Double latitude;
|
||||
@NonNull
|
||||
private Double longitude;
|
||||
|
||||
private String id;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,8 @@
|
||||
spring.pa-config.rest-url=http://localhost:8088/sal
|
||||
spring.pa-config.url=http://localhost:8080/
|
||||
spring.pa-config.login=admin
|
||||
spring.pa-config.password=admin
|
||||
spring.activemq.broker-url=localhost
|
||||
spring.activemq.broker-port=5672
|
||||
spring.activemq.user=admin
|
||||
spring.activemq.password=admin
|
@ -0,0 +1,83 @@
|
||||
package eu.nebulous.utilityevaluator;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mockito;
|
||||
import org.ow2.proactive.sal.model.Cloud;
|
||||
import org.ow2.proactive.sal.model.CloudType;
|
||||
import org.ow2.proactive.sal.model.GeoLocation;
|
||||
import org.ow2.proactive.sal.model.Hardware;
|
||||
import org.ow2.proactive.sal.model.NodeCandidate;
|
||||
import org.ow2.proactive.sal.model.NodeCandidate.NodeCandidateTypeEnum;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.jms.core.JmsTemplate;
|
||||
|
||||
import eu.nebulous.utilityevaluator.communication.activemq.message.FetchNodeCandidatesMessage;
|
||||
import eu.nebulous.utilityevaluator.nodecandidates.NodeCandidateConverter;
|
||||
import eu.nebulous.utilityevaluator.nodecandidates.NodeCandidateDTO;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@SpringBootTest
|
||||
class UtilityEvaluatorApplicationTests {
|
||||
|
||||
@MockBean
|
||||
private JmsTemplate jmsTemplate;
|
||||
|
||||
//@Test
|
||||
void testNodeCandidatesConverter() {
|
||||
// Arrange
|
||||
List<NodeCandidate> mockNodeCandidates = Collections.singletonList(createMockNodeCandidate());
|
||||
Map<String,String> cloudProviders = Map.of("aws-ec2", "longsalid", "openstack", "longsalid2");
|
||||
|
||||
Mockito.when(jmsTemplate.receiveAndConvert("utilityEvaluatorInitialize"))
|
||||
.thenReturn(new FetchNodeCandidatesMessage("appID",cloudProviders ));
|
||||
|
||||
// Act
|
||||
List<NodeCandidateDTO> result = NodeCandidateConverter.convertToDtoList(mockNodeCandidates);
|
||||
|
||||
// Assert
|
||||
assertFalse(result.isEmpty());
|
||||
assertEquals(3.40, result.get(0).getLongitude());
|
||||
assertEquals(56, result.get(0).getPrice());
|
||||
|
||||
|
||||
|
||||
// Add your assertions here to verify that the conversion is correct based on your logic
|
||||
}
|
||||
|
||||
private NodeCandidate createMockNodeCandidate() {
|
||||
// Create and return a mock NodeCandidate object
|
||||
// Customize the object based on your requirements for testing
|
||||
|
||||
Hardware mockHardware = mock(Hardware.class);
|
||||
mockHardware.setCores(10);
|
||||
mockHardware.setRam(1000L);
|
||||
mockHardware.setFpga("f");
|
||||
|
||||
Cloud mockCloud = new Cloud();
|
||||
mockCloud.setId("testCloudID");
|
||||
mockCloud.setCloudType(CloudType.PUBLIC);
|
||||
|
||||
org.ow2.proactive.sal.model.Location mockLocation = mock(org.ow2.proactive.sal.model.Location.class);
|
||||
GeoLocation mockGeoLocation = new GeoLocation("Dublin", "IE", 15.40, 3.40);
|
||||
mockLocation.setGeoLocation(mockGeoLocation);
|
||||
when(mockLocation.getGeoLocation()).thenReturn(mockGeoLocation);
|
||||
|
||||
NodeCandidate nc = new NodeCandidate();
|
||||
nc.setCloud(mockCloud);
|
||||
nc.setHardware(mockHardware);
|
||||
nc.setLocation(mockLocation);
|
||||
nc.setPrice(56.0);
|
||||
nc.setId("That'stestid");
|
||||
nc.setNodeCandidateType(NodeCandidateTypeEnum.IAAS);
|
||||
return nc;
|
||||
}
|
||||
}
|
@ -8,15 +8,15 @@
|
||||
- nebulous-optimiser-utility-evaluator-container-images
|
||||
description: Build the container images.
|
||||
files: &image_files
|
||||
- ^java-spring-boot-demo/
|
||||
- ^utility-evaluator/
|
||||
vars: &image_vars
|
||||
promote_container_image_job: nebulous-optimiser-utility-evaluator-upload-container-images
|
||||
container_images:
|
||||
- context: java-spring-boot-demo
|
||||
- context: utility-evaluator
|
||||
registry: quay.io
|
||||
repository: quay.io/nebulous/optimiser-utility-evaluator-java-spring-boot-demo
|
||||
repository: quay.io/nebulous/optimiser-utility-evaluator
|
||||
namespace: nebulous
|
||||
repo_shortname: optimiser-utility-evaluator-java-spring-boot-demo
|
||||
repo_shortname: optimiser-utility-evaluator
|
||||
repo_description: ""
|
||||
|
||||
- job:
|
||||
@ -44,7 +44,7 @@
|
||||
description: Run Hadolint on Dockerfile(s).
|
||||
vars:
|
||||
dockerfiles:
|
||||
- java-spring-boot-demo/Dockerfile
|
||||
- utility-evaluator/Dockerfile
|
||||
|
||||
- job:
|
||||
name: nebulous-optimiser-utility-evaluator-helm-lint
|
||||
|
Loading…
x
Reference in New Issue
Block a user