Statistics
| Branch: | Tag: | Revision:

root / test / ganeti.query_unittest.py @ 8572f1fe

History | View | Annotate | Download (33.3 kB)

1 4ca96421 Michael Hanselmann
#!/usr/bin/python
2 4ca96421 Michael Hanselmann
#
3 4ca96421 Michael Hanselmann
4 4ca96421 Michael Hanselmann
# Copyright (C) 2010 Google Inc.
5 4ca96421 Michael Hanselmann
#
6 4ca96421 Michael Hanselmann
# This program is free software; you can redistribute it and/or modify
7 4ca96421 Michael Hanselmann
# it under the terms of the GNU General Public License as published by
8 4ca96421 Michael Hanselmann
# the Free Software Foundation; either version 2 of the License, or
9 4ca96421 Michael Hanselmann
# (at your option) any later version.
10 4ca96421 Michael Hanselmann
#
11 4ca96421 Michael Hanselmann
# This program is distributed in the hope that it will be useful, but
12 4ca96421 Michael Hanselmann
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 4ca96421 Michael Hanselmann
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 4ca96421 Michael Hanselmann
# General Public License for more details.
15 4ca96421 Michael Hanselmann
#
16 4ca96421 Michael Hanselmann
# You should have received a copy of the GNU General Public License
17 4ca96421 Michael Hanselmann
# along with this program; if not, write to the Free Software
18 4ca96421 Michael Hanselmann
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 4ca96421 Michael Hanselmann
# 02110-1301, USA.
20 4ca96421 Michael Hanselmann
21 4ca96421 Michael Hanselmann
22 4ca96421 Michael Hanselmann
"""Script for testing ganeti.query"""
23 4ca96421 Michael Hanselmann
24 4ca96421 Michael Hanselmann
import re
25 4ca96421 Michael Hanselmann
import unittest
26 aa29e95f Michael Hanselmann
import random
27 4ca96421 Michael Hanselmann
28 4ca96421 Michael Hanselmann
from ganeti import constants
29 4ca96421 Michael Hanselmann
from ganeti import utils
30 4ca96421 Michael Hanselmann
from ganeti import compat
31 4ca96421 Michael Hanselmann
from ganeti import errors
32 4ca96421 Michael Hanselmann
from ganeti import query
33 4ca96421 Michael Hanselmann
from ganeti import objects
34 1c8addc6 Michael Hanselmann
from ganeti import cmdlib
35 4ca96421 Michael Hanselmann
36 4ca96421 Michael Hanselmann
import testutils
37 4ca96421 Michael Hanselmann
38 4ca96421 Michael Hanselmann
39 4ca96421 Michael Hanselmann
class TestConstants(unittest.TestCase):
40 4ca96421 Michael Hanselmann
  def test(self):
41 4ca96421 Michael Hanselmann
    self.assertEqual(set(query._VERIFY_FN.keys()),
42 4ca96421 Michael Hanselmann
                     constants.QFT_ALL)
43 4ca96421 Michael Hanselmann
44 4ca96421 Michael Hanselmann
45 4ca96421 Michael Hanselmann
class _QueryData:
46 4ca96421 Michael Hanselmann
  def __init__(self, data, **kwargs):
47 4ca96421 Michael Hanselmann
    self.data = data
48 4ca96421 Michael Hanselmann
49 4ca96421 Michael Hanselmann
    for name, value in kwargs.items():
50 4ca96421 Michael Hanselmann
      setattr(self, name, value)
51 4ca96421 Michael Hanselmann
52 4ca96421 Michael Hanselmann
  def __iter__(self):
53 4ca96421 Michael Hanselmann
    return iter(self.data)
54 4ca96421 Michael Hanselmann
55 4ca96421 Michael Hanselmann
56 4ca96421 Michael Hanselmann
def _GetDiskSize(nr, ctx, item):
57 4ca96421 Michael Hanselmann
  disks = item["disks"]
58 4ca96421 Michael Hanselmann
  try:
59 4ca96421 Michael Hanselmann
    return (constants.QRFS_NORMAL, disks[nr])
60 4ca96421 Michael Hanselmann
  except IndexError:
61 4ca96421 Michael Hanselmann
    return (constants.QRFS_UNAVAIL, None)
62 4ca96421 Michael Hanselmann
63 4ca96421 Michael Hanselmann
64 4ca96421 Michael Hanselmann
class TestQuery(unittest.TestCase):
65 4ca96421 Michael Hanselmann
  def test(self):
66 4ca96421 Michael Hanselmann
    (STATIC, DISK) = range(10, 12)
67 4ca96421 Michael Hanselmann
68 4ca96421 Michael Hanselmann
    fielddef = query._PrepareFieldList([
69 4ca96421 Michael Hanselmann
      (query._MakeField("name", "Name", constants.QFT_TEXT),
70 4ca96421 Michael Hanselmann
       STATIC, lambda ctx, item: (constants.QRFS_NORMAL, item["name"])),
71 4ca96421 Michael Hanselmann
      (query._MakeField("master", "Master", constants.QFT_BOOL),
72 4ca96421 Michael Hanselmann
       STATIC, lambda ctx, item: (constants.QRFS_NORMAL,
73 4ca96421 Michael Hanselmann
                                  ctx.mastername == item["name"])),
74 4ca96421 Michael Hanselmann
      ] +
75 4ca96421 Michael Hanselmann
      [(query._MakeField("disk%s.size" % i, "DiskSize%s" % i,
76 4ca96421 Michael Hanselmann
                         constants.QFT_UNIT),
77 4ca96421 Michael Hanselmann
        DISK, compat.partial(_GetDiskSize, i))
78 4ca96421 Michael Hanselmann
       for i in range(4)])
79 4ca96421 Michael Hanselmann
80 4ca96421 Michael Hanselmann
    q = query.Query(fielddef, ["name"])
81 4ca96421 Michael Hanselmann
    self.assertEqual(q.RequestedData(), set([STATIC]))
82 4ca96421 Michael Hanselmann
    self.assertEqual(len(q._fields), 1)
83 4ca96421 Michael Hanselmann
    self.assertEqual(len(q.GetFields()), 1)
84 4ca96421 Michael Hanselmann
    self.assertEqual(q.GetFields()[0].ToDict(),
85 4ca96421 Michael Hanselmann
      objects.QueryFieldDefinition(name="name",
86 4ca96421 Michael Hanselmann
                                   title="Name",
87 4ca96421 Michael Hanselmann
                                   kind=constants.QFT_TEXT).ToDict())
88 4ca96421 Michael Hanselmann
89 4ca96421 Michael Hanselmann
    # Create data only once query has been prepared
90 4ca96421 Michael Hanselmann
    data = [
91 4ca96421 Michael Hanselmann
      { "name": "node1", "disks": [0, 1, 2], },
92 4ca96421 Michael Hanselmann
      { "name": "node2", "disks": [3, 4], },
93 4ca96421 Michael Hanselmann
      { "name": "node3", "disks": [5, 6, 7], },
94 4ca96421 Michael Hanselmann
      ]
95 4ca96421 Michael Hanselmann
96 4ca96421 Michael Hanselmann
    self.assertEqual(q.Query(_QueryData(data, mastername="node3")),
97 4ca96421 Michael Hanselmann
                     [[(constants.QRFS_NORMAL, "node1")],
98 4ca96421 Michael Hanselmann
                      [(constants.QRFS_NORMAL, "node2")],
99 4ca96421 Michael Hanselmann
                      [(constants.QRFS_NORMAL, "node3")]])
100 4ca96421 Michael Hanselmann
    self.assertEqual(q.OldStyleQuery(_QueryData(data, mastername="node3")),
101 4ca96421 Michael Hanselmann
                     [["node1"], ["node2"], ["node3"]])
102 4ca96421 Michael Hanselmann
103 4ca96421 Michael Hanselmann
    q = query.Query(fielddef, ["name", "master"])
104 4ca96421 Michael Hanselmann
    self.assertEqual(q.RequestedData(), set([STATIC]))
105 4ca96421 Michael Hanselmann
    self.assertEqual(len(q._fields), 2)
106 4ca96421 Michael Hanselmann
    self.assertEqual(q.Query(_QueryData(data, mastername="node3")),
107 4ca96421 Michael Hanselmann
                     [[(constants.QRFS_NORMAL, "node1"),
108 4ca96421 Michael Hanselmann
                       (constants.QRFS_NORMAL, False)],
109 4ca96421 Michael Hanselmann
                      [(constants.QRFS_NORMAL, "node2"),
110 4ca96421 Michael Hanselmann
                       (constants.QRFS_NORMAL, False)],
111 4ca96421 Michael Hanselmann
                      [(constants.QRFS_NORMAL, "node3"),
112 4ca96421 Michael Hanselmann
                       (constants.QRFS_NORMAL, True)],
113 4ca96421 Michael Hanselmann
                     ])
114 4ca96421 Michael Hanselmann
115 4ca96421 Michael Hanselmann
    q = query.Query(fielddef, ["name", "master", "disk0.size"])
116 4ca96421 Michael Hanselmann
    self.assertEqual(q.RequestedData(), set([STATIC, DISK]))
117 4ca96421 Michael Hanselmann
    self.assertEqual(len(q._fields), 3)
