Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mgr/dashboard: Add text to empty life expectancy column #47876

Merged
merged 1 commit into from Sep 27, 2022

Conversation

torchiaf
Copy link
Contributor

  • Add life_expectancy_enabled field to /api/osd/{svc_id}/devices
  • Add new value 'n/a' for 'Life Expectancy' column

Fixes: https://tracker.ceph.com/issues/43116
Signed-off-by: Francesco Torchia francesco.torchia@suse.com

Contribution Guidelines

Checklist

  • Tracker (select at least one)
    • References tracker ticket
    • Very recent bug; references commit where it was introduced
    • New feature (ticket optional)
    • Doc update (no ticket needed)
    • Code cleanup (no ticket needed)
  • Component impact
    • Affects Dashboard, opened tracker ticket
    • Affects Orchestrator, opened tracker ticket
    • No impact that needs to be tracked
  • Documentation (select at least one)
    • Updates relevant documentation
    • No doc update is appropriate
  • Tests (select at least one)
Show available Jenkins commands
  • jenkins retest this please
  • jenkins test classic perf
  • jenkins test crimson perf
  • jenkins test signed
  • jenkins test make check
  • jenkins test make check arm64
  • jenkins test submodules
  • jenkins test dashboard
  • jenkins test dashboard cephadm
  • jenkins test api
  • jenkins test docs
  • jenkins render docs
  • jenkins test ceph-volume all
  • jenkins test ceph-volume tox
  • jenkins test windows

@torchiaf torchiaf requested a review from a team as a code owner August 30, 2022 15:50
@torchiaf torchiaf requested review from aaSharma14 and bryanmontalvan and removed request for a team August 30, 2022 15:50
@votdev votdev self-requested a review August 31, 2022 07:29
@votdev votdev added this to In progress in Dashboard via automation Aug 31, 2022
@votdev votdev moved this from In progress to Review in progress in Dashboard Aug 31, 2022
@torchiaf
Copy link
Contributor Author

Below, a demo on how the fix was implemented on the web-gui:

image

@torchiaf
Copy link
Contributor Author

The CI steps which are failed are not apparently related to the changes included in this PR.

@@ -391,8 +391,17 @@ def safe_to_delete(self, svc_ids):

