Revision 526f866b lib/query.py

b/lib/query.py
64 64
from ganeti import ht
65 65
from ganeti import runtime
66 66
from ganeti import qlang
67
from ganeti import jstore
67 68

  
68 69
from ganeti.constants import (QFT_UNKNOWN, QFT_TEXT, QFT_BOOL, QFT_NUMBER,
69 70
                              QFT_UNIT, QFT_TIMESTAMP, QFT_OTHER,
......
103 104
# Query field flags
104 105
QFF_HOSTNAME = 0x01
105 106
QFF_IP_ADDRESS = 0x02
106
# Next values: 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x100, 0x200
107
QFF_ALL = (QFF_HOSTNAME | QFF_IP_ADDRESS)
107
QFF_JOB_ID = 0x04
108
QFF_SPLIT_TIMESTAMP = 0x08
109
# Next values: 0x10, 0x20, 0x40, 0x80, 0x100, 0x200
110
QFF_ALL = (QFF_HOSTNAME | QFF_IP_ADDRESS | QFF_JOB_ID | QFF_SPLIT_TIMESTAMP)
108 111

  
109 112
FIELD_NAME_RE = re.compile(r"^[a-z0-9/._]+$")
110 113
TITLE_RE = re.compile(r"^[^\s]+$")
......
345 348
    raise errors.ParameterError("Invalid regex pattern (%s)" % err)
346 349

  
347 350

  
351
def _PrepareSplitTimestamp(value):
352
  """Prepares a value for comparison by L{_MakeSplitTimestampComparison}.
353

  
354
  """
355
  if ht.TNumber(value):
356
    return value
357
  else:
358
    return utils.MergeTime(value)
359

  
360

  
361
def _MakeSplitTimestampComparison(fn):
362
  """Compares split timestamp values after converting to float.
363

  
364
  """
365
  return lambda lhs, rhs: fn(utils.MergeTime(lhs), rhs)
366

  
367

  
368
def _MakeComparisonChecks(fn):
369
  """Prepares flag-specific comparisons using a comparison function.
370

  
371
  """
372
  return [
373
    (QFF_SPLIT_TIMESTAMP, _MakeSplitTimestampComparison(fn),
374
     _PrepareSplitTimestamp),
375
    (QFF_JOB_ID, lambda lhs, rhs: fn(jstore.ParseJobId(lhs), rhs),
376
     jstore.ParseJobId),
377
    (None, fn, None),
378
    ]
379

  
380

  
348 381
class _FilterCompilerHelper:
349 382
  """Converts a query filter to a callable usable for filtering.
350 383

  
......
363 396

  
364 397
  List of tuples containing flags and a callable receiving the left- and
365 398
  right-hand side of the operator. The flags are an OR-ed value of C{QFF_*}
366
  (e.g. L{QFF_HOSTNAME}).
399
  (e.g. L{QFF_HOSTNAME} or L{QFF_SPLIT_TIMESTAMP}).
367 400

  
368 401
  Order matters. The first item with flags will be used. Flags are checked
369 402
  using binary AND.
......
374 407
     lambda lhs, rhs: utils.MatchNameComponent(rhs, [lhs],
375 408
                                               case_sensitive=False),
376 409
     None),
410
    (QFF_SPLIT_TIMESTAMP, _MakeSplitTimestampComparison(operator.eq),
411
     _PrepareSplitTimestamp),
377 412
    (None, operator.eq, None),
378 413
    ]
379 414

  
......
403 438
    qlang.OP_NOT_EQUAL:
404 439
      (_OPTYPE_BINARY, [(flags, compat.partial(_WrapNot, fn), valprepfn)
405 440
                        for (flags, fn, valprepfn) in _EQUALITY_CHECKS]),
406
    qlang.OP_LT: (_OPTYPE_BINARY, [
407
      (None, operator.lt, None),
408
      ]),
409
    qlang.OP_GT: (_OPTYPE_BINARY, [
410
      (None, operator.gt, None),
411
      ]),
412
    qlang.OP_LE: (_OPTYPE_BINARY, [
413
      (None, operator.le, None),
414
      ]),
415
    qlang.OP_GE: (_OPTYPE_BINARY, [
416
      (None, operator.ge, None),
417
      ]),
441
    qlang.OP_LT: (_OPTYPE_BINARY, _MakeComparisonChecks(operator.lt)),
442
    qlang.OP_LE: (_OPTYPE_BINARY, _MakeComparisonChecks(operator.le)),
443
    qlang.OP_GT: (_OPTYPE_BINARY, _MakeComparisonChecks(operator.gt)),
444
    qlang.OP_GE: (_OPTYPE_BINARY, _MakeComparisonChecks(operator.ge)),
418 445
    qlang.OP_REGEXP: (_OPTYPE_BINARY, [
419 446
      (None, lambda lhs, rhs: rhs.search(lhs), _PrepareRegex),
420 447
      ]),
......
2239 2266
  """
2240 2267
  fields = [
2241 2268
    (_MakeField("id", "ID", QFT_TEXT, "Job ID"),
2242
     None, 0, lambda _, (job_id, job): job_id),
2269
     None, QFF_JOB_ID, lambda _, (job_id, job): job_id),
2243 2270
    (_MakeField("status", "Status", QFT_TEXT, "Job status"),
2244 2271
     None, 0, _JobUnavail(lambda job: job.CalcStatus())),
2245 2272
    (_MakeField("priority", "Priority", QFT_NUMBER,
......
2270 2297
    (_MakeField("oppriority", "OpCode_prio", QFT_OTHER,
2271 2298
                "List of opcode priorities"),
2272 2299
     None, 0, _PerJobOp(operator.attrgetter("priority"))),
2273
    (_MakeField("received_ts", "Received", QFT_OTHER,
2274
                "Timestamp of when job was received"),
2275
     None, 0, _JobTimestamp(operator.attrgetter("received_timestamp"))),
2276
    (_MakeField("start_ts", "Start", QFT_OTHER,
2277
                "Timestamp of job start"),
2278
     None, 0, _JobTimestamp(operator.attrgetter("start_timestamp"))),
2279
    (_MakeField("end_ts", "End", QFT_OTHER,
2280
                "Timestamp of job end"),
2281
     None, 0, _JobTimestamp(operator.attrgetter("end_timestamp"))),
2282 2300
    (_MakeField("summary", "Summary", QFT_OTHER,
2283 2301
                "List of per-opcode summaries"),
2284 2302
     None, 0, _PerJobOp(lambda op: op.input.Summary())),
2285 2303
    ]
2286 2304

  
2305
  # Timestamp fields
2306
  for (name, attr, title, desc) in [
2307
    ("received_ts", "received_timestamp", "Received",
2308
     "Timestamp of when job was received"),
2309
    ("start_ts", "start_timestamp", "Start", "Timestamp of job start"),
2310
    ("end_ts", "end_timestamp", "End", "Timestamp of job end"),
2311
    ]:
2312
    getter = operator.attrgetter(attr)
2313
    fields.extend([
2314
      (_MakeField(name, title, QFT_OTHER,
2315
                  "%s (tuple containing seconds and microseconds)" % desc),
2316
       None, QFF_SPLIT_TIMESTAMP, _JobTimestamp(getter)),
2317
      ])
2318

  
2287 2319
  return _PrepareFieldList(fields, [])
2288 2320

  
2289 2321

  

Also available in: Unified diff