Title: usually contains a verb describing what the patch does. Something
like: "Add tool that..."

Il 11/ago/2014 09:28 "'Aaron Karper' via ganeti-devel" <
[email protected]> ha scritto:
>
> This relies on the ReqConfigQuery and takes several RFC6901 paths and
> will return a table of the keys and values. The data accessible is the
> same as in config.data (typically found at /var/lib/ganeti/config.data).
>
> Signed-off-by: Aaron Karper <[email protected]>
> ---
>  Makefile.am                |   3 +-
>  src/Ganeti/Confd/Server.hs |   3 +-
>  src/Ganeti/Confd/Utils.hs  |   3 +-
>  tools/query-config         | 145
+++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 151 insertions(+), 3 deletions(-)
>  create mode 100755 tools/query-config
>
> diff --git a/Makefile.am b/Makefile.am
> index 3b0fa8f..34d4156 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -1292,7 +1292,8 @@ python_scripts = \
>         tools/move-instance \
>         tools/ovfconverter \
>         tools/post-upgrade \
> -       tools/sanitize-config
> +       tools/sanitize-config \
> +       tools/query-config

Please, double check that this is enough to have the tool built and
distributed (and commit-check happy)

>
>  dist_tools_SCRIPTS = \
>         tools/kvm-console-wrapper \
> diff --git a/src/Ganeti/Confd/Server.hs b/src/Ganeti/Confd/Server.hs
> index 855d1fc..e59d5bc 100644
> --- a/src/Ganeti/Confd/Server.hs
> +++ b/src/Ganeti/Confd/Server.hs
> @@ -233,7 +233,8 @@ buildResponse cdata req@(ConfdRequest { confdRqType =
ReqInstanceDisks }) = do
>      Bad e -> fail $ "Could not retrieve disks: " ++ show e
>
>  -- | Return arbitrary configuration value given by a path.
> -buildResponse cdata req@(ConfdRequest { confdRqType = ReqConfigQuery,
confdRqQuery = pathQ }) = do
> +buildResponse cdata req@(ConfdRequest { confdRqType = ReqConfigQuery
> +                                      , confdRqQuery = pathQ }) = do

Include this in the previous patch.

>    let cfg = fst cdata
>    path <-
>      case pathQ of
> diff --git a/src/Ganeti/Confd/Utils.hs b/src/Ganeti/Confd/Utils.hs
> index b09340b..44151de 100644
> --- a/src/Ganeti/Confd/Utils.hs
> +++ b/src/Ganeti/Confd/Utils.hs
> @@ -127,7 +127,8 @@ pointerFromString s = either J.Error J.Ok $
P.parseOnly parser $ pack s
>        tokens <-  token `P.manyTill` P.endOfInput
>        return $ Pointer tokens
>      token = do
> -      P.char '/' *> (P.many' $ P.choice [escaped, P.satisfy $
P.notInClass "~/"])
> +      P.char '/' *> (P.many' $ P.choice [ escaped
> +                                        , P.satisfy $ P.notInClass "~/"])

This too.

>      escaped = P.choice [escapedSlash, escapedTilde]
>      escapedSlash = P.string (pack "~1") *> return '/'
>      escapedTilde = P.string (pack "~0") *> return '~'
> diff --git a/tools/query-config b/tools/query-config
> new file mode 100755
> index 0000000..68e2b81
> --- /dev/null
> +++ b/tools/query-config
> @@ -0,0 +1,145 @@
> +#!/usr/bin/python
> +#
> +
> +# Copyright (C) 2014 Google Inc.
> +#
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 2 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful, but
> +# WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +# General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program; if not, write to the Free Software
> +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
> +# 02110-1301, USA.
> +
> +
> +"""Tool to query the cluster configuration over RConfD
> +
> +"""
> +
> +# functions in this module need to have a given name structure, so:
> +# pylint: disable=C0103
What is causing you to do this? Maybe a more informative comment would help.

