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

filesystem: handle sorting disks without required metadata #2143

Merged
merged 1 commit into from
Jan 24, 2025

Conversation

rmalz-c
Copy link
Contributor

@rmalz-c rmalz-c commented Jan 21, 2025

If there are at least two disks and one of them is missing any metadata used
during sorting installer will crash. Issue can be reproduced using already
available machine .json file: examples/machines/existing-partitions.json
in which /dev/vda does not have serial value.

This patch makes sure that all values used in sorting are initialized

2025-01-21 15:41:33,340 ERROR root:38 finish: subiquity/apply_autoinstall_config: FAIL: '<' not supported between instances of 'str' and 'NoneType'
2025-01-21 15:41:33,340 ERROR subiquity.server.server:503 top level error
Traceback (most recent call last):
File "/home/rmalz/repos/subiquity/subiquity/server/server.py", line 1021, in start
await self.apply_autoinstall_config()
File "/home/rmalz/repos/subiquity/subiquitycore/context.py", line 165, in decorated_async
return await meth(self, **kw)
File "/home/rmalz/repos/subiquity/subiquity/server/server.py", line 575, in apply_autoinstall_config
await controller.apply_autoinstall_config()
File "/home/rmalz/repos/subiquity/subiquitycore/context.py", line 165, in decorated_async
return await meth(self, **kw)
File "/home/rmalz/repos/subiquity/subiquity/server/controllers/filesystem.py", line 484, in apply_autoinstall_config
await self.convert_autoinstall_config(context=context)
File "/home/rmalz/repos/subiquity/subiquitycore/context.py", line 165, in decorated_async
return await meth(self, **kw)
File "/home/rmalz/repos/subiquity/subiquity/server/controllers/filesystem.py", line 1745, in convert_autoinstall_config
await self.run_autoinstall_guided(self.ai_data["layout"])
File "/home/rmalz/repos/subiquity/subiquity/server/controllers/filesystem.py", line 1684, in run_autoinstall_guided
disk = self.get_bootable_matching_disk(match)
File "/home/rmalz/repos/subiquity/subiquity/server/controllers/filesystem.py", line 1594, in get_bootable_matching_disk
matching_disks = self.get_bootable_matching_disks(match)
File "/home/rmalz/repos/subiquity/subiquity/server/controllers/filesystem.py", line 1582, in get_bootable_matching_disks
matching_disks = self.model.disks_for_match(disks, match)
File "/home/rmalz/repos/subiquity/subiquity/models/filesystem.py", line 1800, in disks_for_match
candidates, _ = self._matching_disks(disks, match)
File "/home/rmalz/repos/subiquity/subiquity/models/filesystem.py", line 1791, in _matching_disks
candidates = self._sorted_matches(candidates, m)
File "/home/rmalz/repos/subiquity/subiquity/models/filesystem.py", line 1769, in _sorted_matches
disks.sort(key=lambda d: d.sort_key)
TypeError: '<' not supported between instances of 'str' and 'NoneType'

Fixes: #2050

LP:#2095295

@rmalz-c
Copy link
Contributor Author

rmalz-c commented Jan 21, 2025

There is no LP bug for this issue, let me know if I should create one.

@yolkispalkis
Copy link

Copy link
Collaborator

@dbungert dbungert left a comment

Choose a reason for hiding this comment

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

@yolkispalkis - yes, I believe that LP:#2095295 is the same root cause issue, thanks for pointing that out. It specifically looks to be failing on wwn instead of serial but I'm pretty certain it's the same problem.

@rmalz-c - thanks very much for this, I think you're on the right track.

So while we could fix the users of sort_key, I don't like that as much as it becomes a hidden requirement on theoretical future users of sort_key, should they emerge. Instead I want to see the existing providers of sort_key return a valid answer. Also, note that Raid and LVM_VolGroup objects provide a nested answer, which I think will still fail to sort but not be adequately fixed up by the current PR since they have a second level of tuple going on before the actual values, so sort_key itself must provide a valid answer.

I think the providers of sort_key that interact with the values should be handling this, so Disk, Partition, and ArbitraryDevice, need to None check and substitute the empty string or zero value as matches the type of the field.

Also, I would appreciate unit tests here so that we don't regress that in the future, and an addition to the docstring in _Device.sort_key acknowledging this requirement that the tuple values must never be None.

def sort_key(self) -> int:
return (self.device.sort_key(), self.number)
def sort_key(self) -> Tuple:
return (self.device.sort_key(), self.number or 0)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

pretty sure self.number cannot be None but left it either way

Copy link
Member

