ACC SHELL
/**
* File: ep-lvm-lib.ycp
* Package: yast2-storage
* Summary: Expert Partitioner
* Authors: Arvin Schnell <aschnell@suse.de>
*
* This file must only be included in other Expert Partitioner files ("ep-*.ycp").
*/
{
textdomain "storage";
boolean AddPvs(string vg_name, list<string> devs)
{
boolean ret = true;
foreach(string dev, devs, {
Storage::SetPartitionId(dev, Partitions::fsid_lvm);
Storage::SetPartitionFormat(dev, false, `none);
if (!Storage::ExtendLvmVg(vg_name, dev))
ret = false;
});
return ret;
}
boolean RemovePvs(string vg_name, list<string> devs)
{
boolean ret = true;
foreach(string dev, devs, {
Storage::UnchangePartitionId(dev);
if (!Storage::ReduceLvmVg(vg_name, dev))
ret = false;
});
return ret;
}
void EpCreateVolumeGroup()
{
map<string, map> target_map = Storage::GetTargetMap();
list<map> unused_pvs = filter(map pv, get_possible_pvs(target_map), { return isempty(pv["used_by"]:[]); });
if (size(unused_pvs) < 1)
{
// error popup
Popup::Error(_("There are not enough suitable unused devices to create a volume group.
To use LVM, at least one unused partition of type 0x8e (or 0x83) or one unused
RAID device is required. Change your partition table accordingly."));
return;
}
map<string, any> data = $[];
if (DlgCreateVolumeGroupNew(data))
{
string vg_name = data["name"]:"error";
integer pe_size = data["pesize"]:0;
if (Storage::CreateLvmVgWithDevs(vg_name, pe_size, true, []))
{
list<string> devices = data["devices"]:[];
AddPvs(vg_name, devices);
UpdateMainStatus();
UpdateNavigationTree(nil);
TreePanel::Create();
UpdateTableFocus("/dev/" + vg_name);
}
}
}
void EpResizeVolumeGroup(string device)
{
if (device == nil)
{
// error popup
Popup::Error(_("No volume group selected."));
return;
}
map<string, map> target_map = Storage::GetTargetMap();
map<string, any> data = (map<string, any>) target_map[device]:$[];
string vgname = data["name"]:"error";
symbol Commit()
{
list<string> devices_old = MergeDevices(data);
list<string> devices_new = data["devices_new"]:[];
list<string> devices_added = AddedToList(devices_old, devices_new);
list<string> devices_removed = RemovedFromList(devices_old, devices_new);
if (size(devices_added) > 0 || size(devices_removed) > 0)
{
AddPvs(vgname, devices_added);
if (!RemovePvs(vgname, devices_removed))
{
// error popup
Popup::Error(_("Failed to remove some physical devices."));
// TODO: update data
return `back;
}
}
return `finish;
}
if (DlgResizeVolumeGroup(data, Commit))
{
UpdateMainStatus();
UpdateNavigationTree(nil);
TreePanel::Create();
}
}
boolean EpDeleteVolumeGroup(string device)
{
if (device == nil)
{
// error popup
Popup::Error(_("No volume group selected."));
return false;
}
string vgname = substring(device, 5);
//LV device names
list<string> log_volumes = Storage::GetAffectedDevices( device );
//how many of those we have?
integer count = size(log_volumes);
boolean ret = false;
boolean proceed = (count > 0) ?
//non-empty VG - make sure user wants to delete all LVs
ConfirmVgDelete(vgname, log_volumes) :
//empty VG - simple
Popup::YesNo(sformat(_("Really delete the volume group \"%1\"?"), vgname));
if (proceed)
{
boolean recursive = Storage::GetRecursiveRemoval();
Storage::SetRecursiveRemoval( true );
if (Storage::DeleteLvmVg(vgname))
{
any new_focus = nil;
if (UI::QueryWidget(`tree, `CurrentItem) == device)
new_focus = `lvm;
UpdateMainStatus();
UpdateNavigationTree(new_focus);
TreePanel::Create();
ret = true;
}
else
{
Popup::Error( sformat(_("Deleting volume group \"%1\" failed."), vgname));
//FIXME: some rollback?
ret = false;
}
Storage::SetRecursiveRemoval( recursive );
}
return ret;
}
void EpCreateLogicalVolume(string device)
{
if (device == nil)
{
// error popup
Popup::Error(_("No logical volume selected."));
return;
}
map<string, map> target_map = Storage::GetTargetMap();
map<string, any> data = $[ "new" : true,
"create" : true ];
string vg_name = substring(device, 5);
if (target_map[device, "pe_free"]:0 == 0)
{
// error popup
Popup::Error(sformat(_("No free space left in the volume group \"%1\"."), vg_name));
return;
}
data["vg_name"] = vg_name;
data["pesize"] = target_map[device, "pesize"]:0;
data["max_size_k"] = (target_map[device, "pe_free"]:0 * target_map[device, "pesize"]:0) / 1024;
data["max_stripes"] = size(MergeDevices((map<string, any>) target_map[device]:$[]));
symbol Commit()
{
if (!addLogicalVolume(data, substring(device, 5)))
return `back;
return `finish;
}
if (DlgCreateLogicalVolume(data, Commit))
{
UpdateMainStatus();
UpdateNavigationTree(nil);
TreePanel::Create();
UpdateTableFocus("/dev/" + data["vg_name"]:"error" + "/" + data["name"]:"error");
}
}
void EpEditLogicalVolume(string device)
{
if (device == nil)
{
// error popup
Popup::Error(_("No logical volume selected."));
return;
}
map<string, map> target_map = Storage::GetTargetMap();
map<string, any> data = Storage::GetPartition(target_map, device);
if (DlgEditLogicalVolume(data))
{
Storage::ChangeVolumeProperties(data);
UpdateMainStatus();
UpdateNavigationTree(nil);
TreePanel::Create();
UpdateTableFocus(device);
}
}
void EpResizeLogicalVolume(string device)
{
if (device == nil)
{
// error popup
Popup::Error(_("No logical volume selected."));
return;
}
map<string, map> target_map = Storage::GetTargetMap();
map<string, any> lv_data = Storage::GetPartition(target_map, device);
map<string, any> vg_data = Storage::GetDisk(target_map, device);
if (DlgResizeLogicalVolumeNew(lv_data, vg_data))
{
Storage::ResizeVolume(device, vg_data["device"]:"error", lv_data["size_k"]:0);
UpdateMainStatus();
TreePanel::Create();
UpdateTableFocus(device);
}
}
void EpDeleteLogicalVolume(string device, symbol context)
{
if (device == nil)
{
// error popup
Popup::Error(_("No logical volume selected."));
return;
}
string parent = ParentDevice(device);
string next = NextDeviceAfterDelete(device);
if (EpDeleteDevice(device))
{
UpdateMainStatus();
switch (context)
{
case `table:
UpdateNavigationTree(nil);
TreePanel::Create();
if (!isempty(next))
UI::ChangeWidget(`id(`table), `CurrentItem, next);
break;
case `overview:
UpdateNavigationTree(parent);
TreePanel::Create();
break;
}
}
}
}
ACC SHELL 2018