Blame SOURCES/bz1315371-04-alerts-related-fixes.patch

15f218
From b438fe5c0eb4e6fa738e21287540c0d8f6b91c68 Mon Sep 17 00:00:00 2001
15f218
From: Ivan Devat <idevat@redhat.com>
15f218
Date: Fri, 19 Aug 2016 02:57:39 +0200
15f218
Subject: [PATCH] squash bz1315371 [RFE] Provide configurable alerts
15f218
15f218
25a25c534ff6 show help when unknown subcommand of 'pcs alert recipient' was given
15f218
15f218
c352ce184093 make syntax of command 'pcs alert recipient add' more consistent
15f218
15f218
8c6ec586d57c fix error handling when upgrading cib schema
15f218
---
15f218
 pcs/alert.py                   |  9 +++--
15f218
 pcs/lib/cib/tools.py           | 36 +++++++++--------
15f218
 pcs/pcs.8                      |  2 +-
15f218
 pcs/test/test_alert.py         | 44 +++++++++++++-------
15f218
 pcs/test/test_lib_cib_tools.py | 91 ++++++++++++++++++++++++++++++++++++++++++
15f218
 pcs/usage.py                   |  2 +-
15f218
 6 files changed, 147 insertions(+), 37 deletions(-)
15f218
15f218
diff --git a/pcs/alert.py b/pcs/alert.py
15f218
index 693bb8d..17f4e8d 100644
15f218
--- a/pcs/alert.py
15f218
+++ b/pcs/alert.py
15f218
@@ -63,6 +63,8 @@ def recipient_cmd(*args):
15f218
             recipient_update(*args)
15f218
         elif sub_cmd == "remove":
15f218
             recipient_remove(*args)
15f218
+        else:
15f218
+            raise CmdLineInputError()
15f218
     except CmdLineInputError as e:
