Add two new opcode options to LUOobCommand
[ganeti-local] / lib / query.py
index 7caa9c5..35f6d27 100644 (file)
@@ -63,8 +63,8 @@ from ganeti import ht
 
 from ganeti.constants import (QFT_UNKNOWN, QFT_TEXT, QFT_BOOL, QFT_NUMBER,
                               QFT_UNIT, QFT_TIMESTAMP, QFT_OTHER,
-                              QRFS_NORMAL, QRFS_UNKNOWN, QRFS_NODATA,
-                              QRFS_UNAVAIL, QRFS_OFFLINE)
+                              RS_NORMAL, RS_UNKNOWN, RS_NODATA,
+                              RS_UNAVAIL, RS_OFFLINE)
 
 
 # Constants for requesting data from the caller/data provider. Each property
@@ -110,6 +110,16 @@ _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,
+  }
+
 
 def _GetUnknownField(ctx, item): # pylint: disable-msg=W0613
   """Gets the contents of an unknown field.
@@ -234,15 +244,15 @@ def _ProcessResult(value):
 
   """
   if value is _FS_UNKNOWN:
-    return (QRFS_UNKNOWN, None)
+    return (RS_UNKNOWN, None)
   elif value is _FS_NODATA:
-    return (QRFS_NODATA, None)
+    return (RS_NODATA, None)
   elif value is _FS_UNAVAIL:
-    return (QRFS_UNAVAIL, None)
+    return (RS_UNAVAIL, None)
   elif value is _FS_OFFLINE:
-    return (QRFS_OFFLINE, None)
+    return (RS_OFFLINE, None)
   else:
-    return (QRFS_NORMAL, value)
+    return (RS_NORMAL, value)
 
 
 def _VerifyResultRow(fields, row):
@@ -257,7 +267,7 @@ def _VerifyResultRow(fields, row):
   assert len(row) == len(fields)
   errs = []
   for ((status, value), (fdef, _, _)) in zip(row, fields):
-    if status == QRFS_NORMAL:
+    if status == RS_NORMAL:
       if not _VERIFY_FN[fdef.kind](value):
         errs.append("normal field %s fails validation (value is %s)" %
                     (fdef.name, value))
@@ -267,14 +277,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}
 
@@ -298,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())
 
@@ -634,7 +656,7 @@ def _BuildNodeFields():
   # Add timestamps
   fields.extend(_GetItemTimestampFields(NQ_CONFIG))
 
-  return _PrepareFieldList(fields)
+  return _PrepareFieldList(fields, [])
 
 
 class InstanceQueryData:
@@ -698,7 +720,7 @@ def _GetInstOperState(ctx, inst):
   @param inst: Instance object
 
   """
-  # Can't use QRFS_OFFLINE here as it would describe the instance to
+  # 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 _FS_NODATA
@@ -723,7 +745,7 @@ 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 _FS_NODATA
 
@@ -973,10 +995,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,
@@ -1024,8 +1042,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),
@@ -1038,13 +1054,13 @@ def _GetInstanceParameterFields():
 
   # HV params
   def _GetInstHvParam(name):
-    return lambda ctx, _: 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), QFT_OTHER),
+    (_MakeField("hv/%s" % name, hv_title.get(name, "hv/%s" % name),
+                _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
     ])
 
@@ -1053,10 +1069,10 @@ def _GetInstanceParameterFields():
     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), QFT_OTHER),
-     IQ_CONFIG, _GetInstBeParam(name))
-    for name in constants.BES_PARAMETERS
+    (_MakeField("be/%s" % name, be_title.get(name, "be/%s" % name),
+                _VTToQFT[kind]), IQ_CONFIG,
+     _GetInstBeParam(name))
+    for name, kind in constants.BES_PARAMETER_TYPES.items()
     ])
 
   return fields
@@ -1109,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:
@@ -1165,7 +1187,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:
@@ -1237,7 +1259,7 @@ def _BuildGroupFields():
 
   fields.extend(_GetItemTimestampFields(GQ_CONFIG))
 
-  return _PrepareFieldList(fields)
+  return _PrepareFieldList(fields, [])
 
 
 #: Fields available for node queries