iota-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From tonyfaust...@apache.org
Subject [1/2] incubator-iota git commit: Implementing first version of Fey - [IOTA-2] [IOTA-3] [IOTA-4] [IOTA-5] [IOTA-6] [IOTA-7] [IOTA-8] [IOTA-9] [IOTA-10] [IOTA-11] [IOTA-12] [IOTA-13] [IOTA-14] [IOTA-15]
Date Fri, 01 Jul 2016 21:55:36 GMT
Repository: incubator-iota
Updated Branches:
  refs/heads/master 407f0d5c7 -> 10042354c


http://git-wip-us.apache.org/repos/asf/incubator-iota/blob/10042354/fey-core/src/main/scala/org/apache/iota/fey/MyService.scala
----------------------------------------------------------------------
diff --git a/fey-core/src/main/scala/org/apache/iota/fey/MyService.scala b/fey-core/src/main/scala/org/apache/iota/fey/MyService.scala
new file mode 100644
index 0000000..3987340
--- /dev/null
+++ b/fey-core/src/main/scala/org/apache/iota/fey/MyService.scala
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.iota.fey
+
+import akka.actor.Actor
+import org.apache.iota.fey.FeyCore.JSON_TREE
+import spray.http.MediaTypes._
+import spray.routing._
+
+class MyServiceActor extends Actor with MyService {
+
+  // the HttpService trait defines only one abstract member, which
+  // connects the services environment to the enclosing actor or test
+  def actorRefFactory = context
+
+  // this actor only runs our route, but you could add
+  // other things here, like request stream processing
+  // or timeout handling
+  def receive = runRoute(myRoute)
+}
+
+sealed trait MyService extends HttpService {
+
+  val home = pathPrefix("fey")
+  val activeActors = path("activeactors")
+  val test = path("test")
+
+  val myRoute =
+    home {
+      activeActors {
+        get{
+          respondWithMediaType(`text/html`) {
+            complete {
+              Application.fey ! JSON_TREE
+              Thread.sleep(2000)
+              val json = IdentifyFeyActors.generateTreeJson()
+              IdentifyFeyActors.getHTMLTree(json)
+            }
+          }
+        }
+      }
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-iota/blob/10042354/fey-core/src/main/scala/org/apache/iota/fey/Orchestration.scala
----------------------------------------------------------------------
diff --git a/fey-core/src/main/scala/org/apache/iota/fey/Orchestration.scala b/fey-core/src/main/scala/org/apache/iota/fey/Orchestration.scala
new file mode 100644
index 0000000..76a8e9f
--- /dev/null
+++ b/fey-core/src/main/scala/org/apache/iota/fey/Orchestration.scala
@@ -0,0 +1,242 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.iota.fey
+
+import akka.actor.SupervisorStrategy.Restart
+import akka.actor.{Actor, ActorLogging, ActorRef, OneForOneStrategy, PoisonPill, Props, Terminated}
+import org.apache.iota.fey.FeyCore.STOP_EMPTY_ORCHESTRATION
+import play.api.libs.json._
+
+import scala.concurrent.duration._
+import scala.collection.mutable.HashMap
+
+protected class Orchestration(val name: String,
+                      val guid: String,
+                      val timestamp: String) extends Actor with ActorLogging{
+
+  import Orchestration._
+  import JSON_PATH._
+  /**
+    * List of map of Ensembles = [EnsembleID, Ensemble]
+    */
+  private val ensembles:HashMap[String, ActorRef] = HashMap.empty[String, ActorRef]
+
+  private val awaitingTermination:HashMap[String, JsObject] = HashMap.empty[String, JsObject]
+
+  override def receive: Receive = {
+
+    case CREATE_ENSEMBLES(ensemblesJsonSpec) => createEnsembles(ensemblesJsonSpec)
+    case DELETE_ENSEMBLES(ensemblesJsonSpec) => deleteEnsembles(ensemblesJsonSpec)
+    case UPDATE_ENSEMBLES(ensemblesJsonSpec) => updateEnsembles(ensemblesJsonSpec)
+
+    case PRINT_PATH =>
+      log.info(s"** ${self.path} **")
+      context.actorSelection(s"*") ! Ensemble.PRINT_ENSEMBLE
+
+    case Terminated(actor) =>
+      context.unwatch(actor)
+      log.warning(s"ACTOR DEAD ${actor.path}")
+      ensembles.remove(actor.path.name)
+      checkForEnsemblesWaitingTermination(actor.path.name)
+      stopIfNoOrchestrationisRunning()
+
+    case x => log.warning(s"Message $x not treated by Orchestrations")
+  }
+
+  override val supervisorStrategy =
+    OneForOneStrategy(maxNrOfRetries = 3, withinTimeRange = 1 minute) {
+      case e: RestartEnsemble => Restart
+      case e: Exception => Restart
+    }
+
+  override def preStart(): Unit = {
+    if (ORCHESTRATION_CACHE.orchestration_metadata.contains(guid)){
+      replayOrchestrationState()
+    }
+  }
+
+  override def postStop() = {
+    log.info(s"STOPPED ${self.path.name}")
+  }
+
+  override def postRestart(reason: Throwable): Unit = {
+    log.info(s"RESTARTED ${self.path}")
+    preStart()
+  }
+
+  /**
+    * This method is called everytime the orchestration receives a terminated message.
+    * It will check if there is no more Ensembles running and will delete the orchestration
+   */
+  private def stopIfNoOrchestrationisRunning() = {
+    if (ensembles.isEmpty){
+      context.parent ! STOP_EMPTY_ORCHESTRATION(guid)
+    }
+  }
+
+  /**
+    * When the orchestration is restarted, all of its children (Ensemble)
+    * are stopped. In order to also restart all the active ensemble when the
+    * orchestration was restarted, we need to look to orchestration cache.
+    */
+  private def replayOrchestrationState() = {
+    val ensemblesSpec = ORCHESTRATION_CACHE.orchestration_metadata.get(guid).get.map(_._2).toList
+    ORCHESTRATION_CACHE.orchestration_metadata.remove(guid)
+    self ! CREATE_ENSEMBLES(ensemblesSpec)
+  }
+
+  /**
+    * Stops the Ensembles and starts a new one with the updated info
+    *
+    * @param ensemblesJsonSpec
+    */
+  private def updateEnsembles(ensemblesJsonSpec: List[JsObject]) = {
+    ensemblesJsonSpec.foreach(ensembleSpec => {
+      val ensembleID = (ensembleSpec \ GUID).as[String]
+      ensembles.get(ensembleID) match {
+        case Some(activeEnsemble) => {
+          awaitingTermination.put(ensembleID, ensembleSpec)
+          stopEnsembles(Array(ensembleID))
+        }
+        case None => log.warning(s"There is no Ensemble $ensembleID to be updated in Orchestration
$guid")
+      }
+    })
+  }
+
+  /**
+    * Check if there is any ensemble that is waiting for the path to be free.
+    * Normally used only when updating Ensembles
+    * @param terminatedEnsembleID
+    * @return
+    */
+  private def checkForEnsemblesWaitingTermination(terminatedEnsembleID: String) = {
+    awaitingTermination.get(terminatedEnsembleID) match {
+      case Some(ensembleSpec) =>
+        awaitingTermination.remove(terminatedEnsembleID)
+        createEnsembles(List(ensembleSpec))
+      case None =>
+    }
+  }
+
+  /**
+    * Stops the list of Ensembles and removes it from the
+    *
+    * @param ensemblesJsonSpec
+    * @return
+    */
+  private def deleteEnsembles(ensemblesJsonSpec: List[JsObject]) = {
+    val ids = ensemblesJsonSpec.map(json => (json \ GUID).as[String]).toArray
+    stopEnsembles(ids)
+
+    //Remove from cache
+    ORCHESTRATION_CACHE.orchestration_metadata.get(guid) match {
+      case None =>
+      case Some(ensembles) =>
+        ORCHESTRATION_CACHE.orchestration_metadata.put(guid, (ensembles -- ids))
+    }
+    Utils.updateOrchestrationState(guid)
+  }
+
+  /**
+    * Creates Ensembles from the json specification and make it
+    * a member of the orchestration Ensembles
+    *
+    * @param ensemblesJsonSpec
+    * @return
+    */
+  private def createEnsembles(ensemblesJsonSpec: List[JsObject]) = {
+    log.info(s"Creating Ensembles: ${ensemblesJsonSpec}")
+    val newEnsembles = ensemblesJsonSpec.map(ensembleSpec => {
+        try {
+          createEnsemble(ensembleSpec)
+        } catch {
+          case e: Exception =>
+            log.error(e,s"Ensembles ${(ensembleSpec \ GUID).as[String]} in Orchestration
$guid could not be created")
+            None
+        }
+      })
+      .filter(_ != None).map(_.get)
+    ensembles ++= (newEnsembles.map(ensemble => (ensemble._1, ensemble._2)).toMap)
+
+    // Save to cache
+    ORCHESTRATION_CACHE.orchestration_metadata.get(guid) match {
+      case None =>
+        ORCHESTRATION_CACHE.orchestration_metadata.put(guid, (newEnsembles.map(ensemble =>
(ensemble._1, ensemble._3)).toMap))
+      case Some(cachedEnsemble) =>
+        ORCHESTRATION_CACHE.orchestration_metadata.put(guid, cachedEnsemble ++ (newEnsembles.map(ensemble
=> (ensemble._1, ensemble._3)).toMap))
+    }
+    Utils.updateOrchestrationState(guid)
+  }
+
+  /**
+    * Creates an Ensemble object from the JSON
+    *
+    * @param ensembleSpecJson
+    * @return Some(EnsemblesUID, EnsemblesObject)
+    *         None if Ensemble exists
+    */
+  private def createEnsemble(ensembleSpecJson: JsObject): Option[(String, ActorRef, JsObject)]
= {
+    val ensembleID = (ensembleSpecJson \ GUID).as[String]
+    if(!ensembles.contains(ensembleID)) {
+
+      val ensemble = context.actorOf(Props(classOf[Ensemble], guid,name,ensembleSpecJson),
name = ensembleID)
+      context.watch(ensemble)
+
+      Some((ensembleID, ensemble, ensembleSpecJson))
+    }else{
+      log.warning(s"Ensembles $ensembleID in Orchestration $guid already exists")
+      None
+    }
+  }
+
+  /**
+    * Send the stop message to the Ensembles
+    *
+    * @param ensembleesID
+    */
+  private def stopEnsembles(ensembleesID: Array[String]) = {
+    ensembleesID.foreach(ensembleID => {
+      ensembles.get(ensembleID) match {
+        case Some(ensemble) =>
+          ensemble ! PoisonPill
+          ensembles --= ensembleesID
+        case None => log.warning(s"No Ensembles $ensembleID to be stopped in Orchestration
$guid")
+      }
+    })
+  }
+
+}
+
+protected object Orchestration{
+  case class CREATE_ENSEMBLES(ensemblesJsonSpec: List[JsObject])
+  case class DELETE_ENSEMBLES(ensemblesJsonSpec: List[JsObject])
+  case class UPDATE_ENSEMBLES(ensemblesJsonSpec: List[JsObject])
+  case object PRINT_PATH
+}
+
+/**
+  * Keeps all the necessary information to restart the orchestration Ensembles
+  * in case of a restart
+  */
+protected object ORCHESTRATION_CACHE{
+  /**
+    * Key = Orchestration GUID
+    * Value = Map[Ensemble GUID, JsObject of the ensemble]
+    */
+  val orchestration_metadata: HashMap[String, Map[String,JsObject]] = HashMap.empty[String,
Map[String,JsObject]]
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-iota/blob/10042354/fey-core/src/main/scala/org/apache/iota/fey/TrieNode.scala
----------------------------------------------------------------------
diff --git a/fey-core/src/main/scala/org/apache/iota/fey/TrieNode.scala b/fey-core/src/main/scala/org/apache/iota/fey/TrieNode.scala
new file mode 100644
index 0000000..4fcb446
--- /dev/null
+++ b/fey-core/src/main/scala/org/apache/iota/fey/TrieNode.scala
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.iota.fey
+
+import play.api.libs.json.{JsArray, JsObject, JsValue, Json}
+
+import scala.annotation.tailrec
+
+/**
+  * Trie data structure used to create actors hierarchy in Fey
+ */
+case class TrieNode(path: String, var children: Array[TrieNode])
+
+class Trie{
+
+  private val root: TrieNode = TrieNode("FEY-MANAGEMENT-SYSTEM", Array.empty)
+  var elements: Int = 0
+
+  def appendPath(path: String): Unit = {
+    appendPath(path.replaceFirst("akka://","").split("/"),root,1)
+  }
+
+  @tailrec private def appendPath(path: Array[String], root: TrieNode, index: Int): Unit
= {
+    if(root != null && index < path.length){
+      var nextRoot = root.children.filter(child => child.path == path(index))
+      if(nextRoot.isEmpty){
+        nextRoot = Array(TrieNode(path(index), Array.empty))
+        val children = root.children ++: nextRoot
+        root.children = children
+        elements += 1
+      }
+      appendPath(path, nextRoot(0),index+1)
+    }
+  }
+
+  def print:JsValue = {
+    getObject(root, null)
+  }
+
+  private def getObject(root: TrieNode, parent: TrieNode):JsObject = {
+    if(root != null) {
+     Json.obj("name" -> root.path,
+       "parent" -> (if(parent != null) parent.path else "null"),
+        "children" -> root.children.map(getObject(_, root))
+     )
+    }else{
+      Json.obj()
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-iota/blob/10042354/fey-core/src/main/scala/org/apache/iota/fey/Utils.scala
----------------------------------------------------------------------
diff --git a/fey-core/src/main/scala/org/apache/iota/fey/Utils.scala b/fey-core/src/main/scala/org/apache/iota/fey/Utils.scala
new file mode 100644
index 0000000..dab47bd
--- /dev/null
+++ b/fey-core/src/main/scala/org/apache/iota/fey/Utils.scala
@@ -0,0 +1,267 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.iota.fey
+
+import java.io.{BufferedWriter, File, FileWriter}
+import java.net.{URL, URLClassLoader}
+import java.nio.file.{Files, Paths}
+
+import ch.qos.logback.classic.{Level, Logger, LoggerContext}
+import ch.qos.logback.core.joran.spi.JoranException
+import ch.qos.logback.core.util.StatusPrinter
+import com.typesafe.config.ConfigFactory
+import org.slf4j.LoggerFactory
+import play.api.libs.json.{JsValue, Json}
+
+import scala.collection.mutable.HashMap
+import scala.io.Source
+
+protected object Utils {
+
+  import CONFIG._
+
+  private val log = LoggerFactory.getLogger(this.getClass)
+
+  /**
+    * Keeps the loaded clazz in memory
+    * JARNAME,[CLASSPATH, CLASS]
+    */
+  val loadedJars: HashMap[String, (URLClassLoader, Map[String, Class[FeyGenericActor]])]
+                = HashMap.empty[String, (URLClassLoader, Map[String, Class[FeyGenericActor]])]
+
+  /**
+    * Gets a list of Files in the directory
+    *
+    * @param stringPath dir path
+    * @return Array of files in the directory
+    */
+  def getFilesInDirectory(stringPath: String): Array[File]= {
+    val dir = new File(stringPath)
+    if (dir.exists && dir.isDirectory) {
+      dir.listFiles()
+    }else{
+      Array.empty
+    }
+  }
+
+  /**
+    * Loads an actor class from a .jar that inherited from FeyGenericActor
+    *
+    * @param path path to the .jar (including the name)
+    * @param className class path inside the jar
+    * @return class of FeyGenericActor
+    */
+  def loadActorClassFromJar(path: String, className: String):Class[FeyGenericActor] = {
+
+    loadedJars.get(path) match {
+
+      case None =>
+        val urls:Array[URL] = Array(new URL("jar:file:" + path+"!/"))
+        val cl: URLClassLoader = URLClassLoader.newInstance(urls)
+        val clazz = cl.loadClass(className)
+        val feyClazz = clazz.asInstanceOf[Class[FeyGenericActor]]
+        loadedJars.put(path, (cl, Map(className -> feyClazz)))
+        feyClazz
+
+      case Some(loadedJar) =>
+        loadedJar._2.get(className) match {
+          case None =>
+            val clazz = loadedJar._1.loadClass(className)
+            val feyClazz = clazz.asInstanceOf[Class[FeyGenericActor]]
+            loadedJars.put(path, (loadedJar._1, Map(className -> feyClazz) ++ loadedJar._2))
+            feyClazz
+          case Some(clazz) =>
+            clazz
+        }
+    }
+
+  }
+
+  /**
+    * Loads a JSON object from a file
+    *
+    * @param file
+    * @return JsValue of the file
+    */
+  def loadJsonFromFile(file: File): Option[JsValue] = {
+    try{
+      val stringJson = Source.fromFile(file).getLines.mkString
+      Option(Json.parse(stringJson))
+    }catch{
+      case e: Exception =>
+        log.error("Could not parse JSON", e)
+        None
+    }
+  }
+
+  def renameProcessedFile(file: File, extension: String) = {
+    if(CHEKPOINT_ENABLED)
+      file.renameTo(new File(s"${file.getAbsoluteFile}.$extension"))
+  }
+
+  /**
+    * Saves the Orchestration JSON to a tmp directory so Fey can recovery in case it stops
or fails
+    *
+    * @param orchestrationID
+    * @param delete
+    * @return
+    */
+  def updateOrchestrationState(orchestrationID: String, delete: Boolean = false) = {
+    if (CHEKPOINT_ENABLED) {
+      FEY_CACHE.activeOrchestrations.get(orchestrationID) match {
+        case None =>
+          if (!delete)
+            log.warn(s"Could not save state for Orchestration ${orchestrationID}. It is not
active on Fey.")
+          else {
+            val file = new File(s"$CHECKPOINT_DIR/${orchestrationID}.json")
+            if (!file.createNewFile()) {
+              file.delete()
+            }
+            ORCHESTRATION_CACHE.orchestration_metadata.remove(orchestrationID)
+          }
+        case Some(orch) =>
+          ORCHESTRATION_CACHE.orchestration_metadata.get(orchestrationID) match {
+            case None => log.warn(s"Could not save state for Orchestration ${orchestrationID}.
No metadata defined.")
+            case Some(metadata) =>
+              val ensembleJSON = metadata.map(ensenble => ensenble._2)
+
+              val orchestrationSpec = Json.obj(JSON_PATH.GUID -> orchestrationID,
+                JSON_PATH.COMMAND -> "CREATE",
+                JSON_PATH.ORCHESTRATION_NAME -> "I DONT KNOW HOW TO SAVE IT YET =P",
+                JSON_PATH.ORCHESTRATION_TIMESTAMP -> System.currentTimeMillis.toString,
+                JSON_PATH.ENSEMBLES -> ensembleJSON
+              )
+
+              val file = new File(s"$CHECKPOINT_DIR/${orchestrationID}.json")
+              file.getParentFile().mkdirs()
+              file.createNewFile()
+              val bw = new BufferedWriter(new FileWriter(file))
+              bw.write(Json.stringify(orchestrationSpec))
+              bw.close()
+              log.info(s"Orchestration ${orchestrationID} saved.")
+          }
+      }
+    }
+  }
+}
+
+object JSON_PATH{
+  val PERFORMERS: String = "performers"
+  val CONNECTIONS: String = "connections"
+  val GUID: String = "guid"
+  val COMMAND: String = "command"
+  val ENSEMBLES: String = "ensembles"
+  val SCHEDULE: String = "schedule"
+  val BACKOFF: String = "backoff"
+  val SOURCE: String = "source"
+  val SOURCE_NAME: String = "name"
+  val SOURCE_CLASSPATH: String = "classPath"
+  val SOURCE_PARAMS: String = "parameters"
+  val ORCHESTRATION_NAME = "name"
+  val ORCHESTRATION_TIMESTAMP = "timestamp"
+  val PERFORMER_AUTO_SCALE = "autoScale"
+}
+
+object CONFIG{
+
+  private val log = LoggerFactory.getLogger(this.getClass)
+
+  val FILE_APPENDER = "FEY-FILE"
+  val CONSOLE_APPENDER = "FEY-CONSOLE"
+
+  var CHECKPOINT_DIR = ""
+  var JSON_REPOSITORY = ""
+  var JSON_EXTENSION = ""
+  var JAR_REPOSITORY = ""
+  var CHEKPOINT_ENABLED = true
+  var LOG_LEVEL = ""
+  var LOG_APPENDER = ""
+
+  def loadUserConfiguration(path: String) = {
+
+    val app = {
+      if(path != "" && Files.exists(Paths.get(path))) {
+          ConfigFactory.parseFile(new File(path)).withFallback(ConfigFactory.load())
+      }else {
+          log.info("Using Fey Default Configuration")
+          log.warn(s"No user configuration defined. Check if your configuration path $path
is right.")
+          ConfigFactory.load()
+      }
+    }.getConfig("fey-global-configuration")
+
+      CHECKPOINT_DIR = app.getString("checkpoint-directory")
+      JSON_REPOSITORY = app.getString("json-repository")
+      JSON_EXTENSION = app.getString("json-extension")
+      JAR_REPOSITORY = app.getString("jar-repository")
+      CHEKPOINT_ENABLED = app.getBoolean("enable-checkpoint")
+      LOG_LEVEL = app.getString("log-level").toUpperCase()
+      LOG_APPENDER = app.getString("log_appender").toUpperCase()
+
+    setLogbackConfiguration()
+  }
+
+  /**
+    * Resets logback context configuration and loads the new one
+    */
+  def setLogbackConfiguration() = {
+    val  context: LoggerContext = LoggerFactory.getILoggerFactory.asInstanceOf[LoggerContext]
+    try {
+      val root = LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME).asInstanceOf[Logger]
+      root.setLevel(getLogLevel)
+      setLogAppenders(root)
+    } catch {
+      case e: Exception => log.error("Could not configure logback",e)
+    }
+    StatusPrinter.printInCaseOfErrorsOrWarnings(context)
+  }
+
+  def setLogAppenders(root: Logger) = {
+    LOG_APPENDER match {
+      case "FILE" =>
+        root.getAppender(CONSOLE_APPENDER).stop()
+      case "STDOUT" =>
+        root.getAppender(FILE_APPENDER).stop()
+      case "FILE_STDOUT" =>
+      case x =>
+        log.warn(s"Appender $x is not defined. Default to FILE_STDOUT")
+    }
+  }
+
+  def getLogLevel: Level = {
+    LOG_LEVEL match {
+      case "DEBUG" => Level.DEBUG
+      case "INFO" => Level.INFO
+      case "WARN" => Level.WARN
+      case "ERROR" => Level.ERROR
+      case "TRACE" => Level.TRACE
+      case "ALL" => Level.ALL
+      case "OFF" => Level.OFF
+      case x =>
+        log.warn(s"Log level $x is not defined. Default to INFO")
+        Level.INFO
+    }
+  }
+}
+
+
+
+case class NetworkAlreadyDefined(message:String)  extends Exception(message)
+case class IllegalPerformerCreation(message:String)  extends Exception(message)
+case class NetworkNotDefined(message:String)  extends Exception(message)
+case class CommandNotRecognized(message:String)  extends Exception(message)
+case class RestartEnsemble(message:String)  extends Exception(message)
\ No newline at end of file


Mime
View raw message