From 163dd74935802f562ef7272cadf0f88b6a63960a Mon Sep 17 00:00:00 2001 From: GuangrongFu Date: Tue, 14 Aug 2018 17:52:44 +0800 Subject: [PATCH] Optimized Rule Deployment Logic Change-Id: Iff47a4d028aaad96ac8d7517d721ae43b50a9b89 Issue-ID: HOLMES-156 Signed-off-by: GuangrongFu --- .../onap/holmes/engine/manager/DroolsEngine.java | 629 ++++++++++----------- .../holmes/engine/resources/EngineResources.java | 7 +- .../holmes/engine/manager/DroolsEngineTest.java | 272 +++++---- .../engine/resources/EngineResourcesTest.java | 15 +- 4 files changed, 492 insertions(+), 431 deletions(-) diff --git a/engine-d/src/main/java/org/onap/holmes/engine/manager/DroolsEngine.java b/engine-d/src/main/java/org/onap/holmes/engine/manager/DroolsEngine.java index bb3795d..7472457 100644 --- a/engine-d/src/main/java/org/onap/holmes/engine/manager/DroolsEngine.java +++ b/engine-d/src/main/java/org/onap/holmes/engine/manager/DroolsEngine.java @@ -1,321 +1,308 @@ -/** - * Copyright 2017 ZTE Corporation. - * - * Licensed 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.onap.holmes.engine.manager; -import java.io.StringReader; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Locale; -import java.util.Set; -import javax.annotation.PostConstruct; -import javax.inject.Inject; -import lombok.extern.slf4j.Slf4j; -import org.drools.compiler.kie.builder.impl.InternalKieModule; -import org.jvnet.hk2.annotations.Service; - -import org.kie.api.KieBase; -import org.kie.api.KieServices; -import org.kie.api.builder.KieBuilder; -import org.kie.api.builder.KieFileSystem; -import org.kie.api.builder.KieRepository; -import org.kie.api.builder.Message; -import org.kie.api.builder.Message.Level; -import org.kie.api.builder.model.KieBaseModel; -import org.kie.api.builder.model.KieModuleModel; -import org.kie.api.builder.model.KieSessionModel; -import org.kie.api.conf.EqualityBehaviorOption; -import org.kie.api.conf.EventProcessingOption; -import org.kie.api.definition.KiePackage; -import org.kie.api.io.KieResources; -import org.kie.api.io.ResourceType; -import org.kie.api.runtime.KieContainer; -import org.kie.api.runtime.KieSession; -import org.kie.api.runtime.conf.ClockTypeOption; -import org.kie.api.runtime.rule.FactHandle; - -import org.onap.holmes.common.api.entity.AlarmInfo; - -import org.onap.holmes.common.api.stat.VesAlarm; -import org.onap.holmes.common.dmaap.DmaapService; -import org.onap.holmes.common.exception.AlarmInfoException; -import org.onap.holmes.common.utils.DbDaoUtil; -import org.onap.holmes.engine.db.AlarmInfoDao; -import org.onap.holmes.engine.request.DeployRuleRequest; -import org.onap.holmes.common.api.entity.CorrelationRule; -import org.onap.holmes.common.exception.CorrelationException; -import org.onap.holmes.common.utils.ExceptionUtil; -import org.onap.holmes.engine.wrapper.RuleMgtWrapper; - -@Slf4j -@Service -public class DroolsEngine { - - private static final int ENABLE = 1; - public static final String UTF_8 = "UTF-8"; - public static final String K_BASE = "KBase"; - private static final String RULES_FILE_NAME = "src/main/resources/rules/rule.drl"; - private final Set packageNames = new HashSet(); - - @Inject - private RuleMgtWrapper ruleMgtWrapper; - - - private KieBase kieBase; - private KieSession kieSession; - private KieContainer kieContainer; - private KieFileSystem kfs; - private KieServices ks; - private KieBuilder kieBuilder; - private KieResources resources; - private KieRepository kieRepository; - - private AlarmInfoDao alarmInfoDao; - @Inject - private DbDaoUtil daoUtil; - - - @PostConstruct - private void init() { - alarmInfoDao = daoUtil.getJdbiDaoByOnDemand(AlarmInfoDao.class); - try { - // start engine - start(); - } catch (Exception e) { - log.error("Failed to start the service: " + e.getMessage(), e); - throw ExceptionUtil.buildExceptionResponse("Failed to start the drools engine!"); - } - } - - private void start() throws AlarmInfoException { - log.info("Drools Engine Initialize Beginning..."); - - initEngineParameter(); - alarmSynchronization(); -// initDeployRule(); - - log.info("Alarm synchronization Successfully."); - } - - public void stop() { - this.kieSession.dispose(); - } - - public void initEngineParameter() { - this.ks = KieServices.Factory.get(); - this.resources = ks.getResources(); - this.kieRepository = ks.getRepository(); - this.kfs = createKieFileSystemWithKProject(ks); - - this.kieBuilder = ks.newKieBuilder(kfs).buildAll(); - this.kieContainer = ks.newKieContainer(kieRepository.getDefaultReleaseId()); - - this.kieBase = kieContainer.getKieBase(); - this.kieSession = kieContainer.newKieSession(); - } - - private void initDeployRule() throws CorrelationException { - List rules = ruleMgtWrapper.queryRuleByEnable(ENABLE); - - if (rules.isEmpty()) { - return; - } - for (CorrelationRule rule : rules) { - if (rule.getContent() != null) { - deployRuleFromDB(rule.getContent()); - DmaapService.loopControlNames.put(rule.getPackageName(), rule.getClosedControlLoopName()); - } - } - } - - private void deployRuleFromDB(String ruleContent) throws CorrelationException { - avoidDeployBug(); - StringReader reader = new StringReader(ruleContent); - kfs.write(RULES_FILE_NAME, - this.resources.newReaderResource(reader, UTF_8).setResourceType(ResourceType.DRL)); - kieBuilder = ks.newKieBuilder(kfs).buildAll(); - try { - InternalKieModule internalKieModule = (InternalKieModule)kieBuilder.getKieModule(); - kieContainer.updateToVersion(internalKieModule.getReleaseId()); - } catch (Exception e) { - throw new CorrelationException(e.getMessage(), e); - } - kieSession.fireAllRules(); - } - - public synchronized String deployRule(DeployRuleRequest rule, Locale locale) - throws CorrelationException { - avoidDeployBug(); - StringReader reader = new StringReader(rule.getContent()); - kfs.write(RULES_FILE_NAME, - this.resources.newReaderResource(reader, UTF_8).setResourceType(ResourceType.DRL)); - kieBuilder = ks.newKieBuilder(kfs).buildAll(); - - judgeRuleContent(locale, kieBuilder, true); - - InternalKieModule internalKieModule = (InternalKieModule)kieBuilder.getKieModule();; - String packageName = internalKieModule.getKnowledgePackagesForKieBase(K_BASE).iterator().next().getName(); - try { - kieContainer.updateToVersion(internalKieModule.getReleaseId()); - } catch (Exception e) { - throw new CorrelationException("Failed to deploy the rule.", e); - } - packageNames.add(packageName); - kieSession.fireAllRules(); - return packageName; - } - - public synchronized void undeployRule(String packageName, Locale locale) - throws CorrelationException { - KiePackage kiePackage = kieBase.getKiePackage(packageName); - if (null == kiePackage) { - throw new CorrelationException("The rule " + packageName + " does not exist!"); - } - try { - kieBase.removeKiePackage(kiePackage.getName()); - } catch (Exception e) { - throw new CorrelationException("Failed to delete the rule: " + packageName, e); - } - packageNames.remove(kiePackage.getName()); - } - - public void compileRule(String content, Locale locale) - throws CorrelationException { - StringReader reader = new StringReader(content); - - kfs.write(RULES_FILE_NAME, - this.resources.newReaderResource(reader, UTF_8).setResourceType(ResourceType.DRL)); - - kieBuilder = ks.newKieBuilder(kfs).buildAll(); - - judgeRuleContent(locale, kieBuilder, false); - } - - private void judgeRuleContent(Locale locale, KieBuilder kbuilder, boolean judgePackageName) - throws CorrelationException { - if (kbuilder.getResults().hasMessages(Message.Level.ERROR)) { - String errorMsg = "There are errors in the rule: " + kbuilder.getResults() - .getMessages(Level.ERROR).toString(); - log.error(errorMsg); - throw new CorrelationException(errorMsg); - } - InternalKieModule internalKieModule = null; - try { - internalKieModule = (InternalKieModule) kbuilder.getKieModule(); - } catch (Exception e) { - throw new CorrelationException("There are errors in the rule!" + e.getMessage(), e); - } - if (internalKieModule == null) { - throw new CorrelationException("There are errors in the rule!"); - } - String packageName = internalKieModule.getKnowledgePackagesForKieBase(K_BASE).iterator().next().getName(); - - if (queryAllPackage().contains(packageName) && judgePackageName) { - throw new CorrelationException("The rule " + packageName + " already exists in the drools engine."); - } - } - - public void putRaisedIntoStream(VesAlarm alarm) { - FactHandle factHandle = this.kieSession.getFactHandle(alarm); - if (factHandle != null) { - Object obj = this.kieSession.getObject(factHandle); - if (obj != null && obj instanceof VesAlarm) { - alarm.setRootFlag(((VesAlarm) obj).getRootFlag()); - } - this.kieSession.delete(factHandle); - - if (alarm.getAlarmIsCleared() == 1) { - alarmInfoDao.deleteClearedAlarm(convertVesAlarm2AlarmInfo(alarm)); - } - } else { - this.kieSession.insert(alarm); - } - - this.kieSession.fireAllRules(); - - } - - public List queryAllPackage() { - List kiePackages = (List)kieBase.getKiePackages(); - List list = new ArrayList<>(); - for(KiePackage kiePackage : kiePackages) { - list.add(kiePackage.getName()); - } - return list; - } - - private KieFileSystem createKieFileSystemWithKProject(KieServices ks) { - KieModuleModel kieModuleModel = ks.newKieModuleModel(); - KieBaseModel kieBaseModel = kieModuleModel.newKieBaseModel(K_BASE) - .addPackage("rules") - .setDefault(true) - .setEqualsBehavior(EqualityBehaviorOption.EQUALITY) - .setEventProcessingMode(EventProcessingOption.STREAM); - KieSessionModel kieSessionModel = kieBaseModel.newKieSessionModel("KSession") - .setDefault( true ) - .setType( KieSessionModel.KieSessionType.STATEFUL ) - .setClockType( ClockTypeOption.get("realtime") ); - KieFileSystem kfs = ks.newKieFileSystem(); - kfs.writeKModuleXML(kieModuleModel.toXML()); - return kfs; - } - - private void avoidDeployBug() { - String tmp = Math.random() + ""; - String rule = "package justInOrderToAvoidDeployBug" + tmp.substring(2); - kfs.write(RULES_FILE_NAME, rule); - kieBuilder = ks.newKieBuilder(kfs).buildAll(); - InternalKieModule internalKieModule = (InternalKieModule)kieBuilder.getKieModule(); - String packageName = internalKieModule.getKnowledgePackagesForKieBase(K_BASE).iterator().next().getName(); - kieRepository.addKieModule(internalKieModule); - kieContainer.updateToVersion(internalKieModule.getReleaseId()); - - KiePackage kiePackage = kieBase.getKiePackage(packageName); - kieBase.removeKiePackage(kiePackage.getName()); - } - - public void alarmSynchronization() throws AlarmInfoException { - alarmInfoDao.queryAllAlarm().forEach(alarmInfo -> alarmInfoDao.deleteClearedAlarm(alarmInfo)); - alarmInfoDao.queryAllAlarm().forEach(alarmInfo -> putRaisedIntoStream(convertAlarmInfo2VesAlarm(alarmInfo))); - } - - private VesAlarm convertAlarmInfo2VesAlarm(AlarmInfo alarmInfo) { - VesAlarm vesAlarm = new VesAlarm(); - vesAlarm.setEventId(alarmInfo.getEventId()); - vesAlarm.setEventName(alarmInfo.getEventName()); - vesAlarm.setStartEpochMicrosec(alarmInfo.getStartEpochMicroSec()); - vesAlarm.setSourceId(alarmInfo.getSourceId()); - vesAlarm.setSourceName(alarmInfo.getSourceName()); - vesAlarm.setRootFlag(alarmInfo.getRootFlag()); - vesAlarm.setAlarmIsCleared(alarmInfo.getAlarmIsCleared()); - vesAlarm.setLastEpochMicrosec(alarmInfo.getLastEpochMicroSec()); - return vesAlarm; - } - - private AlarmInfo convertVesAlarm2AlarmInfo(VesAlarm vesAlarm){ - AlarmInfo alarmInfo = new AlarmInfo(); - alarmInfo.setEventId(vesAlarm.getEventId()); - alarmInfo.setEventName(vesAlarm.getEventName()); - alarmInfo.setStartEpochMicroSec(vesAlarm.getStartEpochMicrosec()); - alarmInfo.setLastEpochMicroSec(vesAlarm.getLastEpochMicrosec()); - alarmInfo.setSourceId(vesAlarm.getSourceId()); - alarmInfo.setSourceName(vesAlarm.getSourceName()); - alarmInfo.setAlarmIsCleared(vesAlarm.getAlarmIsCleared()); - alarmInfo.setRootFlag(vesAlarm.getRootFlag()); - - return alarmInfo; - } - -} +/** + * Copyright 2017 ZTE Corporation. + *

+ * Licensed 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.onap.holmes.engine.manager; + +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; +import javax.annotation.PostConstruct; +import javax.inject.Inject; + +import lombok.extern.slf4j.Slf4j; +import org.drools.compiler.kie.builder.impl.InternalKieModule; +import org.drools.core.util.StringUtils; +import org.jvnet.hk2.annotations.Service; + +import org.kie.api.KieServices; +import org.kie.api.builder.*; +import org.kie.api.builder.Message.Level; +import org.kie.api.io.Resource; +import org.kie.api.runtime.KieContainer; +import org.kie.api.runtime.KieSession; +import org.kie.api.runtime.rule.FactHandle; + +import org.onap.holmes.common.api.entity.AlarmInfo; + +import org.onap.holmes.common.api.stat.VesAlarm; +import org.onap.holmes.common.dmaap.DmaapService; +import org.onap.holmes.common.exception.AlarmInfoException; +import org.onap.holmes.common.utils.DbDaoUtil; +import org.onap.holmes.engine.db.AlarmInfoDao; +import org.onap.holmes.engine.request.DeployRuleRequest; +import org.onap.holmes.common.api.entity.CorrelationRule; +import org.onap.holmes.common.exception.CorrelationException; +import org.onap.holmes.common.utils.ExceptionUtil; +import org.onap.holmes.engine.wrapper.RuleMgtWrapper; + +@Slf4j +@Service +public class DroolsEngine { + + @Inject + private RuleMgtWrapper ruleMgtWrapper; + @Inject + private DbDaoUtil daoUtil; + + private final static int ENABLE = 1; + private AlarmInfoDao alarmInfoDao; + private final Map deployed = new ConcurrentHashMap<>(); + private KieServices ks = KieServices.Factory.get(); + private ReleaseId releaseId = ks.newReleaseId("org.onap.holmes", "rules", "1.0.0-SNAPSHOT"); + private ReleaseId compilationRelease = ks.newReleaseId("org.onap.holmes", "compilation", "1.0.0-SNAPSHOT"); + private KieContainer container; + private KieSession session; + + @PostConstruct + private void init() { + alarmInfoDao = daoUtil.getJdbiDaoByOnDemand(AlarmInfoDao.class); + try { + log.info("Drools engine initializing..."); + initEngine(); + log.info("Drools engine initialized."); + + log.info("Start deploy existing rules..."); + initRules(); + log.info("All rules were deployed."); + + log.info("Synchronizing alarms..."); + syncAlarms(); + log.info("Alarm synchronization succeeded."); + } catch (Exception e) { + log.error("Failed to startup the engine of Holmes: " + e.getMessage(), e); + throw ExceptionUtil.buildExceptionResponse("Failed to startup Drools!"); + } + } + + public void stop() { + session.dispose(); + } + + public void initEngine() { + KieModule km = null; + try { + String drl = "package holmes;"; + deployed.put(getPackageName(drl), drl); + km = createAndDeployJar(ks, releaseId, new ArrayList<>(deployed.values())); + } catch (Exception e) { + log.error("Failed to initialize the engine service module.", e); + } + container = ks.newKieContainer(km.getReleaseId()); + session = container.newKieSession(); + deployed.clear(); + } + + private void initRules() throws CorrelationException { + List rules = ruleMgtWrapper.queryRuleByEnable(ENABLE); + if (rules.isEmpty()) { + return; + } + + for (CorrelationRule rule : rules) { + if (!StringUtils.isEmpty(rule.getContent())) { + deployRule(rule.getContent()); + DmaapService.loopControlNames.put(rule.getPackageName(), rule.getClosedControlLoopName()); + } + } + + session.fireAllRules(); + } + + public void syncAlarms() throws AlarmInfoException { + alarmInfoDao.queryAllAlarm().forEach(alarmInfo -> alarmInfoDao.deleteClearedAlarm(alarmInfo)); + alarmInfoDao.queryAllAlarm().forEach(alarmInfo -> putRaisedIntoStream(convertAlarmInfo2VesAlarm(alarmInfo))); + } + + public String deployRule(DeployRuleRequest rule) throws CorrelationException { + return deployRule(rule.getContent()); + } + + private synchronized String deployRule(String rule) throws CorrelationException { + final String packageName = getPackageName(rule); + + if (StringUtils.isEmpty(packageName)) { + throw new CorrelationException("The package name can not be empty."); + } + + if (deployed.containsKey(packageName)) { + throw new CorrelationException("A rule with the same package name already exists in the system."); + } + + if (!StringUtils.isEmpty(rule)) { + deployed.put(packageName, rule); + try { + refreshInMemRules(); + } catch (CorrelationException e) { + deployed.remove(packageName); + throw e; + } + session.fireAllRules(); + } + + return packageName; + } + + public synchronized void undeployRule(String packageName) throws CorrelationException { + + if (StringUtils.isEmpty(packageName)) { + throw new CorrelationException("The package name should not be null."); + } + + if (!deployed.containsKey(packageName)) { + throw new CorrelationException("The rule " + packageName + " does not exist!"); + } + + String removed = deployed.remove(packageName); + try { + refreshInMemRules(); + } catch (Exception e) { + deployed.put(packageName, removed); + throw new CorrelationException("Failed to delete the rule: " + packageName, e); + } + } + + private void refreshInMemRules() throws CorrelationException { + KieModule km = createAndDeployJar(ks, releaseId, new ArrayList<>(deployed.values())); + container.updateToVersion(km.getReleaseId()); + } + + public void compileRule(String content) + throws CorrelationException { + + KieFileSystem kfs = ks.newKieFileSystem().generateAndWritePomXML(compilationRelease); + kfs.write("src/main/resources/rules/rule.drl", content); + KieBuilder builder = ks.newKieBuilder(kfs).buildAll(); + if (builder.getResults().hasMessages(Message.Level.ERROR)) { + String errorMsg = "There are errors in the rule: " + builder.getResults() + .getMessages(Level.ERROR).toString(); + log.info("Compilation failure: " + errorMsg); + throw new CorrelationException(errorMsg); + } + + if (deployed.containsKey(getPackageName(content))) { + throw new CorrelationException("There's no compilation error. But a rule with the same package name already " + + "exists in the engine, which may cause a deployment failure."); + } + + ks.getRepository().removeKieModule(compilationRelease); + } + + public void putRaisedIntoStream(VesAlarm alarm) { + FactHandle factHandle = this.session.getFactHandle(alarm); + if (factHandle != null) { + Object obj = this.session.getObject(factHandle); + if (obj != null && obj instanceof VesAlarm) { + alarm.setRootFlag(((VesAlarm) obj).getRootFlag()); + } + this.session.delete(factHandle); + + if (alarm.getAlarmIsCleared() == 1) { + alarmInfoDao.deleteClearedAlarm(convertVesAlarm2AlarmInfo(alarm)); + } + } else { + this.session.insert(alarm); + } + + this.session.fireAllRules(); + } + + public List queryPackagesFromEngine() { + return container.getKieBase().getKiePackages().stream() + .filter(pkg -> pkg.getRules().size() != 0) + .map(pkg -> pkg.getName()) + .collect(Collectors.toList()); + } + + + + private VesAlarm convertAlarmInfo2VesAlarm(AlarmInfo alarmInfo) { + VesAlarm vesAlarm = new VesAlarm(); + vesAlarm.setEventId(alarmInfo.getEventId()); + vesAlarm.setEventName(alarmInfo.getEventName()); + vesAlarm.setStartEpochMicrosec(alarmInfo.getStartEpochMicroSec()); + vesAlarm.setSourceId(alarmInfo.getSourceId()); + vesAlarm.setSourceName(alarmInfo.getSourceName()); + vesAlarm.setRootFlag(alarmInfo.getRootFlag()); + vesAlarm.setAlarmIsCleared(alarmInfo.getAlarmIsCleared()); + vesAlarm.setLastEpochMicrosec(alarmInfo.getLastEpochMicroSec()); + return vesAlarm; + } + + private AlarmInfo convertVesAlarm2AlarmInfo(VesAlarm vesAlarm) { + AlarmInfo alarmInfo = new AlarmInfo(); + alarmInfo.setEventId(vesAlarm.getEventId()); + alarmInfo.setEventName(vesAlarm.getEventName()); + alarmInfo.setStartEpochMicroSec(vesAlarm.getStartEpochMicrosec()); + alarmInfo.setLastEpochMicroSec(vesAlarm.getLastEpochMicrosec()); + alarmInfo.setSourceId(vesAlarm.getSourceId()); + alarmInfo.setSourceName(vesAlarm.getSourceName()); + alarmInfo.setAlarmIsCleared(vesAlarm.getAlarmIsCleared()); + alarmInfo.setRootFlag(vesAlarm.getRootFlag()); + + return alarmInfo; + } + + private String getPackageName(String contents) { + String ret = contents.trim(); + StringBuilder stringBuilder = new StringBuilder(); + if (ret.startsWith("package")) { + ret = ret.substring(7).trim(); + for (int i = 0; i < ret.length(); i++) { + char tmp = ret.charAt(i); + if (tmp == ';' || tmp == ' ' || tmp == '\n') { + break; + } + stringBuilder.append(tmp); + } + } + return stringBuilder.toString(); + } + + private KieModule createAndDeployJar(KieServices ks, ReleaseId releaseId, List drls) throws CorrelationException { + byte[] jar = createJar(ks, releaseId, drls); + KieModule km = deployJarIntoRepository(ks, jar); + return km; + } + + private byte[] createJar(KieServices ks, ReleaseId releaseId, List drls) throws CorrelationException { + KieFileSystem kfs = ks.newKieFileSystem().generateAndWritePomXML(releaseId); + int i = 0; + for (String drl : drls) { + if (!StringUtils.isEmpty(drl)) { + kfs.write("src/main/resources/" + getPackageName(drl) + ".drl", drl); + } + } + KieBuilder kb = ks.newKieBuilder(kfs).buildAll(); + if (kb.getResults().hasMessages(Message.Level.ERROR)) { + StringBuilder sb = new StringBuilder(); + for (Message msg : kb.getResults().getMessages()) { + sb.append(String.format("[%s]Line: %d, Col: %d\t%s\n", msg.getLevel().toString(), msg.getLine(), + msg.getColumn(), msg.getText())); + } + throw new CorrelationException("Failed to compile JAR. Details: \n" + sb.toString()); + } + + InternalKieModule kieModule = (InternalKieModule) ks.getRepository() + .getKieModule(releaseId); + + return kieModule.getBytes(); + } + + private KieModule deployJarIntoRepository(KieServices ks, byte[] jar) { + Resource jarRes = ks.getResources().newByteArrayResource(jar); + return ks.getRepository().addKieModule(jarRes); + } + +} diff --git a/engine-d/src/main/java/org/onap/holmes/engine/resources/EngineResources.java b/engine-d/src/main/java/org/onap/holmes/engine/resources/EngineResources.java index 4088d72..0d26b6e 100644 --- a/engine-d/src/main/java/org/onap/holmes/engine/resources/EngineResources.java +++ b/engine-d/src/main/java/org/onap/holmes/engine/resources/EngineResources.java @@ -77,7 +77,7 @@ public class EngineResources { DmaapService.loopControlNames .put(packageName, deployRuleRequest.getLoopControlName()); - String packageNameRet = droolsEngine.deployRule(deployRuleRequest, locale); + String packageNameRet = droolsEngine.deployRule(deployRuleRequest); if (!packageName.equals(packageNameRet)) { log.info("The parsed package name is different from that returned by the engine."); DmaapService.loopControlNames.remove(packageName); @@ -109,12 +109,13 @@ public class EngineResources { Locale locale = LanguageUtil.getLocale(httpRequest); try { - droolsEngine.undeployRule(packageName, locale); + droolsEngine.undeployRule(packageName); DmaapService.loopControlNames.remove(packageName); } catch (CorrelationException correlationException) { log.error(correlationException.getMessage(), correlationException); throw ExceptionUtil.buildExceptionResponse(correlationException.getMessage()); } + return true; } @@ -129,7 +130,7 @@ public class EngineResources { Locale locale = LanguageUtil.getLocale(httpRequest); try { - droolsEngine.compileRule(compileRuleRequest.getContent(), locale); + droolsEngine.compileRule(compileRuleRequest.getContent()); } catch (CorrelationException correlationException) { log.error(correlationException.getMessage(), correlationException); throw ExceptionUtil.buildExceptionResponse(correlationException.getMessage()); diff --git a/engine-d/src/test/java/org/onap/holmes/engine/manager/DroolsEngineTest.java b/engine-d/src/test/java/org/onap/holmes/engine/manager/DroolsEngineTest.java index 71ef172..4ad9107 100644 --- a/engine-d/src/test/java/org/onap/holmes/engine/manager/DroolsEngineTest.java +++ b/engine-d/src/test/java/org/onap/holmes/engine/manager/DroolsEngineTest.java @@ -1,12 +1,12 @@ /** * Copyright 2017 ZTE Corporation. - * + *

* Licensed 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. @@ -16,23 +16,14 @@ package org.onap.holmes.engine.manager; -import org.easymock.EasyMock; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.kie.api.KieBase; -import org.kie.api.KieServices; -import org.kie.api.builder.KieBuilder; -import org.kie.api.builder.KieFileSystem; -import org.kie.api.builder.KieRepository; -import org.kie.api.io.KieResources; -import org.kie.api.runtime.KieContainer; -import org.kie.api.runtime.KieSession; import org.onap.holmes.common.api.entity.AlarmInfo; import org.onap.holmes.common.api.entity.CorrelationRule; import org.onap.holmes.common.api.stat.VesAlarm; -import org.onap.holmes.common.constant.AlarmConst; import org.onap.holmes.common.exception.CorrelationException; import org.onap.holmes.common.utils.DbDaoUtil; import org.onap.holmes.engine.db.AlarmInfoDao; @@ -41,10 +32,12 @@ import org.onap.holmes.engine.wrapper.RuleMgtWrapper; import org.powermock.api.easymock.PowerMock; import org.powermock.reflect.Whitebox; -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.*; +import java.util.stream.Collectors; +import static org.easymock.EasyMock.anyObject; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.core.IsEqual.equalTo; import static org.junit.Assert.assertThat; @@ -56,135 +49,108 @@ public class DroolsEngineTest { private RuleMgtWrapper ruleMgtWrapper; - private KieBase kieBase; - private KieSession kieSession; - private KieContainer kieContainer; - private KieFileSystem kfs; - private KieServices ks; - private KieBuilder kieBuilder; - private KieResources resources; - private KieRepository kieRepository; - private AlarmInfoDao alarmInfoDaoMock; private DroolsEngine droolsEngine; - private DbDaoUtil dbDaoUtilMock; + private DbDaoUtil dbDaoUtilStub; - @Before - public void setUp() throws Exception { + public DroolsEngineTest() throws Exception { droolsEngine = new DroolsEngine(); + ruleMgtWrapper = new RuleMgtWrapperStub(); + dbDaoUtilStub = new DbDaoUtilStub(); + Whitebox.setInternalState(droolsEngine, "daoUtil", dbDaoUtilStub); + Whitebox.setInternalState(droolsEngine, "ruleMgtWrapper", ruleMgtWrapper); + Whitebox.invokeMethod(droolsEngine, "init"); + } - ks = KieServices.Factory.get(); - resources = ks.getResources(); - kieRepository = ks.getRepository(); - kfs = Whitebox.invokeMethod(droolsEngine, "createKieFileSystemWithKProject", ks); - kieBuilder = ks.newKieBuilder(kfs).buildAll(); - kieContainer = ks.newKieContainer(kieRepository.getDefaultReleaseId()); - kieBase = kieContainer.getKieBase(); - kieSession = kieContainer.newKieSession(); - - alarmInfoDaoMock = PowerMock.createMock(AlarmInfoDao.class); - dbDaoUtilMock = PowerMock.createMock(DbDaoUtil.class); - - - Whitebox.setInternalState(droolsEngine, "kieBase", kieBase); - Whitebox.setInternalState(droolsEngine, "kieSession", kieSession); - Whitebox.setInternalState(droolsEngine, "kieContainer", kieContainer); - Whitebox.setInternalState(droolsEngine, "kfs", kfs); - Whitebox.setInternalState(droolsEngine, "ks", ks); - Whitebox.setInternalState(droolsEngine, "kieBuilder", kieBuilder); - Whitebox.setInternalState(droolsEngine, "resources", resources); - Whitebox.setInternalState(droolsEngine, "kieRepository", kieRepository); - - Whitebox.setInternalState(droolsEngine, "daoUtil", dbDaoUtilMock); - Whitebox.setInternalState(droolsEngine, "alarmInfoDao", alarmInfoDaoMock); - + @Before + public void setUp() throws Exception { PowerMock.resetAll(); } @Test - public void init() throws Exception { - - List rules = new ArrayList(); - CorrelationRule rule = new CorrelationRule(); - rule.setContent("package content"); - rule.setClosedControlLoopName("test"); - rule.setPackageName("org.onap.holmes"); - rules.add(rule); - -// expect(ruleMgtWrapper.queryRuleByEnable(anyInt())).andReturn(rules); - List alarmInfoList = new ArrayList(); - EasyMock.expect(dbDaoUtilMock.getJdbiDaoByOnDemand(AlarmInfoDao.class)).andReturn(alarmInfoDaoMock).anyTimes(); - EasyMock.expect(alarmInfoDaoMock.queryAllAlarm()).andReturn(alarmInfoList).anyTimes(); - PowerMock.replayAll(); - - PowerMock.verifyAll(); + public void deployRule_rule_is_null() throws CorrelationException { + thrown.expect(NullPointerException.class); + droolsEngine.deployRule(null); } @Test - public void deployRule_rule_is_null() throws CorrelationException { - Locale locale = PowerMock.createMock(Locale.class); - - thrown.expect(NullPointerException.class); + public void deployRule_invalid_rule_no_pkg_name() throws CorrelationException { + DeployRuleRequest rule = new DeployRuleRequest(); + rule.setContent("rule123;"); + thrown.expect(CorrelationException.class); + thrown.expectMessage("The package name can not be empty."); - droolsEngine.deployRule(null, locale); + droolsEngine.deployRule(rule); } @Test - public void deployRule_kbuilder_has_errors() throws CorrelationException { + public void deployRule_invalid_rule_illegal_contents() throws CorrelationException { DeployRuleRequest rule = new DeployRuleRequest(); - rule.setContent("rule123"); - Locale locale = new Locale(AlarmConst.I18N_EN); - + rule.setContent("package rule123; a random string"); thrown.expect(CorrelationException.class); - droolsEngine.deployRule(rule, locale); + droolsEngine.deployRule(rule); } @Test public void deployRule_package_name_repeat() throws CorrelationException { DeployRuleRequest rule = new DeployRuleRequest(); rule.setContent("package rule123"); - Locale locale = new Locale(AlarmConst.I18N_EN); thrown.expect(CorrelationException.class); - - droolsEngine.deployRule(rule, locale); - droolsEngine.deployRule(rule, locale); + thrown.expectMessage("A rule with the same package name already exists in the system."); + droolsEngine.deployRule(rule); + droolsEngine.deployRule(rule); } @Test public void undeployRule_package_name_is_null() throws CorrelationException { String packageName = null; - Locale locale = new Locale(AlarmConst.I18N_EN); - thrown.expect(CorrelationException.class); + thrown.expectMessage("The package name should not be null."); - droolsEngine.undeployRule(packageName, locale); + droolsEngine.undeployRule(packageName); } @Test public void undeployRule_normal() throws CorrelationException { - Locale locale = new Locale(AlarmConst.I18N_EN); - DeployRuleRequest rule = new DeployRuleRequest(); rule.setContent("package rule123"); - droolsEngine.deployRule(rule, locale); + droolsEngine.deployRule(rule); + droolsEngine.undeployRule("rule123"); + } - String packageName = "rule123"; + @Test + public void compileRule_compilation_failure() throws CorrelationException { + String content = "invalid contents"; - droolsEngine.undeployRule(packageName, locale); + thrown.expect(CorrelationException.class); + + droolsEngine.compileRule(content); } @Test - public void compileRule_kbuilder_has_errors() throws CorrelationException { - String content = "have error content"; - Locale locale = new Locale(AlarmConst.I18N_EN); - + public void compileRule_compilation_deployed_rule() throws CorrelationException { + String content = "package deployed;"; + DeployRuleRequest rule = new DeployRuleRequest(); + rule.setContent(content); + rule.setLoopControlName(UUID.randomUUID().toString()); thrown.expect(CorrelationException.class); - droolsEngine.compileRule(content, locale); + droolsEngine.deployRule(rule); + droolsEngine.compileRule(content); + } + + @Test + public void compileRule_compilation_normal() throws CorrelationException { + String content = "package deployed;"; + DeployRuleRequest rule = new DeployRuleRequest(); + rule.setContent(content); + rule.setLoopControlName(UUID.randomUUID().toString()); + + droolsEngine.compileRule(content); } @Test @@ -221,9 +187,7 @@ public class DroolsEngineTest { alarmInfo.setRootFlag(0); alarmInfo.setAlarmIsCleared(1); - PowerMock.replayAll(); - VesAlarm vesAlarm = Whitebox.invokeMethod(droolsEngine,"convertAlarmInfo2VesAlarm",alarmInfo); - PowerMock.verifyAll(); + VesAlarm vesAlarm = Whitebox.invokeMethod(droolsEngine, "convertAlarmInfo2VesAlarm", alarmInfo); assertThat(vesAlarm.getAlarmIsCleared(), is(1)); assertThat(vesAlarm.getSourceName(), equalTo("sourceName")); @@ -234,4 +198,114 @@ public class DroolsEngineTest { assertThat(vesAlarm.getEventId(), equalTo("eventId")); assertThat(vesAlarm.getRootFlag(), is(0)); } + + @Test + public void testConvertVesAlarm2AlarmInfo() throws Exception { + VesAlarm vesAlarm = new VesAlarm(); + vesAlarm.setEventId("eventId"); + vesAlarm.setEventName("eventName"); + vesAlarm.setStartEpochMicrosec(1L); + vesAlarm.setLastEpochMicrosec(1L); + vesAlarm.setSourceId("sourceId"); + vesAlarm.setSourceName("sourceName"); + vesAlarm.setRootFlag(0); + vesAlarm.setAlarmIsCleared(1); + + AlarmInfo alarmInfo = Whitebox.invokeMethod(droolsEngine, "convertVesAlarm2AlarmInfo", vesAlarm); + + assertThat(alarmInfo.getAlarmIsCleared(), is(1)); + assertThat(alarmInfo.getSourceName(), equalTo("sourceName")); + assertThat(alarmInfo.getSourceId(), equalTo("sourceId")); + assertThat(alarmInfo.getStartEpochMicroSec(), is(1L)); + assertThat(alarmInfo.getLastEpochMicroSec(), is(1L)); + assertThat(alarmInfo.getEventName(), equalTo("eventName")); + assertThat(alarmInfo.getEventId(), equalTo("eventId")); + assertThat(alarmInfo.getRootFlag(), is(0)); + } + + @Test + public void testQueryPackagesFromEngine() throws CorrelationException { + + DeployRuleRequest rule = new DeployRuleRequest(); + rule.setContent("package packageCheck; rule \"test\" when eval(1==1) then System.out.println(1); end"); + rule.setLoopControlName(UUID.randomUUID().toString()); + + droolsEngine.deployRule(rule); + + List packages = droolsEngine.queryPackagesFromEngine(); + + assertThat(packages.contains("packageCheck"), is(true)); + } +} + +class RuleMgtWrapperStub extends RuleMgtWrapper { + private List rules; + + public RuleMgtWrapperStub() { + rules = new ArrayList<>(); + CorrelationRule rule = new CorrelationRule(); + rule.setEnabled(1); + rule.setContent("package org.onap.holmes;"); + rule.setPackageName("UT"); + rule.setClosedControlLoopName(UUID.randomUUID().toString()); + rules.add(rule); + } + + public List getRules() { + return rules; + } + + public void setRules(List rules) { + this.rules = rules; + } + + @Override + public List queryRuleByEnable(int enabled) throws CorrelationException { + return rules.stream().filter(rule -> rule.getEnabled() == enabled).collect(Collectors.toList()); + } +} + +class AlarmInfoDaoStub extends AlarmInfoDao { + + private List alarms; + + public AlarmInfoDaoStub() { + alarms = new ArrayList<>(); + AlarmInfo info = new AlarmInfo(); + info.setEventId("eventId"); + info.setEventName("eventName"); + info.setStartEpochMicroSec(1L); + info.setLastEpochMicroSec(1L); + info.setSourceId("sourceId"); + info.setSourceName("sourceName"); + info.setRootFlag(0); + info.setAlarmIsCleared(1); + alarms.add(info); + } + + @Override + protected String addAlarm(AlarmInfo alarmInfo) { + alarms.add(alarmInfo); + return null; + } + + @Override + protected List queryAlarm() { + return alarms; + } + + @Override + protected int deleteAlarmByAlarmIsCleared(int alarmIsCleared) { + return 1; + } +} + +class DbDaoUtilStub extends DbDaoUtil { + private AlarmInfoDao dao = new AlarmInfoDaoStub(); + @Override + public T getJdbiDaoByOnDemand(Class daoClazz) { + + return (T)dao; + + } } diff --git a/engine-d/src/test/java/org/onap/holmes/engine/resources/EngineResourcesTest.java b/engine-d/src/test/java/org/onap/holmes/engine/resources/EngineResourcesTest.java index 6be232f..a09eb3a 100644 --- a/engine-d/src/test/java/org/onap/holmes/engine/resources/EngineResourcesTest.java +++ b/engine-d/src/test/java/org/onap/holmes/engine/resources/EngineResourcesTest.java @@ -44,7 +44,7 @@ public class EngineResourcesTest { droolsEngine = PowerMock.createMock(DroolsEngine.class); engineResources = new EngineResources(); - Whitebox.setInternalState(engineResources,"droolsEngine",droolsEngine); + Whitebox.setInternalState(engineResources,"droolsEngine", droolsEngine); PowerMock.resetAll(); } @@ -56,7 +56,7 @@ public class EngineResourcesTest { thrown.expect(WebApplicationException.class); expect(httpRequest.getHeader("language-option")).andReturn("en_US"); - expect(droolsEngine.deployRule(anyObject(DeployRuleRequest.class), anyObject(Locale.class))). + expect(droolsEngine.deployRule(anyObject(DeployRuleRequest.class))). andThrow(new CorrelationException("")); PowerMock.replayAll(); engineResources.deployRule(deployRuleRequest, httpRequest); @@ -71,8 +71,7 @@ public class EngineResourcesTest { HttpServletRequest httpRequest = PowerMock.createMock(HttpServletRequest.class); expect(httpRequest.getHeader("language-option")).andReturn("en_US"); - expect(droolsEngine.deployRule(anyObject(DeployRuleRequest.class), - anyObject(Locale.class))).andReturn("packageName"); + expect(droolsEngine.deployRule(anyObject(DeployRuleRequest.class))).andReturn("packageName"); PowerMock.replayAll(); engineResources.deployRule(deployRuleRequest, httpRequest); PowerMock.verifyAll(); @@ -86,7 +85,7 @@ public class EngineResourcesTest { thrown.expect(WebApplicationException.class); expect(httpRequest.getHeader("language-option")).andReturn("en_US"); - droolsEngine.undeployRule(anyObject(String.class), anyObject(Locale.class)); + droolsEngine.undeployRule(anyObject(String.class)); expectLastCall().andThrow(new CorrelationException("")); PowerMock.replayAll(); engineResources.undeployRule(packageName, httpRequest); @@ -99,7 +98,7 @@ public class EngineResourcesTest { HttpServletRequest httpRequest = PowerMock.createMock(HttpServletRequest.class); expect(httpRequest.getHeader("language-option")).andReturn("en_US"); - droolsEngine.undeployRule(anyObject(String.class), anyObject(Locale.class)); + droolsEngine.undeployRule(anyObject(String.class)); PowerMock.replayAll(); engineResources.undeployRule(packageName, httpRequest); PowerMock.verifyAll(); @@ -113,7 +112,7 @@ public class EngineResourcesTest { thrown.expect(WebApplicationException.class); expect(httpRequest.getHeader("language-option")).andReturn("en_US"); - droolsEngine.compileRule(anyObject(String.class),anyObject(Locale.class)); + droolsEngine.compileRule(anyObject(String.class)); expectLastCall().andThrow(new CorrelationException("")); PowerMock.replayAll(); engineResources.compileRule(compileRuleRequest, httpRequest); @@ -126,7 +125,7 @@ public class EngineResourcesTest { HttpServletRequest httpRequest = PowerMock.createMock(HttpServletRequest.class); expect(httpRequest.getHeader("language-option")).andReturn("en_US"); - droolsEngine.compileRule(anyObject(String.class),anyObject(Locale.class)); + droolsEngine.compileRule(anyObject(String.class)); PowerMock.replayAll(); engineResources.compileRule(compileRuleRequest, httpRequest); PowerMock.verifyAll(); -- 2.16.6