Statistics
| Branch: | Tag: | Revision:

root / lib / confd / querylib.py @ cea881e5

History | View | Annotate | Download (8.8 kB)

1 d73ef63f Michael Hanselmann
#
2 e16e4824 Guido Trotter
#
3 e16e4824 Guido Trotter
4 e16e4824 Guido Trotter
# Copyright (C) 2009, Google Inc.
5 e16e4824 Guido Trotter
#
6 e16e4824 Guido Trotter
# This program is free software; you can redistribute it and/or modify
7 e16e4824 Guido Trotter
# it under the terms of the GNU General Public License as published by
8 e16e4824 Guido Trotter
# the Free Software Foundation; either version 2 of the License, or
9 e16e4824 Guido Trotter
# (at your option) any later version.
10 e16e4824 Guido Trotter
#
11 e16e4824 Guido Trotter
# This program is distributed in the hope that it will be useful, but
12 e16e4824 Guido Trotter
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 e16e4824 Guido Trotter
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 e16e4824 Guido Trotter
# General Public License for more details.
15 e16e4824 Guido Trotter
#
16 e16e4824 Guido Trotter
# You should have received a copy of the GNU General Public License
17 e16e4824 Guido Trotter
# along with this program; if not, write to the Free Software
18 e16e4824 Guido Trotter
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 e16e4824 Guido Trotter
# 02110-1301, USA.
20 e16e4824 Guido Trotter
21 e16e4824 Guido Trotter
22 e16e4824 Guido Trotter
"""Ganeti configuration daemon queries library.
23 e16e4824 Guido Trotter

24 e16e4824 Guido Trotter
"""
25 e16e4824 Guido Trotter
26 53bd7366 Guido Trotter
import logging
27 53bd7366 Guido Trotter
28 e16e4824 Guido Trotter
from ganeti import constants
29 e16e4824 Guido Trotter
30 d73ef63f Michael Hanselmann
31 7189e790 Guido Trotter
# constants for some common errors to return from a query
32 7189e790 Guido Trotter
QUERY_UNKNOWN_ENTRY_ERROR = (constants.CONFD_REPL_STATUS_ERROR,
33 7189e790 Guido Trotter
                             constants.CONFD_ERROR_UNKNOWN_ENTRY)
34 7189e790 Guido Trotter
QUERY_INTERNAL_ERROR = (constants.CONFD_REPL_STATUS_ERROR,
35 7189e790 Guido Trotter
                        constants.CONFD_ERROR_INTERNAL)
36 19351457 Guido Trotter
QUERY_ARGUMENT_ERROR = (constants.CONFD_REPL_STATUS_ERROR,
37 19351457 Guido Trotter
                        constants.CONFD_ERROR_ARGUMENT)
38 e16e4824 Guido Trotter
39 d73ef63f Michael Hanselmann
40 e16e4824 Guido Trotter
class ConfdQuery(object):
41 e16e4824 Guido Trotter
  """Confd Query base class.
42 e16e4824 Guido Trotter

43 e16e4824 Guido Trotter
  """
44 e16e4824 Guido Trotter
  def __init__(self, reader):
45 e16e4824 Guido Trotter
    """Constructor for Confd Query
46 e16e4824 Guido Trotter

47 e16e4824 Guido Trotter
    @type reader: L{ssconf.SimpleConfigReader}
48 e16e4824 Guido Trotter
    @param reader: ConfigReader to use to access the config
49 e16e4824 Guido Trotter

50 e16e4824 Guido Trotter
    """
51 e16e4824 Guido Trotter
    self.reader = reader
52 e16e4824 Guido Trotter
53 2d54e29c Iustin Pop
  def Exec(self, query): # pylint: disable-msg=R0201,W0613
54 e16e4824 Guido Trotter
    """Process a single UDP request from a client.
55 e16e4824 Guido Trotter

56 e16e4824 Guido Trotter
    Different queries should override this function, which by defaults returns
57 e16e4824 Guido Trotter
    a "non-implemented" answer.
58 e16e4824 Guido Trotter

59 e16e4824 Guido Trotter
    @type query: (undefined)
60 e16e4824 Guido Trotter
    @param query: ConfdRequest 'query' field
61 e16e4824 Guido Trotter
    @rtype: (integer, undefined)
62 e16e4824 Guido Trotter
    @return: status and answer to give to the client
63 e16e4824 Guido Trotter

64 e16e4824 Guido Trotter
    """
