From 70dc0598f256ab6358ef75026a726ca98ae7a03c Mon Sep 17 00:00:00 2001 From: Digimer Date: Wed, 31 Mar 2021 23:59:19 -0400 Subject: [PATCH] * Created Storage->manage_lvm_conf() that checks / updates lvm.conf to add a filter to avoid seeing DRBD devices as LVM components. This is now called from striker-initialize-host and scan-drbd. Signed-off-by: Digimer --- Anvil/Tools.pm | 1 + Anvil/Tools/Storage.pm | 168 ++++++++++++++++++++++++++++ scancore-agents/scan-drbd/scan-drbd | 4 + share/words.xml | 6 + tools/striker-initialize-host | 34 +++++- 5 files changed, 209 insertions(+), 4 deletions(-) diff --git a/Anvil/Tools.pm b/Anvil/Tools.pm index 90773a4a..97ce3d4b 100644 --- a/Anvil/Tools.pm +++ b/Anvil/Tools.pm @@ -1029,6 +1029,7 @@ sub _set_paths hosts => "/etc/hosts", 'httpd.conf' => "/etc/httpd/conf/httpd.conf", 'journald_anvil' => "/etc/systemd/journald.conf.d/anvil.conf", + 'lvm.conf' => "/etc/lvm/lvm.conf", 'pg_hba.conf' => "/var/lib/pgsql/data/pg_hba.conf", 'postgresql.conf' => "/var/lib/pgsql/data/postgresql.conf", pxe_default => "/var/lib/tftpboot/pxelinux.cfg/default", diff --git a/Anvil/Tools/Storage.pm b/Anvil/Tools/Storage.pm index c7dd72a1..33f9832c 100644 --- a/Anvil/Tools/Storage.pm +++ b/Anvil/Tools/Storage.pm @@ -25,6 +25,7 @@ my $THIS_FILE = "Storage.pm"; # get_file_stats # get_storage_group_details # make_directory +# manage_lvm_conf # move_file # parse_df # parse_lsblk @@ -1778,6 +1779,173 @@ fi;"; return($failed); } + +=head2 manage_lvm_conf + +This method configures C<< lvm.conf >> to add the C<< filter = [ ... ] >> to ensure DRBD devices aren't scanned. + +If there was a problem, C<< 1 >> is returned. Otherwise, C<< 0 >> is returned. + +Parameters; + +=head3 port (optional, default 22) + +If C<< target >> is set, this is the TCP port number used to connect to the remote machine. + +=head3 password (optional) + +If C<< target >> is set, this is the password used to log into the remote system as the C<< remote_user >>. If it is not set, an attempt to connect without a password will be made (though this will usually fail). + +=head3 target (optional) + +If set, the file will be copied on the target machine. This must be either an IP address or a resolvable host name. + +=head3 remote_user (optional, default root) + +If C<< target >> is set, this is the user account that will be used when connecting to the remote system. + +=cut +sub manage_lvm_conf +{ + my $self = shift; + my $parameter = shift; + my $anvil = $self->parent; + my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3; + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Storage->manage_lvm_conf()" }}); + + my $password = defined $parameter->{password} ? $parameter->{password} : ""; + my $port = defined $parameter->{port} ? $parameter->{port} : ""; + my $remote_user = defined $parameter->{remote_user} ? $parameter->{remote_user} : "root"; + my $target = defined $parameter->{target} ? $parameter->{target} : ""; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + password => $anvil->Log->is_secure($password), + port => $port, + remote_user => $remote_user, + target => $target, + }}); + + my $body = $anvil->Storage->read_file({ + debug => $debug, + file => $anvil->data->{path}{configs}{'lvm.conf'}, + password => $password, + port => $port, + target => $target, + remote_user => $remote_user, + }); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { body => $body }}); + + if ($body eq "!!error!!") + { + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0254"}); + return(1); + } + + my $in_device = 0; + foreach my $line (split/\n/, $body) + { + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { line => $line }}); + next if $line =~ /^#/ or $line =~ /^\s+#/; + + if ($line =~ /^devices \{/) + { + $in_device = 1; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { in_device => $in_device }}); + } + if ($in_device) + { + $line =~ s/^\s+//; + if ($line =~ /^\}/) + { + $in_device = 0; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { in_device => $in_device }}); + last; + } + if ($line =~ /^filter = \[(.*?)\]/) + { + # Filter exists, we won't change it. + my $filter = $1; + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0594", variables => { filter => $filter }}); + return(0); + } + } + } + + # If I made it here, I need to add the filter. + $in_device = 0; + my $filter_added = 0; + my $new_body = ""; + my $filter_line = 'filter = [ "r|/dev/drbd*|" ]'; + foreach my $line (split/\n/, $body) + { + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { line => $line }}); + + if ($line =~ /^devices \{/) + { + $in_device = 1; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { in_device => $in_device }}); + } + if ($in_device) + { + if ($line =~ /^\}/) + { + $in_device = 0; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { in_device => $in_device }}); + + # If we didn't find where to inject the filter, do it now. + if (not $filter_added) + { + $new_body .= "\t".$filter_line."\n"; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { filter_line => $filter_line }}); + } + } + if (($line =~ /# filter = \[ "a\|\.\*\|" \]/) && (not $filter_added)) + { + # Add the filter here + $new_body .= $line."\n"; + $new_body .= "\t".$filter_line."\n"; + $filter_added = 1; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + filter_added => $filter_added, + filter_line => $filter_line, + }}); + next; + } + } + $new_body .= $line."\n"; + } + + # Write the file out. + my $error = $anvil->Storage->write_file({ + debug => $debug, + body => $new_body, + file => $anvil->data->{path}{configs}{'lvm.conf'}, + group => "root", + mode => "0644", + overwrite => 1, + backup => 1, + user => "root", + password => $password, + port => $port, + target => $target, + remote_user => $remote_user, + }); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 0, list => { error => $error }}); + + if ($error) + { + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0255"}); + return(1); + } + else + { + # Record that we updated the lvm.conf. + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0595", variables => { filter => $filter_line }}); + } + + return(0); +} + + =head2 move_file This moves a file, with a few additional checks like creating the target directory if it doesn't exist, aborting if the file already exists in the target, etc. It can move files on the local or a remote machine. diff --git a/scancore-agents/scan-drbd/scan-drbd b/scancore-agents/scan-drbd/scan-drbd index 2c27c6b2..295994f3 100755 --- a/scancore-agents/scan-drbd/scan-drbd +++ b/scancore-agents/scan-drbd/scan-drbd @@ -93,6 +93,10 @@ if ($anvil->DRBD->gather_data()) $anvil->nice_exit({exit_code => 2}); } +# Make sure that lvm.conf's filter of DRBD devices is in place. +$problem = $anvil->Storage->manage_lvm_conf(); +$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { problem => $problem }}); + read_last_scan($anvil); find_changes($anvil); diff --git a/share/words.xml b/share/words.xml index 084a91b7..47a6a22f 100644 --- a/share/words.xml +++ b/share/words.xml @@ -355,6 +355,8 @@ The error was: #!variable!error!# ======== + Failed to read the lvm.conf file. The reason why should be logged above. + Failed to write the lvm.conf file. The reason why should be logged above. @@ -745,6 +747,8 @@ It should be provisioned in the next minute or two. All machines are now available on the first BCN! One of the Striker dashboards has not yet updated network information in the database. We need this to know which IP to tell the peer to use to connect to us. We'll wait a moment and check again. The cluster still hasn't started. Calling startup again (will try once per minute). + Successfully added/confirmed the filter in lvm.conf. + Failed to add/confirmed the filter in lvm.conf! This should be corrected later by 'scan-drbd' though. Starting: [#!variable!program!#]. @@ -1432,6 +1436,8 @@ The file: [#!variable!file!#] needs to be updated. The difference is: Wiping any file system signatures and then deleting the logical volume: [#!variable!device_path!#]. The resource name: [#!variable!resource_name!#] was found, returning the first TCP port and minor number. The job: [#!variable!command!#] with UUID: [#!variable!job_uuid!#] is a start-time job, not running it now. + The lvm.conf already has the filter: [#!variable!filter!#], will not change it. + Updated the lvm.conf file to add the filter: [#!variable!filter!#] to prevent LVM from seeing the DRBD devices as LVM devices. The host name: [#!variable!target!#] does not resolve to an IP address. diff --git a/tools/striker-initialize-host b/tools/striker-initialize-host index b6f0c8be..3dc3cfc3 100755 --- a/tools/striker-initialize-host +++ b/tools/striker-initialize-host @@ -57,6 +57,7 @@ get_job_details($anvil); wait_for_access($anvil); set_host_name($anvil); add_repos($anvil); +configure_lvm($anvil); add_databases($anvil); update_progress($anvil, 100, "job_0047"); @@ -67,15 +68,40 @@ $anvil->nice_exit({exit_code => 0}); # Functions # ############################################################################################################# +# This configures filtering on LVM +sub configure_lvm +{ + my ($anvil) = @_; + + my $problem = $anvil->Storage->manage_lvm_conf({ + debug => 2, + password => $anvil->data->{data}{password}, + port => $anvil->data->{data}{ssh_port}, + target => $anvil->data->{data}{host_ip_address}, + remote_user => "root", + }) + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { problem => $problem }}); + if ($problem) + { + $anvil->data->{job}{progress} += 5; + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, 'print' => 1, key => "job_0274"}); + update_progress($anvil, $anvil->data->{job}{progress}, "job_0274"); + } + else + { + $anvil->data->{job}{progress} += 5; + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, 'print' => 1, key => "job_0273"}); + update_progress($anvil, $anvil->data->{job}{progress}, "job_0273"); + } + + return(0); +} + # Set the host name, if needed. sub set_host_name { my ($anvil) = @_; - ### TODO: Left off here; - ### - Validate host name - ### - Update progress values - ### - Set host_namectl if ((not defined $anvil->data->{data}{host_name}) or (not $anvil->data->{data}{host_name})) { return(0);