118 4ca96421 Michael Hanselmann
    self.assertEqual(q.Query(_QueryData(data, mastername="node2")),
119 4ca96421 Michael Hanselmann
                     [[(constants.QRFS_NORMAL, "node1"),
120 4ca96421 Michael Hanselmann
                       (constants.QRFS_NORMAL, False),
121 4ca96421 Michael Hanselmann
                       (constants.QRFS_NORMAL, 0)],
122 4ca96421 Michael Hanselmann
                      [(constants.QRFS_NORMAL, "node2"),
123 4ca96421 Michael Hanselmann
                       (constants.QRFS_NORMAL, True),
124 4ca96421 Michael Hanselmann
                       (constants.QRFS_NORMAL, 3)],
125 4ca96421 Michael Hanselmann
                      [(constants.QRFS_NORMAL, "node3"),
126 4ca96421 Michael Hanselmann
                       (constants.QRFS_NORMAL, False),
127 4ca96421 Michael Hanselmann
                       (constants.QRFS_NORMAL, 5)],
128 4ca96421 Michael Hanselmann
                     ])
129 4ca96421 Michael Hanselmann
130 4ca96421 Michael Hanselmann
    # With unknown column
131 4ca96421 Michael Hanselmann
    q = query.Query(fielddef, ["disk2.size", "disk1.size", "disk99.size",
132 4ca96421 Michael Hanselmann
                               "disk0.size"])
133 4ca96421 Michael Hanselmann
    self.assertEqual(q.RequestedData(), set([DISK]))
134 4ca96421 Michael Hanselmann
    self.assertEqual(len(q._fields), 4)
135 4ca96421 Michael Hanselmann
    self.assertEqual(q.Query(_QueryData(data, mastername="node2")),
136 4ca96421 Michael Hanselmann
                     [[(constants.QRFS_NORMAL, 2),
137 4ca96421 Michael Hanselmann
                       (constants.QRFS_NORMAL, 1),
138 4ca96421 Michael Hanselmann
                       (constants.QRFS_UNKNOWN, None),
139 4ca96421 Michael Hanselmann
                       (constants.QRFS_NORMAL, 0)],
140 4ca96421 Michael Hanselmann
                      [(constants.QRFS_UNAVAIL, None),
141 4ca96421 Michael Hanselmann
                       (constants.QRFS_NORMAL, 4),
142 4ca96421 Michael Hanselmann
                       (constants.QRFS_UNKNOWN, None),
143 4ca96421 Michael Hanselmann
                       (constants.QRFS_NORMAL, 3)],
144 4ca96421 Michael Hanselmann
                      [(constants.QRFS_NORMAL, 7),
145 4ca96421 Michael Hanselmann
                       (constants.QRFS_NORMAL, 6),
146 4ca96421 Michael Hanselmann
                       (constants.QRFS_UNKNOWN, None),
147 4ca96421 Michael Hanselmann
                       (constants.QRFS_NORMAL, 5)],
148 4ca96421 Michael Hanselmann
                     ])
149 4ca96421 Michael Hanselmann
    self.assertRaises(errors.OpPrereqError, q.OldStyleQuery,
150 4ca96421 Michael Hanselmann
                      _QueryData(data, mastername="node2"))
151 4ca96421 Michael Hanselmann
    self.assertEqual([fdef.ToDict() for fdef in q.GetFields()], [
152 4ca96421 Michael Hanselmann
                     { "name": "disk2.size", "title": "DiskSize2",
153 4ca96421 Michael Hanselmann
                       "kind": constants.QFT_UNIT, },
154 4ca96421 Michael Hanselmann
                     { "name": "disk1.size", "title": "DiskSize1",
155 4ca96421 Michael Hanselmann
                       "kind": constants.QFT_UNIT, },
156 4ca96421 Michael Hanselmann
                     { "name": "disk99.size", "title": "disk99.size",
157 4ca96421 Michael Hanselmann
                       "kind": constants.QFT_UNKNOWN, },
158 4ca96421 Michael Hanselmann
                     { "name": "disk0.size", "title": "DiskSize0",
159 4ca96421 Michael Hanselmann
                       "kind": constants.QFT_UNIT, },
160 4ca96421 Michael Hanselmann
                     ])
161 4ca96421 Michael Hanselmann
162 4ca96421 Michael Hanselmann
    # Empty query
163 4ca96421 Michael Hanselmann
    q = query.Query(fielddef, [])
164 4ca96421 Michael Hanselmann
    self.assertEqual(q.RequestedData(), set([]))
165 4ca96421 Michael Hanselmann
    self.assertEqual(len(q._fields), 0)
166 4ca96421 Michael Hanselmann
    self.assertEqual(q.Query(_QueryData(data, mastername="node2")),
167 4ca96421 Michael Hanselmann
                     [[], [], []])
168 4ca96421 Michael Hanselmann
    self.assertEqual(q.OldStyleQuery(_QueryData(data, mastername="node2")),
169 4ca96421 Michael Hanselmann
                     [[], [], []])
170 4ca96421 Michael Hanselmann
    self.assertEqual(q.GetFields(), [])
171 4ca96421 Michael Hanselmann
172 4ca96421 Michael Hanselmann
  def testPrepareFieldList(self):
173 4ca96421 Michael Hanselmann
    # Duplicate titles
174 4ca96421 Michael Hanselmann
    for (a, b) in [("name", "name"), ("NAME", "name")]:
175 4ca96421 Michael Hanselmann
      self.assertRaises(AssertionError, query._PrepareFieldList, [
176 4ca96421 Michael Hanselmann
        (query._MakeField("name", b, constants.QFT_TEXT), None,
177 4ca96421 Michael Hanselmann
         lambda *args: None),
178 4ca96421 Michael Hanselmann
        (query._MakeField("other", a, constants.QFT_TEXT), None,
179 4ca96421 Michael Hanselmann
         lambda *args: None),
180 4ca96421 Michael Hanselmann
        ])
181 4ca96421 Michael Hanselmann
182 4ca96421 Michael Hanselmann
    # Non-lowercase names
183 4ca96421 Michael Hanselmann
    self.assertRaises(AssertionError, query._PrepareFieldList, [
184 4ca96421 Michael Hanselmann
      (query._MakeField("NAME", "Name", constants.QFT_TEXT), None,
185 4ca96421 Michael Hanselmann
       lambda *args: None),
186 4ca96421 Michael Hanselmann
      ])
187 4ca96421 Michael Hanselmann
    self.assertRaises(AssertionError, query._PrepareFieldList, [
188 4ca96421 Michael Hanselmann
      (query._MakeField("Name", "Name", constants.QFT_TEXT), None,
189 4ca96421 Michael Hanselmann
       lambda *args: None),
190 4ca96421 Michael Hanselmann
      ])
191 4ca96421 Michael Hanselmann
192 4ca96421 Michael Hanselmann
    # Empty name
193 4ca96421 Michael Hanselmann
    self.assertRaises(AssertionError, query._PrepareFieldList, [
194 4ca96421 Michael Hanselmann
      (query._MakeField("", "Name", constants.QFT_TEXT), None,
195 4ca96421 Michael Hanselmann
       lambda *args: None),
196 4ca96421 Michael Hanselmann
      ])
197 4ca96421 Michael Hanselmann
198 4ca96421 Michael Hanselmann
    # Empty title
199 4ca96421 Michael Hanselmann
    self.assertRaises(AssertionError, query._PrepareFieldList, [
200 4ca96421 Michael Hanselmann
      (query._MakeField("name", "", constants.QFT_TEXT), None,
201 4ca96421 Michael Hanselmann
       lambda *args: None),
202 4ca96421 Michael Hanselmann
      ])
203 4ca96421 Michael Hanselmann
204 4ca96421 Michael Hanselmann
    # Whitespace in title
205 4ca96421 Michael Hanselmann
    self.assertRaises(AssertionError, query._PrepareFieldList, [
206 4ca96421 Michael Hanselmann
      (query._MakeField("name", "Co lu mn", constants.QFT_TEXT), None,
207 4ca96421 Michael Hanselmann
       lambda *args: None),
208 4ca96421 Michael Hanselmann
      ])
209 4ca96421 Michael Hanselmann
210 4ca96421 Michael Hanselmann
    # No callable function
211 4ca96421 Michael Hanselmann
    self.assertRaises(AssertionError, query._PrepareFieldList, [
212 4ca96421 Michael Hanselmann
      (query._MakeField("name", "Name", constants.QFT_TEXT), None, None),
213 4ca96421 Michael Hanselmann
      ])
214 4ca96421 Michael Hanselmann
215 4ca96421 Michael Hanselmann
  def testUnknown(self):
216 4ca96421 Michael Hanselmann
    fielddef = query._PrepareFieldList([
217 4ca96421 Michael Hanselmann
      (query._MakeField("name", "Name", constants.QFT_TEXT),
218 4ca96421 Michael Hanselmann
       None, lambda _, item: (constants.QRFS_NORMAL, "name%s" % item)),
219 4ca96421 Michael Hanselmann
      (query._MakeField("other0", "Other0", constants.QFT_TIMESTAMP),
220 4ca96421 Michael Hanselmann
       None, lambda *args: (constants.QRFS_NORMAL, 1234)),
221 4ca96421 Michael Hanselmann
      (query._MakeField("nodata", "NoData", constants.QFT_NUMBER),
222 4ca96421 Michael Hanselmann
       None, lambda *args: (constants.QRFS_NODATA, None)),
223 4ca96421 Michael Hanselmann
      (query._MakeField("unavail", "Unavail", constants.QFT_BOOL),
224 4ca96421 Michael Hanselmann
       None, lambda *args: (constants.QRFS_UNAVAIL, None)),
225 4ca96421 Michael Hanselmann
      ])
