summaryrefslogtreecommitdiff
path: root/opendc-harness/opendc-harness-cli
diff options
context:
space:
mode:
authorFabian Mastenbroek <mail.fabianm@gmail.com>2021-05-04 20:31:48 +0200
committerFabian Mastenbroek <mail.fabianm@gmail.com>2021-05-05 10:03:18 +0200
commit6466d5e1b8da4582434f02dff2ab56e8f736ef85 (patch)
treee8c8e6b96c7abdd80fa0a3198da5776488cd06fe /opendc-harness/opendc-harness-cli
parent4a8b32d288ba3ee986ecef7933fa77554d34e762 (diff)
harness: Extend Harness CLI with classpath options
This change adds support for appending libraries to the classpath when searching for experiments to run using the OpenDC Harness command line interface.
Diffstat (limited to 'opendc-harness/opendc-harness-cli')
-rw-r--r--opendc-harness/opendc-harness-cli/build.gradle.kts6
-rw-r--r--opendc-harness/opendc-harness-cli/src/main/kotlin/org/opendc/harness/runner/cli/ConsoleRunner.kt56
2 files changed, 57 insertions, 5 deletions
diff --git a/opendc-harness/opendc-harness-cli/build.gradle.kts b/opendc-harness/opendc-harness-cli/build.gradle.kts
index 26f02f55..3e169e2a 100644
--- a/opendc-harness/opendc-harness-cli/build.gradle.kts
+++ b/opendc-harness/opendc-harness-cli/build.gradle.kts
@@ -25,6 +25,12 @@ description = "Command line interface of OpenDC Harness"
/* Build configuration */
plugins {
`kotlin-library-conventions`
+ application
+}
+
+application {
+ applicationName = "opendc-harness"
+ mainClass.set("org.opendc.harness.runner.cli.ConsoleRunnerKt")
}
dependencies {
diff --git a/opendc-harness/opendc-harness-cli/src/main/kotlin/org/opendc/harness/runner/cli/ConsoleRunner.kt b/opendc-harness/opendc-harness-cli/src/main/kotlin/org/opendc/harness/runner/cli/ConsoleRunner.kt
index c59e623c..82adb2fd 100644
--- a/opendc-harness/opendc-harness-cli/src/main/kotlin/org/opendc/harness/runner/cli/ConsoleRunner.kt
+++ b/opendc-harness/opendc-harness-cli/src/main/kotlin/org/opendc/harness/runner/cli/ConsoleRunner.kt
@@ -23,16 +23,23 @@
package org.opendc.harness.runner.cli
import com.github.ajalt.clikt.core.CliktCommand
+import com.github.ajalt.clikt.parameters.arguments.argument
+import com.github.ajalt.clikt.parameters.arguments.multiple
+import com.github.ajalt.clikt.parameters.arguments.unique
import com.github.ajalt.clikt.parameters.options.default
import com.github.ajalt.clikt.parameters.options.multiple
import com.github.ajalt.clikt.parameters.options.option
+import com.github.ajalt.clikt.parameters.options.unique
+import com.github.ajalt.clikt.parameters.types.file
import com.github.ajalt.clikt.parameters.types.int
import mu.KotlinLogging
+import org.junit.platform.commons.util.ClassLoaderUtils
import org.opendc.harness.engine.ExperimentEngineLauncher
import org.opendc.harness.engine.discovery.DiscoveryProvider
import org.opendc.harness.engine.discovery.DiscoveryRequest
import org.opendc.harness.engine.discovery.DiscoverySelector
import org.opendc.harness.engine.scheduler.ThreadPoolExperimentScheduler
+import java.net.URLClassLoader
/**
* The logger for this experiment runner.
@@ -53,23 +60,38 @@ public class ConsoleRunner : CliktCommand(name = "opendc-harness") {
/**
* The selected experiments to run by name.
*/
- private val experiments by option("-e", "--experiments", help = "Names of experiments to explore")
- .multiple(emptyList())
+ private val experiments by argument(help = "Experiments to explore")
+ .multiple()
+ .unique()
/**
* The maximum number of worker threads to use.
*/
private val parallelism by option("-p", "--parallelism", help = "Maximum number of concurrent simulation runs")
.int()
- .default(Runtime.getRuntime().availableProcessors())
+ .default(Runtime.getRuntime().availableProcessors() - 1)
+
+ /**
+ * Additional classpath entries to load.
+ */
+ private val additionalClasspathEntries by option("--class-path", help = "Additional classpath entries to load")
+ .file(mustExist = true)
+ .multiple()
+ .unique()
override fun run() {
logger.info { "Starting OpenDC Console Experiment Runner" }
- val discovery = DiscoveryProvider.createComposite()
+ val classLoader = createClassLoader()
+ // TODO: Add way to specify class loader for scheduler
+ Thread.currentThread().contextClassLoader = classLoader
+
+ val discovery = DiscoveryProvider.createComposite(classLoader)
val experiments = discovery.discover(
DiscoveryRequest(
- selectors = experiments.map { DiscoverySelector.Name(it) }
+ selectors = experiments.flatMap {
+ listOf(DiscoverySelector.Name(it), DiscoverySelector.Meta("class.name", it))
+ }
)
)
@@ -91,6 +113,30 @@ public class ConsoleRunner : CliktCommand(name = "opendc-harness") {
logger.info { "Finished all experiments. Exiting." }
}
+
+ /**
+ * Create a [ClassLoader] that is used to load the
+ */
+ private fun createClassLoader(): ClassLoader {
+ val parent = ClassLoaderUtils.getDefaultClassLoader()
+
+ if (additionalClasspathEntries.isNotEmpty()) {
+ val urls = additionalClasspathEntries.flatMap { file ->
+ if (file.isDirectory) {
+ file.walk()
+ .filter { it.extension == "jar" }
+ .map { it.toURI().toURL() }
+ .toList()
+ } else {
+ listOf(file.toURI().toURL())
+ }
+ }
+
+ return URLClassLoader.newInstance(urls.toTypedArray(), parent)
+ }
+
+ return parent
+ }
}
/**