1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 """Ganeti configuration daemon queries library.
23
24 """
25
26 import logging
27
28 from ganeti import constants
29
30
31
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 QUERY_ARGUMENT_ERROR = (constants.CONFD_REPL_STATUS_ERROR,
37 constants.CONFD_ERROR_ARGUMENT)
38
39
41 """Confd Query base class.
42
43 """
45 """Constructor for Confd Query
46
47 @type reader: L{ssconf.SimpleConfigReader}
48 @param reader: ConfigReader to use to access the config
49
50 """
51 self.reader = reader
52
53 - def Exec(self, query):
54 """Process a single UDP request from a client.
55
56 Different queries should override this function, which by defaults returns
57 a "non-implemented" answer.
58
59 @type query: (undefined)
60 @param query: ConfdRequest 'query' field
61 @rtype: (integer, undefined)
62 @return: status and answer to give to the client
63
64 """
65 status = constants.CONFD_REPL_STATUS_NOTIMPLEMENTED
66 answer = 'not implemented'
67 return status, answer
68
69
71 """An empty confd query.
72
73 It will return success on an empty argument, and an error on any other
74 argument.
75
76 """
77 - def Exec(self, query):
89
90
92 """Cluster master query.
93
94 It accepts no arguments, and returns the current cluster master.
95
96 """
99
100 - def Exec(self, query):
131
132
134 """A query for the role of a node.
135
136 It will return one of CONFD_NODE_ROLE_*, or an error for non-existing nodes.
137
138 """
139 - def Exec(self, query):
163
164
166 """A query for the location of one or more instance's ips.
167
168 """
169 - def Exec(self, query):
170 """InstanceIpToNodePrimaryIpQuery main execution.
171
172 @type query: string or dict
173 @param query: instance ip or dict containing:
174 constants.CONFD_REQQ_LINK: nic link (optional)
175 constants.CONFD_REQQ_IPLIST: list of ips
176 constants.CONFD_REQQ_IP: single ip
177 (one IP type request is mandatory)
178 @rtype: (integer, ...)
179 @return: ((status, answer) or (success, [(status, answer)...])
180
181 """
182 if isinstance(query, dict):
183 if constants.CONFD_REQQ_IP in query:
184 instances_list = [query[constants.CONFD_REQQ_IP]]
185 mode = constants.CONFD_REQQ_IP
186 elif constants.CONFD_REQQ_IPLIST in query:
187 instances_list = query[constants.CONFD_REQQ_IPLIST]
188 mode = constants.CONFD_REQQ_IPLIST
189 else:
190 logging.debug("missing IP or IPLIST in query dict")
191 return QUERY_ARGUMENT_ERROR
192
193 if constants.CONFD_REQQ_LINK in query:
194 network_link = query[constants.CONFD_REQQ_LINK]
195 else:
196 network_link = None
197 else:
198 logging.debug("Invalid query argument type for: %s", query)
199 return QUERY_ARGUMENT_ERROR
200
201 pnodes_list = []
202
203 for instance_ip in instances_list:
204 if not isinstance(instance_ip, basestring):
205 logging.debug("Invalid IP type for: %s", instance_ip)
206 return QUERY_ARGUMENT_ERROR
207
208 instance = self.reader.GetInstanceByLinkIp(instance_ip, network_link)
209 if not instance:
210 logging.debug("Unknown instance IP: %s", instance_ip)
211 pnodes_list.append(QUERY_UNKNOWN_ENTRY_ERROR)
212 continue
213
214 pnode = self.reader.GetInstancePrimaryNode(instance)
215 if not pnode:
216 logging.error("Instance '%s' doesn't have an associated primary"
217 " node", instance)
218 pnodes_list.append(QUERY_INTERNAL_ERROR)
219 continue
220
221 pnode_primary_ip = self.reader.GetNodePrimaryIp(pnode)
222 if not pnode_primary_ip:
223 logging.error("Primary node '%s' doesn't have an associated"
224 " primary IP", pnode)
225 pnodes_list.append(QUERY_INTERNAL_ERROR)
226 continue
227
228 pnodes_list.append((constants.CONFD_REPL_STATUS_OK, pnode_primary_ip))
229
230
231
232
233 if mode == constants.CONFD_REQQ_IP:
234 return pnodes_list[0]
235
236 return constants.CONFD_REPL_STATUS_OK, pnodes_list
237
238
240 """A query for nodes primary IPs.
241
242 It returns the list of nodes primary IPs.
243
244 """
245 - def Exec(self, query):
257
258
260 """A query for master candidates primary IPs.
261
262 It returns the list of master candidates primary IPs.
263
264 """
265 - def Exec(self, query):
277
278
280 """A query for instances IPs.
281
282 It returns the list of IPs of NICs connected to the requested link or all the
283 instances IPs if no link is submitted.
284
285 """
286 - def Exec(self, query):
295