65 e16e4824 Guido Trotter
    status = constants.CONFD_REPL_STATUS_NOTIMPLEMENTED
66 e16e4824 Guido Trotter
    answer = 'not implemented'
67 e16e4824 Guido Trotter
    return status, answer
68 e16e4824 Guido Trotter
69 e16e4824 Guido Trotter
70 e16e4824 Guido Trotter
class PingQuery(ConfdQuery):
71 e16e4824 Guido Trotter
  """An empty confd query.
72 e16e4824 Guido Trotter

73 4d4a651d Michael Hanselmann
  It will return success on an empty argument, and an error on any other
74 4d4a651d Michael Hanselmann
  argument.
75 e16e4824 Guido Trotter

76 e16e4824 Guido Trotter
  """
77 e16e4824 Guido Trotter
  def Exec(self, query):
78 0bc8432b Guido Trotter
    """PingQuery main execution.
79 e16e4824 Guido Trotter

80 e16e4824 Guido Trotter
    """
81 e16e4824 Guido Trotter
    if query is None:
82 e16e4824 Guido Trotter
      status = constants.CONFD_REPL_STATUS_OK
83 e16e4824 Guido Trotter
      answer = 'ok'
84 e16e4824 Guido Trotter
    else:
85 e16e4824 Guido Trotter
      status = constants.CONFD_REPL_STATUS_ERROR
86 e16e4824 Guido Trotter
      answer = 'non-empty ping query'
87 e16e4824 Guido Trotter
88 e16e4824 Guido Trotter
    return status, answer
89 e16e4824 Guido Trotter
90 d73ef63f Michael Hanselmann
91 48166551 Guido Trotter
class ClusterMasterQuery(ConfdQuery):
92 48166551 Guido Trotter
  """Cluster master query.
93 48166551 Guido Trotter

94 48166551 Guido Trotter
  It accepts no arguments, and returns the current cluster master.
95 48166551 Guido Trotter

96 48166551 Guido Trotter
  """
97 43dc8496 Guido Trotter
  def _GetMasterNode(self):
98 43dc8496 Guido Trotter
    return self.reader.GetMasterNode()
99 43dc8496 Guido Trotter
100 48166551 Guido Trotter
  def Exec(self, query):
101 48166551 Guido Trotter
    """ClusterMasterQuery main execution
102 48166551 Guido Trotter

103 48166551 Guido Trotter
    """
104 250554a9 Guido Trotter
    if isinstance(query, dict):
105 250554a9 Guido Trotter
      if constants.CONFD_REQQ_FIELDS in query:
106 250554a9 Guido Trotter
        status = constants.CONFD_REPL_STATUS_OK
107 250554a9 Guido Trotter
        req_fields = query[constants.CONFD_REQQ_FIELDS]
108 250554a9 Guido Trotter
        if not isinstance(req_fields, (list, tuple)):
109 250554a9 Guido Trotter
          logging.debug("FIELDS request should be a list")
110 250554a9 Guido Trotter
          return QUERY_ARGUMENT_ERROR
111 250554a9 Guido Trotter
112 250554a9 Guido Trotter
        answer = []
113 250554a9 Guido Trotter
        for field in req_fields:
114 250554a9 Guido Trotter
          if field == constants.CONFD_REQFIELD_NAME:
115 43dc8496 Guido Trotter
            answer.append(self._GetMasterNode())
116 250554a9 Guido Trotter
          elif field == constants.CONFD_REQFIELD_IP:
117 250554a9 Guido Trotter
            answer.append(self.reader.GetMasterIP())
118 43dc8496 Guido Trotter
          elif field == constants.CONFD_REQFIELD_MNODE_PIP:
119 43dc8496 Guido Trotter
            answer.append(self.reader.GetNodePrimaryIp(self._GetMasterNode()))
120 250554a9 Guido Trotter
      else:
121 250554a9 Guido Trotter
        logging.debug("missing FIELDS in query dict")
122 250554a9 Guido Trotter
        return QUERY_ARGUMENT_ERROR
123 250554a9 Guido Trotter
    elif not query:
124 48166551 Guido Trotter
      status = constants.CONFD_REPL_STATUS_OK
125 48166551 Guido Trotter
      answer = self.reader.GetMasterNode()
126 48166551 Guido Trotter
    else:
