#
# (c) Jan Gehring <jan.gehring@gmail.com>
#
# vim: set ts=3 sw=3 tw=0:
# vim: set expandtab:
=head1 NAME
Rex::Commands::Partition - Partition module
=head1 DESCRIPTION
With this Module you can partition your harddrive.
=head1 SYNOPSIS
use Rex::Commands::Partition;
=head1 EXPORTED FUNCTIONS
=over 4
=cut
package Rex::Commands::Partition;
use strict;
use warnings;
require Rex::Exporter;
use base qw(Rex::Exporter);
use vars qw(@EXPORT);
use Data::Dumper;
use Rex::Logger;
use Rex::Commands::Run;
use Rex::Commands::File;
use Rex::Commands::LVM;
use Rex::Commands::Fs;
@EXPORT = qw(clearpart partition);
=item clearpart($drive)
Clear partitions on $drive.
clearpart "sda";
clearpart "sda",
initialize => "gpt";
=cut
sub clearpart {
my ($disk, %option) = @_;
if($option{initialize}) {
# will destroy partition table
run "parted -s /dev/$disk mklabel " . $option{initialize};
if($? != 0) {
die("Error setting disklabel from $disk to $option{initialize}");
}
if($option{initialize} eq "gpt") {
Rex::Logger::info("Creating bios boot partition");
partition("none",
fstype => "non-fs",
ondisk => $disk,
size => "1");
run "parted /dev/$disk set 1 bios_grub on";
}
}
else {
my @partitions = grep { /$disk\d+$/ } split /\n/, cat "/proc/partitions";
for my $part_line (@partitions) {
my ($num, $part) = ($part_line =~ m/\d+\s+(\d+)\s+\d+\s(.*)$/);
Rex::Logger::info("Removing $part");
run "parted -s /dev/$disk rm $num";
}
}
}
=item partition($mountpoint, %option)
Create a partition with mountpoint $mountpoint.
partition "/",
fstype => "ext3",
size => 15000,
ondisk => "sda",
type => "primary";
partition "none",
type => "extended",
ondisk => "sda",
grow => 1,
mount => TRUE,
partition "swap",
fstype => "swap",
type => "logical",
ondisk => "sda",
size => 8000;
partition "none",
lvm => 1,
type => "primary",
size => 15000,
ondisk => "vda";
partition "/",
fstype => "ext3",
size => 10000,
onvg => "vg0";
=cut
sub partition {
my ($mountpoint, %option) = @_;
$option{type} ||= "primary"; # primary is default
# info:
# disk size, partition start, partition end is in MB
unless($option{ondisk}) {
die("You have to specify ,,ondisk''.");
}
my $disk = $option{ondisk};
my @output_lines = grep { /^\s+\d+/ } run "parted /dev/$disk print";
my $last_partition_end = 1;
my $unit;
if(@output_lines) {
($last_partition_end, $unit) = ($output_lines[-1] =~ m/\s+[\d\.]+[a-z]+\s+[\d\.]+[a-z]+\s+([\d\.]+)(kB|MB|GB)/i);
if($unit eq "GB") { $last_partition_end = sprintf("%i", (($last_partition_end * 1000)+1)); } # * 1000 because of parted, +1 to round up
if($unit eq "kB") { $last_partition_end = sprintf("%i", (($last_partition_end / 1000)+1)); } # / 1000 because of parted, +1 to round up
}
Rex::Logger::info("Last parition ending at $last_partition_end");
my $next_partition_start = $last_partition_end;
my $next_partition_end = $option{size} + $last_partition_end;
if($option{grow}) {
$next_partition_end = "-- -1";
}
run "parted -s /dev/$disk mkpart $option{type} $next_partition_start $next_partition_end";
if($? != 0) {
die("Error creating partition.");
}
run "partprobe";
# get the partition id
my @partitions = grep { /$disk\d+$/ } split /\n/, cat "/proc/partitions";
my ($part_num) = ($partitions[-1] =~ m/$disk(\d+)/);
if(! $part_num) {
die("Error getting partition number.");
}
if($option{boot}) {
run "parted /dev/$disk set $part_num boot on";
}
if($option{vg}) {
run "parted /dev/$disk set $part_num lvm on";
pvcreate "/dev/$disk$part_num";
my @vgs = vgs();
if( grep { $_->{volume_group} eq $option{vg} } @vgs ) {
# vg exists, so extend it
vgextend $option{vg}, "/dev/$disk$part_num";
}
else {
# vg doesnt exist, create a new one
vgcreate $option{vg} => "/dev/$disk$part_num";
}
}
my $found_part=0;
while($found_part == 0) {
Rex::Logger::debug("Waiting on /dev/$disk$part_num to appear...");
run "ls -l /dev/$disk$part_num";
if($? == 0) { $found_part = 1; last; }
sleep 1;
}
if(! exists $option{fstype} || $option{fstype} eq "non-fs" || $option{fstype} eq "none" || $option{fstype} eq "") {
# nix
}
elsif(can_run("mkfs.$option{fstype}")) {
Rex::Logger::info("Creating filesystem $option{fstype} on /dev/$disk$part_num");
my $add_opts = "";
if(exists $option{label} || exists $option{lable}) {
my $label = $option{label} || $option{lable};
$add_opts .= " -L $label ";
}
run "mkfs.$option{fstype} $add_opts /dev/$disk$part_num";
}
elsif($option{fstype} eq "swap") {
Rex::Logger::info("Creating swap space on /dev/$disk$part_num");
my $add_opts = "";
if(exists $option{label} || exists $option{lable}) {
my $label = $option{label} || $option{lable};
$add_opts .= " -L $label ";
}
run "mkswap $add_opts /dev/$disk$part_num";
}
else {
die("Can't format partition with $option{fstype}");
}
if(exists $option{mount} && $option{mount}) {
mount "/dev/$disk$part_num", $mountpoint,
fs => $option{fstype};
}
if(exists $option{mount_persistent} && $option{mount_persistent}) {
mount "/dev/$disk$part_num", $mountpoint,
fs => $option{fstype},
label => $option{label} || "",
persistent => 1;
}
return "$disk$part_num";
}
=back
=cut
1;