Skip to content

NMS-18182: Karaf shell commands for working with requisitions, foreignSources, and detectors.#8417

Open
dino2gnt wants to merge 5 commits intodevelopfrom
dcy/RequisitionKarafShellCmds
Open

NMS-18182: Karaf shell commands for working with requisitions, foreignSources, and detectors.#8417
dino2gnt wants to merge 5 commits intodevelopfrom
dcy/RequisitionKarafShellCmds

Conversation

@dino2gnt
Copy link
Copy Markdown
Contributor

@dino2gnt dino2gnt commented Apr 4, 2026

Karaf shell commands for working with requisitions, requisitioned nodes, foreign source definitions, and detectors. These have been baking on and off for quite some time now (probably since Q2 2023, cough cough) and after this last round of revisions I have everything working and cleaned up enough for a review.

I think these could enable some really interesting emergent workflows.

External References

Example usage output:

admin@opennms()> add-detector-to-foreignsource --foreignsource TESTING --name ICMP --class org.opennms.netmgt.provision.detector.icmp.IcmpDetector -p timeout=1500
Creating foreign source definition 'TESTING'.
Successfully added detector "ICMP" to "TESTING"!
admin@opennms()> add-detector-to-foreignsource --foreignsource TESTING --name SNMP --class org.opennms.netmgt.provision.detector.snmp.SnmpDetector -p timeout=3000
Successfully added detector "SNMP" to "TESTING"!
admin@opennms()> add-detector-to-foreignsource --foreignsource TESTING --name FOO --class org.opennms.netmgt.provision.detector.loop.LoopDetector -p timeout=3000
Successfully added detector "FOO" to "TESTING"!
admin@opennms()> show-foreignsource-definition TESTING
Name │ Class                                                   │ Parameters
─────┼─────────────────────────────────────────────────────────┼─────────────
ICMP │ org.opennms.netmgt.provision.detector.icmp.IcmpDetector │ timeout=1500
SNMP │ org.opennms.netmgt.provision.detector.snmp.SnmpDetector │ timeout=3000
FOO  │ org.opennms.netmgt.provision.detector.loop.LoopDetector │ timeout=3000
admin@opennms()>  show-foreignsource-definition --xml TESTING

<foreign-source xmlns="http://xmlns.opennms.org/xsd/config/foreign-source" name="TESTING" date-stamp="2026-04-03T20:46:44.046-05:00">
   <scan-interval>1d</scan-interval>
   <detectors>
      <detector name="ICMP" class="org.opennms.netmgt.provision.detector.icmp.IcmpDetector">
         <parameter key="timeout" value="1500"/>
      </detector>
      <detector name="SNMP" class="org.opennms.netmgt.provision.detector.snmp.SnmpDetector">
         <parameter key="timeout" value="3000"/>
      </detector>
      <detector name="FOO" class="org.opennms.netmgt.provision.detector.loop.LoopDetector">
         <parameter key="timeout" value="3000"/>
      </detector>
   </detectors>
   <policies/>
</foreign-source>

admin@opennms()> delete-detector-from-foreignsource --foreignsource TESTING --name FOO
Deleting FOO...
Deleted 1 detector(s).
admin@opennms()> show-foreignsource-definition TESTING
Name │ Class                                                   │ Parameters
─────┼─────────────────────────────────────────────────────────┼─────────────
ICMP │ org.opennms.netmgt.provision.detector.icmp.IcmpDetector │ timeout=1500
SNMP │ org.opennms.netmgt.provision.detector.snmp.SnmpDetector │ timeout=3000
admin@opennms()> show-foreignsource-definition --xml TESTING

<foreign-source xmlns="http://xmlns.opennms.org/xsd/config/foreign-source" name="TESTING" date-stamp="2026-04-03T20:48:14.405-05:00">
   <scan-interval>1d</scan-interval>
   <detectors>
      <detector name="ICMP" class="org.opennms.netmgt.provision.detector.icmp.IcmpDetector">
         <parameter key="timeout" value="1500"/>
      </detector>
      <detector name="SNMP" class="org.opennms.netmgt.provision.detector.snmp.SnmpDetector">
         <parameter key="timeout" value="3000"/>
      </detector>
   </detectors>
   <policies/>
</foreign-source>

