4 # Copyright (C) 2009, Google Inc.
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful, but
12 # WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 # General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 """Ganeti configuration daemon queries library.
28 from ganeti import constants
31 # constants for some common errors to return from a query
32 QUERY_UNKNOWN_ENTRY_ERROR = (constants.CONFD_REPL_STATUS_ERROR,
33 constants.CONFD_ERROR_UNKNOWN_ENTRY)
34 QUERY_INTERNAL_ERROR = (constants.CONFD_REPL_STATUS_ERROR,
35 constants.CONFD_ERROR_INTERNAL)
38 class ConfdQuery(object):
39 """Confd Query base class.
42 def __init__(self, reader):
43 """Constructor for Confd Query
45 @type reader: L{ssconf.SimpleConfigReader}
46 @param reader: ConfigReader to use to access the config
51 def Exec(self, query):
52 """Process a single UDP request from a client.
54 Different queries should override this function, which by defaults returns
55 a "non-implemented" answer.
57 @type query: (undefined)
58 @param query: ConfdRequest 'query' field
59 @rtype: (integer, undefined)
60 @return: status and answer to give to the client
63 status = constants.CONFD_REPL_STATUS_NOTIMPLEMENTED
64 answer = 'not implemented'
68 class PingQuery(ConfdQuery):
69 """An empty confd query.
71 It will return success on an empty argument, and an error on any other
75 def Exec(self, query):
76 """PingQuery main execution.
80 status = constants.CONFD_REPL_STATUS_OK
83 status = constants.CONFD_REPL_STATUS_ERROR
84 answer = 'non-empty ping query'
89 class ClusterMasterQuery(ConfdQuery):
90 """Cluster master query.
92 It accepts no arguments, and returns the current cluster master.
95 def Exec(self, query):
96 """ClusterMasterQuery main execution
100 status = constants.CONFD_REPL_STATUS_OK
101 answer = self.reader.GetMasterNode()
103 status = constants.CONFD_REPL_STATUS_ERROR
104 answer = 'master query accepts no query argument'
106 return status, answer
109 class NodeRoleQuery(ConfdQuery):
110 """A query for the role of a node.
112 It will return one of CONFD_NODE_ROLE_*, or an error for non-existing nodes.
115 def Exec(self, query):
116 """EmptyQuery main execution
120 if self.reader.GetMasterNode() == node:
121 status = constants.CONFD_REPL_STATUS_OK
122 answer = constants.CONFD_NODE_ROLE_MASTER
123 return status, answer
124 flags = self.reader.GetNodeStatusFlags(node)
126 return QUERY_UNKNOWN_ENTRY_ERROR
128 master_candidate, drained, offline = flags
130 answer = constants.CONFD_NODE_ROLE_CANDIDATE
132 answer = constants.CONFD_NODE_ROLE_DRAINED
134 answer = constants.CONFD_NODE_ROLE_OFFLINE
136 answer = constants.CONFD_NODE_ROLE_REGULAR
138 return constants.CONFD_REPL_STATUS_OK, answer
141 class InstanceIpToNodePrimaryIpQuery(ConfdQuery):
142 """A query for the location of an instance's ip.
144 It returns the primary ip of the node hosting the instance having the
145 requested ip address, or an error if no such address is known.
148 def Exec(self, query):
149 """InstanceIpToNodePrimaryIpQuery main execution.
153 instance = self.reader.GetInstanceByIp(instance_ip)
155 return QUERY_UNKNOWN_ENTRY_ERROR
157 pnode = self.reader.GetInstancePrimaryNode(instance)
159 # this shouldn't happen
160 logging.error("Internal configuration inconsistent (instance-to-pnode)")
161 return QUERY_INTERNAL_ERROR
163 pnode_primary_ip = self.reader.GetNodePrimaryIp(pnode)
164 if pnode_primary_ip is None:
165 # this shouldn't happen
166 logging.error("Internal configuration inconsistent (node-to-primary-ip)")
167 return QUERY_INTERNAL_ERROR
169 return constants.CONFD_REPL_STATUS_OK, pnode_primary_ip
172 class NodesPipsQuery(ConfdQuery):
173 """A query for nodes primary IPs.
175 It returns the list of nodes primary IPs.
178 def Exec(self, query):
179 """NodesPipsQuery main execution.
183 status = constants.CONFD_REPL_STATUS_OK
184 answer = self.reader.GetNodesPrimaryIps()
186 status = constants.CONFD_REPL_STATUS_ERROR
187 answer = "non-empty node primary IPs query"
189 return status, answer
192 class MasterCandidatesPipsQuery(ConfdQuery):
193 """A query for master candidates primary IPs.
195 It returns the list of master candidates primary IPs.
198 def Exec(self, query):
199 """MasterCandidatesPipsQuery main execution.
203 status = constants.CONFD_REPL_STATUS_OK
204 answer = self.reader.GetMasterCandidatesPrimaryIps()
206 status = constants.CONFD_REPL_STATUS_ERROR
207 answer = "non-empty master candidates primary IPs query"
209 return status, answer