예제 #1
0
    def test_commit_with_device_is_always_busy(self, mock_utils_exc,
                                               mock_disk_partitioner_exec):
        CONF.set_override('check_device_interval', 0, group='disk_partitioner')
        dp = disk_partitioner.DiskPartitioner('/dev/fake')
        fake_parts = [(1, {
            'boot_flag': None,
            'extra_flags': None,
            'fs_type': 'fake-fs-type',
            'type': 'fake-type',
            'size': 1
        }),
                      (2, {
                          'boot_flag': 'boot',
                          'extra_flags': None,
                          'fs_type': 'fake-fs-type',
                          'type': 'fake-type',
                          'size': 1
                      })]

        with mock.patch.object(dp, 'get_partitions', autospec=True) as mock_gp:
            mock_gp.return_value = fake_parts
            # Test as if the 'busybox' version of 'fuser' which does not have
            # stderr output
            mock_utils_exc.return_value = ("10000 10001", '')
            self.assertRaises(exception.InstanceDeployFailure, dp.commit)

        mock_disk_partitioner_exec.assert_called_once_with(
            mock.ANY, 'mklabel', 'msdos', 'mkpart', 'fake-type',
            'fake-fs-type', '1', '2', 'mkpart', 'fake-type', 'fake-fs-type',
            '2', '3', 'set', '2', 'boot', 'on')
        mock_utils_exc.assert_called_with('fuser',
                                          '/dev/fake',
                                          run_as_root=True,
                                          check_exit_code=[0, 1])
        self.assertEqual(20, mock_utils_exc.call_count)
예제 #2
0
    def test_commit_with_device_disconnected(self, mock_utils_exc,
                                             mock_disk_partitioner_exec):
        CONF.set_override('check_device_interval', 0, group='disk_partitioner')
        dp = disk_partitioner.DiskPartitioner('/dev/fake')
        fake_parts = [(1, {
            'boot_flag': None,
            'extra_flags': None,
            'fs_type': 'fake-fs-type',
            'type': 'fake-type',
            'size': 1
        }),
                      (2, {
                          'boot_flag': 'boot',
                          'extra_flags': None,
                          'fs_type': 'fake-fs-type',
                          'type': 'fake-type',
                          'size': 1
                      })]

        with mock.patch.object(dp, 'get_partitions', autospec=True) as mock_gp:
            mock_gp.return_value = fake_parts
            mock_utils_exc.return_value = ('', "Specified filename /dev/fake"
                                           " does not exist.")
            self.assertRaises(exception.InstanceDeployFailure, dp.commit)

        mock_disk_partitioner_exec.assert_called_once_with(
            mock.ANY, 'mklabel', 'msdos', 'mkpart', 'fake-type',
            'fake-fs-type', '1', '2', 'mkpart', 'fake-type', 'fake-fs-type',
            '2', '3', 'set', '2', 'boot', 'on')
        mock_utils_exc.assert_called_with('fuser',
                                          '/dev/fake',
                                          run_as_root=True,
                                          check_exit_code=[0, 1])
        self.assertEqual(20, mock_utils_exc.call_count)
    def test_commit(self, mock_utils_exc, mock_disk_partitioner_exec):
        dp = disk_partitioner.DiskPartitioner('/dev/fake')
        fake_parts = [(1, {
            'bootable': False,
            'fs_type': 'fake-fs-type',
            'type': 'fake-type',
            'size': 1
        }),
                      (2, {
                          'bootable': True,
                          'fs_type': 'fake-fs-type',
                          'type': 'fake-type',
                          'size': 1
                      })]
        with mock.patch.object(dp, 'get_partitions', autospec=True) as mock_gp:
            mock_gp.return_value = fake_parts
            mock_utils_exc.return_value = (None, None)
            dp.commit()

        mock_disk_partitioner_exec.assert_called_once_with(
            mock.ANY, 'mklabel', 'msdos', 'mkpart', 'fake-type',
            'fake-fs-type', '1', '2', 'mkpart', 'fake-type', 'fake-fs-type',
            '2', '3', 'set', '2', 'boot', 'on')
        mock_utils_exc.assert_called_once_with('fuser',
                                               '/dev/fake',
                                               run_as_root=True,
                                               check_exit_code=[0, 1])