admin@opennms()> add-requisitioned-node -n node1 --category nodes --requisition TESTING --interface 192.168.69.200,P,ICMP
Created requisition 'TESTING'.
Successfully added node "node1" to requisition "TESTING".
admin@opennms()> add-requisitioned-node -n node2 --category nodes --requisition TESTING --interface 192.168.69.201,P,ICMP
Successfully added node "node2" to requisition "TESTING".
admin@opennms()> show-requisition TESTING
Requisition Name │ Last Import Date │ Last Update Date             │ Node Count
─────────────────┼──────────────────┼──────────────────────────────┼───────────
TESTING          │                  │ Fri Apr 03 20:48:48 CDT 2026 │ 2

Node Label │ Foreign ID    │ Minion Location │ Building │ City │ Categories │ Meta Data │ Assets │ Interfaces          │ parentNodeLabel │ parentForeignSource │ parentForeignID
───────────┼───────────────┼─────────────────┼──────────┼──────┼────────────┼───────────┼────────┼─────────────────────┼─────────────────┼─────────────────────┼────────────────
node2      │ 1775267333808 │                 │          │      │ nodes      │           │        │ /192.168.69.201 : P │                 │                     │
           │               │                 │          │      │            │           │        │ ICMP                │                 │                     │
node1      │ 1775267328128 │                 │          │      │ nodes      │           │        │ /192.168.69.200 : P │                 │                     │
           │               │                 │          │      │            │           │        │ ICMP                │                 │                     │

admin@opennms()> show-requisition --xml TESTING
Requisition XML:
<model-import xmlns="http://xmlns.opennms.org/xsd/config/model-import" date-stamp="2026-04-03T20:48:48.130-05:00" foreign-source="TESTING">
   <node foreign-id="1775267333808" node-label="node2">
      <interface ip-addr="192.168.69.201" managed="true" status="1" snmp-primary="P">
         <monitored-service service-name="ICMP"/>
      </interface>
      <category name="nodes"/>
   </node>
   <node foreign-id="1775267328128" node-label="node1">
      <interface ip-addr="192.168.69.200" managed="true" status="1" snmp-primary="P">
         <monitored-service service-name="ICMP"/>
      </interface>
      <category name="nodes"/>
   </node>
</model-import>

admin@opennms()> opennms:filter "categoryName == 'nodes'"
No matching nodes/interfaces for this rule.
admin@opennms()> synchronize-requisition --wait --rescan dbonly TESTING
Requisition import triggered asynchronously for URL:
        file:/opt/opennms/etc/imports/TESTING.xml
........
Import succeeded.
admin@opennms()> opennms:filter "categoryName == 'nodes'"

nodeId=13 nodeLabel=node1 location=Default
        categories:
                nodes   IpAddresses:
                192.168.69.200

nodeId=14 nodeLabel=node2 location=Default
        categories:
                nodes   IpAddresses:
                192.168.69.201
admin@opennms()>
admin@opennms()> add-requisitioned-node -n node3 --category nodes --requisition TESTING --interface 192.168.69.202,P,ICMP
Successfully added node "node3" to requisition "TESTING".
admin@opennms()> opennms:filter "categoryName == 'nodes'"

nodeId=13 nodeLabel=node1 location=Default
        categories:
                nodes   IpAddresses:
                192.168.69.200

nodeId=14 nodeLabel=node2 location=Default
        categories:
                nodes   IpAddresses:
                192.168.69.201
admin@opennms()> synchronize-requisition --wait --rescan dbonly TESTING
Requisition import triggered asynchronously for URL:
        file:/opt/opennms/etc/imports/TESTING.xml
........
Import succeeded.
admin@opennms()> opennms:filter "categoryName == 'nodes'"

nodeId=13 nodeLabel=node1 location=Default
        categories:
                nodes   IpAddresses:
                192.168.69.200

nodeId=14 nodeLabel=node2 location=Default
        categories:
                nodes   IpAddresses:
                192.168.69.201

nodeId=15 nodeLabel=node3 location=Default
        categories:
                nodes   IpAddresses:
                192.168.69.202
admin@opennms()> show-requisition TESTING
Requisition Name │ Last Import Date             │ Last Update Date             │ Node Count
─────────────────┼──────────────────────────────┼──────────────────────────────┼───────────
TESTING          │ Fri Apr 03 20:51:30 CDT 2026 │ Fri Apr 03 20:48:48 CDT 2026 │ 3

Node Label │ Foreign ID    │ Minion Location │ Building │ City │ Categories │ Meta Data │ Assets │ Interfaces          │ parentNodeLabel │ parentForeignSource │ parentForeignID
───────────┼───────────────┼─────────────────┼──────────┼──────┼────────────┼───────────┼────────┼─────────────────────┼─────────────────┼─────────────────────┼────────────────
node3      │ 1775267484833 │                 │          │      │ nodes      │           │        │ /192.168.69.202 : P │                 │                     │
           │               │                 │          │      │            │           │        │ ICMP                │                 │                     │