@RESTController.Resource('GET')
def devices(self, svc_id):
devices: list = CephService.send_command(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which is right type now? Is it a list or a dict as specified in line 403 (# (str) -> dict)?

@epuertat How are type hints handled in the Dashboard code nowadays?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having a look at it, it can return both a str or anything returned by json.loads:

def send_command(srv_type, prefix, srv_spec='', **kwargs):
# type: (str, str, Optional[str], Any) -> Any
"""
:type prefix: str
:param srv_type: mon |
:param kwargs: will be added to argdict
:param srv_spec: typically empty. or something like "<fs_id>:0"
:raises PermissionError: See rados.make_ex
:raises ObjectNotFound: See rados.make_ex
:raises IOError: See rados.make_ex
:raises NoSpace: See rados.make_ex
:raises ObjectExists: See rados.make_ex
:raises ObjectBusy: See rados.make_ex
:raises NoData: See rados.make_ex
:raises InterruptedOrTimeoutError: See rados.make_ex
:raises TimedOut: See rados.make_ex
:raises ValueError: return code != 0
"""
argdict = {
"prefix": prefix,
"format": "json",
}
argdict.update({k: v for k, v in kwargs.items() if v is not None})
result = CommandResult("")
mgr.send_command(result, srv_type, srv_spec, json.dumps(argdict), "")
r, outb, outs = result.wait()
if r != 0:
logger.error("send_command '%s' failed. (r=%s, outs=\"%s\", kwargs=%s)", prefix, r,
outs, kwargs)
raise SendCommandError(outs, prefix, argdict, r)
try:
return json.loads(outb or outs)
except Exception: # pylint: disable=broad-except
return outb

Comment on lines 398 to 498
life_expectancy_enabled = any(
item.startswith('diskprediction_') for item in modules['enabled_modules'])
for device in devices:
device['life_expectancy_enabled'] = life_expectancy_enabled
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should think of a nicer way to deal with cross-module deps. @pereman2 as you're familiar with the ceph-mgr code, isn't there any way to detect whether another module is enabled/running? Or even better, declare that a module depends on others (new global var MODULE_DEPENDS or something like that?) and automatically enable/load them. What do you think?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be possible ernesto, let me take a look.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pereman2 Any news here how to get a list of enabled mgr modules without running a send_command?

Copy link
Member

@votdev votdev Sep 12, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@torchiaf I think mgr.get('mgr_map') and mgr.get('mgr_map')['modules'] or mgr.get('mgr_map')['available_modules'] is the way to go. Have a look at https://github.com/ceph/ceph/blob/main/src/pybind/mgr/dashboard/controllers/mgr_modules.py#L47 how to get the required information. @pereman2 I'm right?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is, MGRMap has all these info and you can get it with mgr.get('mgr_map'). I'll paste a snippet from controllers/mgr_modules.py where this is done.

        result = []
        mgr_map = mgr.get('mgr_map')
        always_on_modules = mgr_map['always_on_modules'].get(mgr.release_name, [])
        for module_config in mgr_map['available_modules']:
            module_name = module_config['name']
            if module_name not in self.ignore_modules:
                always_on = module_name in always_on_modules
                enabled = module_name in mgr_map['modules'] or always_on
                result.append({
                    'name': module_name,
                    'enabled': enabled,
                    'always_on': always_on,
                    'options': self._convert_module_options(
                        module_config['module_options'])
                })

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks guys, I will adapt my fix.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@votdev @pereman2 available modules are now fetched by mgr.get('mgr_map').

Comment on lines 16 to 17
<span *ngIf="!value.life_expectancy_enabled"
i18n>N/A</span>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than dealing with null to N/A converstions case by case, what about implementing this in the datatable behaviour itself? I remember that @avanthakkar did this in other places, so I'd rather avoid doing this ad-hoc and implement it as a default behaviour of the column/cell template. What do you think?

Copy link
Contributor Author

@torchiaf torchiaf Sep 1, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@epuertat do you mean to put a new property, e.g. notAvailable: () => boolean, in TableColumn implementation ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@torchiaf: the component in which the Dashboard datatable is based on, ngx-datatable, supports a pipe property for each column. We already have a notAvailable pipe that converts an empty string to n/a:

@Pipe({
name: 'notAvailable'
})
export class NotAvailablePipe implements PipeTransform {
transform(value: any, text?: string): any {
if (value === '') {
return _.defaultTo(text, $localize`n/a`);
}
return value;
}
}

Instead of implementing this same behaviour case by case, IMHO we should probably:

  • Add that pipe by default to the cd-datatable pipe property,
  • And extend that pipe to also check for undefined or null and display the n/a on those cases.

Otherwise, we'll end up having to patch every single place where an empty/null/undefined string may appear.

Copy link
Contributor Author

@torchiaf torchiaf Sep 1, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@epuertat I agree with you to put a default value when the value of a cell is null or undefined.
In our case however, I think It is different from the general case.

The value of lifeExpectancy column depends on many values (min, max, life_expectancy_enabled), it is not a simple translation null -> N/A.

<ng-template #lifeExpectancy
let-value="value">
<span *ngIf="!value.life_expectancy_enabled"
i18n>N/A</span>
<span *ngIf="value.min && !value.max">&gt; {{value.min | i18nPlural: translationMapping}}</span>
<span *ngIf="value.max && !value.min">&lt; {{value.max | i18nPlural: translationMapping}}</span>
<span *ngIf="value.max && value.min">{{value.min}} to {{value.max | i18nPlural: translationMapping}}</span>
</ng-template>

My fix is supposed to works this way :

  • when min and max are empty, show empty value, because it means there are no enough data to calculate the lifeExpectancy value
  • when life_expectancy_enabled is false, show N/A, because it means that the life expectancy module is disabled.

Probably, I should rename life_expectancy_enabled -> life_expectancy_module_enabled.

What do you think about it?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO the column we're talk about is too specific to use generic pipes. In that case the implementation of a template within the component is right.

What can be done to limit the number of variations (N/A vs n/a) which are sadly spread across the whole code is using this:

<span *ngIf="!value.life_expectancy_enabled" i18n>{{ "" | notAvailable }}</span> 

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@votdev suggestion is good enough for this!

@torchiaf torchiaf force-pushed the fix/43116-2 branch 2 times, most recently from 7dbec7a to d3f40f0 Compare September 6, 2022 08:11
Dashboard automation moved this from Review in progress to Reviewer approved Sep 16, 2022
@votdev
Copy link
Member

votdev commented Sep 16, 2022

jenkins retest this please

@Pegonzal
Copy link
Contributor

@torchiaf make check is failing due to linting issues, could you fix that please?

[lint:tslint ] TSLint's support is discontinued and we're deprecating its support in Angular CLI.
[lint:tslint ] To opt-in using the community driven ESLint builder, see: https://github.com/angular-eslint/angular-eslint#migrating-an-angular-cli-project-from-codelyzer-and-tslint.
[lint:html ]
[lint:html ] [htmllint] found 0 errors out of 166 files
[lint:html ]
[lint:html ] ERROR in /home/jenkins-build/build/workspace/ceph-pull-requests/src/pybind/mgr/dashboard/frontend/src/app/ceph/shared/device-list/device-list.component.html
[lint:html ]
[lint:html ] src/app/ceph/shared/device-list/device-list.component.html
[lint:html ] 16:8 Attributes should vertically align
[lint:html ]
[lint:html ]
[lint:tslint ] Linting "ceph-dashboard"...
[lint:tslint ] All files pass linting.

Try running 'npm run fix' to fix some linting errors. Some errors might need a manual fix.

And also, try to keep commits squashed to have the history easier to read.

- Add life_expectancy_enabled field to /api/osd/{svc_id}/devices
- Add new value 'n/a' for 'Life Expectancy' column

Fixes: https://tracker.ceph.com/issues/43116
Signed-off-by: Francesco Torchia <francesco.torchia@suse.com>
@torchiaf
Copy link
Contributor Author

@torchiaf make check is failing due to linting issues, could you fix that please?

[lint:tslint ] TSLint's support is discontinued and we're deprecating its support in Angular CLI. [lint:tslint ] To opt-in using the community driven ESLint builder, see: https://github.com/angular-eslint/angular-eslint#migrating-an-angular-cli-project-from-codelyzer-and-tslint. [lint:html ] [lint:html ] [htmllint] found 0 errors out of 166 files [lint:html ] [lint:html ] ERROR in /home/jenkins-build/build/workspace/ceph-pull-requests/src/pybind/mgr/dashboard/frontend/src/app/ceph/shared/device-list/device-list.component.html [lint:html ] [lint:html ] src/app/ceph/shared/device-list/device-list.component.html [lint:html ] 16:8 Attributes should vertically align [lint:html ] [lint:html ] [lint:tslint ] Linting "ceph-dashboard"... [lint:tslint ] All files pass linting.

Try running 'npm run fix' to fix some linting errors. Some errors might need a manual fix.

And also, try to keep commits squashed to have the history easier to read.

Hi @Pegonzal , sure, i just pushed the fix, thanks.

@nizamial09
Copy link
Member

jenkins test dashboard

@nizamial09 nizamial09 merged commit 395daf2 into ceph:main Sep 27, 2022
11 of 13 checks passed
Dashboard automation moved this from Reviewer approved to Done Sep 27, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Archived in project
Dashboard
  
Done
6 participants