Merge branch '2.2' into develop
This commit is contained in:
@ -9,14 +9,17 @@
|
|||||||
|
|
||||||
echo TRAVIS_BUILD_DIR: ${TRAVIS_BUILD_DIR}
|
echo TRAVIS_BUILD_DIR: ${TRAVIS_BUILD_DIR}
|
||||||
|
|
||||||
|
# Configure the build environment
|
||||||
|
./BUILD/install_build_deps.sh
|
||||||
|
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
|
|
||||||
cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTS=Y -DBUILD_AVRO=N
|
cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTS=Y
|
||||||
|
|
||||||
make
|
make
|
||||||
make test
|
make test || exit 1
|
||||||
sudo make install
|
|
||||||
|
|
||||||
|
sudo make install
|
||||||
sudo ./postinst
|
sudo ./postinst
|
||||||
maxscale --version
|
maxscale --version
|
||||||
|
|||||||
@ -15,7 +15,7 @@ then
|
|||||||
sudo apt-get install -y --force-yes dpkg-dev git wget \
|
sudo apt-get install -y --force-yes dpkg-dev git wget \
|
||||||
build-essential libssl-dev ncurses-dev bison flex \
|
build-essential libssl-dev ncurses-dev bison flex \
|
||||||
perl libtool libpcre3-dev tcl tcl-dev uuid \
|
perl libtool libpcre3-dev tcl tcl-dev uuid \
|
||||||
uuid-dev libsqlite3-dev liblzma-dev libpam0g-dev
|
uuid-dev libsqlite3-dev liblzma-dev libpam0g-dev pkg-config
|
||||||
## separatelibgnutls installation process for Ubuntu Trusty
|
## separatelibgnutls installation process for Ubuntu Trusty
|
||||||
cat /etc/*release | grep -E "Trusty|wheezy"
|
cat /etc/*release | grep -E "Trusty|wheezy"
|
||||||
if [ $? == 0 ]
|
if [ $? == 0 ]
|
||||||
@ -76,18 +76,18 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# cmake
|
# cmake
|
||||||
wget http://max-tst-01.mariadb.com/ci-repository/cmake-3.7.1-Linux-x86_64.tar.gz --no-check-certificate
|
wget -q http://max-tst-01.mariadb.com/ci-repository/cmake-3.7.1-Linux-x86_64.tar.gz --no-check-certificate
|
||||||
if [ $? != 0 ] ; then
|
if [ $? != 0 ] ; then
|
||||||
echo "CMake can not be downloaded from Maxscale build server, trying from cmake.org"
|
echo "CMake can not be downloaded from Maxscale build server, trying from cmake.org"
|
||||||
wget https://cmake.org/files/v3.7/cmake-3.7.1-Linux-x86_64.tar.gz --no-check-certificate
|
wget -q https://cmake.org/files/v3.7/cmake-3.7.1-Linux-x86_64.tar.gz --no-check-certificate
|
||||||
fi
|
fi
|
||||||
sudo tar xzvf cmake-3.7.1-Linux-x86_64.tar.gz -C /usr/ --strip-components=1
|
sudo tar xzf cmake-3.7.1-Linux-x86_64.tar.gz -C /usr/ --strip-components=1
|
||||||
|
|
||||||
cmake_version=`cmake --version | grep "cmake version" | awk '{ print $3 }'`
|
cmake_version=`cmake --version | grep "cmake version" | awk '{ print $3 }'`
|
||||||
if [ "$cmake_version" \< "3.7.1" ] ; then
|
if [ "$cmake_version" \< "3.7.1" ] ; then
|
||||||
echo "cmake does not work! Trying to build from source"
|
echo "cmake does not work! Trying to build from source"
|
||||||
wget https://cmake.org/files/v3.7/cmake-3.7.1.tar.gz --no-check-certificate
|
wget -q https://cmake.org/files/v3.7/cmake-3.7.1.tar.gz --no-check-certificate
|
||||||
tar xzvf cmake-3.7.1.tar.gz
|
tar xzf cmake-3.7.1.tar.gz
|
||||||
cd cmake-3.7.1
|
cd cmake-3.7.1
|
||||||
|
|
||||||
./bootstrap
|
./bootstrap
|
||||||
@ -116,7 +116,7 @@ cd ../../
|
|||||||
# TCL
|
# TCL
|
||||||
mkdir tcl
|
mkdir tcl
|
||||||
cd tcl
|
cd tcl
|
||||||
wget --no-check-certificate http://prdownloads.sourceforge.net/tcl/tcl8.6.5-src.tar.gz
|
wget -q --no-check-certificate http://prdownloads.sourceforge.net/tcl/tcl8.6.5-src.tar.gz
|
||||||
|
|
||||||
if [ $? != 0 ]
|
if [ $? != 0 ]
|
||||||
then
|
then
|
||||||
@ -124,7 +124,7 @@ then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
tar xzvf tcl8.6.5-src.tar.gz
|
tar xzf tcl8.6.5-src.tar.gz
|
||||||
cd tcl8.6.5/unix
|
cd tcl8.6.5/unix
|
||||||
./configure
|
./configure
|
||||||
sudo make install
|
sudo make install
|
||||||
@ -149,7 +149,7 @@ sudo make install
|
|||||||
cd ../../
|
cd ../../
|
||||||
|
|
||||||
# Avro C API
|
# Avro C API
|
||||||
wget -r -l1 -nH --cut-dirs=2 --no-parent -A.tar.gz --no-directories http://mirror.netinch.com/pub/apache/avro/stable/c
|
wget -q -r -l1 -nH --cut-dirs=2 --no-parent -A.tar.gz --no-directories http://mirror.netinch.com/pub/apache/avro/stable/c
|
||||||
if [ $? != 0 ]
|
if [ $? != 0 ]
|
||||||
then
|
then
|
||||||
echo "Error getting avro-c"
|
echo "Error getting avro-c"
|
||||||
|
|||||||
@ -28,6 +28,7 @@
|
|||||||
the master. There is also limited capability for rejoining nodes.
|
the master. There is also limited capability for rejoining nodes.
|
||||||
|
|
||||||
For more details, please refer to:
|
For more details, please refer to:
|
||||||
|
* [MariaDB MaxScale 2.2.3 Release Notes](Release-Notes/MaxScale-2.2.3-Release-Notes.md)
|
||||||
* [MariaDB MaxScale 2.2.2 Release Notes](Release-Notes/MaxScale-2.2.2-Release-Notes.md)
|
* [MariaDB MaxScale 2.2.2 Release Notes](Release-Notes/MaxScale-2.2.2-Release-Notes.md)
|
||||||
* [MariaDB MaxScale 2.2.1 Release Notes](Release-Notes/MaxScale-2.2.1-Release-Notes.md)
|
* [MariaDB MaxScale 2.2.1 Release Notes](Release-Notes/MaxScale-2.2.1-Release-Notes.md)
|
||||||
* [MariaDB MaxScale 2.2.0 Release Notes](Release-Notes/MaxScale-2.2.0-Release-Notes.md)
|
* [MariaDB MaxScale 2.2.0 Release Notes](Release-Notes/MaxScale-2.2.0-Release-Notes.md)
|
||||||
|
|||||||
@ -17,6 +17,18 @@ being monitored by the mariadbmon monitor, the current GTID position will be
|
|||||||
displayed in the newly added column. If no GTID is available, an empty value is
|
displayed in the newly added column. If no GTID is available, an empty value is
|
||||||
returned.
|
returned.
|
||||||
|
|
||||||
|
### MaxAdmin input from scripts
|
||||||
|
|
||||||
|
The failure to set terminal attributes for MaxScale is no longer considered an
|
||||||
|
error as scripts most often do not have an actual terminal that control the
|
||||||
|
process. This means that passwords and other commands can be passed to MaxAdmin
|
||||||
|
without a controlling terminal.
|
||||||
|
|
||||||
|
### MaxCtrl password input
|
||||||
|
|
||||||
|
MaxCtrl can now query the password from the user. This allows passwords to be
|
||||||
|
given without giving them as process arguments.
|
||||||
|
|
||||||
## Dropped Features
|
## Dropped Features
|
||||||
|
|
||||||
## New Features
|
## New Features
|
||||||
@ -25,6 +37,13 @@ returned.
|
|||||||
|
|
||||||
[Here is a list of bugs fixed in MaxScale 2.2.3.](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.2.3)
|
[Here is a list of bugs fixed in MaxScale 2.2.3.](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.2.3)
|
||||||
|
|
||||||
|
* [MXS-1698](https://jira.mariadb.org/browse/MXS-1698) error:140940F5:SSL routines:ssl3_read_bytes:unexpected record
|
||||||
|
* [MXS-1697](https://jira.mariadb.org/browse/MXS-1697) MaxScale 2.2.2 missing avrorouter library
|
||||||
|
* [MXS-1693](https://jira.mariadb.org/browse/MXS-1693) In Maxscale 2.2.2 getting users with native password from mysql backends does not work
|
||||||
|
* [MXS-1688](https://jira.mariadb.org/browse/MXS-1688) Some date functions are not parsed properly with schemarouter
|
||||||
|
* [MXS-1684](https://jira.mariadb.org/browse/MXS-1684) Empty space on a line in rule file confuses dbfwfilter which refuses to start
|
||||||
|
* [MXS-1683](https://jira.mariadb.org/browse/MXS-1683) Commands that take passwords should allow input from stdin and not just from controlling terminals
|
||||||
|
|
||||||
## Known Issues and Limitations
|
## Known Issues and Limitations
|
||||||
|
|
||||||
There are some limitations and known issues within this version of MaxScale.
|
There are some limitations and known issues within this version of MaxScale.
|
||||||
|
|||||||
@ -43,6 +43,9 @@
|
|||||||
|
|
||||||
#ifdef HISTORY
|
#ifdef HISTORY
|
||||||
#include <histedit.h>
|
#include <histedit.h>
|
||||||
|
#define USE_HIST 1
|
||||||
|
#else
|
||||||
|
#define USE_HIST 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MAX_PASSWORD_LEN 80
|
#define MAX_PASSWORD_LEN 80
|
||||||
@ -62,6 +65,7 @@ static void read_inifile(char **socket,
|
|||||||
char **hostname, char **port, char **user, char **passwd,
|
char **hostname, char **port, char **user, char **passwd,
|
||||||
int *editor);
|
int *editor);
|
||||||
static bool getPassword(char *password, size_t length);
|
static bool getPassword(char *password, size_t length);
|
||||||
|
static void rtrim(char *str);
|
||||||
|
|
||||||
#ifdef HISTORY
|
#ifdef HISTORY
|
||||||
|
|
||||||
@ -93,6 +97,128 @@ static struct option long_options[] =
|
|||||||
#define MAXADMIN_DEFAULT_USER "admin"
|
#define MAXADMIN_DEFAULT_USER "admin"
|
||||||
#define MAXADMIN_BUFFER_SIZE 2048
|
#define MAXADMIN_BUFFER_SIZE 2048
|
||||||
|
|
||||||
|
static bool term_error = false;
|
||||||
|
|
||||||
|
bool process_command(int so, char* buf)
|
||||||
|
{
|
||||||
|
bool rval = true;
|
||||||
|
|
||||||
|
if (isquit(buf))
|
||||||
|
{
|
||||||
|
rval = false;
|
||||||
|
}
|
||||||
|
else if (!strncasecmp(buf, "source", 6))
|
||||||
|
{
|
||||||
|
char *ptr;
|
||||||
|
|
||||||
|
/* Find the filename */
|
||||||
|
ptr = &buf[strlen("source")];
|
||||||
|
while (*ptr && isspace(*ptr))
|
||||||
|
{
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
DoSource(so, ptr);
|
||||||
|
}
|
||||||
|
else if (*buf)
|
||||||
|
{
|
||||||
|
if (!sendCommand(so, buf))
|
||||||
|
{
|
||||||
|
rval = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cmd_with_history(int so, char** argv, bool use_emacs)
|
||||||
|
{
|
||||||
|
#ifdef HISTORY
|
||||||
|
char *buf;
|
||||||
|
EditLine *el = NULL;
|
||||||
|
Tokenizer *tok;
|
||||||
|
History *hist;
|
||||||
|
HistEvent ev;
|
||||||
|
|
||||||
|
hist = history_init(); /* Init the builtin history */
|
||||||
|
|
||||||
|
/* Remember 100 events */
|
||||||
|
history(hist, &ev, H_SETSIZE, 100);
|
||||||
|
|
||||||
|
tok = tok_init(NULL); /* Initialize the tokenizer */
|
||||||
|
|
||||||
|
/* Initialize editline */
|
||||||
|
el = el_init(*argv, stdin, stdout, stderr);
|
||||||
|
|
||||||
|
if (use_emacs)
|
||||||
|
{
|
||||||
|
el_set(el, EL_EDITOR, "emacs"); /** Editor is emacs */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
el_set(el, EL_EDITOR, "vi"); /* Default editor is vi */
|
||||||
|
}
|
||||||
|
el_set(el, EL_SIGNAL, 1); /* Handle signals gracefully */
|
||||||
|
el_set(el, EL_PROMPT, prompt); /* Set the prompt function */
|
||||||
|
|
||||||
|
/* Tell editline to use this history interface */
|
||||||
|
el_set(el, EL_HIST, history, hist);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Bind j, k in vi command mode to previous and next line, instead
|
||||||
|
* of previous and next history.
|
||||||
|
*/
|
||||||
|
el_set(el, EL_BIND, "-a", "k", "ed-prev-line", NULL);
|
||||||
|
el_set(el, EL_BIND, "-a", "j", "ed-next-line", NULL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Source the user's defaults file.
|
||||||
|
*/
|
||||||
|
el_source(el, NULL);
|
||||||
|
|
||||||
|
int num = 0;
|
||||||
|
|
||||||
|
while ((buf = (char *) el_gets(el, &num)))
|
||||||
|
{
|
||||||
|
rtrim(buf);
|
||||||
|
history(hist, &ev, H_ENTER, buf);
|
||||||
|
if (!strcasecmp(buf, "history"))
|
||||||
|
{
|
||||||
|
for (int rv = history(hist, &ev, H_LAST); rv != -1;
|
||||||
|
rv = history(hist, &ev, H_PREV))
|
||||||
|
{
|
||||||
|
fprintf(stdout, "%4d %s\n", ev.num, ev.str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!process_command(so, buf))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
el_end(el);
|
||||||
|
tok_end(tok);
|
||||||
|
history_end(hist);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void cmd_no_history(int so)
|
||||||
|
{
|
||||||
|
char buf[MAXADMIN_BUFFER_SIZE];
|
||||||
|
while (printf("MaxScale> ") && fgets(buf, 1024, stdin) != NULL)
|
||||||
|
{
|
||||||
|
rtrim(buf);
|
||||||
|
if (!strcasecmp(buf, "history"))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "History not supported in this version.\n");
|
||||||
|
}
|
||||||
|
else if (!process_command(so, buf))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The main for the maxadmin client
|
* The main for the maxadmin client
|
||||||
*
|
*
|
||||||
@ -102,15 +228,6 @@ static struct option long_options[] =
|
|||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
#ifdef HISTORY
|
|
||||||
char *buf;
|
|
||||||
EditLine *el = NULL;
|
|
||||||
Tokenizer *tok;
|
|
||||||
History *hist;
|
|
||||||
HistEvent ev;
|
|
||||||
#else
|
|
||||||
char buf[MAXADMIN_BUFFER_SIZE];
|
|
||||||
#endif
|
|
||||||
char *hostname = NULL;
|
char *hostname = NULL;
|
||||||
char *port = NULL;
|
char *port = NULL;
|
||||||
char *user = NULL;
|
char *user = NULL;
|
||||||
@ -293,105 +410,16 @@ main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
(void) setlocale(LC_CTYPE, "");
|
(void) setlocale(LC_CTYPE, "");
|
||||||
#ifdef HISTORY
|
|
||||||
hist = history_init(); /* Init the builtin history */
|
|
||||||
/* Remember 100 events */
|
|
||||||
history(hist, &ev, H_SETSIZE, 100);
|
|
||||||
|
|
||||||
tok = tok_init(NULL); /* Initialize the tokenizer */
|
if (!term_error && USE_HIST)
|
||||||
|
|
||||||
/* Initialize editline */
|
|
||||||
el = el_init(*argv, stdin, stdout, stderr);
|
|
||||||
|
|
||||||
if (use_emacs)
|
|
||||||
{
|
{
|
||||||
el_set(el, EL_EDITOR, "emacs"); /** Editor is emacs */
|
cmd_with_history(so, argv, use_emacs);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
el_set(el, EL_EDITOR, "vi"); /* Default editor is vi */
|
cmd_no_history(so);
|
||||||
}
|
|
||||||
el_set(el, EL_SIGNAL, 1); /* Handle signals gracefully */
|
|
||||||
el_set(el, EL_PROMPT, prompt); /* Set the prompt function */
|
|
||||||
|
|
||||||
/* Tell editline to use this history interface */
|
|
||||||
el_set(el, EL_HIST, history, hist);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Bind j, k in vi command mode to previous and next line, instead
|
|
||||||
* of previous and next history.
|
|
||||||
*/
|
|
||||||
el_set(el, EL_BIND, "-a", "k", "ed-prev-line", NULL);
|
|
||||||
el_set(el, EL_BIND, "-a", "j", "ed-next-line", NULL);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Source the user's defaults file.
|
|
||||||
*/
|
|
||||||
el_source(el, NULL);
|
|
||||||
|
|
||||||
int num;
|
|
||||||
while ((buf = (char *) el_gets(el, &num)) != NULL && num != 0)
|
|
||||||
{
|
|
||||||
#else
|
|
||||||
while (printf("MaxScale> ") && fgets(buf, 1024, stdin) != NULL)
|
|
||||||
{
|
|
||||||
int num = strlen(buf);
|
|
||||||
#endif
|
|
||||||
/* Strip trailing \n\r */
|
|
||||||
for (int i = num - 1; buf[i] == '\r' || buf[i] == '\n'; i--)
|
|
||||||
{
|
|
||||||
buf[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HISTORY
|
|
||||||
history(hist, &ev, H_ENTER, buf);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (isquit(buf))
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if (!strcasecmp(buf, "history"))
|
|
||||||
{
|
|
||||||
#ifdef HISTORY
|
|
||||||
int rv;
|
|
||||||
for (rv = history(hist, &ev, H_LAST); rv != -1;
|
|
||||||
rv = history(hist, &ev, H_PREV))
|
|
||||||
{
|
|
||||||
fprintf(stdout, "%4d %s\n",
|
|
||||||
ev.num, ev.str);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
fprintf(stderr, "History not supported in this version.\n");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else if (!strncasecmp(buf, "source", 6))
|
|
||||||
{
|
|
||||||
char *ptr;
|
|
||||||
|
|
||||||
/* Find the filename */
|
|
||||||
ptr = &buf[strlen("source")];
|
|
||||||
while (*ptr && isspace(*ptr))
|
|
||||||
{
|
|
||||||
ptr++;
|
|
||||||
}
|
|
||||||
|
|
||||||
DoSource(so, ptr);
|
|
||||||
}
|
|
||||||
else if (*buf)
|
|
||||||
{
|
|
||||||
if (!sendCommand(so, buf))
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HISTORY
|
|
||||||
el_end(el);
|
|
||||||
tok_end(tok);
|
|
||||||
history_end(hist);
|
|
||||||
#endif
|
|
||||||
close(so);
|
close(so);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -937,8 +965,7 @@ read_inifile(char **socket,
|
|||||||
*/
|
*/
|
||||||
bool getPassword(char *passwd, size_t len)
|
bool getPassword(char *passwd, size_t len)
|
||||||
{
|
{
|
||||||
bool gotten = false;
|
bool err = false;
|
||||||
|
|
||||||
struct termios tty_attr;
|
struct termios tty_attr;
|
||||||
tcflag_t c_lflag;
|
tcflag_t c_lflag;
|
||||||
|
|
||||||
@ -948,36 +975,55 @@ bool getPassword(char *passwd, size_t len)
|
|||||||
tty_attr.c_lflag &= ~ICANON;
|
tty_attr.c_lflag &= ~ICANON;
|
||||||
tty_attr.c_lflag &= ~ECHO;
|
tty_attr.c_lflag &= ~ECHO;
|
||||||
|
|
||||||
if (tcsetattr(STDIN_FILENO, 0, &tty_attr) == 0)
|
if (tcsetattr(STDIN_FILENO, 0, &tty_attr) != 0)
|
||||||
{
|
{
|
||||||
printf("Password: ");
|
err = true;
|
||||||
if (fgets(passwd, len, stdin) == NULL)
|
}
|
||||||
{
|
}
|
||||||
printf("Failed to read password\n");
|
else
|
||||||
}
|
{
|
||||||
|
err = true;
|
||||||
|
}
|
||||||
|
|
||||||
tty_attr.c_lflag = c_lflag;
|
if (err)
|
||||||
|
{
|
||||||
|
fprintf(stderr,
|
||||||
|
"Warning: Could not configure terminal. Terminal echo is still enabled. This\n"
|
||||||
|
"means that the password will be visible on the controlling terminal when\n"
|
||||||
|
"it is written!\n");
|
||||||
|
}
|
||||||
|
|
||||||
if (tcsetattr(STDIN_FILENO, 0, &tty_attr) == 0)
|
printf("Password: ");
|
||||||
{
|
if (fgets(passwd, len, stdin) == NULL)
|
||||||
int i = strlen(passwd);
|
{
|
||||||
|
printf("Failed to read password\n");
|
||||||
|
}
|
||||||
|
|
||||||
if (i > 1)
|
if (!err)
|
||||||
{
|
{
|
||||||
passwd[i - 1] = '\0';
|
tty_attr.c_lflag = c_lflag;
|
||||||
}
|
|
||||||
|
|
||||||
printf("\n");
|
if (tcsetattr(STDIN_FILENO, 0, &tty_attr) != 0)
|
||||||
|
{
|
||||||
gotten = true;
|
err = true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gotten)
|
int i = strlen(passwd);
|
||||||
|
|
||||||
|
if (i > 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Could not configure terminal.\n");
|
passwd[i - 1] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
return gotten;
|
printf("\n");
|
||||||
|
|
||||||
|
|
||||||
|
// Store failure globally so that interactive parts are skipped
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
term_error = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *passwd;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,6 +17,7 @@ var Table = require('cli-table');
|
|||||||
var consoleLib = require('console')
|
var consoleLib = require('console')
|
||||||
var os = require('os')
|
var os = require('os')
|
||||||
var fs = require('fs')
|
var fs = require('fs')
|
||||||
|
var readlineSync = require('readline-sync')
|
||||||
|
|
||||||
module.exports = function() {
|
module.exports = function() {
|
||||||
|
|
||||||
@ -27,6 +28,13 @@ module.exports = function() {
|
|||||||
// servers.
|
// servers.
|
||||||
this.maxctrl = function(argv, cb) {
|
this.maxctrl = function(argv, cb) {
|
||||||
|
|
||||||
|
// No password given, ask it from the command line
|
||||||
|
if (argv.p == '') {
|
||||||
|
argv.p = readlineSync.question('Enter password: ', {
|
||||||
|
hideEchoBack: true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// Split the hostnames, separated by commas
|
// Split the hostnames, separated by commas
|
||||||
argv.hosts = argv.hosts.split(',')
|
argv.hosts = argv.hosts.split(',')
|
||||||
|
|
||||||
@ -209,7 +217,7 @@ module.exports = function() {
|
|||||||
base = 'https://'
|
base = 'https://'
|
||||||
}
|
}
|
||||||
|
|
||||||
return base + argv.user + ':' + argv.password + '@' + host + '/v1/' + endpoint
|
return base + argv.u + ':' + argv.p + '@' + host + '/v1/' + endpoint
|
||||||
}
|
}
|
||||||
|
|
||||||
this.OK = function() {
|
this.OK = function() {
|
||||||
|
|||||||
@ -31,7 +31,7 @@ program
|
|||||||
})
|
})
|
||||||
.option('p', {
|
.option('p', {
|
||||||
alias: 'password',
|
alias: 'password',
|
||||||
describe: 'Password for the user',
|
describe: 'Password for the user. To input the password manually, give -p as the last argument or use --password=\'\'',
|
||||||
default: 'mariadb',
|
default: 'mariadb',
|
||||||
type: 'string'
|
type: 'string'
|
||||||
})
|
})
|
||||||
@ -104,7 +104,7 @@ program
|
|||||||
.demandCommand(1, 'At least one command is required')
|
.demandCommand(1, 'At least one command is required')
|
||||||
.command('*', 'the default command', {}, function(argv) {
|
.command('*', 'the default command', {}, function(argv) {
|
||||||
maxctrl(argv, function() {
|
maxctrl(argv, function() {
|
||||||
return error('Unknown command. See output of `help` for a list of commands.')
|
return error('Unknown command ' + JSON.stringify(argv._) + '. See output of `help` for a list of commands.')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@ -19,6 +19,7 @@
|
|||||||
"cli-table": "^0.3.1",
|
"cli-table": "^0.3.1",
|
||||||
"lodash": "^4.17.4",
|
"lodash": "^4.17.4",
|
||||||
"lodash-getpath": "^0.2.4",
|
"lodash-getpath": "^0.2.4",
|
||||||
|
"readline-sync": "^1.4.9",
|
||||||
"request": "^2.81.0",
|
"request": "^2.81.0",
|
||||||
"request-promise-native": "^1.0.3",
|
"request-promise-native": "^1.0.3",
|
||||||
"yargs": "^8.0.2"
|
"yargs": "^8.0.2"
|
||||||
|
|||||||
@ -6,6 +6,14 @@
|
|||||||
|
|
||||||
#include "testconnections.h"
|
#include "testconnections.h"
|
||||||
|
|
||||||
|
void list_servers(TestConnections& test)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
char *output = test.maxscales->ssh_node_output_f(0, true, &rc, "maxadmin list servers");
|
||||||
|
test.tprintf("%s", output);
|
||||||
|
free(output);
|
||||||
|
}
|
||||||
|
|
||||||
void do_test(TestConnections& test, int master, int slave)
|
void do_test(TestConnections& test, int master, int slave)
|
||||||
{
|
{
|
||||||
test.maxscales->connect_maxscale(0);
|
test.maxscales->connect_maxscale(0);
|
||||||
@ -15,24 +23,32 @@ void do_test(TestConnections& test, int master, int slave)
|
|||||||
|
|
||||||
test.tprintf("Stop a slave node and perform an insert");
|
test.tprintf("Stop a slave node and perform an insert");
|
||||||
test.galera->block_node(slave);
|
test.galera->block_node(slave);
|
||||||
sleep(5);
|
sleep(10);
|
||||||
|
list_servers(test);
|
||||||
|
|
||||||
test.try_query(test.maxscales->conn_rwsplit[0], "INSERT INTO test.t1 VALUES (1)");
|
test.try_query(test.maxscales->conn_rwsplit[0], "INSERT INTO test.t1 VALUES (1)");
|
||||||
|
|
||||||
test.tprintf("Start the slave node and perform another insert");
|
test.tprintf("Start the slave node and perform another insert");
|
||||||
test.galera->unblock_node(slave);
|
test.galera->unblock_node(slave);
|
||||||
sleep(5);
|
sleep(10);
|
||||||
|
list_servers(test);
|
||||||
|
|
||||||
test.try_query(test.maxscales->conn_rwsplit[0], "INSERT INTO test.t1 VALUES (1)");
|
test.try_query(test.maxscales->conn_rwsplit[0], "INSERT INTO test.t1 VALUES (1)");
|
||||||
test.maxscales->close_maxscale_connections(0);
|
test.maxscales->close_maxscale_connections(0);
|
||||||
|
|
||||||
test.tprintf("Stop the master node and perform an insert");
|
test.tprintf("Stop the master node and perform an insert");
|
||||||
test.galera->block_node(master);
|
test.galera->block_node(master);
|
||||||
sleep(5);
|
sleep(10);
|
||||||
|
list_servers(test);
|
||||||
|
|
||||||
test.maxscales->connect_maxscale(0);
|
test.maxscales->connect_maxscale(0);
|
||||||
test.try_query(test.maxscales->conn_rwsplit[0], "INSERT INTO test.t1 VALUES (1)");
|
test.try_query(test.maxscales->conn_rwsplit[0], "INSERT INTO test.t1 VALUES (1)");
|
||||||
|
|
||||||
test.tprintf("Start the master node and perform another insert (expecting failure)");
|
test.tprintf("Start the master node and perform another insert (expecting failure)");
|
||||||
test.galera->unblock_node(master);
|
test.galera->unblock_node(master);
|
||||||
sleep(5);
|
sleep(10);
|
||||||
|
list_servers(test);
|
||||||
|
|
||||||
test.add_result(execute_query_silent(test.maxscales->conn_rwsplit[0], "INSERT INTO test.t1 VALUES (1)") == 0,
|
test.add_result(execute_query_silent(test.maxscales->conn_rwsplit[0], "INSERT INTO test.t1 VALUES (1)") == 0,
|
||||||
"Query should fail");
|
"Query should fail");
|
||||||
test.maxscales->close_maxscale_connections(0);
|
test.maxscales->close_maxscale_connections(0);
|
||||||
|
|||||||
@ -176,6 +176,11 @@ bool MessageQueue::post(const Message& message) const
|
|||||||
{
|
{
|
||||||
ssize_t n = write(m_write_fd, &message, sizeof(message));
|
ssize_t n = write(m_write_fd, &message, sizeof(message));
|
||||||
rv = (n == sizeof(message));
|
rv = (n == sizeof(message));
|
||||||
|
|
||||||
|
if (n == -1)
|
||||||
|
{
|
||||||
|
MXS_ERROR("Failed to write message: %d, %s", errno, mxs_strerror(errno));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@ -624,11 +624,21 @@ int service_launch_all()
|
|||||||
SERVICE *ptr;
|
SERVICE *ptr;
|
||||||
int n = 0, i;
|
int n = 0, i;
|
||||||
bool error = false;
|
bool error = false;
|
||||||
|
int num_svc = 0;
|
||||||
|
|
||||||
|
for (ptr = allServices; ptr; ptr = ptr->next)
|
||||||
|
{
|
||||||
|
num_svc++;
|
||||||
|
}
|
||||||
|
|
||||||
|
MXS_NOTICE("Starting a total of %d services...", num_svc);
|
||||||
|
|
||||||
|
int curr_svc = 1;
|
||||||
ptr = allServices;
|
ptr = allServices;
|
||||||
while (ptr && !ptr->svc_do_shutdown)
|
while (ptr && !ptr->svc_do_shutdown)
|
||||||
{
|
{
|
||||||
n += (i = serviceInitialize(ptr));
|
n += (i = serviceInitialize(ptr));
|
||||||
|
MXS_NOTICE("Service '%s' started (%d/%d)", ptr->name, curr_svc++, num_svc);
|
||||||
|
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1376,7 +1376,7 @@ mxs_auth_state_t gw_send_backend_auth(DCB *dcb)
|
|||||||
with_ssl, ssl_established);
|
with_ssl, ssl_established);
|
||||||
ss_dassert(buffer);
|
ss_dassert(buffer);
|
||||||
|
|
||||||
if (with_ssl)
|
if (with_ssl && !ssl_established)
|
||||||
{
|
{
|
||||||
if (dcb_write(dcb, buffer) && dcb_connect_SSL(dcb) >= 0)
|
if (dcb_write(dcb, buffer) && dcb_connect_SSL(dcb) >= 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1253,10 +1253,12 @@ static void clientReply(MXS_ROUTER *instance,
|
|||||||
rses->expected_responses--;
|
rses->expected_responses--;
|
||||||
ss_dassert(rses->expected_responses >= 0);
|
ss_dassert(rses->expected_responses >= 0);
|
||||||
ss_dassert(backend->get_reply_state() == REPLY_STATE_DONE);
|
ss_dassert(backend->get_reply_state() == REPLY_STATE_DONE);
|
||||||
|
MXS_INFO("Reply complete, last reply from %s", backend->name());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MXS_DEBUG("Reply not yet complete, waiting for %d replies", rses->expected_responses);
|
MXS_INFO("Reply not yet complete. Waiting for %d replies, got one from %s",
|
||||||
|
rses->expected_responses, backend->name());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user