App-FuguVM

 view release on metacpan or  search on metacpan

lib/App/FuguVM/Config.pm  view on Meta::CPAN

		);
		return 0;
	}

	# Each path directive resolves against the project root, and the
	# file must be readable now. A path that fails at 'up' time, deep
	# inside an install, is a path that failed too late.
	for my $directive (qw(autoinstall base_disk root_password_file)) {
		next if !defined $vm->{$directive};
		my $path = $self->_resolve_path( $vm->{$directive} );
		if ( !-f $path || !-r $path ) {
			$self->{error} =
			    sprintf( "VM '%s': %s file is not readable: %s",
				$name, $directive, $path );
			return 0;
		}
		$vm->{$directive} = $path;
	}

	$vm->{install_mode} =
	      defined $vm->{autoinstall} ? 'autoinstall'
	    : defined $vm->{base_disk}   ? 'import'
	    :                              'expect';

	if ( $vm->{install_mode} eq 'import' && !$vm->{image_cache} ) {
		$self->{error} = sprintf(
			"VM '%s': base_disk needs the image cache;"
			    . " remove 'image_cache no'",
			$name
		);
		return 0;
	}

	# Outside the expect mode the tool does not know the root
	# password of the image, and it cannot install a key without
	# one.
	if (       $vm->{install_mode} ne 'expect'
		&& defined $vm->{ssh_pubkey}
		&& $vm->{ssh_pubkey} ne ''
		&& !defined $vm->{root_password_file} )
	{
		$self->{error} = sprintf(
			"VM '%s': ssh_pubkey needs root_password_file in the"
			    . " %s mode; add the directive, or unset"
			    . " ssh_pubkey and bake the key into the image",
			$name, $vm->{install_mode} );
		return 0;
	}

	return 1;
}

# $self->_resolve_path($value):
#	Expand a leading tilde, then make a relative path absolute
#	against the project root. The result is always absolute: the
#	project root itself can be relative, from a --project option,
#	and a daemonized child can read the path from an other working
#	directory.
sub _resolve_path ( $self, $value )
{
	my $path = Fugu::File->expand_tilde($value);
	$path = "$self->{project_root}/$path" if $path !~ m{^/};

	require File::Spec;
	return File::Spec->rel2abs($path);
}

# $self->error:
#	Return the reason of the last failed load_vm, or undef.
sub error ($self)
{
	return $self->{error};
}

# _valid_port($value):
#	Report if a port directive holds the word AUTO_PORT or a
#	decimal number from 1 to 65535.
sub _valid_port ($value)
{
	return 0 if !defined $value;
	return 1 if $value eq AUTO_PORT;

	# A leading zero is not decimal, and the string-keyed port sets
	# of the probe would not match it.
	return 0 if $value !~ /^[1-9][0-9]*$/;

	return $value <= 65535 ? 1 : 0;
}

# _valid_ipv4($value):
#	Report if a value is one IPv4 address in dotted-decimal form.
#	A host name is not: a name resolves once for QEMU and once for
#	the tool, and the two answers can differ.
sub _valid_ipv4 ($value)
{
	return 0 if !defined $value;

	my @parts = split /\./, $value, -1;
	return 0 if @parts != 4;

	for my $part (@parts) {

		# A leading zero reads as octal in inet_aton, so such a
		# component is not decimal.
		return 0 if $part !~ /^(?:0|[1-9][0-9]{0,2})$/;
		return 0 if $part > 255;
	}

	return 1;
}

sub cache_dir ($self)
{
	my $dir = $self->_setting('cache_dir') // '~/.cache/fuguvm';

	return Fugu::File->expand_tilde($dir);
}

# $self->image_cache:
#	Return whether 'fuguvm up' may use the installed-image cache.
#	The project configuration wins over the global one. The default
#	is on.
sub image_cache ($self)
{
	my $value = $self->_setting('image_cache');
	return 1 if !defined $value;

	return $self->_bool( $value, 1 );
}

# $self->verify:
#	Return whether the tool verifies each mirror download. The
#	project configuration wins over the global one. The default is
#	on.
sub verify ($self)
{
	my $value = $self->_setting('verify');
	return 1 if !defined $value;

	return $self->_bool( $value, 1 );
}

# $self->signify_dir:
#	Return the resolved directory of the signify public keys, or
#	undef without the directive. A leading tilde expands, and a
#	relative path resolves against the project root.
sub signify_dir ($self)
{
	my $dir = $self->_setting('signify_dir');
	return if !defined $dir;

	return $self->_resolve_path($dir);
}

# $self->distfile_cache:
#	Return the distfile cap in bytes. The default is 0, and 0
#	turns the distfile cache off. An unparsable value gives one
#	warning and the value 0: an unrecognized spelling must not
#	silently mean its opposite, and off is the closed state for a
#	cache.
sub distfile_cache ($self)
{
	my $value = $self->_setting('distfile_cache');
	return 0 if !defined $value;

	my $bytes = _parse_size($value);
	if ( !defined $bytes ) {
		Fugu::Log->default->warning(
			"distfile_cache '%s' is not a size; the cache is off",
			$value );
		return 0;
	}

	return $bytes;
}

# _parse_size($value):
#	Return the byte count of a size, or undef. The value is a bare
#	number of bytes, or a number with a K, M or G suffix. The
#	suffix is 1024-based, and the letter case does not matter.
sub _parse_size ($value)
{
	my ( $number, $suffix ) = $value =~ /\A([0-9]+)([KkMmGg]?)\z/;
	return if !defined $number;

	my %scale = ( '' => 1, k => 1024, m => 1024**2, g => 1024**3 );

	return $number * $scale{ lc $suffix };
}

# $self->_bool($value, $default):
#	Read a switch, and report a value that is neither yes nor no.
#	An unrecognized spelling must not silently mean its opposite,
#	so the operator hears about it.
sub _bool ( $self, $value, $default )
{
	my $parser = $self->{project};
	my $result = $parser->parse_bool( $value, $default );

	Fugu::Log->default->warning( '%s', $parser->error )
	    if defined $parser->error;

	return $result;
}



( run in 0.468 second using v1.01-cache-2.11-cpan-a49fcb8fa48 )