示例#1
0
 def test_is_vmfs_partition_false_different_block_device(self):
     node = factory.make_Node(with_boot_disk=False)
     factory.make_PhysicalBlockDevice(node=node, size=LARGE_BLOCK_DEVICE)
     layout = VMFS6StorageLayout(node)
     layout.configure()
     other_bd_part = factory.make_Partition(node=node)
     self.assertFalse(other_bd_part.is_vmfs_partition())
示例#2
0
def make_Node_with_VMFS6_layout(*args, **kwargs):
    """Create a node with the VMFS6 storage layout applied."""
    kwargs['with_boot_disk'] = False
    node = factory.make_Node(*args, **kwargs)
    factory.make_PhysicalBlockDevice(node=node, size=LARGE_BLOCK_DEVICE)
    layout = VMFS6StorageLayout(node)
    layout.configure()
    return node
示例#3
0
 def test_delete_not_allowed_if_part_of_vmfs_layout(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()
     partition = random.choice(list(pt.partitions.all()))
     self.assertRaises(ValidationError, partition.delete)
示例#4
0
 def test_is_vmfs_partition_false_extra_partition(self):
     node = factory.make_Node(with_boot_disk=False)
     bd = factory.make_PhysicalBlockDevice(node=node,
                                           size=LARGE_BLOCK_DEVICE)
     layout = VMFS6StorageLayout(node, {"root_size": 10 * 1024**3})
     layout.configure()
     pt = bd.get_partitiontable()
     extra_partition = pt.add_partition()
     self.assertFalse(extra_partition.is_vmfs_partition())
示例#5
0
 def test_is_vmfs_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_vmfs_partition())
示例#6
0
 def test_get_partition_number_returns_vmfs_order(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()
     self.assertItemsEqual(
         [1, 2, 3, 5, 6, 7, 8, 9],
         [part.get_partition_number() for part in pt.partitions.all()])
示例#7
0
 def test_is_not_valid_if_vmfs_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()
     partition = random.choice(list(pt.partitions.all()))
     form = FormatPartitionForm(partition, {"fstype": FILESYSTEM_TYPE.EXT4})
     self.assertFalse(form.is_valid())
示例#8
0
    def get_partition_number(self):
        """Return the partition number in the table."""
        # Avoid circular imports.
        from maasserver.storage_layouts import VMFS6StorageLayout

        # Sort manually instead of with `order_by`, this will prevent django
        # from making a query if the partitions are already cached.
        partitions_in_table = self.partition_table.partitions.all()
        partitions_in_table = sorted(partitions_in_table, key=attrgetter('id'))
        idx = partitions_in_table.index(self)
        if self.partition_table.table_type == PARTITION_TABLE_TYPE.GPT:
            # In some instances the first partition is skipped because it
            # is used by the machine architecture for a specific reason.
            #   * ppc64el - reserved for prep partition
            #   * amd64 (not UEFI) - reserved for bios_grub partition
            node = self.get_node()
            arch, _ = node.split_arch()
            boot_disk = node.get_boot_disk()
            bios_boot_method = node.get_bios_boot_method()
            block_device = self.partition_table.block_device
            vmfs_layout = VMFS6StorageLayout(self.get_node())
            vmfs_bd = vmfs_layout.is_layout()
            if vmfs_bd is not None:
                # VMware ESXi is a DD image but MAAS allows partitions to
                # be added to the end of the disk as well as resize the
                # datastore partition. The EFI partition is already in the
                # image so there is no reason to account for it.
                if vmfs_bd.id == block_device.id and idx >= 3:
                    # VMware ESXi skips the 4th partition.
                    return idx + 2
                else:
                    return idx + 1
            elif (arch == "ppc64el" and block_device.id == boot_disk.id):
                return idx + 2
            elif arch == "amd64" and bios_boot_method != "uefi":
                if block_device.type == 'physical':
                    # Delay the `type` check because it can cause a query. Only
                    # physical block devices get the bios_grub partition.
                    return idx + 2
                else:
                    return idx + 1
            else:
                return idx + 1
        elif self.partition_table.table_type == PARTITION_TABLE_TYPE.MBR:
            # If more than 4 partitions then the 4th partition number is
            # skipped because that is used for the extended partition.
            if len(partitions_in_table) > 4 and idx > 2:
                return idx + 2
            else:
                return idx + 1
        else:
            raise ValueError("Unknown partition table type.")
示例#9
0
    def is_vmfs_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.get_partition_number() >= 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
示例#10
0
    def test_POST_creates_with_block_devices_and_partitions(self):
        self.become_admin()
        node = factory.make_Machine(status=NODE_STATUS.READY,
                                    with_boot_disk=False)
        node.boot_disk = factory.make_PhysicalBlockDevice(
            node=node, size=LARGE_BLOCK_DEVICE)
        layout = VMFS6StorageLayout(node)
        layout.configure()
        block_devices = [
            factory.make_PhysicalBlockDevice(node=node) for _ in range(3)
        ]
        block_device = factory.make_PhysicalBlockDevice(
            node=node,
            size=MIN_PARTITION_SIZE * 3 + PARTITION_TABLE_EXTRA_SPACE,
        )
        partition_table = factory.make_PartitionTable(
            block_device=block_device)
        partitions = [
            partition_table.add_partition(size=MIN_PARTITION_SIZE)
            for _ in range(2)
        ]
        name = factory.make_name("name")
        vmfs_uuid = uuid.uuid4()

        response = self.client.post(
            self.get_vmfs_uri(node),
            {
                "name": name,
                "uuid": vmfs_uuid,
                "block_devices": [bd.id for bd in block_devices],
                "partitions": [part.id for part in partitions],
            },
        )
        self.assertThat(response, HasStatusCode(http.client.OK))
        parsed_results = json_load_bytes(response.content)
        self.assertEquals(node.system_id, parsed_results["system_id"])
        # VMFS should be using the 5 devices we listed above.
        self.assertEquals(5, len(parsed_results["devices"]))
        # VMFS should be using all the block devices we created.
        self.assertItemsEqual(
            [bd.id for bd in block_devices] + [block_device.id],
            set([result["device_id"] for result in parsed_results["devices"]]),
        )