Revision be3a4b14 lib/cmdlib.py

b/lib/cmdlib.py
3410 3410
      raise errors.OpExecError("Check of out-of-band payload failed due to %s" %
3411 3411
                               utils.CommaJoin(errs))
3412 3412

  
3413
class _OsQuery(_QueryBase):
3414
  FIELDS = query.OS_FIELDS
3413 3415

  
3414

  
3415
class LUOsDiagnose(NoHooksLU):
3416
  """Logical unit for OS diagnose/query.
3417

  
3418
  """
3419
  REQ_BGL = False
3420
  _HID = "hidden"
3421
  _BLK = "blacklisted"
3422
  _VLD = "valid"
3423
  _FIELDS_STATIC = utils.FieldSet()
3424
  _FIELDS_DYNAMIC = utils.FieldSet("name", _VLD, "node_status", "variants",
3425
                                   "parameters", "api_versions", _HID, _BLK)
3426

  
3427
  def CheckArguments(self):
3428
    if self.op.names:
3429
      raise errors.OpPrereqError("Selective OS query not supported",
3430
                                 errors.ECODE_INVAL)
3431

  
3432
    _CheckOutputFields(static=self._FIELDS_STATIC,
3433
                       dynamic=self._FIELDS_DYNAMIC,
3434
                       selected=self.op.output_fields)
3435

  
3436
  def ExpandNames(self):
3437
    # Lock all nodes, in shared mode
3416
  def ExpandNames(self, lu):
3417
    # Lock all nodes in shared mode
3438 3418
    # Temporary removal of locks, should be reverted later
3439 3419
    # TODO: reintroduce locks when they are lighter-weight
3440
    self.needed_locks = {}
3420
    lu.needed_locks = {}
3441 3421
    #self.share_locks[locking.LEVEL_NODE] = 1
3442 3422
    #self.needed_locks[locking.LEVEL_NODE] = locking.ALL_SET
3443 3423

  
3424
    # The following variables interact with _QueryBase._GetNames
3425
    if self.names:
3426
      self.wanted = self.names
3427
    else:
3428
      self.wanted = locking.ALL_SET
3429

  
3430
    self.do_locking = self.use_locking
3431

  
3432
  def DeclareLocks(self, lu, level):
3433
    pass
3434

  
3444 3435
  @staticmethod
3445 3436
  def _DiagnoseByOS(rlist):
3446 3437
    """Remaps a per-node return list into an a per-os per-node dictionary
......
3481 3472
                                        variants, params, api_versions))
3482 3473
    return all_os
3483 3474

  
3484
  def Exec(self, feedback_fn):
3485
    """Compute the list of OSes.
3475
  def _GetQueryData(self, lu):
3476
    """Computes the list of nodes and their attributes.
3486 3477

  
3487 3478
    """
3479
    # Locking is not used
3480
    assert not (lu.acquired_locks or self.do_locking or self.use_locking)
3481

  
3482
    # Used further down
3483
    assert "valid" in self.FIELDS
3484
    assert "hidden" in self.FIELDS
3485
    assert "blacklisted" in self.FIELDS
3486

  
3488 3487
    valid_nodes = [node.name
3489
                   for node in self.cfg.GetAllNodesInfo().values()
3488
                   for node in lu.cfg.GetAllNodesInfo().values()
3490 3489
                   if not node.offline and node.vm_capable]
3491
    node_data = self.rpc.call_os_diagnose(valid_nodes)
3492
    pol = self._DiagnoseByOS(node_data)
3493
    output = []
3494
    cluster = self.cfg.GetClusterInfo()
3490
    pol = self._DiagnoseByOS(lu.rpc.call_os_diagnose(valid_nodes))
3491
    cluster = lu.cfg.GetClusterInfo()
3492

  
3493
    # Build list of used field names
3494
    fields = [fdef.name for fdef in self.query.GetFields()]
3495

  
3496
    data = {}
3497

  
3498
    for (os_name, os_data) in pol.items():
3499
      info = query.OsInfo(name=os_name, valid=True, node_status=os_data,
3500
                          hidden=(os_name in cluster.hidden_os),
3501
                          blacklisted=(os_name in cluster.blacklisted_os))
3502

  
3503
      variants = set()
3504
      parameters = set()
3505
      api_versions = set()
3495 3506

  
3496
    for os_name in utils.NiceSort(pol.keys()):
