Network management as a Neo4j graph model
A graph data model of a data center, from its racks and routers down to the software running on each machine.
Open this model in toro4n
What the model shows
On the hardware side, the data center contains routers and racks, racks hold switches and machines, and each machine has a type. On the network side, routers, switches, machines, and network zones all route to interfaces. Interfaces connect to zones and to each other, and they expose ports. Each Connection joins two ports. On the software side, machines run operating system, application, and service processes, and the application and service processes listen on ports. Operating systems, services, and other software each have a chain of versions. Applications depend on services, other software, and specific versions.
Network management is the most complex of Neo4j's official examples, which makes it a good one to learn from. Several nodes have two labels, such as Router:Egress, and some relationships connect two nodes with the same label, such as PREVIOUS from one Version to another. Three relationship types run from Interface to Port: EXPOSES, OPENS, and LISTENS.
Nodes and properties
Application:Process
name: STRINGpid: INTEGERstartTime: INTEGER
Connection
id: STRINGsource: STRINGtarget: STRINGuser: STRINGtime: INTEGER
DataCenter
name: STRINGlocation: STRING
Interface
ip: STRING
Machine
id: INTEGERname: STRING
Network:Zone
ip: STRINGsize: INTEGERzone: INTEGER
Os:Process
name: STRINGstartTime: INTEGER
Port
port: INTEGER
Rack
name: STRINGrack: INTEGERzone: INTEGER
Router
name: STRINGzone: INTEGER
Router:Egress
name: STRING
Service:Process
name: STRINGpid: INTEGERstartTime: INTEGER
Software
name: STRING
Software:Application
name: STRINGports: LIST<INTEGER>dependencies: LIST<STRING>
Software:Os
name: STRINGversions: LIST<STRING>
Software:Service
name: STRINGversions: LIST<STRING>ports: LIST<INTEGER>dependencies: LIST<STRING>
Switch
ip: STRINGrack: INTEGER
Type
id: INTEGERname: STRINGtype: STRINGcpu: INTEGERram: INTEGERdisk: INTEGER
Version
name: STRING
Relationships
(:DataCenter)-[:CONTAINS]->(:Router)(:DataCenter)-[:CONTAINS]->(:Router:Egress)(:DataCenter)-[:CONTAINS]->(:Rack)(:Rack)-[:HOLDS]->(:Switch)(:Rack)-[:HOLDS]->(:Machine)(:Machine)-[:TYPE]->(:Type)(:Router)-[:ROUTES]->(:Interface)(:Router:Egress)-[:ROUTES]->(:Interface)(:Switch)-[:ROUTES]->(:Interface)(:Machine)-[:ROUTES]->(:Interface)(:Network:Zone)-[:ROUTES]->(:Interface)(:Interface)-[:CONNECTS]->(:Network:Zone)(:Interface)-[:CONNECTS]->(:Interface)(:Interface)-[:CONNECTIONS]->(:Interface)(:Interface)-[:EXPOSES]->(:Port)(:Interface)-[:OPENS]->(:Port)(:Interface)-[:LISTENS]->(:Port)(:Connection)-[:FROM]->(:Port)(:Connection)-[:TO]->(:Port)(:Machine)-[:RUNS]->(:Os:Process)(:Machine)-[:RUNS]->(:Application:Process)(:Machine)-[:RUNS]->(:Service:Process)(:Machine)-[:UPDATE_TO]->(:Version)withts: INTEGER(:Application:Process)-[:LISTENS]->(:Port)(:Service:Process)-[:LISTENS]->(:Port)(:Application:Process)-[:DEPENDS_ON]->(:Service:Process)(:Os:Process)-[:INSTANCE]->(:Version)(:Application:Process)-[:INSTANCE]->(:Software:Application)(:Service:Process)-[:INSTANCE]->(:Software:Service)(:Service:Process)-[:INSTANCE]->(:Version)(:Software:Os)-[:VERSION]->(:Version)(:Software:Service)-[:VERSION]->(:Version)(:Software)-[:VERSION]->(:Version)(:Version)-[:PREVIOUS]->(:Version)(:Software:Service)-[:DEPENDS_ON]->(:Version)(:Software:Application)-[:DEPENDS_ON]->(:Version)(:Software:Application)-[:DEPENDS_ON]->(:Software:Service)(:Software:Application)-[:DEPENDS_ON]->(:Software)
Layers
- Software: 8 nodes
- Network: 4 nodes
- Hardware: 7 nodes
Modeling notes
- A second label, Egress, lets queries match egress routers directly instead of filtering on a property.
- PREVIOUS runs from each version to the one before it, so the versions form a linked list. That lets a query tell which of two versions is older, even when sorting by name would put them in the wrong order.
- UPDATE_TO marks a machine for an upgrade to a newer version. The relationship's ts property records when the upgrade was requested.
- Connection is an intermediate node: FROM and TO point to the two ports it joins. Because it's a node rather than a relationship between the ports, other relationships can start or end at the connection.
- Each Process node is one running instance of a piece of software. INSTANCE points to that software, or to the specific version the process runs.
Cypher
Here's the Cypher script toro4n generates for this model. It creates every node and relationship, with each property's type name as a placeholder value.
CREATE (DataCenter:DataCenter {name: "STRING", location: "STRING"})
CREATE (Type:Type {id: "INTEGER", name: "STRING", type: "STRING", cpu: "INTEGER", ram: "INTEGER", disk: "INTEGER"})
CREATE (Machine:Machine {id: "INTEGER", name: "STRING"})
CREATE (Rack:Rack {name: "STRING", rack: "INTEGER", zone: "INTEGER"})
CREATE (Switch:Switch {ip: "STRING", rack: "INTEGER"})
CREATE (Router:Router {name: "STRING", zone: "INTEGER"})
CREATE (RouterEgress:Router:Egress {name: "STRING"})
CREATE (Interface:Interface {ip: "STRING"})
CREATE (NetworkZone:Network:Zone {ip: "STRING", size: "INTEGER", zone: "INTEGER"})
CREATE (Port:Port {port: "INTEGER"})
CREATE (Connection:Connection {id: "STRING", source: "STRING", target: "STRING", user: "STRING", time: "INTEGER"})
CREATE (OsProcess:Os:Process {name: "STRING", startTime: "INTEGER"})
CREATE (ApplicationProcess:Application:Process {name: "STRING", pid: "INTEGER", startTime: "INTEGER"})
CREATE (ServiceProcess:Service:Process {name: "STRING", pid: "INTEGER", startTime: "INTEGER"})
CREATE (Version:Version {name: "STRING"})
CREATE (SoftwareOs:Software:Os {name: "STRING", versions: "LIST<STRING>"})
CREATE (SoftwareApplication:Software:Application {name: "STRING", ports: "LIST<INTEGER>", dependencies: "LIST<STRING>"})
CREATE (SoftwareService:Software:Service {name: "STRING", versions: "LIST<STRING>", ports: "LIST<INTEGER>", dependencies: "LIST<STRING>"})
CREATE (Software:Software {name: "STRING"})
CREATE (DataCenter)-[:CONTAINS]->(Router)
CREATE (DataCenter)-[:CONTAINS]->(RouterEgress)
CREATE (DataCenter)-[:CONTAINS]->(Rack)
CREATE (Rack)-[:HOLDS]->(Switch)
CREATE (Rack)-[:HOLDS]->(Machine)
CREATE (Machine)-[:TYPE]->(Type)
CREATE (Router)-[:ROUTES]->(Interface)
CREATE (RouterEgress)-[:ROUTES]->(Interface)
CREATE (Switch)-[:ROUTES]->(Interface)
CREATE (Machine)-[:ROUTES]->(Interface)
CREATE (NetworkZone)-[:ROUTES]->(Interface)
CREATE (Interface)-[:CONNECTS]->(NetworkZone)
CREATE (Interface)-[:CONNECTS]->(Interface)
CREATE (Interface)-[:CONNECTIONS]->(Interface)
CREATE (Interface)-[:EXPOSES]->(Port)
CREATE (Interface)-[:OPENS]->(Port)
CREATE (Interface)-[:LISTENS]->(Port)
CREATE (Connection)-[:FROM]->(Port)
CREATE (Connection)-[:TO]->(Port)
CREATE (Machine)-[:RUNS]->(OsProcess)
CREATE (Machine)-[:RUNS]->(ApplicationProcess)
CREATE (Machine)-[:RUNS]->(ServiceProcess)
CREATE (Machine)-[:UPDATE_TO {ts: "INTEGER"}]->(Version)
CREATE (ApplicationProcess)-[:LISTENS]->(Port)
CREATE (ServiceProcess)-[:LISTENS]->(Port)
CREATE (ApplicationProcess)-[:DEPENDS_ON]->(ServiceProcess)
CREATE (OsProcess)-[:INSTANCE]->(Version)
CREATE (ApplicationProcess)-[:INSTANCE]->(SoftwareApplication)
CREATE (ServiceProcess)-[:INSTANCE]->(SoftwareService)
CREATE (ServiceProcess)-[:INSTANCE]->(Version)
CREATE (SoftwareOs)-[:VERSION]->(Version)
CREATE (SoftwareService)-[:VERSION]->(Version)
CREATE (Software)-[:VERSION]->(Version)
CREATE (Version)-[:PREVIOUS]->(Version)
CREATE (SoftwareService)-[:DEPENDS_ON]->(Version)
CREATE (SoftwareApplication)-[:DEPENDS_ON]->(Version)
CREATE (SoftwareApplication)-[:DEPENDS_ON]->(SoftwareService)
CREATE (SoftwareApplication)-[:DEPENDS_ON]->(Software)
Source
The model is based on neo4j-graph-examples/network-management on GitHub. Download the model as network-management.json.