sts-sponsors team mailing list archive
-
sts-sponsors team
-
Mailing list archive
-
Message #07814
[Merge] ~alexsander-souza/maas:fix_vmfs_layout into maas:master
Alexsander de Souza has proposed merging ~alexsander-souza/maas:fix_vmfs_layout into maas:master.
Commit message:
Update ESXi 7+ layout to new disk size
packer-maas template has been updated to use a 32GB image, and as consequence the size of the partitions has grow. This patch reflects this change in the MAAS storage layout.
Requested reviews:
MAAS Maintainers (maas-maintainers)
For more details, see:
https://code.launchpad.net/~alexsander-souza/maas/+git/maas/+merge/442046
a 32GB disk has always been a requirement of ESXi 7+ storage layout, but only recently the installer started to enforce this limit.
--
Your team MAAS Committers is subscribed to branch maas:master.
diff --git a/src/maasserver/models/partition.py b/src/maasserver/models/partition.py
index 84a8fba..76515e5 100644
--- a/src/maasserver/models/partition.py
+++ b/src/maasserver/models/partition.py
@@ -304,44 +304,26 @@ class Partition(CleanSave, TimestampedModel):
}
)
- def is_vmfs6_partition(self):
- # Avoid circular imports.
- from maasserver.storage_layouts import VMFS6StorageLayout
-
- vmfs_layout = VMFS6StorageLayout(self.get_node())
- vmfs_bd = vmfs_layout.is_layout()
- if vmfs_bd is None:
- return False
- if vmfs_bd.id != self.partition_table.block_device_id:
- return False
- if self.index >= len(vmfs_layout.base_partitions) + 2:
- # A user may apply the VMFS6 layout and leave space at the end of
- # the disk for additional VMFS datastores. Those partitions may be
- # deleted, the base partitions may not as they are part of the DD.
- # The + 2 is to account for partition 4 being skipped.
- return False
- return True
-
- def is_vmfs7_partition(self):
+ def is_vmfs_partition(self):
# Avoid circular imports.
- from maasserver.storage_layouts import VMFS7StorageLayout
-
- vmfs_layout = VMFS7StorageLayout(self.get_node())
- vmfs_bd = vmfs_layout.is_layout()
- if vmfs_bd is None:
- return False
- if vmfs_bd.id != self.partition_table.block_device_id:
- return False
- if self.index < len(vmfs_layout.base_partitions) + 3:
- # A user may apply the VMFS7 layout and leave space at the end of
- # the disk for additional VMFS datastores. Those partitions may be
- # deleted, the base partitions may not as they are part of the DD.
- # The + 3 is to account for partition 2-4 being skipped.
- return True
- return False
+ from maasserver.storage_layouts import (
+ VMFS6StorageLayout,
+ VMFS7StorageLayout,
+ )
- def is_vmfs_partition(self):
- return self.is_vmfs6_partition() or self.is_vmfs7_partition()
+ part_blk_dev_id = self.partition_table.block_device_id
+
+ for layout_class in (VMFS7StorageLayout, VMFS6StorageLayout):
+ vmfs_layout = layout_class(self.get_node())
+ vmfs_bd = vmfs_layout.is_layout()
+ if vmfs_bd is None or vmfs_bd.id != part_blk_dev_id:
+ continue
+ if self.index <= vmfs_layout.last_base_partition_index:
+ # A user may apply the VMFS layout and leave space at the end of
+ # the disk for additional VMFS datastores. Those partitions may be
+ # deleted, the base partitions may not as they are part of the DD.
+ return True
+ return False
def delete(self):
"""Delete the partition.
diff --git a/src/maasserver/models/tests/test_partition.py b/src/maasserver/models/tests/test_partition.py
index 4956d8f..2c9f3bb 100644
--- a/src/maasserver/models/tests/test_partition.py
+++ b/src/maasserver/models/tests/test_partition.py
@@ -544,45 +544,26 @@ class TestPartition(MAASServerTestCase):
[partition.index for partition in partitions],
)
- def test_is_vmfs6_partition(self):
- node = factory.make_Node(with_boot_disk=False)
- bd = factory.make_PhysicalBlockDevice(
- node=node, size=LARGE_BLOCK_DEVICE
- )
- layout = VMFS6StorageLayout(node)
- layout.configure()
- pt = bd.get_partitiontable()
- for partition in pt.partitions.all():
- self.assertTrue(partition.is_vmfs6_partition())
-
- def test_is_vmfs7_partition(self):
- node = factory.make_Node(with_boot_disk=False)
- bd = factory.make_PhysicalBlockDevice(
- node=node, size=LARGE_BLOCK_DEVICE
- )
- layout = VMFS7StorageLayout(node)
- layout.configure()
- pt = bd.get_partitiontable()
- for partition in pt.partitions.all():
- if partition.index >= 8:
- self.assertFalse(partition.is_vmfs7_partition())
- else:
- self.assertTrue(partition.is_vmfs7_partition())
-
def test_is_vmfs_partition(self):
node = factory.make_Node(with_boot_disk=False)
bd = factory.make_PhysicalBlockDevice(
node=node, size=LARGE_BLOCK_DEVICE
)
- vmfs_layout = random.choice([VMFS6StorageLayout, VMFS7StorageLayout])
- layout = vmfs_layout(node)
- layout_name = layout.configure()
- pt = bd.get_partitiontable()
- for partition in pt.partitions.all():
- if layout_name == "vmfs7" and partition.index >= 8:
- self.assertFalse(partition.is_vmfs_partition())
- else:
- self.assertTrue(partition.is_vmfs_partition())
+ for vmfs_layout in [VMFS6StorageLayout, VMFS7StorageLayout]:
+ layout = vmfs_layout(node)
+ layout_name = layout.configure()
+ pt = bd.get_partitiontable()
+ for partition in pt.partitions.all():
+ if layout_name == "vmfs7" and partition.index >= 8:
+ self.assertFalse(
+ partition.is_vmfs_partition(),
+ f"{layout_name} index {partition.index} is VMFS",
+ )
+ else:
+ self.assertTrue(
+ partition.is_vmfs_partition(),
+ f"{layout_name} index {partition.index} is VMFS",
+ )
def test_is_vmfs_partition_false_no_vmfs(self):
partition = factory.make_Partition()
diff --git a/src/maasserver/storage_layouts.py b/src/maasserver/storage_layouts.py
index 8e1b1e8..4056191 100644
--- a/src/maasserver/storage_layouts.py
+++ b/src/maasserver/storage_layouts.py
@@ -798,25 +798,29 @@ class VMFS6StorageLayout(StorageLayoutBase):
name = "vmfs6"
title = "VMFS6 layout"
- base_partitions = [
- # EFI System
- {"index": 1, "size": 3 * 1024**2, "bootable": True},
- # Basic Data
- {"index": 2, "size": 4 * 1024**3},
- # VMFS Datastore, size is 0 so the partition order is correct, its
- # fixed after everything is applied.
- {"index": 3, "size": 0},
- # Basic Data
- {"index": 5, "size": 249 * 1024**2},
- # Basic Data
- {"index": 6, "size": 249 * 1024**2},
- # VMKCore Diagnostic
- {"index": 7, "size": 109 * 1024**2},
- # Basic Data
- {"index": 8, "size": 285 * 1024**2},
- # VMKCore Diagnostic
- {"index": 9, "size": 2560 * 1024**2},
- ]
+ _default_layout = "default"
+
+ base_partitions = {
+ "default": [
+ # EFI System
+ {"index": 1, "size": 3 * 1024**2, "bootable": True},
+ # Basic Data
+ {"index": 2, "size": 4 * 1024**3},
+ # VMFS Datastore, size is 0 so the partition order is correct, its
+ # fixed after everything is applied.
+ {"index": 3, "size": 0},
+ # Basic Data
+ {"index": 5, "size": 249 * 1024**2},
+ # Basic Data
+ {"index": 6, "size": 249 * 1024**2},
+ # VMKCore Diagnostic
+ {"index": 7, "size": 109 * 1024**2},
+ # Basic Data
+ {"index": 8, "size": 285 * 1024**2},
+ # VMKCore Diagnostic
+ {"index": 9, "size": 2560 * 1024**2},
+ ],
+ }
def _clean_boot_disk(self):
if self.boot_disk.size < (10 * 1024**3):
@@ -854,7 +858,7 @@ class VMFS6StorageLayout(StorageLayoutBase):
updated=now,
**partition,
)
- for partition in self.base_partitions
+ for partition in self.base_partitions[self._default_layout]
]
)
vmfs_part = boot_partition_table.partitions.get(size=0)
@@ -877,54 +881,77 @@ class VMFS6StorageLayout(StorageLayoutBase):
if pt.table_type != PARTITION_TABLE_TYPE.GPT:
continue
partitions = sorted(pt.partitions.all(), key=attrgetter("id"))
- if len(partitions) < len(self.base_partitions):
- continue
- for i, (partition, base_partition) in enumerate(
- zip(partitions, self.base_partitions)
- ):
- if (i + 1) == len(self.base_partitions):
- return bd
- if partition.bootable != base_partition.get("bootable", False):
- break
- # Skip checking the size of the Datastore partition as that
- # changes based on available disk size/user input.
- if base_partition["size"] == 0:
+ for layout in self.base_partitions.values():
+ if len(partitions) < len(layout):
continue
- if partition.size != base_partition["size"]:
- break
+ for i, (partition, base_partition) in enumerate(
+ zip(partitions, layout)
+ ):
+ if (i + 1) == len(layout):
+ return bd
+ if partition.bootable != base_partition.get(
+ "bootable", False
+ ):
+ break
+ # Skip checking the size of the Datastore partition as that
+ # changes based on available disk size/user input.
+ if base_partition["size"] == 0:
+ continue
+ if partition.size != base_partition["size"]:
+ break
return None
+ @property
+ def last_base_partition_index(self):
+ return self.base_partitions[self._default_layout][-1]["index"]
+
class VMFS7StorageLayout(VMFS6StorageLayout):
"""VMFS7 layout.
The VMware ESXi 7+ image is a DD. The image has 5 partitions which are
in order but not linear. Users may only change the last partition which
- is partition 8 and stored at the end of the disk.
-
- NAME PARTITION SIZE START BLOCK END BLOCK
- EFI System 1 105MB 0 105
- Basic Data 5 1074MB 106 1180
- Basic Data 6 1074MB 1181 2255
- VMFSL 7 8.5GB 2256 10959
- VMFS 8 Remaining 10960 End of disk
+ is partition 8 and stored at the end of the disk. In recent ESXi 7 ISOs
+ and version 8 onwards, the 32GB minimum disk size is being enforced,
+ so the Packer template has been updated.
+
+ NAME PARTITION SIZE
+ EFI System 1 100MB
+ Basic Data 5 4GB
+ Basic Data 6 4GB
+ VMFSL 7 23.8GB
+ VMFS 8 Remaining
"""
name = "vmfs7"
title = "VMFS7 layout"
- base_partitions = [
- # EFI System
- {"index": 1, "size": 105 * 1024**2, "bootable": True},
- # Basic Data
- {"index": 5, "size": 1074 * 1024**2},
- # Basic Data
- {"index": 6, "size": 1074 * 1024**2},
- # VMFSL
- {"index": 7, "size": 8704 * 1024**2},
- # VMFS
- {"index": 8, "size": 0},
- ]
+ base_partitions = {
+ "default": [
+ # EFI System
+ {"index": 1, "size": 100 * 1024**2, "bootable": True},
+ # Basic Data
+ {"index": 5, "size": 4 * 1024**3},
+ # Basic Data
+ {"index": 6, "size": 4 * 1024**3},
+ # VMFSL
+ {"index": 7, "size": 24320 * 1024**2},
+ # VMFS
+ {"index": 8, "size": 0},
+ ],
+ "legacy": [
+ # EFI System
+ {"index": 1, "size": 105 * 1024**2, "bootable": True},
+ # Basic Data
+ {"index": 5, "size": 1074 * 1024**2},
+ # Basic Data
+ {"index": 6, "size": 1074 * 1024**2},
+ # VMFSL
+ {"index": 7, "size": 8704 * 1024**2},
+ # VMFS
+ {"index": 8, "size": 0},
+ ],
+ }
def _clean_boot_disk(self):
"""https://docs.vmware.com/en/VMware-vSphere/7.0/com.vmware.esxi.install.doc/GUID-DEB8086A-306B-4239-BF76-E354679202FC.html
@@ -939,9 +966,10 @@ class VMFS7StorageLayout(VMFS6StorageLayout):
self, "boot_size", "Boot disk must be at least 32Gb."
)
- def configure_storage(self, allow_fallback):
- super().configure_storage(allow_fallback)
- return self.name
+ @property
+ def last_base_partition_index(self):
+ # VMFS partition can be modified by the user
+ return self.base_partitions[self._default_layout][-2]["index"]
class CustomStorageLayout(StorageLayoutBase):
diff --git a/src/maasserver/tests/test_storage_layouts.py b/src/maasserver/tests/test_storage_layouts.py
index 0fd7a94..84128ad 100644
--- a/src/maasserver/tests/test_storage_layouts.py
+++ b/src/maasserver/tests/test_storage_layouts.py
@@ -1992,18 +1992,18 @@ class TestVMFS7StorageLayout(MAASServerTestCase):
pt = node.boot_disk.get_partitiontable()
self.assertEqual(
{
- "%s-part1" % node.boot_disk.name: 105 * 1024**2,
- "%s-part5" % node.boot_disk.name: 1074 * 1024**2,
- "%s-part6" % node.boot_disk.name: 1074 * 1024**2,
- "%s-part7" % node.boot_disk.name: 8704 * 1024**2,
+ "%s-part1" % node.boot_disk.name: 100 * 1024**2,
+ "%s-part5" % node.boot_disk.name: 4 * 1024**3,
+ "%s-part6" % node.boot_disk.name: 4 * 1024**3,
+ "%s-part7" % node.boot_disk.name: 24320 * 1024**2,
"%s-part8"
% node.boot_disk.name: (
node.boot_disk.size
- - 105 * 1024**2
- - 1074 * 1024**2
- - 1074 * 1024**2
- - 8704 * 1024**2
- - 7 * 1024**2
+ - 100 * 1024**2
+ - 4 * 1024**3
+ - 4 * 1024**3
+ - 24320 * 1024**2
+ - 8 * 1024**2 # rounding
),
},
{part.name: part.size for part in pt.partitions.all()},
@@ -2035,18 +2035,18 @@ class TestVMFS7StorageLayout(MAASServerTestCase):
pt = root_disk.get_partitiontable()
self.assertEqual(
{
- "%s-part1" % root_disk.name: 105 * 1024**2,
- "%s-part5" % root_disk.name: 1074 * 1024**2,
- "%s-part6" % root_disk.name: 1074 * 1024**2,
- "%s-part7" % root_disk.name: 8704 * 1024**2,
+ "%s-part1" % root_disk.name: 100 * 1024**2,
+ "%s-part5" % root_disk.name: 4 * 1024**3,
+ "%s-part6" % root_disk.name: 4 * 1024**3,
+ "%s-part7" % root_disk.name: 24320 * 1024**2,
"%s-part8"
% root_disk.name: (
root_disk.size
- - 105 * 1024**2
- - 1074 * 1024**2
- - 1074 * 1024**2
- - 8704 * 1024**2
- - 7 * 1024**2
+ - 100 * 1024**2
+ - 4 * 1024**3
+ - 4 * 1024**3
+ - 24320 * 1024**2
+ - 8 * 1024**2
),
},
{part.name: part.size for part in pt.partitions.all()},
@@ -2062,10 +2062,10 @@ class TestVMFS7StorageLayout(MAASServerTestCase):
pt = node.boot_disk.get_partitiontable()
self.assertEqual(
{
- "%s-part1" % node.boot_disk.name: 105 * 1024**2,
- "%s-part5" % node.boot_disk.name: 1074 * 1024**2,
- "%s-part6" % node.boot_disk.name: 1074 * 1024**2,
- "%s-part7" % node.boot_disk.name: 8704 * 1024**2,
+ "%s-part1" % node.boot_disk.name: 100 * 1024**2,
+ "%s-part5" % node.boot_disk.name: 4 * 1024**3,
+ "%s-part6" % node.boot_disk.name: 4 * 1024**3,
+ "%s-part7" % node.boot_disk.name: 24320 * 1024**2,
"%s-part8" % node.boot_disk.name: 10 * 1024**3,
},
{part.name: part.size for part in pt.partitions.all()},
@@ -2080,6 +2080,16 @@ class TestVMFS7StorageLayout(MAASServerTestCase):
layout.configure()
self.assertEqual(bd, layout.is_layout())
+ def test_is_layout_legacy(self):
+ node = make_Node_with_uefi_boot_method()
+ bd = factory.make_PhysicalBlockDevice(
+ node=node, size=LARGE_BLOCK_DEVICE
+ )
+ layout = VMFS7StorageLayout(node)
+ layout._default_layout = "legacy"
+ layout.configure()
+ self.assertEqual(bd, layout.is_layout())
+
def test_is_layout_without_datastore(self):
node = make_Node_with_uefi_boot_method()
bd = factory.make_PhysicalBlockDevice(
Follow ups