VM-EC2
view release on metacpan or search on metacpan
lib/VM/EC2/Staging/Volume.pm view on Meta::CPAN
package VM::EC2::Staging::Volume;
=head1 NAME
VM::EC2::Staging::Volume - High level functions for provisioning and populating EC2 volumes
=head1 SYNOPSIS
use VM::EC2::Staging::manager;
# get a new staging manager
my $ec2 = VM::EC2->new;
my $staging = $ec2->staging_manager(); );
my $vol1 = $staging->get_volume(-name => 'Backup',
-fstype => 'ext4',
-size => 11,
-zone => 'us-east-1a');
# make a couple of directories in new volume
$vol1->mkdir('pictures');
$vol1->mkdir('videos');
# use rsync to copy local files onto a subdirectory of this volume
$vol1->put('/usr/local/my_pictures/' =>'pictures');
$vol1->put('/usr/local/my_videos/' =>'videos');
# use rsync to to copy a set of files on the volume to a local directory
mkdir('/tmp/jpegs');
$vol1->get('pictures/*.jpg','/tmp/jpegs');
# note that these commands are executed on the remote server as root!
@listing = $vol1->ls('-r','pictures');
$vol1->chown('fred','pictures');
$vol1->chgrp('nobody','pictures');
$vol1->chmod('0700','pictures');
$vol1->rm('-rf','pictures/*');
$vol1->rmdir('pictures');
# get some information about the volume
my $mtpt = $vol->mtpt;
my $mtdev = $vol->mtdev;
my $mounted = $vol->mounted;
my $server = $vol->server;
# detach the volume
$vol->detach;
# delete the volume entirely
$vol->delete;
=head1 DESCRIPTION
This is a high-level interface to EBS volumes which is used in
conjunction with VM::EC2::Staging::Manager and
VM::EC2::Staging::Server. It is intended to ease the process of
allocating and managing EBS volumes, and provides for completely
automated filesystem creation, directory management, and data transfer
to and from the volume.
You can use staging volumes without having to manually create and
manage the instances needed to manipulate the volumes. As needed, the
staging manager will create the server(s) needed to execute the
desired actions on the volumes.
Staging volumes are wrappers around VM::EC2::Volume, and have all the
methods associated with those objects. In addition to the standard EC2
volume characteristics, each staging volume in an EC2 region has a
symbolic name, which can be used to retrieve previously-created
volumes without remembering their volume ID. This symbolic name is
stored in the tag StagingName. Volumes also have a filesystem type
(stored in the tag StagingFsType). When a volume is mounted on a
staging server, it will also have a mount point on the file system,
and a mounting device (e.g. /dev/sdf1).
=cut
use strict;
use VM::EC2;
use Carp 'croak';
use File::Spec;
use overload
'""' => sub {my $self = shift;
return $self->short_name; # "inherited" from VM::EC2::Volume
},
fallback => 1;
my $Volume = 1; # for anonymously-named volumes
our $AUTOLOAD;
sub AUTOLOAD {
my $self = shift;
my ($pack,$func_name) = $AUTOLOAD=~/(.+)::([^:]+)$/;
lib/VM/EC2/Staging/Volume.pm view on Meta::CPAN
# volume will be appended to it.
sub put {
my $self = shift;
croak 'usage: ',ref($self),'->put($source1,$source2,$source3....,$dest_path)'
unless @_;
push @_,'.' if @_ < 2;
my $dest = pop;
my @source = @_;
$self->_spin_up;
my $server = $self->server or croak "no staging server available";
($dest) = $self->_rel2abs($dest);
$server->rsync(@source,$dest);
}
=head2 $vol->dd($destination_volume)
The dd() method performs a block level copy of the volume's disk onto
the destination. The destination must be another staging volume.
=cut
sub dd {
my $self = shift;
unshift @_,$self if @_ < 2;
$self->_spin_up;
$self->server->dd(@_);
}
=head2 $output = $vol->cmd($cmd,@args)
This method runs command $cmd on the server that is mounting the
volume using ssh. Before the command is run, the working directory is
changed to the top level of the volume's mount point. Any arguments,
switches, etc you wish to pass to the command can be provided as
@args. The output of the command is returned as a string in a scalar
context, or an array of lines in a list context.
Example:
@log = $volume->cmd('tar cvf /tmp/archive.tar .');
=head2 $result = $vol->ssh($cmd,@args)
This is similar to cmd(), except that the output of the command is
sent to STDOUT and the method returns true if the command executed
succcessfully on the remote machine. The cmd() and ssh() methods are
equivalent to backticks are system() respectively.
Example:
$volume->ssh('gzip /tmp/archive.tar') or die "couldn't compress archive";
=head2 $output = $vol->df(@args)
=head2 $output = $vol->ls(@args)
=head2 $success = $vol->mkdir(@args)
=head2 $success = $vol->chown(@args)
=head2 $success = $vol->chgrp(@args)
=head2 $success = $vol->chmod(@args)
=head2 $success = $vol->cp(@args)
=head2 $success = $vol->mv(@args)
=head2 $success = $vol->rm(@args)
=head2 $success = $vol->rmdir(@args)
Each of these methods performs the same function as the like-named
command-line function, after first changing the working directory to
the top level of the volume. They behave as shown in the pseudocode
below:
chdir $vol->mtpt;
sudo $method @args
The df() and ls() methods return the output of their corresponding
commands. In a scalar context each method returns a string
corresponding to the output of running the command on the server to
which the volume is attached. In a list context, the methods return
one element per line of output.
For example:
my $free = $volume->df('.'); # free on current directory
my ($percent) = $free =~ /(\d+)%/;
warn "almost out of space" if $percent > 90;
The other methods return a boolean value indicating successful
execution of the command on the remote machine.
Command line switches can be passed along with other arguments:
$volume->mkdir('-p','media/photos/vacation');
$volume->chown('-R','fred','media');
With the exception of df, each of these commands runs as the
superuser, so be careful how you call them.
You may run your own commands using the cmd() and ssh() methods. The
former returns the output of the command. The latter returns a success
code:
@log = $volume->cmd('tar cvf /tmp/archive.tar .');
$volume->ssh('gzip /tmp/archive.tar') or die "couldn't compress archive";
Before calling any of these methods, the volume must be mounted and
its server running. A fatal error will occur otherwise.
=cut
sub df { shift->_cmd('df',@_) }
sub ls { shift->_cmd('sudo ls',@_) }
sub mkdir { shift->_ssh('sudo mkdir',@_) }
sub chown { shift->_ssh('sudo chown',@_) }
sub chgrp { shift->_ssh('sudo chgrp',@_) }
sub chmod { shift->_ssh('sudo chmod',@_) }
sub rm { shift->_ssh('sudo rm',@_) }
sub rmdir { shift->_ssh('sudo rmdir',@_) }
sub cp { shift->_ssh('sudo cp',@_) }
sub mv { shift->_ssh('sudo mv',@_) }
sub _cmd {
my $self = shift;
my $cmd = shift;
my @args = map {quotemeta} @_;
$self->mounted or croak "Volume is not currently mounted";
my $mtpt = $self->mtpt;
$self->server->scmd("cd '$mtpt'; $cmd @args");
}
sub _ssh {
my $self = shift;
my $cmd = shift;
my @args = map {quotemeta} @_;
$self->mounted or croak "Volume is not currently mounted";
my $mtpt = $self->mtpt;
$self->server->ssh("cd '$mtpt'; $cmd @args");
}
sub cmd { shift->_cmd(@_) }
sub ssh { shift->_ssh(@_) }
sub _rel2abs {
my $self = shift;
my @paths = @_;
my $server = $self->server or croak "no server";
my @result;
foreach (@paths) {
if (/^([^:]+):(.+)$/) {
push @result,$_;
}
elsif (m!^/!) { # absolute path
push @result,"$server:".$_;
}
else {
my $p = "$server:".File::Spec->rel2abs($_,$self->mtpt);
$p .= '/' if m!/$!;
push @result,$p;
}
}
return @result;
}
sub _select_zone {
my $self = shift;
my $ec2 = shift;
if (my @servers = VM::EC2::Staging::Server->_servers($ec2->endpoint)) {
return $servers[0]->instance->placement;
} else {
my @zones = $ec2->describe_availability_zones;
return $zones[rand @zones];
}
( run in 0.655 second using v1.01-cache-2.11-cpan-5511b514fd6 )