On Thu, Jun 06, 2013 at 05:19:03PM +0200, Dejan Muhamedagic wrote:
> Hi,
>
> On Thu, Jun 06, 2013 at 03:11:16PM +0300, Vladislav Bogdanov wrote:
> > 06.06.2013 08:43, Vladislav Bogdanov wrote:
> > [...]
> > >>>>> I recall that LDAP has similar problem, which is easily worked around
> > >>>>> with specifying two values, one is original, second is new.
> > >>>>> That way you tell LDAP server:
> > >>>>> Replace value Y in attribute X to value Z. And if value is not Y at
> > >>>>> the
> > >>>>> moment of modification request, then command fails.
> > >>>>
> > >>>> "cibadmin --patch" works this way
> > >>>
> > >>> Who is baking new CIB in that case, cibadmin or cib?
> > >>
> > >> The patch is applied on the server - so "cib"
> > >
> > > Then that is safe way to go, assuming that cib daemon serializes
> > > modification requests.
> > >
> >
> > It would be great if crmsh use that trick.
>
> Hope to have something soon. Stay tuned.
The patch for crmsh is attached and you'll need the very latest
pacemaker (because cibadmin needed some fixing). Unfortunately,
I cannot push this yet to the repository, as the current
pacemaker 1.1.10-rc still identifies itself as 1.1.9. I'd
appreciate if you could test it.
Once again:
Do not use this patch with anything before pacemaker
commit 7cd53c!
Cheers,
Dejan
> Thanks,
>
> Dejan
> _______________________________________________
> Linux-HA mailing list
> [email protected]
> http://lists.linux-ha.org/mailman/listinfo/linux-ha
> See also: http://linux-ha.org/ReportingProblems
# HG changeset patch
# User Dejan Muhamedagic <[email protected]>
# Date 1372250948 -7200
# Wed Jun 26 14:49:08 2013 +0200
# Node ID c60a0e24683631aa4f7ac5903b0bab51cff472e6
# Parent 186677999fcdc42dbaf97aa211c0d3b45870787b
High: cibconfig: use cibadmin patch to update live CIB
diff -r 186677999fcd -r c60a0e246836 modules/cibconfig.py
--- a/modules/cibconfig.py Wed Jun 26 14:43:52 2013 +0200
+++ b/modules/cibconfig.py Wed Jun 26 14:49:08 2013 +0200
@@ -1928,7 +1928,6 @@ class CibFactory(Singleton):
self._init_vars()
self.regtest = options.regression_tests
self.last_commit_time = 0
- self.all_committed = True # has commit produced error
self._no_constraint_rm_msg = False # internal (just not to produce silly messages)
self.supported_cib_re = "^pacemaker-1[.][012]$"
def is_cib_sane(self):
@@ -2052,18 +2051,15 @@ class CibFactory(Singleton):
# create a doc from the list of objects
# (used by CibObjectSetRaw)
#
- def _regtest_filter(self, cib):
- for attr in ("epoch", "admin_epoch"):
- if cib.get(attr):
- cib.set(attr, "0")
- for attr in ("cib-last-written",):
- if cib.get(attr):
- del cib.attrib[attr]
+ def bump_epoch(self):
+ try:
+ self.cib_attrs["epoch"] = str(int(self.cib_attrs["epoch"])+1)
+ except:
+ common_warn("could not bump epoch, setting it to 1")
+ self.cib_attrs["epoch"] = "1"
def _set_cib_attributes(self, cib):
for attr in self.cib_attrs:
cib.set(attr, self.cib_attrs[attr])
- if self.regtest:
- self._regtest_filter(cib)
def objlist2doc(self, obj_list, obj_filter=None):
'''
Return document containing objects in obj_list.
@@ -2096,8 +2092,6 @@ class CibFactory(Singleton):
cib_attr = None
return c.get(a) == cib_attr
def is_current_cib_equal(self, silent=False):
- if self.overwrite:
- return True
cib_elem = read_cib(cibdump2elem)
if cib_elem is None:
return False
@@ -2122,9 +2116,10 @@ class CibFactory(Singleton):
'Commit the configuration to the CIB.'
if not self.is_cib_sane():
return False
- # all_committed is updated in the invoked object methods
- self.all_committed = True
- rc = self._commit_doc(force)
+ if cibadmin_can_patch():
+ rc = self._patch_cib(force)
+ else:
+ rc = self._replace_cib(force)
if rc:
# reload the cib!
common_debug("CIB commit successful")
@@ -2132,8 +2127,8 @@ class CibFactory(Singleton):
self.last_commit_time = time.time()
self.reset()
self.initialize()
- return self.all_committed
- def _commit_schema(self):
+ return rc
+ def _update_schema(self):
'''
Set the validate-with, if the schema changed.
'''
@@ -2144,13 +2139,13 @@ class CibFactory(Singleton):
return False
self.new_schema = False
return True
- def _commit_doc(self, force):
+ def _replace_cib(self, force):
try:
conf_el = self.cib_elem.findall("configuration")[0]
except IndexErr:
common_error("cannot find the configuration element")
return False
- if self.new_schema and not self._commit_schema():
+ if self.new_schema and not self._update_schema():
return False
cibadmin_opts = force and "-R --force" or "-R"
rc = pipe_string("%s %s" % (cib_piped, cibadmin_opts), etree.tostring(conf_el))
@@ -2158,6 +2153,22 @@ class CibFactory(Singleton):
update_err("cib", cibadmin_opts, etree.tostring(conf_el), rc)
return False
return True
+ def _patch_cib(self, force):
+ self.bump_epoch()
+ self._set_cib_attributes(self.cib_elem)
+ cibadmin_opts = force and "-P --force" or "-P"
+ # produce a diff:
+ # dump_new_conf | crm_diff -o self.cib_orig -n -
+ rc, cib_diff = filter_string("crm_diff -o %s -n -" % \
+ self.cib_orig, etree.tostring(self.cib_elem))
+ if not cib_diff:
+ common_err("crm_diff apparently failed to produce the diff (rc=%d)" % rc)
+ return False
+ rc = pipe_string("%s %s" % (cib_piped,cibadmin_opts), cib_diff)
+ if rc != 0:
+ update_err("cib", cibadmin_opts, cib_diff, rc)
+ return False
+ return True
#
# initialize cib_objects from CIB
#
@@ -2203,21 +2214,30 @@ class CibFactory(Singleton):
if not self._import_cib():
return False
sanitize_cib(self.cib_elem)
+ for attr in self.cib_elem.keys():
+ self.cib_attrs[attr] = self.cib_elem.get(attr)
+ if cibadmin_can_patch():
+ self.cib_orig = \
+ str2tmp(etree.tostring(self.cib_elem, pretty_print=True), \
+ suffix=".xml")
show_unrecognized_elems(self.cib_elem)
self._populate()
return self.check_structure()
def _init_vars(self):
self.cib_elem = None # the cib
+ self.cib_orig = None # the file holding the CIB which we loaded
self.cib_attrs = {} # cib version dictionary
self.cib_objects = [] # a list of cib objects
self.remove_queue = [] # a list of cib objects to be removed
self.id_refs = {} # dict of id-refs
- self.overwrite = False # update cib unconditionally
self.new_schema = False # schema changed
def reset(self):
if self.cib_elem is None:
return
self.cib_elem = None
+ if self.cib_orig:
+ try: os.unlink(self.cib_orig)
+ except: pass
self._init_vars()
id_store.clear()
def find_object(self, obj_id):
diff -r 186677999fcd -r c60a0e246836 modules/cibstatus.py
--- a/modules/cibstatus.py Wed Jun 26 14:43:52 2013 +0200
+++ b/modules/cibstatus.py Wed Jun 26 14:49:08 2013 +0200
@@ -104,7 +104,7 @@ class CibStatus(Singleton):
def _load_cib(self, source):
if source == "live":
if not self.backing_file:
- self.backing_file = cib2tmp()
+ self.backing_file = cibdump2tmp()
if not self.backing_file:
return None
else:
diff -r 186677999fcd -r c60a0e246836 modules/msg.py
--- a/modules/msg.py Wed Jun 26 14:43:52 2013 +0200
+++ b/modules/msg.py Wed Jun 26 14:49:08 2013 +0200
@@ -153,11 +153,15 @@ def update_err(obj_id, cibadm_opt, xml,
task = "update"
elif cibadm_opt == '-D':
task = "delete"
+ elif cibadm_opt == '-P':
+ task = "patch"
else:
task = "replace"
- err_buf.error("could not %s %s"%(task, obj_id))
+ err_buf.error("could not %s %s (rc=%d)" % (task, obj_id, rc))
if rc == 54:
err_buf.info("Permission denied.")
+ elif task == "patch":
+ err_buf.info("offending xml diff: %s" % xml)
else:
err_buf.info("offending xml: %s" % xml)
diff -r 186677999fcd -r c60a0e246836 modules/ui.py.in
--- a/modules/ui.py.in Wed Jun 26 14:43:52 2013 +0200
+++ b/modules/ui.py.in Wed Jun 26 14:49:08 2013 +0200
@@ -332,7 +332,7 @@ class CibShadow(UserInterface):
if not is_filename_sane(name):
return False
if ext_cmd("%s -C '%s' --force" % (self.extcmd, name)) == 0:
- common_info("commited '%s' shadow CIB to the cluster"%name)
+ common_info("committed '%s' shadow CIB to the cluster"%name)
else:
common_err("failed to commit the %s shadow CIB"%name)
return False
@@ -1768,9 +1768,9 @@ class CibConfig(UserInterface):
return cib_factory.commit()
if force or user_prefs.get_force():
common_info("commit forced")
- return cib_factory.commit(True)
+ return cib_factory.commit(force=True)
if ask("Do you still want to commit?"):
- return cib_factory.commit(True)
+ return cib_factory.commit(force=True)
return False
def upgrade(self, cmd, force=None):
"usage: upgrade [force]"
diff -r 186677999fcd -r c60a0e246836 modules/utils.py
--- a/modules/utils.py Wed Jun 26 14:43:52 2013 +0200
+++ b/modules/utils.py Wed Jun 26 14:49:08 2013 +0200
@@ -183,12 +183,12 @@ def filter_string(cmd, s, stderr_on=True
common_info("from: %s" % cmd)
return rc, outp
-def str2tmp(s):
+def str2tmp(s, suffix=".pcmk"):
'''
Write the given string to a temporary file. Return the name
of the file.
'''
- fd, tmp = mkstemp(suffix=".pcmk")
+ fd, tmp = mkstemp(suffix=suffix)
try:
f = os.fdopen(fd,"w")
except IOError, msg:
@@ -869,7 +869,7 @@ def get_cib_attributes(cib_f, tag, attr_
f.close()
return val_l
-def is_pcmk_118(cib_f=None):
+def is_min_pcmk_ver(min_ver, cib_f=None):
if not vars.pcmk_version:
if cib_f:
vars.pcmk_version = get_cib_property(cib_f, "dc-version", "1.1.1")
@@ -878,7 +878,12 @@ def is_pcmk_118(cib_f=None):
else:
vars.pcmk_version = get_pcmk_version("1.1.1")
from distutils.version import LooseVersion
- return LooseVersion(vars.pcmk_version) >= LooseVersion("1.1.8")
+ return LooseVersion(vars.pcmk_version) >= LooseVersion(min_ver)
+def is_pcmk_118(cib_f=None):
+ return is_min_pcmk_ver("1.1.8", cib_f=cib_f)
+def cibadmin_can_patch():
+ return True
+ #return is_min_pcmk_ver("1.1.10")
user_prefs = UserPrefs.getInstance()
options = Options.getInstance()
diff -r 186677999fcd -r c60a0e246836 modules/xmlutil.py
--- a/modules/xmlutil.py Wed Jun 26 14:43:52 2013 +0200
+++ b/modules/xmlutil.py Wed Jun 26 14:49:08 2013 +0200
@@ -55,7 +55,7 @@ def cibdump2file(fname):
common_err(msg)
return None
return str2file(s, fname)
-def cib2tmp():
+def cibdump2tmp():
cmd = add_sudo(cib_dump)
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
try:
_______________________________________________
Linux-HA mailing list
[email protected]
http://lists.linux-ha.org/mailman/listinfo/linux-ha
See also: http://linux-ha.org/ReportingProblems