CPS-615 - CSIT for model sync & passthrough
[cps.git] / csit / plans / cps / pnfsim / netconf-config / subscriber.py
1 #!/usr/bin/env python3
2
3 __author__ = "Mislav Novakovic <mislav.novakovic@sartura.hr>"
4 __copyright__ = "Copyright 2018, Deutsche Telekom AG"
5 __license__ = "Apache 2.0"
6
7 # ============LICENSE_START=======================================================
8 # Copyright (C) 2018 Deutsche Telekom AG
9 # Modifications Copyright (C) 2021 Nordix Foundation
10 # ================================================================================
11 # Licensed under the Apache License, Version 2.0 (the "License");
12 # you may not use this file except in compliance with the License.
13 # You may obtain a copy of the License at
14 #
15 #       http://www.apache.org/licenses/LICENSE-2.0
16 #
17 # Unless required by applicable law or agreed to in writing, software
18 # distributed under the License is distributed on an "AS IS" BASIS,
19 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 # See the License for the specific language governing permissions and
21 # limitations under the License.
22 # ============LICENSE_END=========================================================
23
24 import sysrepo as sr
25 import sys
26
27
28 # Helper function for printing changes given operation, old and new value.
29 def print_change(op, old_val, new_val):
30     if op == sr.SR_OP_CREATED:
31         print(f"CREATED: {new_val.to_string()}")
32     elif op == sr.SR_OP_DELETED:
33         print(f"DELETED: {old_val.to_string()}")
34     elif op == sr.SR_OP_MODIFIED:
35         print(f"MODIFIED: {old_val.to_string()} to {new_val.to_string()}")
36     elif op == sr.SR_OP_MOVED:
37         print(f"MOVED: {new_val.xpath()} after {old_val.xpath()}")
38
39
40 # Helper function for printing events.
41 def ev_to_str(ev):
42     if ev == sr.SR_EV_VERIFY:
43         return "verify"
44     elif ev == sr.SR_EV_APPLY:
45         return "apply"
46     elif ev == sr.SR_EV_ABORT:
47         return "abort"
48     else:
49         return "unknown"
50
51
52 # Function to print current configuration state.
53 # It does so by loading all the items of a session and printing them out.
54 def print_current_config(session, module_name):
55     select_xpath = f"/{module_name}:*//*"
56
57     values = session.get_items(select_xpath)
58
59     if values is not None:
60         print("========== BEGIN CONFIG ==========")
61         for i in range(values.val_cnt()):
62             print(values.val(i).to_string(), end='')
63         print("=========== END CONFIG ===========")
64
65
66 # Function to be called for subscribed client of given session whenever configuration changes.
67 def module_change_cb(sess, module_name, event, private_ctx):
68     try:
69         print("========== Notification " + ev_to_str(event) + " =============================================")
70         if event == sr.SR_EV_APPLY:
71             print_current_config(sess, module_name)
72
73         print("========== CHANGES: =============================================")
74
75         change_path = f"/{module_name}:*"
76
77         it = sess.get_changes_iter(change_path)
78
79         while True:
80             change = sess.get_change_next(it)
81             if change is None:
82                 break
83             print_change(change.oper(), change.old_val(), change.new_val())
84
85         print("========== END OF CHANGES =======================================")
86     except Exception as e:
87         print(e)
88
89     return sr.SR_ERR_OK
90
91
92 def main():
93     # Notable difference between c implementation is using exception mechanism for open handling unexpected events.
94     # Here it is useful because `Connection`, `Session` and `Subscribe` could throw an exception.
95     try:
96         module_name = "ietf-interfaces"
97         if len(sys.argv) > 1:
98             module_name = sys.argv[1]
99         else:
100             print("\nYou can pass the module name to be subscribed as the first argument")
101
102         print(f"Application will watch for changes in {module_name}")
103
104         # connect to sysrepo
105         conn = sr.Connection(module_name)
106
107         # start session
108         sess = sr.Session(conn)
109
110         # subscribe for changes in running config */
111         subscribe = sr.Subscribe(sess)
112
113         subscribe.module_change_subscribe(module_name, module_change_cb)
114
115         try:
116             print_current_config(sess, module_name)
117         except Exception as e:
118             print(e)
119
120         print("========== STARTUP CONFIG APPLIED AS RUNNING ==========")
121
122         sr.global_loop()
123
124         print("Application exit requested, exiting.")
125
126     except Exception as e:
127         print(e)
128
129
130 if __name__ == '__main__':
131     main()