LGTM, thanks

On Thu, Nov 26, 2015 at 1:08 PM, 'Oleg Ponomarev' via ganeti-devel <
[email protected]> wrote:

> Test 3 main cases of global post hooks usage:
>   - successful LU execution;
>   - LU with the prerequisites failed;
>   - disappeared LU process.
> All the tests are performed on the master node.
>
> Signed-off-by: Oleg Ponomarev <[email protected]>
> ---
>  Makefile.am           |   1 +
>  qa/ganeti-qa.py       |   3 +
>  qa/qa-sample.json     |   2 +
>  qa/qa_global_hooks.py | 167
> ++++++++++++++++++++++++++++++++++++++++++++++++++
>  qa/qa_utils.py        |  13 +++-
>  5 files changed, 185 insertions(+), 1 deletion(-)
>  create mode 100644 qa/qa_global_hooks.py
>
> diff --git a/Makefile.am b/Makefile.am
> index 8ba84a5..0080f00 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -1347,6 +1347,7 @@ qa_scripts = \
>         qa/qa_error.py \
>         qa/qa_filters.py \
>         qa/qa_group.py \
> +       qa/qa_global_hooks.py \
>         qa/qa_instance.py \
>         qa/qa_instance_utils.py \
>         qa/qa_iptables.py \
> diff --git a/qa/ganeti-qa.py b/qa/ganeti-qa.py
> index 9b475e2..36a9263 100755
> --- a/qa/ganeti-qa.py
> +++ b/qa/ganeti-qa.py
> @@ -48,6 +48,7 @@ import qa_env
>  import qa_error
>  import qa_filters
>  import qa_group
> +import qa_global_hooks
>  import qa_instance
>  import qa_iptables
>  import qa_maintd
> @@ -965,6 +966,8 @@ def RunQa():
>    RunTestBlock(RunNetworkTests)
>    RunTestBlock(RunFilterTests)
>
> +  RunTestIf("global-hooks", qa_global_hooks.RunGlobalHooksTests)
> +
>    # The master shouldn't be readded or put offline; "delay" needs a
> non-master
>    # node to test
>    pnode = qa_config.AcquireNode(exclude=qa_config.GetMasterNode())
> diff --git a/qa/qa-sample.json b/qa/qa-sample.json
> index ac10a05..9b0a1a1 100644
> --- a/qa/qa-sample.json
> +++ b/qa/qa-sample.json
> @@ -253,6 +253,8 @@
>
>      "job-list": true,
>
> +    "global-hooks": true,
> +
>      "jobqueue-performance": true,
>      "parallel-performance": true,
>
> diff --git a/qa/qa_global_hooks.py b/qa/qa_global_hooks.py
> new file mode 100644
> index 0000000..8e5457a
> --- /dev/null
> +++ b/qa/qa_global_hooks.py
> @@ -0,0 +1,167 @@
> +#
> +#
> +
> +# Copyright (C) 2015 Google Inc.
> +# All rights reserved.
> +#
> +# Redistribution and use in source and binary forms, with or without
> +# modification, are permitted provided that the following conditions are
> +# met:
> +#
> +# 1. Redistributions of source code must retain the above copyright
> notice,
> +# this list of conditions and the following disclaimer.
> +#
> +# 2. Redistributions in binary form must reproduce the above copyright
> +# notice, this list of conditions and the following disclaimer in the
> +# documentation and/or other materials provided with the distribution.
> +#
> +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
> +# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
> +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
> PARTICULAR
> +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
> +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
> +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
> +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
> +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
> +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
> +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
> +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> +
> +
> +"""QA tests for the universal job hooks.
> +
> +"""
> +
> +import time
> +
> +from ganeti import constants
> +from ganeti import pathutils
> +from qa_config import GetMasterNode
> +from qa_job_utils import ExecuteJobProducingCommand
> +from qa_utils import AssertEqual, GetCommandOutput, IsFileExists
> +
> +PRE_PATH = "%s/global-pre.d" % pathutils.HOOKS_BASE_DIR
> +POST_PATH = "%s/global-post.d" % pathutils.HOOKS_BASE_DIR
> +H_DIR = "/var/log/ganeti/qa_global_hooks"
> +
> +
> +def _GetHookFilePath(job_id, phase, status=None):
> +  """Returns the path to the qa hooks temporary files.
> +
> +  """
> +  h_fname = H_DIR + "/%d_OP_TEST_DELAY_%s" % (job_id, phase)
> +  if phase == "pre":
> +    return h_fname
> +  return h_fname + "_" + status
> +
> +
> +def TestHooksInitialize():
> +  """Creates global hooks on the master node
> +
> +  """
> +  master = GetMasterNode().primary
> +  GetCommandOutput(master, "mkdir -p %s" % pathutils.HOOKS_BASE_DIR)
> +  GetCommandOutput(master, "mkdir -p %s" % PRE_PATH)
> +  GetCommandOutput(master, "mkdir -p %s" % POST_PATH)
> +  GetCommandOutput(master, "mkdir -p %s" % H_DIR)
> +  h_name = "/qa_test_hook"
> +  create_hook_common = """
> +FOUT=%s
> +echo '#!/bin/sh' > $FOUT
> +echo 'touch %s/$GANETI_JOB_ID"_"$GANETI_OP_CODE%s' >> $FOUT
> +chmod +x $FOUT
> +"""
> +  create_pre = create_hook_common % (PRE_PATH + h_name, H_DIR, '"_pre"')
> +  create_post = create_hook_common % (POST_PATH + h_name, H_DIR,
> +                                      '"_post_"$GANETI_POST_STATUS')
> +  GetCommandOutput(master, create_pre)
> +  GetCommandOutput(master, create_post)
> +
> +
> +def TestHookSucceeded():
> +  """Checks whether the global hooks have been executed (status succes).
> +
> +  - Global pre hook should has been executed.
> +  - Global post hook should with status *success* should has been
> executed.
> +  - Global post hooks with failed statuses shouldn't have been executed.
> +  """
> +  master = GetMasterNode().primary
> +  job_id = ExecuteJobProducingCommand("gnt-debug delay --submit 1")
> +  time.sleep(3)
> +  AssertEqual(IsFileExists(master, _GetHookFilePath(job_id, "pre")), True,
> +              "Global pre hook hasn't been executed.")
> +  AssertEqual(IsFileExists(master, _GetHookFilePath(job_id, "post",
> +                           constants.POST_HOOKS_STATUS_SUCCESS)), True,
> +              "Global post hook hasn't been executed with status
> *success*")
> +  AssertEqual(IsFileExists(master, _GetHookFilePath(job_id, "post",
> +                           constants.POST_HOOKS_STATUS_ERROR)), False,
> +              "Global post hook has been executed with status *error*")
> +  AssertEqual(IsFileExists(master, _GetHookFilePath(job_id, "post",
> +                           constants.POST_HOOKS_STATUS_DISAPPEARED)),
> False,
> +              "Global post hook has been executed with status
> *disappeared*")
> +
> +
> +def TestHookFailed():
> +  """Checks whether the global hooks have been executed (status error).
> +
> +  - Global post hook should with status *error* should has been executed.
> +  - Global post hook with other statuses shouldn't have been executed.
> +  """
> +  master = GetMasterNode().primary
> +  job_id = ExecuteJobProducingCommand("gnt-debug delay --submit 0")
> +  time.sleep(1)
> +  AssertEqual(IsFileExists(master, _GetHookFilePath(job_id, "post",
> +                           constants.POST_HOOKS_STATUS_SUCCESS)), False,
> +              "Global post hook has been executed with status *success*")
> +  AssertEqual(IsFileExists(master, _GetHookFilePath(job_id, "post",
> +                           constants.POST_HOOKS_STATUS_ERROR)), True,
> +              "Global post hook hasn't been executed with status *error*")
> +  AssertEqual(IsFileExists(master, _GetHookFilePath(job_id, "post",
> +                           constants.POST_HOOKS_STATUS_DISAPPEARED)),
> False,
> +              "Global post hook has been executed with status
> *disappeared*")
> +
> +
> +def TestHookDisappeared():
> +  """Checks whether the global hooks have been executed (status
> disappeared).
> +
> +  - Global pre hook should has been executed.
> +  - Global post hook should with status *disappeared* should has been
> executed.
> +  - Global post hook with other statuses shouldn't have been executed.
> +  """
> +  master = GetMasterNode().primary
> +  job_id = ExecuteJobProducingCommand("gnt-debug delay --submit 10")
> +  time.sleep(1)
> +  GetCommandOutput(master, "gnt-job cancel --kill --yes-do-it %d" %
> job_id)
> +  time.sleep(10)
> +  AssertEqual(IsFileExists(master, _GetHookFilePath(job_id, "pre")), True,
> +              "Global pre hook hasn't been executed.")
> +  AssertEqual(IsFileExists(master, _GetHookFilePath(job_id, "post",
> +                           constants.POST_HOOKS_STATUS_SUCCESS)), False,
> +              "Global post hook has been executed with status *success*")
> +  AssertEqual(IsFileExists(master, _GetHookFilePath(job_id, "post",
> +                           constants.POST_HOOKS_STATUS_ERROR)), False,
> +              "Global post hook has been executed with status *error*")
> +  AssertEqual(IsFileExists(master, _GetHookFilePath(job_id, "post",
> +                           constants.POST_HOOKS_STATUS_DISAPPEARED)),
> True,
> +              "Global post hook hasn't been executed with status
> *disappeared*")
> +
> +
> +def TestHooksCleanup():
> +  """Remove the directories created by the tests
> +
> +  """
> +  master = GetMasterNode().primary
> +  GetCommandOutput(master, "rm %s/*" % PRE_PATH)
> +  GetCommandOutput(master, "rm %s/*" % POST_PATH)
> +  GetCommandOutput(master, "rm -rf %s" % H_DIR)
> +
> +
> +def RunGlobalHooksTests():
> +  """Runs tests for global hooks considering different job execution
> cases.
> +
> +  """
> +  TestHooksInitialize()
> +  TestHookSucceeded()
> +  TestHookFailed()
> +  TestHookDisappeared()
> +  TestHooksCleanup()
> diff --git a/qa/qa_utils.py b/qa/qa_utils.py
> index f2b2c2e..94e1dce 100644
> --- a/qa/qa_utils.py
> +++ b/qa/qa_utils.py
> @@ -1,7 +1,7 @@
>  #
>  #
>
> -# Copyright (C) 2007, 2011, 2012, 2013 Google Inc.
> +# Copyright (C) 2007, 2011, 2012, 2013, 2015 Google Inc.
>  # All rights reserved.
>  #
>  # Redistribution and use in source and binary forms, with or without
> @@ -523,6 +523,17 @@ def BackupFile(node, path):
>    return result
>
>
> +def IsFileExists(node, path):
> +  """Checks if a file on the node exists.
> +
> +  """
> +  cmd = ("[[ -f \"%s\" ]] && echo yes || echo no" % path)
> +
> +  # Return temporary filename
> +  result = GetCommandOutput(node, cmd).strip()
> +  return True if result == "yes" else False
> +
> +
>  @contextlib.contextmanager
>  def CheckFileUnmodified(node, filename):
>    """Checks that the content of a given file remains the same after
> running a
> --
> 2.6.0.rc2.230.g3dd15c0
>
>
Hrvoje Ribicic
Ganeti Engineering
Google Germany GmbH
Dienerstr. 12, 80331, München

Geschäftsführer: Matthew Scott Sucherman, Paul Terence Manicle
Registergericht und -nummer: Hamburg, HRB 86891
Sitz der Gesellschaft: Hamburg

Diese E-Mail ist vertraulich. Wenn Sie nicht der richtige Adressat sind,
leiten Sie diese bitte nicht weiter, informieren Sie den Absender und
löschen Sie die E-Mail und alle Anhänge. Vielen Dank.

This e-mail is confidential. If you are not the right addressee please do
not forward it, please inform the sender, and please erase this e-mail
including any attachments. Thanks.

Reply via email to