def _get_combined_df(self, **kwargs): """OSPF has info divided across multiple tables. Get a single one""" columns = kwargs.pop('columns', ['default']) state = kwargs.pop('state', '') addnl_fields = kwargs.pop('addnl_fields', self.iobj._addnl_fields) addnl_nbr_fields = self.iobj._addnl_nbr_fields cols = SchemaForTable('ospf', schema=self.schemas) \ .get_display_fields(columns) if columns == ['default']: cols.append('timestamp') ifschema = SchemaForTable('ospfIf', schema=self.schemas) nbrschema = SchemaForTable('ospfNbr', schema=self.schemas) if (columns != ['default']) and (columns != ['*']): ifkeys = ifschema.key_fields() nbrkeys = nbrschema.key_fields() if_flds = ifschema.fields nbr_flds = nbrschema.fields ifcols = ifkeys nbrcols = nbrkeys for fld in columns: if fld in if_flds and fld not in ifcols: ifcols.append(fld) elif fld in nbr_flds and fld not in nbrcols: nbrcols.append(fld) else: ifcols = ifschema.get_display_fields(columns) nbrcols = nbrschema.get_display_fields(columns) if state == "full": query_str = 'adjState == "full" or adjState == "passive"' elif state == "other": query_str = 'adjState != "full" and adjState != "passive"' elif state == "passive": query_str = 'adjState == "passive"' else: query_str = '' df = self.get_valid_df('ospfIf', addnl_fields=addnl_fields, columns=ifcols, **kwargs) nbr_df = self.get_valid_df('ospfNbr', addnl_fields=addnl_nbr_fields, columns=nbrcols, **kwargs) if nbr_df.empty: return nbr_df merge_cols = [ x for x in ['namespace', 'hostname', 'ifname'] if x in nbr_df.columns ] # Merge the two tables df = df.merge(nbr_df, on=merge_cols, how='left') if columns == ['*']: df = df.drop(columns=['area_y', 'instance_y', 'vrf_y', 'areaStub_y', 'timestamp_y']) \ .rename(columns={ 'instance_x': 'instance', 'areaStub_x': 'areaStub', 'area_x': 'area', 'vrf_x': 'vrf', 'state_x': 'ifState', 'state_y': 'adjState', 'sqvers_x': 'sqvers', 'active_x': 'active', 'timestamp_x': 'timestamp'}) else: df = df.rename( columns={ 'vrf_x': 'vrf', 'area_x': 'area', 'state_x': 'ifState', 'state_y': 'adjState', 'timestamp_x': 'timestamp' }) df = df.drop(list(df.filter(regex='_y$')), axis=1) \ .fillna({'peerIP': '-', 'numChanges': 0, 'lastChangeTime': 0}) # Fill the adjState column with passive if passive if 'passive' in df.columns: df.loc[df['adjState'].isnull(), 'adjState'] = df['passive'] df.loc[df['adjState'].eq(True), 'adjState'] = 'passive' df.loc[df['adjState'].eq(False), 'adjState'] = 'fail' df.drop(columns=['passive'], inplace=True) df.bfill(axis=0, inplace=True) # Move the timestamp column to the end if query_str: return df.query(query_str)[cols] return df[cols]
def _get_combined_df(self, **kwargs): """OSPF has info divided across multiple tables. Get a single one""" columns = kwargs.pop('columns', ['default']) state = kwargs.pop('state', '') addnl_fields = kwargs.pop('addnl_fields', self.iobj._addnl_fields) addnl_nbr_fields = self.iobj._addnl_nbr_fields user_query = kwargs.pop('query_str', '') cols = SchemaForTable('ospf', schema=self.schemas) \ .get_display_fields(columns) if columns == ['default']: cols.append('timestamp') ifschema = SchemaForTable('ospfIf', schema=self.schemas) nbrschema = SchemaForTable('ospfNbr', schema=self.schemas) if (columns != ['default']) and (columns != ['*']): ifkeys = ifschema.key_fields() nbrkeys = nbrschema.key_fields() if_flds = ifschema.fields nbr_flds = nbrschema.fields ifcols = ifkeys nbrcols = nbrkeys for fld in columns: if fld in if_flds and fld not in ifcols: ifcols.append(fld) elif fld in nbr_flds and fld not in nbrcols: nbrcols.append(fld) else: ifcols = ifschema.get_display_fields(columns) nbrcols = nbrschema.get_display_fields(columns) if state == "full": query_str = 'adjState == "full" or adjState == "passive"' elif state == "other": query_str = 'adjState != "full" and adjState != "passive"' elif state == "passive": query_str = 'adjState == "passive"' else: query_str = '' df = self.get_valid_df('ospfIf', addnl_fields=addnl_fields, columns=ifcols, **kwargs) nbr_df = self.get_valid_df('ospfNbr', addnl_fields=addnl_nbr_fields, columns=nbrcols, **kwargs) if nbr_df.empty: return df merge_cols = [ x for x in ['namespace', 'hostname', 'ifname'] if x in nbr_df.columns ] # Merge the two tables df = df.merge(nbr_df, on=merge_cols, how='left') # This is because some NOS have the ipAddress in nbr table and some in # interface table. Nbr table wins over interface table if present if 'ipAddress_y' in df: df['ipAddress'] = np.where(df['ipAddress_y'] == "", df['ipAddress_x'], df['ipAddress_y']) df['ipAddress'] = np.where(df['ipAddress'], df['ipAddress'], df['ipAddress_x']) if columns == ['*']: df = df.drop(columns=['area_y', 'instance_y', 'vrf_y', 'ipAddress_x', 'ipAddress_y', 'areaStub_y', 'timestamp_y'], errors='ignore') \ .rename(columns={ 'instance_x': 'instance', 'areaStub_x': 'areaStub', 'area_x': 'area', 'vrf_x': 'vrf', 'state_x': 'ifState', 'state_y': 'adjState', 'sqvers_x': 'sqvers', 'active_x': 'active', 'timestamp_x': 'timestamp'}) else: df = df.rename( columns={ 'vrf_x': 'vrf', 'area_x': 'area', 'state_x': 'ifState', 'state_y': 'adjState', 'timestamp_x': 'timestamp' }) df = df.drop(list(df.filter(regex='_y$')), axis=1) \ .drop('ipAddress_x', axis=1, errors='ignore') \ .fillna({'peerIP': '-', 'numChanges': 0, 'lastChangeTime': 0}) # Fill the adjState column with passive if passive if 'passive' in df.columns: df.loc[df['adjState'].isnull(), 'adjState'] = df['passive'] df.loc[df['adjState'].eq(True), 'adjState'] = 'passive' df.loc[df['adjState'].eq(False), 'adjState'] = 'fail' df.drop(columns=['passive'], inplace=True) df.bfill(axis=0, inplace=True) if 'peerHostname' in columns or (columns in [['*'], ['default']]): nfdf = df.query('adjState != "full"').reset_index() nfdf['peerHostname'] = '' newdf = df.query('adjState == "full"').reset_index() \ .drop('peerHostname', axis=1, errors='ignore') if not newdf.empty: newdf['matchIP'] = newdf.ipAddress.str.split('/').str[0] newdf = newdf.merge(newdf[['namespace', 'hostname', 'vrf', 'matchIP']], left_on=['namespace', 'vrf', 'peerIP'], right_on=['namespace', 'vrf', 'matchIP'], suffixes=["", "_y"]) \ .rename(columns={'hostname_y': 'peerHostname'}) \ .drop_duplicates(subset=['namespace', 'hostname', 'vrf', 'ifname']) \ .drop(columns=['matchIP', 'matchIP_y'], errors='ignore') if newdf.empty: newdf = df.query('adjState == "full"').reset_index() newdf['peerHostname'] = '' final_df = pd.concat([nfdf, newdf]) else: final_df = df else: final_df = df if query_str: final_df = final_df.query(query_str).reset_index(drop=True) if user_query and not final_df.empty: final_df = self._handle_user_query_str(final_df, user_query) # Move the timestamp column to the end return final_df[cols]