예제 #4
0
    def test_commit_with_device_is_busy_once(self, mock_utils_exc,
                                             mock_disk_partitioner_exec):
        CONF.set_override('check_device_interval', 0, group='disk_partitioner')
        dp = disk_partitioner.DiskPartitioner('/dev/fake')
        fake_parts = [(1, {
            'boot_flag': None,
            'extra_flags': None,
            'fs_type': 'fake-fs-type',
            'type': 'fake-type',
            'size': 1
        }),
                      (2, {
                          'boot_flag': 'boot',
                          'extra_flags': None,
                          'fs_type': 'fake-fs-type',
                          'type': 'fake-type',
                          'size': 1
                      })]
        # Test as if the 'psmisc' version of 'fuser' which has stderr output
        fuser_outputs = iter([(" 10000 10001", '/dev/fake:\n'), ('', '')])

        with mock.patch.object(dp, 'get_partitions', autospec=True) as mock_gp:
            mock_gp.return_value = fake_parts
            mock_utils_exc.side_effect = fuser_outputs
            dp.commit()

        mock_disk_partitioner_exec.assert_called_once_with(
            mock.ANY, 'mklabel', 'msdos', 'mkpart', 'fake-type',
            'fake-fs-type', '1', '2', 'mkpart', 'fake-type', 'fake-fs-type',
            '2', '3', 'set', '2', 'boot', 'on')
        mock_utils_exc.assert_called_with('fuser',
                                          '/dev/fake',
                                          run_as_root=True,
                                          check_exit_code=[0, 1])
        self.assertEqual(2, mock_utils_exc.call_count)
    def test_commit_with_device_is_busy_once(self, mock_utils_exc,
                                             mock_disk_partitioner_exec):
        dp = disk_partitioner.DiskPartitioner('/dev/fake')
        fake_parts = [(1, {
            'bootable': False,
            'fs_type': 'fake-fs-type',
            'type': 'fake-type',
            'size': 1
        }),
                      (2, {
                          'bootable': True,
                          'fs_type': 'fake-fs-type',
                          'type': 'fake-type',
                          'size': 1
                      })]
        fuser_outputs = iter([("/dev/fake: 10000 10001", None), (None, None)])

        with mock.patch.object(dp, 'get_partitions', autospec=True) as mock_gp:
            mock_gp.return_value = fake_parts
            mock_utils_exc.side_effect = fuser_outputs
            dp.commit()

        mock_disk_partitioner_exec.assert_called_once_with(
            mock.ANY, 'mklabel', 'msdos', 'mkpart', 'fake-type',
            'fake-fs-type', '1', '2', 'mkpart', 'fake-type', 'fake-fs-type',
            '2', '3', 'set', '2', 'boot', 'on')
        mock_utils_exc.assert_called_with('fuser',
                                          '/dev/fake',
                                          run_as_root=True,
                                          check_exit_code=[0, 1])
        self.assertEqual(2, mock_utils_exc.call_count)
 def test_add_partition(self):
     dp = disk_partitioner.DiskPartitioner('/dev/fake')
     dp.add_partition(1024)
     dp.add_partition(512, fs_type='linux-swap')
     dp.add_partition(2048, bootable=True)
     expected = [(1, {
         'bootable': False,
         'fs_type': '',
         'type': 'primary',
         'size': 1024
     }),
                 (2, {
                     'bootable': False,
                     'fs_type': 'linux-swap',
                     'type': 'primary',
                     'size': 512
                 }),
                 (3, {
                     'bootable': True,
                     'fs_type': '',
                     'type': 'primary',
                     'size': 2048
                 })]
     partitions = [(n, p) for n, p in dp.get_partitions()]
     self.assertThat(partitions, HasLength(3))
     self.assertEqual(expected, partitions)
    def test_commit_with_device_is_always_busy(self, mock_utils_exc,
                                               mock_disk_partitioner_exec):
        dp = disk_partitioner.DiskPartitioner('/dev/fake')
        fake_parts = [(1, {
            'bootable': False,
            'fs_type': 'fake-fs-type',
            'type': 'fake-type',
            'size': 1
        }),
                      (2, {
                          'bootable': True,
                          'fs_type': 'fake-fs-type',
                          'type': 'fake-type',
                          'size': 1
                      })]

        with mock.patch.object(dp, 'get_partitions', autospec=True) as mock_gp:
            mock_gp.return_value = fake_parts
            mock_utils_exc.return_value = ("/dev/fake: 10000 10001", None)
            self.assertRaises(exception.InstanceDeployFailure, dp.commit)

        mock_disk_partitioner_exec.assert_called_once_with(
            mock.ANY, 'mklabel', 'msdos', 'mkpart', 'fake-type',
            'fake-fs-type', '1', '2', 'mkpart', 'fake-type', 'fake-fs-type',
            '2', '3', 'set', '2', 'boot', 'on')
        mock_utils_exc.assert_called_with('fuser',
                                          '/dev/fake',
                                          run_as_root=True,
                                          check_exit_code=[0, 1])
        self.assertEqual(20, mock_utils_exc.call_count)
