PITA::Guest::Storage::Simple - A (relatively) simple Guest Storage object


PITA documentation Contained in the PITA distribution.

Index


Code Index:

NAME

Top

PITA::Guest::Storage::Simple - A (relatively) simple Guest Storage object

DESCRIPTION

Top

The PITA::Guest::Storage class provides an API for cataloguing and retrieving Guest images, with all the data stored on the filesystem using the native XML file formats.

PITA::Guest::Storage::Simple implements a very simple version of the PITA::Guest::Storage API.

Guest image location and searching is done the long way, with no indexing.

METHODS

Top

new

  my $store = PITA::Guest::Storage::Simple->new(
  	storage_dir => '/var/PITA-Guest-Storable-Simple',
  	);

The new method creates a new simple storage object. It takes a single named param

Returns a PITA::Guest::Storage::Simple object, or throws an exception on error.

storage_dir

The storage_dir accessor returns the location of the directory that serves as the root of the data store.

create

  my $store = PITA::Guest::Storage::Simple->new(
  	storage_dir => '/var/PITA-Guest-Storable-Simple',
  	);

The create constructor creates a new PITA::Guest::Storage::Simple repository.

storage_lock

The storage_lock method takes a lock on the storage_lock file, creating it if needed (in the create method case).

It does not wait to take the lock, failing immediately if the lock cannot be taken.

Returns true if the lock is taken, false if the lock cannot be taken, or throws an exception on error.

SUPPORT

Top

Bugs should be reported via the CPAN bug tracker at

http://rt.cpan.org/NoAuth/ReportBug.html?Queue=PITA

For other issues, contact the author.

AUTHOR

Top

Adam Kennedy <adamk@cpan.org>

SEE ALSO

Top

PITA::Guest::Storage, PITA, http://ali.as/pita/

COPYRIGHT

Top


PITA documentation Contained in the PITA distribution.
package PITA::Guest::Storage::Simple;

use 5.008;
use strict;
use Carp                 ();
use File::Spec           ();
use File::Path           ();
use Params::Util         '_INSTANCE';
use Data::GUID           ();
use PITA::XML::Guest     ();
use PITA::Guest::Storage ();

our $VERSION  = '0.50';
our @ISA      = 'PITA::Guest::Storage';
our $LOCKFILE = 'PITA-Guest-Storage-Simple.lock';





#####################################################################
# Constructor and Accessors

sub new {
	my $class = shift;
	my $self  = $class->SUPER::new(@_);

	# Check params
	unless ( $self->storage_dir and -d $self->storage_dir and -w _ ) {
		Carp::croak('The storage_dir is not a writable directory');
	}

	$self;
}

sub storage_dir {
	$_[0]->{storage_dir};
}





#####################################################################
# PITA::Guest::Storage::Simple Methods

sub create {
	my $class = shift;
	my $self  = bless { @_ }, $class;

	# The storage_dir should not exist, we will create it
	my $storage_dir = $self->storage_dir;
	unless ( $storage_dir ) { 
		Carp::croak("The storage_dir param was not provided");
	}
	if ( -d $storage_dir ) {
		Carp::croak("The storage_dir '$storage_dir' already exists");
	}
	eval { File::Path::mkpath( $storage_dir, 1, 0711 ) };
	if ( $@ ) {
		Carp::croak("Failed to create the storage_dir '$storage_dir': $@");
	}

	$self;
}

sub storage_lock {
	return 1 if $^O eq 'MSWin32';

	# Only lock on Unix
	require File::Flock;
	File::Flock->new(
		File::Spec->catfile( $_[0]->storage_dir, $LOCKFILE ),
	);
}





#####################################################################
# PITA::Guest::Storage Methods

sub add_guest {
	my $self = shift;
	my $xml  = _INSTANCE(shift, 'PITA::XML::Guest')
		or Carp::croak('Did not provide a PITA::XML::Guest to add_guest');

	# Is the driver available for this guest
	unless ( $xml->driver_available ) {
		Carp::croak("The guest driver " . $xml->driver . " is not available");
	}

	# Does the guest have a guid...
	$xml->set_id( Data::GUID->new->as_string ) unless $xml->id;

	# Does the GUID match an existing one
	if ( $self->guest( $xml->id ) ) {
		Carp::croak("The guest " . $xml->id . " already exists");
	}

	# Load a full PITA::Guest object from the file
	my $guest = PITA::Guest->new( $xml )
		or die "Failed to load PITA::Guest";

	# Can we ping the guest
	unless ( $guest->ping ) {
		Carp::croak("Ping failed, not a valid guest image");
	}

	# Run discovery if needed
	unless ( $guest->discovered ) {
		$guest->discover or Carp::croak("Failed to discover platforms in guest");
	}

	# Store the guest
	my $lock = $self->storage_lock;
	my $file = File::Spec->catfile( $self->storage_dir, $xml->id . '.pita' );
	$xml->write( $file ) or Carp::croak("Failed to save guest XML file");

	return $xml;
}

# Each guest has a matching directory name
sub guest {
	my $self = shift;
	my $id   = shift;

	# Find the file
	my $file = $self->guest_file($id);
	unless ( -f $file ) {
		return undef;
	}

	# Load the guest metadata object
	my $guest = PITA::XML::Guest->read($file);
	unless ( $guest->id ) {
		Carp::croak("Guest id mismatch for $file");
	}

	return $guest;
}

sub guest_exists {
	-f shift->guest_file(shift);
}

sub guest_file {
	File::Spec->catfile(
		$_[0]->storage_dir, "$_[1].pita",
	);
}

sub guests {
	my $self = shift;

	# Find all *.pita files in the storage directory
	opendir( STORAGE, $self->storage_dir ) or Carp::croak("opendir: $!");
	my @files = readdir(STORAGE)           or Carp::croak("readdir: $!");
	closedir( STORAGE )                    or Carp::croak("closedir: $!");

	# Load and check the metadata files
	my @guests = ();
	foreach my $file ( @files ) {
		# Filter out unwanted things
		next if $file =~ /^\./;
		next unless -f $file;
		next unless $file =~ /^(.+)\.pita$/;

		# Load the object
		my $id    = $1;
		my $path  = File::Spec->catfile( $self->storage_dir, $file );
		my $guest = PITA::XML::Guest->read( $path );
		unless ( $guest->id eq $id ) {
			Carp::croak("Guest id mismatch for $path");
		}

		push @guests, $guest;
	}

	return @guests;
}

sub platform {
	my $self = shift;
	die 'CODE INCOMPLETE';
}

sub platforms {
	my $self = shift;
	die 'CODE INCOMPLETE';
}

1;