/**
 * Module:		target_modify.ycp
 *
 * Authors:		Thomas Fehr (fehr@suse.de)
 *			Michael Hager (mike@suse.de)
 *
 * Purpose:
 * Start of new disk preparation
 *
 *
 *
 * $Id: target_modify.ycp 22583 2005-03-15 12:54:28Z fehr $
 */

{

textdomain "storage";

import "Directory";
import "Label";
import "Partitions";
import "Storage";

define boolean target_modify( map modify_targets, boolean installation )
    ``{

    y2debug( "BEGINNING of modify_targets" );


    /////////////////////////////////////////////////
    // handle all inserted modification requests
    //
    // Example data:
    //
    // 	  $[ 1 : $[
    // 		"use_module" : "lvm_ll"
    // 		"type"       : "create_lv",
    // 		"name"       : "usr"
    // 		"size"     : 12121
    // 		"vgname"   : "system"
    // 		"stripes"  : 1 ]
    //
    // 	     2:  $[  "use_module" : "lvm_ll"
    // 		  "type"       : "remove_lv",
    // 		  "name" : "usr"
    // 		  "vgname" : "system"
    // 		  "target_map_entry" : $[...]
    // 	         ]
    // 	 ...
    //   disk_ll change_id is supported only for
    //   compatability and should not be used any more!
    //
    //  use targetMap "change_fsid" : true instead (see README.target_partition)

    integer number_of_modifications = size( modify_targets );
    integer curr_modification       = 0;
    boolean ok                      = true;
    boolean writefstab              = false;
    map<string,map> tg              = Storage::GetTargetMap();


    while ( ok && (curr_modification < number_of_modifications) )
	{
	curr_modification = curr_modification +1;
	string curr_module = "";
	map curr_map = modify_targets[curr_modification]:$[];

	// Choose the module, which can handle this request:

	curr_module = curr_map["use_module"]:"error";

	y2debug( "cur=%1 cnr=%2 module=%3", curr_modification,
		 number_of_modifications, curr_module );
	y2debug( "map=%1", curr_map );
	if ( curr_module == "lvm_ll" )
	    {
	    if( !installation && curr_map["type"]:"" =="remove_lv" )
		{
		string umnt = "umount /dev/" + curr_map["vgname"]:"";
		umnt = umnt + "/" + curr_map["name"]:"";
		y2debug( "umnt=%1", umnt );
		SCR::Execute (.target.bash, umnt );
		}
	    ok = SCR::Write(.lvm.command, curr_map);
	    if( ok == false )
		{
		map ret = (map)SCR::Read( .lvm.error, "" );
		y2milestone( "ret=%1", ret );
		string lvm_cmd = ret["cmdline"]:"";
		string error_text = 
		    mergestring( filter( string s, 
		                         splitstring( ret["errtxt"]:"", "\n"),
					 ``(size(s)>0)), 
				 "<br>" );
		if( size(lvm_cmd)>0 )
		    {
		    lvm_cmd = "<b>" + lvm_cmd;
		    lvm_cmd = lvm_cmd + "</b><p>";
		    }
		term content = `RichText( lvm_cmd + error_text );
		// heading text
		Popup::LongText( _("LVM error"), content, 50, 20 );
		}
	    else if( ! installation )
		{
		string cmd = curr_map["type"]:"";
		if( cmd=="remove_lv" || cmd=="create_lv" )
		    {
		    string device = "/dev/" + curr_map["vgname"]:"" + "/" +
				    curr_map["name"]:"";
		    map part = Storage::GetPartition( tg, device );
		    y2milestone( "device %1 part %2", device,  part );
		    if( cmd=="remove_lv" )
			{
			writefstab = writefstab || size(part["mount"]:"")>0;
			}
		    else if( cmd=="create_lv" )
			{
			part["create"] = true;
			writefstab = writefstab || size(part["mount"]:"")>0;
			}
		    if( size(part)>1 )
			{
			tg = (map<string,map>)Storage::SetPartition( tg, part );
			}
		    y2milestone( "writefstab=%1", writefstab );
		    }
		}
	    }
	else if( curr_module == "evms_ll" )
	    {
	    if( !installation && curr_map["type"]:"" =="remove_lv" )
		{
		string umnt = "umount /dev/" + curr_map["vgname"]:"";
		umnt = umnt + "/" + curr_map["name"]:"";
		y2debug( "umnt=%1", umnt );
		SCR::Execute (.target.bash, umnt );
		}
	    ok = SCR::Write(.evms.command, curr_map);
	    if( ok == false )
		{
		map ret = (map)SCR::Read( .evms.error, "" );
		y2milestone( "ret=%1", ret );
		string error_text = ret["errtxt"]:"";
		string lvm_cmd = ret["cmd"]:"";
		if( size(lvm_cmd)>0 )
		    {
		    lvm_cmd = "<b>" + lvm_cmd;
		    lvm_cmd = lvm_cmd + "</b><p>";
		    }
		term content = `RichText( lvm_cmd + error_text );
		// heading text
		Popup::LongText( _("EVMS Error"), content, 50, 20 );
		}
	    else if( ! installation )
		{
		string cmd = curr_map["type"]:"";
		if( cmd=="remove_lv" || cmd=="create_lv" )
		    {
		    string device = "/dev/" + curr_map["vgname"]:"" + "/" +
				    curr_map["name"]:"";
		    map part = Storage::GetPartition( tg, device );
		    y2milestone( "device %1 part %2", device,  part );
		    if( cmd=="remove_lv" )
			{
			writefstab = writefstab || size(part["mount"]:"")>0;
			}
		    else if( cmd=="create_lv" )
			{
			part["create"] = true;
			writefstab = writefstab || size(part["mount"]:"")>0;
			}
		    if( size(part)>1 )
			{
			tg = (map<string,map>)Storage::SetPartition( tg, part );
			}
		    y2milestone( "writefstab=%1", writefstab );
		    }
		}
	    }
	else if( curr_module == "disk_ll" )
	    {
	    ok = Storage::DiskAgentCall( curr_map );
	    }
	}

    if( writefstab )
	{
	Storage::WriteFstab( tg );
	}

    y2debug("END target_modify");
    return ( ok );
    };


////////////////////////////////////////////////////////////////////
// change the id of a partition:
//  "disk" : "/dev/sdb",
//  "id"   : 142,          // new id
//   "nr"  : 8,            // for sdb8

define boolean disk_change_id( string disk, integer nr, integer id  )
    ``{
    map curr_change_id = $[
			   "disk" : disk,
			   "id"   :  id,
			   "nr"   :  nr,
			   "type" : "change_id" ];

    return( Storage::DiskAgentCall( curr_change_id ));
    };



    ////////////////////////////////////////////////////////////////////
    // resize a partition:
    //  "disk"          : "/dev/sdb",
    //   "nr"           : 8,            // for sdb8
    //   "new_cyl_num"  : 1500          // resize to 1500 cylinders

define boolean disk_resize( string disk, integer nr, integer new_cyl  )
    ``{
    map curr_change = $[
			   "disk"         : disk,
			   "new_cyl_cnt" : new_cyl,
			   "nr"           :  nr,
			   "type"         : "resize" ];

    return( Storage::DiskAgentCall( curr_change ));
    };


define map HandleFilesystem( string device, symbol fs, integer new_size,
			     boolean decrease, string mp )
    ``{
    boolean ret = true;
    string cmd = "";
    string errtxt = "";
    y2milestone( "HandleFilesystem device:%1 fs:%2 new:%3 decrease:%4 mp:%5",
                 device, fs, new_size, decrease, mp );
    if( fs == `reiser )
	{
	cmd = sformat( "echo Yes | reiserfsck -q --check %1", device );
	y2milestone( "HandleFilesystem execute cmd:%1", cmd );
	map bm = (map)SCR::Execute(.target.bash_output, cmd );
	y2milestone( "HandleFilesystem bm %1", bm );
	if( !decrease && size(mp)>0 )
	    {
	    cmd = sformat("mount -oremount,resize=%1 %2", new_size*256, mp );
	    }
	else
	    {
	    cmd = sformat("echo y | resize_reiserfs -q -s %1M -f %2", new_size,
			device );
	    }
	y2milestone( "HandleFilesystem execute cmd:%1", cmd );
	bm = (map)SCR::Execute(.target.bash_output, cmd );
	y2milestone( "HandleFilesystem bm %1", bm );
	ret = bm["exit"]:1 == 0;
	}
    else if( fs == `ntfs )
	{
	string cmd = sformat( "echo y | ntfsresize -f -s %1k %2",
	                      new_size*1024*1024/1000, device );
	y2milestone( "HandleFilesystem cmd %1", cmd );
	map bm = (map)SCR::Execute(.target.bash_output, cmd );
	y2milestone( "HandleFilesystem ret %1", bm );
	ret = bm["exit"]:1 == 0;
	if( !ret )
	    {
	    errtxt = bm["stdout"]:"" + bm["stderr"]:"";
	    }
	}
    else if( fs == `ext2 || fs == `ext3 )
	{
	string cmd = sformat( "/sbin/resize2fs -f %1", device );
	if( decrease )
	    {
	    cmd = cmd + sformat( " %1M", new_size );
	    }
	y2milestone( "HandleFilesystem cmd %1", cmd );
	ret = SCR::Execute(.target.bash, cmd ) == 0;
	}
    else if( fs == `xfs && !decrease )
	{
	string mdir = Directory::tmpdir + "/m1";
	if( size(mp)==0 )
	    {
	    cmd = sformat("mkdir %1", mdir );
	    SCR::Execute(.target.bash, cmd );
	    cmd = sformat("mount %1 %2", device, mdir );
	    y2milestone( "HandleFilesystem execute cmd:%1", cmd );
	    ret = SCR::Execute(.target.bash, cmd ) == 0;
	    }
	else
	    {
	    mdir = mp;
	    }
	if( ret )
	    {
	    cmd = sformat("xfs_growfs %1", mdir );
	    y2milestone( "HandleFilesystem execute cmd:%1", cmd );
	    ret = SCR::Execute(.target.bash, cmd ) == 0;
	    }
	if( size(mp)==0 )
	    {
	    cmd = sformat("umount %1", device );
	    y2milestone( "HandleFilesystem execute cmd:%1", cmd );
	    SCR::Execute(.target.bash, cmd );
	    cmd = sformat("rmdir %1", mdir );
	    SCR::Execute(.target.bash, cmd );
	    }
	}
    map m = $[ "errtxt":errtxt, "ret" : ret ];
    y2milestone( "HandleFilesystem ret:%1", m );
    return( m );
    }

define boolean HandleResize( string disk_dev, map part, integer new_size,
                             integer old_size )
    ``{
    boolean ret = true;
    string err_txt = "";
    y2milestone( "HandleResize disk:%1 new:%2 old:%3", disk_dev, new_size,
                 old_size );
    y2milestone( "HandleResize part:%1", part );
    // label text sort for Megabyte (MB)
    string unit = _("MB");
    boolean retry = false;
    string cmd = "";
    string device = Storage::GetDeviceName( disk_dev, part["nr"]:(any)0 );
    symbol fs = part["used_fs"]:`unknown;
    // label text
    string fs_name = FileSystems::GetName( fs, _("unknown") );
    boolean lvm = contains( [`lvm, `evms], part["type"]:`unknown );
    boolean decrease = new_size < old_size;
    boolean format = part["format"]:false;
    map possible = FileSystems::IsResizable( fs );
    list swap = Storage::SwappingPartitions();
    do
	{
	UI::ChangeWidget(`id(`progress), `Label,
	                 // label text Example: Resizing device /dev/hda1 with file system ext2 from 5 GB to 2 GB
			 sformat(_("Resizing device %1 with file system %2 from %3 %4 to %5 %4"),
				 device, fs_name, old_size, unit, new_size ));
	retry = false;
	boolean result = true;
	boolean need_umount = false;
	string mp = "";
	if( Mode::normal () )
	    mp = Partitions::MountedOn( device, Partitions::CurMounted() );
	if( size(mp)>0 )
	    {
	    if( decrease && !possible["mount_shrink"]:false )
		need_umount = true;
	    if( !decrease && !possible["mount_extend"]:false )
		need_umount = true;
	    if( format )
		need_umount = true;
	    }
	if( contains( swap, device ))
	    {
	    cmd = sformat( "swapoff %1", device );
	    y2milestone( "execute cmd:%1", cmd );
	    SCR::Execute(.target.bash, cmd );
	    need_umount = false;
	    }
	if( need_umount )
	    {
	    cmd = sformat("umount %1", mp );
	    y2milestone( "execute cmd:%1", cmd );
	    result = SCR::Execute(.target.bash, cmd ) == 0;
	    if( !result )
		{
		// popup text
		Popup::Message( _("
Resizing the given file system is only possible while the file system
is not mounted. Unmounting failed for some reason.
Resizing is therefore not possible.
You could unmount the file system manually and retry resizing.
"));
		}
	    }
	if( result && decrease && !format )
	    {
	    map m = HandleFilesystem( device, fs, new_size, decrease, mp );
	    result = m["ret"]:false;
	    if( !result )
		{
		err_txt = m["errtxt"]:"";
		}
	    }
	if( result && lvm && !format && decrease && possible["parted"]:false )
	    {
	    cmd = sformat( "/usr/sbin/parted -s %1 resize 1 0 %2", device,
	                   new_size );
	    y2milestone( "execute cmd:%1", cmd );
	    result = SCR::Execute(.target.bash, cmd ) == 0;
	    }
	if( result && !lvm )
	    {
	    result = disk_resize( disk_dev, part["nr"]:0, part["region",1]:0 );
	    y2milestone( "disk_resize ret:%1", result );
	    }
	if( result && lvm && !format && !decrease && possible["parted"]:false )
	    {
	    cmd = sformat( "/usr/sbin/parted -s %1 resize 1 0 %2", device,
	                   new_size );
	    y2milestone( "execute cmd:%1", cmd );
	    result = SCR::Execute(.target.bash, cmd ) == 0;
	    }
	if( result && !decrease && !format )
	    {
	    map m = HandleFilesystem( device, fs, new_size, decrease, mp );
	    result = m["ret"]:false;
	    if( !result )
		{
		err_txt = m["errtxt"]:"";
		}
	    }
	if( need_umount && !format )
	    {
	    cmd = sformat("mount %1 %2", device, mp );
	    y2milestone( "execute cmd:%1", cmd );
	    SCR::Execute(.target.bash, cmd );
	    }
	if( contains( swap, device ))
	    {
	    cmd = sformat( "mkswap %1", device );
	    y2milestone( "execute cmd:%1", cmd );
	    SCR::Execute(.target.bash, cmd );
	    cmd = sformat( "swapon %1", device );
	    y2milestone( "execute cmd:%1", cmd );
	    SCR::Execute(.target.bash, cmd );
	    }
	if ( !result )
	  {
	  y2error("Oops, partition resize failed for device %1", device);
	  symbol ans=`yes;
	  // popup text
	  string txt = sformat (_("Resizing device %1 failed."), device);
	  if( size(err_txt)>0 )
	      {
	      txt = txt + "\n\n";
	      // popup text
	      txt = txt + _("Program Output:\n") + err_txt;
	      }
	  // heading text
	  ans = Popup::AnyQuestion3(_("Resize failed."), txt,
		  Label::ContinueButton(), Label::AbortButton(), Label::RetryButton(), `focus_no);

	  if( ans == `retry )
	    {
	    retry = true;
	    }
	  else if( ans == `no )
	    {
	    ret = false;
	    }
	  }
	else
	  {
	  map <string,map> tg = Storage::GetTargetMap();
	  tg = Storage::DelPartitionData( tg, part["device"]:"", "ori_length" );
	  tg = Storage::DelPartitionData( tg, part["device"]:"", "resize" );
	  Storage::SetTargetMap( tg );
	  }
	} while ( retry );
    y2milestone( "ret %1", ret );
    return( ret );
    }


define boolean HandleResizePartitions( string disk_dev, map disk,
				       boolean decrease )
    ``{
    boolean ret = true;
    integer cyl_size = disk["cyl_size"]:0;

    list<map> part = filter( map p, disk["partitions"]:[],
			``(p["resize"]:false && !p["delete"]:false));
    if( decrease )
	{
	part = filter( map p, part, ``(p["region",1]:0 < p["ori_length"]:0));
	}
    else
	{
	part = filter( map p, part, ``(p["region",1]:0 > p["ori_length"]:0));
	}
    if( Stage::initial () )
	{
	part = filter( map p, part,
		       ``(!Partitions::IsDosWinNtPartition( p["fsid"]:0 ) ||
		          p["detected_fs"]:`none==`ntfs));
	}

    foreach( map p, part, ``{
        if( ret )
	    {
	    integer new_size = p["region",1]:0*cyl_size/(1024*1024);
	    integer old_size = p["ori_length"]:0*cyl_size/(1024*1024);
	    ret = HandleResize( disk_dev, p, new_size, old_size );
	    }
	});
    y2milestone( "ret %1", ret );
    return( ret );
    }

define boolean HandleResizeLvm( map<string,map> target, 
                                map<integer,map> mod, boolean decrease )
    ``{
    y2milestone( "HandleResizeLvm decrease:%1 mod:%2", decrease, mod );
    boolean ret = true;
    integer num = 1;
    map<integer,map> doit = $[];
    foreach( any n, map e, mod, ``{
	string device = "/dev/" + e["vgname"]:"" + "/" + e["name"]:"abcde";
        map p = Storage::GetPartition( target, device );
	y2debug( "p:%1", p );
        integer new_size = e["size"]:0;
        integer old_size = p["ori_length"]:new_size;
	old_size = old_size / (1024*1024);
	new_size = new_size / (1024*1024);
	if( (decrease && old_size > new_size) ||
	    (!decrease && old_size < new_size) )
	    {
	    e["part"] = eval(p);
	    doit[num] = e;
	    num = num + 1;
	    }
	});
    y2debug( "doit:%1", doit );
    if( size(doit)>0 )
	{
	if( !decrease )
	    {
	    ret = target_modify( doit, Stage::initial () );
	    }
	foreach( any n, map e, doit, ``{
	    if( ret )
		{
		y2debug( "n:%1 e:%2", n, e );
		integer new_size = e["size"]:0 / (1024*1024);
		integer old_size = e["part","ori_length"]:0 / (1024*1024);
		ret = HandleResize( "/dev/"+e["vgname"]:"", e["part"]:$[],
		                    new_size, old_size );
		}
	    });
	if( decrease )
	    {
	    ret = target_modify( doit, Stage::initial () );
	    }
	}
    y2milestone( "ret %1", ret );
    return( ret );
    }

define boolean HandleEvmsChanges( map<string,map> target, boolean before_part,
                                  boolean doit )
    ``{
    boolean ret = true;
    y2milestone( "HandleEvmsChanges tg %1", target );
    map<string,map> tg = filter( string k, map e, target, 
                                 ``(find(k,"/dev/evms")==0));
    list<map> todo = [];
    y2milestone( "HandleEvmsChanges before_part %1 doit %2", before_part,
                 doit );
    y2milestone( "HandleEvmsChanges tg %1", tg );
    map m = $[ "use_module" : "evms_ll" ];
    if( before_part )
	{
	m["type"] = "remove_lv";
	foreach( string k, map e, tg,
	    ``{
	    if( e["is_evms_container"]:false )
		{
		foreach( map p, e["partitions"]:[],
		    ``{
		    if( p["delete"]:false )
			{
			m["name"] = p["nr"]:"";
			m["container"] = substring( k, 10 );
			todo = add( todo, m );
			}
		    });
		}
	    });
	m = $[ "use_module" : "evms_ll" ];
	m["type"] = "resize_lv";
	foreach( string k, map e, tg,
	    ``{
	    if( e["is_evms_container"]:false )
		{
		foreach( map p, filter( map x, e["partitions"]:[], 
		                        ``(haskey(x,"ori_length"))),
		    ``{
		    integer new_size = p["region",1]:0*e["cyl_size"]:0;
		    integer old_size = p["ori_length"]:new_size;
		    old_size = old_size / (1024*1024);
		    new_size = new_size / (1024*1024);
		    if( old_size > new_size ) 
			{
			m["name"] = p["nr"]:"";
			m["container"] = substring( k, 10 );
			m["size"] = new_size;
			m["old_size"] = old_size;
			m["part"] = p;
			todo = add( todo, m );
			}
		    });
		}
	    });
	m = $[ "use_module" : "evms_ll" ];
	m["type"] = "remove_pv";
	foreach( string k, map e, tg,
	    ``{
	    if( e["is_evms_container"]:false )
		{
		foreach( string d, e["removed"]:[],
		    ``{
		    m["device"] = d;
		    m["container"] = substring( k, 10 );
		    todo = add( todo, m );
		    });
		}
	    });
	m = $[ "use_module" : "evms_ll" ];
	m["type"] = "remove_vg";
	foreach( string k, map e, tg,
	    ``{
	    if( e["is_evms_container"]:false && e["delete"]:false )
		{
		m["container"] = substring( k, 10 );
		todo = add( todo, m );
		}
	    });
	if( doit )
	    {
	    foreach( map e, filter( map t, todo, ``(m["type"]:""=="resize_lv")),
		``{
		ret = HandleResize( "/dev/evms/"+e["container"]:"", 
		                    e["part"]:$[], e["size"]:0, 
				    e["old_size"]:0 );
		});
	    integer n = 0;
	    map t = listmap( map e, todo, ``{n=n+1; return( $[n:e]);});
	    y2milestone( "t = %1", t );
	    ret = target_modify( t, Stage::initial () );
	    }
	else
	    {
	    ret = size(todo)>0;
	    }
	}
    else
	{
	m["type"] = "create_vg";
	foreach( string k, map e, tg,
	    ``{
	    if( e["is_evms_container"]:false && e["create"]:false )
		{
		m["container"] = substring( k, 10 );
		m["pesize"] = e["cyl_size"]:0;
		m["devices"] = e["added"]:[];
		todo = add( todo, m );
		}
	    });
	m = $[ "use_module" : "evms_ll" ];
	m["type"] = "create_pv";
	foreach( string k, map e, tg,
	    ``{
	    if( e["is_evms_container"]:false && !e["create"]:false )
		{
		foreach( string d, e["added"]:[],
		    ``{
		    m["device"] = d;
		    m["container"] = substring( k, 10 );
		    todo = add( todo, m );
		    });
		}
	    });
	m = $[ "use_module" : "evms_ll" ];
	m["type"] = "create_lv";
	foreach( string k, map e, tg,
	    ``{
	    if( e["is_evms_container"]:false )
		{
		foreach( map p, e["partitions"]:[],
		    ``{
		    if( p["create"]:false )
			{
			m["name"] = p["nr"]:"";
			m["size"] = p["region",1]:0*e["cyl_size"]:0;
			m["stripes"] = p["stripes"]:1;
			if( haskey( p, "stripesize" ) )
			    m["stripesize"] = p["stripesize"]:64;
			m["container"] = substring( k, 10 );
			todo = add( todo, m );
			}
		    });
		}
	    });
	m = $[ "use_module" : "evms_ll" ];
	m["type"] = "resize_lv";
	foreach( string k, map e, tg,
	    ``{
	    if( e["is_evms_container"]:false )
		{
		foreach( map p, filter( map x, e["partitions"]:[], 
		                        ``(haskey(x,"ori_length"))),
		    ``{
		    integer new_size = p["region",1]:0*e["cyl_size"]:0;
		    integer old_size = p["ori_length"]:new_size;
		    old_size = old_size / (1024*1024);
		    new_size = new_size / (1024*1024);
		    if( old_size < new_size ) 
			{
			m["name"] = p["nr"]:"";
			m["container"] = substring( k, 10 );
			m["size"] = new_size;
			m["old_size"] = old_size;
			m["part"] = p;
			todo = add( todo, m );
			}
		    });
		}
	    });
	m = $[ "use_module" : "evms_ll" ];
	m["type"] = "create_vol";
	foreach( string k, map e, tg,
	    ``{
	    foreach( map p, e["partitions"]:[],
		``{
		if( size(p["mount"]:"")>0 )
		    {
		    m["name"] = p["device"]:"";
		    todo = add( todo, m );
		    }
		});
	    });
	if( doit )
	    {
	    integer n = 0;
	    map t = listmap( map e, todo, ``{n=n+1; return( $[n:e]);});
	    y2milestone( "t = %1", t );
	    ret = target_modify( t, Stage::initial () );
	    foreach( map e, filter( map t, todo, ``(m["type"]:""=="resize_lv")),
		``{
		ret = HandleResize( "/dev/evms/"+e["container"]:"", 
		                    e["part"]:$[], e["size"]:0, 
				    e["old_size"]:0 );
		});
	    }
	else
	    {
	    ret = size(todo)>0;
	    }
	}
    y2milestone( "HandleEvmsChanges ret %1", ret );
    return( ret );
    }

define void RemoveUsedNonEvmsDm( map<string,map> target )
    ``{
    boolean ret = true;
    map<string,map> tg = filter( string k, map e, target, 
                                 ``(find(k,"/dev/evms")!=0));
    y2milestone( "RemoveUsedNonEvmsDm tg %1", tg );
    list<map> dlist = [];
    foreach( string k, map e, tg,
	``{
	foreach( map p, e["partitions"]:[],
	    ``{
	    if( !p["delete"]:false && 
	        (size(p["mount"]:"")>0 ||
	         size(p["raid_name"]:"")>0 ||
	         size(p["lvm_group"]:"")>0))
		{
		dlist = add( dlist, p );
		}
	    });
	});
    y2milestone( "RemoveUsedNonEvmsDm dlist %1", dlist );
    foreach( map p, dlist,
	``{
	string dmmap = substring( p["device"]:"", 5 );
	string cmd = sformat( "dmsetup info %1", dmmap );
	y2milestone( "RemoveUsedNonEvmsDm executed %1 ret %2", cmd,
	             SCR::Execute( .target.bash_output, cmd ));
	cmd = sformat( "dmsetup remove %1", dmmap );
	y2milestone( "RemoveUsedNonEvmsDm executed %1 ret %2", cmd,
	             SCR::Execute( .target.bash_output, cmd ));
	});
    y2milestone( "RemoveUsedNonEvmsDm %1",
		 SCR::Execute( .target.bash_output, "/sbin/dmsetup ls" ));
    }

define map<integer,map> HandleDeletedVgs( map<string,map> tg, 
					  map<integer,map> modify_targets )
    ``{
    y2milestone( "HandleDeletedVgs mod %1", modify_targets );
    tg = filter( string dev, map disk, tg,
		 ``(disk["is_lvm_vg"]:false&&disk["delete"]:false));
    y2milestone( "HandleDeletedVgs tg %1", tg );
    foreach( string device, map disk, tg,
	``{
	if( size( filter( integer n, map p, modify_targets,
	                  ``(p["type"]:""=="remove_vg" &&
			     p["vgname"]:""==substring(device,5))))==0 )
	    {
	    modify_targets[size(modify_targets)+1] = 
		$[ "use_module" : "lvm_ll",
		   "type"       : "remove_vg",
		   "vgname"     : substring(device,5) ];
	    }
	});
    y2milestone( "HandleDeletedVgs ret %1", modify_targets );
    return( modify_targets );
    }

}
