-
René Nussbaumer authored
Signed-off-by:
René Nussbaumer <rn@google.com> Reviewed-by:
Iustin Pop <iustin@google.com> Reviewed-by:
Michael Hanselmann <hansmi@google.com>
8572f1fe
ganeti.query_unittest.py 33.25 KiB
#!/usr/bin/python
#
# Copyright (C) 2010 Google Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
"""Script for testing ganeti.query"""
import re
import unittest
import random
from ganeti import constants
from ganeti import utils
from ganeti import compat
from ganeti import errors
from ganeti import query
from ganeti import objects
from ganeti import cmdlib
import testutils
class TestConstants(unittest.TestCase):
def test(self):
self.assertEqual(set(query._VERIFY_FN.keys()),
constants.QFT_ALL)
class _QueryData:
def __init__(self, data, **kwargs):
self.data = data
for name, value in kwargs.items():
setattr(self, name, value)
def __iter__(self):
return iter(self.data)
def _GetDiskSize(nr, ctx, item):
disks = item["disks"]
try:
return (constants.QRFS_NORMAL, disks[nr])
except IndexError:
return (constants.QRFS_UNAVAIL, None)
class TestQuery(unittest.TestCase):
def test(self):
(STATIC, DISK) = range(10, 12)
fielddef = query._PrepareFieldList([
(query._MakeField("name", "Name", constants.QFT_TEXT),
STATIC, lambda ctx, item: (constants.QRFS_NORMAL, item["name"])),
(query._MakeField("master", "Master", constants.QFT_BOOL),
STATIC, lambda ctx, item: (constants.QRFS_NORMAL,
ctx.mastername == item["name"])),
] +
[(query._MakeField("disk%s.size" % i, "DiskSize%s" % i,
constants.QFT_UNIT),
DISK, compat.partial(_GetDiskSize, i))
for i in range(4)])
q = query.Query(fielddef, ["name"])
self.assertEqual(q.RequestedData(), set([STATIC]))
self.assertEqual(len(q._fields), 1)
self.assertEqual(len(q.GetFields()), 1)
self.assertEqual(q.GetFields()[0].ToDict(),
objects.QueryFieldDefinition(name="name",
title="Name",
kind=constants.QFT_TEXT).ToDict())
# Create data only once query has been prepared
data = [
{ "name": "node1", "disks": [0, 1, 2], },
{ "name": "node2", "disks": [3, 4], },
{ "name": "node3", "disks": [5, 6, 7], },
]
self.assertEqual(q.Query(_QueryData(data, mastername="node3")),
[[(constants.QRFS_NORMAL, "node1")],
[(constants.QRFS_NORMAL, "node2")],
[(constants.QRFS_NORMAL, "node3")]])
self.assertEqual(q.OldStyleQuery(_QueryData(data, mastername="node3")),
[["node1"], ["node2"], ["node3"]])
q = query.Query(fielddef, ["name", "master"])
self.assertEqual(q.RequestedData(), set([STATIC]))
self.assertEqual(len(q._fields), 2)
self.assertEqual(q.Query(_QueryData(data, mastername="node3")),
[[(constants.QRFS_NORMAL, "node1"),
(constants.QRFS_NORMAL, False)],
[(constants.QRFS_NORMAL, "node2"),
(constants.QRFS_NORMAL, False)],
[(constants.QRFS_NORMAL, "node3"),
(constants.QRFS_NORMAL, True)],
])
q = query.Query(fielddef, ["name", "master", "disk0.size"])
self.assertEqual(q.RequestedData(), set([STATIC, DISK]))
self.assertEqual(len(q._fields), 3)
self.assertEqual(q.Query(_QueryData(data, mastername="node2")),
[[(constants.QRFS_NORMAL, "node1"),
(constants.QRFS_NORMAL, False),
(constants.QRFS_NORMAL, 0)],
[(constants.QRFS_NORMAL, "node2"),
(constants.QRFS_NORMAL, True),
(constants.QRFS_NORMAL, 3)],
[(constants.QRFS_NORMAL, "node3"),
(constants.QRFS_NORMAL, False),
(constants.QRFS_NORMAL, 5)],
])
# With unknown column
q = query.Query(fielddef, ["disk2.size", "disk1.size", "disk99.size",
"disk0.size"])
self.assertEqual(q.RequestedData(), set([DISK]))
self.assertEqual(len(q._fields), 4)
self.assertEqual(q.Query(_QueryData(data, mastername="node2")),
[[(constants.QRFS_NORMAL, 2),
(constants.QRFS_NORMAL, 1),
(constants.QRFS_UNKNOWN, None),
(constants.QRFS_NORMAL, 0)],
[(constants.QRFS_UNAVAIL, None),
(constants.QRFS_NORMAL, 4),
(constants.QRFS_UNKNOWN, None),
(constants.QRFS_NORMAL, 3)],
[(constants.QRFS_NORMAL, 7),
(constants.QRFS_NORMAL, 6),
(constants.QRFS_UNKNOWN, None),
(constants.QRFS_NORMAL, 5)],
])
self.assertRaises(errors.OpPrereqError, q.OldStyleQuery,
_QueryData(data, mastername="node2"))
self.assertEqual([fdef.ToDict() for fdef in q.GetFields()], [
{ "name": "disk2.size", "title": "DiskSize2",
"kind": constants.QFT_UNIT, },
{ "name": "disk1.size", "title": "DiskSize1",
"kind": constants.QFT_UNIT, },
{ "name": "disk99.size", "title": "disk99.size",
"kind": constants.QFT_UNKNOWN, },
{ "name": "disk0.size", "title": "DiskSize0",
"kind": constants.QFT_UNIT, },
])
# Empty query
q = query.Query(fielddef, [])
self.assertEqual(q.RequestedData(), set([]))
self.assertEqual(len(q._fields), 0)
self.assertEqual(q.Query(_QueryData(data, mastername="node2")),
[[], [], []])
self.assertEqual(q.OldStyleQuery(_QueryData(data, mastername="node2")),
[[], [], []])
self.assertEqual(q.GetFields(), [])
def testPrepareFieldList(self):
# Duplicate titles
for (a, b) in [("name", "name"), ("NAME", "name")]:
self.assertRaises(AssertionError, query._PrepareFieldList, [
(query._MakeField("name", b, constants.QFT_TEXT), None,
lambda *args: None),
(query._MakeField("other", a, constants.QFT_TEXT), None,
lambda *args: None),
])
# Non-lowercase names
self.assertRaises(AssertionError, query._PrepareFieldList, [
(query._MakeField("NAME", "Name", constants.QFT_TEXT), None,
lambda *args: None),
])
self.assertRaises(AssertionError, query._PrepareFieldList, [
(query._MakeField("Name", "Name", constants.QFT_TEXT), None,
lambda *args: None),
])
# Empty name
self.assertRaises(AssertionError, query._PrepareFieldList, [
(query._MakeField("", "Name", constants.QFT_TEXT), None,
lambda *args: None),
])
# Empty title
self.assertRaises(AssertionError, query._PrepareFieldList, [
(query._MakeField("name", "", constants.QFT_TEXT), None,
lambda *args: None),
])
# Whitespace in title
self.assertRaises(AssertionError, query._PrepareFieldList, [
(query._MakeField("name", "Co lu mn", constants.QFT_TEXT), None,
lambda *args: None),
])
# No callable function
self.assertRaises(AssertionError, query._PrepareFieldList, [
(query._MakeField("name", "Name", constants.QFT_TEXT), None, None),
])
def testUnknown(self):
fielddef = query._PrepareFieldList([
(query._MakeField("name", "Name", constants.QFT_TEXT),
None, lambda _, item: (constants.QRFS_NORMAL, "name%s" % item)),
(query._MakeField("other0", "Other0", constants.QFT_TIMESTAMP),
None, lambda *args: (constants.QRFS_NORMAL, 1234)),
(query._MakeField("nodata", "NoData", constants.QFT_NUMBER),
None, lambda *args: (constants.QRFS_NODATA, None)),
(query._MakeField("unavail", "Unavail", constants.QFT_BOOL),
None, lambda *args: (constants.QRFS_UNAVAIL, None)),
])
for selected in [["foo"], ["Hello", "World"],
["name1", "other", "foo"]]:
q = query.Query(fielddef, selected)
self.assertEqual(len(q._fields), len(selected))
self.assert_(compat.all(len(row) == len(selected)
for row in q.Query(_QueryData(range(1, 10)))))
self.assertEqual(q.Query(_QueryData(range(1, 10))),
[[(constants.QRFS_UNKNOWN, None)] * len(selected)
for i in range(1, 10)])
self.assertEqual([fdef.ToDict() for fdef in q.GetFields()],
[{ "name": name, "title": name,
"kind": constants.QFT_UNKNOWN, }
for name in selected])
q = query.Query(fielddef, ["name", "other0", "nodata", "unavail"])
self.assertEqual(len(q._fields), 4)
self.assertEqual(q.OldStyleQuery(_QueryData(range(1, 10))), [
["name%s" % i, 1234, None, None]
for i in range(1, 10)
])
q = query.Query(fielddef, ["name", "other0", "nodata", "unavail", "unk"])
self.assertEqual(len(q._fields), 5)
self.assertEqual(q.Query(_QueryData(range(1, 10))),
[[(constants.QRFS_NORMAL, "name%s" % i),
(constants.QRFS_NORMAL, 1234),
(constants.QRFS_NODATA, None),
(constants.QRFS_UNAVAIL, None),
(constants.QRFS_UNKNOWN, None)]
for i in range(1, 10)])
class TestGetNodeRole(unittest.TestCase):
def testMaster(self):
node = objects.Node(name="node1")
self.assertEqual(query._GetNodeRole(node, "node1"), "M")
def testMasterCandidate(self):
node = objects.Node(name="node1", master_candidate=True)
self.assertEqual(query._GetNodeRole(node, "master"), "C")
def testRegular(self):
node = objects.Node(name="node1")
self.assertEqual(query._GetNodeRole(node, "master"), "R")
def testDrained(self):
node = objects.Node(name="node1", drained=True)
self.assertEqual(query._GetNodeRole(node, "master"), "D")
def testOffline(self):
node = objects.Node(name="node1", offline=True)
self.assertEqual(query._GetNodeRole(node, "master"), "O")
class TestNodeQuery(unittest.TestCase):
def _Create(self, selected):
return query.Query(query.NODE_FIELDS, selected)
def testSimple(self):
nodes = [
objects.Node(name="node1", drained=False),
objects.Node(name="node2", drained=True),
objects.Node(name="node3", drained=False),
]
for live_data in [None, dict.fromkeys([node.name for node in nodes], {})]:
nqd = query.NodeQueryData(nodes, live_data, None, None, None, None, None,
None)
q = self._Create(["name", "drained"])
self.assertEqual(q.RequestedData(), set([query.NQ_CONFIG]))
self.assertEqual(q.Query(nqd),
[[(constants.QRFS_NORMAL, "node1"),
(constants.QRFS_NORMAL, False)],
[(constants.QRFS_NORMAL, "node2"),
(constants.QRFS_NORMAL, True)],
[(constants.QRFS_NORMAL, "node3"),
(constants.QRFS_NORMAL, False)],
])
self.assertEqual(q.OldStyleQuery(nqd),
[["node1", False],
["node2", True],
["node3", False]])
def test(self):
selected = query.NODE_FIELDS.keys()
field_index = dict((field, idx) for idx, field in enumerate(selected))
q = self._Create(selected)
self.assertEqual(q.RequestedData(),
set([query.NQ_CONFIG, query.NQ_LIVE, query.NQ_INST,
query.NQ_GROUP, query.NQ_OOB]))
cluster = objects.Cluster(cluster_name="testcluster",
hvparams=constants.HVC_DEFAULTS,
beparams={
constants.PP_DEFAULT: constants.BEC_DEFAULTS,
},
nicparams={
constants.PP_DEFAULT: constants.NICC_DEFAULTS,
},
ndparams=constants.NDC_DEFAULTS,
)
node_names = ["node%s" % i for i in range(20)]
master_name = node_names[3]
nodes = [
objects.Node(name=name,
primary_ip="192.0.2.%s" % idx,
secondary_ip="192.0.100.%s" % idx,
serial_no=7789 * idx,
master_candidate=(name != master_name and idx % 3 == 0),
offline=False,
drained=False,
vm_capable=False,
master_capable=False,
ndparams={},
group="default",
ctime=1290006900,
mtime=1290006913,
uuid="fd9ccebe-6339-43c9-a82e-94bbe575%04d" % idx)
for idx, name in enumerate(node_names)
]
master_node = nodes[3]
master_node.AddTag("masternode")
master_node.AddTag("another")
master_node.AddTag("tag")
master_node.ctime = None
master_node.mtime = None
assert master_node.name == master_name
live_data_name = node_names[4]
assert live_data_name != master_name
fake_live_data = {
"bootid": "a2504766-498e-4b25-b21e-d23098dc3af4",
"cnodes": 4,
"csockets": 4,
"ctotal": 8,
"mnode": 128,
"mfree": 100,
"mtotal": 4096,
"dfree": 5 * 1024 * 1024,
"dtotal": 100 * 1024 * 1024,
}
assert (sorted(query._NODE_LIVE_FIELDS.keys()) ==
sorted(fake_live_data.keys()))
live_data = dict.fromkeys(node_names, {})
live_data[live_data_name] = \
dict((query._NODE_LIVE_FIELDS[name][2], value)
for name, value in fake_live_data.items())
node_to_primary = dict((name, set()) for name in node_names)
node_to_primary[master_name].update(["inst1", "inst2"])
node_to_secondary = dict((name, set()) for name in node_names)
node_to_secondary[live_data_name].update(["instX", "instY", "instZ"])
ng_uuid = "492b4b74-8670-478a-b98d-4c53a76238e6"
groups = {
ng_uuid: objects.NodeGroup(name="ng1", uuid=ng_uuid, ndparams={}),
}
oob_support = dict((name, False) for name in node_names)
master_node.group = ng_uuid
nqd = query.NodeQueryData(nodes, live_data, master_name,
node_to_primary, node_to_secondary, groups,
oob_support, cluster)
result = q.Query(nqd)
self.assert_(compat.all(len(row) == len(selected) for row in result))
self.assertEqual([row[field_index["name"]] for row in result],
[(constants.QRFS_NORMAL, name) for name in node_names])
node_to_row = dict((row[field_index["name"]][1], idx)
for idx, row in enumerate(result))
master_row = result[node_to_row[master_name]]
self.assert_(master_row[field_index["master"]])
self.assert_(master_row[field_index["role"]], "M")
self.assertEqual(master_row[field_index["group"]],
(constants.QRFS_NORMAL, "ng1"))
self.assertEqual(master_row[field_index["group.uuid"]],
(constants.QRFS_NORMAL, ng_uuid))
self.assertEqual(master_row[field_index["ctime"]],
(constants.QRFS_UNAVAIL, None))
self.assertEqual(master_row[field_index["mtime"]],
(constants.QRFS_UNAVAIL, None))
self.assert_(row[field_index["pip"]] == node.primary_ip and
row[field_index["sip"]] == node.secondary_ip and
set(row[field_index["tags"]]) == node.GetTags() and
row[field_index["serial_no"]] == node.serial_no and
row[field_index["role"]] == query._GetNodeRole(node,
master_name) and
(node.name == master_name or
(row[field_index["group"]] == "<unknown>" and
row[field_index["group.uuid"]] is None and
row[field_index["ctime"]] == (constants.QRFS_NORMAL,
node.ctime) and
row[field_index["mtime"]] == (constants.QRFS_NORMAL,
node.mtime)))
for row, node in zip(result, nodes))
live_data_row = result[node_to_row[live_data_name]]
for (field, value) in fake_live_data.items():
self.assertEqual(live_data_row[field_index[field]],
(constants.QRFS_NORMAL, value))
self.assertEqual(master_row[field_index["pinst_cnt"]],
(constants.QRFS_NORMAL, 2))
self.assertEqual(live_data_row[field_index["sinst_cnt"]],
(constants.QRFS_NORMAL, 3))
self.assertEqual(master_row[field_index["pinst_list"]],
(constants.QRFS_NORMAL,
list(node_to_primary[master_name])))
self.assertEqual(live_data_row[field_index["sinst_list"]],
(constants.QRFS_NORMAL,
list(node_to_secondary[live_data_name])))
def testGetLiveNodeField(self):
nodes = [
objects.Node(name="node1", drained=False, offline=False),
objects.Node(name="node2", drained=True, offline=False),
objects.Node(name="node3", drained=False, offline=False),
objects.Node(name="node4", drained=False, offline=True),
]
live_data = dict.fromkeys([node.name for node in nodes], {})
# No data
nqd = query.NodeQueryData(None, None, None, None, None, None, None, None)
self.assertEqual(query._GetLiveNodeField("hello", constants.QFT_NUMBER,
nqd, nodes[0]),
(constants.QRFS_NODATA, None))
# Missing field
ctx = _QueryData(None, curlive_data={
"some": 1,
"other": 2,
})
self.assertEqual(query._GetLiveNodeField("hello", constants.QFT_NUMBER,
ctx, nodes[0]),
(constants.QRFS_UNAVAIL, None))
# Wrong format/datatype
ctx = _QueryData(None, curlive_data={
"hello": ["Hello World"],
"other": 2,
})
self.assertEqual(query._GetLiveNodeField("hello", constants.QFT_NUMBER,
ctx, nodes[0]),
(constants.QRFS_UNAVAIL, None))
# Offline node
assert nodes[3].offline
ctx = _QueryData(None, curlive_data={})
self.assertEqual(query._GetLiveNodeField("hello", constants.QFT_NUMBER,
ctx, nodes[3]),
(constants.QRFS_OFFLINE, None))
# Wrong field type
ctx = _QueryData(None, curlive_data={"hello": 123})
self.assertRaises(AssertionError, query._GetLiveNodeField,
"hello", constants.QFT_BOOL, ctx, nodes[0])
class TestInstanceQuery(unittest.TestCase):
def _Create(self, selected):
return query.Query(query.INSTANCE_FIELDS, selected)
def testSimple(self):
q = self._Create(["name", "be/memory", "ip"])
self.assertEqual(q.RequestedData(), set([query.IQ_CONFIG]))
cluster = objects.Cluster(cluster_name="testcluster",
hvparams=constants.HVC_DEFAULTS,
beparams={
constants.PP_DEFAULT: constants.BEC_DEFAULTS,
},
nicparams={
constants.PP_DEFAULT: constants.NICC_DEFAULTS,
})
instances = [
objects.Instance(name="inst1", hvparams={}, beparams={}, nics=[]),
objects.Instance(name="inst2", hvparams={}, nics=[],
beparams={
constants.BE_MEMORY: 512,
}),
objects.Instance(name="inst3", hvparams={}, beparams={},
nics=[objects.NIC(ip="192.0.2.99", nicparams={})]),
]
iqd = query.InstanceQueryData(instances, cluster, None, [], [], {})
self.assertEqual(q.Query(iqd),
[[(constants.QRFS_NORMAL, "inst1"),
(constants.QRFS_NORMAL, 128),
(constants.QRFS_UNAVAIL, None),
],
[(constants.QRFS_NORMAL, "inst2"),
(constants.QRFS_NORMAL, 512),
(constants.QRFS_UNAVAIL, None),
],
[(constants.QRFS_NORMAL, "inst3"),
(constants.QRFS_NORMAL, 128),
(constants.QRFS_NORMAL, "192.0.2.99"),
]])
self.assertEqual(q.OldStyleQuery(iqd),
[["inst1", 128, None],
["inst2", 512, None],
["inst3", 128, "192.0.2.99"]])
def test(self):
selected = query.INSTANCE_FIELDS.keys()
fieldidx = dict((field, idx) for idx, field in enumerate(selected))
macs = ["00:11:22:%02x:%02x:%02x" % (i % 255, i % 3, (i * 123) % 255)
for i in range(20)]
q = self._Create(selected)
self.assertEqual(q.RequestedData(),
set([query.IQ_CONFIG, query.IQ_LIVE, query.IQ_DISKUSAGE]))
cluster = objects.Cluster(cluster_name="testcluster",
hvparams=constants.HVC_DEFAULTS,
beparams={
constants.PP_DEFAULT: constants.BEC_DEFAULTS,
},
nicparams={
constants.PP_DEFAULT: constants.NICC_DEFAULTS,
},
os_hvp={},
tcpudp_port_pool=set())
offline_nodes = ["nodeoff1", "nodeoff2"]
bad_nodes = ["nodebad1", "nodebad2", "nodebad3"] + offline_nodes
nodes = ["node%s" % i for i in range(10)] + bad_nodes
instances = [
objects.Instance(name="inst1", hvparams={}, beparams={}, nics=[],
uuid="f90eccb3-e227-4e3c-bf2a-94a21ca8f9cd",
ctime=1291244000, mtime=1291244400, serial_no=30,
admin_up=True, hypervisor=constants.HT_XEN_PVM, os="linux1",
primary_node="node1",
disk_template=constants.DT_PLAIN,
disks=[]),
objects.Instance(name="inst2", hvparams={}, nics=[],
uuid="73a0f8a7-068c-4630-ada2-c3440015ab1a",
ctime=1291211000, mtime=1291211077, serial_no=1,
admin_up=True, hypervisor=constants.HT_XEN_HVM, os="deb99",
primary_node="node5",
disk_template=constants.DT_DISKLESS,
disks=[],
beparams={
constants.BE_MEMORY: 512,
}),
objects.Instance(name="inst3", hvparams={}, beparams={},
uuid="11ec8dff-fb61-4850-bfe0-baa1803ff280",
ctime=1291011000, mtime=1291013000, serial_no=1923,
admin_up=False, hypervisor=constants.HT_KVM, os="busybox",
primary_node="node6",
disk_template=constants.DT_DRBD8,
disks=[],
nics=[
objects.NIC(ip="192.0.2.99", mac=macs.pop(),
nicparams={
constants.NIC_LINK: constants.DEFAULT_BRIDGE,
}),
objects.NIC(ip=None, mac=macs.pop(), nicparams={}),
]),
objects.Instance(name="inst4", hvparams={}, beparams={},
uuid="68dab168-3ef5-4c9d-b4d3-801e0672068c",
ctime=1291244390, mtime=1291244395, serial_no=25,
admin_up=False, hypervisor=constants.HT_XEN_PVM, os="linux1",
primary_node="nodeoff2",
disk_template=constants.DT_DRBD8,
disks=[],
nics=[
objects.NIC(ip="192.0.2.1", mac=macs.pop(),
nicparams={
constants.NIC_LINK: constants.DEFAULT_BRIDGE,
}),
objects.NIC(ip="192.0.2.2", mac=macs.pop(), nicparams={}),
objects.NIC(ip="192.0.2.3", mac=macs.pop(),
nicparams={
constants.NIC_MODE: constants.NIC_MODE_ROUTED,
}),
objects.NIC(ip="192.0.2.4", mac=macs.pop(),
nicparams={
constants.NIC_MODE: constants.NIC_MODE_BRIDGED,
constants.NIC_LINK: "eth123",
}),
]),
objects.Instance(name="inst5", hvparams={}, nics=[],
uuid="0e3dca12-5b42-4e24-98a2-415267545bd0",
ctime=1231211000, mtime=1261200000, serial_no=3,
admin_up=True, hypervisor=constants.HT_XEN_HVM, os="deb99",
primary_node="nodebad2",
disk_template=constants.DT_DISKLESS,
disks=[],
beparams={
constants.BE_MEMORY: 512,
}),
objects.Instance(name="inst6", hvparams={}, nics=[],
uuid="72de6580-c8d5-4661-b902-38b5785bb8b3",
ctime=7513, mtime=11501, serial_no=13390,
admin_up=False, hypervisor=constants.HT_XEN_HVM, os="deb99",
primary_node="node7",
disk_template=constants.DT_DISKLESS,
disks=[],
beparams={
constants.BE_MEMORY: 768,
}),
objects.Instance(name="inst7", hvparams={}, nics=[],
uuid="ceec5dc4-b729-4f42-ae28-69b3cd24920e",
ctime=None, mtime=None, serial_no=1947,
admin_up=False, hypervisor=constants.HT_XEN_HVM, os="deb99",
primary_node="node6",
disk_template=constants.DT_DISKLESS,
disks=[],
beparams={}),
]
assert not utils.FindDuplicates(inst.name for inst in instances)
disk_usage = dict((inst.name,
cmdlib._ComputeDiskSize(inst.disk_template,
[{"size": disk.size}
for disk in inst.disks]))
for inst in instances)
inst_bridges = {
"inst3": [constants.DEFAULT_BRIDGE, constants.DEFAULT_BRIDGE],
"inst4": [constants.DEFAULT_BRIDGE, constants.DEFAULT_BRIDGE,
None, "eth123"],
}
live_data = {
"inst2": {
"vcpus": 3,
},
"inst4": {
"memory": 123,
},
"inst6": {
"memory": 768,
},
}
iqd = query.InstanceQueryData(instances, cluster, disk_usage,
offline_nodes, bad_nodes, live_data)
result = q.Query(iqd)
self.assertEqual(len(result), len(instances))
self.assert_(compat.all(len(row) == len(selected)
for row in result))
assert len(set(bad_nodes) & set(offline_nodes)) == len(offline_nodes), \
"Offline nodes not included in bad nodes"
tested_status = set()
for (inst, row) in zip(instances, result):
assert inst.primary_node in nodes
self.assertEqual(row[fieldidx["name"]],
(constants.QRFS_NORMAL, inst.name))
if inst.primary_node in offline_nodes:
exp_status = "ERROR_nodeoffline"
elif inst.primary_node in bad_nodes:
exp_status = "ERROR_nodedown"
elif inst.name in live_data:
if inst.admin_up:
exp_status = "running"
else:
exp_status = "ERROR_up"
elif inst.admin_up:
exp_status = "ERROR_down"
else:
exp_status = "ADMIN_down"
self.assertEqual(row[fieldidx["status"]],
(constants.QRFS_NORMAL, exp_status))
(_, status) = row[fieldidx["status"]]
tested_status.add(status)
for (field, livefield) in [("oper_ram", "memory"),
("oper_vcpus", "vcpus")]:
if inst.primary_node in bad_nodes:
exp = (constants.QRFS_NODATA, None)
elif inst.name in live_data:
value = live_data[inst.name].get(livefield, None)
if value is None:
exp = (constants.QRFS_UNAVAIL, None)
else:
exp = (constants.QRFS_NORMAL, value)
else:
exp = (constants.QRFS_UNAVAIL, None)
self.assertEqual(row[fieldidx[field]], exp)
bridges = inst_bridges.get(inst.name, [])
self.assertEqual(row[fieldidx["nic.bridges"]],
(constants.QRFS_NORMAL, bridges))
if bridges:
self.assertEqual(row[fieldidx["bridge"]],
(constants.QRFS_NORMAL, bridges[0]))
else:
self.assertEqual(row[fieldidx["bridge"]],
(constants.QRFS_UNAVAIL, None))
for i in range(constants.MAX_NICS):
if i < len(bridges) and bridges[i] is not None:
exp = (constants.QRFS_NORMAL, bridges[i])
else:
exp = (constants.QRFS_UNAVAIL, None)
self.assertEqual(row[fieldidx["nic.bridge/%s" % i]], exp)
if inst.primary_node in bad_nodes:
exp = (constants.QRFS_NODATA, None)
else:
exp = (constants.QRFS_NORMAL, inst.name in live_data)
self.assertEqual(row[fieldidx["oper_state"]], exp)
usage = disk_usage[inst.name]
if usage is None:
usage = 0
self.assertEqual(row[fieldidx["disk_usage"]],
(constants.QRFS_NORMAL, usage))
self.assertEqual(row[fieldidx["sda_size"]], row[fieldidx["disk.size/0"]])
self.assertEqual(row[fieldidx["sdb_size"]], row[fieldidx["disk.size/1"]])
for field in ["ctime", "mtime"]:
if getattr(inst, field) is None:
# No ctime/mtime
exp = (constants.QRFS_UNAVAIL, None)
else:
exp = (constants.QRFS_NORMAL, getattr(inst, field))
self.assertEqual(row[fieldidx[field]], exp)
# Ensure all possible status' have been tested
self.assertEqual(tested_status,
set(["ERROR_nodeoffline", "ERROR_nodedown",
"running", "ERROR_up", "ERROR_down",
"ADMIN_down"]))
class TestGroupQuery(unittest.TestCase):
def setUp(self):
self.groups = [
objects.NodeGroup(name="default",
uuid="c0e89160-18e7-11e0-a46e-001d0904baeb",
alloc_policy=constants.ALLOC_POLICY_PREFERRED),
objects.NodeGroup(name="restricted",
uuid="d2a40a74-18e7-11e0-9143-001d0904baeb",
alloc_policy=constants.ALLOC_POLICY_LAST_RESORT),
]
def _Create(self, selected):
return query.Query(query.GROUP_FIELDS, selected)
def testSimple(self):
q = self._Create(["name", "uuid", "alloc_policy"])
gqd = query.GroupQueryData(self.groups, None, None)
self.assertEqual(q.RequestedData(), set([query.GQ_CONFIG]))
self.assertEqual(q.Query(gqd),
[[(constants.QRFS_NORMAL, "default"),
(constants.QRFS_NORMAL, "c0e89160-18e7-11e0-a46e-001d0904baeb"),
(constants.QRFS_NORMAL, constants.ALLOC_POLICY_PREFERRED)
],
[(constants.QRFS_NORMAL, "restricted"),
(constants.QRFS_NORMAL, "d2a40a74-18e7-11e0-9143-001d0904baeb"),
(constants.QRFS_NORMAL, constants.ALLOC_POLICY_LAST_RESORT)
],
])
def testNodes(self):
groups_to_nodes = {
"c0e89160-18e7-11e0-a46e-001d0904baeb": ["node1", "node2"],
"d2a40a74-18e7-11e0-9143-001d0904baeb": ["node1", "node10", "node9"],
}
q = self._Create(["name", "node_cnt", "node_list"])
gqd = query.GroupQueryData(self.groups, groups_to_nodes, None)
self.assertEqual(q.RequestedData(), set([query.GQ_CONFIG, query.GQ_NODE]))
self.assertEqual(q.Query(gqd),
[[(constants.QRFS_NORMAL, "default"),
(constants.QRFS_NORMAL, 2),
(constants.QRFS_NORMAL, ["node1", "node2"]),
],
[(constants.QRFS_NORMAL, "restricted"),
(constants.QRFS_NORMAL, 3),
(constants.QRFS_NORMAL, ["node1", "node9", "node10"]),
],
])
def testInstances(self):
groups_to_instances = {
"c0e89160-18e7-11e0-a46e-001d0904baeb": ["inst1", "inst2"],
"d2a40a74-18e7-11e0-9143-001d0904baeb": ["inst1", "inst10", "inst9"],
}
q = self._Create(["pinst_cnt", "pinst_list"])
gqd = query.GroupQueryData(self.groups, None, groups_to_instances)
self.assertEqual(q.RequestedData(), set([query.GQ_INST]))
self.assertEqual(q.Query(gqd),
[[(constants.QRFS_NORMAL, 2),
(constants.QRFS_NORMAL, ["inst1", "inst2"]),
],
[(constants.QRFS_NORMAL, 3),
(constants.QRFS_NORMAL, ["inst1", "inst9", "inst10"]),
],
])
class TestQueryFields(unittest.TestCase):
def testAllFields(self):
for fielddefs in query.ALL_FIELD_LISTS:
result = query.QueryFields(fielddefs, None)
self.assert_(isinstance(result, dict))
response = objects.QueryFieldsResponse.FromDict(result)
self.assertEqual([(fdef.name, fdef.title) for fdef in response.fields],
[(fdef2.name, fdef2.title)
for (fdef2, _, _) in utils.NiceSort(fielddefs.values(),
key=lambda x: x[0].name)])
def testSomeFields(self):
rnd = random.Random(5357)
for _ in range(10):
for fielddefs in query.ALL_FIELD_LISTS:
if len(fielddefs) > 20:
sample_size = rnd.randint(5, 20)
else:
sample_size = rnd.randint(1, max(1, len(fielddefs) - 1))
fields = [fdef for (fdef, _, _) in rnd.sample(fielddefs.values(),
sample_size)]
result = query.QueryFields(fielddefs, [fdef.name for fdef in fields])
self.assert_(isinstance(result, dict))
response = objects.QueryFieldsResponse.FromDict(result)
self.assertEqual([(fdef.name, fdef.title) for fdef in response.fields],
[(fdef2.name, fdef2.title) for fdef2 in fields])
if __name__ == "__main__":
testutils.GanetiTestProgram()