226 4ca96421 Michael Hanselmann
227 4ca96421 Michael Hanselmann
    for selected in [["foo"], ["Hello", "World"],
228 4ca96421 Michael Hanselmann
                     ["name1", "other", "foo"]]:
229 4ca96421 Michael Hanselmann
      q = query.Query(fielddef, selected)
230 4ca96421 Michael Hanselmann
      self.assertEqual(len(q._fields), len(selected))
231 4ca96421 Michael Hanselmann
      self.assert_(compat.all(len(row) == len(selected)
232 4ca96421 Michael Hanselmann
                              for row in q.Query(_QueryData(range(1, 10)))))
233 4ca96421 Michael Hanselmann
      self.assertEqual(q.Query(_QueryData(range(1, 10))),
234 4ca96421 Michael Hanselmann
                       [[(constants.QRFS_UNKNOWN, None)] * len(selected)
235 4ca96421 Michael Hanselmann
                        for i in range(1, 10)])
236 4ca96421 Michael Hanselmann
      self.assertEqual([fdef.ToDict() for fdef in q.GetFields()],
237 4ca96421 Michael Hanselmann
                       [{ "name": name, "title": name,
238 4ca96421 Michael Hanselmann
                          "kind": constants.QFT_UNKNOWN, }
239 4ca96421 Michael Hanselmann
                        for name in selected])
240 4ca96421 Michael Hanselmann
241 4ca96421 Michael Hanselmann
    q = query.Query(fielddef, ["name", "other0", "nodata", "unavail"])
242 4ca96421 Michael Hanselmann
    self.assertEqual(len(q._fields), 4)
243 4ca96421 Michael Hanselmann
    self.assertEqual(q.OldStyleQuery(_QueryData(range(1, 10))), [
244 4ca96421 Michael Hanselmann
                     ["name%s" % i, 1234, None, None]
245 4ca96421 Michael Hanselmann
                     for i in range(1, 10)
246 4ca96421 Michael Hanselmann
                     ])
247 4ca96421 Michael Hanselmann
248 4ca96421 Michael Hanselmann
    q = query.Query(fielddef, ["name", "other0", "nodata", "unavail", "unk"])
249 4ca96421 Michael Hanselmann
    self.assertEqual(len(q._fields), 5)
250 4ca96421 Michael Hanselmann
    self.assertEqual(q.Query(_QueryData(range(1, 10))),
251 4ca96421 Michael Hanselmann
                     [[(constants.QRFS_NORMAL, "name%s" % i),
252 4ca96421 Michael Hanselmann
                       (constants.QRFS_NORMAL, 1234),
253 4ca96421 Michael Hanselmann
                       (constants.QRFS_NODATA, None),
254 4ca96421 Michael Hanselmann
                       (constants.QRFS_UNAVAIL, None),
255 4ca96421 Michael Hanselmann
                       (constants.QRFS_UNKNOWN, None)]
256 4ca96421 Michael Hanselmann
                      for i in range(1, 10)])
257 4ca96421 Michael Hanselmann
258 4ca96421 Michael Hanselmann
259 8235fe04 Michael Hanselmann
class TestGetNodeRole(unittest.TestCase):
260 8235fe04 Michael Hanselmann
  def testMaster(self):
261 8235fe04 Michael Hanselmann
    node = objects.Node(name="node1")
262 8235fe04 Michael Hanselmann
    self.assertEqual(query._GetNodeRole(node, "node1"), "M")
263 8235fe04 Michael Hanselmann
264 8235fe04 Michael Hanselmann
  def testMasterCandidate(self):
265 8235fe04 Michael Hanselmann
    node = objects.Node(name="node1", master_candidate=True)
266 8235fe04 Michael Hanselmann
    self.assertEqual(query._GetNodeRole(node, "master"), "C")
267 8235fe04 Michael Hanselmann
268 8235fe04 Michael Hanselmann
  def testRegular(self):
269 8235fe04 Michael Hanselmann
    node = objects.Node(name="node1")
270 8235fe04 Michael Hanselmann
    self.assertEqual(query._GetNodeRole(node, "master"), "R")
271 8235fe04 Michael Hanselmann
272 8235fe04 Michael Hanselmann
  def testDrained(self):
273 8235fe04 Michael Hanselmann
    node = objects.Node(name="node1", drained=True)
274 8235fe04 Michael Hanselmann
    self.assertEqual(query._GetNodeRole(node, "master"), "D")
275 8235fe04 Michael Hanselmann
276 8235fe04 Michael Hanselmann
  def testOffline(self):
277 8235fe04 Michael Hanselmann
    node = objects.Node(name="node1", offline=True)
278 8235fe04 Michael Hanselmann
    self.assertEqual(query._GetNodeRole(node, "master"), "O")
279 8235fe04 Michael Hanselmann
280 8235fe04 Michael Hanselmann
281 8235fe04 Michael Hanselmann
class TestNodeQuery(unittest.TestCase):
282 8235fe04 Michael Hanselmann
  def _Create(self, selected):
283 8235fe04 Michael Hanselmann
    return query.Query(query.NODE_FIELDS, selected)
284 8235fe04 Michael Hanselmann
285 8235fe04 Michael Hanselmann
  def testSimple(self):
286 8235fe04 Michael Hanselmann
    nodes = [
287 8235fe04 Michael Hanselmann
      objects.Node(name="node1", drained=False),
288 8235fe04 Michael Hanselmann
      objects.Node(name="node2", drained=True),
289 8235fe04 Michael Hanselmann
      objects.Node(name="node3", drained=False),
290 8235fe04 Michael Hanselmann
      ]
291 8235fe04 Michael Hanselmann
    for live_data in [None, dict.fromkeys([node.name for node in nodes], {})]:
292 8572f1fe Renรฉ Nussbaumer
      nqd = query.NodeQueryData(nodes, live_data, None, None, None, None, None,
293 8572f1fe Renรฉ Nussbaumer
                                None)
294 8235fe04 Michael Hanselmann
295 8235fe04 Michael Hanselmann
      q = self._Create(["name", "drained"])
296 8235fe04 Michael Hanselmann
      self.assertEqual(q.RequestedData(), set([query.NQ_CONFIG]))
297 8235fe04 Michael Hanselmann
      self.assertEqual(q.Query(nqd),
298 8235fe04 Michael Hanselmann
                       [[(constants.QRFS_NORMAL, "node1"),
299 8235fe04 Michael Hanselmann
                         (constants.QRFS_NORMAL, False)],
300 8235fe04 Michael Hanselmann
                        [(constants.QRFS_NORMAL, "node2"),
301 8235fe04 Michael Hanselmann
                         (constants.QRFS_NORMAL, True)],
302 8235fe04 Michael Hanselmann
                        [(constants.QRFS_NORMAL, "node3"),
303 8235fe04 Michael Hanselmann
                         (constants.QRFS_NORMAL, False)],
304 8235fe04 Michael Hanselmann
                       ])
305 8235fe04 Michael Hanselmann
      self.assertEqual(q.OldStyleQuery(nqd),
306 8235fe04 Michael Hanselmann
                       [["node1", False],
307 8235fe04 Michael Hanselmann
                        ["node2", True],
308 8235fe04 Michael Hanselmann
                        ["node3", False]])
309 8235fe04 Michael Hanselmann
310 8235fe04 Michael Hanselmann
  def test(self):
311 8235fe04 Michael Hanselmann
    selected = query.NODE_FIELDS.keys()
312 8235fe04 Michael Hanselmann
    field_index = dict((field, idx) for idx, field in enumerate(selected))
313 8235fe04 Michael Hanselmann
314 8235fe04 Michael Hanselmann
    q = self._Create(selected)
315 8235fe04 Michael Hanselmann
    self.assertEqual(q.RequestedData(),
316 8235fe04 Michael Hanselmann
                     set([query.NQ_CONFIG, query.NQ_LIVE, query.NQ_INST,
317 52b5d286 Renรฉ Nussbaumer
                          query.NQ_GROUP, query.NQ_OOB]))
318 8235fe04 Michael Hanselmann
319 8572f1fe Renรฉ Nussbaumer
    cluster = objects.Cluster(cluster_name="testcluster",
320 8572f1fe Renรฉ Nussbaumer
      hvparams=constants.HVC_DEFAULTS,
321 8572f1fe Renรฉ Nussbaumer
      beparams={
322 8572f1fe Renรฉ Nussbaumer
        constants.PP_DEFAULT: constants.BEC_DEFAULTS,
323 8572f1fe Renรฉ Nussbaumer
        },
324 8572f1fe Renรฉ Nussbaumer
      nicparams={
325 8572f1fe Renรฉ Nussbaumer
        constants.PP_DEFAULT: constants.NICC_DEFAULTS,
326 8572f1fe Renรฉ Nussbaumer
        },
327 8572f1fe Renรฉ Nussbaumer
      ndparams=constants.NDC_DEFAULTS,
328 8572f1fe Renรฉ Nussbaumer
        )
329 8572f1fe Renรฉ Nussbaumer
330 8235fe04 Michael Hanselmann
    node_names = ["node%s" % i for i in range(20)]
331 8235fe04 Michael Hanselmann
    master_name = node_names[3]
