Hello community, here is the log from the commit of package crmsh for openSUSE:Factory checked in at 2014-05-15 19:10:28 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/crmsh (Old) and /work/SRC/openSUSE:Factory/.crmsh.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "crmsh" Changes: -------- --- /work/SRC/openSUSE:Factory/crmsh/crmsh.changes 2014-05-14 10:39:04.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.crmsh.new/crmsh.changes 2014-05-15 19:10:29.000000000 +0200 @@ -1,0 +2,7 @@ +Wed May 14 14:34:56 UTC 2014 - [email protected] + +- medium: ui_resource: Fix race in start/stop/manage/unmanage (bnc#877640) +- medium: report: Return to handling timestamps internally (bnc#877495) +- upstream: 2.0.0-73-g5f04128 + +------------------------------------------------------------------- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ crmsh.spec ++++++ --- /var/tmp/diff_new_pack.7Uwjme/_old 2014-05-15 19:10:30.000000000 +0200 +++ /var/tmp/diff_new_pack.7Uwjme/_new 2014-05-15 19:10:30.000000000 +0200 @@ -41,7 +41,7 @@ Summary: High Availability cluster command-line interface License: GPL-2.0+ Group: %{pkg_group} -Version: 2.0+git63 +Version: 2.0+git73 Release: %{?crmsh_release}%{?dist} Url: http://crmsh.github.io Source0: crmsh.tar.bz2 ++++++ crmsh.tar.bz2 ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/TODO new/crmsh/TODO --- old/crmsh/TODO 2014-05-13 16:18:05.000000000 +0200 +++ new/crmsh/TODO 2014-05-14 16:04:21.000000000 +0200 @@ -20,15 +20,13 @@ . CIB features - - Rules in primitive attribute declarations + - Support ACL commands in Pacemaker 1.1.12> - primitive dummy ocf:heartbeat:IPaddr2 \ - params 3: rule 0: #uname eq pcmk-1 nic=eth1 \ - params 2: rule 1: #uname eq pcmk-2 nic=eth2 \ - params 1: netmask=32 ip=127.0.0.1 nic=eth0 +. Command features - Adding parser support is easy. + - Relative commands: /status from configure, ../resource stop foo + from configure, cib/new from configure... for example. - Difficulty is adding support for multiple sets of parameters - with different scores - (right now they are all aggregated) in cibconfig.py + Tricky part: Have to push/pop levels invisibly, resource + commands modify CIB while CIB is edited in configure. Similar + races could occur with other commands. \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/modules/cibconfig.py new/crmsh/modules/cibconfig.py --- old/crmsh/modules/cibconfig.py 2014-05-13 16:18:05.000000000 +0200 +++ new/crmsh/modules/cibconfig.py 2014-05-14 16:04:21.000000000 +0200 @@ -887,6 +887,10 @@ def __str__(self): return "%s:%s" % (self.obj_type, self.obj_id) + def set_updated(self): + self.updated = True + self.propagate_updated() + def _dump_state(self): 'Print object status' print self.state_fmt % (self.obj_id, @@ -977,10 +981,20 @@ also show rule expressions if found ''' + + has_nvpairs = len(node.xpath('.//nvpair')) > 0 + idref = node.get('id-ref') + + # empty set + if not (has_nvpairs or idref is not None): + return '' + ret = "%s " % (clidisplay.keyword(self.set_names[node.tag])) node_id = node.get("id") - if cib_factory.is_id_refd(node.tag, node_id): + if node_id is not None and cib_factory.is_id_refd(node.tag, node_id): ret += "%s " % (nvpair_format("$id", node_id)) + elif idref is not None: + ret += "%s " % (nvpair_format("$id-ref", idref)) score = node.get("score") if score: @@ -1400,9 +1414,7 @@ node.remove(comment) if comments and self.node is not None: stuff_comments(self.node, [c.text for c in comments]) - # the resource is updated - self.updated = True - self.propagate_updated() + self.set_updated() return self def del_operation(self, op_node): @@ -1413,8 +1425,7 @@ idmgmt.remove_xml(op_node) if len(ops_node) == 0: rmnode(ops_node) - self.updated = True - self.propagate_updated() + self.set_updated() def is_dummy_operation(self, op_node): '''If the op has just name, id, and interval=0, then it's @@ -1434,8 +1445,7 @@ new_op_node = op_obj.mkxml() self._append_op(new_op_node) # the resource is updated - self.updated = True - self.propagate_updated() + self.set_updated() return new_op_node def del_op_attr(self, op_node, attr_n): @@ -1444,9 +1454,7 @@ op_obj.del_attr(attr_n) new_op_node = op_obj.mkxml() self._append_op(new_op_node) - # the resource is updated - self.updated = True - self.propagate_updated() + self.set_updated() return new_op_node def check_sanity(self): @@ -2626,19 +2634,16 @@ adv_timeout = ra.get_adv_timeout(op) if not adv_timeout: continue - head_pl = ["op", []] - head_pl[1].append(["name", op]) - head_pl[1].append(["timeout", adv_timeout]) - head_pl[1].append(["interval", "0"]) - cli_list = [] - cli_list.append(head_pl) - if not obj.add_operation(cli_list): + n = etree.Element('op') + n.set('name', op) + n.set('timeout', adv_timeout) + n.set('interval', '0') + if not obj.add_operation(n): rc = False else: obj_modified = True if obj_modified: - obj.updated = True - obj.propagate_updated() + obj.set_updated() return rc def is_id_refd(self, attr_list_type, id): @@ -2866,7 +2871,7 @@ topnode.append(obj.node) self.cib_objects.append(obj) copy_nvpairs(obj.node, node) - obj.updated = True + obj.set_updated() return obj def add_op(self, node): @@ -2954,8 +2959,7 @@ common_debug("update_element: validation failed (%s, %s)" % (obj, etree.tostring(newnode))) obj.nocli_warn = True obj.nocli = True - obj.updated = True - obj.propagate_updated() + obj.set_updated() return True def merge_from_cli(self, obj, node): @@ -2965,8 +2969,7 @@ else: rc = merge_nodes(obj.node, node) if rc: - obj.updated = True - obj.propagate_updated() + obj.set_updated() return True def _cli_set_update(self, edit_d, mk_set, upd_set, del_set, method): @@ -3139,6 +3142,24 @@ self.cib_objects.append(obj) return obj + def _add_children(self, obj_type, node): + """ + Called from create_from_node + In case this is a clone/group/master create from XML, + and the child node(s) haven't been added as a separate objects. + """ + if obj_type not in constants.container_tags: + return True + + for c in node.iterchildren('primitive'): + pid = c.get('id') + child_obj = self.find_object(pid) + if child_obj is None: + child_obj = self.create_from_node(copy.deepcopy(c)) + if not child_obj: + return False + return True + def create_from_node(self, node): 'Create a new cib object from a document node.' if node is None: @@ -3154,6 +3175,10 @@ if node is None: common_debug("create_from_node: get_rscop_defaults_meta_node failed") return None + + if not self._add_children(obj_type, node): + return None + obj = self.new_object(obj_type, node.get("id")) if not obj: return None @@ -3305,8 +3330,7 @@ rename_id(obj.node, old_id, new_id) obj.obj_id = new_id idmgmt.rename(old_id, new_id) - obj.updated = True - obj.propagate_updated() + obj.set_updated() def erase(self): "Remove all cib objects." diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/modules/parse.py new/crmsh/modules/parse.py --- old/crmsh/modules/parse.py 2014-05-13 16:18:05.000000000 +0200 +++ new/crmsh/modules/parse.py 2014-05-14 16:04:21.000000000 +0200 @@ -316,7 +316,7 @@ if self.try_match(self._SCORE_RE): score = self.matched(1) rules = self.match_rules() - values = self.match_nvpairs(minpairs=1) + values = self.match_nvpairs(minpairs=0) return xmlbuilder.attributes(tag, rules, values, xmlid=xmlid, score=score) def match_attr_lists(self, name_map): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/modules/report.py new/crmsh/modules/report.py --- old/crmsh/modules/report.py 2014-05-13 16:18:05.000000000 +0200 +++ new/crmsh/modules/report.py 2014-05-14 16:04:21.000000000 +0200 @@ -71,28 +71,32 @@ common_debug("setting year to %s (ts: %s)" % (YEAR, str(ts))) -def make_datetime(t): +def make_time(t): ''' t: time in seconds / datetime / other - returns: datetime object + returns: time in floating point ''' if t is None: return None elif isinstance(t, datetime.datetime): - return t - return datetime.datetime.fromtimestamp(t) + return convert_dt(t) + return t def syslog_ts(s): + """ + Finds the timestamp in the given line + Returns as floating point, seconds + """ try: # strptime defaults year to 1900 (sigh) # strptime returns a time_struct tm = time.strptime(' '.join([YEAR] + s.split()[0:3]), "%Y %b %d %H:%M:%S") - return make_datetime(time.mktime(tm)) + return time.mktime(tm) except: # try the rfc5424 try: - return parse_time(s.split()[0]) + return convert_dt(parse_time(s.split()[0])) except Exception: common_debug("malformed line: %s" % s) return None @@ -155,7 +159,7 @@ badline = 0 maxbadline = 10 common_debug("seek %s:%s in %s" % - (ts, + (time.ctime(ts), to_end and "end" or "start", f.name)) while first <= last: @@ -256,8 +260,13 @@ def convert_dt(dt): + """ + Convert a datetime object into a floating-point second value + """ try: - return time.mktime(dt.timetuple()) + ts = time.mktime(dt.timetuple()) + ts += dt.microsecond / 1000000.0 + return ts except: return None @@ -305,8 +314,8 @@ find out start/end file positions. Logs need to be already open. ''' - self.from_ts = make_datetime(from_dt) - self.to_ts = make_datetime(to_dt) + self.from_ts = make_time(from_dt) + self.to_ts = make_time(to_dt) bad_logs = [] for log in self.f: f = self.f[log] @@ -395,7 +404,7 @@ l.append(top_line[first]) top_line[first] = self.get_match_line(fl[first], patt)[0] if not top_line[first]: - top_line_ts[first] = datetime.datetime.now() + top_line_ts[first] = time.time() else: top_line_ts[first] = syslog_ts(top_line[first]) return l @@ -542,7 +551,7 @@ else: common_warn("end of transition %s not found in logs (transition not complete yet?)" % self) - self.end_ts = datetime.datetime.now() + self.end_ts = time.time() def actions_count(self): if self.run_msg: @@ -1300,7 +1309,7 @@ myts = min([syslog_ts(x) for x in first_log_lines(self.log_l)]) elif whence == "bottom": myts = max([syslog_ts(x) for x in last_log_lines(self.log_l)]) - return myts + return datetime.datetime.fromtimestamp(myts) except: return None diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/modules/ui_resource.py new/crmsh/modules/ui_resource.py --- old/crmsh/modules/ui_resource.py 2014-05-13 16:18:05.000000000 +0200 +++ new/crmsh/modules/ui_resource.py 2014-05-14 16:04:21.000000000 +0200 @@ -93,17 +93,8 @@ return True -def set_deep_meta_attr_tag(tag, attr, value): +def set_deep_meta_attr(rsc, attr, value, commit=True): """ - tag: an etree tag node - TODO: make transactional (shadow CIB?) - """ - return all(set_deep_meta_attr(attr, value, ref.get('id')) - for ref in tag.xpath("./obj_ref")) - - -def set_deep_meta_attr(attr, value, rsc_id): - ''' If the referenced rsc is a primitive that belongs to a group, then set its attribute. Otherwise, go up to the topmost resource which contains this @@ -113,20 +104,53 @@ the attribute set to a value different from the one given, then ask the user whether to reset them or not (exact behaviour depends on the value of config.core.manage_children). - ''' - target_node = xmlutil.RscState().rsc2node(rsc_id) - if target_node is None: - common_error("resource %s does not exist" % rsc_id) + """ + + def update_obj(obj): + """ + set the meta attribute in the given object + """ + node = obj.node + obj.set_updated() + if not (node.tag == "primitive" and + node.getparent().tag == "group"): + node = xmlutil.get_topmost_rsc(node) + return set_deep_meta_attr_node(node, attr, value) + + def flatten(objs): + for obj in objs: + if isinstance(obj, list): + for subobj in obj: + yield subobj + else: + yield obj + + def resolve(obj): + if obj.obj_type == 'tag': + return [cib_factory.find_object(o) for o in obj.node.xpath('./obj_ref/@id')] + return obj + + objs = cib_factory.find_objects(rsc) + while any(obj for obj in objs if obj.obj_type == 'tag'): + objs = list(flatten(resolve(obj) for obj in objs)) + common_debug("set_deep_meta_attr: %s" % (', '.join([obj.obj_id for obj in objs]))) + if not objs: + common_error("Resource not found: %s" % (rsc)) return False - if target_node.tag == 'tag': - return set_deep_meta_attr_tag(target_node, attr, value) - if not (target_node.tag == "primitive" and - target_node.getparent().tag == "group"): - target_node = xmlutil.get_topmost_rsc(target_node) - if not set_deep_meta_attr_node(target_node, attr, value): + ok = all(update_obj(obj) for obj in objs) + if not ok: + common_error("Failed to update meta attributes for %s" % (rsc)) return False - return xmlutil.commit_rsc(target_node) + + if not commit: + return True + + ok = cib_factory.commit() + if not ok: + common_error("Failed to commit updates to %s" % (rsc)) + return False + return True def cleanup_resource(rsc, node=''): @@ -209,35 +233,40 @@ else: return utils.ext_cmd(self.rsc_status_all) == 0 + def _commit_meta_attr(self, context, rsc, name, value): + """ + Perform change to resource + """ + if not utils.is_name_sane(rsc): + return False + commit = not cib_factory.has_cib_changed() + if not commit: + context.info("Currently editing the CIB, changes will not be committed") + return set_deep_meta_attr(rsc, name, value, commit=commit) + @command.wait @command.completers(compl.resources) def do_start(self, context, rsc): "usage: start <rsc>" - if not utils.is_name_sane(rsc): - return False - return set_deep_meta_attr("target-role", "Started", rsc) + return self._commit_meta_attr(context, rsc, "target-role", "Started") + + @command.wait + @command.completers(compl.resources) + def do_stop(self, context, rsc): + "usage: stop <rsc>" + return self._commit_meta_attr(context, rsc, "target-role", "Stopped") @command.wait @command.completers(compl.resources) def do_restart(self, context, rsc): "usage: restart <rsc>" - if not utils.is_name_sane(rsc): - return False common_info("ordering %s to stop" % rsc) - if not self.do_stop(context, rsc): + if not self._commit_meta_attr(context, rsc, "target-role", "Stopped"): return False if not utils.wait4dc("stop", not options.batch): return False common_info("ordering %s to start" % rsc) - return self.do_start(context, rsc) - - @command.wait - @command.completers(compl.resources) - def do_stop(self, context, rsc): - "usage: stop <rsc>" - if not utils.is_name_sane(rsc): - return False - return set_deep_meta_attr("target-role", "Stopped", rsc) + return self._commit_meta_attr(context, rsc, "target-role", "Started") @command.wait @command.completers(compl.resources) @@ -273,16 +302,12 @@ @command.completers(compl.resources) def do_manage(self, context, rsc): "usage: manage <rsc>" - if not utils.is_name_sane(rsc): - return False - return set_deep_meta_attr("is-managed", "true", rsc) + return self._commit_meta_attr(context, rsc, "is-managed", "true") @command.completers(compl.resources) def do_unmanage(self, context, rsc): "usage: unmanage <rsc>" - if not utils.is_name_sane(rsc): - return False - return set_deep_meta_attr("is-managed", "false", rsc) + return self._commit_meta_attr(context, rsc, "is-managed", "false") @command.alias('move') @command.skill_level('administrator') @@ -444,13 +469,12 @@ common_err("not allowed to create non-0 interval operation %s" % op) return False if op_node is None: - head_pl = ["op", []] - head_pl[1].append(["name", op]) - head_pl[1].append(["interval", interval]) - head_pl[1].append([constants.trace_ra_attr, "1"]) - cli_list = [] - cli_list.append(head_pl) - if not rsc.add_operation(cli_list): + from lxml import etree + n = etree.Element('op') + n.set('name', op) + n.set('interval', interval) + n.set(constants.trace_ra_attr, '1') + if not rsc.add_operation(n): return False else: op_node = rsc.set_op_attr(op_node, constants.trace_ra_attr, "1") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/modules/xmlutil.py new/crmsh/modules/xmlutil.py --- old/crmsh/modules/xmlutil.py 2014-05-13 16:18:05.000000000 +0200 +++ new/crmsh/modules/xmlutil.py 2014-05-14 16:04:21.000000000 +0200 @@ -124,17 +124,6 @@ common_error("running %s: %s" % (cmd, err_outp)) return None -cib_piped = "cibadmin -p" - - -def commit_rsc(node): - "Replace a resource definition using cibadmin -R" - xml_processnodes(node, is_emptynvpairs, rmnodes) - xml_processnodes(node, is_emptyops, rmnodes) - rc = pipe_string("%s -R -o %s" % (cib_piped, "resources"), - etree.tostring(node)) - return rc == 0 - def read_cib(fun, params=None): cib_elem = fun(params) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/test/testcases/resource.exp new/crmsh/test/testcases/resource.exp --- old/crmsh/test/testcases/resource.exp 2014-05-13 16:18:05.000000000 +0200 +++ new/crmsh/test/testcases/resource.exp 2014-05-14 16:04:21.000000000 +0200 @@ -3,7 +3,8 @@ resource p0 is NOT running .SETENV showobj=p3 .TRY resource start p3 -.EXT cibadmin -p -R -o resources +.EXT crm_resource --list-standards +.EXT crm_resource --list-ocf-alternatives Delay .INP: configure .INP: _regtest on .INP: show xml p3 @@ -26,7 +27,8 @@ </cib> .TRY resource stop p3 -.EXT cibadmin -p -R -o resources +.EXT crm_resource --list-standards +.EXT crm_resource --list-ocf-alternatives Delay .INP: configure .INP: _regtest on .INP: show xml p3 @@ -50,7 +52,8 @@ .SETENV showobj=c1 .TRY resource manage c1 -.EXT cibadmin -p -R -o resources +.EXT crm_resource --list-standards +.EXT crm_resource --list-ocf-alternatives Delay .INP: configure .INP: _regtest on .INP: show xml c1 @@ -74,7 +77,8 @@ </cib> .TRY resource unmanage c1 -.EXT cibadmin -p -R -o resources +.EXT crm_resource --list-standards +.EXT crm_resource --list-ocf-alternatives Delay .INP: configure .INP: _regtest on .INP: show xml c1 @@ -331,7 +335,8 @@ </cib> .TRY resource start g -.EXT cibadmin -p -R -o resources +.EXT crm_resource --list-standards +.EXT crm_resource --list-ocf-alternatives Delay .INP: configure .INP: _regtest on .INP: show xml p0 @@ -360,7 +365,8 @@ </cib> .TRY resource start p0 -.EXT cibadmin -p -R -o resources +.EXT crm_resource --list-standards +.EXT crm_resource --list-ocf-alternatives Delay .INP: configure .INP: _regtest on .INP: show xml p0 @@ -393,7 +399,8 @@ </cib> .TRY resource stop g -.EXT cibadmin -p -R -o resources +.EXT crm_resource --list-standards +.EXT crm_resource --list-ocf-alternatives Delay .INP: configure .INP: _regtest on .INP: show xml p0 @@ -496,7 +503,8 @@ </cib> .TRY resource start g -.EXT cibadmin -p -R -o resources +.EXT crm_resource --list-standards +.EXT crm_resource --list-ocf-alternatives Delay .INP: configure .INP: _regtest on .INP: show xml p0 @@ -527,7 +535,8 @@ </cib> .TRY resource stop g -.EXT cibadmin -p -R -o resources +.EXT crm_resource --list-standards +.EXT crm_resource --list-ocf-alternatives Delay .INP: configure .INP: _regtest on .INP: show xml p0 @@ -554,7 +563,8 @@ </cib> .TRY resource start cg -.EXT cibadmin -p -R -o resources +.EXT crm_resource --list-standards +.EXT crm_resource --list-ocf-alternatives Delay .INP: configure .INP: _regtest on .INP: show xml p0 @@ -581,7 +591,8 @@ </cib> .TRY resource stop p0 -.EXT cibadmin -p -R -o resources +.EXT crm_resource --list-standards +.EXT crm_resource --list-ocf-alternatives Delay .INP: configure .INP: _regtest on .INP: show xml p0 @@ -612,7 +623,8 @@ </cib> .TRY resource start cg -.EXT cibadmin -p -R -o resources +.EXT crm_resource --list-standards +.EXT crm_resource --list-ocf-alternatives Delay .INP: configure .INP: _regtest on .INP: show xml p0 @@ -639,7 +651,8 @@ </cib> .TRY resource stop cg -.EXT cibadmin -p -R -o resources +.EXT crm_resource --list-standards +.EXT crm_resource --list-ocf-alternatives Delay .INP: configure .INP: _regtest on .INP: show xml p0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/test/unittests/test_bugs.py new/crmsh/test/unittests/test_bugs.py --- old/crmsh/test/unittests/test_bugs.py 2014-05-13 16:18:05.000000000 +0200 +++ new/crmsh/test/unittests/test_bugs.py 2014-05-14 16:04:21.000000000 +0200 @@ -18,6 +18,7 @@ import cibconfig from lxml import etree +from nose.tools import eq_ import xmlutil factory = cibconfig.cib_factory @@ -37,10 +38,7 @@ </primitive> """ data = etree.fromstring(xml) - obj = factory.new_object('primitive', 'bug41660') - assert obj is not None - obj.node = data - obj.set_id() + obj = factory.create_from_node(data) print etree.tostring(obj.node) data = obj.repr_cli(format=-1) print data @@ -48,30 +46,15 @@ assert data == exp assert obj.cli_use_validate() - def mock_commit_rsc(node): - xmlutil.xml_processnodes(node, xmlutil.is_emptynvpairs, xmlutil.rmnodes) - xmlutil.xml_processnodes(node, xmlutil.is_emptyops, xmlutil.rmnodes) - assert 'name="target-role" value="Started"' in etree.tostring(node) - return True - - def mock_cibdump2elem(section=None): - if section == 'configuration': - return xmlutil.cibtext2elem( - """<configuration><resources>""" + xml + - """</resources></configuration>""") - assert False - - commit_rsc_holder = xmlutil.commit_rsc - cibdump2elem_holder = xmlutil.cibdump2elem + commit_holder = factory.commit try: - xmlutil.commit_rsc = mock_commit_rsc - xmlutil.cibdump2elem = mock_cibdump2elem - + factory.commit = lambda *args: True from ui_resource import set_deep_meta_attr - set_deep_meta_attr("target-role", "Started", "bug41660") + set_deep_meta_attr("bug41660", "target-role", "Started") + eq_(['Started'], + obj.node.xpath('.//nvpair[@name="target-role"]/@value')) finally: - xmlutil.commit_rsc = commit_rsc_holder - xmlutil.cibdump2elem = cibdump2elem_holder + factory.commit = commit_holder def test_bug41660_2(): @@ -93,41 +76,27 @@ </clone> """ data = etree.fromstring(xml) - obj = factory.new_object('clone', 'libvirtd-clone') + obj = factory.create_from_node(data) assert obj is not None - obj.node = data - obj.set_id() - data = obj.repr_cli(format=-1) - print data - exp = 'clone libvirtd-clone libvirtd meta interleave=true ordered=true target-role=Stopped' - assert data == exp + #data = obj.repr_cli(format=-1) + #print data + #exp = 'clone libvirtd-clone libvirtd meta interleave=true ordered=true target-role=Stopped' + #assert data == exp #assert obj.cli_use_validate() - def mock_commit_rsc(node): - xmlutil.xml_processnodes(node, xmlutil.is_emptynvpairs, xmlutil.rmnodes) - xmlutil.xml_processnodes(node, xmlutil.is_emptyops, xmlutil.rmnodes) - print etree.tostring(node) - assert etree.tostring(node).count('name="target-role" value="Started"') == 1 - return True - - def mock_cibdump2elem(section=None): - if section == 'configuration': - return xmlutil.cibtext2elem( - """<configuration><resources>""" + xml + - """</resources></configuration>""") - assert False + print etree.tostring(obj.node) - commit_rsc_holder = xmlutil.commit_rsc - cibdump2elem_holder = xmlutil.cibdump2elem + commit_holder = factory.commit try: - xmlutil.commit_rsc = mock_commit_rsc - xmlutil.cibdump2elem = mock_cibdump2elem - + factory.commit = lambda *args: True from ui_resource import set_deep_meta_attr - set_deep_meta_attr("target-role", "Started", "libvirtd-clone") + print "PRE", etree.tostring(obj.node) + set_deep_meta_attr("libvirtd-clone", "target-role", "Started") + print "POST", etree.tostring(obj.node) + eq_(['Started'], + obj.node.xpath('.//nvpair[@name="target-role"]/@value')) finally: - xmlutil.commit_rsc = commit_rsc_holder - xmlutil.cibdump2elem = cibdump2elem_holder + factory.commit = commit_holder def test_bug41660_3(): @@ -147,41 +116,24 @@ </clone> """ data = etree.fromstring(xml) - obj = factory.new_object('clone', 'libvirtd-clone') + obj = factory.create_from_node(data) assert obj is not None - obj.node = data - obj.set_id() data = obj.repr_cli(format=-1) print data exp = 'clone libvirtd-clone libvirtd meta target-role=Stopped' assert data == exp - #assert obj.cli_use_validate() - - def mock_commit_rsc(node): - xmlutil.xml_processnodes(node, xmlutil.is_emptynvpairs, xmlutil.rmnodes) - xmlutil.xml_processnodes(node, xmlutil.is_emptyops, xmlutil.rmnodes) - print etree.tostring(node) - assert etree.tostring(node).count('name="target-role" value="Started"') == 1 - return True - - def mock_cibdump2elem(section=None): - if section == 'configuration': - return xmlutil.cibtext2elem( - """<configuration><resources>""" + xml + - """</resources></configuration>""") - assert False + assert obj.cli_use_validate() - commit_rsc_holder = xmlutil.commit_rsc - cibdump2elem_holder = xmlutil.cibdump2elem + commit_holder = factory.commit try: - xmlutil.commit_rsc = mock_commit_rsc - xmlutil.cibdump2elem = mock_cibdump2elem - + factory.commit = lambda *args: True from ui_resource import set_deep_meta_attr - set_deep_meta_attr("target-role", "Started", "libvirtd-clone") + set_deep_meta_attr("libvirtd-clone", "target-role", "Started") + eq_(['Started'], + obj.node.xpath('.//nvpair[@name="target-role"]/@value')) finally: - xmlutil.commit_rsc = commit_rsc_holder - xmlutil.cibdump2elem = cibdump2elem_holder + factory.commit = commit_holder + def test_comments(): 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"> @@ -273,7 +225,7 @@ elem = etree.fromstring(xml) from ui_resource import set_deep_meta_attr_node - assert len(elem.xpath("//meta_attributes/nvpair[@name='target-role']")) == 1 + assert len(elem.xpath(".//meta_attributes/nvpair[@name='target-role']")) == 1 print "BEFORE:", etree.tostring(elem) @@ -281,4 +233,4 @@ print "AFTER:", etree.tostring(elem) - assert len(elem.xpath("//meta_attributes/nvpair[@name='target-role']")) == 1 + assert len(elem.xpath(".//meta_attributes/nvpair[@name='target-role']")) == 1 -- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
