[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: python (parted) question



[ Please CC replies, I'm not subscribed to either list ]
[ d-python: this is a restatement of my previous question. Hope its ]
[ clearer this time. ]

I posed this question several days ago and received no response.  mdz
(correctly) nudged me with a cluestick by telling me that perhaps I should
be more specific in describing my problem.  So here goes... I'm no python
hacker, so maybe I'm missing something obvious.

I have attached part of a script (python_parted).  It is intended to
partition a disk drive.  I have edited out much of the script before and
after the problem section (such as reading in config files, etc) so that
the size is manageable, if you want the complete script refer to the
'autoinstall' package in Debian unstable.  (I believe the included section
completely describes the problem.)  I have also attached the partition.py
module which is loaded by this script.  All other modules should be
standard... available from either the python or python-parted packages 
in
Debian unstable.

My problem occurs at line 101 of python_parted, that reads:
	drvnewpart = drvdisk.get_partition(drvpartnum)

The get_partition function is defined by the parted module, and always
returns 'None' when I call it.  I have stepped through line-by-line and
every other value appears to be correct up to that point.

get_partition is as follows:

    def get_partition(self, num):
        """Returns the partition numbered num.
        """

        r = _parted.disk_get_partition(self._o, num)
        if r:
            return Partition(self, None, None, None, None, r)
        else:
            return None



and the corresponding C call which accesses libparted:

static PyObject *
disk_get_partition(PyObject *self, PyObject *args)
{
        PyPartedObject *o;
        int num;

        if (!PyArg_ParseTuple(args, "Oi", &o, &num))
                return NULL;

        return PyPartedObject_new("PedPartition",
                                  ped_disk_get_partition((PedDisk *)o->obj,
                                                         num));
}



This same code worked with libparted1.4, and broke at the 1.6 upgrade.  
I'm not sure if the problem is in libparted, python-parted, or user-error.  
I'm perfectly willing to accept the latter, but I hope to find a solution 
anyway.  :)

Is anyone else out there even using python-parted?  There doesn't seem to 
be much info about it...


Thanks,


--
Paul Telford | 1024D/431B38BA | pxt@debian.org | paul@droflet.net
       C903 0E85 9AF5 1B80 6A5F  F169 D7E9 4363 431B 38BA





#!/usr/bin/python -i

import sys
import os
import popen2
import stat
import traceback
import signal
import string
import time
import copy
import parted

# Arch-specific modules
import partition

try:

        drvlist = []
        parted.init()
        parted.device_probe_all()

        print "Examining drives..."
        try:
           drvinstlist = [parted.get_devices()[0]]
        except:
           print "No available drives found!"
           killsystem()

        bootdrv = ""

        for drv in drvinstlist:
            if not bootdrv:
                bootdrv = drv.get_path()

            drvdisk = drv.disk_open()
            if drvdisk is not None:
                partlist = drvdisk.get_part_list()
                isdata = 0
                for part in partlist:
                    if part.get_type() != parted.PARTITION_FREESPACE:
                        isdata = 1

                drvdisk.close()

    # Partition and format drive.
        for drv in drvinstlist:
            print "Partitioning drive %s..." % drv.get_path()

            drvobj = partition.Partition(drv)
            drvsectors = drv.get_length()
            drvobj.create_partition_table()

            partabssect = 0
            # for reference, partcfg at this point looks like:
            # [['ext2', '80%', '/', ['primary']], ['swap', '256M', 'swap', ['primary']]]
            for partinfo in partcfg:
                if partinfo[2] == "/":
                    rootpart = partinfo
                partsizetype = string.upper(partinfo[1][-1])
                if partsizetype == "M":
                    partsize = string.atoi(partinfo[1][:-1])
                    partsect = int(float(partsize) * 1024 * 1024 / parted.SECTOR_SIZE)
                    partabssect = partabssect + partsect
                elif partsizetype != "%":
                    raise RuntimeError, "invalid partition size specifier"
            partremsect = drvsectors - partabssect - curpartend

            for (partfs, partsizestr, partmount, parthints) in partcfg:
                print "Creating %s partition for %s..." % (partfs, partmount)
                partsizetype = string.upper(partsizestr[-1])
                partsize = string.atoi(partsizestr[:-1])

                if partfs == "swap":
                    partfs = "linux-swap"
                partfstype = parted.file_system_type_get(partfs)

                if partsizetype == "%":
                    partsect = int(partremsect * (float(partsize) / 100))
                else:
                    partsect = int(float(partsize) * 1024 * 1024 / parted.SECTOR_SIZE)

                partdevice = drvobj.create_partition(curpartend,
                                                     curpartend + partsect - 1,
                                                     partfstype, parthints)
                mountlist.append([partdevice, partmount, partfs])
                curpartend = curpartend + partsect

            drvobj.commit_changes()

            drvdisk = drv.disk_open()
            for (partdevice, partmount, partfs) in mountlist:
                print "Creating %s file system on %s..." % (partfs, partdevice)

                drvpartnumstr = partdevice[-2:]
                if drvpartnumstr[0] not in string.digits:
                    drvpartnumstr = drvpartnumstr[1]
                drvpartnum = string.atoi(drvpartnumstr)

                partfstype = parted.file_system_type_get(partfs)
                drvnewpart = drvdisk.get_partition(drvpartnum)
                parted.FileSystem(drvnewpart.get_geom(), partfstype).close()

            drvdisk.close()
            drv.close()

    # Since we're done with partitioning, we can call this now.  This
    # ensures that the partition table is reread by the system.  It's
    # important not to call parted for anything after this.

        parted.done()

# Autoinstaller partition code for MS-DOS style partitions.

# Copyright (c) 2001 Progeny Linux Systems, Inc.
# Written by Jeff Licquia.

# This module assumes that the parted subsystem has already been
# initialized fully; it simply stands in for certain calls that may be
# different for different partition types.

# from python-parted package
import parted

class Partition:
    def __init__(self, drive):
        self.drive = drive
        self.disk = None

        self.primarynum = 0
        self.extnum = 0
        self.isext = 0

    def get_freespace(self):
        if self.disk is None:
            self.disk = self.drive.disk_open()

        if self.disk is not None:
            freelist = []
            partlist = self.disk.get_part_list()
            for part in partlist:
                partnum = part.get_num()
                if part.get_type() == parted.PED_PARTITION_PRIMARY:
                    self.primarynum = partnum + 1
                elif part.get_type() == parted.PED_PARTITION_EXTENDED:
                    self.extnum = partnum + 1
                elif part.get_type() == parted.PED_PARTITION_LOGICAL:
                    self.isext = 1
                elif part.get_type() == parted.PED_PARTITION_FREESPACE:
                    freelist.append([part.get_geom().get_start(),
                                     part.get_geom().get_end()])

            if not self.primarynum:
                if self.isext:
                    self.primarynum = 2
                else:
                    self.primarynum = 1
            if not self.extnum:
                self.extnum = 5
            
            return freelist
        else:
            return None

    def create_partition_table(self):
        self.primarynum = 1
        self.extnum = 5
        self.isext = 0

        self.disk = self.drive.disk_create(parted.disk_type_get("msdos"))
        return self.get_freespace()

    def create_partition(self, start, end, type, hints):
        drvsectors = self.drive.get_length()
        if self.disk is None:
            self.disk = self.drive.disk_open()
        if self.disk is None:
            raise RuntimeError, "drive has no partition table"

        if "primary" in hints:
            if self.primarynum > 4:
                raise RuntimeError, "out of primary partitions"
            if self.isext:
                raise RuntimeError, "cannot create primary partition after extended partition"
            partnum = self.primarynum
            self.primarynum = self.primarynum + 1
            parttypecode = parted.PED_PARTITION_PRIMARY
        else:
            if not self.isext:
                if self.primarynum > 4:
                    raise RuntimeError, "out of slots for extended partition"
                self.disk.add_partition(
                    parted.Partition(self.disk,
                                     parted.PED_PARTITION_EXTENDED,
                                     None, start, drvsectors - 1))
            self.primarynum = self.primarynum + 1
            self.isext = 1
            partnum = self.extnum
            self.extnum = self.extnum + 1
            parttypecode = parted.PED_PARTITION_LOGICAL

        drvnewpart = parted.Partition(self.disk, parttypecode, type,
                                      start, end)
        self.disk.add_partition(drvnewpart)

        partdevice = "%s%d" % (self.drive.get_path(), partnum)
        return partdevice

    def commit_changes(self):
        if self.disk is not None:
            self.disk.write()
            self.disk.close()
            self.disk = None
            self.drive.sync()

Reply to: