Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ncm-afsclt: fix handling of size AUTOMATIC #816

Merged
merged 18 commits into from
Jul 18, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions ncm-afsclt/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,9 @@
<name>Alan Fitton</name>
<email>[email protected]</email>
</developer>
<developer>
<name>Michel Jouvin</name>
<email>[email protected]</email>
</developer>
</developers>
</project>
21 changes: 10 additions & 11 deletions ncm-afsclt/src/main/pan/components/afsclt/schema.pan
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,20 @@

declaration template components/afsclt/schema;

include 'quattor/schema';
include 'quattor/types/component';

type component_afsclt_entry = {
include structure_component

"thiscell" : string # "AFS home cell"
"thesecells" ? string[] # "Cell list to authenticate to"
"settime" ? boolean # "Shall AFS client sync sys time?"
"cellservdb" ? string # "Where Master CellServDB can be found"
"cachemount" ? string # "AFS cache location (/usr/vice/etc/cache)"
"cachesize" ? string # "AFS cache size in kB"
"options" ? nlist # "AFS client options"
"enabled" : string with match (SELF, 'yes|no')
# "Shall AFS client be active ?"
"afsd_args" ? string{} # /etc/afsd.args values for rc.afs
"thiscell" : string # AFS home cell
"thesecells" ? string[] # Cell list to authenticate to
"settime" ? boolean # Shall AFS client sync sys time?
"cellservdb" ? string # Where Master CellServDB can be found
"afs_mount" ? string # AFS mount point (e.g. /afs)
"cachemount" ? string # AFS cache location (/usr/vice/etc/cache)
"cachesize" ? string # AFS cache size in kB
"enabled" : legacy_binary_affirmation_string # Shall AFS client be active ?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMHO this is a retrograde step for readability. I now need to locate this type defined in some other file before I can understand how to populate this mandatory field, which has no default. legacy_yes_or_no_string would be more intuitive.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tend to agree... I was thinking the same thing when doing the modification suggested by @stdweird ...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feel free to open an issue to change. This is work done in quattor/template-library-core#111 and #749; but renaming the type should be very trivial.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMHO it would be better to make the effort to change the type to boolean instead of renaming the legacy type.

"afsd_args" ? string{} # /etc/afsd.args values for rc.afs
};

bind "/software/components/afsclt" = component_afsclt_entry;
Expand Down
147 changes: 85 additions & 62 deletions ncm-afsclt/src/main/perl/afsclt.pm
Original file line number Diff line number Diff line change
Expand Up @@ -25,55 +25,60 @@ Readonly my $THESECELLS => '/usr/vice/etc/TheseCells';
Readonly my $AFSD_ARGS => '/etc/afsd.args';
Readonly my $PREFIX => '/software/components/afsclt';

Readonly my $AFS_MOUNTPOINT_DEF => '/afs';


sub Configure {
my ( $self, $config ) = @_;
$self->Configure_Cell($config);
$self->Configure_TheseCells($config);
$self->Configure_Cache($config);
$self->Configure_CellServDB($config);
$self->Configure_Afsd_Args($config);

my $afsclt_config = $config->getElement($PREFIX)->getTree();

$self->Configure_Cell($afsclt_config);
$self->Configure_TheseCells($afsclt_config);
$self->Configure_Cache($afsclt_config);
$self->Configure_CellServDB($afsclt_config);
$self->Configure_Afsd_Args($afsclt_config);
}

