Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F1842086
CIB.py.in
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
18 KB
Referenced Files
None
Subscribers
None
CIB.py.in
View Options
#!@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
Details
Attached
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)
Attached To
Mode
rP Pacemaker
Attached
Detach File
Event Timeline
Log In to Comment