Mac Build Scripts: Python

From FreekiWiki
Revision as of 10:11, 6 March 2007 by Tonyr (talk | contribs) (→‎globals.py: update)
Jump to navigation Jump to search

Now let's try that Linux Disk Replication script in Python.

Disk Replication

replicate.py

#!/usr/bin/python
from platform import *
from globals import *
from scripts import *
import sys, getopt, string

def usage():
    errExit(2,"usage: replicate -t macType targetdev")

def getArgs():
    macType = target = None
    try:
        opts, args = getopt.getopt(sys.argv[1:], "ht:", ["help"])
    except getopt.GetoptError:
        # print help information and exit:
        usage()
    if not opts: 
        usage()
    for o, a in opts:
        if o == "-t":
            macType = a
        if o in ("-h", "--help"):
            usage()
    if args:
        target = args[0]
    else:
        target = os.environ.get('REPL_TARGET_DRIVE')
    if target is None:
        print "error: no target drive specified"
        usage()
    return macType, target
        

def verifyTarget(host):
    """ target device must exist and have no partition map.  Existence
        is tested by probing with hdparm; partition map is probed with
        fdisk.
    """ 
    devPath = host.get_hdPath()
    cmd = 'hdparm -i ' +  devPath
    r = os.popen(cmd)
    status = r.close()
    if status is not None:
        errExit(8,'error: device ' + devPath + ' does not seem to exist')
    cmd = ('fdisk -l ' + devPath + '| grep ' + devPath + ' | wc -l')
    nPartitions = map(string.strip, os.popen(cmd).readlines())
    if nPartitions:
        errExit(9,'error: there appear to be existing partitions on ' + devPath)

def createPartitions(host):
    """ create an fdisk script for creating partitions on the local
        target drive; create an ext3 filesystem on the linux partition, 
        and initinitialize the swap partition.  Initialializing the swap 
        partition has the benefit of creating a UUID for it.
    """
    # generate fdisk script and apply it
    devPath = host.get_hdPath()
    genFdiskScript(devPath)
    cmd = 'fdisk ' + devPath + ' < ' + fdiskScript
#    os.system(cmd)
    print 'os.system(' + cmd + ')'

    # verify partition existence, and create linux filesystem and swap space
    cmd = 'fdisk -l ' + devPath + ' | grep ' + host.get_linuxPart() \
           + ' | wc -l'
    n_partitions = map(string.strip, os.popen(cmd).readlines())
    if (not n_partitions or n_partitions[0] is not '1'):
        err = 'error: no linux partition ' + host.get_linuxPart() \
              + ' for fs creation'
        errExit(10, err)
#    os.system('mkfs3.ext3' + host.get_linuxPart())
#    os.system('mkswap' + host.get_swapPart())
    print 'os.system(mkfs3.ext3 ' + host.get_linuxPart() + ')'
    print 'os.system(mkswap ' + host.get_swapPart() + ')'

def setupForCopy(host):
    """ verify/create all the necessary mount points
    """
    ## linux target
    mntPath = '/mnt/' + host.get_hd() + linuxpart
    if os.path.exists(mntPath):
        if not os.path.isdir(mntPath):
            errExit(18,'error: mount point ' + mntPath + 'is a regular file;'
                        + 'it must be a directory')
        # else it exists and it is a directory
    else:
        # it does not exist, so create it
#        os.path.mkdir(mntPath,0644)
        print 'os.path.mkdir(' + mntPath + ',0644)'
    # mount target linux partition
    cmd = 'mount -t ext3 -o rw ' + host.get_linuxPart()  + ' ' + mntPath
#    status = os.system(cmd)
    print 'os.system(' + cmd + ')'
#    if (status is not 0):
#        errExit(12,'error: mount target linux partition failed: ' \
#                    + host.get_linuxPart() + ' to ' + mntPath)
#    else:
#        os.system('umount ' + mntPath)

    ## boot target
    mntPath = '/mnt/' + host.get_hd() + swappart
    if os.path.exists(mntPath):
        if not os.path.isdir(mntPath):
            errExit(18,'error: mount point ' + mntPath + 'is a regular file;'
                        + 'it must be a directory')
        # else it exists and it is a directory
    else:
        # it does not exist, so create it
#        os.path.mkdir(mntPath,0644)
        print 'os.path.mkdir(' + mntPath + ',0644)'

def copyPartitions(host,pfm):
    """ copy boot partition with dd, and copy linux install image with 
        rsync; verify boot partition by mounting it as an hfs filesystem
    """
    # copy the boot partition
    mntPath = '/mnt/' + host.get_hd() + bootpart
    bootimgPath = srcHome + '/' + pfm.get_imageType() + '/' + bootpartImg
    cmd = 'dd if=' + bootimgPath + ' of=' + mntPath
#    os.system(cmd)
    print 'os.system(' + cmd + ')'
    
    # mount/verify target boot partition
    cmd = 'mount -t hfs ' + host.get_bootPart()  + ' ' + mntPath
#    status = os.system(cmd)
    print 'os.system(' + cmd + ')'
#    if (status is not 0):
#        errExit(12,'error: mount target swap partition failed: ' \
#                    + host.get_swapPart() + ' to ' + mntPath)
#    else:
#        os.system('umount ' + mntPath)

    # copy the linux partition
    mntPath = '/mnt/' + host.get_hd() + linuxpart
    linuximgPath = srcHome + '/' + pfm.get_imageType() + '/' + linuxImg
    cmd = 'rsync -av ' + linuximgPath + '/ ' + mntPath + '/'
