Service Health RESTCONF Notifications

1. Introduction

You want to receive notifications when a customer-facing service is affected by some issue, so you can proactively identify issues and improve customer experiences. As soon as Crosswork detects that the service is down or degraded, it sends a notification that contains the name of the service, the service's health state (such as "degraded"), the time this issue was detected, the severity level of the change, and symptoms. If you later return the service to a healthy state, this same service-affecting notification should be cleared.

In the following sections, we will use the RESTCONF SSE notification to handle this.

2. Service Affecting Notification Data Model

Here is the YANG definition for supported notifications in Service Health.

cisco-crosswork-service-health.yang:

 module cisco-crosswork-service-health {
    namespace "urn:cisco:params:xml:ns:yang:cw:app:sh";
    prefix sh;
 
    organization "Cisco Systems Inc.";
    contact "mailto:cnc-support@cisco.com";
    description "Example Notification Data Model Module.";
    revision "2022-09-13" {
        description "Initial version.";
    }
 
    import ietf-yang-types {
        prefix yang;
    }
 
    typedef health-status {
        type enumeration {
            enum "unknown" {
                value 1;
                description "Default state displayed by CNC-ISTP, when monitoring is not enabled for a given service.";
            }
            enum "monitoring-initiated" {
                value 2;
                description "When Service Health receives monitoring request for a given service, the service or subservice gets initialized to this state.";
            }
            enum "monitoring-failed" {
                value 3;
                description "State reflecting that Service Health ran into some internal error or failure.";
            }
            enum "monitoring-paused" {
                value 4;
                description "State reflecting that monitoring is in "pause" state; that is not active monitoring but historical data is available for inspection via the timeline.";
            }
            enum "up" {
                value 5;
                description "At the Service level, this state indicates that all the different subservices of the Service that is being monitored are healthy, with no issues to report. At the subservice level, this state indicates that the subservice being monitored is healthy.";
            }
            enum "down" {
                value 6;
                description "This state indicates that all the different subservices of the Service that is being monitored are reporting issues.";
            }
            enum "degraded" {
                value 7;
                description "At the Service level, this state indicates that some of the subservices of the Service that is being monitored are reporting issues. At the subservice level, this state indicates that the subservice being monitored is degraded.";
            }
        }
    }
 
    notification service-health-notification {
        description "Service Health Notification";
        container service-health-report {
            leaf timestamp {
                type yang:date-and-time;
                description "The timestamp of Service Health report.";
            }
            leaf service-id {
                type string;
                description "Service Identity.";
            }
            leaf status {
                type health-status;
                description "Service Health status.";
            }
            leaf error {
                type string;
                description "The error message (if any).";
            }
            list subservice-health-reports {
                key "subservice-id";
                leaf subservice-id {
                    type string;
                    description "Subservice identity.";
                }
                leaf status {
                    type health-status;
                    description "Subservice health status.";
                }
                leaf-list symptom {
                    type string;
                    description "Symptom at subservice level.";
                }
                leaf-list error {
                    type string;
                    description "Error at subservice level.";
                }
            }
        }
    }
}

Sample Notification Data

Here is a sample notification:

{
   "ietf-restconf:notification":{
      "cisco-crosswork-service-health:service-health-notification":{
         "service-health-report":{
            "timestamp":"2021-05-25T22:11:23.947Z",
            "status":"degraded",
            "service-id":"ietf-l2vpn-ntw:l2vpn-ntw/vpn-services/vpn-service=0-SimL2VPN_NM-EVPN",
            "error":"Something is wrong",
            "subservice-health-reports":[
               {
                  "subservice-id":"red",
                  "status":"monitoring-initiated",
                  "symptom":[
                     "Dashboard is very hot"
                  ],
                  "error":[
                     "P15 happened",
                     "P11 happened"
                  ]
               },
               {
                  "subservice-id":"green",
                  "status":"monitoring-failed",
                  "symptom":[
                     "Service blocked",
                     "Connection lost"
                  ],
                  "error":[
                     "Shutdown happening"
                  ]
               }
            ]
         }
      }
   },
   "event-time":"2022-10-16T05:50:06.332796Z"
}

3. NBI endpoint to receive the notification


<https://${host}:30603/crosswork/nbi/cat-inventory/v1/restconf/notif/notification-stream/cisco-crosswork-service-health:service-health-notification/JSON>

4. How to Receive Notifications

The following steps describe how to receive a Crosswork Network Controller RESTCONF notification for Service Health.

Step 1: Request a Ticket Granting Ticket (TGT)


curl -k -X POST 'https://{cw-server}:30603/crosswork/sso/v1/tickets' \

--header 'Content-Type: application/x-www-form-urlencoded' \

--header 'Accept: text/plain' \

--data-raw 'username={username}&password={password}'

Remember to replace {cw-server}, {username} and {password} with real values.

The TGT response will look like the following snippet. This response is used in the next step.


TGT-10-yelMq0H-iO2xjYRtiuqbeD-UM0PsTzqxy-QtQ6lHZi5M8D-S7DKKX0zSjZ-ErwFFOnc-cas-1