3497
      os_data = pol[os_name]
3498
      row = []
3499
      valid = True
3500
      (variants, params, api_versions) = null_state = (set(), set(), set())
3501 3507
      for idx, osl in enumerate(os_data.values()):
3502
        valid = bool(valid and osl and osl[0][1])
3503
        if not valid:
3504
          (variants, params, api_versions) = null_state
3508
        info.valid = bool(info.valid and osl and osl[0][1])
3509
        if not info.valid:
3505 3510
          break
3506
        node_variants, node_params, node_api = osl[0][3:6]
3507
        if idx == 0: # first entry
3508
          variants = set(node_variants)
3509
          params = set(node_params)
3510
          api_versions = set(node_api)
3511
        else: # keep consistency
3511

  
3512
        (node_variants, node_params, node_api) = osl[0][3:6]
3513
        if idx == 0:
3514
          # First entry
3515
          variants.update(node_variants)
3516
          parameters.update(node_params)
3517
          api_versions.update(node_api)
3518
        else:
3519
          # Filter out inconsistent values
3512 3520
          variants.intersection_update(node_variants)
3513
          params.intersection_update(node_params)
3521
          parameters.intersection_update(node_params)
3514 3522
          api_versions.intersection_update(node_api)
3515 3523

  
3516
      is_hid = os_name in cluster.hidden_os
3517
      is_blk = os_name in cluster.blacklisted_os
3518
      if ((self._HID not in self.op.output_fields and is_hid) or
3519
          (self._BLK not in self.op.output_fields and is_blk) or
3520
          (self._VLD not in self.op.output_fields and not valid)):
3524
      info.variants = list(variants)
3525
      info.parameters = list(parameters)
3526
      info.api_versions = list(api_versions)
3527

  
3528
      # TODO: Move this to filters provided by the client
3529
      if (("hidden" not in fields and info.hidden) or
3530
          ("blacklisted" not in fields and info.blacklisted) or
3531
          ("valid" not in fields and not info.valid)):
3521 3532
        continue
3522 3533

  
3523
      for field in self.op.output_fields:
3524
        if field == "name":
3525
          val = os_name
3526
        elif field == self._VLD:
3527
          val = valid
3528
        elif field == "node_status":
3529
          # this is just a copy of the dict
3530
          val = {}
3531
          for node_name, nos_list in os_data.items():
3532
            val[node_name] = nos_list
3533
        elif field == "variants":
3534
          val = utils.NiceSort(list(variants))
3535
        elif field == "parameters":
3536
          val = list(params)
3537
        elif field == "api_versions":
3538
          val = list(api_versions)
3539
        elif field == self._HID:
3540
          val = is_hid
3541
        elif field == self._BLK:
3542
          val = is_blk
3543
        else:
3544
          raise errors.ParameterError(field)
3545
        row.append(val)
3546
      output.append(row)
3534
      data[os_name] = info
3547 3535

  
3548
    return output
3536
    # Prepare data in requested order
3537
    return [data[name] for name in self._GetNames(lu, pol.keys(), None)
3538
            if name in data]
3539

  
3540

  
3541
class LUOsDiagnose(NoHooksLU):
3542
  """Logical unit for OS diagnose/query.
3543

  
3544
  """
3545
  REQ_BGL = False
3546

  
3547
  def CheckArguments(self):
3548
    self.oq = _OsQuery(qlang.MakeSimpleFilter("name", self.op.names),
3549
                       self.op.output_fields, False)
3550

  
3551
  def ExpandNames(self):
3552
    self.oq.ExpandNames(self)
3553

  
3554
  def Exec(self, feedback_fn):
3555
    return self.oq.OldStyleQuery(self)
3549 3556

  
3550 3557

  
3551 3558
class LUNodeRemove(LogicalUnit):
......
11643 11650
  constants.QR_INSTANCE: _InstanceQuery,
11644 11651
  constants.QR_NODE: _NodeQuery,
11645 11652
  constants.QR_GROUP: _GroupQuery,
11653
  constants.QR_OS: _OsQuery,
11646 11654
  }
11647 11655

  
11656
assert set(_QUERY_IMPL.keys()) == constants.QR_OP_QUERY
11657

  
11648 11658

  
11649 11659
def _GetQueryImplementation(name):
11650 11660
  """Returns the implemtnation for a query type.

Also available in: Unified diff