ACC SHELL

Path : /usr/share/YaST2/include/partitioning/
File Upload :
Current File : //usr/share/YaST2/include/partitioning/ep-lvm-lib.ycp

/**
 * 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