root / test / py / ganeti.query_unittest.py @ 6ccce5d4
History | View | Annotate | Download (75.9 kB)
1 |
#!/usr/bin/python
|
---|---|
2 |
#
|
3 |
|
4 |
# Copyright (C) 2010, 2011, 2012, 2013 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 |
"""Script for testing ganeti.query"""
|
23 |
|
24 |
import re |
25 |
import unittest |
26 |
import random |
27 |
|
28 |
from ganeti import constants |
29 |
from ganeti import utils |
30 |
from ganeti import compat |
31 |
from ganeti import errors |
32 |
from ganeti import query |
33 |
from ganeti import objects |
34 |
from ganeti import cmdlib |
35 |
|
36 |
import ganeti.masterd.instance as gmi |
37 |
from ganeti.hypervisor import hv_base |
38 |
|
39 |
import testutils |
40 |
|
41 |
|
42 |
class TestConstants(unittest.TestCase): |
43 |
def test(self): |
44 |
self.assertEqual(set(query._VERIFY_FN.keys()), |
45 |
constants.QFT_ALL) |
46 |
|
47 |
|
48 |
class _QueryData: |
49 |
def __init__(self, data, **kwargs): |
50 |
self.data = data
|
51 |
|
52 |
for name, value in kwargs.items(): |
53 |
setattr(self, name, value) |
54 |
|
55 |
def __iter__(self): |
56 |
return iter(self.data) |
57 |
|
58 |
|
59 |
def _GetDiskSize(nr, ctx, item): |
60 |
disks = item["disks"]
|
61 |
try:
|
62 |
return disks[nr]
|
63 |
except IndexError: |
64 |
return query._FS_UNAVAIL
|
65 |
|
66 |
|
67 |
class TestQuery(unittest.TestCase): |
68 |
def test(self): |
69 |
(STATIC, DISK) = range(10, 12) |
70 |
|
71 |
fielddef = query._PrepareFieldList([ |
72 |
(query._MakeField("name", "Name", constants.QFT_TEXT, "Name"), |
73 |
STATIC, 0, lambda ctx, item: item["name"]), |
74 |
(query._MakeField("master", "Master", constants.QFT_BOOL, "Master"), |
75 |
STATIC, 0, lambda ctx, item: ctx.mastername == item["name"]), |
76 |
] + |
77 |
[(query._MakeField("disk%s.size" % i, "DiskSize%s" % i, |
78 |
constants.QFT_UNIT, "Disk size %s" % i),
|
79 |
DISK, 0, compat.partial(_GetDiskSize, i))
|
80 |
for i in range(4)], []) |
81 |
|
82 |
q = query.Query(fielddef, ["name"])
|
83 |
self.assertEqual(q.RequestedData(), set([STATIC])) |
84 |
self.assertEqual(len(q._fields), 1) |
85 |
self.assertEqual(len(q.GetFields()), 1) |
86 |
self.assertEqual(q.GetFields()[0].ToDict(), |
87 |
objects.QueryFieldDefinition(name="name",
|
88 |
title="Name",
|
89 |
kind=constants.QFT_TEXT, |
90 |
doc="Name").ToDict())
|
91 |
|
92 |
# Create data only once query has been prepared
|
93 |
data = [ |
94 |
{ "name": "node1", "disks": [0, 1, 2], }, |
95 |
{ "name": "node2", "disks": [3, 4], }, |
96 |
{ "name": "node3", "disks": [5, 6, 7], }, |
97 |
] |
98 |
|
99 |
self.assertEqual(q.Query(_QueryData(data, mastername="node3")), |
100 |
[[(constants.RS_NORMAL, "node1")],
|
101 |
[(constants.RS_NORMAL, "node2")],
|
102 |
[(constants.RS_NORMAL, "node3")]])
|
103 |
self.assertEqual(q.OldStyleQuery(_QueryData(data, mastername="node3")), |
104 |
[["node1"], ["node2"], ["node3"]]) |
105 |
|
106 |
q = query.Query(fielddef, ["name", "master"]) |
107 |
self.assertEqual(q.RequestedData(), set([STATIC])) |
108 |
self.assertEqual(len(q._fields), 2) |
109 |
self.assertEqual(q.Query(_QueryData(data, mastername="node3")), |
110 |
[[(constants.RS_NORMAL, "node1"),
|
111 |
(constants.RS_NORMAL, False)],
|
112 |
[(constants.RS_NORMAL, "node2"),
|
113 |
(constants.RS_NORMAL, False)],
|
114 |
[(constants.RS_NORMAL, "node3"),
|
115 |
(constants.RS_NORMAL, True)],
|
116 |
]) |
117 |
|
118 |
q = query.Query(fielddef, ["name", "master", "disk0.size"]) |
119 |
self.assertEqual(q.RequestedData(), set([STATIC, DISK])) |
120 |
self.assertEqual(len(q._fields), 3) |
121 |
self.assertEqual(q.Query(_QueryData(data, mastername="node2")), |
122 |
[[(constants.RS_NORMAL, "node1"),
|
123 |
(constants.RS_NORMAL, False),
|
124 |
(constants.RS_NORMAL, 0)],
|
125 |
[(constants.RS_NORMAL, "node2"),
|
126 |
(constants.RS_NORMAL, True),
|
127 |
(constants.RS_NORMAL, 3)],
|
128 |
[(constants.RS_NORMAL, "node3"),
|
129 |
(constants.RS_NORMAL, False),
|
130 |
(constants.RS_NORMAL, 5)],
|
131 |
]) |
132 |
|
133 |
# With unknown column
|
134 |
q = query.Query(fielddef, ["disk2.size", "disk1.size", "disk99.size", |
135 |
"disk0.size"])
|
136 |
self.assertEqual(q.RequestedData(), set([DISK])) |
137 |
self.assertEqual(len(q._fields), 4) |
138 |
self.assertEqual(q.Query(_QueryData(data, mastername="node2")), |
139 |
[[(constants.RS_NORMAL, 2),
|
140 |
(constants.RS_NORMAL, 1),
|
141 |
(constants.RS_UNKNOWN, None),
|
142 |
(constants.RS_NORMAL, 0)],
|
143 |
[(constants.RS_UNAVAIL, None),
|
144 |
(constants.RS_NORMAL, 4),
|
145 |
(constants.RS_UNKNOWN, None),
|
146 |
(constants.RS_NORMAL, 3)],
|
147 |
[(constants.RS_NORMAL, 7),
|
148 |
(constants.RS_NORMAL, 6),
|
149 |
(constants.RS_UNKNOWN, None),
|
150 |
(constants.RS_NORMAL, 5)],
|
151 |
]) |
152 |
self.assertRaises(errors.OpPrereqError, q.OldStyleQuery,
|
153 |
_QueryData(data, mastername="node2"))
|
154 |
self.assertEqual([fdef.ToDict() for fdef in q.GetFields()], [ |
155 |
{ "name": "disk2.size", "title": "DiskSize2", |
156 |
"kind": constants.QFT_UNIT, "doc": "Disk size 2", }, |
157 |
{ "name": "disk1.size", "title": "DiskSize1", |
158 |
"kind": constants.QFT_UNIT, "doc": "Disk size 1", }, |
159 |
{ "name": "disk99.size", "title": "disk99.size", |
160 |
"kind": constants.QFT_UNKNOWN,
|
161 |
"doc": "Unknown field 'disk99.size'", }, |
162 |
{ "name": "disk0.size", "title": "DiskSize0", |
163 |
"kind": constants.QFT_UNIT, "doc": "Disk size 0", }, |
164 |
]) |
165 |
|
166 |
# Empty query
|
167 |
q = query.Query(fielddef, []) |
168 |
self.assertEqual(q.RequestedData(), set([])) |
169 |
self.assertEqual(len(q._fields), 0) |
170 |
self.assertEqual(q.Query(_QueryData(data, mastername="node2")), |
171 |
[[], [], []]) |
172 |
self.assertEqual(q.OldStyleQuery(_QueryData(data, mastername="node2")), |
173 |
[[], [], []]) |
174 |
self.assertEqual(q.GetFields(), [])
|
175 |
|
176 |
def testPrepareFieldList(self): |
177 |
# Duplicate titles
|
178 |
for (a, b) in [("name", "name"), ("NAME", "name")]: |
179 |
self.assertRaises(AssertionError, query._PrepareFieldList, [ |
180 |
(query._MakeField("name", b, constants.QFT_TEXT, "Name"), None, 0, |
181 |
lambda *args: None), |
182 |
(query._MakeField("other", a, constants.QFT_TEXT, "Other"), None, 0, |
183 |
lambda *args: None), |
184 |
], []) |
185 |
|
186 |
# Non-lowercase names
|
187 |
self.assertRaises(AssertionError, query._PrepareFieldList, [ |
188 |
(query._MakeField("NAME", "Name", constants.QFT_TEXT, "Name"), None, 0, |
189 |
lambda *args: None), |
190 |
], []) |
191 |
self.assertRaises(AssertionError, query._PrepareFieldList, [ |
192 |
(query._MakeField("Name", "Name", constants.QFT_TEXT, "Name"), None, 0, |
193 |
lambda *args: None), |
194 |
], []) |
195 |
|
196 |
# Empty name
|
197 |
self.assertRaises(AssertionError, query._PrepareFieldList, [ |
198 |
(query._MakeField("", "Name", constants.QFT_TEXT, "Name"), None, 0, |
199 |
lambda *args: None), |
200 |
], []) |
201 |
|
202 |
# Empty title
|
203 |
self.assertRaises(AssertionError, query._PrepareFieldList, [ |
204 |
(query._MakeField("name", "", constants.QFT_TEXT, "Name"), None, 0, |
205 |
lambda *args: None), |
206 |
], []) |
207 |
|
208 |
# Whitespace in title
|
209 |
self.assertRaises(AssertionError, query._PrepareFieldList, [ |
210 |
(query._MakeField("name", "Co lu mn", constants.QFT_TEXT, "Name"), |
211 |
None, 0, lambda *args: None), |
212 |
], []) |
213 |
|
214 |
# No callable function
|
215 |
self.assertRaises(AssertionError, query._PrepareFieldList, [ |
216 |
(query._MakeField("name", "Name", constants.QFT_TEXT, "Name"), |
217 |
None, 0, None), |
218 |
], []) |
219 |
|
220 |
# Invalid documentation
|
221 |
for doc in ["", ".", "Hello world\n", "Hello\nWo\nrld", "Hello World!", |
222 |
"HelloWorld.", "only lowercase", ",", " x y z .\t", " "]: |
223 |
self.assertRaises(AssertionError, query._PrepareFieldList, [ |
224 |
(query._MakeField("name", "Name", constants.QFT_TEXT, doc), |
225 |
None, 0, lambda *args: None), |
226 |
], []) |
227 |
|
228 |
# Duplicate field name
|
229 |
self.assertRaises(ValueError, query._PrepareFieldList, [ |
230 |
(query._MakeField("name", "Name", constants.QFT_TEXT, "Name"), |
231 |
None, 0, lambda *args: None), |
232 |
(query._MakeField("name", "Other", constants.QFT_OTHER, "Other"), |
233 |
None, 0, lambda *args: None), |
234 |
], []) |
235 |
|
236 |
def testUnknown(self): |
237 |
fielddef = query._PrepareFieldList([ |
238 |
(query._MakeField("name", "Name", constants.QFT_TEXT, "Name"), |
239 |
None, 0, lambda _, item: "name%s" % item), |
240 |
(query._MakeField("other0", "Other0", constants.QFT_TIMESTAMP, "Other"), |
241 |
None, 0, lambda *args: 1234), |
242 |
(query._MakeField("nodata", "NoData", constants.QFT_NUMBER, "No data"), |
243 |
None, 0, lambda *args: query._FS_NODATA ), |
244 |
(query._MakeField("unavail", "Unavail", constants.QFT_BOOL, "Unavail"), |
245 |
None, 0, lambda *args: query._FS_UNAVAIL), |
246 |
], []) |
247 |
|
248 |
for selected in [["foo"], ["Hello", "World"], |
249 |
["name1", "other", "foo"]]: |
250 |
q = query.Query(fielddef, selected) |
251 |
self.assertEqual(len(q._fields), len(selected)) |
252 |
self.assert_(compat.all(len(row) == len(selected) |
253 |
for row in q.Query(_QueryData(range(1, 10))))) |
254 |
self.assertEqual(q.Query(_QueryData(range(1, 10))), |
255 |
[[(constants.RS_UNKNOWN, None)] * len(selected) |
256 |
for i in range(1, 10)]) |
257 |
self.assertEqual([fdef.ToDict() for fdef in q.GetFields()], |
258 |
[{ "name": name, "title": name, |
259 |
"kind": constants.QFT_UNKNOWN,
|
260 |
"doc": "Unknown field '%s'" % name} |
261 |
for name in selected]) |
262 |
|
263 |
q = query.Query(fielddef, ["name", "other0", "nodata", "unavail"]) |
264 |
self.assertEqual(len(q._fields), 4) |
265 |
self.assertEqual(q.OldStyleQuery(_QueryData(range(1, 10))), [ |
266 |
["name%s" % i, 1234, None, None] |
267 |
for i in range(1, 10) |
268 |
]) |
269 |
|
270 |
q = query.Query(fielddef, ["name", "other0", "nodata", "unavail", "unk"]) |
271 |
self.assertEqual(len(q._fields), 5) |
272 |
self.assertEqual(q.Query(_QueryData(range(1, 10))), |
273 |
[[(constants.RS_NORMAL, "name%s" % i),
|
274 |
(constants.RS_NORMAL, 1234),
|
275 |
(constants.RS_NODATA, None),
|
276 |
(constants.RS_UNAVAIL, None),
|
277 |
(constants.RS_UNKNOWN, None)]
|
278 |
for i in range(1, 10)]) |
279 |
|
280 |
def testAliases(self): |
281 |
fields = [ |
282 |
(query._MakeField("a", "a-title", constants.QFT_TEXT, "Field A"), |
283 |
None, 0, lambda *args: None), |
284 |
(query._MakeField("b", "b-title", constants.QFT_TEXT, "Field B"), |
285 |
None, 0, lambda *args: None), |
286 |
] |
287 |
# duplicate field
|
288 |
self.assertRaises(AssertionError, query._PrepareFieldList, fields, |
289 |
[("b", "a")]) |
290 |
self.assertRaises(AssertionError, query._PrepareFieldList, fields, |
291 |
[("c", "b"), ("c", "a")]) |
292 |
# missing target
|
293 |
self.assertRaises(AssertionError, query._PrepareFieldList, fields, |
294 |
[("c", "d")]) |
295 |
fdefs = query._PrepareFieldList(fields, [("c", "b")]) |
296 |
self.assertEqual(len(fdefs), 3) |
297 |
self.assertEqual(fdefs["b"][1:], fdefs["c"][1:]) |
298 |
|
299 |
|
300 |
class TestGetNodeRole(unittest.TestCase): |
301 |
def test(self): |
302 |
tested_role = set()
|
303 |
master_uuid = "969502b9-f632-4d3d-83a5-a78b0ca8cdf6"
|
304 |
node_uuid = "d75499b5-83e3-4b80-b6fe-3e1aee7e5a35"
|
305 |
checks = [ |
306 |
(constants.NR_MASTER, |
307 |
objects.Node(name="node1", uuid=master_uuid)),
|
308 |
(constants.NR_MCANDIDATE, |
309 |
objects.Node(name="node1", uuid=node_uuid, master_candidate=True)), |
310 |
(constants.NR_REGULAR, |
311 |
objects.Node(name="node1", uuid=node_uuid)),
|
312 |
(constants.NR_DRAINED, |
313 |
objects.Node(name="node1", uuid=node_uuid, drained=True)), |
314 |
(constants.NR_OFFLINE, |
315 |
objects.Node(name="node1", uuid=node_uuid, offline=True)), |
316 |
] |
317 |
|
318 |
for (role, node) in checks: |
319 |
result = query._GetNodeRole(node, master_uuid) |
320 |
self.assertEqual(result, role)
|
321 |
tested_role.add(result) |
322 |
|
323 |
self.assertEqual(tested_role, constants.NR_ALL)
|
324 |
|
325 |
|
326 |
class TestNodeQuery(unittest.TestCase): |
327 |
def _Create(self, selected): |
328 |
return query.Query(query.NODE_FIELDS, selected)
|
329 |
|
330 |
def testSimple(self): |
331 |
cluster = objects.Cluster(cluster_name="testcluster",
|
332 |
ndparams=constants.NDC_DEFAULTS.copy()) |
333 |
grp1 = objects.NodeGroup(name="default",
|
334 |
uuid="c0e89160-18e7-11e0-a46e-001d0904baeb",
|
335 |
alloc_policy=constants.ALLOC_POLICY_PREFERRED, |
336 |
ipolicy=objects.MakeEmptyIPolicy(), |
337 |
ndparams={}, |
338 |
) |
339 |
grp2 = objects.NodeGroup(name="group2",
|
340 |
uuid="c0e89160-18e7-11e0-a46e-001d0904babe",
|
341 |
alloc_policy=constants.ALLOC_POLICY_PREFERRED, |
342 |
ipolicy=objects.MakeEmptyIPolicy(), |
343 |
ndparams={constants.ND_SPINDLE_COUNT: 2},
|
344 |
) |
345 |
groups = {grp1.uuid: grp1, grp2.uuid: grp2} |
346 |
nodes = [ |
347 |
objects.Node(name="node1", drained=False, group=grp1.uuid, ndparams={}), |
348 |
objects.Node(name="node2", drained=True, group=grp2.uuid, ndparams={}), |
349 |
objects.Node(name="node3", drained=False, group=grp1.uuid, |
350 |
ndparams={constants.ND_SPINDLE_COUNT: 4}),
|
351 |
] |
352 |
for live_data in [None, dict.fromkeys([node.name for node in nodes], {})]: |
353 |
nqd = query.NodeQueryData(nodes, live_data, None, None, None, None, |
354 |
groups, None, cluster)
|
355 |
|
356 |
q = self._Create(["name", "drained"]) |
357 |
self.assertEqual(q.RequestedData(), set([query.NQ_CONFIG])) |
358 |
self.assertEqual(q.Query(nqd),
|
359 |
[[(constants.RS_NORMAL, "node1"),
|
360 |
(constants.RS_NORMAL, False)],
|
361 |
[(constants.RS_NORMAL, "node2"),
|
362 |
(constants.RS_NORMAL, True)],
|
363 |
[(constants.RS_NORMAL, "node3"),
|
364 |
(constants.RS_NORMAL, False)],
|
365 |
]) |
366 |
self.assertEqual(q.OldStyleQuery(nqd),
|
367 |
[["node1", False], |
368 |
["node2", True], |
369 |
["node3", False]]) |
370 |
q = self._Create(["ndp/spindle_count"]) |
371 |
self.assertEqual(q.RequestedData(), set([query.NQ_GROUP])) |
372 |
self.assertEqual(q.Query(nqd),
|
373 |
[[(constants.RS_NORMAL, |
374 |
constants.NDC_DEFAULTS[constants.ND_SPINDLE_COUNT])], |
375 |
[(constants.RS_NORMAL, |
376 |
grp2.ndparams[constants.ND_SPINDLE_COUNT])], |
377 |
[(constants.RS_NORMAL, |
378 |
nodes[2].ndparams[constants.ND_SPINDLE_COUNT])],
|
379 |
]) |
380 |
|
381 |
def test(self): |
382 |
selected = query.NODE_FIELDS.keys() |
383 |
field_index = dict((field, idx) for idx, field in enumerate(selected)) |
384 |
|
385 |
q = self._Create(selected)
|
386 |
self.assertEqual(q.RequestedData(),
|
387 |
set([query.NQ_CONFIG, query.NQ_LIVE, query.NQ_INST,
|
388 |
query.NQ_GROUP, query.NQ_OOB])) |
389 |
|
390 |
cluster = objects.Cluster(cluster_name="testcluster",
|
391 |
hvparams=constants.HVC_DEFAULTS, |
392 |
beparams={ |
393 |
constants.PP_DEFAULT: constants.BEC_DEFAULTS, |
394 |
}, |
395 |
nicparams={ |
396 |
constants.PP_DEFAULT: constants.NICC_DEFAULTS, |
397 |
}, |
398 |
ndparams=constants.NDC_DEFAULTS, |
399 |
) |
400 |
|
401 |
node_names = ["node%s" % i for i in range(20)] |
402 |
master_name = node_names[3]
|
403 |
nodes = [ |
404 |
objects.Node(name=name, |
405 |
primary_ip="192.0.2.%s" % idx,
|
406 |
secondary_ip="192.0.100.%s" % idx,
|
407 |
serial_no=7789 * idx,
|
408 |
master_candidate=(name != master_name and idx % 3 == 0), |
409 |
offline=False,
|
410 |
drained=False,
|
411 |
powered=True,
|
412 |
vm_capable=True,
|
413 |
master_capable=False,
|
414 |
ndparams={}, |
415 |
group="default",
|
416 |
ctime=1290006900,
|
417 |
mtime=1290006913,
|
418 |
uuid="fd9ccebe-6339-43c9-a82e-94bbe575%04d" % idx)
|
419 |
for idx, name in enumerate(node_names) |
420 |
] |
421 |
|
422 |
master_node = nodes[3]
|
423 |
master_node.AddTag("masternode")
|
424 |
master_node.AddTag("another")
|
425 |
master_node.AddTag("tag")
|
426 |
master_node.ctime = None
|
427 |
master_node.mtime = None
|
428 |
assert master_node.name == master_name
|
429 |
|
430 |
live_data_node = nodes[4]
|
431 |
assert live_data_node.name != master_name
|
432 |
|
433 |
fake_live_data = { |
434 |
"bootid": "a2504766-498e-4b25-b21e-d23098dc3af4", |
435 |
"cnodes": 4, |
436 |
"cnos": 3, |
437 |
"csockets": 4, |
438 |
"ctotal": 8, |
439 |
"mnode": 128, |
440 |
"mfree": 100, |
441 |
"mtotal": 4096, |
442 |
"dfree": 5 * 1024 * 1024, |
443 |
"dtotal": 100 * 1024 * 1024, |
444 |
"spfree": 0, |
445 |
"sptotal": 0, |
446 |
} |
447 |
|
448 |
assert (sorted(query._NODE_LIVE_FIELDS.keys()) == |
449 |
sorted(fake_live_data.keys()))
|
450 |
|
451 |
live_data = dict.fromkeys([node.uuid for node in nodes], {}) |
452 |
live_data[live_data_node.uuid] = \ |
453 |
dict((query._NODE_LIVE_FIELDS[name][2], value) |
454 |
for name, value in fake_live_data.items()) |
455 |
|
456 |
node_to_primary_uuid = dict((node.uuid, set()) for node in nodes) |
457 |
node_to_primary_uuid[master_node.uuid].update(["inst1", "inst2"]) |
458 |
|
459 |
node_to_secondary_uuid = dict((node.uuid, set()) for node in nodes) |
460 |
node_to_secondary_uuid[live_data_node.uuid].update(["instX", "instY", |
461 |
"instZ"])
|
462 |
|
463 |
inst_uuid_to_inst_name = { |
464 |
"inst1": "inst1-name", |
465 |
"inst2": "inst2-name", |
466 |
"instX": "instX-name", |
467 |
"instY": "instY-name", |
468 |
"instZ": "instZ-name" |
469 |
} |
470 |
|
471 |
ng_uuid = "492b4b74-8670-478a-b98d-4c53a76238e6"
|
472 |
groups = { |
473 |
ng_uuid: objects.NodeGroup(name="ng1", uuid=ng_uuid, ndparams={}),
|
474 |
} |
475 |
|
476 |
oob_not_powered_node = nodes[0]
|
477 |
oob_not_powered_node.powered = False
|
478 |
oob_support = dict((node.uuid, False) for node in nodes) |
479 |
oob_support[master_node.uuid] = True
|
480 |
oob_support[oob_not_powered_node.uuid] = True
|
481 |
|
482 |
master_node.group = ng_uuid |
483 |
|
484 |
nqd = query.NodeQueryData(nodes, live_data, master_node.uuid, |
485 |
node_to_primary_uuid, node_to_secondary_uuid, |
486 |
inst_uuid_to_inst_name, groups, oob_support, |
487 |
cluster) |
488 |
result = q.Query(nqd) |
489 |
self.assert_(compat.all(len(row) == len(selected) for row in result)) |
490 |
self.assertEqual([row[field_index["name"]] for row in result], |
491 |
[(constants.RS_NORMAL, name) for name in node_names]) |
492 |
|
493 |
node_to_row = dict((row[field_index["name"]][1], idx) |
494 |
for idx, row in enumerate(result)) |
495 |
|
496 |
master_row = result[node_to_row[master_name]] |
497 |
self.assert_(master_row[field_index["master"]]) |
498 |
self.assert_(master_row[field_index["role"]], "M") |
499 |
self.assertEqual(master_row[field_index["group"]], |
500 |
(constants.RS_NORMAL, "ng1"))
|
501 |
self.assertEqual(master_row[field_index["group.uuid"]], |
502 |
(constants.RS_NORMAL, ng_uuid)) |
503 |
self.assertEqual(master_row[field_index["ctime"]], |
504 |
(constants.RS_UNAVAIL, None))
|
505 |
self.assertEqual(master_row[field_index["mtime"]], |
506 |
(constants.RS_UNAVAIL, None))
|
507 |
|
508 |
self.assert_(row[field_index["pip"]] == node.primary_ip and |
509 |
row[field_index["sip"]] == node.secondary_ip and |
510 |
set(row[field_index["tags"]]) == node.GetTags() and |
511 |
row[field_index["serial_no"]] == node.serial_no and |
512 |
row[field_index["role"]] == query._GetNodeRole(node,
|
513 |
master_name) and
|
514 |
(node.name == master_name or
|
515 |
(row[field_index["group"]] == "<unknown>" and |
516 |
row[field_index["group.uuid"]] is None and |
517 |
row[field_index["ctime"]] == (constants.RS_NORMAL,
|
518 |
node.ctime) and
|
519 |
row[field_index["mtime"]] == (constants.RS_NORMAL,
|
520 |
node.mtime) and
|
521 |
row[field_index["powered"]] == (constants.RS_NORMAL,
|
522 |
True))) or |
523 |
(node.name == oob_not_powered_node and
|
524 |
row[field_index["powered"]] == (constants.RS_NORMAL,
|
525 |
False)) or |
526 |
row[field_index["powered"]] == (constants.RS_UNAVAIL, None) |
527 |
for row, node in zip(result, nodes)) |
528 |
|
529 |
live_data_row = result[node_to_row[live_data_node.name]] |
530 |
|
531 |
for (field, value) in fake_live_data.items(): |
532 |
self.assertEqual(live_data_row[field_index[field]],
|
533 |
(constants.RS_NORMAL, value)) |
534 |
|
535 |
self.assertEqual(master_row[field_index["pinst_cnt"]], |
536 |
(constants.RS_NORMAL, 2))
|
537 |
self.assertEqual(live_data_row[field_index["sinst_cnt"]], |
538 |
(constants.RS_NORMAL, 3))
|
539 |
self.assertEqual(master_row[field_index["pinst_list"]], |
540 |
(constants.RS_NORMAL, |
541 |
[inst_uuid_to_inst_name[uuid] for uuid in |
542 |
node_to_primary_uuid[master_node.uuid]])) |
543 |
self.assertEqual(live_data_row[field_index["sinst_list"]], |
544 |
(constants.RS_NORMAL, |
545 |
utils.NiceSort( |
546 |
[inst_uuid_to_inst_name[uuid] for uuid in |
547 |
node_to_secondary_uuid[live_data_node.uuid]]))) |
548 |
|
549 |
def testGetLiveNodeField(self): |
550 |
nodes = [ |
551 |
objects.Node(name="node1", drained=False, offline=False, |
552 |
vm_capable=True),
|
553 |
objects.Node(name="node2", drained=True, offline=False, |
554 |
vm_capable=True),
|
555 |
objects.Node(name="node3", drained=False, offline=False, |
556 |
vm_capable=True),
|
557 |
objects.Node(name="node4", drained=False, offline=True, |
558 |
vm_capable=True),
|
559 |
objects.Node(name="node5", drained=False, offline=False, |
560 |
vm_capable=False),
|
561 |
] |
562 |
live_data = dict.fromkeys([node.name for node in nodes], {}) |
563 |
|
564 |
# No data
|
565 |
nqd = query.NodeQueryData(None, None, None, None, None, None, None, None, |
566 |
None)
|
567 |
self.assertEqual(query._GetLiveNodeField("hello", constants.QFT_NUMBER, |
568 |
nqd, nodes[0]),
|
569 |
query._FS_NODATA) |
570 |
|
571 |
# Missing field
|
572 |
ctx = _QueryData(None, curlive_data={
|
573 |
"some": 1, |
574 |
"other": 2, |
575 |
}) |
576 |
self.assertEqual(query._GetLiveNodeField("hello", constants.QFT_NUMBER, |
577 |
ctx, nodes[0]),
|
578 |
query._FS_UNAVAIL) |
579 |
|
580 |
# Wrong format/datatype
|
581 |
ctx = _QueryData(None, curlive_data={
|
582 |
"hello": ["Hello World"], |
583 |
"other": 2, |
584 |
}) |
585 |
self.assertEqual(query._GetLiveNodeField("hello", constants.QFT_NUMBER, |
586 |
ctx, nodes[0]),
|
587 |
query._FS_UNAVAIL) |
588 |
|
589 |
# Offline node
|
590 |
assert nodes[3].offline |
591 |
ctx = _QueryData(None, curlive_data={})
|
592 |
self.assertEqual(query._GetLiveNodeField("hello", constants.QFT_NUMBER, |
593 |
ctx, nodes[3]),
|
594 |
query._FS_OFFLINE, None)
|
595 |
|
596 |
# Wrong field type
|
597 |
ctx = _QueryData(None, curlive_data={"hello": 123}) |
598 |
self.assertRaises(AssertionError, query._GetLiveNodeField, |
599 |
"hello", constants.QFT_BOOL, ctx, nodes[0]) |
600 |
|
601 |
# Non-vm_capable node
|
602 |
assert not nodes[4].vm_capable |
603 |
ctx = _QueryData(None, curlive_data={})
|
604 |
self.assertEqual(query._GetLiveNodeField("hello", constants.QFT_NUMBER, |
605 |
ctx, nodes[4]),
|
606 |
query._FS_UNAVAIL, None)
|
607 |
|
608 |
|
609 |
class TestInstanceQuery(unittest.TestCase): |
610 |
def _Create(self, selected): |
611 |
return query.Query(query.INSTANCE_FIELDS, selected)
|
612 |
|
613 |
def testSimple(self): |
614 |
q = self._Create(["name", "be/maxmem", "ip"]) |
615 |
self.assertEqual(q.RequestedData(), set([query.IQ_CONFIG])) |
616 |
|
617 |
cluster = objects.Cluster(cluster_name="testcluster",
|
618 |
hvparams=constants.HVC_DEFAULTS, |
619 |
beparams={ |
620 |
constants.PP_DEFAULT: constants.BEC_DEFAULTS, |
621 |
}, |
622 |
nicparams={ |
623 |
constants.PP_DEFAULT: constants.NICC_DEFAULTS, |
624 |
}, |
625 |
os_hvp={}, |
626 |
osparams={}) |
627 |
|
628 |
instances = [ |
629 |
objects.Instance(name="inst1", hvparams={}, beparams={}, osparams={},
|
630 |
nics=[], os="deb1"),
|
631 |
objects.Instance(name="inst2", hvparams={}, nics=[], osparams={},
|
632 |
os="foomoo",
|
633 |
beparams={ |
634 |
constants.BE_MAXMEM: 512,
|
635 |
}), |
636 |
objects.Instance(name="inst3", hvparams={}, beparams={}, osparams={},
|
637 |
os="dos", nics=[objects.NIC(ip="192.0.2.99", nicparams={})]), |
638 |
] |
639 |
|
640 |
iqd = query.InstanceQueryData(instances, cluster, None, [], [], {},
|
641 |
set(), {}, None, None, None) |
642 |
self.assertEqual(q.Query(iqd),
|
643 |
[[(constants.RS_NORMAL, "inst1"),
|
644 |
(constants.RS_NORMAL, 128),
|
645 |
(constants.RS_UNAVAIL, None),
|
646 |
], |
647 |
[(constants.RS_NORMAL, "inst2"),
|
648 |
(constants.RS_NORMAL, 512),
|
649 |
(constants.RS_UNAVAIL, None),
|
650 |
], |
651 |
[(constants.RS_NORMAL, "inst3"),
|
652 |
(constants.RS_NORMAL, 128),
|
653 |
(constants.RS_NORMAL, "192.0.2.99"),
|
654 |
]]) |
655 |
self.assertEqual(q.OldStyleQuery(iqd),
|
656 |
[["inst1", 128, None], |
657 |
["inst2", 512, None], |
658 |
["inst3", 128, "192.0.2.99"]]) |
659 |
|
660 |
def test(self): |
661 |
selected = query.INSTANCE_FIELDS.keys() |
662 |
fieldidx = dict((field, idx) for idx, field in enumerate(selected)) |
663 |
|
664 |
macs = ["00:11:22:%02x:%02x:%02x" % (i % 255, i % 3, (i * 123) % 255) |
665 |
for i in range(20)] |
666 |
|
667 |
q = self._Create(selected)
|
668 |
self.assertEqual(q.RequestedData(),
|
669 |
set([query.IQ_CONFIG, query.IQ_LIVE, query.IQ_DISKUSAGE,
|
670 |
query.IQ_CONSOLE, query.IQ_NODES, query.IQ_NETWORKS])) |
671 |
|
672 |
cluster = objects.Cluster(cluster_name="testcluster",
|
673 |
hvparams=constants.HVC_DEFAULTS, |
674 |
beparams={ |
675 |
constants.PP_DEFAULT: constants.BEC_DEFAULTS, |
676 |
}, |
677 |
nicparams={ |
678 |
constants.PP_DEFAULT: constants.NICC_DEFAULTS, |
679 |
}, |
680 |
os_hvp={}, |
681 |
tcpudp_port_pool=set(),
|
682 |
osparams={ |
683 |
"deb99": {
|
684 |
"clean_install": "yes", |
685 |
}, |
686 |
}) |
687 |
|
688 |
offline_nodes = ["nodeoff1-uuid", "nodeoff2-uuid"] |
689 |
bad_nodes = ["nodebad1-uuid", "nodebad2-uuid", "nodebad3-uuid"] +\ |
690 |
offline_nodes |
691 |
node_uuids = ["node%s-uuid" % i for i in range(10)] + bad_nodes |
692 |
|
693 |
instances = [ |
694 |
objects.Instance(name="inst1", hvparams={}, beparams={}, nics=[],
|
695 |
uuid="inst1-uuid",
|
696 |
ctime=1291244000, mtime=1291244400, serial_no=30, |
697 |
admin_state=constants.ADMINST_UP, hypervisor=constants.HT_XEN_PVM, |
698 |
os="linux1",
|
699 |
primary_node="node1-uuid",
|
700 |
secondary_nodes=[], |
701 |
disk_template=constants.DT_PLAIN, |
702 |
disks=[], |
703 |
disks_active=True,
|
704 |
osparams={}), |
705 |
objects.Instance(name="inst2", hvparams={}, nics=[],
|
706 |
uuid="inst2-uuid",
|
707 |
ctime=1291211000, mtime=1291211077, serial_no=1, |
708 |
admin_state=constants.ADMINST_UP, hypervisor=constants.HT_XEN_HVM, |
709 |
os="deb99",
|
710 |
primary_node="node5-uuid",
|
711 |
secondary_nodes=[], |
712 |
disk_template=constants.DT_DISKLESS, |
713 |
disks=[], |
714 |
disks_active=True,
|
715 |
beparams={ |
716 |
constants.BE_MAXMEM: 512,
|
717 |
constants.BE_MINMEM: 256,
|
718 |
}, |
719 |
osparams={}), |
720 |
objects.Instance(name="inst3", hvparams={}, beparams={},
|
721 |
uuid="inst3-uuid",
|
722 |
ctime=1291011000, mtime=1291013000, serial_no=1923, |
723 |
admin_state=constants.ADMINST_DOWN, hypervisor=constants.HT_KVM, |
724 |
os="busybox",
|
725 |
primary_node="node6-uuid",
|
726 |
secondary_nodes=[], |
727 |
disk_template=constants.DT_DRBD8, |
728 |
disks=[], |
729 |
disks_active=False,
|
730 |
nics=[ |
731 |
objects.NIC(ip="192.0.2.99", mac=macs.pop(),
|
732 |
nicparams={ |
733 |
constants.NIC_LINK: constants.DEFAULT_BRIDGE, |
734 |
}), |
735 |
objects.NIC(ip=None, mac=macs.pop(), nicparams={}),
|
736 |
], |
737 |
osparams={}), |
738 |
objects.Instance(name="inst4", hvparams={}, beparams={},
|
739 |
uuid="inst4-uuid",
|
740 |
ctime=1291244390, mtime=1291244395, serial_no=25, |
741 |
admin_state=constants.ADMINST_DOWN, hypervisor=constants.HT_XEN_PVM, |
742 |
os="linux1",
|
743 |
primary_node="nodeoff2-uuid",
|
744 |
secondary_nodes=[], |
745 |
disk_template=constants.DT_DRBD8, |
746 |
disks=[], |
747 |
disks_active=True,
|
748 |
nics=[ |
749 |
objects.NIC(ip="192.0.2.1", mac=macs.pop(),
|
750 |
nicparams={ |
751 |
constants.NIC_LINK: constants.DEFAULT_BRIDGE, |
752 |
}), |
753 |
objects.NIC(ip="192.0.2.2", mac=macs.pop(), nicparams={}),
|
754 |
objects.NIC(ip="192.0.2.3", mac=macs.pop(),
|
755 |
nicparams={ |
756 |
constants.NIC_MODE: constants.NIC_MODE_ROUTED, |
757 |
}), |
758 |
objects.NIC(ip="192.0.2.4", mac=macs.pop(),
|
759 |
nicparams={ |
760 |
constants.NIC_MODE: constants.NIC_MODE_BRIDGED, |
761 |
constants.NIC_LINK: "eth123",
|
762 |
}), |
763 |
], |
764 |
osparams={}), |
765 |
objects.Instance(name="inst5", hvparams={}, nics=[],
|
766 |
uuid="inst5-uuid",
|
767 |
ctime=1231211000, mtime=1261200000, serial_no=3, |
768 |
admin_state=constants.ADMINST_UP, hypervisor=constants.HT_XEN_HVM, |
769 |
os="deb99",
|
770 |
primary_node="nodebad2-uuid",
|
771 |
secondary_nodes=[], |
772 |
disk_template=constants.DT_DISKLESS, |
773 |
disks=[], |
774 |
disks_active=True,
|
775 |
beparams={ |
776 |
constants.BE_MAXMEM: 512,
|
777 |
constants.BE_MINMEM: 512,
|
778 |
}, |
779 |
osparams={}), |
780 |
objects.Instance(name="inst6", hvparams={}, nics=[],
|
781 |
uuid="inst6-uuid",
|
782 |
ctime=7513, mtime=11501, serial_no=13390, |
783 |
admin_state=constants.ADMINST_DOWN, hypervisor=constants.HT_XEN_HVM, |
784 |
os="deb99",
|
785 |
primary_node="node7-uuid",
|
786 |
secondary_nodes=[], |
787 |
disk_template=constants.DT_DISKLESS, |
788 |
disks=[], |
789 |
disks_active=False,
|
790 |
beparams={ |
791 |
constants.BE_MAXMEM: 768,
|
792 |
constants.BE_MINMEM: 256,
|
793 |
}, |
794 |
osparams={ |
795 |
"clean_install": "no", |
796 |
}), |
797 |
objects.Instance(name="inst7", hvparams={}, nics=[],
|
798 |
uuid="inst7-uuid",
|
799 |
ctime=None, mtime=None, serial_no=1947, |
800 |
admin_state=constants.ADMINST_DOWN, hypervisor=constants.HT_XEN_HVM, |
801 |
os="deb99",
|
802 |
primary_node="node6-uuid",
|
803 |
secondary_nodes=[], |
804 |
disk_template=constants.DT_DISKLESS, |
805 |
disks=[], |
806 |
disks_active=False,
|
807 |
beparams={}, |
808 |
osparams={}), |
809 |
objects.Instance(name="inst8", hvparams={}, nics=[],
|
810 |
uuid="inst8-uuid",
|
811 |
ctime=None, mtime=None, serial_no=19478, |
812 |
admin_state=constants.ADMINST_OFFLINE, hypervisor=constants.HT_XEN_HVM, |
813 |
os="deb99",
|
814 |
primary_node="node6-uuid",
|
815 |
secondary_nodes=[], |
816 |
disk_template=constants.DT_DISKLESS, |
817 |
disks=[], |
818 |
disks_active=False,
|
819 |
beparams={}, |
820 |
osparams={}), |
821 |
objects.Instance(name="inst9", hvparams={}, nics=[],
|
822 |
uuid="inst9-uuid",
|
823 |
ctime=None, mtime=None, serial_no=19478, |
824 |
admin_state=constants.ADMINST_UP, hypervisor=constants.HT_XEN_HVM, |
825 |
os="deb99",
|
826 |
primary_node="node6-uuid",
|
827 |
secondary_nodes=[], |
828 |
disk_template=constants.DT_DISKLESS, |
829 |
disks=[], |
830 |
disks_active=False,
|
831 |
beparams={}, |
832 |
osparams={}), |
833 |
] |
834 |
|
835 |
assert not utils.FindDuplicates(inst.uuid for inst in instances) |
836 |
assert not utils.FindDuplicates(inst.name for inst in instances) |
837 |
|
838 |
instbyname = dict((inst.name, inst) for inst in instances) |
839 |
|
840 |
disk_usage = dict((inst.uuid,
|
841 |
gmi.ComputeDiskSize(inst.disk_template, |
842 |
[{"size": disk.size}
|
843 |
for disk in inst.disks])) |
844 |
for inst in instances) |
845 |
|
846 |
inst_bridges = { |
847 |
"inst3-uuid": [constants.DEFAULT_BRIDGE, constants.DEFAULT_BRIDGE],
|
848 |
"inst4-uuid": [constants.DEFAULT_BRIDGE, constants.DEFAULT_BRIDGE,
|
849 |
None, "eth123"], |
850 |
} |
851 |
|
852 |
live_data = { |
853 |
"inst2-uuid": {
|
854 |
"vcpus": 3, |
855 |
"state": hv_base.HvInstanceState.RUNNING,
|
856 |
}, |
857 |
"inst4-uuid": {
|
858 |
"memory": 123, |
859 |
"state": hv_base.HvInstanceState.RUNNING,
|
860 |
}, |
861 |
"inst6-uuid": {
|
862 |
"memory": 768, |
863 |
"state": hv_base.HvInstanceState.RUNNING,
|
864 |
}, |
865 |
"inst7-uuid": {
|
866 |
"vcpus": 3, |
867 |
"state": hv_base.HvInstanceState.RUNNING,
|
868 |
}, |
869 |
"inst9-uuid": {
|
870 |
"vcpus": 3, |
871 |
"state": hv_base.HvInstanceState.SHUTDOWN,
|
872 |
}, |
873 |
} |
874 |
wrongnode_inst = set(["inst7-uuid"]) |
875 |
|
876 |
consinfo = dict((inst.uuid, None) for inst in instances) |
877 |
consinfo["inst7-uuid"] = \
|
878 |
objects.InstanceConsole(instance="inst7", kind=constants.CONS_SSH,
|
879 |
host=instbyname["inst7"].primary_node,
|
880 |
user="root",
|
881 |
command=["hostname"]).ToDict()
|
882 |
|
883 |
nodes = dict([(uuid, objects.Node(
|
884 |
name="%s.example.com" % uuid,
|
885 |
uuid=uuid, |
886 |
group="default-uuid"))
|
887 |
for uuid in node_uuids]) |
888 |
|
889 |
iqd = query.InstanceQueryData(instances, cluster, disk_usage, |
890 |
offline_nodes, bad_nodes, live_data, |
891 |
wrongnode_inst, consinfo, nodes, {}, {}) |
892 |
result = q.Query(iqd) |
893 |
self.assertEqual(len(result), len(instances)) |
894 |
self.assert_(compat.all(len(row) == len(selected) |
895 |
for row in result)) |
896 |
|
897 |
assert len(set(bad_nodes) & set(offline_nodes)) == len(offline_nodes), \ |
898 |
"Offline nodes not included in bad nodes"
|
899 |
|
900 |
tested_status = set()
|
901 |
|
902 |
for (inst, row) in zip(instances, result): |
903 |
assert inst.primary_node in node_uuids |
904 |
|
905 |
self.assertEqual(row[fieldidx["name"]], |
906 |
(constants.RS_NORMAL, inst.name)) |
907 |
|
908 |
if inst.primary_node in offline_nodes: |
909 |
exp_status = constants.INSTST_NODEOFFLINE |
910 |
elif inst.primary_node in bad_nodes: |
911 |
exp_status = constants.INSTST_NODEDOWN |
912 |
elif inst.uuid in live_data: |
913 |
if inst.uuid in wrongnode_inst: |
914 |
exp_status = constants.INSTST_WRONGNODE |
915 |
else:
|
916 |
instance_state = live_data[inst.uuid]["state"]
|
917 |
if hv_base.HvInstanceState.IsShutdown(instance_state):
|
918 |
if inst.admin_state == constants.ADMINST_UP:
|
919 |
exp_status = constants.INSTST_USERDOWN |
920 |
else:
|
921 |
exp_status = constants.INSTST_ADMINDOWN |
922 |
else:
|
923 |
if inst.admin_state == constants.ADMINST_UP:
|
924 |
exp_status = constants.INSTST_RUNNING |
925 |
else:
|
926 |
exp_status = constants.INSTST_ERRORUP |
927 |
else:
|
928 |
if inst.admin_state == constants.ADMINST_UP:
|
929 |
exp_status = constants.INSTST_ERRORDOWN |
930 |
elif inst.admin_state == constants.ADMINST_DOWN:
|
931 |
exp_status = constants.INSTST_ADMINDOWN |
932 |
else:
|
933 |
exp_status = constants.INSTST_ADMINOFFLINE |
934 |
|
935 |
self.assertEqual(row[fieldidx["status"]], |
936 |
(constants.RS_NORMAL, exp_status)) |
937 |
|
938 |
(_, status) = row[fieldidx["status"]]
|
939 |
tested_status.add(status) |
940 |
|
941 |
#FIXME(dynmem): check oper_ram vs min/max mem
|
942 |
for (field, livefield) in [("oper_vcpus", "vcpus")]: |
943 |
if inst.primary_node in bad_nodes: |
944 |
exp = (constants.RS_NODATA, None)
|
945 |
elif inst.uuid in live_data: |
946 |
value = live_data[inst.uuid].get(livefield, None)
|
947 |
if value is None: |
948 |
exp = (constants.RS_UNAVAIL, None)
|
949 |
else:
|
950 |
exp = (constants.RS_NORMAL, value) |
951 |
else:
|
952 |
exp = (constants.RS_UNAVAIL, None)
|
953 |
|
954 |
self.assertEqual(row[fieldidx[field]], exp)
|
955 |
|
956 |
bridges = inst_bridges.get(inst.uuid, []) |
957 |
self.assertEqual(row[fieldidx["nic.bridges"]], |
958 |
(constants.RS_NORMAL, bridges)) |
959 |
if bridges:
|
960 |
self.assertEqual(row[fieldidx["bridge"]], |
961 |
(constants.RS_NORMAL, bridges[0]))
|
962 |
else:
|
963 |
self.assertEqual(row[fieldidx["bridge"]], |
964 |
(constants.RS_UNAVAIL, None))
|
965 |
|
966 |
for i in range(constants.MAX_NICS): |
967 |
if i < len(bridges) and bridges[i] is not None: |
968 |
exp = (constants.RS_NORMAL, bridges[i]) |
969 |
else:
|
970 |
exp = (constants.RS_UNAVAIL, None)
|
971 |
self.assertEqual(row[fieldidx["nic.bridge/%s" % i]], exp) |
972 |
|
973 |
if inst.primary_node in bad_nodes: |
974 |
exp = (constants.RS_NODATA, None)
|
975 |
else:
|
976 |
exp = (constants.RS_NORMAL, inst.uuid in live_data)
|
977 |
self.assertEqual(row[fieldidx["oper_state"]], exp) |
978 |
|
979 |
cust_exp = (constants.RS_NORMAL, {}) |
980 |
if inst.os == "deb99": |
981 |
if inst.uuid == "inst6-uuid": |
982 |
exp = (constants.RS_NORMAL, {"clean_install": "no"}) |
983 |
cust_exp = exp |
984 |
else:
|
985 |
exp = (constants.RS_NORMAL, {"clean_install": "yes"}) |
986 |
else:
|
987 |
exp = (constants.RS_NORMAL, {}) |
988 |
self.assertEqual(row[fieldidx["osparams"]], exp) |
989 |
self.assertEqual(row[fieldidx["custom_osparams"]], cust_exp) |
990 |
|
991 |
usage = disk_usage[inst.uuid] |
992 |
if usage is None: |
993 |
usage = 0
|
994 |
self.assertEqual(row[fieldidx["disk_usage"]], |
995 |
(constants.RS_NORMAL, usage)) |
996 |
|
997 |
for alias, target in [("sda_size", "disk.size/0"), |
998 |
("sdb_size", "disk.size/1"), |
999 |
("vcpus", "be/vcpus"), |
1000 |
("ip", "nic.ip/0"), |
1001 |
("mac", "nic.mac/0"), |
1002 |
("bridge", "nic.bridge/0"), |
1003 |
("nic_mode", "nic.mode/0"), |
1004 |
("nic_link", "nic.link/0"), |
1005 |
]: |
1006 |
self.assertEqual(row[fieldidx[alias]], row[fieldidx[target]])
|
1007 |
|
1008 |
for field in ["ctime", "mtime"]: |
1009 |
if getattr(inst, field) is None: |
1010 |
# No ctime/mtime
|
1011 |
exp = (constants.RS_UNAVAIL, None)
|
1012 |
else:
|
1013 |
exp = (constants.RS_NORMAL, getattr(inst, field))
|
1014 |
self.assertEqual(row[fieldidx[field]], exp)
|
1015 |
|
1016 |
self._CheckInstanceConsole(inst, row[fieldidx["console"]]) |
1017 |
|
1018 |
# Ensure all possible status' have been tested
|
1019 |
self.assertEqual(tested_status, set(constants.INSTST_ALL)) |
1020 |
|
1021 |
def _CheckInstanceConsole(self, instance, (status, consdata)): |
1022 |
if instance.name == "inst7": |
1023 |
self.assertEqual(status, constants.RS_NORMAL)
|
1024 |
console = objects.InstanceConsole.FromDict(consdata) |
1025 |
self.assertTrue(console.Validate())
|
1026 |
self.assertEqual(console.host, instance.primary_node)
|
1027 |
else:
|
1028 |
self.assertEqual(status, constants.RS_UNAVAIL)
|
1029 |
|
1030 |
|
1031 |
class TestGroupQuery(unittest.TestCase): |
1032 |
|
1033 |
def setUp(self): |
1034 |
self.custom_diskparams = {
|
1035 |
constants.DT_DRBD8: { |
1036 |
constants.DRBD_DEFAULT_METAVG: "foobar",
|
1037 |
}, |
1038 |
} |
1039 |
|
1040 |
self.groups = [
|
1041 |
objects.NodeGroup(name="default",
|
1042 |
uuid="c0e89160-18e7-11e0-a46e-001d0904baeb",
|
1043 |
alloc_policy=constants.ALLOC_POLICY_PREFERRED, |
1044 |
ipolicy=objects.MakeEmptyIPolicy(), |
1045 |
ndparams={}, |
1046 |
diskparams={}, |
1047 |
), |
1048 |
objects.NodeGroup(name="restricted",
|
1049 |
uuid="d2a40a74-18e7-11e0-9143-001d0904baeb",
|
1050 |
alloc_policy=constants.ALLOC_POLICY_LAST_RESORT, |
1051 |
ipolicy=objects.MakeEmptyIPolicy(), |
1052 |
ndparams={}, |
1053 |
diskparams=self.custom_diskparams,
|
1054 |
), |
1055 |
] |
1056 |
self.cluster = objects.Cluster(cluster_name="testcluster", |
1057 |
hvparams=constants.HVC_DEFAULTS, |
1058 |
beparams={ |
1059 |
constants.PP_DEFAULT: constants.BEC_DEFAULTS, |
1060 |
}, |
1061 |
nicparams={ |
1062 |
constants.PP_DEFAULT: constants.NICC_DEFAULTS, |
1063 |
}, |
1064 |
ndparams=constants.NDC_DEFAULTS, |
1065 |
ipolicy=constants.IPOLICY_DEFAULTS, |
1066 |
diskparams=constants.DISK_DT_DEFAULTS, |
1067 |
) |
1068 |
|
1069 |
def _Create(self, selected): |
1070 |
return query.Query(query.GROUP_FIELDS, selected)
|
1071 |
|
1072 |
def testSimple(self): |
1073 |
q = self._Create(["name", "uuid", "alloc_policy"]) |
1074 |
gqd = query.GroupQueryData(self.cluster, self.groups, None, None, False) |
1075 |
|
1076 |
self.assertEqual(q.RequestedData(), set([query.GQ_CONFIG])) |
1077 |
|
1078 |
self.assertEqual(q.Query(gqd),
|
1079 |
[[(constants.RS_NORMAL, "default"),
|
1080 |
(constants.RS_NORMAL, "c0e89160-18e7-11e0-a46e-001d0904baeb"),
|
1081 |
(constants.RS_NORMAL, constants.ALLOC_POLICY_PREFERRED) |
1082 |
], |
1083 |
[(constants.RS_NORMAL, "restricted"),
|
1084 |
(constants.RS_NORMAL, "d2a40a74-18e7-11e0-9143-001d0904baeb"),
|
1085 |
(constants.RS_NORMAL, constants.ALLOC_POLICY_LAST_RESORT) |
1086 |
], |
1087 |
]) |
1088 |
|
1089 |
def testNodes(self): |
1090 |
groups_to_nodes = { |
1091 |
"c0e89160-18e7-11e0-a46e-001d0904baeb": ["node1", "node2"], |
1092 |
"d2a40a74-18e7-11e0-9143-001d0904baeb": ["node1", "node10", "node9"], |
1093 |
} |
1094 |
|
1095 |
q = self._Create(["name", "node_cnt", "node_list"]) |
1096 |
gqd = query.GroupQueryData(self.cluster, self.groups, groups_to_nodes, None, |
1097 |
False)
|
1098 |
|
1099 |
self.assertEqual(q.RequestedData(), set([query.GQ_CONFIG, query.GQ_NODE])) |
1100 |
|
1101 |
self.assertEqual(q.Query(gqd),
|
1102 |
[[(constants.RS_NORMAL, "default"),
|
1103 |
(constants.RS_NORMAL, 2),
|
1104 |
(constants.RS_NORMAL, ["node1", "node2"]), |
1105 |
], |
1106 |
[(constants.RS_NORMAL, "restricted"),
|
1107 |
(constants.RS_NORMAL, 3),
|
1108 |
(constants.RS_NORMAL, ["node1", "node9", "node10"]), |
1109 |
], |
1110 |
]) |
1111 |
|
1112 |
def testInstances(self): |
1113 |
groups_to_instances = { |
1114 |
"c0e89160-18e7-11e0-a46e-001d0904baeb": ["inst1", "inst2"], |
1115 |
"d2a40a74-18e7-11e0-9143-001d0904baeb": ["inst1", "inst10", "inst9"], |
1116 |
} |
1117 |
|
1118 |
q = self._Create(["pinst_cnt", "pinst_list"]) |
1119 |
gqd = query.GroupQueryData(self.cluster, self.groups, None, |
1120 |
groups_to_instances, False)
|
1121 |
|
1122 |
self.assertEqual(q.RequestedData(), set([query.GQ_INST])) |
1123 |
|
1124 |
self.assertEqual(q.Query(gqd),
|
1125 |
[[(constants.RS_NORMAL, 2),
|
1126 |
(constants.RS_NORMAL, ["inst1", "inst2"]), |
1127 |
], |
1128 |
[(constants.RS_NORMAL, 3),
|
1129 |
(constants.RS_NORMAL, ["inst1", "inst9", "inst10"]), |
1130 |
], |
1131 |
]) |
1132 |
|
1133 |
def testDiskparams(self): |
1134 |
q = self._Create(["name", "uuid", "diskparams", "custom_diskparams"]) |
1135 |
gqd = query.GroupQueryData(self.cluster, self.groups, None, None, True) |
1136 |
|
1137 |
self.assertEqual(q.RequestedData(),
|
1138 |
set([query.GQ_CONFIG, query.GQ_DISKPARAMS]))
|
1139 |
|
1140 |
self.assertEqual(q.Query(gqd),
|
1141 |
[[(constants.RS_NORMAL, "default"),
|
1142 |
(constants.RS_NORMAL, "c0e89160-18e7-11e0-a46e-001d0904baeb"),
|
1143 |
(constants.RS_NORMAL, constants.DISK_DT_DEFAULTS), |
1144 |
(constants.RS_NORMAL, {}), |
1145 |
], |
1146 |
[(constants.RS_NORMAL, "restricted"),
|
1147 |
(constants.RS_NORMAL, "d2a40a74-18e7-11e0-9143-001d0904baeb"),
|
1148 |
(constants.RS_NORMAL, objects.FillDiskParams(constants.DISK_DT_DEFAULTS, |
1149 |
self.custom_diskparams)),
|
1150 |
(constants.RS_NORMAL, self.custom_diskparams),
|
1151 |
], |
1152 |
]) |
1153 |
|
1154 |
|
1155 |
class TestOsQuery(unittest.TestCase): |
1156 |
def _Create(self, selected): |
1157 |
return query.Query(query.OS_FIELDS, selected)
|
1158 |
|
1159 |
def test(self): |
1160 |
variants = ["v00", "plain", "v3", "var0", "v33", "v20"] |
1161 |
api_versions = [10, 0, 15, 5] |
1162 |
parameters = ["zpar3", "apar9"] |
1163 |
|
1164 |
assert variants != sorted(variants) and variants != utils.NiceSort(variants) |
1165 |
assert (api_versions != sorted(api_versions) and |
1166 |
api_versions != utils.NiceSort(variants)) |
1167 |
assert (parameters != sorted(parameters) and |
1168 |
parameters != utils.NiceSort(parameters)) |
1169 |
|
1170 |
data = [ |
1171 |
query.OsInfo(name="debian", valid=False, hidden=False, blacklisted=False, |
1172 |
variants=set(), api_versions=set(), parameters=set(), |
1173 |
node_status={ "some": "status", }), |
1174 |
query.OsInfo(name="dos", valid=True, hidden=False, blacklisted=True, |
1175 |
variants=set(variants),
|
1176 |
api_versions=set(api_versions),
|
1177 |
parameters=set(parameters),
|
1178 |
node_status={ "some": "other", "status": None, }), |
1179 |
] |
1180 |
|
1181 |
|
1182 |
q = self._Create(["name", "valid", "hidden", "blacklisted", "variants", |
1183 |
"api_versions", "parameters", "node_status"]) |
1184 |
self.assertEqual(q.RequestedData(), set([])) |
1185 |
self.assertEqual(q.Query(data),
|
1186 |
[[(constants.RS_NORMAL, "debian"),
|
1187 |
(constants.RS_NORMAL, False),
|
1188 |
(constants.RS_NORMAL, False),
|
1189 |
(constants.RS_NORMAL, False),
|
1190 |
(constants.RS_NORMAL, []), |
1191 |
(constants.RS_NORMAL, []), |
1192 |
(constants.RS_NORMAL, []), |
1193 |
(constants.RS_NORMAL, {"some": "status"})], |
1194 |
[(constants.RS_NORMAL, "dos"),
|
1195 |
(constants.RS_NORMAL, True),
|
1196 |
(constants.RS_NORMAL, False),
|
1197 |
(constants.RS_NORMAL, True),
|
1198 |
(constants.RS_NORMAL, |
1199 |
["plain", "v00", "v3", "v20", "v33", "var0"]), |
1200 |
(constants.RS_NORMAL, [0, 5, 10, 15]), |
1201 |
(constants.RS_NORMAL, ["apar9", "zpar3"]), |
1202 |
(constants.RS_NORMAL, |
1203 |
{ "some": "other", "status": None, }) |
1204 |
]]) |
1205 |
|
1206 |
|
1207 |
class TestQueryFields(unittest.TestCase): |
1208 |
def testAllFields(self): |
1209 |
for fielddefs in query.ALL_FIELD_LISTS: |
1210 |
result = query.QueryFields(fielddefs, None)
|
1211 |
self.assert_(isinstance(result, dict)) |
1212 |
response = objects.QueryFieldsResponse.FromDict(result) |
1213 |
self.assertEqual([(fdef.name, fdef.title) for fdef in response.fields], |
1214 |
[(fdef2.name, fdef2.title) |
1215 |
for (fdef2, _, _, _) in utils.NiceSort(fielddefs.values(), |
1216 |
key=lambda x: x[0].name)]) |
1217 |
|
1218 |
def testSomeFields(self): |
1219 |
rnd = random.Random(5357)
|
1220 |
|
1221 |
for _ in range(10): |
1222 |
for fielddefs in query.ALL_FIELD_LISTS: |
1223 |
if len(fielddefs) > 20: |
1224 |
sample_size = rnd.randint(5, 20) |
1225 |
else:
|
1226 |
sample_size = rnd.randint(1, max(1, len(fielddefs) - 1)) |
1227 |
fields = [fdef for (fdef, _, _, _) in rnd.sample(fielddefs.values(), |
1228 |
sample_size)] |
1229 |
result = query.QueryFields(fielddefs, [fdef.name for fdef in fields]) |
1230 |
self.assert_(isinstance(result, dict)) |
1231 |
response = objects.QueryFieldsResponse.FromDict(result) |
1232 |
self.assertEqual([(fdef.name, fdef.title) for fdef in response.fields], |
1233 |
[(fdef2.name, fdef2.title) for fdef2 in fields]) |
1234 |
|
1235 |
|
1236 |
class TestQueryFilter(unittest.TestCase): |
1237 |
def testRequestedNames(self): |
1238 |
for (what, fielddefs) in query.ALL_FIELDS.items(): |
1239 |
if what == constants.QR_JOB:
|
1240 |
namefield = "id"
|
1241 |
nameval = 123
|
1242 |
namevalempty = 0
|
1243 |
genval = lambda i: i * 10 |
1244 |
randvals = [17361, 22015, 13193, 15215] |
1245 |
else:
|
1246 |
nameval = "abc"
|
1247 |
namevalempty = ""
|
1248 |
genval = lambda i: "x%s" % i |
1249 |
randvals = ["x17361", "x22015", "x13193", "x15215"] |
1250 |
if what == constants.QR_EXPORT:
|
1251 |
namefield = "export"
|
1252 |
else:
|
1253 |
namefield = "name"
|
1254 |
|
1255 |
assert namefield in fielddefs |
1256 |
|
1257 |
reqnames = [genval(i) for i in range(4)] |
1258 |
innerfilter = [["=", namefield, v] for v in reqnames] |
1259 |
|
1260 |
# No name field
|
1261 |
q = query.Query(fielddefs, [namefield], |
1262 |
qfilter=["=", namefield, nameval], namefield=None) |
1263 |
self.assertEqual(q.RequestedNames(), None) |
1264 |
|
1265 |
# No filter
|
1266 |
q = query.Query(fielddefs, [namefield], qfilter=None, namefield=namefield)
|
1267 |
self.assertEqual(q.RequestedNames(), None) |
1268 |
|
1269 |
# Check empty query
|
1270 |
q = query.Query(fielddefs, [namefield], qfilter=["|"],
|
1271 |
namefield=namefield) |
1272 |
self.assertEqual(q.RequestedNames(), None) |
1273 |
|
1274 |
# Check order
|
1275 |
q = query.Query(fielddefs, [namefield], qfilter=["|"] + innerfilter,
|
1276 |
namefield=namefield) |
1277 |
self.assertEqual(q.RequestedNames(), reqnames)
|
1278 |
|
1279 |
# Check reverse order
|
1280 |
q = query.Query(fielddefs, [namefield], |
1281 |
qfilter=["|"] + list(reversed(innerfilter)), |
1282 |
namefield=namefield) |
1283 |
self.assertEqual(q.RequestedNames(), list(reversed(reqnames))) |
1284 |
|
1285 |
# Duplicates
|
1286 |
q = query.Query(fielddefs, [namefield], |
1287 |
qfilter=["|"] + innerfilter + list(reversed(innerfilter)), |
1288 |
namefield=namefield) |
1289 |
self.assertEqual(q.RequestedNames(), reqnames)
|
1290 |
|
1291 |
# Unknown name field
|
1292 |
self.assertRaises(AssertionError, query.Query, fielddefs, [namefield], |
1293 |
namefield="_unknown_field_")
|
1294 |
|
1295 |
# Filter with AND
|
1296 |
q = query.Query(fielddefs, [namefield], |
1297 |
qfilter=["|", ["=", namefield, nameval], |
1298 |
["&", ["=", namefield, namevalempty]]], |
1299 |
namefield=namefield) |
1300 |
self.assertTrue(q.RequestedNames() is None) |
1301 |
|
1302 |
# Filter with NOT
|
1303 |
q = query.Query(fielddefs, [namefield], |
1304 |
qfilter=["|", ["=", namefield, nameval], |
1305 |
["!", ["=", namefield, namevalempty]]], |
1306 |
namefield=namefield) |
1307 |
self.assertTrue(q.RequestedNames() is None) |
1308 |
|
1309 |
# Filter with only OR (names must be in correct order)
|
1310 |
q = query.Query(fielddefs, [namefield], |
1311 |
qfilter=["|", ["=", namefield, randvals[0]], |
1312 |
["|", ["=", namefield, randvals[1]]], |
1313 |
["|", ["|", ["=", namefield, randvals[2]]]], |
1314 |
["=", namefield, randvals[3]]], |
1315 |
namefield=namefield) |
1316 |
self.assertEqual(q.RequestedNames(), randvals)
|
1317 |
|
1318 |
@staticmethod
|
1319 |
def _GenNestedFilter(namefield, op, depth, nameval): |
1320 |
nested = ["=", namefield, nameval]
|
1321 |
for i in range(depth): |
1322 |
nested = [op, nested] |
1323 |
return nested
|
1324 |
|
1325 |
def testCompileFilter(self): |
1326 |
levels_max = query._FilterCompilerHelper._LEVELS_MAX |
1327 |
|
1328 |
for (what, fielddefs) in query.ALL_FIELDS.items(): |
1329 |
if what == constants.QR_JOB:
|
1330 |
namefield = "id"
|
1331 |
nameval = 123
|
1332 |
elif what == constants.QR_EXPORT:
|
1333 |
namefield = "export"
|
1334 |
nameval = "value"
|
1335 |
else:
|
1336 |
namefield = "name"
|
1337 |
nameval = "value"
|
1338 |
|
1339 |
checks = [ |
1340 |
[], ["="], ["=", "foo"], ["unknownop"], ["!"], |
1341 |
["=", "_unknown_field", "value"], |
1342 |
self._GenNestedFilter(namefield, "|", levels_max, nameval), |
1343 |
self._GenNestedFilter(namefield, "|", levels_max * 3, nameval), |
1344 |
self._GenNestedFilter(namefield, "!", levels_max, nameval), |
1345 |
] |
1346 |
|
1347 |
for qfilter in checks: |
1348 |
self.assertRaises(errors.ParameterError, query._CompileFilter,
|
1349 |
fielddefs, None, qfilter)
|
1350 |
|
1351 |
for op in ["|", "!"]: |
1352 |
qfilter = self._GenNestedFilter(namefield, op, levels_max - 1, nameval) |
1353 |
self.assertTrue(callable(query._CompileFilter(fielddefs, None, |
1354 |
qfilter))) |
1355 |
|
1356 |
def testQueryInputOrder(self): |
1357 |
fielddefs = query._PrepareFieldList([ |
1358 |
(query._MakeField("pnode", "PNode", constants.QFT_TEXT, "Primary"), |
1359 |
None, 0, lambda ctx, item: item["pnode"]), |
1360 |
(query._MakeField("snode", "SNode", constants.QFT_TEXT, "Secondary"), |
1361 |
None, 0, lambda ctx, item: item["snode"]), |
1362 |
], []) |
1363 |
|
1364 |
data = [ |
1365 |
{ "pnode": "node1", "snode": "node44", }, |
1366 |
{ "pnode": "node30", "snode": "node90", }, |
1367 |
{ "pnode": "node25", "snode": "node1", }, |
1368 |
{ "pnode": "node20", "snode": "node1", }, |
1369 |
] |
1370 |
|
1371 |
qfilter = ["|", ["=", "pnode", "node1"], ["=", "snode", "node1"]] |
1372 |
|
1373 |
q = query.Query(fielddefs, ["pnode", "snode"], namefield="pnode", |
1374 |
qfilter=qfilter) |
1375 |
self.assertTrue(q.RequestedNames() is None) |
1376 |
self.assertFalse(q.RequestedData())
|
1377 |
self.assertEqual(q.Query(data),
|
1378 |
[[(constants.RS_NORMAL, "node1"), (constants.RS_NORMAL, "node44")], |
1379 |
[(constants.RS_NORMAL, "node20"), (constants.RS_NORMAL, "node1")], |
1380 |
[(constants.RS_NORMAL, "node25"), (constants.RS_NORMAL, "node1")]]) |
1381 |
|
1382 |
# Try again with reversed input data
|
1383 |
self.assertEqual(q.Query(reversed(data)), |
1384 |
[[(constants.RS_NORMAL, "node1"), (constants.RS_NORMAL, "node44")], |
1385 |
[(constants.RS_NORMAL, "node20"), (constants.RS_NORMAL, "node1")], |
1386 |
[(constants.RS_NORMAL, "node25"), (constants.RS_NORMAL, "node1")]]) |
1387 |
|
1388 |
# No name field, result must be in incoming order
|
1389 |
q = query.Query(fielddefs, ["pnode", "snode"], namefield=None, |
1390 |
qfilter=qfilter) |
1391 |
self.assertFalse(q.RequestedData())
|
1392 |
self.assertEqual(q.Query(data),
|
1393 |
[[(constants.RS_NORMAL, "node1"), (constants.RS_NORMAL, "node44")], |
1394 |
[(constants.RS_NORMAL, "node25"), (constants.RS_NORMAL, "node1")], |
1395 |
[(constants.RS_NORMAL, "node20"), (constants.RS_NORMAL, "node1")]]) |
1396 |
self.assertEqual(q.OldStyleQuery(data), [
|
1397 |
["node1", "node44"], |
1398 |
["node25", "node1"], |
1399 |
["node20", "node1"], |
1400 |
]) |
1401 |
self.assertEqual(q.Query(reversed(data)), |
1402 |
[[(constants.RS_NORMAL, "node20"), (constants.RS_NORMAL, "node1")], |
1403 |
[(constants.RS_NORMAL, "node25"), (constants.RS_NORMAL, "node1")], |
1404 |
[(constants.RS_NORMAL, "node1"), (constants.RS_NORMAL, "node44")]]) |
1405 |
self.assertEqual(q.OldStyleQuery(reversed(data)), [ |
1406 |
["node20", "node1"], |
1407 |
["node25", "node1"], |
1408 |
["node1", "node44"], |
1409 |
]) |
1410 |
|
1411 |
# Name field, but no sorting, result must be in incoming order
|
1412 |
q = query.Query(fielddefs, ["pnode", "snode"], namefield="pnode") |
1413 |
self.assertFalse(q.RequestedData())
|
1414 |
self.assertEqual(q.Query(data, sort_by_name=False), |
1415 |
[[(constants.RS_NORMAL, "node1"), (constants.RS_NORMAL, "node44")], |
1416 |
[(constants.RS_NORMAL, "node30"), (constants.RS_NORMAL, "node90")], |
1417 |
[(constants.RS_NORMAL, "node25"), (constants.RS_NORMAL, "node1")], |
1418 |
[(constants.RS_NORMAL, "node20"), (constants.RS_NORMAL, "node1")]]) |
1419 |
self.assertEqual(q.OldStyleQuery(data, sort_by_name=False), [ |
1420 |
["node1", "node44"], |
1421 |
["node30", "node90"], |
1422 |
["node25", "node1"], |
1423 |
["node20", "node1"], |
1424 |
]) |
1425 |
self.assertEqual(q.Query(reversed(data), sort_by_name=False), |
1426 |
[[(constants.RS_NORMAL, "node20"), (constants.RS_NORMAL, "node1")], |
1427 |
[(constants.RS_NORMAL, "node25"), (constants.RS_NORMAL, "node1")], |
1428 |
[(constants.RS_NORMAL, "node30"), (constants.RS_NORMAL, "node90")], |
1429 |
[(constants.RS_NORMAL, "node1"), (constants.RS_NORMAL, "node44")]]) |
1430 |
self.assertEqual(q.OldStyleQuery(reversed(data), sort_by_name=False), [ |
1431 |
["node20", "node1"], |
1432 |
["node25", "node1"], |
1433 |
["node30", "node90"], |
1434 |
["node1", "node44"], |
1435 |
]) |
1436 |
|
1437 |
def testEqualNamesOrder(self): |
1438 |
fielddefs = query._PrepareFieldList([ |
1439 |
(query._MakeField("pnode", "PNode", constants.QFT_TEXT, "Primary"), |
1440 |
None, 0, lambda ctx, item: item["pnode"]), |
1441 |
(query._MakeField("num", "Num", constants.QFT_NUMBER, "Num"), |
1442 |
None, 0, lambda ctx, item: item["num"]), |
1443 |
], []) |
1444 |
|
1445 |
data = [ |
1446 |
{ "pnode": "node1", "num": 100, }, |
1447 |
{ "pnode": "node1", "num": 25, }, |
1448 |
{ "pnode": "node2", "num": 90, }, |
1449 |
{ "pnode": "node2", "num": 30, }, |
1450 |
] |
1451 |
|
1452 |
q = query.Query(fielddefs, ["pnode", "num"], namefield="pnode", |
1453 |
qfilter=["|", ["=", "pnode", "node1"], |
1454 |
["=", "pnode", "node2"], |
1455 |
["=", "pnode", "node1"]]) |
1456 |
self.assertEqual(q.RequestedNames(), ["node1", "node2"], |
1457 |
msg="Did not return unique names")
|
1458 |
self.assertFalse(q.RequestedData())
|
1459 |
self.assertEqual(q.Query(data),
|
1460 |
[[(constants.RS_NORMAL, "node1"), (constants.RS_NORMAL, 100)], |
1461 |
[(constants.RS_NORMAL, "node1"), (constants.RS_NORMAL, 25)], |
1462 |
[(constants.RS_NORMAL, "node2"), (constants.RS_NORMAL, 90)], |
1463 |
[(constants.RS_NORMAL, "node2"), (constants.RS_NORMAL, 30)]]) |
1464 |
self.assertEqual(q.Query(data, sort_by_name=False), |
1465 |
[[(constants.RS_NORMAL, "node1"), (constants.RS_NORMAL, 100)], |
1466 |
[(constants.RS_NORMAL, "node1"), (constants.RS_NORMAL, 25)], |
1467 |
[(constants.RS_NORMAL, "node2"), (constants.RS_NORMAL, 90)], |
1468 |
[(constants.RS_NORMAL, "node2"), (constants.RS_NORMAL, 30)]]) |
1469 |
|
1470 |
data = [ |
1471 |
{ "pnode": "nodeX", "num": 50, }, |
1472 |
{ "pnode": "nodeY", "num": 40, }, |
1473 |
{ "pnode": "nodeX", "num": 30, }, |
1474 |
{ "pnode": "nodeX", "num": 20, }, |
1475 |
{ "pnode": "nodeM", "num": 10, }, |
1476 |
] |
1477 |
|
1478 |
q = query.Query(fielddefs, ["pnode", "num"], namefield="pnode", |
1479 |
qfilter=["|", ["=", "pnode", "nodeX"], |
1480 |
["=", "pnode", "nodeY"], |
1481 |
["=", "pnode", "nodeY"], |
1482 |
["=", "pnode", "nodeY"], |
1483 |
["=", "pnode", "nodeM"]]) |
1484 |
self.assertEqual(q.RequestedNames(), ["nodeX", "nodeY", "nodeM"], |
1485 |
msg="Did not return unique names")
|
1486 |
self.assertFalse(q.RequestedData())
|
1487 |
|
1488 |
# First sorted by name, then input order
|
1489 |
self.assertEqual(q.Query(data, sort_by_name=True), |
1490 |
[[(constants.RS_NORMAL, "nodeM"), (constants.RS_NORMAL, 10)], |
1491 |
[(constants.RS_NORMAL, "nodeX"), (constants.RS_NORMAL, 50)], |
1492 |
[(constants.RS_NORMAL, "nodeX"), (constants.RS_NORMAL, 30)], |
1493 |
[(constants.RS_NORMAL, "nodeX"), (constants.RS_NORMAL, 20)], |
1494 |
[(constants.RS_NORMAL, "nodeY"), (constants.RS_NORMAL, 40)]]) |
1495 |
|
1496 |
# Input order
|
1497 |
self.assertEqual(q.Query(data, sort_by_name=False), |
1498 |
[[(constants.RS_NORMAL, "nodeX"), (constants.RS_NORMAL, 50)], |
1499 |
[(constants.RS_NORMAL, "nodeY"), (constants.RS_NORMAL, 40)], |
1500 |
[(constants.RS_NORMAL, "nodeX"), (constants.RS_NORMAL, 30)], |
1501 |
[(constants.RS_NORMAL, "nodeX"), (constants.RS_NORMAL, 20)], |
1502 |
[(constants.RS_NORMAL, "nodeM"), (constants.RS_NORMAL, 10)]]) |
1503 |
|
1504 |
def testFilter(self): |
1505 |
(DK_A, DK_B) = range(1000, 1002) |
1506 |
|
1507 |
fielddefs = query._PrepareFieldList([ |
1508 |
(query._MakeField("name", "Name", constants.QFT_TEXT, "Name"), |
1509 |
DK_A, 0, lambda ctx, item: item["name"]), |
1510 |
(query._MakeField("other", "Other", constants.QFT_TEXT, "Other"), |
1511 |
DK_B, 0, lambda ctx, item: item["other"]), |
1512 |
], []) |
1513 |
|
1514 |
data = [ |
1515 |
{ "name": "node1", "other": "foo", }, |
1516 |
{ "name": "node2", "other": "bar", }, |
1517 |
{ "name": "node3", "other": "Hello", }, |
1518 |
] |
1519 |
|
1520 |
# Empty filter
|
1521 |
q = query.Query(fielddefs, ["name", "other"], namefield="name", |
1522 |
qfilter=["|"])
|
1523 |
self.assertTrue(q.RequestedNames() is None) |
1524 |
self.assertEqual(q.RequestedData(), set([DK_A, DK_B])) |
1525 |
self.assertEqual(q.Query(data), [])
|
1526 |
|
1527 |
# Normal filter
|
1528 |
q = query.Query(fielddefs, ["name", "other"], namefield="name", |
1529 |
qfilter=["=", "name", "node1"]) |
1530 |
self.assertEqual(q.RequestedNames(), ["node1"]) |
1531 |
self.assertEqual(q.Query(data),
|
1532 |
[[(constants.RS_NORMAL, "node1"), (constants.RS_NORMAL, "foo")]]) |
1533 |
|
1534 |
q = query.Query(fielddefs, ["name", "other"], namefield="name", |
1535 |
qfilter=(["|", ["=", "name", "node1"], |
1536 |
["=", "name", "node3"]])) |
1537 |
self.assertEqual(q.RequestedNames(), ["node1", "node3"]) |
1538 |
self.assertEqual(q.Query(data),
|
1539 |
[[(constants.RS_NORMAL, "node1"), (constants.RS_NORMAL, "foo")], |
1540 |
[(constants.RS_NORMAL, "node3"), (constants.RS_NORMAL, "Hello")]]) |
1541 |
|
1542 |
# Complex filter
|
1543 |
q = query.Query(fielddefs, ["name", "other"], namefield="name", |
1544 |
qfilter=(["|", ["=", "name", "node1"], |
1545 |
["|", ["=", "name", "node3"], |
1546 |
["=", "name", "node2"]], |
1547 |
["=", "name", "node3"]])) |
1548 |
self.assertEqual(q.RequestedNames(), ["node1", "node3", "node2"]) |
1549 |
self.assertEqual(q.RequestedData(), set([DK_A, DK_B])) |
1550 |
self.assertEqual(q.Query(data),
|
1551 |
[[(constants.RS_NORMAL, "node1"), (constants.RS_NORMAL, "foo")], |
1552 |
[(constants.RS_NORMAL, "node2"), (constants.RS_NORMAL, "bar")], |
1553 |
[(constants.RS_NORMAL, "node3"), (constants.RS_NORMAL, "Hello")]]) |
1554 |
|
1555 |
# Filter data type mismatch
|
1556 |
for i in [-1, 0, 1, 123, [], None, True, False]: |
1557 |
self.assertRaises(errors.ParameterError, query.Query,
|
1558 |
fielddefs, ["name", "other"], namefield="name", |
1559 |
qfilter=["=", "name", i]) |
1560 |
|
1561 |
# Negative filter
|
1562 |
q = query.Query(fielddefs, ["name", "other"], namefield="name", |
1563 |
qfilter=["!", ["|", ["=", "name", "node1"], |
1564 |
["=", "name", "node3"]]]) |
1565 |
self.assertTrue(q.RequestedNames() is None) |
1566 |
self.assertEqual(q.Query(data),
|
1567 |
[[(constants.RS_NORMAL, "node2"), (constants.RS_NORMAL, "bar")]]) |
1568 |
|
1569 |
# Not equal
|
1570 |
q = query.Query(fielddefs, ["name", "other"], namefield="name", |
1571 |
qfilter=["!=", "name", "node3"]) |
1572 |
self.assertTrue(q.RequestedNames() is None) |
1573 |
self.assertEqual(q.Query(data),
|
1574 |
[[(constants.RS_NORMAL, "node1"), (constants.RS_NORMAL, "foo")], |
1575 |
[(constants.RS_NORMAL, "node2"), (constants.RS_NORMAL, "bar")]]) |
1576 |
|
1577 |
# Data type
|
1578 |
q = query.Query(fielddefs, [], namefield="name",
|
1579 |
qfilter=["|", ["=", "other", "bar"], |
1580 |
["=", "name", "foo"]]) |
1581 |
self.assertTrue(q.RequestedNames() is None) |
1582 |
self.assertEqual(q.RequestedData(), set([DK_A, DK_B])) |
1583 |
self.assertEqual(q.Query(data), [[]])
|
1584 |
|
1585 |
# Only one data type
|
1586 |
q = query.Query(fielddefs, ["other"], namefield="name", |
1587 |
qfilter=["=", "other", "bar"]) |
1588 |
self.assertTrue(q.RequestedNames() is None) |
1589 |
self.assertEqual(q.RequestedData(), set([DK_B])) |
1590 |
self.assertEqual(q.Query(data), [[(constants.RS_NORMAL, "bar")]]) |
1591 |
|
1592 |
q = query.Query(fielddefs, [], namefield="name",
|
1593 |
qfilter=["=", "other", "bar"]) |
1594 |
self.assertTrue(q.RequestedNames() is None) |
1595 |
self.assertEqual(q.RequestedData(), set([DK_B])) |
1596 |
self.assertEqual(q.Query(data), [[]])
|
1597 |
|
1598 |
# Data type in boolean operator
|
1599 |
q = query.Query(fielddefs, [], namefield="name",
|
1600 |
qfilter=["?", "name"]) |
1601 |
self.assertTrue(q.RequestedNames() is None) |
1602 |
self.assertEqual(q.RequestedData(), set([DK_A])) |
1603 |
self.assertEqual(q.Query(data), [[], [], []])
|
1604 |
|
1605 |
q = query.Query(fielddefs, [], namefield="name",
|
1606 |
qfilter=["!", ["?", "name"]]) |
1607 |
self.assertTrue(q.RequestedNames() is None) |
1608 |
self.assertEqual(q.RequestedData(), set([DK_A])) |
1609 |
self.assertEqual(q.Query(data), [])
|
1610 |
|
1611 |
def testFilterContains(self): |
1612 |
fielddefs = query._PrepareFieldList([ |
1613 |
(query._MakeField("name", "Name", constants.QFT_TEXT, "Name"), |
1614 |
None, 0, lambda ctx, item: item["name"]), |
1615 |
(query._MakeField("other", "Other", constants.QFT_OTHER, "Other"), |
1616 |
None, 0, lambda ctx, item: item["other"]), |
1617 |
], []) |
1618 |
|
1619 |
data = [ |
1620 |
{ "name": "node2", "other": ["x", "y", "bar"], }, |
1621 |
{ "name": "node3", "other": "Hello", }, |
1622 |
{ "name": "node1", "other": ["a", "b", "foo"], }, |
1623 |
{ "name": "empty", "other": []}, |
1624 |
] |
1625 |
|
1626 |
q = query.Query(fielddefs, ["name", "other"], namefield="name", |
1627 |
qfilter=["=[]", "other", "bar"]) |
1628 |
self.assertTrue(q.RequestedNames() is None) |
1629 |
self.assertEqual(q.Query(data), [
|
1630 |
[(constants.RS_NORMAL, "node2"),
|
1631 |
(constants.RS_NORMAL, ["x", "y", "bar"])], |
1632 |
]) |
1633 |
|
1634 |
q = query.Query(fielddefs, ["name", "other"], namefield="name", |
1635 |
qfilter=["|", ["=[]", "other", "bar"], |
1636 |
["=[]", "other", "a"], |
1637 |
["=[]", "other", "b"]]) |
1638 |
self.assertTrue(q.RequestedNames() is None) |
1639 |
self.assertEqual(q.Query(data), [
|
1640 |
[(constants.RS_NORMAL, "node1"),
|
1641 |
(constants.RS_NORMAL, ["a", "b", "foo"])], |
1642 |
[(constants.RS_NORMAL, "node2"),
|
1643 |
(constants.RS_NORMAL, ["x", "y", "bar"])], |
1644 |
]) |
1645 |
self.assertEqual(q.OldStyleQuery(data), [
|
1646 |
["node1", ["a", "b", "foo"]], |
1647 |
["node2", ["x", "y", "bar"]], |
1648 |
]) |
1649 |
|
1650 |
# Boolean test
|
1651 |
q = query.Query(fielddefs, ["name", "other"], namefield="name", |
1652 |
qfilter=["?", "other"]) |
1653 |
self.assertEqual(q.OldStyleQuery(data), [
|
1654 |
["node1", ["a", "b", "foo"]], |
1655 |
["node2", ["x", "y", "bar"]], |
1656 |
["node3", "Hello"], |
1657 |
]) |
1658 |
|
1659 |
q = query.Query(fielddefs, ["name", "other"], namefield="name", |
1660 |
qfilter=["!", ["?", "other"]]) |
1661 |
self.assertEqual(q.OldStyleQuery(data), [
|
1662 |
["empty", []],
|
1663 |
]) |
1664 |
|
1665 |
def testFilterHostname(self): |
1666 |
fielddefs = query._PrepareFieldList([ |
1667 |
(query._MakeField("name", "Name", constants.QFT_TEXT, "Name"), |
1668 |
None, query.QFF_HOSTNAME, lambda ctx, item: item["name"]), |
1669 |
], []) |
1670 |
|
1671 |
data = [ |
1672 |
{ "name": "node1.example.com", }, |
1673 |
{ "name": "node2.example.com", }, |
1674 |
{ "name": "node2.example.net", }, |
1675 |
] |
1676 |
|
1677 |
q = query.Query(fielddefs, ["name"], namefield="name", |
1678 |
qfilter=["=", "name", "node2"]) |
1679 |
self.assertEqual(q.RequestedNames(), ["node2"]) |
1680 |
self.assertEqual(q.Query(data), [
|
1681 |
[(constants.RS_NORMAL, "node2.example.com")],
|
1682 |
[(constants.RS_NORMAL, "node2.example.net")],
|
1683 |
]) |
1684 |
|
1685 |
q = query.Query(fielddefs, ["name"], namefield="name", |
1686 |
qfilter=["=", "name", "node1"]) |
1687 |
self.assertEqual(q.RequestedNames(), ["node1"]) |
1688 |
self.assertEqual(q.Query(data), [
|
1689 |
[(constants.RS_NORMAL, "node1.example.com")],
|
1690 |
]) |
1691 |
|
1692 |
q = query.Query(fielddefs, ["name"], namefield="name", |
1693 |
qfilter=["=", "name", "othername"]) |
1694 |
self.assertEqual(q.RequestedNames(), ["othername"]) |
1695 |
self.assertEqual(q.Query(data), [])
|
1696 |
|
1697 |
q = query.Query(fielddefs, ["name"], namefield="name", |
1698 |
qfilter=["|", ["=", "name", "node1.example.com"], |
1699 |
["=", "name", "node2"]]) |
1700 |
self.assertEqual(q.RequestedNames(), ["node1.example.com", "node2"]) |
1701 |
self.assertEqual(q.Query(data), [
|
1702 |
[(constants.RS_NORMAL, "node1.example.com")],
|
1703 |
[(constants.RS_NORMAL, "node2.example.com")],
|
1704 |
[(constants.RS_NORMAL, "node2.example.net")],
|
1705 |
]) |
1706 |
self.assertEqual(q.OldStyleQuery(data), [
|
1707 |
["node1.example.com"],
|
1708 |
["node2.example.com"],
|
1709 |
["node2.example.net"],
|
1710 |
]) |
1711 |
|
1712 |
q = query.Query(fielddefs, ["name"], namefield="name", |
1713 |
qfilter=["!=", "name", "node1"]) |
1714 |
self.assertTrue(q.RequestedNames() is None) |
1715 |
self.assertEqual(q.Query(data), [
|
1716 |
[(constants.RS_NORMAL, "node2.example.com")],
|
1717 |
[(constants.RS_NORMAL, "node2.example.net")],
|
1718 |
]) |
1719 |
self.assertEqual(q.OldStyleQuery(data), [
|
1720 |
["node2.example.com"],
|
1721 |
["node2.example.net"],
|
1722 |
]) |
1723 |
|
1724 |
def testFilterBoolean(self): |
1725 |
fielddefs = query._PrepareFieldList([ |
1726 |
(query._MakeField("name", "Name", constants.QFT_TEXT, "Name"), |
1727 |
None, query.QFF_HOSTNAME, lambda ctx, item: item["name"]), |
1728 |
(query._MakeField("value", "Value", constants.QFT_BOOL, "Value"), |
1729 |
None, 0, lambda ctx, item: item["value"]), |
1730 |
], []) |
1731 |
|
1732 |
data = [ |
1733 |
{ "name": "node1", "value": False, }, |
1734 |
{ "name": "node2", "value": True, }, |
1735 |
{ "name": "node3", "value": True, }, |
1736 |
] |
1737 |
|
1738 |
q = query.Query(fielddefs, ["name", "value"], |
1739 |
qfilter=["|", ["=", "value", False], |
1740 |
["=", "value", True]]) |
1741 |
self.assertTrue(q.RequestedNames() is None) |
1742 |
self.assertEqual(q.Query(data), [
|
1743 |
[(constants.RS_NORMAL, "node1"), (constants.RS_NORMAL, False)], |
1744 |
[(constants.RS_NORMAL, "node2"), (constants.RS_NORMAL, True)], |
1745 |
[(constants.RS_NORMAL, "node3"), (constants.RS_NORMAL, True)], |
1746 |
]) |
1747 |
|
1748 |
q = query.Query(fielddefs, ["name", "value"], |
1749 |
qfilter=["|", ["=", "value", False], |
1750 |
["!", ["=", "value", False]]]) |
1751 |
self.assertTrue(q.RequestedNames() is None) |
1752 |
self.assertEqual(q.Query(data), [
|
1753 |
[(constants.RS_NORMAL, "node1"), (constants.RS_NORMAL, False)], |
1754 |
[(constants.RS_NORMAL, "node2"), (constants.RS_NORMAL, True)], |
1755 |
[(constants.RS_NORMAL, "node3"), (constants.RS_NORMAL, True)], |
1756 |
]) |
1757 |
|
1758 |
# Comparing bool with string
|
1759 |
for i in ["False", "True", "0", "1", "no", "yes", "N", "Y"]: |
1760 |
self.assertRaises(errors.ParameterError, query.Query,
|
1761 |
fielddefs, ["name", "value"], |
1762 |
qfilter=["=", "value", i]) |
1763 |
|
1764 |
# Truth filter
|
1765 |
q = query.Query(fielddefs, ["name", "value"], qfilter=["?", "value"]) |
1766 |
self.assertTrue(q.RequestedNames() is None) |
1767 |
self.assertEqual(q.Query(data), [
|
1768 |
[(constants.RS_NORMAL, "node2"), (constants.RS_NORMAL, True)], |
1769 |
[(constants.RS_NORMAL, "node3"), (constants.RS_NORMAL, True)], |
1770 |
]) |
1771 |
|
1772 |
# Negative bool filter
|
1773 |
q = query.Query(fielddefs, ["name", "value"], qfilter=["!", ["?", "value"]]) |
1774 |
self.assertTrue(q.RequestedNames() is None) |
1775 |
self.assertEqual(q.Query(data), [
|
1776 |
[(constants.RS_NORMAL, "node1"), (constants.RS_NORMAL, False)], |
1777 |
]) |
1778 |
|
1779 |
# Complex truth filter
|
1780 |
q = query.Query(fielddefs, ["name", "value"], |
1781 |
qfilter=["|", ["&", ["=", "name", "node1"], |
1782 |
["!", ["?", "value"]]], |
1783 |
["?", "value"]]) |
1784 |
self.assertTrue(q.RequestedNames() is None) |
1785 |
self.assertEqual(q.Query(data), [
|
1786 |
[(constants.RS_NORMAL, "node1"), (constants.RS_NORMAL, False)], |
1787 |
[(constants.RS_NORMAL, "node2"), (constants.RS_NORMAL, True)], |
1788 |
[(constants.RS_NORMAL, "node3"), (constants.RS_NORMAL, True)], |
1789 |
]) |
1790 |
|
1791 |
def testFilterRegex(self): |
1792 |
fielddefs = query._PrepareFieldList([ |
1793 |
(query._MakeField("name", "Name", constants.QFT_TEXT, "Name"), |
1794 |
None, 0, lambda ctx, item: item["name"]), |
1795 |
], []) |
1796 |
|
1797 |
data = [ |
1798 |
{ "name": "node1.example.com", }, |
1799 |
{ "name": "node2.site.example.com", }, |
1800 |
{ "name": "node2.example.net", }, |
1801 |
|
1802 |
# Empty name
|
1803 |
{ "name": "", }, |
1804 |
] |
1805 |
|
1806 |
q = query.Query(fielddefs, ["name"], namefield="name", |
1807 |
qfilter=["=~", "name", "site"]) |
1808 |
self.assertTrue(q.RequestedNames() is None) |
1809 |
self.assertEqual(q.Query(data), [
|
1810 |
[(constants.RS_NORMAL, "node2.site.example.com")],
|
1811 |
]) |
1812 |
|
1813 |
q = query.Query(fielddefs, ["name"], namefield="name", |
1814 |
qfilter=["=~", "name", "^node2"]) |
1815 |
self.assertTrue(q.RequestedNames() is None) |
1816 |
self.assertEqual(q.Query(data), [
|
1817 |
[(constants.RS_NORMAL, "node2.example.net")],
|
1818 |
[(constants.RS_NORMAL, "node2.site.example.com")],
|
1819 |
]) |
1820 |
|
1821 |
q = query.Query(fielddefs, ["name"], namefield="name", |
1822 |
qfilter=["=~", "name", r"(?i)\.COM$"]) |
1823 |
self.assertTrue(q.RequestedNames() is None) |
1824 |
self.assertEqual(q.Query(data), [
|
1825 |
[(constants.RS_NORMAL, "node1.example.com")],
|
1826 |
[(constants.RS_NORMAL, "node2.site.example.com")],
|
1827 |
]) |
1828 |
|
1829 |
q = query.Query(fielddefs, ["name"], namefield="name", |
1830 |
qfilter=["=~", "name", r"."]) |
1831 |
self.assertTrue(q.RequestedNames() is None) |
1832 |
self.assertEqual(q.Query(data), [
|
1833 |
[(constants.RS_NORMAL, "node1.example.com")],
|
1834 |
[(constants.RS_NORMAL, "node2.example.net")],
|
1835 |
[(constants.RS_NORMAL, "node2.site.example.com")],
|
1836 |
]) |
1837 |
|
1838 |
q = query.Query(fielddefs, ["name"], namefield="name", |
1839 |
qfilter=["=~", "name", r"^$"]) |
1840 |
self.assertTrue(q.RequestedNames() is None) |
1841 |
self.assertEqual(q.Query(data), [
|
1842 |
[(constants.RS_NORMAL, "")],
|
1843 |
]) |
1844 |
|
1845 |
# Invalid regular expression
|
1846 |
self.assertRaises(errors.ParameterError, query.Query, fielddefs, ["name"], |
1847 |
qfilter=["=~", "name", r"["]) |
1848 |
|
1849 |
def testFilterLessGreater(self): |
1850 |
fielddefs = query._PrepareFieldList([ |
1851 |
(query._MakeField("value", "Value", constants.QFT_NUMBER, "Value"), |
1852 |
None, 0, lambda ctx, item: item), |
1853 |
], []) |
1854 |
|
1855 |
data = range(100) |
1856 |
|
1857 |
q = query.Query(fielddefs, ["value"],
|
1858 |
qfilter=["<", "value", 20]) |
1859 |
self.assertTrue(q.RequestedNames() is None) |
1860 |
self.assertEqual(q.Query(data),
|
1861 |
[[(constants.RS_NORMAL, i)] for i in range(20)]) |
1862 |
|
1863 |
q = query.Query(fielddefs, ["value"],
|
1864 |
qfilter=["<=", "value", 30]) |
1865 |
self.assertTrue(q.RequestedNames() is None) |
1866 |
self.assertEqual(q.Query(data),
|
1867 |
[[(constants.RS_NORMAL, i)] for i in range(31)]) |
1868 |
|
1869 |
q = query.Query(fielddefs, ["value"],
|
1870 |
qfilter=[">", "value", 40]) |
1871 |
self.assertTrue(q.RequestedNames() is None) |
1872 |
self.assertEqual(q.Query(data),
|
1873 |
[[(constants.RS_NORMAL, i)] for i in range(41, 100)]) |
1874 |
|
1875 |
q = query.Query(fielddefs, ["value"],
|
1876 |
qfilter=[">=", "value", 50]) |
1877 |
self.assertTrue(q.RequestedNames() is None) |
1878 |
self.assertEqual(q.Query(data),
|
1879 |
[[(constants.RS_NORMAL, i)] for i in range(50, 100)]) |
1880 |
|
1881 |
def testFilterLessGreaterJobId(self): |
1882 |
fielddefs = query._PrepareFieldList([ |
1883 |
(query._MakeField("id", "ID", constants.QFT_TEXT, "Job ID"), |
1884 |
None, query.QFF_JOB_ID, lambda ctx, item: item), |
1885 |
], []) |
1886 |
|
1887 |
data = ["1", "2", "3", "10", "102", "120", "125", "15", "100", "7"] |
1888 |
|
1889 |
assert data != utils.NiceSort(data), "Test data should not be sorted" |
1890 |
|
1891 |
q = query.Query(fielddefs, ["id"], qfilter=["<", "id", "20"]) |
1892 |
self.assertTrue(q.RequestedNames() is None) |
1893 |
self.assertEqual(q.Query(data), [
|
1894 |
[(constants.RS_NORMAL, "1")],
|
1895 |
[(constants.RS_NORMAL, "2")],
|
1896 |
[(constants.RS_NORMAL, "3")],
|
1897 |
[(constants.RS_NORMAL, "10")],
|
1898 |
[(constants.RS_NORMAL, "15")],
|
1899 |
[(constants.RS_NORMAL, "7")],
|
1900 |
]) |
1901 |
|
1902 |
q = query.Query(fielddefs, ["id"], qfilter=[">=", "id", "100"]) |
1903 |
self.assertTrue(q.RequestedNames() is None) |
1904 |
self.assertEqual(q.Query(data), [
|
1905 |
[(constants.RS_NORMAL, "102")],
|
1906 |
[(constants.RS_NORMAL, "120")],
|
1907 |
[(constants.RS_NORMAL, "125")],
|
1908 |
[(constants.RS_NORMAL, "100")],
|
1909 |
]) |
1910 |
|
1911 |
# Integers are no valid job IDs
|
1912 |
self.assertRaises(errors.ParameterError, query.Query,
|
1913 |
fielddefs, ["id"], qfilter=[">=", "id", 10]) |
1914 |
|
1915 |
def testFilterLessGreaterSplitTimestamp(self): |
1916 |
fielddefs = query._PrepareFieldList([ |
1917 |
(query._MakeField("ts", "Timestamp", constants.QFT_OTHER, "Timestamp"), |
1918 |
None, query.QFF_SPLIT_TIMESTAMP, lambda ctx, item: item), |
1919 |
], []) |
1920 |
|
1921 |
data = [ |
1922 |
utils.SplitTime(0),
|
1923 |
utils.SplitTime(0.1),
|
1924 |
utils.SplitTime(18224.7872),
|
1925 |
utils.SplitTime(919896.12623),
|
1926 |
utils.SplitTime(999),
|
1927 |
utils.SplitTime(989.9999),
|
1928 |
] |
1929 |
|
1930 |
for i in [0, [0, 0]]: |
1931 |
q = query.Query(fielddefs, ["ts"], qfilter=["<", "ts", i]) |
1932 |
self.assertTrue(q.RequestedNames() is None) |
1933 |
self.assertEqual(q.Query(data), [])
|
1934 |
|
1935 |
q = query.Query(fielddefs, ["ts"], qfilter=["<", "ts", 1000]) |
1936 |
self.assertTrue(q.RequestedNames() is None) |
1937 |
self.assertEqual(q.Query(data), [
|
1938 |
[(constants.RS_NORMAL, (0, 0))], |
1939 |
[(constants.RS_NORMAL, (0, 100000))], |
1940 |
[(constants.RS_NORMAL, (999, 0))], |
1941 |
[(constants.RS_NORMAL, (989, 999900))], |
1942 |
]) |
1943 |
|
1944 |
q = query.Query(fielddefs, ["ts"], qfilter=[">=", "ts", 5000.3]) |
1945 |
self.assertTrue(q.RequestedNames() is None) |
1946 |
self.assertEqual(q.Query(data), [
|
1947 |
[(constants.RS_NORMAL, (18224, 787200))], |
1948 |
[(constants.RS_NORMAL, (919896, 126230))], |
1949 |
]) |
1950 |
|
1951 |
for i in [18224.7772, utils.SplitTime(18224.7772)]: |
1952 |
q = query.Query(fielddefs, ["ts"], qfilter=[">=", "ts", i]) |
1953 |
self.assertTrue(q.RequestedNames() is None) |
1954 |
self.assertEqual(q.Query(data), [
|
1955 |
[(constants.RS_NORMAL, (18224, 787200))], |
1956 |
[(constants.RS_NORMAL, (919896, 126230))], |
1957 |
]) |
1958 |
|
1959 |
q = query.Query(fielddefs, ["ts"], qfilter=[">", "ts", 18224.7880]) |
1960 |
self.assertTrue(q.RequestedNames() is None) |
1961 |
self.assertEqual(q.Query(data), [
|
1962 |
[(constants.RS_NORMAL, (919896, 126230))], |
1963 |
]) |
1964 |
|
1965 |
|
1966 |
if __name__ == "__main__": |
1967 |
testutils.GanetiTestProgram() |