예제 #8
0
 def test_add_partition(self):
     dp = disk_partitioner.DiskPartitioner('/dev/fake')
     dp.add_partition(1024)
     dp.add_partition(512, fs_type='linux-swap')
     dp.add_partition(2048, boot_flag='boot')
     dp.add_partition(2048, boot_flag='bios_grub')
     expected = [(1, {'boot_flag': None,
                      'extra_flags': None,
                      'fs_type': '',
                      'type': 'primary',
                      'size': 1024}),
                 (2, {'boot_flag': None,
                      'extra_flags': None,
                      'fs_type': 'linux-swap',
                      'type': 'primary',
                      'size': 512}),
                 (3, {'boot_flag': 'boot',
                      'extra_flags': None,
                      'fs_type': '',
                      'type': 'primary',
                      'size': 2048}),
                 (4, {'boot_flag': 'bios_grub',
                      'extra_flags': None,
                      'fs_type': '',
                      'type': 'primary',
                      'size': 2048})]
     partitions = [(n, p) for n, p in dp.get_partitions()]
     self.assertThat(partitions, HasLength(4))
     self.assertEqual(expected, partitions)
예제 #9
0
    def test_commit(self, mock_utils_exc, mock_disk_partitioner_exec):
        dp = disk_partitioner.DiskPartitioner('/dev/fake')
        fake_parts = [(1, {
            'boot_flag': None,
            'extra_flags': None,
            'fs_type': 'fake-fs-type',
            'type': 'fake-type',
            'size': 1
        }),
                      (2, {
                          'boot_flag': 'boot',
                          'extra_flags': None,
                          'fs_type': 'fake-fs-type',
                          'type': 'fake-type',
                          'size': 1
                      }),
                      (3, {
                          'boot_flag': 'bios_grub',
                          'extra_flags': None,
                          'fs_type': 'fake-fs-type',
                          'type': 'fake-type',
                          'size': 1
                      }),
                      (4, {
                          'boot_flag': 'boot',
                          'extra_flags': ['prep', 'fake-flag'],
                          'fs_type': 'fake-fs-type',
                          'type': 'fake-type',
                          'size': 1
                      })]
        with mock.patch.object(dp, 'get_partitions', autospec=True) as mock_gp:
            mock_gp.return_value = fake_parts
            mock_utils_exc.return_value = ('', '')
            dp.commit()

        mock_disk_partitioner_exec.assert_called_once_with(
            mock.ANY, 'mklabel', 'msdos', 'mkpart', 'fake-type',
            'fake-fs-type', '1', '2', 'mkpart', 'fake-type', 'fake-fs-type',
            '2', '3', 'set', '2', 'boot', 'on', 'mkpart', 'fake-type',
            'fake-fs-type', '3', '4', 'set', '3', 'bios_grub', 'on', 'mkpart',
            'fake-type', 'fake-fs-type', '4', '5', 'set', '4', 'boot', 'on',
            'set', '4', 'prep', 'on', 'set', '4', 'fake-flag', 'on')
        mock_utils_exc.assert_called_once_with('fuser',
                                               '/dev/fake',
                                               run_as_root=True,
                                               check_exit_code=[0, 1])
