<commit_before>#!/usr/bin/python3 -u
#

# Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013 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.


"""Script for doing QA on Ganeti.

"""

# pylint: disable=C0103
# due to invalid name

import copy
import datetime
import optparse
import sys

from qa import colors
from qa import qa_cluster
from qa import qa_config
from qa import qa_daemon
from qa import qa_env
from qa import qa_error
from qa import qa_filters
from qa import qa_group
from qa import qa_instance
from qa import qa_iptables
from qa import qa_monitoring
from qa import qa_network
from qa import qa_node
from qa import qa_os
from qa import qa_performance
from qa import qa_job
from qa import qa_rapi
from qa import qa_tags
from qa import qa_utils

from ganeti import utils
from ganeti import rapi # pylint: disable=W0611
from ganeti import constants
from ganeti import netutils

import ganeti.rapi.client # pylint: disable=W0611
from ganeti.rapi.client import UsesRapiClient


def _FormatHeader(line, end=72, mark="-", color=None):
  """Fill a line up to the end column.

  """
  line = (mark * 4) + " " + line + " "
  line += "-" * (end - len(line))
  line = line.rstrip()
  line = colors.colorize(line, color=color)
  return line


def _DescriptionOf(fn):
  """Computes the description of an item.

  """
  if fn.__doc__:
    desc = fn.__doc__.splitlines()[0].strip()
    desc = desc.rstrip(".")
    if fn.__name__:
      desc = "[" + fn.__name__ + "] " + desc
  else:
    desc = "%r" % fn

  return desc


def RunTest(fn, *args, **kwargs):
  """Runs a test after printing a header.

  """

  tstart = datetime.datetime.now()

  desc = _DescriptionOf(fn)

  print()
  print(_FormatHeader("%s start %s" % (tstart, desc),
                      color=colors.YELLOW, mark="<"))

  try:
    retval = fn(*args, **kwargs)
    print(_FormatHeader("PASSED %s" % (desc, ), color=colors.GREEN))
    return retval
  except Exception as e:
    print(_FormatHeader("FAILED %s: %s" % (desc, e), color=colors.RED))
    raise
  finally:
    tstop = datetime.datetime.now()
    tdelta = tstop - tstart
    print(_FormatHeader("%s time=%s %s" % (tstop, tdelta, desc),
                        color=colors.MAGENTA, mark=">"))


def ReportTestSkip(desc, testnames):
  """Reports that tests have been skipped.

  @type desc: string
  @param desc: string
  @type testnames: string or list of string
  @param testnames: either a single test name in the configuration
      file, or a list of testnames (which will be AND-ed together)

  """
  tstart = datetime.datetime.now()
  # TODO: Formatting test names when non-string names are involved
  print(_FormatHeader("%s skipping %s, test(s) %s disabled" %
                      (tstart, desc, testnames),
                      color=colors.BLUE, mark="*"))


def RunTestIf(testnames, fn, *args, **kwargs):
  """Runs a test conditionally.

  @param testnames: either a single test name in the configuration
      file, or a list of testnames (which will be AND-ed together)

  """
  if qa_config.TestEnabled(testnames):
    RunTest(fn, *args, **kwargs)
  else:
    desc = _DescriptionOf(fn)
    ReportTestSkip(desc, testnames)


def RunTestBlock(fn, *args, **kwargs):
  """Runs a block of tests after printing a header.

  """
  tstart = datetime.datetime.now()

  desc = _DescriptionOf(fn)

  print()
  print(_FormatHeader("BLOCK %s start %s" % (tstart, desc),
                      color=[colors.YELLOW, colors.BOLD], mark="v"))

  try:
    return fn(*args, **kwargs)
  except Exception as e:
    print(_FormatHeader("BLOCK FAILED %s: %s" % (desc, e),
                        color=[colors.RED, colors.BOLD]))
    raise
  finally:
    tstop = datetime.datetime.now()
    tdelta = tstop - tstart
    print(_FormatHeader("BLOCK %s time=%s %s" % (tstop, tdelta, desc),
                        color=[colors.MAGENTA, colors.BOLD], mark="^"))


def RunEnvTests():
  """Run several environment tests.

  """
  RunTestIf("env", qa_env.TestSshConnection)
  RunTestIf("env", qa_env.TestIcmpPing)
  RunTestIf("env", qa_env.TestGanetiCommands)


def SetupCluster():
  """Initializes the cluster.

  """

  RunTestIf("create-cluster", qa_cluster.TestClusterInit)
  if not qa_config.TestEnabled("create-cluster"):
    # If the cluster is already in place, we assume that exclusive-storage is
    # already set according to the configuration
    qa_config.SetExclusiveStorage(qa_config.get("exclusive-storage", False))

  qa_rapi.SetupRapi()

  qa_group.ConfigureGroups()

  # Test on empty cluster
  RunTestIf("node-list", qa_node.TestNodeList)
  RunTestIf("instance-list", qa_instance.TestInstanceList)<commit_msg>Ganeti QA: save profiling info to separate log file<commit_after>#!/usr/bin/python3 -u
#

# Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013 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.


"""Script for doing QA on Ganeti.

"""

# pylint: disable=C0103
# due to invalid name

import copy
import datetime
import optparse
import sys

from qa import colors
from qa import qa_cluster
from qa import qa_config
from qa import qa_daemon
from qa import qa_env
from qa import qa_error
from qa import qa_filters
from qa import qa_group
from qa import qa_instance
from qa import qa_iptables
from qa import qa_monitoring
from qa import qa_network
from qa import qa_node
from qa import qa_os
from qa import qa_performance
from qa import qa_job
from qa import qa_rapi
from qa import qa_tags
from qa import qa_utils