Step 2: Request a JWT Service Ticket

Use the TGT from the previous step to request a JWT service ticket.

curl -k -X POST 'https://{cw-server}:30603/crosswork/sso/v1/tickets/TGT-10-yelMq0H-iO2xjYRtiuqbeD-UM0PsTzqxy-QtQ6lHZi5M8D-S7DKKX0zSjZ-ErwFFOnc-cas-1' \

--header 'Content-Type: application/x-www-form-urlencoded' \

--data-raw 'service=<https://{cw-server}:30603/app-dashboard>'

The response JWT token looks like below. This response is used in the next step.

eyJhbGciOiJIUzUxMiJ9.eyJjbGllbnRJcEFkZHJlc3MiOiIxMC4yNDQuNTYuMCIsInN1YiI6ImFkbWluIiwiYXV0aEhhbmRsZU5hbWUiOiJRdWVyeURhdGFiYXNlQXV0aGVudGljYXRpb25IYW5kbGVyIiwiaXNGcm9tTmV3TG9naW4iOnRydWUsImF1dGhlbnRpY2F0aW9uRGF0ZSI6IjIwMjMtMDEtMTlUMDQ6NDE6MDguMzI4NjAwWiIsInBvbGljeV9pZCI6ImFkbWluIiwic3VjY2Vzc2Z1bEF1dGhlbnRpY2F0aW9uSGFuZGxlcnMiOiJRdWVyeURhdGFiYXNlQXV0aGVudGljYXRpb25IYW5kbGVyIiwiaXNzIjoiaHR0cHM6XC9cLzEwLjE5NC41Ny4xNTY6MzA2MDNcL2Nyb3Nzd29ya1wvc3NvIiwidXNlckFnZW50IjoiUG9zdG1hblJ1bnRpbWVcLzcuMjkuMiIsImNyZWRlbnRpYWxUeXBlIjoiVXNlcm5hbWVQYXNzd29yZENyZWRlbnRpYWwiLCJhdWQiOiJodHRwczpcL1wvMTAuMTk0LjU3LjE1NjozMDYwM1wvYXBwLWRhc2hib2FyZCIsImF1dGhlbnRpY2F0aW9uTWV0aG9kIjoiUXVlcnlEYXRhYmFzZUF1dGhlbnRpY2F0aW9uSGFuZGxlciIsImdlb0xvY2F0aW9uIjoidW5rbm93biIsInZpcnR1YWxEb21haW5zIjoiUk9PVC1ET01BSU4iLCJzZXJ2ZXJJcEFkZHJlc3MiOiIxMC4yNDQuMjExLjI3IiwibG9uZ1Rlcm1BdXRoZW50aWNhdGlvblJlcXVlc3RUb2tlblVzZWQiOmZhbHNlLCJjaGFuZ2VfcHdkIjoiZmFsc2UiLCJleHAiOjE2NzQxMzIwNzUsImlhdCI6MTY3NDEwMzI3NSwianRpIjoiU1QtMTAtMTZ3ZjNVWDRkZTdudU1xN3FhNzR5dFJVLUtkTHZtSkZtdWRLS2M1dlVlYTNHSE00R3o3TzVZdUdWUG5RMHJRUW92UTJ5UWlqQWJOM1Q4a3dpNm5id0lPd0w1UnE4dzVsbHhMSU1kYnlQTUJucFNiTnhJLTgyQnYyUG9GeGRkaG9uYlYydnZ2b0VXWFFqR1pSMm5EdVF0eWhzRW14MG03TC1jYXMtMSJ9.cy1DkTF-MJduosZMlDF9eC6J8SjGMxNT-5Bhwwwxu2\_VMXk4-cs\_QK6Sp8IbzuYf1TthuOCc4zaWI1VBygFSXg

The following is an example shell command requesting the event streams. Be sure to replace the "Authorization: Bearer" header's contents with the JWT token you acquired in Step 2. You will get a JSON response. You don't need to take any action with respect to the JSON response.

Step 3: Retrieve the list of supported event streams from a RESTCONF server


curl -k -X GET 'https://{cw-server}:30603/crosswork/nbi/cat-inventory/v1/restconf/data/ietf-restconf-monitoring:restconf-state/streams' \

--header 'Accept: application/json' \

--header 'Authorization: Bearer {header}'

The following is an example shell command requesting the notification resource. Be sure to replace the "Authorization: Bearer" header's contents with the JWT token you acquired in Step 2. You will get a JSON response. You don't need to take any action with respect to the JSON response.

Step 4: Retrieve the notification resource


curl -k -X GET 'https://{cw-server}:30603/crosswork/nbi/cat-inventory/v1/restconf/data/ietf-restconf-monitoring:restconf-state/streams/stream=service-health-notification/access=JSON/location' \

--header 'Accept: application/json' \

--header 'Authorization: Bearer {header}'

The following is an example shell command requesting the event stream. Be sure to replace the "Authorization: Bearer" header's contents with the JWT token you acquired in Step 2. You will get a JSON response. You don't need to take any action with respect to the JSON response.