332 8235fe04 Michael Hanselmann
    nodes = [
333 8235fe04 Michael Hanselmann
      objects.Node(name=name,
334 8235fe04 Michael Hanselmann
                   primary_ip="192.0.2.%s" % idx,
335 8235fe04 Michael Hanselmann
                   secondary_ip="192.0.100.%s" % idx,
336 8235fe04 Michael Hanselmann
                   serial_no=7789 * idx,
337 8235fe04 Michael Hanselmann
                   master_candidate=(name != master_name and idx % 3 == 0),
338 8235fe04 Michael Hanselmann
                   offline=False,
339 8235fe04 Michael Hanselmann
                   drained=False,
340 8235fe04 Michael Hanselmann
                   vm_capable=False,
341 8235fe04 Michael Hanselmann
                   master_capable=False,
342 8572f1fe Renรฉ Nussbaumer
                   ndparams={},
343 8235fe04 Michael Hanselmann
                   group="default",
344 8235fe04 Michael Hanselmann
                   ctime=1290006900,
345 8235fe04 Michael Hanselmann
                   mtime=1290006913,
346 8235fe04 Michael Hanselmann
                   uuid="fd9ccebe-6339-43c9-a82e-94bbe575%04d" % idx)
347 8235fe04 Michael Hanselmann
      for idx, name in enumerate(node_names)
348 8235fe04 Michael Hanselmann
      ]
349 8235fe04 Michael Hanselmann
350 8235fe04 Michael Hanselmann
    master_node = nodes[3]
351 8235fe04 Michael Hanselmann
    master_node.AddTag("masternode")
352 8235fe04 Michael Hanselmann
    master_node.AddTag("another")
353 8235fe04 Michael Hanselmann
    master_node.AddTag("tag")
354 145bea54 Michael Hanselmann
    master_node.ctime = None
355 145bea54 Michael Hanselmann
    master_node.mtime = None
356 8235fe04 Michael Hanselmann
    assert master_node.name == master_name
357 8235fe04 Michael Hanselmann
358 8235fe04 Michael Hanselmann
    live_data_name = node_names[4]
359 8235fe04 Michael Hanselmann
    assert live_data_name != master_name
360 8235fe04 Michael Hanselmann
361 8235fe04 Michael Hanselmann
    fake_live_data = {
362 8235fe04 Michael Hanselmann
      "bootid": "a2504766-498e-4b25-b21e-d23098dc3af4",
363 8235fe04 Michael Hanselmann
      "cnodes": 4,
364 8235fe04 Michael Hanselmann
      "csockets": 4,
365 8235fe04 Michael Hanselmann
      "ctotal": 8,
366 8235fe04 Michael Hanselmann
      "mnode": 128,
367 8235fe04 Michael Hanselmann
      "mfree": 100,
368 8235fe04 Michael Hanselmann
      "mtotal": 4096,
369 8235fe04 Michael Hanselmann
      "dfree": 5 * 1024 * 1024,
370 8235fe04 Michael Hanselmann
      "dtotal": 100 * 1024 * 1024,
371 8235fe04 Michael Hanselmann
      }
372 8235fe04 Michael Hanselmann
373 8235fe04 Michael Hanselmann
    assert (sorted(query._NODE_LIVE_FIELDS.keys()) ==
374 8235fe04 Michael Hanselmann
            sorted(fake_live_data.keys()))
375 8235fe04 Michael Hanselmann
376 8235fe04 Michael Hanselmann
    live_data = dict.fromkeys(node_names, {})
377 8235fe04 Michael Hanselmann
    live_data[live_data_name] = \
378 8235fe04 Michael Hanselmann
      dict((query._NODE_LIVE_FIELDS[name][2], value)
379 8235fe04 Michael Hanselmann
           for name, value in fake_live_data.items())
380 8235fe04 Michael Hanselmann
381 8235fe04 Michael Hanselmann
    node_to_primary = dict((name, set()) for name in node_names)
382 8235fe04 Michael Hanselmann
    node_to_primary[master_name].update(["inst1", "inst2"])
383 8235fe04 Michael Hanselmann
384 8235fe04 Michael Hanselmann
    node_to_secondary = dict((name, set()) for name in node_names)
385 8235fe04 Michael Hanselmann
    node_to_secondary[live_data_name].update(["instX", "instY", "instZ"])
386 8235fe04 Michael Hanselmann
387 8235fe04 Michael Hanselmann
    ng_uuid = "492b4b74-8670-478a-b98d-4c53a76238e6"
388 8235fe04 Michael Hanselmann
    groups = {
389 8572f1fe Renรฉ Nussbaumer
      ng_uuid: objects.NodeGroup(name="ng1", uuid=ng_uuid, ndparams={}),
390 8235fe04 Michael Hanselmann
      }
391 8235fe04 Michael Hanselmann
392 52b5d286 Renรฉ Nussbaumer
    oob_support = dict((name, False) for name in node_names)
393 52b5d286 Renรฉ Nussbaumer
394 8235fe04 Michael Hanselmann
    master_node.group = ng_uuid
395 8235fe04 Michael Hanselmann
396 8235fe04 Michael Hanselmann
    nqd = query.NodeQueryData(nodes, live_data, master_name,
397 52b5d286 Renรฉ Nussbaumer
                              node_to_primary, node_to_secondary, groups,
398 8572f1fe Renรฉ Nussbaumer
                              oob_support, cluster)
399 8235fe04 Michael Hanselmann
    result = q.Query(nqd)
400 8235fe04 Michael Hanselmann
    self.assert_(compat.all(len(row) == len(selected) for row in result))
401 8235fe04 Michael Hanselmann
    self.assertEqual([row[field_index["name"]] for row in result],
402 8235fe04 Michael Hanselmann
                     [(constants.QRFS_NORMAL, name) for name in node_names])
403 8235fe04 Michael Hanselmann
404 8235fe04 Michael Hanselmann
    node_to_row = dict((row[field_index["name"]][1], idx)
405 8235fe04 Michael Hanselmann
                       for idx, row in enumerate(result))
406 8235fe04 Michael Hanselmann
407 8235fe04 Michael Hanselmann
    master_row = result[node_to_row[master_name]]
408 8235fe04 Michael Hanselmann
    self.assert_(master_row[field_index["master"]])
409 8235fe04 Michael Hanselmann
    self.assert_(master_row[field_index["role"]], "M")
410 8235fe04 Michael Hanselmann
    self.assertEqual(master_row[field_index["group"]],
411 8235fe04 Michael Hanselmann
                     (constants.QRFS_NORMAL, "ng1"))
412 8235fe04 Michael Hanselmann
    self.assertEqual(master_row[field_index["group.uuid"]],
413 8235fe04 Michael Hanselmann
                     (constants.QRFS_NORMAL, ng_uuid))
414 145bea54 Michael Hanselmann
    self.assertEqual(master_row[field_index["ctime"]],
415 145bea54 Michael Hanselmann
                     (constants.QRFS_UNAVAIL, None))
416 145bea54 Michael Hanselmann
    self.assertEqual(master_row[field_index["mtime"]],
417 145bea54 Michael Hanselmann
                     (constants.QRFS_UNAVAIL, None))
418 8235fe04 Michael Hanselmann
419 8235fe04 Michael Hanselmann
    self.assert_(row[field_index["pip"]] == node.primary_ip and
420 8235fe04 Michael Hanselmann
                 row[field_index["sip"]] == node.secondary_ip and
421 8235fe04 Michael Hanselmann
                 set(row[field_index["tags"]]) == node.GetTags() and
422 8235fe04 Michael Hanselmann
                 row[field_index["serial_no"]] == node.serial_no and
423 8235fe04 Michael Hanselmann
                 row[field_index["role"]] == query._GetNodeRole(node,
424 8235fe04 Michael Hanselmann
                                                                master_name) and
425 8235fe04 Michael Hanselmann
                 (node.name == master_name or
426 8235fe04 Michael Hanselmann
                  (row[field_index["group"]] == "<unknown>" and
427 145bea54 Michael Hanselmann
                   row[field_index["group.uuid"]] is None and
428 145bea54 Michael Hanselmann
                   row[field_index["ctime"]] == (constants.QRFS_NORMAL,
429 145bea54 Michael Hanselmann
                                                 node.ctime) and
430 145bea54 Michael Hanselmann
                   row[field_index["mtime"]] == (constants.QRFS_NORMAL,
431 145bea54 Michael Hanselmann
                                                 node.mtime)))
432 8235fe04 Michael Hanselmann
                 for row, node in zip(result, nodes))
433 8235fe04 Michael Hanselmann
434 8235fe04 Michael Hanselmann
    live_data_row = result[node_to_row[live_data_name]]
435 8235fe04 Michael Hanselmann
436 8235fe04 Michael Hanselmann
    for (field, value) in fake_live_data.items():
437 8235fe04 Michael Hanselmann
      self.assertEqual(live_data_row[field_index[field]],
438 8235fe04 Michael Hanselmann
                       (constants.QRFS_NORMAL, value))
439 8235fe04 Michael Hanselmann
440 8235fe04 Michael Hanselmann
    self.assertEqual(master_row[field_index["pinst_cnt"]],
441 8235fe04 Michael Hanselmann
                     (constants.QRFS_NORMAL, 2))
442 8235fe04 Michael Hanselmann
    self.assertEqual(live_data_row[field_index["sinst_cnt"]],
443 8235fe04 Michael Hanselmann
                     (constants.QRFS_NORMAL, 3))
444 8235fe04 Michael Hanselmann
    self.assertEqual(master_row[field_index["pinst_list"]],
445 8235fe04 Michael Hanselmann
                     (constants.QRFS_NORMAL,
446 8235fe04 Michael Hanselmann
                      list(node_to_primary[master_name])))
447 8235fe04 Michael Hanselmann
    self.assertEqual(live_data_row[field_index["sinst_list"]],
448 8235fe04 Michael Hanselmann
                     (constants.QRFS_NORMAL,
449 8235fe04 Michael Hanselmann
                      list(node_to_secondary[live_data_name])))
