ACC SHELL
/*
*************************************************************
*
* 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.
*
*************************************************************
*/
{
import "Arch";
import "Storage";
import "Partitions";
import "Label";
import "Product";
import "AutoinstData";
import "FileSystems";
import "Stage";
import "Region";
include "partitioning/custom_part_helptexts.ycp";
textdomain "storage";
/*---------------------------------------------------------------------
* Checks the generated partition table.
*---------------------------------------------------------------------
* Checkpoints:
* - popup if unformated mounted partitions exist
* - detect the fs on this partition
* - checks if / mountpoint is set
* - check if the boot partition ends in a bootable cylinder (/or/boot)
*/
boolean check_created_partition_table(const map<string,map> targetMap, boolean installation)
{
y2milestone("now checking generated target map installation:%1", installation);
boolean show_all_popups = false;
boolean diskless = true;
boolean partition_mounted_but_not_formated = false;
boolean swap_found = false;
boolean boot_found = false;
boolean root_found = false;
boolean gpt_boot_ia64 = false;
integer boot_end = 0;
integer root_end = 0;
boolean root_raid = false;
boolean root_dmraid = false;
boolean boot_raid = false;
boolean root_lvm = false;
symbol root_fs = `unknown;
symbol boot_fs = `unknown;
integer boot_size_k = 0;
boolean boot_size_check = !(Arch::board_chrp() || Arch::board_prep() || Arch::board_iseries() || Arch::board_mac());
boolean fat_system_mount = false;
boolean fat_system_boot = false;
string raid_type = "";
foreach (string disk, map diskinfo, targetMap, {
list<map> part_info = diskinfo["partitions"]:[];
integer cyl_size = diskinfo["cyl_size"]:1000000;
if (contains([ `CT_DISK, `CT_DMRAID, `CT_DMMULTIPATH, `CT_MDPART ], diskinfo["type"]:`CT_UNKNOWN))
diskless = false;
foreach (map part, part_info, {
// All valid partitions ...
integer fsid = part["fsid"]:0;
string mountpoint = part["mount"]:"";
//////////////////////////////////////////////////////////////
// look for root and boot
//////////////////////////////////////////////////////////////
if( mountpoint == "/" )
{
root_found = true;
root_dmraid = diskinfo["type"]:`CT_UNKNOWN == `CT_DMRAID;
root_end = Region::End(part["region"]:[]);
if( !contains( [ `primary, `logical ], part["type"]:`unknown ))
{
// root_end does not have anything to do with physical cylinders
root_end = 0;
}
root_fs = part["used_fs"]:`unknown;
if ( part["type"]:`unknown==`sw_raid ) root_raid = true;
if( !boot_raid ) raid_type = part["raid_type"]:"";
if ( part["type"]:`unknown==`lvm ) root_lvm = true;
}
else if( mountpoint == Partitions::BootMount() )
{
if( (Partitions::EfiBoot() || Arch::ia64()) && diskinfo["label"]:"gpt" != "gpt" )
{
gpt_boot_ia64 = true;
}
boot_found = true;
if( diskinfo["type"]:`CT_UNKNOWN==`CT_DISK )
{
boot_end = Region::End(part["region"]:[]);
}
else
{
boot_end = 0;
}
boot_fs = part["used_fs"]:`unknown;
boot_size_k = part["size_k"]:0;
if (part["type"]:`unknown == `sw_raid)
boot_raid = true;
raid_type = part["raid_type"]:"";
}
else if ( mountpoint == "" )
{
if( Partitions::PrepBoot() &&
(fsid == Partitions::fsid_prep_chrp_boot || fsid==6) )
{
boot_found = true;
boot_end = Region::End(part["region"]:[]);
boot_fs = part["used_fs"]:`unknown;
boot_size_k = part["size_k"]:0;
}
else if( Arch::board_mac() && part["used_fs"]:`unknown==`hfs )
{
boot_found = true;
boot_end = Region::End(part["region"]:[]);
boot_fs = part["used_fs"]:`unknown;
boot_size_k = part["size_k"]:0;
}
}
//////////////////////////////////////////////////////////////
// look for swap partition and check:
// - is there any
//
// check only "swap" not fsid cause for example on pdisk fsid = 0
//
//////////////////////////////////////////////////////////////
if( mountpoint == "swap" )
{
swap_found = true;
}
if( part["used_fs"]:`unknown==`vfat && part["format"]:false )
{
// uses a mountpoint like /usr / /var /home /opt with fat
if( !fat_system_mount &&
contains( [ "/usr", "/", "/home", "/var", "/opt" ],
mountpoint ))
{
fat_system_mount = true;
}
}
if( !(Partitions::EfiBoot() || Arch::ia64()) && part["used_fs"]:`unknown==`vfat && part["format"]:false )
{
// uses mountpoint /boot with fat
if( !fat_system_boot && mountpoint=="/boot" )
{
fat_system_boot = true;
}
}
if( !part["format"]:false && part["used_fs"]:`unknown!=`nfs &&
FileSystems::IsSystemMp( part["mount"]:"", false ) )
{
partition_mounted_but_not_formated = true;
}
});
});
y2milestone("diskless:%1", diskless);
y2milestone("root_found:%1 root_fs:%2", root_found, root_fs);
y2milestone("boot_found:%1 boot_fs:%2", boot_found, boot_fs);
y2milestone("root_dmraid:%1 root_raid:%2 boot_raid:%3 raid_type:%4",
root_dmraid, root_raid, boot_raid, raid_type);
boolean ok = true;
if (( !root_found && installation ) || show_all_popups )
{
// popup text
string message = _("You have not assigned a root partition for
installation. This does not work. Assign the root mount point \"/\" to a
partition.
Really use this setup?
");
if (!Popup::YesNo(message))
ok = false;
}
if( fat_system_mount || show_all_popups )
{
// popup text
string message = _("You tried to mount a fat partition to one of
the following mount points: / /usr /home /opt /var. This will very likely
cause problems. Use a Linux file system, such as ext3 or ext4, for these mount
points.
Really use this setup?
");
if (!Popup::YesNo(message))
ok = false;
}
if( fat_system_boot || show_all_popups )
{
// popup text
string message = _("You tried to mount a fat partition to the
mount point /boot. This will very likely cause problems. Use a Linux file
system, such as ext3 or ext4, for this mount point.
Really use this setup?
");
if (!Popup::YesNo(message))
ok = false;
}
if ((boot_found && contains([ `btrfs ], boot_fs)) || show_all_popups)
{
// popup text
string message = _("You have mounted a partition with btrfs to the
mount point /boot. This will very likely cause problems. Use a Linux file
system, such as ext3 or ext4, for this mount point.
Really use this setup?
");
if (!Popup::YesNo(message))
ok = false;
}
if (!boot_found && contains([ `btrfs ], root_fs) || show_all_popups)
{
// popup text
string message = _("You have mounted a partition with btrfs to the
mount point /. This will very likely cause problems. Use a Linux file system,
such as ext3 or ext4, for this mount point or an extra partition for /boot.
Really use this setup?
");
if (!Popup::YesNo(message))
ok = false;
}
if( (boot_found) && installation || show_all_popups )
{
if( boot_end >= Partitions::BootCyl() || show_all_popups )
{
// popup text, %1 is a number
string message = 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.
Really use this setup?
"), Partitions::BootCyl(), Product::name);
if (!Popup::YesNo(message))
ok = false;
}
if ( (boot_size_k < 12*1024 && boot_size_check) || show_all_popups )
{
// popup text, %1 is a size
string message = sformat(_("Warning:
Your boot partition is smaller than %1.
It is recommended to increase the size of /boot.
Really keep this size of boot partition?
"), Storage::KByteToHumanStringOmitZeroes(12*1024));
if (!Popup::YesNo(message))
ok = false;
}
}
///////////////////////////// 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() && !diskless) || show_all_popups)
{
// popup text
// If the user chooses 'no' here, the system will not be able to
// boot from the hard drive!
string message = sformat(_("Warning: There is no partition mounted as /boot.
To boot from your hard disk, a small /boot partition
(approx. %1) is required. Consider creating one.
(Partitions assigned to /boot will automatically be changed to
type 0x41 PReP/CHRP).
Really use the setup without /boot partition?
"), Storage::KByteToHumanStringOmitZeroes(4*1024));
if (!Popup::YesNo(message))
ok = false;
}
// no boot but root
if( (root_end >= Partitions::BootCyl() || show_all_popups) && AutoinstData::BootCylWarning )
{
// popup text
string message = 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.
Really use this setup?
"), Partitions::BootCyl(), Product::name);
if (!Popup::YesNo(message))
ok = false;
}
}
// 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) &&
AutoinstData::BootRaidWarning)
{
// popup text
string message = 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.
Really use this setup?
"), Product::name);
if (!Popup::YesNo(message))
ok = false;
}
// 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) &&
AutoinstData::BootLVMWarning )
{
// popup text
string message = 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.
Really use this setup?
"), Product::name);
if (!Popup::YesNo(message))
ok = false;
}
if( ((Partitions::EfiBoot() || Arch::ia64()) && installation && (!boot_found || boot_fs != `vfat)) ||
show_all_popups )
{
// popup text
string message = 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.
Really use this setup?
"), Partitions::BootMount(), Product::name);
if (!Popup::YesNo(message))
ok = false;
}
if( (root_dmraid && !boot_found) || show_all_popups )
{
// popup text
string message = sformat(_("Warning: With your current setup, your %2 installation will
encounter problems when booting, because you have no
separate %1 partition on your RAID disk.
This will give severe problems with the normal boot setup.
If you do not know exactly what you are doing, use a normal
partition for your files below %1.
Really use this setup?
"), Partitions::BootMount(), Product::name);
if (!Popup::YesNo(message))
ok = false;
}
if( ((Partitions::EfiBoot() || Arch::ia64()) && installation && boot_found && gpt_boot_ia64) ||
show_all_popups )
{
// popup text
string message = ia64_gpt_text() + "\n" + _("Really use this setup?");
if (!Popup::YesNo(message))
ok = false;
}
if ( (!swap_found && Stage::initial() && root_fs!=`nfs) || show_all_popups )
{
// popup text
string message = _("
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.
Really use the setup without swap partition?
");
if (!Popup::YesNo(message))
ok = false;
}
if( (partition_mounted_but_not_formated && installation) || show_all_popups )
{
// popup text
string message = _("
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.
Really keep the partition unformatted?
");
if (!Popup::YesNo(message))
ok = false;
}
return ok;
}
symbol check_devices_used(list<map> partitions, boolean not_cr)
{
symbol ret = `UB_NONE;
list<map> pl = filter( map p, partitions,
``( p["used_by_type"]:`UB_NONE!=`UB_NONE));
if( not_cr && size(pl)>0 )
{
map<string,map> tg = Storage::GetTargetMap();
list<map> ppl = [];
foreach( map p, pl,
``{
if( p["used_by_type"]:`UB_NONE==`UB_MD ||
p["used_by_type"]:`UB_NONE==`UB_DM )
{
string dev = p["used_by_device"]:"";
map pa = Storage::GetPartition( tg, dev );
if( size(pa)==0 || !pa["create"]:false )
ppl = add( ppl, p );
}
else if( p["used_by_type"]:`UB_NONE==`UB_LVM )
{
if( !tg[p["used_by_device"]:"", "create"]:false )
ppl = add( ppl, p );
}
});
pl = ppl;
}
if( size(pl)>0 )
ret = pl[0,"used_by_type"]:`UB_NONE;
return( ret );
}
boolean check_device_edit(map curr_part)
{
symbol used = check_devices_used( [ curr_part ], false );
if( used == `UB_MD)
{
// popup text %1 is replaced by a raid name e.g. md0
Popup::Message(sformat(_("The selected device belongs to the RAID (%1).
Remove it from the RAID before editing it.
"),curr_part["used_by_device"]:""));
return false;
}
else if( used == `UB_LVM )
{
// popup text %1 is replaced by a name e.g. system
Popup::Message(sformat(_("The selected device belongs to a volume group (%1).
Remove it from the volume group before editing it.
"),curr_part["used_by_device"]:"" ));
}
else if( used != `UB_NONE )
{
// popup text %1 is replaced by a name e.g. system
Popup::Message(sformat(_("The selected device is used by volume (%1).
Remove the volume before editing it.
"), curr_part["used_by_device"]:"" ));
}
boolean ret = used==`UB_NONE;
if( ret )
ret = Storage::CanEdit( curr_part, true );
return( ret );
}
boolean check_device_delete(map curr_part, boolean installation, map disk)
{
string part_name = curr_part["device"]:"";
symbol used = check_devices_used( [ curr_part ], false );
if( used != `UB_NONE )
{
/*if( used == `UB_LVM)
{
// popup text %2 is a device name, %1 is the volume group name
Popup::Error(sformat(_("The device (%2) belongs to a volume group (%1).
Remove it from the volume group before deleting it.
"),curr_part["used_by_device"]:"" , part_name) );
}*/
if( used == `UB_MD)
{
// popup text %2 is a device name, %1 is the raid name
Popup::Message(sformat(_("The device (%2) belongs to the RAID (%1).
Remove it from the RAID before deleting it.
"), curr_part["used_by_device"]:"", part_name ));
}
else
{
// popup text, %1 and %2 are device names
Popup::Message(sformat(_("The device (%2) is used by %1.
Remove %1 before deleting it.
"), curr_part["used_by_device"]:"", part_name ));
}
return false;
}
if( !installation )
{
string mounts = Storage::DeviceMounted( part_name );
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 false;
}
else
{
symbol ret = `none;
do
{
if( !Storage::Umount( part_name ) )
{
// popup text %1 is directory name
message = sformat(_("Unmount of %1 failed.
Remove the device 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 false;
}
}
}
if( !installation && curr_part["type"]:`unknown==`logical )
{
boolean ok = true;
list<map> ppl = filter( map p, disk["partitions"]:[],
``(p["nr"]:0>curr_part["nr"]:0));
if( size(ppl)>0 && check_devices_used( ppl, true )!=`UB_NONE )
ok = false;
if( ok && !installation && size(ppl)>0 )
{
integer i = 0;
while( i<size(ppl) && ok )
{
if( size(Storage::DeviceMounted(ppl[i,"device"]:""))>0 )
ok = false;
i = i+1;
}
}
if( !ok )
{
// popup text, %1 is a device name
Popup::Message(sformat(_("The device (%1) cannot be removed
Since it is a logical partition and another logical
partition with higher number is in use.
"), part_name ));
return( false );
}
}
boolean ret = used==`UB_NONE;
if( ret )
ret = Storage::CanDelete( curr_part, disk, true );
return ret;
}
boolean check_extended_delete( map curr_disk, boolean installation )
{
/////////////////////////////////////////////////
// filter delete partitions
list<map> partitions = curr_disk["partitions"]:[];
string del_dev = curr_disk["device"]:"";
/////////////////////////////////////////////////
// get logical partitions
list<map> logical_parts = filter( map part, partitions,
``( part["type"]:`primary == `logical));
y2milestone( "check_extended_delete logical_parts %1", logical_parts );
list logical_parts_names = [];
logical_parts_names = maplist( map p, logical_parts, ``(p["device"]:"") );
y2milestone( "check_extended_delete logical_parts_names %1",
logical_parts_names );
if( logical_parts_names == [] )
return true;
/////////////////////////////////////////////////
// check mounted partitions
if( !installation )
{
list<map> mounts = Storage::mountedPartitionsOnDisk( del_dev );
y2milestone( "check_extended_delete mounts:%1", mounts );
mounts = filter( map mount, mounts,
``( contains( logical_parts_names, mount["device"]:"")));
y2milestone( "check_extended_delete mounts:%1", mounts );
if( size( mounts ) != 0 )
{
/////////////////////////////////////////////////////////////////////////////////////////
// mount points found
string mounted_parts = "";
foreach( map mount, mounts , ``{
// %1 is replaced by device name, %1 by directory e.g /dev/hdd1 on /usr
mounted_parts = mounted_parts +
sformat( "%1 --> %2", mount["device"]:"",
mount["mount"]:"") + "\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;
}
}
}
symbol used = check_devices_used( logical_parts, false );
if( used == `UB_LVM )
{
// 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.
"));
}
else if( used == `UB_MD )
{
// popup text, Do not translate RAID.
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.
"));
}
else if( used != `UB_NONE )
{
// popup text
Popup::Message(_("
The selected extended partition contains at least one partition
that is in use. Remove the used volume before
deleting the extended partition.
"));
}
boolean ret = used==`UB_NONE;
if( ret )
{
map extd = find( map p, partitions,
``(p["type"]:`primary==`extended));
if( extd!=nil && size(extd)>0 )
ret = Storage::CanDelete( extd, curr_disk, true );
}
return( ret );
}
}
ACC SHELL 2018