1from __future__ import print_function 2from __future__ import unicode_literals 3# Copyright (C) 2014 Kristoffer Gronlund <kgronlund@suse.com> 4# See COPYING for license information. 5 6 7from crmsh import cibconfig 8from lxml import etree 9from crmsh import xmlutil 10 11factory = cibconfig.cib_factory 12 13 14def setup_function(): 15 "set up test fixtures" 16 from crmsh import idmgmt 17 idmgmt.clear() 18 factory._push_state() 19 20 21def teardown_function(): 22 factory._pop_state() 23 24 25def test_bug41660_1(): 26 xml = """<primitive id="bug41660" class="ocf" provider="pacemaker" type="Dummy"> \ 27 <meta_attributes id="bug41660-meta"> \ 28 <nvpair id="bug41660-meta-target-role" name="target-role" value="Stopped"/> \ 29 </meta_attributes> \ 30 </primitive> 31""" 32 data = etree.fromstring(xml) 33 obj = factory.create_from_node(data) 34 print(etree.tostring(obj.node)) 35 data = obj.repr_cli(format_mode=-1) 36 print(data) 37 exp = 'primitive bug41660 ocf:pacemaker:Dummy meta target-role=Stopped' 38 assert data == exp 39 assert obj.cli_use_validate() 40 41 commit_holder = factory.commit 42 try: 43 factory.commit = lambda *args: True 44 from crmsh.ui_resource import set_deep_meta_attr 45 set_deep_meta_attr("bug41660", "target-role", "Started") 46 assert ['Started'] == obj.node.xpath('.//nvpair[@name="target-role"]/@value') 47 finally: 48 factory.commit = commit_holder 49 50 51def test_bug41660_2(): 52 xml = """ 53<clone id="libvirtd-clone"> 54 <primitive class="lsb" id="libvirtd" type="libvirtd"> 55 <operations> 56 <op id="libvirtd-monitor-interval-15" interval="15" name="monitor" start-delay="15" timeout="15"/> 57 <op id="libvirtd-start-interval-0" interval="0" name="start" on-fail="restart" timeout="15"/> 58 <op id="libvirtd-stop-interval-0" interval="0" name="stop" on-fail="ignore" timeout="15"/> 59 </operations> 60 <meta_attributes id="libvirtd-meta_attributes"/> 61 </primitive> 62 <meta_attributes id="libvirtd-clone-meta"> 63 <nvpair id="libvirtd-interleave" name="interleave" value="true"/> 64 <nvpair id="libvirtd-ordered" name="ordered" value="true"/> 65 <nvpair id="libvirtd-clone-meta-target-role" name="target-role" value="Stopped"/> 66 </meta_attributes> 67</clone> 68""" 69 data = etree.fromstring(xml) 70 obj = factory.create_from_node(data) 71 assert obj is not None 72 #data = obj.repr_cli(format_mode=-1) 73 #print data 74 #exp = 'clone libvirtd-clone libvirtd meta interleave=true ordered=true target-role=Stopped' 75 #assert data == exp 76 #assert obj.cli_use_validate() 77 78 print(etree.tostring(obj.node)) 79 80 commit_holder = factory.commit 81 try: 82 factory.commit = lambda *args: True 83 from crmsh.ui_resource import set_deep_meta_attr 84 print("PRE", etree.tostring(obj.node)) 85 set_deep_meta_attr("libvirtd-clone", "target-role", "Started") 86 print("POST", etree.tostring(obj.node)) 87 assert ['Started'] == obj.node.xpath('.//nvpair[@name="target-role"]/@value') 88 finally: 89 factory.commit = commit_holder 90 91 92def test_bug41660_3(): 93 xml = """ 94<clone id="libvirtd-clone"> 95 <primitive class="lsb" id="libvirtd" type="libvirtd"> 96 <operations> 97 <op id="libvirtd-monitor-interval-15" interval="15" name="monitor" start-delay="15" timeout="15"/> 98 <op id="libvirtd-start-interval-0" interval="0" name="start" on-fail="restart" timeout="15"/> 99 <op id="libvirtd-stop-interval-0" interval="0" name="stop" on-fail="ignore" timeout="15"/> 100 </operations> 101 <meta_attributes id="libvirtd-meta_attributes"/> 102 </primitive> 103 <meta_attributes id="libvirtd-clone-meta_attributes"> 104 <nvpair id="libvirtd-clone-meta_attributes-target-role" name="target-role" value="Stopped"/> 105 </meta_attributes> 106</clone> 107""" 108 data = etree.fromstring(xml) 109 obj = factory.create_from_node(data) 110 assert obj is not None 111 data = obj.repr_cli(format_mode=-1) 112 print(data) 113 exp = 'clone libvirtd-clone libvirtd meta target-role=Stopped' 114 assert data == exp 115 assert obj.cli_use_validate() 116 117 commit_holder = factory.commit 118 try: 119 factory.commit = lambda *args: True 120 from crmsh.ui_resource import set_deep_meta_attr 121 set_deep_meta_attr("libvirtd-clone", "target-role", "Started") 122 assert ['Started'] == obj.node.xpath('.//nvpair[@name="target-role"]/@value') 123 finally: 124 factory.commit = commit_holder 125 126 127def test_comments(): 128 xml = """<cib epoch="25" num_updates="1" admin_epoch="0" validate-with="pacemaker-1.2" cib-last-written="Thu Mar 6 15:53:49 2014" update-origin="beta1" update-client="cibadmin" update-user="root" crm_feature_set="3.0.8" have-quorum="1" dc-uuid="1"> 129 <configuration> 130 <crm_config> 131 <cluster_property_set id="cib-bootstrap-options"> 132 <nvpair id="cib-bootstrap-options-dc-version" name="dc-version" value="1.1.11-3.3-3ca8c3b"/> 133 <nvpair id="cib-bootstrap-options-cluster-infrastructure" name="cluster-infrastructure" value="corosync"/> 134 <!--# COMMENT TEXT 1 --> 135 </cluster_property_set> 136 </crm_config> 137 <nodes> 138 <node uname="beta1" id="1"> 139 <!--# COMMENT TEXT 2 --> 140 </node> 141 </nodes> 142 <resources/> 143 <constraints/> 144 <rsc_defaults> 145 <meta_attributes id="rsc-options"> 146 <nvpair name="resource-stickiness" value="1" id="rsc-options-resource-stickiness"/> 147 <!--# COMMENT TEXT 3 --> 148 </meta_attributes> 149 </rsc_defaults> 150 </configuration> 151 <status> 152 <node_state id="1" uname="beta1" in_ccm="true" crmd="online" crm-debug-origin="do_state_transition" join="member" expected="member"> 153 <lrm id="1"> 154 <lrm_resources/> 155 </lrm> 156 <transient_attributes id="1"> 157 <instance_attributes id="status-1"> 158 <nvpair id="status-1-shutdown" name="shutdown" value="0"/> 159 <nvpair id="status-1-probe_complete" name="probe_complete" value="true"/> 160 </instance_attributes> 161 </transient_attributes> 162 </node_state> 163 </status> 164</cib>""" 165 elems = etree.fromstring(xml) 166 xmlutil.sanitize_cib(elems) 167 assert xmlutil.xml_tostring(elems).count("COMMENT TEXT") == 3 168 169 170def test_eq1(): 171 xml1 = """<cluster_property_set id="cib-bootstrap-options"> 172 <nvpair id="cib-bootstrap-options-stonith-enabled" name="stonith-enabled" value="true"></nvpair> 173 <nvpair id="cib-bootstrap-options-stonith-timeout" name="stonith-timeout" value="180"></nvpair> 174 <nvpair id="cib-bootstrap-options-symmetric-cluster" name="symmetric-cluster" value="false"></nvpair> 175 <nvpair id="cib-bootstrap-options-no-quorum-policy" name="no-quorum-policy" value="freeze"></nvpair> 176 <nvpair id="cib-bootstrap-options-batch-limit" name="batch-limit" value="20"></nvpair> 177 <nvpair id="cib-bootstrap-options-dc-version" name="dc-version" value="1.1.10-c1a326d"></nvpair> 178 <nvpair id="cib-bootstrap-options-cluster-infrastructure" name="cluster-infrastructure" value="corosync"></nvpair> 179 <nvpair id="cib-bootstrap-options-last-lrm-refresh" name="last-lrm-refresh" value="1391433789"></nvpair> 180 <nvpair id="cib-bootstrap-options-is-managed-default" name="is-managed-default" value="true"></nvpair> 181 </cluster_property_set> 182 """ 183 xml2 = """<cluster_property_set id="cib-bootstrap-options"> 184 <nvpair id="cib-bootstrap-options-stonith-enabled" name="stonith-enabled" value="true"></nvpair> 185 <nvpair id="cib-bootstrap-options-stonith-timeout" name="stonith-timeout" value="180"></nvpair> 186 <nvpair id="cib-bootstrap-options-symmetric-cluster" name="symmetric-cluster" value="false"></nvpair> 187 <nvpair id="cib-bootstrap-options-no-quorum-policy" name="no-quorum-policy" value="freeze"></nvpair> 188 <nvpair id="cib-bootstrap-options-batch-limit" name="batch-limit" value="20"></nvpair> 189 <nvpair id="cib-bootstrap-options-dc-version" name="dc-version" value="1.1.10-c1a326d"></nvpair> 190 <nvpair id="cib-bootstrap-options-cluster-infrastructure" name="cluster-infrastructure" value="corosync"></nvpair> 191 <nvpair id="cib-bootstrap-options-last-lrm-refresh" name="last-lrm-refresh" value="1391433789"></nvpair> 192 <nvpair id="cib-bootstrap-options-is-managed-default" name="is-managed-default" value="true"></nvpair> 193 </cluster_property_set> 194 """ 195 e1 = etree.fromstring(xml1) 196 e2 = etree.fromstring(xml2) 197 assert xmlutil.xml_equals(e1, e2, show=True) 198 199 200def test_pcs_interop_1(): 201 """ 202 pcs<>crmsh interop bug 203 """ 204 205 xml = """<clone id="dummies"> 206 <meta_attributes id="dummies-meta"> 207 <nvpair name="globally-unique" value="false" id="dummies-meta-globally-unique"/> 208 </meta_attributes> 209 <meta_attributes id="dummies-meta_attributes"> 210 <nvpair id="dummies-meta_attributes-target-role" name="target-role" value="Stopped"/> 211 </meta_attributes> 212 <primitive id="dummy-1" class="ocf" provider="heartbeat" type="Dummy"/> 213 </clone>""" 214 elem = etree.fromstring(xml) 215 from crmsh.ui_resource import set_deep_meta_attr_node 216 217 assert len(elem.xpath(".//meta_attributes/nvpair[@name='target-role']")) == 1 218 219 print("BEFORE:", etree.tostring(elem)) 220 221 set_deep_meta_attr_node(elem, 'target-role', 'Stopped') 222 223 print("AFTER:", etree.tostring(elem)) 224 225 assert len(elem.xpath(".//meta_attributes/nvpair[@name='target-role']")) == 1 226 227 228def test_bnc878128(): 229 """ 230 L3: "crm configure show" displays XML information instead of typical crm output. 231 """ 232 xml = """<rsc_location id="cli-prefer-dummy-resource" rsc="dummy-resource" 233role="Started"> 234 <rule id="cli-prefer-rule-dummy-resource" score="INFINITY"> 235 <expression id="cli-prefer-expr-dummy-resource" attribute="#uname" 236operation="eq" value="x64-4"/> 237 <date_expression id="cli-prefer-lifetime-end-dummy-resource" operation="lt" 238end="2014-05-17 17:56:11Z"/> 239 </rule> 240</rsc_location>""" 241 data = etree.fromstring(xml) 242 obj = factory.create_from_node(data) 243 assert obj is not None 244 data = obj.repr_cli(format_mode=-1) 245 print("OUTPUT:", data) 246 exp = 'location cli-prefer-dummy-resource dummy-resource role=Started rule #uname eq x64-4 and date lt "2014-05-17 17:56:11Z"' 247 assert data == exp 248 assert obj.cli_use_validate() 249 250 251def test_order_without_score_kind(): 252 """ 253 Spec says order doesn't require score or kind to be set 254 """ 255 xml = '<rsc_order first="a" first-action="promote" id="order-a-b" then="b" then-action="start"/>' 256 data = etree.fromstring(xml) 257 obj = factory.create_from_node(data) 258 assert obj is not None 259 data = obj.repr_cli(format_mode=-1) 260 print("OUTPUT:", data) 261 exp = 'order order-a-b a:promote b:start' 262 assert data == exp 263 assert obj.cli_use_validate() 264 265 266 267def test_bnc878112(): 268 """ 269 crm configure group can hijack a cloned primitive (and then crash) 270 """ 271 obj1 = factory.create_object('primitive', 'p1', 'Dummy') 272 assert obj1 is True 273 obj2 = factory.create_object('group', 'g1', 'p1') 274 assert obj2 is True 275 obj3 = factory.create_object('group', 'g2', 'p1') 276 print(obj3) 277 assert obj3 is False 278 279 280def test_copy_nvpairs(): 281 from crmsh.cibconfig import copy_nvpairs 282 283 to = etree.fromstring(''' 284 <node> 285 <nvpair name="stonith-enabled" value="true"/> 286 </node> 287 ''') 288 copy_nvpairs(to, etree.fromstring(''' 289 <node> 290 <nvpair name="stonith-enabled" value="false"/> 291 </node> 292 ''')) 293 294 assert ['stonith-enabled'] == to.xpath('./nvpair/@name') 295 assert ['false'] == to.xpath('./nvpair/@value') 296 297 copy_nvpairs(to, etree.fromstring(''' 298 <node> 299 <nvpair name="stonith-enabled" value="true"/> 300 </node> 301 ''')) 302 303 assert ['stonith-enabled'] == to.xpath('./nvpair/@name') 304 assert ['true'] == to.xpath('./nvpair/@value') 305 306 307def test_pengine_test(): 308 xml = '''<primitive class="ocf" id="rsc1" provider="pacemaker" type="Dummy"> 309 <instance_attributes id="rsc1-instance_attributes-1"> 310 <nvpair id="rsc1-instance_attributes-1-state" name="state" value="/var/run/Dummy-rsc1-clusterA"/> 311 <rule id="rsc1-instance_attributes-1-rule-1" score="0"> 312 <expression id="rsc1-instance_attributes-1-rule-1-expr-1" attribute="#cluster-name" operation="eq" value="clusterA"/> 313 </rule> 314 </instance_attributes> 315 <instance_attributes id="rsc1-instance_attributes-2"> 316 <nvpair id="rsc1-instance_attributes-2-state" name="state" value="/var/run/Dummy-rsc1-clusterB"/> 317 <rule id="rsc1-instance_attributes-2-rule-1" score="0"> 318 <expression id="rsc1-instance_attributes-2-rule-1-expr-1" attribute="#cluster-name" operation="eq" value="clusterB"/> 319 </rule> 320 </instance_attributes> 321 <operations> 322 <op id="rsc1-monitor-10" interval="10" name="monitor"/> 323 </operations> 324 </primitive>''' 325 data = etree.fromstring(xml) 326 obj = factory.create_from_node(data) 327 assert obj is not None 328 data = obj.repr_cli(format_mode=-1) 329 print("OUTPUT:", data) 330 exp = 'primitive rsc1 ocf:pacemaker:Dummy params rule 0: #cluster-name eq clusterA state="/var/run/Dummy-rsc1-clusterA" params rule 0: #cluster-name eq clusterB state="/var/run/Dummy-rsc1-clusterB" op monitor interval=10' 331 assert data == exp 332 assert obj.cli_use_validate() 333 334 335def test_tagset(): 336 xml = '''<primitive class="ocf" id="%s" provider="pacemaker" type="Dummy"/>''' 337 tag = '''<tag id="t0"><obj_ref id="r1"/><obj_ref id="r2"/></tag>''' 338 factory.create_from_node(etree.fromstring(xml % ('r1'))) 339 factory.create_from_node(etree.fromstring(xml % ('r2'))) 340 factory.create_from_node(etree.fromstring(xml % ('r3'))) 341 factory.create_from_node(etree.fromstring(tag)) 342 elems = factory.get_elems_on_tag("tag:t0") 343 assert set(x.obj_id for x in elems) == set(['r1', 'r2']) 344 345 346def test_ratrace(): 347 xml = '''<primitive class="ocf" id="%s" provider="pacemaker" type="Dummy"/>''' 348 factory.create_from_node(etree.fromstring(xml % ('r1'))) 349 factory.create_from_node(etree.fromstring(xml % ('r2'))) 350 factory.create_from_node(etree.fromstring(xml % ('r3'))) 351 352 context = object() 353 354 from crmsh.ui_resource import RscMgmt 355 obj = factory.find_object('r1') 356 RscMgmt()._trace_resource(context, 'r1', obj) 357 358 obj = factory.find_object('r1') 359 ops = obj.node.xpath('./operations/op') 360 for op in ops: 361 assert op.xpath('./instance_attributes/nvpair[@name="trace_ra"]/@value') == ["1"] 362 assert set(obj.node.xpath('./operations/op/@name')) == set(['start', 'stop']) 363 364 365def test_op_role(): 366 xml = '''<primitive class="ocf" id="rsc2" provider="pacemaker" type="Dummy"> 367 <operations> 368 <op id="rsc2-monitor-10" interval="10" name="monitor" role="Stopped"/> 369 </operations> 370 </primitive>''' 371 data = etree.fromstring(xml) 372 obj = factory.create_from_node(data) 373 assert obj is not None 374 data = obj.repr_cli(format_mode=-1) 375 print("OUTPUT:", data) 376 exp = 'primitive rsc2 ocf:pacemaker:Dummy op monitor interval=10 role=Stopped' 377 assert data == exp 378 assert obj.cli_use_validate() 379 380 381def test_nvpair_no_value(): 382 xml = '''<primitive class="ocf" id="rsc3" provider="heartbeat" type="Dummy"> 383 <instance_attributes id="rsc3-instance_attributes-1"> 384 <nvpair id="rsc3-instance_attributes-1-verbose" name="verbose"/> 385 <nvpair id="rsc3-instance_attributes-1-verbase" name="verbase" value=""/> 386 <nvpair id="rsc3-instance_attributes-1-verbese" name="verbese" value=" "/> 387 </instance_attributes> 388 </primitive>''' 389 data = etree.fromstring(xml) 390 obj = factory.create_from_node(data) 391 assert obj is not None 392 data = obj.repr_cli(format_mode=-1) 393 print("OUTPUT:", data) 394 exp = 'primitive rsc3 Dummy params verbose verbase="" verbese=" "' 395 assert data == exp 396 assert obj.cli_use_validate() 397 398 399def test_delete_ticket(): 400 xml0 = '<primitive id="daa0" class="ocf" provider="heartbeat" type="Dummy"/>' 401 xml1 = '<primitive id="daa1" class="ocf" provider="heartbeat" type="Dummy"/>' 402 xml2 = '''<rsc_ticket id="taa0" ticket="taaA"> 403 <resource_set id="taa0-0"> 404 <resource_ref id="daa0"/> 405 <resource_ref id="daa1"/> 406 </resource_set> 407 </rsc_ticket>''' 408 for x in (xml0, xml1, xml2): 409 data = etree.fromstring(x) 410 obj = factory.create_from_node(data) 411 assert obj is not None 412 data = obj.repr_cli(format_mode=-1) 413 414 factory.delete('daa0') 415 assert factory.find_object('daa0') is None 416 assert factory.find_object('taa0') is not None 417 418 419def test_quotes(): 420 """ 421 Parsing escaped quotes 422 """ 423 xml = '''<primitive class="ocf" id="q1" provider="pacemaker" type="Dummy"> 424 <instance_attributes id="q1-instance_attributes-1"> 425 <nvpair id="q1-instance_attributes-1-state" name="state" value="foo"foo""/> 426 </instance_attributes> 427 </primitive> 428 ''' 429 data = etree.fromstring(xml) 430 obj = factory.create_from_node(data) 431 assert obj is not None 432 data = obj.repr_cli(format_mode=-1) 433 print("OUTPUT:", data) 434 exp = 'primitive q1 ocf:pacemaker:Dummy params state="foo\\"foo\\""' 435 assert data == exp 436 assert obj.cli_use_validate() 437 438 439def test_nodeattrs(): 440 """ 441 bug with parsing node attrs 442 """ 443 xml = '''<node id="1" uname="dell71"> \ 444 <instance_attributes id="dell71-instance_attributes"> \ 445 <nvpair name="staging-0-0-placement" value="true" id="dell71-instance_attributes-staging-0-0-placement"/> \ 446 <nvpair name="meta-0-0-placement" value="true" id="dell71-instance_attributes-meta-0-0-placement"/> \ 447 </instance_attributes> \ 448 <instance_attributes id="nodes-1"> \ 449 <nvpair id="nodes-1-standby" name="standby" value="off"/> \ 450 </instance_attributes> \ 451</node>''' 452 453 data = etree.fromstring(xml) 454 obj = factory.create_from_node(data) 455 assert obj is not None 456 data = obj.repr_cli(format_mode=-1) 457 exp = 'node 1: dell71 attributes staging-0-0-placement=true meta-0-0-placement=true attributes standby=off' 458 assert data == exp 459 assert obj.cli_use_validate() 460 461 462def test_nodeattrs2(): 463 xml = """<node id="h04" uname="h04"> \ 464 <utilization id="h04-utilization"> \ 465 <nvpair id="h04-utilization-utl_ram" name="utl_ram" value="1200"/> \ 466 <nvpair id="h04-utilization-utl_cpu" name="utl_cpu" value="200"/> \ 467 </utilization> \ 468 <instance_attributes id="nodes-h04"> \ 469 <nvpair id="nodes-h04-standby" name="standby" value="off"/> \ 470 </instance_attributes> \ 471</node>""" 472 data = etree.fromstring(xml) 473 obj = factory.create_from_node(data) 474 assert obj is not None 475 data = obj.repr_cli(format_mode=-1) 476 exp = 'node h04 utilization utl_ram=1200 utl_cpu=200 attributes standby=off' 477 assert data == exp 478 assert obj.cli_use_validate() 479 480 481def test_group_constraint_location(): 482 """ 483 configuring a location constraint on a grouped resource is OK 484 """ 485 factory.create_object('node', 'node1') 486 factory.create_object('primitive', 'p1', 'Dummy') 487 factory.create_object('primitive', 'p2', 'Dummy') 488 factory.create_object('group', 'g1', 'p1', 'p2') 489 factory.create_object('location', 'loc-p1', 'p1', 'inf:', 'node1') 490 c = factory.find_object('loc-p1') 491 assert c and c.check_sanity() == 0 492 493 494def test_group_constraint_colocation(): 495 """ 496 configuring a colocation constraint on a grouped resource is bad 497 """ 498 factory.create_object('primitive', 'p1', 'Dummy') 499 factory.create_object('primitive', 'p2', 'Dummy') 500 factory.create_object('group', 'g1', 'p1', 'p2') 501 factory.create_object('colocation', 'coloc-p1-p2', 'inf:', 'p1', 'p2') 502 c = factory.find_object('coloc-p1-p2') 503 assert c and c.check_sanity() > 0 504 505 506def test_group_constraint_colocation_rscset(): 507 """ 508 configuring a constraint on a grouped resource is bad 509 """ 510 factory.create_object('primitive', 'p1', 'Dummy') 511 factory.create_object('primitive', 'p2', 'Dummy') 512 factory.create_object('primitive', 'p3', 'Dummy') 513 factory.create_object('group', 'g1', 'p1', 'p2') 514 factory.create_object('colocation', 'coloc-p1-p2-p3', 'inf:', 'p1', 'p2', 'p3') 515 c = factory.find_object('coloc-p1-p2-p3') 516 assert c and c.check_sanity() > 0 517 518 519def test_clone_constraint_colocation_rscset(): 520 """ 521 configuring a constraint on a cloned resource is bad 522 """ 523 factory.create_object('primitive', 'p1', 'Dummy') 524 factory.create_object('primitive', 'p2', 'Dummy') 525 factory.create_object('primitive', 'p3', 'Dummy') 526 factory.create_object('clone', 'c1', 'p1') 527 factory.create_object('colocation', 'coloc-p1-p2-p3', 'inf:', 'p1', 'p2', 'p3') 528 c = factory.find_object('coloc-p1-p2-p3') 529 assert c and c.check_sanity() > 0 530 531 532def test_existing_node_resource(): 533 factory.create_object('primitive', 'ha-one', 'Dummy') 534 535 n = factory.find_node('ha-one') 536 assert factory.test_element(n) 537 538 r = factory.find_resource('ha-one') 539 assert factory.test_element(r) 540 541 assert n != r 542 543 assert factory.check_structure() 544 factory.cli_use_validate_all() 545 546 ok, s = factory.mkobj_set('ha-one') 547 assert ok 548 549 550def test_existing_node_resource_2(): 551 obj = cibconfig.mkset_obj() 552 assert obj is not None 553 554 from crmsh import clidisplay 555 with clidisplay.nopretty(): 556 text = obj.repr() 557 text += "\nprimitive ha-one Dummy" 558 ok = obj.save(text) 559 assert ok 560 561 obj = cibconfig.mkset_obj() 562 assert obj is not None 563 with clidisplay.nopretty(): 564 text2 = obj.repr() 565 566 assert sorted(text.split('\n')) == sorted(text2.split('\n')) 567 568 569def test_id_collision_breakage_1(): 570 from crmsh import clidisplay 571 572 obj = cibconfig.mkset_obj() 573 assert obj is not None 574 with clidisplay.nopretty(): 575 original_cib = obj.repr() 576 print(original_cib) 577 578 obj = cibconfig.mkset_obj() 579 assert obj is not None 580 581 ok = obj.save("""node node1 582primitive p0 ocf:pacemaker:Dummy 583primitive p1 ocf:pacemaker:Dummy 584primitive p2 ocf:heartbeat:Delay \ 585 params startdelay=2 mondelay=2 stopdelay=2 586primitive p3 ocf:pacemaker:Dummy 587primitive st stonith:null params hostlist=node1 588clone c1 p1 589ms m1 p2 590op_defaults timeout=60s 591""") 592 assert ok 593 594 obj = cibconfig.mkset_obj() 595 assert obj is not None 596 ok = obj.save("""op_defaults timeout=2m 597node node1 \ 598 attributes mem=16G 599primitive st stonith:null \ 600 params hostlist='node1' \ 601 meta description="some description here" requires=nothing \ 602 op monitor interval=60m 603primitive p1 ocf:heartbeat:Dummy \ 604 op monitor interval=60m \ 605 op monitor interval=120m OCF_CHECK_LEVEL=10 606""") 607 assert ok 608 609 obj = cibconfig.mkset_obj() 610 with clidisplay.nopretty(): 611 text = obj.repr() 612 text = text + "\nprimitive p2 ocf:heartbeat:Dummy" 613 ok = obj.save(text) 614 assert ok 615 616 obj = cibconfig.mkset_obj() 617 with clidisplay.nopretty(): 618 text = obj.repr() 619 text = text + "\ngroup g1 p1 p2" 620 ok = obj.save(text) 621 assert ok 622 623 obj = cibconfig.mkset_obj("g1") 624 with clidisplay.nopretty(): 625 text = obj.repr() 626 text = text.replace("group g1 p1 p2", "group g1 p1 p3") 627 text = text + "\nprimitive p3 ocf:heartbeat:Dummy" 628 ok = obj.save(text) 629 assert ok 630 631 obj = cibconfig.mkset_obj("g1") 632 with clidisplay.nopretty(): 633 print(obj.repr().strip()) 634 assert obj.repr().strip() == "group g1 p1 p3" 635 636 obj = cibconfig.mkset_obj() 637 assert obj is not None 638 ok = obj.save(original_cib) 639 assert ok 640 obj = cibconfig.mkset_obj() 641 with clidisplay.nopretty(): 642 print("*** ORIGINAL") 643 print(original_cib) 644 print("*** NOW") 645 print(obj.repr()) 646 assert original_cib == obj.repr() 647 648 649def test_id_collision_breakage_3(): 650 from crmsh import clidisplay 651 652 obj = cibconfig.mkset_obj() 653 assert obj is not None 654 with clidisplay.nopretty(): 655 original_cib = obj.repr() 656 print(original_cib) 657 658 obj = cibconfig.mkset_obj() 659 assert obj is not None 660 ok = obj.save("""node node1 661primitive node1 Dummy params fake=something 662 """) 663 assert ok 664 665 print("** baseline") 666 obj = cibconfig.mkset_obj() 667 assert obj is not None 668 with clidisplay.nopretty(): 669 print(obj.repr()) 670 671 obj = cibconfig.mkset_obj() 672 assert obj is not None 673 ok = obj.save("""primitive node1 Dummy params fake=something-else 674 """, remove=False, method='update') 675 assert ok 676 677 print("** end") 678 679 obj = cibconfig.mkset_obj() 680 assert obj is not None 681 ok = obj.save(original_cib, remove=True, method='replace') 682 assert ok 683 obj = cibconfig.mkset_obj() 684 with clidisplay.nopretty(): 685 print("*** ORIGINAL") 686 print(original_cib) 687 print("*** NOW") 688 print(obj.repr()) 689 assert original_cib == obj.repr() 690 691 692def test_id_collision_breakage_2(): 693 from crmsh import clidisplay 694 695 obj = cibconfig.mkset_obj() 696 assert obj is not None 697 with clidisplay.nopretty(): 698 original_cib = obj.repr() 699 print(original_cib) 700 701 obj = cibconfig.mkset_obj() 702 assert obj is not None 703 704 ok = obj.save("""node 168633610: webui 705node 168633611: node1 706rsc_template web-server apache \ 707 params port=8000 \ 708 op monitor interval=10s 709primitive d0 Dummy \ 710 meta target-role=Started 711primitive d1 Dummy 712primitive d2 Dummy 713# Never use this STONITH agent in production! 714primitive development-stonith stonith:null \ 715 params hostlist="webui node1 node2 node3" 716primitive proxy systemd:haproxy \ 717 op monitor interval=10s 718primitive proxy-vip IPaddr2 \ 719 params ip=10.13.37.20 720primitive srv1 @web-server 721primitive srv2 @web-server 722primitive vip1 IPaddr2 \ 723 params ip=10.13.37.21 \ 724 op monitor interval=20s 725primitive vip2 IPaddr2 \ 726 params ip=10.13.37.22 \ 727 op monitor interval=20s 728primitive virtual-ip IPaddr2 \ 729 params ip=10.13.37.77 lvs_support=false \ 730 op start timeout=20 interval=0 \ 731 op stop timeout=20 interval=0 \ 732 op monitor interval=10 timeout=20 733primitive yet-another-virtual-ip IPaddr2 \ 734 params ip=10.13.37.72 cidr_netmask=24 \ 735 op start interval=0 timeout=20 \ 736 op stop interval=0 timeout=20 \ 737 op monitor interval=10 timeout=20 \ 738 meta target-role=Started 739group dovip d0 virtual-ip \ 740 meta target-role=Stopped 741group g-proxy proxy-vip proxy 742group g-serv1 vip1 srv1 743group g-serv2 vip2 srv2 744clone d2-clone d2 \ 745 meta target-role=Started 746tag dummytag d0 d1 d1-on-node1 d2 d2-clone 747# Never put the two web servers on the same node 748colocation co-serv -inf: g-serv1 g-serv2 749location d1-on-node1 d1 inf: node1 750# Never put any web server or haproxy on webui 751location l-avoid-webui { g-proxy g-serv1 g-serv2 } -inf: webui 752# Prever to spread groups across nodes 753location l-proxy g-proxy 200: node1 754location l-serv1 g-serv1 200: node2 755location l-serv2 g-serv2 200: node3 756property cib-bootstrap-options: \ 757 have-watchdog=false \ 758 dc-version="1.1.13+git20150917.20c2178-224.2-1.1.13+git20150917.20c2178" \ 759 cluster-infrastructure=corosync \ 760 cluster-name=hacluster \ 761 stonith-enabled=true \ 762 no-quorum-policy=ignore 763rsc_defaults rsc-options: \ 764 resource-stickiness=1 \ 765 migration-threshold=3 766op_defaults op-options: \ 767 timeout=600 \ 768 record-pending=true 769""") 770 assert ok 771 772 obj = cibconfig.mkset_obj() 773 assert obj is not None 774 ok = obj.save(original_cib) 775 assert ok 776 obj = cibconfig.mkset_obj() 777 with clidisplay.nopretty(): 778 print("*** ORIGINAL") 779 print(original_cib) 780 print("*** NOW") 781 print(obj.repr()) 782 assert original_cib == obj.repr() 783 784 785def test_bug_110(): 786 """ 787 configuring attribute-based fencing-topology 788 """ 789 factory.create_object(*"primitive stonith-libvirt stonith:null".split()) 790 factory.create_object(*"primitive fence-nova stonith:null".split()) 791 cmd = "fencing_topology attr:OpenStack-role=compute stonith-libvirt,fence-nova".split() 792 ok = factory.create_object(*cmd) 793 assert ok 794 obj = cibconfig.mkset_obj() 795 assert obj is not None 796 797 for o in obj.obj_set: 798 if o.node.tag == 'fencing-topology': 799 assert o.check_sanity() == 0 800 801 802def test_reordering_resource_sets(): 803 """ 804 Can we reorder resource sets? 805 """ 806 from crmsh import clidisplay 807 obj1 = factory.create_object('primitive', 'p1', 'Dummy') 808 assert obj1 is True 809 obj2 = factory.create_object('primitive', 'p2', 'Dummy') 810 assert obj2 is True 811 obj3 = factory.create_object('primitive', 'p3', 'Dummy') 812 assert obj3 is True 813 obj4 = factory.create_object('primitive', 'p4', 'Dummy') 814 assert obj4 is True 815 o1 = factory.create_object('order', 'o1', 'p1', 'p2', 'p3', 'p4') 816 assert o1 is True 817 818 obj = cibconfig.mkset_obj('o1') 819 assert obj is not None 820 rc = obj.save('order o1 p4 p3 p2 p1') 821 assert rc == True 822 823 obj2 = cibconfig.mkset_obj('o1') 824 with clidisplay.nopretty(): 825 assert "order o1 p4 p3 p2 p1" == obj2.repr().strip() 826 827 828def test_bug959895(): 829 """ 830 Allow importing XML with cloned groups 831 """ 832 xml = """<clone id="c-bug959895"> 833 <group id="g-bug959895"> 834 <primitive id="p-bug959895-a" class="ocf" provider="pacemaker" type="Dummy" /> 835 <primitive id="p-bug959895-b" class="ocf" provider="pacemaker" type="Dummy" /> 836 </group> 837</clone> 838""" 839 data = etree.fromstring(xml) 840 obj = factory.create_from_node(data) 841 print(etree.tostring(obj.node)) 842 data = obj.repr_cli(format_mode=-1) 843 print(data) 844 exp = 'clone c-bug959895 g-bug959895' 845 assert data == exp 846 assert obj.cli_use_validate() 847 848 commit_holder = factory.commit 849 try: 850 factory.commit = lambda *args: True 851 from crmsh.ui_resource import set_deep_meta_attr 852 set_deep_meta_attr("c-bug959895", "target-role", "Started") 853 assert ['Started'] == obj.node.xpath('.//nvpair[@name="target-role"]/@value') 854 finally: 855 factory.commit = commit_holder 856 857 858def test_node_util_attr(): 859 """ 860 Handle node with utitilization before attributes correctly 861 """ 862 xml = """<node id="aberfeldy" uname="aberfeldy"> 863 <utilization id="nodes-aberfeldy-utilization"> 864 <nvpair id="nodes-aberfeldy-utilization-cpu" name="cpu" value="2"/> 865 <nvpair id="nodes-aberfeldy-utilization-memory" name="memory" value="500"/> 866 </utilization> 867 <instance_attributes id="nodes-aberfeldy"> 868 <nvpair id="nodes-aberfeldy-standby" name="standby" value="on"/> 869 </instance_attributes> 870</node>""" 871 872 data = etree.fromstring(xml) 873 obj = factory.create_from_node(data) 874 print(etree.tostring(obj.node)) 875 data = obj.repr_cli(format_mode=-1) 876 print(data) 877 exp = 'node aberfeldy utilization cpu=2 memory=500 attributes standby=on' 878 assert data == exp 879 assert obj.cli_use_validate() 880 881 882def test_dup_create_same_name(): 883 """ 884 Creating two objects with the same name 885 """ 886 ok = factory.create_object(*"primitive dup1 Dummy".split()) 887 assert ok 888 ok = factory.create_object(*"primitive dup1 Dummy".split()) 889 assert not ok 890 891 892def test_dup_create(): 893 """ 894 Creating property sets with unknown properties 895 """ 896 ok = factory.create_object(*"property hana_test1: hana_attribute_1=5 hana_attribute_2=mohican".split()) 897 assert ok 898 ok = factory.create_object(*"property hana_test2: hana_attribute_1=5s a-b-c-d=e-f-g".split()) 899 assert ok 900