#!/usr/bin/python
#
-# Copyright (C) 2010, 2011 Google Inc.
+# Copyright (C) 2010, 2011, 2012 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
from ganeti import objects
from ganeti import cmdlib
+import ganeti.masterd.instance as gmi
+
import testutils
(STATIC, DISK) = range(10, 12)
fielddef = query._PrepareFieldList([
- (query._MakeField("name", "Name", constants.QFT_TEXT),
- STATIC, lambda ctx, item: item["name"]),
- (query._MakeField("master", "Master", constants.QFT_BOOL),
- STATIC, lambda ctx, item: ctx.mastername == item["name"]),
+ (query._MakeField("name", "Name", constants.QFT_TEXT, "Name"),
+ STATIC, 0, lambda ctx, item: item["name"]),
+ (query._MakeField("master", "Master", constants.QFT_BOOL, "Master"),
+ STATIC, 0, lambda ctx, item: ctx.mastername == item["name"]),
] +
[(query._MakeField("disk%s.size" % i, "DiskSize%s" % i,
- constants.QFT_UNIT),
- DISK, compat.partial(_GetDiskSize, i))
+ constants.QFT_UNIT, "Disk size %s" % i),
+ DISK, 0, compat.partial(_GetDiskSize, i))
for i in range(4)], [])
q = query.Query(fielddef, ["name"])
self.assertEqual(q.GetFields()[0].ToDict(),
objects.QueryFieldDefinition(name="name",
title="Name",
- kind=constants.QFT_TEXT).ToDict())
+ kind=constants.QFT_TEXT,
+ doc="Name").ToDict())
# Create data only once query has been prepared
data = [
_QueryData(data, mastername="node2"))
self.assertEqual([fdef.ToDict() for fdef in q.GetFields()], [
{ "name": "disk2.size", "title": "DiskSize2",
- "kind": constants.QFT_UNIT, },
+ "kind": constants.QFT_UNIT, "doc": "Disk size 2", },
{ "name": "disk1.size", "title": "DiskSize1",
- "kind": constants.QFT_UNIT, },
+ "kind": constants.QFT_UNIT, "doc": "Disk size 1", },
{ "name": "disk99.size", "title": "disk99.size",
- "kind": constants.QFT_UNKNOWN, },
+ "kind": constants.QFT_UNKNOWN,
+ "doc": "Unknown field 'disk99.size'", },
{ "name": "disk0.size", "title": "DiskSize0",
- "kind": constants.QFT_UNIT, },
+ "kind": constants.QFT_UNIT, "doc": "Disk size 0", },
])
# Empty query
# Duplicate titles
for (a, b) in [("name", "name"), ("NAME", "name")]:
self.assertRaises(AssertionError, query._PrepareFieldList, [
- (query._MakeField("name", b, constants.QFT_TEXT), None,
+ (query._MakeField("name", b, constants.QFT_TEXT, "Name"), None, 0,
lambda *args: None),
- (query._MakeField("other", a, constants.QFT_TEXT), None,
+ (query._MakeField("other", a, constants.QFT_TEXT, "Other"), None, 0,
lambda *args: None),
], [])
# Non-lowercase names
self.assertRaises(AssertionError, query._PrepareFieldList, [
- (query._MakeField("NAME", "Name", constants.QFT_TEXT), None,
+ (query._MakeField("NAME", "Name", constants.QFT_TEXT, "Name"), None, 0,
lambda *args: None),
], [])
self.assertRaises(AssertionError, query._PrepareFieldList, [
- (query._MakeField("Name", "Name", constants.QFT_TEXT), None,
+ (query._MakeField("Name", "Name", constants.QFT_TEXT, "Name"), None, 0,
lambda *args: None),
], [])
# Empty name
self.assertRaises(AssertionError, query._PrepareFieldList, [
- (query._MakeField("", "Name", constants.QFT_TEXT), None,
+ (query._MakeField("", "Name", constants.QFT_TEXT, "Name"), None, 0,
lambda *args: None),
], [])
# Empty title
self.assertRaises(AssertionError, query._PrepareFieldList, [
- (query._MakeField("name", "", constants.QFT_TEXT), None,
+ (query._MakeField("name", "", constants.QFT_TEXT, "Name"), None, 0,
lambda *args: None),
], [])
# Whitespace in title
self.assertRaises(AssertionError, query._PrepareFieldList, [
- (query._MakeField("name", "Co lu mn", constants.QFT_TEXT), None,
- lambda *args: None),
+ (query._MakeField("name", "Co lu mn", constants.QFT_TEXT, "Name"),
+ None, 0, lambda *args: None),
], [])
# No callable function
self.assertRaises(AssertionError, query._PrepareFieldList, [
- (query._MakeField("name", "Name", constants.QFT_TEXT), None, None),
+ (query._MakeField("name", "Name", constants.QFT_TEXT, "Name"),
+ None, 0, None),
+ ], [])
+
+ # Invalid documentation
+ for doc in ["", ".", "Hello world\n", "Hello\nWo\nrld", "Hello World!",
+ "HelloWorld.", "only lowercase", ",", " x y z .\t", " "]:
+ self.assertRaises(AssertionError, query._PrepareFieldList, [
+ (query._MakeField("name", "Name", constants.QFT_TEXT, doc),
+ None, 0, lambda *args: None),
+ ], [])
+
+ # Duplicate field name
+ self.assertRaises(ValueError, query._PrepareFieldList, [
+ (query._MakeField("name", "Name", constants.QFT_TEXT, "Name"),
+ None, 0, lambda *args: None),
+ (query._MakeField("name", "Other", constants.QFT_OTHER, "Other"),
+ None, 0, lambda *args: None),
], [])
def testUnknown(self):
fielddef = query._PrepareFieldList([
- (query._MakeField("name", "Name", constants.QFT_TEXT),
- None, lambda _, item: "name%s" % item),
- (query._MakeField("other0", "Other0", constants.QFT_TIMESTAMP),
- None, lambda *args: 1234),
- (query._MakeField("nodata", "NoData", constants.QFT_NUMBER),
- None, lambda *args: query._FS_NODATA ),
- (query._MakeField("unavail", "Unavail", constants.QFT_BOOL),
- None, lambda *args: query._FS_UNAVAIL),
+ (query._MakeField("name", "Name", constants.QFT_TEXT, "Name"),
+ None, 0, lambda _, item: "name%s" % item),
+ (query._MakeField("other0", "Other0", constants.QFT_TIMESTAMP, "Other"),
+ None, 0, lambda *args: 1234),
+ (query._MakeField("nodata", "NoData", constants.QFT_NUMBER, "No data"),
+ None, 0, lambda *args: query._FS_NODATA ),
+ (query._MakeField("unavail", "Unavail", constants.QFT_BOOL, "Unavail"),
+ None, 0, lambda *args: query._FS_UNAVAIL),
], [])
for selected in [["foo"], ["Hello", "World"],
for i in range(1, 10)])
self.assertEqual([fdef.ToDict() for fdef in q.GetFields()],
[{ "name": name, "title": name,
- "kind": constants.QFT_UNKNOWN, }
+ "kind": constants.QFT_UNKNOWN,
+ "doc": "Unknown field '%s'" % name}
for name in selected])
q = query.Query(fielddef, ["name", "other0", "nodata", "unavail"])
def testAliases(self):
fields = [
- (query._MakeField("a", "a-title", constants.QFT_TEXT), None,
- lambda *args: None),
- (query._MakeField("b", "b-title", constants.QFT_TEXT), None,
- lambda *args: None),
+ (query._MakeField("a", "a-title", constants.QFT_TEXT, "Field A"),
+ None, 0, lambda *args: None),
+ (query._MakeField("b", "b-title", constants.QFT_TEXT, "Field B"),
+ None, 0, lambda *args: None),
]
# duplicate field
self.assertRaises(AssertionError, query._PrepareFieldList, fields,
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 test(self):
+ tested_role = set()
+
+ checks = [
+ (constants.NR_MASTER, "node1", objects.Node(name="node1")),
+ (constants.NR_MCANDIDATE, "master",
+ objects.Node(name="node1", master_candidate=True)),
+ (constants.NR_REGULAR, "master", objects.Node(name="node1")),
+ (constants.NR_DRAINED, "master",
+ objects.Node(name="node1", drained=True)),
+ (constants.NR_OFFLINE,
+ "master", objects.Node(name="node1", offline=True)),
+ ]
- def testDrained(self):
- node = objects.Node(name="node1", drained=True)
- self.assertEqual(query._GetNodeRole(node, "master"), "D")
+ for (role, master_name, node) in checks:
+ result = query._GetNodeRole(node, master_name)
+ self.assertEqual(result, role)
+ tested_role.add(result)
- def testOffline(self):
- node = objects.Node(name="node1", offline=True)
- self.assertEqual(query._GetNodeRole(node, "master"), "O")
+ self.assertEqual(tested_role, constants.NR_ALL)
class TestNodeQuery(unittest.TestCase):
return query.Query(query.NODE_FIELDS, selected)
def testSimple(self):
+ cluster = objects.Cluster(cluster_name="testcluster",
+ ndparams=constants.NDC_DEFAULTS.copy())
+ grp1 = objects.NodeGroup(name="default",
+ uuid="c0e89160-18e7-11e0-a46e-001d0904baeb",
+ alloc_policy=constants.ALLOC_POLICY_PREFERRED,
+ ipolicy=objects.MakeEmptyIPolicy(),
+ ndparams={},
+ )
+ grp2 = objects.NodeGroup(name="group2",
+ uuid="c0e89160-18e7-11e0-a46e-001d0904babe",
+ alloc_policy=constants.ALLOC_POLICY_PREFERRED,
+ ipolicy=objects.MakeEmptyIPolicy(),
+ ndparams={constants.ND_SPINDLE_COUNT: 2},
+ )
+ groups = {grp1.uuid: grp1, grp2.uuid: grp2}
nodes = [
- objects.Node(name="node1", drained=False),
- objects.Node(name="node2", drained=True),
- objects.Node(name="node3", drained=False),
+ objects.Node(name="node1", drained=False, group=grp1.uuid, ndparams={}),
+ objects.Node(name="node2", drained=True, group=grp2.uuid, ndparams={}),
+ objects.Node(name="node3", drained=False, group=grp1.uuid,
+ ndparams={constants.ND_SPINDLE_COUNT: 4}),
]
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)
+ nqd = query.NodeQueryData(nodes, live_data, None, None, None,
+ groups, None, cluster)
q = self._Create(["name", "drained"])
self.assertEqual(q.RequestedData(), set([query.NQ_CONFIG]))
[["node1", False],
["node2", True],
["node3", False]])
+ q = self._Create(["ndp/spindle_count"])
+ self.assertEqual(q.RequestedData(), set([query.NQ_GROUP]))
+ self.assertEqual(q.Query(nqd),
+ [[(constants.RS_NORMAL,
+ constants.NDC_DEFAULTS[constants.ND_SPINDLE_COUNT])],
+ [(constants.RS_NORMAL,
+ grp2.ndparams[constants.ND_SPINDLE_COUNT])],
+ [(constants.RS_NORMAL,
+ nodes[2].ndparams[constants.ND_SPINDLE_COUNT])],
+ ])
def test(self):
selected = query.NODE_FIELDS.keys()
master_candidate=(name != master_name and idx % 3 == 0),
offline=False,
drained=False,
- vm_capable=False,
+ powered=True,
+ vm_capable=True,
master_capable=False,
ndparams={},
group="default",
ng_uuid: objects.NodeGroup(name="ng1", uuid=ng_uuid, ndparams={}),
}
+ oob_not_powered_node = node_names[0]
+ nodes[0].powered = False
oob_support = dict((name, False) for name in node_names)
+ oob_support[master_name] = True
+ oob_support[oob_not_powered_node] = True
master_node.group = ng_uuid
row[field_index["ctime"]] == (constants.RS_NORMAL,
node.ctime) and
row[field_index["mtime"]] == (constants.RS_NORMAL,
- node.mtime)))
+ node.mtime) and
+ row[field_index["powered"]] == (constants.RS_NORMAL,
+ True))) or
+ (node.name == oob_not_powered_node and
+ row[field_index["powered"]] == (constants.RS_NORMAL,
+ False)) or
+ row[field_index["powered"]] == (constants.RS_UNAVAIL, None)
for row, node in zip(result, nodes))
live_data_row = result[node_to_row[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),
+ objects.Node(name="node1", drained=False, offline=False,
+ vm_capable=True),
+ objects.Node(name="node2", drained=True, offline=False,
+ vm_capable=True),
+ objects.Node(name="node3", drained=False, offline=False,
+ vm_capable=True),
+ objects.Node(name="node4", drained=False, offline=True,
+ vm_capable=True),
+ objects.Node(name="node5", drained=False, offline=False,
+ vm_capable=False),
]
live_data = dict.fromkeys([node.name for node in nodes], {})
self.assertRaises(AssertionError, query._GetLiveNodeField,
"hello", constants.QFT_BOOL, ctx, nodes[0])
+ # Non-vm_capable node
+ assert not nodes[4].vm_capable
+ ctx = _QueryData(None, curlive_data={})
+ self.assertEqual(query._GetLiveNodeField("hello", constants.QFT_NUMBER,
+ ctx, nodes[4]),
+ query._FS_UNAVAIL, None)
+
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"])
+ q = self._Create(["name", "be/maxmem", "ip"])
self.assertEqual(q.RequestedData(), set([query.IQ_CONFIG]))
cluster = objects.Cluster(cluster_name="testcluster",
},
nicparams={
constants.PP_DEFAULT: constants.NICC_DEFAULTS,
- })
+ },
+ os_hvp={},
+ osparams={})
instances = [
- objects.Instance(name="inst1", hvparams={}, beparams={}, nics=[]),
- objects.Instance(name="inst2", hvparams={}, nics=[],
+ objects.Instance(name="inst1", hvparams={}, beparams={}, osparams={},
+ nics=[], os="deb1"),
+ objects.Instance(name="inst2", hvparams={}, nics=[], osparams={},
+ os="foomoo",
beparams={
- constants.BE_MEMORY: 512,
+ constants.BE_MAXMEM: 512,
}),
- objects.Instance(name="inst3", hvparams={}, beparams={},
- nics=[objects.NIC(ip="192.0.2.99", nicparams={})]),
+ objects.Instance(name="inst3", hvparams={}, beparams={}, osparams={},
+ os="dos", nics=[objects.NIC(ip="192.0.2.99", nicparams={})]),
]
- iqd = query.InstanceQueryData(instances, cluster, None, [], [], {})
+ iqd = query.InstanceQueryData(instances, cluster, None, [], [], {},
+ set(), {}, None, None)
self.assertEqual(q.Query(iqd),
[[(constants.RS_NORMAL, "inst1"),
(constants.RS_NORMAL, 128),
q = self._Create(selected)
self.assertEqual(q.RequestedData(),
- set([query.IQ_CONFIG, query.IQ_LIVE, query.IQ_DISKUSAGE]))
+ set([query.IQ_CONFIG, query.IQ_LIVE, query.IQ_DISKUSAGE,
+ query.IQ_CONSOLE, query.IQ_NODES]))
cluster = objects.Cluster(cluster_name="testcluster",
hvparams=constants.HVC_DEFAULTS,
constants.PP_DEFAULT: constants.NICC_DEFAULTS,
},
os_hvp={},
- tcpudp_port_pool=set())
+ tcpudp_port_pool=set(),
+ osparams={
+ "deb99": {
+ "clean_install": "yes",
+ },
+ })
offline_nodes = ["nodeoff1", "nodeoff2"]
bad_nodes = ["nodebad1", "nodebad2", "nodebad3"] + offline_nodes
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",
+ admin_state=constants.ADMINST_UP, hypervisor=constants.HT_XEN_PVM,
+ os="linux1",
primary_node="node1",
disk_template=constants.DT_PLAIN,
- disks=[]),
+ disks=[],
+ osparams={}),
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",
+ admin_state=constants.ADMINST_UP, hypervisor=constants.HT_XEN_HVM,
+ os="deb99",
primary_node="node5",
disk_template=constants.DT_DISKLESS,
disks=[],
beparams={
- constants.BE_MEMORY: 512,
- }),
+ constants.BE_MAXMEM: 512,
+ constants.BE_MINMEM: 256,
+ },
+ osparams={}),
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",
+ admin_state=constants.ADMINST_DOWN, hypervisor=constants.HT_KVM,
+ os="busybox",
primary_node="node6",
disk_template=constants.DT_DRBD8,
disks=[],
constants.NIC_LINK: constants.DEFAULT_BRIDGE,
}),
objects.NIC(ip=None, mac=macs.pop(), nicparams={}),
- ]),
+ ],
+ osparams={}),
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",
+ admin_state=constants.ADMINST_DOWN, hypervisor=constants.HT_XEN_PVM,
+ os="linux1",
primary_node="nodeoff2",
disk_template=constants.DT_DRBD8,
disks=[],
constants.NIC_MODE: constants.NIC_MODE_BRIDGED,
constants.NIC_LINK: "eth123",
}),
- ]),
+ ],
+ osparams={}),
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",
+ admin_state=constants.ADMINST_UP, hypervisor=constants.HT_XEN_HVM,
+ os="deb99",
primary_node="nodebad2",
disk_template=constants.DT_DISKLESS,
disks=[],
beparams={
- constants.BE_MEMORY: 512,
- }),
+ constants.BE_MAXMEM: 512,
+ constants.BE_MINMEM: 512,
+ },
+ osparams={}),
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",
+ admin_state=constants.ADMINST_DOWN, hypervisor=constants.HT_XEN_HVM,
+ os="deb99",
primary_node="node7",
disk_template=constants.DT_DISKLESS,
disks=[],
beparams={
- constants.BE_MEMORY: 768,
- }),
+ constants.BE_MAXMEM: 768,
+ constants.BE_MINMEM: 256,
+ },
+ osparams={
+ "clean_install": "no",
+ }),
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",
+ admin_state=constants.ADMINST_DOWN, hypervisor=constants.HT_XEN_HVM,
+ os="deb99",
+ primary_node="node6",
+ disk_template=constants.DT_DISKLESS,
+ disks=[],
+ beparams={},
+ osparams={}),
+ objects.Instance(name="inst8", hvparams={}, nics=[],
+ uuid="ceec5dc4-b729-4f42-ae28-69b3cd24920f",
+ ctime=None, mtime=None, serial_no=19478,
+ admin_state=constants.ADMINST_OFFLINE, hypervisor=constants.HT_XEN_HVM,
+ os="deb99",
primary_node="node6",
disk_template=constants.DT_DISKLESS,
disks=[],
- beparams={}),
+ beparams={},
+ osparams={}),
]
assert not utils.FindDuplicates(inst.name for inst in instances)
+ instbyname = dict((inst.name, inst) for inst in instances)
+
disk_usage = dict((inst.name,
- cmdlib._ComputeDiskSize(inst.disk_template,
- [{"size": disk.size}
- for disk in inst.disks]))
+ gmi.ComputeDiskSize(inst.disk_template,
+ [{"size": disk.size}
+ for disk in inst.disks]))
for inst in instances)
inst_bridges = {
"inst6": {
"memory": 768,
},
+ "inst7": {
+ "vcpus": 3,
+ },
}
+ wrongnode_inst = set(["inst7"])
+
+ consinfo = dict((inst.name, None) for inst in instances)
+ consinfo["inst7"] = \
+ objects.InstanceConsole(instance="inst7", kind=constants.CONS_SSH,
+ host=instbyname["inst7"].primary_node,
+ user=constants.GANETI_RUNAS,
+ command=["hostname"]).ToDict()
iqd = query.InstanceQueryData(instances, cluster, disk_usage,
- offline_nodes, bad_nodes, live_data)
+ offline_nodes, bad_nodes, live_data,
+ wrongnode_inst, consinfo, {}, {})
result = q.Query(iqd)
self.assertEqual(len(result), len(instances))
self.assert_(compat.all(len(row) == len(selected)
(constants.RS_NORMAL, inst.name))
if inst.primary_node in offline_nodes:
- exp_status = "ERROR_nodeoffline"
+ exp_status = constants.INSTST_NODEOFFLINE
elif inst.primary_node in bad_nodes:
- exp_status = "ERROR_nodedown"
+ exp_status = constants.INSTST_NODEDOWN
elif inst.name in live_data:
- if inst.admin_up:
- exp_status = "running"
+ if inst.name in wrongnode_inst:
+ exp_status = constants.INSTST_WRONGNODE
+ elif inst.admin_state == constants.ADMINST_UP:
+ exp_status = constants.INSTST_RUNNING
else:
- exp_status = "ERROR_up"
- elif inst.admin_up:
- exp_status = "ERROR_down"
+ exp_status = constants.INSTST_ERRORUP
+ elif inst.admin_state == constants.ADMINST_UP:
+ exp_status = constants.INSTST_ERRORDOWN
+ elif inst.admin_state == constants.ADMINST_DOWN:
+ exp_status = constants.INSTST_ADMINDOWN
else:
- exp_status = "ADMIN_down"
+ exp_status = constants.INSTST_ADMINOFFLINE
self.assertEqual(row[fieldidx["status"]],
(constants.RS_NORMAL, exp_status))
(_, status) = row[fieldidx["status"]]
tested_status.add(status)
- for (field, livefield) in [("oper_ram", "memory"),
- ("oper_vcpus", "vcpus")]:
+ #FIXME(dynmem): check oper_ram vs min/max mem
+ for (field, livefield) in [("oper_vcpus", "vcpus")]:
if inst.primary_node in bad_nodes:
exp = (constants.RS_NODATA, None)
elif inst.name in live_data:
exp = (constants.RS_NORMAL, inst.name in live_data)
self.assertEqual(row[fieldidx["oper_state"]], exp)
+ cust_exp = (constants.RS_NORMAL, {})
+ if inst.os == "deb99":
+ if inst.name == "inst6":
+ exp = (constants.RS_NORMAL, {"clean_install": "no"})
+ cust_exp = exp
+ else:
+ exp = (constants.RS_NORMAL, {"clean_install": "yes"})
+ else:
+ exp = (constants.RS_NORMAL, {})
+ self.assertEqual(row[fieldidx["osparams"]], exp)
+ self.assertEqual(row[fieldidx["custom_osparams"]], cust_exp)
+
usage = disk_usage[inst.name]
if usage is None:
usage = 0
self.assertEqual(row[fieldidx["disk_usage"]],
(constants.RS_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 alias, target in [("sda_size", "disk.size/0"),
+ ("sdb_size", "disk.size/1"),
+ ("vcpus", "be/vcpus"),
+ ("ip", "nic.ip/0"),
+ ("mac", "nic.mac/0"),
+ ("bridge", "nic.bridge/0"),
+ ("nic_mode", "nic.mode/0"),
+ ("nic_link", "nic.link/0"),
+ ]:
+ self.assertEqual(row[fieldidx[alias]], row[fieldidx[target]])
for field in ["ctime", "mtime"]:
if getattr(inst, field) is None:
exp = (constants.RS_NORMAL, getattr(inst, field))
self.assertEqual(row[fieldidx[field]], exp)
+ self._CheckInstanceConsole(inst, row[fieldidx["console"]])
+
# Ensure all possible status' have been tested
- self.assertEqual(tested_status,
- set(["ERROR_nodeoffline", "ERROR_nodedown",
- "running", "ERROR_up", "ERROR_down",
- "ADMIN_down"]))
+ self.assertEqual(tested_status, constants.INSTST_ALL)
+
+ def _CheckInstanceConsole(self, instance, (status, consdata)):
+ if instance.name == "inst7":
+ self.assertEqual(status, constants.RS_NORMAL)
+ console = objects.InstanceConsole.FromDict(consdata)
+ self.assertTrue(console.Validate())
+ self.assertEqual(console.host, instance.primary_node)
+ else:
+ self.assertEqual(status, constants.RS_UNAVAIL)
class TestGroupQuery(unittest.TestCase):
def setUp(self):
+ self.custom_diskparams = {
+ constants.DT_DRBD8: {
+ constants.DRBD_DEFAULT_METAVG: "foobar",
+ },
+ }
+
self.groups = [
objects.NodeGroup(name="default",
uuid="c0e89160-18e7-11e0-a46e-001d0904baeb",
- alloc_policy=constants.ALLOC_POLICY_PREFERRED),
+ alloc_policy=constants.ALLOC_POLICY_PREFERRED,
+ ipolicy=objects.MakeEmptyIPolicy(),
+ ndparams={},
+ diskparams={},
+ ),
objects.NodeGroup(name="restricted",
uuid="d2a40a74-18e7-11e0-9143-001d0904baeb",
- alloc_policy=constants.ALLOC_POLICY_LAST_RESORT),
+ alloc_policy=constants.ALLOC_POLICY_LAST_RESORT,
+ ipolicy=objects.MakeEmptyIPolicy(),
+ ndparams={},
+ diskparams=self.custom_diskparams,
+ ),
]
+ self.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,
+ ipolicy=constants.IPOLICY_DEFAULTS,
+ diskparams=constants.DISK_DT_DEFAULTS,
+ )
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)
+ gqd = query.GroupQueryData(self.cluster, self.groups, None, None, False)
self.assertEqual(q.RequestedData(), set([query.GQ_CONFIG]))
}
q = self._Create(["name", "node_cnt", "node_list"])
- gqd = query.GroupQueryData(self.groups, groups_to_nodes, None)
+ gqd = query.GroupQueryData(self.cluster, self.groups, groups_to_nodes, None,
+ False)
self.assertEqual(q.RequestedData(), set([query.GQ_CONFIG, query.GQ_NODE]))
}
q = self._Create(["pinst_cnt", "pinst_list"])
- gqd = query.GroupQueryData(self.groups, None, groups_to_instances)
+ gqd = query.GroupQueryData(self.cluster, self.groups, None,
+ groups_to_instances, False)
self.assertEqual(q.RequestedData(), set([query.GQ_INST]))
],
])
+ def testDiskparams(self):
+ q = self._Create(["name", "uuid", "diskparams", "custom_diskparams"])
+ gqd = query.GroupQueryData(self.cluster, self.groups, None, None, True)
+
+ self.assertEqual(q.RequestedData(),
+ set([query.GQ_CONFIG, query.GQ_DISKPARAMS]))
+
+ self.assertEqual(q.Query(gqd),
+ [[(constants.RS_NORMAL, "default"),
+ (constants.RS_NORMAL, "c0e89160-18e7-11e0-a46e-001d0904baeb"),
+ (constants.RS_NORMAL, constants.DISK_DT_DEFAULTS),
+ (constants.RS_NORMAL, {}),
+ ],
+ [(constants.RS_NORMAL, "restricted"),
+ (constants.RS_NORMAL, "d2a40a74-18e7-11e0-9143-001d0904baeb"),
+ (constants.RS_NORMAL, objects.FillDiskParams(constants.DISK_DT_DEFAULTS,
+ self.custom_diskparams)),
+ (constants.RS_NORMAL, self.custom_diskparams),
+ ],
+ ])
+
+
+class TestOsQuery(unittest.TestCase):
+ def _Create(self, selected):
+ return query.Query(query.OS_FIELDS, selected)
+
+ def test(self):
+ variants = ["v00", "plain", "v3", "var0", "v33", "v20"]
+ api_versions = [10, 0, 15, 5]
+ parameters = ["zpar3", "apar9"]
+
+ assert variants != sorted(variants) and variants != utils.NiceSort(variants)
+ assert (api_versions != sorted(api_versions) and
+ api_versions != utils.NiceSort(variants))
+ assert (parameters != sorted(parameters) and
+ parameters != utils.NiceSort(parameters))
+
+ data = [
+ query.OsInfo(name="debian", valid=False, hidden=False, blacklisted=False,
+ variants=set(), api_versions=set(), parameters=set(),
+ node_status={ "some": "status", }),
+ query.OsInfo(name="dos", valid=True, hidden=False, blacklisted=True,
+ variants=set(variants),
+ api_versions=set(api_versions),
+ parameters=set(parameters),
+ node_status={ "some": "other", "status": None, }),
+ ]
+
+
+ q = self._Create(["name", "valid", "hidden", "blacklisted", "variants",
+ "api_versions", "parameters", "node_status"])
+ self.assertEqual(q.RequestedData(), set([]))
+ self.assertEqual(q.Query(data),
+ [[(constants.RS_NORMAL, "debian"),
+ (constants.RS_NORMAL, False),
+ (constants.RS_NORMAL, False),
+ (constants.RS_NORMAL, False),
+ (constants.RS_NORMAL, []),
+ (constants.RS_NORMAL, []),
+ (constants.RS_NORMAL, []),
+ (constants.RS_NORMAL, {"some": "status"})],
+ [(constants.RS_NORMAL, "dos"),
+ (constants.RS_NORMAL, True),
+ (constants.RS_NORMAL, False),
+ (constants.RS_NORMAL, True),
+ (constants.RS_NORMAL,
+ ["plain", "v00", "v3", "v20", "v33", "var0"]),
+ (constants.RS_NORMAL, [0, 5, 10, 15]),
+ (constants.RS_NORMAL, ["apar9", "zpar3"]),
+ (constants.RS_NORMAL,
+ { "some": "other", "status": None, })
+ ]])
+
class TestQueryFields(unittest.TestCase):
def testAllFields(self):
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)])
+ for (fdef2, _, _, _) in utils.NiceSort(fielddefs.values(),
+ key=lambda x: x[0].name)])
def testSomeFields(self):
rnd = random.Random(5357)
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)]
+ 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)
[(fdef2.name, fdef2.title) for fdef2 in fields])
+class TestQueryFilter(unittest.TestCase):
+ def testRequestedNames(self):
+ for (what, fielddefs) in query.ALL_FIELDS.items():
+ if what == constants.QR_JOB:
+ namefield = "id"
+ nameval = 123
+ namevalempty = 0
+ genval = lambda i: i * 10
+ randvals = [17361, 22015, 13193, 15215]
+ else:
+ nameval = "abc"
+ namevalempty = ""
+ genval = lambda i: "x%s" % i
+ randvals = ["x17361", "x22015", "x13193", "x15215"]
+ if what == constants.QR_EXPORT:
+ namefield = "export"
+ else:
+ namefield = "name"
+
+ assert namefield in fielddefs
+
+ reqnames = [genval(i) for i in range(4)]
+ innerfilter = [["=", namefield, v] for v in reqnames]
+
+ # No name field
+ q = query.Query(fielddefs, [namefield],
+ qfilter=["=", namefield, nameval], namefield=None)
+ self.assertEqual(q.RequestedNames(), None)
+
+ # No filter
+ q = query.Query(fielddefs, [namefield], qfilter=None, namefield=namefield)
+ self.assertEqual(q.RequestedNames(), None)
+
+ # Check empty query
+ q = query.Query(fielddefs, [namefield], qfilter=["|"],
+ namefield=namefield)
+ self.assertEqual(q.RequestedNames(), None)
+
+ # Check order
+ q = query.Query(fielddefs, [namefield], qfilter=["|"] + innerfilter,
+ namefield=namefield)
+ self.assertEqual(q.RequestedNames(), reqnames)
+
+ # Check reverse order
+ q = query.Query(fielddefs, [namefield],
+ qfilter=["|"] + list(reversed(innerfilter)),
+ namefield=namefield)
+ self.assertEqual(q.RequestedNames(), list(reversed(reqnames)))
+
+ # Duplicates
+ q = query.Query(fielddefs, [namefield],
+ qfilter=["|"] + innerfilter + list(reversed(innerfilter)),
+ namefield=namefield)
+ self.assertEqual(q.RequestedNames(), reqnames)
+
+ # Unknown name field
+ self.assertRaises(AssertionError, query.Query, fielddefs, [namefield],
+ namefield="_unknown_field_")
+
+ # Filter with AND
+ q = query.Query(fielddefs, [namefield],
+ qfilter=["|", ["=", namefield, nameval],
+ ["&", ["=", namefield, namevalempty]]],
+ namefield=namefield)
+ self.assertTrue(q.RequestedNames() is None)
+
+ # Filter with NOT
+ q = query.Query(fielddefs, [namefield],
+ qfilter=["|", ["=", namefield, nameval],
+ ["!", ["=", namefield, namevalempty]]],
+ namefield=namefield)
+ self.assertTrue(q.RequestedNames() is None)
+
+ # Filter with only OR (names must be in correct order)
+ q = query.Query(fielddefs, [namefield],
+ qfilter=["|", ["=", namefield, randvals[0]],
+ ["|", ["=", namefield, randvals[1]]],
+ ["|", ["|", ["=", namefield, randvals[2]]]],
+ ["=", namefield, randvals[3]]],
+ namefield=namefield)
+ self.assertEqual(q.RequestedNames(), randvals)
+
+ @staticmethod
+ def _GenNestedFilter(namefield, op, depth, nameval):
+ nested = ["=", namefield, nameval]
+ for i in range(depth):
+ nested = [op, nested]
+ return nested
+
+ def testCompileFilter(self):
+ levels_max = query._FilterCompilerHelper._LEVELS_MAX
+
+ for (what, fielddefs) in query.ALL_FIELDS.items():
+ if what == constants.QR_JOB:
+ namefield = "id"
+ nameval = 123
+ elif what == constants.QR_EXPORT:
+ namefield = "export"
+ nameval = "value"
+ else:
+ namefield = "name"
+ nameval = "value"
+
+ checks = [
+ [], ["="], ["=", "foo"], ["unknownop"], ["!"],
+ ["=", "_unknown_field", "value"],
+ self._GenNestedFilter(namefield, "|", levels_max, nameval),
+ self._GenNestedFilter(namefield, "|", levels_max * 3, nameval),
+ self._GenNestedFilter(namefield, "!", levels_max, nameval),
+ ]
+
+ for qfilter in checks:
+ self.assertRaises(errors.ParameterError, query._CompileFilter,
+ fielddefs, None, qfilter)
+
+ for op in ["|", "!"]:
+ qfilter = self._GenNestedFilter(namefield, op, levels_max - 1, nameval)
+ self.assertTrue(callable(query._CompileFilter(fielddefs, None,
+ qfilter)))
+
+ def testQueryInputOrder(self):
+ fielddefs = query._PrepareFieldList([
+ (query._MakeField("pnode", "PNode", constants.QFT_TEXT, "Primary"),
+ None, 0, lambda ctx, item: item["pnode"]),
+ (query._MakeField("snode", "SNode", constants.QFT_TEXT, "Secondary"),
+ None, 0, lambda ctx, item: item["snode"]),
+ ], [])
+
+ data = [
+ { "pnode": "node1", "snode": "node44", },
+ { "pnode": "node30", "snode": "node90", },
+ { "pnode": "node25", "snode": "node1", },
+ { "pnode": "node20", "snode": "node1", },
+ ]
+
+ qfilter = ["|", ["=", "pnode", "node1"], ["=", "snode", "node1"]]
+
+ q = query.Query(fielddefs, ["pnode", "snode"], namefield="pnode",
+ qfilter=qfilter)
+ self.assertTrue(q.RequestedNames() is None)
+ self.assertFalse(q.RequestedData())
+ self.assertEqual(q.Query(data),
+ [[(constants.RS_NORMAL, "node1"), (constants.RS_NORMAL, "node44")],
+ [(constants.RS_NORMAL, "node20"), (constants.RS_NORMAL, "node1")],
+ [(constants.RS_NORMAL, "node25"), (constants.RS_NORMAL, "node1")]])
+
+ # Try again with reversed input data
+ self.assertEqual(q.Query(reversed(data)),
+ [[(constants.RS_NORMAL, "node1"), (constants.RS_NORMAL, "node44")],
+ [(constants.RS_NORMAL, "node20"), (constants.RS_NORMAL, "node1")],
+ [(constants.RS_NORMAL, "node25"), (constants.RS_NORMAL, "node1")]])
+
+ # No name field, result must be in incoming order
+ q = query.Query(fielddefs, ["pnode", "snode"], namefield=None,
+ qfilter=qfilter)
+ self.assertFalse(q.RequestedData())
+ self.assertEqual(q.Query(data),
+ [[(constants.RS_NORMAL, "node1"), (constants.RS_NORMAL, "node44")],
+ [(constants.RS_NORMAL, "node25"), (constants.RS_NORMAL, "node1")],
+ [(constants.RS_NORMAL, "node20"), (constants.RS_NORMAL, "node1")]])
+ self.assertEqual(q.OldStyleQuery(data), [
+ ["node1", "node44"],
+ ["node25", "node1"],
+ ["node20", "node1"],
+ ])
+ self.assertEqual(q.Query(reversed(data)),
+ [[(constants.RS_NORMAL, "node20"), (constants.RS_NORMAL, "node1")],
+ [(constants.RS_NORMAL, "node25"), (constants.RS_NORMAL, "node1")],
+ [(constants.RS_NORMAL, "node1"), (constants.RS_NORMAL, "node44")]])
+ self.assertEqual(q.OldStyleQuery(reversed(data)), [
+ ["node20", "node1"],
+ ["node25", "node1"],
+ ["node1", "node44"],
+ ])
+
+ # Name field, but no sorting, result must be in incoming order
+ q = query.Query(fielddefs, ["pnode", "snode"], namefield="pnode")
+ self.assertFalse(q.RequestedData())
+ self.assertEqual(q.Query(data, sort_by_name=False),
+ [[(constants.RS_NORMAL, "node1"), (constants.RS_NORMAL, "node44")],
+ [(constants.RS_NORMAL, "node30"), (constants.RS_NORMAL, "node90")],
+ [(constants.RS_NORMAL, "node25"), (constants.RS_NORMAL, "node1")],
+ [(constants.RS_NORMAL, "node20"), (constants.RS_NORMAL, "node1")]])
+ self.assertEqual(q.OldStyleQuery(data, sort_by_name=False), [
+ ["node1", "node44"],
+ ["node30", "node90"],
+ ["node25", "node1"],
+ ["node20", "node1"],
+ ])
+ self.assertEqual(q.Query(reversed(data), sort_by_name=False),
+ [[(constants.RS_NORMAL, "node20"), (constants.RS_NORMAL, "node1")],
+ [(constants.RS_NORMAL, "node25"), (constants.RS_NORMAL, "node1")],
+ [(constants.RS_NORMAL, "node30"), (constants.RS_NORMAL, "node90")],
+ [(constants.RS_NORMAL, "node1"), (constants.RS_NORMAL, "node44")]])
+ self.assertEqual(q.OldStyleQuery(reversed(data), sort_by_name=False), [
+ ["node20", "node1"],
+ ["node25", "node1"],
+ ["node30", "node90"],
+ ["node1", "node44"],
+ ])
+
+ def testEqualNamesOrder(self):
+ fielddefs = query._PrepareFieldList([
+ (query._MakeField("pnode", "PNode", constants.QFT_TEXT, "Primary"),
+ None, 0, lambda ctx, item: item["pnode"]),
+ (query._MakeField("num", "Num", constants.QFT_NUMBER, "Num"),
+ None, 0, lambda ctx, item: item["num"]),
+ ], [])
+
+ data = [
+ { "pnode": "node1", "num": 100, },
+ { "pnode": "node1", "num": 25, },
+ { "pnode": "node2", "num": 90, },
+ { "pnode": "node2", "num": 30, },
+ ]
+
+ q = query.Query(fielddefs, ["pnode", "num"], namefield="pnode",
+ qfilter=["|", ["=", "pnode", "node1"],
+ ["=", "pnode", "node2"],
+ ["=", "pnode", "node1"]])
+ self.assertEqual(q.RequestedNames(), ["node1", "node2"],
+ msg="Did not return unique names")
+ self.assertFalse(q.RequestedData())
+ self.assertEqual(q.Query(data),
+ [[(constants.RS_NORMAL, "node1"), (constants.RS_NORMAL, 100)],
+ [(constants.RS_NORMAL, "node1"), (constants.RS_NORMAL, 25)],
+ [(constants.RS_NORMAL, "node2"), (constants.RS_NORMAL, 90)],
+ [(constants.RS_NORMAL, "node2"), (constants.RS_NORMAL, 30)]])
+ self.assertEqual(q.Query(data, sort_by_name=False),
+ [[(constants.RS_NORMAL, "node1"), (constants.RS_NORMAL, 100)],
+ [(constants.RS_NORMAL, "node1"), (constants.RS_NORMAL, 25)],
+ [(constants.RS_NORMAL, "node2"), (constants.RS_NORMAL, 90)],
+ [(constants.RS_NORMAL, "node2"), (constants.RS_NORMAL, 30)]])
+
+ data = [
+ { "pnode": "nodeX", "num": 50, },
+ { "pnode": "nodeY", "num": 40, },
+ { "pnode": "nodeX", "num": 30, },
+ { "pnode": "nodeX", "num": 20, },
+ { "pnode": "nodeM", "num": 10, },
+ ]
+
+ q = query.Query(fielddefs, ["pnode", "num"], namefield="pnode",
+ qfilter=["|", ["=", "pnode", "nodeX"],
+ ["=", "pnode", "nodeY"],
+ ["=", "pnode", "nodeY"],
+ ["=", "pnode", "nodeY"],
+ ["=", "pnode", "nodeM"]])
+ self.assertEqual(q.RequestedNames(), ["nodeX", "nodeY", "nodeM"],
+ msg="Did not return unique names")
+ self.assertFalse(q.RequestedData())
+
+ # First sorted by name, then input order
+ self.assertEqual(q.Query(data, sort_by_name=True),
+ [[(constants.RS_NORMAL, "nodeM"), (constants.RS_NORMAL, 10)],
+ [(constants.RS_NORMAL, "nodeX"), (constants.RS_NORMAL, 50)],
+ [(constants.RS_NORMAL, "nodeX"), (constants.RS_NORMAL, 30)],
+ [(constants.RS_NORMAL, "nodeX"), (constants.RS_NORMAL, 20)],
+ [(constants.RS_NORMAL, "nodeY"), (constants.RS_NORMAL, 40)]])
+
+ # Input order
+ self.assertEqual(q.Query(data, sort_by_name=False),
+ [[(constants.RS_NORMAL, "nodeX"), (constants.RS_NORMAL, 50)],
+ [(constants.RS_NORMAL, "nodeY"), (constants.RS_NORMAL, 40)],
+ [(constants.RS_NORMAL, "nodeX"), (constants.RS_NORMAL, 30)],
+ [(constants.RS_NORMAL, "nodeX"), (constants.RS_NORMAL, 20)],
+ [(constants.RS_NORMAL, "nodeM"), (constants.RS_NORMAL, 10)]])
+
+ def testFilter(self):
+ (DK_A, DK_B) = range(1000, 1002)
+
+ fielddefs = query._PrepareFieldList([
+ (query._MakeField("name", "Name", constants.QFT_TEXT, "Name"),
+ DK_A, 0, lambda ctx, item: item["name"]),
+ (query._MakeField("other", "Other", constants.QFT_TEXT, "Other"),
+ DK_B, 0, lambda ctx, item: item["other"]),
+ ], [])
+
+ data = [
+ { "name": "node1", "other": "foo", },
+ { "name": "node2", "other": "bar", },
+ { "name": "node3", "other": "Hello", },
+ ]
+
+ # Empty filter
+ q = query.Query(fielddefs, ["name", "other"], namefield="name",
+ qfilter=["|"])
+ self.assertTrue(q.RequestedNames() is None)
+ self.assertEqual(q.RequestedData(), set([DK_A, DK_B]))
+ self.assertEqual(q.Query(data), [])
+
+ # Normal filter
+ q = query.Query(fielddefs, ["name", "other"], namefield="name",
+ qfilter=["=", "name", "node1"])
+ self.assertEqual(q.RequestedNames(), ["node1"])
+ self.assertEqual(q.Query(data),
+ [[(constants.RS_NORMAL, "node1"), (constants.RS_NORMAL, "foo")]])
+
+ q = query.Query(fielddefs, ["name", "other"], namefield="name",
+ qfilter=(["|", ["=", "name", "node1"],
+ ["=", "name", "node3"]]))
+ self.assertEqual(q.RequestedNames(), ["node1", "node3"])
+ self.assertEqual(q.Query(data),
+ [[(constants.RS_NORMAL, "node1"), (constants.RS_NORMAL, "foo")],
+ [(constants.RS_NORMAL, "node3"), (constants.RS_NORMAL, "Hello")]])
+
+ # Complex filter
+ q = query.Query(fielddefs, ["name", "other"], namefield="name",
+ qfilter=(["|", ["=", "name", "node1"],
+ ["|", ["=", "name", "node3"],
+ ["=", "name", "node2"]],
+ ["=", "name", "node3"]]))
+ self.assertEqual(q.RequestedNames(), ["node1", "node3", "node2"])
+ self.assertEqual(q.RequestedData(), set([DK_A, DK_B]))
+ self.assertEqual(q.Query(data),
+ [[(constants.RS_NORMAL, "node1"), (constants.RS_NORMAL, "foo")],
+ [(constants.RS_NORMAL, "node2"), (constants.RS_NORMAL, "bar")],
+ [(constants.RS_NORMAL, "node3"), (constants.RS_NORMAL, "Hello")]])
+
+ # Filter data type mismatch
+ for i in [-1, 0, 1, 123, [], None, True, False]:
+ self.assertRaises(errors.ParameterError, query.Query,
+ fielddefs, ["name", "other"], namefield="name",
+ qfilter=["=", "name", i])
+
+ # Negative filter
+ q = query.Query(fielddefs, ["name", "other"], namefield="name",
+ qfilter=["!", ["|", ["=", "name", "node1"],
+ ["=", "name", "node3"]]])
+ self.assertTrue(q.RequestedNames() is None)
+ self.assertEqual(q.Query(data),
+ [[(constants.RS_NORMAL, "node2"), (constants.RS_NORMAL, "bar")]])
+
+ # Not equal
+ q = query.Query(fielddefs, ["name", "other"], namefield="name",
+ qfilter=["!=", "name", "node3"])
+ self.assertTrue(q.RequestedNames() is None)
+ self.assertEqual(q.Query(data),
+ [[(constants.RS_NORMAL, "node1"), (constants.RS_NORMAL, "foo")],
+ [(constants.RS_NORMAL, "node2"), (constants.RS_NORMAL, "bar")]])
+
+ # Data type
+ q = query.Query(fielddefs, [], namefield="name",
+ qfilter=["|", ["=", "other", "bar"],
+ ["=", "name", "foo"]])
+ self.assertTrue(q.RequestedNames() is None)
+ self.assertEqual(q.RequestedData(), set([DK_A, DK_B]))
+ self.assertEqual(q.Query(data), [[]])
+
+ # Only one data type
+ q = query.Query(fielddefs, ["other"], namefield="name",
+ qfilter=["=", "other", "bar"])
+ self.assertTrue(q.RequestedNames() is None)
+ self.assertEqual(q.RequestedData(), set([DK_B]))
+ self.assertEqual(q.Query(data), [[(constants.RS_NORMAL, "bar")]])
+
+ q = query.Query(fielddefs, [], namefield="name",
+ qfilter=["=", "other", "bar"])
+ self.assertTrue(q.RequestedNames() is None)
+ self.assertEqual(q.RequestedData(), set([DK_B]))
+ self.assertEqual(q.Query(data), [[]])
+
+ def testFilterContains(self):
+ fielddefs = query._PrepareFieldList([
+ (query._MakeField("name", "Name", constants.QFT_TEXT, "Name"),
+ None, 0, lambda ctx, item: item["name"]),
+ (query._MakeField("other", "Other", constants.QFT_OTHER, "Other"),
+ None, 0, lambda ctx, item: item["other"]),
+ ], [])
+
+ data = [
+ { "name": "node2", "other": ["x", "y", "bar"], },
+ { "name": "node3", "other": "Hello", },
+ { "name": "node1", "other": ["a", "b", "foo"], },
+ { "name": "empty", "other": []},
+ ]
+
+ q = query.Query(fielddefs, ["name", "other"], namefield="name",
+ qfilter=["=[]", "other", "bar"])
+ self.assertTrue(q.RequestedNames() is None)
+ self.assertEqual(q.Query(data), [
+ [(constants.RS_NORMAL, "node2"),
+ (constants.RS_NORMAL, ["x", "y", "bar"])],
+ ])
+
+ q = query.Query(fielddefs, ["name", "other"], namefield="name",
+ qfilter=["|", ["=[]", "other", "bar"],
+ ["=[]", "other", "a"],
+ ["=[]", "other", "b"]])
+ self.assertTrue(q.RequestedNames() is None)
+ self.assertEqual(q.Query(data), [
+ [(constants.RS_NORMAL, "node1"),
+ (constants.RS_NORMAL, ["a", "b", "foo"])],
+ [(constants.RS_NORMAL, "node2"),
+ (constants.RS_NORMAL, ["x", "y", "bar"])],
+ ])
+ self.assertEqual(q.OldStyleQuery(data), [
+ ["node1", ["a", "b", "foo"]],
+ ["node2", ["x", "y", "bar"]],
+ ])
+
+ # Boolean test
+ q = query.Query(fielddefs, ["name", "other"], namefield="name",
+ qfilter=["?", "other"])
+ self.assertEqual(q.OldStyleQuery(data), [
+ ["node1", ["a", "b", "foo"]],
+ ["node2", ["x", "y", "bar"]],
+ ["node3", "Hello"],
+ ])
+
+ q = query.Query(fielddefs, ["name", "other"], namefield="name",
+ qfilter=["!", ["?", "other"]])
+ self.assertEqual(q.OldStyleQuery(data), [
+ ["empty", []],
+ ])
+
+ def testFilterHostname(self):
+ fielddefs = query._PrepareFieldList([
+ (query._MakeField("name", "Name", constants.QFT_TEXT, "Name"),
+ None, query.QFF_HOSTNAME, lambda ctx, item: item["name"]),
+ ], [])
+
+ data = [
+ { "name": "node1.example.com", },
+ { "name": "node2.example.com", },
+ { "name": "node2.example.net", },
+ ]
+
+ q = query.Query(fielddefs, ["name"], namefield="name",
+ qfilter=["=", "name", "node2"])
+ self.assertEqual(q.RequestedNames(), ["node2"])
+ self.assertEqual(q.Query(data), [
+ [(constants.RS_NORMAL, "node2.example.com")],
+ [(constants.RS_NORMAL, "node2.example.net")],
+ ])
+
+ q = query.Query(fielddefs, ["name"], namefield="name",
+ qfilter=["=", "name", "node1"])
+ self.assertEqual(q.RequestedNames(), ["node1"])
+ self.assertEqual(q.Query(data), [
+ [(constants.RS_NORMAL, "node1.example.com")],
+ ])
+
+ q = query.Query(fielddefs, ["name"], namefield="name",
+ qfilter=["=", "name", "othername"])
+ self.assertEqual(q.RequestedNames(), ["othername"])
+ self.assertEqual(q.Query(data), [])
+
+ q = query.Query(fielddefs, ["name"], namefield="name",
+ qfilter=["|", ["=", "name", "node1.example.com"],
+ ["=", "name", "node2"]])
+ self.assertEqual(q.RequestedNames(), ["node1.example.com", "node2"])
+ self.assertEqual(q.Query(data), [
+ [(constants.RS_NORMAL, "node1.example.com")],
+ [(constants.RS_NORMAL, "node2.example.com")],
+ [(constants.RS_NORMAL, "node2.example.net")],
+ ])
+ self.assertEqual(q.OldStyleQuery(data), [
+ ["node1.example.com"],
+ ["node2.example.com"],
+ ["node2.example.net"],
+ ])
+
+ q = query.Query(fielddefs, ["name"], namefield="name",
+ qfilter=["!=", "name", "node1"])
+ self.assertTrue(q.RequestedNames() is None)
+ self.assertEqual(q.Query(data), [
+ [(constants.RS_NORMAL, "node2.example.com")],
+ [(constants.RS_NORMAL, "node2.example.net")],
+ ])
+ self.assertEqual(q.OldStyleQuery(data), [
+ ["node2.example.com"],
+ ["node2.example.net"],
+ ])
+
+ def testFilterBoolean(self):
+ fielddefs = query._PrepareFieldList([
+ (query._MakeField("name", "Name", constants.QFT_TEXT, "Name"),
+ None, query.QFF_HOSTNAME, lambda ctx, item: item["name"]),
+ (query._MakeField("value", "Value", constants.QFT_BOOL, "Value"),
+ None, 0, lambda ctx, item: item["value"]),
+ ], [])
+
+ data = [
+ { "name": "node1", "value": False, },
+ { "name": "node2", "value": True, },
+ { "name": "node3", "value": True, },
+ ]
+
+ q = query.Query(fielddefs, ["name", "value"],
+ qfilter=["|", ["=", "value", False],
+ ["=", "value", True]])
+ self.assertTrue(q.RequestedNames() is None)
+ self.assertEqual(q.Query(data), [
+ [(constants.RS_NORMAL, "node1"), (constants.RS_NORMAL, False)],
+ [(constants.RS_NORMAL, "node2"), (constants.RS_NORMAL, True)],
+ [(constants.RS_NORMAL, "node3"), (constants.RS_NORMAL, True)],
+ ])
+
+ q = query.Query(fielddefs, ["name", "value"],
+ qfilter=["|", ["=", "value", False],
+ ["!", ["=", "value", False]]])
+ self.assertTrue(q.RequestedNames() is None)
+ self.assertEqual(q.Query(data), [
+ [(constants.RS_NORMAL, "node1"), (constants.RS_NORMAL, False)],
+ [(constants.RS_NORMAL, "node2"), (constants.RS_NORMAL, True)],
+ [(constants.RS_NORMAL, "node3"), (constants.RS_NORMAL, True)],
+ ])
+
+ # Comparing bool with string
+ for i in ["False", "True", "0", "1", "no", "yes", "N", "Y"]:
+ self.assertRaises(errors.ParameterError, query.Query,
+ fielddefs, ["name", "value"],
+ qfilter=["=", "value", i])
+
+ # Truth filter
+ q = query.Query(fielddefs, ["name", "value"], qfilter=["?", "value"])
+ self.assertTrue(q.RequestedNames() is None)
+ self.assertEqual(q.Query(data), [
+ [(constants.RS_NORMAL, "node2"), (constants.RS_NORMAL, True)],
+ [(constants.RS_NORMAL, "node3"), (constants.RS_NORMAL, True)],
+ ])
+
+ # Negative bool filter
+ q = query.Query(fielddefs, ["name", "value"], qfilter=["!", ["?", "value"]])
+ self.assertTrue(q.RequestedNames() is None)
+ self.assertEqual(q.Query(data), [
+ [(constants.RS_NORMAL, "node1"), (constants.RS_NORMAL, False)],
+ ])
+
+ # Complex truth filter
+ q = query.Query(fielddefs, ["name", "value"],
+ qfilter=["|", ["&", ["=", "name", "node1"],
+ ["!", ["?", "value"]]],
+ ["?", "value"]])
+ self.assertTrue(q.RequestedNames() is None)
+ self.assertEqual(q.Query(data), [
+ [(constants.RS_NORMAL, "node1"), (constants.RS_NORMAL, False)],
+ [(constants.RS_NORMAL, "node2"), (constants.RS_NORMAL, True)],
+ [(constants.RS_NORMAL, "node3"), (constants.RS_NORMAL, True)],
+ ])
+
+ def testFilterRegex(self):
+ fielddefs = query._PrepareFieldList([
+ (query._MakeField("name", "Name", constants.QFT_TEXT, "Name"),
+ None, 0, lambda ctx, item: item["name"]),
+ ], [])
+
+ data = [
+ { "name": "node1.example.com", },
+ { "name": "node2.site.example.com", },
+ { "name": "node2.example.net", },
+
+ # Empty name
+ { "name": "", },
+ ]
+
+ q = query.Query(fielddefs, ["name"], namefield="name",
+ qfilter=["=~", "name", "site"])
+ self.assertTrue(q.RequestedNames() is None)
+ self.assertEqual(q.Query(data), [
+ [(constants.RS_NORMAL, "node2.site.example.com")],
+ ])
+
+ q = query.Query(fielddefs, ["name"], namefield="name",
+ qfilter=["=~", "name", "^node2"])
+ self.assertTrue(q.RequestedNames() is None)
+ self.assertEqual(q.Query(data), [
+ [(constants.RS_NORMAL, "node2.example.net")],
+ [(constants.RS_NORMAL, "node2.site.example.com")],
+ ])
+
+ q = query.Query(fielddefs, ["name"], namefield="name",
+ qfilter=["=~", "name", r"(?i)\.COM$"])
+ self.assertTrue(q.RequestedNames() is None)
+ self.assertEqual(q.Query(data), [
+ [(constants.RS_NORMAL, "node1.example.com")],
+ [(constants.RS_NORMAL, "node2.site.example.com")],
+ ])
+
+ q = query.Query(fielddefs, ["name"], namefield="name",
+ qfilter=["=~", "name", r"."])
+ self.assertTrue(q.RequestedNames() is None)
+ self.assertEqual(q.Query(data), [
+ [(constants.RS_NORMAL, "node1.example.com")],
+ [(constants.RS_NORMAL, "node2.example.net")],
+ [(constants.RS_NORMAL, "node2.site.example.com")],
+ ])
+
+ q = query.Query(fielddefs, ["name"], namefield="name",
+ qfilter=["=~", "name", r"^$"])
+ self.assertTrue(q.RequestedNames() is None)
+ self.assertEqual(q.Query(data), [
+ [(constants.RS_NORMAL, "")],
+ ])
+
+ # Invalid regular expression
+ self.assertRaises(errors.ParameterError, query.Query, fielddefs, ["name"],
+ qfilter=["=~", "name", r"["])
+
+ def testFilterLessGreater(self):
+ fielddefs = query._PrepareFieldList([
+ (query._MakeField("value", "Value", constants.QFT_NUMBER, "Value"),
+ None, 0, lambda ctx, item: item),
+ ], [])
+
+ data = range(100)
+
+ q = query.Query(fielddefs, ["value"],
+ qfilter=["<", "value", 20])
+ self.assertTrue(q.RequestedNames() is None)
+ self.assertEqual(q.Query(data),
+ [[(constants.RS_NORMAL, i)] for i in range(20)])
+
+ q = query.Query(fielddefs, ["value"],
+ qfilter=["<=", "value", 30])
+ self.assertTrue(q.RequestedNames() is None)
+ self.assertEqual(q.Query(data),
+ [[(constants.RS_NORMAL, i)] for i in range(31)])
+
+ q = query.Query(fielddefs, ["value"],
+ qfilter=[">", "value", 40])
+ self.assertTrue(q.RequestedNames() is None)
+ self.assertEqual(q.Query(data),
+ [[(constants.RS_NORMAL, i)] for i in range(41, 100)])
+
+ q = query.Query(fielddefs, ["value"],
+ qfilter=[">=", "value", 50])
+ self.assertTrue(q.RequestedNames() is None)
+ self.assertEqual(q.Query(data),
+ [[(constants.RS_NORMAL, i)] for i in range(50, 100)])
+
+ def testFilterLessGreaterJobId(self):
+ fielddefs = query._PrepareFieldList([
+ (query._MakeField("id", "ID", constants.QFT_TEXT, "Job ID"),
+ None, query.QFF_JOB_ID, lambda ctx, item: item),
+ ], [])
+
+ data = ["1", "2", "3", "10", "102", "120", "125", "15", "100", "7"]
+
+ assert data != utils.NiceSort(data), "Test data should not be sorted"
+
+ q = query.Query(fielddefs, ["id"], qfilter=["<", "id", "20"])
+ self.assertTrue(q.RequestedNames() is None)
+ self.assertEqual(q.Query(data), [
+ [(constants.RS_NORMAL, "1")],
+ [(constants.RS_NORMAL, "2")],
+ [(constants.RS_NORMAL, "3")],
+ [(constants.RS_NORMAL, "10")],
+ [(constants.RS_NORMAL, "15")],
+ [(constants.RS_NORMAL, "7")],
+ ])
+
+ q = query.Query(fielddefs, ["id"], qfilter=[">=", "id", "100"])
+ self.assertTrue(q.RequestedNames() is None)
+ self.assertEqual(q.Query(data), [
+ [(constants.RS_NORMAL, "102")],
+ [(constants.RS_NORMAL, "120")],
+ [(constants.RS_NORMAL, "125")],
+ [(constants.RS_NORMAL, "100")],
+ ])
+
+ # Integers are no valid job IDs
+ self.assertRaises(errors.ParameterError, query.Query,
+ fielddefs, ["id"], qfilter=[">=", "id", 10])
+
+ def testFilterLessGreaterSplitTimestamp(self):
+ fielddefs = query._PrepareFieldList([
+ (query._MakeField("ts", "Timestamp", constants.QFT_OTHER, "Timestamp"),
+ None, query.QFF_SPLIT_TIMESTAMP, lambda ctx, item: item),
+ ], [])
+
+ data = [
+ utils.SplitTime(0),
+ utils.SplitTime(0.1),
+ utils.SplitTime(18224.7872),
+ utils.SplitTime(919896.12623),
+ utils.SplitTime(999),
+ utils.SplitTime(989.9999),
+ ]
+
+ for i in [0, [0, 0]]:
+ q = query.Query(fielddefs, ["ts"], qfilter=["<", "ts", i])
+ self.assertTrue(q.RequestedNames() is None)
+ self.assertEqual(q.Query(data), [])
+
+ q = query.Query(fielddefs, ["ts"], qfilter=["<", "ts", 1000])
+ self.assertTrue(q.RequestedNames() is None)
+ self.assertEqual(q.Query(data), [
+ [(constants.RS_NORMAL, (0, 0))],
+ [(constants.RS_NORMAL, (0, 100000))],
+ [(constants.RS_NORMAL, (999, 0))],
+ [(constants.RS_NORMAL, (989, 999900))],
+ ])
+
+ q = query.Query(fielddefs, ["ts"], qfilter=[">=", "ts", 5000.3])
+ self.assertTrue(q.RequestedNames() is None)
+ self.assertEqual(q.Query(data), [
+ [(constants.RS_NORMAL, (18224, 787200))],
+ [(constants.RS_NORMAL, (919896, 126230))],
+ ])
+
+ for i in [18224.7772, utils.SplitTime(18224.7772)]:
+ q = query.Query(fielddefs, ["ts"], qfilter=[">=", "ts", i])
+ self.assertTrue(q.RequestedNames() is None)
+ self.assertEqual(q.Query(data), [
+ [(constants.RS_NORMAL, (18224, 787200))],
+ [(constants.RS_NORMAL, (919896, 126230))],
+ ])
+
+ q = query.Query(fielddefs, ["ts"], qfilter=[">", "ts", 18224.7880])
+ self.assertTrue(q.RequestedNames() is None)
+ self.assertEqual(q.Query(data), [
+ [(constants.RS_NORMAL, (919896, 126230))],
+ ])
+
+
if __name__ == "__main__":
testutils.GanetiTestProgram()