-#!/usr/bin/python
+#
#
# Copyright (C) 2009, Google Inc.
from ganeti import errors
from ganeti import utils
from ganeti import serializer
+from ganeti import ssconf
+
+from ganeti.confd import querylib
class ConfdProcessor(object):
"""A processor for confd requests.
+ @ivar reader: confd SimpleConfigReader
+ @ivar disabled: whether confd serving is disabled
+
"""
DISPATCH_TABLE = {
- }
-
- def __init__(self, reader):
+ constants.CONFD_REQ_PING: querylib.PingQuery,
+ constants.CONFD_REQ_NODE_ROLE_BYNAME: querylib.NodeRoleQuery,
+ constants.CONFD_REQ_NODE_PIP_BY_INSTANCE_IP:
+ querylib.InstanceIpToNodePrimaryIpQuery,
+ constants.CONFD_REQ_CLUSTER_MASTER: querylib.ClusterMasterQuery,
+ constants.CONFD_REQ_NODE_PIP_LIST: querylib.NodesPipsQuery,
+ constants.CONFD_REQ_MC_PIP_LIST: querylib.MasterCandidatesPipsQuery,
+ constants.CONFD_REQ_INSTANCES_IPS_LIST: querylib.InstancesIpsQuery,
+ }
+
+ def __init__(self):
"""Constructor for ConfdProcessor
- @type reader: L{ssconf.SimpleConfigReader}
- @param reader: ConfigReader to use to access the config
-
"""
- self.reader = reader
+ self.disabled = True
self.hmac_key = utils.ReadFile(constants.HMAC_CLUSTER_KEY)
+ self.reader = None
+ assert \
+ not constants.CONFD_REQS.symmetric_difference(self.DISPATCH_TABLE), \
+ "DISPATCH_TABLE is unaligned with CONFD_REQS"
+
+ def Enable(self):
+ try:
+ self.reader = ssconf.SimpleConfigReader()
+ self.disabled = False
+ except errors.ConfigurationError:
+ self.disabled = True
+ raise
+
+ def Disable(self):
+ self.disabled = True
+ self.reader = None
def ExecQuery(self, payload_in, ip, port):
"""Process a single UDP request from a client.
@type port: source port
"""
+ if self.disabled:
+ logging.debug('Confd is disabled. Ignoring query.')
+ return
try:
request = self.ExtractRequest(payload_in)
reply, rsalt = self.ProcessRequest(request)
payload_out = self.PackReply(reply, rsalt)
return payload_out
except errors.ConfdRequestError, err:
- logging.info('Ignoring broken query from %s:%d: %s' % (ip, port, err))
+ logging.info('Ignoring broken query from %s:%d: %s', ip, port, err)
return None
def ExtractRequest(self, payload):
"""
current_time = time.time()
- logging.debug("Extracting request with size: %d" % (len(payload)))
+ logging.debug("Extracting request with size: %d", len(payload))
try:
(message, salt) = serializer.LoadSigned(payload, self.hmac_key)
except errors.SignatureError, err:
@return: tuple of reply and salt to add to the signature
"""
- logging.debug("Processing request: %s" % request)
+ logging.debug("Processing request: %s", request)
if request.protocol != constants.CONFD_PROTOCOL_VERSION:
msg = "wrong protocol version %d" % request.protocol
raise errors.ConfdRequestError(msg)
msg = "missing requested salt"
raise errors.ConfdRequestError(msg)
- if request.type not in self.DISPATCH_TABLE:
- answer = 'not implemented'
- status = constants.CONFD_REPL_STATUS_NOTIMPLEMENTED
- reply = objects.ConfdReply(
- protocol=constants.CONFD_PROTOCOL_VERSION,
- status=status,
- answer=answer,
- )
- else:
- # TODO: actually dispatch queries to some classes to handle them
- assert False, "DISPATCH_TABLE is populated but handler is not"
+ query_object = self.DISPATCH_TABLE[request.type](self.reader)
+ status, answer = query_object.Exec(request.query)
+ reply = objects.ConfdReply(
+ protocol=constants.CONFD_PROTOCOL_VERSION,
+ status=status,
+ answer=answer,
+ serial=self.reader.GetConfigSerialNo(),
+ )
- logging.debug("Sending reply: %s" % reply)
+ logging.debug("Sending reply: %s", reply)
return (reply, rsalt)
"""
return serializer.DumpSigned(reply.ToDict(), self.hmac_key, rsalt)
-