/*
 *************************************************************
 *
 *     YaST2      SuSE Labs                        -o)
 *     --------------------                        /\\
 *                                                _\_v
 *           www.suse.de / www.suse.com
 * ----------------------------------------------------------
 *
 * Author:        Michael Hager <mike@suse.de>
 *
 * Description:   Partitioner for experts.
 *
 *
 *
 * Purpose:
 *                      -Determing possible partitions.
 *                      -Ask the user which partition to use.
 *                      -Check the input and return error-messages.
 *
 * external function:   get_partition_info: get a list of current partitions
 *                      check4partitions:   read the disk-information
 *                      target-agent.bash
 *
 *************************************************************

 $Id: custom_part_check_generated.ycp 20155 2004-11-03 16:35:04Z fehr $

HINTS: Always use
         lookup( part, "delete", false)
         lookup( part, "create", false)
       instead of
         lookup( part, "delete")
         lookup( part, "create")
       cause delete, create are not always set to false

*/
{
  import "Arch";
  import "Storage";
  import "Partitions";
  import "Package";
  import "Label";
  import "Product";
  import "AutoinstStorage";

  include "partitioning/partition_defines.ycp";

  textdomain "storage";


/*---------------------------------------------------------------------
 * change_boot_region
 *---------------------------------------------------------------------
 * changes the "region" key in the (all) partitions, which have a
 * mountpoint "/boot"
 *---------------------------------------------------------------------
 */

define map<string,map> change_boot_region( map<string,map> targetMap, list new_region )
  ``{
  foreach( string disk, map diskinfo, targetMap,
      ``{
      list new_part_info = [];
      list<map> part_info     = diskinfo["partitions"]:[];

      foreach( map part, part_info,
	  ``{
	  map new_part = part;

	  if( !part["delete"]:false &&
	      part["fsid"]:0 == Partitions::fsid_prep_chrp_boot )
	      {
	      new_part["region"] = new_region;
	      }
	  new_part_info = add( new_part_info, new_part );
	  });

      diskinfo["partitions"] = new_part_info;
      targetMap[disk] = diskinfo;
      });
  return( targetMap );
  };


define boolean check_raid_possible( map<string,map> targetMap )
    ``{
    integer possible_parts_found = 0;

    foreach( string disk, map target, targetMap, 
	``{
	list<map> partitions = target["partitions"]:[];

	possible_parts_found = possible_parts_found +
	       size(filter( map part, partitions, 
			    ``( part["lvm_group"]:"" == ""    &&
				!part["delete"]:false &&
				!part["format"]:false &&
				( part["mount"]:"" == "" ||
				  substring(part["mount"]:"", 0, 5) == "/data" )  &&
			        part["raid_name"]:"" == "" &&
			        (part["fsid"]:0 == Partitions::fsid_native ||
				 part["fsid"]:0 == Partitions::fsid_raid))));
       });

   if(  possible_parts_found < 2 )
       {
       // Translators: the text 'do not format' must match the label in the corresponding popup!
       Popup::Message(_("To use RAID, at least two partitions of type 0xFD (or 0x83)
are required. Change your partition table accordingly.
In most cases, this can be done in the following way:
click 'Create', select 'Do not format', and set the partition ID to 0xFD.
"));

       return false;
       }
   return true;
   }


define boolean check_lvm_possible( map<string,map> targetMap )
   ``{
   boolean possible_part_found = false;

   foreach( string disk, map target, targetMap, 
       ``{
       list<map> partitions = target["partitions"]:[];


       if( size(filter( map part, partitions, 
                        ``(part["raid_name"]:"" == "" &&
			   !part["delete"]:false && !part["format"]:false &&
			   (part["mount"]:""  == "" ||
			    substring(part["mount"]:"", 0, 5) == "/data" )  &&
			   ( part["fsid"]:0 == Partitions::fsid_native ||
			     part["fsid"]:0 == Partitions::fsid_lvm )))) > 0)
	   {
	   possible_part_found = true;
	   }
       });

   if( !possible_part_found )
       {
       // Translators: the text 'do not format' must match the label in the corresponding popup!
       Popup::Message(_("To use LVM, at least one partition of type 0x8e (or 0x83)
is required. Change your partition table accordingly.
In most cases, this can be done in the following way:
click 'Create', select 'Do not format', and set the partition ID to 0x8e.
"));
       }
   else if( Mode::normal () )
       {
       possible_part_found = Package::InstallAll( ["lvm2"] );
       }
   return possible_part_found;
   }

    /*---------------------------------------------------------------------
     * Checks the generated partition table.  (adds whole_disk - flags to the table)
     *---------------------------------------------------------------------
     * Checkpoints:
     * - popup if unformated mounted partitions exist
     *   - detect the fs on this partition
     * - checks if yast can take a whole disk
     *   all partitions have a fsid have of the type 130 131 5 // all fsid 131 partitions are mounted
     *
     * - checks if / mountpoint is set
     * - check if the boot partition ends in a bootable cylinder (/or/boot)
     * - check that all reiser Filesystems are bigger than 60MB
     */

define list check_created_partiton_table( map<string,map> targetMap, boolean setup_lvm,
					  boolean installation )
    ``{
    y2milestone( "now checking generated target map ...");
    string  curr_boot_mode  = "fritz";
    /* FIXME string  curr_boot_mode  = Bootloader::getLoaderType ();*/
    boolean show_all_popups = false;

    boolean partition_mounted_but_not_formated = false;
    boolean have_swap            = false;
    symbol  retval               = `next;
    boolean sparc_first_is_swap  = false;
    string  sparc_first_dev      = "";
    boolean swap_found           = false;
    boolean boot_found           = false;
    boolean root_found           = false;
    boolean gpt_warning          = false;
    integer boot_end             = 0;
    integer root_end             = 0;
    boolean root_raid            = false;
    boolean boot_raid            = false;
    boolean root_lvm             = false;
    boolean jfs_found            = false;
    boolean xfs_found            = false;
    symbol  root_fs              = `unknown;
    symbol  boot_fs              = `unknown;
    integer boot_cyl_nb          = 0;
    integer boot_start_cyl       = 0;
    integer boot_cyl_size        = 0;
    integer boot_size            = 0;
    boolean boot_size_check      = !(Arch::board_chrp () || Arch::board_prep () || Arch::board_iseries ());
    integer root_cyl_for_gb      = 0;
    integer boot_cyl_for_gb      = 0;
    string  axp_start_dev        = "";
    integer axp_start_nth        = 0;
    boolean axp_start_Cr_failure = false;
    boolean axp_start_Ex_failure = false;
    boolean all_whole_disk       = true;
    boolean fat_system_mount     = false;
    string raid_type             = "";

    foreach( string disk, map diskinfo, targetMap,
        ``{
	list<map> part_info     = diskinfo["partitions"]:[];
	boolean whole_disk = true;
	integer cyl_size   = diskinfo["cyl_size"]:1000000;

	//////////////////////////////////////////////////////////////
	// for axp
	// look if the user wants to create a partition
	// or there is a partition, which overlaps
	// the zone from 0-th cylinder to <n>th-cylinder
	// <n> ist that cylinder, which is even for little part written,
	// when I write 1MB to the disk, starting from cylinder 0
	// (typically its only the first cylinder)
	//
	// now we calculate <n> : nth-cyl
	//////////////////////////////////////////////////////////////

	integer nth_cyl = (1048576 / cyl_size);

	boolean id_sw_raid_dev = (disk == "/dev/md");


	foreach( map part, part_info, ``{

	    if( !part["delete"]:false )
		{
		// All valid partitions ...
		integer fsid       = part["fsid"]:0;
		string  mountpoint = part["mount"]:"";
		boolean is_mounted = size(mountpoint)>0;

		//////////////////////////////////////////////////////////////
		// axp+aboot (bsd-label): look for first cylinders of disk
		// see comment above
		//////////////////////////////////////////////////////////////

		if ( (curr_boot_mode == "aboot") &&
		     part["region",0]:0 <= nth_cyl && part["nr"]:0 != 3 )
		{
		    axp_start_dev          = disk;
		    axp_start_nth          = nth_cyl;
		    y2error("WWWWWWWWWWWWWWW1 %1", nth_cyl );

		    if ( part["create"]:false )
		    {
			y2error("WWWWWWWWWWWWWWW2 %1", nth_cyl );
			axp_start_Cr_failure = true;
		    }
		    else
		    {
			y2error("WWWWWWWWWWWWWWW3 %1", nth_cyl );
			axp_start_Ex_failure = true;
		    }
		}

		//////////////////////////////////////////////////////////////
		// check for xfs: its experimental
		//////////////////////////////////////////////////////////////
		if ( part["used_fs"]:`unknown == `xfs &&
		     part["format"]:false )
		{
		    xfs_found = true;
		}

		//////////////////////////////////////////////////////////////
		// check for jfs: in ppc its experimental
		//////////////////////////////////////////////////////////////
		if ( Arch::ppc () && part["used_fs"]:`unknown == `jfs &&
		     part["format"]:false )
		{
		    jfs_found = true;
		}


		//////////////////////////////////////////////////////////////
		// look for root and boot
		//
		//////////////////////////////////////////////////////////////

		if ( mountpoint == "/" )
		{
		    if( diskinfo["label"]:"" == "gpt" )
			{
			gpt_warning = true;
			}
		    root_found = true;
		    root_end   = part["region",0]:0 + part["region",1]:1-1;
		    if( size(part["raid_type"]:"")>0 ||
		        part["type"]:`unknown==`lvm || 
			part["type"]:`unknown==`evms )
		      {
		      // root_end does not have anything to do with physical cylinders
		      root_end = 0;
		      }
		    root_fs = part["used_fs"]:`unknown;
		    root_cyl_for_gb = 1073741824 / diskinfo["cyl_size"]:1000000;   // 1GB/cylinder size

		    if ( id_sw_raid_dev ) root_raid = true;
		    if( !boot_raid ) raid_type = part["raid_type"]:"unknown";
		    if ( part["type"]:`unknown==`lvm ) root_lvm = true;
		}
		else if ( mountpoint == Partitions::BootMount() )
		{
		    if( diskinfo["label"]:"" == "gpt" )
			{
			gpt_warning = true;
			}
		    boot_found      = true;
		    boot_start_cyl  = part["region",0]:0;
		    boot_cyl_nb     = part["region",1]:0;
		    boot_end        = part["region",0]:0 + part["region",1]:1-1;
		    boot_fs         = part["used_fs"]:`unknown;
		    boot_cyl_size   = diskinfo["cyl_size"]:1000000;
		    // 1GB/cylinder size
		    boot_cyl_for_gb = 1073741824 / boot_cyl_size;
		    boot_size       = boot_cyl_size * boot_cyl_nb;
		    if ( id_sw_raid_dev ) boot_raid = true;
		    raid_type = part["raid_type"]:"unknown";
		}
		else if ( mountpoint == "" )
		{
		    if( Partitions::PrepBoot() &&
			fsid == Partitions::fsid_prep_chrp_boot )
		    {
			boot_found      = true;
			boot_end        = part["region",0]:0 + part["region",1]:1-1;
			boot_cyl_nb     = part["region",1]:0;
			boot_fs         = part["used_fs"]:`unknown;
			boot_cyl_size   = diskinfo["cyl_size"]:1000000;
			boot_cyl_for_gb = 1073741824 / boot_cyl_size;
			boot_size       = boot_cyl_size * boot_cyl_nb;
			boot_start_cyl  = part["region",0]:0;
		    }
		}


		//////////////////////////////////////////////////////////////
		// look for swap partition and check:
		// - is there any
		// - on sparc: is first partition a swap partition
		//
		// check only "swap" not fsid cause for example on pdisk fsid = 0
		//
		//////////////////////////////////////////////////////////////

		if( mountpoint == "swap" )
		    {
		    have_swap = true;

		    // first partition of a sparc system shouldn't be a swap
		    // parition

		    if( Arch::sparc () && part["nr"]:0 == 1 )
			{
			sparc_first_is_swap = true;
			sparc_first_dev     = disk;
			}
		    }


		// check if a fat filesystem  is greater than 2 GB
		if( (part["used_fs"]:`unknown==`fat32 ||
		     part["used_fs"]:`unknown==`fat16) && part["format"]:false )
		{
		    // uses a mountpoint like /usr / /var /home /opt with fat
		    if( ! fat_system_mount )
		    {
			if( mountpoint == "/usr"  || mountpoint == "/"     ||
			    mountpoint == "/home" || mountpoint == "/var"  ||
			    mountpoint == "/opt"  )
			{
			    fat_system_mount = true;
			}
		    }

		}

		//    | NOT
		//    v
		if (  ! ( fsid==Partitions::fsid_native ||
			  fsid==Partitions::fsid_swap ||
			  fsid==Partitions::fsid_extended ||
			  fsid==Partitions::fsid_extended_win ||
			  fsid==Partitions::fsid_raid ||
			  fsid==Partitions::fsid_lvm ) )
		{
		    whole_disk = false;
		}

		if( !part["format"]:false &&
		    FileSystems::IsSystemMp( part["mount"]:"", false ) )
		    {
		    partition_mounted_but_not_formated = true;
		    }

	    }
	});

	whole_disk = whole_disk || diskinfo["is_lvm_vg"]:false ||
	                           diskinfo["is_evms"]:false;
	diskinfo  = add( diskinfo, "whole_disk", whole_disk );
	all_whole_disk = all_whole_disk && whole_disk;
	targetMap = add( targetMap, disk, diskinfo );

    } );

    y2milestone( "root_found:%1 boot_found %2 root_raid %3 boot_raid %4 raid_type:%5", 
	         root_found, boot_found, root_raid, boot_raid, raid_type );


      Storage::SetWholeDisk( all_whole_disk );

      if ( (axp_start_Cr_failure && installation) || show_all_popups )
      {
          // popup text %2 is a disk name e.g. /dev/hda %1 is a number
	  Popup::Error( sformat(_("\
You have created a partition at the beginning of the disk %2.
This is not compatible with the bootloader.
Change the start cylinder of your partition to cylinder %1
or delete this partition"), axp_start_nth +1, axp_start_dev ));

	  retval = `again;
      }



      if ( ( axp_start_Ex_failure && installation ) || show_all_popups )
      {
          // popup text %2 is a disk name e.g. /dev/hda %1 is a number
	  boolean ret = Popup::YesNo( sformat(_("You have a partition at the beginning of disk %2.
This is not compatible with the bootloader.
You should delete this partition and create a
new partition starting at cylinder %1.

Do you want to change your partitioning?
"), axp_start_nth +1, axp_start_dev ) );

	  if (ret == true) retval = `again;
      }

      if ( ( !Arch::ia64 () && installation && gpt_warning) || show_all_popups )
      {
          // popup text %2 is a disk name e.g. /dev/hda %1 is a number
	  boolean ret = Popup::YesNo( sformat(_("The disk label type on your system disk is GPT.
Linux can handle a GPT partition table fine, but most BIOS
versions cannot handle the disk label. To remove the GPT
disk label from a disk, use the menu entry
\"%1\" of the \"%2\" button.

Change your partitioning?
"),
	deletechars( _("Delete partition &table and disk label"), "&"),
	deletechars( _("E&xpert.."), "&") ) );

	  if (ret == true) retval = `again;
      }


    if (( !root_found  && installation ) || show_all_popups  )
    {
          // popup text
	Popup::Error(_("
YaST2 needs a root partition to install.
Assign the root mount point \"/\" to a partition.
"));

	retval = `again;
    }



    if( fat_system_mount || show_all_popups )
    {
        // popup text
	Popup::Error(_("You tried to mount a fat partition to
one of the following mount points: / /usr /home /opt /var.
Use a Linux file system, such as ext2 or reiserfs, for these mount points.
"));

	retval = `again;
    }

    if( (boot_found) && installation || show_all_popups )
    {
	if ( boot_end >= Partitions::BootCyl() || show_all_popups )
	{
	    // popup text %1 is a number
	    boolean ret = Popup::YesNo(sformat(_("Warning:
Your boot partition ends above cylinder %1.
Your BIOS does not seem able to boot
partitions above cylinder %1.
With the current setup, your %2
installation might not be directly bootable.

Change this?
"),Partitions::BootCyl(),Product::name));

	    if ( ret ) retval = `again;
	}


	// not substring sparc!
	if ( ( Arch::sparc32 () && boot_end >= boot_cyl_for_gb ) || show_all_popups )
	{
	    // popup text
	    boolean ret = Popup::YesNo(sformat(_("Warning:
With the current setup, your %1
installation might not be directly bootable.
Some PROM versions have problems with a boot
partition with an end cylinder above 1 GB.

Change this?
"),Product::name));


	    if (ret == true) retval = `again;
	}


	if ( (boot_size < 12*1024*1024 && boot_size_check) || show_all_popups )
	{
	    // popup text
	    boolean ret = Popup::YesNo(_("Warning:
Your boot partition is less than 12MB.
It is recommended to increase the size of /boot.

Do you want to do this?
"));

	    if (ret == true) retval = `again;
	}
    }

    ///////////////////////////// NO BOOT ///////////////////////////

    if( (! boot_found && installation ) || show_all_popups )
    {

	// iSeries does not really need a boot partition
	// a bootable binary will be written to a kernel slot in /proc
	if( (Partitions::PrepBoot() && ! Arch::board_iseries ()) || show_all_popups )
	{
	    // popup text
	    // If the user chooses 'no' here, the system will not be able to
	    // boot from the hard drive!
	    boolean ret = Popup::YesNo(_("Warning: There is no partition mounted as /boot.
To boot from your hard disk, a small /boot partition
(approx. 4MB) is required.  Consider creating one.
(Partitions assigned to /boot will automatically be changed to
type 0x41 PReP/CHRP).

Do you want to change your setup?
"));

	    if (ret == true)  retval = `again;

	}


	// no boot but root
	if( (root_end >= Partitions::BootCyl() || show_all_popups) && AutoinstStorage::BootCylWarning )
	{
	    // popup text
	    boolean ret = Popup::YesNo(sformat(_("Warning: According to your setup, you intend to
boot your machine from the root partition (/), which, unfortunately,
has an end cylinder above %1. Your BIOS does not seem capable
of booting partitions beyond the %1 cylinder boundary,
which means your %2 installation will not be
directly bootable.

Change this?
"), Partitions::BootCyl(),Product::name));

	    if (ret == true)  retval = `again;
	}

	if ( (Arch::sparc32 () && root_end >= root_cyl_for_gb) || show_all_popups )
	{
	    // popup text
	    boolean ret = Popup::YesNo(sformat(_("Warning: With your current setup, your %1
installation might not be directly bootable, because
some PROM versions have problems with a boot partition
ending above the 1 GB boundary.

Change this?
"),Product::name));

	    if (ret == true) retval = `again;
	}

	if ( (Arch::sparc () && root_fs != `ext2) || show_all_popups )
	{
	    // popup text
	    boolean ret = Popup::YesNo(sformat(
_("Warning: With your current setup, your %1
installation might not be directly bootable, because
some PROM versions have problems with a boot partition
ending above the 1 GB boundary.

Change this?
"),Product::name));

	    if (ret == true) retval = `again;
	}
    }

	// iSeries has no problems with this configuration
	// an initrd will be created and you can boot from a kernel slot
    if ( installation && !Arch::board_iseries () &&
         ((((root_raid && !boot_found) || boot_raid) && raid_type!="raid1") || show_all_popups) && 
	 AutoinstStorage::BootRaidWarning)
	{
	    // popup text
	    boolean ret = Popup::YesNo(sformat(
_("Warning: With your current setup, your %1
installation might not be directly bootable, because
your files below \"/boot\" are on a software RAID device.
The boot loader setup sometimes fails in this configuration.

Change this?
"),Product::name));

	    if (ret == true) retval = `again;
	}

	// iSeries has no problems with this configuration
	// an initrd will be created and you can boot from a kernel slot
    if ( installation && !Arch::board_iseries () &&
	 ((root_lvm && !boot_found) || show_all_popups ) &&
	 AutoinstStorage::BootLVMWarning )
	{
	    // popup text
	    boolean ret = Popup::YesNo(sformat(_("Warning: With your current setup, your %1 installation
will encounter problems when booting, because you have no \"boot\"
partition and your \"root\" partition is an LVM logical volume.
This does not work.


If you do not know exactly what you are doing, use a normal
partition for your files below /boot.

Change this?
"),Product::name));

	    if (ret == true) retval = `again;
	}


    if( (Arch::ia64 () && installation &&
         (!boot_found || (boot_fs != `fat16 && boot_fs != `fat32))) ||
        show_all_popups )
	{
	// popup text
	boolean ret = Popup::YesNo(sformat(_("Warning: With your current setup, your %2 installation
will encounter problems when booting, because you have no
FAT partition mounted onto %1.

This will give severe problems with the normal boot setup.

If you do not know exactly what you are doing, use a normal
FAT partition for your files below %1.

Change this?
"), Partitions::BootMount(),Product::name));

	if (ret == true) retval = `again;
	}

    if ( (!have_swap && Stage::initial ()) || show_all_popups )
    {
	// popup text
	boolean ret = Popup::YesNo(_("
You have not assigned a swap partition. There is nothing wrong with that, but
in most cases it is highly recommended to create and assign a swap partition.
Swap partitions on your system are listed in the main window with the
type \"Linux Swap\". An assigned swap partition has the mount point \"swap\".
You can assign more than one swap partition, if desired.


Do you want to change this?
"));

	if (ret == true) retval = `again;
    }

    if ( sparc_first_is_swap || show_all_popups )
    {
	// popup message
	Popup::Error(  sformat(_("
Your swap partition is the first partition of %1.
It is strongly recommended to change this, because
the disk label will be deleted.
"), sparc_first_dev ));
	retval = `again;
    }

    if( (partition_mounted_but_not_formated && installation) || show_all_popups )
	{
	// popup text
	string message = _("
WARNING:

You chose to install onto an existing partition that will not be
formatted. YaST2 cannot guarantee your installation will succeed,
particularly in any of the following cases:
") +
// continued popup text
_("- if this is an existing ReiserFS partition
- if this partition already contains a Linux distribution that will be
overwritten
- if this partition does not yet contain a file system
") +
// continued popup text
_("If in doubt, you might want to go back and mark this partition for
formatting, especially if it is assigned to one of the standard mount points
like /, /boot, /usr, /opt, or /var.
") +
// continued popup text
_("If you decide to format the partition, all data on it will be lost.

Do you want to change your setup?
");

	boolean ret = Popup::YesNo( message);

	if (ret == true) retval = `again;
	}

    if( !Storage::CheckEvmsLvm() )
	{
	if( Popup::YesNo( evms_texts_evms_lvm() ))
	    {
	    Storage::DoCheckEvmsLvm = false;
	    }
	else
	    {
	    retval = `again;
	    }
	}
    if( !Storage::CheckEvmsNonEvms() )
	{
	if( Popup::YesNo( evms_texts_evms_nonevms() ))
	    {
	    Storage::DoCheckEvmsNonEvms = false;
	    }
	else
	    {
	    retval = `again;
	    }
	}

    return( [targetMap, retval] );
    };





define symbol check_partition_edit( map curr_part, boolean bsd_label )
    ``{
    ///////////////////////////////////////////////////////
    // with a BSD-Disklabel partition 3 is always an additional entry
    // which describes the disk and should not be edited

    if( bsd_label && ( curr_part["nr"]:0 == 3 ) )
	{
	// popup text
	Popup::Message(_("Partition 3 \"Entire Disk\" is not changeable"));
	return `no_edit;
	}

    if( curr_part["raid_name"]:"" != "")
	{
	// popup text %1 is replaced by a raid name e.g. /dev/md0
	Popup::Message(sformat(_("The selected partition belongs to the RAID (%1).
Please remove it from the RAID before you edit it."),curr_part["raid_name"]:""));
	return `no_edit;
	}

    if( curr_part["lvm_group"]:"" != "")
	{
	// popup text %1 is replaced by a name
	Popup::Message(sformat(_("The selected partition belongs to a volume group (%1).
Please remove it from the volume group before you edit it."),curr_part["lvm_group"]:"" ));
	return `no_edit;
	}
    return `edit;
    }





define symbol check_partition_delete( map curr_disk, map curr_part, 
				      boolean bsd_label, boolean c_bsd,
				      boolean c_lvm, boolean c_raid, 
				      boolean installation )
    ``{
    string part_name = curr_part["device"]:"";

    if( c_bsd )
	{
	///////////////////////////////////////////////////////
	// with BSD-Disklabel partition 3 is always an additionl entry,
	// which describes the disk and should not be edited

	if( bsd_label && curr_part["nr"]:0==3 )
	    {
	    // popup text
	    Popup::Message(_("Partition 3 \"Entire Disk\" is not changeable"));
	    return `no_delete;
	    }
	}

    if( c_lvm )
	{
	if( curr_part["lvm_group"]:"" != "" )
	    {
	    // popup text %2 is a partition name, %1 is the volume group name
	    Popup::Error(sformat(_("The partition (%2) belongs to a volume group (%1).
Please remove it from the volume group before you delete it."),curr_part["lvm_group"]:"" , part_name) );
	    return  `no_delete;
	    }
	}

    if( c_raid )
	{
	////////////////////////////////////////////////////////////////////////////////////
	//  check raid
	if( curr_part["raid_name"]:"" != "")
	    {
	    // popup text %2 is a partition name, %1 is the raid name
	    Popup::Message(sformat(_("The partition (%2) belongs to the RAID (%1).
Please remove it from the RAID before you delete it."), curr_part["raid_name"]:"", part_name ));
	    return `no_delete;
	    }

	}

    if( !installation )
	{
	string mounts =  Partitions::MountedOn( part_name,
						Partitions::CurMounted() );
	if( mounts != "" )
	    {
	    // popup text %1 is directory name
	    string message = sformat(_("The selected device is currently mounted on %1.
It is *strongly* recommended to unmount it manually
before deleting it.

Click Cancel unless you know exactly what you are doing.

If you proceed, YaST2 will try unmounting before deleting it.
"), mounts );


	    if( ! Popup::ContinueCancel(message))
		{
		return  `no_delete;
		}
	    else
		{
		symbol ret = `none;
		do
		    {
		    if( SCR::Execute(.target.bash, "/bin/umount " + part_name )!=0)
			{
			// popup text %1 is directory name
			message = sformat(_("Unmount of %1 failed.
Remove partition anyway?
"), mounts );
			ret = Popup::AnyQuestion3( Label::WarningMsg(), message,
						     Label::YesButton(),
						     Label::NoButton(),
						     // button text
						     _("&Retry umount"),
						     `focus_yes );
			}
		    }
		while( ret == `retry );
		if( ret == `no )
		    return `no_delete;
		}
	    }
	}

    return `delete;
    };





define boolean check_extended_delete( string del_dev, map curr_disk, 
				      boolean installation ) 
    ``{

    /////////////////////////////////////////////////
    // filter delete partitions
    list<map> partitions =  curr_disk["partitions"]:[];
    partitions = filter( map part, partitions, ``( !part["delete"]:false ));

    /////////////////////////////////////////////////
    // get logical partitions
    list<map> logical_parts = filter( map part, partitions, 
                                 ``( part["type"]:`primary == `logical));
    list logical_parts_names = [];

    foreach( map logical_part, logical_parts , 
	``{
	logical_parts_names =
		add( logical_parts_names,
		     Storage::GetDeviceName( del_dev, logical_part["nr"]:0));
	});

    if( logical_parts_names == [] )
	return true;


    /////////////////////////////////////////////////
    // check mounted partitions
    if( !installation )
	{
	list<map> mounts = Partitions::mountedPartitionsOnDisk( del_dev,
							   Partitions::CurMounted() );
	mounts      = filter( map mount, mounts, ``( contains( logical_parts_names, mount["spec"]:"")));

	if ( size( mounts ) != 0 )
	    {
	    /////////////////////////////////////////////////////////////////////////////////////////
	    // mount points found

	    string mounted_parts  = "";
	    foreach( map mount, mounts , ``{

		//The selected extended partition contains partitions which are currently mounted:
		//           /dev/hda1 on /
		//           /dev/hdd1 on /usr
		//   ....
		mounted_parts = mounted_parts + sformat("%1 on %2",mount["spec"]:"", mount["file"]:"") + "\n";
	    });

	    // popup text
	    string message = sformat(_("The selected extended partition contains partitions which are currently mounted:
%1
It is *strongly* recommended to unmount these partitions before you delete the extended partition.
Please choose Cancel unless you know exactly what you are doing.
"), mounted_parts );

	    if( ! Popup::ContinueCancel(message))
		{
		return false;
		}
	    }
	}


    /////////////////////////////////////////////////////////////////////////////////////////
    // check LVM partitions

    if( size(filter( map part, logical_parts , ``( part["lvm_group"]:"" != "" ))) != 0)
	{
	// popup text, Do not translate LVM.
	Popup::Message(_("
The selected extended partition contains at least one LVM partition
assigned to a volume group. Remove all
partitions from their respective volume groups
before deleting the extended partition.
"));
	return false;
	}


    /////////////////////////////////////////////////////////////////////////////////////////
    // check RAID partitions

    if( size(filter( map part, logical_parts, ``( part["raid_name"]:"" != "" ))) != 0)
	{
	// popup text, Do not translate LVM.
	Popup::Message(_("
The selected extended partition contains at least one partition
that is part of a RAID system. Unassign the
partitions from their respective RAID systems before
deleting the extended partition.
"));
	return false;
	}

    return true;
    };
}




