A Code Walkthrough of Holmes Rule Management
Understanding major lines of the source code of a component surely helps one to understand how it works, but it may take a lot of effort. This page walks you through the source code of Holmes Rule Management, in the hope to
Help you to understand how things work internally.
Help people working with the code to grasp the main plot.
You can check out the source code from ONAP gerrit. There are two sub modules, rulemgt-standalone and rulemgt. rulemgt-standalone is for packaging rulemgt into a Docker image, while rulemgt has all the business logic.
Setup Docker Image
Holmes Rule Management can run in a Docker container. In folder /rulemgt-standalone/src/main/assembly/, Dockerfile is used to pack the Docker image. During the packing, PostgreSQL client is installed, for accessing rule database. Docker ENTRYPOINT is bin/run.sh, where conf/rulemgt.yml is used to inject parameters to Dropwizard configuration, org.onap.holmes.rulemgt.RuleAppConfig, which is then passed to org.onap.holmes.rulemgt.RuleActiveApp. RuleActiveApp, a Dropwizard application, is the entrance point to Holmes Rule Management application. Dropwizard is an open source Java framework for developing RESTful web services, like Spring Boot.
Four Things Happen in RuleActiveApp
Register Holmes Rule Management service to MSB.
Set up a servlet filter to generate unique transaction ids for REST requests.
Setup a background task to periodically (every 30 seconds) check if there is any rule change in DCAE configuration.
Register a REST resource to Dropwizard environment to serve REST APIs.
The following sections will go into details on these four aspects.
Register to MSB (Microservices Bus)
It is required that env variable HOSTNAME is provided. Rule Management service host and port are obtained from Consul by passing in HOSTNAME (in org.onap.holmes.common.config.MicroServiceConfig.getMicroServiceIpAndPort()):
http://{CONSUL_HOST}:8500/v1/catalog/service/{HOSTNAME} ,
where CONSUL_HOST is defined in env as well.
Host and port are then submitted to MSB, along with: (in RuleActiveApp)
msinfo.setServiceName("holmes-rule-mgmt");
msinfo.setVersion("v1");
msinfo.setUrl("/api/holmes-rule-mgmt/v1");
msinfo.setProtocol("REST");
msinfo.setVisualRange("0|1");
msinfo.setEnable_ssl(true);
Transaction ID Servlet Filter
Servlet filter TransactionIdFilter is setup to intercepts all HTTP requests. (In RuleActiveApp)
If header “X-TransactionID" does not present in a HTTP request, the filter generates a random UUID and insert it to request header “X-TransactionID".
When sending responses to HTTP clients, response header “X-TransactionID" is set with the above value, and a new UUID is generated for another header, "X-InvocationID". (In TransactionIdFilter).
DCAE Configuration Polling
A thread is forked using JDK Executors.newSingleThreadScheduledExecutor(), and the forked task, org.onap.holmes.rulemgt.dcae.DcaeConfigurationPolling, runs at an interval of 30 seconds. (In RuleActiveApp)
Config Binding Service (CBS) endpoint is obtained from DCAE Consul: (In org.onap.holmes.common.config.MicroServiceConfig)
http://{CONSUL_HOST}:8500/v1/catalog/service/{CONFIG_BINDING_SERVICE}
From CBS, configuration info on HOSTNAME is obtained through: (In MicroServiceConfig.getServiceConfigInfoFromCBS())
http://{CBS ServiceAddress}:{CBS ServicePort}/service_component/{HOSTNAME}
The configuration data from CBS is in JSON format, and is parsed by DcaeConfigurationParser. The result is a DcaeConfigurations object, which contains rules, DMaaP Publisher topics, and DMaaP Subscriber topics. (In DcaeConfigurationParser.parse())
If the DcaeConfigurations has update (by checking its MD5 against the previous version), all existing rules are wiped out, and a rule is generated for each rule in DcaeConfigurations. All the rule operations are done through the Rule Management REST APIs discussed in the next section. (In DcaeConfigurationPolling.run())
Rule Management REST API
Like Spring Boot Controllers, Dropwizard Jersey resources are the entrance points of web services. RuleMgtResources is a such resource that provides all Rule Management REST APIs, and has the following services:
Creating a Rule
This service saves a rule into the database, and deploys it to the Drools rule engine if it is enabled. The HTTP request should be in such format:
PUT /api/holmes-rule-mgmt/v1/rule
{"ruleName": "Alarm Compression",
"loopControlName": "Control Loop Name",
"description"(optional): "This is the description of the rule.",
"content": "template header\n ruleId\n package packageName...",
"enabled": 0|1}
This request is handled by RuleMgtResources.addCorrelationRule(), where the “content” in the HTTP body is used as the rule. The rule is deployed to the Doorls rule engine via Holmes Engine Management REST API, and is saved to database table APLUS_RULE. On successfully deploying the rule, the rule ID is returned to the client. Note that if a rule with the same name already exists in database, the deployment will fail, and an error message "A rule with the same name already exists." is returned to the client.Modifying a Rule
This service updates an existing rule, and deploys it to the Drools engine if it is enabled. The HTTP request should be in such format:
POST /api/holmes-rule-mgmt/v1/rule
{“ruleId": "ruleid0937261",
"loopControlName": "Control Loop Name",
"description"(optional): "This is the description of the rule.",
"content": "template header\n ruleId\n package packageName...",
"enabled": 0|1}
This request is handled by RuleMgtResources.updateCorrelationRule(), where the “content” in the HTTP body is used as the new rule. The old rule is retrieved from database table APLUS_RULE using the rule ID. If the new rule is the same as the old, nothing will be done and the rule ID is returned to the client; else, the old rule is deleted from the Doorls rule engine, and the new rule is saved to database and is deployed to rule engine if it is enabled. Both rule operations (delete and deploy) are done through Holmes Engine Management REST API. At the end the rule ID is returned to the client.Deleting a Rule
This service removes a rule from Holmes. The HTTP request should be in such format:
DELETE /api/holmes-rule-mgmt/v1/rule/{ruleid}
where {ruleid} is the rule ID, which is used to delete the rule from database and the Doorls rule engine (via Holmes Engine Management REST API).Querying Rules
This service queries rules using certain criteria. The HTTP request should be in such format:
DELETE /api/holmes-rule-mgmt/v1/rule/queryrequest={“ruleid": "ruleid0937261","rulename": "Alarm Compression","creator":"creator name","modifier":"modifier name","enabled":=0}
where all the query parameters are optional. This request is handled by RuleMgtResources.getCorrelationRules(), where the query parameters are used to query the database for matching rules. In the SQL query, rulename is wildcat match, the rest is exact match.
Here is a sample result returned to the client:{
"correlationRules": [
{
"ruleId": "ruleid098271",
"ruleName": "Alarm Compression",
"description": "The description of the rule.",
"content": "template header\n ruleId\n package packageName...",
"createTime": 1484188925231,
"creator": "admin",
"updateTime": 1485188925231,
"modifier": "user1",
"enabled": 0}
],
"totalCount": 1
}
Note that this service does not query the rule engine, all information is from database.
rulemgt/src/main/resources/swagger.json is the OpenAPI Specification (OAS) file that describes all the above APIs. This wiki page has the complete spec of these REST APIs.