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