diff --git a/nebulous-requirements-extractor/src/main/java/eu/nebulouscloud/optimiser/kubevela/KubevelaAnalyzer.java b/nebulous-requirements-extractor/src/main/java/eu/nebulouscloud/optimiser/kubevela/KubevelaAnalyzer.java
index f142c50..8ede88a 100644
--- a/nebulous-requirements-extractor/src/main/java/eu/nebulouscloud/optimiser/kubevela/KubevelaAnalyzer.java
+++ b/nebulous-requirements-extractor/src/main/java/eu/nebulouscloud/optimiser/kubevela/KubevelaAnalyzer.java
@@ -17,6 +17,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Set;
/**
* A collection of methods to extract node requirements from KubeVela files.
@@ -76,17 +77,27 @@ public class KubevelaAnalyzer {
}
/**
- * Add frequirements for Ubuntu version 22.04. Also add requirement for
- * 2GB of RAM for now until we know more about the size / cpu requirements
- * of the nebulous runtime.
+ * Add the following requirements:
+ *
+ * - Ubuntu version 22.04
+ *
- 2GB of RAM (until we know more about the size / cpu requirements
+ * of the nebulous runtime.)
+ *
- Cloud IDs, if given.
+ *
*
* @param reqs The list of requirements to add to.
+ * @param cloudIDs the Cloud IDs to filter for.
*/
- private static void addNebulousRequirements(List reqs) {
+ private static void addNebulousRequirements(List reqs, Set cloudIDs) {
reqs.add(new AttributeRequirement("image", "operatingSystem.family",
RequirementOperator.IN, OperatingSystemFamily.UBUNTU.toString()));
reqs.add(new AttributeRequirement("image", "name", RequirementOperator.INC, "22"));
reqs.add(new AttributeRequirement("hardware", "ram", RequirementOperator.GEQ, "2048"));
+ if (cloudIDs != null && !cloudIDs.isEmpty()) {
+ reqs.add(new AttributeRequirement("cloud", "id",
+ RequirementOperator.IN, String.join(" ", cloudIDs)));
+ }
+
}
/**
@@ -188,18 +199,21 @@ public class KubevelaAnalyzer {
* @param includeNebulousRequirements if true, include requirements for
* minimum memory size, Ubuntu OS. These requirements ensure that the
* node candidate can run the Nebulous software.
+ * @param cloudIDs The IDs of the clouds that the node candidates should
+ * come from. Will only be handled if non-null and
+ * includeNebulousRequirements is true.
* @return a map of component name to (potentially empty, except for OS
* family) list of requirements for that component. No requirements mean
* any node will suffice.
*/
- public static Map> getBoundedRequirements(JsonNode kubevela, boolean includeNebulousRequirements) {
+ public static Map> getBoundedRequirements(JsonNode kubevela, boolean includeNebulousRequirements, Set cloudIDs) {
Map> result = new HashMap<>();
ArrayNode components = kubevela.withArray("/spec/components");
for (final JsonNode c : components) {
String componentName = c.get("name").asText();
ArrayList reqs = new ArrayList<>();
if (includeNebulousRequirements) {
- addNebulousRequirements(reqs);
+ addNebulousRequirements(reqs, cloudIDs);
}
long cores = getCpuRequirement(c, componentName);
if (cores > 0) {
@@ -228,8 +242,8 @@ public class KubevelaAnalyzer {
*
* @see #getBoundedRequirements(JsonNode, boolean)
*/
- public static Map> getBoundedRequirements(JsonNode kubevela) {
- return getBoundedRequirements(kubevela, true);
+ public static Map> getBoundedRequirements(JsonNode kubevela, Set cloudIDs) {
+ return getBoundedRequirements(kubevela, true, cloudIDs);
}
/**
@@ -239,13 +253,13 @@ public class KubevelaAnalyzer {
* cpu >= 2, cpu <= 4. Take care to not ask for less than 2048Mb of
* memory since that's the minimum Nebulous requirement for now.
*/
- public static Map> getClampedRequirements(JsonNode kubevela) {
+ public static Map> getClampedRequirements(JsonNode kubevela, Set cloudIDs) {
Map> result = new HashMap<>();
ArrayNode components = kubevela.withArray("/spec/components");
for (final JsonNode c : components) {
String componentName = c.get("name").asText();
ArrayList reqs = new ArrayList<>();
- addNebulousRequirements(reqs);
+ addNebulousRequirements(reqs, cloudIDs);
long cores = getCpuRequirement(c, componentName);
if (cores > 0) {
reqs.add(new AttributeRequirement("hardware", "cores",
@@ -279,13 +293,13 @@ public class KubevelaAnalyzer {
* asking for >= or <=. Note that we still ask for >= 2048 Mb since
* that's the nebulous lower bound for now.
*/
- public static Map> getPreciseRequirements(JsonNode kubevela) {
+ public static Map> getPreciseRequirements(JsonNode kubevela, Set cloudIDs) {
Map> result = new HashMap<>();
ArrayNode components = kubevela.withArray("/spec/components");
for (final JsonNode c : components) {
String componentName = c.get("name").asText();
ArrayList reqs = new ArrayList<>();
- addNebulousRequirements(reqs);
+ addNebulousRequirements(reqs, cloudIDs);
long cores = getCpuRequirement(c, componentName);
if (cores > 0) {
reqs.add(new AttributeRequirement("hardware", "cores",
@@ -313,13 +327,16 @@ public class KubevelaAnalyzer {
*
* @see #getBoundedRequirements(JsonNode)
* @param kubevela The KubeVela file, as a YAML string.
+ * @param cloudIDs The IDs of the clouds that the node candidates should
+ * come from. Will only be handled if non-null and
+ * includeNebulousRequirements is true.
* @return a map of component name to (potentially empty, except for OS
* family) list of requirements for that component. No requirements mean
* any node will suffice.
* @throws JsonProcessingException if kubevela does not contain valid YAML.
*/
- public static Map> getBoundedRequirements(String kubevela) throws JsonProcessingException {
- return getBoundedRequirements(parseKubevela(kubevela));
+ public static Map> getBoundedRequirements(String kubevela, Set cloudIDs) throws JsonProcessingException {
+ return getBoundedRequirements(parseKubevela(kubevela), cloudIDs);
}
/**
diff --git a/optimiser-controller/src/main/java/eu/nebulouscloud/optimiser/controller/ExnConnector.java b/optimiser-controller/src/main/java/eu/nebulouscloud/optimiser/controller/ExnConnector.java
index a4b64e1..18c56b9 100644
--- a/optimiser-controller/src/main/java/eu/nebulouscloud/optimiser/controller/ExnConnector.java
+++ b/optimiser-controller/src/main/java/eu/nebulouscloud/optimiser/controller/ExnConnector.java
@@ -229,7 +229,9 @@ public class ExnConnector {
try {
log.info("App creation message received");
JsonNode appMessage = mapper.valueToTree(body);
- Main.logFile("app-message-" + appMessage.at("/uuid").asText() + ".json", appMessage.toPrettyString());
+ String appID = appMessage.at("/uuid").asText();
+ MDC.put("appId", appID);
+ Main.logFile("app-message-" + appID + ".json", appMessage.toPrettyString());
app = NebulousApp.newFromAppMessage(mapper.valueToTree(body), ExnConnector.this);
String appIdFromMessage = app.getUUID();
MDC.put("appId", appIdFromMessage);
diff --git a/optimiser-controller/src/main/java/eu/nebulouscloud/optimiser/controller/NebulousApp.java b/optimiser-controller/src/main/java/eu/nebulouscloud/optimiser/controller/NebulousApp.java
index 56a99d3..bd680bf 100644
--- a/optimiser-controller/src/main/java/eu/nebulouscloud/optimiser/controller/NebulousApp.java
+++ b/optimiser-controller/src/main/java/eu/nebulouscloud/optimiser/controller/NebulousApp.java
@@ -139,6 +139,13 @@ public class NebulousApp {
@Getter private JsonNode originalAppMessage;
private ObjectNode originalKubevela;
+ /**
+ * The cloud IDs to be used. These are given in the `resources` section
+ * of the app message; we collect all cloud IDs where `enabled:true`
+ * holds.
+ */
+ @Getter private Set cloudIDs;
+
/**
* The current "generation" of deployment. Initial deployment sets this
* to 1, each subsequent redeployment increases by 1. This value is used
@@ -237,7 +244,9 @@ public class NebulousApp {
// are performance indicators in disguise.
boolean done = false;
Set metrics = StreamSupport.stream(
- Spliterators.spliteratorUnknownSize(app_message.withArray("/metrics").elements(), Spliterator.ORDERED), false)
+ Spliterators.spliteratorUnknownSize(
+ app_message.withArray("/metrics").elements(),
+ Spliterator.ORDERED), false)
.collect(Collectors.toSet());
while (!done) {
// Pick out all raw metrics. Then pick out all composite metrics
@@ -284,6 +293,16 @@ public class NebulousApp {
break;
}
}
+ cloudIDs = StreamSupport.stream(
+ Spliterators.spliteratorUnknownSize(
+ app_message.withArray("/resources").elements(),
+ Spliterator.ORDERED), false)
+ .filter((c) -> c.get("enabled").asBoolean())
+ .map((c) -> c.get("uuid").asText())
+ .collect(Collectors.toSet());
+ if (cloudIDs.isEmpty()) {
+ log.warn("No clouds enabled or specified in app creation message, will try to deploy only on edge nodes.");
+ }
log.debug("New App instantiated.");
}
diff --git a/optimiser-controller/src/main/java/eu/nebulouscloud/optimiser/controller/NebulousAppDeployer.java b/optimiser-controller/src/main/java/eu/nebulouscloud/optimiser/controller/NebulousAppDeployer.java
index 55ff696..0994ef0 100644
--- a/optimiser-controller/src/main/java/eu/nebulouscloud/optimiser/controller/NebulousAppDeployer.java
+++ b/optimiser-controller/src/main/java/eu/nebulouscloud/optimiser/controller/NebulousAppDeployer.java
@@ -254,7 +254,7 @@ public class NebulousAppDeployer {
// ------------------------------------------------------------
// Extract node requirements
- Map> componentRequirements = KubevelaAnalyzer.getBoundedRequirements(kubevela);
+ Map> componentRequirements = KubevelaAnalyzer.getBoundedRequirements(kubevela, app.getCloudIDs());
Map nodeCounts = KubevelaAnalyzer.getNodeCount(kubevela);
List controllerRequirements = getControllerRequirements(appUUID);
// // HACK: do this only when cloud id = nrec
@@ -520,7 +520,7 @@ public class NebulousAppDeployer {
// ------------------------------------------------------------
// 1. Extract node requirements
- Map> componentRequirements = KubevelaAnalyzer.getBoundedRequirements(updatedKubevela);
+ Map> componentRequirements = KubevelaAnalyzer.getBoundedRequirements(updatedKubevela, app.getCloudIDs());
Map componentReplicaCounts = KubevelaAnalyzer.getNodeCount(updatedKubevela);
Map> oldComponentRequirements = app.getComponentRequirements();
diff --git a/optimiser-controller/src/test/java/eu/nebulouscloud/optimiser/controller/NebulousAppTests.java b/optimiser-controller/src/test/java/eu/nebulouscloud/optimiser/controller/NebulousAppTests.java
index f5479aa..7663d1b 100644
--- a/optimiser-controller/src/test/java/eu/nebulouscloud/optimiser/controller/NebulousAppTests.java
+++ b/optimiser-controller/src/test/java/eu/nebulouscloud/optimiser/controller/NebulousAppTests.java
@@ -91,7 +91,7 @@ public class NebulousAppTests {
String kubevela_str = Files.readString(getResourcePath("vela-deployment-v2.yml"),
StandardCharsets.UTF_8);
JsonNode kubevela = yaml_mapper.readTree(kubevela_str);
- Map> requirements = KubevelaAnalyzer.getBoundedRequirements(kubevela);
+ Map> requirements = KubevelaAnalyzer.getBoundedRequirements(kubevela, null);
// We could compare the requirements with what is contained in
// KubeVela, or compare keys with component names, but this would
// essentially duplicate the method code--so we just make sure the
@@ -111,7 +111,7 @@ public class NebulousAppTests {
ObjectNode replacements = solutions.withObject("VariableValues");
ObjectNode kubevela1 = app.rewriteKubevelaWithSolution(replacements);
- Map> requirements = KubevelaAnalyzer.getBoundedRequirements(kubevela1);
+ Map> requirements = KubevelaAnalyzer.getBoundedRequirements(kubevela1, null);
// We could compare the requirements with what is contained in
// KubeVela, or compare keys with component names, but this would
// essentially duplicate the method code--so we just make sure the