X-Git-Url: https://code.grnet.gr/git/ganeti-local/blobdiff_plain/b288b6f32a169d776bd4fbe1fe4dbee3007d60db..bfceedbe:/lib/query.py diff --git a/lib/query.py b/lib/query.py index 21caea6..35f6d27 100644 --- a/lib/query.py +++ b/lib/query.py @@ -1,7 +1,7 @@ # # -# Copyright (C) 2010 Google Inc. +# Copyright (C) 2010, 2011 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 @@ -19,7 +19,36 @@ # 02110-1301, USA. -"""Module for query operations""" +"""Module for query operations + +How it works: + + - Add field definitions + - See how L{NODE_FIELDS} is built + - Each field gets: + - Query field definition (L{objects.QueryFieldDefinition}, use + L{_MakeField} for creating), containing: + - Name, must be lowercase and match L{FIELD_NAME_RE} + - Title for tables, must not contain whitespace and match + L{TITLE_RE} + - Value data type, e.g. L{constants.QFT_NUMBER} + - Data request type, see e.g. C{NQ_*} + - A retrieval function, see L{Query.__init__} for description + - Pass list of fields through L{_PrepareFieldList} for preparation and + checks + - Instantiate L{Query} with prepared field list definition and selected fields + - Call L{Query.RequestedData} to determine what data to collect/compute + - Call L{Query.Query} or L{Query.OldStyleQuery} with collected data and use + result + - Data container must support iteration using C{__iter__} + - Items are passed to retrieval functions and can have any format + - Call L{Query.GetFields} to get list of definitions for selected fields + +@attention: Retrieval functions must be idempotent. They can be called multiple + times, in any order and any number of times. This is important to keep in + mind for implementing filters in the future. + +""" import logging import operator @@ -32,6 +61,15 @@ from ganeti import compat from ganeti import objects from ganeti import ht +from ganeti.constants import (QFT_UNKNOWN, QFT_TEXT, QFT_BOOL, QFT_NUMBER, + QFT_UNIT, QFT_TIMESTAMP, QFT_OTHER, + RS_NORMAL, RS_UNKNOWN, RS_NODATA, + RS_UNAVAIL, RS_OFFLINE) + + +# Constants for requesting data from the caller/data provider. Each property +# collected/computed separately by the data provider should have its own to +# only collect the requested data and not more. (NQ_CONFIG, NQ_INST, @@ -57,13 +95,29 @@ TITLE_RE = re.compile(r"^[^\s]+$") #: Verification function for each field type _VERIFY_FN = { - constants.QFT_UNKNOWN: ht.TNone, - constants.QFT_TEXT: ht.TString, - constants.QFT_BOOL: ht.TBool, - constants.QFT_NUMBER: ht.TInt, - constants.QFT_UNIT: ht.TInt, - constants.QFT_TIMESTAMP: ht.TOr(ht.TInt, ht.TFloat), - constants.QFT_OTHER: lambda _: True, + QFT_UNKNOWN: ht.TNone, + QFT_TEXT: ht.TString, + QFT_BOOL: ht.TBool, + QFT_NUMBER: ht.TInt, + QFT_UNIT: ht.TInt, + QFT_TIMESTAMP: ht.TOr(ht.TInt, ht.TFloat), + QFT_OTHER: lambda _: True, + } + +# Unique objects for special field statuses +_FS_UNKNOWN = object() +_FS_NODATA = object() +_FS_UNAVAIL = object() +_FS_OFFLINE = object() + +#: VType to QFT mapping +_VTToQFT = { + # TODO: fix validation of empty strings + constants.VTYPE_STRING: QFT_OTHER, # since VTYPE_STRINGs can be empty + constants.VTYPE_MAYBE_STRING: QFT_OTHER, + constants.VTYPE_BOOL: QFT_BOOL, + constants.VTYPE_SIZE: QFT_UNIT, + constants.VTYPE_INT: QFT_NUMBER, } @@ -71,7 +125,7 @@ def _GetUnknownField(ctx, item): # pylint: disable-msg=W0613 """Gets the contents of an unknown field. """ - return (constants.QRFS_UNKNOWN, None) + return _FS_UNKNOWN def _GetQueryFields(fielddefs, selected): @@ -91,8 +145,7 @@ def _GetQueryFields(fielddefs, selected): try: fdef = fielddefs[name] except KeyError: - fdef = (_MakeField(name, name, constants.QFT_UNKNOWN), - None, _GetUnknownField) + fdef = (_MakeField(name, name, QFT_UNKNOWN), None, _GetUnknownField) assert len(fdef) == 3 @@ -159,15 +212,13 @@ class Query: support iteration using C{__iter__} """ - result = [[fn(ctx, item) for (_, _, fn) in self._fields] + result = [[_ProcessResult(fn(ctx, item)) for (_, _, fn) in self._fields] for item in ctx] # Verify result if __debug__: - for (idx, row) in enumerate(result): - assert _VerifyResultRow(self._fields, row), \ - ("Inconsistent result for fields %s in row %s: %r" % - (GetAllFields(self._fields), idx, row)) + for row in result: + _VerifyResultRow(self._fields, row) return result @@ -178,8 +229,7 @@ class Query: """ unknown = set(fdef.name - for (fdef, _, _) in self._fields - if fdef.kind == constants.QFT_UNKNOWN) + for (fdef, _, _) in self._fields if fdef.kind == QFT_UNKNOWN) if unknown: raise errors.OpPrereqError("Unknown output fields selected: %s" % (utils.CommaJoin(unknown), ), @@ -189,6 +239,22 @@ class Query: for row in self.Query(ctx)] +def _ProcessResult(value): + """Converts result values into externally-visible ones. + + """ + if value is _FS_UNKNOWN: + return (RS_UNKNOWN, None) + elif value is _FS_NODATA: + return (RS_NODATA, None) + elif value is _FS_UNAVAIL: + return (RS_UNAVAIL, None) + elif value is _FS_OFFLINE: + return (RS_OFFLINE, None) + else: + return (RS_NORMAL, value) + + def _VerifyResultRow(fields, row): """Verifies the contents of a query result row. @@ -198,22 +264,31 @@ def _VerifyResultRow(fields, row): @param row: Row data """ - return (len(row) == len(fields) and - compat.all((status == constants.QRFS_NORMAL and - _VERIFY_FN[fdef.kind](value)) or - # Value for an abnormal status must be None - (status != constants.QRFS_NORMAL and value is None) - for ((status, value), (fdef, _, _)) in zip(row, fields))) - - -def _PrepareFieldList(fields): + assert len(row) == len(fields) + errs = [] + for ((status, value), (fdef, _, _)) in zip(row, fields): + if status == RS_NORMAL: + if not _VERIFY_FN[fdef.kind](value): + errs.append("normal field %s fails validation (value is %s)" % + (fdef.name, value)) + elif value is not None: + errs.append("abnormal field %s has a non-None value" % fdef.name) + assert not errs, ("Failed validation: %s in row %s" % + (utils.CommaJoin(errors), row)) + + +def _PrepareFieldList(fields, aliases): """Prepares field list for use by L{Query}. Converts the list to a dictionary and does some verification. - @type fields: list of tuples; (L{objects.QueryFieldDefinition}, data kind, - retrieval function) - @param fields: List of fields + @type fields: list of tuples; (L{objects.QueryFieldDefinition}, data + kind, retrieval function) + @param fields: List of fields, see L{Query.__init__} for a better + description + @type aliases: list of tuples; (alias, target) + @param aliases: list of tuples containing aliases; for each + alias/target pair, a duplicate will be created in the field list @rtype: dict @return: Field dictionary for L{Query} @@ -237,7 +312,15 @@ def _PrepareFieldList(fields): result[fdef.name] = field - assert len(result) == len(fields) + for alias, target in aliases: + assert alias not in result, "Alias %s overrides an existing field" % alias + assert target in result, "Missing target %s for alias %s" % (target, alias) + (fdef, k, fn) = result[target] + fdef = fdef.Copy() + fdef.name = alias + result[alias] = (fdef, k, fn) + + assert len(result) == len(fields) + len(aliases) assert compat.all(name == fdef.name for (name, (fdef, _, _)) in result.items()) @@ -315,7 +398,7 @@ def _GetItemAttr(attr): """ getter = operator.attrgetter(attr) - return lambda _, item: (constants.QRFS_NORMAL, getter(item)) + return lambda _, item: getter(item) def _GetItemTimestamp(getter): @@ -332,9 +415,9 @@ def _GetItemTimestamp(getter): timestamp = getter(item) if timestamp is None: # Old configs might not have all timestamps - return (constants.QRFS_UNAVAIL, None) + return _FS_UNAVAIL else: - return (constants.QRFS_NORMAL, timestamp) + return timestamp return fn @@ -346,9 +429,9 @@ def _GetItemTimestampFields(datatype): """ return [ - (_MakeField("ctime", "CTime", constants.QFT_TIMESTAMP), datatype, + (_MakeField("ctime", "CTime", QFT_TIMESTAMP), datatype, _GetItemTimestamp(operator.attrgetter("ctime"))), - (_MakeField("mtime", "MTime", constants.QFT_TIMESTAMP), datatype, + (_MakeField("mtime", "MTime", QFT_TIMESTAMP), datatype, _GetItemTimestamp(operator.attrgetter("mtime"))), ] @@ -391,28 +474,28 @@ class NodeQueryData: #: Fields that are direct attributes of an L{objects.Node} object _NODE_SIMPLE_FIELDS = { - "drained": ("Drained", constants.QFT_BOOL), - "master_candidate": ("MasterC", constants.QFT_BOOL), - "master_capable": ("MasterCapable", constants.QFT_BOOL), - "name": ("Node", constants.QFT_TEXT), - "offline": ("Offline", constants.QFT_BOOL), - "serial_no": ("SerialNo", constants.QFT_NUMBER), - "uuid": ("UUID", constants.QFT_TEXT), - "vm_capable": ("VMCapable", constants.QFT_BOOL), + "drained": ("Drained", QFT_BOOL), + "master_candidate": ("MasterC", QFT_BOOL), + "master_capable": ("MasterCapable", QFT_BOOL), + "name": ("Node", QFT_TEXT), + "offline": ("Offline", QFT_BOOL), + "serial_no": ("SerialNo", QFT_NUMBER), + "uuid": ("UUID", QFT_TEXT), + "vm_capable": ("VMCapable", QFT_BOOL), } #: Fields requiring talking to the node _NODE_LIVE_FIELDS = { - "bootid": ("BootID", constants.QFT_TEXT, "bootid"), - "cnodes": ("CNodes", constants.QFT_NUMBER, "cpu_nodes"), - "csockets": ("CSockets", constants.QFT_NUMBER, "cpu_sockets"), - "ctotal": ("CTotal", constants.QFT_NUMBER, "cpu_total"), - "dfree": ("DFree", constants.QFT_UNIT, "vg_free"), - "dtotal": ("DTotal", constants.QFT_UNIT, "vg_size"), - "mfree": ("MFree", constants.QFT_UNIT, "memory_free"), - "mnode": ("MNode", constants.QFT_UNIT, "memory_dom0"), - "mtotal": ("MTotal", constants.QFT_UNIT, "memory_total"), + "bootid": ("BootID", QFT_TEXT, "bootid"), + "cnodes": ("CNodes", QFT_NUMBER, "cpu_nodes"), + "csockets": ("CSockets", QFT_NUMBER, "cpu_sockets"), + "ctotal": ("CTotal", QFT_NUMBER, "cpu_total"), + "dfree": ("DFree", QFT_UNIT, "vg_free"), + "dtotal": ("DTotal", QFT_UNIT, "vg_size"), + "mfree": ("MFree", QFT_UNIT, "memory_free"), + "mnode": ("MNode", QFT_UNIT, "memory_dom0"), + "mtotal": ("MTotal", QFT_UNIT, "memory_total"), } @@ -433,7 +516,7 @@ def _GetGroup(cb): ng = ctx.groups.get(node.group, None) if ng is None: # Nodes always have a group, or the configuration is corrupt - return (constants.QRFS_UNAVAIL, None) + return _FS_UNAVAIL return cb(ctx, node, ng) @@ -450,7 +533,7 @@ def _GetNodeGroup(ctx, node, ng): # pylint: disable-msg=W0613 @param ng: The node group this node belongs to """ - return (constants.QRFS_NORMAL, ng.name) + return ng.name def _GetNodePower(ctx, node): @@ -462,9 +545,9 @@ def _GetNodePower(ctx, node): """ if ctx.oob_support[node.name]: - return (constants.QRFS_NORMAL, node.powered) + return node.powered - return (constants.QRFS_UNAVAIL, None) + return _FS_UNAVAIL def _GetNdParams(ctx, node, ng): @@ -477,7 +560,7 @@ def _GetNdParams(ctx, node, ng): @param ng: The node group this node belongs to """ - return (constants.QRFS_NORMAL, ctx.cluster.SimpleFillND(ng.FillND(node))) + return ctx.cluster.SimpleFillND(ng.FillND(node)) def _GetLiveNodeField(field, kind, ctx, node): @@ -491,28 +574,28 @@ def _GetLiveNodeField(field, kind, ctx, node): """ if node.offline: - return (constants.QRFS_OFFLINE, None) + return _FS_OFFLINE if not ctx.curlive_data: - return (constants.QRFS_NODATA, None) + return _FS_NODATA try: value = ctx.curlive_data[field] except KeyError: - return (constants.QRFS_UNAVAIL, None) + return _FS_UNAVAIL - if kind == constants.QFT_TEXT: - return (constants.QRFS_NORMAL, value) + if kind == QFT_TEXT: + return value - assert kind in (constants.QFT_NUMBER, constants.QFT_UNIT) + assert kind in (QFT_NUMBER, QFT_UNIT) # Try to convert into number try: - return (constants.QRFS_NORMAL, int(value)) + return int(value) except (ValueError, TypeError): logging.exception("Failed to convert node field '%s' (value %r) to int", value, field) - return (constants.QRFS_UNAVAIL, None) + return _FS_UNAVAIL def _BuildNodeFields(): @@ -520,47 +603,42 @@ def _BuildNodeFields(): """ fields = [ - (_MakeField("pip", "PrimaryIP", constants.QFT_TEXT), NQ_CONFIG, - lambda ctx, node: (constants.QRFS_NORMAL, node.primary_ip)), - (_MakeField("sip", "SecondaryIP", constants.QFT_TEXT), NQ_CONFIG, - lambda ctx, node: (constants.QRFS_NORMAL, node.secondary_ip)), - (_MakeField("tags", "Tags", constants.QFT_OTHER), NQ_CONFIG, - lambda ctx, node: (constants.QRFS_NORMAL, list(node.GetTags()))), - (_MakeField("master", "IsMaster", constants.QFT_BOOL), NQ_CONFIG, - lambda ctx, node: (constants.QRFS_NORMAL, node.name == ctx.master_name)), - (_MakeField("role", "Role", constants.QFT_TEXT), NQ_CONFIG, - lambda ctx, node: (constants.QRFS_NORMAL, - _GetNodeRole(node, ctx.master_name))), - (_MakeField("group", "Group", constants.QFT_TEXT), NQ_GROUP, + (_MakeField("pip", "PrimaryIP", QFT_TEXT), NQ_CONFIG, + _GetItemAttr("primary_ip")), + (_MakeField("sip", "SecondaryIP", QFT_TEXT), NQ_CONFIG, + _GetItemAttr("secondary_ip")), + (_MakeField("tags", "Tags", QFT_OTHER), NQ_CONFIG, + lambda ctx, node: list(node.GetTags())), + (_MakeField("master", "IsMaster", QFT_BOOL), NQ_CONFIG, + lambda ctx, node: node.name == ctx.master_name), + (_MakeField("role", "Role", QFT_TEXT), NQ_CONFIG, + lambda ctx, node: _GetNodeRole(node, ctx.master_name)), + (_MakeField("group", "Group", QFT_TEXT), NQ_GROUP, _GetGroup(_GetNodeGroup)), - (_MakeField("group.uuid", "GroupUUID", constants.QFT_TEXT), - NQ_CONFIG, lambda ctx, node: (constants.QRFS_NORMAL, node.group)), - (_MakeField("powered", "Powered", constants.QFT_BOOL), NQ_OOB, - _GetNodePower), - (_MakeField("ndparams", "NodeParameters", constants.QFT_OTHER), NQ_GROUP, + (_MakeField("group.uuid", "GroupUUID", QFT_TEXT), + NQ_CONFIG, _GetItemAttr("group")), + (_MakeField("powered", "Powered", QFT_BOOL), NQ_OOB, _GetNodePower), + (_MakeField("ndparams", "NodeParameters", QFT_OTHER), NQ_GROUP, _GetGroup(_GetNdParams)), - (_MakeField("custom_ndparams", "CustomNodeParameters", constants.QFT_OTHER), - NQ_GROUP, lambda ctx, node: (constants.QRFS_NORMAL, node.ndparams)), + (_MakeField("custom_ndparams", "CustomNodeParameters", QFT_OTHER), + NQ_GROUP, _GetItemAttr("ndparams")), ] def _GetLength(getter): - return lambda ctx, node: (constants.QRFS_NORMAL, - len(getter(ctx)[node.name])) + return lambda ctx, node: len(getter(ctx)[node.name]) def _GetList(getter): - return lambda ctx, node: (constants.QRFS_NORMAL, - list(getter(ctx)[node.name])) + return lambda ctx, node: list(getter(ctx)[node.name]) # Add fields operating on instance lists for prefix, titleprefix, getter in \ [("p", "Pri", operator.attrgetter("node_to_primary")), ("s", "Sec", operator.attrgetter("node_to_secondary"))]: fields.extend([ - (_MakeField("%sinst_cnt" % prefix, "%sinst" % prefix.upper(), - constants.QFT_NUMBER), + (_MakeField("%sinst_cnt" % prefix, "%sinst" % prefix.upper(), QFT_NUMBER), NQ_INST, _GetLength(getter)), (_MakeField("%sinst_list" % prefix, "%sInstances" % titleprefix, - constants.QFT_OTHER), + QFT_OTHER), NQ_INST, _GetList(getter)), ]) @@ -578,7 +656,7 @@ def _BuildNodeFields(): # Add timestamps fields.extend(_GetItemTimestampFields(NQ_CONFIG)) - return _PrepareFieldList(fields) + return _PrepareFieldList(fields, []) class InstanceQueryData: @@ -642,12 +720,12 @@ def _GetInstOperState(ctx, inst): @param inst: Instance object """ - # Can't use QRFS_OFFLINE here as it would describe the instance to be offline - # when we actually don't know due to missing data + # Can't use RS_OFFLINE here as it would describe the instance to + # be offline when we actually don't know due to missing data if inst.primary_node in ctx.bad_nodes: - return (constants.QRFS_NODATA, None) + return _FS_NODATA else: - return (constants.QRFS_NORMAL, bool(ctx.live_data.get(inst.name))) + return bool(ctx.live_data.get(inst.name)) def _GetInstLiveData(name): @@ -667,16 +745,16 @@ def _GetInstLiveData(name): """ if (inst.primary_node in ctx.bad_nodes or inst.primary_node in ctx.offline_nodes): - # Can't use QRFS_OFFLINE here as it would describe the instance to be + # Can't use RS_OFFLINE here as it would describe the instance to be # offline when we actually don't know due to missing data - return (constants.QRFS_NODATA, None) + return _FS_NODATA if inst.name in ctx.live_data: data = ctx.live_data[inst.name] if name in data: - return (constants.QRFS_NORMAL, data[name]) + return data[name] - return (constants.QRFS_UNAVAIL, None) + return _FS_UNAVAIL return fn @@ -690,21 +768,21 @@ def _GetInstStatus(ctx, inst): """ if inst.primary_node in ctx.offline_nodes: - return (constants.QRFS_NORMAL, "ERROR_nodeoffline") + return "ERROR_nodeoffline" if inst.primary_node in ctx.bad_nodes: - return (constants.QRFS_NORMAL, "ERROR_nodedown") + return "ERROR_nodedown" if bool(ctx.live_data.get(inst.name)): if inst.admin_up: - return (constants.QRFS_NORMAL, "running") + return "running" else: - return (constants.QRFS_NORMAL, "ERROR_up") + return "ERROR_up" if inst.admin_up: - return (constants.QRFS_NORMAL, "ERROR_down") + return "ERROR_down" - return (constants.QRFS_NORMAL, "ADMIN_down") + return "ADMIN_down" def _GetInstDiskSize(index): @@ -722,9 +800,9 @@ def _GetInstDiskSize(index): """ try: - return (constants.QRFS_NORMAL, inst.disks[index].size) + return inst.disks[index].size except IndexError: - return (constants.QRFS_UNAVAIL, None) + return _FS_UNAVAIL return fn @@ -749,7 +827,7 @@ def _GetInstNic(index, cb): try: nic = inst.nics[index] except IndexError: - return (constants.QRFS_UNAVAIL, None) + return _FS_UNAVAIL return cb(ctx, index, nic) @@ -765,9 +843,9 @@ def _GetInstNicIp(ctx, _, nic): # pylint: disable-msg=W0613 """ if nic.ip is None: - return (constants.QRFS_UNAVAIL, None) + return _FS_UNAVAIL else: - return (constants.QRFS_NORMAL, nic.ip) + return nic.ip def _GetInstNicBridge(ctx, index, _): @@ -783,9 +861,9 @@ def _GetInstNicBridge(ctx, index, _): nicparams = ctx.inst_nicparams[index] if nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED: - return (constants.QRFS_NORMAL, nicparams[constants.NIC_LINK]) + return nicparams[constants.NIC_LINK] else: - return (constants.QRFS_UNAVAIL, None) + return _FS_UNAVAIL def _GetInstAllNicBridges(ctx, inst): @@ -808,7 +886,7 @@ def _GetInstAllNicBridges(ctx, inst): assert len(result) == len(inst.nics) - return (constants.QRFS_NORMAL, result) + return result def _GetInstNicParam(name): @@ -829,7 +907,7 @@ def _GetInstNicParam(name): """ assert len(ctx.inst_nicparams) >= index - return (constants.QRFS_NORMAL, ctx.inst_nicparams[index][name]) + return ctx.inst_nicparams[index][name] return fn @@ -840,54 +918,52 @@ def _GetInstanceNetworkFields(): @return: List of field definitions used as input for L{_PrepareFieldList} """ - nic_mac_fn = lambda ctx, _, nic: (constants.QRFS_NORMAL, nic.mac) + nic_mac_fn = lambda ctx, _, nic: nic.mac nic_mode_fn = _GetInstNicParam(constants.NIC_MODE) nic_link_fn = _GetInstNicParam(constants.NIC_LINK) fields = [ # First NIC (legacy) - (_MakeField("ip", "IP_address", constants.QFT_TEXT), IQ_CONFIG, + (_MakeField("ip", "IP_address", QFT_TEXT), IQ_CONFIG, _GetInstNic(0, _GetInstNicIp)), - (_MakeField("mac", "MAC_address", constants.QFT_TEXT), IQ_CONFIG, + (_MakeField("mac", "MAC_address", QFT_TEXT), IQ_CONFIG, _GetInstNic(0, nic_mac_fn)), - (_MakeField("bridge", "Bridge", constants.QFT_TEXT), IQ_CONFIG, + (_MakeField("bridge", "Bridge", QFT_TEXT), IQ_CONFIG, _GetInstNic(0, _GetInstNicBridge)), - (_MakeField("nic_mode", "NIC_Mode", constants.QFT_TEXT), IQ_CONFIG, + (_MakeField("nic_mode", "NIC_Mode", QFT_TEXT), IQ_CONFIG, _GetInstNic(0, nic_mode_fn)), - (_MakeField("nic_link", "NIC_Link", constants.QFT_TEXT), IQ_CONFIG, + (_MakeField("nic_link", "NIC_Link", QFT_TEXT), IQ_CONFIG, _GetInstNic(0, nic_link_fn)), # All NICs - (_MakeField("nic.count", "NICs", constants.QFT_NUMBER), IQ_CONFIG, - lambda ctx, inst: (constants.QRFS_NORMAL, len(inst.nics))), - (_MakeField("nic.macs", "NIC_MACs", constants.QFT_OTHER), IQ_CONFIG, - lambda ctx, inst: (constants.QRFS_NORMAL, [nic.mac for nic in inst.nics])), - (_MakeField("nic.ips", "NIC_IPs", constants.QFT_OTHER), IQ_CONFIG, - lambda ctx, inst: (constants.QRFS_NORMAL, [nic.ip for nic in inst.nics])), - (_MakeField("nic.modes", "NIC_modes", constants.QFT_OTHER), IQ_CONFIG, - lambda ctx, inst: (constants.QRFS_NORMAL, - [nicp[constants.NIC_MODE] - for nicp in ctx.inst_nicparams])), - (_MakeField("nic.links", "NIC_links", constants.QFT_OTHER), IQ_CONFIG, - lambda ctx, inst: (constants.QRFS_NORMAL, - [nicp[constants.NIC_LINK] - for nicp in ctx.inst_nicparams])), - (_MakeField("nic.bridges", "NIC_bridges", constants.QFT_OTHER), IQ_CONFIG, + (_MakeField("nic.count", "NICs", QFT_NUMBER), IQ_CONFIG, + lambda ctx, inst: len(inst.nics)), + (_MakeField("nic.macs", "NIC_MACs", QFT_OTHER), IQ_CONFIG, + lambda ctx, inst: [nic.mac for nic in inst.nics]), + (_MakeField("nic.ips", "NIC_IPs", QFT_OTHER), IQ_CONFIG, + lambda ctx, inst: [nic.ip for nic in inst.nics]), + (_MakeField("nic.modes", "NIC_modes", QFT_OTHER), IQ_CONFIG, + lambda ctx, inst: [nicp[constants.NIC_MODE] + for nicp in ctx.inst_nicparams]), + (_MakeField("nic.links", "NIC_links", QFT_OTHER), IQ_CONFIG, + lambda ctx, inst: [nicp[constants.NIC_LINK] + for nicp in ctx.inst_nicparams]), + (_MakeField("nic.bridges", "NIC_bridges", QFT_OTHER), IQ_CONFIG, _GetInstAllNicBridges), ] # NICs by number for i in range(constants.MAX_NICS): fields.extend([ - (_MakeField("nic.ip/%s" % i, "NicIP/%s" % i, constants.QFT_TEXT), + (_MakeField("nic.ip/%s" % i, "NicIP/%s" % i, QFT_TEXT), IQ_CONFIG, _GetInstNic(i, _GetInstNicIp)), - (_MakeField("nic.mac/%s" % i, "NicMAC/%s" % i, constants.QFT_TEXT), + (_MakeField("nic.mac/%s" % i, "NicMAC/%s" % i, QFT_TEXT), IQ_CONFIG, _GetInstNic(i, nic_mac_fn)), - (_MakeField("nic.mode/%s" % i, "NicMode/%s" % i, constants.QFT_TEXT), + (_MakeField("nic.mode/%s" % i, "NicMode/%s" % i, QFT_TEXT), IQ_CONFIG, _GetInstNic(i, nic_mode_fn)), - (_MakeField("nic.link/%s" % i, "NicLink/%s" % i, constants.QFT_TEXT), + (_MakeField("nic.link/%s" % i, "NicLink/%s" % i, QFT_TEXT), IQ_CONFIG, _GetInstNic(i, nic_link_fn)), - (_MakeField("nic.bridge/%s" % i, "NicBridge/%s" % i, constants.QFT_TEXT), + (_MakeField("nic.bridge/%s" % i, "NicBridge/%s" % i, QFT_TEXT), IQ_CONFIG, _GetInstNic(i, _GetInstNicBridge)), ]) @@ -907,7 +983,7 @@ def _GetInstDiskUsage(ctx, inst): if usage is None: usage = 0 - return (constants.QRFS_NORMAL, usage) + return usage def _GetInstanceDiskFields(): @@ -917,22 +993,17 @@ def _GetInstanceDiskFields(): """ fields = [ - (_MakeField("disk_usage", "DiskUsage", constants.QFT_UNIT), IQ_DISKUSAGE, + (_MakeField("disk_usage", "DiskUsage", QFT_UNIT), IQ_DISKUSAGE, _GetInstDiskUsage), - (_MakeField("sda_size", "LegacyDisk/0", constants.QFT_UNIT), IQ_CONFIG, - _GetInstDiskSize(0)), - (_MakeField("sdb_size", "LegacyDisk/1", constants.QFT_UNIT), IQ_CONFIG, - _GetInstDiskSize(1)), - (_MakeField("disk.count", "Disks", constants.QFT_NUMBER), IQ_CONFIG, - lambda ctx, inst: (constants.QRFS_NORMAL, len(inst.disks))), - (_MakeField("disk.sizes", "Disk_sizes", constants.QFT_OTHER), IQ_CONFIG, - lambda ctx, inst: (constants.QRFS_NORMAL, - [disk.size for disk in inst.disks])), + (_MakeField("disk.count", "Disks", QFT_NUMBER), IQ_CONFIG, + lambda ctx, inst: len(inst.disks)), + (_MakeField("disk.sizes", "Disk_sizes", QFT_OTHER), IQ_CONFIG, + lambda ctx, inst: [disk.size for disk in inst.disks]), ] # Disks by number fields.extend([ - (_MakeField("disk.size/%s" % i, "Disk/%s" % i, constants.QFT_UNIT), + (_MakeField("disk.size/%s" % i, "Disk/%s" % i, QFT_UNIT), IQ_CONFIG, _GetInstDiskSize(i)) for i in range(constants.MAX_DISKS) ]) @@ -949,8 +1020,8 @@ def _GetInstanceParameterFields(): # TODO: Consider moving titles closer to constants be_title = { constants.BE_AUTO_BALANCE: "Auto_balance", - constants.BE_MEMORY: "Configured_memory", - constants.BE_VCPUS: "VCPUs", + constants.BE_MEMORY: "ConfigMemory", + constants.BE_VCPUS: "ConfigVCPUs", } hv_title = { @@ -967,66 +1038,55 @@ def _GetInstanceParameterFields(): fields = [ # Filled parameters - (_MakeField("hvparams", "HypervisorParameters", constants.QFT_OTHER), - IQ_CONFIG, lambda ctx, _: (constants.QRFS_NORMAL, ctx.inst_hvparams)), - (_MakeField("beparams", "BackendParameters", constants.QFT_OTHER), - IQ_CONFIG, lambda ctx, _: (constants.QRFS_NORMAL, ctx.inst_beparams)), - (_MakeField("vcpus", "LegacyVCPUs", constants.QFT_NUMBER), IQ_CONFIG, - lambda ctx, _: (constants.QRFS_NORMAL, - ctx.inst_beparams[constants.BE_VCPUS])), + (_MakeField("hvparams", "HypervisorParameters", QFT_OTHER), + IQ_CONFIG, lambda ctx, _: ctx.inst_hvparams), + (_MakeField("beparams", "BackendParameters", QFT_OTHER), + IQ_CONFIG, lambda ctx, _: ctx.inst_beparams), # Unfilled parameters - (_MakeField("custom_hvparams", "CustomHypervisorParameters", - constants.QFT_OTHER), - IQ_CONFIG, lambda ctx, inst: (constants.QRFS_NORMAL, inst.hvparams)), - (_MakeField("custom_beparams", "CustomBackendParameters", - constants.QFT_OTHER), - IQ_CONFIG, lambda ctx, inst: (constants.QRFS_NORMAL, inst.beparams)), - (_MakeField("custom_nicparams", "CustomNicParameters", - constants.QFT_OTHER), - IQ_CONFIG, lambda ctx, inst: (constants.QRFS_NORMAL, - [nic.nicparams for nic in inst.nics])), + (_MakeField("custom_hvparams", "CustomHypervisorParameters", QFT_OTHER), + IQ_CONFIG, _GetItemAttr("hvparams")), + (_MakeField("custom_beparams", "CustomBackendParameters", QFT_OTHER), + IQ_CONFIG, _GetItemAttr("beparams")), + (_MakeField("custom_nicparams", "CustomNicParameters", QFT_OTHER), + IQ_CONFIG, lambda ctx, inst: [nic.nicparams for nic in inst.nics]), ] # HV params def _GetInstHvParam(name): - return lambda ctx, _: (constants.QRFS_NORMAL, - ctx.inst_hvparams.get(name, None)) + return lambda ctx, _: ctx.inst_hvparams.get(name, _FS_UNAVAIL) fields.extend([ - # For now all hypervisor parameters are exported as QFT_OTHER (_MakeField("hv/%s" % name, hv_title.get(name, "hv/%s" % name), - constants.QFT_OTHER), + _VTToQFT[kind]), IQ_CONFIG, _GetInstHvParam(name)) - for name in constants.HVS_PARAMETERS + for name, kind in constants.HVS_PARAMETER_TYPES.items() if name not in constants.HVC_GLOBALS ]) # BE params def _GetInstBeParam(name): - return lambda ctx, _: (constants.QRFS_NORMAL, - ctx.inst_beparams.get(name, None)) + return lambda ctx, _: ctx.inst_beparams.get(name, None) fields.extend([ - # For now all backend parameters are exported as QFT_OTHER (_MakeField("be/%s" % name, be_title.get(name, "be/%s" % name), - constants.QFT_OTHER), - IQ_CONFIG, _GetInstBeParam(name)) - for name in constants.BES_PARAMETERS + _VTToQFT[kind]), IQ_CONFIG, + _GetInstBeParam(name)) + for name, kind in constants.BES_PARAMETER_TYPES.items() ]) return fields _INST_SIMPLE_FIELDS = { - "disk_template": ("Disk_template", constants.QFT_TEXT), - "hypervisor": ("Hypervisor", constants.QFT_TEXT), - "name": ("Node", constants.QFT_TEXT), + "disk_template": ("Disk_template", QFT_TEXT), + "hypervisor": ("Hypervisor", QFT_TEXT), + "name": ("Node", QFT_TEXT), # Depending on the hypervisor, the port can be None - "network_port": ("Network_port", constants.QFT_OTHER), - "os": ("OS", constants.QFT_TEXT), - "serial_no": ("SerialNo", constants.QFT_NUMBER), - "uuid": ("UUID", constants.QFT_TEXT), + "network_port": ("Network_port", QFT_OTHER), + "os": ("OS", QFT_TEXT), + "serial_no": ("SerialNo", QFT_NUMBER), + "uuid": ("UUID", QFT_TEXT), } @@ -1035,14 +1095,14 @@ def _BuildInstanceFields(): """ fields = [ - (_MakeField("pnode", "Primary_node", constants.QFT_TEXT), IQ_CONFIG, - lambda ctx, inst: (constants.QRFS_NORMAL, inst.primary_node)), - (_MakeField("snodes", "Secondary_Nodes", constants.QFT_OTHER), IQ_CONFIG, - lambda ctx, inst: (constants.QRFS_NORMAL, list(inst.secondary_nodes))), - (_MakeField("admin_state", "Autostart", constants.QFT_BOOL), IQ_CONFIG, - lambda ctx, inst: (constants.QRFS_NORMAL, inst.admin_up)), - (_MakeField("tags", "Tags", constants.QFT_OTHER), IQ_CONFIG, - lambda ctx, inst: (constants.QRFS_NORMAL, list(inst.GetTags()))), + (_MakeField("pnode", "Primary_node", QFT_TEXT), IQ_CONFIG, + _GetItemAttr("primary_node")), + (_MakeField("snodes", "Secondary_Nodes", QFT_OTHER), IQ_CONFIG, + lambda ctx, inst: list(inst.secondary_nodes)), + (_MakeField("admin_state", "Autostart", QFT_BOOL), IQ_CONFIG, + _GetItemAttr("admin_up")), + (_MakeField("tags", "Tags", QFT_OTHER), IQ_CONFIG, + lambda ctx, inst: list(inst.GetTags())), ] # Add simple fields @@ -1051,14 +1111,13 @@ def _BuildInstanceFields(): # Fields requiring talking to the node fields.extend([ - (_MakeField("oper_state", "Running", constants.QFT_BOOL), IQ_LIVE, + (_MakeField("oper_state", "Running", QFT_BOOL), IQ_LIVE, _GetInstOperState), - (_MakeField("oper_ram", "RuntimeMemory", constants.QFT_UNIT), IQ_LIVE, + (_MakeField("oper_ram", "Memory", QFT_UNIT), IQ_LIVE, _GetInstLiveData("memory")), - (_MakeField("oper_vcpus", "RuntimeVCPUs", constants.QFT_NUMBER), IQ_LIVE, + (_MakeField("oper_vcpus", "VCPUs", QFT_NUMBER), IQ_LIVE, _GetInstLiveData("vcpus")), - (_MakeField("status", "Status", constants.QFT_TEXT), IQ_LIVE, - _GetInstStatus), + (_MakeField("status", "Status", QFT_TEXT), IQ_LIVE, _GetInstStatus), ]) fields.extend(_GetInstanceParameterFields()) @@ -1066,7 +1125,13 @@ def _BuildInstanceFields(): fields.extend(_GetInstanceNetworkFields()) fields.extend(_GetItemTimestampFields(IQ_CONFIG)) - return _PrepareFieldList(fields) + aliases = [ + ("vcpus", "be/vcpus"), + ("sda_size", "disk.size/0"), + ("sdb_size", "disk.size/1"), + ] + + return _PrepareFieldList(fields, aliases) class LockQueryData: @@ -1095,7 +1160,7 @@ def _GetLockOwners(_, data): if owners: owners = utils.NiceSort(owners) - return (constants.QRFS_NORMAL, owners) + return owners def _GetLockPending(_, data): @@ -1108,7 +1173,7 @@ def _GetLockPending(_, data): pending = [(mode, utils.NiceSort(names)) for (mode, names) in pending] - return (constants.QRFS_NORMAL, pending) + return pending def _BuildLockFields(): @@ -1116,15 +1181,13 @@ def _BuildLockFields(): """ return _PrepareFieldList([ - (_MakeField("name", "Name", constants.QFT_TEXT), None, - lambda ctx, (name, mode, owners, pending): (constants.QRFS_NORMAL, name)), - (_MakeField("mode", "Mode", constants.QFT_OTHER), LQ_MODE, - lambda ctx, (name, mode, owners, pending): (constants.QRFS_NORMAL, mode)), - (_MakeField("owner", "Owner", constants.QFT_OTHER), LQ_OWNER, - _GetLockOwners), - (_MakeField("pending", "Pending", constants.QFT_OTHER), LQ_PENDING, - _GetLockPending), - ]) + (_MakeField("name", "Name", QFT_TEXT), None, + lambda ctx, (name, mode, owners, pending): name), + (_MakeField("mode", "Mode", QFT_OTHER), LQ_MODE, + lambda ctx, (name, mode, owners, pending): mode), + (_MakeField("owner", "Owner", QFT_OTHER), LQ_OWNER, _GetLockOwners), + (_MakeField("pending", "Pending", QFT_OTHER), LQ_PENDING, _GetLockPending), + ], []) class GroupQueryData: @@ -1153,11 +1216,11 @@ class GroupQueryData: _GROUP_SIMPLE_FIELDS = { - "alloc_policy": ("AllocPolicy", constants.QFT_TEXT), - "name": ("Group", constants.QFT_TEXT), - "serial_no": ("SerialNo", constants.QFT_NUMBER), - "uuid": ("UUID", constants.QFT_TEXT), - "ndparams": ("NDParams", constants.QFT_OTHER), + "alloc_policy": ("AllocPolicy", QFT_TEXT), + "name": ("Group", QFT_TEXT), + "serial_no": ("SerialNo", QFT_NUMBER), + "uuid": ("UUID", QFT_TEXT), + "ndparams": ("NDParams", QFT_OTHER), } @@ -1170,35 +1233,33 @@ def _BuildGroupFields(): for (name, (title, kind)) in _GROUP_SIMPLE_FIELDS.items()] def _GetLength(getter): - return lambda ctx, group: (constants.QRFS_NORMAL, - len(getter(ctx)[group.uuid])) + return lambda ctx, group: len(getter(ctx)[group.uuid]) def _GetSortedList(getter): - return lambda ctx, group: (constants.QRFS_NORMAL, - utils.NiceSort(getter(ctx)[group.uuid])) + return lambda ctx, group: utils.NiceSort(getter(ctx)[group.uuid]) group_to_nodes = operator.attrgetter("group_to_nodes") group_to_instances = operator.attrgetter("group_to_instances") # Add fields for nodes fields.extend([ - (_MakeField("node_cnt", "Nodes", constants.QFT_NUMBER), + (_MakeField("node_cnt", "Nodes", QFT_NUMBER), GQ_NODE, _GetLength(group_to_nodes)), - (_MakeField("node_list", "NodeList", constants.QFT_OTHER), + (_MakeField("node_list", "NodeList", QFT_OTHER), GQ_NODE, _GetSortedList(group_to_nodes)), ]) # Add fields for instances fields.extend([ - (_MakeField("pinst_cnt", "Instances", constants.QFT_NUMBER), + (_MakeField("pinst_cnt", "Instances", QFT_NUMBER), GQ_INST, _GetLength(group_to_instances)), - (_MakeField("pinst_list", "InstanceList", constants.QFT_OTHER), + (_MakeField("pinst_list", "InstanceList", QFT_OTHER), GQ_INST, _GetSortedList(group_to_instances)), ]) fields.extend(_GetItemTimestampFields(GQ_CONFIG)) - return _PrepareFieldList(fields) + return _PrepareFieldList(fields, []) #: Fields available for node queries