15f218
         utils.exit_on_cmdline_input_errror(
15f218
             e, "alert", "recipient {0}".format(sub_cmd)
15f218
@@ -127,15 +129,14 @@ def recipient_add(lib, argv, modifiers):
15f218
         raise CmdLineInputError()
15f218
 
15f218
     alert_id = argv[0]
15f218
-    recipient_value = argv[1]
15f218
 
15f218
-    sections = parse_cmd_sections(argv[2:], set(["options", "meta"]))
15f218
+    sections = parse_cmd_sections(argv[1:], set(["options", "meta"]))
15f218
     main_args = prepare_options(sections["main"])
15f218
-    ensure_only_allowed_options(main_args, ["description", "id"])
15f218
+    ensure_only_allowed_options(main_args, ["description", "id", "value"])
15f218
 
15f218
     lib.alert.add_recipient(
15f218
         alert_id,
15f218
-        recipient_value,
15f218
+        main_args.get("value", None),
15f218
         prepare_options(sections["options"]),
15f218
         prepare_options(sections["meta"]),
15f218
         recipient_id=main_args.get("id", None),
15f218
diff --git a/pcs/lib/cib/tools.py b/pcs/lib/cib/tools.py
15f218
index d8ce57a..8141360 100644
15f218
--- a/pcs/lib/cib/tools.py
15f218
+++ b/pcs/lib/cib/tools.py
15f218
@@ -176,29 +176,31 @@ def upgrade_cib(cib, runner):
15f218
     cib -- cib etree
15f218
     runner -- CommandRunner
15f218
     """
15f218
-    temp_file = tempfile.NamedTemporaryFile("w+", suffix=".pcs")
15f218
-    temp_file.write(etree.tostring(cib).decode())
15f218
-    temp_file.flush()
15f218
-    output, retval = runner.run(
15f218
-        [
15f218
-            os.path.join(settings.pacemaker_binaries, "cibadmin"),
15f218
-            "--upgrade",
15f218
-            "--force"
15f218
-        ],
15f218
-        env_extend={"CIB_file": temp_file.name}
15f218
-    )
15f218
+    temp_file = None
15f218
+    try:
15f218
+        temp_file = tempfile.NamedTemporaryFile("w+", suffix=".pcs")
15f218
+        temp_file.write(etree.tostring(cib).decode())
15f218
+        temp_file.flush()
15f218
+        output, retval = runner.run(
15f218
+            [
15f218
+                os.path.join(settings.pacemaker_binaries, "cibadmin"),
15f218
+                "--upgrade",
15f218
+                "--force"
15f218
+            ],
15f218
+            env_extend={"CIB_file": temp_file.name}
15f218
+        )
15f218
 
15f218
-    if retval != 0:
15f218
-        temp_file.close()
15f218
-        LibraryError(reports.cib_upgrade_failed(output))
15f218
+        if retval != 0:
15f218
+            temp_file.close()
15f218
+            raise LibraryError(reports.cib_upgrade_failed(output))
15f218
 
15f218
-    try:
15f218
         temp_file.seek(0)
15f218
         return etree.fromstring(temp_file.read())
15f218
     except (EnvironmentError, etree.XMLSyntaxError, etree.DocumentInvalid) as e:
15f218
-        LibraryError(reports.cib_upgrade_failed(str(e)))
15f218
+        raise LibraryError(reports.cib_upgrade_failed(str(e)))
15f218
     finally:
15f218
-        temp_file.close()
15f218
+        if temp_file:
15f218
+            temp_file.close()
15f218
 
15f218
 
15f218
 def ensure_cib_version(runner, cib, version):
15f218
diff --git a/pcs/pcs.8 b/pcs/pcs.8
15f218
index 7a054ca..b3c4877 100644
15f218
--- a/pcs/pcs.8
15f218
+++ b/pcs/pcs.8
15f218
@@ -727,7 +727,7 @@ Update existing alert handler with specified id.
15f218
 remove <alert\-id>
15f218
 Remove alert handler with specified id.
15f218
 .TP
15f218
-recipient add <alert\-id> <recipient\-value> [id=<recipient\-id>] [description=<description>] [options [<option>=<value>]...] [meta [<meta-option>=<value>]...]
15f218
+recipient add <alert\-id> value=<recipient\-value> [id=<recipient\-id>] [description=<description>] [options [<option>=<value>]...] [meta [<meta-option>=<value>]...]
15f218
 Add new recipient to specified alert handler.
15f218
 .TP
15f218
 recipient update <recipient\-id> [value=<recipient\-value>] [description=<description>] [options [<option>=<value>]...] [meta [<meta-option>=<value>]...]
15f218
diff --git a/pcs/test/test_alert.py b/pcs/test/test_alert.py
15f218
index f6ea70d..d919ff6 100644
15f218
--- a/pcs/test/test_alert.py
15f218
+++ b/pcs/test/test_alert.py
15f218
@@ -233,7 +233,7 @@ Alerts:
15f218
  Alert: alert (path=test)
15f218
 """
15f218
         )
15f218
-        self.assert_pcs_success("alert recipient add alert rec_value")
15f218
+        self.assert_pcs_success("alert recipient add alert value=rec_value")
15f218
         self.assert_pcs_success(
15f218
             "alert config",
15f218
             """\
15f218
@@ -244,7 +244,7 @@ Alerts:
15f218
 """
15f218
         )
15f218
         self.assert_pcs_success(
15f218
-            "alert recipient add alert rec_value2 id=my-recipient "
15f218
+            "alert recipient add alert value=rec_value2 id=my-recipient "
15f218
             "description=description options o1=1 o2=2 meta m1=v1 m2=v2"
15f218
         )
15f218
         self.assert_pcs_success(
15f218
@@ -263,21 +263,25 @@ Alerts:
15f218
 
15f218
     def test_already_exists(self):
15f218
         self.assert_pcs_success("alert create path=test")
15f218
-        self.assert_pcs_success("alert recipient add alert rec_value id=rec")
15f218
+        self.assert_pcs_success(
15f218
+            "alert recipient add alert value=rec_value id=rec"
15f218
+        )
15f218
         self.assert_pcs_fail(
15f218
-            "alert recipient add alert value id=rec",
15f218
+            "alert recipient add alert value=value id=rec",
15f218
             "Error: 'rec' already exists\n"
15f218
         )
15f218
         self.assert_pcs_fail(
15f218
-            "alert recipient add alert value id=alert",
15f218
+            "alert recipient add alert value=value id=alert",
15f218
             "Error: 'alert' already exists\n"
15f218
         )
15f218
 
15f218
     def test_same_value(self):
15f218
         self.assert_pcs_success("alert create path=test")
15f218
-        self.assert_pcs_success("alert recipient add alert rec_value id=rec")
15f218
+        self.assert_pcs_success(
15f218
+            "alert recipient add alert value=rec_value id=rec"
15f218
+        )
15f218
         self.assert_pcs_fail(
15f218
-            "alert recipient add alert rec_value",
15f218
+            "alert recipient add alert value=rec_value",
15f218
             "Error: Recipient 'rec_value' in alert 'alert' already exists, "
15f218
             "use --force to override\n"
15f218
         )
15f218
@@ -291,7 +295,7 @@ Alerts:
15f218
 """
15f218
         )
15f218
         self.assert_pcs_success(
15f218
-            "alert recipient add alert rec_value --force",
15f218
+            "alert recipient add alert value=rec_value --force",
15f218
             "Warning: Recipient 'rec_value' in alert 'alert' already exists\n"
15f218
         )
15f218
         self.assert_pcs_success(
15f218
@@ -305,13 +309,21 @@ Alerts:
15f218
 """
15f218
         )
15f218
 
15f218
+    def test_no_value(self):
15f218
+        self.assert_pcs_success("alert create path=test")
15f218
+        self.assert_pcs_fail(
15f218
+            "alert recipient add alert id=rec",
15f218
+            "Error: required option 'value' is missing\n"
15f218
+        )
15f218
+
15f218
+
15f218
 
15f218
 @unittest.skipUnless(ALERTS_SUPPORTED, ALERTS_NOT_SUPPORTED_MSG)
15f218
 class UpdateRecipientAlert(PcsAlertTest):
15f218
     def test_success(self):
15f218
         self.assert_pcs_success("alert create path=test")
15f218
         self.assert_pcs_success(
15f218
-            "alert recipient add alert rec_value description=description "
15f218
+            "alert recipient add alert value=rec_value description=description "
15f218
             "options o1=1 o2=2 meta m1=v1 m2=v2"
15f218
         )
15f218
         self.assert_pcs_success(
15f218
@@ -360,8 +372,8 @@ Alerts:
15f218
 
15f218
     def test_value_exists(self):
15f218
         self.assert_pcs_success("alert create path=test")
15f218
-        self.assert_pcs_success("alert recipient add alert rec_value")
15f218
-        self.assert_pcs_success("alert recipient add alert value")
15f218
+        self.assert_pcs_success("alert recipient add alert value=rec_value")
15f218
+        self.assert_pcs_success("alert recipient add alert value=value")
15f218
         self.assert_pcs_success(
15f218
             "alert config",
15f218
             """\
15f218
@@ -394,7 +406,7 @@ Alerts:
15f218
 
15f218
     def test_value_same_as_previous(self):
15f218
         self.assert_pcs_success("alert create path=test")
15f218
-        self.assert_pcs_success("alert recipient add alert rec_value")
15f218
+        self.assert_pcs_success("alert recipient add alert value=rec_value")
15f218
         self.assert_pcs_success(
15f218
             "alert config",
15f218
             """\
15f218
@@ -425,7 +437,9 @@ Alerts:
15f218
 
15f218
     def test_empty_value(self):
15f218
         self.assert_pcs_success("alert create path=test")
15f218
-        self.assert_pcs_success("alert recipient add alert rec_value id=rec")
15f218
+        self.assert_pcs_success(
15f218
+            "alert recipient add alert value=rec_value id=rec"
15f218
+        )
15f218
         self.assert_pcs_fail(
15f218
             "alert recipient update rec value=",
15f218
             "Error: Recipient value '' is not valid.\n"
15f218
@@ -436,7 +450,9 @@ Alerts:
15f218
 class RemoveRecipientTest(PcsAlertTest):
15f218
     def test_success(self):
15f218
         self.assert_pcs_success("alert create path=test")
15f218
-        self.assert_pcs_success("alert recipient add alert rec_value id=rec")
15f218
+        self.assert_pcs_success(
15f218
+            "alert recipient add alert value=rec_value id=rec"
15f218
+        )
15f218
         self.assert_pcs_success(
15f218
             "alert config",
15f218
             """\
15f218
diff --git a/pcs/test/test_lib_cib_tools.py b/pcs/test/test_lib_cib_tools.py
15f218
index 10f8a96..0fd4d22 100644
15f218
--- a/pcs/test/test_lib_cib_tools.py
15f218
+++ b/pcs/test/test_lib_cib_tools.py
15f218
@@ -7,6 +7,7 @@ from __future__ import (
15f218
 
15f218
 from unittest import TestCase
15f218
 
15f218
+from os.path import join
15f218
 from lxml import etree
15f218
 
15f218
 from pcs.test.tools.assertions import (
15f218
@@ -17,6 +18,7 @@ from pcs.test.tools.misc import get_test_resource as rc
15f218
 from pcs.test.tools.pcs_mock import mock
15f218
 from pcs.test.tools.xml import get_xml_manipulation_creator_from_file
15f218
 
15f218
+from pcs import settings
15f218
 from pcs.common import report_codes
15f218
 from pcs.lib.external import CommandRunner
15f218
 from pcs.lib.errors import ReportItemSeverity as severities
15f218
@@ -369,3 +371,92 @@ class EnsureCibVersionTest(TestCase):
15f218
             )
15f218
         )
15f218
         mock_upgrade_cib.assert_called_once_with(self.cib, self.mock_runner)
15f218
+
15f218
+
15f218
+@mock.patch("tempfile.NamedTemporaryFile")
15f218
+class UpgradeCibTest(TestCase):
15f218
+    def setUp(self):
15f218
+        self.mock_runner = mock.MagicMock(spec_set=CommandRunner)
15f218
+
15f218
+    def test_success(self, mock_named_file):
15f218
+        mock_file = mock.MagicMock()
15f218
+        mock_file.name = "mock_file_name"
15f218
+        mock_file.read.return_value = "<cib/>"
15f218
+        mock_named_file.return_value = mock_file
15f218
+        self.mock_runner.run.return_value = ("", 0)
15f218
+        assert_xml_equal(
15f218
+            "<cib/>",
15f218
+            etree.tostring(
15f218
+                lib.upgrade_cib(etree.XML("<old_cib/>"), self.mock_runner)
15f218
+            ).decode()
15f218
+        )
15f218
+        mock_named_file.assert_called_once_with("w+", suffix=".pcs")
15f218
+        mock_file.write.assert_called_once_with("<old_cib/>")
15f218
+        mock_file.flush.assert_called_once_with()
15f218
+        self.mock_runner.run.assert_called_once_with(
15f218
+            [
15f218
+                join(settings.pacemaker_binaries, "cibadmin"),
15f218
+                "--upgrade",
15f218
+                "--force"
15f218
+            ],
15f218
+            env_extend={"CIB_file": "mock_file_name"}
15f218
+        )
15f218
+        mock_file.seek.assert_called_once_with(0)
15f218
+        mock_file.read.assert_called_once_with()
15f218
+
15f218
+    def test_upgrade_failed(self, mock_named_file):
15f218
+        mock_file = mock.MagicMock()
15f218
+        mock_file.name = "mock_file_name"
15f218
+        mock_named_file.return_value = mock_file
15f218
+        self.mock_runner.run.return_value = ("reason", 1)
15f218
+        assert_raise_library_error(
15f218
+            lambda: lib.upgrade_cib(etree.XML("<old_cib/>"), self.mock_runner),
15f218
+            (
15f218
+                severities.ERROR,
15f218
+                report_codes.CIB_UPGRADE_FAILED,
15f218
+                {"reason": "reason"}
15f218
+            )
15f218
+        )
15f218
+        mock_named_file.assert_called_once_with("w+", suffix=".pcs")
15f218
+        mock_file.write.assert_called_once_with("<old_cib/>")
15f218
+        mock_file.flush.assert_called_once_with()
15f218
+        self.mock_runner.run.assert_called_once_with(
15f218
+            [
15f218
+                join(settings.pacemaker_binaries, "cibadmin"),
15f218
+                "--upgrade",
15f218
+                "--force"
15f218
+            ],
15f218
+            env_extend={"CIB_file": "mock_file_name"}
15f218
+        )
15f218
+
15f218
+    def test_unable_to_parse_upgraded_cib(self, mock_named_file):
15f218
+        mock_file = mock.MagicMock()
15f218
+        mock_file.name = "mock_file_name"
15f218
+        mock_file.read.return_value = "not xml"
15f218
+        mock_named_file.return_value = mock_file
15f218
+        self.mock_runner.run.return_value = ("", 0)
15f218
+        assert_raise_library_error(
15f218
+            lambda: lib.upgrade_cib(etree.XML("<old_cib/>"), self.mock_runner),
15f218
+            (
15f218
+                severities.ERROR,
15f218
+                report_codes.CIB_UPGRADE_FAILED,
15f218
+                {
15f218
+                    "reason":
15f218
+                        "Start tag expected, '<' not found, line 1, column 1",
15f218
+                }
15f218
+            )
15f218
+        )
15f218
+        mock_named_file.assert_called_once_with("w+", suffix=".pcs")
15f218
+        mock_file.write.assert_called_once_with("<old_cib/>")
15f218
+        mock_file.flush.assert_called_once_with()
15f218
+        self.mock_runner.run.assert_called_once_with(
15f218
+            [
15f218
+                join(settings.pacemaker_binaries, "cibadmin"),
15f218
+                "--upgrade",
15f218
+                "--force"
15f218
+            ],
15f218
+            env_extend={"CIB_file": "mock_file_name"}
15f218
+        )
15f218
+        mock_file.seek.assert_called_once_with(0)
15f218
+        mock_file.read.assert_called_once_with()
15f218
+
15f218
diff --git a/pcs/usage.py b/pcs/usage.py
15f218
index 9ebbca9..78e340b 100644
15f218
--- a/pcs/usage.py
15f218
+++ b/pcs/usage.py
15f218
@@ -1507,7 +1507,7 @@ Commands:
15f218
     remove <alert-id>
15f218
         Remove alert handler with specified id.
15f218
 
15f218
-    recipient add <alert-id> <recipient-value> [id=<recipient-id>]
15f218
+    recipient add <alert-id> value=<recipient-value> [id=<recipient-id>]
15f218
             [description=<description>] [options [<option>=<value>]...]
15f218
             [meta [<meta-option>=<value>]...]
15f218
         Add new recipient to specified alert handler.
15f218
-- 
15f218
1.8.3.1
15f218