ACC SHELL
/**
* File: ep-main.ycp
* Package: yast2-storage
* Summary: Expert Partitioner
* Authors: Arvin Schnell <aschnell@suse.de>
*/
{
textdomain "storage";
import "Arch";
import "Mode";
import "Stage";
import "Label";
import "Hostname";
import "Event";
import "ContextMenu";
import "TabPanel";
import "TreePanel";
import "Popup";
import "Storage";
import "StorageFields";
import "StorageIcons";
import "StorageSettings";
import "Wizard";
import "MiniWorkflow";
import "Greasemonkey";
import "Partitions";
import "FileSystems";
import "DevicesSelectionBox";
import "Integer";
import "String";
import "Region";
import "ProductFeatures";
import "Directory";
import "HTML";
import "Map";
import "Icon";
include "partitioning/lvm_ui_dialogs.ycp";
include "partitioning/raid_lib.ycp";
include "partitioning/custom_part_check_generated.ycp";
// dialog caption
string caption = _("Expert Partitioner");
void UpdateMainStatus();
void UpdateNavigationTree(any new_focus);
void UpdateTableFocus(string device)
{
if (UI::WidgetExists(`id(`table)))
UI::ChangeWidget(`id(`table), `CurrentItem, device);
}
void EpContextMenuDevice(string device);
include "partitioning/ep-lib.ycp";
include "partitioning/ep-dialogs.ycp";
include "partitioning/ep-import.ycp";
include "partitioning/ep-all.ycp";
include "partitioning/ep-hd.ycp";
include "partitioning/ep-lvm.ycp";
include "partitioning/ep-raid.ycp";
include "partitioning/ep-loop.ycp";
include "partitioning/ep-dm.ycp";
include "partitioning/ep-nfs.ycp";
include "partitioning/ep-unused.ycp";
include "partitioning/ep-graph.ycp";
include "partitioning/ep-summary.ycp";
include "partitioning/ep-settings.ycp";
include "partitioning/ep-log.ycp";
void UpdateMainStatus()
{
if (Mode::normal())
{
string next_label = Storage::EqualBackupStates("expert-partitioner", "", true) ?
Label::FinishButton() : Label::NextButton();
Wizard::SetNextButton(`next, next_label);
}
}
void MakeNavigationTree(map open_items, list<term>& tree, map<any, map>& data)
{
// TODO: somehow use AlwaysHideDisk
data = $[ `all : $[ `create : CreateAllPanel, `handle : HandleAllPanel ],
`hd : $[ `create : CreateHdMainPanel, `handle : HandleHdMainPanel ],
`lvm : $[ `create : CreateLvmMainPanel, `handle : HandleLvmMainPanel ],
`md : $[ `create : CreateRaidMainPanel, `handle : HandleRaidMainPanel ],
`loop : $[ `create : CreateLoopMainPanel, `handle : HandleLoopMainPanel ],
`dm : $[ `create : CreateDmMainPanel, `handle : HandleDmMainPanel ],
`nfs : $[ `create : CreateNfsMainPanel, `handle : HandleNfsMainPanel ],
`unused : $[ `create : CreateUnusedPanel, `handle : HandleUnusedPanel ],
`devicegraph : $[ `create : CreateDeviceGraphPanel, `refresh : RefreshDeviceGraphPanel, `handle : HandleDeviceGraphPanel ],
`mountgraph : $[ `create : CreateMountGraphPanel, `refresh : RefreshDeviceGraphPanel, `handle : HandleMountGraphPanel ],
`summary : $[ `create : CreateSummaryPanel ],
`settings : $[ `create : CreateSettingsPanel, `handle : HandleSettingsPanel, `destroy : DestroySettingsPanel ],
`log : $[ `create : CreateLogPanel, `handle : HandleLogPanel, `destroy : DestroyLogPanel ] ];
map<symbol, list> subtree = $[];
map<string, map> target_map = Storage::GetTargetMap();
boolean open(any id)
{
return open_items[id]:"" == "ID";
}
void huhu(map disk, symbol type, map a, map b)
{
string disk_device = disk["device"]:"";
list<map> partitions = disk["partitions"]:[];
partitions = filter(map partition, partitions, {
return !StorageFields::AlwaysHidePartition(target_map, disk, partition);
});
list<term> tmp = [];
foreach(map partition, partitions, {
string part_device = partition["device"]:"";
string part_displayname = StorageSettings::DisplayName(partition);
tmp = add(tmp, `item(`id(part_device), part_displayname, open(part_device)));
data = add(data, part_device, union(a, $[ `user_data : part_device ]));
});
if (b != nil)
{
string disk_displayname = StorageSettings::DisplayName(disk);
subtree[type] = add(subtree[type]:[], `item(`id(disk_device), disk_displayname, open(disk_device), tmp));
data = add(data, disk_device, union(b, $[ `user_data : disk_device ]));
}
else
{
subtree[type] = merge(subtree[type]:[], tmp);
}
}
void callback(map<string, map> target_map, map disk)
{
symbol type = disk["type"]:`CT_UNKNOWN;
switch(type)
{
case `CT_DISK:
case `CT_DMRAID:
case `CT_DMMULTIPATH:
case `CT_MDPART:
huhu(disk, `hd, $[ `create : CreateHdPartitionPanel, `handle : HandleHdPartitionPanel ],
$[ `create : CreateHdDiskPanel, `handle : HandleHdDiskPanel ]);
break;
case `CT_LVM:
huhu(disk, `lvm, $[ `create : CreateLvmLvPanel, `handle : HandleLvmLvPanel ],
$[ `create : CreateLvmVgPanel, `handle : HandleLvmVgPanel ]);
break;
case `CT_MD:
huhu(disk, `md, $[ `create : CreateRaidPanel, `handle : HandleRaidPanel ], nil);
break;
case `CT_LOOP:
huhu(disk, `loop, $[ `create : CreateLoopPanel, `handle : HandleLoopPanel ], nil);
break;
case `CT_DM:
huhu(disk, `dm, $[ `create : CreateDmPanel, `handle : HandleDmPanel ], nil);
break;
case `CT_NFS:
huhu(disk, `nfs, $[ `create : CreateNfsPanel, `handle: HandleNfsMainPanel ], nil);
break;
}
}
StorageFields::IterateTargetMap(target_map, callback);
string short_hostname = Hostname::CurrentHostname();
// TODO: same ordering as with IterateTargetMap
tree = [ `item(`id(`all), `icon(StorageIcons::all_icon), short_hostname, open(`all), [
// tree node label
`item(`id(`hd), `icon(StorageIcons::hd_icon), _("Hard Disks"), open(`hd), subtree[`hd]:[]),
// tree node label
`item(`id(`md), `icon(StorageIcons::raid_icon), _("RAID"), open(`md), subtree[`md]:[]),
// tree node label
`item(`id(`lvm), `icon(StorageIcons::lvm_icon), _("Volume Management"), open(`lvm), subtree[`lvm]:[]),
// tree node label
`item(`id(`loop), `icon(StorageIcons::loop_icon), _("Crypt Files"), open(`loop), subtree[`loop]:[]),
// tree node label
`item(`id(`dm), `icon(StorageIcons::dm_icon), _("Device Mapper"), open(`dm), subtree[`dm]:[]),
// tree node label
`item(`id(`nfs), `icon(StorageIcons::nfs_icon), _("NFS"), open(`nfs)),
// tree node label
`item(`id(`unused), `icon(StorageIcons::unused_icon), _("Unused Devices"), open(`unused))
])
];
if (UI::HasSpecialWidget(`Graph))
{
// tree node label
tree = add(tree, `item(`id(`devicegraph), `icon(StorageIcons::graph_icon), _("Device Graph"), open(`devicegraph)));
// tree node label
tree = add(tree, `item(`id(`mountgraph), `icon(StorageIcons::graph_icon), _("Mount Graph"), open(`mountgraph)));
}
// tree node label
tree = add(tree, `item(`id(`summary), `icon(StorageIcons::summary_icon), _("Installation Summary"), open(`summary)));
// tree node label
tree = add(tree, `item(`id(`settings), `icon(StorageIcons::settings_icon), _("Settings"), open(`settings)));
if (Mode::normal())
// tree node label
tree = add(tree, `item(`id(`log), `icon(StorageIcons::log_icon), _("Log"), open(`log)));
}
void UpdateNavigationTree(any new_focus)
{
list<term> tree = [];
map<any, map> data = $[];
map open_items = (map) UI::QueryWidget(`id(`tree), `OpenItems);
MakeNavigationTree(open_items, tree, data);
TreePanel::Update(data, tree, new_focus);
}
void EpContextMenuDevice(string device)
{
map<string, map> target_map = Storage::GetTargetMap();
map disk = nil;
map part = nil;
SplitDevice(target_map, device, disk, part);
switch (disk["type"]:`unknown)
{
case `CT_DISK:
case `CT_MDPART:
case `CT_DMRAID:
case `CT_DMMULTIPATH:
if (part == nil)
EpContextMenuHdDisk(device);
else
EpContextMenuHdPartition(device);
break;
case `CT_MD:
if (part != nil)
EpContextMenuRaid(device);
break;
case `CT_LOOP:
if (part != nil)
EpContextMenuLoop(device);
break;
case `CT_LVM:
if (part == nil)
EpContextMenuLvmVg(device);
else
EpContextMenuLvmLv(device);
break;
case `CT_DM:
if (part != nil)
EpContextMenuDm(device);
break;
}
}
/**
* Confirm leaving the module
*/
boolean ReallyQuit( string label )
{
// popup text, %1 will be replaces with button text
string text = sformat(_("You have changed the partitioning or storage settings. These changes
will be lost if you exit the partitioner with %1.
Really exit?"), deletechars(label, "&"));
return Popup::YesNo(text);
}
string SummaryDialogHelptext()
{
// helptext
string helptext = _("<p>Here you can see the partitioning summary.</p>");
return helptext;
}
/**
* Fullscreen summary of changes
*/
symbol SummaryDialog()
{
symbol ret = `none;
Wizard::CreateDialog();
Wizard::SetContentsButtons(caption + _(": Summary"),
`VBox(`RichText(CompleteSummary())),
SummaryDialogHelptext(),
Label::BackButton(),
Label::FinishButton());
Wizard::SetDesktopIcon("disk");
while (true)
{
ret = (symbol) UI::UserInput();
if (ret == `next || ret == `back)
break;
if( ret == `abort && ReallyQuit( Label::AbortButton() ))
{
ret =`abort;
break;
}
}
Wizard::CloseDialog();
y2milestone("Summary dialog returned %1", ret);
return ret;
}
/**
* apply changes in running system
*/
symbol DoApply()
{
symbol ret1 = SummaryDialog();
if (ret1 == `back)
{
return `back;
}
else if (ret1 == `next)
{
Wizard::CreateDialog();
Wizard::SetDesktopIcon("disk");
symbol ret2 = (symbol) WFM::CallFunction("inst_prepdisk", [true, true]);
StorageSettings::Save();
Wizard::CloseDialog();
Storage::CreateTargetBackup("expert-partitioner");
if (ret2 != `next)
return `back;
else
return `next;
}
}
symbol ExpertPartitioner()
{
SCR::Write(.target.ycp, Storage::SaveDumpPath("targetmap-ep-start"), Storage::GetTargetMap());
Storage::CreateTargetBackup("expert-partitioner");
list<term> tree = [];
map<any, map> data = $[];
MakeNavigationTree($[`all : "ID"], tree, data);
string back_label = Label::BackButton();
string next_label = Mode::normal() ? Label::FinishButton() : Label::AcceptButton();
string abort_label = Label::AbortButton();
term contents = `MarginBox(0.5, 0.5,
`HBox(
`HWeight(30,
// tree node label
`Tree(`id(`tree), `opt(`notify), _("System View"), tree)
),
`HWeight(70,
`ReplacePoint(`id(`tree_panel), TreePanel::empty_panel)
)
)
);
// heading text
Wizard::SetContentsButtons(caption, contents, "", back_label, next_label);
if (Mode::normal())
Wizard::HideBackButton();
TreePanel::Init(data);
symbol widget = nil;
repeat
{
map event = Wizard::WaitForEvent();
TreePanel::Handle(event);
widget = event["ID"]:(symbol) nil;
switch (widget)
{
case `back:
case `abort: {
if (!Storage::EqualBackupStates("expert-partitioner", "", true))
{
if (!ReallyQuit(widget == `back ? back_label : abort_label))
widget = `again;
}
} break;
case `next: {
if (!Storage::EqualBackupStates("expert-partitioner", "", true) || StorageSettings::GetModified())
{
if (!check_created_partition_table(Storage::GetTargetMap(),
Stage::initial() && !Mode::repair()))
{
widget = `again;
}
else
{
if (Mode::normal())
{
if (DoApply() == `back)
widget = `again;
}
}
}
else
{
y2milestone("No changes to partitioning - nothing to do");
widget = `abort;
}
} break;
}
switch (Event::IsWidgetActivated(event))
{
case `table: {
any citem = UI::QueryWidget(`id(`table), `CurrentItem);
TreePanel::SwitchToNew(citem);
UI::SetFocus( UI::WidgetExists(`id(`table)) ? `id(`table) : `id(`text));
} break;
}
}
until (widget == `back || widget == `abort || widget == `next);
TreePanel::Destroy();
switch (widget)
{
case `back:
case `abort:
if (Storage::GetPartMode() == "NORMAL")
Storage::SetPartMode("CUSTOM");
break;
case `next:
if (!Storage::EqualBackupStates("expert-partitioner", "", true))
{
Storage::SetPartMode("CUSTOM");
Storage::UpdateChangeTime();
}
break;
}
Storage::DisposeTargetBackup("expert-partitioner");
SCR::Write(.target.ycp, Storage::SaveDumpPath("targetmap-ep-end"), Storage::GetTargetMap());
return widget;
}
}
ACC SHELL 2018