ACC SHELL

Path : /usr/share/YaST2/modules/
File Upload :
Current File : //usr/share/YaST2/modules/AutoinstDrive.ycp

/**
 * File:	modules/AutoinstCommon.ycp
 * Package:	Auto-installation/Partition
 * Summary:	Drive related functions module
 * Author:	Sven Schober (sschober@suse.de)
 *
 * $Id: AutoinstDrive.ycp 2813 2008-06-12 13:52:30Z sschober $
 */
{
  module "AutoinstDrive";

  include "autoinstall/types.ycp";
  include "autoinstall/common.ycp";
  include "autoinstall/tree.ycp";

  import "AutoinstCommon";
  import "AutoinstPartition";

  textdomain "autoinst";


  /**
   * Structure of a drive, or volume group.
   */
  define DriveT fields =
  $[
      "_id"	    : 0,	  /* Internal id; won't appear in XML	    */
      "device"	    : "",	  /* device name (e.g. "/dev/hda")	    */
      "initialize"  : true,	  /* wipe out disk			    */
      "partitions"  : [],	  /* list of partitions on this drive	    */
      "type"	    : `CT_DISK,	  /* type of drive, see diskTypes below	    */
      "use"	    : `all,	  /* `all, `linux, `free, or list of
				      partition numbers to use		    */
      "pesize"	    : ""	  /* size of physical extents
				    (currently no GUI support for this
				    setting				    */
   ];

  /* Every drive created gets an id. */
  define integer _id = 0;
  /* List of allowd disk/drive types */
  define list<symbol> diskTypes = [ `CT_DISK, `CT_LVM, `CT_MD, `CT_NFS ];

  /**
   * Determine if type is a valid drive type.
   *
   * @param type symbol supposedly identifying a drive type.
   *
   * @return true of type is valid false otherwise.
   */
  define boolean isValidDiskType( symbol type ){
    return contains( diskTypes, type );
  }

  /**
   * Set field on drive to value. Convenience wrapper for generic setter.
   *
   * @param drive drive to be updated.
   * @param field field to be set.
   * @param value value to be stored.
   */
  global define DriveT set( DriveT drive, string field, any value){
    return AutoinstCommon::set( fields, drive, field, value );
  }

  /**
   * Constructor
   * Constructs a new drive of type type with "device" set to name.
   *
   * @param name device name of new drive.
   * @param type type of new drive.
   */
  global define DriveT new( string name , symbol type ){
    if( ! isValidDiskType( type ) ){
      y2warning("Invalid disk type: '%1'. Defaulting to CT_DISK",type);
      type = `CT_DISK;
    }
    DriveT result = set( set( set( fields, "device", name ), "_id", _id ), "type", type );
    _id = _id + 1;
    return result;
  }

  /**
   * Convenience wrappers for more general object predicates
   */
  global define boolean isDrive( DriveT drive ){
    return AutoinstCommon::isValidObject( fields, drive );
  }
  global define boolean isField( string field ){
    return AutoinstCommon::isValidField( fields, field );
  }
  global define boolean hasValidType( string field, any value ){
    return AutoinstCommon::hasValidType( fields, field, value );
  }
  global define boolean areEqual( DriveT d1, DriveT d2 ){
    return AutoinstCommon::areEqual( d1, d2 );
  }

  /**
   * Construct reference to drive for use in tree. The references
   * are of the form:
   *	"{drive,volgroup}_<id>",
   *  e.g. "drive_1", or "volgroup_3"
   *
   * @param drive drive to create the reference for.
   *
   * @return string reference
   */
  global define string getNodeReference( DriveT drive ){
    integer dev_id = drive["_id"]:999;
    string ref = "drive_";
    if( drive["type"]:`CT_DISK != `CT_DISK ){
      ref="volgroup_";
    }
    return ref+tostring( dev_id );
  }

  /**
   * Construct node name for display in tree.
   *
   * Constructed names are of the form:
   *  "<device name> - {drive,volgroup}
   *
   * @param drive to create node name for
   *
   * @return the newly created node name
   */
  global define string getNodeName( DriveT drive, boolean enableHTML ){
    string nodeName = drive["device"]:"";
    if( enableHTML ){
      nodeName = sformat( "<b>%1</b>", nodeName );
    }
    string description = _(" - Drive");
    symbol driveType =  drive["type"]:`CT_DISK;
    if( driveType != `CT_DISK ){
      /* volume group */
      description = _(" - Volume group");
      description = description + ", " + removePrefix(symbol2string( driveType ), "CT_");
    }
    else{
      /* physical drive */
      string useTypeDesc = drive["initialize"]:true ? "initialize" : "reuse";
      if( enableHTML ){
	description = sformat( "%1 to be %2d", description, useTypeDesc );
      }
      else{
	description = sformat( "%1 , %2", description, useTypeDesc );
      }
    }
    return nodeName + description;
  }
  /**
   * Create tree representation of drive for the tree widget.
   *
   * @param drive Drive to process.
   *
   * @return A term representing an `Item with the current drive as
   * top node and all partitions as children.
   */
  global define term
    createTree( DriveT drive ){
      list<PartitionT> partitions = drive["partitions"]:[];
      list<term> partitionTerms = [];
      integer part_id = 0;
      string driveRef = getNodeReference(drive);

      if ( size (partitions) > 0 )
      {
	foreach(PartitionT p, partitions, ``{
	    partitionTerms = add( partitionTerms, AutoinstPartition::createTree( p, driveRef, part_id ));
	    part_id = part_id + 1;
	});
      }
      return createTreeNode( driveRef, getNodeName(drive, false), partitionTerms );
    }

  /**
   * Get partition identified by idx from drive.
   *
   * CAUTION: Indexes may be invalidated by modifications of the
   * partition list on a drive.
   *
   */
  global define PartitionT
    getPartition( DriveT drive, integer idx ){
    PartitionT result = $[];
    if( isDrive( drive ) ){
      list<PartitionT> partList = drive["partitions"]:[];
      result = partList[idx]:$[];
    }
    else{
      y2error("Invalid drive: '%1'.", drive );
    }
    return result;
  }

  /**
  * Returns number of partitions on spcified drive.
  *
  * @param drive The drive to inspect.
  *
  * @return Number of partitions on drive.
  */
  global define integer
    getPartitionCount( DriveT drive ){
      return size( drive["partitions"]:[] );
  }

  /**
  * Return lowest partition number not already in use. 
  *
  * @param drive The drive to process.
  *
  * @return Lowest free partition number.
  */
  global define integer
    getNextAvailablePartitionNumber( DriveT drive ){
    list<integer> usedPartitionNumbers = [];
    /* gather all used numbers */
    foreach( PartitionT part, drive["partitions"]:[], {
      integer partitionNumber = part["partition_nr"]:999;
      if( partitionNumber != 999 ){
	usedPartitionNumbers = add( usedPartitionNumbers, partitionNumber );
      }
    });
    integer newPartitionNumber = 1;
    /* then look for the lowest number not used */
    while( contains( usedPartitionNumbers, newPartitionNumber ) ){
      newPartitionNumber = newPartitionNumber + 1;
    }
    return newPartitionNumber;
  }

  /**
   * Mutators
   */

  /**
  * Add a partition to a drive.
  *
  * @param drive Drive to be added to.
  * @param partition Partition to be added.
  *
  * @return Drive containing the new parition.
  */
  global define DriveT
    addPartition( DriveT drive, PartitionT partition ){
      if( AutoinstPartition::isPartition( partition ) ){
	list<PartitionT> partitionList = drive["partitions"]:[];
	/**
	 * TODO: which constraints are on inserting?
	 */
	partitionList = add( partitionList, partition);

	return add(drive, "partitions", partitionList );
      }
      else{
	y2error("No valid partition: '%1'", partition );
      }
    }

  /**
  * Update partition on drive.
  *
  * @param drive Drive containing parition to be updated.
  * @param idx Integer identifying the partition to be updated (list
  * index).
  * @param partition New/Updated partition.
  *
  * @return Drive containing updated partition.
  */
  global define DriveT
    updatePartition( DriveT drive, integer idx, PartitionT partition ){
      if( isDrive( drive ) ){
	if( AutoinstPartition::isPartition( partition ) ){
	 list<PartitionT> partitionList = drive["partitions"]:[];
	 if( idx < size( partitionList ) ){
	    partitionList[idx] = partition;
	    return add(drive, "partitions", partitionList );
	 }
	 else{
	  y2error( "Index '%1' out of bounds. Drive has only '%2' partitions.",
	    idx, size( partitionList ));
	 }
	}
	else{
	  y2error( "No valid partition: '%1'.", partition );
	}
      }
      else{
	y2error( "No valid drive '%1'.", drive );
      }
      return drive;
    }

  /**
  * Remove partition from drive.
  *
  * @param drive Drive containing the partition to be deleted.
  * @param idx Integer identifying partition to be deleted (list
  * index).
  *
  * @return Drive missing the deleted partition.
  */
  global define DriveT
    removePartition( DriveT drive, integer idx ){
    if( isDrive( drive ) ){
      list<PartitionT> partitionList = drive["partitions"]:[];
      if( idx < size( partitionList ) ){
	partitionList = remove(partitionList, idx);
	return add(drive, "partitions", partitionList );
      }
      else{
	y2error("Cannot remove partition '%1', index out of bounds. Drive has only '%2' partitions",
	  idx, size( partitionList ));
      }
    }
    else{
      y2error("Cannot remove partition '%1' from invalid drive '%2'.",idx, drive );
    }
  }

  /**
  * Import a generic drive map and create DriveT from it. Called by
  * AutoinstPartPlan::Import().
  *
  * @param drive A map containing the drive information.
  *
  * @return DriveT containing the same info.
  */
  global define DriveT
    parseDrive( map drive ){
    DriveT newDrive = new( "auto", drive["type"]:`CT_DISK );
    newDrive = set( newDrive, "device", drive["device"]:"auto" );
    newDrive = set( newDrive, "initialize", drive["initialize"]:true );
    newDrive = set( newDrive, "use", string2symbol( drive["use"]:"all" ));
    newDrive = set( newDrive, "pesize", drive["pesize"]:"" );
    foreach( map part, drive["partitions"]:[], {
      PartitionT newPart = AutoinstPartition::parsePartition( part );
      if( AutoinstPartition::isPartition( newPart ) ){
	newDrive = addPartition( newDrive, newPart );
      }
      else{
	y2error("Couldn't construct PartitionT from '%1'", part );
      }
    });
    return newDrive;
  }

  /**
  * Export the DriveT to the generic map representation used by
  * autoyast. Filters out our surrogate id.
  *
  * @param drive Drive to export
  *
  * @return Exported generic map representation of DriveT.
  */
  global define map
    Export( DriveT drive ){
      /* get rid of id */
      map exportDrive = remove( drive, "_id" );
      /* translate e.g. `all to "all"  */
      exportDrive["use"] = symbol2string( exportDrive["use"]:`Empty );
      /* let AutoinstPartition do it's own filtering */
      exportDrive["partitions"] =
	maplist( PartitionT part, exportDrive["partitions"]:[], {
	  return AutoinstPartition::exportPartition( part );
	});
      return exportDrive;
    }
}

ACC SHELL 2018