X-Git-Url: https://code.grnet.gr/git/ganeti-local/blobdiff_plain/0fdf247d0395039ed064c724e8d7632296d92628..4a78c361a6de3bcbf98f02abfe41ae3b11de2b00:/lib/query.py diff --git a/lib/query.py b/lib/query.py index 2a1213b..ffd4d20 100644 --- a/lib/query.py +++ b/lib/query.py @@ -62,6 +62,7 @@ from ganeti import utils from ganeti import compat from ganeti import objects from ganeti import ht +from ganeti import runtime from ganeti import qlang from ganeti.constants import (QFT_UNKNOWN, QFT_TEXT, QFT_BOOL, QFT_NUMBER, @@ -92,7 +93,12 @@ from ganeti.constants import (QFT_UNKNOWN, QFT_TEXT, QFT_BOOL, QFT_NUMBER, (GQ_CONFIG, GQ_NODE, - GQ_INST) = range(200, 203) + GQ_INST, + GQ_DISKPARAMS) = range(200, 204) + +(CQ_CONFIG, + CQ_QUEUE_DRAINED, + CQ_WATCHER_PAUSE) = range(300, 303) # Query field flags QFF_HOSTNAME = 0x01 @@ -874,6 +880,20 @@ def _MakeField(name, title, kind, doc): doc=doc) +def _StaticValueInner(value, ctx, _): # pylint: disable=W0613 + """Returns a static value. + + """ + return value + + +def _StaticValue(value): + """Prepares a function to return a static value. + + """ + return compat.partial(_StaticValueInner, value) + + def _GetNodeRole(node, master_name): """Determine node role. @@ -1983,7 +2003,8 @@ class GroupQueryData: """Data container for node group data queries. """ - def __init__(self, cluster, groups, group_to_nodes, group_to_instances): + def __init__(self, cluster, groups, group_to_nodes, group_to_instances, + want_diskparams): """Initializes this class. @param cluster: Cluster object @@ -1992,16 +2013,20 @@ class GroupQueryData: @param group_to_nodes: Per-group list of nodes @type group_to_instances: dict; group UUID as key @param group_to_instances: Per-group list of (primary) instances + @type want_diskparams: bool + @param want_diskparams: Whether diskparamters should be calculated """ self.groups = groups self.group_to_nodes = group_to_nodes self.group_to_instances = group_to_instances self.cluster = cluster + self.want_diskparams = want_diskparams # Used for individual rows self.group_ipolicy = None self.ndparams = None + self.group_dp = None def __iter__(self): """Iterate over all node groups. @@ -2013,6 +2038,10 @@ class GroupQueryData: for group in self.groups: self.group_ipolicy = self.cluster.SimpleFillIPolicy(group.ipolicy) self.ndparams = self.cluster.SimpleFillND(group.ndparams) + if self.want_diskparams: + self.group_dp = self.cluster.SimpleFillDP(group.diskparams) + else: + self.group_dp = None yield group @@ -2076,6 +2105,12 @@ def _BuildGroupFields(): (_MakeField("ndparams", "NDParams", QFT_OTHER, "Node parameters"), GQ_CONFIG, 0, lambda ctx, _: ctx.ndparams), + (_MakeField("diskparams", "DiskParameters", QFT_OTHER, + "Disk parameters (merged)"), + GQ_DISKPARAMS, 0, lambda ctx, _: ctx.group_dp), + (_MakeField("custom_diskparams", "CustomDiskParameters", QFT_OTHER, + "Custom disk parameters"), + GQ_CONFIG, 0, _GetItemAttr("diskparams")), ]) # ND parameters @@ -2264,6 +2299,99 @@ def _BuildExportFields(): return _PrepareFieldList(fields, []) +_CLUSTER_VERSION_FIELDS = { + "software_version": ("SoftwareVersion", QFT_TEXT, constants.RELEASE_VERSION, + "Software version"), + "protocol_version": ("ProtocolVersion", QFT_NUMBER, + constants.PROTOCOL_VERSION, + "RPC protocol version"), + "config_version": ("ConfigVersion", QFT_NUMBER, constants.CONFIG_VERSION, + "Configuration format version"), + "os_api_version": ("OsApiVersion", QFT_NUMBER, max(constants.OS_API_VERSIONS), + "API version for OS template scripts"), + "export_version": ("ExportVersion", QFT_NUMBER, constants.EXPORT_VERSION, + "Import/export file format version"), + } + + +_CLUSTER_SIMPLE_FIELDS = { + "cluster_name": ("Name", QFT_TEXT, QFF_HOSTNAME, "Cluster name"), + "master_node": ("Master", QFT_TEXT, QFF_HOSTNAME, "Master node name"), + "volume_group_name": ("VgName", QFT_TEXT, 0, "LVM volume group name"), + } + + +class ClusterQueryData: + def __init__(self, cluster, drain_flag, watcher_pause): + """Initializes this class. + + @type cluster: L{objects.Cluster} + @param cluster: Instance of cluster object + @type drain_flag: bool + @param drain_flag: Whether job queue is drained + @type watcher_pause: number + @param watcher_pause: Until when watcher is paused (Unix timestamp) + + """ + self._cluster = cluster + self.drain_flag = drain_flag + self.watcher_pause = watcher_pause + + def __iter__(self): + return iter([self._cluster]) + + +def _ClusterWatcherPause(ctx, _): + """Returns until when watcher is paused (if available). + + """ + if ctx.watcher_pause is None: + return _FS_UNAVAIL + else: + return ctx.watcher_pause + + +def _BuildClusterFields(): + """Builds list of fields for cluster information. + + """ + fields = [ + (_MakeField("tags", "Tags", QFT_OTHER, "Tags"), CQ_CONFIG, 0, + lambda ctx, cluster: list(cluster.GetTags())), + (_MakeField("architecture", "ArchInfo", QFT_OTHER, + "Architecture information"), None, 0, + lambda ctx, _: runtime.GetArchInfo()), + (_MakeField("drain_flag", "QueueDrained", QFT_BOOL, + "Flag whether job queue is drained"), CQ_QUEUE_DRAINED, 0, + lambda ctx, _: ctx.drain_flag), + (_MakeField("watcher_pause", "WatcherPause", QFT_TIMESTAMP, + "Until when watcher is paused"), CQ_WATCHER_PAUSE, 0, + _ClusterWatcherPause), + ] + + # Simple fields + 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() + ]) + + # Add timestamps + fields.extend(_GetItemTimestampFields(CQ_CONFIG)) + + return _PrepareFieldList(fields, [ + ("name", "cluster_name"), + ]) + + +#: Fields for cluster information +CLUSTER_FIELDS = _BuildClusterFields() + #: Fields available for node queries NODE_FIELDS = _BuildNodeFields() @@ -2287,6 +2415,7 @@ EXPORT_FIELDS = _BuildExportFields() #: All available resources ALL_FIELDS = { + constants.QR_CLUSTER: CLUSTER_FIELDS, constants.QR_INSTANCE: INSTANCE_FIELDS, constants.QR_NODE: NODE_FIELDS, constants.QR_LOCK: LOCK_FIELDS,