450 8235fe04 Michael Hanselmann
451 8235fe04 Michael Hanselmann
  def testGetLiveNodeField(self):
452 8235fe04 Michael Hanselmann
    nodes = [
453 a6070ef7 Michael Hanselmann
      objects.Node(name="node1", drained=False, offline=False),
454 a6070ef7 Michael Hanselmann
      objects.Node(name="node2", drained=True, offline=False),
455 a6070ef7 Michael Hanselmann
      objects.Node(name="node3", drained=False, offline=False),
456 a6070ef7 Michael Hanselmann
      objects.Node(name="node4", drained=False, offline=True),
457 8235fe04 Michael Hanselmann
      ]
458 8235fe04 Michael Hanselmann
    live_data = dict.fromkeys([node.name for node in nodes], {})
459 8235fe04 Michael Hanselmann
460 8235fe04 Michael Hanselmann
    # No data
461 8572f1fe Renรฉ Nussbaumer
    nqd = query.NodeQueryData(None, None, None, None, None, None, None, None)
462 8235fe04 Michael Hanselmann
    self.assertEqual(query._GetLiveNodeField("hello", constants.QFT_NUMBER,
463 a6070ef7 Michael Hanselmann
                                             nqd, nodes[0]),
464 8235fe04 Michael Hanselmann
                     (constants.QRFS_NODATA, None))
465 8235fe04 Michael Hanselmann
466 8235fe04 Michael Hanselmann
    # Missing field
467 8235fe04 Michael Hanselmann
    ctx = _QueryData(None, curlive_data={
468 8235fe04 Michael Hanselmann
      "some": 1,
469 8235fe04 Michael Hanselmann
      "other": 2,
470 8235fe04 Michael Hanselmann
      })
471 8235fe04 Michael Hanselmann
    self.assertEqual(query._GetLiveNodeField("hello", constants.QFT_NUMBER,
472 a6070ef7 Michael Hanselmann
                                             ctx, nodes[0]),
473 8235fe04 Michael Hanselmann
                     (constants.QRFS_UNAVAIL, None))
474 8235fe04 Michael Hanselmann
475 8235fe04 Michael Hanselmann
    # Wrong format/datatype
476 8235fe04 Michael Hanselmann
    ctx = _QueryData(None, curlive_data={
477 8235fe04 Michael Hanselmann
      "hello": ["Hello World"],
478 8235fe04 Michael Hanselmann
      "other": 2,
479 8235fe04 Michael Hanselmann
      })
480 8235fe04 Michael Hanselmann
    self.assertEqual(query._GetLiveNodeField("hello", constants.QFT_NUMBER,
481 a6070ef7 Michael Hanselmann
                                             ctx, nodes[0]),
482 8235fe04 Michael Hanselmann
                     (constants.QRFS_UNAVAIL, None))
483 8235fe04 Michael Hanselmann
484 a6070ef7 Michael Hanselmann
    # Offline node
485 a6070ef7 Michael Hanselmann
    assert nodes[3].offline
486 a6070ef7 Michael Hanselmann
    ctx = _QueryData(None, curlive_data={})
487 a6070ef7 Michael Hanselmann
    self.assertEqual(query._GetLiveNodeField("hello", constants.QFT_NUMBER,
488 a6070ef7 Michael Hanselmann
                                             ctx, nodes[3]),
489 a6070ef7 Michael Hanselmann
                     (constants.QRFS_OFFLINE, None))
490 a6070ef7 Michael Hanselmann
491 8235fe04 Michael Hanselmann
    # Wrong field type
492 8235fe04 Michael Hanselmann
    ctx = _QueryData(None, curlive_data={"hello": 123})
493 8235fe04 Michael Hanselmann
    self.assertRaises(AssertionError, query._GetLiveNodeField,
494 a6070ef7 Michael Hanselmann
                      "hello", constants.QFT_BOOL, ctx, nodes[0])
495 8235fe04 Michael Hanselmann
496 8235fe04 Michael Hanselmann
497 1c8addc6 Michael Hanselmann
class TestInstanceQuery(unittest.TestCase):
498 1c8addc6 Michael Hanselmann
  def _Create(self, selected):
499 1c8addc6 Michael Hanselmann
    return query.Query(query.INSTANCE_FIELDS, selected)
500 1c8addc6 Michael Hanselmann
501 1c8addc6 Michael Hanselmann
  def testSimple(self):
502 1c8addc6 Michael Hanselmann
    q = self._Create(["name", "be/memory", "ip"])
503 1c8addc6 Michael Hanselmann
    self.assertEqual(q.RequestedData(), set([query.IQ_CONFIG]))
504 1c8addc6 Michael Hanselmann
505 1c8addc6 Michael Hanselmann
    cluster = objects.Cluster(cluster_name="testcluster",
506 1c8addc6 Michael Hanselmann
      hvparams=constants.HVC_DEFAULTS,
507 1c8addc6 Michael Hanselmann
      beparams={
508 1c8addc6 Michael Hanselmann
        constants.PP_DEFAULT: constants.BEC_DEFAULTS,
509 1c8addc6 Michael Hanselmann
        },
510 1c8addc6 Michael Hanselmann
      nicparams={
511 1c8addc6 Michael Hanselmann
        constants.PP_DEFAULT: constants.NICC_DEFAULTS,
512 1c8addc6 Michael Hanselmann
        })
513 1c8addc6 Michael Hanselmann
514 1c8addc6 Michael Hanselmann
    instances = [
515 1c8addc6 Michael Hanselmann
      objects.Instance(name="inst1", hvparams={}, beparams={}, nics=[]),
516 1c8addc6 Michael Hanselmann
      objects.Instance(name="inst2", hvparams={}, nics=[],
517 1c8addc6 Michael Hanselmann
        beparams={
518 1c8addc6 Michael Hanselmann
          constants.BE_MEMORY: 512,
519 1c8addc6 Michael Hanselmann
        }),
520 1c8addc6 Michael Hanselmann
      objects.Instance(name="inst3", hvparams={}, beparams={},
521 1c8addc6 Michael Hanselmann
        nics=[objects.NIC(ip="192.0.2.99", nicparams={})]),
522 1c8addc6 Michael Hanselmann
      ]
523 1c8addc6 Michael Hanselmann
524 1c8addc6 Michael Hanselmann
    iqd = query.InstanceQueryData(instances, cluster, None, [], [], {})
525 1c8addc6 Michael Hanselmann
    self.assertEqual(q.Query(iqd),
526 1c8addc6 Michael Hanselmann
      [[(constants.QRFS_NORMAL, "inst1"),
527 1c8addc6 Michael Hanselmann
        (constants.QRFS_NORMAL, 128),
528 1c8addc6 Michael Hanselmann
        (constants.QRFS_UNAVAIL, None),
529 1c8addc6 Michael Hanselmann
       ],
530 1c8addc6 Michael Hanselmann
       [(constants.QRFS_NORMAL, "inst2"),
531 1c8addc6 Michael Hanselmann
        (constants.QRFS_NORMAL, 512),
532 1c8addc6 Michael Hanselmann
        (constants.QRFS_UNAVAIL, None),
533 1c8addc6 Michael Hanselmann
       ],
534 1c8addc6 Michael Hanselmann
       [(constants.QRFS_NORMAL, "inst3"),
535 1c8addc6 Michael Hanselmann
        (constants.QRFS_NORMAL, 128),
536 1c8addc6 Michael Hanselmann
        (constants.QRFS_NORMAL, "192.0.2.99"),
537 1c8addc6 Michael Hanselmann
       ]])
538 1c8addc6 Michael Hanselmann
    self.assertEqual(q.OldStyleQuery(iqd),
539 1c8addc6 Michael Hanselmann
      [["inst1", 128, None],
540 1c8addc6 Michael Hanselmann
       ["inst2", 512, None],
541 1c8addc6 Michael Hanselmann
       ["inst3", 128, "192.0.2.99"]])
542 1c8addc6 Michael Hanselmann
543 1c8addc6 Michael Hanselmann
  def test(self):
544 1c8addc6 Michael Hanselmann
    selected = query.INSTANCE_FIELDS.keys()
545 1c8addc6 Michael Hanselmann
    fieldidx = dict((field, idx) for idx, field in enumerate(selected))
546 1c8addc6 Michael Hanselmann
547 1c8addc6 Michael Hanselmann
    macs = ["00:11:22:%02x:%02x:%02x" % (i % 255, i % 3, (i * 123) % 255)
548 1c8addc6 Michael Hanselmann
            for i in range(20)]
549 1c8addc6 Michael Hanselmann
550 1c8addc6 Michael Hanselmann
    q = self._Create(selected)
551 1c8addc6 Michael Hanselmann
    self.assertEqual(q.RequestedData(),
552 1c8addc6 Michael Hanselmann
                     set([query.IQ_CONFIG, query.IQ_LIVE, query.IQ_DISKUSAGE]))
553 1c8addc6 Michael Hanselmann
554 1c8addc6 Michael Hanselmann
    cluster = objects.Cluster(cluster_name="testcluster",
555 1c8addc6 Michael Hanselmann
      hvparams=constants.HVC_DEFAULTS,
556 1c8addc6 Michael Hanselmann
      beparams={
557 1c8addc6 Michael Hanselmann
        constants.PP_DEFAULT: constants.BEC_DEFAULTS,
558 1c8addc6 Michael Hanselmann
        },
559 1c8addc6 Michael Hanselmann
      nicparams={
560 1c8addc6 Michael Hanselmann
        constants.PP_DEFAULT: constants.NICC_DEFAULTS,
561 1c8addc6 Michael Hanselmann
        },
562 1c8addc6 Michael Hanselmann
      os_hvp={},
563 1c8addc6 Michael Hanselmann
      tcpudp_port_pool=set())
