Skip to content

Commit 7699b9b

Browse files
authored
NMS-19599: Fix metadata tags not being added to InterfaceLevelResource (#8352)
* NMS-19599: Fix metadata tags not being added to InterfaceLevelResource * NMS-19599: Add indexing for snmp ifname
1 parent 21741a8 commit 7699b9b

File tree

11 files changed

+141
-10
lines changed

11 files changed

+141
-10
lines changed

core/ipc/rpc/mock-impl/src/main/java/org/opennms/core/rpc/mock/MockEntityScopeProvider.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,11 @@ public Scope getScopeForInterfaceByIfIndex(Integer nodeId, int ifIndex) {
4949
return EmptyScope.EMPTY;
5050
}
5151

52+
@Override
53+
public Scope getScopeForInterfaceByIfName(Integer nodeId, String ifName) {
54+
return EmptyScope.EMPTY;
55+
}
56+
5257
@Override
5358
public Scope getScopeForService(final Integer nodeId, final InetAddress ipAddress, final String serviceName) {
5459
return EmptyScope.EMPTY;

core/mate/api/src/main/java/org/opennms/core/mate/api/EntityScopeProvider.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ interface Contexts {
4040

4141
Scope getScopeForInterfaceByIfIndex(final Integer nodeId, final int ifIndex);
4242

43+
Scope getScopeForInterfaceByIfName(final Integer nodeId, final String ifName);
44+
4345
Scope getScopeForService(final Integer nodeId, final InetAddress ipAddress, final String serviceName);
4446

4547
default ScopeProvider getScopeProviderForScv() {
@@ -58,6 +60,10 @@ default ScopeProvider getScopeProviderForInterfaceByIfIndex(final Integer nodeId
5860
return () -> getScopeForInterfaceByIfIndex(nodeId, ifIndex);
5961
}
6062

63+
default ScopeProvider getScopeProviderForInterfaceByIfName(final Integer nodeId, final String ifName) {
64+
return () -> getScopeForInterfaceByIfName(nodeId, ifName);
65+
}
66+
6167
default ScopeProvider getScopeProviderForService(final Integer nodeId, final InetAddress ipAddress, final String serviceName) {
6268
return () -> getScopeForService(nodeId, ipAddress, serviceName);
6369
}

core/mate/model/src/main/java/org/opennms/core/mate/model/EntityScopeProviderImpl.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import java.util.Map;
3535
import java.util.Objects;
3636
import java.util.Optional;
37+
import java.util.function.Supplier;
3738
import java.util.stream.Collectors;
3839

3940
import org.opennms.core.mate.api.ContextKey;
@@ -273,9 +274,20 @@ public Scope getScopeForInterfaceByIfIndex(final Integer nodeId, final int ifInd
273274
if (nodeId == null) {
274275
return EmptyScope.EMPTY;
275276
}
277+
return buildScopeForSnmpInterface(() -> this.snmpInterfaceDao.findByNodeIdAndIfIndex(nodeId, ifIndex));
278+
}
279+
280+
@Override
281+
public Scope getScopeForInterfaceByIfName(final Integer nodeId, final String ifName) {
282+
if (nodeId == null || Strings.isNullOrEmpty(ifName)) {
283+
return EmptyScope.EMPTY;
284+
}
285+
return buildScopeForSnmpInterface(() -> this.snmpInterfaceDao.findByNodeIdAndIfName(nodeId, ifName));
286+
}
276287

288+
private Scope buildScopeForSnmpInterface(final Supplier<OnmsSnmpInterface> snmpInterfaceLookup) {
277289
return this.sessionUtils.withReadOnlyTransaction(() -> {
278-
final OnmsSnmpInterface snmpInterface = this.snmpInterfaceDao.findByNodeIdAndIfIndex(nodeId, ifIndex);
290+
final OnmsSnmpInterface snmpInterface = snmpInterfaceLookup.get();
279291
if (snmpInterface == null) {
280292
return EmptyScope.EMPTY;
281293
}
@@ -286,7 +298,7 @@ public Scope getScopeForInterfaceByIfIndex(final Integer nodeId, final int ifInd
286298
scopes.add(new ObjectScope<>(Scope.ScopeName.INTERFACE, snmpInterface)
287299
.map(INTERFACE, "if-alias", (i) -> Optional.ofNullable(i.getIfAlias()))
288300
.map(INTERFACE, "if-description", (i) -> Optional.ofNullable(i.getIfDescr()))
289-
.map(INTERFACE, "if-name", (i) -> Optional.ofNullable(i.getIfName()))
301+
.map(INTERFACE, "if-name", (i) -> Optional.ofNullable(i.getIfName()))
290302
.map(INTERFACE, "phy-addr", (i) -> Optional.ofNullable(i.getPhysAddr())));
291303

292304
// IP interface facts w/ meta-data extracted from IP interface

core/mate/model/src/test/java/org/opennms/core/mate/model/EntityScopeProviderIT.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,23 @@ public final void testInterface() throws Exception {
144144
assertThat(scope.get(new ContextKey("interface", "phy-addr")), Matchers.is(Optional.of(new Scope.ScopeValue(Scope.ScopeName.INTERFACE, "34E45604BB69"))));
145145
}
146146

147+
@Test
148+
public final void testInterfaceByIfName() throws Exception {
149+
final Scope scope = this.provider.getScopeForInterfaceByIfName(this.populator.getNode1().getId(), "atm0");
150+
151+
assertThat(scope.get(new ContextKey("interface", "if-alias")), Matchers.is(Optional.of(new Scope.ScopeValue(Scope.ScopeName.INTERFACE, "Initial ifAlias value"))));
152+
assertThat(scope.get(new ContextKey("interface", "if-description")), Matchers.is(Optional.of(new Scope.ScopeValue(Scope.ScopeName.INTERFACE, "ATM0"))));
153+
assertThat(scope.get(new ContextKey("interface", "if-name")), Matchers.is(Optional.of(new Scope.ScopeValue(Scope.ScopeName.INTERFACE, "atm0"))));
154+
assertThat(scope.get(new ContextKey("interface", "phy-addr")), Matchers.is(Optional.of(new Scope.ScopeValue(Scope.ScopeName.INTERFACE, "34E45604BB69"))));
155+
}
156+
157+
@Test
158+
public final void testInterfaceByIfNameNotFound() throws Exception {
159+
final Scope scope = this.provider.getScopeForInterfaceByIfName(this.populator.getNode1().getId(), "nonexistent0");
160+
161+
assertThat(scope.get(new ContextKey("interface", "if-name")), Matchers.is(Optional.empty()));
162+
}
163+
147164
@Test
148165
public final void testService() throws Exception {
149166
final Scope scope = this.provider.getScopeForService(this.populator.getNode1().getId(), InetAddressUtils.getInetAddress("192.168.1.1"), "ICMP");

core/schema/src/main/liquibase/33.0.3/changelog.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,11 @@
2626
<changeSet author="cpape" id="33.0.3-assets-userlastmodified">
2727
<modifyDataType tableName="assets" columnName="userlastmodified" newDataType="varchar(256)"/>
2828
</changeSet>
29+
30+
<changeSet author="cgorantla" id="33.0.3-snmpinterface_nodeid_ifname-index">
31+
<createIndex tableName="snmpinterface" indexName="snmpinterface_nodeid_ifname_idx" unique="false">
32+
<column name="nodeid" />
33+
<column name="snmpifname" />
34+
</createIndex>
35+
</changeSet>
2936
</databaseChangeLog>

features/timeseries/src/main/java/org/opennms/netmgt/timeseries/samplewrite/MetaTagDataLoader.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -94,12 +94,14 @@ public Set<Tag> load(final CollectionResource resource) {
9494
OnmsNode node = nodeOptional.get();
9595
scopes.add(this.entityScopeProvider.getScopeForNode(node.getId()));
9696
if (resource.getResourceTypeName().equals(CollectionResource.RESOURCE_TYPE_IF)) {
97-
// We expect #getInstance to return the ifIndex for interface-level resources
98-
try {
99-
int ifIndex = Integer.parseInt(resource.getInstance());
100-
scopes.add(this.entityScopeProvider.getScopeForInterfaceByIfIndex(node.getId(), ifIndex));
101-
} catch(NumberFormatException nfe) {
102-
// pass
97+
String instance = resource.getInstance();
98+
if (instance != null && !instance.isEmpty()) {
99+
if (checkNumeric(instance)) {
100+
scopes.add(this.entityScopeProvider.getScopeForInterfaceByIfIndex(node.getId(), Integer.parseInt(instance)));
101+
} else {
102+
// Streaming telemetry resources use interface name instead of ifIndex
103+
scopes.add(this.entityScopeProvider.getScopeForInterfaceByIfName(node.getId(), instance));
104+
}
103105
}
104106
}
105107

features/timeseries/src/test/java/org/opennms/netmgt/timeseries/samplewrite/TimeseriesRoundtripIT.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,42 @@ public void canPersist() throws InterruptedException, StorageException, UnknownH
247247
}
248248

249249

250+
@Test
251+
public void verifyStreamingTelemetryInterfaceResource() {
252+
// Streaming telemetry uses interface name (e.g. "en1/0") instead of numeric ifIndex
253+
var collectionResource = mock(CollectionResource.class);
254+
when(collectionResource.getResourceTypeName()).thenReturn(CollectionResource.RESOURCE_TYPE_IF);
255+
when(collectionResource.getInstance()).thenReturn("en1/0"); // interface name, not ifIndex
256+
when(collectionResource.getParent()).thenReturn(ResourcePath.get("1"));
257+
when(collectionResource.getTags()).thenReturn(Collections.emptyMap());
258+
when(collectionResource.getServiceParams()).thenReturn(Collections.emptyMap());
259+
when(collectionResource.getInterfaceLabel()).thenReturn(null);
260+
261+
var tags = metaTagDataLoader.load(collectionResource);
262+
263+
// Should resolve interface scope via ifName fallback
264+
assertTrue("if_name tag should be present", tags.stream().anyMatch(tag -> tag.getKey().equals("if_name") && tag.getValue().equals("en1/0")));
265+
assertTrue("if_description tag should be present", tags.stream().anyMatch(tag -> tag.getKey().equals("if_description") && tag.getValue().equals("myDescription")));
266+
}
267+
268+
@Test
269+
public void verifySnmpInterfaceResource() {
270+
// SNMP uses numeric ifIndex
271+
var collectionResource = mock(CollectionResource.class);
272+
when(collectionResource.getResourceTypeName()).thenReturn(CollectionResource.RESOURCE_TYPE_IF);
273+
when(collectionResource.getInstance()).thenReturn("1"); // numeric ifIndex
274+
when(collectionResource.getParent()).thenReturn(ResourcePath.get("1"));
275+
when(collectionResource.getTags()).thenReturn(Collections.emptyMap());
276+
when(collectionResource.getServiceParams()).thenReturn(Collections.emptyMap());
277+
when(collectionResource.getInterfaceLabel()).thenReturn(null);
278+
279+
var tags = metaTagDataLoader.load(collectionResource);
280+
281+
// Should resolve interface scope via ifIndex
282+
assertTrue("if_name tag should be present", tags.stream().anyMatch(tag -> tag.getKey().equals("if_name") && tag.getValue().equals("en1/0")));
283+
assertTrue("if_description tag should be present", tags.stream().anyMatch(tag -> tag.getKey().equals("if_description") && tag.getValue().equals("myDescription")));
284+
}
285+
250286
@Test
251287
public void verifyLatencyResourceTags() throws UnknownHostException {
252288

opennms-dao-api/src/main/java/org/opennms/netmgt/dao/api/SnmpInterfaceDao.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ public interface SnmpInterfaceDao extends LegacyOnmsDao<OnmsSnmpInterface, Integ
6666

6767
OnmsSnmpInterface findByNodeIdAndDescription(Integer nodeId, String description);
6868

69+
OnmsSnmpInterface findByNodeIdAndIfName(Integer nodeId, String ifName);
70+
6971
void markHavingIngressFlows(final Integer nodeId, final Collection<Integer> ingressSnmpIfIndexes);
7072
void markHavingEgressFlows(final Integer nodeId, final Collection<Integer> egressSnmpIfIndexes);
7173

opennms-dao-mock/src/main/java/org/opennms/netmgt/dao/mock/MockSnmpInterfaceDao.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,16 @@ public OnmsSnmpInterface findByNodeIdAndDescription(Integer nodeId, String descr
125125
return null;
126126
}
127127

128+
@Override
129+
public OnmsSnmpInterface findByNodeIdAndIfName(Integer nodeId, String ifName) {
130+
for (final OnmsSnmpInterface iface : findAll()) {
131+
if (iface.getNode() != null && nodeId.equals(iface.getNode().getId()) && ifName.equals(iface.getIfName())) {
132+
return iface;
133+
}
134+
}
135+
return null;
136+
}
137+
128138
@Override
129139
public void markHavingIngressFlows(final Integer nodeId, final Collection<Integer> ingressSnmpIfIndexes) {
130140
}

opennms-dao/src/main/java/org/opennms/netmgt/dao/hibernate/SnmpInterfaceDaoHibernate.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,14 @@ public OnmsSnmpInterface findByNodeIdAndDescription(Integer nodeId, String descr
9393
);
9494
}
9595

96+
@Override
97+
public OnmsSnmpInterface findByNodeIdAndIfName(Integer nodeId, String ifName) {
98+
Assert.notNull(nodeId, "nodeId may not be null");
99+
Assert.notNull(ifName, "ifName may not be null");
100+
return findUnique("select snmpIf from OnmsSnmpInterface as snmpIf where snmpIf.node.id = ? and snmpIf.ifName = ?",
101+
nodeId, ifName);
102+
}
103+
96104
@Override
97105
public void markHavingIngressFlows(final Integer nodeId, final Collection<Integer> ingressSnmpIfIndexes) {
98106
getHibernateTemplate().executeWithNativeSession(session -> session.createSQLQuery("update snmpinterface set last_ingress_flow = NOW() where nodeid = :nodeid and snmpifindex in (:snmpIfIndexes)")

0 commit comments

Comments
 (0)