RS_NORMAL, RS_UNKNOWN, RS_NODATA,
RS_UNAVAIL, RS_OFFLINE)
+(NETQ_CONFIG,
+ NETQ_GROUP,
+ NETQ_STATS,
+ NETQ_INST) = range(300, 304)
# Constants for requesting data from the caller/data provider. Each property
# collected/computed separately by the data provider should have its own to
# Add simple fields
fields.extend([
(_MakeField(name, title, kind, doc), NQ_CONFIG, flags, _GetItemAttr(name))
- for (name, (title, kind, flags, doc)) in _NODE_SIMPLE_FIELDS.items()
- ])
+ for (name, (title, kind, flags, doc)) in _NODE_SIMPLE_FIELDS.items()])
# Add fields requiring live data
fields.extend([
(_MakeField(name, title, kind, doc), NQ_LIVE, 0,
compat.partial(_GetLiveNodeField, nfield, kind))
- for (name, (title, kind, nfield, doc)) in _NODE_LIVE_FIELDS.items()
- ])
+ for (name, (title, kind, nfield, doc)) in _NODE_LIVE_FIELDS.items()])
# Add timestamps
fields.extend(_GetItemTimestampFields(NQ_CONFIG))
return fn
+def _GetInstNicNetwork(ctx, _, nic): # pylint: disable=W0613
+ """Get a NIC's Network.
+
+ @type ctx: L{InstanceQueryData}
+ @type nic: L{objects.NIC}
+ @param nic: NIC object
+
+ """
+ if nic.network is None:
+ return _FS_UNAVAIL
+ else:
+ return nic.network
+
+
def _GetInstNicIp(ctx, _, nic): # pylint: disable=W0613
"""Get a NIC's IP address.
(_MakeField("nic.bridges", "NIC_bridges", QFT_OTHER,
"List containing each network interface's bridge"),
IQ_CONFIG, 0, _GetInstAllNicBridges),
+ (_MakeField("nic.networks", "NIC_networks", QFT_OTHER,
+ "List containing each interface's network"), IQ_CONFIG, 0,
+ lambda ctx, inst: [nic.network for nic in inst.nics]),
]
# NICs by number
(_MakeField("nic.bridge/%s" % i, "NicBridge/%s" % i, QFT_TEXT,
"Bridge of %s network interface" % numtext),
IQ_CONFIG, 0, _GetInstNic(i, _GetInstNicBridge)),
+ (_MakeField("nic.network/%s" % i, "NicNetwork/%s" % i, QFT_TEXT,
+ "Network of %s network interface" % numtext),
+ IQ_CONFIG, 0, _GetInstNic(i, _GetInstNicNetwork)),
])
aliases = [
("bridge", "nic.bridge/0"),
("nic_mode", "nic.mode/0"),
("nic_link", "nic.link/0"),
+ ("nic_network", "nic.network/0"),
]
return (fields, aliases)
(_MakeField("disk.size/%s" % i, "Disk/%s" % i, QFT_UNIT,
"Disk size of %s disk" % utils.FormatOrdinal(i + 1)),
IQ_CONFIG, 0, _GetInstDiskSize(i))
- for i in range(constants.MAX_DISKS)
- ])
+ for i in range(constants.MAX_DISKS)])
return fields
_VTToQFT[kind], "The \"%s\" hypervisor parameter" % name),
IQ_CONFIG, 0, _GetInstHvParam(name))
for name, kind in constants.HVS_PARAMETER_TYPES.items()
- if name not in constants.HVC_GLOBALS
- ])
+ if name not in constants.HVC_GLOBALS])
# BE params
def _GetInstBeParam(name):
constants.BES_PARAMETER_TITLES.get(name, "be/%s" % name),
_VTToQFT[kind], "The \"%s\" backend parameter" % name),
IQ_CONFIG, 0, _GetInstBeParam(name))
- for name, kind in constants.BES_PARAMETER_TYPES.items()
- ])
+ for name, kind in constants.BES_PARAMETER_TYPES.items()])
return fields
# Add simple fields
fields.extend([
(_MakeField(name, title, kind, doc), IQ_CONFIG, flags, _GetItemAttr(name))
- for (name, (title, kind, flags, doc)) in _INST_SIMPLE_FIELDS.items()
- ])
+ for (name, (title, kind, flags, doc)) in _INST_SIMPLE_FIELDS.items()])
# Fields requiring talking to the node
fields.extend([
fields.extend([
(_MakeField(name, title, kind, doc), CQ_CONFIG, flags, _GetItemAttr(name))
for (name, (title, kind, flags, doc)) in _CLUSTER_SIMPLE_FIELDS.items()
- ])
+ ],)
# Version fields
fields.extend([
(_MakeField(name, title, kind, doc), None, 0, _StaticValue(value))
- for (name, (title, kind, value, doc)) in _CLUSTER_VERSION_FIELDS.items()
- ])
+ for (name, (title, kind, value, doc)) in _CLUSTER_VERSION_FIELDS.items()])
# Add timestamps
fields.extend(_GetItemTimestampFields(CQ_CONFIG))
return _PrepareFieldList(fields, [
- ("name", "cluster_name"),
+ ("name", "cluster_name")])
+
+
+class NetworkQueryData:
+ """Data container for network data queries.
+
+ """
+ def __init__(self, networks, network_to_groups,
+ network_to_instances, stats):
+ """Initializes this class.
+
+ @param networks: List of network objects
+ @type network_to_groups: dict; network UUID as key
+ @param network_to_groups: Per-network list of groups
+ @type network_to_instances: dict; network UUID as key
+ @param network_to_instances: Per-network list of instances
+ @type stats: dict; network UUID as key
+ @param stats: Per-network usage statistics
+
+ """
+ self.networks = networks
+ self.network_to_groups = network_to_groups
+ self.network_to_instances = network_to_instances
+ self.stats = stats
+
+ def __iter__(self):
+ """Iterate over all networks.
+
+ """
+ for net in self.networks:
+ if self.stats:
+ self.curstats = self.stats.get(net.uuid, None)
+ else:
+ self.curstats = None
+ yield net
+
+
+_NETWORK_SIMPLE_FIELDS = {
+ "name": ("Network", QFT_TEXT, 0, "The network"),
+ "network": ("Subnet", QFT_TEXT, 0, "The subnet"),
+ "gateway": ("Gateway", QFT_OTHER, 0, "The gateway"),
+ "network6": ("IPv6Subnet", QFT_OTHER, 0, "The ipv6 subnet"),
+ "gateway6": ("IPv6Gateway", QFT_OTHER, 0, "The ipv6 gateway"),
+ "mac_prefix": ("MacPrefix", QFT_OTHER, 0, "The mac prefix"),
+ "network_type": ("NetworkType", QFT_OTHER, 0, "The network type"),
+ "serial_no": ("SerialNo", QFT_NUMBER, 0, _SERIAL_NO_DOC % "Network"),
+ "uuid": ("UUID", QFT_TEXT, 0, "Network UUID"),
+ }
+
+
+_NETWORK_STATS_FIELDS = {
+ "free_count": ("FreeCount", QFT_NUMBER, 0, "How many addresses are free"),
+ "reserved_count": ("ReservedCount", QFT_NUMBER, 0,
+ "How many addresses are reserved"),
+ "map": ("Map", QFT_TEXT, 0, "The actual mapping"),
+ "external_reservations": ("ExternalReservations", QFT_TEXT, 0,
+ "The external reservations"),
+ }
+
+
+def _GetNetworkStatsField(field, kind, ctx, _):
+ """Gets the value of a "stats" field from L{NetworkQueryData}.
+
+ @param field: Field name
+ @param kind: Data kind, one of L{constants.QFT_ALL}
+ @type ctx: L{NetworkQueryData}
+
+ """
+
+ try:
+ value = ctx.curstats[field]
+ except KeyError:
+ return _FS_UNAVAIL
+
+ if kind == QFT_TEXT:
+ return value
+
+ assert kind in (QFT_NUMBER, QFT_UNIT)
+
+ # Try to convert into number
+ try:
+ return int(value)
+ except (ValueError, TypeError):
+ logging.exception("Failed to convert network field '%s' (value %r) to int",
+ field, value)
+ return _FS_UNAVAIL
+
+
+def _BuildNetworkFields():
+ """Builds list of fields for network queries.
+
+ """
+ fields = [
+ (_MakeField("tags", "Tags", QFT_OTHER, "Tags"), IQ_CONFIG, 0,
+ lambda ctx, inst: list(inst.GetTags())),
+ ]
+
+ # Add simple fields
+ fields.extend([
+ (_MakeField(name, title, kind, doc),
+ NETQ_CONFIG, 0, _GetItemAttr(name))
+ for (name, (title, kind, _, doc)) in _NETWORK_SIMPLE_FIELDS.items()])
+
+ def _GetLength(getter):
+ return lambda ctx, network: len(getter(ctx)[network.uuid])
+
+ def _GetSortedList(getter):
+ return lambda ctx, network: utils.NiceSort(getter(ctx)[network.uuid])
+
+ network_to_groups = operator.attrgetter("network_to_groups")
+ network_to_instances = operator.attrgetter("network_to_instances")
+
+ # Add fields for node groups
+ fields.extend([
+ (_MakeField("group_cnt", "NodeGroups", QFT_NUMBER, "Number of nodegroups"),
+ NETQ_GROUP, 0, _GetLength(network_to_groups)),
+ (_MakeField("group_list", "GroupList", QFT_OTHER, "List of nodegroups"),
+ NETQ_GROUP, 0, _GetSortedList(network_to_groups)),
+ ])
+
+ # Add fields for instances
+ fields.extend([
+ (_MakeField("inst_cnt", "Instances", QFT_NUMBER, "Number of instances"),
+ NETQ_INST, 0, _GetLength(network_to_instances)),
+ (_MakeField("inst_list", "InstanceList", QFT_OTHER, "List of instances"),
+ NETQ_INST, 0, _GetSortedList(network_to_instances)),
])
+ # Add fields for usage statistics
+ fields.extend([
+ (_MakeField(name, title, kind, doc), NETQ_STATS, 0,
+ compat.partial(_GetNetworkStatsField, name, kind))
+ for (name, (title, kind, _, doc)) in _NETWORK_STATS_FIELDS.items()])
+
+ return _PrepareFieldList(fields, [])
#: Fields for cluster information
CLUSTER_FIELDS = _BuildClusterFields()
#: Fields available for exports
EXPORT_FIELDS = _BuildExportFields()
+#: Fields available for network queries
+NETWORK_FIELDS = _BuildNetworkFields()
+
#: All available resources
ALL_FIELDS = {
constants.QR_CLUSTER: CLUSTER_FIELDS,
constants.QR_OS: OS_FIELDS,
constants.QR_JOB: JOB_FIELDS,
constants.QR_EXPORT: EXPORT_FIELDS,
+ constants.QR_NETWORK: NETWORK_FIELDS,
}
#: All available field lists