Reject incomplete backing ancestry and allow empty optical drives
This commit is contained in:
+15
-3
@@ -97,8 +97,13 @@ class Topology:
|
||||
size, identity = node.get('size'), node.get('maj:min')
|
||||
if not isinstance(mounts, list) or any(m is not None and not isinstance(m, str) for m in mounts):
|
||||
raise InstallError('Malformed lsblk mountpoints')
|
||||
if isinstance(size, bool) or not isinstance(size, int) or size <= 0:
|
||||
if isinstance(size, bool) or not isinstance(size, int) or size < 0:
|
||||
raise InstallError('Invalid lsblk size')
|
||||
empty_optical = (kind == 'rom' and not any(mounts)
|
||||
and not node.get('children') and node.get('pkname') is None
|
||||
and ancestor is None)
|
||||
if size == 0 and not empty_optical:
|
||||
raise InstallError('Zero-size device is not an unrelated empty optical drive')
|
||||
if not isinstance(identity, str) or not re.fullmatch(r'\d+:\d+', identity):
|
||||
raise InstallError('Invalid lsblk device identity')
|
||||
if path in result.nodes and any(result.nodes[path][key] != node[key] for key in ('type', 'size', 'maj:min', 'mountpoints')):
|
||||
@@ -149,8 +154,13 @@ class Topology:
|
||||
for path in directed:
|
||||
check_cycle(path)
|
||||
for path, node in result.nodes.items():
|
||||
if node['type'] == 'part' and not result.edges[path]:
|
||||
raise InstallError('Partition has no known parent')
|
||||
if node['size'] == 0 and result.edges[path]:
|
||||
raise InstallError('Empty optical drive has block-device dependencies')
|
||||
# An undirected child edge does not establish backing ancestry.
|
||||
# Each layer must identify its own parent, even when another
|
||||
# apparently unrelated disk is the requested installation target.
|
||||
if node['type'] not in {'disk', 'rom', 'loop', 'zram'} and not directed[path]:
|
||||
raise InstallError(f"Device has no known backing parent: {path} ({node['type']})")
|
||||
return result
|
||||
|
||||
def link(self, child, parent):
|
||||
@@ -162,6 +172,8 @@ class Topology:
|
||||
def protect(self, path):
|
||||
if path not in self.nodes:
|
||||
raise InstallError(f'Cannot resolve mounted/live source: {path}')
|
||||
if self.nodes[path]['size'] == 0:
|
||||
raise InstallError(f'Empty optical drive unexpectedly backs mounted/live storage: {path}')
|
||||
self.protected.add(path)
|
||||
|
||||
def component(self, path):
|
||||
|
||||
Reference in New Issue
Block a user