Statistics
| Branch: | Tag: | Revision:

root / lib / confd / querylib.py @ 0bc8432b

History | View | Annotate | Download (4.1 kB)

1
#!/usr/bin/python
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
# constants for some common errors to return from a query
31
QUERY_UNKNOWN_ENTRY_ERROR = (constants.CONFD_REPL_STATUS_ERROR,
32
                             constants.CONFD_ERROR_UNKNOWN_ENTRY)
33
QUERY_INTERNAL_ERROR = (constants.CONFD_REPL_STATUS_ERROR,
34
                        constants.CONFD_ERROR_INTERNAL)
35

    
36
class ConfdQuery(object):
37
  """Confd Query base class.
38

39
  """
40
  def __init__(self, reader):
41
    """Constructor for Confd Query
42

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

46
    """
47
    self.reader = reader
48

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

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

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

60
    """
61
    status = constants.CONFD_REPL_STATUS_NOTIMPLEMENTED
62
    answer = 'not implemented'
63
    return status, answer
64

    
65

    
66
class PingQuery(ConfdQuery):
67
  """An empty confd query.
68

69
  It will return success on an empty argument, and an error on any other argument.
70

71
  """
72
  def Exec(self, query):
73
    """PingQuery main execution.
74

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

    
83
    return status, answer
84

    
85

    
86
class NodeRoleQuery(ConfdQuery):
87
  """A query for the role of a node.
88

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

91
  """
92
  def Exec(self, query):
93
    """EmptyQuery main execution
94

95
    """
96
    node = query
97
    if self.reader.GetMasterNode() == node:
98
      status = constants.CONFD_REPL_STATUS_OK
99
      answer = constants.CONFD_NODE_ROLE_MASTER
100
      return status, answer
101
    flags = self.reader.GetNodeStatusFlags(node)
102
    if flags is None:
103
      return QUERY_UNKNOWN_ENTRY_ERROR
104

    
105
    master_candidate, drained, offline = flags
106
    if master_candidate:
107
      answer = constants.CONFD_NODE_ROLE_CANDIDATE
108
    elif drained:
109
      answer = constants.CONFD_NODE_ROLE_DRAINED
110
    elif offline:
111
      answer = constants.CONFD_NODE_ROLE_OFFLINE
112
    else:
113
      answer = constants.CONFD_NODE_ROLE_REGULAR
114

    
115
    return constants.CONFD_REPL_STATUS_OK, answer
116

    
117

    
118
class InstanceIpToNodePrimaryIpQuery(ConfdQuery):
119
  """A query for the location of an instance's ip.
120

121
  It returns the primary ip of the node hosting the instance having the
122
  requested ip address, or an error if no such address is known.
123

124
  """
125
  def Exec(self, query):
126
    """InstanceIpToNodePrimaryIpQuery main execution.
127

128
    """
129
    instance_ip = query
130
    instance = self.reader.GetInstanceByIp(instance_ip)
131
    if instance is None:
132
      return QUERY_UNKNOWN_ENTRY_ERROR
133

    
134
    pnode = self.reader.GetInstancePrimaryNode(instance)
135
    if pnode is None:
136
      # this shouldn't happen
137
      logging.error("Internal configuration inconsistent (instance-to-pnode)")
138
      return QUERY_INTERNAL_ERROR
139

    
140
    pnode_primary_ip = self.reader.GetNodePrimaryIp(pnode)
141
    if pnode_primary_ip is None:
142
      # this shouldn't happen
143
      logging.error("Internal configuration inconsistent (node-to-primary-ip)")
144
      return QUERY_INTERNAL_ERROR
145

    
146
    return constants.CONFD_REPL_STATUS_OK, pnode_primary_ip
147