Skip to content

Commit

Permalink
Add filtering by cloud IDs.
Browse files Browse the repository at this point in the history
Change-Id: I99535d261c84a91700fe2c95c70e507cd84f6e42
  • Loading branch information
rudi committed May 13, 2024
1 parent 1ae236f commit 173752a
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
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.
Expand Down Expand Up @@ -76,17 +77,27 @@ public static Map<String, Integer> getNodeCount(String kubevela) throws JsonProc
}

/**
* 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)));
}

}

/**
Expand Down Expand Up @@ -188,18 +199,21 @@ private static long getMemoryRequirement(JsonNode c, String componentName) {
* @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) {
Expand Down Expand Up @@ -228,8 +242,8 @@ public static Map<String, List<Requirement>> getBoundedRequirements(JsonNode kub
*
* @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);
}

/**
Expand All @@ -239,13 +253,13 @@ public static Map<String, List<Requirement>> getBoundedRequirements(JsonNode kub
* 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",
Expand Down Expand Up @@ -279,13 +293,13 @@ public static Map<String, List<Requirement>> getClampedRequirements(JsonNode kub
* 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",
Expand Down Expand Up @@ -313,13 +327,16 @@ public static Map<String, List<Requirement>> getPreciseRequirements(JsonNode kub
*
* @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);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,9 @@ public void onMessage(String key, String address, Map body, Message message, Con
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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,13 @@ public enum State {
@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
Expand Down Expand Up @@ -237,7 +244,9 @@ public NebulousApp(JsonNode app_message, ObjectNode kubevela, ExnConnector exnCo
// 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
Expand Down Expand Up @@ -284,6 +293,16 @@ public NebulousApp(JsonNode app_message, ObjectNode kubevela, ExnConnector exnCo
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.");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ public static void deployApplication(NebulousApp app, JsonNode kubevela) {

// ------------------------------------------------------------
// 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
Expand Down Expand Up @@ -520,7 +520,7 @@ public static void redeployApplication(NebulousApp app, ObjectNode updatedKubeve

// ------------------------------------------------------------
// 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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ void calculateNodeRequirements() throws IOException, URISyntaxException {
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
Expand All @@ -111,7 +111,7 @@ void calculateRewrittenNodeRequirements() throws IOException, URISyntaxException
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
Expand Down

0 comments on commit 173752a

Please sign in to comment.