Commit 145bea54 authored by Michael Hanselmann's avatar Michael Hanselmann
Browse files

query: Handle items missing timestamps



In upgraded configurations, some items might miss the “ctime” and/or
“mtime” values and need to be handled specially.
Signed-off-by: default avatarMichael Hanselmann <hansmi@google.com>
Reviewed-by: default avatarIustin Pop <iustin@google.com>
parent 38f9d2cf
......@@ -277,6 +277,41 @@ def _GetItemAttr(attr):
return lambda _, item: (constants.QRFS_NORMAL, getter(item))
def _GetItemTimestamp(getter):
"""Returns function for getting timestamp of item.
@type getter: callable
@param getter: Function to retrieve timestamp attribute
"""
def fn(_, item):
"""Returns a timestamp of item.
"""
timestamp = getter(item)
if timestamp is None:
# Old configs might not have all timestamps
return (constants.QRFS_UNAVAIL, None)
else:
return (constants.QRFS_NORMAL, timestamp)
return fn
def _GetItemTimestampFields(datatype):
"""Returns common timestamp fields.
@param datatype: Field data type for use by L{Query.RequestedData}
"""
return [
(_MakeField("ctime", "CTime", constants.QFT_TIMESTAMP), datatype,
_GetItemTimestamp(operator.attrgetter("ctime"))),
(_MakeField("mtime", "MTime", constants.QFT_TIMESTAMP), datatype,
_GetItemTimestamp(operator.attrgetter("mtime"))),
]
class NodeQueryData:
"""Data container for node data queries.
......@@ -313,11 +348,9 @@ class NodeQueryData:
#: Fields that are direct attributes of an L{objects.Node} object
_NODE_SIMPLE_FIELDS = {
"ctime": ("CTime", constants.QFT_TIMESTAMP),
"drained": ("Drained", constants.QFT_BOOL),
"master_candidate": ("MasterC", constants.QFT_BOOL),
"master_capable": ("MasterCapable", constants.QFT_BOOL),
"mtime": ("MTime", constants.QFT_TIMESTAMP),
"name": ("Node", constants.QFT_TEXT),
"offline": ("Offline", constants.QFT_BOOL),
"serial_no": ("SerialNo", constants.QFT_NUMBER),
......@@ -439,6 +472,9 @@ def _BuildNodeFields():
for (name, (title, kind, nfield)) in _NODE_LIVE_FIELDS.items()
])
# Add timestamps
fields.extend(_GetItemTimestampFields(NQ_CONFIG))
return _PrepareFieldList(fields)
......@@ -876,10 +912,8 @@ def _GetInstanceParameterFields():
_INST_SIMPLE_FIELDS = {
"ctime": ("CTime", constants.QFT_TIMESTAMP),
"disk_template": ("Disk_template", constants.QFT_TEXT),
"hypervisor": ("Hypervisor", constants.QFT_TEXT),
"mtime": ("MTime", constants.QFT_TIMESTAMP),
"name": ("Node", constants.QFT_TEXT),
# Depending on the hypervisor, the port can be None
"network_port": ("Network_port", constants.QFT_OTHER),
......@@ -923,6 +957,7 @@ def _BuildInstanceFields():
fields.extend(_GetInstanceParameterFields())
fields.extend(_GetInstanceDiskFields())
fields.extend(_GetInstanceNetworkFields())
fields.extend(_GetItemTimestampFields(IQ_CONFIG))
return _PrepareFieldList(fields)
......
......@@ -337,6 +337,8 @@ class TestNodeQuery(unittest.TestCase):
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]
......@@ -392,6 +394,10 @@ class TestNodeQuery(unittest.TestCase):
(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
......@@ -401,7 +407,11 @@ class TestNodeQuery(unittest.TestCase):
master_name) and
(node.name == master_name or
(row[field_index["group"]] == "<unknown>" and
row[field_index["group.uuid"]] is None))
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]]
......@@ -606,8 +616,18 @@ class TestInstanceQuery(unittest.TestCase):
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}
......@@ -717,6 +737,14 @@ class TestInstanceQuery(unittest.TestCase):
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",
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment