summaryrefslogtreecommitdiff
path: root/opendc-experiments/opendc-experiments-greenifier/src/test
diff options
context:
space:
mode:
authorDante Niewenhuis <d.niewenhuis@hotmail.com>2023-11-10 22:30:49 +0100
committerDante Niewenhuis <d.niewenhuis@hotmail.com>2023-11-10 22:32:29 +0100
commit059a09949e839fe9e906c398710b5235b452b0e0 (patch)
tree6d8fdca4db4697b3d5dbe6ae291425d07fa84276 /opendc-experiments/opendc-experiments-greenifier/src/test
parentaa9149b9c49be570c2b14254d3c6a23d7c077e34 (diff)
added greenifier demo, fixed HostTableReader
Diffstat (limited to 'opendc-experiments/opendc-experiments-greenifier/src/test')
-rw-r--r--opendc-experiments/opendc-experiments-greenifier/src/test/kotlin/org/opendc/experiments/capelin/GreenifierIntegrationTest.kt287
-rw-r--r--opendc-experiments/opendc-experiments-greenifier/src/test/kotlin/org/opendc/experiments/capelin/GreenifierRunnerTest.kt86
-rw-r--r--opendc-experiments/opendc-experiments-greenifier/src/test/resources/env/single.txt3
-rw-r--r--opendc-experiments/opendc-experiments-greenifier/src/test/resources/env/topology.txt5
-rw-r--r--opendc-experiments/opendc-experiments-greenifier/src/test/resources/trace/bitbrains-small/interference-model.json21
-rw-r--r--opendc-experiments/opendc-experiments-greenifier/src/test/resources/trace/bitbrains-small/meta.parquetbin0 -> 2723 bytes
-rw-r--r--opendc-experiments/opendc-experiments-greenifier/src/test/resources/trace/bitbrains-small/trace.parquetbin0 -> 2163354 bytes
7 files changed, 402 insertions, 0 deletions
diff --git a/opendc-experiments/opendc-experiments-greenifier/src/test/kotlin/org/opendc/experiments/capelin/GreenifierIntegrationTest.kt b/opendc-experiments/opendc-experiments-greenifier/src/test/kotlin/org/opendc/experiments/capelin/GreenifierIntegrationTest.kt
new file mode 100644
index 00000000..5431a061
--- /dev/null
+++ b/opendc-experiments/opendc-experiments-greenifier/src/test/kotlin/org/opendc/experiments/capelin/GreenifierIntegrationTest.kt
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 2020 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.experiments.greenifier
+
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.assertAll
+import org.opendc.compute.service.ComputeService
+import org.opendc.compute.service.scheduler.FilterScheduler
+import org.opendc.compute.service.scheduler.filters.ComputeFilter
+import org.opendc.compute.service.scheduler.filters.RamFilter
+import org.opendc.compute.service.scheduler.filters.VCpuFilter
+import org.opendc.compute.service.scheduler.weights.CoreRamWeigher
+import org.opendc.experiments.greenifier.topology.clusterTopology
+import org.opendc.experiments.compute.ComputeWorkloadLoader
+import org.opendc.experiments.compute.VirtualMachine
+import org.opendc.experiments.compute.grid5000
+import org.opendc.experiments.compute.registerComputeMonitor
+import org.opendc.experiments.compute.replay
+import org.opendc.experiments.compute.sampleByLoad
+import org.opendc.experiments.compute.setupComputeService
+import org.opendc.experiments.compute.setupHosts
+import org.opendc.experiments.compute.telemetry.ComputeMonitor
+import org.opendc.experiments.compute.telemetry.table.HostTableReader
+import org.opendc.experiments.compute.telemetry.table.ServiceTableReader
+import org.opendc.experiments.compute.topology.HostSpec
+import org.opendc.experiments.compute.trace
+import org.opendc.experiments.provisioner.Provisioner
+import org.opendc.simulator.kotlin.runSimulation
+import java.io.File
+import java.time.Duration
+import java.util.Random
+
+/**
+ * An integration test suite for the Greenifier experiments.
+ */
+class GreenifierIntegrationTest {
+ /**
+ * The monitor used to keep track of the metrics.
+ */
+ private lateinit var monitor: TestComputeMonitor
+
+ /**
+ * The [FilterScheduler] to use for all experiments.
+ */
+ private lateinit var computeScheduler: FilterScheduler
+
+ /**
+ * The [ComputeWorkloadLoader] responsible for loading the traces.
+ */
+ private lateinit var workloadLoader: ComputeWorkloadLoader
+
+ /**
+ * Set up the experimental environment.
+ */
+ @BeforeEach
+ fun setUp() {
+ monitor = TestComputeMonitor()
+ computeScheduler = FilterScheduler(
+ filters = listOf(ComputeFilter(), VCpuFilter(16.0), RamFilter(1.0)),
+ weighers = listOf(CoreRamWeigher(multiplier = 1.0))
+ )
+ workloadLoader = ComputeWorkloadLoader(File("src/test/resources/trace"))
+ }
+
+ /**
+ * Test a large simulation setup.
+ */
+ @Test
+ fun testLarge() = runSimulation {
+ val seed = 0L
+ val workload = createTestWorkload(1.0, seed)
+ val topology = createTopology()
+ val monitor = monitor
+
+ Provisioner(dispatcher, seed).use { provisioner ->
+ provisioner.runSteps(
+ setupComputeService(serviceDomain = "compute.opendc.org", { computeScheduler }),
+ registerComputeMonitor(serviceDomain = "compute.opendc.org", monitor),
+ setupHosts(serviceDomain = "compute.opendc.org", topology)
+ )
+
+ val service = provisioner.registry.resolve("compute.opendc.org", ComputeService::class.java)!!
+ service.replay(timeSource, workload, seed)
+ }
+
+ println(
+ "Scheduler " +
+ "Success=${monitor.attemptsSuccess} " +
+ "Failure=${monitor.attemptsFailure} " +
+ "Error=${monitor.attemptsError} " +
+ "Pending=${monitor.serversPending} " +
+ "Active=${monitor.serversActive}"
+ )
+
+ // Note that these values have been verified beforehand
+ assertAll(
+ { assertEquals(50, monitor.attemptsSuccess, "The scheduler should schedule 50 VMs") },
+ { assertEquals(0, monitor.serversActive, "All VMs should finish after a run") },
+ { assertEquals(0, monitor.attemptsFailure, "No VM should be unscheduled") },
+ { assertEquals(0, monitor.serversPending, "No VM should not be in the queue") },
+ { assertEquals(223394101, monitor.idleTime) { "Incorrect idle time" } },
+ { assertEquals(66977086, monitor.activeTime) { "Incorrect active time" } },
+ { assertEquals(3160276, monitor.stealTime) { "Incorrect steal time" } },
+ { assertEquals(0, monitor.lostTime) { "Incorrect lost time" } },
+ { assertEquals(5.84093E9, monitor.energyUsage, 1E4) { "Incorrect power draw" } }
+ )
+ }
+
+ /**
+ * Test a small simulation setup.
+ */
+ @Test
+ fun testSmall() = runSimulation {
+ val seed = 1L
+ val workload = createTestWorkload(0.25, seed)
+ val topology = createTopology("single")
+ val monitor = monitor
+
+ Provisioner(dispatcher, seed).use { provisioner ->
+ provisioner.runSteps(
+ setupComputeService(serviceDomain = "compute.opendc.org", { computeScheduler }),
+ registerComputeMonitor(serviceDomain = "compute.opendc.org", monitor),
+ setupHosts(serviceDomain = "compute.opendc.org", topology)
+ )
+
+ val service = provisioner.registry.resolve("compute.opendc.org", ComputeService::class.java)!!
+ service.replay(timeSource, workload, seed)
+ }
+
+ println(
+ "Scheduler " +
+ "Success=${monitor.attemptsSuccess} " +
+ "Failure=${monitor.attemptsFailure} " +
+ "Error=${monitor.attemptsError} " +
+ "Pending=${monitor.serversPending} " +
+ "Active=${monitor.serversActive}"
+ )
+
+ // Note that these values have been verified beforehand
+ assertAll(
+ { assertEquals(10999514, monitor.idleTime) { "Idle time incorrect" } },
+ { assertEquals(9741285, monitor.activeTime) { "Active time incorrect" } },
+ { assertEquals(0, monitor.stealTime) { "Steal time incorrect" } },
+ { assertEquals(0, monitor.lostTime) { "Lost time incorrect" } },
+ { assertEquals(7.0116E8, monitor.energyUsage, 1E4) { "Incorrect power draw" } }
+ )
+ }
+
+ /**
+ * Test a small simulation setup with interference.
+ */
+ @Test
+ fun testInterference() = runSimulation {
+ val seed = 0L
+ val workload = createTestWorkload(1.0, seed)
+ val topology = createTopology("single")
+
+ Provisioner(dispatcher, seed).use { provisioner ->
+ provisioner.runSteps(
+ setupComputeService(serviceDomain = "compute.opendc.org", { computeScheduler }),
+ registerComputeMonitor(serviceDomain = "compute.opendc.org", monitor),
+ setupHosts(serviceDomain = "compute.opendc.org", topology)
+ )
+
+ val service = provisioner.registry.resolve("compute.opendc.org", ComputeService::class.java)!!
+ service.replay(timeSource, workload, seed, interference = true)
+ }
+
+ println(
+ "Scheduler " +
+ "Success=${monitor.attemptsSuccess} " +
+ "Failure=${monitor.attemptsFailure} " +
+ "Error=${monitor.attemptsError} " +
+ "Pending=${monitor.serversPending} " +
+ "Active=${monitor.serversActive}"
+ )
+
+ // Note that these values have been verified beforehand
+ assertAll(
+ { assertEquals(6028018, monitor.idleTime) { "Idle time incorrect" } },
+ { assertEquals(14712781, monitor.activeTime) { "Active time incorrect" } },
+ { assertEquals(12532934, monitor.stealTime) { "Steal time incorrect" } },
+ { assertEquals(424267, monitor.lostTime) { "Lost time incorrect" } }
+ )
+ }
+
+ /**
+ * Test a small simulation setup with failures.
+ */
+ @Test
+ fun testFailures() = runSimulation {
+ val seed = 0L
+ val topology = createTopology("single")
+ val workload = createTestWorkload(0.25, seed)
+ val monitor = monitor
+
+ Provisioner(dispatcher, seed).use { provisioner ->
+ provisioner.runSteps(
+ setupComputeService(serviceDomain = "compute.opendc.org", { computeScheduler }),
+ registerComputeMonitor(serviceDomain = "compute.opendc.org", monitor),
+ setupHosts(serviceDomain = "compute.opendc.org", topology)
+ )
+
+ val service = provisioner.registry.resolve("compute.opendc.org", ComputeService::class.java)!!
+ service.replay(timeSource, workload, seed, failureModel = grid5000(Duration.ofDays(7)))
+ }
+
+ // Note that these values have been verified beforehand
+ assertAll(
+ { assertEquals(10085111, monitor.idleTime) { "Idle time incorrect" } },
+ { assertEquals(8539204, monitor.activeTime) { "Active time incorrect" } },
+ { assertEquals(0, monitor.stealTime) { "Steal time incorrect" } },
+ { assertEquals(0, monitor.lostTime) { "Lost time incorrect" } },
+ { assertEquals(2328039558, monitor.uptime) { "Uptime incorrect" } }
+ )
+ }
+
+ /**
+ * Obtain the trace reader for the test.
+ */
+ private fun createTestWorkload(fraction: Double, seed: Long): List<VirtualMachine> {
+ val source = trace("bitbrains-small").sampleByLoad(fraction)
+ return source.resolve(workloadLoader, Random(seed))
+ }
+
+ /**
+ * Obtain the topology factory for the test.
+ */
+ private fun createTopology(name: String = "topology"): List<HostSpec> {
+ val stream = checkNotNull(object {}.javaClass.getResourceAsStream("/env/$name.txt"))
+ return stream.use { clusterTopology(stream) }
+ }
+
+ class TestComputeMonitor : ComputeMonitor {
+ var attemptsSuccess = 0
+ var attemptsFailure = 0
+ var attemptsError = 0
+ var serversPending = 0
+ var serversActive = 0
+
+ override fun record(reader: ServiceTableReader) {
+ attemptsSuccess = reader.attemptsSuccess
+ attemptsFailure = reader.attemptsFailure
+ attemptsError = reader.attemptsError
+ serversPending = reader.serversPending
+ serversActive = reader.serversActive
+ }
+
+ var idleTime = 0L
+ var activeTime = 0L
+ var stealTime = 0L
+ var lostTime = 0L
+ var energyUsage = 0.0
+ var uptime = 0L
+
+ override fun record(reader: HostTableReader) {
+ idleTime += reader.cpuIdleTime
+ activeTime += reader.cpuActiveTime
+ stealTime += reader.cpuStealTime
+ lostTime += reader.cpuLostTime
+ energyUsage += reader.powerTotal
+ uptime += reader.uptime
+ }
+ }
+}
diff --git a/opendc-experiments/opendc-experiments-greenifier/src/test/kotlin/org/opendc/experiments/capelin/GreenifierRunnerTest.kt b/opendc-experiments/opendc-experiments-greenifier/src/test/kotlin/org/opendc/experiments/capelin/GreenifierRunnerTest.kt
new file mode 100644
index 00000000..b6e361d7
--- /dev/null
+++ b/opendc-experiments/opendc-experiments-greenifier/src/test/kotlin/org/opendc/experiments/capelin/GreenifierRunnerTest.kt
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2022 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.experiments.greenifier
+
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.assertDoesNotThrow
+import org.opendc.experiments.greenifier.model.OperationalPhenomena
+import org.opendc.experiments.greenifier.model.Scenario
+import org.opendc.experiments.greenifier.model.Topology
+import org.opendc.experiments.greenifier.model.Workload
+import org.opendc.experiments.compute.trace
+import java.io.File
+import java.nio.file.Files
+
+/**
+ * Test suite for [GreenifierRunner].
+ */
+class GreenifierRunnerTest {
+ /**
+ * The path to the environments.
+ */
+ private val envPath = File("src/test/resources/env")
+
+ /**
+ * The path to the traces.
+ */
+ private val tracePath = File("src/test/resources/trace")
+
+ /**
+ * Smoke test with output.
+ */
+ @Test
+ fun testSmoke() {
+ val outputPath = Files.createTempDirectory("output").toFile()
+
+ try {
+ val runner = GreenifierRunner(envPath, tracePath, outputPath)
+ val scenario = Scenario(
+ Topology("topology"),
+ Workload("bitbrains-small", trace("bitbrains-small")),
+ OperationalPhenomena(failureFrequency = 24.0 * 7, hasInterference = true),
+ "active-servers"
+ )
+
+ assertDoesNotThrow { runner.runScenario(scenario, seed = 0L) }
+ } finally {
+ outputPath.delete()
+ }
+ }
+
+ /**
+ * Smoke test without output.
+ */
+ @Test
+ fun testSmokeNoOutput() {
+ val runner = GreenifierRunner(envPath, tracePath, null)
+ val scenario = Scenario(
+ Topology("topology"),
+ Workload("bitbrains-small", trace("bitbrains-small")),
+ OperationalPhenomena(failureFrequency = 24.0 * 7, hasInterference = true),
+ "active-servers"
+ )
+
+ assertDoesNotThrow { runner.runScenario(scenario, seed = 0L) }
+ }
+}
diff --git a/opendc-experiments/opendc-experiments-greenifier/src/test/resources/env/single.txt b/opendc-experiments/opendc-experiments-greenifier/src/test/resources/env/single.txt
new file mode 100644
index 00000000..5642003d
--- /dev/null
+++ b/opendc-experiments/opendc-experiments-greenifier/src/test/resources/env/single.txt
@@ -0,0 +1,3 @@
+ClusterID;ClusterName;Cores;Speed;Memory;numberOfHosts;memoryCapacityPerHost;coreCountPerHost
+A01;A01;8;3.2;128;1;128;8
+
diff --git a/opendc-experiments/opendc-experiments-greenifier/src/test/resources/env/topology.txt b/opendc-experiments/opendc-experiments-greenifier/src/test/resources/env/topology.txt
new file mode 100644
index 00000000..6b347bff
--- /dev/null
+++ b/opendc-experiments/opendc-experiments-greenifier/src/test/resources/env/topology.txt
@@ -0,0 +1,5 @@
+ClusterID;ClusterName;Cores;Speed;Memory;numberOfHosts;memoryCapacityPerHost;coreCountPerHost
+A01;A01;32;3.2;2048;1;256;32
+B01;B01;48;2.93;1256;6;64;8
+C01;C01;32;3.2;2048;2;128;16
+
diff --git a/opendc-experiments/opendc-experiments-greenifier/src/test/resources/trace/bitbrains-small/interference-model.json b/opendc-experiments/opendc-experiments-greenifier/src/test/resources/trace/bitbrains-small/interference-model.json
new file mode 100644
index 00000000..51fc6366
--- /dev/null
+++ b/opendc-experiments/opendc-experiments-greenifier/src/test/resources/trace/bitbrains-small/interference-model.json
@@ -0,0 +1,21 @@
+[
+ {
+ "vms": [
+ "141",
+ "379",
+ "851",
+ "116"
+ ],
+ "minServerLoad": 0.0,
+ "performanceScore": 0.8830158730158756
+ },
+ {
+ "vms": [
+ "205",
+ "116",
+ "463"
+ ],
+ "minServerLoad": 0.0,
+ "performanceScore": 0.7133055555552751
+ }
+]
diff --git a/opendc-experiments/opendc-experiments-greenifier/src/test/resources/trace/bitbrains-small/meta.parquet b/opendc-experiments/opendc-experiments-greenifier/src/test/resources/trace/bitbrains-small/meta.parquet
new file mode 100644
index 00000000..9cded35f
--- /dev/null
+++ b/opendc-experiments/opendc-experiments-greenifier/src/test/resources/trace/bitbrains-small/meta.parquet
Binary files differ
diff --git a/opendc-experiments/opendc-experiments-greenifier/src/test/resources/trace/bitbrains-small/trace.parquet b/opendc-experiments/opendc-experiments-greenifier/src/test/resources/trace/bitbrains-small/trace.parquet
new file mode 100644
index 00000000..9d953956
--- /dev/null
+++ b/opendc-experiments/opendc-experiments-greenifier/src/test/resources/trace/bitbrains-small/trace.parquet
Binary files differ