Add ExaBGP route injector, Grafana dashboards, and full documentation
- Add exabgp/ container: ExaBGP 5.x + Flask REST API for on-demand BGP
route injection into CML IOS-XR lab (AS 65020 via eBGP from AS 65100)
- Add 6 injection scenarios: internet_sample, churn, blackhole, anycast,
full_table, lab_prefixes
- Add inject.py CLI wrapper for the ExaBGP API
- Add iosxr_bgp_config.md with IOS-XR neighbor config and NETCONF script
- Add obmp-grafana/ dashboards and provisioning (17 dashboards)
- Update docker-compose.yml: add exabgp service, fix Kafka external
listener IP, extend log retention from 90min to 720min
- Add DOCS.md: full project documentation including architecture, setup,
user guide, sanity checks, troubleshooting, and command reference
- Update .gitignore: exclude .env and .claude/
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 14:46:37 -07:00
{
"annotations" : {
"list" : [
{
"builtIn" : 1 ,
"datasource" : {
"type" : "datasource" ,
"uid" : "grafana"
} ,
"enable" : true ,
"hide" : true ,
"iconColor" : "rgba(0, 211, 255, 1)" ,
"name" : "Annotations & Alerts" ,
"target" : {
"limit" : 100 ,
"matchAny" : false ,
"tags" : [ ] ,
"type" : "dashboard"
} ,
"type" : "dashboard"
}
]
} ,
"editable" : true ,
"fiscalYearStartMonth" : 0 ,
"graphTooltip" : 0 ,
2026-05-18 20:55:03 -07:00
"id" : null ,
"links" : [
{ "asDropdown" : true , "icon" : "external link" , "includeVars" : true , "keepTime" : true , "tags" : [ "obmp-nav" ] , "title" : "OBMP Dashboards" , "type" : "dashboards" }
] ,
Add ExaBGP route injector, Grafana dashboards, and full documentation
- Add exabgp/ container: ExaBGP 5.x + Flask REST API for on-demand BGP
route injection into CML IOS-XR lab (AS 65020 via eBGP from AS 65100)
- Add 6 injection scenarios: internet_sample, churn, blackhole, anycast,
full_table, lab_prefixes
- Add inject.py CLI wrapper for the ExaBGP API
- Add iosxr_bgp_config.md with IOS-XR neighbor config and NETCONF script
- Add obmp-grafana/ dashboards and provisioning (17 dashboards)
- Update docker-compose.yml: add exabgp service, fix Kafka external
listener IP, extend log retention from 90min to 720min
- Add DOCS.md: full project documentation including architecture, setup,
user guide, sanity checks, troubleshooting, and command reference
- Update .gitignore: exclude .env and .claude/
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 14:46:37 -07:00
"liveNow" : false ,
"panels" : [
{
"datasource" : {
"type" : "postgres" ,
"uid" : "obmp_postgres"
} ,
"fieldConfig" : {
"defaults" : {
"color" : {
"mode" : "palette-classic"
} ,
"custom" : {
"hideFrom" : {
"legend" : false ,
"tooltip" : false ,
"viz" : false
}
} ,
"decimals" : 0 ,
"mappings" : [ ] ,
"unit" : "none"
} ,
"overrides" : [
{
"matcher" : {
"id" : "byName" ,
"options" : "up"
} ,
"properties" : [
{
"id" : "color" ,
"value" : {
"fixedColor" : "light-green" ,
"mode" : "fixed"
}
}
]
} ,
{
"matcher" : {
"id" : "byName" ,
"options" : "down"
} ,
"properties" : [
{
"id" : "color" ,
"value" : {
"fixedColor" : "light-red" ,
"mode" : "fixed"
}
}
]
}
]
} ,
"gridPos" : {
"h" : 11 ,
"w" : 4 ,
"x" : 0 ,
"y" : 0
} ,
"id" : 3 ,
"links" : [ ] ,
"maxDataPoints" : 3 ,
"options" : {
"displayLabels" : [ ] ,
"legend" : {
"calcs" : [ ] ,
"displayMode" : "table" ,
"placement" : "bottom" ,
"values" : [
"value" ,
"percent"
]
} ,
"pieType" : "pie" ,
"reduceOptions" : {
"calcs" : [
"lastNotNull"
] ,
"fields" : "" ,
"values" : true
} ,
"tooltip" : {
"mode" : "single" ,
"sort" : "none"
}
} ,
"targets" : [
{
"alias" : "" ,
"datasource" : {
"type" : "postgres" ,
"uid" : "obmp_postgres"
} ,
"format" : "table" ,
"group" : [ ] ,
"hide" : false ,
"metricColumn" : "none" ,
"rawQuery" : true ,
"rawSql" : "SELECT\n count(distinct router_hash_id) as value,\n r.state as metric\nFROM routers r\n JOIN bgp_peers p on (r.hash_id = p.router_hash_id)\n group by r.state\n" ,
"refId" : "A" ,
"select" : [
[
{
"params" : [
"value"
] ,
"type" : "column"
}
]
] ,
"timeColumn" : "time" ,
"where" : [
{
"name" : "$__timeFilter" ,
"params" : [ ] ,
"type" : "macro"
}
]
}
] ,
"title" : "Router Status" ,
"type" : "piechart"
} ,
{
"datasource" : {
"type" : "postgres" ,
"uid" : "obmp_postgres"
} ,
"fieldConfig" : {
"defaults" : {
"color" : {
"mode" : "thresholds"
} ,
"custom" : {
"align" : "auto" ,
"displayMode" : "auto" ,
"inspect" : false
} ,
"mappings" : [ ] ,
"thresholds" : {
"mode" : "absolute" ,
"steps" : [
{
"color" : "green" ,
"value" : null
} ,
{
"color" : "red" ,
"value" : 80
}
]
}
} ,
2026-05-18 20:55:03 -07:00
"overrides" : [
{
"matcher" : { "id" : "byName" , "options" : "name" } ,
"properties" : [
{ "id" : "links" , "value" : [ { "title" : "Open Router Detail" , "url" : "/d/obmp-router-detail/router-detail?var-router_hash=${__data.fields[\"hash_id\"]}" } ] }
]
} ,
{
"matcher" : { "id" : "byName" , "options" : "hash_id" } ,
"properties" : [ { "id" : "custom.hidden" , "value" : true } ]
} ,
{
"matcher" : { "id" : "byName" , "options" : "state" } ,
"properties" : [
{ "id" : "custom.displayMode" , "value" : "color-background" } ,
{ "id" : "mappings" , "value" : [ { "options" : { "down" : { "color" : "red" , "index" : 1 , "text" : "DOWN" } , "up" : { "color" : "green" , "index" : 0 , "text" : "UP" } } , "type" : "value" } ] }
]
}
]
Add ExaBGP route injector, Grafana dashboards, and full documentation
- Add exabgp/ container: ExaBGP 5.x + Flask REST API for on-demand BGP
route injection into CML IOS-XR lab (AS 65020 via eBGP from AS 65100)
- Add 6 injection scenarios: internet_sample, churn, blackhole, anycast,
full_table, lab_prefixes
- Add inject.py CLI wrapper for the ExaBGP API
- Add iosxr_bgp_config.md with IOS-XR neighbor config and NETCONF script
- Add obmp-grafana/ dashboards and provisioning (17 dashboards)
- Update docker-compose.yml: add exabgp service, fix Kafka external
listener IP, extend log retention from 90min to 720min
- Add DOCS.md: full project documentation including architecture, setup,
user guide, sanity checks, troubleshooting, and command reference
- Update .gitignore: exclude .env and .claude/
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 14:46:37 -07:00
} ,
"gridPos" : {
"h" : 11 ,
"w" : 20 ,
"x" : 4 ,
"y" : 0
} ,
"id" : 1 ,
"links" : [ ] ,
"options" : {
"footer" : {
"fields" : "" ,
"reducer" : [
"sum"
] ,
"show" : false
} ,
"showHeader" : true
} ,
"pluginVersion" : "8.5.4" ,
"targets" : [
{
"alias" : "" ,
"datasource" : {
"type" : "postgres" ,
"uid" : "obmp_postgres"
} ,
"format" : "table" ,
"group" : [ ] ,
"hide" : false ,
"metricColumn" : "none" ,
"rawQuery" : true ,
2026-05-18 20:55:03 -07:00
"rawSql" : "select max(r.hash_id::text) as hash_id,max(r.timestamp) as timestamp,r.name,max(ip_address) as ip_address,max(r.state) as state,\n count(*) as peers,max(description) as description, CASE WHEN max(r.state) = 'up' THEN 1 ELSE 0 END as stateBool\n from routers r\n JOIN bgp_peers p on (r.hash_id = p.router_hash_id)\n GROUP BY r.name;" ,
Add ExaBGP route injector, Grafana dashboards, and full documentation
- Add exabgp/ container: ExaBGP 5.x + Flask REST API for on-demand BGP
route injection into CML IOS-XR lab (AS 65020 via eBGP from AS 65100)
- Add 6 injection scenarios: internet_sample, churn, blackhole, anycast,
full_table, lab_prefixes
- Add inject.py CLI wrapper for the ExaBGP API
- Add iosxr_bgp_config.md with IOS-XR neighbor config and NETCONF script
- Add obmp-grafana/ dashboards and provisioning (17 dashboards)
- Update docker-compose.yml: add exabgp service, fix Kafka external
listener IP, extend log retention from 90min to 720min
- Add DOCS.md: full project documentation including architecture, setup,
user guide, sanity checks, troubleshooting, and command reference
- Update .gitignore: exclude .env and .claude/
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 14:46:37 -07:00
"refId" : "A" ,
"select" : [
[
{
"params" : [
"value"
] ,
"type" : "column"
}
]
] ,
"timeColumn" : "time" ,
"where" : [
{
"name" : "$__timeFilter" ,
"params" : [ ] ,
"type" : "macro"
}
]
}
] ,
"title" : "Routers" ,
"type" : "table"
} ,
{
"datasource" : {
"type" : "postgres" ,
"uid" : "obmp_postgres"
} ,
"fieldConfig" : {
"defaults" : {
"color" : {
"mode" : "palette-classic"
} ,
"custom" : {
"hideFrom" : {
"legend" : false ,
"tooltip" : false ,
"viz" : false
}
} ,
"decimals" : 0 ,
"mappings" : [ ] ,
"unit" : "none"
} ,
"overrides" : [
{
"matcher" : {
"id" : "byName" ,
"options" : "up"
} ,
"properties" : [
{
"id" : "color" ,
"value" : {
"fixedColor" : "light-green" ,
"mode" : "fixed"
}
}
]
} ,
{
"matcher" : {
"id" : "byName" ,
"options" : "down"
} ,
"properties" : [
{
"id" : "color" ,
"value" : {
"fixedColor" : "light-red" ,
"mode" : "fixed"
}
}
]
}
]
} ,
"gridPos" : {
"h" : 7 ,
"w" : 4 ,
"x" : 0 ,
"y" : 11
} ,
"id" : 4 ,
"links" : [ ] ,
"maxDataPoints" : 3 ,
"options" : {
"displayLabels" : [ ] ,
"legend" : {
"calcs" : [ ] ,
"displayMode" : "table" ,
"placement" : "bottom" ,
"sortBy" : "Value" ,
"sortDesc" : true ,
"values" : [
"value" ,
"percent"
]
} ,
"pieType" : "pie" ,
"reduceOptions" : {
"calcs" : [
"last"
] ,
"fields" : "" ,
"values" : true
} ,
"tooltip" : {
"mode" : "single" ,
"sort" : "none"
}
} ,
"pluginVersion" : "8.3.4" ,
"targets" : [
{
"alias" : "" ,
"datasource" : {
"type" : "postgres" ,
"uid" : "obmp_postgres"
} ,
"format" : "table" ,
"group" : [ ] ,
"hide" : false ,
"metricColumn" : "none" ,
"rawQuery" : true ,
"rawSql" : "SELECT\n state as metric,\n count(*) value\nFROM bgp_peers\ngroup by metric" ,
"refId" : "A" ,
"select" : [
[
{
"params" : [
"value"
] ,
"type" : "column"
}
]
] ,
"timeColumn" : "time" ,
"where" : [
{
"name" : "$__timeFilter" ,
"params" : [ ] ,
"type" : "macro"
}
]
}
] ,
"title" : "Peer Status" ,
"type" : "piechart"
} ,
{
"datasource" : {
"type" : "postgres" ,
"uid" : "obmp_postgres"
} ,
"fieldConfig" : {
"defaults" : {
"color" : {
"mode" : "thresholds"
} ,
"custom" : {
"align" : "auto" ,
"displayMode" : "auto" ,
"inspect" : false
} ,
"mappings" : [ ] ,
"thresholds" : {
"mode" : "absolute" ,
"steps" : [
{
"color" : "green" ,
"value" : null
} ,
{
"color" : "red" ,
"value" : 80
}
]
}
} ,
2026-05-18 20:55:03 -07:00
"overrides" : [
{
"matcher" : { "id" : "byName" , "options" : "PeerName" } ,
"properties" : [
{ "id" : "links" , "value" : [ { "title" : "Open Peer Detail" , "url" : "/d/obmp-peer-detail/peer-detail?var-peer_hash=${__data.fields[\"peer_hash_id\"]}" } ] }
]
} ,
{
"matcher" : { "id" : "byName" , "options" : "peer_hash_id" } ,
"properties" : [ { "id" : "custom.hidden" , "value" : true } ]
} ,
{
"matcher" : { "id" : "byName" , "options" : "State" } ,
"properties" : [
{ "id" : "custom.displayMode" , "value" : "color-background" } ,
{ "id" : "mappings" , "value" : [ { "options" : { "down" : { "color" : "red" , "index" : 1 , "text" : "DOWN" } , "up" : { "color" : "green" , "index" : 0 , "text" : "UP" } } , "type" : "value" } ] }
]
}
]
Add ExaBGP route injector, Grafana dashboards, and full documentation
- Add exabgp/ container: ExaBGP 5.x + Flask REST API for on-demand BGP
route injection into CML IOS-XR lab (AS 65020 via eBGP from AS 65100)
- Add 6 injection scenarios: internet_sample, churn, blackhole, anycast,
full_table, lab_prefixes
- Add inject.py CLI wrapper for the ExaBGP API
- Add iosxr_bgp_config.md with IOS-XR neighbor config and NETCONF script
- Add obmp-grafana/ dashboards and provisioning (17 dashboards)
- Update docker-compose.yml: add exabgp service, fix Kafka external
listener IP, extend log retention from 90min to 720min
- Add DOCS.md: full project documentation including architecture, setup,
user guide, sanity checks, troubleshooting, and command reference
- Update .gitignore: exclude .env and .claude/
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 14:46:37 -07:00
} ,
"gridPos" : {
"h" : 14 ,
"w" : 20 ,
"x" : 4 ,
"y" : 11
} ,
"id" : 2 ,
"links" : [ ] ,
"options" : {
"footer" : {
"fields" : "" ,
"reducer" : [
"sum"
] ,
"show" : false
} ,
"showHeader" : true ,
"sortBy" : [
{
"desc" : true ,
"displayName" : "IPv4 Prefixes"
}
]
} ,
"pluginVersion" : "8.5.4" ,
"targets" : [
{
"alias" : "" ,
"datasource" : {
"type" : "postgres" ,
"uid" : "obmp_postgres"
} ,
"format" : "table" ,
"group" : [ ] ,
"metricColumn" : "none" ,
"rawQuery" : true ,
2026-05-18 20:55:03 -07:00
"rawSql" : " SELECT\n p.peer_hash_id as peer_hash_id,\n max(RouterName) as \"RouterName\",\n max(PeerName) as \"PeerName\",\n max(PeerIP) as \"PeerIP\",\n max(PeerASN) as \"PeerASN\",\n max(peer_state) as \"State\",\n max(LastModified) as \"LastModified\",\n max(v4_prefixes) as \"IPv4 Prefixes\",\n max(v6_prefixes) as \"IPv6 Prefixes\",\n CASE WHEN max(peer_state) = 'up' THEN 1 ELSE 0 END as stateBool\nFROM v_peers p\n LEFT JOIN stats_peer_rib s ON (p.peer_hash_id = s.peer_hash_id\n AND s.interval_time >= now() - interval '20 minutes')\nGROUP BY p.peer_hash_id;\n" ,
Add ExaBGP route injector, Grafana dashboards, and full documentation
- Add exabgp/ container: ExaBGP 5.x + Flask REST API for on-demand BGP
route injection into CML IOS-XR lab (AS 65020 via eBGP from AS 65100)
- Add 6 injection scenarios: internet_sample, churn, blackhole, anycast,
full_table, lab_prefixes
- Add inject.py CLI wrapper for the ExaBGP API
- Add iosxr_bgp_config.md with IOS-XR neighbor config and NETCONF script
- Add obmp-grafana/ dashboards and provisioning (17 dashboards)
- Update docker-compose.yml: add exabgp service, fix Kafka external
listener IP, extend log retention from 90min to 720min
- Add DOCS.md: full project documentation including architecture, setup,
user guide, sanity checks, troubleshooting, and command reference
- Update .gitignore: exclude .env and .claude/
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 14:46:37 -07:00
"refId" : "A" ,
"select" : [
[
{
"params" : [
"value"
] ,
"type" : "column"
}
]
] ,
"timeColumn" : "time" ,
"where" : [
{
"name" : "$__timeFilter" ,
"params" : [ ] ,
"type" : "macro"
}
]
}
] ,
"title" : "Peers" ,
"type" : "table"
}
] ,
"schemaVersion" : 36 ,
"style" : "dark" ,
"tags" : [
2026-05-18 20:55:03 -07:00
"obmp" ,
"obmp-nav" ,
"operations"
Add ExaBGP route injector, Grafana dashboards, and full documentation
- Add exabgp/ container: ExaBGP 5.x + Flask REST API for on-demand BGP
route injection into CML IOS-XR lab (AS 65020 via eBGP from AS 65100)
- Add 6 injection scenarios: internet_sample, churn, blackhole, anycast,
full_table, lab_prefixes
- Add inject.py CLI wrapper for the ExaBGP API
- Add iosxr_bgp_config.md with IOS-XR neighbor config and NETCONF script
- Add obmp-grafana/ dashboards and provisioning (17 dashboards)
- Update docker-compose.yml: add exabgp service, fix Kafka external
listener IP, extend log retention from 90min to 720min
- Add DOCS.md: full project documentation including architecture, setup,
user guide, sanity checks, troubleshooting, and command reference
- Update .gitignore: exclude .env and .claude/
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 14:46:37 -07:00
] ,
"templating" : {
"list" : [ ]
} ,
"time" : {
"from" : "now-1h" ,
"to" : "now"
} ,
"timepicker" : {
"refresh_intervals" : [
"5s" ,
"10s" ,
"30s" ,
"1m" ,
"5m" ,
"15m" ,
"30m" ,
"1h" ,
"2h" ,
"1d"
] ,
"time_options" : [
"5m" ,
"15m" ,
"1h" ,
"6h" ,
"12h" ,
"24h" ,
"2d" ,
"7d" ,
"30d"
]
} ,
"timezone" : "utc" ,
"title" : "Inventory" ,
"uid" : "inventory" ,
"version" : 3 ,
"weekStart" : ""
}