127 250554a9 Guido Trotter
      logging.debug("Invalid master query argument: not dict or empty")
128 250554a9 Guido Trotter
      return QUERY_ARGUMENT_ERROR
129 48166551 Guido Trotter
130 48166551 Guido Trotter
    return status, answer
131 48166551 Guido Trotter
132 6daf26a0 Guido Trotter
133 6daf26a0 Guido Trotter
class NodeRoleQuery(ConfdQuery):
134 0bc8432b Guido Trotter
  """A query for the role of a node.
135 6daf26a0 Guido Trotter

136 0bc8432b Guido Trotter
  It will return one of CONFD_NODE_ROLE_*, or an error for non-existing nodes.
137 6daf26a0 Guido Trotter

138 6daf26a0 Guido Trotter
  """
139 6daf26a0 Guido Trotter
  def Exec(self, query):
140 6daf26a0 Guido Trotter
    """EmptyQuery main execution
141 6daf26a0 Guido Trotter

142 6daf26a0 Guido Trotter
    """
143 6daf26a0 Guido Trotter
    node = query
144 6daf26a0 Guido Trotter
    if self.reader.GetMasterNode() == node:
145 6daf26a0 Guido Trotter
      status = constants.CONFD_REPL_STATUS_OK
146 6daf26a0 Guido Trotter
      answer = constants.CONFD_NODE_ROLE_MASTER
147 6daf26a0 Guido Trotter
      return status, answer
148 6daf26a0 Guido Trotter
    flags = self.reader.GetNodeStatusFlags(node)
149 6daf26a0 Guido Trotter
    if flags is None:
150 7189e790 Guido Trotter
      return QUERY_UNKNOWN_ENTRY_ERROR
151 6daf26a0 Guido Trotter
152 6daf26a0 Guido Trotter
    master_candidate, drained, offline = flags
153 6daf26a0 Guido Trotter
    if master_candidate:
154 6daf26a0 Guido Trotter
      answer = constants.CONFD_NODE_ROLE_CANDIDATE
155 6daf26a0 Guido Trotter
    elif drained:
156 6daf26a0 Guido Trotter
      answer = constants.CONFD_NODE_ROLE_DRAINED
157 6daf26a0 Guido Trotter
    elif offline:
158 6daf26a0 Guido Trotter
      answer = constants.CONFD_NODE_ROLE_OFFLINE
159 6daf26a0 Guido Trotter
    else:
160 6daf26a0 Guido Trotter
      answer = constants.CONFD_NODE_ROLE_REGULAR
161 6daf26a0 Guido Trotter
162 6daf26a0 Guido Trotter
    return constants.CONFD_REPL_STATUS_OK, answer
163 6daf26a0 Guido Trotter
164 53bd7366 Guido Trotter
165 53bd7366 Guido Trotter
class InstanceIpToNodePrimaryIpQuery(ConfdQuery):
166 95b487bb Flavio Silvestrow
  """A query for the location of one or more instance's ips.
167 53bd7366 Guido Trotter

168 53bd7366 Guido Trotter
  """
169 53bd7366 Guido Trotter
  def Exec(self, query):
170 0bc8432b Guido Trotter
    """InstanceIpToNodePrimaryIpQuery main execution.
171 53bd7366 Guido Trotter

172 23057d29 Michael Hanselmann
    @type query: string or dict
173 23057d29 Michael Hanselmann
    @param query: instance ip or dict containing:
174 23057d29 Michael Hanselmann
                  constants.CONFD_REQQ_LINK: nic link (optional)
175 23057d29 Michael Hanselmann
                  constants.CONFD_REQQ_IPLIST: list of ips
176 23057d29 Michael Hanselmann
                  constants.CONFD_REQQ_IP: single ip
177 23057d29 Michael Hanselmann
                  (one IP type request is mandatory)
178 23057d29 Michael Hanselmann
    @rtype: (integer, ...)
179 23057d29 Michael Hanselmann
    @return: ((status, answer) or (success, [(status, answer)...])
180 23057d29 Michael Hanselmann

181 53bd7366 Guido Trotter
    """
182 19351457 Guido Trotter
    if isinstance(query, dict):
183 19351457 Guido Trotter
      if constants.CONFD_REQQ_IP in query:
184 19351457 Guido Trotter
        instances_list = [query[constants.CONFD_REQQ_IP]]
185 19351457 Guido Trotter
        mode = constants.CONFD_REQQ_IP
