summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Pokorný <jpokorny@redhat.com>2013-04-03 18:34:07 +0200
committerJan Pokorný <jpokorny@redhat.com>2013-04-03 18:34:07 +0200
commit422bad775ba43250974c6ef2fbd2bc98357b46c5 (patch)
tree0863b5ad9b7211cde207600f41aad7db3dc78cb5
downloadcluster-overview-422bad775ba43250974c6ef2fbd2bc98357b46c5.tar.gz
cluster-overview-422bad775ba43250974c6ef2fbd2bc98357b46c5.tar.xz
cluster-overview-422bad775ba43250974c6ef2fbd2bc98357b46c5.zip
Let's start
Signed-off-by: Jan Pokorný <jpokorny@redhat.com>
-rwxr-xr-xoverview.py329
1 files changed, 329 insertions, 0 deletions
diff --git a/overview.py b/overview.py
new file mode 100755
index 0000000..5a6c6d0
--- /dev/null
+++ b/overview.py
@@ -0,0 +1,329 @@
+#!/usr/bin/env python
+# vim: set fileencoding=UTF-8:
+# Copyright 2013 Red Hat, Inc.
+# Author: Jan Pokorný <jpokorny at redhat dot com>
+# Distributed under GPLv2+; generated content under CC-BY-SA 3.0
+# (to view a copy, visit http://creativecommons.org/licenses/by-sa/3.0/)
+"""Model of cman-based cluster capturing deployment, communication, etc.
+
+By default, output is a PDF file named as per this script modulo extension.
+Generally, you can specify arbitrary format/extension supported by graphviz
+as a first parameter and you'll get what you ask for, including original
+'.dot' file for further utilization.
+"""
+
+from pydot import Dot, Edge, Node, Subgraph
+from sys import argv
+from os.path import extsep, splitext
+
+
+FONT = 'Inconsolata'
+FONTDEF = map(lambda switch: '-' + switch + 'fontname=' + FONT, "GNE")
+OUTPUT = splitext(__file__)[0]
+
+
+#
+# Subgraph inheritance
+#
+
+
+class GraphNode(Subgraph):
+ def __init__(self, *args, **kwargs):
+ kwargs.setdefault('style', 'bold')
+ super(GraphNode, self).__init__(*args, **kwargs)
+
+
+class GraphSubnode(Subgraph):
+ def __init__(self, *args, **kwargs):
+ kwargs.setdefault('fillcolor', 'azure')
+ kwargs.setdefault('style', 'filled')
+ super(GraphSubnode, self).__init__(*args, **kwargs)
+
+
+#
+# Node inheritance
+#
+
+
+class Program(Node):
+ def __init__(self, *args, **kwargs):
+ kwargs.setdefault('shape', 'box')
+ super(Program, self).__init__(*args, **kwargs)
+
+
+class Agent(Program):
+ def __init__(self, *args, **kwargs):
+ kwargs.setdefault('fillcolor', 'lavenderblush')
+ kwargs.setdefault('style', 'filled')
+ super(Agent, self).__init__(*args, **kwargs)
+
+
+class Executable(Program):
+ pass
+
+
+class Daemon(Executable):
+ def __init__(self, *args, **kwargs):
+ kwargs.setdefault('fillcolor', 'cornsilk')
+ kwargs.setdefault('style', 'filled')
+ super(Daemon, self).__init__(*args, **kwargs)
+
+
+class Artefact(Node):
+ def __init__(self, *args, **kwargs):
+ kwargs.setdefault('shape', 'box3d')
+ kwargs.setdefault('fillcolor', 'wheat')
+ kwargs.setdefault('style', 'filled')
+ super(Artefact, self).__init__(*args, **kwargs)
+
+
+#
+# Edge inheritance
+#
+
+
+class DBUS(Edge):
+ def __init__(self, *args, **kwargs):
+ kwargs.setdefault('style', 'dotted')
+ super(DBUS, self).__init__(*args, **kwargs)
+
+
+class OddjobExec(DBUS):
+ def __init__(self, *args, **kwargs):
+ kwargs.setdefault('label', 'oddjob exec')
+ super(OddjobExec, self).__init__(*args, **kwargs)
+
+
+class HTTPS(Edge):
+ def __init__(self, *args, **kwargs):
+ kwargs.setdefault('style', 'bold')
+ super(HTTPS, self).__init__(*args, **kwargs)
+
+
+class LuciHTTPS(HTTPS):
+ def __init__(self, *args, **kwargs):
+ kwargs.setdefault('label', 'port 8084')
+ super(LuciHTTPS, self).__init__(*args, **kwargs)
+
+
+class ApplicationSpecificProtocol(Edge):
+ def __init__(self, *args, **kwargs):
+ kwargs.setdefault('style', 'dashed')
+ super(ApplicationSpecificProtocol, self).__init__(*args, **kwargs)
+
+
+class RICCIRPC(ApplicationSpecificProtocol):
+ def __init__(self, *args, **kwargs):
+ kwargs.setdefault('label', 'port 11111')
+ super(RICCIRPC, self).__init__(*args, **kwargs)
+
+
+class SNMP(ApplicationSpecificProtocol):
+ def __init__(self, *args, **kwargs):
+ kwargs.setdefault('label', 'port 161')
+ super(SNMP, self).__init__(*args, **kwargs)
+
+
+class CIM(ApplicationSpecificProtocol):
+ def __init__(self, *args, **kwargs):
+ kwargs.setdefault('label', 'port 898[89]')
+ super(CIM, self).__init__(*args, **kwargs)
+
+
+class Consume(Edge):
+ def __init__(self, *args, **kwargs):
+ kwargs.setdefault('color', 'darkgreen')
+ kwargs.setdefault('fontcolor', 'darkgreen')
+ super(Consume, self).__init__(*args, **kwargs)
+
+
+class ConsumeReversed(Consume):
+ def __init__(self, *args, **kwargs):
+ kwargs.setdefault('dir', 'back')
+ super(ConsumeReversed, self).__init__(*reversed(args), **kwargs)
+
+
+class Produce(Edge):
+ def __init__(self, *args, **kwargs):
+ kwargs.setdefault('color', 'orangered')
+ kwargs.setdefault('fontcolor', 'orangered')
+ super(Produce, self).__init__(*args, **kwargs)
+
+
+class Delegate(Edge):
+ def __init__(self, *args, **kwargs):
+ kwargs.setdefault('color', 'navy')
+ kwargs.setdefault('fontcolor', 'navy')
+ kwargs.setdefault('dir', 'both')
+ super(Delegate, self).__init__(*args, **kwargs)
+
+
+# peer-to-peer
+class Exchange(Edge):
+ def __init__(self, *args, **kwargs):
+ kwargs.setdefault('color', 'saddlebrown')
+ kwargs.setdefault('fontcolor', 'saddlebrown')
+ kwargs.setdefault('dir', 'both')
+ super(Exchange, self).__init__(*args, **kwargs)
+
+
+# mixing
+
+class DelegateOddjobExec(Delegate, OddjobExec):
+ pass
+
+
+class DelegateRICCIRPC(Delegate, RICCIRPC):
+ pass
+
+
+class DelegateLuciHTTPS(Delegate, LuciHTTPS):
+ pass
+
+
+class DelegateSNMP(Delegate, SNMP):
+ pass
+
+
+class DelegateCIM(Delegate, CIM):
+ pass
+
+
+#
+# Here we go
+#
+
+
+# management client
+
+node_mgmt = Subgraph('cluster-climgmt', label='management client')
+
+node_mgmt.add_node(Program('luci'))
+node_mgmt.add_node(Program('ccs'))
+
+
+# other monitoring
+
+node_mon = Subgraph('cluster-monitor', label='other monitoring')
+
+node_mon.add_node(Program('snmpwalk'))
+node_mon.add_node(Program('wbemcli'))
+
+
+# node b - management
+
+node_b_conga = GraphSubnode('cluster-node_b-conga', label='management')
+
+node_b_conga.add_node(Agent('node_b-libClusterMonitorSnmp.so', label='libClusterMonitorSnmp.so'))
+node_b_conga.add_node(Agent('node_b-libRedHatClusterProvider.so', label='libRedHatClusterProvider.so'))
+node_b_conga.add_node(Artefact('node_b-clumond.sock', label='/var/run/clumond.sock'))
+node_b_conga.add_node(Daemon('node_b-ricci', label='ricci'))
+node_b_conga.add_node(Daemon('node_b-modclusterd', label='modclusterd'))
+node_b_conga.add_node(Program('node_b-modcluster', label='modcluster'))
+
+node_b_conga.add_edge(Consume('node_b-libClusterMonitorSnmp.so', 'node_b-clumond.sock'))
+node_b_conga.add_edge(Consume('node_b-libRedHatClusterProvider.so', 'node_b-clumond.sock'))
+node_b_conga.add_edge(Consume('node_b-modcluster', 'node_b-clumond.sock'))
+node_b_conga.add_edge(Produce('node_b-modclusterd', 'node_b-clumond.sock'))
+
+
+# node b - core
+
+node_b_core = GraphSubnode('cluster-node_b-core', label='core')
+
+node_b_core.add_node(Node('node_b-libccsconfdb', label='libccsconfdb'))
+node_b_core.add_node(Daemon('node_b-rgmanager', label='rgmanager'))
+node_b_core.add_node(Program('node_b-clustat', label='clustat'))
+node_b_core.add_node(Artefact('node_b-rgmanager.sk', label='/var/run/cluster/rgmanager.sk'))
+
+node_b_core.add_edge(Consume('node_b-clustat', 'node_b-rgmanager.sk'))
+node_b_core.add_edge(Consume('node_b-rgmanager', 'node_b-libccsconfdb'))
+node_b_core.add_edge(Produce('node_b-rgmanager', 'node_b-rgmanager.sk'))
+
+
+# node b - general
+
+node_b = GraphNode('cluster-node_b', label='NODE B')
+node_b.add_subgraph(node_b_conga)
+node_b.add_subgraph(node_b_core)
+
+node_b.add_node(Artefact('node_b-cluster.conf', label='/etc/cluster/cluster.conf'))
+node_b.add_node(Daemon('node_b-snmpd', label='snmpd'))
+node_b.add_node(Daemon('node_b-cimserver', label='cimserver'))
+
+node_b.add_edge(Consume('node_b-modcluster', 'node_b-cluster.conf', label='version?'))
+node_b.add_edge(Consume('node_b-modclusterd', 'node_b-cluster.conf', label='version?'))
+node_b.add_edge(Consume('node_b-libccsconfdb', 'node_b-cluster.conf', label='version?'))
+node_b.add_edge(Consume('node_b-ricci', 'node_b-cluster.conf', label='clustername\nclusteralias'))
+node_b.add_edge(Consume('node_b-snmpd', 'node_b-libClusterMonitorSnmp.so'))
+node_b.add_edge(Consume('node_b-cimserver', 'node_b-libRedHatClusterProvider.so'))
+node_b.add_edge(DelegateOddjobExec('node_b-ricci', 'node_b-modcluster'))
+
+
+# node a - management
+
+node_a_conga = GraphSubnode('cluster-node_a-conga', label='management (incomplete)')
+
+node_a_conga.add_node(Daemon('node_a-ricci', label='ricci'))
+node_a_conga.add_node(Daemon('node_a-modclusterd', label='modclusterd'))
+
+
+# node a - general
+
+node_a = GraphNode('cluster-node_a', label='NODE A')
+node_a.add_subgraph(node_a_conga)
+
+
+# node c - management
+
+node_c_conga = GraphSubnode('cluster-node_c-conga', label='management (incomplete)')
+
+node_c_conga.add_node(Daemon('node_c-ricci', label='ricci'))
+node_c_conga.add_node(Daemon('node_c-modclusterd', label='modclusterd'))
+
+
+# node c - general
+
+node_c = GraphNode('cluster-node_c', label='NODE C')
+node_c.add_subgraph(node_c_conga)
+
+
+# nodes
+
+nodes = Subgraph('cluster-nodes', style='invis')
+nodes.add_subgraph(node_b)
+nodes.add_subgraph(node_c)
+nodes.add_subgraph(node_a)
+
+
+# global environment
+
+graph = Dot('Cluster.conf-related tools', graph_type='digraph', overlap='scalexy', compound='true', splines='yes') # , ranksep='1.2'
+graph.add_subgraph(node_mgmt)
+graph.add_subgraph(node_mon)
+#graph.add_subgraph(node_a)
+#graph.add_subgraph(node_b)
+graph.add_subgraph(nodes)
+
+graph.add_node(Program('firefox'))
+
+graph.add_edge(DelegateRICCIRPC('luci', 'node_a-ricci', ltail='cluster-climgmt', constraint='false'))
+graph.add_edge(DelegateRICCIRPC('luci', 'node_b-ricci', ltail='cluster-climgmt'))
+graph.add_edge(DelegateRICCIRPC('luci', 'node_c-ricci', ltail='cluster-climgmt', constraint='false'))
+graph.add_edge(DelegateLuciHTTPS('firefox', 'luci'))
+
+graph.add_edge(DelegateSNMP('snmpwalk', 'node_b-snmpd'))
+graph.add_edge(DelegateCIM('wbemcli', 'node_b-cimserver'))
+
+graph.add_edge(Exchange('node_a-modclusterd', 'node_b-modclusterd', label='port 16851 (either direction)', constraint='false'))
+graph.add_edge(Exchange('node_a-modclusterd', 'node_c-modclusterd', label='port 16851 (either direction)', constraint='false'))
+graph.add_edge(Exchange('node_b-modclusterd', 'node_c-modclusterd', label='port 16851 (either direction)', constraint='false'))
+
+
+###
+
+
+if __name__ == '__main__':
+ ext = argv[1] if len(argv) > 1 else 'pdf'
+ fmt = {'dot': 'raw'}.get(ext, ext)
+ graph.write(OUTPUT + extsep + ext, format=fmt, prog=['dot'] + FONTDEF)