import pcs-0.10.12-6.el8
This commit is contained in:
parent
90bf1707ad
commit
fcbd3f1a7e
@ -0,0 +1,934 @@
|
|||||||
|
From ae3435418f0af6e5f22f463871aa90a5c5b2d15f Mon Sep 17 00:00:00 2001
|
||||||
|
From: Tomas Jelinek <tojeline@redhat.com>
|
||||||
|
Date: Fri, 4 Feb 2022 16:23:18 +0100
|
||||||
|
Subject: [PATCH 1/3] process invalid OCF agents as if they complied with OCF
|
||||||
|
1.0
|
||||||
|
|
||||||
|
---
|
||||||
|
pcs/common/reports/codes.py | 4 +-
|
||||||
|
pcs/common/reports/messages.py | 13 +-
|
||||||
|
pcs/lib/commands/resource.py | 3 +-
|
||||||
|
pcs/lib/commands/resource_agent.py | 4 +-
|
||||||
|
pcs/lib/commands/stonith.py | 3 +-
|
||||||
|
pcs/lib/resource_agent/__init__.py | 1 -
|
||||||
|
pcs/lib/resource_agent/error.py | 14 --
|
||||||
|
pcs/lib/resource_agent/facade.py | 37 ++-
|
||||||
|
pcs/lib/resource_agent/xml.py | 15 +-
|
||||||
|
.../tier0/common/reports/test_messages.py | 18 +-
|
||||||
|
.../tier0/lib/resource_agent/test_facade.py | 47 ++++
|
||||||
|
pcs_test/tier0/lib/resource_agent/test_xml.py | 226 ++++++++----------
|
||||||
|
12 files changed, 201 insertions(+), 184 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/pcs/common/reports/codes.py b/pcs/common/reports/codes.py
|
||||||
|
index 3e0512d9..e8dee00f 100644
|
||||||
|
--- a/pcs/common/reports/codes.py
|
||||||
|
+++ b/pcs/common/reports/codes.py
|
||||||
|
@@ -36,8 +36,8 @@ ADD_REMOVE_CANNOT_SPECIFY_ADJACENT_ITEM_WITHOUT_ITEMS_TO_ADD = M(
|
||||||
|
"ADD_REMOVE_CANNOT_SPECIFY_ADJACENT_ITEM_WITHOUT_ITEMS_TO_ADD"
|
||||||
|
)
|
||||||
|
AGENT_GENERIC_ERROR = M("AGENT_GENERIC_ERROR")
|
||||||
|
-AGENT_IMPLEMENTS_UNSUPPORTED_OCF_VERSION = M(
|
||||||
|
- "AGENT_IMPLEMENTS_UNSUPPORTED_OCF_VERSION"
|
||||||
|
+AGENT_IMPLEMENTS_UNSUPPORTED_OCF_VERSION_ASSUMED_VERSION = M(
|
||||||
|
+ "AGENT_IMPLEMENTS_UNSUPPORTED_OCF_VERSION_ASSUMED_VERSION"
|
||||||
|
)
|
||||||
|
AGENT_NAME_GUESS_FOUND_MORE_THAN_ONE = M("AGENT_NAME_GUESS_FOUND_MORE_THAN_ONE")
|
||||||
|
AGENT_NAME_GUESS_FOUND_NONE = M("AGENT_NAME_GUESS_FOUND_NONE")
|
||||||
|
diff --git a/pcs/common/reports/messages.py b/pcs/common/reports/messages.py
|
||||||
|
index 9d665e73..7df1e1eb 100644
|
||||||
|
--- a/pcs/common/reports/messages.py
|
||||||
|
+++ b/pcs/common/reports/messages.py
|
||||||
|
@@ -3789,9 +3789,9 @@ class AgentNameGuessFoundNone(ReportItemMessage):
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
-class AgentImplementsUnsupportedOcfVersion(ReportItemMessage):
|
||||||
|
+class AgentImplementsUnsupportedOcfVersionAssumedVersion(ReportItemMessage):
|
||||||
|
"""
|
||||||
|
- Specified agent implements OCF version not supported by pcs
|
||||||
|
+ Specified agent implements OCF version not supported by pcs, assumed OCF 1.0
|
||||||
|
|
||||||
|
agent -- name of the agent
|
||||||
|
ocf_version -- OCF version implemented by the agent
|
||||||
|
@@ -3801,7 +3801,8 @@ class AgentImplementsUnsupportedOcfVersion(ReportItemMessage):
|
||||||
|
agent: str
|
||||||
|
ocf_version: str
|
||||||
|
supported_versions: List[str]
|
||||||
|
- _code = codes.AGENT_IMPLEMENTS_UNSUPPORTED_OCF_VERSION
|
||||||
|
+ assumed_version: str
|
||||||
|
+ _code = codes.AGENT_IMPLEMENTS_UNSUPPORTED_OCF_VERSION_ASSUMED_VERSION
|
||||||
|
|
||||||
|
@property
|
||||||
|
def message(self) -> str:
|
||||||
|
@@ -3809,9 +3810,9 @@ class AgentImplementsUnsupportedOcfVersion(ReportItemMessage):
|
||||||
|
_is = format_plural(self.supported_versions, "is")
|
||||||
|
_version_list = format_list(self.supported_versions)
|
||||||
|
return (
|
||||||
|
- f"Unable to process agent '{self.agent}' as it implements "
|
||||||
|
- f"unsupported OCF version '{self.ocf_version}', supported "
|
||||||
|
- f"{_version} {_is}: {_version_list}"
|
||||||
|
+ f"Agent '{self.agent}' implements unsupported OCF version "
|
||||||
|
+ f"'{self.ocf_version}', supported {_version} {_is}: "
|
||||||
|
+ f"{_version_list}; assumed version '{self.assumed_version}'"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
diff --git a/pcs/lib/commands/resource.py b/pcs/lib/commands/resource.py
|
||||||
|
index 82ce73e0..c4b6252c 100644
|
||||||
|
--- a/pcs/lib/commands/resource.py
|
||||||
|
+++ b/pcs/lib/commands/resource.py
|
||||||
|
@@ -84,7 +84,6 @@ from pcs.lib.resource_agent import (
|
||||||
|
ResourceAgentName,
|
||||||
|
split_resource_agent_name,
|
||||||
|
UnableToGetAgentMetadata,
|
||||||
|
- UnsupportedOcfVersion,
|
||||||
|
)
|
||||||
|
from pcs.lib.tools import get_tmp_cib
|
||||||
|
from pcs.lib.validate import ValueTimeInterval
|
||||||
|
@@ -162,7 +161,7 @@ def _get_agent_facade(
|
||||||
|
else find_one_resource_agent_by_type(runner, report_processor, name)
|
||||||
|
)
|
||||||
|
return factory.facade_from_parsed_name(split_name)
|
||||||
|
- except (UnableToGetAgentMetadata, UnsupportedOcfVersion) as e:
|
||||||
|
+ except UnableToGetAgentMetadata as e:
|
||||||
|
if allow_absent_agent:
|
||||||
|
report_processor.report(
|
||||||
|
resource_agent_error_to_report_item(
|
||||||
|
diff --git a/pcs/lib/commands/resource_agent.py b/pcs/lib/commands/resource_agent.py
|
||||||
|
index e6167b13..4a1831c0 100644
|
||||||
|
--- a/pcs/lib/commands/resource_agent.py
|
||||||
|
+++ b/pcs/lib/commands/resource_agent.py
|
||||||
|
@@ -139,7 +139,9 @@ def _complete_agent_list(
|
||||||
|
try:
|
||||||
|
split_name = split_resource_agent_name(name)
|
||||||
|
metadata = (
|
||||||
|
- agent_factory.facade_from_parsed_name(split_name).metadata
|
||||||
|
+ agent_factory.facade_from_parsed_name(
|
||||||
|
+ split_name, report_warnings=False
|
||||||
|
+ ).metadata
|
||||||
|
if describe
|
||||||
|
else name_to_void_metadata(split_name)
|
||||||
|
)
|
||||||
|
diff --git a/pcs/lib/commands/stonith.py b/pcs/lib/commands/stonith.py
|
||||||
|
index 093f5be9..2aa299d7 100644
|
||||||
|
--- a/pcs/lib/commands/stonith.py
|
||||||
|
+++ b/pcs/lib/commands/stonith.py
|
||||||
|
@@ -45,7 +45,6 @@ from pcs.lib.resource_agent import (
|
||||||
|
ResourceAgentFacadeFactory,
|
||||||
|
ResourceAgentName,
|
||||||
|
UnableToGetAgentMetadata,
|
||||||
|
- UnsupportedOcfVersion,
|
||||||
|
)
|
||||||
|
from pcs.lib.validate import validate_add_remove_items
|
||||||
|
from pcs.lib.xml_tools import get_root
|
||||||
|
@@ -62,7 +61,7 @@ def _get_agent_facade(
|
||||||
|
raise InvalidResourceAgentName(name)
|
||||||
|
full_name = ResourceAgentName("stonith", None, name)
|
||||||
|
return factory.facade_from_parsed_name(full_name)
|
||||||
|
- except (UnableToGetAgentMetadata, UnsupportedOcfVersion) as e:
|
||||||
|
+ except UnableToGetAgentMetadata as e:
|
||||||
|
if allow_absent_agent:
|
||||||
|
report_processor.report(
|
||||||
|
resource_agent_error_to_report_item(
|
||||||
|
diff --git a/pcs/lib/resource_agent/__init__.py b/pcs/lib/resource_agent/__init__.py
|
||||||
|
index 4548017f..c6086331 100644
|
||||||
|
--- a/pcs/lib/resource_agent/__init__.py
|
||||||
|
+++ b/pcs/lib/resource_agent/__init__.py
|
||||||
|
@@ -10,7 +10,6 @@ from .error import (
|
||||||
|
ResourceAgentError,
|
||||||
|
resource_agent_error_to_report_item,
|
||||||
|
UnableToGetAgentMetadata,
|
||||||
|
- UnsupportedOcfVersion,
|
||||||
|
)
|
||||||
|
from .facade import ResourceAgentFacade, ResourceAgentFacadeFactory
|
||||||
|
from .list import (
|
||||||
|
diff --git a/pcs/lib/resource_agent/error.py b/pcs/lib/resource_agent/error.py
|
||||||
|
index d4178333..f1dd7f3d 100644
|
||||||
|
--- a/pcs/lib/resource_agent/error.py
|
||||||
|
+++ b/pcs/lib/resource_agent/error.py
|
||||||
|
@@ -2,8 +2,6 @@ from typing import Iterable
|
||||||
|
|
||||||
|
from pcs.common import reports
|
||||||
|
|
||||||
|
-from . import const
|
||||||
|
-
|
||||||
|
|
||||||
|
class ResourceAgentError(Exception):
|
||||||
|
def __init__(self, agent_name: str):
|
||||||
|
@@ -37,12 +35,6 @@ class UnableToGetAgentMetadata(ResourceAgentError):
|
||||||
|
self.message = message
|
||||||
|
|
||||||
|
|
||||||
|
-class UnsupportedOcfVersion(ResourceAgentError):
|
||||||
|
- def __init__(self, agent_name: str, ocf_version: str):
|
||||||
|
- super().__init__(agent_name)
|
||||||
|
- self.ocf_version = ocf_version
|
||||||
|
-
|
||||||
|
-
|
||||||
|
def resource_agent_error_to_report_item(
|
||||||
|
e: ResourceAgentError,
|
||||||
|
severity: reports.ReportItemSeverity = reports.ReportItemSeverity.error(),
|
||||||
|
@@ -69,10 +61,4 @@ def resource_agent_error_to_report_item(
|
||||||
|
message = reports.messages.UnableToGetAgentMetadata(
|
||||||
|
e.agent_name, e.message
|
||||||
|
)
|
||||||
|
- elif isinstance(e, UnsupportedOcfVersion):
|
||||||
|
- message = reports.messages.AgentImplementsUnsupportedOcfVersion(
|
||||||
|
- e.agent_name,
|
||||||
|
- e.ocf_version,
|
||||||
|
- sorted(const.SUPPORTED_OCF_VERSIONS),
|
||||||
|
- )
|
||||||
|
return reports.ReportItem(severity, message)
|
||||||
|
diff --git a/pcs/lib/resource_agent/facade.py b/pcs/lib/resource_agent/facade.py
|
||||||
|
index 4dbb59b8..dea59a1a 100644
|
||||||
|
--- a/pcs/lib/resource_agent/facade.py
|
||||||
|
+++ b/pcs/lib/resource_agent/facade.py
|
||||||
|
@@ -188,18 +188,32 @@ class ResourceAgentFacadeFactory:
|
||||||
|
self._fenced_metadata = None
|
||||||
|
|
||||||
|
def facade_from_parsed_name(
|
||||||
|
- self, name: ResourceAgentName
|
||||||
|
+ self, name: ResourceAgentName, report_warnings=True
|
||||||
|
) -> ResourceAgentFacade:
|
||||||
|
"""
|
||||||
|
Create ResourceAgentFacade based on specified agent name
|
||||||
|
|
||||||
|
name -- agent name to get a facade for
|
||||||
|
"""
|
||||||
|
- return self._facade_from_metadata(
|
||||||
|
- ocf_version_to_ocf_unified(
|
||||||
|
- parse_metadata(name, load_metadata(self._runner, name))
|
||||||
|
- )
|
||||||
|
+ metadata, raw_ocf_version = parse_metadata(
|
||||||
|
+ name,
|
||||||
|
+ load_metadata(self._runner, name),
|
||||||
|
)
|
||||||
|
+ if (
|
||||||
|
+ report_warnings
|
||||||
|
+ and raw_ocf_version not in const.SUPPORTED_OCF_VERSIONS
|
||||||
|
+ ):
|
||||||
|
+ self._report_processor.report(
|
||||||
|
+ reports.ReportItem.warning(
|
||||||
|
+ reports.messages.AgentImplementsUnsupportedOcfVersionAssumedVersion(
|
||||||
|
+ name.full_name,
|
||||||
|
+ raw_ocf_version,
|
||||||
|
+ sorted(const.SUPPORTED_OCF_VERSIONS),
|
||||||
|
+ const.OCF_1_0,
|
||||||
|
+ )
|
||||||
|
+ )
|
||||||
|
+ )
|
||||||
|
+ return self._facade_from_metadata(ocf_version_to_ocf_unified(metadata))
|
||||||
|
|
||||||
|
def void_facade_from_parsed_name(
|
||||||
|
self, name: ResourceAgentName
|
||||||
|
@@ -232,15 +246,12 @@ class ResourceAgentFacadeFactory:
|
||||||
|
const.FAKE_AGENT_STANDARD, None, const.PACEMAKER_FENCED
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
+ metadata, _ = parse_metadata(
|
||||||
|
+ agent_name,
|
||||||
|
+ load_fake_agent_metadata(self._runner, agent_name.type),
|
||||||
|
+ )
|
||||||
|
self._fenced_metadata = ocf_unified_to_pcs(
|
||||||
|
- ocf_version_to_ocf_unified(
|
||||||
|
- parse_metadata(
|
||||||
|
- agent_name,
|
||||||
|
- load_fake_agent_metadata(
|
||||||
|
- self._runner, agent_name.type
|
||||||
|
- ),
|
||||||
|
- )
|
||||||
|
- )
|
||||||
|
+ ocf_version_to_ocf_unified(metadata)
|
||||||
|
)
|
||||||
|
except ResourceAgentError as e:
|
||||||
|
# If pcs is unable to load fenced metadata, cache an empty
|
||||||
|
diff --git a/pcs/lib/resource_agent/xml.py b/pcs/lib/resource_agent/xml.py
|
||||||
|
index 82f8fbfa..1ba97216 100644
|
||||||
|
--- a/pcs/lib/resource_agent/xml.py
|
||||||
|
+++ b/pcs/lib/resource_agent/xml.py
|
||||||
|
@@ -8,7 +8,7 @@ from pcs.common.tools import xml_fromstring
|
||||||
|
from pcs.lib.external import CommandRunner
|
||||||
|
|
||||||
|
from . import const
|
||||||
|
-from .error import UnableToGetAgentMetadata, UnsupportedOcfVersion
|
||||||
|
+from .error import UnableToGetAgentMetadata
|
||||||
|
from .types import (
|
||||||
|
FakeAgentName,
|
||||||
|
ResourceAgentActionOcf1_0,
|
||||||
|
@@ -137,8 +137,11 @@ def load_fake_agent_metadata(
|
||||||
|
|
||||||
|
|
||||||
|
def parse_metadata(
|
||||||
|
- name: ResourceAgentName, metadata: _Element
|
||||||
|
-) -> Union[ResourceAgentMetadataOcf1_0, ResourceAgentMetadataOcf1_1]:
|
||||||
|
+ name: ResourceAgentName,
|
||||||
|
+ metadata: _Element,
|
||||||
|
+) -> Tuple[
|
||||||
|
+ Union[ResourceAgentMetadataOcf1_0, ResourceAgentMetadataOcf1_1], str
|
||||||
|
+]:
|
||||||
|
"""
|
||||||
|
Parse XML metadata to a dataclass
|
||||||
|
|
||||||
|
@@ -146,11 +149,9 @@ def parse_metadata(
|
||||||
|
metadata -- metadata XML document
|
||||||
|
"""
|
||||||
|
ocf_version = _get_ocf_version(metadata)
|
||||||
|
- if ocf_version == const.OCF_1_0:
|
||||||
|
- return _parse_agent_1_0(name, metadata)
|
||||||
|
if ocf_version == const.OCF_1_1:
|
||||||
|
- return _parse_agent_1_1(name, metadata)
|
||||||
|
- raise UnsupportedOcfVersion(name.full_name, ocf_version)
|
||||||
|
+ return _parse_agent_1_1(name, metadata), ocf_version
|
||||||
|
+ return _parse_agent_1_0(name, metadata), ocf_version
|
||||||
|
|
||||||
|
|
||||||
|
def _parse_agent_1_0(
|
||||||
|
diff --git a/pcs_test/tier0/common/reports/test_messages.py b/pcs_test/tier0/common/reports/test_messages.py
|
||||||
|
index 4a7b4945..b885a9eb 100644
|
||||||
|
--- a/pcs_test/tier0/common/reports/test_messages.py
|
||||||
|
+++ b/pcs_test/tier0/common/reports/test_messages.py
|
||||||
|
@@ -2833,22 +2833,22 @@ class AgentNameGuessFoundNone(NameBuildTest):
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
-class AgentImplementsUnsupportedOcfVersion(NameBuildTest):
|
||||||
|
+class AgentImplementsUnsupportedOcfVersionAssumedVersion(NameBuildTest):
|
||||||
|
def test_singular(self):
|
||||||
|
self.assert_message_from_report(
|
||||||
|
- "Unable to process agent 'agent-name' as it implements unsupported "
|
||||||
|
- "OCF version 'ocf-2.3', supported version is: 'v1'",
|
||||||
|
- reports.AgentImplementsUnsupportedOcfVersion(
|
||||||
|
- "agent-name", "ocf-2.3", ["v1"]
|
||||||
|
+ "Agent 'agent-name' implements unsupported OCF version 'ocf-2.3', "
|
||||||
|
+ "supported version is: 'v1'; assumed version 'v1'",
|
||||||
|
+ reports.AgentImplementsUnsupportedOcfVersionAssumedVersion(
|
||||||
|
+ "agent-name", "ocf-2.3", ["v1"], "v1"
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_plural(self):
|
||||||
|
self.assert_message_from_report(
|
||||||
|
- "Unable to process agent 'agent-name' as it implements unsupported "
|
||||||
|
- "OCF version 'ocf-2.3', supported versions are: 'v1', 'v2', 'v3'",
|
||||||
|
- reports.AgentImplementsUnsupportedOcfVersion(
|
||||||
|
- "agent-name", "ocf-2.3", ["v1", "v2", "v3"]
|
||||||
|
+ "Agent 'agent-name' implements unsupported OCF version 'ocf-2.3', "
|
||||||
|
+ "supported versions are: 'v1', 'v2', 'v3'; assumed version 'v1'",
|
||||||
|
+ reports.AgentImplementsUnsupportedOcfVersionAssumedVersion(
|
||||||
|
+ "agent-name", "ocf-2.3", ["v1", "v2", "v3"], "v1"
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
diff --git a/pcs_test/tier0/lib/resource_agent/test_facade.py b/pcs_test/tier0/lib/resource_agent/test_facade.py
|
||||||
|
index 654eb35e..f6a9899c 100644
|
||||||
|
--- a/pcs_test/tier0/lib/resource_agent/test_facade.py
|
||||||
|
+++ b/pcs_test/tier0/lib/resource_agent/test_facade.py
|
||||||
|
@@ -92,6 +92,14 @@ class ResourceAgentFacadeFactory(TestCase):
|
||||||
|
</parameters>
|
||||||
|
</resource-agent>
|
||||||
|
"""
|
||||||
|
+ _fixture_agent_bad_version_xml = """
|
||||||
|
+ <resource-agent name="agent">
|
||||||
|
+ <version>0.1.2</version>
|
||||||
|
+ <parameters>
|
||||||
|
+ <parameter name="agent-param"/>
|
||||||
|
+ </parameters>
|
||||||
|
+ </resource-agent>
|
||||||
|
+ """
|
||||||
|
_fixture_fenced_xml = """
|
||||||
|
<resource-agent name="pacemaker-fenced">
|
||||||
|
<parameters>
|
||||||
|
@@ -125,6 +133,45 @@ class ResourceAgentFacadeFactory(TestCase):
|
||||||
|
self.assertEqual(facade.metadata.name, name)
|
||||||
|
self.assertTrue(facade.metadata.agent_exists)
|
||||||
|
|
||||||
|
+ def test_facade_bad_ocf_version(self):
|
||||||
|
+ name = ra.ResourceAgentName("service", None, "daemon")
|
||||||
|
+ self.config.runner.pcmk.load_agent(
|
||||||
|
+ agent_name="service:daemon",
|
||||||
|
+ stdout=self._fixture_agent_bad_version_xml,
|
||||||
|
+ )
|
||||||
|
+
|
||||||
|
+ env = self.env_assist.get_env()
|
||||||
|
+ facade = ra.ResourceAgentFacadeFactory(
|
||||||
|
+ env.cmd_runner(), env.report_processor
|
||||||
|
+ ).facade_from_parsed_name(name)
|
||||||
|
+ self.assertEqual(facade.metadata.name, name)
|
||||||
|
+ self.assertTrue(facade.metadata.agent_exists)
|
||||||
|
+ self.env_assist.assert_reports(
|
||||||
|
+ [
|
||||||
|
+ fixture.warn(
|
||||||
|
+ reports.codes.AGENT_IMPLEMENTS_UNSUPPORTED_OCF_VERSION_ASSUMED_VERSION,
|
||||||
|
+ agent=name.full_name,
|
||||||
|
+ ocf_version="0.1.2",
|
||||||
|
+ supported_versions=sorted(ra.const.SUPPORTED_OCF_VERSIONS),
|
||||||
|
+ assumed_version=ra.const.OCF_1_0,
|
||||||
|
+ )
|
||||||
|
+ ]
|
||||||
|
+ )
|
||||||
|
+
|
||||||
|
+ def test_facade_bad_ocf_version_disabled_warning(self):
|
||||||
|
+ name = ra.ResourceAgentName("service", None, "daemon")
|
||||||
|
+ self.config.runner.pcmk.load_agent(
|
||||||
|
+ agent_name="service:daemon",
|
||||||
|
+ stdout=self._fixture_agent_bad_version_xml,
|
||||||
|
+ )
|
||||||
|
+
|
||||||
|
+ env = self.env_assist.get_env()
|
||||||
|
+ facade = ra.ResourceAgentFacadeFactory(
|
||||||
|
+ env.cmd_runner(), env.report_processor
|
||||||
|
+ ).facade_from_parsed_name(name, report_warnings=False)
|
||||||
|
+ self.assertEqual(facade.metadata.name, name)
|
||||||
|
+ self.assertTrue(facade.metadata.agent_exists)
|
||||||
|
+
|
||||||
|
def test_facade_missing_agent(self):
|
||||||
|
name = ra.ResourceAgentName("service", None, "daemon")
|
||||||
|
self.config.runner.pcmk.load_agent(
|
||||||
|
diff --git a/pcs_test/tier0/lib/resource_agent/test_xml.py b/pcs_test/tier0/lib/resource_agent/test_xml.py
|
||||||
|
index c4176f32..26bbbb7d 100644
|
||||||
|
--- a/pcs_test/tier0/lib/resource_agent/test_xml.py
|
||||||
|
+++ b/pcs_test/tier0/lib/resource_agent/test_xml.py
|
||||||
|
@@ -351,6 +351,7 @@ class LoadFakeAgentMetadata(TestCase):
|
||||||
|
class ParseOcfToolsMixin:
|
||||||
|
agent_name = ra.ResourceAgentName("ocf", "pacemaker", "Dummy")
|
||||||
|
ocf_version = None
|
||||||
|
+ parsed_ocf_version = None
|
||||||
|
|
||||||
|
def parse(self, xml, agent_name=None):
|
||||||
|
agent_name = agent_name or self.agent_name
|
||||||
|
@@ -383,19 +384,17 @@ class ParseOcfToolsMixin:
|
||||||
|
version_el.text = ocf_version
|
||||||
|
return etree_to_str(dom)
|
||||||
|
|
||||||
|
-
|
||||||
|
-class ParseOcfGeneric(ParseOcfToolsMixin, TestCase):
|
||||||
|
- def test_unsupported_ocf_version(self):
|
||||||
|
- with self.assertRaises(ra.UnsupportedOcfVersion) as cm:
|
||||||
|
- self.parse(self.xml("""<resource-agent/>""", ocf_version="1.2"))
|
||||||
|
- self.assertEqual(cm.exception.agent_name, self.agent_name.full_name)
|
||||||
|
- self.assertEqual(cm.exception.ocf_version, "1.2")
|
||||||
|
+ def assert_parse_result(self, xml, metadata):
|
||||||
|
+ self.assertEqual(
|
||||||
|
+ self.parse(xml),
|
||||||
|
+ (metadata, self.parsed_ocf_version or self.ocf_version),
|
||||||
|
+ )
|
||||||
|
|
||||||
|
|
||||||
|
class ParseOcf10BaseMixin(ParseOcfToolsMixin):
|
||||||
|
def test_empty_agent(self):
|
||||||
|
- self.assertEqual(
|
||||||
|
- self.parse(self.xml("""<resource-agent/>""")),
|
||||||
|
+ self.assert_parse_result(
|
||||||
|
+ self.xml("""<resource-agent/>"""),
|
||||||
|
ResourceAgentMetadataOcf1_0(
|
||||||
|
self.agent_name,
|
||||||
|
shortdesc=None,
|
||||||
|
@@ -406,16 +405,14 @@ class ParseOcf10BaseMixin(ParseOcfToolsMixin):
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_desc_element(self):
|
||||||
|
- self.assertEqual(
|
||||||
|
- self.parse(
|
||||||
|
- self.xml(
|
||||||
|
- """
|
||||||
|
+ self.assert_parse_result(
|
||||||
|
+ self.xml(
|
||||||
|
+ """
|
||||||
|
<resource-agent>
|
||||||
|
<shortdesc>This is a shortdesc</shortdesc>
|
||||||
|
<longdesc>This is a longdesc</longdesc>
|
||||||
|
</resource-agent>
|
||||||
|
"""
|
||||||
|
- )
|
||||||
|
),
|
||||||
|
ResourceAgentMetadataOcf1_0(
|
||||||
|
self.agent_name,
|
||||||
|
@@ -427,16 +424,14 @@ class ParseOcf10BaseMixin(ParseOcfToolsMixin):
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_desc_element_empty(self):
|
||||||
|
- self.assertEqual(
|
||||||
|
- self.parse(
|
||||||
|
- self.xml(
|
||||||
|
- """
|
||||||
|
+ self.assert_parse_result(
|
||||||
|
+ self.xml(
|
||||||
|
+ """
|
||||||
|
<resource-agent>
|
||||||
|
<longdesc/>
|
||||||
|
<shortdesc/>
|
||||||
|
</resource-agent>
|
||||||
|
"""
|
||||||
|
- )
|
||||||
|
),
|
||||||
|
ResourceAgentMetadataOcf1_0(
|
||||||
|
self.agent_name,
|
||||||
|
@@ -448,15 +443,13 @@ class ParseOcf10BaseMixin(ParseOcfToolsMixin):
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_desc_attribute(self):
|
||||||
|
- self.assertEqual(
|
||||||
|
- self.parse(
|
||||||
|
- self.xml(
|
||||||
|
- """
|
||||||
|
+ self.assert_parse_result(
|
||||||
|
+ self.xml(
|
||||||
|
+ """
|
||||||
|
<resource-agent shortdesc="This is a shortdesc">
|
||||||
|
<longdesc></longdesc>
|
||||||
|
</resource-agent>
|
||||||
|
"""
|
||||||
|
- )
|
||||||
|
),
|
||||||
|
ResourceAgentMetadataOcf1_0(
|
||||||
|
self.agent_name,
|
||||||
|
@@ -468,13 +461,11 @@ class ParseOcf10BaseMixin(ParseOcfToolsMixin):
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_desc_attribute_empty(self):
|
||||||
|
- self.assertEqual(
|
||||||
|
- self.parse(
|
||||||
|
- self.xml(
|
||||||
|
- """
|
||||||
|
+ self.assert_parse_result(
|
||||||
|
+ self.xml(
|
||||||
|
+ """
|
||||||
|
<resource-agent shortdesc=""/>
|
||||||
|
"""
|
||||||
|
- )
|
||||||
|
),
|
||||||
|
ResourceAgentMetadataOcf1_0(
|
||||||
|
self.agent_name,
|
||||||
|
@@ -486,15 +477,13 @@ class ParseOcf10BaseMixin(ParseOcfToolsMixin):
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_desc_element_and_attribute(self):
|
||||||
|
- self.assertEqual(
|
||||||
|
- self.parse(
|
||||||
|
- self.xml(
|
||||||
|
- """
|
||||||
|
+ self.assert_parse_result(
|
||||||
|
+ self.xml(
|
||||||
|
+ """
|
||||||
|
<resource-agent shortdesc="shortdesc attribute">
|
||||||
|
<shortdesc>shortdesc element</shortdesc>
|
||||||
|
</resource-agent>
|
||||||
|
"""
|
||||||
|
- )
|
||||||
|
),
|
||||||
|
ResourceAgentMetadataOcf1_0(
|
||||||
|
self.agent_name,
|
||||||
|
@@ -506,15 +495,13 @@ class ParseOcf10BaseMixin(ParseOcfToolsMixin):
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_desc_element_empty_and_attribute(self):
|
||||||
|
- self.assertEqual(
|
||||||
|
- self.parse(
|
||||||
|
- self.xml(
|
||||||
|
- """
|
||||||
|
+ self.assert_parse_result(
|
||||||
|
+ self.xml(
|
||||||
|
+ """
|
||||||
|
<resource-agent shortdesc="shortdesc attribute">
|
||||||
|
<shortdesc></shortdesc>
|
||||||
|
</resource-agent>
|
||||||
|
"""
|
||||||
|
- )
|
||||||
|
),
|
||||||
|
ResourceAgentMetadataOcf1_0(
|
||||||
|
self.agent_name,
|
||||||
|
@@ -526,15 +513,13 @@ class ParseOcf10BaseMixin(ParseOcfToolsMixin):
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_desc_element_empty_and_attribute_empty(self):
|
||||||
|
- self.assertEqual(
|
||||||
|
- self.parse(
|
||||||
|
- self.xml(
|
||||||
|
- """
|
||||||
|
+ self.assert_parse_result(
|
||||||
|
+ self.xml(
|
||||||
|
+ """
|
||||||
|
<resource-agent shortdesc="">
|
||||||
|
<shortdesc></shortdesc>
|
||||||
|
</resource-agent>
|
||||||
|
"""
|
||||||
|
- )
|
||||||
|
),
|
||||||
|
ResourceAgentMetadataOcf1_0(
|
||||||
|
self.agent_name,
|
||||||
|
@@ -546,15 +531,13 @@ class ParseOcf10BaseMixin(ParseOcfToolsMixin):
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_parameters_empty_list(self):
|
||||||
|
- self.assertEqual(
|
||||||
|
- self.parse(
|
||||||
|
- self.xml(
|
||||||
|
- """
|
||||||
|
+ self.assert_parse_result(
|
||||||
|
+ self.xml(
|
||||||
|
+ """
|
||||||
|
<resource-agent>
|
||||||
|
<parameters/>
|
||||||
|
</resource-agent>
|
||||||
|
"""
|
||||||
|
- )
|
||||||
|
),
|
||||||
|
ResourceAgentMetadataOcf1_0(
|
||||||
|
self.agent_name,
|
||||||
|
@@ -581,17 +564,15 @@ class ParseOcf10BaseMixin(ParseOcfToolsMixin):
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_parameters_minimal(self):
|
||||||
|
- self.assertEqual(
|
||||||
|
- self.parse(
|
||||||
|
- self.xml(
|
||||||
|
- """
|
||||||
|
+ self.assert_parse_result(
|
||||||
|
+ self.xml(
|
||||||
|
+ """
|
||||||
|
<resource-agent>
|
||||||
|
<parameters>
|
||||||
|
<parameter name="a_parameter"/>
|
||||||
|
</parameters>
|
||||||
|
</resource-agent>
|
||||||
|
"""
|
||||||
|
- )
|
||||||
|
),
|
||||||
|
ResourceAgentMetadataOcf1_0(
|
||||||
|
self.agent_name,
|
||||||
|
@@ -616,10 +597,9 @@ class ParseOcf10BaseMixin(ParseOcfToolsMixin):
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_parameters_all_settings(self):
|
||||||
|
- self.assertEqual(
|
||||||
|
- self.parse(
|
||||||
|
- self.xml(
|
||||||
|
- """
|
||||||
|
+ self.assert_parse_result(
|
||||||
|
+ self.xml(
|
||||||
|
+ """
|
||||||
|
<resource-agent>
|
||||||
|
<parameters>
|
||||||
|
<parameter name="a_parameter" required="1"
|
||||||
|
@@ -632,7 +612,6 @@ class ParseOcf10BaseMixin(ParseOcfToolsMixin):
|
||||||
|
</parameters>
|
||||||
|
</resource-agent>
|
||||||
|
"""
|
||||||
|
- )
|
||||||
|
),
|
||||||
|
ResourceAgentMetadataOcf1_0(
|
||||||
|
self.agent_name,
|
||||||
|
@@ -657,10 +636,9 @@ class ParseOcf10BaseMixin(ParseOcfToolsMixin):
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_parameters_content(self):
|
||||||
|
- self.assertEqual(
|
||||||
|
- self.parse(
|
||||||
|
- self.xml(
|
||||||
|
- """
|
||||||
|
+ self.assert_parse_result(
|
||||||
|
+ self.xml(
|
||||||
|
+ """
|
||||||
|
<resource-agent>
|
||||||
|
<parameters>
|
||||||
|
<parameter name="with_type">
|
||||||
|
@@ -676,7 +654,6 @@ class ParseOcf10BaseMixin(ParseOcfToolsMixin):
|
||||||
|
</parameters>
|
||||||
|
</resource-agent>
|
||||||
|
"""
|
||||||
|
- )
|
||||||
|
),
|
||||||
|
ResourceAgentMetadataOcf1_0(
|
||||||
|
self.agent_name,
|
||||||
|
@@ -713,15 +690,13 @@ class ParseOcf10BaseMixin(ParseOcfToolsMixin):
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_actions_empty_list(self):
|
||||||
|
- self.assertEqual(
|
||||||
|
- self.parse(
|
||||||
|
- self.xml(
|
||||||
|
- """
|
||||||
|
+ self.assert_parse_result(
|
||||||
|
+ self.xml(
|
||||||
|
+ """
|
||||||
|
<resource-agent>
|
||||||
|
<actions/>
|
||||||
|
</resource-agent>
|
||||||
|
"""
|
||||||
|
- )
|
||||||
|
),
|
||||||
|
ResourceAgentMetadataOcf1_0(
|
||||||
|
self.agent_name,
|
||||||
|
@@ -748,10 +723,9 @@ class ParseOcf10BaseMixin(ParseOcfToolsMixin):
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_actions_multiple(self):
|
||||||
|
- self.assertEqual(
|
||||||
|
- self.parse(
|
||||||
|
- self.xml(
|
||||||
|
- """
|
||||||
|
+ self.assert_parse_result(
|
||||||
|
+ self.xml(
|
||||||
|
+ """
|
||||||
|
<resource-agent>
|
||||||
|
<actions>
|
||||||
|
<action name="minimal"/>
|
||||||
|
@@ -764,7 +738,6 @@ class ParseOcf10BaseMixin(ParseOcfToolsMixin):
|
||||||
|
</actions>
|
||||||
|
</resource-agent>
|
||||||
|
"""
|
||||||
|
- )
|
||||||
|
),
|
||||||
|
ResourceAgentMetadataOcf1_0(
|
||||||
|
self.agent_name,
|
||||||
|
@@ -808,7 +781,26 @@ class ParseOcf10BaseMixin(ParseOcfToolsMixin):
|
||||||
|
|
||||||
|
|
||||||
|
class ParseOcf10NoVersion(ParseOcf10BaseMixin, TestCase):
|
||||||
|
- pass
|
||||||
|
+ parsed_ocf_version = "1.0"
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+class ParseOcf10UnsupportedVersion(ParseOcf10BaseMixin, TestCase):
|
||||||
|
+ ocf_version = "0.1.2"
|
||||||
|
+
|
||||||
|
+ # These tests test that pcs raises an error if an agent doesn't conform to
|
||||||
|
+ # OCF schema. There is, however, no validation against OCF schema for
|
||||||
|
+ # agents with unsupported OCF version. That means no error message, pcs
|
||||||
|
+ # tries to process the agent and crashes. However bad that sounds, it's
|
||||||
|
+ # indended as that's how pcs behaved before OCF 1.1 was implemented.
|
||||||
|
+ # There's therefore no point in running these tests.
|
||||||
|
+
|
||||||
|
+ def test_parameters_empty_parameter(self):
|
||||||
|
+ # parameters must have at least 'name' attribute
|
||||||
|
+ pass
|
||||||
|
+
|
||||||
|
+ def test_actions_empty_action(self):
|
||||||
|
+ # actions must have at least 'name' attribute
|
||||||
|
+ pass
|
||||||
|
|
||||||
|
|
||||||
|
class ParseOcf10ExplicitVersion(ParseOcf10BaseMixin, TestCase):
|
||||||
|
@@ -819,8 +811,8 @@ class ParseOcf11(ParseOcfToolsMixin, TestCase):
|
||||||
|
ocf_version = "1.1"
|
||||||
|
|
||||||
|
def test_empty_agent(self):
|
||||||
|
- self.assertEqual(
|
||||||
|
- self.parse(self.xml("""<resource-agent/>""")),
|
||||||
|
+ self.assert_parse_result(
|
||||||
|
+ self.xml("""<resource-agent/>"""),
|
||||||
|
ResourceAgentMetadataOcf1_1(
|
||||||
|
self.agent_name,
|
||||||
|
shortdesc=None,
|
||||||
|
@@ -831,16 +823,14 @@ class ParseOcf11(ParseOcfToolsMixin, TestCase):
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_desc_element(self):
|
||||||
|
- self.assertEqual(
|
||||||
|
- self.parse(
|
||||||
|
- self.xml(
|
||||||
|
- """
|
||||||
|
+ self.assert_parse_result(
|
||||||
|
+ self.xml(
|
||||||
|
+ """
|
||||||
|
<resource-agent>
|
||||||
|
<shortdesc>This is a shortdesc</shortdesc>
|
||||||
|
<longdesc>This is a longdesc</longdesc>
|
||||||
|
</resource-agent>
|
||||||
|
"""
|
||||||
|
- )
|
||||||
|
),
|
||||||
|
ResourceAgentMetadataOcf1_1(
|
||||||
|
self.agent_name,
|
||||||
|
@@ -852,16 +842,14 @@ class ParseOcf11(ParseOcfToolsMixin, TestCase):
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_desc_element_empty(self):
|
||||||
|
- self.assertEqual(
|
||||||
|
- self.parse(
|
||||||
|
- self.xml(
|
||||||
|
- """
|
||||||
|
+ self.assert_parse_result(
|
||||||
|
+ self.xml(
|
||||||
|
+ """
|
||||||
|
<resource-agent>
|
||||||
|
<longdesc/>
|
||||||
|
<shortdesc/>
|
||||||
|
</resource-agent>
|
||||||
|
"""
|
||||||
|
- )
|
||||||
|
),
|
||||||
|
ResourceAgentMetadataOcf1_1(
|
||||||
|
self.agent_name,
|
||||||
|
@@ -873,15 +861,13 @@ class ParseOcf11(ParseOcfToolsMixin, TestCase):
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_parameters_empty_list(self):
|
||||||
|
- self.assertEqual(
|
||||||
|
- self.parse(
|
||||||
|
- self.xml(
|
||||||
|
- """
|
||||||
|
+ self.assert_parse_result(
|
||||||
|
+ self.xml(
|
||||||
|
+ """
|
||||||
|
<resource-agent>
|
||||||
|
<parameters/>
|
||||||
|
</resource-agent>
|
||||||
|
"""
|
||||||
|
- )
|
||||||
|
),
|
||||||
|
ResourceAgentMetadataOcf1_1(
|
||||||
|
self.agent_name,
|
||||||
|
@@ -908,17 +894,15 @@ class ParseOcf11(ParseOcfToolsMixin, TestCase):
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_parameters_minimal(self):
|
||||||
|
- self.assertEqual(
|
||||||
|
- self.parse(
|
||||||
|
- self.xml(
|
||||||
|
- """
|
||||||
|
+ self.assert_parse_result(
|
||||||
|
+ self.xml(
|
||||||
|
+ """
|
||||||
|
<resource-agent>
|
||||||
|
<parameters>
|
||||||
|
<parameter name="a_parameter"/>
|
||||||
|
</parameters>
|
||||||
|
</resource-agent>
|
||||||
|
"""
|
||||||
|
- )
|
||||||
|
),
|
||||||
|
ResourceAgentMetadataOcf1_1(
|
||||||
|
self.agent_name,
|
||||||
|
@@ -945,10 +929,9 @@ class ParseOcf11(ParseOcfToolsMixin, TestCase):
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_parameters_deprecated_minimal(self):
|
||||||
|
- self.assertEqual(
|
||||||
|
- self.parse(
|
||||||
|
- self.xml(
|
||||||
|
- """
|
||||||
|
+ self.assert_parse_result(
|
||||||
|
+ self.xml(
|
||||||
|
+ """
|
||||||
|
<resource-agent>
|
||||||
|
<parameters>
|
||||||
|
<parameter name="a_parameter">
|
||||||
|
@@ -957,7 +940,6 @@ class ParseOcf11(ParseOcfToolsMixin, TestCase):
|
||||||
|
</parameters>
|
||||||
|
</resource-agent>
|
||||||
|
"""
|
||||||
|
- )
|
||||||
|
),
|
||||||
|
ResourceAgentMetadataOcf1_1(
|
||||||
|
self.agent_name,
|
||||||
|
@@ -984,10 +966,9 @@ class ParseOcf11(ParseOcfToolsMixin, TestCase):
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_parameters_deprecated_replaced_with(self):
|
||||||
|
- self.assertEqual(
|
||||||
|
- self.parse(
|
||||||
|
- self.xml(
|
||||||
|
- """
|
||||||
|
+ self.assert_parse_result(
|
||||||
|
+ self.xml(
|
||||||
|
+ """
|
||||||
|
<resource-agent>
|
||||||
|
<parameters>
|
||||||
|
<parameter name="a_parameter">
|
||||||
|
@@ -999,7 +980,6 @@ class ParseOcf11(ParseOcfToolsMixin, TestCase):
|
||||||
|
</parameters>
|
||||||
|
</resource-agent>
|
||||||
|
"""
|
||||||
|
- )
|
||||||
|
),
|
||||||
|
ResourceAgentMetadataOcf1_1(
|
||||||
|
self.agent_name,
|
||||||
|
@@ -1026,10 +1006,9 @@ class ParseOcf11(ParseOcfToolsMixin, TestCase):
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_parameters_all_settings(self):
|
||||||
|
- self.assertEqual(
|
||||||
|
- self.parse(
|
||||||
|
- self.xml(
|
||||||
|
- """
|
||||||
|
+ self.assert_parse_result(
|
||||||
|
+ self.xml(
|
||||||
|
+ """
|
||||||
|
<resource-agent>
|
||||||
|
<parameters>
|
||||||
|
<parameter name="a_parameter"
|
||||||
|
@@ -1048,7 +1027,6 @@ class ParseOcf11(ParseOcfToolsMixin, TestCase):
|
||||||
|
</parameters>
|
||||||
|
</resource-agent>
|
||||||
|
"""
|
||||||
|
- )
|
||||||
|
),
|
||||||
|
ResourceAgentMetadataOcf1_1(
|
||||||
|
self.agent_name,
|
||||||
|
@@ -1075,10 +1053,9 @@ class ParseOcf11(ParseOcfToolsMixin, TestCase):
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_parameters_content(self):
|
||||||
|
- self.assertEqual(
|
||||||
|
- self.parse(
|
||||||
|
- self.xml(
|
||||||
|
- """
|
||||||
|
+ self.assert_parse_result(
|
||||||
|
+ self.xml(
|
||||||
|
+ """
|
||||||
|
<resource-agent>
|
||||||
|
<parameters>
|
||||||
|
<parameter name="with_type">
|
||||||
|
@@ -1094,7 +1071,6 @@ class ParseOcf11(ParseOcfToolsMixin, TestCase):
|
||||||
|
</parameters>
|
||||||
|
</resource-agent>
|
||||||
|
"""
|
||||||
|
- )
|
||||||
|
),
|
||||||
|
ResourceAgentMetadataOcf1_1(
|
||||||
|
self.agent_name,
|
||||||
|
@@ -1135,15 +1111,13 @@ class ParseOcf11(ParseOcfToolsMixin, TestCase):
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_actions_empty_list(self):
|
||||||
|
- self.assertEqual(
|
||||||
|
- self.parse(
|
||||||
|
- self.xml(
|
||||||
|
- """
|
||||||
|
+ self.assert_parse_result(
|
||||||
|
+ self.xml(
|
||||||
|
+ """
|
||||||
|
<resource-agent>
|
||||||
|
<actions/>
|
||||||
|
</resource-agent>
|
||||||
|
"""
|
||||||
|
- )
|
||||||
|
),
|
||||||
|
ResourceAgentMetadataOcf1_1(
|
||||||
|
self.agent_name,
|
||||||
|
@@ -1170,10 +1144,9 @@ class ParseOcf11(ParseOcfToolsMixin, TestCase):
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_actions_multiple(self):
|
||||||
|
- self.assertEqual(
|
||||||
|
- self.parse(
|
||||||
|
- self.xml(
|
||||||
|
- """
|
||||||
|
+ self.assert_parse_result(
|
||||||
|
+ self.xml(
|
||||||
|
+ """
|
||||||
|
<resource-agent>
|
||||||
|
<actions>
|
||||||
|
<action name="minimal"/>
|
||||||
|
@@ -1186,7 +1159,6 @@ class ParseOcf11(ParseOcfToolsMixin, TestCase):
|
||||||
|
</actions>
|
||||||
|
</resource-agent>
|
||||||
|
"""
|
||||||
|
- )
|
||||||
|
),
|
||||||
|
ResourceAgentMetadataOcf1_1(
|
||||||
|
self.agent_name,
|
||||||
|
--
|
||||||
|
2.34.1
|
||||||
|
|
587
SOURCES/bz2050274-02-relax-OCF-1.0-parser.patch
Normal file
587
SOURCES/bz2050274-02-relax-OCF-1.0-parser.patch
Normal file
@ -0,0 +1,587 @@
|
|||||||
|
From 65b30a04a234449cb4aa65606d47bf1d673592a4 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Tomas Jelinek <tojeline@redhat.com>
|
||||||
|
Date: Wed, 9 Feb 2022 11:16:49 +0100
|
||||||
|
Subject: [PATCH 2/3] relax OCF 1.0 parser
|
||||||
|
|
||||||
|
---
|
||||||
|
pcs/lib/resource_agent/facade.py | 50 ++++--
|
||||||
|
pcs/lib/resource_agent/ocf_transform.py | 51 +++++-
|
||||||
|
pcs/lib/resource_agent/xml.py | 8 +-
|
||||||
|
.../tier0/lib/resource_agent/test_facade.py | 44 +++++
|
||||||
|
.../lib/resource_agent/test_ocf_transform.py | 48 +++++-
|
||||||
|
pcs_test/tier0/lib/resource_agent/test_xml.py | 155 ++++++++++--------
|
||||||
|
6 files changed, 256 insertions(+), 100 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/pcs/lib/resource_agent/facade.py b/pcs/lib/resource_agent/facade.py
|
||||||
|
index dea59a1a..8a65eb1c 100644
|
||||||
|
--- a/pcs/lib/resource_agent/facade.py
|
||||||
|
+++ b/pcs/lib/resource_agent/facade.py
|
||||||
|
@@ -2,12 +2,19 @@ from collections import defaultdict
|
||||||
|
from dataclasses import replace as dc_replace
|
||||||
|
from typing import Dict, Iterable, List, Optional, Set
|
||||||
|
|
||||||
|
+from lxml import etree
|
||||||
|
+
|
||||||
|
+from pcs import settings
|
||||||
|
from pcs.common import reports
|
||||||
|
from pcs.lib import validate
|
||||||
|
from pcs.lib.external import CommandRunner
|
||||||
|
|
||||||
|
from . import const
|
||||||
|
-from .error import ResourceAgentError, resource_agent_error_to_report_item
|
||||||
|
+from .error import (
|
||||||
|
+ ResourceAgentError,
|
||||||
|
+ resource_agent_error_to_report_item,
|
||||||
|
+ UnableToGetAgentMetadata,
|
||||||
|
+)
|
||||||
|
from .name import name_to_void_metadata
|
||||||
|
from .ocf_transform import ocf_version_to_ocf_unified
|
||||||
|
from .pcs_transform import get_additional_trace_parameters, ocf_unified_to_pcs
|
||||||
|
@@ -195,24 +202,33 @@ class ResourceAgentFacadeFactory:
|
||||||
|
|
||||||
|
name -- agent name to get a facade for
|
||||||
|
"""
|
||||||
|
- metadata, raw_ocf_version = parse_metadata(
|
||||||
|
- name,
|
||||||
|
- load_metadata(self._runner, name),
|
||||||
|
- )
|
||||||
|
- if (
|
||||||
|
- report_warnings
|
||||||
|
- and raw_ocf_version not in const.SUPPORTED_OCF_VERSIONS
|
||||||
|
- ):
|
||||||
|
- self._report_processor.report(
|
||||||
|
- reports.ReportItem.warning(
|
||||||
|
- reports.messages.AgentImplementsUnsupportedOcfVersionAssumedVersion(
|
||||||
|
- name.full_name,
|
||||||
|
- raw_ocf_version,
|
||||||
|
- sorted(const.SUPPORTED_OCF_VERSIONS),
|
||||||
|
- const.OCF_1_0,
|
||||||
|
+ dom_metadata = load_metadata(self._runner, name)
|
||||||
|
+ metadata, raw_ocf_version = parse_metadata(name, dom_metadata)
|
||||||
|
+ if report_warnings:
|
||||||
|
+ if raw_ocf_version not in const.SUPPORTED_OCF_VERSIONS:
|
||||||
|
+ self._report_processor.report(
|
||||||
|
+ reports.ReportItem.warning(
|
||||||
|
+ reports.messages.AgentImplementsUnsupportedOcfVersionAssumedVersion(
|
||||||
|
+ name.full_name,
|
||||||
|
+ raw_ocf_version,
|
||||||
|
+ sorted(const.SUPPORTED_OCF_VERSIONS),
|
||||||
|
+ const.OCF_1_0,
|
||||||
|
+ )
|
||||||
|
)
|
||||||
|
)
|
||||||
|
- )
|
||||||
|
+ if raw_ocf_version != const.OCF_1_1:
|
||||||
|
+ try:
|
||||||
|
+ etree.RelaxNG(
|
||||||
|
+ file=settings.path.ocf_1_0_schema
|
||||||
|
+ ).assertValid(dom_metadata)
|
||||||
|
+ except etree.DocumentInvalid as e:
|
||||||
|
+ self._report_processor.report(
|
||||||
|
+ resource_agent_error_to_report_item(
|
||||||
|
+ UnableToGetAgentMetadata(name.full_name, str(e)),
|
||||||
|
+ severity=reports.ReportItemSeverity.warning(),
|
||||||
|
+ is_stonith=name.is_stonith,
|
||||||
|
+ )
|
||||||
|
+ )
|
||||||
|
return self._facade_from_metadata(ocf_version_to_ocf_unified(metadata))
|
||||||
|
|
||||||
|
def void_facade_from_parsed_name(
|
||||||
|
diff --git a/pcs/lib/resource_agent/ocf_transform.py b/pcs/lib/resource_agent/ocf_transform.py
|
||||||
|
index e841b55e..7e6a14ad 100644
|
||||||
|
--- a/pcs/lib/resource_agent/ocf_transform.py
|
||||||
|
+++ b/pcs/lib/resource_agent/ocf_transform.py
|
||||||
|
@@ -67,20 +67,42 @@ def _ocf_1_1_to_ocf_unified(
|
||||||
|
longdesc=metadata.longdesc,
|
||||||
|
parameters=_ocf_1_1_parameter_list_to_ocf_unified(metadata.parameters),
|
||||||
|
# OCF 1.1 actions are the same as in OCF 1.0
|
||||||
|
- actions=_ocf_1_0_action_list_to_ocf_unified(metadata.actions),
|
||||||
|
+ actions=_ocf_1_1_action_list_to_ocf_unified(metadata.actions),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _ocf_1_0_action_list_to_ocf_unified(
|
||||||
|
- action_list: Iterable[
|
||||||
|
- Union[ResourceAgentActionOcf1_0, ResourceAgentActionOcf1_1]
|
||||||
|
- ],
|
||||||
|
+ action_list: Iterable[ResourceAgentActionOcf1_0],
|
||||||
|
) -> List[ResourceAgentAction]:
|
||||||
|
"""
|
||||||
|
Transform OCF 1.0 actions to a universal format
|
||||||
|
|
||||||
|
action_list -- actions according OCF 1.0
|
||||||
|
"""
|
||||||
|
+ return [
|
||||||
|
+ ResourceAgentAction(
|
||||||
|
+ name=action.name,
|
||||||
|
+ timeout=action.timeout,
|
||||||
|
+ interval=action.interval,
|
||||||
|
+ role=action.role,
|
||||||
|
+ start_delay=action.start_delay,
|
||||||
|
+ depth=action.depth,
|
||||||
|
+ automatic=_bool_value_legacy(action.automatic),
|
||||||
|
+ on_target=_bool_value_legacy(action.on_target),
|
||||||
|
+ )
|
||||||
|
+ for action in action_list
|
||||||
|
+ if action.name
|
||||||
|
+ ]
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+def _ocf_1_1_action_list_to_ocf_unified(
|
||||||
|
+ action_list: Iterable[ResourceAgentActionOcf1_1],
|
||||||
|
+) -> List[ResourceAgentAction]:
|
||||||
|
+ """
|
||||||
|
+ Transform OCF 1.1 actions to a universal format
|
||||||
|
+
|
||||||
|
+ action_list -- actions according OCF 1.1
|
||||||
|
+ """
|
||||||
|
return [
|
||||||
|
ResourceAgentAction(
|
||||||
|
name=action.name,
|
||||||
|
@@ -111,6 +133,8 @@ def _ocf_1_0_parameter_list_to_ocf_unified(
|
||||||
|
|
||||||
|
result = []
|
||||||
|
for parameter in parameter_list:
|
||||||
|
+ if not parameter.name:
|
||||||
|
+ continue
|
||||||
|
result.append(
|
||||||
|
ResourceAgentParameter(
|
||||||
|
name=parameter.name,
|
||||||
|
@@ -119,17 +143,17 @@ def _ocf_1_0_parameter_list_to_ocf_unified(
|
||||||
|
type=parameter.type,
|
||||||
|
default=parameter.default,
|
||||||
|
enum_values=parameter.enum_values,
|
||||||
|
- required=_bool_value(parameter.required),
|
||||||
|
+ required=_bool_value_legacy(parameter.required),
|
||||||
|
advanced=False,
|
||||||
|
- deprecated=_bool_value(parameter.deprecated),
|
||||||
|
+ deprecated=_bool_value_legacy(parameter.deprecated),
|
||||||
|
deprecated_by=sorted(deprecated_by_dict[parameter.name]),
|
||||||
|
deprecated_desc=None,
|
||||||
|
unique_group=(
|
||||||
|
f"{const.DEFAULT_UNIQUE_GROUP_PREFIX}{parameter.name}"
|
||||||
|
- if _bool_value(parameter.unique)
|
||||||
|
+ if _bool_value_legacy(parameter.unique)
|
||||||
|
else None
|
||||||
|
),
|
||||||
|
- reloadable=_bool_value(parameter.unique),
|
||||||
|
+ reloadable=_bool_value_legacy(parameter.unique),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return result
|
||||||
|
@@ -170,3 +194,14 @@ def _bool_value(value: Optional[str]) -> bool:
|
||||||
|
value -- raw bool value
|
||||||
|
"""
|
||||||
|
return value == "1"
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+def _bool_value_legacy(value: Optional[str]) -> bool:
|
||||||
|
+ """
|
||||||
|
+ Transform raw bool value from metadata to bool type in backward compatible way
|
||||||
|
+
|
||||||
|
+ value -- raw bool value
|
||||||
|
+ """
|
||||||
|
+ return (
|
||||||
|
+ False if not value else value.lower() in {"true", "on", "yes", "y", "1"}
|
||||||
|
+ )
|
||||||
|
diff --git a/pcs/lib/resource_agent/xml.py b/pcs/lib/resource_agent/xml.py
|
||||||
|
index 1ba97216..0fc70527 100644
|
||||||
|
--- a/pcs/lib/resource_agent/xml.py
|
||||||
|
+++ b/pcs/lib/resource_agent/xml.py
|
||||||
|
@@ -94,9 +94,7 @@ def _metadata_xml_to_dom(metadata: str) -> _Element:
|
||||||
|
"""
|
||||||
|
dom = xml_fromstring(metadata)
|
||||||
|
ocf_version = _get_ocf_version(dom)
|
||||||
|
- if ocf_version == const.OCF_1_0:
|
||||||
|
- etree.RelaxNG(file=settings.path.ocf_1_0_schema).assertValid(dom)
|
||||||
|
- elif ocf_version == const.OCF_1_1:
|
||||||
|
+ if ocf_version == const.OCF_1_1:
|
||||||
|
etree.RelaxNG(file=settings.path.ocf_1_1_schema).assertValid(dom)
|
||||||
|
return dom
|
||||||
|
|
||||||
|
@@ -230,7 +228,7 @@ def _parse_parameters_1_0(
|
||||||
|
)
|
||||||
|
result.append(
|
||||||
|
ResourceAgentParameterOcf1_0(
|
||||||
|
- name=str(parameter_el.attrib["name"]),
|
||||||
|
+ name=str(parameter_el.get("name", "")),
|
||||||
|
shortdesc=_get_shortdesc(parameter_el),
|
||||||
|
longdesc=_get_longdesc(parameter_el),
|
||||||
|
type=value_type,
|
||||||
|
@@ -286,7 +284,7 @@ def _parse_parameters_1_1(
|
||||||
|
def _parse_actions_1_0(element: _Element) -> List[ResourceAgentActionOcf1_0]:
|
||||||
|
return [
|
||||||
|
ResourceAgentActionOcf1_0(
|
||||||
|
- name=str(action.attrib["name"]),
|
||||||
|
+ name=str(action.get("name", "")),
|
||||||
|
timeout=action.get("timeout"),
|
||||||
|
interval=action.get("interval"),
|
||||||
|
role=action.get("role"),
|
||||||
|
diff --git a/pcs_test/tier0/lib/resource_agent/test_facade.py b/pcs_test/tier0/lib/resource_agent/test_facade.py
|
||||||
|
index f6a9899c..313dfa2b 100644
|
||||||
|
--- a/pcs_test/tier0/lib/resource_agent/test_facade.py
|
||||||
|
+++ b/pcs_test/tier0/lib/resource_agent/test_facade.py
|
||||||
|
@@ -100,6 +100,13 @@ class ResourceAgentFacadeFactory(TestCase):
|
||||||
|
</parameters>
|
||||||
|
</resource-agent>
|
||||||
|
"""
|
||||||
|
+ _fixture_agent_not_valid_xml = """
|
||||||
|
+ <resource-agent name="agent">
|
||||||
|
+ <parameters>
|
||||||
|
+ <parameter label="something wrong"/>
|
||||||
|
+ </parameters>
|
||||||
|
+ </resource-agent>
|
||||||
|
+ """
|
||||||
|
_fixture_fenced_xml = """
|
||||||
|
<resource-agent name="pacemaker-fenced">
|
||||||
|
<parameters>
|
||||||
|
@@ -172,6 +179,43 @@ class ResourceAgentFacadeFactory(TestCase):
|
||||||
|
self.assertEqual(facade.metadata.name, name)
|
||||||
|
self.assertTrue(facade.metadata.agent_exists)
|
||||||
|
|
||||||
|
+ def test_facade_ocf_1_0_not_valid(self):
|
||||||
|
+ name = ra.ResourceAgentName("service", None, "daemon")
|
||||||
|
+ self.config.runner.pcmk.load_agent(
|
||||||
|
+ agent_name="service:daemon",
|
||||||
|
+ stdout=self._fixture_agent_not_valid_xml,
|
||||||
|
+ )
|
||||||
|
+
|
||||||
|
+ env = self.env_assist.get_env()
|
||||||
|
+ facade = ra.ResourceAgentFacadeFactory(
|
||||||
|
+ env.cmd_runner(), env.report_processor
|
||||||
|
+ ).facade_from_parsed_name(name)
|
||||||
|
+ self.assertEqual(facade.metadata.name, name)
|
||||||
|
+ self.assertTrue(facade.metadata.agent_exists)
|
||||||
|
+ self.env_assist.assert_reports(
|
||||||
|
+ [
|
||||||
|
+ fixture.warn(
|
||||||
|
+ reports.codes.UNABLE_TO_GET_AGENT_METADATA,
|
||||||
|
+ agent=name.full_name,
|
||||||
|
+ reason="Element parameter failed to validate attributes, line 3",
|
||||||
|
+ )
|
||||||
|
+ ]
|
||||||
|
+ )
|
||||||
|
+
|
||||||
|
+ def test_facade_ocf_1_0_not_valid_disabled_warning(self):
|
||||||
|
+ name = ra.ResourceAgentName("service", None, "daemon")
|
||||||
|
+ self.config.runner.pcmk.load_agent(
|
||||||
|
+ agent_name="service:daemon",
|
||||||
|
+ stdout=self._fixture_agent_not_valid_xml,
|
||||||
|
+ )
|
||||||
|
+
|
||||||
|
+ env = self.env_assist.get_env()
|
||||||
|
+ facade = ra.ResourceAgentFacadeFactory(
|
||||||
|
+ env.cmd_runner(), env.report_processor
|
||||||
|
+ ).facade_from_parsed_name(name, report_warnings=False)
|
||||||
|
+ self.assertEqual(facade.metadata.name, name)
|
||||||
|
+ self.assertTrue(facade.metadata.agent_exists)
|
||||||
|
+
|
||||||
|
def test_facade_missing_agent(self):
|
||||||
|
name = ra.ResourceAgentName("service", None, "daemon")
|
||||||
|
self.config.runner.pcmk.load_agent(
|
||||||
|
diff --git a/pcs_test/tier0/lib/resource_agent/test_ocf_transform.py b/pcs_test/tier0/lib/resource_agent/test_ocf_transform.py
|
||||||
|
index 9e41b6af..d0de86e5 100644
|
||||||
|
--- a/pcs_test/tier0/lib/resource_agent/test_ocf_transform.py
|
||||||
|
+++ b/pcs_test/tier0/lib/resource_agent/test_ocf_transform.py
|
||||||
|
@@ -66,6 +66,18 @@ class OcfVersionToOcfUnified(TestCase):
|
||||||
|
obsoletes=None,
|
||||||
|
unique=None,
|
||||||
|
),
|
||||||
|
+ ra.types.ResourceAgentParameterOcf1_0(
|
||||||
|
+ name="",
|
||||||
|
+ shortdesc="Parameters with no name are ignored",
|
||||||
|
+ longdesc=None,
|
||||||
|
+ type="string",
|
||||||
|
+ default=None,
|
||||||
|
+ enum_values=None,
|
||||||
|
+ required=None,
|
||||||
|
+ deprecated=None,
|
||||||
|
+ obsoletes=None,
|
||||||
|
+ unique=None,
|
||||||
|
+ ),
|
||||||
|
ra.types.ResourceAgentParameterOcf1_0(
|
||||||
|
name="param_2",
|
||||||
|
shortdesc="param_2 shortdesc",
|
||||||
|
@@ -109,10 +121,10 @@ class OcfVersionToOcfUnified(TestCase):
|
||||||
|
type="string",
|
||||||
|
default=None,
|
||||||
|
enum_values=None,
|
||||||
|
- required="1",
|
||||||
|
- deprecated="1",
|
||||||
|
+ required="yeS",
|
||||||
|
+ deprecated="True",
|
||||||
|
obsoletes="param_4",
|
||||||
|
- unique="1",
|
||||||
|
+ unique="on",
|
||||||
|
),
|
||||||
|
ra.types.ResourceAgentParameterOcf1_0(
|
||||||
|
name="param_6",
|
||||||
|
@@ -138,6 +150,16 @@ class OcfVersionToOcfUnified(TestCase):
|
||||||
|
automatic=None,
|
||||||
|
on_target=None,
|
||||||
|
),
|
||||||
|
+ ra.types.ResourceAgentActionOcf1_0(
|
||||||
|
+ name="",
|
||||||
|
+ timeout=None,
|
||||||
|
+ interval=None,
|
||||||
|
+ role=None,
|
||||||
|
+ start_delay=None,
|
||||||
|
+ depth=None,
|
||||||
|
+ automatic=None,
|
||||||
|
+ on_target=None,
|
||||||
|
+ ),
|
||||||
|
ra.types.ResourceAgentActionOcf1_0(
|
||||||
|
name="action_2",
|
||||||
|
timeout="12",
|
||||||
|
@@ -158,6 +180,16 @@ class OcfVersionToOcfUnified(TestCase):
|
||||||
|
automatic="1",
|
||||||
|
on_target="0",
|
||||||
|
),
|
||||||
|
+ ra.types.ResourceAgentActionOcf1_0(
|
||||||
|
+ name="action_4",
|
||||||
|
+ timeout=None,
|
||||||
|
+ interval=None,
|
||||||
|
+ role=None,
|
||||||
|
+ start_delay=None,
|
||||||
|
+ depth=None,
|
||||||
|
+ automatic="yes",
|
||||||
|
+ on_target="True",
|
||||||
|
+ ),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
metadata_out = ra.ResourceAgentMetadata(
|
||||||
|
@@ -289,6 +321,16 @@ class OcfVersionToOcfUnified(TestCase):
|
||||||
|
automatic=True,
|
||||||
|
on_target=False,
|
||||||
|
),
|
||||||
|
+ ra.ResourceAgentAction(
|
||||||
|
+ name="action_4",
|
||||||
|
+ timeout=None,
|
||||||
|
+ interval=None,
|
||||||
|
+ role=None,
|
||||||
|
+ start_delay=None,
|
||||||
|
+ depth=None,
|
||||||
|
+ automatic=True,
|
||||||
|
+ on_target=True,
|
||||||
|
+ ),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
diff --git a/pcs_test/tier0/lib/resource_agent/test_xml.py b/pcs_test/tier0/lib/resource_agent/test_xml.py
|
||||||
|
index 26bbbb7d..ea055ee2 100644
|
||||||
|
--- a/pcs_test/tier0/lib/resource_agent/test_xml.py
|
||||||
|
+++ b/pcs_test/tier0/lib/resource_agent/test_xml.py
|
||||||
|
@@ -164,8 +164,13 @@ class MetadataXmlToDom(TestCase):
|
||||||
|
ra.xml._metadata_xml_to_dom("not an xml")
|
||||||
|
|
||||||
|
def test_no_version_not_valid(self):
|
||||||
|
- with self.assertRaises(etree.DocumentInvalid):
|
||||||
|
- ra.xml._metadata_xml_to_dom("<resource-agent/>")
|
||||||
|
+ # pylint: disable=no-self-use
|
||||||
|
+ metadata = """
|
||||||
|
+ <resource-agent/>
|
||||||
|
+ """
|
||||||
|
+ assert_xml_equal(
|
||||||
|
+ metadata, etree_to_str(ra.xml._metadata_xml_to_dom(metadata))
|
||||||
|
+ )
|
||||||
|
|
||||||
|
def test_no_version_valid(self):
|
||||||
|
# pylint: disable=no-self-use
|
||||||
|
@@ -178,14 +183,15 @@ class MetadataXmlToDom(TestCase):
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_ocf_1_0_not_valid(self):
|
||||||
|
- with self.assertRaises(etree.DocumentInvalid):
|
||||||
|
- ra.xml._metadata_xml_to_dom(
|
||||||
|
- """
|
||||||
|
- <resource-agent>
|
||||||
|
- <version>1.0</version>
|
||||||
|
- </resource-agent>
|
||||||
|
- """
|
||||||
|
- )
|
||||||
|
+ # pylint: disable=no-self-use
|
||||||
|
+ metadata = """
|
||||||
|
+ <resource-agent>
|
||||||
|
+ <version>1.0</version>
|
||||||
|
+ </resource-agent>
|
||||||
|
+ """
|
||||||
|
+ assert_xml_equal(
|
||||||
|
+ metadata, etree_to_str(ra.xml._metadata_xml_to_dom(metadata))
|
||||||
|
+ )
|
||||||
|
|
||||||
|
def test_ocf_1_0_valid(self):
|
||||||
|
# pylint: disable=no-self-use
|
||||||
|
@@ -273,19 +279,16 @@ class LoadMetadata(TestCase):
|
||||||
|
|
||||||
|
def test_not_valid_xml(self):
|
||||||
|
agent_name = ra.ResourceAgentName("ocf", "pacemaker", "Dummy")
|
||||||
|
+ metadata = "<resource-agent/>"
|
||||||
|
self.config.runner.pcmk.load_agent(
|
||||||
|
agent_name="ocf:pacemaker:Dummy",
|
||||||
|
- stdout="<resource-agent/>",
|
||||||
|
+ stdout=metadata,
|
||||||
|
)
|
||||||
|
|
||||||
|
env = self.env_assist.get_env()
|
||||||
|
- with self.assertRaises(ra.UnableToGetAgentMetadata) as cm:
|
||||||
|
- ra.xml.load_metadata(env.cmd_runner(), agent_name)
|
||||||
|
- self.assertEqual(cm.exception.agent_name, "ocf:pacemaker:Dummy")
|
||||||
|
- self.assertTrue(
|
||||||
|
- cm.exception.message.startswith(
|
||||||
|
- "Element resource-agent failed to validate"
|
||||||
|
- )
|
||||||
|
+ assert_xml_equal(
|
||||||
|
+ metadata,
|
||||||
|
+ etree_to_str(ra.xml.load_metadata(env.cmd_runner(), agent_name)),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@@ -335,16 +338,15 @@ class LoadFakeAgentMetadata(TestCase):
|
||||||
|
|
||||||
|
def test_not_valid_xml(self):
|
||||||
|
agent_name = ra.const.PACEMAKER_FENCED
|
||||||
|
- self.config.runner.pcmk.load_fenced_metadata(stdout="<resource-agent/>")
|
||||||
|
+ metadata = "<resource-agent/>"
|
||||||
|
+ self.config.runner.pcmk.load_fenced_metadata(stdout=metadata)
|
||||||
|
|
||||||
|
env = self.env_assist.get_env()
|
||||||
|
- with self.assertRaises(ra.UnableToGetAgentMetadata) as cm:
|
||||||
|
- ra.xml.load_fake_agent_metadata(env.cmd_runner(), agent_name)
|
||||||
|
- self.assertEqual(cm.exception.agent_name, "pacemaker-fenced")
|
||||||
|
- self.assertTrue(
|
||||||
|
- cm.exception.message.startswith(
|
||||||
|
- "Element resource-agent failed to validate"
|
||||||
|
- )
|
||||||
|
+ assert_xml_equal(
|
||||||
|
+ metadata,
|
||||||
|
+ etree_to_str(
|
||||||
|
+ ra.xml.load_fake_agent_metadata(env.cmd_runner(), agent_name)
|
||||||
|
+ ),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@@ -549,19 +551,37 @@ class ParseOcf10BaseMixin(ParseOcfToolsMixin):
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_parameters_empty_parameter(self):
|
||||||
|
- # parameters must have at least 'name' attribute
|
||||||
|
- with self.assertRaises(ra.UnableToGetAgentMetadata):
|
||||||
|
- self.parse(
|
||||||
|
- self.xml(
|
||||||
|
- """
|
||||||
|
- <resource-agent>
|
||||||
|
- <parameters>
|
||||||
|
- <parameter/>
|
||||||
|
- </parameters>
|
||||||
|
- </resource-agent>
|
||||||
|
- """
|
||||||
|
- )
|
||||||
|
- )
|
||||||
|
+ self.assert_parse_result(
|
||||||
|
+ self.xml(
|
||||||
|
+ """
|
||||||
|
+ <resource-agent>
|
||||||
|
+ <parameters>
|
||||||
|
+ <parameter/>
|
||||||
|
+ </parameters>
|
||||||
|
+ </resource-agent>
|
||||||
|
+ """
|
||||||
|
+ ),
|
||||||
|
+ ResourceAgentMetadataOcf1_0(
|
||||||
|
+ self.agent_name,
|
||||||
|
+ shortdesc=None,
|
||||||
|
+ longdesc=None,
|
||||||
|
+ parameters=[
|
||||||
|
+ ResourceAgentParameterOcf1_0(
|
||||||
|
+ name="",
|
||||||
|
+ shortdesc=None,
|
||||||
|
+ longdesc=None,
|
||||||
|
+ type="string",
|
||||||
|
+ default=None,
|
||||||
|
+ enum_values=None,
|
||||||
|
+ required=None,
|
||||||
|
+ deprecated=None,
|
||||||
|
+ obsoletes=None,
|
||||||
|
+ unique=None,
|
||||||
|
+ )
|
||||||
|
+ ],
|
||||||
|
+ actions=[],
|
||||||
|
+ ),
|
||||||
|
+ )
|
||||||
|
|
||||||
|
def test_parameters_minimal(self):
|
||||||
|
self.assert_parse_result(
|
||||||
|
@@ -708,19 +728,35 @@ class ParseOcf10BaseMixin(ParseOcfToolsMixin):
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_actions_empty_action(self):
|
||||||
|
- # actions must have at least 'name' attribute
|
||||||
|
- with self.assertRaises(ra.UnableToGetAgentMetadata):
|
||||||
|
- self.parse(
|
||||||
|
- self.xml(
|
||||||
|
- """
|
||||||
|
- <resource-agent>
|
||||||
|
- <actions>
|
||||||
|
- <action/>
|
||||||
|
- </actions>
|
||||||
|
- </resource-agent>
|
||||||
|
- """
|
||||||
|
- )
|
||||||
|
- )
|
||||||
|
+ self.assert_parse_result(
|
||||||
|
+ self.xml(
|
||||||
|
+ """
|
||||||
|
+ <resource-agent>
|
||||||
|
+ <actions>
|
||||||
|
+ <action/>
|
||||||
|
+ </actions>
|
||||||
|
+ </resource-agent>
|
||||||
|
+ """
|
||||||
|
+ ),
|
||||||
|
+ ResourceAgentMetadataOcf1_0(
|
||||||
|
+ self.agent_name,
|
||||||
|
+ shortdesc=None,
|
||||||
|
+ longdesc=None,
|
||||||
|
+ parameters=[],
|
||||||
|
+ actions=[
|
||||||
|
+ ResourceAgentActionOcf1_0(
|
||||||
|
+ name="",
|
||||||
|
+ timeout=None,
|
||||||
|
+ interval=None,
|
||||||
|
+ role=None,
|
||||||
|
+ start_delay=None,
|
||||||
|
+ depth=None,
|
||||||
|
+ automatic=None,
|
||||||
|
+ on_target=None,
|
||||||
|
+ ),
|
||||||
|
+ ],
|
||||||
|
+ ),
|
||||||
|
+ )
|
||||||
|
|
||||||
|
def test_actions_multiple(self):
|
||||||
|
self.assert_parse_result(
|
||||||
|
@@ -787,21 +823,6 @@ class ParseOcf10NoVersion(ParseOcf10BaseMixin, TestCase):
|
||||||
|
class ParseOcf10UnsupportedVersion(ParseOcf10BaseMixin, TestCase):
|
||||||
|
ocf_version = "0.1.2"
|
||||||
|
|
||||||
|
- # These tests test that pcs raises an error if an agent doesn't conform to
|
||||||
|
- # OCF schema. There is, however, no validation against OCF schema for
|
||||||
|
- # agents with unsupported OCF version. That means no error message, pcs
|
||||||
|
- # tries to process the agent and crashes. However bad that sounds, it's
|
||||||
|
- # indended as that's how pcs behaved before OCF 1.1 was implemented.
|
||||||
|
- # There's therefore no point in running these tests.
|
||||||
|
-
|
||||||
|
- def test_parameters_empty_parameter(self):
|
||||||
|
- # parameters must have at least 'name' attribute
|
||||||
|
- pass
|
||||||
|
-
|
||||||
|
- def test_actions_empty_action(self):
|
||||||
|
- # actions must have at least 'name' attribute
|
||||||
|
- pass
|
||||||
|
-
|
||||||
|
|
||||||
|
class ParseOcf10ExplicitVersion(ParseOcf10BaseMixin, TestCase):
|
||||||
|
ocf_version = "1.0"
|
||||||
|
--
|
||||||
|
2.34.1
|
||||||
|
|
@ -1,7 +1,7 @@
|
|||||||
From 5ea2b99f6bd32b74e20ad2f83d131a735df1cd24 Mon Sep 17 00:00:00 2001
|
From f7230b92c946add84ed6072c20a4df5d97c77de2 Mon Sep 17 00:00:00 2001
|
||||||
From: Ivan Devat <idevat@redhat.com>
|
From: Ivan Devat <idevat@redhat.com>
|
||||||
Date: Tue, 20 Nov 2018 15:03:56 +0100
|
Date: Tue, 20 Nov 2018 15:03:56 +0100
|
||||||
Subject: [PATCH 2/2] do not support cluster setup with udp(u) transport
|
Subject: [PATCH 3/3] do not support cluster setup with udp(u) transport
|
||||||
|
|
||||||
---
|
---
|
||||||
pcs/pcs.8.in | 2 ++
|
pcs/pcs.8.in | 2 ++
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
Name: pcs
|
Name: pcs
|
||||||
Version: 0.10.12
|
Version: 0.10.12
|
||||||
Release: 5%{?dist}
|
Release: 6%{?dist}
|
||||||
# https://docs.fedoraproject.org/en-US/packaging-guidelines/LicensingGuidelines/
|
# https://docs.fedoraproject.org/en-US/packaging-guidelines/LicensingGuidelines/
|
||||||
# https://fedoraproject.org/wiki/Licensing:Main?rd=Licensing#Good_Licenses
|
# https://fedoraproject.org/wiki/Licensing:Main?rd=Licensing#Good_Licenses
|
||||||
# GPLv2: pcs
|
# GPLv2: pcs
|
||||||
@ -125,6 +125,8 @@ Patch4: bz2036633-01-Make-ocf-linbit-drbd-agent-pass-OCF-validation.patch
|
|||||||
Patch5: bz1990784-01-Multiple-fixes-of-pcs-resource-move-autodelete-comma.patch
|
Patch5: bz1990784-01-Multiple-fixes-of-pcs-resource-move-autodelete-comma.patch
|
||||||
Patch6: bz2022463-01-fix-creating-empty-cib.patch
|
Patch6: bz2022463-01-fix-creating-empty-cib.patch
|
||||||
Patch7: bz2047983-01-Fix-snmp-client.patch
|
Patch7: bz2047983-01-Fix-snmp-client.patch
|
||||||
|
Patch8: bz2050274-01-process-invalid-OCF-agents-the-same-way-as-before.patch
|
||||||
|
Patch9: bz2050274-02-relax-OCF-1.0-parser.patch
|
||||||
|
|
||||||
# Downstream patches do not come from upstream. They adapt pcs for specific
|
# Downstream patches do not come from upstream. They adapt pcs for specific
|
||||||
# RHEL needs.
|
# RHEL needs.
|
||||||
@ -334,6 +336,8 @@ update_times_patch %{PATCH4}
|
|||||||
update_times_patch %{PATCH5}
|
update_times_patch %{PATCH5}
|
||||||
update_times_patch %{PATCH6}
|
update_times_patch %{PATCH6}
|
||||||
update_times_patch %{PATCH7}
|
update_times_patch %{PATCH7}
|
||||||
|
update_times_patch %{PATCH8}
|
||||||
|
update_times_patch %{PATCH9}
|
||||||
update_times_patch %{PATCH101}
|
update_times_patch %{PATCH101}
|
||||||
|
|
||||||
cp -f %SOURCE1 %{pcsd_public_dir}/images
|
cp -f %SOURCE1 %{pcsd_public_dir}/images
|
||||||
@ -583,6 +587,10 @@ remove_all_tests
|
|||||||
%license pyagentx_LICENSE.txt
|
%license pyagentx_LICENSE.txt
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Fri Feb 11 2022 Miroslav Lisik <mlisik@redhat.com> - 0.10.12-6
|
||||||
|
- Fixed processing agents not conforming to OCF schema
|
||||||
|
- Resolves: rhbz#2050274
|
||||||
|
|
||||||
* Tue Feb 01 2022 Miroslav Lisik <mlisik@redhat.com> - 0.10.12-5
|
* Tue Feb 01 2022 Miroslav Lisik <mlisik@redhat.com> - 0.10.12-5
|
||||||
- Fixed snmp client
|
- Fixed snmp client
|
||||||
- Resolves: rhbz#2047983
|
- Resolves: rhbz#2047983
|
||||||
|
Loading…
Reference in New Issue
Block a user