Step 5: Subscribe to the Service Health notification event stream

curl -k -X GET 'https://{cw-server}:30603/crosswork/nbi/cat-inventory/v1/restconf/notif/notification-stream/cisco-crosswork-service-health:service-health-notification/JSON' \

--header 'Content-Type: application/json' \

--header 'Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJjbGllbnRJcEFkZHJlc3MiOiIxMC4yNDQuNTYuMCIsInN1YiI6ImFkbWluIiwiYXV0aEhhbmRsZU5hbWUiOiJRdWVyeURhdGFiYXNlQXV0aGVudGljYXRpb25IYW5kbGVyIiwiaXNGcm9tTmV3TG9naW4iOnRydWUsImF1dGhlbnRpY2F0aW9uRGF0ZSI6IjIwMjMtMDEtMTlUMDQ6NDE6MDguMzI4NjAwWiIsInBvbGljeV9pZCI6ImFkbWluIiwic3VjY2Vzc2Z1bEF1dGhlbnRpY2F0aW9uSGFuZGxlcnMiOiJRdWVyeURhdGFiYXNlQXV0aGVudGljYXRpb25IYW5kbGVyIiwiaXNzIjoiaHR0cHM6XC9cLzEwLjE5NC41Ny4xNTY6MzA2MDNcL2Nyb3Nzd29ya1wvc3NvIiwidXNlckFnZW50IjoiUG9zdG1hblJ1bnRpbWVcLzcuMjkuMiIsImNyZWRlbnRpYWxUeXBlIjoiVXNlcm5hbWVQYXNzd29yZENyZWRlbnRpYWwiLCJhdWQiOiJodHRwczpcL1wvMTAuMTk0LjU3LjE1NjozMDYwM1wvYXBwLWRhc2hib2FyZCIsImF1dGhlbnRpY2F0aW9uTWV0aG9kIjoiUXVlcnlEYXRhYmFzZUF1dGhlbnRpY2F0aW9uSGFuZGxlciIsImdlb0xvY2F0aW9uIjoidW5rbm93biIsInZpcnR1YWxEb21haW5zIjoiUk9PVC1ET01BSU4iLCJzZXJ2ZXJJcEFkZHJlc3MiOiIxMC4yNDQuMjExLjI3IiwibG9uZ1Rlcm1BdXRoZW50aWNhdGlvblJlcXVlc3RUb2tlblVzZWQiOmZhbHNlLCJjaGFuZ2VfcHdkIjoiZmFsc2UiLCJleHAiOjE2NzQxMzIwNzUsImlhdCI6MTY3NDEwMzI3NSwianRpIjoiU1QtMTAtMTZ3ZjNVWDRkZTdudU1xN3FhNzR5dFJVLUtkTHZtSkZtdWRLS2M1dlVlYTNHSE00R3o3TzVZdUdWUG5RMHJRUW92UTJ5UWlqQWJOM1Q4a3dpNm5id0lPd0w1UnE4dzVsbHhMSU1kYnlQTUJucFNiTnhJLTgyQnYyUG9GeGRkaG9uYlYydnZ2b0VXWFFqR1pSMm5EdVF0eWhzRW14MG03TC1jYXMtMSJ9.cy1DkTF-MJduosZMlDF9eC6J8SjGMxNT-5Bhwwwxu2\_VMXk4-cs\_QK6Sp8IbzuYf1TthuOCc4zaWI1VBygFSXg'

The notification stream will look like the following example.

: ping

data: {"ietf-restconf:notification":{"cisco-crosswork-service-health:service-health-notification":{"service-health-report":{"timestamp":"2021-05-25T22:11:23.947Z","status":"degraded","service-id":"ietf-l2vpn-ntw:l2vpn-ntw/vpn-services/vpn-service=0-SimL2VPN\_NM-EVPN","error":"Something is wrong","subservice-health-reports":[{"subservice-id":"red","status":"monitoring-initiated","symptom":["Dashboard is very hot"],"error":["P15 happened","P11 happened"]},{"subservice-id":"green","status":"monitoring-failed","symptom":["Service blocked","Connection lost"],"error":["Shutdown happening"]}]}}},"event-time":"2022-10-16T05:50:06.332796Z"}

data: {"ietf-restconf:notification":{"cisco-crosswork-service-health:service-health-notification":{"service-health-report":{"timestamp":"2021-05-25T22:11:23.947Z","status":"degraded","service-id":"ietf-l2vpn-ntw:l2vpn-ntw/vpn-services/vpn-service=0-SimL2VPN\_NM-EVPN","error":"Something is wrong","subservice-health-reports":[{"subservice-id":"red","status":"monitoring-initiated","symptom":["Dashboard is very hot"],"error":["P15 happened","P11 happened"]},{"subservice-id":"green","status":"monitoring-failed","symptom":["Service blocked","Connection lost"],"error":["Shutdown happening"]}]}}},"event-time":"2022-10-16T05:50:06.332796Z"}

: ping