from installclass import BaseInstallClass
from rhpl.translate import N_, _
from constants import *
import os
import iutil
from fsset import *

from autopart import getAutopartitionBoot, autoCreatePartitionRequests, autoCreateLVMPartitionRequests
from rhpl.log import log
import string
import partRequests
import partedUtils

class Script:
    def __repr__(self):
	str = ("(s: '%s' i: %s c: %d)") %  \
	    (self.script, self.interp, self.inChroot)
	return string.replace(str, "\n", "|")

    def __init__(self, script, interp, inChroot, logfile = None):
	self.script = script
	self.interp = interp
	self.inChroot = inChroot
        self.logfile = logfile

    def run(self, chroot, serial):
	scriptRoot = "/"
	if self.inChroot:
	    scriptRoot = chroot

	path = scriptRoot + "/tmp/sme-script"

	f = open(path, "w")
	f.write(self.script)
	f.close()
	os.chmod(path, 0700)

        if self.logfile is not None:
            messages = self.logfile
	elif serial:
	    messages = "/tmp/sme-script.log"
	else:
	    messages = "/dev/tty3"

	rc = iutil.execWithRedirect(self.interp,
				    [self.interp,"/tmp/sme-script"],
				    stdout = messages, stderr = messages,
				    root = scriptRoot)

	if rc != 0:
	    log("WARNING - Error code %s encountered running a sme script", rc)

	os.unlink(path)

