Statistics
| Branch: | Tag: | Revision:

root / lib / confd / querylib.py @ 23824641

History | View | Annotate | Download (5.9 kB)

1
#
2
#
3

    
4
# Copyright (C) 2009, Google Inc.
5
#
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.
10
#
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.
15
#
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
19
# 02110-1301, USA.
20

    
21

    
22
"""Ganeti configuration daemon queries library.
23

24
"""
25

    
26
import logging
27

    
28
from ganeti import constants
29

    
30

    
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)
36

    
37

    
38
class ConfdQuery(object):
39
  """Confd Query base class.
40

41
  """
42
  def __init__(self, reader):
43
    """Constructor for Confd Query
44

45
    @type reader: L{ssconf.SimpleConfigReader}
46
    @param reader: ConfigReader to use to access the config
47

48
    """
49
    self.reader = reader
50

    
51
  def Exec(self, query):
52
    """Process a single UDP request from a client.
53

54
    Different queries should override this function, which by defaults returns
55
    a "non-implemented" answer.
56

57
    @type query: (undefined)
58
    @param query: ConfdRequest 'query' field
59
    @rtype: (integer, undefined)
60
    @return: status and answer to give to the client
61

62
    """
63
    status = constants.CONFD_REPL_STATUS_NOTIMPLEMENTED
64
    answer = 'not implemented'
65
    return status, answer
66

    
67

    
68
class PingQuery(ConfdQuery):
69
  """An empty confd query.
70

71
  It will return success on an empty argument, and an error on any other
72
  argument.
73

74
  """
75
  def Exec(self, query):
76
    """PingQuery main execution.
77

78
    """
79
    if query is None:
80
      status = constants.CONFD_REPL_STATUS_OK
81
      answer = 'ok'
82
    else:
83
      status = constants.CONFD_REPL_STATUS_ERROR
84
      answer = 'non-empty ping query'
85

    
86
    return status, answer
87

    
88

    
89
class ClusterMasterQuery(ConfdQuery):
90
  """Cluster master query.
91

92
  It accepts no arguments, and returns the current cluster master.
93

94
  """
95
  def Exec(self, query):
96
    """ClusterMasterQuery main execution
97

98
    """
99
    if query is None:
100
      status = constants.CONFD_REPL_STATUS_OK
101
      answer = self.reader.GetMasterNode()
102
    else:
103
      status = constants.CONFD_REPL_STATUS_ERROR
104
      answer = 'master query accepts no query argument'
105

    
106
    return status, answer
107

    
108

    
109
class NodeRoleQuery(ConfdQuery):
110
  """A query for the role of a node.
111

112
  It will return one of CONFD_NODE_ROLE_*, or an error for non-existing nodes.
113

114
  """
115
  def Exec(self, query):
116
    """EmptyQuery main execution
117

118
    """
119
    node = query
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)
125
    if flags is None:
126
      return QUERY_UNKNOWN_ENTRY_ERROR
127

    
128
    master_candidate, drained, offline = flags
129
    if master_candidate:
130
      answer = constants.CONFD_NODE_ROLE_CANDIDATE
131
    elif drained:
132
      answer = constants.CONFD_NODE_ROLE_DRAINED
133
    elif offline:
134
      answer = constants.CONFD_NODE_ROLE_OFFLINE
135
    else:
136
      answer = constants.CONFD_NODE_ROLE_REGULAR
137

    
138
    return constants.CONFD_REPL_STATUS_OK, answer
139

    
140

    
141
class InstanceIpToNodePrimaryIpQuery(ConfdQuery):
142
  """A query for the location of an instance's ip.
143

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.
146

147
  """
148
  def Exec(self, query):
149
    """InstanceIpToNodePrimaryIpQuery main execution.
150

151
    """
152
    instance_ip = query
153
    instance = self.reader.GetInstanceByIp(instance_ip)
154
    if instance is None:
155
      return QUERY_UNKNOWN_ENTRY_ERROR
156

    
157
    pnode = self.reader.GetInstancePrimaryNode(instance)
158
    if pnode is None:
159
      # this shouldn't happen
160
      logging.error("Internal configuration inconsistent (instance-to-pnode)")
161
      return QUERY_INTERNAL_ERROR
162

    
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
168

    
169
    return constants.CONFD_REPL_STATUS_OK, pnode_primary_ip
170

    
171

    
172
class NodesPipsQuery(ConfdQuery):
173
  """A query for nodes primary IPs.
174

175
  It returns the list of nodes primary IPs.
176

177
  """
178
  def Exec(self, query):
179
    """NodesPipsQuery main execution.
180

181
    """
182
    if query is None:
183
      status = constants.CONFD_REPL_STATUS_OK
184
      answer = self.reader.GetNodesPrimaryIps()
185
    else:
186
      status = constants.CONFD_REPL_STATUS_ERROR
187
      answer = "non-empty node primary IPs query"
188

    
189
    return status, answer
190

    
191

    
192
class MasterCandidatesPipsQuery(ConfdQuery):
193
  """A query for master candidates primary IPs.
194

195
  It returns the list of master candidates primary IPs.
196

197
  """
198
  def Exec(self, query):
199
    """MasterCandidatesPipsQuery main execution.
200

201
    """
202
    if query is None:
203
      status = constants.CONFD_REPL_STATUS_OK
204
      answer = self.reader.GetMasterCandidatesPrimaryIps()
205
    else:
206
      status = constants.CONFD_REPL_STATUS_ERROR
207
      answer = "non-empty master candidates primary IPs query"
208

    
209
    return status, answer
210

    
211

    
212
class InstancesIpsQuery(ConfdQuery):
213
  """A query for instances IPs.
214

215
  It returns the list of IPs of NICs connected to the requested link or all the
216
  instances IPs if no link is submitted.
217

218
  """
219
  def Exec(self, query):
220
    """InstancesIpsQuery main execution.
221

222
    """
223
    link = query
224
    status = constants.CONFD_REPL_STATUS_OK
225
    answer = self.reader.GetInstancesIps(link)
226

    
227
    return status, answer
228