def run_unset(self, node_name): key = Consts.STATIC_PREFIX_ALLOC_PARAM_KEY # Retrieve previous allocation resp = self.client.get_keys([key]) allocs = None if key in resp.keyVals: allocs = serializer.deserialize_thrift_object( resp.keyVals.get(key).value, alloc_types.StaticAllocation ) else: allocs = alloc_types.StaticAllocation(nodePrefixes={node_name: ""}) # Return if there need no change if node_name not in allocs.nodePrefixes: print("No changes needed. {}'s prefix is not set".format(node_name)) # Update value in KvStore del allocs.nodePrefixes[node_name] value = serializer.serialize_thrift_object(allocs) self.run(key, value, "breeze", None, Consts.CONST_TTL_INF)
def build_global_prefix_db(resp): """ build a map of all prefixes in the network. this is used for checking for changes in topology :param resp kv_store_types.Publication: the parsed publication :return map(node, set([prefix])): the global prefix map, prefixes mapped to the node """ # map: (node) -> set([prefix]) global_prefix_db = {} for (key, value) in resp.keyVals.items(): if not key.startswith(Consts.PREFIX_DB_MARKER): continue prefix_db = deserialize_thrift_object(value.value, lsdb_types.PrefixDatabase) update_global_prefix_db(global_prefix_db, prefix_db) return global_prefix_db
def build_global_adj_db(resp): """ build a map of all adjacencies in the network. this is used for bi-directional validation :param resp kv_store_types.Publication: the parsed publication :return map(node, AdjacencyDatabase): the global adj map, devices name mapped to devices it connects to, and properties of that connection """ # map: (node) -> AdjacencyDatabase) global_adj_db = {} for (key, value) in resp.keyVals.items(): if not key.startswith(Consts.ADJ_DB_MARKER): continue adj_db = deserialize_thrift_object(value.value, lsdb_types.AdjacencyDatabase) update_global_adj_db(global_adj_db, adj_db) return global_adj_db
def print_db_delta_adj(self, key, value, kvstore_adj_node_names, decision_adj_dbs, json): """Returns status code. 0 = success, 1 = failure""" kvstore_adj_db = deserialize_thrift_object( value.value, openr_types.AdjacencyDatabase) node_name = kvstore_adj_db.thisNodeName kvstore_adj_node_names.add(node_name) if node_name not in decision_adj_dbs: print( printing.render_vertical_table([[ "node {}'s adj db is missing in Decision".format(node_name) ]])) return 1 decision_adj_db = decision_adj_dbs[node_name] return_code = 0 if json: tags = ("in_decision", "in_kvstore", "changed_in_decision_and_kvstore") adj_list_deltas = utils.find_adj_list_deltas( decision_adj_db.adjacencies, kvstore_adj_db.adjacencies, tags=tags) deltas_json, return_code = utils.adj_list_deltas_json( adj_list_deltas, tags=tags) if return_code: utils.print_json(deltas_json) else: lines = utils.sprint_adj_db_delta(kvstore_adj_db, decision_adj_db) if lines: print( printing.render_vertical_table([[ "node {}'s adj db in Decision out of sync with " "KvStore's".format(node_name) ]])) print("\n".join(lines)) return_code = 1 return return_code
def interface_db_to_dict(value): ''' Convert a thrift::Value representation of InterfaceDatabase to bunch object ''' def _parse_intf_info(info): return bunch.Bunch(**{ 'isUp': info.isUp, 'ifIndex': info.ifIndex, 'v4Addrs': [sprint_addr(v.addr) for v in info.v4Addrs], 'v6Addrs': [sprint_addr(v.addr) for v in info.v6LinkLocalAddrs], }) assert(isinstance(value, kv_store_types.Value)) intf_db = deserialize_thrift_object(value.value, lsdb_types.InterfaceDatabase) return bunch.Bunch(**{ 'thisNodeName': intf_db.thisNodeName, 'interfaces': {k: _parse_intf_info(v) for k, v in intf_db.interfaces.items()}, })
def get_connected_nodes(self, adj_keys: openr_types.Publication, node_id: str) -> Set[str]: """ Build graph of adjacencies and return list of connected node from current node-id """ import networkx as nx edges = set() graph = nx.Graph() for adj_value in adj_keys.keyVals.values(): adj_db = serializer.deserialize_thrift_object( adj_value.value, openr_types.AdjacencyDatabase) graph.add_node(adj_db.thisNodeName) for adj in adj_db.adjacencies: # Add edge only when we see the reverse side of it. if (adj.otherNodeName, adj_db.thisNodeName, adj.otherIfName) in edges: graph.add_edge(adj.otherNodeName, adj_db.thisNodeName) continue edges.add((adj_db.thisNodeName, adj.otherNodeName, adj.ifName)) return nx.node_connected_component(graph, node_id)
def print_adj_delta(self, key, value, delta, global_adj_db, global_publication_db): _, reported_node_name = key.split(':', 1) new_adj_db = deserialize_thrift_object(value.value, lsdb_types.AdjacencyDatabase) if delta: old_adj_db = global_adj_db.get(new_adj_db.thisNodeName, None) if old_adj_db is None: lines = ["ADJ_DB_ADDED: {}".format(new_adj_db.thisNodeName)] else: lines = utils.sprint_adj_db_delta(new_adj_db, old_adj_db) lines = '\n'.join(lines) else: _, lines = utils.sprint_adj_db_full(global_adj_db, new_adj_db, False) if lines: print_publication_delta( "{}'s adjacencies".format(reported_node_name), utils.sprint_pub_update(global_publication_db, key, value), lines) utils.update_global_adj_db(global_adj_db, new_adj_db)
def print_prefix_delta( self, key, value, delta, global_prefix_db, global_publication_db ): _, reported_node_name = key.split(":", 1) prefix_db = serializer.deserialize_thrift_object( value.value, lsdb_types.PrefixDatabase ) if delta: lines = "\n".join( utils.sprint_prefixes_db_delta(global_prefix_db, prefix_db) ) else: lines = utils.sprint_prefixes_db_full(prefix_db) if lines: print_timestamp() print_publication_delta( "{}'s prefixes".format(reported_node_name), utils.sprint_pub_update(global_publication_db, key, value), lines, ) utils.update_global_prefix_db(global_prefix_db, prefix_db)
def run_set(self, node_name, prefix_str): key = Consts.STATIC_PREFIX_ALLOC_PARAM_KEY prefix = utils.ip_str_to_prefix(prefix_str) # Retrieve previous allocation resp = self.client.get_keys([key]) allocs = None if key in resp.keyVals: allocs = serializer.deserialize_thrift_object( resp.keyVals.get(key).value, alloc_types.StaticAllocation) else: allocs = alloc_types.StaticAllocation(nodePrefixes={}) # Return if there is no change if allocs.nodePrefixes.get(node_name) == prefix: print('No changes needed. {}\'s prefix is already set to {}' .format(node_name, prefix_str)) return # Update value in KvStore allocs.nodePrefixes[node_name] = prefix value = serializer.serialize_thrift_object(allocs) self.run(key, value, 'breeze', None, Consts.CONST_TTL_INF)
def send_and_recv_thrift_obj(self, thrift_obj_to_send, thrift_type_to_recv): req = serializer.serialize_thrift_object( thrift_obj_to_send, self.cli_opts.proto_factory ) resp = None if self.thrift_client: try: resp = self.thrift_client.command(self.module_type, req) except Exception as e: print( "Tried to connect via thrift but could not. Exception: " "{}".format(e), file=sys.stderr, ) self.cleanup_thrift() raise e else: try: self.zmq_client.send(req) resp = self.zmq_client.recv() # TODO: remove after Link monitor socket is changed to ROUTER everywhere except Exception as e: if OpenrModuleType.LINK_MONITOR == self.module_type: dealer_client = self.get_zmq_client(zmq.DEALER) dealer_client.send(req) resp = dealer_client.recv() else: raise e if thrift_type_to_recv is str: return str(resp) return serializer.deserialize_thrift_object( resp, thrift_type_to_recv, self.cli_opts.proto_factory )
def print_db_delta( self, key, value, kvstore_adj_node_names, kvstore_prefix_node_names, decision_adj_dbs, decision_prefix_dbs, json, ): """ Returns status code. 0 = success, 1 = failure""" if key.startswith(Consts.ADJ_DB_MARKER): kvstore_adj_db = deserialize_thrift_object( value.value, lsdb_types.AdjacencyDatabase ) node_name = kvstore_adj_db.thisNodeName kvstore_adj_node_names.add(node_name) if node_name not in decision_adj_dbs: print( printing.render_vertical_table( [["node {}'s adj db is missing in Decision".format(node_name)]] ) ) return 1 decision_adj_db = decision_adj_dbs[node_name] return_code = 0 if json: tags = ("in_decision", "in_kvstore", "changed_in_decision_and_kvstore") adj_list_deltas = utils.find_adj_list_deltas( decision_adj_db.adjacencies, kvstore_adj_db.adjacencies, tags=tags ) deltas_json, return_code = utils.adj_list_deltas_json( adj_list_deltas, tags=tags ) if return_code: utils.print_json(deltas_json) else: lines = utils.sprint_adj_db_delta(kvstore_adj_db, decision_adj_db) if lines: print( printing.render_vertical_table( [ [ "node {}'s adj db in Decision out of sync with " "KvStore's".format(node_name) ] ] ) ) print("\n".join(lines)) return_code = 1 return return_code if key.startswith(Consts.PREFIX_DB_MARKER): kvstore_prefix_db = deserialize_thrift_object( value.value, lsdb_types.PrefixDatabase ) node_name = kvstore_prefix_db.thisNodeName kvstore_prefix_node_names.add(node_name) if node_name not in decision_prefix_dbs: print( printing.render_vertical_table( [ [ "node {}'s prefix db is missing in Decision".format( node_name ) ] ] ) ) return 1 decision_prefix_db = decision_prefix_dbs[node_name] decision_prefix_set = {} utils.update_global_prefix_db(decision_prefix_set, decision_prefix_db) lines = utils.sprint_prefixes_db_delta( decision_prefix_set, kvstore_prefix_db ) if lines: print( printing.render_vertical_table( [ [ "node {}'s prefix db in Decision out of sync with " "KvStore's".format(node_name) ] ] ) ) print("\n".join(lines)) return 1 return 0
def _parse_nodes(node_dict, value): prefix_db = deserialize_thrift_object(value.value, lsdb_types.PrefixDatabase) node_dict[prefix_db.thisNodeName] = self.get_node_ip(prefix_db)
def _parse_nodes(node_set, value): prefix_db = deserialize_thrift_object( value.value, lsdb_types.PrefixDatabase) node_set.add(prefix_db.thisNodeName)
def _run(self, client: OpenrCtrl.Client) -> None: prefix_mgr_config_blob = client.getConfigKey(Consts.PREFIX_MGR_KEY) prefix_mgr_config = deserialize_thrift_object( prefix_mgr_config_blob, lsdb_types.PrefixDatabase) self.print_config(prefix_mgr_config)
def _run(self, client: OpenrCtrl.Client) -> None: lm_config_blob = client.getConfigKey(Consts.LINK_MONITOR_KEY) lm_config = deserialize_thrift_object(lm_config_blob, lm_types.LinkMonitorConfig) self.print_config(lm_config)
def _run(self, client: OpenrCtrl.Client): prefix_alloc_blob = client.getConfigKey(Consts.PREFIX_ALLOC_KEY) prefix_alloc = deserialize_thrift_object(prefix_alloc_blob, ap_types.AllocPrefix) self.print_config(prefix_alloc)