Skip to content

Commit

Permalink
Merge pull request #58 from mariux64/add-mxmount
Browse files Browse the repository at this point in the history
Add mxmount
  • Loading branch information
donald authored Nov 23, 2018
2 parents 3a8b44e + d5cf90d commit 1c8e076
Show file tree
Hide file tree
Showing 4 changed files with 309 additions and 0 deletions.
11 changes: 11 additions & 0 deletions clusterd/clusterd
Original file line number Diff line number Diff line change
Expand Up @@ -579,6 +579,7 @@ our %UDP_HANDLER=
'restart' => \&udp_rx_restart,
'flush-gidcache' => \&udp_rx_flush_gidcache,
'make-automaps' => \&udp_rx_make_automaps,
'reexport' => \&udp_rx_reexport,
'log' => \&udp_rx_log,
'exec' => \&udp_rx_exec,
'push' => \&udp_rx_push,
Expand Down Expand Up @@ -1089,6 +1090,10 @@ sub udp_rx_make_automaps {
system '/sbin/make-automaps';
}

sub udp_rx_reexport {
system '/usr/bin/mxmount --reexport-only';
}

#----------- tcp mgmt console -----------------------------

our $MGMT_PORT=234;
Expand Down Expand Up @@ -1824,6 +1829,7 @@ usage: $0 [options]
--exec @node cmd [args...] # execute cmd on node
--flush-gidcache # flush rpc auth.unix.gid cache on all nodes
--make-automaps # execute /usr/sbin/make-automaps on all nodes
--reexport # execute /usr/bin/mxmount --reexport-only on all nodes
--lsof=pattern
Expand Down Expand Up @@ -1851,6 +1857,7 @@ GetOptions
'send-restart' => \$options{'send-restart'},
'flush-gidcache' => \$options{'flush-gidcache'},
'make-automaps' => \$options{'make-automaps'},
'reexport' => \$options{'reexport'},
'lsof=s' => \$options{'lsof'},

) or die USAGE;
Expand Down Expand Up @@ -1885,6 +1892,10 @@ if (defined $options{'push'}) {
sync_cluster_pw() or die "$CLUSTER_PW_FILE: $!\n";
$donald_s=new My::Select::INET(Proto=>'udp') or die "$!\n";
udp_broadcast_message($donald_s,'make-automaps');
} elsif (defined $options{'reexport'}) {
sync_cluster_pw() or die "$CLUSTER_PW_FILE: $!\n";
$donald_s=new My::Select::INET(Proto=>'udp') or die "$!\n";
udp_broadcast_message($donald_s,'reexport');
} elsif (defined $options{'daemon'}) {
$options{'kill'} and Donald::Tools::kill_previous_server('clusterd') and sleep 2;

Expand Down
2 changes: 2 additions & 0 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -127,4 +127,6 @@ install_data clusterd/clusterd.service "$DESTDIR$systemdunitdi
install_exec clusterd/clusterd "$DESTDIR$usr_sbindir/clusterd"
install_exec setuid/setuid "$DESTDIR$usr_sbindir/setuid"
install_exec uvpn/uvpn "$DESTDIR$usr_bindir/uvpn"
install_exec mxmount/mxmount "$DESTDIR$usr_bindir/mxmount"
install_data mxmount/mxmount.service "$DESTDIR$systemdunitdir/mxmount.service"
exit
284 changes: 284 additions & 0 deletions mxmount/mxmount
Original file line number Diff line number Diff line change
@@ -0,0 +1,284 @@
#! /usr/local/system/perl/bin/perl

use strict;
use warnings;
use Sys::Hostname;
use Getopt::Long;

my $configfile = "/etc/mxmounts";
my $exports = "/etc/exports";

my $exportstag = "# DO NOT EDIT BELOW THIS LINE # created by /usr/bin/mxmount #";

my $fullhostname;
my $hostname;
my @lines;
my @exports;
my %V;
my %D;

our $USAGE=<<"_EOF_";
usage: $0
$0 --reexport-only
_EOF_

our ($opt_reexport_only);

$fullhostname = hostname();
($hostname) = $fullhostname =~ /^(.*?)\./;

%D = ();
%V = (
DEFAULT_MOUNT_OPTIONS => '',
DEFAULT_EXPORT_OPTIONS => '',
DEFAULT_MOUNT_PREFIX => '/',

SHORTHOST => $hostname,
);

@lines = read_file($configfile);
@exports = read_file_raw($exports);

@lines = parse_variables(@lines);

@lines = parse_data(@lines);

foreach(@lines) {
print STDERR "skipping: '$_'\n";
}

add_data0_if_not_present();

my %options;
GetOptions (
'reexport-only' => \$opt_reexport_only,
) or die $USAGE;
@ARGV and die $USAGE;

mount_all() unless $opt_reexport_only;
create_exports();
system("exportfs -ra");

sub safe_qx { open my $pipe,'-|',@_; return join('',<$pipe>) }

sub add_data0_if_not_present {
my $allmp = $D{$hostname};

$allmp = [] unless (defined $allmp);

foreach my $mp (sort { $a->{mountpoint} cmp $b->{mountpoint} } @$allmp ) {
if ($mp->{label} eq "data0") {
return;
}
if ($mp->{mountpoint} eq "$V{DEFAULT_MOUNT_PREFIX}/$hostname/0") {
print STDERR "$mp->{mountpoint} already blocked by $mp->{label}\n";
return;
}
}
parse_data("$hostname !data0");
}

sub create_exports {
my $allmp = $D{$hostname};
my $newexport=system('hostconfig newexport')==0;

open(EXPORTS, '>', $exports) or die "can't open $exports: $!";

foreach my $exp (@exports) {
chomp($exp);
next if($exp =~ /^\s*$/);
last if($exp eq $exportstag);
print EXPORTS "$exp\n";
}
print EXPORTS "\n$exportstag\n\n";

foreach my $mp (@$allmp) {
next if($mp->{noexport});
unless ($newexport) {
my @CMD = ($mp->{mountpoint}, $mp->{exportopts});
print join " ", "$exports: ", @CMD, "\n";
print EXPORTS join " ", @CMD, "\n";
} else {
my ($mountpoint,$exportopts)=($mp->{mountpoint}, $mp->{exportopts}); # '/amd/theinternet/1','@amd(sync,rw,...)'
my ($hostspec,$optspec)=$exportopts=~/^([^(]+)(.*)/; # '@amd','(sync,rw,...)'
my ($opts)=$optspec=~/\((.*)\)/; # 'sync,rw,...'
my $hosts='';
warn "export $mountpoint to $hostspec opts $opts\n";
if (my ($group) = $hostspec=~/^@(.+)/) {
$hosts=safe_qx('/usr/sbin/hostconfig','--list',$group); # expanded group
$hosts or warn "group $group is empty\n";
} else {
$hosts=$hostspec; # single host
}
$hosts and printf EXPORTS "%s -%s %s\n",$mountpoint,$opts,$hosts;
}
}
close EXPORTS;
}

sub mount_all {
my $allmp = $D{$hostname};
my @CMD;
foreach my $mp (sort { $a->{mountpoint} cmp $b->{mountpoint} } @$allmp) {

@CMD = ();

push @CMD, 'mount', "LABEL=$mp->{label}", $mp->{mountpoint};

if($mp->{fs}) {
push @CMD, '-t', $mp->{fs};
}
if($mp->{mountopts}) {
push @CMD, '-o', $mp->{mountopts};
}
system('mkdir','-p',$mp->{mountpoint});
print STDERR join " ", @CMD, "\n";
system(@CMD);
}
}

sub parse_data {
my @lines = @_;
my @invalid = ();
my @data;

my $rest;

foreach(@lines) {
@data = split /\s+/, $_;

unless($data[1]) {
push @invalid, $_;
next;
}

my $D = {};

$D->{line} = $_;

$D->{host} = $data[0];
$D->{label} = $data[1];
if($D->{label} =~ /^!(.*)/) {
$D->{noexport} = 1;
$D->{label} = $1;
}

if($D->{label} =~ /(.*):(.*)/) {
$D->{label} = $1;
$D->{mountpoint} = $2;
} else {
if($D->{label} =~ /^X/) { # X: decent controller based raid
$D->{mountpoint} = 'X/' . $D->{label};
$D->{label} = lc($D->{label});
} elsif($D->{label} =~ /^C/) { # C: controller based raid, confidential
$D->{mountpoint} = 'C/' . $D->{label};
$D->{label} = lc($D->{label});
if (!$data[3]) {
$D->{noexport} = 1;
}
} elsif($D->{label} =~ /^D/) { # D: scratch software raid (mdadm)
$D->{mountpoint} = 'D/' . $D->{label};
$D->{label} = lc($D->{label});
} elsif($D->{label} =~ /^M/) { # M: decent software raid (mdadm)
$D->{mountpoint} = 'M/' . $D->{label};
$D->{label} = lc($D->{label});
} elsif($D->{label} =~ /^data(.*)/) {
$D->{mountpoint} = $1;
} else {
warn "mxmount: unknown shortlabel '$D->{label}'.. skipping..";
next;
}
}
if($D->{mountpoint} !~ m(^\/)) {
$D->{mountpoint} = "$V{DEFAULT_MOUNT_PREFIX}/" . $D->{mountpoint};
}

$D->{fs} = 'auto';
$D->{mountopts} = $data[2] ? $data[2] : $V{DEFAULT_MOUNT_OPTIONS};
if($D->{mountopts} =~ /\[(.*)\](.*)/) {
$D->{fs} = $1;
$D->{mountopts} = $2;
}

$D->{exportopts} = $data[3] ? $data[3] : $V{DEFAULT_EXPORT_OPTIONS};

foreach(qw(host label mountpoint fs mountopts exportopts )) {
$D->{$_} = expand_variables($D->{$_});
}
push @{$D{$D->{host}}}, $D;
}
return @invalid;
}

sub expand_variables {
my $s = shift;

foreach my $k (keys %V) {
$s =~ s/$k/$V{$k}/g;
}
return $s;
}

sub parse_variables {
my @lines = @_;
my @invalid = ();

my ($key, $value);

foreach(@lines) {
if(($key, $value) = /^(\S+)=\s*(.*)$/) {
$V{$key} = $value;
} else {
push @invalid,expand_variables($_);
}
}
return @invalid;
}
sub read_file {
my $file = shift;
open F, "$file" or die "can't open $file: $!\n";
my @lines=();
my $line="";
my $cont=0;
while(<F>) {
chomp;
next if(/^\s*#/ or /^\s*$/);
$cont=0;
s/#.*$//; # remove comments..
$_ = $line . $_;

if(s/\\\s*$//) {
# line continous in next line..
$cont=1;
}

$line = $_;

unless($cont) {
$line =~ s/\s+/ /g;
$line =~ s/^\s+//;
$line =~ s/\s+$//;
push @lines, $line;
$line="";
}
}
close F;
return @lines;
}

sub read_file_raw {
my $file = shift;
my @lines;

open F, "$file" or return;
@lines = <F>;
close F;

return @lines;
}
12 changes: 12 additions & 0 deletions mxmount/mxmount.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[Unit]
Description=MX mount local data filessystems
After=mxraid.startup.service
ConditionPathExists=/etc/mxmounts

[Service]
Type=oneshot
ExecStart=/usr/bin/mxmount
RemainAfterExit=yes

[Install]
WantedBy=local-fs.target

0 comments on commit 1c8e076

Please sign in to comment.