diff options
author | toby <smorgrav@yahoo-inc.com> | 2017-10-12 12:07:13 +0200 |
---|---|---|
committer | toby <smorgrav@yahoo-inc.com> | 2017-10-12 12:07:13 +0200 |
commit | 039e81aafd0fa4ad7eac5ff17a514b5d5362d4be (patch) | |
tree | f8d405419f5014ca05e6080ef86f04e48d8621f7 | |
parent | 7b7beb1a88e78bb2747d98ce52c74cb56225d1be (diff) |
Add more flavor info and redefine cluster tco and waste
7 files changed, 68 insertions, 13 deletions
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/ClusterCost.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/ClusterCost.java index b337f85bd6c..59200af2594 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/ClusterCost.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/ClusterCost.java @@ -41,8 +41,10 @@ public class ClusterCost { this.targetUtilization = new ClusterUtilization(0.7,0.2, 0.7, 0.3); this.resultUtilization = calculateResultUtilization(systemUtilization, targetUtilization); - this.tco = clusterInfo.getCost() * Math.min(1, this.resultUtilization.getMaxUtilization()); - this.waste = clusterInfo.getCost() - tco; + this.tco = clusterInfo.getHostnames().size() * clusterInfo.getFlavorCost(); + + double unusedUtilization = 1 - Math.max(1, systemUtilization.getMaxUtilization()); + this.waste = tco * unusedUtilization; } /** @return The TCO in dollars for this cluster (node tco * nodes) */ diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/ClusterInfo.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/ClusterInfo.java index cb39177c811..40fc57acdc8 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/ClusterInfo.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/ClusterInfo.java @@ -9,31 +9,62 @@ import java.util.List; * Value object of static cluster information, in particular the TCO * of the hardware used for this cluster. * + * Some duplication/flattening of flavor info is done to simplify client usage. + * * @author smorgrav */ public class ClusterInfo { private final String flavor; - private final int cost; + private final double flavorCPU; + private final double flavorMem; + private final double flavorDisk; + private final int flavorCost; private final ClusterSpec.Type clusterType; private final List<String> hostnames; - public ClusterInfo(String flavor, int cost, ClusterSpec.Type clusterType, List<String> hostnames) { + /** + * @param flavor The name of the flavor eg. 'C-2B/24/500' + * @param flavorCost The cost of one node in dollars + * @param flavorCPU The number of cpu cores granted + * @param flavorMem The memory granted in Gb + * @param flavorDisk The disk size granted in Gb + * @param clusterType The vespa cluster type e.g 'container' or 'content' + * @param hostnames All hostnames in this cluster + */ + public ClusterInfo(String flavor, int flavorCost, double flavorCPU, double flavorMem, + double flavorDisk, ClusterSpec.Type clusterType, List<String> hostnames) { this.flavor = flavor; - this.cost = cost; + this.flavorCost = flavorCost; + this.flavorCPU = flavorCPU; + this.flavorMem = flavorMem; + this.flavorDisk = flavorDisk; this.clusterType = clusterType; this.hostnames = hostnames; } + /** @return The name of the flavor eg. 'C-2B/24/500' */ public String getFlavor() { return flavor; } - public int getCost() { return cost; } + /** @return The cost of one node in dollars */ + public int getFlavorCost() { return flavorCost; } + + /** @return The disk size granted in Gb */ + public double getFlavorDisk() { return flavorDisk; } + + /** @return The number of cpu cores granted */ + public double getFlavorCPU() { return flavorCPU; } + + /** @return The memory granted in Gb */ + public double getFlavorMem() { return flavorMem; } + /** @return The vespa cluster type e.g 'container' or 'content' */ public ClusterSpec.Type getClusterType() { return clusterType; } + /** @return All hostnames in this cluster */ public List<String> getHostnames() { return hostnames; } diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ClusterInfoMaintainer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ClusterInfoMaintainer.java index 8f5db8832fa..c807a7f0586 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ClusterInfoMaintainer.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ClusterInfoMaintainer.java @@ -2,6 +2,8 @@ package com.yahoo.vespa.hosted.controller.maintenance; import com.yahoo.config.provision.ClusterSpec; +import com.yahoo.config.provision.Flavor; +import com.yahoo.config.provision.Zone; import com.yahoo.vespa.curator.Lock; import com.yahoo.vespa.hosted.controller.Application; import com.yahoo.vespa.hosted.controller.Controller; @@ -15,6 +17,7 @@ import java.time.Duration; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.logging.Logger; import java.util.stream.Collectors; @@ -38,7 +41,7 @@ public class ClusterInfoMaintainer extends Maintainer { return node.membership.clusterId; } - private Map<ClusterSpec.Id, ClusterInfo> getClusterInfo(NodeList nodes) { + private Map<ClusterSpec.Id, ClusterInfo> getClusterInfo(NodeList nodes, Zone zone) { Map<ClusterSpec.Id, ClusterInfo> infoMap = new HashMap<>(); // Group nodes by clusterid @@ -53,9 +56,24 @@ public class ClusterInfoMaintainer extends Maintainer { //Assume they are all equal and use first node as a representatitve for the cluster NodeList.Node node = clusterNodes.get(0); + // Extract flavor info + double cpu = 0; + double mem = 0; + double disk = 0; + if (zone.nodeFlavors().isPresent()) { + Optional<Flavor> flavorOptional = zone.nodeFlavors().get().getFlavor(node.flavor); + if ((flavorOptional.isPresent())) { + Flavor flavor = flavorOptional.get(); + cpu = flavor.getMinCpuCores(); + mem = flavor.getMinMainMemoryAvailableGb(); + disk = flavor.getMinMainMemoryAvailableGb(); + } + } + // Add to map List<String> hostnames = clusterNodes.stream().map(node1 -> node1.hostname).collect(Collectors.toList()); - ClusterInfo inf = new ClusterInfo(node.flavor, node.cost, ClusterSpec.Type.from(node.membership.clusterType), hostnames); + ClusterInfo inf = new ClusterInfo(node.flavor, node.cost, cpu, mem, disk, + ClusterSpec.Type.from(node.membership.clusterType), hostnames); infoMap.put(new ClusterSpec.Id(id), inf); } @@ -71,7 +89,7 @@ public class ClusterInfoMaintainer extends Maintainer { DeploymentId deploymentId = new DeploymentId(application.id(), deployment.zone()); try { NodeList nodes = controller().applications().configserverClient().getNodeList(deploymentId); - Map<ClusterSpec.Id, ClusterInfo> clusterInfo = getClusterInfo(nodes); + Map<ClusterSpec.Id, ClusterInfo> clusterInfo = getClusterInfo(nodes, deployment.zone()); Application app = application.with(deployment.withClusterInfo(clusterInfo)); controller.applications().store(app, lock); } catch (IOException ioe) { diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/ApplicationSerializer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/ApplicationSerializer.java index 859e322b227..70a878ef93f 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/ApplicationSerializer.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/ApplicationSerializer.java @@ -134,7 +134,7 @@ public class ApplicationSerializer { private void toSlime(ClusterInfo info, Cursor object) { object.setString(clusterInfoFlavorField, info.getFlavor()); - object.setLong(clusterInfoCostField, info.getCost()); + object.setLong(clusterInfoCostField, info.getFlavorCost()); object.setString(clusterInfoTypeField, info.getClusterType().name()); Cursor array = object.setArray(clusterInfoHostnamesField); for (String host : info.getHostnames()) { diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java index 42e89e7893f..e4e62379f01 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java @@ -1096,8 +1096,12 @@ public class ApplicationApiHandler extends LoggingRequestHandler { object.setString("resource", getResourceName(clusterCost.getResultUtilization())); object.setDouble("utilization", clusterCost.getResultUtilization().getMaxUtilization()); object.setLong("tco", (int)clusterCost.getTco()); - object.setString("flavor", clusterCost.getClusterInfo().getFlavor()); object.setLong("waste", (int)clusterCost.getWaste()); + object.setString("flavor", clusterCost.getClusterInfo().getFlavor()); + object.setDouble("flavorCost", clusterCost.getClusterInfo().getFlavorCost()); + object.setDouble("flavorCpu", clusterCost.getClusterInfo().getFlavorCPU()); + object.setDouble("flavorMem", clusterCost.getClusterInfo().getFlavorMem()); + object.setDouble("flavorDisk", clusterCost.getClusterInfo().getFlavorDisk()); object.setString("type", clusterCost.getClusterInfo().getClusterType().name()); Cursor utilObject = object.setObject("util"); utilObject.setDouble("cpu", clusterCost.getResultUtilization().getCpu()); diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/ClusterInfoMaintainerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/ClusterInfoMaintainerTest.java index 7ae89082660..13919cefd3b 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/ClusterInfoMaintainerTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/ClusterInfoMaintainerTest.java @@ -31,7 +31,7 @@ public class ClusterInfoMaintainerTest { deployment = tester.controller().applications().get(app).get().deployments().values().stream().findAny().get(); Assert.assertEquals(2, deployment.clusterInfo().size()); - Assert.assertEquals(10, deployment.clusterInfo().get(ClusterSpec.Id.from("clusterA")).getCost()); + Assert.assertEquals(10, deployment.clusterInfo().get(ClusterSpec.Id.from("clusterA")).getFlavorCost()); } diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/ApplicationSerializerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/ApplicationSerializerTest.java index 3e73bf4445b..22d67b7af7d 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/ApplicationSerializerTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/ApplicationSerializerTest.java @@ -118,7 +118,7 @@ public class ApplicationSerializerTest { // Test cluster info assertEquals(3, serialized.deployments().get(zone2).clusterInfo().size()); - assertEquals(10, serialized.deployments().get(zone2).clusterInfo().get(ClusterSpec.Id.from("id2")).getCost()); + assertEquals(10, serialized.deployments().get(zone2).clusterInfo().get(ClusterSpec.Id.from("id2")).getFlavorCost()); assertEquals(ClusterSpec.Type.content, serialized.deployments().get(zone2).clusterInfo().get(ClusterSpec.Id.from("id2")).getClusterType()); assertEquals("flavor2", serialized.deployments().get(zone2).clusterInfo().get(ClusterSpec.Id.from("id2")).getFlavor()); assertEquals(4, serialized.deployments().get(zone2).clusterInfo().get(ClusterSpec.Id.from("id2")).getHostnames().size()); |