iallocator: add ht-checking for the request
[ganeti-local] / lib / query.py
index 28afec1..51448ba 100644 (file)
@@ -322,6 +322,16 @@ def _WrapNot(fn, lhs, rhs):
   return not fn(lhs, rhs)
 
 
+def _PrepareRegex(pattern):
+  """Compiles a regular expression.
+
+  """
+  try:
+    return re.compile(pattern)
+  except re.error, err:
+    raise errors.ParameterError("Invalid regex pattern (%s)" % err)
+
+
 class _FilterCompilerHelper:
   """Converts a query filter to a callable usable for filtering.
 
@@ -349,8 +359,9 @@ class _FilterCompilerHelper:
   _EQUALITY_CHECKS = [
     (QFF_HOSTNAME,
      lambda lhs, rhs: utils.MatchNameComponent(rhs, [lhs],
-                                               case_sensitive=False)),
-    (None, operator.eq),
+                                               case_sensitive=False),
+     None),
+    (None, operator.eq, None),
     ]
 
   """Known operators
@@ -377,12 +388,13 @@ class _FilterCompilerHelper:
     # Binary operators
     qlang.OP_EQUAL: (_OPTYPE_BINARY, _EQUALITY_CHECKS),
     qlang.OP_NOT_EQUAL:
-      (_OPTYPE_BINARY, [(flags, compat.partial(_WrapNot, fn))
-                        for (flags, fn) in _EQUALITY_CHECKS]),
-    qlang.OP_GLOB: (_OPTYPE_BINARY, NotImplemented),
-    qlang.OP_REGEXP: (_OPTYPE_BINARY, NotImplemented),
+      (_OPTYPE_BINARY, [(flags, compat.partial(_WrapNot, fn), valprepfn)
+                        for (flags, fn, valprepfn) in _EQUALITY_CHECKS]),
+    qlang.OP_REGEXP: (_OPTYPE_BINARY, [
+      (None, lambda lhs, rhs: rhs.search(lhs), _PrepareRegex),
+      ]),
     qlang.OP_CONTAINS: (_OPTYPE_BINARY, [
-      (None, operator.contains),
+      (None, operator.contains, None),
       ]),
     }
 
@@ -556,8 +568,12 @@ class _FilterCompilerHelper:
     if hints_fn:
       hints_fn(op, datakind, name, value)
 
-    for (fn_flags, fn) in op_data:
+    for (fn_flags, fn, valprepfn) in op_data:
       if fn_flags is None or fn_flags & field_flags:
+        # Prepare value if necessary (e.g. compile regular expression)
+        if valprepfn:
+          value = valprepfn(value)
+
         return compat.partial(_WrapBinaryOp, fn, retrieval_fn, value)
 
     raise errors.ProgrammerError("Unable to find operator implementation"
@@ -1243,6 +1259,7 @@ class InstanceQueryData:
     # Used for individual rows
     self.inst_hvparams = None
     self.inst_beparams = None
+    self.inst_osparams = None
     self.inst_nicparams = None
 
   def __iter__(self):
@@ -1255,6 +1272,7 @@ class InstanceQueryData:
     for inst in self.instances:
       self.inst_hvparams = self.cluster.FillHV(inst, skip_globals=True)
       self.inst_beparams = self.cluster.FillBE(inst)
+      self.inst_osparams = self.cluster.SimpleFillOS(inst.os, inst.osparams)
       self.inst_nicparams = [self.cluster.SimpleFillNIC(nic.nicparams)
                              for nic in inst.nics]
 
@@ -1620,11 +1638,14 @@ def _GetInstanceParameterFields():
   fields = [
     # Filled parameters
     (_MakeField("hvparams", "HypervisorParameters", QFT_OTHER,
-                "Hypervisor parameters"),
+                "Hypervisor parameters (merged)"),
      IQ_CONFIG, 0, lambda ctx, _: ctx.inst_hvparams),
     (_MakeField("beparams", "BackendParameters", QFT_OTHER,
-                "Backend parameters"),
+                "Backend parameters (merged)"),
      IQ_CONFIG, 0, lambda ctx, _: ctx.inst_beparams),