예제 #10
0
def make_partitions(dev, root_mb, swap_mb, ephemeral_mb,
                    configdrive_mb, node_uuid, commit=True,
                    boot_option="netboot", boot_mode="bios",
                    disk_label=None, cpu_arch=""):
    """Partition the disk device.

    Create partitions for root, swap, ephemeral and configdrive on a
    disk device.

    :param dev: Path for the device to work on.
    :param root_mb: Size of the root partition in mebibytes (MiB).
    :param swap_mb: Size of the swap partition in mebibytes (MiB). If 0,
        no partition will be created.
    :param ephemeral_mb: Size of the ephemeral partition in mebibytes (MiB).
        If 0, no partition will be created.
    :param configdrive_mb: Size of the configdrive partition in
        mebibytes (MiB). If 0, no partition will be created.
    :param commit: True/False. Default for this setting is True. If False
        partitions will not be written to disk.
    :param boot_option: Can be "local" or "netboot". "netboot" by default.
    :param boot_mode: Can be "bios" or "uefi". "bios" by default.
    :param node_uuid: Node's uuid. Used for logging.
    :param disk_label: The disk label to be used when creating the
        partition table. Valid values are: "msdos", "gpt" or None; If None
        Ironic will figure it out according to the boot_mode parameter.
    :param cpu_arch: Architecture of the node the disk device belongs to.
        When using the default value of None, no architecture specific
        steps will be taken. This default should be used for x86_64. When
        set to ppc64*, architecture specific steps are taken for booting a
        partition image locally.
    :returns: A dictionary containing the partition type as Key and partition
        path as Value for the partitions created by this method.

    """
    LOG.debug("Starting to partition the disk device: %(dev)s "
              "for node %(node)s",
              {'dev': dev, 'node': node_uuid})
    # the actual device names in the baremetal are like /dev/sda, /dev/sdb etc.
    # While for the iSCSI device, the naming convention has a format which has
    # iqn also embedded in it.
    # When this function is called by ironic-conductor, the iSCSI device name
    # should be appended by "part%d". While on the baremetal, it should name
    # the device partitions as /dev/sda1 and not /dev/sda-part1.
    if is_iscsi_device(dev, node_uuid):
        part_template = dev + '-part%d'
    elif is_nvme_device(dev):
        part_template = dev + 'p%d'
    else:
        part_template = dev + '%d'
    part_dict = {}

    if disk_label is None:
        disk_label = 'gpt' if boot_mode == 'uefi' else 'msdos'

    dp = disk_partitioner.DiskPartitioner(dev, disk_label=disk_label)

    # For uefi localboot, switch partition table to gpt and create the efi
    # system partition as the first partition.
    if boot_mode == "uefi" and boot_option == "local":
        part_num = dp.add_partition(CONF.disk_utils.efi_system_partition_size,
                                    fs_type='fat32',
                                    boot_flag='boot')
        part_dict['efi system partition'] = part_template % part_num

    if (boot_mode == "bios" and boot_option == "local" and disk_label == "gpt"
        and not cpu_arch.startswith('ppc64')):
        part_num = dp.add_partition(CONF.disk_utils.bios_boot_partition_size,
                                    boot_flag='bios_grub')
        part_dict['BIOS Boot partition'] = part_template % part_num

    # NOTE(mjturek): With ppc64* nodes, partition images are expected to have
    # a PrEP partition at the start of the disk. This is an 8 MiB partition
    # with the boot and prep flags set. The bootloader should be installed
    # here.
    if (cpu_arch.startswith("ppc64") and boot_mode == "bios" and
        boot_option == "local"):
        LOG.debug("Add PReP boot partition (8 MB) to device: "
                  "%(dev)s for node %(node)s",
                  {'dev': dev, 'node': node_uuid})
        boot_flag = 'boot' if disk_label == 'msdos' else None
        part_num = dp.add_partition(8, part_type='primary',
                                    boot_flag=boot_flag, extra_flags=['prep'])
        part_dict['PReP Boot partition'] = part_template % part_num
    if ephemeral_mb:
        LOG.debug("Add ephemeral partition (%(size)d MB) to device: %(dev)s "
                  "for node %(node)s",
                  {'dev': dev, 'size': ephemeral_mb, 'node': node_uuid})
        part_num = dp.add_partition(ephemeral_mb)
        part_dict['ephemeral'] = part_template % part_num
    if swap_mb:
        LOG.debug("Add Swap partition (%(size)d MB) to device: %(dev)s "
                  "for node %(node)s",
                  {'dev': dev, 'size': swap_mb, 'node': node_uuid})
        part_num = dp.add_partition(swap_mb, fs_type='linux-swap')
        part_dict['swap'] = part_template % part_num
    if configdrive_mb:
        LOG.debug("Add config drive partition (%(size)d MB) to device: "
                  "%(dev)s for node %(node)s",
                  {'dev': dev, 'size': configdrive_mb, 'node': node_uuid})
        part_num = dp.add_partition(configdrive_mb)
        part_dict['configdrive'] = part_template % part_num

    # NOTE(lucasagomes): Make the root partition the last partition. This
    # enables tools like cloud-init's growroot utility to expand the root
    # partition until the end of the disk.
    LOG.debug("Add root partition (%(size)d MB) to device: %(dev)s "
              "for node %(node)s",
              {'dev': dev, 'size': root_mb, 'node': node_uuid})

    boot_val = 'boot' if (not cpu_arch.startswith("ppc64")
                          and boot_mode == "bios"
                          and boot_option == "local"
                          and disk_label == "msdos") else None

    part_num = dp.add_partition(root_mb, boot_flag=boot_val)

    part_dict['root'] = part_template % part_num

    if commit:
        # write to the disk
        dp.commit()
    return part_dict