sub Configure_Cell {
my ( $self, $config ) = @_;
unless ( $config->elementExists("$PREFIX/thiscell") ) {
$self->error("Cannot get $PREFIX/thiscell (required in profile)");
unless ( defined($config->{thiscell}) ) {
$self->error("$PREFIX/thiscell missing in the configuration");
return 1;
}

my $afscell = $config->getValue("$PREFIX/thiscell");
my $thiscell_fh = CAF::FileWriter->new( $THISCELL, log => $self );
print $thiscell_fh "$afscell\n";
print $thiscell_fh "$config->{thiscell}\n";

if ( $thiscell_fh->close() ) {
$self->info("Updated thiscell to $afscell");
$self->info("Updated thiscell to $config->{thiscell}");
}

return 0;
}

sub Configure_TheseCells {
my ( $self, $config ) = @_;

if ( $config->elementExists("$PREFIX/thesecells") ) {
my $cells = $config->getElement("$PREFIX/thesecells")->getTree();
if ( defined($config->{thesecells}) ) {
my $thesecells_fh = CAF::FileWriter->new( $THESECELLS, log => $self );
print $thesecells_fh join ( " ", @$cells ) . "\n";
print $thesecells_fh join ( " ", @{$config->{thesecells}} ) . "\n";
if ( $thesecells_fh->close() ) {
$self->info("Configured cell list for authentication $THESECELLS");
}
}
elsif ( -f $THESECELLS ) {
} elsif ( -f $THESECELLS ) {
if ($NoAction) {
$self->info("Would remove $THESECELLS");
}
else {
} else {
if ( unlink($THESECELLS) ) {
$self->info("Removed cell list for authentication $THESECELLS");
}
else {
} else {
$self->error("Could not remove $THESECELLS: $!");
}
}
}

return 0;
}

sub Configure_Cache {
Expand All @@ -85,14 +90,25 @@ sub Configure_Cache {
my $new_cache = 0; # in 1k blocks.
my $file_afsmount = '';

if ( $config->elementExists("$PREFIX/cachesize") ) {
$new_cache = $config->getValue("$PREFIX/cachesize"); #new cache size
}
else {
$self->info("Cannot get CDB $PREFIX/cachesize - not setting cache size");
if ( defined($config->{cachesize}) ) {
$new_cache = $config->{cachesize}
} else {
$self->info("$PREFIX/cachesize undefined: not setting cache size");
return 1;
}

if ( defined($config->{cachemount}) ) {
$file_cachemount = $config->{cachemount}; # mount point for AFS cache partition
} else {
$self->debug(1, "No explicit cache mount point defined in the configuration: will use currently defined one, if any");
}

if ( defined($config->{afs_mount}) ) {
$file_afsmount = $config->{afs_mount}; # AFS mount point
} else {
$self->debug(1, "No explicit AFS mount point defined in the configuration");
}

my $proc = CAF::Process->new( [ "fs", "getcacheparms" ], log => $self, keeps_state => 1 );
my $output = $proc->output();
if ( !( $? >> 8 ) && $output =~ /AFS using \d+ of the cache's available (\d+) (\w+) byte blocks/ ) {
Expand All @@ -106,39 +122,45 @@ sub Configure_Cache {
$self->warn("Cannot determine current AFS cache size, changing only config file");
}

my $afs_cacheinfo_fh = CAF::FileEditor->new( $AFS_CACHEINFO, log => $self ); # TODO use FileReader
$afs_cacheinfo_fh->cancel();
if ( "$afs_cacheinfo_fh" =~ m;^([^:]+):([^:]+):(\d+)$; ) {
$file_afsmount = $1;
$file_cachemount = $2;
my $afs_cacheinfo_fh = CAF::FileReader->new( $AFS_CACHEINFO, log => $self );
$self->debug(2, "$AFS_CACHEINFO current contents: >>>$afs_cacheinfo_fh<<<");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

only in else block? (and in that case, maybe in the error message)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In fact, I realized that my mod was wrong because if was no longer possible to override value in cacheinfo by the Quattor configuration. cacheinfo should only be used as default values. fixed.

if ( "$afs_cacheinfo_fh" =~ m;^([^:]+):([^:]+):(\d+|AUTOMATIC)$; ) {
$file_afsmount = $1 if $file_afsmount eq "";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these cannot be emtpy, since the regex have +; same below

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure to understand... You probably misread... The point is that you use the value from the file only if it is not defined in the configuration (in which case $file_afs_mount is not the default empty string).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indeed, i misread.

$file_cachemount = $2 if $file_cachemount eq "";
$file_cache = $3;
}
else {
} elsif ( "$afs_cacheinfo_fh" ne "" ) {
$self->error("Cannot parse stored AFS cache mount or size from $AFS_CACHEINFO");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add the unparseable content in the message?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure it adds anything... It is enough to look at fhe cacheinfo file contents.

return 1;
} else {
$self->debug(1, "No existing cacheinfo file found");
}
$afs_cacheinfo_fh->close();

# sanity check - don't allow cachesize bigger than 95% of a partition size
$proc = CAF::Process->new( [ "df", "-k", $file_cachemount ], log => $self, keeps_state => 1 );
foreach my $line ( split ( "\n", $proc->output() ) ) {
if ($line =~ m{^.*?\s+(\d+)\s+\d+\s+\d+\s+\d+%\s+(.*)}) {
my $disk_cachesize = $1;
my $mount = $2;
if ( $mount eq $file_cachemount && $new_cache > 0.95 * $disk_cachesize ) {
$self->error("Cache size ($disk_cachesize) on $mount cannot exceed 95% of its partition size. Not changing.");
return 1;
if ( $new_cache ne "AUTOMATIC" ) {
# sanity check - don't allow cachesize bigger than 95% of a partition size
$proc = CAF::Process->new( [ "df", "-k", $file_cachemount ], log => $self, keeps_state => 1 );
foreach my $line ( split ( "\n", $proc->output() ) ) {
if ($line =~ m{^.*?\s+(\d+)\s+\d+\s+\d+\s+\d+%\s+(.*)}) {
my $disk_cachesize = $1;
my $mount = $2;
if ( $mount eq $file_cachemount && $new_cache > 0.95 * $disk_cachesize ) {
$self->error("Cache size ($disk_cachesize) on $mount cannot exceed 95% of its partition size. Not changing.");
return 1;
}
}
}
}

# adjust stored cache size (gets overwritten on restart for OpenAFS-1.4)
if ( $new_cache != $file_cache ) {
my $afs_cacheinfo_fh = CAF::FileWriter->new( $AFS_CACHEINFO, log => $self );
print $afs_cacheinfo_fh "$file_afsmount:$file_cachemount:$new_cache\n";
if ( $afs_cacheinfo_fh->close() ) {
$self->info("Changed AFS cache config file $AFS_CACHEINFO: $file_cachemount $run_cache -> $new_cache (1K blocks)");
}
# Adjust cacheinfo file if needed.
# Force string interpolation of cache size as it can be AUTOMATIC
if ( $file_afsmount eq "" ) {
$self->debug(1, "AFS mount point not defined: using default ($AFS_MOUNTPOINT_DEF)");
$file_afsmount = $AFS_MOUNTPOINT_DEF;
}
my $afs_cacheinfo_fh = CAF::FileWriter->new( $AFS_CACHEINFO, log => $self );
print $afs_cacheinfo_fh "$file_afsmount:$file_cachemount:$new_cache\n";
if ( $afs_cacheinfo_fh->close() ) {
$self->info("Changed AFS cache config ($AFS_CACHEINFO). New cache size (1K blocks): $new_cache (current: $run_cache)");
}

# adjust online (in-kernel) value
Expand All @@ -152,22 +174,22 @@ sub Configure_Cache {
$self->info("Changed running AFS cache $run_cache -> $new_cache (1K blocks)");
}
}

return 0;
}

sub Configure_CellServDB {
my ( $self, $config ) = @_;
my $master_cellservdb;
if ( $config->elementExists("$PREFIX/cellservdb") ) {
$master_cellservdb = $config->getValue("$PREFIX/cellservdb");
if ( defined($config->{cellservdb}) ) {
$master_cellservdb = $config->{cellservdb};
if ( $master_cellservdb =~ m/^\/\w/i ) { # non-URI -> file
$master_cellservdb = "file://" . $master_cellservdb;
}
elsif ( $master_cellservdb !~ m/^(ftp|http|file)/i ) { # known URIs
$self->error("Don't know how to handle URI: $master_cellservdb, giving up");
} elsif ( $master_cellservdb !~ m/^(ftp|http|file)/i ) { # known URIs
$self->error("Unsupported protocol to access master CellServDB ($master_cellservdb), giving up");
return 1;
}
}
else {
} else {
return 0;
}

Expand All @@ -183,9 +205,8 @@ sub Configure_CellServDB {
if ($cellservdb_fh->close()) {
$self->info("Updated CellServDB");
}
$self->update_afs_cells();

return 1;
return $self->update_afs_cells();
}

# update the list of known AFS cells and run "fs newcell" when needed
Expand All @@ -201,8 +222,7 @@ sub update_afs_cells ( $$ ) {
if ($line =~ /^>(.\S+)/) {
$cell = $1;
$ipaddrs{$cell} = [];
}
elsif ($line =~ /^(\S+)\s+\#\s*\S+/) {
} elsif ($line =~ /^(\S+)\s+\#\s*\S+/) {
# new entry
push ( @{ $ipaddrs{$cell} }, $1 );
}
Expand Down Expand Up @@ -262,21 +282,24 @@ sub update_afs_cells ( $$ ) {
else {
$self->info("Nothing to do for AFS cell information");
}

return 0;
}

sub Configure_Afsd_Args {
my ( $self, $config ) = @_;

if ( $config->elementExists("$PREFIX/afsd_args") ) {
my $args = $config->getElement("$PREFIX/afsd_args")->getTree();
if ( defined($config->{afsd_args}) ) {
my $fh = CAF::FileWriter->new( $AFSD_ARGS, log => $self, backup => ".old" );
foreach my $key (sort keys %$args) {
print $fh "$key:" . $args->{$key} . "\n";
foreach my $key (sort keys %{$config->{afsd_args}}) {
print $fh "$key:$config->{afsd_args}->{$key}\n";
}
if ( $fh->close() ) {
$self->info("Updated afsd.args");
}
}

return 0;
}

1; #required for Perl modules
49 changes: 26 additions & 23 deletions ncm-afsclt/src/main/perl/afsclt.pod
Original file line number Diff line number Diff line change
Expand Up @@ -17,55 +17,58 @@ NCM::afsclt - NCM AFS client configuration component

=item Configure()

Sets ThisCell and enables AFS authentication (via authconfig) and a
few options in /etc/sysconfig/afs. Configures /etc/sysconfig/iptables
for the AFS client callback port.

=item Unconfigure()

/etc/sysconfig/afs: reset to defaults
iptables: remove the AFS ports
authconfig: no action
CellServDB: no action
Configure the cell, the AFS cacheinfo file and the afsd daemon.

=back

=head1 RESOURCES

=over

=item /software/components/afsclt/active : boolean

activates/deactivates the component.

=item /software/components/afsclt/thiscell : string
=item /software/components/afsclt/afsd_args : nlist (optional)

local AFS cell for this machine
various command-line options for the afsd daemon

=item /software/components/afsclt/settime : boolean
=item /software/components/afsclt/afs_mount : string (optional)

make AFS client set the system time or not.
AFS mount point. If not defined, C</afs> is used.

=item /software/components/afsclt/options : nlist
=item /software/components/afsclt/cachemount : string (optional)

various command-line options for the afsd daemon
AFS cache mount point. No default.

=item /software/components/afsclt/cachesize : int
=item /software/components/afsclt/cachesize : string (optional)

desired AFS cache size on disk, in 1K blocks. The running AFS cache
desired AFS cache size on disk, in 1K blocks, or C<AUTOMATIC>. The running AFS cache
will get adjusted online, and $afs_cacheinfo will be changed if
required. Please note that an available (mounted) AFS cache partition
has precedence over this value, i.e. you cannot force a lower usage of
the cache partition. For Linux machines, a cache partition will use
CACHESIZE=AUTOMATIC, for other OSes, a hardcoded fill rate of 85% is
used.

=item /software/components/afsclt/cellservdb : string
=item /software/components/afsclt/cellservdb : string (optional)

A regularly-updated AFS CellServDB URL or filename (e.g. from AFS)
that this component will copy to local disk. The local AFS client will
get notified of any additions or changes within a cell.

=item /software/components/afsclt/enabled : C<yes> or C<no> (required)

Whether the AFS client should be enabled or not. No default.

=item /software/components/afsclt/settime : boolean (optional)

make AFS client set the system time or not.

=item /software/components/afsclt/thiscell : string (required)

local AFS cell for this machine. No default.

=item /software/components/afsclt/thesecells : list of string (optional)

List of AFS cells to authenticate to. No default.

=back

=head1 DEPENDENCIES
Expand Down
Loading