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