diff --git a/src/confd_gnmi_api_adapter.py b/src/confd_gnmi_api_adapter.py index 42dd26f..fff575b 100644 --- a/src/confd_gnmi_api_adapter.py +++ b/src/confd_gnmi_api_adapter.py @@ -115,9 +115,9 @@ def get_subscription_notifications(self): return [gnmi_pb2.Notification(timestamp=get_timestamp_ns(), prefix=prefix, update=updates, - delete=[], + delete=deletes, atomic=False) - for prefix, updates in self._get_subscription_notifications()] + for prefix, updates, deletes in self._get_subscription_notifications()] def _get_subscription_notifications(self): with self.change_db_lock: @@ -131,11 +131,16 @@ def _get_subscription_notifications(self): prefix = gnmi_pb2.Path(elem=elems, target=sub_prefix.target, origin=sub_prefix.origin) + changegroup = list(changegroup) updates = [gnmi_pb2.Update(path=remove_path_prefix(path, prefix), val=value) - for _op, path, value in changegroup] - log.debug("update=%s", updates) - yield prefix, updates + for op, path, value in changegroup + if op is self.ChangeOp.MODIFIED] + deletes = [remove_path_prefix(path, prefix) + for op, path, _ in changegroup + if op is self.ChangeOp.DELETED] + log.debug("update=%s deletes=%s", updates, deletes) + yield prefix, updates, deletes self.change_db = [] def get_monitored_changes(self): @@ -177,6 +182,7 @@ def kp_to_xpath(kp): class ChangeOp(Enum): MODIFIED = "mod" + DELETED = "del" def _append_changes(self, sub_point, changes): """ @@ -198,7 +204,9 @@ def cdb_iter(kp, op, oldv, newv, changes): csnode = _tm.cs_node_cd(None, str(kp)) if op == _tm.MOP_CREATED: log.debug("_tm.MOP_CREATED") - # TODO CREATE not handled for now + # TODO in case of empty leaves or possibly presence + # containers, something needs to be done; the rest is + # handled after ITER_RECURSE if op == _tm.MOP_VALUE_SET: log.debug("_tm.MOP_VALUE_SET") changes.append((self.ChangeOp.MODIFIED, @@ -207,10 +215,12 @@ def cdb_iter(kp, op, oldv, newv, changes): # TODO MOP_VALUE_SET implement elif op == _tm.MOP_DELETED: log.debug("_tm.MOP_DELETED") - # TODO DELETE not handled for now + changes.append((self.ChangeOp.DELETED, + self.adapter.make_gnmi_keypath(kp, csnode), + None)) elif op == _tm.MOP_MODIFIED: log.debug("_tm.MOP_MODIFIED") - # TODO MODIFIED not handled for now + # nothing to do, will be handled after ITER_RECURSE else: log.warning( "Operation op=%d is not expected, kp=%s. Skipping!", @@ -232,7 +242,7 @@ def _external_changes(self, data): path = make_gnmi_path(xpath) cval = _tm.Value.str2val(value, csnode.info().type()) json_value = self.adapter.make_gnmi_json_value(cval, csnode) - yield op, path, json_value + yield self.ChangeOp(op), path, json_value def process_external_change(self, ext_sock): log.info("==>") diff --git a/src/confd_gnmi_client.py b/src/confd_gnmi_client.py index ac2f866..a17d768 100755 --- a/src/confd_gnmi_client.py +++ b/src/confd_gnmi_client.py @@ -157,6 +157,8 @@ def print_notification(n): value = str(u.val) print("path: {} value {}".format(pfx_str + make_xpath_path(u.path), value)) + for dpath in n.delete: + print("path deleted: {}".format(pfx_str + make_xpath_path(dpath))) @staticmethod def read_subscribe_responses(responses, read_count=-1): diff --git a/src/route_status.py b/src/route_status.py index f55f9f9..e1712ad 100755 --- a/src/route_status.py +++ b/src/route_status.py @@ -81,10 +81,14 @@ def cb_get_elem(self, tctx, kp): assert len(self.route_provider.routes) elem = str(kp[0]) key = str(kp[1][0]) - route = self.route_provider.routes[key] + route = self.route_provider.routes.get(key, None) log.debug("elem=%s key=%s route=%s", elem, key, route) val = None - if elem == "leaf1": + if route is None: + pass + elif elem == "id": + val = _confd.Value(key) + elif elem == "leaf1": val = _confd.Value(route.leaf1) elif elem == "leaf2": val = _confd.Value(route.leaf2) @@ -236,7 +240,7 @@ def generate_changes(stop_fun, route_data: RouteData, sleep_val=2): log.info("msg=%s", msg) s.sendall(msg.encode("utf-8")) except Exception: - log.info("Cannot connect to the change server!") + log.debug("Cannot connect to the change server!") if stop_fun(): break