564 1c8addc6 Michael Hanselmann
565 1c8addc6 Michael Hanselmann
    offline_nodes = ["nodeoff1", "nodeoff2"]
566 1c8addc6 Michael Hanselmann
    bad_nodes = ["nodebad1", "nodebad2", "nodebad3"] + offline_nodes
567 1c8addc6 Michael Hanselmann
    nodes = ["node%s" % i for i in range(10)] + bad_nodes
568 1c8addc6 Michael Hanselmann
569 1c8addc6 Michael Hanselmann
    instances = [
570 1c8addc6 Michael Hanselmann
      objects.Instance(name="inst1", hvparams={}, beparams={}, nics=[],
571 1c8addc6 Michael Hanselmann
        uuid="f90eccb3-e227-4e3c-bf2a-94a21ca8f9cd",
572 1c8addc6 Michael Hanselmann
        ctime=1291244000, mtime=1291244400, serial_no=30,
573 1c8addc6 Michael Hanselmann
        admin_up=True, hypervisor=constants.HT_XEN_PVM, os="linux1",
574 1c8addc6 Michael Hanselmann
        primary_node="node1",
575 1c8addc6 Michael Hanselmann
        disk_template=constants.DT_PLAIN,
576 1c8addc6 Michael Hanselmann
        disks=[]),
577 1c8addc6 Michael Hanselmann
      objects.Instance(name="inst2", hvparams={}, nics=[],
578 1c8addc6 Michael Hanselmann
        uuid="73a0f8a7-068c-4630-ada2-c3440015ab1a",
579 1c8addc6 Michael Hanselmann
        ctime=1291211000, mtime=1291211077, serial_no=1,
580 1c8addc6 Michael Hanselmann
        admin_up=True, hypervisor=constants.HT_XEN_HVM, os="deb99",
581 1c8addc6 Michael Hanselmann
        primary_node="node5",
582 1c8addc6 Michael Hanselmann
        disk_template=constants.DT_DISKLESS,
583 1c8addc6 Michael Hanselmann
        disks=[],
584 1c8addc6 Michael Hanselmann
        beparams={
585 1c8addc6 Michael Hanselmann
          constants.BE_MEMORY: 512,
586 1c8addc6 Michael Hanselmann
        }),
587 1c8addc6 Michael Hanselmann
      objects.Instance(name="inst3", hvparams={}, beparams={},
588 1c8addc6 Michael Hanselmann
        uuid="11ec8dff-fb61-4850-bfe0-baa1803ff280",
589 1c8addc6 Michael Hanselmann
        ctime=1291011000, mtime=1291013000, serial_no=1923,
590 1c8addc6 Michael Hanselmann
        admin_up=False, hypervisor=constants.HT_KVM, os="busybox",
591 1c8addc6 Michael Hanselmann
        primary_node="node6",
592 1c8addc6 Michael Hanselmann
        disk_template=constants.DT_DRBD8,
593 1c8addc6 Michael Hanselmann
        disks=[],
594 1c8addc6 Michael Hanselmann
        nics=[
595 1c8addc6 Michael Hanselmann
          objects.NIC(ip="192.0.2.99", mac=macs.pop(),
596 1c8addc6 Michael Hanselmann
                      nicparams={
597 1c8addc6 Michael Hanselmann
                        constants.NIC_LINK: constants.DEFAULT_BRIDGE,
598 1c8addc6 Michael Hanselmann
                        }),
599 1c8addc6 Michael Hanselmann
          objects.NIC(ip=None, mac=macs.pop(), nicparams={}),
600 1c8addc6 Michael Hanselmann
          ]),
601 1c8addc6 Michael Hanselmann
      objects.Instance(name="inst4", hvparams={}, beparams={},
602 1c8addc6 Michael Hanselmann
        uuid="68dab168-3ef5-4c9d-b4d3-801e0672068c",
603 1c8addc6 Michael Hanselmann
        ctime=1291244390, mtime=1291244395, serial_no=25,
604 1c8addc6 Michael Hanselmann
        admin_up=False, hypervisor=constants.HT_XEN_PVM, os="linux1",
605 1c8addc6 Michael Hanselmann
        primary_node="nodeoff2",
606 1c8addc6 Michael Hanselmann
        disk_template=constants.DT_DRBD8,
607 1c8addc6 Michael Hanselmann
        disks=[],
608 1c8addc6 Michael Hanselmann
        nics=[
609 1c8addc6 Michael Hanselmann
          objects.NIC(ip="192.0.2.1", mac=macs.pop(),
610 1c8addc6 Michael Hanselmann
                      nicparams={
611 1c8addc6 Michael Hanselmann
                        constants.NIC_LINK: constants.DEFAULT_BRIDGE,
612 1c8addc6 Michael Hanselmann
                        }),
613 1c8addc6 Michael Hanselmann
          objects.NIC(ip="192.0.2.2", mac=macs.pop(), nicparams={}),
614 1c8addc6 Michael Hanselmann
          objects.NIC(ip="192.0.2.3", mac=macs.pop(),
615 1c8addc6 Michael Hanselmann
                      nicparams={
616 1c8addc6 Michael Hanselmann
                        constants.NIC_MODE: constants.NIC_MODE_ROUTED,
617 1c8addc6 Michael Hanselmann
                        }),
618 1c8addc6 Michael Hanselmann
          objects.NIC(ip="192.0.2.4", mac=macs.pop(),
619 1c8addc6 Michael Hanselmann
                      nicparams={
620 1c8addc6 Michael Hanselmann
                        constants.NIC_MODE: constants.NIC_MODE_BRIDGED,
621 1c8addc6 Michael Hanselmann
                        constants.NIC_LINK: "eth123",
622 1c8addc6 Michael Hanselmann
                        }),
623 1c8addc6 Michael Hanselmann
          ]),
624 1c8addc6 Michael Hanselmann
      objects.Instance(name="inst5", hvparams={}, nics=[],
625 1c8addc6 Michael Hanselmann
        uuid="0e3dca12-5b42-4e24-98a2-415267545bd0",
626 1c8addc6 Michael Hanselmann
        ctime=1231211000, mtime=1261200000, serial_no=3,
627 1c8addc6 Michael Hanselmann
        admin_up=True, hypervisor=constants.HT_XEN_HVM, os="deb99",
628 1c8addc6 Michael Hanselmann
        primary_node="nodebad2",
629 1c8addc6 Michael Hanselmann
        disk_template=constants.DT_DISKLESS,
630 1c8addc6 Michael Hanselmann
        disks=[],
631 1c8addc6 Michael Hanselmann
        beparams={
632 1c8addc6 Michael Hanselmann
          constants.BE_MEMORY: 512,
633 1c8addc6 Michael Hanselmann
        }),
634 1c8addc6 Michael Hanselmann
      objects.Instance(name="inst6", hvparams={}, nics=[],
635 1c8addc6 Michael Hanselmann
        uuid="72de6580-c8d5-4661-b902-38b5785bb8b3",
636 1c8addc6 Michael Hanselmann
        ctime=7513, mtime=11501, serial_no=13390,
637 1c8addc6 Michael Hanselmann
        admin_up=False, hypervisor=constants.HT_XEN_HVM, os="deb99",
638 1c8addc6 Michael Hanselmann
        primary_node="node7",
639 1c8addc6 Michael Hanselmann
        disk_template=constants.DT_DISKLESS,
640 1c8addc6 Michael Hanselmann
        disks=[],
641 1c8addc6 Michael Hanselmann
        beparams={
642 1c8addc6 Michael Hanselmann
          constants.BE_MEMORY: 768,
643 1c8addc6 Michael Hanselmann
        }),
644 145bea54 Michael Hanselmann
      objects.Instance(name="inst7", hvparams={}, nics=[],
645 145bea54 Michael Hanselmann
        uuid="ceec5dc4-b729-4f42-ae28-69b3cd24920e",
646 145bea54 Michael Hanselmann
        ctime=None, mtime=None, serial_no=1947,
647 145bea54 Michael Hanselmann
        admin_up=False, hypervisor=constants.HT_XEN_HVM, os="deb99",
648 145bea54 Michael Hanselmann
        primary_node="node6",
649 145bea54 Michael Hanselmann
        disk_template=constants.DT_DISKLESS,
650 145bea54 Michael Hanselmann
        disks=[],
651 145bea54 Michael Hanselmann
        beparams={}),
652 1c8addc6 Michael Hanselmann
      ]
653 1c8addc6 Michael Hanselmann
654 145bea54 Michael Hanselmann
    assert not utils.FindDuplicates(inst.name for inst in instances)
655 145bea54 Michael Hanselmann
656 1c8addc6 Michael Hanselmann
    disk_usage = dict((inst.name,
657 1c8addc6 Michael Hanselmann
                       cmdlib._ComputeDiskSize(inst.disk_template,
658 1c8addc6 Michael Hanselmann
                                               [{"size": disk.size}
659 1c8addc6 Michael Hanselmann
                                                for disk in inst.disks]))
660 1c8addc6 Michael Hanselmann
                      for inst in instances)
