|
90 | 90 | check_container_engine, |
91 | 91 | find_container_engine, |
92 | 92 | normalize_container_id, |
93 | | - parsed_container_cpu_perc, |
94 | 93 | parsed_container_image_stats, |
95 | 94 | parsed_container_mem_usage, |
96 | 95 | pull_command, |
|
101 | 100 | get_legacy_daemon_fsid, |
102 | 101 | is_fsid, |
103 | 102 | normalize_image_digest, |
104 | | - try_convert_datetime, |
105 | 103 | read_config, |
106 | 104 | _extract_host_info_from_applied_spec, |
107 | 105 | ) |
108 | 106 | from cephadmlib.file_utils import ( |
109 | | - get_file_timestamp, |
110 | 107 | makedirs, |
111 | 108 | pathify, |
112 | 109 | read_file, |
|
194 | 191 | ) |
195 | 192 | from cephadmlib.agent import http_query |
196 | 193 | from cephadmlib.listing import ( |
197 | | - LegacyDaemonEntry, |
| 194 | + DaemonStatusUpdater, |
| 195 | + NoOpDaemonStatusUpdater, |
| 196 | + CombinedStatusUpdater, |
198 | 197 | daemons_matching, |
199 | 198 | daemons_summary, |
200 | 199 | ) |
| 200 | +from cephadmlib.listing_updaters import ( |
| 201 | + CPUUsageStatusUpdater, |
| 202 | + CoreStatusUpdater, |
| 203 | + DigestsStatusUpdater, |
| 204 | + MemUsageStatusUpdater, |
| 205 | + VersionStatusUpdater, |
| 206 | +) |
201 | 207 |
|
202 | 208 |
|
203 | 209 | FuncT = TypeVar('FuncT', bound=Callable) |
@@ -3397,315 +3403,24 @@ def list_daemons( |
3397 | 3403 | daemon_name: Optional[str] = None, |
3398 | 3404 | type_of_daemon: Optional[str] = None, |
3399 | 3405 | ) -> List[Dict[str, str]]: |
3400 | | - legacy_cache: Dict[str, Any] = {} |
3401 | | - ls = [] |
3402 | | - |
3403 | | - data_dir = ctx.data_dir |
3404 | | - if legacy_dir is not None: |
3405 | | - data_dir = os.path.abspath(legacy_dir + data_dir) |
3406 | | - |
3407 | | - if not os.path.exists(data_dir): |
3408 | | - # data_dir (/var/lib/ceph typically) is missing. Return empty list. |
3409 | | - logger.warning('%s is missing: no daemon listing available', data_dir) |
3410 | | - return [] |
3411 | | - |
3412 | | - # keep track of ceph versions we see |
3413 | | - seen_versions: Dict[str, Optional[str]] = {} |
3414 | | - |
3415 | | - # keep track of image digests |
3416 | | - seen_digests: Dict[str, List[str]] = {} |
3417 | | - |
3418 | | - # keep track of memory and cpu usage we've seen |
3419 | | - seen_memusage_cid_len, seen_memusage = parsed_container_mem_usage(ctx) |
3420 | | - seen_cpuperc_cid_len, seen_cpuperc = parsed_container_cpu_perc(ctx) |
| 3406 | + _updater: DaemonStatusUpdater = NoOpDaemonStatusUpdater() |
| 3407 | + if detail: |
| 3408 | + detail_updaters = [ |
| 3409 | + CoreStatusUpdater(), |
| 3410 | + DigestsStatusUpdater(), |
| 3411 | + VersionStatusUpdater(), |
| 3412 | + MemUsageStatusUpdater(), |
| 3413 | + CPUUsageStatusUpdater(), |
| 3414 | + ] |
| 3415 | + _updater = CombinedStatusUpdater(detail_updaters) |
3421 | 3416 |
|
3422 | 3417 | daemon_entries = daemons_matching( |
3423 | 3418 | ctx, |
3424 | 3419 | legacy_dir, |
3425 | 3420 | daemon_name=daemon_name, |
3426 | 3421 | daemon_type=type_of_daemon, |
3427 | 3422 | ) |
3428 | | - for entry in daemon_entries: |
3429 | | - if isinstance(entry, LegacyDaemonEntry): |
3430 | | - status = cast(Dict[str, Any], entry.status) |
3431 | | - if detail: |
3432 | | - _update_legacy_status( |
3433 | | - status, ctx, entry.name, legacy_cache, |
3434 | | - ) |
3435 | | - ls.append(status) |
3436 | | - else: |
3437 | | - status = cast(Dict[str, Any], entry.status) |
3438 | | - if detail: |
3439 | | - _update_daemon_and_container_status( |
3440 | | - status, |
3441 | | - ctx, |
3442 | | - entry.identity, |
3443 | | - data_dir, |
3444 | | - seen_versions, |
3445 | | - seen_digests, |
3446 | | - seen_memusage_cid_len, |
3447 | | - seen_memusage, |
3448 | | - seen_cpuperc_cid_len, |
3449 | | - seen_cpuperc, |
3450 | | - ) |
3451 | | - ls.append(status) |
3452 | | - return ls |
3453 | | - |
3454 | | - |
3455 | | -def _update_legacy_status( |
3456 | | - val: Dict[str, Any], |
3457 | | - ctx: CephadmContext, |
3458 | | - legacy_unit_name: str, |
3459 | | - cache: Dict[str, Any], |
3460 | | -) -> None: |
3461 | | - (val['enabled'], val['state'], _) = check_unit( |
3462 | | - ctx, legacy_unit_name |
3463 | | - ) |
3464 | | - if not cache.get('host_version'): |
3465 | | - try: |
3466 | | - out, err, code = call( |
3467 | | - ctx, |
3468 | | - ['ceph', '-v'], |
3469 | | - verbosity=CallVerbosity.QUIET, |
3470 | | - ) |
3471 | | - if not code and out.startswith('ceph version '): |
3472 | | - cache['host_version'] = out.split(' ')[2] |
3473 | | - except Exception: |
3474 | | - pass |
3475 | | - val['host_version'] = cache.get('host_version') |
3476 | | - |
3477 | | - |
3478 | | -def _update_daemon_and_container_status( |
3479 | | - val: Dict[str, Any], |
3480 | | - ctx: CephadmContext, |
3481 | | - identity: DaemonIdentity, |
3482 | | - data_dir: str, |
3483 | | - seen_versions: Dict[str, Optional[str]], |
3484 | | - seen_digests: Dict[str, List[str]], |
3485 | | - seen_memusage_cid_len: int, |
3486 | | - seen_memusage: Dict[str, int], |
3487 | | - seen_cpuperc_cid_len: int, |
3488 | | - seen_cpuperc: Dict[str, str], |
3489 | | -) -> None: |
3490 | | - # aliases (to clean up later) |
3491 | | - container_path = ctx.container_engine.path |
3492 | | - fsid = identity.fsid |
3493 | | - daemon_type = identity.daemon_type |
3494 | | - daemon_id = identity.daemon_id |
3495 | | - name = j = identity.daemon_name |
3496 | | - |
3497 | | - # get container id |
3498 | | - (val['enabled'], val['state'], _) = check_unit( |
3499 | | - ctx, identity.unit_name |
3500 | | - ) |
3501 | | - container_id = None |
3502 | | - image_name = None |
3503 | | - image_id = None |
3504 | | - image_digests = None |
3505 | | - version = None |
3506 | | - start_stamp = None |
3507 | | - |
3508 | | - cinfo = get_container_stats( |
3509 | | - ctx, |
3510 | | - DaemonIdentity(fsid, daemon_type, daemon_id), |
3511 | | - container_path=container_path, |
3512 | | - ) |
3513 | | - if cinfo: |
3514 | | - container_id = cinfo.container_id |
3515 | | - image_name = cinfo.image_name |
3516 | | - image_id = cinfo.image_id |
3517 | | - start = cinfo.start |
3518 | | - version = cinfo.version |
3519 | | - image_id = normalize_container_id(image_id) |
3520 | | - daemon_type = name.split('.', 1)[0] |
3521 | | - start_stamp = try_convert_datetime(start) |
3522 | | - |
3523 | | - # collect digests for this image id |
3524 | | - image_digests = seen_digests.get(image_id) |
3525 | | - if not image_digests: |
3526 | | - out, err, code = call( |
3527 | | - ctx, |
3528 | | - [ |
3529 | | - container_path, |
3530 | | - 'image', |
3531 | | - 'inspect', |
3532 | | - image_id, |
3533 | | - '--format', |
3534 | | - '{{.RepoDigests}}', |
3535 | | - ], |
3536 | | - verbosity=CallVerbosity.QUIET, |
3537 | | - ) |
3538 | | - if not code: |
3539 | | - image_digests = list( |
3540 | | - set( |
3541 | | - map( |
3542 | | - normalize_image_digest, |
3543 | | - out.strip()[1:-1].split(' '), |
3544 | | - ) |
3545 | | - ) |
3546 | | - ) |
3547 | | - seen_digests[image_id] = image_digests |
3548 | | - |
3549 | | - # identify software version inside the container (if we can) |
3550 | | - if not version or '.' not in version: |
3551 | | - version = seen_versions.get(image_id, None) |
3552 | | - if daemon_type == NFSGanesha.daemon_type: |
3553 | | - version = NFSGanesha.get_version( |
3554 | | - ctx, container_id |
3555 | | - ) |
3556 | | - if daemon_type == CephIscsi.daemon_type: |
3557 | | - version = CephIscsi.get_version(ctx, container_id) |
3558 | | - if daemon_type == CephNvmeof.daemon_type: |
3559 | | - version = CephNvmeof.get_version( |
3560 | | - ctx, container_id |
3561 | | - ) |
3562 | | - if daemon_type == SMB.daemon_type: |
3563 | | - version = SMB.get_version(ctx, container_id) |
3564 | | - elif not version: |
3565 | | - if daemon_type in ceph_daemons(): |
3566 | | - out, err, code = call( |
3567 | | - ctx, |
3568 | | - [ |
3569 | | - container_path, |
3570 | | - 'exec', |
3571 | | - container_id, |
3572 | | - 'ceph', |
3573 | | - '-v', |
3574 | | - ], |
3575 | | - verbosity=CallVerbosity.QUIET, |
3576 | | - ) |
3577 | | - if not code and out.startswith( |
3578 | | - 'ceph version ' |
3579 | | - ): |
3580 | | - version = out.split(' ')[2] |
3581 | | - seen_versions[image_id] = version |
3582 | | - elif daemon_type == 'grafana': |
3583 | | - out, err, code = call( |
3584 | | - ctx, |
3585 | | - [ |
3586 | | - container_path, |
3587 | | - 'exec', |
3588 | | - container_id, |
3589 | | - 'grafana', |
3590 | | - 'server', |
3591 | | - '-v', |
3592 | | - ], |
3593 | | - verbosity=CallVerbosity.QUIET, |
3594 | | - ) |
3595 | | - if not code and out.startswith('Version '): |
3596 | | - version = out.split(' ')[1] |
3597 | | - seen_versions[image_id] = version |
3598 | | - elif daemon_type in [ |
3599 | | - 'prometheus', |
3600 | | - 'alertmanager', |
3601 | | - 'node-exporter', |
3602 | | - 'loki', |
3603 | | - 'promtail', |
3604 | | - ]: |
3605 | | - version = Monitoring.get_version( |
3606 | | - ctx, container_id, daemon_type |
3607 | | - ) |
3608 | | - seen_versions[image_id] = version |
3609 | | - elif daemon_type == 'haproxy': |
3610 | | - out, err, code = call( |
3611 | | - ctx, |
3612 | | - [ |
3613 | | - container_path, |
3614 | | - 'exec', |
3615 | | - container_id, |
3616 | | - 'haproxy', |
3617 | | - '-v', |
3618 | | - ], |
3619 | | - verbosity=CallVerbosity.QUIET, |
3620 | | - ) |
3621 | | - if ( |
3622 | | - not code |
3623 | | - and out.startswith('HA-Proxy version ') |
3624 | | - or out.startswith('HAProxy version ') |
3625 | | - ): |
3626 | | - version = out.split(' ')[2] |
3627 | | - seen_versions[image_id] = version |
3628 | | - elif daemon_type == 'keepalived': |
3629 | | - out, err, code = call( |
3630 | | - ctx, |
3631 | | - [ |
3632 | | - container_path, |
3633 | | - 'exec', |
3634 | | - container_id, |
3635 | | - 'keepalived', |
3636 | | - '--version', |
3637 | | - ], |
3638 | | - verbosity=CallVerbosity.QUIET, |
3639 | | - ) |
3640 | | - if not code and err.startswith('Keepalived '): |
3641 | | - version = err.split(' ')[1] |
3642 | | - if version[0] == 'v': |
3643 | | - version = version[1:] |
3644 | | - seen_versions[image_id] = version |
3645 | | - elif daemon_type == CustomContainer.daemon_type: |
3646 | | - # Because a custom container can contain |
3647 | | - # everything, we do not know which command |
3648 | | - # to execute to get the version. |
3649 | | - pass |
3650 | | - elif daemon_type == SNMPGateway.daemon_type: |
3651 | | - version = SNMPGateway.get_version( |
3652 | | - ctx, fsid, daemon_id |
3653 | | - ) |
3654 | | - seen_versions[image_id] = version |
3655 | | - elif daemon_type == MgmtGateway.daemon_type: |
3656 | | - version = MgmtGateway.get_version( |
3657 | | - ctx, container_id |
3658 | | - ) |
3659 | | - seen_versions[image_id] = version |
3660 | | - elif daemon_type == OAuth2Proxy.daemon_type: |
3661 | | - version = OAuth2Proxy.get_version( |
3662 | | - ctx, container_id |
3663 | | - ) |
3664 | | - seen_versions[image_id] = version |
3665 | | - else: |
3666 | | - logger.warning( |
3667 | | - 'version for unknown daemon type %s' |
3668 | | - % daemon_type |
3669 | | - ) |
3670 | | - else: |
3671 | | - vfile = os.path.join(data_dir, fsid, j, 'unit.image') |
3672 | | - try: |
3673 | | - with open(vfile, 'r') as f: |
3674 | | - image_name = f.read().strip() or None |
3675 | | - except IOError: |
3676 | | - pass |
3677 | | - |
3678 | | - # unit.meta? |
3679 | | - mfile = os.path.join(data_dir, fsid, j, 'unit.meta') |
3680 | | - try: |
3681 | | - with open(mfile, 'r') as f: |
3682 | | - meta = json.loads(f.read()) |
3683 | | - val.update(meta) |
3684 | | - except IOError: |
3685 | | - pass |
3686 | | - |
3687 | | - val['container_id'] = container_id |
3688 | | - val['container_image_name'] = image_name |
3689 | | - val['container_image_id'] = image_id |
3690 | | - val['container_image_digests'] = image_digests |
3691 | | - if container_id: |
3692 | | - val['memory_usage'] = seen_memusage.get( |
3693 | | - container_id[0:seen_memusage_cid_len] |
3694 | | - ) |
3695 | | - val['cpu_percentage'] = seen_cpuperc.get( |
3696 | | - container_id[0:seen_cpuperc_cid_len] |
3697 | | - ) |
3698 | | - val['version'] = version |
3699 | | - val['started'] = start_stamp |
3700 | | - val['created'] = get_file_timestamp( |
3701 | | - os.path.join(data_dir, fsid, j, 'unit.created') |
3702 | | - ) |
3703 | | - val['deployed'] = get_file_timestamp( |
3704 | | - os.path.join(data_dir, fsid, j, 'unit.image') |
3705 | | - ) |
3706 | | - val['configured'] = get_file_timestamp( |
3707 | | - os.path.join(data_dir, fsid, j, 'unit.configured') |
3708 | | - ) |
| 3423 | + return [_updater.expand(ctx, entry) for entry in daemon_entries] |
3709 | 3424 |
|
3710 | 3425 |
|
3711 | 3426 | def get_daemon_description(ctx, fsid, name, detail=False, legacy_dir=None): |
|
0 commit comments