ACC SHELL
/**
* Module: include/installation/rootpart.ycp
*
* Authors: Stefan Schubert <schubi@suse.de>
* Arvin Schnell <arvin@suse.de>
* Jiri Srain <jsrain@suse.cz>
*
* Purpose: Select root partition for update or booting.
* RootPart::rootPartitions must be filled before
* calling this module.
*/
{
textdomain "update";
import "Wizard";
import "Popup";
import "Label";
import "RootPart";
import "GetInstArgs";
import "Report";
import "Update";
import "Installation";
import "FileSystems";
// Returns boolean whether partition can be
// a Linux 'root' file system
boolean CanBeLinuxRootFS (symbol partition_fs) {
if (partition_fs == nil) {
y2error("partition_fs not defined!");
return false;
}
// possible_root_fs contains list of supported FSs
return contains (FileSystems::possible_root_fs, partition_fs);
}
// flavor is either `update or `boot
list <term> make_partition_list (boolean withall, symbol flavor) {
list<term> part_list = [];
foreach (string partition, map i, RootPart::rootPartitions, {
// see https://bugzilla.novell.com/attachment.cgi?id=96783&action=view
// see bugzilla #288201
// architecture needs to be valid when updating, not booting
boolean arch_is_valid = (flavor == `boot ? true:i[`arch_valid]:false);
if (withall || (i[`valid]:false && arch_is_valid))
{
// `ext2, `jfs, ...
symbol part_fs = (symbol) i[`fs]:nil;
string part_fs_name = tostring (part_fs);
if (part_fs_name != nil && regexpmatch (part_fs_name, "^`(.*)$")) {
part_fs_name = regexpsub (part_fs_name, "^`(.*)$", "\\1");
}
string system = i[`name]:"error";
// unknown system
if (system == "unknown") {
if (part_fs != nil) {
if (CanBeLinuxRootFS (part_fs)) {
// Table item (unknown system)
system = _("Unknown Linux");
} else {
// Table item (unknown system)
system = _("Unknown or Non-Linux");
}
} else {
// Table item (unknown system [neither openSUSE 11.1 nor SLES 14 nor ...])
if (system == "unknown") system = _("Unknown");
}
}
string arch = i[`arch]:"error";
// Table item (unknown architecture)
if (arch == "unknown") arch = _("Unknown");
// fist, use the name of file system (with short name for Linux)
// then the file system short name
// then "Unknown"
string fs = "";
// is a linux fs, can be a root fs, has a fs name
if (part_fs != nil && i[`fstype]:nil != nil && CanBeLinuxRootFS (part_fs) && part_fs_name != nil) {
fs = sformat(
_("%1 (%2)"),
i[`fstype]:"", part_fs_name
);
} else {
fs = i[`fstype]:i[`fs]:"";
}
// Table item (unknown file system)
if (fs == "") fs = _("Unknown");
string label = i[`label]:"";
part_list = add (part_list,
`item (`id (partition),
system, partition, arch, fs, label
)
);
}
});
return part_list;
}
// Returns whether wanted and selected architectures match
// bnc #372309
boolean DoArchitecturesMatch (string arch_1, string arch_2) {
list <string> ppc_archs = ["ppc", "ppc64"];
// exact match
if (arch_1 == arch_2) {
return true;
// ppc exception
} else if (contains (ppc_archs, arch_1) && contains (ppc_archs, arch_2)) {
return true;
}
// else
return false;
}
void UmountMountedPartition () {
Update::Detach ();
RootPart::UnmountPartitions (false);
}
/**
* This dialog comes in several different flavors:
* `update_dialog - used to show partitions available for upgrade,
* `update_popup - obsolete, used to be used as a pop-up in proposal dialog (MakeProposal),
* `update_dialog_proposal - obsolete, used to be used as a pop-up in proposal dialog (AskUser),
* `boot_popup - obsolete, used to be used as a dilaog offering to boot to a selected partition,
*
* @param symbol flavor
* @return symbol `cancel, `back, `next, `abort
*/
symbol RootPartitionDialog (symbol flavor) {
// FIXME: Most of the code in this function is obsolete
list<term> partition_list = make_partition_list (
RootPart::showAllPartitions,
(flavor == `boot_popup ? `boot : `update)
);
string title = "";
string label = "";
string help_text = "";
if (flavor == `boot_popup)
{
// label for selection of root partition (for boot)
label = _("Partition or System to Boot:");
// help text for root partition dialog (for boot)
help_text = _("<p>
Select the partition or system to boot.
</p>
");
}
else
{
// label for selection of root partition (for update)
label = _("Partition or System to Update:");
// help text for root partition dialog (for update)
help_text = _("<p>
Select the partition or system to update.
</p>
");
if (flavor == `update_dialog || flavor == `update_dialog_proposal)
{
// headline for dialog "Select for update"
title = _("Select for Update");
}
}
// help text for root partition dialog (general part)
help_text = help_text + _("<p>
<b>Show All Partitions</b> expands the list to a
general overview of your system's partitions.
</p>
");
term contents = `HBox (
`VBox (
`VSpacing (1),
`Left (`Label (label)),
`MinSize (
70, 14,
`Table (
`id (`partition),
`opt(`hstretch),
`header (
// table header
_("System"),
// table header item
_("Partition"),
// table header item
_("Architecture"),
// table header item
_("File System"),
// table header item
_("Label")
),
partition_list
)
),
`Left(`CheckBox(`id(`showall), `opt(`notify),
// check box
_("&Show All Partitions"), false)),
`VSpacing (1)
)
);
// bnc #429080
// finishing the target before selecting a new system to load
if (flavor == `update_dialog) {
Pkg::TargetFinish();
}
if (flavor == `update_dialog)
{
Wizard::SetContents (title, contents, help_text, true, true);
}
else if (flavor == `update_dialog_proposal)
{
Wizard::CreateDialog ();
Wizard::SetContentsButtons (title, contents, help_text,
Label::BackButton (), Label::OKButton ());
}
else
{
term buttons = `PushButton (`id(`next), `opt(`default), Label::OKButton());
if (flavor == `boot_popup)
{
buttons = `HBox (
`HStretch (),
// pushbutton to (rightaway) boot the system selected above
`HWeight( 1, `PushButton(`id(`next), `opt(`default), _("&Boot")) ),
`HSpacing( 1 ),
`HWeight( 1, `PushButton(`id(`cancel), Label::CancelButton() ) ),
`HStretch ()
);
}
term full = `MinHeight (
16,
`HBox (
`HSquash (
`MinWidth (
26,
`RichText (`opt(`vstretch), help_text)
)
),
`HSpacing (2),
`VBox (
`MinHeight (
15,
contents
),
buttons
),
`HSpacing (2)
)
);
UI::OpenDialog (full);
}
if (size (RootPart::selectedRootPartition) > 0)
UI::ChangeWidget (`id(`partition), `CurrentItem, RootPart::selectedRootPartition);
UI::ChangeWidget(`id(`showall), `Value, RootPart::showAllPartitions);
any ret = nil;
while (true)
{
if (flavor == `update_dialog || flavor == `update_dialog_proposal)
ret = Wizard::UserInput ();
else
ret = UI::UserInput ();
if (ret == `abort && Popup::ConfirmAbort (`painless))
break;
if (ret == `showall)
{
string tmp = (string) UI::QueryWidget (`id(`partition), `CurrentItem);
partition_list = make_partition_list (
(boolean) UI::QueryWidget (`id(`showall), `Value),
(flavor == `boot_popup ? `boot : `update)
);
UI::ChangeWidget (`id(`partition), `Items, partition_list);
if (tmp != nil)
UI::ChangeWidget (`id(`partition), `CurrentItem, tmp);
continue;
}
if ((flavor == `update_dialog || flavor == `update_popup
|| flavor == `update_dialog_proposal)
&& ret == `next)
{
string selected = (string) UI::QueryWidget (`id(`partition), `CurrentItem);
map freshman = RootPart::rootPartitions[selected]:$[];
boolean cont = true;
y2milestone ("Selected root partition: %1 %2",
selected, freshman);
if (freshman[`name]:"unknown" == "unknown")
{
cont = Popup::ContinueCancel (
// continue-cancel popup
_("No installed system that can be upgraded with this product was found
on the selected partition."));
}
else if (! DoArchitecturesMatch (freshman[`arch]:"", RootPart::GetDistroArch()))
{
cont = Popup::ContinueCancel (
// continue-cancel popup
_("The architecture of the system installed in the selected partition
is different than the one of this product."));
}
if (! cont)
ret = nil;
}
if (ret == `next)
{
RootPart::selectedRootPartition = (string) UI::QueryWidget (`id(`partition), `CurrentItem);
RootPart::showAllPartitions = (boolean) UI::QueryWidget (`id(`showall), `Value);
if (flavor == `update_dialog)
{
RootPart::targetOk = RootPart::mount_target ();
// Not mounted correctly
if (! RootPart::targetOk) {
// error report
Report::Error (_("Failed to mount target system"));
UmountMountedPartition();
continue;
// Correctly mounted but incomplete installation found
} else if (RootPart::IncompleteInstallationDetected (Installation::destdir)) {
if (Popup::AnyQuestion (
Label::WarningMsg(),
// pop-up question
_("A possibly incomplete installation has been detected on the selected partition.
Are sure you want to use it anyway?"),
// button label
_("&Yes, Use It"),
Label::CancelButton(),
`focus_no
)) {
y2milestone ("User wants to update possibly incomplete system");
} else {
y2milestone ("User decided not to update incomplete system");
UmountMountedPartition();
continue;
}
}
}
break;
}
if (ret == `cancel || ret == `back || ret == `next)
break;
}
if (flavor != `update_dialog)
UI::CloseDialog ();
// New partition has been mounted
if (flavor == `update_dialog && ret == `next) {
// Target load failed, #466803
if (Pkg::TargetInitialize (Installation::destdir) != true) {
y2error ("Pkg::TargetInitialize failed");
if (Popup::AnyQuestion (
Label::ErrorMsg(),
_("Initializing the system for upgrade has failed for unknown reason.
It is highly recommended not to continue the upgrade process.
Are you sure you want to continue?"),
_("&Yes, Continue"),
Label::CancelButton(),
`focus_no
)) {
ret = `back;
} else {
y2warning ("User decided to continue despite the error above (Pkg::TargetInit() failed)");
}
}
// not aborted
if (ret != `back) {
// Target load failed, #466803
if (Pkg::TargetLoad() != true) {
y2error ("Pkg::TargetLoad failed");
if (Popup::AnyQuestion (
Label::ErrorMsg(),
_("Initializing the system for upgrade has failed for unknown reason.
It is highly recommended not to continue the upgrade process.
Are you sure you want to continue?"),
_("&Yes, Continue"),
Label::CancelButton(),
`focus_no
)) {
ret = `back;
} else {
y2warning ("User decided to continue despite the error above (Pkg::TargetLoad() failed)");
}
}
}
}
return (symbol)ret;
}
} // EOF
ACC SHELL 2018