class InstallClass(BaseInstallClass):
    id = "smeserver"
    name = N_("New _SME Server Install")
    pixmap = "smeserver.png"
    description = N_("This option performs a new install of "
                     "SME Server.  All attached hard drives "
                     "will be repartitioned and formated.")
    sortPriority = 1

    parentClass = ( _("Install SME Server"), "smeserver.png" )

    def requiredDisplayMode(self):
        return 't'

    def setSteps(self, dispatch):
        dispatch.setStepList(
		 "language",
		 "keyboard",
                 "findrootparts",
		 "installtype",
                 "partitionobjinit",
                 "autopartitionexecute",
                 "partition",
		 "partitiondone",
		 "bootloadersetup",                 
		 "languagesupport",
		 "timezone",
		 "readcomps",
                 "selectlangpackages",
		 "checkdeps",
		 "dependencies",
		 "install",
		 "enablefilesystems",
                 "migratefilesystems",
                 "setuptime",
                 "preinstallconfig",
		 "installpackages",
                 "postinstallconfig",
		 "writeconfig",
		 "instbootloader",
                 "dopostaction",
		 "writeksconfig",
                 "methodcomplete",
                 "copylogs",
                 "setfilecon",
		 "complete"
                )

        # 'partition' can be used on the command line to force 
        # verification of partitions.  useful in some cases...
        cmdline = open("/proc/cmdline", "r").read()
        cmdline = cmdline.split()
        if "partition" in cmdline:
            dispatch.skipStep("partition", skip = 0)
        else:
            dispatch.skipStep("partition", skip = 1)

    def setDefaultPartitioning(self, partitions, clear = CLEARPART_TYPE_LINUX, doClear = 1):
        uniqueID = 100
	(swapMin, swapMax) = iutil.swapSuggestion()
	diskset = partedUtils.DiskSet()
	drives = diskset.driveList()
	usedDrives = []

	spares = 0
	useable = 0
	for drive in drives:
	    if not isys.driveIsRemovable(drive):
		useable = useable + 1

	if useable >= 1:
	    if "noraid" in cmdline:
		for drive in drives:
		    if not isys.driveIsRemovable(drive):
			filesystem = fileSystemTypeGet("ext3")
			request = partRequests.PartitionSpec(filesystem, mountpoint="/boot", drive=[drive],
				size=100, primary=1, format=1)
			partitions.autoPartitionRequests.append(request)
			usedDrives.append(drive);

			if "nolvm" in cmdline:
			    filesystem = fileSystemTypeGet("ext3")
			    request = partRequests.PartitionSpec(filesystem, mountpoint="/", drive=[drive],
				    size=1300, grow=1, primary=1, format=1)
			    partitions.autoPartitionRequests.append(request)

			    filesystem = fileSystemTypeGet("swap")
			    request = partRequests.PartitionSpec(filesystem, drive=[drive], size=swapMin, 
				    maxSizeMB=swapMax, grow=1, primary=1, format=1)
			    partitions.autoPartitionRequests.append(request)

			else:
			    filesystem = fileSystemTypeGet("physical volume (LVM)")
			    request = partRequests.PartitionSpec(filesystem, drive=[drive], size=swapMin+1500,
				    grow=1, primary=1, format=1)
			    request.uniqueID = 200
			    partitions.autoPartitionRequests.append(request)

			break

	    else:
		raid1 = []
		raid2 = []
		raid3 = []

		if useable >= 3 and "nospare" not in cmdline:
		    useable = useable - 1
		    spares = 1

		if "raid1" in cmdline and useable >= 1:
		    useable = 1
		    raidLevel = "RAID1"
		else:
		    if useable >= 6:
			useable = useable - 2
			raidLevel = "RAID6"
		    elif useable >= 2:
			useable = useable - 1
			if useable >= 2:
			    raidLevel = "RAID5"
			else:
			    raidLevel = "RAID1"
		    else:
		        raidLevel = "RAID1"

		for drive in drives:
		    if not isys.driveIsRemovable(drive):
			filesystem = fileSystemTypeGet("software RAID")
			request = partRequests.PartitionSpec(filesystem, drive=[drive], size=100, primary=1, format=1)
			request.uniqueID = uniqueID
			raid1.append(uniqueID)
			partitions.autoPartitionRequests.append(request)
			usedDrives.append(drive);

			if "nolvm" in cmdline:
			    filesystem = fileSystemTypeGet("software RAID")
			    request = partRequests.PartitionSpec(filesystem, drive=[drive], size=swapMin/useable+10,
				    maxSizeMB=swapMax/useable, grow=1, primary=1, format=1)
			    request.uniqueID = uniqueID + 30
			    raid2.append(uniqueID + 30)
			    partitions.autoPartitionRequests.append(request)

			    filesystem = fileSystemTypeGet("software RAID")
			    request = partRequests.PartitionSpec(filesystem, drive=[drive], size=1500/useable,
				    grow=1, primary=1, format=1)
			    request.uniqueID = uniqueID + 60
			    raid3.append(uniqueID + 60)
			    partitions.autoPartitionRequests.append(request)

			else:
			    filesystem = fileSystemTypeGet("software RAID")
			    if "multipart" in cmdline:
				request = partRequests.PartitionSpec(filesystem, drive=[drive], size=(swapMin+3000)/useable,
					grow=1, format=1)
			    else:
				request = partRequests.PartitionSpec(filesystem, drive=[drive], size=(swapMin+1500)/useable,
					grow=1, format=1)
			    request.uniqueID = uniqueID + 50
			    raid2.append(uniqueID + 50)
			    partitions.autoPartitionRequests.append(request)

			uniqueID = uniqueID + 1

			if "raid1" in cmdline and len(raid1)-spares >= 2:
			    break

		filesystem = fileSystemTypeGet("ext3")
		request = partRequests.RaidRequestSpec(filesystem, mountpoint="/boot", raidminor=1,
			raidmembers=raid1, raidlevel="RAID1", format=1, raidspares=spares)
		partitions.autoPartitionRequests.append(request)

		if "nolvm" in cmdline:
		    filesystem = fileSystemTypeGet("swap")
		    request = partRequests.RaidRequestSpec(filesystem, raidmembers=raid2,  raidminor=2,
			    raidlevel=raidLevel, format=1, raidspares=spares)
		    partitions.autoPartitionRequests.append(request)

		    filesystem = fileSystemTypeGet("ext3")
		    request = partRequests.RaidRequestSpec(filesystem, mountpoint="/", raidmembers=raid3,  raidminor=3,
			    raidlevel=raidLevel, format=1, raidspares=spares)
		    partitions.autoPartitionRequests.append(request)

		else:
		    filesystem = fileSystemTypeGet("physical volume (LVM)")
		    request = partRequests.RaidRequestSpec(filesystem, raidmembers=raid2,  raidminor=2,
			    raidlevel=raidLevel, format=1, raidspares=spares)
		    request.uniqueID = 200
		    partitions.autoPartitionRequests.append(request)

	    if not "nolvm" in cmdline:
		request = partRequests.VolumeGroupRequestSpec(vgname="main", physvols=[200], 
			pesize=32768, format=1)
		request.uniqueID = 201
		partitions.autoPartitionRequests.append(request)

		if "multipart" in cmdline:
		    filesystem = fileSystemTypeGet("ext3")
		    request = partRequests.LogicalVolumeRequestSpec(filesystem, mountpoint="/", size=2048, 
			    maxSizeMB=4096, volgroup=201, lvname="root", grow=1, format=1)
		    partitions.autoPartitionRequests.append(request)

		    filesystem = fileSystemTypeGet("ext3")
		    request = partRequests.LogicalVolumeRequestSpec(filesystem, mountpoint="/var", size=1024, 
			    maxSizeMB=4096, volgroup=201, lvname="var", grow=1, format=1)
		    partitions.autoPartitionRequests.append(request)

		    filesystem = fileSystemTypeGet("ext3")
		    request = partRequests.LogicalVolumeRequestSpec(filesystem, mountpoint="/home/e-smith/files", size=1024, 
			    maxSizeMB=8192, volgroup=201, lvname="files", grow=1, format=1)
		    partitions.autoPartitionRequests.append(request)

		    filesystem = fileSystemTypeGet("ext3")
		    request = partRequests.LogicalVolumeRequestSpec(filesystem, mountpoint="/tmp", size=512, 
			    maxSizeMB=4096, volgroup=201, lvname="tmp", grow=1, format=1)
		    partitions.autoPartitionRequests.append(request)

		    filesystem = fileSystemTypeGet("swap")
		    request = partRequests.LogicalVolumeRequestSpec(filesystem, size=swapMin, maxSizeMB=swapMax, 
			    volgroup=201, lvname="swap", grow=1, format=1)
		    partitions.autoPartitionRequests.append(request)
		else:
		    filesystem = fileSystemTypeGet("ext3")
		    request = partRequests.LogicalVolumeRequestSpec(filesystem, mountpoint="/", size=1300, 
			    volgroup=201, lvname="root", grow=1, format=1)
		    partitions.autoPartitionRequests.append(request)

		    filesystem = fileSystemTypeGet("swap")
		    request = partRequests.LogicalVolumeRequestSpec(filesystem, size=swapMin, maxSizeMB=swapMax, 
			    volgroup=201, lvname="swap", grow=1, format=1)
		    partitions.autoPartitionRequests.append(request)

	    partitions.autoClearPartDrives = usedDrives
	else:
	    BaseInstallClass.setDefaultPartitioning(self, partitions, clear, doClear)

    def setAsHeadless(self, dispatch, isHeadless = 0):
        if isHeadless == 0:
            pass
        else:
	    dispatch.skipStep("handleX11pkgs", permanent = 1)
	    dispatch.skipStep("videocard", permanent = 1)
	    dispatch.skipStep("monitor", permanent = 1)
	    dispatch.skipStep("xcustom", permanent = 1)
	    dispatch.skipStep("writexconfig", permanent = 1)

    def setGroupSelection(self, grpset, intf):
        grpset.unselectAll()
        grpset.selectGroup("Base")

    def postAction(self, rootPath, serial, intf):
        win = intf.waitWindow(_("Post Install Script"),
           _("The post installation script is running..."))

        script = ( "/sbin/syslogd &\n"
                   "sleep 2\n"
                   "/sbin/e-smith/signal-event post-install\n" )
        s = Script(script, interp="/bin/sh", inChroot=1)
        log("%s", s)
        s.run(rootPath, serial)
        win.pop()

    def setInstallData(self, id, intf = None):
        BaseInstallClass.setInstallData(self, id)
        self.setAuthentication(id, useShadow=1, salt="md5")
        self.setRootPassword(id, pw="ThisIsGoingToBeDisabledAnyway", isCrypted=0)
        self.setZeroMbr(id, zeroMbr=1)
        self.setClearParts(id, clear=CLEARPART_TYPE_ALL, initAll=1)
        self.setDefaultPartitioning(id.partitions, doClear=0)
        self.setBootloader(id, useLilo=0, location="mbr", linear=1)

    def __init__(self, expert):
	BaseInstallClass.__init__(self, expert)
