...
}
}
Establish
...
Persistent Connection
Functionality
Collector establishes long term connectivity persistent connection with SOTN Controller and the controller will continuously Push the subscribed notification over.
...
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
version: '2.1'
services:
restconfcollector:
image: "restconfcollector"
container_name: "restconf_collector"
restart: "always"
hostname: "restconf-collector"
labels:
- "SERVICE_NAME=restconf_collector"
|
Blueprint for Holmes Rule Manager
...
Rule Creation
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
{ "ruleName": "CCVPN", "loopControlNamecontent": "ControlLoop-CCVPN-2179b738-fd36-4843-a71a-a8c24c70c55b", "description": "This rule is designed for the correlation analysis for the CCVPN use case.", "content": "package "package org.onap.holmes.ccvpn;\n\ndialect \"java\"\n\nimport org.onap.holmes.droolsRule;\ncommon.api.stat.VesAlarm;\nimport org.onap.holmes.common.api.dmaapstat.DmaapServiceAlarmAdditionalField;\nimport org.onap.holmes.common.apiaai.stat.VesAlarmAaiQuery4Ccvpn;\nimport org.onap.holmes.common.aaiexception.CorrelationUtilCorrelationException;\nimport org.onap.holmes.common.dmaap.entity.PolicyMsg;\nimport org.onap.holmes.common.dropwizard.ioc.dmaap.DmaapService;\nimport org.onap.holmes.common.utils.ServiceLocatorHolderDroolsLog;\nimport org.onap.holmes.common.dropwizard.ioc.utils.DroolsLogServiceLocatorHolder;\n \n\nrule \"Relation_analysis_Rule\"\nsalience 200\nno-loop true\n when\n $root : VesAlarm(alarmIsCleared == 0,\n $sourceId: sourceId, sourceId != null && !sourceId.equals(\"\"),\n\t\t\t$sourceName: sourceName, sourceName != null && !sourceName.equals(\"\"),\n\t\t\t$startEpochMicrosec: startEpochMicrosec,\n specificProblem in (\"Fault_SOTN_Service_Failure\"),\n $eventId: eventId)\n $child : VesAlarm( eventId != $eventId, parentId == null,\n specificProblem in (\"Fault_SOTN_Service_Failure\"),\n startEpochMicrosec < $startEpochMicrosec + 60000 && startEpochMicrosec > $startEpochMicrosec - 60000 )\n then\n\t\t$child.setParentId($root.getEventId());\n\t\tupdate($child);\n\t\t\nend\n\nrule \"root_has_child_handle_Rule\"\nsalience 150\nno-loop true\n\twhen\n\t\t$root : VesAlarm(alarmIsCleared == 0, rootFlag == 0, $eventId: eventId)\n\t\t$child : VesAlarm(eventId != $eventId, parentId == $eventId)\n\tthen\n\t\tDmaapService dmaapService = ServiceLocatorHolder.getLocator().getService(DmaapService.class);\n\t\tPolicyMsg policyMsg = dmaapService.getPolicyMsg($root, $child, \"org.onap.holmes.droolsRule\");\n dmaapService.publishPolicyMsg(policyMsg, \"unauthenticated.DCAE_CL_OUTPUT\");\n\t\t$root.setRootFlag(1);\n\t\tupdate($root);\nend\n\nrule \"root_no_child_handle_Rule\"\nsalience 100\nno-loop true\n when\n $root : VesAlarm(alarmIsCleared == 0, rootFlag == 0,\n sourceId != null && !sourceId.equals(\"\"),\n\t\t\tsourceName != null && !sourceName.equals(\"\"),\n specificProblem in (\"Fault_SOTN_Service_Failure\"))\n then\n\t\tDmaapService dmaapService = ServiceLocatorHolder.getLocator().getService(DmaapService.class);\n\t\tPolicyMsg policyMsg = dmaapService.getPolicyMsg($root, null, \"org.onap.holmes.droolsRule\");\n dmaapService.publishPolicyMsg(policyMsg, \"unauthenticated.DCAE_CL_OUTPUT\");\n\t\t$root.setRootFlag(1);\n\t\tupdate($root);\nend\n\nrule \"root_cleared_handle_Rule\"\nsalience 100\nno-loop true\n when\n $root : VesAlarm(alarmIsCleared == 1, rootFlag == 1)\n then\n\t\tDmaapService dmaapService = ServiceLocatorHolder.getLocator().getService(DmaapService.class);\n\t\tPolicyMsg policyMsg = dmaapService.getPolicyMsg($root, null, \"org.onap.holmes.droolsRule\");\n dmaapService.publishPolicyMsg(policyMsg, \"unauthenticated.DCAE_CL_OUTPUT\");\n\t\tretract($root);\nend\n\nrule \"child_handle_Rule\"\nsalience 100\nno-loop true\n when\n $child : VesAlarm(alarmIsCleared == 1, rootFlag == 0)\n then\n\t\tretract($child);\nend", "enabled": 1 } |
To illustrate, the content field in the above rule is presented as readable format in the following. We need to convert it to valid json string when uploading to Holmes.
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
package org.onap.holmes.ccvpn;
dialect "java"
import org.onap.holmes.common.api.stat.VesAlarm;
import org.onap.holmes.common.api.stat.AlarmAdditionalField;
import org.onap.holmes.common.aai.AaiQuery4Ccvpn;
import org.onap.holmes.common.exception.CorrelationException;
import org.onap.holmes.common.dmaap.entity.PolicyMsg;
import org.onap.holmes.common.dmaap.DmaapService;
import org.onap.holmes.common.utils.DroolsLog;
import org.onap.holmes.common.dropwizard.ioc.utils.ServiceLocatorHolder;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import java.util.List;
import java.util.Map;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.UUID;
function String getAdditionalField(VesAlarm a, String field) {
List<AlarmAdditionalField> fields = a.getAlarmAdditionalInformation();
for (AlarmAdditionalField f : fields) {
if (f.getName().equals(field)) {
return f.getValue();
}
}
return null;
}
function String getLogicLink(VesAlarm alarm) {
AaiQuery4Ccvpn aai = AaiQuery4Ccvpn.newInstance();
return aai.getLogicLink(
getAdditionalField(alarm, "networkId"),
getAdditionalField(alarm, "node"),
getAdditionalField(alarm, "tp-id"),
getAdditionalField(alarm, "oper-status")
);
}
function boolean isCorrelated(VesAlarm a, VesAlarm b) {
String logicLinkA = getLogicLink(a);
if (logicLinkA == null) {
return false;
}
String logicLinkB = getLogicLink(b);
if (logicLinkB == null) {
return false;
}
return logicLinkA.equals(logicLinkB);
}
function void updateAaiStatus(String networkId, String pnfName, String ifName,
String linkName, String status) {
AaiQuery4Ccvpn aai = AaiQuery4Ccvpn.newInstance();
Map<String, Object> body = new HashMap<String, Object>(){
{
put("operational-status", status);
}
};
aai.updateLogicLinkStatus(linkName, body);
aai.updateTerminalPointStatus(networkId, pnfName, ifName, body);
}
function Map<String, Object> getAdditionalResourceInfo(String networkId, String pnfName, String ifName, String status) {
AaiQuery4Ccvpn aai = AaiQuery4Ccvpn.newInstance();
JSONArray instances = aai.getServiceInstances(networkId, pnfName, ifName, status);
Map<String, Object> ret = new HashMap<String, Object>();
StringBuilder sb = new StringBuilder();
for(int i = 0; i < instances.size(); ++i) {
JSONObject o = instances.getJSONObject(i);
String name = o.getString("service-instance-name");
ret.put(name + ".input-parameters", o.getString("input-parameters"));
sb.append(name).append(",");
}
ret.put("service-instance.service-instance-name", sb.substring(0, sb.length() -1).toString());
ret.put("vserver.vserver-name", "TBD");
ret.put("globalSubscriberId", instances.getJSONObject(0).getString("globalSubscriberId"));
ret.put("serviceType", instances.getJSONObject(0).getString("serviceType"));
return ret;
}
function PolicyMsg createPolicyMsg(VesAlarm alarm) {
PolicyMsg m = new PolicyMsg();
m.setPolicyVersion("1.0.0.5");
m.setPolicyName("CCVPN");
m.setPolicyScope("service=SOTNService,type=SampleType,closedLoopControlName=CL-CCVPN-d925ed73-8231-4d02-9545-db4e101f88f8");
m.setClosedLoopControlName(DmaapService.loopControlNames.get("org.onap.holmes.ccvpn"));
m.setRequestID(UUID.randomUUID().toString());
m.setClosedLoopAlarmStart(alarm.getStartEpochMicrosec());
m.setClosedLoopAlarmEnd(alarm.getLastEpochMicrosec());
m.setTarget("vserver.vserver-name");
m.setAai(getAdditionalResourceInfo(
getAdditionalField(alarm, "networkId"),
getAdditionalField(alarm, "node"),
getAdditionalField(alarm, "tp-id"),
getAdditionalField(alarm, "oper-status")
));
DmaapService.alarmUniqueRequestID.put(alarm.getEventId(), m.getRequestID());
return m;
}
rule "Update AAI Information"
no-loop true
salience 300
when
$a: VesAlarm(eventName.indexOf("Fault_Route_Status") != -1)
then
updateAaiStatus (
getAdditionalField($a, "networkId"),
getAdditionalField($a, "node"),
getAdditionalField($a, "tp-id"),
getLogicLink($a),
getAdditionalField($a, "oper-status")
);
end
rule "Set Up Correlation"
no-loop true
salience 200
when
$a: VesAlarm($id: eventId,
$start: startEpochMicrosec,
eventName.indexOf("Fault_Route_Status") != -1)
$b: VesAlarm(eventId != $id,
eventName.indexOf("Fault_Route_Status") != -1,
Math.abs(startEpochMicrosec - $start) < 60000)
then
if ("down".equalsIgnoreCase(getAdditionalField($a, "oper-status"))
&& "down".equalsIgnoreCase(getAdditionalField($b, "oper-status"))) {
if (isCorrelated($a, $b)){
// If any of the alarms have been marked as root, a policy message has ever been created and sent. Do NOT send it again.
if ($a.getRootFlag() != 1 && $b.getRootFlag() != 1) {
PolicyMsg msg = createPolicyMsg($a);
DmaapService dmaapService = ServiceLocatorHolder.getLocator().getService(DmaapService.class);
dmaapService.publishPolicyMsg(msg, "unauthenticated.DCAE_CL_OUTPUT");
}
$a.setRootFlag(1);
$b.setRootFlag(1);
update($a);
update($b);
}
}
end
rule "Clear Alarms"
no-loop true
salience 100
when
$a: VesAlarm(eventName.indexOf("Fault_Route_Status") != -1)
then
if ("up".equalsIgnoreCase(getAdditionalField($a, "oper-status"))) {
if (DmaapService.alarmUniqueRequestID.containsKey($a.getEventId())) {
DmaapService.alarmUniqueRequestID.remove($a.getEventId());
}
//TODO: send alarm clearing message to Policy - for now it's not needed.
//...
retract($a);
}
end |
Rule Execution
After the correlation is done successfully, there should be a corresponding control loop event defined in the following section published on the unauthenticated.DCAE_CL_OUTPUT topic of DMaaP.
POLICY
Policy Creation
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
controlLoop:
version: 2.0.0
controlLoopName: ControlLoop-CCVPN-2179b738-fd36-4843-a71a-a8c24c70c55b
trigger_policy: unique-policy-id-16-receateE2EService
timeout: 3600
abatement: false
policies:
- id: unique-policy-id-16-recreateE2EService
name: Recreate E2E Service
description:
actor: SO
recipe: Recreate_E2E_Service
target:
type: VM
retry: 3
timeout: 1200
success: final_success
failure: final_failure
failure_timeout: final_failure_timeout
failure_retries: final_failure_retries
failure_exception: final_failure_exception
failure_guard: final_failure_guard
|
nimport com.alibaba.fastjson.JSONArray;\nimport com.alibaba.fastjson.JSONObject;\n\nimport java.util.List;\nimport java.util.Map;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.UUID;\n\nfunction String getAdditionalField(VesAlarm a, String field) {\n List<AlarmAdditionalField> fields = a.getAlarmAdditionalInformation();\n for (AlarmAdditionalField f : fields) {\n if (f.getName().equals(field)) {\n return f.getValue();\n }\n }\n return null;\n}\n\nfunction String getLogicLink(VesAlarm alarm) {\n AaiQuery4Ccvpn aai = AaiQuery4Ccvpn.newInstance();\n return aai.getLogicLink(\n getAdditionalField(alarm, \"networkId\"),\n getAdditionalField(alarm, \"node\"),\n getAdditionalField(alarm, \"tp-id\"),\n null\n );\n}\n\nfunction boolean isCorrelated(VesAlarm a, VesAlarm b) {\n String logicLinkA = getLogicLink(a);\n if (logicLinkA == null) {\n return false;\n }\n\n String logicLinkB = getLogicLink(b);\n if (logicLinkB == null) {\n return false;\n }\n\n return logicLinkA.equals(logicLinkB);\n}\n\nfunction void updateAaiLinkStatus(String linkName, String status) {\n AaiQuery4Ccvpn aai = AaiQuery4Ccvpn.newInstance();\n Map<String, Object> body = new HashMap<String, Object>(){\n {\n put(\"operational-status\", status);\n }\n };\n aai.updateLogicLinkStatus(linkName, body);\n}\n\nfunction void updateAaiTpStatus(String networkId, String pnfName, String ifName, String status) {\n AaiQuery4Ccvpn aai = AaiQuery4Ccvpn.newInstance();\n Map<String, Object> body = new HashMap<String, Object>(){\n {\n put(\"operational-status\", status);\n }\n };\n aai.updateTerminalPointStatus(networkId, pnfName, ifName, body);\n}\n\nfunction Map<String, Object> getAdditionalResourceInfo(String networkId, String pnfName, String ifName, String status) {\n AaiQuery4Ccvpn aai = AaiQuery4Ccvpn.newInstance();\n JSONArray instances = aai.getServiceInstances(networkId, pnfName, ifName, status);\n\n Map<String, Object> ret = new HashMap<String, Object>();\n\n StringBuilder sbn = new StringBuilder();\n StringBuilder sbi = new StringBuilder();\n for(int i = 0; i < instances.size(); ++i) {\n JSONObject o = instances.getJSONObject(i);\n String name = o.getString(\"service-instance-name\");\n String id = o.getString(\"service-instance-id\");\n ret.put(id + \".input-parameters\", o.getString(\"input-parameters\"));\n sbn.append(name).append(\",\");\n sbi.append(id).append(\",\");\n }\n ret.put(\"service-instance.service-instance-name\", sbn.substring(0, sbn.length() -1).toString());\n ret.put(\"service-instance.service-instance-id\", sbi.substring(0, sbi.length() -1).toString());\n ret.put(\"vserver.vserver-name\", \"TBD\");\n ret.put(\"globalSubscriberId\", instances.getJSONObject(0).getString(\"globalSubscriberId\"));\n ret.put(\"serviceType\", instances.getJSONObject(0).getString(\"serviceType\"));\n\n return ret;\n}\n\nfunction PolicyMsg createPolicyMsg(VesAlarm alarm) {\n PolicyMsg m = new PolicyMsg();\n m.setPolicyVersion(\"1.0.0.5\");\n m.setPolicyName(\"CCVPN\");\n m.setPolicyScope(\"service=SOTNService,type=SampleType,closedLoopControlName=CL-CCVPN-d925ed73-8231-4d02-9545-db4e101f88f8\");\n m.setClosedLoopControlName(DmaapService.loopControlNames.get(\"org.onap.holmes.ccvpn\"));\n m.setRequestID(UUID.randomUUID().toString());\n m.setClosedLoopAlarmStart(alarm.getStartEpochMicrosec());\n m.setClosedLoopAlarmEnd(alarm.getLastEpochMicrosec());\n m.setTarget(\"vserver.vserver-name\");\n m.setAai(getAdditionalResourceInfo(\n getAdditionalField(alarm, \"networkId\"),\n getAdditionalField(alarm, \"node\"),\n getAdditionalField(alarm, \"tp-id\"),\n getAdditionalField(alarm, \"oper-status\")\n ));\n\n DmaapService.alarmUniqueRequestID.put(alarm.getEventId(), m.getRequestID());\n\n return m;\n}\n\nrule \"Update AAI Information\"\n no-loop true\n salience 300\n when\n $a: VesAlarm(eventName.indexOf(\"Fault_Route_Status\") != -1)\n then\n updateAaiTpStatus (\n getAdditionalField($a, \"networkId\"),\n getAdditionalField($a, \"node\"),\n getAdditionalField($a, \"tp-id\"),\n getAdditionalField($a, \"oper-status\")\n );\nend\n\nrule \"Set Up Correlation\"\n no-loop true\n salience 200\n when\n $a: VesAlarm($id: eventId, \n $start: startEpochMicrosec, \n eventName.indexOf(\"Fault_Route_Status\") != -1)\n $b: VesAlarm(eventId != $id, \n eventName.indexOf(\"Fault_Route_Status\") != -1, \n Math.abs(startEpochMicrosec - $start) < 60000)\n then\n String status = \"down\";\n if (status.equalsIgnoreCase(getAdditionalField($a, \"oper-status\")) \n && status.equalsIgnoreCase(getAdditionalField($b, \"oper-status\"))) {\n if (isCorrelated($a, $b)){\n // If any of the alarms have been marked as root, a policy message has ever been created and sent. Do NOT send it again.\n if ($a.getRootFlag() != 1 && $b.getRootFlag() != 1) {\n PolicyMsg msg = createPolicyMsg($a);\n DmaapService dmaapService = ServiceLocatorHolder.getLocator().getService(DmaapService.class);\n dmaapService.publishPolicyMsg(msg, \"unauthenticated.DCAE_CL_OUTPUT\");\n updateAaiLinkStatus(getLogicLink($a), status);\n }\n $a.setRootFlag(1);\n $b.setRootFlag(1);\n update($a);\n update($b);\n }\n }\nend\n\nrule \"Clear Alarms\"\n no-loop true\n salience 100\n when\n $a: VesAlarm(eventName.indexOf(\"Fault_Route_Status\") != -1)\n then\n if (\"up\".equalsIgnoreCase(getAdditionalField($a, \"oper-status\"))) {\n if (DmaapService.alarmUniqueRequestID.containsKey($a.getEventId())) {\n DmaapService.alarmUniqueRequestID.remove($a.getEventId());\n }\n \n //TODO: send alarm clearing message to Policy - for now it's not needed.\n //...\n \n retract($a);\n }\nend\n",
"description":"This rule is designed for the correlation analysis for the CCVPN use case.",
"enabled":1,
"loopControlName":"ControlLoop-CCVPN-2179b738-fd36-4843-a71a-a8c24c70c55b",
"ruleName":"CCVPN"
} |
To illustrate, the content field in the above rule is presented as readable format in the following. We need to convert it to valid json string when uploading to Holmes.
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
package org.onap.holmes.ccvpn;
dialect "java"
import org.onap.holmes.common.api.stat.VesAlarm;
import org.onap.holmes.common.api.stat.AlarmAdditionalField;
import org.onap.holmes.common.aai.AaiQuery4Ccvpn;
import org.onap.holmes.common.exception.CorrelationException;
import org.onap.holmes.common.dmaap.entity.PolicyMsg;
import org.onap.holmes.common.dmaap.DmaapService;
import org.onap.holmes.common.utils.DroolsLog;
import org.onap.holmes.common.dropwizard.ioc.utils.ServiceLocatorHolder;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import java.util.List;
import java.util.Map;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.UUID;
function String getAdditionalField(VesAlarm a, String field) {
List<AlarmAdditionalField> fields = a.getAlarmAdditionalInformation();
for (AlarmAdditionalField f : fields) {
if (f.getName().equals(field)) {
return f.getValue();
}
}
return null;
}
function String getLogicLink(VesAlarm alarm) {
AaiQuery4Ccvpn aai = AaiQuery4Ccvpn.newInstance();
return aai.getLogicLink(
getAdditionalField(alarm, "networkId"),
getAdditionalField(alarm, "node"),
getAdditionalField(alarm, "tp-id"),
null
);
}
function boolean isCorrelated(VesAlarm a, VesAlarm b) {
String logicLinkA = getLogicLink(a);
if (logicLinkA == null) {
return false;
}
String logicLinkB = getLogicLink(b);
if (logicLinkB == null) {
return false;
}
return logicLinkA.equals(logicLinkB);
}
function void updateAaiLinkStatus(String linkName, String status) {
AaiQuery4Ccvpn aai = AaiQuery4Ccvpn.newInstance();
Map<String, Object> body = new HashMap<String, Object>(){
{
put("operational-status", status);
}
};
aai.updateLogicLinkStatus(linkName, body);
}
function void updateAaiTpStatus(String networkId, String pnfName, String ifName, String status) {
AaiQuery4Ccvpn aai = AaiQuery4Ccvpn.newInstance();
Map<String, Object> body = new HashMap<String, Object>(){
{
put("operational-status", status);
}
};
aai.updateTerminalPointStatus(networkId, pnfName, ifName, body);
}
function Map<String, Object> getAdditionalResourceInfo(String networkId, String pnfName, String ifName, String status) {
AaiQuery4Ccvpn aai = AaiQuery4Ccvpn.newInstance();
JSONArray instances = aai.getServiceInstances(networkId, pnfName, ifName, status);
Map<String, Object> ret = new HashMap<String, Object>();
StringBuilder sbn = new StringBuilder();
StringBuilder sbi = new StringBuilder();
for(int i = 0; i < instances.size(); ++i) {
JSONObject o = instances.getJSONObject(i);
String name = o.getString("service-instance-name");
String id = o.getString("service-instance-id");
ret.put(id + ".input-parameters", o.getString("input-parameters"));
sbn.append(name).append(",");
sbi.append(id).append(",");
}
ret.put("service-instance.service-instance-name", sbn.substring(0, sbn.length() -1).toString());
ret.put("service-instance.service-instance-id", sbi.substring(0, sbi.length() -1).toString());
ret.put("vserver.vserver-name", "TBD");
ret.put("globalSubscriberId", instances.getJSONObject(0).getString("globalSubscriberId"));
ret.put("serviceType", instances.getJSONObject(0).getString("serviceType"));
return ret;
}
function PolicyMsg createPolicyMsg(VesAlarm alarm) {
PolicyMsg m = new PolicyMsg();
m.setPolicyVersion("1.0.0.5");
m.setPolicyName("CCVPN");
m.setPolicyScope(" | ||||||
Code Block | ||||||
| ||||||
{ "closedLoopEventClient": "DCAE.HolmesInstance", "policyVersion": "1.0.0.5", "policyName": "CCVPN", "policyScope": "service=SOTNService,type=SampleType,closedLoopControlName=CL-CCVPN-d925ed73-8231-4d02-9545-db4e101f88f8", "target_type": "VM", "AAI": { ); m.setClosedLoopControlName(DmaapService.loopControlNames.get("org.onap.holmes.ccvpn")); m.setRequestID(UUID.randomUUID().toString()); m.setClosedLoopAlarmStart(alarm.getStartEpochMicrosec()); m.setClosedLoopAlarmEnd(alarm.getLastEpochMicrosec()); m.setTarget("vserver.vserver-name" :); m.setAai(getAdditionalResourceInfo( getAdditionalField(alarm, "TBDnetworkId"), getAdditionalField(alarm, "globalSubscriberId" :node"), getAdditionalField(alarm, "e151059a-d924-4629-845f-264db19e50b4"tp-id"), "serviceType" : "SOTN", "service-instance.service-instance-id" : "service-instance-id-example-1,service-instance-id-example-2,service-instance-id-example-3", "service-instance.service-instance-name" : "service-instance-example-1,service-instance-example-2,service-instance-example-3", "service-instance-example-1.input-parameters" : "...", "service-instance-example-2.input-parameters" : "...", "service-instance-example-3.input-parameters" : "..." }, "closedLoopAlarmStart": 1484677482204798, "closedLoopEventStatus": "ONSET", "closedLoopControlName": "ControlLoop-CCVPN-2179b738-fd36-4843-a71a-a8c24c70c55b", "version": "1.0.2", "target": "vserver.vserver-name", "requestID": "97964e10-686e-4790-8c45-bdfa61df770f", "from": "DCAE" } |
Policy Engine subscribes the unauthenticated.DCAE_CL_OUTPUT on DMAAP.
AAI Enrichment APIs
DCAE VES event A&AI enrichment for previous use cases are defined here as reference. More CCVPN related AAI API discussion can be found on this page,
Note: pnfName = Nodeid and p-interface-name = tp-id
- The query logic from tp-id through service instance is that : p-interface → vpn-vpnbinding → connectivity → service instance. Then from service-instance to 'customer-request' for service instance recreation for phase 1.
- For event from different tp-id to be correlated: p-interface → logical link, then logic link is the same from ONAP domain.
- When link down event is detected, Closed Loop needs to update logical-link/p-interface's operational-status to “DOWN” for the recreated service instance picking up new links.
The following APIs are used to support the above looking up.
Status Update
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
URL: https://<AAI host>:<AAI port>/aai/v14/network/network-resources/network-resource/{networkId}/pnfs/pnf/{pnfName}/p-interfaces/p-interface/{ifName}
Method: PATCH
Request Body:
{
"operational-status": "some status"
}
|
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
URL: https://<AAI host>:<AAI port>/aai/v14/network/logical-links/logical-link/{linkName}
Method: PATCH
Request Body:
{
"operational-status": "some status"
} |
Service Instance ID Look Up
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
URL:
https://<AAI host>:<AAI port>/aai/v14/network/network-resources/network-resource/{networkId}/pnfs/pnf/{pnfName}/p-interfaces?interface-name={ifName}&operational-status={status}
Method: GET
Request Body:
{
}
Response Body:
{
"results": [
{
"p-interface": {
"interface-name": "{ifName}",
"network-ref": "some ref",
"transparent": "some value",
"operational-status ": "{status}",
"speed-value": "some speed",
"relationship-list": {
"relationship" : [
{
"related-to": "vpn-binding",
"related-link": "url of vpn-binding",
"relationship-data": [
"relationship-key": "vpn-binding.vpn-id",
"relationship-value": "some id"
]
}
]
}
}
}
]
} |
getAdditionalField(alarm, "oper-status")
));
DmaapService.alarmUniqueRequestID.put(alarm.getEventId(), m.getRequestID());
return m;
}
rule "Update AAI Information"
no-loop true
salience 300
when
$a: VesAlarm(eventName.indexOf("Fault_Route_Status") != -1)
then
updateAaiTpStatus (
getAdditionalField($a, "networkId"),
getAdditionalField($a, "node"),
getAdditionalField($a, "tp-id"),
getAdditionalField($a, "oper-status")
);
end
rule "Set Up Correlation"
no-loop true
salience 200
when
$a: VesAlarm($id: eventId,
$start: startEpochMicrosec,
eventName.indexOf("Fault_Route_Status") != -1)
$b: VesAlarm(eventId != $id,
eventName.indexOf("Fault_Route_Status") != -1,
Math.abs(startEpochMicrosec - $start) < 60000)
then
String status = "down";
if (status.equalsIgnoreCase(getAdditionalField($a, "oper-status"))
&& status.equalsIgnoreCase(getAdditionalField($b, "oper-status"))) {
if (isCorrelated($a, $b)){
// If any of the alarms have been marked as root, a policy message has ever been created and sent. Do NOT send it again.
if ($a.getRootFlag() != 1 && $b.getRootFlag() != 1) {
PolicyMsg msg = createPolicyMsg($a);
DmaapService dmaapService = ServiceLocatorHolder.getLocator().getService(DmaapService.class);
dmaapService.publishPolicyMsg(msg, "unauthenticated.DCAE_CL_OUTPUT");
updateAaiLinkStatus(getLogicLink($a), status);
}
$a.setRootFlag(1);
$b.setRootFlag(1);
update($a);
update($b);
}
}
end
rule "Clear Alarms"
no-loop true
salience 100
when
$a: VesAlarm(eventName.indexOf("Fault_Route_Status") != -1)
then
if ("up".equalsIgnoreCase(getAdditionalField($a, "oper-status"))) {
if (DmaapService.alarmUniqueRequestID.containsKey($a.getEventId())) {
DmaapService.alarmUniqueRequestID.remove($a.getEventId());
}
//TODO: send alarm clearing message to Policy - for now it's not needed.
//...
retract($a);
}
end |
Rule Execution
After the correlation is done successfully, there should be a corresponding control loop event defined in the following section published on the unauthenticated.DCAE_CL_OUTPUT topic of DMaaP.
POLICY
Policy Creation
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
controlLoop:
version: 2.0.0
controlLoopName: ControlLoop-CCVPN-2179b738-fd36-4843-a71a-a8c24c70c66b
trigger_policy: unique-policy-id-16-Reroute
timeout: 3600
abatement: false
policies:
- id: unique-policy-id-16-Reroute
name: Connectivity Reroute
description:
actor: SDNC
recipe: Reroute
target:
type: VM
retry: 3
timeout: 1200
success: final_success
failure: final_failure
failure_timeout: final_failure_timeout
failure_retries: final_failure_retries
failure_exception: final_failure_exception
failure_guard: final_failure_guard
|
For now, Policy bases on the parameters looked up and encoded in by Holmes to the 'AAI' portion of the following event to invoke SDNC API to re-route the network connectivity.
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
{
"closedLoopEventClient": "DCAE.HolmesInstance",
"policyVersion": "1.0.0.5",
"policyName": "CCVPN",
"policyScope": "service=SOTNService,type=SampleType,closedLoopControlName=CL-CCVPN-d925ed73-8231-4d02-9545-db4e101f88f8",
"target_type": "VM",
"AAI": {
"vserver.vserver-name" : "TBD",
"globalSubscriberId" : "e151059a-d924-4629-845f-264db19e50b4",
"serviceType" : "SOTN",
"service-information.service-instance-id" : "service-instance-id-example-1",
"network-information. network-id " : "id"
},
"closedLoopAlarmStart": 1484677482204798,
"closedLoopEventStatus": "ONSET",
"closedLoopControlName": "ControlLoop-CCVPN-2179b738-fd36-4843-a71a-a8c24c70c66b",
"version": "1.0.2",
"target": "vserver.vserver-name",
"requestID": "97964e10-686e-4790-8c45-bdfa61df770f",
"from": "DCAE"
} |
Policy Engine subscribes the unauthenticated.DCAE_CL_OUTPUT on DMAAP.
AAI Enrichment APIs
DCAE VES event A&AI enrichment for previous use cases are defined here as reference. More CCVPN related AAI API discussion can be found on this page,
Note: pnfName = Nodeid and p-interface-name = tp-id
- The query logic from tp-id through service instance is that : p-interface → vpn-vpnbinding → connectivity → service instance. Then from service-instance to 'customer-request' for service instance recreation for phase 1.
- For event from different tp-id to be correlated: p-interface → logical link, then logic link is the same from ONAP domain.
- When link down event is detected, Closed Loop needs to update logical-link/p-interface's operational-status to “DOWN” for the recreated service instance picking up new links.
The following APIs are used to support the above looking up.
Status Update
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
URL: https://<AAI host>:<AAI port>/aai/v14/network/network-resources/network-resource/{networkId}/pnfs/pnf/{pnfName}/p-interfaces/p-interface/{ifName}
Method: PATCH
Request Body:
{
"operational-status": "some status"
}
|
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
URL: https://<AAI host>:<AAI port>/aai/v14/network/logical-links/logical-link/{linkName}
Method: PATCH
Request Body:
{
"operational-status": "some status"
} |
Service Instance ID Look Up
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
URL:
https://<AAI host>:<AAI port>/aai/v14/network/network-resources/network-resource/{networkId}/pnfs/pnf/{pnfName}/p-interfaces?interface-name={ifName}&operational-status={status}
Method: GET
Request Body:
{
}
Response Body:
{
"results": [
{
"p-interface": { | ||||||
Code Block | ||||||
| ||||||
URL: https://<AAI host>:<AAI port>/aai/v14/network/vpn-bindings?vpn-id={vpnId} Method: GET Request Body: { } Response Body: { "results": [ { "vpn-binding": { "vpn-id": "{vpnId}", "vpn-name": "some name", "access-provider-id": "provider id", "access-client-id": "client id", "accessinterface-topology-idname": "topology id{ifName}", "src-access-node-idnetwork-ref": "srcsome node idref", "src-access-ltp-idtransparent": "srcsome ltp idvalue", "dst-access-node-idoperational-status ": "dst node id{status}", "dst-access-ltp-id": "dst ltp id, "operational-status"speed-value": "some statusspeed", "relationship-list": { "relationship" : [ { "related-to": "connectivityvpn-binding", "related-link": "url of connectivityvpn-binding", "relationship-data": [ "relationship-key": "connectivity. connectivityvpn-binding.vpn-id", "relationship-value": "some id" ] } ] } } } ] } |
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
URL: https://<AAI host>:<AAI port>/aai/v14/network/connectivities/connectivity/{connectivityIdvpn-bindings?vpn-id={vpnId} Method: GetGET Request Body: { } Response Body: { "results": [ { "connectivityvpn-binding": { "connectivityvpn-id": "{connectivityIdvpnId}", "bandwidthvpn-profile-name": "some profilename", "vpnaccess-provider-typeid": "someprovider typeid", "ciraccess-client-id": "circlient valueid", "eiraccess-topology-id": "eirtopology valueid", "cbssrc-access-node-id": "cbssrc node valueid", "ebssrc-access-ltp-id": "ebssrc ltp valueid", "color-awaredst-access-node-id": "colordst node valueid", "coupling-flagdst-access-ltp-id": "flag value"dst ltp id, "ethtoperational-svc-namestatus": "some namestatus", "accessrelationship-provider-idlist": "provider id", { "access-client-id": "client id", "relationship" : [ "access-topology-id": "topology id", "access-node-id": "node id",{ "access-ltp-id": "ltp id", "connectivityrelated-selflinkto": "some URLconnectivity", "cvlan ": "some tag", "operationalrelated-statuslink": "someurl of statusconnectivity", "relationship-list": { "relationship-data" : [ { "relationship-key": "related-to": "service-instance", "related-link"connectivity. connectivity-id", "relationship-value": "url of service-instance",some id" "relationship-data": [] "relationship-key": "service-instance.service-instance-id",} ] "relationship-value": "some id"} } } ] } |
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
URL: https://<AAI host>:<AAI port>/aai/v14/network/connectivities/connectivity/{connectivityId} Method: ] Get Request Body: { } Response Body: { "results": [ { } "connectivity": { ]"connectivity-id": "{connectivityId}", "bandwidth-profile-name": "some }profile", "vpn-type": "some }type", ] | ||||||
Code Block | ||||||
| ||||||
From service-instance URL: URL: https://<AAI host>:<AAI port>/aai/v14/business/customers/customer/{global-customer-id}/service-subscriptions/service-subscription/{service-type}/service-instances?service-instance-id={servId} Derive the service-subscription URL: URL: https://<AAI host>:<AAI port>/aai/v14/business/customers/customer/{global-customer-id}/service-subscriptions/service-subscription/{service-type} Method: GET Request Body: { } Response Body: { "results": [ "cir": "cir value", "eir": "eir value", "cbs": "cbs value", "ebs": "ebs value", { "servicecolor-subscriptionaware": { "color value", "servicecoupling-typeflag": "{service-type}flag value", "tempetht-ub-sub-account-idsvc-name": "some sub accountname", "serviceaccess-provider-instancesid": { "provider id", "service-instance"access-client-id": ["client id", "access-topology-id": "topology id", { "access-node-id": "node id", "serviceaccess-instanceltp-id": "someltp id 1", "serviceconnectivity-instance-nameselflink": "some name 1URL", "environment-context""cvlan ": "some context 1tag", "workloadoperational-contextstatus": "some workload 1status", "relationship-list": { "relationship" : [ { ] } "related-to": "service-instance", }, "related-link": "url of { service-instance", "servicerelationship-instance-iddata": "some id 2", [ "service-instance-name "relationship-key": "some name 2", service-instance.service-instance-id", "environment-context": "some context 2", "workload-context "relationship-value": "some workload 2id", "relationship-list": { ] } "relationship" : [ ] ]} } ] |
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
From service-instance URL: URL: https://<AAI } }, { host>:<AAI port>/aai/v14/business/customers/customer/{global-customer-id}/service-subscriptions/service-subscription/{service-type}/service-instances?service-instance-id={servId} Derive the service-subscription URL: URL: https://<AAI host>:<AAI port>/aai/v14/business/customers/customer/{global-customer-id}/service-subscriptions/service-subscription/{service-type} Method: GET Request Body: { } Response Body: { "results": [ { "service-instance-idsubscription": "some{ id 3", "service-type": "{service-type}", "service-instance-nametemp-ub-sub-account-id": "some namesub 3account", "service-instances": { "environmentservice-contextinstance": [ "some context 3", { "workload-context": "some workload 3 "service-instance-id": "some id 1", "relationshipservice-instance-listname": { "some name 1", "environment-context": "relationship"some :context [1", "workload-context": "some workload ]1", }"relationship-list": { } "relationship" : [ ] }, ] "relationship-list": { "relationship"} : [ ]}, } { } } ] } For each item in results: - Get item."service-subscription.service-instances -instance-id": "some id 2", For each data in service-instances: - Get service-instance object |
Alarm Correlation
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
URL: https://<AAI host>:<AAI port>/aai/v14/network/pnfs/pnf/{pnfName}/p-interfaces?interface-name={ifName}&operational-status={status} Method: GET Resquest Body: { } Response Body: { "results" : [ { "service-instance-name": "some name 2", "p-interface" : { environment-context": "some context 2", "interfaceworkload-namecontext":{ifName} "some workload 2", "networkrelationship-reflist": "some ref", { "transparent": "some blue", "relationship" : [ "operational-status":"{status}", "speed-value" : "some speed",] "relationship-list": } "relationship" : [ }, { "relatedservice-toinstance-id" : "logic-linksome id 3", "relatedservice-instance-linkname": :'url of logical-link"some name 3", "environment-context": "some context "relationship-data":[3", "workload-context": "some workload 3", "relationship-keylist" : "logical-link.link.name", { "relationship-value"; "some: name"[ ] } } ] } }, ] } |
Look up for 'input-parameters' by 'service-instance-id'
"relationship-list": {
"relationship" : [
]
}
}
}
]
}
For each
item in results: - Get item.service-subscription.service-instances
- For each data in service-instances:
- Get service-instance object
|
Alarm Correlation
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
URL: https://<AAI host>:<AAI port>/aai/v14/network/pnfs/pnf/{pnfName}/p-interfaces?interface-name={ifName}&operational-status={status}
Method: GET
Resquest Body:
{
}
Response Body:
{
"results" : [
{
"p-interface" : {
| ||||||
Code Block | ||||||
| ||||||
URL: https://<AAI host>:<AAI port>/aai/v14/business/customers/customer/{global-custoner-id}/service-subscriptions/service-subscription/{service-type}/service-instances?service-instance-id={serviceId} Method: GET Request Body: { } Response Body: { "service-instance-id": "{service-instance-id}", "service-instance-name" : "instance name", "service-type": "some type", "service-role": "some role", "model-invariant-id": "model id", "model-version-id": "model version", "input-parameters:"request parameters", // ... This is the service instance recreation input looked up by CL. "resource-version": "some version" } Example of response body: { "service-instance-id": "176d9eba-1662-4289-8396-0097b50fd485", "service-type": "E2E Service", "service-role": "E2E Service", "model-invariant-id": "c22a9483-d2b6-49cc-b1f7-ef34c93572a1", "model-version-id": "71d0e396-e246-4c23-aa57-6da2043d6209", "input-parameters:".....;", // ... This is the service instance recreation input looked up by CL. "resource-version": "1528975017336" "relationship-list": { "relationship": [ { "interface-name":{ifName}", "related-to": "pnf", "relatednetwork-linkref": "/aai/v11/network/pnfs/pnf/MME-0001some ref", "relationship-data "transparent": [ "some blue", { "operational-status":"{status}", "relationshipspeed-keyvalue" : "pnf.pnf-idsome speed", "relationship-list": "relationship-value" : "176d9eba-1662-4289-8396-0097b50fd466" [ } ], { "related-to-property": [ { "property-key": "pnf.pnflogic-namelink", "property-value": "MME-0001" } ] } ] } } |
Others
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
URL: https://<AAI host>:<AAI port>/aai/v14/network/logical-links?link-name={linkName}&operational-status={status} Method: GET { } Response Body: { "results": [ "logic-links" : { "related-link" :'url of logical-link", "relationship-data":[ "linkrelationship-namekey" : "{linkName}logical-link.link.name", "operational-status": "{status}", "model-invariant-id": "some invariant", "model-version-id" : "some version", "link-id":"relationship-value"; "some idname", "relationship-list" : [ {] "relationship" : [ } { ] } "related-to": "p-interface", "related-link": "url of p-interface 1] } |
Look up for 'input-parameters' by 'service-instance-id'
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
URL: https://<AAI host>:<AAI port>/aai/v14/business/customers/customer/{global-custoner-id}/service-subscriptions/service-subscription/{service-type}/service-instances?service-instance-id={serviceId} Method: GET Request Body: { } Response Body: { "service-instance-id": "{service-instance-id}", "service-instance-name" : "instance name", "service-type": "relationship-data":[ "relationship-key" : "p-interface.interface-name", "relationship-value" : "some name 1" ] "some type", "service-role": "some role", "model-invariant-id": "model id", "model-version-id": "model version", "input-parameters:"request parameters", // ... This is the service instance recreation input looked up by CL. "resource-version": "some version" } Example of response body: { "service-instance-id": "176d9eba-1662-4289-8396-0097b50fd485", "service-type": "E2E Service", "service-role": "E2E Service", "model-invariant-id": "c22a9483-d2b6-49cc-b1f7-ef34c93572a1", "model-version-id": "71d0e396-e246-4c23-aa57-6da2043d6209", "input-parameters:".....;", // ... This } is the service instance recreation input looked up ], }, by CL. "resource-version": "1528975017336" "relationship-list": { "relationship" : [ { "related-to": "p-interfacepnf", "related-link": "url of p-interface 2/aai/v11/network/pnfs/pnf/MME-0001", "relationship-data": [ { "relationship-key" : "p-interfacepnf.interfacepnf-nameid", "relationship-value" : "some name 2176d9eba-1662-4289-8396-0097b50fd466" } ], ] "related-to-property": [ { "property-key": "pnf.pnf-name", "property-value": "MME-0001" } ], } ] } |
...
]
}
]
}
}
|
Others
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
URL: https://<AAI host>:<AAI port>/aai/v14/network/logical-links?link-name={linkName}&operational-status={status}
Method: GET
{
}
Response Body:
{
"results": [
"logic-links" : {
"link-name" : "{linkName}",
"operational-status": "{status}",
"model-invariant-id": "some invariant",
"model-version-id" : "some version",
"link-id":"some id",
"relationship-list" : [
{
"relationship" : [
{
"related-to": "p-interface",
"related-link": "url of p-interface 1",
"relationship-data":[
"relationship-key" : "p-interface.interface-name",
"relationship-value" : "some name 1"
]
}
],
},
{
"relationship" : [
{
"related-to": "p-interface",
"related-link": "url of p-interface 2",
"relationship-data":[
"relationship-key" : "p-interface.interface-name",
"relationship-value" : "some name 2"
]
}
],
}
]
}
|