661 1c8addc6 Michael Hanselmann
662 1c8addc6 Michael Hanselmann
    inst_bridges = {
663 1c8addc6 Michael Hanselmann
      "inst3": [constants.DEFAULT_BRIDGE, constants.DEFAULT_BRIDGE],
664 1c8addc6 Michael Hanselmann
      "inst4": [constants.DEFAULT_BRIDGE, constants.DEFAULT_BRIDGE,
665 1c8addc6 Michael Hanselmann
                None, "eth123"],
666 1c8addc6 Michael Hanselmann
      }
667 1c8addc6 Michael Hanselmann
668 1c8addc6 Michael Hanselmann
    live_data = {
669 1c8addc6 Michael Hanselmann
      "inst2": {
670 1c8addc6 Michael Hanselmann
        "vcpus": 3,
671 1c8addc6 Michael Hanselmann
        },
672 1c8addc6 Michael Hanselmann
      "inst4": {
673 1c8addc6 Michael Hanselmann
        "memory": 123,
674 1c8addc6 Michael Hanselmann
        },
675 1c8addc6 Michael Hanselmann
      "inst6": {
676 1c8addc6 Michael Hanselmann
        "memory": 768,
677 1c8addc6 Michael Hanselmann
        },
678 1c8addc6 Michael Hanselmann
      }
679 1c8addc6 Michael Hanselmann
680 1c8addc6 Michael Hanselmann
    iqd = query.InstanceQueryData(instances, cluster, disk_usage,
681 1c8addc6 Michael Hanselmann
                                  offline_nodes, bad_nodes, live_data)
682 1c8addc6 Michael Hanselmann
    result = q.Query(iqd)
683 1c8addc6 Michael Hanselmann
    self.assertEqual(len(result), len(instances))
684 1c8addc6 Michael Hanselmann
    self.assert_(compat.all(len(row) == len(selected)
685 1c8addc6 Michael Hanselmann
                            for row in result))
686 1c8addc6 Michael Hanselmann
687 1c8addc6 Michael Hanselmann
    assert len(set(bad_nodes) & set(offline_nodes)) == len(offline_nodes), \
688 1c8addc6 Michael Hanselmann
           "Offline nodes not included in bad nodes"
689 1c8addc6 Michael Hanselmann
690 1c8addc6 Michael Hanselmann
    tested_status = set()
691 1c8addc6 Michael Hanselmann
692 1c8addc6 Michael Hanselmann
    for (inst, row) in zip(instances, result):
693 1c8addc6 Michael Hanselmann
      assert inst.primary_node in nodes
694 1c8addc6 Michael Hanselmann
695 1c8addc6 Michael Hanselmann
      self.assertEqual(row[fieldidx["name"]],
696 1c8addc6 Michael Hanselmann
                       (constants.QRFS_NORMAL, inst.name))
697 1c8addc6 Michael Hanselmann
698 1c8addc6 Michael Hanselmann
      if inst.primary_node in offline_nodes:
699 1c8addc6 Michael Hanselmann
        exp_status = "ERROR_nodeoffline"
700 1c8addc6 Michael Hanselmann
      elif inst.primary_node in bad_nodes:
701 1c8addc6 Michael Hanselmann
        exp_status = "ERROR_nodedown"
702 1c8addc6 Michael Hanselmann
      elif inst.name in live_data:
703 1c8addc6 Michael Hanselmann
        if inst.admin_up:
704 1c8addc6 Michael Hanselmann
          exp_status = "running"
705 1c8addc6 Michael Hanselmann
        else:
706 1c8addc6 Michael Hanselmann
          exp_status = "ERROR_up"
707 1c8addc6 Michael Hanselmann
      elif inst.admin_up:
708 1c8addc6 Michael Hanselmann
        exp_status = "ERROR_down"
709 1c8addc6 Michael Hanselmann
      else:
710 1c8addc6 Michael Hanselmann
        exp_status = "ADMIN_down"
711 1c8addc6 Michael Hanselmann
712 1c8addc6 Michael Hanselmann
      self.assertEqual(row[fieldidx["status"]],
713 1c8addc6 Michael Hanselmann
                       (constants.QRFS_NORMAL, exp_status))
714 1c8addc6 Michael Hanselmann
715 1c8addc6 Michael Hanselmann
      (_, status) = row[fieldidx["status"]]
716 1c8addc6 Michael Hanselmann
      tested_status.add(status)
717 1c8addc6 Michael Hanselmann
718 1c8addc6 Michael Hanselmann
      for (field, livefield) in [("oper_ram", "memory"),
719 1c8addc6 Michael Hanselmann
                                 ("oper_vcpus", "vcpus")]:
720 1c8addc6 Michael Hanselmann
        if inst.primary_node in bad_nodes:
721 1c8addc6 Michael Hanselmann
          exp = (constants.QRFS_NODATA, None)
722 1c8addc6 Michael Hanselmann
        elif inst.name in live_data:
723 1c8addc6 Michael Hanselmann
          value = live_data[inst.name].get(livefield, None)
724 1c8addc6 Michael Hanselmann
          if value is None:
725 1c8addc6 Michael Hanselmann
            exp = (constants.QRFS_UNAVAIL, None)
726 1c8addc6 Michael Hanselmann
          else:
727 1c8addc6 Michael Hanselmann
            exp = (constants.QRFS_NORMAL, value)
728 1c8addc6 Michael Hanselmann
        else:
729 1c8addc6 Michael Hanselmann
          exp = (constants.QRFS_UNAVAIL, None)
730 1c8addc6 Michael Hanselmann
731 1c8addc6 Michael Hanselmann
        self.assertEqual(row[fieldidx[field]], exp)
732 1c8addc6 Michael Hanselmann
733 1c8addc6 Michael Hanselmann
      bridges = inst_bridges.get(inst.name, [])
734 1c8addc6 Michael Hanselmann
      self.assertEqual(row[fieldidx["nic.bridges"]],
735 1c8addc6 Michael Hanselmann
                       (constants.QRFS_NORMAL, bridges))
736 1c8addc6 Michael Hanselmann
      if bridges:
737 1c8addc6 Michael Hanselmann
        self.assertEqual(row[fieldidx["bridge"]],
738 1c8addc6 Michael Hanselmann
                         (constants.QRFS_NORMAL, bridges[0]))
739 1c8addc6 Michael Hanselmann
      else:
740 1c8addc6 Michael Hanselmann
        self.assertEqual(row[fieldidx["bridge"]],
741 1c8addc6 Michael Hanselmann
                         (constants.QRFS_UNAVAIL, None))
742 1c8addc6 Michael Hanselmann
743 1c8addc6 Michael Hanselmann
      for i in range(constants.MAX_NICS):
744 1c8addc6 Michael Hanselmann
        if i < len(bridges) and bridges[i] is not None:
745 1c8addc6 Michael Hanselmann
          exp = (constants.QRFS_NORMAL, bridges[i])
746 1c8addc6 Michael Hanselmann
        else:
747 1c8addc6 Michael Hanselmann
          exp = (constants.QRFS_UNAVAIL, None)
748 1c8addc6 Michael Hanselmann
        self.assertEqual(row[fieldidx["nic.bridge/%s" % i]], exp)
749 1c8addc6 Michael Hanselmann
750 1c8addc6 Michael Hanselmann
      if inst.primary_node in bad_nodes:
751 1c8addc6 Michael Hanselmann
        exp = (constants.QRFS_NODATA, None)
752 1c8addc6 Michael Hanselmann
      else:
753 1c8addc6 Michael Hanselmann
        exp = (constants.QRFS_NORMAL, inst.name in live_data)
754 1c8addc6 Michael Hanselmann
      self.assertEqual(row[fieldidx["oper_state"]], exp)
755 1c8addc6 Michael Hanselmann
756 1c8addc6 Michael Hanselmann
      usage = disk_usage[inst.name]
757 1c8addc6 Michael Hanselmann
      if usage is None:
758 1c8addc6 Michael Hanselmann
        usage = 0
759 1c8addc6 Michael Hanselmann
      self.assertEqual(row[fieldidx["disk_usage"]],
760 1c8addc6 Michael Hanselmann
                       (constants.QRFS_NORMAL, usage))
761 1c8addc6 Michael Hanselmann
762 1c8addc6 Michael Hanselmann
      self.assertEqual(row[fieldidx["sda_size"]], row[fieldidx["disk.size/0"]])
763 1c8addc6 Michael Hanselmann
      self.assertEqual(row[fieldidx["sdb_size"]], row[fieldidx["disk.size/1"]])
764 1c8addc6 Michael Hanselmann
765 145bea54 Michael Hanselmann
      for field in ["ctime", "mtime"]:
766 145bea54 Michael Hanselmann
        if getattr(inst, field) is None:
767 145bea54 Michael Hanselmann
          # No ctime/mtime
768 145bea54 Michael Hanselmann
          exp = (constants.QRFS_UNAVAIL, None)
769 145bea54 Michael Hanselmann
        else:
770 145bea54 Michael Hanselmann
          exp = (constants.QRFS_NORMAL, getattr(inst, field))
771 145bea54 Michael Hanselmann
        self.assertEqual(row[fieldidx[field]], exp)
772 145bea54 Michael Hanselmann
773 1c8addc6 Michael Hanselmann
    # Ensure all possible status' have been tested
774 1c8addc6 Michael Hanselmann
    self.assertEqual(tested_status,
775 1c8addc6 Michael Hanselmann
                     set(["ERROR_nodeoffline", "ERROR_nodedown",
776 1c8addc6 Michael Hanselmann
                          "running", "ERROR_up", "ERROR_down",
777 1c8addc6 Michael Hanselmann
                          "ADMIN_down"]))