node2      │ 1775267333808 │                 │          │      │ nodes      │           │        │ /192.168.69.201 : P │                 │                     │
           │               │                 │          │      │            │           │        │ ICMP                │                 │                     │
node1      │ 1775267328128 │                 │          │      │ nodes      │           │        │ /192.168.69.200 : P │                 │                     │
           │               │                 │          │      │            │           │        │ ICMP                │                 │                     │

admin@opennms()> delete-requisitioned-node --requisition TESTING --foreignid 1775267328128
Deleting foreignid '1775267328128'...
Deleted 1 node(s)
admin@opennms()> show-requisition TESTING
Requisition Name │ Last Import Date             │ Last Update Date             │ Node Count
─────────────────┼──────────────────────────────┼──────────────────────────────┼───────────
TESTING          │ Fri Apr 03 20:51:30 CDT 2026 │ Fri Apr 03 20:48:48 CDT 2026 │ 2

Node Label │ Foreign ID    │ Minion Location │ Building │ City │ Categories │ Meta Data │ Assets │ Interfaces          │ parentNodeLabel │ parentForeignSource │ parentForeignID
───────────┼───────────────┼─────────────────┼──────────┼──────┼────────────┼───────────┼────────┼─────────────────────┼─────────────────┼─────────────────────┼────────────────
node3      │ 1775267484833 │                 │          │      │ nodes      │           │        │ /192.168.69.202 : P │                 │                     │
           │               │                 │          │      │            │           │        │ ICMP                │                 │                     │
node2      │ 1775267333808 │                 │          │      │ nodes      │           │        │ /192.168.69.201 : P │                 │                     │
           │               │                 │          │      │            │           │        │ ICMP                │                 │                     │

admin@opennms()> opennms:filter "categoryName == 'nodes'"

nodeId=13 nodeLabel=node1 location=Default
        categories:
                nodes   IpAddresses:
                192.168.69.200

nodeId=14 nodeLabel=node2 location=Default
        categories:
                nodes   IpAddresses:
                192.168.69.201

nodeId=15 nodeLabel=node3 location=Default
        categories:
                nodes   IpAddresses:
                192.168.69.202
admin@opennms()> synchronize-requisition --wait --rescan dbonly TESTING
Requisition import triggered asynchronously for URL:
        file:/opt/opennms/etc/imports/TESTING.xml
.
Import succeeded.
admin@opennms()> opennms:filter "categoryName == 'nodes'"

nodeId=14 nodeLabel=node2 location=Default
        categories:
                nodes   IpAddresses:
                192.168.69.201

nodeId=15 nodeLabel=node3 location=Default
        categories:
                nodes   IpAddresses:
                192.168.69.202
admin@opennms()> delete-requisition --empty --yes-i-really-mean-it TESTING
Requisition contains 2 nodes.
Deleted 2 nodes.
admin@opennms()> synchronize-requisition --wait --rescan dbonly TESTING
Requisition import triggered asynchronously for URL:
        file:/opt/opennms/etc/imports/TESTING.xml
........
Import succeeded.
admin@opennms()> delete-requisition --yes-i-really-mean-it TESTING
Deleted 'TESTING'.
admin@opennms()> show-foreignsource-definition TESTING
Name │ Class                                                   │ Parameters
─────┼─────────────────────────────────────────────────────────┼─────────────
ICMP │ org.opennms.netmgt.provision.detector.icmp.IcmpDetector │ timeout=1500
SNMP │ org.opennms.netmgt.provision.detector.snmp.SnmpDetector │ timeout=3000
admin@opennms()> delete-foreignsource -f TESTING
Deleted foreign source 'TESTING'.
admin@opennms()> show-foreignsource-definition TESTING
ForeignSource 'TESTING' does not exist, displaying Default Foreign Source:
Name                │ Class                                                      │ Parameters
────────────────────┼────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────────────
DNS                 │ org.opennms.netmgt.provision.detector.datagram.DnsDetector │
FTP                 │ org.opennms.netmgt.provision.detector.simple.FtpDetector   │
HTTP                │ org.opennms.netmgt.provision.detector.simple.HttpDetector  │
HTTPS               │ org.opennms.netmgt.provision.detector.simple.HttpsDetector │
ICMP                │ org.opennms.netmgt.provision.detector.icmp.IcmpDetector    │
IMAP                │ org.opennms.netmgt.provision.detector.simple.ImapDetector  │
LDAP                │ org.opennms.netmgt.provision.detector.simple.LdapDetector  │
NRPE                │ org.opennms.netmgt.provision.detector.simple.NrpeDetector  │
POP3                │ org.opennms.netmgt.provision.detector.simple.Pop3Detector  │
SMTP                │ org.opennms.netmgt.provision.detector.simple.SmtpDetector  │
SNMP                │ org.opennms.netmgt.provision.detector.snmp.SnmpDetector    │
SSH                 │ org.opennms.netmgt.provision.detector.ssh.SshDetector      │
WS-Man              │ org.opennms.netmgt.provision.detector.wsman.WsManDetector  │
OpenNMS-JVM         │ org.opennms.netmgt.provision.detector.jmx.Jsr160Detector   │ port=18980
                    │                                                            │ factory=PASSWORD_CLEAR
                    │                                                            │ username=admin
                    │                                                            │ password=admin
                    │                                                            │ protocol=rmi
                    │                                                            │ urlPath=/jmxrmi
                    │                                                            │ timeout=3000
                    │                                                            │ retries=2
                    │                                                            │ type=default
                    │                                                            │ ipMatch=127.0.0.1