> +
> +
> +import optparse
> +import sys
> +
> +from ganeti import constants
> +from ganeti import cli
> +from ganeti import utils
> +from ganeti import pathutils
> +
> +from ganeti.confd import client as confd_client
> +
> +USAGE = ("\tquery-config [--addr=host] [--hmac=key] QUERY [QUERY...]")
> +
> +OPTIONS = [
> +  cli.cli_option("--hmac", dest="hmac", default=None,
> +                 help="Specify HMAC key instead of reading"
> +                 " it from the filesystem",
> +                 metavar="<KEY>"),
> +  cli.cli_option("-a", "--address", dest="mc", default="127.0.0.1",
> +                 help="Server IP to query (default: 127.0.0.1)",
> +                 metavar="<ADDRESS>"),
> +  cli.cli_option("-r", "--requests", dest="requests", default=100,
> +                 help="Number of requests for the timing tests",
> +                 type="int", metavar="<REQUESTS>"),
Is this option actually being used somewhere?
> +  ]
> +
> +
> +def Err(msg, exit_code=1):
> +  """Simple error logging that prints to stderr.
> +
> +  """
> +  sys.stderr.write(msg + "\n")
> +  sys.stderr.flush()
> +  sys.exit(exit_code)
> +
> +
> +def Usage():
> +  """Shows program usage information and exits the program."""
> +
> +  print >> sys.stderr, "Usage:"
> +  print >> sys.stderr, USAGE
> +  sys.exit(2)
> +
> +
> +class QueryClient(object):
> +  """Confd client for querying the configuration JSON."""

An empty line at the end of the comment is missing, here and in the other
docstrings.

> +  def __init__(self):
> +    """Constructor."""
> +    self.opts = None
> +    self.cluster_master = None
> +    self.instance_ips = None
> +    self.is_timing = False
> +    self.ParseOptions()
> +
> +  def ParseOptions(self):
> +    """Parses the command line options.
> +
> +    In case of command line errors, it will show the usage and exit the
> +    program.
> +
> +    @return: a tuple (options, args), as returned by
OptionParser.parse_args
> +
> +    """
> +    parser = optparse.OptionParser(usage="\n%s" % USAGE,
> +                                   version=("%%prog (ganeti) %s" %
> +                                            constants.RELEASE_VERSION),
> +                                   option_list=OPTIONS)
> +
> +    options, args = parser.parse_args()
> +    if args == []:
> +      Usage()
> +
> +    self.paths = args
> +
> +    if options.hmac is None:
> +      options.hmac = utils.ReadFile(pathutils.CONFD_HMAC_KEY)
> +
> +    self.hmac_key = options.hmac
> +
> +    self.mc_list = [options.mc]
> +
> +    self.opts = options
> +
> +  def Run(self):
> +    self.store_callback = confd_client.StoreResultCallback()
> +
> +    self.confd_client = confd_client.ConfdClient(self.hmac_key,
> +                                      self.mc_list,
> +                                      self.store_callback)
> +
> +    responses = []
> +    for path in self.paths:
> +      req = confd_client.ConfdClientRequest(
> +        type=constants.CONFD_REQ_CONFIG_QUERY, query=path)
> +      _, response = self.DoConfdRequestReply(req)
> +      responses.append(str(response.server_reply.answer))
> +    table = zip(self.paths, responses)
> +    longest_path = max(len(p) for p in self.paths)
> +    for p, a in table:
> +      print "%s\t%s" % (p.ljust(longest_path), a)
> +
> +  def DoConfdRequestReply(self, req):
> +    """Send request to Confd and await all responses."""
> +    self.confd_client.SendRequest(req, async=False)
> +    if not self.confd_client.ReceiveReply():
> +      Err("Did not receive all expected confd replies")
> +    return self.store_callback.GetResponse(req.rsalt)
> +
> +def main():
> +  """Application entry point.
> +
> +  """
> +  QueryClient().Run()
> +
> +
> +if __name__ == "__main__":
> +  main()
> --
> 2.0.0.526.g5318336
>

Thanks,
Michele

Reply via email to