diff --git a/CMakeLists.txt b/CMakeLists.txt index 85734a085..040bc4ed6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -185,7 +185,6 @@ if (BUILD_CDC) endif() add_subdirectory(maxutils) -add_subdirectory(plugins) add_subdirectory(query_classifier) add_subdirectory(server) add_subdirectory(include/maxscale) diff --git a/Documentation/Changelog.md b/Documentation/Changelog.md index a362a0547..b2f90f0aa 100644 --- a/Documentation/Changelog.md +++ b/Documentation/Changelog.md @@ -17,7 +17,9 @@ by adding the `--rdns`-option to the command. * The following MariaDB-Monitor settings have been removed and cause a startup error if defined: `mysql51_replication`, `multimaster` and `allow_cluster_recovery`. The - setting `detect_replication_lag` is deprecated and is ignored. + setting `detect_replication_lag` is deprecated and ignored. +* `enforce_simple_topology`-setting added to MariaDB-Monitor. +* The mqfilter has been deprecated. For more details, please refer to: diff --git a/Documentation/Filters/RabbitMQ-Filter.md b/Documentation/Filters/RabbitMQ-Filter.md index 051323611..a2371d37c 100644 --- a/Documentation/Filters/RabbitMQ-Filter.md +++ b/Documentation/Filters/RabbitMQ-Filter.md @@ -2,6 +2,9 @@ ## Overview +The **mqfilter** has been deprecated in MaxScale 2.4 and it will be removed +in a future version of MaxScale. We advise against using it. + This filter is designed to extract queries and transform them into a canonical form e.g. `INSERT INTO database.table VALUES ("John Doe", "Downtown",100,50.0);` turns into `INSERT INTO database.table VALUES ("?", "?",?,?);`. The filter diff --git a/Documentation/Monitors/MariaDB-Monitor.md b/Documentation/Monitors/MariaDB-Monitor.md index 7afc24221..07543619b 100644 --- a/Documentation/Monitors/MariaDB-Monitor.md +++ b/Documentation/Monitors/MariaDB-Monitor.md @@ -30,6 +30,7 @@ Table of Contents * [auto_failover](#auto_failover) * [auto_rejoin](#auto_rejoin) * [switchover_on_low_disk_space](#switchover_on_low_disk_space) + * [enforce_simple_topology](#enforce_simple_topology) * [replication_user and replication_password](#replication_user-and-replication_password) * [failover_timeout and switchover_timeout](#failover_timeout-and-switchover_timeout) * [verify_master_failure and master_failure_timeout](#verify_master_failure-and-master_failure_timeout) @@ -644,6 +645,23 @@ must be defined for the monitor. switchover_on_low_disk_space=true ``` +#### `enforce_simple_topology` + +This setting tells the monitor to assume that the servers should be arranged in a +1-master-N-slaves topology and the monitor should try to keep it that way. If +`enforce_simple_topology` is enabled, the settings `assume_unique_hostnames`, +`auto_failover` and `auto_rejoin` are also activated regardless of their individual +settings. + +This setting also allows the monitor to perform a failover to a cluster where the master +server has not been seen [Running]. This is usually the case when the master goes down +before MaxScale is started. When using this feature, the monitor will guess the GTID +domain id of the master from the slaves. For reliable results, the GTID:s of the cluster +should be simple. +``` +enforce_simple_topology=true +``` + #### `replication_user` and `replication_password` The username and password of the replication user. These are given as the values diff --git a/Documentation/Release-Notes/MaxScale-2.4.0-Release-Notes.md b/Documentation/Release-Notes/MaxScale-2.4.0-Release-Notes.md index e845a79fe..0995f8dae 100644 --- a/Documentation/Release-Notes/MaxScale-2.4.0-Release-Notes.md +++ b/Documentation/Release-Notes/MaxScale-2.4.0-Release-Notes.md @@ -75,11 +75,29 @@ The `ndbclustermon` module has been removed. The `mmmon` module has been removed as the `mariadbmon` monitor largely does what it used to do. +### MariaDB-Monitor settings + +The following settings have been removed and cause a startup error +if defined: `mysql51_replication`, `multimaster` and `allow_cluster_recovery`. + ### `log_to_shm` The `log_to_shm` parameter that was removed in 2.3 will be treated as an unknown parameter in 2.4.0. +## Deprecated Features + +### `mqfilter` + +The `mqfilter` has been deprecated and it will be removed in a future version +of MaxScale. + +We advise against using it. + +### Nagios Plugins + +MaxScale no longer ships the example scripts and configuration files for Nagios. + ## New Features ### Clustrix Support @@ -289,6 +307,13 @@ is done directly from a remote master server. This skips the binlogrouter definition completely making the conversion process faster and more space efficient. +### `enforce_simple_topology` + +This MariaDB-Monitor setting allows the monitor greater freedom in managing the +backend servers. Please see +[MariaDB-Monitor documentation](../Monitors/MariaDB-Monitor.md#enforce_simple_topology) +for more information. + ## Bug fixes [Here is a list of bugs fixed in MaxScale 2.4.0.](https://jira.mariadb.org/issues/?jql=project%20%3D%20MXS%20AND%20issuetype%20%3D%20Bug%20AND%20status%20%3D%20Closed%20AND%20fixVersion%20%3D%202.4.0) diff --git a/Documentation/Routers/Avrorouter.md b/Documentation/Routers/Avrorouter.md index ce612a749..2a36834d6 100644 --- a/Documentation/Routers/Avrorouter.md +++ b/Documentation/Routers/Avrorouter.md @@ -24,6 +24,44 @@ streams from a database table. [TOC] +## Direct Replication Mode + +MaxScale 2.4.0 added a direct replication mode that connects the avrorouter +directly to a MariaDB server. This mode is an improvement over the binlogrouter +based replication as it provides a more space-efficient and faster conversion +process. + +To enable the direct replication mode, add either the `servers` or the `cluster` +parameter to the avrorouter service. The avrorouter will then use one of the +servers as the replication source. In this mode the `source` parameter is +ignored as there is no need for a source service. + +Here is a minimal avrorouter direct replication configuration: + +``` +[maxscale] +threads=auto + +[server1] +type=server +address=127.0.0.1 +port=3306 +protocol=MariaDBBackend + +[cdc-service] +type=service +router=avrorouter +servers=server1 +user=maxuser +password=maxpwd + +[cdc-listener] +type=listener +service=cdc-service +protocol=CDC +port=4001 +``` + ## Configuration For information about common service parameters, refer to the @@ -33,7 +71,8 @@ For information about common service parameters, refer to the #### `source` -The source for the binary logs. This is an optional parameter. +The source for the binary logs. This is an optional parameter and is ignored if +the router is configured in direct replication mode. **Note:** If the `source` parameter is defined the values for `binlogdir` and `filestem` are only read from the source service. This means that the diff --git a/include/maxscale/config.hh b/include/maxscale/config.hh index ac945045e..335a641e0 100644 --- a/include/maxscale/config.hh +++ b/include/maxscale/config.hh @@ -114,6 +114,7 @@ extern const char CN_CACHE_SIZE[]; extern const char CN_CACHE[]; extern const char CN_CLASSIFICATION[]; extern const char CN_CLASSIFY[]; +extern const char CN_CLUSTER[]; extern const char CN_CONNECTION_TIMEOUT[]; extern const char CN_DATA[]; extern const char CN_DEFAULT[]; diff --git a/maxscale-system-test/CMakeLists.txt b/maxscale-system-test/CMakeLists.txt index fb69b7855..ac3c9ab54 100644 --- a/maxscale-system-test/CMakeLists.txt +++ b/maxscale-system-test/CMakeLists.txt @@ -287,6 +287,9 @@ add_test_executable(mysqlmon_switchover_auto.cpp mysqlmon_switchover_auto mysqlm # MySQL Monitor series of failovers and rejoins add_test_executable(mysqlmon_failover_readonly.cpp mysqlmon_failover_readonly mysqlmon_failover_readonly LABELS mysqlmon REPL_BACKEND) +# MariaDB-Monitor enforce_simple_topology +add_test_executable(mysqlmon_enforce_simple.cpp mysqlmon_enforce_simple mysqlmon_enforce_simple LABELS mysqlmon REPL_BACKEND) + # MXS-1506: Delayed query retry # https://jira.mariadb.org/browse/MXS-1506 add_test_executable(mxs1506_delayed_retry.cpp mxs1506_delayed_retry mxs1506_delayed_retry LABELS readwritesplit REPL_BACKEND) diff --git a/maxscale-system-test/cnf/maxscale.cnf.template.kill_query b/maxscale-system-test/cnf/maxscale.cnf.template.kill_query index 6eaad58ca..5c8de6287 100755 --- a/maxscale-system-test/cnf/maxscale.cnf.template.kill_query +++ b/maxscale-system-test/cnf/maxscale.cnf.template.kill_query @@ -19,10 +19,8 @@ servers=###server_line### user=maxskysql password=skysql -[Read-Connection-Router-Slave] -type=service -router=readconnroute -router_options=slave -servers=###server_line### -user=maxskysql -password=skysql +[RW-Split-Listener] +type=listener +service=RW-Split-Router +protocol=MySQLClient +port=4006 diff --git a/maxscale-system-test/cnf/maxscale.cnf.template.mysqlmon_enforce_simple b/maxscale-system-test/cnf/maxscale.cnf.template.mysqlmon_enforce_simple new file mode 100644 index 000000000..502475200 --- /dev/null +++ b/maxscale-system-test/cnf/maxscale.cnf.template.mysqlmon_enforce_simple @@ -0,0 +1,65 @@ +[maxscale] +threads=###threads### + +[MariaDB-Monitor] +type=monitor +module=mariadbmon +servers= server1, server2, server3, server4 +user=maxskysql +password= skysql +monitor_interval=1000 +failcount=2 +enforce_simple_topology=true +replication_user=repl +replication_password=repl +backend_connect_timeout=10 +backend_read_timeout=10 +backend_write_timeout=10 + +[RW-Split-Router] +type=service +router= readwritesplit +servers=server1, server2, server3, server4 +user=maxskysql +password=skysql + +[RW-Split-Listener] +type=listener +service=RW-Split-Router +protocol=MySQLClient +port=4006 + +[CLI] +type=service +router=cli + +[CLI-Listener] +type=listener +service=CLI +protocol=maxscaled +socket=default + +[server1] +type=server +address=###node_server_IP_1### +port=###node_server_port_1### +protocol=MySQLBackend + +[server2] +type=server +address=###node_server_IP_2### +port=###node_server_port_2### +protocol=MySQLBackend + +[server3] +type=server +address=###node_server_IP_3### +port=###node_server_port_3### +protocol=MySQLBackend + +[server4] +type=server +address=###node_server_IP_4### +port=###node_server_port_4### +protocol=MySQLBackend + diff --git a/maxscale-system-test/mysqlmon_enforce_simple.cpp b/maxscale-system-test/mysqlmon_enforce_simple.cpp new file mode 100644 index 000000000..2d021fd72 --- /dev/null +++ b/maxscale-system-test/mysqlmon_enforce_simple.cpp @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2019 MariaDB Corporation Ab + * + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file and at www.mariadb.com/bsl11. + * + * Change Date: 2023-01-01 + * + * On the date above, in accordance with the Business Source License, use + * of this software will be governed by version 2 or later of the General + * Public License. + */ + +#include "testconnections.h" +#include +#include + +using std::string; +using std::cout; + +int get_master_server_id(TestConnections& test) +{ + MYSQL* conn = test.maxscales->open_rwsplit_connection(0); + int id = -1; + char str[1024]; + + if (find_field(conn, "SELECT @@server_id, @@last_insert_id;", "@@server_id", str) == 0) + { + id = atoi(str); + } + + mysql_close(conn); + return id; +} + +int main(int argc, char** argv) +{ + Mariadb_nodes::require_gtid(true); + TestConnections::skip_maxscale_start(true); + + TestConnections test(argc, argv); + + if (test.repl->N < 4) + { + test.expect(false, "This test requires at least 4 backends."); + return test.global_result; + } + + test.repl->connect(); + auto server_ids = test.repl->get_all_server_ids(); + + // Stop the master and the last slave, then start MaxScale. + int master_ind = 0; + int last_slave_ind = 3; + + string master_name = mxb::string_printf("server%i", master_ind + 1); + string slave_name = mxb::string_printf("server%i", last_slave_ind + 1); + + test.tprintf("Stopping %s and %s.", master_name.c_str(), slave_name.c_str()); + test.repl->stop_node(master_ind); + test.repl->stop_node(last_slave_ind); + + test.tprintf("Starting MaxScale"); + test.start_maxscale(0); + + sleep(3); + test.maxscales->wait_for_monitor(3); + + test.log_includes(0, "Performing automatic failover"); + int new_master_id = get_master_server_id(test); + int expected_id1 = server_ids[1]; + int expected_id2 = server_ids[2]; + test.expect(new_master_id == expected_id1 || new_master_id == expected_id2, + "Unexpected master server id. Got %i when %i or %i was expected.", + new_master_id, expected_id1, expected_id2); + + if (test.ok()) + { + // Restart server4, check that it rejoins. + test.repl->start_node(last_slave_ind, (char*)""); + test.maxscales->wait_for_monitor(2); + + auto states = test.maxscales->get_server_status(slave_name.c_str()); + test.expect(states.count("Slave") == 1, "%s is not replicating as it should.", slave_name.c_str()); + } + + if (test.ok()) + { + // Finally, bring back old master and swap to it. + test.repl->start_node(master_ind, (char*)""); + test.maxscales->wait_for_monitor(2); + + test.tprintf("Switching back old master %s.", master_name.c_str()); + string switchover = "call command mariadbmon switchover MariaDB-Monitor " + master_name; + test.maxscales->execute_maxadmin_command(0, switchover.c_str()); + test.maxscales->wait_for_monitor(2); + new_master_id = get_master_server_id(test); + test.expect(new_master_id == server_ids[master_ind], "Switchover to original master failed."); + } + return test.global_result; +} diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt deleted file mode 100644 index ebff248a2..000000000 --- a/plugins/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -install_custom_file(nagios/check_maxscale_monitors.pl ${MAXSCALE_SHAREDIR}/plugins/nagios/ core) -install_custom_file(nagios/check_maxscale_resources.pl ${MAXSCALE_SHAREDIR}/plugins/nagios/ core) -install_custom_file(nagios/check_maxscale_threads.pl ${MAXSCALE_SHAREDIR}/plugins/nagios/ core) -install_custom_file(nagios/maxscale_commands.cfg ${MAXSCALE_SHAREDIR}/plugins/nagios/ core) -install_custom_file(nagios/server1.cfg ${MAXSCALE_SHAREDIR}/plugins/nagios/ core) diff --git a/plugins/nagios/check_maxscale_monitors.pl b/plugins/nagios/check_maxscale_monitors.pl deleted file mode 100755 index 0475b37ef..000000000 --- a/plugins/nagios/check_maxscale_monitors.pl +++ /dev/null @@ -1,207 +0,0 @@ -#!/usr/bin/perl -# -# Copyright (c) 2016 MariaDB Corporation Ab -# -# Use of this software is governed by the Business Source License included -# in the LICENSE.TXT file and at www.mariadb.com/bsl11. -# -# Change Date: 2023-01-01 -# -# On the date above, in accordance with the Business Source License, use -# of this software will be governed by version 2 or later of the General -# Public License. -# - -# -# @file check_maxscale_monitors.pl - Nagios plugin for MaxScale monitors -# -# Revision History -# -# Date Who Description -# 06-03-2015 Massimiliano Pinto Initial implementation -# 20-05-2016 Massimiliano Pinto Maxadmin can connect with UNIX domain socket -# in maxscale server only. -# Commands changed with "ssh -i /somepath/id_rsa user@maxscalehost maxadmin ...." -# - -#use strict; -#use warnings; -use Getopt::Std; - -my %opts; -my $TIMEOUT = 15; # we don't want to wait long for a response -my %ERRORS = ('UNKNOWN' , '3', - 'OK', '0', - 'WARNING', '1', - 'CRITICAL', '2'); - -my $curr_script = "$0"; -$curr_script =~ s{.*/}{}; - -sub usage { - my $rc = shift; - - print <<"EOF"; -MaxScale monitor checker plugin for Nagios - -Usage: $curr_script [-r ] [-H ] [-u ] [-S ] [-m ] [-h] - -Options: - -r = monitors - -h = provide this usage message - -H = which host to connect to with SSH - -u = username to connect to maxscale host via SSH (same user is used for maxadmin authentication) - -i = identity file to use for at - -m = /path/to/maxadmin - -S = UNIX socket path between maxadmin and maxscale (default is /tmp/maxadmin.sock) -EOF - exit $rc; -} - -%opts =( - 'r' => 'monitors', # default maxscale resource to show - 'h' => '', # give help - 'H' => 'localhost', # host - 'u' => 'root', # username - 'm' => '/usr/local/mariadb-maxscale/bin/maxadmin', # maxadmin -); - -my $MAXADMIN_DEFAULT = $opts{'m'}; - -getopts('r:hH:u:i:S:m:', \%opts) - or usage( $ERRORS{"UNKNOWN"} ); -usage( $ERRORS{'OK'} ) if $opts{'h'}; - -my $MAXADMIN_RESOURCE = $opts{'r'}; -my $MAXADMIN = $opts{'m'}; -my $MAXADMIN_SOCKET = $opts{'S'}; -my $MAXSCALE_HOST_IDENTITY_FILE = $opts{'i'}; - -if (!defined $MAXSCALE_HOST_IDENTITY_FILE || length($MAXSCALE_HOST_IDENTITY_FILE) == 0) { - die "$curr_script: ssh identity file for user $opts{'u'} is required"; -} - -if (!defined $MAXADMIN || length($MAXADMIN) == 0) { - $MAXADMIN = $MAXADMIN_DEFAULT; -} -if (defined $MAXADMIN_SOCKET && length($MAXADMIN_SOCKET) > 0) { - $MAXADMIN_SOCKET = ' -S ' . $MAXADMIN_SOCKET; -} else { - $MAXADMIN_SOCKET = ''; -} -# Just in case of problems, let's not hang Nagios -$SIG{'ALRM'} = sub { - print ("UNKNOWN: No response from MaxScale server (alarm)\n"); - exit $ERRORS{"UNKNOWN"}; -}; -alarm($TIMEOUT); - -my $command = "ssh -i " . $MAXSCALE_HOST_IDENTITY_FILE . ' ' . $opts{'u'} . '@' . $opts{'H'} . ' ' . $MAXADMIN . $MAXADMIN_SOCKET . ' ' . " show " . $MAXADMIN_RESOURCE; - -# -# print "maxadmin command: $command\n"; -# - -open (MAXSCALE, "$command 2>&1 |") - or die "can't get data out of Maxscale: $!"; - -my $hostname = qx{hostname}; chomp $hostname; -my $waiting_backend = 0; -my $start_output = 0; -my $n_monitors = 0; -my $performance_data=""; - - -my $resource_type = $MAXADMIN_RESOURCE; -chop($resource_type); - -my $resource_match = ucfirst("$resource_type Name"); - -my $this_key; -my %monitor_data; - -while ( ) { - chomp; - - if ( /(Failed|Unable) to connect to MaxScale/ ) { - printf "CRITICAL: $_\n"; - close(MAXSCALE); - exit(2); - } - - if ( /^Monitor\:/ ) { - $n_monitors++; - $this_key = 'monitor' . $n_monitors; - $monitor_data{$this_key} = { - '1name'=> '', - '2state' => '', - '3servers' => '', - '4interval' => '', - '5repl_lag' => '' - }; - - next; - } - - next if (/--/ || $_ eq ''); - - if ( /Name\:/) { - - my $str; - my $perf_line; - my @data_row = split(':', $_); - my $name = $data_row[1]; - $name =~ s/^\s+|\s+$//g; - $monitor_data{$this_key}{'1name'}=$name; - - } - - if (/(State\:\s+)(.*)/) { - $monitor_data{$this_key}{'2state'}=$2; - } - - if ( /Monitored servers\:/ ) { - my $server_list; - my @data_row = split(':', $_); - shift(@data_row); - foreach my $name (@data_row) { - $name =~ s/^\s+|\s+$//g; - $name =~ s/ //g; - $server_list .= $name . ":"; - } - chop($server_list); - $monitor_data{$this_key}{'3servers'}=$server_list; - } - - if ( /(Sampling interval\:)\s+(\d+) milliseconds/ ) { - $monitor_data{$this_key}{'4interval'}=$2; - } - - if ( /Replication lag\:/ ) { - my @data_row = split(':', $_); - my $name = $data_row[1]; - $name =~ s/^\s+|\s+$//g; - $monitor_data{$this_key}{'5repl_lag'}=$name; - } -} - -for my $key ( sort(keys %monitor_data) ) { - my $local_hash = {}; - $performance_data .= " $key="; - $local_hash = $monitor_data{$key}; - my %new_hash = %$local_hash; - foreach my $key (sort (keys (%new_hash))) { - $performance_data .= $new_hash{$key} . ";"; - } - chop($performance_data); -} - -if ($n_monitors) { - printf "OK: %d monitors found |%s\n", $n_monitors, $performance_data; - close(MAXSCALE); - exit 0; -} else { - printf "WARNING: 0 monitors found\n"; - close(MAXSCALE); - exit 1; -} diff --git a/plugins/nagios/check_maxscale_resources.pl b/plugins/nagios/check_maxscale_resources.pl deleted file mode 100755 index a3598a1ff..000000000 --- a/plugins/nagios/check_maxscale_resources.pl +++ /dev/null @@ -1,191 +0,0 @@ -#!/usr/bin/perl -# -# Copyright (c) 2016 MariaDB Corporation Ab -# -# Use of this software is governed by the Business Source License included -# in the LICENSE.TXT file and at www.mariadb.com/bsl11. -# -# Change Date: 2023-01-01 -# -# On the date above, in accordance with the Business Source License, use -# of this software will be governed by version 2 or later of the General -# Public License. -# - -# -# @file check_maxscale_resources.pl - Nagios plugin for MaxScale resources -# -# Revision History -# -# Date Who Description -# 06-03-2015 Massimiliano Pinto Initial implementation -# 20-05-2016 Massimiliano Pinto Maxadmin can connect with UNIX domain socket -# in maxscale server only. -# Commands changed with "ssh -i /somepath/id_rsa user@maxscalehost maxadmin ...." -# - -#use strict; -#use warnings; -use Getopt::Std; - -my %opts; -my $TIMEOUT = 15; # we don't want to wait long for a response -my %ERRORS = ('UNKNOWN' , '3', - 'OK', '0', - 'WARNING', '1', - 'CRITICAL', '2'); - -my $curr_script = "$0"; -$curr_script =~ s{.*/}{}; - -sub usage { - my $rc = shift; - - print <<"EOF"; -MaxScale monitor checker plugin for Nagios - -Usage: $curr_script [-r ] [-H ] [-u ] [-S ] [-m ] [-h] - -Options: - -r = modules|services|filters|listeners|servers|sessions - -h = provide this usage message - -H = which host to connect to with SSH - -u = username to connect to maxscale host via SSH (same user is used for maxadmin authentication) - -i = identity file to use for at - -m = /path/to/maxadmin - -S = UNIX socket path between maxadmin and maxscale (default is /tmp/maxadmin.sock) -EOF - exit $rc; -} - -%opts =( - 'r' => 'services', # default maxscale resource to show - 'h' => '', # give help - 'H' => 'localhost', # host - 'u' => 'root', # username - 'm' => '/usr/local/mariadb-maxscale/bin/maxadmin', # maxadmin -); - -my $MAXADMIN_DEFAULT = $opts{'m'}; - -getopts('r:hH:u:i:S:m:', \%opts) - or usage( $ERRORS{"UNKNOWN"} ); -usage( $ERRORS{'OK'} ) if $opts{'h'}; - -my $MAXADMIN_RESOURCE = $opts{'r'}; -my $MAXADMIN = $opts{'m'}; -my $MAXADMIN_SOCKET = $opts{'S'}; -my $MAXSCALE_HOST_IDENTITY_FILE = $opts{'i'}; - -if (!defined $MAXSCALE_HOST_IDENTITY_FILE || length($MAXSCALE_HOST_IDENTITY_FILE) == 0) { - die "$curr_script: ssh identity file for user $opts{'u'} is required"; -} - -if (!defined $MAXADMIN || length($MAXADMIN) == 0) { - $MAXADMIN = $MAXADMIN_DEFAULT; -} - -if (defined $MAXADMIN_SOCKET && length($MAXADMIN_SOCKET) > 0) { - $MAXADMIN_SOCKET = ' -S ' . $MAXADMIN_SOCKET; -} else { - $MAXADMIN_SOCKET = ''; -} -# Just in case of problems, let's not hang Nagios -$SIG{'ALRM'} = sub { - print ("UNKNOWN: No response from MaxScale server (alarm)\n"); - exit $ERRORS{"UNKNOWN"}; -}; -alarm($TIMEOUT); - -my $command = "ssh -i " . $MAXSCALE_HOST_IDENTITY_FILE . ' ' . $opts{'u'} . '@' . $opts{'H'} . ' ' . $MAXADMIN . $MAXADMIN_SOCKET . ' ' . " list " . $MAXADMIN_RESOURCE; - -# -# print "maxadmin command: $command\n"; -# - -open (MAXSCALE, "$command 2>&1 |") or die "can't get data out of Maxscale: $!"; - -my $hostname = qx{hostname}; chomp $hostname; - -my $start_output = 0; -my $n_resources = 0; -my $performance_data=""; - - -my $resource_type = $MAXADMIN_RESOURCE; -chop($resource_type); - -my $resource_match = ucfirst("$resource_type Name"); - -if ($resource_type eq "listener") { - $resource_match = "Name"; -} -if ($resource_type eq "filter") { - $resource_match = "Filter"; -} -if ($resource_type eq "server") { - $resource_match = "Server"; -} -if ($resource_type eq "session") { - $resource_match = "Session"; -} - -# -# print "Matching [$resource_match]\n"; -# - -while ( ) { - chomp; - - if ( /(Failed|Unable) to connect to MaxScale/ ) { - printf "CRITICAL: $_\n"; - close(MAXSCALE); - exit(2); - } - - if ( ! /^$resource_match/ ) { - } else { - $start_output = 1; - next; - } - if ($start_output) { - next if (/--/ || $_ eq ''); - $n_resources++; - if ($resource_type ne "session") { - my $str; - my $perf_line; - my @data_row = split('\|', $_); - $performance_data .= "$MAXADMIN_RESOURCE$n_resources="; - foreach my $val (@data_row) { - $str = $val; - $str =~ s/^\s+|\s+$//g; - $perf_line .= $str . ';'; - } - chop($perf_line); - $performance_data .= $perf_line . ' '; - } - } -} - -chop($performance_data); - -############################################### -# -# print OK or CRITICAL based on $n_resources -# -################################################ - -if ($n_resources) { - if ($performance_data eq '') { - printf "OK: %d $MAXADMIN_RESOURCE found\n", $n_resources; - } else { - printf "OK: %d $MAXADMIN_RESOURCE found | %s\n", $n_resources, $performance_data; - } - close(MAXSCALE); - exit 0; -} else { - printf "CRITICAL: 0 $MAXADMIN_RESOURCE found\n"; - close(MAXSCALE); - exit 2; -} - diff --git a/plugins/nagios/check_maxscale_threads.pl b/plugins/nagios/check_maxscale_threads.pl deleted file mode 100755 index b21fbbc55..000000000 --- a/plugins/nagios/check_maxscale_threads.pl +++ /dev/null @@ -1,249 +0,0 @@ -#!/usr/bin/perl -# -# Copyright (c) 2016 MariaDB Corporation Ab -# -# Use of this software is governed by the Business Source License included -# in the LICENSE.TXT file and at www.mariadb.com/bsl11. -# -# Change Date: 2023-01-01 -# -# On the date above, in accordance with the Business Source License, use -# of this software will be governed by version 2 or later of the General -# Public License. -# - -# -# @file check_maxscale_threads.pl - Nagios plugin for MaxScale threads and events -# -# Revision History -# -# Date Who Description -# 06-03-2015 Massimiliano Pinto Initial implementation -# 20-05-2016 Massimiliano Pinto Maxadmin can connect with UNIX domain socket -# in maxscale server only. -# Commands changed with "ssh -i /somepath/id_rsa user@maxscalehost maxadmin ...." -# - -#use strict; -#use warnings; -use Getopt::Std; - -my %opts; -my $TIMEOUT = 15; # we don't want to wait long for a response -my %ERRORS = ('UNKNOWN' , '3', - 'OK', '0', - 'WARNING', '1', - 'CRITICAL', '2'); - -my $curr_script = "$0"; -$curr_script =~ s{.*/}{}; - -sub usage { - my $rc = shift; - - print <<"EOF"; -MaxScale monitor checker plugin for Nagios - -Usage: $curr_script [-r ] [-H ] [-u ] [-S ] [-m ] [-h] - -Options: - -r = threads - -h = provide this usage message - -H = which host to connect to with SSH - -u = username to connect to maxscale host via SSH (same user is used for maxadmin authentication) - -i = identity file to use for at - -m = /path/to/maxadmin - -S = UNIX socket path between maxadmin and maxscale (default is /tmp/maxadmin.sock) -EOF - exit $rc; -} - -%opts =( - 'r' => 'threads', # default maxscale resource to show - 'h' => '', # give help - 'H' => 'localhost', # host - 'u' => 'root', # username - 'm' => '/usr/local/mariadb-maxscale/bin/maxadmin', # maxadmin -); - -my $MAXADMIN_DEFAULT = $opts{'m'}; - -getopts('r:hH:u:i:S:m:', \%opts) - or usage( $ERRORS{"UNKNOWN"} ); -usage( $ERRORS{'OK'} ) if $opts{'h'}; - -my $MAXADMIN_RESOURCE = $opts{'r'}; -my $MAXADMIN = $opts{'m'}; -my $MAXADMIN_SOCKET = $opts{'S'}; -my $MAXSCALE_HOST_IDENTITY_FILE = $opts{'i'}; - -if (!defined $MAXSCALE_HOST_IDENTITY_FILE || length($MAXSCALE_HOST_IDENTITY_FILE) == 0) { - die "$curr_script: ssh identity file for user $opts{'u'} is required"; -} - -if (!defined $MAXADMIN || length($MAXADMIN) == 0) { - $MAXADMIN = $MAXADMIN_DEFAULT; -} - -if (defined $MAXADMIN_SOCKET && length($MAXADMIN_SOCKET) > 0) { - $MAXADMIN_SOCKET = ' -S ' . $MAXADMIN_SOCKET; -} else { - $MAXADMIN_SOCKET = ''; -} -# Just in case of problems, let's not hang Nagios -$SIG{'ALRM'} = sub { - print ("UNKNOWN: No response from MaxScale server (alarm)\n"); - exit $ERRORS{"UNKNOWN"}; -}; -alarm($TIMEOUT); - -my $command = "ssh -i " . $MAXSCALE_HOST_IDENTITY_FILE . ' ' . $opts{'u'} . '@' . $opts{'H'} . ' ' . $MAXADMIN . $MAXADMIN_SOCKET . ' ' . " show " . $MAXADMIN_RESOURCE; - -# -# print "maxadmin command: $command\n"; -# - -open (MAXSCALE, "$command 2>&1 |") or die "can't get data out of Maxscale: $!"; - -my $hostname = qx{hostname}; chomp $hostname; -my $start_output = 0; -my $n_threads = 0; -my $p_threads = 0; -my $performance_data=""; - - -my $resource_type = $MAXADMIN_RESOURCE; -chop($resource_type); - -my $resource_match = ucfirst("$resource_type Name"); - -my $historic_thread_load_average = 0; -my $current_thread_load_average = 0; - -my %thread_data; -my %event_data; - -my $start_queue_len = 0; - -while ( ) { - chomp; - - if ( /(Failed|Unable) to connect to MaxScale/ ) { - printf "CRITICAL: $_\n"; - close(MAXSCALE); - exit(2); - } - - if ( /Historic Thread Load Average/) { - my $str; - my @data_row = split(':', $_); - foreach my $val (@data_row) { - $str = $val; - $str =~ s/^\s+|\s+$//g; - } - chop($str); - $historic_thread_load_average = $str; - } - - if (/Current Thread Load Average/) { - my $str; - my @data_row = split(':', $_); - foreach my $val (@data_row) { - $str = $val; - $str =~ s/^\s+|\s+$//g; - } - chop($str); - $current_thread_load_average = $str; - } - - if (/Minute Average/) { - my $str; - my $in_str; - my @data_row = split(',', $_); - foreach my $val (@data_row) { - my ($i,$j)= split(':', $val); - $i =~ s/^\s+|\s+$//g; - $j =~ s/^\s+|\s+$//g; - if ($start_queue_len) { - $event_data{$i} = $j; - } else { - $thread_data{$i} = $j; - } - } - } - - if ( /Pending event queue length averages/) { - $start_queue_len = 1; - next; - } - - if (/^\s+ID/ ) { - $start_output = 1; - next; - } - - if ($start_output && /^\s+\d/) { - $n_threads++; - if (/Processing/) { - $p_threads++; - } - } -} - -close(MAXSCALE); - -$command = "ssh -i " . $MAXSCALE_HOST_IDENTITY_FILE . ' ' . $opts{'u'} . '@' . $opts{'H'} . ' ' . $MAXADMIN . $MAXADMIN_SOCKET . ' ' . " show epoll"; - -open (MAXSCALE, "$command 2>&1 |") or die "can't get data out of Maxscale: $!"; - -my $queue_len = 0; - -while ( ) { - chomp; - - if ( /(Failed|Unable) to connect to MaxScale/ ) { - printf "CRITICAL: $_\n"; - close(MAXSCALE); - exit(2); - } - - if ( ! /Current event queue length/ ) { - next; - } else { - my $str; - my @data_row = split(':', $_); - foreach my $val (@data_row) { - $str = $val; - $str =~ s/^\s+|\s+$//g; - } - $queue_len = $str; - - last; - } -} - -my $performance_data_thread = ""; -my $performance_data_event = ""; - -my $in_str; -my $in_key; -my $in_val; - -my @new_thread_array = @thread_data{'15 Minute Average', '5 Minute Average', '1 Minute Average'}; -my @new_event_array = @event_data{'15 Minute Average', '5 Minute Average', '1 Minute Average'}; - -$performance_data_thread = join(';', @new_thread_array); -$performance_data_event = join(';', @new_event_array); - -$performance_data .= "threads=$historic_thread_load_average;$current_thread_load_average avg_threads=$performance_data_thread avg_events=$performance_data_event"; - -if (($p_threads < $n_threads) || ($n_threads == 1)) { - printf "OK: Processing threads: %d/%d Events: %d | $performance_data\n", $p_threads, $n_threads, $queue_len; - close(MAXSCALE); - exit 0; -} else { - printf "WARNING: Processing threads: %d/%d Events: %d | $performance_data\n", $p_threads, $n_threads, $queue_len; - close(MAXSCALE); - exit 1; -} - diff --git a/plugins/nagios/maxscale_commands.cfg b/plugins/nagios/maxscale_commands.cfg deleted file mode 100644 index da480fc18..000000000 --- a/plugins/nagios/maxscale_commands.cfg +++ /dev/null @@ -1,32 +0,0 @@ -############################################################################### -# MAXSCALE_COMMANDS.CFG - SAMPLE COMMAND DEFINITIONS FOR NAGIOS 3.5.1 -# -# Massimiliano Pinto -# Last Modified: 06-03-2015 -# -# NOTES: This config file provides you with some example command definitions -# that you can reference in host, service, and contact definitions. -# -# You don't need to keep commands in a separate file from your other -# object definitions. This has been done just to make things easier to -# understand. -# -############################################################################### - -# check maxscale monitors -define command{ - command_name check_maxscale_monitors - command_line $USER1$/check_maxscale_monitors.pl -H $HOSTADDRESS$ -u $ARG1$ -i $ARG2$ -r $ARG3$ -S $ARG4$ -m $ARG5$ -} - -# check maxscale threads -define command{ - command_name check_maxscale_threads - command_line $USER1$/check_maxscale_threads.pl -H $HOSTADDRESS$ -u $ARG1$ -i $ARG2$ -r $ARG3$ -S $ARG4$ -m $ARG5$ -} - -# check maxscale resource (listeners, services, etc) -define command{ - command_name check_maxscale_resource - command_line $USER1$/check_maxscale_resources.pl -H $HOSTADDRESS$ -u $ARG1$ -i $ARG2$ -r $ARG3$ -S $ARG4$ -m $ARG5$ -} diff --git a/plugins/nagios/server1.cfg b/plugins/nagios/server1.cfg deleted file mode 100644 index 2571f6ea0..000000000 --- a/plugins/nagios/server1.cfg +++ /dev/null @@ -1,111 +0,0 @@ - -############################################################################### -############################################################################### -# -# HOST DEFINITION -# -############################################################################### -############################################################################### - -# Define a host for the remote machine - -define host{ - use linux-server ; Name of host template to use - ; This host definition will inherit all variables that are defined - ; in (or inherited by) the linux-server host template definition. - host_name server1 - alias server1 - address xxx.xxx.xxx.xxx - } - - - -############################################################################### -############################################################################### -# -# HOST GROUP DEFINITION -# -############################################################################### -############################################################################### - -# Define an optional hostgroup for Linux machines - -define hostgroup{ - hostgroup_name linux-real-servers ; The name of the hostgroup - alias Linux Real Servers ; Long name of the group - members server1 ; Comma separated list of hosts that belong to this group - } - - - -# Check MaxScale modules, on the remote machine. -define service{ - use local-service ; Name of service template to use - host_name server1 - service_description MaxScale_modules - check_command check_maxscale_resource!maxscale!/ssh/maxscale_host/id_rsa!modules - notifications_enabled 0 - } - -# Check MaxScale services, on the remote machine. -define service{ - use local-service ; Name of service template to use - host_name server1 - service_description MaxScale_services - check_command check_maxscale_resource!maxscale!/ssh/maxscale_host/id_rsa!services - notifications_enabled 0 - } - -# Check MaxScale listeners, on the remote machine. -define service{ - use local-service ; Name of service template to use - host_name server1 - service_description MaxScale_listeners - check_command check_maxscale_resource!maxscale!/ssh/maxscale_host/id_rsa!listeners - notifications_enabled 0 - } - -# Check MaxScale servers, on the remote machine. -define service{ - use local-service ; Name of service template to use - host_name server1 - service_description MaxScale_servers - check_command check_maxscale_resource!maxscale!/ssh/maxscale_host/id_rsa!servers - notifications_enabled 0 - } - -# Check MaxScale sessions, on the remote machine. -define service{ - use local-service ; Name of service template to use - host_name server1 - service_description MaxScale_sessions - check_command check_maxscale_resource!maxscale!/ssh/maxscale_host/id_rsa!sessions - notifications_enabled 0 - } - -# Check MaxScale filters, on the remote machine. -define service{ - use local-service ; Name of service template to use - host_name server1 - service_description MaxScale_filters - check_command check_maxscale_resource!maxscale!/ssh/maxscale_host/id_rsa!filters - notifications_enabled 0 - } - -# Check MaxScale monitors, on the remote machine. -define service{ - use local-service ; Name of service template to use - host_name server1 - service_description MaxScale_monitors - check_command check_maxscale_monitors!maxscale!/ssh/maxscale_host/id_rsa!monitors!/tmp/maxadmin.sock - notifications_enabled 0 - } - -# Define a service to check Script on the remote machine, with maxadmin path -define service{ - use local-service ; Name of service template to use - host_name server1 - service_description MaxScale_threads - check_command check_maxscale_threads!maxscale!/ssh/maxscale_host/id_rsa!threads!/tmp/maxadmin.sock!/usr/bin/maxadmin - notifications_enabled 0 - } diff --git a/server/modules/authenticator/PAM/PAMAuth/pam_client_session.cc b/server/modules/authenticator/PAM/PAMAuth/pam_client_session.cc index 4751f1240..673fe475b 100644 --- a/server/modules/authenticator/PAM/PAMAuth/pam_client_session.cc +++ b/server/modules/authenticator/PAM/PAMAuth/pam_client_session.cc @@ -112,7 +112,7 @@ PamClientSession* PamClientSession::create(const PamInstance& inst) } PamClientSession* rval = NULL; - if (!error && ((rval = new(std::nothrow) PamClientSession(dbhandle, inst)) == NULL)) + if (!error && ((rval = new (std::nothrow) PamClientSession(dbhandle, inst)) == NULL)) { error = true; } diff --git a/server/modules/authenticator/PAM/PAMAuth/pam_instance.cc b/server/modules/authenticator/PAM/PAMAuth/pam_instance.cc index 8103dc72e..34b2e8c8f 100644 --- a/server/modules/authenticator/PAM/PAMAuth/pam_instance.cc +++ b/server/modules/authenticator/PAM/PAMAuth/pam_instance.cc @@ -56,8 +56,8 @@ PamInstance* PamInstance::create(char** options) bool error = false; /* This handle may be used from multiple threads, set full mutex. */ sqlite3* dbhandle = NULL; - int db_flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE - | SQLITE_OPEN_SHAREDCACHE | SQLITE_OPEN_FULLMUTEX; + int db_flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | + SQLITE_OPEN_SHAREDCACHE | SQLITE_OPEN_FULLMUTEX; const char* filename = pam_db_fname.c_str(); if (sqlite3_open_v2(filename, &dbhandle, db_flags, NULL) != SQLITE_OK) { @@ -74,7 +74,7 @@ PamInstance* PamInstance::create(char** options) error = true; } - char* err = NULL; + char *err = NULL; if (!error && sqlite3_exec(dbhandle, drop_sql.c_str(), NULL, NULL, &err) != SQLITE_OK) { MXS_ERROR("Failed to drop table: '%s'", err); @@ -88,9 +88,9 @@ PamInstance* PamInstance::create(char** options) error = true; } - PamInstance* instance = NULL; - if (!error - && ((instance = new(std::nothrow) PamInstance(dbhandle, pam_db_fname, pam_table_name)) == NULL)) + PamInstance *instance = NULL; + if (!error && + ((instance = new (std::nothrow) PamInstance(dbhandle, pam_db_fname, pam_table_name)) == NULL)) { error = true; } diff --git a/server/modules/filter/mqfilter/mqfilter.cc b/server/modules/filter/mqfilter/mqfilter.cc index 7caff34dc..8185cf321 100644 --- a/server/modules/filter/mqfilter/mqfilter.cc +++ b/server/modules/filter/mqfilter/mqfilter.cc @@ -570,6 +570,9 @@ char** parse_optstr(const char* str, const char* tok, int* szstore) */ static MXS_FILTER* createInstance(const char* name, MXS_CONFIG_PARAMETER* params) { + MXS_WARNING("The mqfilter has been DEPRECATED in MaxScale 2.4 " + "and it will be removed in a future release of MaxScale."); + MQ_INSTANCE* my_instance = static_cast(MXS_CALLOC(1, sizeof(MQ_INSTANCE))); if (my_instance) diff --git a/server/modules/monitor/clustrixmon/clustrixmonitor.cc b/server/modules/monitor/clustrixmon/clustrixmonitor.cc index 2316988d8..b5e1c1e45 100644 --- a/server/modules/monitor/clustrixmon/clustrixmonitor.cc +++ b/server/modules/monitor/clustrixmon/clustrixmonitor.cc @@ -178,11 +178,16 @@ sqlite3* open_or_create_db(const std::string& path) } else { - MXS_ERROR("Opening/creating the sqlite3 database %s failed: %s", - path.c_str(), sqlite3_errstr(rv)); + if (pDb) + { + // Memory allocation failure is explained by the caller. Don't close the handle, as the + // caller will still use it even if open failed!! + MXS_ERROR("Opening/creating the sqlite3 database %s failed: %s", + path.c_str(), sqlite3_errmsg(pDb)); + } MXS_ERROR("Could not open sqlite3 database for storing information " "about dynamically detected Clustrix nodes. The Clustrix " - "monitor will remain dependant upon statically defined " + "monitor will remain dependent upon statically defined " "bootstrap nodes."); } diff --git a/server/modules/routing/avrorouter/avro.cc b/server/modules/routing/avrorouter/avro.cc index 54e33406a..68b836474 100644 --- a/server/modules/routing/avrorouter/avro.cc +++ b/server/modules/routing/avrorouter/avro.cc @@ -133,7 +133,7 @@ Avro::Avro(SERVICE* service, MXS_CONFIG_PARAMETER* params, SERVICE* source, SRow , handler(service, handler, params->get_compiled_regex("match", 0, NULL).release(), params->get_compiled_regex("exclude", 0, NULL).release()) { - if (params->contains(CN_SERVERS)) + if (params->contains(CN_SERVERS) || params->contains(CN_CLUSTER)) { MXS_NOTICE("Replicating directly from a master server"); cdc::Config cnf; diff --git a/server/modules/routing/avrorouter/avro_client.cc b/server/modules/routing/avrorouter/avro_client.cc index 1d3bf87d4..bf35dfbd6 100644 --- a/server/modules/routing/avrorouter/avro_client.cc +++ b/server/modules/routing/avrorouter/avro_client.cc @@ -279,17 +279,20 @@ std::pair get_avrofile_and_gtid(std::string file) auto first_dot = filename.find_first_of('.'); auto last_dot = filename.find_last_of('.'); - if (first_dot != std::string::npos - && last_dot != std::string::npos - && first_dot != last_dot) + if (!file.empty()) { - // Exact file version specified e.g. test.t1.000002 - filename += ".avro"; - } - else - { - // No version specified, send first file - filename += ".000001.avro"; + if (first_dot != std::string::npos + && last_dot != std::string::npos + && first_dot != last_dot) + { + // Exact file version specified e.g. test.t1.000002 + filename += ".avro"; + } + else + { + // No version specified, send first file + filename += ".000001.avro"; + } } return std::make_pair(filename, gtid); @@ -329,13 +332,17 @@ void AvroSession::process_command(GWBUF* queue) avro_binfile = file_and_gtid.first; - if (file_in_dir(router->avrodir.c_str(), avro_binfile.c_str())) + if (avro_binfile.empty()) { - queue_client_callback(); + dcb_printf(dcb, "ERR NO-FILE Filename not specified.\n"); + } + else if (!file_in_dir(router->avrodir.c_str(), avro_binfile.c_str())) + { + dcb_printf(dcb, "ERR NO-FILE File '%s' not found.\n", avro_binfile.c_str()); } else { - dcb_printf(dcb, "ERR NO-FILE File '%s' not found.\n", avro_binfile.c_str()); + queue_client_callback(); } } else @@ -714,6 +721,7 @@ void AvroSession::client_callback() /** Stream the data to the client */ bool read_more = stream_data(); + mxb_assert(!avro_binfile.empty() && strstr(avro_binfile.c_str(), ".avro")); std::string filename = get_next_filename(avro_binfile, router->avrodir); bool next_file; diff --git a/server/modules/routing/avrorouter/avro_main.cc b/server/modules/routing/avrorouter/avro_main.cc index 634e310eb..c940fd5fc 100644 --- a/server/modules/routing/avrorouter/avro_main.cc +++ b/server/modules/routing/avrorouter/avro_main.cc @@ -68,7 +68,7 @@ MXS_ROUTER* createInstance(SERVICE* service, MXS_CONFIG_PARAMETER* params) Avro* router = Avro::create(service, handler); - if (router && !params->contains(CN_SERVERS)) + if (router && !params->contains(CN_SERVERS) && !params->contains(CN_CLUSTER)) { conversion_task_ctl(router, true); }