Commit 82861fea by Tomasz Ciesielczyk

some management improvements

parent 529268b2
......@@ -23,7 +23,7 @@ abstract class RTMAlgorithm(currentState: CurrentState) {
fun saveState() {
if (Keys.RTM.dump_current_state.getBoolean()) {
nextDumpIndex?.let {idx->
this.state.toJson(RTMProperties.parsePath("${RTMProperties.basePath}/${this::class.java.simpleName}_$idx.dmp").toString())
this.state.toJson(RTMProperties.parsePath("${RTMProperties.basePath}/dmp/${this::class.java.simpleName}_$idx.dmp").toString())
}?: logWarn("invalid dump dump_current_state_count: ${ Keys.RTM.dump_current_state_count}")
}
......
......@@ -35,7 +35,7 @@ repositories {
jar {
manifest {
attributes 'Main-Class': 'psnc.m2dc.rtm.RTMApiKt'
attributes 'Main-Class': 'psnc.m2dc.rtm.RTMServerApiKt'
}
exclude 'META-INF/*.RSA', 'META-INF/*.SF','META-INF/*.DSA'
}
......@@ -69,7 +69,7 @@ task publishJar(type: Jar) {
manifest {
attributes 'Implementation-Title': 'Gradle Jar File Example',
'Implementation-Version': version,
'Main-Class': 'psnc.m2dc.rtm.RTMApiKt'
'Main-Class': 'psnc.m2dc.rtm.RTMServerApiKt'
}
baseName = 'rtm-server'
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
......
......@@ -61,18 +61,37 @@ object ServerConfInitializer {
RECSApiImpl.Instance.loadRECSHosts().forEach {
params.add("-h");params.add(it)
}
val result = runScript("bin/get_recs_nodes.sh", params, true)
val result = runScript("bin/get_recs_nodes.sh", params, debug = true)
val lines = result.split("\n")
val nodeData = File("resource_map.data").loadDataTable()
var nodeData = File("resource_map.data").loadDataTable()
lines.forEach {
it.split(";").let {
nodeData[it[0]]?.set("recs_id", it[1])
}
}
//filter node data
nodeData = nodeData.filter { nodeRow ->
nodeRow.value["is_active"] ?: "0" == "1"
}
if (Keys.SSHHosts.host_filter.getNullable() != null) {
if (!File(Keys.SSHHosts.host_filter.get()).exists()) {
throw IllegalArgumentException("Inappropriate host filter configuration")
}
val timeout = 10000L * nodeData.size
val sshFilter = runScript(Keys.SSHHosts.host_filter.get(), timeout = timeout).split("\n").map {
it.split(" ")[0]
}.toList()
nodeData = nodeData.filter {
val host = it.value["ssh_host"]
!(host == null || sshFilter.contains(host))
}
}
val resources = nodeData.filter { nodeRow ->
nodeRow.value["is_active"] ?: "0" == "1"
}.map { nodeRow ->
}.mapNotNull { nodeRow ->
val cells = nodeRow.value
val nodeId = cells["node_id"]!!
val typeId = cells["type_id"]!!
......@@ -92,7 +111,7 @@ object ServerConfInitializer {
}
private val installProperties = listOf("RAPL")
private fun install(resource: Resource): Resource {
private fun install(resource: Resource): Resource? {
val params = mutableListOf<String>()
resource.get("ssh_host")?.let { params.add("-h");params.add(it) }
......@@ -104,9 +123,13 @@ object ServerConfInitializer {
}
}
runScript("bin/install_node.sh", params, true)
return resource
return try {
runScript("bin/install_node.sh", params, debug = true)
resource
} catch (e: Exception) {
logError("Cannot install: ${resource.id}, cause:${e.message}")
null
}
}
......
package psnc.m2dc.rtm.commands.java
val APP_VERSION = "1.0.624_58959"
\ No newline at end of file
val APP_VERSION = "1.0.631_57738"
\ No newline at end of file
......@@ -30,6 +30,7 @@ fun main(args: Array<String>) {
// CommandLine.populateCommand(cmd, *args)
CommandLine.run(cmd, *arguments)
} catch (e: Exception) {
e.printStackTrace()
logError(e, "Command not executed:")
logDebug("stacktrace:\t ${e.stackTrace.joinToString(separator = "\n")}")
// RTMProperties.storage.save()
......
package psnc.m2dc.rtm.client
const val APP_VERSION = "1.1.624_58959"
\ No newline at end of file
const val APP_VERSION = "1.1.631_57738"
\ No newline at end of file
......@@ -75,7 +75,7 @@ object ConfigurationGenerator {
// }
private fun <T> generate(printer: Printer<T>): T {
Keys.initializeKeys()
val sectionMap = Keys::class.declaredMemberProperties.filter { it.visibility == KVisibility.PUBLIC }.map {
it.name.toLowerCase() to it
}.toMap()
......
......@@ -80,6 +80,7 @@ class ResourceDAO(val storage: TreeStorage) {
return true
}
fun getResources(): HashMap<String, Resource> {
val obj = LightStorage.getObjectTree("resources")
?: throw NullPointerException("Resource has not been loaded")
......@@ -102,11 +103,6 @@ class ResourceDAO(val storage: TreeStorage) {
fun getNodes(): Map<String, Resource> {
val obj = LightStorage.getObjectsTree("nodes")
return LightStorage.convert<Resource>(obj).map { it.id to it }.toMap()
// ?: throw IllegalArgumentException("Resources parse error")
// return this.getResources().filter {
// //only nodes
// it.value.get(Resource.Property.is_node, true)
// }
}
......
......@@ -9,6 +9,7 @@ import psnc.m2dc.rtm.rpm.nativeapi.RECSApiImpl
import psnc.m2dc.rtm.rpm.nativeapi.RECSMonitoringApi
import psnc.m2dc.rtm.utils.*
import psnc.m2dc.rtm.utils.Timer
import java.io.File
import java.util.*
import java.util.concurrent.Future
import java.util.concurrent.TimeUnit
......@@ -87,33 +88,45 @@ class ResourceManager : DataDAO() {
val srcList = Keys.RTM.resources_src_list.get()
printConsole(srcList.toJson())
val orderedSourceList = listOf("RECS", "JSON", "FILE")
// val resources = HashMap<String, Resource>()
orderedSourceList.forEach { src ->
if (srcList.contains(src)) {
loadResources(src).filter {
val filteredNodes = loadResources(src).filter {
(!Keys.TestBed.filter_nodes.get() ||
Keys.TestBed.resource_list.getNullable()?.contains(it.key) ?: false)
}.forEach { loaded ->
}
filteredNodes.forEach { loaded ->
loaded.value.get(Resource.Property.is_node, true)
loaded.value.saveIndex(nodeIndex, "resources", loaded.key)
//child resources
// if (Keys.RTM.load_node_children.get()) {
// logInfo("Load child resources for${loaded.key}")
// this.loadChildResources(loaded.value).forEach { child ->
// if ((DAO.Resource.getParentId(child.value.id)?.equals(loaded.value.id)) == false) {
// throw IllegalStateException(
// "Duplicate child for: ${loaded.value.id} -> child:${child.value.id}:${child.value.parentId}!")
// }
// loaded.value.get(Resource.Property.is_node, true)
// loaded.value.saveIndex(nodeIndex, "resources", loaded.key)
// DAO.Resource.addChild(loaded.value.id, child.value.id)
// }
// }
}
}
}
logDebug("""resource List before ssh filter: ${DAO.Resource.getNodes().keys.joinToString(separator = "\n", prefix = "\n") { it }}""")
if (Keys.SSHHosts.require_ssh.get()) {
if (Keys.SSHHosts.host_filter.getNullable() == null || !File(Keys.SSHHosts.host_filter.get()).exists()) {
throw IllegalArgumentException("Inappropriate host filter configuration")
}
val l = DAO.Resource.getNodes().keys
val timeout = 10000L * l.size
val filter = runScript(Keys.SSHHosts.host_filter.get(), timeout = timeout).split("\n").map {
it.split(" ")[0]
}.toList()
l.forEach { resourceId ->
val host = DAO.Resource.getRemoteApiEndpoint(ManagementApi.ssh, resourceId)
if (host == null || filter.contains(host)) {
LightStorage.instance.delete("resources", resourceId)
}
}
}
logInfo("""resource List after ssh filter: ${DAO.Resource.getNodes().keys.joinToString(separator = "\n", prefix = "\n") { it }}""")
}
......@@ -162,52 +175,6 @@ class ResourceManager : DataDAO() {
}
// private fun loadChildResources(resource: Resource): HashMap<String, Resource> {
// logDebug("Loading child resources for: ${resource.id}")
// val res = HashMap<String, Resource>()
// try {
// if (resource.childResources == null) resource.childResources = ArrayList()
// val type = this.getResourceType(resource)
// type.apiMap[ApiType.sub_component]?.firstOrNull()?.let { apiDetails ->
// when (apiDetails.api) {
// ManagementApi.ssh -> SSHApiImpl.init(resource).getChildResources().let {
// it.forEach { child ->
// child.put(Resource.Property.is_node, false)
// child.put(Resource.Property.node_id, resource.id)
//// val currentChild = resource.childResources?.find { it.id == child.id }
//// if (currentChild == null) {
//// resource.childResources?.add(child)
//// } else {
//// currentChild.extend(child)
//// }
// }
// it
// }.forEach { child ->
// res[child.id] = child
// child.getChildren().values.forEach { subchild ->
// //TODO: rekurencyjnie
// subchild.put(Resource.Property.is_node, false)
// subchild.put(Resource.Property.node_id, resource.id)
// res[subchild.id] = subchild
// }
// }
// else -> {
// logError("Resource source(${apiDetails.api}) not supported")
// throw IllegalArgumentException("src:${apiDetails.api} not found")
// }
// }
// }
// } catch (e: Exception) {
// logError("${e.message}")
// e.printStackTrace()
// return HashMap()
// }
// setParentNodeId(res)
// // printConsole(res.toJson(), false)
// return res
//
//
// }
private fun loadRecsResources(): HashMap<String, Resource> {
return try {
......@@ -493,3 +460,15 @@ class ResourceManager : DataDAO() {
// })
// return r
// }
// if (Keys.RTM.load_node_children.get()) {
// logInfo("Load child resources for${loaded.key}")
// this.loadChildResources(loaded.value).forEach { child ->
// if ((DAO.Resource.getParentId(child.value.id)?.equals(loaded.value.id)) == false) {
// throw IllegalStateException(
// "Duplicate child for: ${loaded.value.id} -> child:${child.value.id}:${child.value.parentId}!")
// }
// loaded.value.get(Resource.Property.is_node, true)
// loaded.value.saveIndex(nodeIndex, "resources", loaded.key)
// DAO.Resource.addChild(loaded.value.id, child.value.id)
// }
// }
\ No newline at end of file
......@@ -12,10 +12,7 @@ import org.apache.commons.configuration2.builder.fluent.Configurations
import org.apache.log4j.PropertyConfigurator
import org.slf4j.LoggerFactory
import psnc.m2dc.rtm.properties.keys.Keys
import psnc.m2dc.rtm.utils.FileUtils
import psnc.m2dc.rtm.utils.logDebug
import psnc.m2dc.rtm.utils.logError
import psnc.m2dc.rtm.utils.printConsole
import psnc.m2dc.rtm.utils.*
import java.io.BufferedReader
import java.io.File
import java.io.FileReader
......@@ -46,13 +43,12 @@ class RTMProperties {
}
/**
* path to ini file
*/
fun init(path: String) {
try {
log.debug("Init properties:${path}")
logInfo("Init properties:${path}")
val configurations = Configurations()
val parsedPath = parseParam(path) ?: ""
......@@ -63,7 +59,8 @@ class RTMProperties {
basePath = p.toAbsolutePath().parent.toString()
// printConsole(basePath+ " dd")
conf = configurations.ini(p.toString())
val confDirPath=conf.getString("Default.configuration_dir_path")?:"$basePath${File.separator}conf${File.separator}additional"
val confDirPath = conf.getString("Default.configuration_dir_path")
?: "$basePath${File.separator}conf${File.separator}additional"
if (File("$basePath${File.separator}conf${File.separator}additional").exists())
FileUtils.listFiles(confDirPath, ".conf").forEach { it ->
var c = Configurations().ini("$confDirPath${File.separator}$it")
......@@ -237,6 +234,7 @@ class RTMProperties {
if (i == 0) {
sb.append(param.substring(0, it.range.start))
}
when (it.value) {
"$[basePath]" -> sb.append(this.basePath)
"$[null]" -> return null
......
......@@ -31,11 +31,11 @@ class RTM {
val ipmi_user = RTMProperty(RTM + "ipmi_user", null, String::class.java)
val ipmi_password = RTMProperty(RTM + "ipmi_password", null, String::class.java)
val default_ssh_user = RTMProperty(RTM + "default_ssh_user", null, String::class.java)
val model_map_directory = RTMProperty(RTM + "model_map_directory", "\$[basePath]/models",
val model_map_directory = RTMProperty(RTM + "model_map_directory", "$[basePath]/models",
String::class.java)
val notification_endpoint = RTMProperty(RTM + "notification_endpoint", null, String::class.java, description = "Notify about actions")
val model_map_file = RTMProperty(RTM + "model_map_file", " \$[basePath]/models/model_map.txt ", String::class.java)
val model_map_file = RTMProperty(RTM + "model_map_file", "\$[basePath]/models/model_map.txt", String::class.java)
val resource_type_map = RTMMapProperty(RTM + "resource_type_map", GenericTypeMapWrapper.get<ResourceType>(ResourceTypeMapWrapperInstance), "\$[file]\$[basePath]/models/type.map.json")
val scan_timeout_ms = RTMProperty(RTM + "scan_timeout_ms", 60000L)
......
......@@ -3,7 +3,7 @@ package psnc.m2dc.rtm.properties.keys
import psnc.m2dc.rtm.properties.RTMProperty
/**
*
*
* Created by Tomek on 2018-01-09.
*/
class SSHHosts {
......@@ -14,12 +14,16 @@ class SSHHosts {
return description
}
val default_host = RTMProperty(SSH_HOSTS + "default_host",
null)
// val default_host = RTMProperty(SSH_HOSTS + "default_host",
// null)
val host_filter = RTMProperty(SSH_HOSTS + "host_filter",
"\$[basePath]/bin/ssh_host_filter.sh", description = "Host filter executable, output: each line consists of filtered host details separated with 'space' where first field is host")
val require_ssh = RTMProperty(SSH_HOSTS + "require_ssh",
false, description = "True - filter nodes without ssh connection, False - no filter is applied")
fun get(nodeId: String): String? {
return RTMProperty(SSH_HOSTS + nodeId,
default_host.getNullable()).getNullable()
return RTMProperty(SSH_HOSTS + nodeId,null).getNullable()
}
// ssh_host_filter.sh
}
\ No newline at end of file
......@@ -288,6 +288,7 @@ class RPMApiImpl : RPMApi {
get power usage of specific nodes
*/
override fun getPowerUsageList(): HashMap<String, Double> {
logDebug("getPowerUsageList")
val result = HashMap<String, Double>()
DAO.ResourcesManagerApi.getPowerUsage().forEach { resourceId, usage ->
try {
......
......@@ -37,6 +37,7 @@ class RECSMonitoringApi private constructor(/*storage: IStorage<String>? = null*
logInfo("RECS: get nodes from: $hosts")
val l = ArrayList<Resource>()
d
/**
* resources to update via ssh api
*/
......
......@@ -46,17 +46,12 @@ fun logDebug(e: Exception, msg: String) {
RTMProperties.log.debug(e::class.java.simpleName + "(" + e.stackTrace[0].lineNumber + ")" + ": " + msg + e.message)
}
fun logDebug(msg: String, trimMessage: Boolean = true) {
fun logDebug(msg: String, trimMessage: Boolean = true, msgLength: Int = _MSG_MAX_LENGTH) {
val i = Throwable().stackTrace[2]
val trimmed = if (trimMessage && msg.length > _MSG_MAX_LENGTH + 1) msg.substring(0,
_MSG_MAX_LENGTH) else msg
val m = if (trimMessage) msg.take(msgLength) else msg
if (_PRINT_DEBUG)
println("${parseDate(Date())}:[DEBUG]:${i.className}-${i.methodName}(${i.fileName}:${i.lineNumber}): $trimmed")
// val result = "${parseDate(Date())}:${i.className}-${i.methodName}(${i.fileName}:${i.lineNumber}): ${_msg}"
RTMProperties.log.debug("${parseDate(Date())}:${i.className}-${i.methodName}(${i.fileName}:${i.lineNumber}): $trimmed")
println("${parseDate(Date())}:[DEBUG]:${i.className}-${i.methodName}(${i.fileName}:${i.lineNumber}): $m")
RTMProperties.log.debug("${parseDate(Date())}:${i.className}-${i.methodName}(${i.fileName}:${i.lineNumber}): $m")
}
fun logError(log: Logger, msg: String, trimMessage: Boolean = false) {
......@@ -125,6 +120,7 @@ fun Any.toJsonObj(): JsonElement {
fun Any.toJson(path: String) {
val f = File(path)
File(f.parent).iF({ !it.exists() }, { it.mkdirs() })
f.writeText(RTMProperties.JSONParser.toJson(this))
}
......@@ -133,6 +129,7 @@ fun Any.toJson(path: String, pretty: Boolean = true) {
return this.toJson(path)
}
val f = File(path)
File(f.parent).iF({ !it.exists() }, { it.mkdirs() })
val g = GsonBuilder().setPrettyPrinting().create()
f.writeText(g.toJson(this))
}
......@@ -295,7 +292,7 @@ fun File.loadDataTable(separator: String = "\t", idIndex: Int = 0, headers: List
// logDebug(this.exists().toString())
// logDebug(this.readText())
this.forEachLine { line ->
logDebug(line)
// logDebug(line)
if (mHeaders == null) {
// logDebug(line.split(separator).toJson())
mHeaders = line.split(separator)
......@@ -345,6 +342,7 @@ fun generateBindToml(data: Map<String, Map<String, String>>, user: String = "tom
val hId = "h$idx"
val bindStr = """
[bind.$hId]
#${m["host"]} - ${m["model"]}}
monitor = "default_monitor"
launch = "default_launch"
launch-interval = 30
......@@ -368,3 +366,8 @@ fun generateBindToml(data: Map<String, Map<String, String>>, user: String = "tom
return hostSection + other + bindSection
}
fun <T, R> T.iF(condition: (T) -> Boolean, block: (T) -> R) {
if (condition(this)) block(this)
}
......@@ -14,7 +14,7 @@ import java.util.concurrent.TimeUnit
*/
const val MAX_SCRIPT_EXECUTION_TIME = 60000L
private fun getOutput(process: Process, stdOut: StringBuilder, stdErr: StringBuilder): Pair<Any, Any> {
private fun getOutput(process: Process, stdOut: StringBuilder, stdErr: StringBuilder, timeout: Long = MAX_SCRIPT_EXECUTION_TIME): Pair<Any, Any> {
val newFixedThreadPool = Executors.newFixedThreadPool(2)
......@@ -41,14 +41,15 @@ private fun getOutput(process: Process, stdOut: StringBuilder, stdErr: StringBui
newFixedThreadPool.shutdown()
// process.waitFor();
if (!process.waitFor(MAX_SCRIPT_EXECUTION_TIME, TimeUnit.MILLISECONDS)) {
if (!process.waitFor(timeout, TimeUnit.MILLISECONDS)) {
logError("script execution timeout")
process.destroy()
}
return Pair(output.get(), error.get())
}
fun runScript(scriptName: String, params: List<String> = ArrayList(), debug: Boolean = false): String {
fun runScript(scriptName: String, params: List<String> = ArrayList(), timeout: Long = MAX_SCRIPT_EXECUTION_TIME, debug: Boolean = false): String {
val stdOut = StringBuilder()
......@@ -62,28 +63,32 @@ fun runScript(scriptName: String, params: List<String> = ArrayList(), debug: Boo
}
p = Runtime.getRuntime().exec(array)
// printConsole("pwait for : ${cmd.host}")
getOutput(p, stdOut, stdErr)//.toJson(true)
getOutput(p, stdOut, stdErr, timeout)//.toJson(true)
if (!stdOut.isEmpty() && Keys.Default.debug.get()) {
logDebug(stdOut.toString())
logDebug(stdOut.toString(), msgLength = 128)
}
if (!stdErr.isEmpty()) {
logError(stdErr.toString())
// logError(stdErr.toString())
if (!stdOut.isEmpty() && Keys.Default.debug.get()) {
logDebug(stdOut.toString(), msgLength = 128)
}
throw Exception(stdErr.toString())
}
} catch (e: Exception) {
when (e) {
is IOException, is InterruptedException -> {
logError("Script execution error" + e.message)
logError("Script execution error:" + e.message)
throw Exception(e)
}
}
throw Exception(e)
}
logDebug(stdOut.toString())
// logDebug(stdOut.toString(),msgLength = 128)
// printConsole("output for ${cmd.host} :$stdOut")
return if (!stdOut.isEmpty()) stdOut.toString() else
stdErr.toString().trim().let { logError("script execution error: $scriptName :$it"); it }
return if (!stdOut.isEmpty() || stdErr.isEmpty()) stdOut.toString() else
stdErr.toString().trim().let { logError("script execution error: $scriptName :[$it]"); throw Exception(it) }
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment