3 __author__ = "Mislav Novakovic <mislav.novakovic@sartura.hr>"
4 __copyright__ = "Copyright 2018, Deutsche Telekom AG"
5 __license__ = "Apache 2.0"
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
11 # http://www.apache.org/licenses/LICENSE-2.0
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.
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
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.
27 # The original c implementation is also available in the source, so one can refer to it to evaluate trade-offs.
33 # Helper function for printing changes given operation, old and new value.
34 def 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()}")
45 # Helper function for printing events.
47 if ev == sr.SR_EV_VERIFY:
49 elif ev == sr.SR_EV_APPLY:
51 elif ev == sr.SR_EV_ABORT:
57 # Function to print current configuration state.
58 # It does so by loading all the items of a session and printing them out.
59 def print_current_config(session, module_name):
60 select_xpath = f"/{module_name}:*//*"
62 values = session.get_items(select_xpath)
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 ===========")
71 # Function to be called for subscribed client of given session whenever configuration changes.
72 def module_change_cb(sess, module_name, event, private_ctx):
74 print("========== Notification " + ev_to_str(event) + " =============================================")
75 if event == sr.SR_EV_APPLY:
76 print_current_config(sess, module_name)
78 print("========== CHANGES: =============================================")
80 change_path = f"/{module_name}:*"
82 it = sess.get_changes_iter(change_path)
85 change = sess.get_change_next(it)
88 print_change(change.oper(), change.old_val(), change.new_val())
90 print("========== END OF CHANGES =======================================")
91 except Exception as e:
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.
101 module_name = "ietf-interfaces"
102 if len(sys.argv) > 1:
103 module_name = sys.argv[1]
105 print("\nYou can pass the module name to be subscribed as the first argument")
107 print(f"Application will watch for changes in {module_name}")
110 conn = sr.Connection(module_name)
113 sess = sr.Session(conn)
115 # subscribe for changes in running config */
116 subscribe = sr.Subscribe(sess)
118 subscribe.module_change_subscribe(module_name, module_change_cb)
121 print_current_config(sess, module_name)
122 except Exception as e:
125 print("========== STARTUP CONFIG APPLIED AS RUNNING ==========")
129 print("Application exit requested, exiting.")
131 except Exception as e:
135 if __name__ == '__main__':