+    (_MakeField("osparams", "OpSysParameters", QFT_OTHER,
+                "Operating system parameters (merged)"),
+     IQ_CONFIG, 0, lambda ctx, _: ctx.inst_osparams),
 
     # Unfilled parameters
     (_MakeField("custom_hvparams", "CustomHypervisorParameters", QFT_OTHER,
@@ -1633,6 +1654,9 @@ def _GetInstanceParameterFields():
     (_MakeField("custom_beparams", "CustomBackendParameters", QFT_OTHER,
                 "Custom backend parameters",),
      IQ_CONFIG, 0, _GetItemAttr("beparams")),
+    (_MakeField("custom_osparams", "CustomOpSysParameters", QFT_OTHER,
+                "Custom operating system parameters",),
+     IQ_CONFIG, 0, _GetItemAttr("osparams")),
     (_MakeField("custom_nicparams", "CustomNicParameters", QFT_OTHER,
                 "Custom network interface parameters"),
      IQ_CONFIG, 0, lambda ctx, inst: [nic.nicparams for nic in inst.nics]),
@@ -1883,11 +1907,63 @@ def _BuildGroupFields():
      GQ_INST, 0, _GetSortedList(group_to_instances)),
     ])
 
+  # Other fields
+  fields.extend([
+    (_MakeField("tags", "Tags", QFT_OTHER, "Tags"), GQ_CONFIG, 0,
+     lambda ctx, group: list(group.GetTags())),
+    ])
+
   fields.extend(_GetItemTimestampFields(GQ_CONFIG))
 
   return _PrepareFieldList(fields, [])
 
 
+class OsInfo(objects.ConfigObject):
+  __slots__ = [
+    "name",
+    "valid",
+    "hidden",
+    "blacklisted",
+    "variants",
+    "api_versions",
+    "parameters",
+    "node_status",
+    ]
+
+
+def _BuildOsFields():
+  """Builds list of fields for operating system queries.
+
+  """
+  fields = [
+    (_MakeField("name", "Name", QFT_TEXT, "Operating system name"),
+     None, 0, _GetItemAttr("name")),
+    (_MakeField("valid", "Valid", QFT_BOOL,
+                "Whether operating system definition is valid"),
+     None, 0, _GetItemAttr("valid")),
+    (_MakeField("hidden", "Hidden", QFT_BOOL,
+                "Whether operating system is hidden"),
+     None, 0, _GetItemAttr("hidden")),
+    (_MakeField("blacklisted", "Blacklisted", QFT_BOOL,
+                "Whether operating system is blacklisted"),
+     None, 0, _GetItemAttr("blacklisted")),
+    (_MakeField("variants", "Variants", QFT_OTHER,
+                "Operating system variants"),
+     None, 0, _ConvWrap(utils.NiceSort, _GetItemAttr("variants"))),
+    (_MakeField("api_versions", "ApiVersions", QFT_OTHER,
+                "Operating system API versions"),
+     None, 0, _ConvWrap(sorted, _GetItemAttr("api_versions"))),
+    (_MakeField("parameters", "Parameters", QFT_OTHER,
+                "Operating system parameters"),
+     None, 0, _ConvWrap(utils.NiceSort, _GetItemAttr("parameters"))),
+    (_MakeField("node_status", "NodeStatus", QFT_OTHER,
+                "Status from node"),
+     None, 0, _GetItemAttr("node_status")),
+    ]
+
+  return _PrepareFieldList(fields, [])
+
+
 #: Fields available for node queries
 NODE_FIELDS = _BuildNodeFields()
 
@@ -1900,12 +1976,16 @@ LOCK_FIELDS = _BuildLockFields()
 #: Fields available for node group queries
 GROUP_FIELDS = _BuildGroupFields()
 
+#: Fields available for operating system queries
+OS_FIELDS = _BuildOsFields()
+
 #: All available resources
 ALL_FIELDS = {
   constants.QR_INSTANCE: INSTANCE_FIELDS,
   constants.QR_NODE: NODE_FIELDS,
   constants.QR_LOCK: LOCK_FIELDS,
   constants.QR_GROUP: GROUP_FIELDS,
+  constants.QR_OS: OS_FIELDS,
   }
 
 #: All available field lists