JMX-Minion          │ org.opennms.netmgt.provision.detector.jmx.Jsr160Detector   │ port=1299
                    │                                                            │ factory=PASSWORD_CLEAR
                    │                                                            │ username=admin
                    │                                                            │ password=admin
                    │                                                            │ protocol=rmi
                    │                                                            │ urlPath=/karaf-minion
                    │                                                            │ timeout=3000
                    │                                                            │ retries=2
                    │                                                            │ type=default
JMX-Cassandra       │ org.opennms.netmgt.provision.detector.jmx.Jsr160Detector   │ port=7199
                    │                                                            │ retries=2
                    │                                                            │ timeout=3000
                    │                                                            │ protocol=rmi
                    │                                                            │ urlPath=/jmxrmi
                    │                                                            │ factory=PASSWORD_CLEAR
                    │                                                            │ username=cassandra-username
                    │                                                            │ password=cassandra-password
                    │                                                            │ type=default
JMX-Cassandra-Newts │ org.opennms.netmgt.provision.detector.jmx.Jsr160Detector   │ port=7199
                    │                                                            │ retries=2
                    │                                                            │ timeout=3000
                    │                                                            │ protocol=rmi
                    │                                                            │ urlPath=/jmxrmi
                    │                                                            │ factory=PASSWORD_CLEAR
                    │                                                            │ username=cassandra-username
                    │                                                            │ password=cassandra-password
                    │                                                            │ type=default
                    │                                                            │ object=org.apache.cassandra.db:type=ColumnFamilies,keyspace=newts,columnfamily=samples
MS-RDP              │ org.opennms.netmgt.provision.detector.simple.TcpDetector   │ port=3389
admin@opennms()>

@github-actions github-actions bot added the docs label Apr 4, 2026
@github-actions github-actions bot requested a review from indigo423 April 4, 2026 02:56
Copy link
Copy Markdown
Contributor

@marshallmassengill marshallmassengill left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks awesome. I'd be ok with targeting this at 2025 if we know it doesn't break anything. It looks like everything is net new.

garcia-sr
garcia-sr previously approved these changes Apr 7, 2026
Copy link
Copy Markdown
Contributor

@garcia-sr garcia-sr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! This is awesome stuff and I think it'll be super handy to have this inside Karaf.

Copy link
Copy Markdown
Contributor

@cgorantla cgorantla left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to trim down these commands and think about what we really need.

IMO, we should limit karaf commands to debug things quickly and understand the current state of the application. Expanding them to do complex operations will be extra burden to maintain.

@Option(name = "-v", aliases = "--verbose", description = "Be verbose; show us the node XML")
private boolean verbose = false;

public Object execute() {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if having so many options with so many multi valued makes sense. We should consider improvements to this command

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The node model is complicated. I wanted to make sure that as many bases as possible were covered, but the only required arguments are requisition, nodelabel and ipaddress.


if (wait) {
try {
while (!importEventListener.isDone()) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what if importEventListener never done ? We should not hang the command.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will print dots until the event comes in. This is a copy of what was already done in ImportRequisition.java , not an original idea :-)

User can always ctrl+c to end the command if they do not wish to wait (or run without --wait)

@dino2gnt dino2gnt dismissed stale reviews from garcia-sr and marshallmassengill via b82a671 April 8, 2026 21:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants