...
CCVPN Close Loop requires Holmes to correlate route down alarms from SOTN Controllers from different sites. (Refer to this page on Holmes installation,)
In Phase 1, for the minimum, two of the above defined Route_Down_Alarm will be correlated within time window of 15 - 30, for instance, milliseconds. (Refer to this page as examples.)
Rule Creation
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
{ "content":"package org.onap.holmes.ccvpn;\n\ndialect \"java\"\n\nimport org.onap.holmes.common.api.stat.VesAlarm;\nimport org.onap.holmes.common.api.stat.AlarmAdditionalField;\nimport test.drools.AaiQuery4Ccvpn;\n//import org.onap.holmes.common.aai.AaiQuery4Ccvpn;\nimport org.onap.holmes.common.exception.CorrelationException;\nimport org.onap.holmes.common.dmaap.entity.PolicyMsg;\nimport org.onap.holmes.common.dmaap.DmaapService;\nimport org.onap.holmes.common.utils.DroolsLog;\nimport org.onap.holmes.common.dropwizard.ioc.utils.ServiceLocatorHolder;\n\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 getAdditionalField(alarm, \"oper-status\")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 System.out.println(JSONObject.toJSONString(msg));\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" } |
...
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") 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("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 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 |
...
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
controlLoop: version: 2.0.0 controlLoopName: ControlLoop-CCVPN-2179b738-fd36-4843-a71a-a8c24c70c55ba8c24c70c66b trigger_policy: unique-policy-id-16-receateE2EServiceReroute timeout: 3600 abatement: false policies: - id: unique-policy-id-16-recreateE2EServiceReroute name: RecreateConnectivity E2E ServiceReroute description: actor: SOSDNC recipe: Recreate_E2E_ServiceReroute 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-instanceinformation.service-instance-id" : "service-instance-id-example-1,service-instance-id-example-2,service-instance-id-example-3", "servicenetwork-instance.service-instance-name" : "name-1,name-2,name-3", "service-instance-id-example-1.input-parameters" : "...", "service-instance-id-example-2.input-parametersinformation. network-id " : "...", "service-instance-id-example-3.input-parameters" : "..." }, "closedLoopAlarmStart": 1484677482204798, "closedLoopEventStatus": "ONSET", "closedLoopControlName": "ControlLoop-CCVPN-2179b738-fd36-4843-a71a-a8c24c70c55ba8c24c70c66b", "version": "1.0.2", "target": "vserver.vserver-name", "requestID": "97964e10-686e-4790-8c45-bdfa61df770f", "from": "DCAE" } |
...
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
...