from ganeti import utils
from ganeti import rapi # pylint: disable=W0611
from ganeti import constants
from ganeti import netutils
from ganeti import pathutils

import ganeti.rapi.client # pylint: disable=W0611
from ganeti.rapi.client import UsesRapiClient

_QA_PROFILE = pathutils.GetLogFilename("qa-profile")
_PROFILE_LOG_INDENT = ""

def _FormatHeader(line, end=72, mark="-", color=None):
  """Fill a line up to the end column.

  """
  line = (mark * 4) + " " + line + " "
  line += "-" * (end - len(line))
  line = line.rstrip()
  line = colors.colorize(line, color=color)
  return line


def _DescriptionOf(fn):
  """Computes the description of an item.

  """
  if fn.__doc__:
    desc = fn.__doc__.splitlines()[0].strip()
    desc = desc.rstrip(".")
    if fn.__name__:
      desc = "[" + fn.__name__ + "] " + desc
  else:
    desc = "%r" % fn

  return desc


def RunTest(fn, *args, **kwargs):
  """Runs a test after printing a header.

  """
  global _PROFILE_LOG_INDENT
  tstart = datetime.datetime.now()

  desc = _DescriptionOf(fn)

  print()
  print(_FormatHeader("%s start %s" % (tstart, desc),
                      color=colors.YELLOW, mark="<"))
  with open(_QA_PROFILE, "a") as f:
    f.write("%sExecuting Function %s\n" % (_PROFILE_LOG_INDENT,
                                           fn.__name__))
  _PROFILE_LOG_INDENT += " "

  try:
    retval = fn(*args, **kwargs)
    print(_FormatHeader("PASSED %s" % (desc, ), color=colors.GREEN))
    return retval
  except Exception as e:
    print(_FormatHeader("FAILED %s: %s" % (desc, e), color=colors.RED))
    raise
  finally:
    tstop = datetime.datetime.now()
    tdelta = tstop - tstart
    print(_FormatHeader("%s time=%s %s" % (tstop, tdelta, desc),
                        color=colors.MAGENTA, mark=">"))
    _PROFILE_LOG_INDENT = _PROFILE_LOG_INDENT[:-1]
    with open(_QA_PROFILE, "a") as f:
      f.write("%sFunction %s ran for %s\n" % (_PROFILE_LOG_INDENT,
                                              fn.__name__,
                                              tdelta))


def ReportTestSkip(desc, testnames):
  """Reports that tests have been skipped.

  @type desc: string
  @param desc: string
  @type testnames: string or list of string
  @param testnames: either a single test name in the configuration
      file, or a list of testnames (which will be AND-ed together)

  """
  tstart = datetime.datetime.now()
  # TODO: Formatting test names when non-string names are involved
  print(_FormatHeader("%s skipping %s, test(s) %s disabled" %
                      (tstart, desc, testnames),
                      color=colors.BLUE, mark="*"))


def RunTestIf(testnames, fn, *args, **kwargs):
  """Runs a test conditionally.

  @param testnames: either a single test name in the configuration
      file, or a list of testnames (which will be AND-ed together)

  """
  if qa_config.TestEnabled(testnames):
    RunTest(fn, *args, **kwargs)
  else:
    desc = _DescriptionOf(fn)
    ReportTestSkip(desc, testnames)


def RunTestBlock(fn, *args, **kwargs):
  """Runs a block of tests after printing a header.

  """
  global _PROFILE_LOG_INDENT
  tstart = datetime.datetime.now()

  desc = _DescriptionOf(fn)

  print()
  print(_FormatHeader("BLOCK %s start %s" % (tstart, desc),
                      color=[colors.YELLOW, colors.BOLD], mark="v"))
  with open(_QA_PROFILE, "a") as f:
    f.write("%sExecuting Function %s\n" % (_PROFILE_LOG_INDENT,
                                           fn.__name__))
  _PROFILE_LOG_INDENT += " "

  try:
    return fn(*args, **kwargs)
  except Exception as e:
    print(_FormatHeader("BLOCK FAILED %s: %s" % (desc, e),
                        color=[colors.RED, colors.BOLD]))
    raise
  finally:
    tstop = datetime.datetime.now()
    tdelta = tstop - tstart
    print(_FormatHeader("BLOCK %s time=%s %s" % (tstop, tdelta, desc),
                        color=[colors.MAGENTA, colors.BOLD], mark="^"))
    _PROFILE_LOG_INDENT = _PROFILE_LOG_INDENT[:-1]
    with open(_QA_PROFILE, "a") as f:
      f.write("%sFunction %s ran for %s\n" % (_PROFILE_LOG_INDENT,
                                              fn.__name__,
                                              tdelta))


def RunEnvTests():
  """Run several environment tests.

  """
  RunTestIf("env", qa_env.TestSshConnection)
  RunTestIf("env", qa_env.TestIcmpPing)
  RunTestIf("env", qa_env.TestGanetiCommands)


def SetupCluster():
  """Initializes the cluster.

  """

  RunTestIf("create-cluster", qa_cluster.TestClusterInit)
  if not qa_config.TestEnabled("create-cluster"):
    # If the cluster is already in place, we assume that exclusive-storage is
    # already set according to the configuration
    qa_config.SetExclusiveStorage(qa_config.get("exclusive-storage", False))

  qa_rapi.SetupRapi()

  qa_group.ConfigureGroups()

  # Test on empty cluster
  RunTestIf("node-list", qa_node.TestNodeList)
  RunTestIf("instance-list", qa_instance.TestInstanceList)
{'fraction_non_alphanumeric': 0.10278422273781902, 'fraction_numerical': 0.007424593967517401, 'mean_word_length': 3.398299319727891, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4844104', 'n_tokens_mistral': 4190, 'n_tokens_neox': 3922, 'n_words': 1370}