186 19351457 Guido Trotter
      elif constants.CONFD_REQQ_IPLIST in query:
187 19351457 Guido Trotter
        instances_list = query[constants.CONFD_REQQ_IPLIST]
188 19351457 Guido Trotter
        mode = constants.CONFD_REQQ_IPLIST
189 19351457 Guido Trotter
      else:
190 19351457 Guido Trotter
        logging.debug("missing IP or IPLIST in query dict")
191 19351457 Guido Trotter
        return QUERY_ARGUMENT_ERROR
192 19351457 Guido Trotter
193 19351457 Guido Trotter
      if constants.CONFD_REQQ_LINK in query:
194 19351457 Guido Trotter
        network_link = query[constants.CONFD_REQQ_LINK]
195 19351457 Guido Trotter
      else:
196 19351457 Guido Trotter
        network_link = None # default will be used
197 19351457 Guido Trotter
    elif isinstance(query, basestring):
198 19351457 Guido Trotter
      # 2.1 beta1 and beta2 mode, to be deprecated for 2.2
199 95b487bb Flavio Silvestrow
      instances_list = [query]
200 19351457 Guido Trotter
      network_link = None
201 19351457 Guido Trotter
      mode = constants.CONFD_REQQ_IP
202 19351457 Guido Trotter
    else:
203 07b8a2b5 Iustin Pop
      logging.debug("Invalid query argument type for: %s", query)
204 19351457 Guido Trotter
      return QUERY_ARGUMENT_ERROR
205 19351457 Guido Trotter
206 95b487bb Flavio Silvestrow
    pnodes_list = []
207 95b487bb Flavio Silvestrow
208 95b487bb Flavio Silvestrow
    for instance_ip in instances_list:
209 19351457 Guido Trotter
      if not isinstance(instance_ip, basestring):
210 07b8a2b5 Iustin Pop
        logging.debug("Invalid IP type for: %s", instance_ip)
211 19351457 Guido Trotter
        return QUERY_ARGUMENT_ERROR
212 19351457 Guido Trotter
213 19351457 Guido Trotter
      instance = self.reader.GetInstanceByLinkIp(instance_ip, network_link)
214 95b487bb Flavio Silvestrow
      if not instance:
215 07b8a2b5 Iustin Pop
        logging.debug("Unknown instance IP: %s", instance_ip)
216 95b487bb Flavio Silvestrow
        pnodes_list.append(QUERY_UNKNOWN_ENTRY_ERROR)
217 95b487bb Flavio Silvestrow
        continue
218 53bd7366 Guido Trotter
219 95b487bb Flavio Silvestrow
      pnode = self.reader.GetInstancePrimaryNode(instance)
220 95b487bb Flavio Silvestrow
      if not pnode:
221 95b487bb Flavio Silvestrow
        logging.error("Instance '%s' doesn't have an associated primary"
222 07b8a2b5 Iustin Pop
                      " node", instance)
223 95b487bb Flavio Silvestrow
        pnodes_list.append(QUERY_INTERNAL_ERROR)
224 95b487bb Flavio Silvestrow
        continue
225 53bd7366 Guido Trotter
226 95b487bb Flavio Silvestrow
      pnode_primary_ip = self.reader.GetNodePrimaryIp(pnode)
227 95b487bb Flavio Silvestrow
      if not pnode_primary_ip:
228 95b487bb Flavio Silvestrow
        logging.error("Primary node '%s' doesn't have an associated"
229 07b8a2b5 Iustin Pop
                      " primary IP", pnode)
230 95b487bb Flavio Silvestrow
        pnodes_list.append(QUERY_INTERNAL_ERROR)
231 95b487bb Flavio Silvestrow
        continue
232 53bd7366 Guido Trotter
233 95b487bb Flavio Silvestrow
      pnodes_list.append((constants.CONFD_REPL_STATUS_OK, pnode_primary_ip))
234 95b487bb Flavio Silvestrow
235 07b8a2b5 Iustin Pop
    # If a single ip was requested, return a single answer, otherwise
236 07b8a2b5 Iustin Pop
    # the whole list, with a success status (since each entry has its
237 07b8a2b5 Iustin Pop
    # own success/failure)
238 19351457 Guido Trotter
    if mode == constants.CONFD_REQQ_IP:
239 95b487bb Flavio Silvestrow
      return pnodes_list[0]
