Fix punctuation in an error message
[ganeti-local] / lib / query.py
index 8935f45..1bb014d 100644 (file)
@@ -79,7 +79,8 @@ from ganeti.constants import (QFT_UNKNOWN, QFT_TEXT, QFT_BOOL, QFT_NUMBER,
 
 (IQ_CONFIG,
  IQ_LIVE,
- IQ_DISKUSAGE) = range(100, 103)
+ IQ_DISKUSAGE,
+ IQ_CONSOLE) = range(100, 104)
 
 (LQ_MODE,
  LQ_OWNER,
@@ -277,14 +278,18 @@ def _VerifyResultRow(fields, row):
                     (utils.CommaJoin(errors), row))
 
 
-def _PrepareFieldList(fields):
+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, see L{Query.__init__} for a better description
+  @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}
 
@@ -308,7 +313,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())
 
@@ -474,6 +487,7 @@ _NODE_SIMPLE_FIELDS = {
 
 
 #: Fields requiring talking to the node
+# Note that none of these are available for non-vm_capable nodes
 _NODE_LIVE_FIELDS = {
   "bootid": ("BootID", QFT_TEXT, "bootid"),
   "cnodes": ("CNodes", QFT_NUMBER, "cpu_nodes"),
@@ -564,6 +578,9 @@ def _GetLiveNodeField(field, kind, ctx, node):
   if node.offline:
     return _FS_OFFLINE
 
+  if not node.vm_capable:
+    return _FS_UNAVAIL
+
   if not ctx.curlive_data:
     return _FS_NODATA
 
@@ -644,7 +661,7 @@ def _BuildNodeFields():
   # Add timestamps
   fields.extend(_GetItemTimestampFields(NQ_CONFIG))
 
-  return _PrepareFieldList(fields)
+  return _PrepareFieldList(fields, [])
 
 
 class InstanceQueryData:
@@ -652,7 +669,7 @@ class InstanceQueryData:
 
   """
   def __init__(self, instances, cluster, disk_usage, offline_nodes, bad_nodes,
-               live_data):
+               live_data, wrongnode_inst, console):
     """Initializes this class.
 
     @param instances: List of instance objects
@@ -665,6 +682,10 @@ class InstanceQueryData:
     @param bad_nodes: List of faulty nodes
     @type live_data: dict; instance name as key
     @param live_data: Per-instance live data
+    @type wrongnode_inst: set
+    @param wrongnode_inst: Set of instances running on wrong node(s)
+    @type console: dict; instance name as key
+    @param console: Per-instance console information
 
     """
     assert len(set(bad_nodes) & set(offline_nodes)) == len(offline_nodes), \
@@ -678,6 +699,8 @@ class InstanceQueryData:
     self.offline_nodes = offline_nodes
     self.bad_nodes = bad_nodes
     self.live_data = live_data
+    self.wrongnode_inst = wrongnode_inst
+    self.console = console
 
     # Used for individual rows
     self.inst_hvparams = None
@@ -762,7 +785,9 @@ def _GetInstStatus(ctx, inst):
     return "ERROR_nodedown"
 
   if bool(ctx.live_data.get(inst.name)):
-    if inst.admin_up:
+    if inst.name in ctx.wrongnode_inst:
+      return "ERROR_wrongnode"
+    elif inst.admin_up:
       return "running"
     else:
       return "ERROR_up"
@@ -974,6 +999,22 @@ def _GetInstDiskUsage(ctx, inst):
   return usage
 
 
+def _GetInstanceConsole(ctx, inst):
+  """Get console information for instance.
+
+  @type ctx: L{InstanceQueryData}
+  @type inst: L{objects.Instance}
+  @param inst: Instance object
+
+  """
+  consinfo = ctx.console[inst.name]
+
+  if consinfo is None:
+    return _FS_UNAVAIL
+
+  return consinfo
+
+
 def _GetInstanceDiskFields():
   """Get instance fields involving disks.
 
@@ -983,10 +1024,6 @@ def _GetInstanceDiskFields():
   fields = [
     (_MakeField("disk_usage", "DiskUsage", QFT_UNIT), IQ_DISKUSAGE,
      _GetInstDiskUsage),
-    (_MakeField("sda_size", "LegacyDisk/0", QFT_UNIT), IQ_CONFIG,
-     _GetInstDiskSize(0)),
-    (_MakeField("sdb_size", "LegacyDisk/1", QFT_UNIT), IQ_CONFIG,
-     _GetInstDiskSize(1)),
     (_MakeField("disk.count", "Disks", QFT_NUMBER), IQ_CONFIG,
      lambda ctx, inst: len(inst.disks)),
     (_MakeField("disk.sizes", "Disk_sizes", QFT_OTHER), IQ_CONFIG,
@@ -1034,8 +1071,6 @@ def _GetInstanceParameterFields():
      IQ_CONFIG, lambda ctx, _: ctx.inst_hvparams),
     (_MakeField("beparams", "BackendParameters", QFT_OTHER),
      IQ_CONFIG, lambda ctx, _: ctx.inst_beparams),
-    (_MakeField("vcpus", "LegacyVCPUs", QFT_NUMBER), IQ_CONFIG,
-     lambda ctx, _: ctx.inst_beparams[constants.BE_VCPUS]),
 
     # Unfilled parameters
     (_MakeField("custom_hvparams", "CustomHypervisorParameters", QFT_OTHER),
@@ -1075,7 +1110,7 @@ def _GetInstanceParameterFields():
 _INST_SIMPLE_FIELDS = {
   "disk_template": ("Disk_template", QFT_TEXT),
   "hypervisor": ("Hypervisor", QFT_TEXT),
-  "name": ("Node", QFT_TEXT),
+  "name": ("Instance", QFT_TEXT),
   # Depending on the hypervisor, the port can be None
   "network_port": ("Network_port", QFT_OTHER),
   "os": ("OS", QFT_TEXT),
@@ -1097,6 +1132,8 @@ def _BuildInstanceFields():
      _GetItemAttr("admin_up")),
     (_MakeField("tags", "Tags", QFT_OTHER), IQ_CONFIG,
      lambda ctx, inst: list(inst.GetTags())),
+    (_MakeField("console", "Console", QFT_OTHER), IQ_CONSOLE,
+     _GetInstanceConsole),
     ]
 
   # Add simple fields
@@ -1119,7 +1156,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:
@@ -1175,7 +1218,7 @@ def _BuildLockFields():
      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:
@@ -1247,7 +1290,7 @@ def _BuildGroupFields():
 
   fields.extend(_GetItemTimestampFields(GQ_CONFIG))
 
-  return _PrepareFieldList(fields)
+  return _PrepareFieldList(fields, [])
 
 
 #: Fields available for node queries