예제 #11
0
def make_partitions(dev,
                    root_mb,
                    swap_mb,
                    ephemeral_mb,
                    configdrive_mb,
                    node_uuid,
                    commit=True,
                    boot_option="netboot",
                    boot_mode="bios",
                    disk_label=None):
    """Partition the disk device.

    Create partitions for root, swap, ephemeral and configdrive on a
    disk device.

    :param root_mb: Size of the root partition in mebibytes (MiB).
    :param swap_mb: Size of the swap partition in mebibytes (MiB). If 0,
        no partition will be created.
    :param ephemeral_mb: Size of the ephemeral partition in mebibytes (MiB).
        If 0, no partition will be created.
    :param configdrive_mb: Size of the configdrive partition in
        mebibytes (MiB). If 0, no partition will be created.
    :param commit: True/False. Default for this setting is True. If False
        partitions will not be written to disk.
    :param boot_option: Can be "local" or "netboot". "netboot" by default.
    :param boot_mode: Can be "bios" or "uefi". "bios" by default.
    :param node_uuid: Node's uuid. Used for logging.
    :param disk_label: The disk label to be used when creating the
        partition table. Valid values are: "msdos", "gpt" or None; If None
        Ironic will figure it out according to the boot_mode parameter.
    :returns: A dictionary containing the partition type as Key and partition
        path as Value for the partitions created by this method.

    """
    LOG.debug(
        "Starting to partition the disk device: %(dev)s "
        "for node %(node)s", {
            'dev': dev,
            'node': node_uuid
        })
    # the actual device names in the baremetal are like /dev/sda, /dev/sdb etc.
    # While for the iSCSI device, the naming convention has a format which has
    # iqn also embedded in it.
    # When this function is called by ironic-conductor, the iSCSI device name
    # should be appended by "part%d". While on the baremetal, it should name
    # the device partitions as /dev/sda1 and not /dev/sda-part1.
    if is_iscsi_device(dev, node_uuid):
        part_template = dev + '-part%d'
    else:
        part_template = dev + '%d'
    part_dict = {}

    if disk_label is None:
        disk_label = 'gpt' if boot_mode == 'uefi' else 'msdos'

    dp = disk_partitioner.DiskPartitioner(dev, disk_label=disk_label)

    # For uefi localboot, switch partition table to gpt and create the efi
    # system partition as the first partition.
    if boot_mode == "uefi" and boot_option == "local":
        part_num = dp.add_partition(CONF.disk_utils.efi_system_partition_size,
                                    fs_type='fat32',
                                    bootable=True)
        part_dict['efi system partition'] = part_template % part_num

    if ephemeral_mb:
        LOG.debug(
            "Add ephemeral partition (%(size)d MB) to device: %(dev)s "
            "for node %(node)s", {
                'dev': dev,
                'size': ephemeral_mb,
                'node': node_uuid
            })
        part_num = dp.add_partition(ephemeral_mb)
        part_dict['ephemeral'] = part_template % part_num
    if swap_mb:
        LOG.debug(
            "Add Swap partition (%(size)d MB) to device: %(dev)s "
            "for node %(node)s", {
                'dev': dev,
                'size': swap_mb,
                'node': node_uuid
            })
        part_num = dp.add_partition(swap_mb, fs_type='linux-swap')
        part_dict['swap'] = part_template % part_num
    if configdrive_mb:
        LOG.debug(
            "Add config drive partition (%(size)d MB) to device: "
            "%(dev)s for node %(node)s", {
                'dev': dev,
                'size': configdrive_mb,
                'node': node_uuid
            })
        part_num = dp.add_partition(configdrive_mb)
        part_dict['configdrive'] = part_template % part_num

    # NOTE(lucasagomes): Make the root partition the last partition. This
    # enables tools like cloud-init's growroot utility to expand the root
    # partition until the end of the disk.
    LOG.debug(
        "Add root partition (%(size)d MB) to device: %(dev)s "
        "for node %(node)s", {
            'dev': dev,
            'size': root_mb,
            'node': node_uuid
        })
    part_num = dp.add_partition(root_mb,
                                bootable=(boot_option == "local"
                                          and boot_mode == "bios"))
    part_dict['root'] = part_template % part_num

    if commit:
        # write to the disk
        dp.commit()
    return part_dict
