Page MenuHomeClusterLabs Projects

CIB.py.in
No OneTemporary

CIB.py.in

#!@PYTHON@
'''CTS: Cluster Testing System: CIB generator
'''
__copyright__='''
Author: Andrew Beekhof <abeekhof@suse.de>
Copyright (C) 2008 Andrew Beekhof
'''
from UserDict import UserDict
import sys, time, types, syslog, os, struct, string, signal, traceback, warnings
from CTS import ClusterManager
from CM_hb import HeartbeatCM
from popen2 import Popen3
class CibBase:
cts_cib = None
cib_tmpfile = None
version = "unknown"
feature_set = "unknown"
def __init__(self, CM, tmpfile=None):
self.CM = CM
if not tmpfile:
warnings.filterwarnings("ignore")
self.cib_tmpfile=os.tmpnam()
warnings.resetwarnings()
else:
self.cib_tmpfile = tmpfile
def version(self):
return self.version
def NextIP(self):
fields = string.split(self.CM.Env["IPBase"], '.')
fields[3] = str(int(fields[3])+1)
ip = string.join(fields, '.')
self.CM.Env["IPBase"] = ip
return ip
class CIB06(CibBase):
version = "transitional-0.6"
coloc_template = """<rsc_colocation id="%s" from="%s" to="%s" to_role="%s" score="%s"/>"""
cib_template ='''
<cib admin_epoch="1" epoch="0" num_updates="0" remote_access_port="9898">
<configuration>
<crm_config> %s
</crm_config>
<nodes/>
<resources> %s
</resources>
<constraints> %s
</constraints>
</configuration>
<status/>
</cib> '''
cib_option_template = '''
<cluster_property_set id="cib-bootstrap-options"><attributes>
<nvpair id="cib-bootstrap-1" name="start-failure-is-fatal" value="false"/>
<nvpair id="cib-bootstrap-2" name="stonith-enabled" value="%d"/>
<nvpair id="cib-bootstrap-3" name="pe-input-series-max" value="30000"/>
<nvpair id="cib-bootstrap-4" name="shutdown-escalation" value="5min"/>
<nvpair id="cib-bootstrap-5" name="startup-fencing" value="false"/>
<nvpair id="cib-bootstrap-6" name="batch-limit" value="10"/>
<nvpair id="cib-bootstrap-7" name="no-quorum-policy" value="%s"/>
</attributes></cluster_property_set>'''
lsb_resource = '''
<primitive id="lsb_dummy" class="lsb" type="@datadir@/@PKG_NAME@/cts/LSBDummy">
<operations>
<op id="ocf_lsb_monitor" name="monitor" interval="5s"/>
</operations>
</primitive> '''
clustermon_location_constraint = '''
<rsc_location id="run_cluster_mon" rsc="cluster_mon">
<rule id="cant_run_cluster_mon" score="-INFINITY" boolean_op="and">
<expression id="mon_expr" attribute="#is_dc" operation="eq" value="false"/>
</rule>
</rsc_location> '''
resource_group_template = '''<group id="group-1">%s %s %s</group>'''
per_node_constraint_template = '''
<rsc_location id="preferred-%s" rsc="%s" node="%s" score="100"/>'''
pingd_constraint_template = '''
<rsc_location id="%s-is-connected" rsc="%s">
<rule id="%s-connected-rule" role="%s" score="-INFINITY">
<expression id="%s-connected-expr" attribute="connected" operation="lt" value="%d"/>
</rule>
</rsc_location>'''
dummy_resource_template = '''
<primitive id="%s" class="ocf" type="Dummy" provider="heartbeat">
<operations>
<op id="mon-%s" name="monitor" interval="P10S"/>
</operations>
<instance_attributes id="%s-attrs"><attributes>
<nvpair id="migrate-%s" name="allow_migrate" value="1"/>
</attributes></instance_attributes>
</primitive> '''
clustermon_resource_template = '''
<primitive id="cluster_mon" class="ocf" type="ClusterMon" provider="heartbeat">
<operations>
<op id="cluster_mon-1" name="monitor" interval="5s" prereq="nothing"/>
<op id="cluster_mon-2" name="start" prereq="nothing"/>
</operations>
<instance_attributes id="cluster_mon-attrs">
<attributes>
<nvpair id="cluster_mon-1" name="htmlfile" value="/suse/abeekhof/Export/cluster.html"/>
<nvpair id="cluster_mon-2" name="update" value="10"/>
<nvpair id="cluster_mon-3" name="extra_options" value="-n -r"/>
<nvpair id="cluster_mon-4" name="user" value="abeekhof"/>
</attributes>
</instance_attributes>
</primitive> '''
master_slave_resource = '''
<master_slave id="master-1">
<instance_attributes id="master_rsc">
<attributes>
<nvpair id="clone_max_1" name="clone_max" value="%d"/>
<nvpair id="clone_node_max_2" name="clone_node_max" value="%d"/>
<nvpair id="master_max_3" name="master_max" value="%d"/>
<nvpair id="master_node_max_4" name="master_node_max" value="%d"/>
</attributes>
</instance_attributes>
<primitive id="ocf_msdummy" class="ocf" type="Stateful" provider="heartbeat">
<operations>
<op id="ocf_msdummy_monitor" name="monitor" interval="15s"/>
<op id="ocf_msdummy_monitor_master" name="monitor" interval="16s" role="Master"/>
</operations>
</primitive>
</master_slave>'''
pingd_resource_template = """
<clone id="Connectivity">
<meta_attributes id="pingd-opts">
<attributes>
<nvpair id="pingd-opt-1" name="globally_unique" value="false"/>
</attributes>
</meta_attributes>
<primitive id="pingd" class="ocf" provider="pacemaker" type="pingd">
<operations>
<op id="pingd-op-1" name="monitor" interval="120s"/>
</operations>
<instance_attributes id="pingd-attrs">
<attributes>
<nvpair id="pingd-attr-1" name="host_list" value="%s"/>
<nvpair id="pingd-attr-2" name="name" value="connected"/>
</attributes>
</instance_attributes>
</primitive>
</clone>"""
stonith_resource_template = """
<clone id="DoFencing">
<meta_attributes id="fencing">
<attributes>
<nvpair id="DoFencing-attr-1" name="resource_failure_stickiness" value="-1"/>
<nvpair id="DoFencing-attr-2" name="globally_unique" value="false"/>
</attributes>
</meta_attributes>
<primitive id="child_DoFencing" class="stonith" type="%s">
<operations>
<op id="DoFencing-op-1" name="monitor" interval="120s" prereq="nothing" timeout="300s"/>
<op id="DoFencing-op-2" name="start" prereq="nothing" timeout="180s"/>
<op id="DoFencing-op-3" name="stop" timeout="180s"/>
</operations>
<instance_attributes id="fencing-child">
<attributes>
<nvpair id="child_DoFencing-1" name="%s" value="%s"/>
<nvpair id="child_DoFencing-2" name="livedangerously" value="yes"/>
</attributes>
</instance_attributes>
</primitive>
</clone>"""
bsc_template = '''
<cluster_property_set id="bsc-options">
<attributes>
<nvpair id="bsc-options-ident-string" name="ident-string" value="Linux-HA TEST configuration file - REMOVEME!!"/>
</attributes>
</cluster_property_set>'''
def NewIP(self, name=None):
template = '''
<primitive id="%s" class="ocf" type="IPaddr" provider="heartbeat">
<operations>
<op id="mon-%s" name="monitor" interval="5s"/>
</operations>
<instance_attributes id="attrs-%s"><attributes>
<nvpair id="netmask-%s" name="cidr_netmask" value="32"/>
<nvpair id="ip-%s" name="ip" value="%s"/>
</attributes></instance_attributes>
</primitive> '''
ip = self.NextIP()
if not name:
name = "r"+ip
return template % (name, name, name, name, name, ip)
def NewHBIP(self, name=None):
template = '''
<primitive id="%s" class="heartbeat" type="IPaddr">
<operations>
<op id="mon-%s" name="monitor" interval="5s"/>
</operations>
<instance_attributes id="attrs-%s"><attributes>
<nvpair id="ip-%s" name="1" value="%s/32"/>
</attributes></instance_attributes>
</primitive> '''
ip = self.NextIP()
if not name:
name = "r"+ip
return template % (name, name, name, name, ip)
def NewDummy(self, name):
return self.dummy_resource_template % (name, name, name, name)
def contents(self):
# fencing resource
if self.cts_cib:
return self.cts_cib
nodelist = ""
num_nodes = 0
for node in self.CM.Env["nodes"]:
nodelist += node + " "
num_nodes = num_nodes + 1
no_quorum = "stop"
if num_nodes < 3:
no_quorum = "ignore"
self.CM.debug("Cluster only has %d nodes, ignoring quorum" % num_nodes)
#make up crm config
cib_options = self.cib_option_template % (self.CM.Env["DoFencing"], no_quorum)
#create resources and their constraints
resources = ""
constraints = ""
if self.CM.Env["DoBSC"] == 1:
cib_options = cib_options + self.bsc_template
if self.CM.Env["CIBResource"] != 1:
# generate cib
self.cts_cib = self.cib_template % (cib_options, resources, constraints)
return self.cts_cib
if self.CM.cluster_monitor == 1:
resources += self.clustermon_resource_template
constraints += self.clustermon_location_constraint
ip1_rsc = self.NewIP()
ip2_rsc = self.NewHBIP()
ip3_rsc = self.NewIP()
resources += self.resource_group_template % (ip1_rsc, ip2_rsc, ip3_rsc)
# lsb resource
resources += self.lsb_resource
# Mirgator
resources += self.NewDummy("migrator")
constraints += self.coloc_template % ("group-with-master", "group-1", "master-1", "Master", "INFINITY")
constraints += self.coloc_template % ("lsb-with-group", "lsb_dummy", "group-1", "Started", "INFINITY")
# per node resource
for node in self.CM.Env["nodes"]:
per_node_resources = self.NewIP("rsc_"+node)
per_node_constraint = self.per_node_constraint_template % (node, "rsc_"+node, node)
resources += per_node_resources
constraints += per_node_constraint
# Ping the test master
resources += self.pingd_resource_template % os.uname()[1]
# Require conectivity to run
constraints += self.pingd_constraint_template % ("master-1", "master-1", "m", "Started", "m", 1)
if self.CM.Env["DoFencing"]:
stonith_resource = self.stonith_resource_template % \
(self.CM.Env["reset"].stonithtype, self.CM.Env["reset"].configName, self.CM.Env["reset"].configValue)
resources += stonith_resource
#master slave resource
resources += self.master_slave_resource % (num_nodes, 1, 1, 1)
# generate cib
self.cts_cib = self.cib_template % (cib_options, resources, constraints)
return self.cts_cib
class CIB10(CibBase):
feature_set = "3.0"
version = "pacemaker-1.0"
cib_template = '''
<cib crm_feature_set='%s' admin_epoch='1' epoch='0' num_updates='0' validate-with='%s' %s>
<configuration>
<crm_config/>
<nodes/>
<resources/>
<constraints/>
</configuration>
<status/>
</cib>'''
def _create(self, command):
fixed = "CIB_file="+self.cib_tmpfile+" crm configure " + command
self.CM.debug("Configure command: "+ fixed)
rc = os.system(fixed)
if rc != 0:
self.CM.log("Configure call failed: "+fixed)
sys.exit(1)
def _show(self, command=""):
output = ""
p = Popen3("CIB_file="+self.cib_tmpfile+" crm configure show "+command, None)
p.tochild.close()
result = p.fromchild.readlines()
p.fromchild.close()
self.lastrc = p.wait()
for line in result:
output += line
self.CM.debug("Generated Config: "+line)
return output
def NewIP(self, name=None, standard="ocf:heartbeat"):
ip = self.NextIP()
if not name:
name = "r"+ip
if not standard:
standard = ""
else:
standard += ":"
self._create('''primitive %s %sIPaddr params ip=%s cidr_netmask=32 op monitor interval=5s'''
% (name, standard, ip))
return name
def contents(self):
# fencing resource
if self.cts_cib:
return self.cts_cib
os.system("rm -f "+self.cib_tmpfile)
cib_base = self.cib_template % (self.feature_set, self.version, ''' remote-tls-port='9898' ''')
os.system('''echo "%s" > %s''' % (cib_base, self.cib_tmpfile))
nodelist = ""
num_nodes = 0
for node in self.CM.Env["nodes"]:
nodelist += node + " "
num_nodes = num_nodes + 1
no_quorum = "stop"
if num_nodes < 3:
no_quorum = "ignore"
self.CM.debug("Cluster only has %d nodes, ignoring quorum" % num_nodes)
self._create('''property start-failure-is-fatal=false pe-input-series-max=5000''')
self._create('''property shutdown-escalation=5min startup-fencing=false batch-limit=10''')
self._create('''property no-quorum-policy=%s stonith-enabled=%s''' % (no_quorum, self.CM.Env["DoFencing"]))
if self.CM.Env["DoBSC"] == 1:
self._create('''property ident-string="Linux-HA TEST configuration file - REMOVEME!!"''')
# Add resources?
if self.CM.Env["CIBResource"] != 1:
self.cts_cib = self._show("xml")
os.system("rm -f "+self.cib_tmpfile)
return self.cts_cib
# Group Resource
r1 = self.NewIP()
ip = self.NextIP()
r2 = "r"+ip
self._create('''primitive %s heartbeat::IPaddr params 1=%s/32 op monitor interval=5s''' % (r2, ip))
r3 = self.NewIP()
self._create('''group group-1 %s %s %s''' % (r1, r2, r3))
# Per-node resources
for node in self.CM.Env["nodes"]:
r = self.NewIP("rsc_"+node)
self._create('''location prefer-%s %s rule 100: \#uname eq %s''' % (node, r, node))
# LSB resource
self._create('''primitive lsb-dummy lsb::@datadir@/@PKG_NAME@/cts/LSBDummy op monitor interval=5s''')
self._create('''colocation lsb-with-group INFINITY: lsb-dummy group-1''')
self._create('''order lsb-after-group mandatory: group-1 lsb-dummy symmetrical=true''')
# Migrator
self._create('''primitive migrator ocf:pacemaker:Dummy meta allow-migrate=1 op monitor interval=P10S''')
# Ping the test master
self._create('''primitive ping-1 ocf:pacemaker:pingd params host_list=%s name=connected op monitor interval=120s''' % os.uname()[1])
self._create('''clone Connectivity ping-1 meta globally-unique=false''')
#master slave resource
self._create('''primitive stateful-1 ocf:pacemaker:Stateful op monitor interval=15s op monitor interval=16s role=Master''')
self._create('''ms master-1 stateful-1 meta clone-max=%d clone-node-max=%d master-max=%d master-node-max=%d'''
% (num_nodes, 1, 1, 1))
# Require conectivity to run the master
self._create('''location %s-is-connected %s rule -INFINITY: connected lt %d''' % ("m1", "master-1", 1))
# Group with the master
self._create('''colocation group-with-master INFINITY: group-1 master-1:Master''')
self._create('''order group-after-master mandatory: master-1:promote group-1:start symmetrical=true''')
# Fencing resource
if self.CM.Env["DoFencing"]:
self._create('''primitive FencingChild stonith::%s params %s="%s" livedangerously=yes op monitor interval=120s timeout=300 op start interval=0 timeout=180s op stop interval=0 timeout=180s''' % (self.CM.Env["reset"].stonithtype, self.CM.Env["reset"].configName, self.CM.Env["reset"].configValue))
# Set a threshold for unreliable stonith devices such as the vmware one
self._create('''clone Fencing FencingChild meta globally-unique=false migration-threshold=5''')
if self.CM.cluster_monitor == 1:
self._create('''primitive cluster_mon ocf:pacemaker:ClusterMon params update=10 extra_options="-r -n" user=abeekhof htmlfile=/suse/abeekhof/Export/cluster.html op start interval=0 requires=nothing op monitor interval=5s requires=nothing''')
self._create('''location prefer-dc cluster_mon rule -INFINITY: \#is_dc eq false''')
# generate cib
self.cts_cib = self._show("xml")
os.system("rm -f "+self.cib_tmpfile)
return self.cts_cib
class ConfigFactory:
def __init__(self, CM):
self.CM = CM
self.register("pacemaker06", CIB06, CM)
self.register("pacemaker10", CIB10, CM)
def register(self, methodName, constructor, *args, **kargs):
"""register a constructor"""
_args = [constructor]
_args.extend(args)
setattr(self, methodName, apply(ConfigFactoryItem,_args, kargs))
def unregister(self, methodName):
"""unregister a constructor"""
delattr(self, methodName)
def createConfig(self, name="pacemaker-1.0"):
if name == "pacemaker-0.6":
return self.pacemaker06()
return self.pacemaker10()
class ConfigFactoryItem:
def __init__(self, function, *args, **kargs):
assert callable(function), "function should be a callable obj"
self._function = function
self._args = args
self._kargs = kargs
def __call__(self, *args, **kargs):
"""call function"""
_args = list(self._args)
_args.extend(args)
_kargs = self._kargs.copy()
_kargs.update(kargs)
return apply(self._function,_args,_kargs)
#CibFactory = ConfigFactory()

File Metadata

Mime Type
text/x-script.python
Expires
Sat, Nov 23, 11:52 AM (1 d, 3 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1018693
Default Alt Text
CIB.py.in (18 KB)

Event Timeline