Skip to content

Commit

Permalink
Work in progress
Browse files Browse the repository at this point in the history
  • Loading branch information
ElaadF committed Mar 11, 2020
1 parent e1996c2 commit 5a8c99e
Show file tree
Hide file tree
Showing 4 changed files with 285 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import com.normation.plugins.RudderPluginModule
import com.normation.plugins.scaleoutrelay.ScalaOutRelayPluginDef
import com.normation.plugins.scaleoutrelay.CheckRudderPluginEnableImpl
import com.normation.plugins.scaleoutrelay.ScaleOutRelayAgentSpecificGeneration
import com.normation.plugins.scaleoutrelay.api.ScaleOutRelayApiImpl

/*
* Actual configuration of the plugin logic
Expand All @@ -53,6 +54,8 @@ object ScalaOutRelayConf extends RudderPluginModule {

lazy val pluginDef = new ScalaOutRelayPluginDef(ScalaOutRelayConf.pluginStatusService)

lazy val api = new ScaleOutRelayApiImpl(RudderConfig.restExtractorService)

// add policy generation for AIX nodes
RudderConfig.agentRegister.addAgentLogic(new ScaleOutRelayAgentSpecificGeneration(pluginStatusService))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,15 @@

package com.normation.plugins.scaleoutrelay

import bootstrap.liftweb.Boot
import bootstrap.rudder.plugin.ScalaOutRelayConf
import com.normation.plugins._
import com.normation.rudder.AuthorizationType.Administration
import com.normation.rudder.rest.EndpointSchema
import com.normation.rudder.rest.lift.LiftApiModuleProvider
import net.liftweb.http.ClasspathTemplates
import net.liftweb.sitemap.Loc.{LocGroup, Template, TestAccess}
import net.liftweb.sitemap.Menu

class ScalaOutRelayPluginDef(override val status: PluginStatus) extends DefaultPluginDef {

Expand All @@ -48,4 +56,16 @@ class ScalaOutRelayPluginDef(override val status: PluginStatus) extends DefaultP
def oneTimeInit : Unit = {}

val configFiles = Seq()

override def apis: Option[LiftApiModuleProvider[_ <: EndpointSchema]] = Some(ScalaOutRelayConf.api)


override def pluginMenuEntry: Option[Menu] = {
Some(Menu("scaleoutrelay", <span>Scale Out Relay</span>) /
"secure" / "plugins" / "scaleoutrelay"
>> LocGroup("pluginsGroup")
>> TestAccess ( () => Boot.userIsAllowed("/secure/index", Administration.Read))
>> Template(() => ClasspathTemplates("template" :: "ScaleOutRelay" :: Nil ) openOr <div>Template not found</div>)
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
package com.normation.plugins.scaleoutrelay

import bootstrap.liftweb.RudderConfig
import com.normation.box.IOToBox
import com.normation.cfclerk.domain.TechniqueVersion
import com.normation.eventlog.{EventActor, ModificationId}
import com.normation.inventory.domain.NodeId
import com.normation.rudder.domain.nodes.NodeGroup
import com.normation.rudder.domain.nodes.NodeGroupCategoryId
import com.normation.rudder.domain.nodes.NodeGroupId
import com.normation.rudder.domain.policies._
import com.normation.rudder.domain.queries._
import com.normation.rudder.rule.category.RuleCategoryId
import net.liftweb.common.Failure
import net.liftweb.common.Full

object ScaleOutRelayService {
private val nodeInfosService = RudderConfig.nodeInfoService
private val woLDAPNodeGroupRepository = RudderConfig.woNodeGroupRepository
private val woLDAPNodeRepository = RudderConfig.woNodeRepository
private val woDirectiveRepository = RudderConfig.woDirectiveRepository
private val woRuleRepository = RudderConfig.woRuleRepository
private val uuidGen = RudderConfig.stringUuidGenerator

def saveAllObjects(uuid: NodeId, actor: EventActor, reason:Option[String]) = {
for {
updatedNode <- createNodeToPolicyServerType(uuid)
commonDirective <- createCommonDirective(uuid)

directDistribPolicy = createDirectiveDistributePolicy(uuid)
ruleTarget = createPolicyServer(uuid)
nodeGroup = createNodeGroup(uuid)
ruleDistribPolicy = createRuleDistributePolicy(uuid)
ruleSetup = createRuleSetup(uuid)
modId = ModificationId(uuidGen.newUuid)
categoryId = NodeGroupCategoryId("SystemGroups")
activeTechniqueId = ActiveTechniqueId("distributePolicy")
activeTechniqueIdCommon = ActiveTechniqueId("common")

a <- woLDAPNodeGroupRepository.createPolicyServerTarget(ruleTarget, modId, actor, reason).toBox
b <- woLDAPNodeGroupRepository.create(nodeGroup, categoryId, modId, actor, reason).toBox
c <- woDirectiveRepository.saveSystemDirective(activeTechniqueId,directDistribPolicy, modId, actor, reason).toBox
d <- woDirectiveRepository.saveSystemDirective(activeTechniqueIdCommon,commonDirective, modId, actor, reason).toBox
e <- woRuleRepository.create(ruleSetup, modId, actor, reason).toBox
f <- woRuleRepository.create(ruleDistribPolicy, modId, actor, reason).toBox
g <- woLDAPNodeRepository.updateNode(updatedNode, modId, actor, reason).toBox
} yield {
uuid
}
}

def createNodeToPolicyServerType(uuid: NodeId) = {
for {
nodeInfos <- nodeInfosService.getNodeInfo(uuid)
node <- nodeInfos match {
case Some(nodeinf) => Full(nodeinf.node)
case _ => Failure(s"Cannot retrieve node of ${uuid}")
}
} yield {
node.copy(id = uuid, name = uuid.value,description = "A relay server" , isSystem = true)
}
}

def createPolicyServer(uuid: NodeId) = {
PolicyServerTarget(uuid)
}

def createNodeGroup(uuid: NodeId) = {
val objectType = ObjectCriterion("node", Seq(Criterion("policyServerId", StringComparator, None),Criterion("agentName", AgentComparator, None)))
val attribute = Criterion("agentName", StringComparator)
val comparator = Equals
val value = "cfengine"

val objectType2 = ObjectCriterion("node", Seq(Criterion("policyServerId", StringComparator, None),Criterion("agentName", AgentComparator, None)))
val attribute2 = Criterion("policyServerId", StringComparator)
val comparator2 = Equals
val value2 = uuid.value
NodeGroup(
NodeGroupId(s"cecuwecewcbyewb-${uuid.value}")
, s"rudder-configuration"
, s"All classic Nodes known by Rudder directly connected to the ${uuid.value} server. This group exists only as internal purpose and should not be used to configure Nodes."
, Some(Query(NodeAndPolicyServerReturnType, And, List(CriterionLine(objectType, attribute, comparator, value), CriterionLine(objectType2, attribute2, comparator2, value2))))
, true
, Set()
, true
, true
)
}

def createDirectiveDistributePolicy(uuid: NodeId) = {
Directive(
DirectiveId(s"$uuid-distributePolicy")
, TechniqueVersion("1.0")
, Map()
, s"$uuid-Distribute Policy"
, "Distribute policy - Technical"
, None
, ""
, 0
, true
, true
, Tags(Set.empty)
)
}

def createCommonDirective(uuid: NodeId) = {
for {
nodeInfos <- nodeInfosService.getNodeInfo(uuid)
hostname <- nodeInfos match {
case Some(n) => Full(n.hostname)
case _ => Failure(s"Cannot retrieve hostname of ${uuid}")
}
policyserverId <- nodeInfos match {
case Some(n) => Full(n.policyServerId)
case _ => Failure(s"Cannot retrieve Policy Server ID of ${uuid}")
}
authorizedNetworks <- nodeInfos match {
case Some(n) => Full(n.ips)
case _ => Failure("Cannot retrieve Authorized networks of ${uuid}")
}
} yield {
val parameters =
Map (
"OWNER" -> Seq("${rudder.node.admin}")
, "UUID" -> Seq("${rudder.node.id}")
, "POLICYSERVER" -> Seq(hostname)
, "POLICYSERVER_ID" -> Seq(policyserverId.value)
, "POLICYSERVER_ADMIN" -> Seq("root")
, "ALLOWEDNETWORK" -> authorizedNetworks
)
Directive(
DirectiveId(s"common-$uuid")
, TechniqueVersion("0:1.0")
, parameters
, s"Common-$uuid"
, "Distribute policy - Technical"
, None
, ""
, 0
, true
, true
, Tags(Set.empty)
)
}
}

def createRuleDistributePolicy(uuid: NodeId) = {
val ruleTarget = RuleTarget.unser("policyServer:root") match {
case Some(targets) => List(targets)
case _ => List.empty
}
Rule(
RuleId(s"${uuid}-DP")
, "distrivutePolicy"
, RuleCategoryId("rootRuleCategory")
, ruleTarget.toSet
, Set(DirectiveId(s"${uuid}-distributePolicy"))
, "Distribute Policy - Technical"
, "This rule allows to distribute policies to nodes"
, true
, true
)
}

def createRuleSetup(uuid: NodeId) = {
val ruleTarget = RuleTarget.unser(s"group:hasPolicyServer-${uuid}") match {
case Some(targets) => List(targets)
case _ => List.empty
}
Rule(
RuleId(s"hasPolicyServer-${uuid}")
, "Rudder system policy: basic setup (common)"
, RuleCategoryId("rootRuleCategory")
, ruleTarget.toSet
, Set(DirectiveId(s"common-${uuid}"))
, "Common - Technical"
, "This is the basic system rule which all nodes must have."
, true
, true
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package com.normation.plugins.scaleoutrelay.api


import com.normation.eventlog.EventActor
import com.normation.inventory.domain.NodeId
import com.normation.plugins.scaleoutrelay.ScaleOutRelayService
import com.normation.rudder.api.HttpAction.POST
import com.normation.rudder.repository.json.DataExtractor.CompleteJson
import com.normation.rudder.rest.EndpointSchema.syntax._
import com.normation.rudder.rest.RestUtils.toJsonError
import com.normation.rudder.rest.RestUtils.toJsonResponse
import com.normation.rudder.rest._
import com.normation.rudder.rest.lift.DefaultParams
import com.normation.rudder.rest.lift.LiftApiModule
import com.normation.rudder.rest.lift.LiftApiModuleProvider
import net.liftweb.common.Box
import net.liftweb.common.Full
import net.liftweb.http.LiftResponse
import net.liftweb.http.Req
import net.liftweb.json.JsonAST.JValue
import net.liftweb.json.JsonDSL._
import net.liftweb.json.NoTypeHints
import sourcecode.Line



sealed trait ScaleOutRelayApi extends EndpointSchema with GeneralApi with SortIndex
object ScaleOutRelayApi extends ApiModuleProvider[ScaleOutRelayApi] {

final case object PromoteNodeToRelay extends ScaleOutRelayApi with OneParam with StartsAtVersion10 {
val z = implicitly[Line].value
val description = "Promote a node to relay"
val (action, path) = POST / "scaleoutrelay" / "promote" / "{nodeId}"
}

override def endpoints: List[ScaleOutRelayApi] = ca.mrvisser.sealerate.values[ScaleOutRelayApi].toList.sortBy( _.z )
}

class ScaleOutRelayApiImpl(
restExtractorService: RestExtractorService
) extends LiftApiModuleProvider[ScaleOutRelayApi] {

api =>

implicit val formats = net.liftweb.json.Serialization.formats((NoTypeHints))
override def schemas = ScaleOutRelayApi

override def getLiftEndpoints(): List[LiftApiModule] = {
ScaleOutRelayApi.endpoints.map {
case ScaleOutRelayApi.PromoteNodeToRelay => PromoteNodeToRelay
}.toList
}

def extractNodeUUID(json: JValue): Box[String] = {
for {
nodeUUID <- CompleteJson.extractJsonString(json, "UUID")
} yield {
nodeUUID
}
}

def response(function: Box[JValue], req: Req, errorMessage: String, id: Option[String], dataName: String)(implicit action: String): LiftResponse = {
RestUtils.response(restExtractorService, dataName, id)(function, req, errorMessage)
}

object PromoteNodeToRelay extends LiftApiModule {
val schema = ScaleOutRelayApi.PromoteNodeToRelay
val restExtractor = api.restExtractorService

def process(version: ApiVersion, path: ApiPath, nodeId: String, req: Req, params: DefaultParams, authz: AuthzToken): LiftResponse = {
val response: JValue = "toto" -> "Ok"
val uuid = ScaleOutRelayService.saveAllObjects(NodeId(nodeId), EventActor("rudder"), Some(s"Promote node ${nodeId} to relay"))
println(uuid)
uuid match {
case Full(id) => toJsonResponse(None,id.value)("promoteToRelay",true)
case _ => toJsonError(None, s"Error when trying to promote mode $nodeId")("promoteToRelay",true)
}
}
}
}

0 comments on commit 5a8c99e

Please sign in to comment.