예제 #12
0
def make_partitions(dev,
                    root_mb,
                    swap_mb,
                    ephemeral_mb,
                    configdrive_mb,
                    commit=True,
                    boot_option="netboot",
                    boot_mode="bios"):
    """Partition the disk device.

    Create partitions for root, swap, ephemeral and configdrive on a
    disk device.

    :param root_mb: Size of the root partition in mebibytes (MiB).
    :param swap_mb: Size of the swap partition in mebibytes (MiB). If 0,
        no partition will be created.
    :param ephemeral_mb: Size of the ephemeral partition in mebibytes (MiB).
        If 0, no partition will be created.
    :param configdrive_mb: Size of the configdrive partition in
        mebibytes (MiB). If 0, no partition will be created.
    :param commit: True/False. Default for this setting is True. If False
        partitions will not be written to disk.
    :param boot_option: Can be "local" or "netboot". "netboot" by default.
    :param boot_mode: Can be "bios" or "uefi". "bios" by default.
    :returns: A dictionary containing the partition type as Key and partition
        path as Value for the partitions created by this method.

    """
    LOG.debug("Starting to partition the disk device: %(dev)s", {'dev': dev})

    if is_iscsi_device(dev):
        part_template = dev + '-part%d'
    else:
        part_template = dev + '%d'

    part_dict = {}

    # For uefi localboot, switch partition table to gpt and create the efi
    # system partition as the first partition.
    if boot_mode == "uefi" and boot_option == "local":
        dp = disk_partitioner.DiskPartitioner(dev, disk_label="gpt")
        part_num = dp.add_partition(CONF.disk_utils.efi_system_partition_size,
                                    fs_type='fat32',
                                    bootable=True)
        part_dict['efi system partition'] = part_template % part_num
    else:
        dp = disk_partitioner.DiskPartitioner(dev)

    if ephemeral_mb:
        LOG.debug("Add ephemeral partition (%(size)d MB) to device: %(dev)s", {
            'dev': dev,
            'size': ephemeral_mb
        })
        part_num = dp.add_partition(ephemeral_mb)
        part_dict['ephemeral'] = part_template % part_num
    if swap_mb:
        LOG.debug("Add Swap partition (%(size)d MB) to device: %(dev)s", {
            'dev': dev,
            'size': swap_mb
        })
        part_num = dp.add_partition(swap_mb, fs_type='linux-swap')
        part_dict['swap'] = part_template % part_num
    if configdrive_mb:
        LOG.debug(
            "Add config drive partition (%(size)d MB) to device: "
            "%(dev)s", {
                'dev': dev,
                'size': configdrive_mb
            })
        part_num = dp.add_partition(configdrive_mb)
        part_dict['configdrive'] = part_template % part_num

    # NOTE(lucasagomes): Make the root partition the last partition. This
    # enables tools like cloud-init's growroot utility to expand the root
    # partition until the end of the disk.
    LOG.debug("Add root partition (%(size)d MB) to device: %(dev)s", {
        'dev': dev,
        'size': root_mb
    })
    part_num = dp.add_partition(root_mb,
                                bootable=(boot_option == "local"
                                          and boot_mode == "bios"))
    part_dict['root'] = part_template % part_num

    if commit:
        # write to the disk
        dp.commit()
    return part_dict