240 95b487bb Flavio Silvestrow
241 95b487bb Flavio Silvestrow
    return constants.CONFD_REPL_STATUS_OK, pnodes_list
242 efbb4fd2 Luca Bigliardi
243 efbb4fd2 Luca Bigliardi
244 efbb4fd2 Luca Bigliardi
class NodesPipsQuery(ConfdQuery):
245 efbb4fd2 Luca Bigliardi
  """A query for nodes primary IPs.
246 efbb4fd2 Luca Bigliardi

247 efbb4fd2 Luca Bigliardi
  It returns the list of nodes primary IPs.
248 efbb4fd2 Luca Bigliardi

249 efbb4fd2 Luca Bigliardi
  """
250 efbb4fd2 Luca Bigliardi
  def Exec(self, query):
251 efbb4fd2 Luca Bigliardi
    """NodesPipsQuery main execution.
252 efbb4fd2 Luca Bigliardi

253 efbb4fd2 Luca Bigliardi
    """
254 efbb4fd2 Luca Bigliardi
    if query is None:
255 efbb4fd2 Luca Bigliardi
      status = constants.CONFD_REPL_STATUS_OK
256 efbb4fd2 Luca Bigliardi
      answer = self.reader.GetNodesPrimaryIps()
257 efbb4fd2 Luca Bigliardi
    else:
258 efbb4fd2 Luca Bigliardi
      status = constants.CONFD_REPL_STATUS_ERROR
259 efbb4fd2 Luca Bigliardi
      answer = "non-empty node primary IPs query"
260 efbb4fd2 Luca Bigliardi
261 efbb4fd2 Luca Bigliardi
    return status, answer
262 efbb4fd2 Luca Bigliardi
263 efbb4fd2 Luca Bigliardi
264 efbb4fd2 Luca Bigliardi
class MasterCandidatesPipsQuery(ConfdQuery):
265 efbb4fd2 Luca Bigliardi
  """A query for master candidates primary IPs.
266 efbb4fd2 Luca Bigliardi

267 efbb4fd2 Luca Bigliardi
  It returns the list of master candidates primary IPs.
268 efbb4fd2 Luca Bigliardi

269 efbb4fd2 Luca Bigliardi
  """
270 efbb4fd2 Luca Bigliardi
  def Exec(self, query):
271 efbb4fd2 Luca Bigliardi
    """MasterCandidatesPipsQuery main execution.
272 efbb4fd2 Luca Bigliardi

273 efbb4fd2 Luca Bigliardi
    """
274 efbb4fd2 Luca Bigliardi
    if query is None:
275 efbb4fd2 Luca Bigliardi
      status = constants.CONFD_REPL_STATUS_OK
276 efbb4fd2 Luca Bigliardi
      answer = self.reader.GetMasterCandidatesPrimaryIps()
277 efbb4fd2 Luca Bigliardi
    else:
278 efbb4fd2 Luca Bigliardi
      status = constants.CONFD_REPL_STATUS_ERROR
279 efbb4fd2 Luca Bigliardi
      answer = "non-empty master candidates primary IPs query"
280 efbb4fd2 Luca Bigliardi
281 efbb4fd2 Luca Bigliardi
    return status, answer
282 efbb4fd2 Luca Bigliardi
283 d01ae714 Luca Bigliardi
284 d01ae714 Luca Bigliardi
class InstancesIpsQuery(ConfdQuery):
285 d01ae714 Luca Bigliardi
  """A query for instances IPs.
286 d01ae714 Luca Bigliardi

287 23824641 Luca Bigliardi
  It returns the list of IPs of NICs connected to the requested link or all the
288 23824641 Luca Bigliardi
  instances IPs if no link is submitted.
289 d01ae714 Luca Bigliardi

290 d01ae714 Luca Bigliardi
  """
291 d01ae714 Luca Bigliardi
  def Exec(self, query):
292 d01ae714 Luca Bigliardi
    """InstancesIpsQuery main execution.
293 d01ae714 Luca Bigliardi

294 d01ae714 Luca Bigliardi
    """
295 23824641 Luca Bigliardi
    link = query
296 23824641 Luca Bigliardi
    status = constants.CONFD_REPL_STATUS_OK
297 23824641 Luca Bigliardi
    answer = self.reader.GetInstancesIps(link)
298 d01ae714 Luca Bigliardi
299 d01ae714 Luca Bigliardi
    return status, answer