Choose a reason for hiding this comment

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

In theory it shouldn't .... but in practice it has at least happened recently

https://bugs.launchpad.net/subiquity/+bug/2095159

@rmalz-c
Copy link
Contributor Author

rmalz-c commented Jan 22, 2025

@dbungert thanks for the review, I have moved a logic as proposed and included a unit test for it.
Also updated, commit message to properly reflect on the changes. As commit message was changed I have also changed PR description.

@rmalz-c rmalz-c changed the title filesystem: handle sorting disks without serial filesystem: handle sorting disks without required metadata Jan 22, 2025
def sort_key(self) -> int:
return (self.device.sort_key(), self.number)
def sort_key(self) -> Tuple:
return (self.device.sort_key(), self.number or 0)
Copy link
Member

Choose a reason for hiding this comment

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

In theory it shouldn't .... but in practice it has at least happened recently

https://bugs.launchpad.net/subiquity/+bug/2095159

subiquity/models/filesystem.py Outdated Show resolved Hide resolved
Copy link
Collaborator

@dbungert dbungert left a comment

Choose a reason for hiding this comment

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

Almost ready, with a fix for Partition.sort_key we can merge this.

If there are at least two disks and one of them is missing any metadata used
during sorting installer will crash. Issue can be reproduced using already
available machine .json file: examples/machines/existing-partitions.json
in which /dev/vda does not have serial value.

This patch makes sure that all values used in sorting are initialized

2025-01-21 15:41:33,340 ERROR root:38 finish: subiquity/apply_autoinstall_config: FAIL: '<' not supported between instances of 'str' and 'NoneType'
2025-01-21 15:41:33,340 ERROR subiquity.server.server:503 top level error
Traceback (most recent call last):
  File "/home/rmalz/repos/subiquity/subiquity/server/server.py", line 1021, in start
    await self.apply_autoinstall_config()
  File "/home/rmalz/repos/subiquity/subiquitycore/context.py", line 165, in decorated_async
    return await meth(self, **kw)
  File "/home/rmalz/repos/subiquity/subiquity/server/server.py", line 575, in apply_autoinstall_config
    await controller.apply_autoinstall_config()
  File "/home/rmalz/repos/subiquity/subiquitycore/context.py", line 165, in decorated_async
    return await meth(self, **kw)
  File "/home/rmalz/repos/subiquity/subiquity/server/controllers/filesystem.py", line 484, in apply_autoinstall_config
    await self.convert_autoinstall_config(context=context)
  File "/home/rmalz/repos/subiquity/subiquitycore/context.py", line 165, in decorated_async
    return await meth(self, **kw)
  File "/home/rmalz/repos/subiquity/subiquity/server/controllers/filesystem.py", line 1745, in convert_autoinstall_config
    await self.run_autoinstall_guided(self.ai_data["layout"])
  File "/home/rmalz/repos/subiquity/subiquity/server/controllers/filesystem.py", line 1684, in run_autoinstall_guided
    disk = self.get_bootable_matching_disk(match)
  File "/home/rmalz/repos/subiquity/subiquity/server/controllers/filesystem.py", line 1594, in get_bootable_matching_disk
    matching_disks = self.get_bootable_matching_disks(match)
  File "/home/rmalz/repos/subiquity/subiquity/server/controllers/filesystem.py", line 1582, in get_bootable_matching_disks
    matching_disks = self.model.disks_for_match(disks, match)
  File "/home/rmalz/repos/subiquity/subiquity/models/filesystem.py", line 1800, in disks_for_match
    candidates, _ = self._matching_disks(disks, match)
  File "/home/rmalz/repos/subiquity/subiquity/models/filesystem.py", line 1791, in _matching_disks
    candidates = self._sorted_matches(candidates, m)
  File "/home/rmalz/repos/subiquity/subiquity/models/filesystem.py", line 1769, in _sorted_matches
    disks.sort(key=lambda d: d.sort_key)
TypeError: '<' not supported between instances of 'str' and 'NoneType'

Fixes: canonical#2050
Copy link
Member

@ogayot ogayot left a comment

Choose a reason for hiding this comment

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

Thank you, LGTM!

for future PRs, I'd prefer to see separate patches for the different fixes. Typically one for the type hint fixes, one for the None keys and one for the sort_keys() -> sort_keys.

Copy link
Collaborator

@Chris-Peterson444 Chris-Peterson444 left a comment

Choose a reason for hiding this comment

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

Thanks!

@dbungert dbungert merged commit 42b6e90 into canonical:main Jan 24, 2025
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants