X-Git-Url: https://code.grnet.gr/git/ganeti-local/blobdiff_plain/cd195419a63977001dcd4fb9dcc0b96bbed13da9..e9ed4f2e29d5de9a28f060bfc0a6eaf518be7cb0:/lib/confd/querylib.py diff --git a/lib/confd/querylib.py b/lib/confd/querylib.py index 5e7370e..e231a14 100644 --- a/lib/confd/querylib.py +++ b/lib/confd/querylib.py @@ -1,7 +1,7 @@ # # -# Copyright (C) 2009, Google Inc. +# Copyright (C) 2009 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 @@ -33,6 +33,8 @@ QUERY_UNKNOWN_ENTRY_ERROR = (constants.CONFD_REPL_STATUS_ERROR, constants.CONFD_ERROR_UNKNOWN_ENTRY) QUERY_INTERNAL_ERROR = (constants.CONFD_REPL_STATUS_ERROR, constants.CONFD_ERROR_INTERNAL) +QUERY_ARGUMENT_ERROR = (constants.CONFD_REPL_STATUS_ERROR, + constants.CONFD_ERROR_ARGUMENT) class ConfdQuery(object): @@ -48,7 +50,7 @@ class ConfdQuery(object): """ self.reader = reader - def Exec(self, query): + def Exec(self, query): # pylint: disable=R0201,W0613 """Process a single UDP request from a client. Different queries should override this function, which by defaults returns @@ -92,16 +94,38 @@ class ClusterMasterQuery(ConfdQuery): It accepts no arguments, and returns the current cluster master. """ + def _GetMasterNode(self): + return self.reader.GetMasterNode() + def Exec(self, query): """ClusterMasterQuery main execution """ - if query is None: + if isinstance(query, dict): + if constants.CONFD_REQQ_FIELDS in query: + status = constants.CONFD_REPL_STATUS_OK + req_fields = query[constants.CONFD_REQQ_FIELDS] + if not isinstance(req_fields, (list, tuple)): + logging.debug("FIELDS request should be a list") + return QUERY_ARGUMENT_ERROR + + answer = [] + for field in req_fields: + if field == constants.CONFD_REQFIELD_NAME: + answer.append(self._GetMasterNode()) + elif field == constants.CONFD_REQFIELD_IP: + answer.append(self.reader.GetMasterIP()) + elif field == constants.CONFD_REQFIELD_MNODE_PIP: + answer.append(self.reader.GetNodePrimaryIp(self._GetMasterNode())) + else: + logging.debug("missing FIELDS in query dict") + return QUERY_ARGUMENT_ERROR + elif not query: status = constants.CONFD_REPL_STATUS_OK answer = self.reader.GetMasterNode() else: - status = constants.CONFD_REPL_STATUS_ERROR - answer = 'master query accepts no query argument' + logging.debug("Invalid master query argument: not dict or empty") + return QUERY_ARGUMENT_ERROR return status, answer @@ -141,50 +165,72 @@ class NodeRoleQuery(ConfdQuery): class InstanceIpToNodePrimaryIpQuery(ConfdQuery): """A query for the location of one or more instance's ips. - Given a list of instance IPs, returns an ordered list with the same - number of elements as the input. Each element of the list is a tuple - containing the status (success or failure) and the content of the - query (IP of the primary node if successful, error constant if not). - - If a string (instance's IP) is given instead of a list it will return - a single tuple, as opposed to a 1-element list containing that tuple. - """ def Exec(self, query): """InstanceIpToNodePrimaryIpQuery main execution. + @type query: string or dict + @param query: instance ip or dict containing: + constants.CONFD_REQQ_LINK: nic link (optional) + constants.CONFD_REQQ_IPLIST: list of ips + constants.CONFD_REQQ_IP: single ip + (one IP type request is mandatory) + @rtype: (integer, ...) + @return: ((status, answer) or (success, [(status, answer)...]) + """ - if isinstance(query, list): - instances_list = query + if isinstance(query, dict): + if constants.CONFD_REQQ_IP in query: + instances_list = [query[constants.CONFD_REQQ_IP]] + mode = constants.CONFD_REQQ_IP + elif constants.CONFD_REQQ_IPLIST in query: + instances_list = query[constants.CONFD_REQQ_IPLIST] + mode = constants.CONFD_REQQ_IPLIST + else: + logging.debug("missing IP or IPLIST in query dict") + return QUERY_ARGUMENT_ERROR + + if constants.CONFD_REQQ_LINK in query: + network_link = query[constants.CONFD_REQQ_LINK] + else: + network_link = None # default will be used else: - instances_list = [query] + logging.debug("Invalid query argument type for: %s", query) + return QUERY_ARGUMENT_ERROR + pnodes_list = [] for instance_ip in instances_list: - instance = self.reader.GetInstanceByLinkIp(instance_ip, None) + if not isinstance(instance_ip, basestring): + logging.debug("Invalid IP type for: %s", instance_ip) + return QUERY_ARGUMENT_ERROR + + instance = self.reader.GetInstanceByLinkIp(instance_ip, network_link) if not instance: - logging.debug("Invalid instance IP: %s" % instance) + logging.debug("Unknown instance IP: %s", instance_ip) pnodes_list.append(QUERY_UNKNOWN_ENTRY_ERROR) continue pnode = self.reader.GetInstancePrimaryNode(instance) if not pnode: logging.error("Instance '%s' doesn't have an associated primary" - " node" % instance) + " node", instance) pnodes_list.append(QUERY_INTERNAL_ERROR) continue pnode_primary_ip = self.reader.GetNodePrimaryIp(pnode) if not pnode_primary_ip: logging.error("Primary node '%s' doesn't have an associated" - " primary IP" % pnode) + " primary IP", pnode) pnodes_list.append(QUERY_INTERNAL_ERROR) continue pnodes_list.append((constants.CONFD_REPL_STATUS_OK, pnode_primary_ip)) - # If input was a string, return a tuple instead of a 1-element list - if isinstance(query, basestring): + # If a single ip was requested, return a single answer, otherwise + # the whole list, with a success status (since each entry has its + # own success/failure) + if mode == constants.CONFD_REQQ_IP: return pnodes_list[0] return constants.CONFD_REPL_STATUS_OK, pnodes_list