Skip to content

Conversation

@faganihajizada
Copy link
Contributor

@faganihajizada faganihajizada commented Dec 10, 2025

Summary

The current code uses import ClusterShell followed by ClusterShell.NodeSet.NodeSet(), which causes an AttributeError because the ClusterShell module doesn't expose NodeSet as a direct attribute when imported this way.
This bug prevents users from viewing jobs filtered by a specific node in the web UI.

examples: https://github.com/cea-hpc/clustershell/blob/master/doc/examples/check_nodes.py

Solution

Changed to import NodeSet directly:

from ClusterShell.NodeSet import NodeSet

This fix has been applied to:

  • Main code (slurmweb/slurmrestd/init.py)
  • Test files (slurmweb/tests/slurmrestd/test_slurmrestd.py, slurmweb/tests/views/test_agent.py)

Test

  • The import works correctly with ClusterShell
  • Only NodeSet functionality is used in the codebase
  • No other ClusterShell modules are required

@github-actions
Copy link

github-actions bot commented Dec 10, 2025

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@faganihajizada
Copy link
Contributor Author

I have read the CLA Document and I hereby sign the CLA

@faganihajizada
Copy link
Contributor Author

recheck

@faganihajizada faganihajizada force-pushed the fix/clustershell-import branch 2 times, most recently from 64f5095 to b151f63 Compare December 10, 2025 12:17
@rezib
Copy link
Contributor

rezib commented Dec 10, 2025

In what environment did you get this attribute error? Can you please provide the exception backtrace?

@faganihajizada
Copy link
Contributor Author

Environment:

I see this behavior when RacksDB is disabled and patched RacksDB imports to make it optional.

Slurm-web v6.0.0
Python 3.11
ClusterShell 1.9.3

How to Reproduce:

  1. Access the Slurm-web UI
  2. Navigate to the "Jobs" page
  3. Click on a node name where a job is running
  4. This triggers a request to /v6.0.0/jobs?node=<node_name>

Trace:

Thread-80 (process_request_thread): [INFO] 10.0.147.123 - - [10/Dec/2025 12:48:38] "GET /v6.0.0/nodes HTTP/1.1" 200 -
Thread-81 (process_request_thread): [INFO] 10.0.147.123 - - [10/Dec/2025 12:48:42] "GET /v6.0.0/node/awsgpu-0 HTTP/1.1" 200 -
Thread-83 (process_request_thread): [ERROR] Exception on /v6.0.0/jobs [GET]
Traceback (most recent call last):
  File "/usr/local/lib/python3.11/site-packages/flask/app.py", line 1511, in wsgi_app
    response = self.full_dispatch_request()
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/flask/app.py", line 919, in full_dispatch_request
    rv = self.handle_user_exception(e)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/flask/app.py", line 917, in full_dispatch_request
    rv = self.dispatch_request()
         ^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/flask/app.py", line 902, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)  # type: ignore[no-any-return]
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/rfl/web/tokens.py", line 102, in wrapped
    return view(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/slurmweb/views/agent.py", line 162, in jobs
    return jsonify(slurmrest("jobs_by_node", node))
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/slurmweb/views/agent.py", line 73, in wrapper
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/slurmweb/views/agent.py", line 123, in slurmrest
    return getattr(current_app.slurmrestd, method)(*args)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/slurmweb/slurmrestd/__init__.py", line 234, in jobs_by_node
    return [job for job in self.jobs() if on_node(job) and not terminated(job)]
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/slurmweb/slurmrestd/__init__.py", line 234, in <listcomp>
    return [job for job in self.jobs() if on_node(job) and not terminated(job)]
                                          ^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/slurmweb/slurmrestd/__init__.py", line 225, in on_node
    return node in ClusterShell.NodeSet.NodeSet(job["nodes"])
                   ^^^^^^^^^^^^^^^^^^^^
AttributeError: module 'ClusterShell' has no attribute 'NodeSet'

@rezib
Copy link
Contributor

rezib commented Dec 10, 2025

OK, I see!

I wrote a simple reproducer:

$ cat main.py 
import ClusterShell
print(ClusterShell)
print(ClusterShell.NodeSet)
print(ClusterShell.NodeSet.NodeSet)
$ python3 main.py 
<module 'ClusterShell' from '/…/.venv/lib/python3.12/site-packages/ClusterShell/__init__.py'>
Traceback (most recent call last):
  File "/…/main.py", line 3, in <module>
    print(ClusterShell.NodeSet)
          ^^^^^^^^^^^^^^^^^^^^
AttributeError: module 'ClusterShell' has no attribute 'NodeSet'
$ cat pre.py 
from ClusterShell.NodeSet import NodeSet
$ sed -i '1s/^/import pre\n/' main.py
$ python3 main.py 
<module 'ClusterShell' from '/…/.venv/lib/python3.12/site-packages/ClusterShell/__init__.py'>
<module 'ClusterShell.NodeSet' from '/…/.venv/lib/python3.12/site-packages/ClusterShell/NodeSet.py'>
<class 'ClusterShell.NodeSet.NodeSet'>

Indeed, the bug is hidden by RacksDB which imports NodeSet correctly. That explains why I never met the bug in CI and in supported installations.

Thank you @faganihajizada for reporting!

@faganihajizada
Copy link
Contributor Author

Thanks @rezib

If you are fine, I am planning to submit another PR to update RacksDB imports to make it optional.

The module was incorrectly imported as 'import ClusterShell' which doesn't
expose NodeSet as a direct attribute. This causes AttributeError when trying
to access ClusterShell.NodeSet.NodeSet().

Changed to import NodeSet directly from ClusterShell.NodeSet module and
updated the usage accordingly throughout the codebase.

This fixes the error when viewing jobs on a specific node in the web UI.

Signed-off-by: Rémi Palancher <[email protected]>
@rezib rezib force-pushed the fix/clustershell-import branch from b151f63 to 2bd9919 Compare December 10, 2025 14:23
@rezib rezib self-requested a review December 10, 2025 14:36
@rezib rezib self-assigned this Dec 10, 2025
@rezib rezib added this to the v6.1.0 milestone Dec 10, 2025
@rezib rezib merged commit d7fe3b0 into rackslab:main Dec 10, 2025
16 checks passed
@github-actions github-actions bot locked and limited conversation to collaborators Dec 10, 2025
@rezib
Copy link
Contributor

rezib commented Dec 10, 2025

If you are fine, I am planning to submit another PR to update RacksDB imports to make it optional.

I'm fine with it!

@faganihajizada faganihajizada deleted the fix/clustershell-import branch December 10, 2025 14:52
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants