blob: d87a7d161bb3da04092cca2e2e80ae142424b0b1 [file] [log] [blame]
#!/usr/bin/python
#
# Copyright (C) 2014 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.
"""Tool to query the cluster configuration over RConfD
"""
# tool name shouldn't follow module naming.
# pylint: disable=C0103
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>")
]
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.
"""
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()