778 1c8addc6 Michael Hanselmann
779 1c8addc6 Michael Hanselmann
780 d8b7ff5f Adeodato Simo
class TestGroupQuery(unittest.TestCase):
781 d8b7ff5f Adeodato Simo
782 d8b7ff5f Adeodato Simo
  def setUp(self):
783 d8b7ff5f Adeodato Simo
    self.groups = [
784 d8b7ff5f Adeodato Simo
      objects.NodeGroup(name="default",
785 d8b7ff5f Adeodato Simo
                        uuid="c0e89160-18e7-11e0-a46e-001d0904baeb",
786 d8b7ff5f Adeodato Simo
                        alloc_policy=constants.ALLOC_POLICY_PREFERRED),
787 d8b7ff5f Adeodato Simo
      objects.NodeGroup(name="restricted",
788 d8b7ff5f Adeodato Simo
                        uuid="d2a40a74-18e7-11e0-9143-001d0904baeb",
789 d8b7ff5f Adeodato Simo
                        alloc_policy=constants.ALLOC_POLICY_LAST_RESORT),
790 d8b7ff5f Adeodato Simo
      ]
791 d8b7ff5f Adeodato Simo
792 d8b7ff5f Adeodato Simo
  def _Create(self, selected):
793 d8b7ff5f Adeodato Simo
    return query.Query(query.GROUP_FIELDS, selected)
794 d8b7ff5f Adeodato Simo
795 d8b7ff5f Adeodato Simo
  def testSimple(self):
796 d8b7ff5f Adeodato Simo
    q = self._Create(["name", "uuid", "alloc_policy"])
797 d8b7ff5f Adeodato Simo
    gqd = query.GroupQueryData(self.groups, None, None)
798 d8b7ff5f Adeodato Simo
799 d8b7ff5f Adeodato Simo
    self.assertEqual(q.RequestedData(), set([query.GQ_CONFIG]))
800 d8b7ff5f Adeodato Simo
801 d8b7ff5f Adeodato Simo
    self.assertEqual(q.Query(gqd),
802 d8b7ff5f Adeodato Simo
      [[(constants.QRFS_NORMAL, "default"),
803 d8b7ff5f Adeodato Simo
        (constants.QRFS_NORMAL, "c0e89160-18e7-11e0-a46e-001d0904baeb"),
804 d8b7ff5f Adeodato Simo
        (constants.QRFS_NORMAL, constants.ALLOC_POLICY_PREFERRED)
805 d8b7ff5f Adeodato Simo
        ],
806 d8b7ff5f Adeodato Simo
       [(constants.QRFS_NORMAL, "restricted"),
807 d8b7ff5f Adeodato Simo
        (constants.QRFS_NORMAL, "d2a40a74-18e7-11e0-9143-001d0904baeb"),
808 d8b7ff5f Adeodato Simo
        (constants.QRFS_NORMAL, constants.ALLOC_POLICY_LAST_RESORT)
809 d8b7ff5f Adeodato Simo
        ],
810 d8b7ff5f Adeodato Simo
       ])
811 d8b7ff5f Adeodato Simo
812 d8b7ff5f Adeodato Simo
  def testNodes(self):
813 d8b7ff5f Adeodato Simo
    groups_to_nodes = {
814 d8b7ff5f Adeodato Simo
      "c0e89160-18e7-11e0-a46e-001d0904baeb": ["node1", "node2"],
815 d8b7ff5f Adeodato Simo
      "d2a40a74-18e7-11e0-9143-001d0904baeb": ["node1", "node10", "node9"],
816 d8b7ff5f Adeodato Simo
      }
817 d8b7ff5f Adeodato Simo
818 d8b7ff5f Adeodato Simo
    q = self._Create(["name", "node_cnt", "node_list"])
819 d8b7ff5f Adeodato Simo
    gqd = query.GroupQueryData(self.groups, groups_to_nodes, None)
820 d8b7ff5f Adeodato Simo
821 d8b7ff5f Adeodato Simo
    self.assertEqual(q.RequestedData(), set([query.GQ_CONFIG, query.GQ_NODE]))
822 d8b7ff5f Adeodato Simo
823 d8b7ff5f Adeodato Simo
    self.assertEqual(q.Query(gqd),
824 d8b7ff5f Adeodato Simo
                     [[(constants.QRFS_NORMAL, "default"),
825 d8b7ff5f Adeodato Simo
                       (constants.QRFS_NORMAL, 2),
826 d8b7ff5f Adeodato Simo
                       (constants.QRFS_NORMAL, ["node1", "node2"]),
827 d8b7ff5f Adeodato Simo
                       ],
828 d8b7ff5f Adeodato Simo
                      [(constants.QRFS_NORMAL, "restricted"),
829 d8b7ff5f Adeodato Simo
                       (constants.QRFS_NORMAL, 3),
830 d8b7ff5f Adeodato Simo
                       (constants.QRFS_NORMAL, ["node1", "node9", "node10"]),
831 d8b7ff5f Adeodato Simo
                       ],
832 d8b7ff5f Adeodato Simo
                      ])
833 d8b7ff5f Adeodato Simo
834 d8b7ff5f Adeodato Simo
  def testInstances(self):
835 d8b7ff5f Adeodato Simo
    groups_to_instances = {
836 d8b7ff5f Adeodato Simo
      "c0e89160-18e7-11e0-a46e-001d0904baeb": ["inst1", "inst2"],
837 d8b7ff5f Adeodato Simo
      "d2a40a74-18e7-11e0-9143-001d0904baeb": ["inst1", "inst10", "inst9"],
838 d8b7ff5f Adeodato Simo
      }
839 d8b7ff5f Adeodato Simo
840 d8b7ff5f Adeodato Simo
    q = self._Create(["pinst_cnt", "pinst_list"])
841 d8b7ff5f Adeodato Simo
    gqd = query.GroupQueryData(self.groups, None, groups_to_instances)
842 d8b7ff5f Adeodato Simo
843 d8b7ff5f Adeodato Simo
    self.assertEqual(q.RequestedData(), set([query.GQ_INST]))
844 d8b7ff5f Adeodato Simo
845 d8b7ff5f Adeodato Simo
    self.assertEqual(q.Query(gqd),
846 d8b7ff5f Adeodato Simo
                     [[(constants.QRFS_NORMAL, 2),
847 d8b7ff5f Adeodato Simo
                       (constants.QRFS_NORMAL, ["inst1", "inst2"]),
848 d8b7ff5f Adeodato Simo
                       ],
849 d8b7ff5f Adeodato Simo
                      [(constants.QRFS_NORMAL, 3),
850 d8b7ff5f Adeodato Simo
                       (constants.QRFS_NORMAL, ["inst1", "inst9", "inst10"]),
851 d8b7ff5f Adeodato Simo
                       ],
852 d8b7ff5f Adeodato Simo
                      ])
853 d8b7ff5f Adeodato Simo
854 d8b7ff5f Adeodato Simo
855 aa29e95f Michael Hanselmann
class TestQueryFields(unittest.TestCase):
856 aa29e95f Michael Hanselmann
  def testAllFields(self):
857 e571ee44 Adeodato Simo
    for fielddefs in query.ALL_FIELD_LISTS:
858 aa29e95f Michael Hanselmann
      result = query.QueryFields(fielddefs, None)
859 aa29e95f Michael Hanselmann
      self.assert_(isinstance(result, dict))
860 aa29e95f Michael Hanselmann
      response = objects.QueryFieldsResponse.FromDict(result)
861 aa29e95f Michael Hanselmann
      self.assertEqual([(fdef.name, fdef.title) for fdef in response.fields],
862 aa29e95f Michael Hanselmann
        [(fdef2.name, fdef2.title)
863 aa29e95f Michael Hanselmann
         for (fdef2, _, _) in utils.NiceSort(fielddefs.values(),
864 aa29e95f Michael Hanselmann
                                             key=lambda x: x[0].name)])
865 aa29e95f Michael Hanselmann
866 aa29e95f Michael Hanselmann
  def testSomeFields(self):
867 aa29e95f Michael Hanselmann
    rnd = random.Random(5357)
868 aa29e95f Michael Hanselmann
869 aa29e95f Michael Hanselmann
    for _ in range(10):
870 e571ee44 Adeodato Simo
      for fielddefs in query.ALL_FIELD_LISTS:
871 e571ee44 Adeodato Simo
        if len(fielddefs) > 20:
872 e571ee44 Adeodato Simo
          sample_size = rnd.randint(5, 20)
873 e571ee44 Adeodato Simo
        else:
874 e571ee44 Adeodato Simo
          sample_size = rnd.randint(1, max(1, len(fielddefs) - 1))
875 e571ee44 Adeodato Simo
        fields = [fdef for (fdef, _, _) in rnd.sample(fielddefs.values(),
876 e571ee44 Adeodato Simo
                                                      sample_size)]
877 aa29e95f Michael Hanselmann
        result = query.QueryFields(fielddefs, [fdef.name for fdef in fields])
878 aa29e95f Michael Hanselmann
        self.assert_(isinstance(result, dict))
879 aa29e95f Michael Hanselmann
        response = objects.QueryFieldsResponse.FromDict(result)
880 aa29e95f Michael Hanselmann
        self.assertEqual([(fdef.name, fdef.title) for fdef in response.fields],
881 aa29e95f Michael Hanselmann
                         [(fdef2.name, fdef2.title) for fdef2 in fields])
882 aa29e95f Michael Hanselmann
883 aa29e95f Michael Hanselmann
884 4ca96421 Michael Hanselmann
if __name__ == "__main__":
885 4ca96421 Michael Hanselmann
  testutils.GanetiTestProgram()