Add filtering by cloud IDs.
Change-Id: I99535d261c84a91700fe2c95c70e507cd84f6e42
This commit is contained in:
parent
1ae236f759
commit
173752a608
@ -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:
|
||||
* <ul>
|
||||
* <li> Ubuntu version 22.04
|
||||
* <li> 2GB of RAM (until we know more about the size / cpu requirements
|
||||
* of the nebulous runtime.)
|
||||
* <li> Cloud IDs, if given.
|
||||
* </ul>
|
||||
*
|
||||
* @param reqs The list of requirements to add to.
|
||||
* @param cloudIDs the Cloud IDs to filter for.
|
||||
*/
|
||||
private static void addNebulousRequirements(List<Requirement> reqs) {
|
||||
private static void addNebulousRequirements(List<Requirement> reqs, Set<String> 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<String, List<Requirement>> getBoundedRequirements(JsonNode kubevela, boolean includeNebulousRequirements) {
|
||||
public static Map<String, List<Requirement>> getBoundedRequirements(JsonNode kubevela, boolean includeNebulousRequirements, Set<String> cloudIDs) {
|
||||
Map<String, List<Requirement>> result = new HashMap<>();
|
||||
ArrayNode components = kubevela.withArray("/spec/components");
|
||||
for (final JsonNode c : components) {
|
||||
String componentName = c.get("name").asText();
|
||||
ArrayList<Requirement> 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<String, List<Requirement>> getBoundedRequirements(JsonNode kubevela) {
|
||||
return getBoundedRequirements(kubevela, true);
|
||||
public static Map<String, List<Requirement>> getBoundedRequirements(JsonNode kubevela, Set<String> 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<String, List<Requirement>> getClampedRequirements(JsonNode kubevela) {
|
||||
public static Map<String, List<Requirement>> getClampedRequirements(JsonNode kubevela, Set<String> cloudIDs) {
|
||||
Map<String, List<Requirement>> result = new HashMap<>();
|
||||
ArrayNode components = kubevela.withArray("/spec/components");
|
||||
for (final JsonNode c : components) {
|
||||
String componentName = c.get("name").asText();
|
||||
ArrayList<Requirement> 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<String, List<Requirement>> getPreciseRequirements(JsonNode kubevela) {
|
||||
public static Map<String, List<Requirement>> getPreciseRequirements(JsonNode kubevela, Set<String> cloudIDs) {
|
||||
Map<String, List<Requirement>> result = new HashMap<>();
|
||||
ArrayNode components = kubevela.withArray("/spec/components");
|
||||
for (final JsonNode c : components) {
|
||||
String componentName = c.get("name").asText();
|
||||
ArrayList<Requirement> 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<String, List<Requirement>> getBoundedRequirements(String kubevela) throws JsonProcessingException {
|
||||
return getBoundedRequirements(parseKubevela(kubevela));
|
||||
public static Map<String, List<Requirement>> getBoundedRequirements(String kubevela, Set<String> cloudIDs) throws JsonProcessingException {
|
||||
return getBoundedRequirements(parseKubevela(kubevela), cloudIDs);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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);
|
||||
|
@ -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<String> 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<JsonNode> 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.");
|
||||
}
|
||||
|
||||
|
@ -254,7 +254,7 @@ public class NebulousAppDeployer {
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// Extract node requirements
|
||||
Map<String, List<Requirement>> componentRequirements = KubevelaAnalyzer.getBoundedRequirements(kubevela);
|
||||
Map<String, List<Requirement>> componentRequirements = KubevelaAnalyzer.getBoundedRequirements(kubevela, app.getCloudIDs());
|
||||
Map<String, Integer> nodeCounts = KubevelaAnalyzer.getNodeCount(kubevela);
|
||||
List<Requirement> controllerRequirements = getControllerRequirements(appUUID);
|
||||
// // HACK: do this only when cloud id = nrec
|
||||
@ -520,7 +520,7 @@ public class NebulousAppDeployer {
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// 1. Extract node requirements
|
||||
Map<String, List<Requirement>> componentRequirements = KubevelaAnalyzer.getBoundedRequirements(updatedKubevela);
|
||||
Map<String, List<Requirement>> componentRequirements = KubevelaAnalyzer.getBoundedRequirements(updatedKubevela, app.getCloudIDs());
|
||||
Map<String, Integer> componentReplicaCounts = KubevelaAnalyzer.getNodeCount(updatedKubevela);
|
||||
|
||||
Map<String, List<Requirement>> oldComponentRequirements = app.getComponentRequirements();
|
||||
|
@ -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<String, List<Requirement>> requirements = KubevelaAnalyzer.getBoundedRequirements(kubevela);
|
||||
Map<String, List<Requirement>> 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<String, List<Requirement>> requirements = KubevelaAnalyzer.getBoundedRequirements(kubevela1);
|
||||
Map<String, List<Requirement>> 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
|
||||
|
Loading…
x
Reference in New Issue
Block a user