VPN Service Change Processor: Subscribe to and Process Service State Change Notifications in CNC

This example shows step-by-step NB API calls to subscribe to service intent change notifications in CNC, enabling OSS/BSS/HCO systems to monitor and respond to service changes.

The scenario demonstrates the following steps:

  • Step 1: Subscribe to service state change notifications to monitor service configuration intent changes.
  • Step 2: Process the SSE data stream and assemble it into event data.
  • Step 3: Invoke a function to process event data according to the event model.
  • Step 4: Conditionally process the event to identify when the service configuration intent change completes.
  • Step 5: Retrieve the service configuration intent data after processing the service state change event.

This example uses the operations from the following API references.

  • Service Provisioning Status Notifications API - Subscribe and receive NSO Restconf notifications on service provisioning state changes through CNC NSO proxy endpoint.
  • L3VPN Service Config Intent Retrieval API: This API retrieves the L3VPN service configuration intent after processing state change events.

Prerequisites

Before running the examples, ensure that the following prerequisites are met:

  1. Complete the Day-0 device configurations on all devices.
  2. Set up the device topology correctly in the CNC cluster.
  3. If your topology or data differs from the example input, adjust the input data accordingly. Refer to the CNC installation guide and administration guide for details on configuring day-0 devices and topology.

Process Service Change Events

To run this example end-to-end, you must run two scripts in separate terminals.

  • Step 1: In first terminal, run the script service-change-processor.sh from the example directory to subscribe to service state change notifications, process the event, and retrieve the service config intent on the change completion.
  • Step 2: In second terminal, run the script create-l3vpn-with-odn.sh to observe the service state change events processing in the first terminal.

    Note: If the L3VPN service with ODN has already been created, it should be removed before being created again. This ensures that the example generates service state change events and processes them.

cd ~/cnc-api-examples/service-notifications;./service-change-processor.sh
cd ~/cnc-api-examples/l3vpn-with-odn;./create-l3vpn-with-odn.sh

The script execution outputs the API execution and results to standard output and store the results in multiple files in output folder.

Output

During and after executing the script, the system creates the following output files in the output directory: ~/cnc-api-examples/service-notifications/output

  • service-state-change-event.txt
  • service-config-intent.json
  • get-service-state-change-stream-output.json

Note: During script execution, while subscribing to notifications, the system appends the event data received on the stream to service-state-change-event.txt. To continuously monitor all events received on the stream, tail the file in separate terminal. tail -F ~/cnc-api-examples/service-notifications/output/service-state-change-event.txt.

Script Details: service-change-processor.sh

#!/bin/bash
#
# Usecase:
# This example scenario demonstrates step by step NB API invocation with the required input
# to subscribe and receive notifications on service intent changes in CNC. 
# Any OSS/BSS/HCO sytems that collect the service inventory can use these APIs to monitor service
# changes in CNC.
# The scenario demonstrates the following steps:
# Step 1: Subscribe to service state change notifications to monitor service configuration intent changes.
# Step 2: Process the SSE data stream and assemble it into event data.
# Step 3: Invoke a function to process event data according to the event model.
# Step 4: Conditionally process the event to identify when the service configuration intent change is completed.
# Step 5: Retrieve the service configuration intent data after processing the service state change completion event.

export PRJ=$(cd `dirname $0`; pwd)
. $PRJ/../common-scripts/env
. $PRJ/../common-scripts/cnc-api-common.sh 

# Shows the details of the service state change notification stream 
get-service-state-change-stream-details() {
    echo "Retrieving service state change Stream details..."
    # invoke stream data api
    export CNC_API_URL="$CNC_NSO_RESTCONF_CTX/data/ietf-restconf-monitoring:restconf-state/streams/stream=service-state-changes"
    export CNC_API_OUTPUT="$PRJ/output/get-service-state-change-stream-output.json"
    http_get $CNC_API_URL $CNC_API_OUTPUT

}

