blob: 61272967513f98ea6d86b66d4bf7f90b3c00eb0a [file] [log] [blame]
ajay_dp001ebc79b22020-04-14 13:07:48 +05301#!/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# Licensed under the Apache License, Version 2.0 (the "License");
8# you may not use this file except in compliance with the License.
9# You may obtain a copy of the License at
10#
11# http://www.apache.org/licenses/LICENSE-2.0
12#
13# Unless required by applicable law or agreed to in writing, software
14# distributed under the License is distributed on an "AS IS" BASIS,
15# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16# See the License for the specific language governing permissions and
17# limitations under the License.
18
19# This sample application demonstrates use of Python programming language bindings for sysrepo library.
20# Original c application was rewritten in Python to show similarities and differences
21# between the two.
22#
23# Most notable difference is in the very different nature of languages, c is weakly statically typed language
24# while Python is strongly dynamically typed. Python code is much easier to read and logic easier to comprehend
25# for smaller scripts. Memory safety is not an issue but lower performance can be expected.
26#
27# The original c implementation is also available in the source, so one can refer to it to evaluate trade-offs.
28
29import sysrepo as sr
30import sys
31
32
33# Helper function for printing changes given operation, old and new value.
34def print_change(op, old_val, new_val):
35 if op == sr.SR_OP_CREATED:
36 print(f"CREATED: {new_val.to_string()}")
37 elif op == sr.SR_OP_DELETED:
38 print(f"DELETED: {old_val.to_string()}")
39 elif op == sr.SR_OP_MODIFIED:
40 print(f"MODIFIED: {old_val.to_string()} to {new_val.to_string()}")
41 elif op == sr.SR_OP_MOVED:
42 print(f"MOVED: {new_val.xpath()} after {old_val.xpath()}")
43
44
45# Helper function for printing events.
46def ev_to_str(ev):
47 if ev == sr.SR_EV_VERIFY:
48 return "verify"
49 elif ev == sr.SR_EV_APPLY:
50 return "apply"
51 elif ev == sr.SR_EV_ABORT:
52 return "abort"
53 else:
54 return "unknown"
55
56
57# Function to print current configuration state.
58# It does so by loading all the items of a session and printing them out.
59def print_current_config(session, module_name):
60 select_xpath = f"/{module_name}:*//*"
61
62 values = session.get_items(select_xpath)
63
64 if values is not None:
65 print("========== BEGIN CONFIG ==========")
66 for i in range(values.val_cnt()):
67 print(values.val(i).to_string(), end='')
68 print("=========== END CONFIG ===========")
69
70
71# Function to be called for subscribed client of given session whenever configuration changes.
72def module_change_cb(sess, module_name, event, private_ctx):
73 try:
74 print("========== Notification " + ev_to_str(event) + " =============================================")
75 if event == sr.SR_EV_APPLY:
76 print_current_config(sess, module_name)
77
78 print("========== CHANGES: =============================================")
79
80 change_path = f"/{module_name}:*"
81
82 it = sess.get_changes_iter(change_path)
83
84 while True:
85 change = sess.get_change_next(it)
86 if change is None:
87 break
88 print_change(change.oper(), change.old_val(), change.new_val())
89
90 print("========== END OF CHANGES =======================================")
91 except Exception as e:
92 print(e)
93
94 return sr.SR_ERR_OK
95
96
97def main():
98 # Notable difference between c implementation is using exception mechanism for open handling unexpected events.
99 # Here it is useful because `Connection`, `Session` and `Subscribe` could throw an exception.
100 try:
101 module_name = "ietf-interfaces"
102 if len(sys.argv) > 1:
103 module_name = sys.argv[1]
104 else:
105 print("\nYou can pass the module name to be subscribed as the first argument")
106
107 print(f"Application will watch for changes in {module_name}")
108
109 # connect to sysrepo
110 conn = sr.Connection(module_name)
111
112 # start session
113 sess = sr.Session(conn)
114
115 # subscribe for changes in running config */
116 subscribe = sr.Subscribe(sess)
117
118 subscribe.module_change_subscribe(module_name, module_change_cb)
119
120 try:
121 print_current_config(sess, module_name)
122 except Exception as e:
123 print(e)
124
125 print("========== STARTUP CONFIG APPLIED AS RUNNING ==========")
126
127 sr.global_loop()
128
129 print("Application exit requested, exiting.")
130
131 except Exception as e:
132 print(e)
133
134
135if __name__ == '__main__':
136 main()