#    status = os.system(cmd)
    print 'os.system(' + cmd + ')'
#    if (status is not 0):
#        errExit(12,'error: mount target linux partition failed: ' \
#                    + host.get_linuxPart() + ' to ' + mntPath)
#    else:
#        os.system('umount ' + mntPath)

def tweakConfigFiles(host,pfm):
    r1=re.compile(r'UUID=([0-9a-fA-F\-]+)')
    cmd = 'vol_id ' + host.get_linuxPart() + ' | grep -i uuid'
    print 'os.system(' + cmd + ')'
    for line in os.popen(cmd).readlines():
        m = r1.search(line)
        if (m):
            linuxuuid = m.group(1)
            break
    cmd = 'vol_id ' + host.get_swapPart() + ' | grep -i uuid'
    print 'os.system(' + cmd + ')'
    for line in os.popen(cmd).readlines():
        print line
        m = r1.search(line)
        if (m):
            swapuuid = m.group(1)
            break

    try:
        genYbConf(pfm)
    except:
        errExit(19,"error: failed to generate yaboot configuration")
    try:
        genFstab(pfm,linuxuuid,swapuuid)
    except:
        errExit(20,"error: failed to generate fstab") 

    mntPath = '/mnt/' + host.get_hd() + linuxpart
    cmd = 'mount -t ext3 -o rw ' + host.get_linuxPart()  + ' ' + mntPath
#    status = os.system(cmd)
    print 'os.system(' + cmd + ')'
    cmd = 'cp ' + fstabFile + ' ' + mntPath + '/etc/yaboot.conf' 
#    os.system(cmd)
    print 'os.system(' + cmd + ')'
    cmd = 'cp ' + ybConfFile + ' ' + mntPath + '/etc/fstab' 
#    os.system(cmd)
    print 'os.system(' + cmd + ')'
    cmd = 'mkofboot -b ' + host.get_bootPart() + ' ' + pfm.get_bootPart() \
          + ' -o ' + pfm.get_bootdev() + ' -C ' + mntPath \
          + '/etc/yaboot.conf ' + '--nonvram'
#    status = os.system(cmd)
    print 'os.system(' + cmd + ')'
#    if (status is not 0):
#        errExit(15,'error:failed to update boot partition')
#    else:
#        os.system('umount ' + mntPath)

def main():
    # first, ensure root user
    if os.getuid() is not 0:
        errExit(1 ,"You must be root to run this script; try using sudo")
    
    macType, target = getArgs()
    h = aPlatform("host")
    p = aPlatform(macType)
    h.set_hd(target)
    verifyTarget(h)
    createPartitions(h)
    setupForCopy(h)
    copyPartitions(h,p)
    tweakConfigFiles(h,p)

if __name__ == "__main__":
    main()

globals.py

import sys

srcHome     = "/root"
bootpartImg = "bootpart.img"
linuxImg    = "rootdir"
fdiskScript = "/tmp/fdisk.script"
ybconfFile  = "/tmp/yaboot.conf"
fstabFile   = "/tmp/fstab"
bootpart    = "2"
linuxpart   = "3"
swappart    = "4"
macType     = "imac"


def errExit(errno, msg):
    print msg
    sys.exit(errno)

platform.py

class Platform:
    def __init__(self):
        self.name = "prototype"
        self.hd_device = "hda"
        self.cd_device = "hdc"
        self.of_bootdev = "hd:"

    def get_name(self):
        return self.name
    def set_name(self,name):
        self.name = name
    def get_hd(self):
        return self.hd_device
    def set_hd(self,device):
        self.hd_device = device
    def get_cd(self):
        return self.cd_device
    def set_cd(self,device):
        self.cd_device = device
    def get_bootdev(self):
        return self.of_bootdev
    def set_cd(self,ofpath):
        self.of_bootdev = ofpath


class imac(Platform):
    def __init__(self):
        self.name = "iMac"
        self.hd_device = "hda"
        self.cd_device = "hdb"
        self.of_bootdev = "/pci@f2000000/mac-io@17/ata-4@1f000/disk@0:"

class g3(Platform):
    def __init__(self):
        self.name = "g3"
        self.hd_device = "hdc"
        self.cd_device = "hda"
        self.of_bootdev = "/pci@80000000/pci-bridge@d/pci-ata@1/@0/disk@0:"

class g4(Platform):
    def __init__(self):
        self.name = "g4"
        self.hd_device = "hda"
        self.cd_device = "hdc"
        self.of_bootdev = "/pci@f2000000/pci-bridge@d/mac-io@7/ata-4@1f000/disk@0:" 

class g4q(Platform):
    def __init__(self):
        self.name = "g4q"
        self.hd_device = "hda"
        self.cd_device = "hdc"
        self.of_bootdev = "/pci@f2000000/mac-io@17/ata-4@1f000/disk@0:" 
        

def aPlatform(name):
    if name == "imac":
        return imac()
    elif name == "g3":
        return g3()
    elif name == "g4":
        return g4()
    elif name == "g4q":
        return g4q()
    else: 
        return Platform()

def dump_platform(p):
    print 'name      : %s '% p.get_name().upper()
    print 'hd        : %s '% p.get_hd()
    print 'cd        : %s '% p.get_cd()
    print 'of_bootdev: %s '% p.get_bootdev()
    print 

if __name__ == "__main__":
    dump_platform(aPlatform("g4"))
    dump_platform(aPlatform("imac"))
    dump_platform(aPlatform("g3"))
    dump_platform(aPlatform("g4q"))

scripts.py