# Retrieve the service config intent - can be used to retrieve service config intent 
# in processing service state change notifications
get-service-config-intent() {
    local svcXPath="$1"
    local svcRcPath=$(xpath2restconf "$svcXPath")
    echo ""
    echo "Retrieving service config intent for - $svcRcPath"
    echo ""
    CNC_API_URL="$CNC_NSO_RESTCONF_CTX/data$svcRcPath?content=config"
    CNC_API_OUTPUT=$PRJ/output/service-config-intent.json
    http_get $CNC_API_URL $CNC_API_OUTPUT
    echo ""
}

# Process the service state change event.
# Input - rcEvent: event data as a whole that is assembled from service state change notification stream
process-service-state-change-event() {
    local rcEvent="$1"
    # process and extract the event specific data
    eSvc=$(jq -r '."ietf-restconf:notification"."tailf-ncs:plan-state-change"."service"' <<< "$rcEvent")
    eComp=$(jq -r '."ietf-restconf:notification"."tailf-ncs:plan-state-change"."component"' <<< "$rcEvent")
    eState=$(jq -r '."ietf-restconf:notification"."tailf-ncs:plan-state-change"."state"' <<< "$rcEvent")
    eStatus=$(jq -r '."ietf-restconf:notification"."tailf-ncs:plan-state-change"."status"' <<< "$rcEvent")
    eOper=$(jq -r '."ietf-restconf:notification"."tailf-ncs:plan-state-change"."operation"' <<< "$rcEvent")
    # log all events
    echo "$rcEvent" >> $PRJ/output/service-state-change-event.txt
    # on receiving the event that indicates the change is complete, call a function to retrieve the service config intent
    if [ "$eComp" == "self" ] && [ "$eState" == "tailf-ncs:ready" ] && [ "$eStatus" == "reached" ] && [ "$eOper" == "modified" ]; then 
        IFS=']' read -r svcPath svcSubPath <<< "$eSvc"
        if [[ -z "$svcSubPath" ]]; then
            # not a sub service instance path. fetch the service config intent
            echo ""
            echo "==== service state change event ===="
            echo "Service   : $eSvc"
            echo "Component : $eComp"
            echo "State     : $eState"
            echo "Status    : $eStatus"
            echo "Operation : $eOper"
            echo "====================================="
            echo ""
            get-service-config-intent "$eSvc"
        fi
    fi

}

# Subscribe to the service state change notifications stream to assemble the stream data 
# into a sequence of events and call a process event function to process the event data
subcribe-and-process-service-state-change-notif() {
    echo "Subscribing and Processing Service State Change Notifications..."
    export CNC_API_URL="$CNC_NSO_RESTCONF_CTX/streams/service-state-changes/json"
    export RC_EVENT
    while true; do
    curl $CURL_OPTS -N -X GET $CNC_API_URL -H 'Accept: text/event-stream' -H "$AUTH_TOKEN_HDR" | while read -r line; do
        if [[ "$line" == "data:"* ]]; then
            data=$(echo "$line" | sed 's/^data: //')
            # append the event data until new empty line
            RC_EVENT+="$data"$'\n'
        elif [[ -z "$line" ]]; then
            # Received empty line indicating end of event data or ping
            # process the data if needed and reset
            process-service-state-change-event "$RC_EVENT"
            RC_EVENT=""
        else 
            echo "Received unknown data $line"
        fi
    done
    sleep 0.1 # Optional: add a small delay to prevent excessive CPU usage
    done

}

main() {
    # Assume CNC JWT has been obtained prior to invoking this method by executing get-cnc-jwt.sh script
    # Read from JWT file and export it as AUTH_TOKEN_HDR
    export_jwt
    # print the details of the service state change stream
    get-service-state-change-stream-details
    # subscribe to the service state change notificaitons and process the events 
    # to conditionally retreive the service config intent on receiving a change complete event.
    subcribe-and-process-service-state-change-notif

}

main