|
|
be1b1f |
From e8d95b4ba03e62658ece669d6389b71b8553df1f Mon Sep 17 00:00:00 2001
|
|
|
be1b1f |
From: Ivan Devat <idevat@redhat.com>
|
|
|
be1b1f |
Date: Wed, 8 Aug 2018 13:48:24 +0200
|
|
|
be1b1f |
Subject: [PATCH] fix pcs cluster cib-push for old feature set
|
|
|
be1b1f |
|
|
|
be1b1f |
---
|
|
|
be1b1f |
pcs/cluster.py | 56 +++++++++++++++++++++++++++++++++++++-----
|
|
|
be1b1f |
pcs/lib/cib/test/test_tools.py | 29 ++++++++++++++++++++++
|
|
|
be1b1f |
pcs/lib/cib/tools.py | 6 ++---
|
|
|
be1b1f |
pcs/lib/env.py | 10 ++++++--
|
|
|
be1b1f |
4 files changed, 90 insertions(+), 11 deletions(-)
|
|
|
be1b1f |
|
|
|
be1b1f |
diff --git a/pcs/cluster.py b/pcs/cluster.py
|
|
|
be1b1f |
index b4d49d27..e8c94ab8 100644
|
|
|
be1b1f |
--- a/pcs/cluster.py
|
|
|
be1b1f |
+++ b/pcs/cluster.py
|
|
|
be1b1f |
@@ -35,6 +35,7 @@ from pcs import (
|
|
|
be1b1f |
)
|
|
|
be1b1f |
from pcs.utils import parallel_for_nodes
|
|
|
be1b1f |
from pcs.common import report_codes
|
|
|
be1b1f |
+from pcs.common.tools import Version
|
|
|
be1b1f |
from pcs.cli.common.errors import (
|
|
|
be1b1f |
CmdLineInputError,
|
|
|
be1b1f |
ERR_NODE_LIST_AND_ALL_MUTUALLY_EXCLUSIVE,
|
|
|
be1b1f |
@@ -46,6 +47,7 @@ from pcs.lib import (
|
|
|
be1b1f |
reports as lib_reports,
|
|
|
be1b1f |
)
|
|
|
be1b1f |
from pcs.lib.booth import sync as booth_sync
|
|
|
be1b1f |
+from pcs.lib.cib.tools import VERSION_FORMAT
|
|
|
be1b1f |
from pcs.lib.commands.remote_node import _share_authkey, _destroy_pcmk_remote_env
|
|
|
be1b1f |
from pcs.lib.commands.quorum import _add_device_model_net
|
|
|
be1b1f |
from pcs.lib.communication.corosync import CheckCorosyncOffline
|
|
|
be1b1f |
@@ -74,6 +76,7 @@ from pcs.lib.external import (
|
|
|
be1b1f |
NodeCommunicationException,
|
|
|
be1b1f |
node_communicator_exception_to_report_item,
|
|
|
be1b1f |
)
|
|
|
be1b1f |
+from pcs.lib.env import MIN_FEATURE_SET_VERSION_FOR_DIFF
|
|
|
be1b1f |
from pcs.lib.env_tools import get_nodes
|
|
|
be1b1f |
from pcs.lib.node import NodeAddresses
|
|
|
be1b1f |
from pcs.lib import node_communication_format
|
|
|
be1b1f |
@@ -1566,21 +1569,62 @@ def cluster_push(argv):
|
|
|
be1b1f |
|
|
|
be1b1f |
if diff_against:
|
|
|
be1b1f |
try:
|
|
|
be1b1f |
- xml.dom.minidom.parse(diff_against)
|
|
|
be1b1f |
+ original_cib = xml.dom.minidom.parse(diff_against)
|
|
|
be1b1f |
except (EnvironmentError, xml.parsers.expat.ExpatError) as e:
|
|
|
be1b1f |
utils.err("unable to parse original cib: %s" % e)
|
|
|
be1b1f |
+
|
|
|
be1b1f |
+ def unable_to_diff(reason):
|
|
|
be1b1f |
+ return error(
|
|
|
be1b1f |
+ "unable to diff against original cib '{0}': {1}"
|
|
|
be1b1f |
+ .format(diff_against, reason)
|
|
|
be1b1f |
+ )
|
|
|
be1b1f |
+
|
|
|
be1b1f |
+ cib_element_list = original_cib.getElementsByTagName("cib")
|
|
|
be1b1f |
+
|
|
|
be1b1f |
+ if len(cib_element_list) != 1:
|
|
|
be1b1f |
+ raise unable_to_diff("there is not exactly one 'cib' element")
|
|
|
be1b1f |
+
|
|
|
be1b1f |
+ crm_feature_set = cib_element_list[0].getAttribute("crm_feature_set")
|
|
|
be1b1f |
+ if not crm_feature_set:
|
|
|
be1b1f |
+ raise unable_to_diff(
|
|
|
be1b1f |
+ "the 'cib' element is missing 'crm_feature_set' value"
|
|
|
be1b1f |
+ )
|
|
|
be1b1f |
+
|
|
|
be1b1f |
+ match = re.match(VERSION_FORMAT, crm_feature_set)
|
|
|
be1b1f |
+ if not match:
|
|
|
be1b1f |
+ raise unable_to_diff(
|
|
|
be1b1f |
+ "the attribute 'crm_feature_set' of the element 'cib' has an"
|
|
|
be1b1f |
+ " invalid value: '{0}'".format(crm_feature_set)
|
|
|
be1b1f |
+ )
|
|
|
be1b1f |
+ crm_feature_set_version = Version(
|
|
|
be1b1f |
+ int(match.group("major")),
|
|
|
be1b1f |
+ int(match.group("minor")),
|
|
|
be1b1f |
+ int(match.group("rev")) if match.group("rev") else None
|
|
|
be1b1f |
+ )
|
|
|
be1b1f |
+
|
|
|
be1b1f |
+ if crm_feature_set_version < MIN_FEATURE_SET_VERSION_FOR_DIFF:
|
|
|
be1b1f |
+ raise unable_to_diff(
|
|
|
be1b1f |
+ (
|
|
|
be1b1f |
+ "the 'crm_feature_set' version is '{0}'"
|
|
|
be1b1f |
+ " but at least version '{1}' is required"
|
|
|
be1b1f |
+ ).format(
|
|
|
be1b1f |
+ crm_feature_set_version,
|
|
|
be1b1f |
+ MIN_FEATURE_SET_VERSION_FOR_DIFF,
|
|
|
be1b1f |
+ )
|
|
|
be1b1f |
+ )
|
|
|
be1b1f |
+
|
|
|
be1b1f |
runner = utils.cmd_runner()
|
|
|
be1b1f |
command = [
|
|
|
be1b1f |
"crm_diff", "--original", diff_against, "--new", filename,
|
|
|
be1b1f |
"--no-version"
|
|
|
be1b1f |
]
|
|
|
be1b1f |
- patch, error, dummy_retval = runner.run(command)
|
|
|
be1b1f |
+ patch, stderr, dummy_retval = runner.run(command)
|
|
|
be1b1f |
# dummy_retval == 1 means one of two things:
|
|
|
be1b1f |
# a) an error has occured
|
|
|
be1b1f |
# b) --original and --new differ
|
|
|
be1b1f |
# therefore it's of no use to see if an error occurred
|
|
|
be1b1f |
- if error.strip():
|
|
|
be1b1f |
- utils.err("unable to diff the CIBs:\n" + error)
|
|
|
be1b1f |
+ if stderr.strip():
|
|
|
be1b1f |
+ utils.err("unable to diff the CIBs:\n" + stderr)
|
|
|
be1b1f |
if not patch.strip():
|
|
|
be1b1f |
print(
|
|
|
be1b1f |
"The new CIB is the same as the original CIB, nothing to push."
|
|
|
be1b1f |
@@ -1588,9 +1632,9 @@ def cluster_push(argv):
|
|
|
be1b1f |
sys.exit(0)
|
|
|
be1b1f |
|
|
|
be1b1f |
command = ["cibadmin", "--patch", "--xml-pipe"]
|
|
|
be1b1f |
- output, error, retval = runner.run(command, patch)
|
|
|
be1b1f |
+ output, stderr, retval = runner.run(command, patch)
|
|
|
be1b1f |
if retval != 0:
|
|
|
be1b1f |
- utils.err("unable to push cib\n" + error + output)
|
|
|
be1b1f |
+ utils.err("unable to push cib\n" + stderr + output)
|
|
|
be1b1f |
|
|
|
be1b1f |
else:
|
|
|
be1b1f |
command = ["cibadmin", "--replace", "--xml-file", filename]
|
|
|
be1b1f |
diff --git a/pcs/lib/cib/test/test_tools.py b/pcs/lib/cib/test/test_tools.py
|
|
|
be1b1f |
index fab39ce7..2bdc7695 100644
|
|
|
be1b1f |
--- a/pcs/lib/cib/test/test_tools.py
|
|
|
be1b1f |
+++ b/pcs/lib/cib/test/test_tools.py
|
|
|
be1b1f |
@@ -436,6 +436,21 @@ class GetPacemakerVersionByWhichCibWasValidatedTest(TestCase):
|
|
|
be1b1f |
)
|
|
|
be1b1f |
)
|
|
|
be1b1f |
|
|
|
be1b1f |
+ def test_invalid_version_at_end(self):
|
|
|
be1b1f |
+ assert_raise_library_error(
|
|
|
be1b1f |
+ lambda: lib.get_pacemaker_version_by_which_cib_was_validated(
|
|
|
be1b1f |
+ etree.XML('<cib validate-with="pacemaker-1.2.3x"/>')
|
|
|
be1b1f |
+ ),
|
|
|
be1b1f |
+ (
|
|
|
be1b1f |
+ severities.ERROR,
|
|
|
be1b1f |
+ report_codes.CIB_LOAD_ERROR_BAD_FORMAT,
|
|
|
be1b1f |
+ {
|
|
|
be1b1f |
+ "reason": "the attribute 'validate-with' of the element"
|
|
|
be1b1f |
+ " 'cib' has an invalid value: 'pacemaker-1.2.3x'"
|
|
|
be1b1f |
+ }
|
|
|
be1b1f |
+ )
|
|
|
be1b1f |
+ )
|
|
|
be1b1f |
+
|
|
|
be1b1f |
def test_no_revision(self):
|
|
|
be1b1f |
self.assertEqual(
|
|
|
be1b1f |
Version(1, 2),
|
|
|
be1b1f |
@@ -507,6 +522,20 @@ class getCibCrmFeatureSet(TestCase):
|
|
|
be1b1f |
)
|
|
|
be1b1f |
)
|
|
|
be1b1f |
|
|
|
be1b1f |
+ def test_invalid_version_at_end(self):
|
|
|
be1b1f |
+ assert_raise_library_error(
|
|
|
be1b1f |
+ lambda: lib.get_cib_crm_feature_set(
|
|
|
be1b1f |
+ etree.XML('<cib crm_feature_set="3.0.9x" />')
|
|
|
be1b1f |
+ ),
|
|
|
be1b1f |
+ fixture.error(
|
|
|
be1b1f |
+ report_codes.CIB_LOAD_ERROR_BAD_FORMAT,
|
|
|
be1b1f |
+ reason=(
|
|
|
be1b1f |
+ "the attribute 'crm_feature_set' of the element 'cib' has "
|
|
|
be1b1f |
+ "an invalid value: '3.0.9x'"
|
|
|
be1b1f |
+ )
|
|
|
be1b1f |
+ )
|
|
|
be1b1f |
+ )
|
|
|
be1b1f |
+
|
|
|
be1b1f |
|
|
|
be1b1f |
find_group = partial(lib.find_element_by_tag_and_id, "group")
|
|
|
be1b1f |
class FindTagWithId(TestCase):
|
|
|
be1b1f |
diff --git a/pcs/lib/cib/tools.py b/pcs/lib/cib/tools.py
|
|
|
be1b1f |
index 2cff96f3..ab2a9df5 100644
|
|
|
be1b1f |
--- a/pcs/lib/cib/tools.py
|
|
|
be1b1f |
+++ b/pcs/lib/cib/tools.py
|
|
|
be1b1f |
@@ -16,7 +16,7 @@ from pcs.lib.pacemaker.values import (
|
|
|
be1b1f |
)
|
|
|
be1b1f |
from pcs.lib.xml_tools import get_root, get_sub_element
|
|
|
be1b1f |
|
|
|
be1b1f |
-_VERSION_FORMAT = r"(?P<major>\d+)\.(?P<minor>\d+)(\.(?P<rev>\d+))?"
|
|
|
be1b1f |
+VERSION_FORMAT = r"(?P<major>\d+)\.(?P<minor>\d+)(\.(?P<rev>\d+))?$"
|
|
|
be1b1f |
|
|
|
be1b1f |
class IdProvider(object):
|
|
|
be1b1f |
"""
|
|
|
be1b1f |
@@ -289,7 +289,7 @@ def get_pacemaker_version_by_which_cib_was_validated(cib):
|
|
|
be1b1f |
return _get_cib_version(
|
|
|
be1b1f |
cib,
|
|
|
be1b1f |
"validate-with",
|
|
|
be1b1f |
- re.compile(r"pacemaker-{0}".format(_VERSION_FORMAT))
|
|
|
be1b1f |
+ re.compile(r"pacemaker-{0}".format(VERSION_FORMAT))
|
|
|
be1b1f |
)
|
|
|
be1b1f |
|
|
|
be1b1f |
def get_cib_crm_feature_set(cib, none_if_missing=False):
|
|
|
be1b1f |
@@ -303,6 +303,6 @@ def get_cib_crm_feature_set(cib, none_if_missing=False):
|
|
|
be1b1f |
return _get_cib_version(
|
|
|
be1b1f |
cib,
|
|
|
be1b1f |
"crm_feature_set",
|
|
|
be1b1f |
- re.compile(_VERSION_FORMAT),
|
|
|
be1b1f |
+ re.compile(r"^{0}".format(VERSION_FORMAT)),
|
|
|
be1b1f |
none_if_missing=none_if_missing
|
|
|
be1b1f |
)
|
|
|
be1b1f |
diff --git a/pcs/lib/env.py b/pcs/lib/env.py
|
|
|
be1b1f |
index 86f67b64..3b2c06b6 100644
|
|
|
be1b1f |
--- a/pcs/lib/env.py
|
|
|
be1b1f |
+++ b/pcs/lib/env.py
|
|
|
be1b1f |
@@ -57,6 +57,8 @@ from pcs.lib.pacemaker.values import get_valid_timeout_seconds
|
|
|
be1b1f |
from pcs.lib.tools import write_tmpfile
|
|
|
be1b1f |
from pcs.lib.xml_tools import etree_to_str
|
|
|
be1b1f |
|
|
|
be1b1f |
+MIN_FEATURE_SET_VERSION_FOR_DIFF = Version(3, 0, 9)
|
|
|
be1b1f |
+
|
|
|
be1b1f |
class LibraryEnvironment(object):
|
|
|
be1b1f |
# pylint: disable=too-many-instance-attributes
|
|
|
be1b1f |
|
|
|
be1b1f |
@@ -211,10 +213,14 @@ class LibraryEnvironment(object):
|
|
|
be1b1f |
# only check the version if a CIB has been loaded, otherwise the push
|
|
|
be1b1f |
# fails anyway. By my testing it seems that only the source CIB's
|
|
|
be1b1f |
# version matters.
|
|
|
be1b1f |
- if self.__loaded_cib_diff_source_feature_set < Version(3, 0, 9):
|
|
|
be1b1f |
+ if(
|
|
|
be1b1f |
+ self.__loaded_cib_diff_source_feature_set
|
|
|
be1b1f |
+ <
|
|
|
be1b1f |
+ MIN_FEATURE_SET_VERSION_FOR_DIFF
|
|
|
be1b1f |
+ ):
|
|
|
be1b1f |
self.report_processor.process(
|
|
|
be1b1f |
reports.cib_push_forced_full_due_to_crm_feature_set(
|
|
|
be1b1f |
- Version(3, 0, 9),
|
|
|
be1b1f |
+ MIN_FEATURE_SET_VERSION_FOR_DIFF,
|
|
|
be1b1f |
self.__loaded_cib_diff_source_feature_set
|
|
|
be1b1f |
)
|
|
|
be1b1f |
)
|
|
|
be1b1f |
--
|
|
|
be1b1f |
2.13.6
|
|
|
be1b1f |
|