Statistics
| Branch: | Tag: | Revision:

root / lib / confd / querylib.py @ 19351457

History | View | Annotate | Download (7.9 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 e16e4824 Guido Trotter
  def Exec(self, query):
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 48166551 Guido Trotter
  def Exec(self, query):
98 48166551 Guido Trotter
    """ClusterMasterQuery main execution
99 48166551 Guido Trotter

100 48166551 Guido Trotter
    """
101 48166551 Guido Trotter
    if query is None:
102 48166551 Guido Trotter
      status = constants.CONFD_REPL_STATUS_OK
103 48166551 Guido Trotter
      answer = self.reader.GetMasterNode()
104 48166551 Guido Trotter
    else:
105 48166551 Guido Trotter
      status = constants.CONFD_REPL_STATUS_ERROR
106 48166551 Guido Trotter
      answer = 'master query accepts no query argument'
107 48166551 Guido Trotter
108 48166551 Guido Trotter
    return status, answer
109 48166551 Guido Trotter
110 6daf26a0 Guido Trotter
111 6daf26a0 Guido Trotter
class NodeRoleQuery(ConfdQuery):
112 0bc8432b Guido Trotter
  """A query for the role of a node.
113 6daf26a0 Guido Trotter

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

116 6daf26a0 Guido Trotter
  """
117 6daf26a0 Guido Trotter
  def Exec(self, query):
118 6daf26a0 Guido Trotter
    """EmptyQuery main execution
119 6daf26a0 Guido Trotter

120 6daf26a0 Guido Trotter
    """
121 6daf26a0 Guido Trotter
    node = query
122 6daf26a0 Guido Trotter
    if self.reader.GetMasterNode() == node:
123 6daf26a0 Guido Trotter
      status = constants.CONFD_REPL_STATUS_OK
124 6daf26a0 Guido Trotter
      answer = constants.CONFD_NODE_ROLE_MASTER
125 6daf26a0 Guido Trotter
      return status, answer
126 6daf26a0 Guido Trotter
    flags = self.reader.GetNodeStatusFlags(node)
127 6daf26a0 Guido Trotter
    if flags is None:
128 7189e790 Guido Trotter
      return QUERY_UNKNOWN_ENTRY_ERROR
129 6daf26a0 Guido Trotter
130 6daf26a0 Guido Trotter
    master_candidate, drained, offline = flags
131 6daf26a0 Guido Trotter
    if master_candidate:
132 6daf26a0 Guido Trotter
      answer = constants.CONFD_NODE_ROLE_CANDIDATE
133 6daf26a0 Guido Trotter
    elif drained:
134 6daf26a0 Guido Trotter
      answer = constants.CONFD_NODE_ROLE_DRAINED
135 6daf26a0 Guido Trotter
    elif offline:
136 6daf26a0 Guido Trotter
      answer = constants.CONFD_NODE_ROLE_OFFLINE
137 6daf26a0 Guido Trotter
    else:
138 6daf26a0 Guido Trotter
      answer = constants.CONFD_NODE_ROLE_REGULAR
139 6daf26a0 Guido Trotter
140 6daf26a0 Guido Trotter
    return constants.CONFD_REPL_STATUS_OK, answer
141 6daf26a0 Guido Trotter
142 53bd7366 Guido Trotter
143 53bd7366 Guido Trotter
class InstanceIpToNodePrimaryIpQuery(ConfdQuery):
144 95b487bb Flavio Silvestrow
  """A query for the location of one or more instance's ips.
145 53bd7366 Guido Trotter

146 19351457 Guido Trotter
  @type query: string or dict
147 19351457 Guido Trotter
  @param query: instance ip or dict containing:
148 19351457 Guido Trotter
                constants.CONFD_REQQ_LINK: nic link (optional)
149 19351457 Guido Trotter
                constants.CONFD_REQQ_IPLIST: list of ips
150 19351457 Guido Trotter
                constants.CONFD_REQQ_IP: single ip
151 19351457 Guido Trotter
                (one IP type request is mandatory)
152 19351457 Guido Trotter
  @rtype: (integer, ...)
153 19351457 Guido Trotter
  @return: ((status, answer) or (success, [(status, answer)...])
154 53bd7366 Guido Trotter

155 53bd7366 Guido Trotter
  """
156 53bd7366 Guido Trotter
  def Exec(self, query):
157 0bc8432b Guido Trotter
    """InstanceIpToNodePrimaryIpQuery main execution.
158 53bd7366 Guido Trotter

159 53bd7366 Guido Trotter
    """
160 19351457 Guido Trotter
    if isinstance(query, dict):
161 19351457 Guido Trotter
      if constants.CONFD_REQQ_IP in query:
162 19351457 Guido Trotter
        instances_list = [query[constants.CONFD_REQQ_IP]]
163 19351457 Guido Trotter
        mode = constants.CONFD_REQQ_IP
164 19351457 Guido Trotter
      elif constants.CONFD_REQQ_IPLIST in query:
165 19351457 Guido Trotter
        instances_list = query[constants.CONFD_REQQ_IPLIST]
166 19351457 Guido Trotter
        mode = constants.CONFD_REQQ_IPLIST
167 19351457 Guido Trotter
      else:
168 19351457 Guido Trotter
        status = constants.CONFD_REPL_STATUS_ERROR
169 19351457 Guido Trotter
        logging.debug("missing IP or IPLIST in query dict")
170 19351457 Guido Trotter
        return QUERY_ARGUMENT_ERROR
171 19351457 Guido Trotter
172 19351457 Guido Trotter
      if constants.CONFD_REQQ_LINK in query:
173 19351457 Guido Trotter
        network_link = query[constants.CONFD_REQQ_LINK]
174 19351457 Guido Trotter
      else:
175 19351457 Guido Trotter
        network_link = None # default will be used
176 19351457 Guido Trotter
    elif isinstance(query, basestring):
177 19351457 Guido Trotter
      # 2.1 beta1 and beta2 mode, to be deprecated for 2.2
178 95b487bb Flavio Silvestrow
      instances_list = [query]
179 19351457 Guido Trotter
      network_link = None
180 19351457 Guido Trotter
      mode = constants.CONFD_REQQ_IP
181 19351457 Guido Trotter
    else:
182 19351457 Guido Trotter
      logging.debug("Invalid query argument type for: %s" % query)
183 19351457 Guido Trotter
      return QUERY_ARGUMENT_ERROR
184 19351457 Guido Trotter
185 95b487bb Flavio Silvestrow
    pnodes_list = []
186 95b487bb Flavio Silvestrow
187 95b487bb Flavio Silvestrow
    for instance_ip in instances_list:
188 19351457 Guido Trotter
      if not isinstance(instance_ip, basestring):
189 19351457 Guido Trotter
        logging.debug("Invalid IP type for: %s" % instance_ip)
190 19351457 Guido Trotter
        return QUERY_ARGUMENT_ERROR
191 19351457 Guido Trotter
192 19351457 Guido Trotter
      instance = self.reader.GetInstanceByLinkIp(instance_ip, network_link)
193 95b487bb Flavio Silvestrow
      if not instance:
194 19351457 Guido Trotter
        logging.debug("Unknown instance IP: %s" % instance_ip)
195 95b487bb Flavio Silvestrow
        pnodes_list.append(QUERY_UNKNOWN_ENTRY_ERROR)
196 95b487bb Flavio Silvestrow
        continue
197 53bd7366 Guido Trotter
198 95b487bb Flavio Silvestrow
      pnode = self.reader.GetInstancePrimaryNode(instance)
199 95b487bb Flavio Silvestrow
      if not pnode:
200 95b487bb Flavio Silvestrow
        logging.error("Instance '%s' doesn't have an associated primary"
201 95b487bb Flavio Silvestrow
                      " node" % instance)
202 95b487bb Flavio Silvestrow
        pnodes_list.append(QUERY_INTERNAL_ERROR)
203 95b487bb Flavio Silvestrow
        continue
204 53bd7366 Guido Trotter
205 95b487bb Flavio Silvestrow
      pnode_primary_ip = self.reader.GetNodePrimaryIp(pnode)
206 95b487bb Flavio Silvestrow
      if not pnode_primary_ip:
207 95b487bb Flavio Silvestrow
        logging.error("Primary node '%s' doesn't have an associated"
208 95b487bb Flavio Silvestrow
                      " primary IP" % pnode)
209 95b487bb Flavio Silvestrow
        pnodes_list.append(QUERY_INTERNAL_ERROR)
210 95b487bb Flavio Silvestrow
        continue
211 53bd7366 Guido Trotter
212 95b487bb Flavio Silvestrow
      pnodes_list.append((constants.CONFD_REPL_STATUS_OK, pnode_primary_ip))
213 95b487bb Flavio Silvestrow
214 19351457 Guido Trotter
    # If a single ip was requested, return a single answer, otherwise the whole
215 19351457 Guido Trotter
    # list, with a success status (since each entry has its own success/failure)
216 19351457 Guido Trotter
    if mode == constants.CONFD_REQQ_IP:
217 95b487bb Flavio Silvestrow
      return pnodes_list[0]
218 95b487bb Flavio Silvestrow
219 95b487bb Flavio Silvestrow
    return constants.CONFD_REPL_STATUS_OK, pnodes_list
220 efbb4fd2 Luca Bigliardi
221 efbb4fd2 Luca Bigliardi
222 efbb4fd2 Luca Bigliardi
class NodesPipsQuery(ConfdQuery):
223 efbb4fd2 Luca Bigliardi
  """A query for nodes primary IPs.
224 efbb4fd2 Luca Bigliardi

225 efbb4fd2 Luca Bigliardi
  It returns the list of nodes primary IPs.
226 efbb4fd2 Luca Bigliardi

227 efbb4fd2 Luca Bigliardi
  """
228 efbb4fd2 Luca Bigliardi
  def Exec(self, query):
229 efbb4fd2 Luca Bigliardi
    """NodesPipsQuery main execution.
230 efbb4fd2 Luca Bigliardi

231 efbb4fd2 Luca Bigliardi
    """
232 efbb4fd2 Luca Bigliardi
    if query is None:
233 efbb4fd2 Luca Bigliardi
      status = constants.CONFD_REPL_STATUS_OK
234 efbb4fd2 Luca Bigliardi
      answer = self.reader.GetNodesPrimaryIps()
235 efbb4fd2 Luca Bigliardi
    else:
236 efbb4fd2 Luca Bigliardi
      status = constants.CONFD_REPL_STATUS_ERROR
237 efbb4fd2 Luca Bigliardi
      answer = "non-empty node primary IPs query"
238 efbb4fd2 Luca Bigliardi
239 efbb4fd2 Luca Bigliardi
    return status, answer
240 efbb4fd2 Luca Bigliardi
241 efbb4fd2 Luca Bigliardi
242 efbb4fd2 Luca Bigliardi
class MasterCandidatesPipsQuery(ConfdQuery):
243 efbb4fd2 Luca Bigliardi
  """A query for master candidates primary IPs.
244 efbb4fd2 Luca Bigliardi

245 efbb4fd2 Luca Bigliardi
  It returns the list of master candidates primary IPs.
246 efbb4fd2 Luca Bigliardi

247 efbb4fd2 Luca Bigliardi
  """
248 efbb4fd2 Luca Bigliardi
  def Exec(self, query):
249 efbb4fd2 Luca Bigliardi
    """MasterCandidatesPipsQuery main execution.
250 efbb4fd2 Luca Bigliardi

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

265 23824641 Luca Bigliardi
  It returns the list of IPs of NICs connected to the requested link or all the
266 23824641 Luca Bigliardi
  instances IPs if no link is submitted.
267 d01ae714 Luca Bigliardi

268 d01ae714 Luca Bigliardi
  """
269 d01ae714 Luca Bigliardi
  def Exec(self, query):
270 d01ae714 Luca Bigliardi
    """InstancesIpsQuery main execution.
271 d01ae714 Luca Bigliardi

272 d01ae714 Luca Bigliardi
    """
273 23824641 Luca Bigliardi
    link = query
274 23824641 Luca Bigliardi
    status = constants.CONFD_REPL_STATUS_OK
275 23824641 Luca Bigliardi
    answer = self.reader.GetInstancesIps(link)
276 d01ae714 Luca Bigliardi
277 d01ae714 Luca Bigliardi
    return status, answer