Merge branch '2.0' into develop

This commit is contained in:
Johan Wikman
2016-09-09 15:12:58 +03:00
48 changed files with 1658 additions and 547 deletions

View File

@ -37,13 +37,25 @@
* 23/07/13 Mark Riddoch Addition of error mechanism to add user
* 23/05/16 Massimiliano Pinto admin_add_user and admin_remove_user
* no longer accept password parameter
* 02/09/16 Johan Wikman Enabled Linux accounts and MaxScale users
*
* @endverbatim
*/
static USERS *loadUsers();
static void initialise();
static USERS *users = NULL;
static USERS *loadLinuxUsers();
static USERS *loadInetUsers();
static const char *admin_add_user(USERS** pusers, const char* fname,
const char* uname, const char* password);
static const char* admin_remove_user(USERS *users, const char* fname,
const char *uname, const char *passwd);
static bool admin_search_user(USERS *users, const char *uname);
static USERS *linux_users = NULL;
static USERS *inet_users = NULL;
static int admin_init = 0;
static char *ADMIN_ERR_NOMEM = "Out of memory";
@ -61,7 +73,11 @@ static char *ADMIN_SUCCESS = NULL;
static const int LINELEN = 80;
static const char USERS_FILE_NAME[] = "maxadmin-users";
static const char LINUX_USERS_FILE_NAME[] = "maxadmin-users";
static const char INET_USERS_FILE_NAME[] = "passwd";
static const char INET_DEFAULT_USERNAME[] = "admin";
static const char INET_DEFAULT_PASSWORD[] = "mariadb";
/**
* Admin Users initialisation
@ -75,125 +91,15 @@ initialise()
}
admin_init = 1;
users = loadUsers();
linux_users = loadLinuxUsers();
inet_users = loadInetUsers();
}
/**
* Verify a username and password
*
* @param username Username to verify
* @param password Password to verify
* @return Non-zero if the username/password combination is valid
*/
int
admin_verify(char *username, char *password)
{
char *pw;
initialise();
if (users == NULL)
{
if (strcmp(username, "admin") == 0 && strcmp(password, "mariadb") == 0)
{
return 1;
}
}
else
{
if ((pw = users_fetch(users, username)) == NULL)
{
return 0;
}
struct crypt_data cdata;
cdata.initialized = 0;
if (strcmp(pw, crypt_r(password, ADMIN_SALT, &cdata)) == 0)
{
return 1;
}
}
return 0;
}
/**
* Load the admin users
*
* @return Table of users
*/
static USERS *
loadUsers()
{
USERS *rval;
FILE *fp;
char fname[PATH_MAX], *home;
char uname[80];
int added_users = 0;
initialise();
snprintf(fname, sizeof(fname), "%s/%s", get_datadir(), USERS_FILE_NAME);
if ((fp = fopen(fname, "r")) == NULL)
{
return NULL;
}
if ((rval = users_alloc()) == NULL)
{
fclose(fp);
return NULL;
}
while (fgets(uname, sizeof(uname), fp))
{
char *nl = strchr(uname, '\n');
if (nl)
{
*nl = '\0';
}
else if (!feof(fp))
{
MXS_ERROR("Line length exceeds %d characters, possible corrupted "
"'passwd' file in: %s", LINELEN, fname);
users_free(rval);
rval = NULL;
break;
}
char *tmp_ptr = strchr(uname, ':');
if (tmp_ptr)
{
*tmp_ptr = '\0';
MXS_WARNING("Found user '%s' with password. "
"This user might not be compatible with new maxadmin in MaxScale 2.0. "
"Remove it with \"remove user %s\" through MaxAdmin", uname, uname);
}
if (users_add(rval, uname, ""))
{
added_users++;
}
}
fclose(fp);
if (!added_users)
{
users_free(rval);
rval = NULL;
}
return rval;
}
/**
* Add user
*
* @param uname Name of the new user
* @return NULL on success or an error string on failure
*/
char *
admin_add_user(char *uname)
static const char *admin_add_user(USERS** pusers, const char* fname,
const char* uname, const char* password)
{
FILE *fp;
char fname[PATH_MAX], *home;
initialise();
char path[PATH_MAX], *home;
if (access(get_datadir(), F_OK) != 0)
{
@ -203,51 +109,51 @@ admin_add_user(char *uname)
}
}
snprintf(fname, sizeof(fname), "%s/%s", get_datadir(), USERS_FILE_NAME);
if (users == NULL)
snprintf(path, sizeof(path), "%s/%s", get_datadir(), fname);
if (*pusers == NULL)
{
MXS_NOTICE("Create initial password file.");
if ((users = users_alloc()) == NULL)
if ((*pusers = users_alloc()) == NULL)
{
return ADMIN_ERR_NOMEM;
}
if ((fp = fopen(fname, "w")) == NULL)
if ((fp = fopen(path, "w")) == NULL)
{
MXS_ERROR("Unable to create password file %s.", fname);
MXS_ERROR("Unable to create password file %s.", path);
return ADMIN_ERR_PWDFILEOPEN;
}
fclose(fp);
}
if (users_fetch(users, uname) != NULL)
if (users_fetch(*pusers, (char*)uname) != NULL) // TODO: Make users const correct.
{
return ADMIN_ERR_DUPLICATE;
}
users_add(users, uname, "");
if ((fp = fopen(fname, "a")) == NULL)
users_add(*pusers, (char*)uname, password ? (char*)password : ""); // TODO: Make users const correct.
if ((fp = fopen(path, "a")) == NULL)
{
MXS_ERROR("Unable to append to password file %s.", fname);
MXS_ERROR("Unable to append to password file %s.", path);
return ADMIN_ERR_FILEAPPEND;
}
fprintf(fp, "%s\n", uname);
if (password)
{
fprintf(fp, "%s:%s\n", uname, password);
}
else
{
fprintf(fp, "%s\n", uname);
}
fclose(fp);
return ADMIN_SUCCESS;
}
/**
* Remove maxscale user from in-memory structure and from password file
*
* @param uname Name of the new user
* @return NULL on success or an error string on failure
*/
char* admin_remove_user(
char* uname)
static const char* admin_remove_user(USERS *users, const char* fname,
const char *uname, const char *passwd)
{
FILE* fp;
FILE* fp_tmp;
char fname[PATH_MAX];
char fname_tmp[PATH_MAX];
char path[PATH_MAX];
char path_tmp[PATH_MAX];
char* home;
char fusr[LINELEN];
char fpwd[LINELEN];
@ -260,43 +166,53 @@ char* admin_remove_user(
return ADMIN_ERR_DELROOT;
}
if (!admin_search_user(uname))
if (!admin_search_user(users, uname))
{
MXS_ERROR("Couldn't find user %s. Removing user failed.", uname);
return ADMIN_ERR_USERNOTFOUND;
}
if (passwd)
{
if (admin_verify_inet_user(uname, passwd) == 0)
{
MXS_ERROR("Authentication failed, wrong user/password "
"combination. Removing user failed.");
return ADMIN_ERR_AUTHENTICATION;
}
}
/** Remove user from in-memory structure */
users_delete(users, uname);
users_delete(users, (char*)uname); // TODO: Make users const correct.
/**
* Open passwd file and remove user from the file.
*/
snprintf(fname, sizeof(fname), "%s/%s", get_datadir(), USERS_FILE_NAME);
snprintf(fname_tmp, sizeof(fname_tmp), "%s/%s_tmp", get_datadir(), USERS_FILE_NAME);
snprintf(path, sizeof(path), "%s/%s", get_datadir(), fname);
snprintf(path_tmp, sizeof(path_tmp), "%s/%s_tmp", get_datadir(), fname);
/**
* Rewrite passwd file from memory.
*/
if ((fp = fopen(fname, "r")) == NULL)
if ((fp = fopen(path, "r")) == NULL)
{
int err = errno;
MXS_ERROR("Unable to open password file %s : errno %d.\n"
"Removing user from file failed; it must be done "
"manually.",
fname,
path,
err);
return ADMIN_ERR_PWDFILEOPEN;
}
/**
* Open temporary passwd file.
*/
if ((fp_tmp = fopen(fname_tmp, "w")) == NULL)
if ((fp_tmp = fopen(path_tmp, "w")) == NULL)
{
int err = errno;
MXS_ERROR("Unable to open tmp file %s : errno %d.\n"
"Removing user from passwd file failed; it must be done "
"manually.",
fname_tmp,
path_tmp,
err);
fclose(fp);
return ADMIN_ERR_TMPFILEOPEN;
@ -311,11 +227,11 @@ char* admin_remove_user(
MXS_ERROR("Unable to process passwd file %s : errno %d.\n"
"Removing user from file failed, and must be done "
"manually.",
fname,
path,
err);
fclose(fp);
fclose(fp_tmp);
unlink(fname_tmp);
unlink(path_tmp);
return ADMIN_ERR_PWDFILEACCESS;
}
@ -330,7 +246,7 @@ char* admin_remove_user(
else if (!feof(fp))
{
MXS_ERROR("Line length exceeds %d characters, possible corrupted "
"'passwd' file in: %s", LINELEN, fname);
"'passwd' file in: %s", LINELEN, path);
fclose(fp);
fclose(fp_tmp);
return ADMIN_ERR_PWDFILEACCESS;
@ -358,11 +274,11 @@ char* admin_remove_user(
"errno %d.\n"
"Removing user from file failed, and must be "
"done manually.",
fname,
path,
err);
fclose(fp);
fclose(fp_tmp);
unlink(fname_tmp);
unlink(path_tmp);
return ADMIN_ERR_PWDFILEACCESS;
}
}
@ -370,16 +286,16 @@ char* admin_remove_user(
/**
* Replace original passwd file with new.
*/
if (rename(fname_tmp, fname))
if (rename(path_tmp, path))
{
int err = errno;
MXS_ERROR("Unable to rename new passwd file %s : errno "
"%d.\n"
"Rename it to %s manually.",
fname_tmp,
path_tmp,
err,
fname);
unlink(fname_tmp);
path);
unlink(path_tmp);
fclose(fp_tmp);
return ADMIN_ERR_PWDFILEACCESS;
}
@ -387,47 +303,284 @@ char* admin_remove_user(
return ADMIN_SUCCESS;
}
/**
* Check for existance of the user
*
* @param user The user name to test
* @return Non-zero if the user exists
* @param uname The user name to test
* @return True if the user exists
*/
int
admin_search_user(char *user)
static bool admin_search_user(USERS *users, const char *uname)
{
return (users_fetch(users, (char*)uname) != NULL); // TODO: Make users const correct.
}
/**
*/
void dcb_print_users(DCB *dcb, const char* heading, USERS *users)
{
dcb_printf(dcb, "%s", heading);
if (users)
{
HASHITERATOR *iter = hashtable_iterator(users->data);
if (iter)
{
char *sep = "";
const char *user;
while ((user = hashtable_next(iter)) != NULL)
{
dcb_printf(dcb, "%s%s", sep, user);
sep = ", ";
}
hashtable_iterator_free(iter);
}
}
dcb_printf(dcb, "%s", "\n");
}
/**
* Load the admin users
*
* @return Table of users
*/
static USERS *
loadUsers(const char *fname)
{
USERS *rval;
FILE *fp;
char path[PATH_MAX], *home;
char uname[80];
int added_users = 0;
initialise();
snprintf(path, sizeof(path), "%s/%s", get_datadir(), fname);
if ((fp = fopen(path, "r")) == NULL)
{
return NULL;
}
if ((rval = users_alloc()) == NULL)
{
fclose(fp);
return NULL;
}
while (fgets(uname, sizeof(uname), fp))
{
char *nl = strchr(uname, '\n');
if (nl)
{
*nl = '\0';
}
else if (!feof(fp))
{
MXS_ERROR("Line length exceeds %d characters, possibly corrupted "
"'passwd' file in: %s", LINELEN, path);
users_free(rval);
rval = NULL;
break;
}
char *password;
char *colon = strchr(uname, ':');
if (colon)
{
// Inet case
*colon = 0;
password = colon + 1;
}
else
{
// Linux case.
password = "";
}
if (users_add(rval, uname, password))
{
added_users++;
}
}
fclose(fp);
if (!added_users)
{
users_free(rval);
rval = NULL;
}
return rval;
}
static USERS *loadLinuxUsers()
{
return loadUsers(LINUX_USERS_FILE_NAME);
}
static USERS *loadInetUsers()
{
return loadUsers(INET_USERS_FILE_NAME);
}
/**
* Enable Linux account
*
* @param uname Name of Linux user
*
* @return NULL on success or an error string on failure.
*/
const char *admin_enable_linux_account(const char *uname)
{
initialise();
int rv = 0;
return admin_add_user(&linux_users, LINUX_USERS_FILE_NAME, uname, NULL);
}
if (strcmp(user, DEFAULT_ADMIN_USER) == 0)
/**
* Disable Linux account
*
* @param uname Name of Linux user
*
* @return NULL on success or an error string on failure.
*/
const char* admin_disable_linux_account(const char* uname)
{
initialise();
return admin_remove_user(linux_users, LINUX_USERS_FILE_NAME, uname, NULL);
}
/**
* Check whether Linux account is enabled
*
* @param uname The user name
*
* @return True if the account is enabled, false otherwise.
*/
bool admin_linux_account_enabled(const char *uname)
{
initialise();
bool rv = false;
if (strcmp(uname, DEFAULT_ADMIN_USER) == 0)
{
rv = 1;
rv = true;
}
else if (users)
else if (linux_users)
{
rv = (users_fetch(users, user) != NULL);
rv = admin_search_user(linux_users, uname);
}
return rv;
}
/**
* Print the statistics and user names of the administration users
* Add insecure remote (network) user.
*
* @param dcb A DCB to send the output to
* @param uname Name of the new user.
* @param password Password of the new user.
*
* @return NULL on success or an error string on failure.
*/
void
dcb_PrintAdminUsers(DCB *dcb)
const char *admin_add_inet_user(const char *uname, const char* password)
{
if (users)
initialise();
struct crypt_data cdata;
cdata.initialized = 0;
char *cpassword = crypt_r(password, ADMIN_SALT, &cdata);
return admin_add_user(&inet_users, INET_USERS_FILE_NAME, uname, cpassword);
}
/**
* Remove insecure remote (network) user
*
* @param uname Name of user to be removed.
* @param password Password of user to be removed.
*
* @return NULL on success or an error string on failure.
*/
const char* admin_remove_inet_user(const char* uname, const char *password)
{
initialise();
return admin_remove_user(inet_users, INET_USERS_FILE_NAME, uname, password);
}
/**
* Check for existance of remote user.
*
* @param user The user name to test.
*
* @return True if the user exists, false otherwise.
*/
bool admin_inet_user_exists(const char *uname)
{
initialise();
bool rv = false;
if (inet_users)
{
dcb_usersPrint(dcb, users);
rv = admin_search_user(inet_users, uname);
}
return rv;
}
/**
* Verify a remote user name and password
*
* @param username Username to verify
* @param password Password to verify
*
* @return True if the username/password combination is valid
*/
bool
admin_verify_inet_user(const char *username, const char *password)
{
bool rv = false;
initialise();
if (inet_users)
{
const char* pw = users_fetch(inet_users, (char*)username); // TODO: Make users const-correct.
if (pw)
{
struct crypt_data cdata;
cdata.initialized = 0;
if (strcmp(pw, crypt_r(password, ADMIN_SALT, &cdata)) == 0)
{
rv = true;
}
}
}
else
{
dcb_printf(dcb, "No administration users have been defined.\n");
if (strcmp(username, INET_DEFAULT_USERNAME) == 0
&& strcmp(password, INET_DEFAULT_PASSWORD) == 0)
{
rv = true;
}
}
return rv;
}
/**
* Print Linux and and inet users
*
* @param dcb A DCB to send the output to.
*/
void dcb_PrintAdminUsers(DCB *dcb)
{
dcb_print_users(dcb, "Enabled Linux accounts (secure) : ", linux_users);
dcb_print_users(dcb, "Created network accounts (insecure): ", inet_users);
}

View File

@ -84,6 +84,7 @@ static bool process_config_context(CONFIG_CONTEXT *);
static int process_config_update(CONFIG_CONTEXT *);
static void free_config_context(CONFIG_CONTEXT *);
static char *config_get_value(CONFIG_PARAMETER *, const char *);
static char *config_get_password(CONFIG_PARAMETER *);
static const char *config_get_value_string(CONFIG_PARAMETER *, const char *);
static int handle_global_item(const char *, const char *);
static int handle_feedback_item(const char *, const char *);
@ -119,7 +120,8 @@ static char *service_params[] =
"router_options",
"servers",
"user",
"passwd",
"passwd", // DEPRECATE: See config_get_password.
"password",
"enable_root_user",
"max_connections",
"max_queued_connections",
@ -139,6 +141,7 @@ static char *service_params[] =
"ignore_databases_regex",
"log_auth_warnings",
"source", /**< Avrorouter only */
"retry_on_failure",
NULL
};
@ -166,7 +169,8 @@ static char *monitor_params[] =
"module",
"servers",
"user",
"passwd",
"passwd", // DEPRECATE: See config_get_password.
"password",
"script",
"events",
"mysql51_replication",
@ -594,6 +598,30 @@ config_get_value(CONFIG_PARAMETER *params, const char *name)
return NULL;
}
// DEPRECATE: In 2.1 complain but accept if "passwd" is provided, in 2.2
// DEPRECATE: drop support for "passwd".
/**
* Get the value of the password parameter
*
* The words looked for are "password" and "passwd".
*
* @param params The linked list of config parameters
* @return the parameter value or NULL if not found
*/
static char *
config_get_password(CONFIG_PARAMETER *params)
{
char *password = config_get_value(params, "password");
char *passwd = config_get_value(params, "passwd");
if (password && passwd)
{
MXS_WARNING("Both 'password' and 'passwd' specified. Using value of 'password'.");
}
return passwd ? passwd : password;
}
/**
* Get the value of a config parameter as a string
*
@ -1386,7 +1414,7 @@ process_config_update(CONFIG_CONTEXT *context)
max_queued_connections = config_get_value_string(obj->parameters, "max_queued_connections");
queued_connection_timeout = config_get_value_string(obj->parameters, "queued_connection_timeout");
user = config_get_value(obj->parameters, "user");
auth = config_get_value(obj->parameters, "passwd");
auth = config_get_password(obj->parameters);
auth_all_servers = config_get_value(obj->parameters, "auth_all_servers");
strip_db_esc = config_get_value(obj->parameters, "strip_db_esc");
@ -2318,7 +2346,7 @@ int create_new_service(CONFIG_CONTEXT *obj)
}
char *user = config_get_value(obj->parameters, "user");
char *auth = config_get_value(obj->parameters, "passwd");
char *auth = config_get_password(obj->parameters);
if (user && auth)
{
@ -2331,7 +2359,7 @@ int create_new_service(CONFIG_CONTEXT *obj)
obj->object,
user ? "" : "the 'user' parameter",
!user && !auth ? " and " : "",
auth ? "" : "the 'passwd' parameter");
auth ? "" : "the 'password' or 'passwd' parameter");
}
char *subservices = config_get_value(obj->parameters, "subservices");
@ -2736,7 +2764,7 @@ int create_new_monitor(CONFIG_CONTEXT *context, CONFIG_CONTEXT *obj, HASHTABLE*
}
char *user = config_get_value(obj->parameters, "user");
char *passwd = config_get_value(obj->parameters, "passwd");
char *passwd = config_get_password(obj->parameters);
if (user && passwd)
{
monitorAddUser(obj->element, user, passwd);

View File

@ -137,6 +137,7 @@ static struct option long_options[] =
{"execdir", required_argument, 0, 'E'},
{"language", required_argument, 0, 'N'},
{"piddir", required_argument, 0, 'P'},
{"basedir", required_argument, 0, 'R'},
{"user", required_argument, 0, 'U'},
{"syslog", required_argument, 0, 's'},
{"maxlog", required_argument, 0, 'S'},
@ -164,7 +165,7 @@ static void write_footer(void);
static int ntfw_cb(const char*, const struct stat*, int, struct FTW*);
static bool file_is_readable(const char* absolute_pathname);
static bool file_is_writable(const char* absolute_pathname);
bool handle_path_arg(char** dest, char* path, char* arg, bool rd, bool wr);
bool handle_path_arg(char** dest, const char* path, char* arg, bool rd, bool wr);
static void set_log_augmentation(const char* value);
static void usage(void);
static char* get_expanded_pathname(
@ -697,30 +698,27 @@ static void print_log_n_stderr(
const char* fprstr, /*< string to be printed to stderr */
int eno) /*< errno, if it is set, zero, otherwise */
{
char* log_err = "Error :";
char* fpr_err = "*\n* Error :";
char* fpr_end = "\n*\n";
if (do_log)
{
mxs_log_init(NULL, get_logdir(), MXS_LOG_TARGET_FS);
char errbuf[STRERROR_BUFLEN];
MXS_ERROR("%s %s %s %s",
log_err,
logstr,
eno == 0 ? " " : "Error :",
eno == 0 ? " " : strerror_r(eno, errbuf, sizeof(errbuf)));
if (mxs_log_init(NULL, get_logdir(), MXS_LOG_TARGET_FS))
{
char errbuf[STRERROR_BUFLEN];
MXS_ERROR("%s%s%s%s",
logstr,
eno == 0 ? "" : " (",
eno == 0 ? "" : strerror_r(eno, errbuf, sizeof(errbuf)),
eno == 0 ? "" : ")");
}
}
if (do_stderr)
{
char errbuf[STRERROR_BUFLEN];
fprintf(stderr,
"%s %s %s %s %s",
fpr_err,
"* Error: %s%s%s%s\n",
fprstr,
eno == 0 ? " " : "Error :",
eno == 0 ? " " : strerror_r(eno, errbuf, sizeof(errbuf)),
fpr_end);
eno == 0 ? "" : " (",
eno == 0 ? "" : strerror_r(eno, errbuf, sizeof(errbuf)),
eno == 0 ? "" : ")");
}
}
@ -887,32 +885,52 @@ static void usage(void)
{
fprintf(stderr,
"\nUsage : %s [OPTION]...\n\n"
" -c, --config-check Validate configuration file and exit\n"
" -d, --nodaemon enable running in terminal process (default:disabled)\n"
" -f, --config=FILE relative or absolute pathname of MaxScale configuration file\n"
" (default:/etc/maxscale.cnf)\n"
" -l, --log=[file|shm|stdout] log to file, shared memory or stdout (default: file)\n"
" -L, --logdir=PATH path to log file directory (default: /var/log/maxscale)\n"
" -A, --cachedir=PATH path to cache directory (default: /var/cache/maxscale)\n"
" -B, --libdir=PATH path to module directory (default: /usr/lib64/maxscale)\n"
" -C, --configdir=PATH path to configuration file directory (default: /etc/)\n"
" -D, --datadir=PATH path to data directory, stored embedded mysql tables\n"
" (default: /var/cache/maxscale)\n"
" -c, --config-check validate configuration file and exit\n"
" -d, --nodaemon enable running in terminal process\n"
" -f, --config=FILE relative or absolute pathname of config file\n"
" -l, --log=[file|shm|stdout] log to file, shared memory or stdout\n"
" (default: file)\n"
" -L, --logdir=PATH path to log file directory\n"
" -A, --cachedir=PATH path to cache directory\n"
" -B, --libdir=PATH path to module directory\n"
" -C, --configdir=PATH path to configuration file directory\n"
" -D, --datadir=PATH path to data directory,\n"
" stored embedded mysql tables\n"
" -E, --execdir=PATH path to the maxscale and other executable files\n"
" (default: /usr/bin)\n"
" -N, --language=PATH path to errmsg.sys file (default: /var/lib/maxscale)\n"
" -P, --piddir=PATH path to PID file directory (default: /var/run/maxscale)\n"
" -U, --user=USER run MaxScale as another user.\n"
" The user ID and group ID of this user are used to run MaxScale.\n"
" -N, --language=PATH path to errmsg.sys file\n"
" -P, --piddir=PATH path to PID file directory\n"
" -R, --basedir=PATH base path for all other paths\n"
" -U, --user=USER user ID and group ID of specified user are used to\n"
" run MaxScale\n"
" -s, --syslog=[yes|no] log messages to syslog (default:yes)\n"
" -S, --maxlog=[yes|no] log messages to MaxScale log (default: yes)\n"
" -G, --log_augmentation=0|1 augment messages with the name of the function where\n"
" the message was logged (default: 0). Primarily for \n"
" development purposes.\n"
" -G, --log_augmentation=0|1 augment messages with the name of the function\n"
" where the message was logged (default: 0)\n"
" -v, --version print version info and exit\n"
" -V, --version-full print full version info and exit\n"
" -?, --help show this help\n"
, progname);
"\n"
"Defaults paths:\n"
" config file: %s/%s\n"
" configdir : %s\n"
" logdir : %s\n"
" cachedir : %s\n"
" libdir : %s\n"
" datadir : %s\n"
" execdir : %s\n"
" language : %s\n"
" piddir : %s\n"
"\n"
"If '--basedir' is provided then all other paths, including the default\n"
"configuration file path, are defined relative to that. As an example,\n"
"if '--basedir /path/maxscale' is specified, then, for instance, the log\n"
"dir will be '/path/maxscale/var/log/maxscale', the config dir will be\n"
"'/path/maxscale/etc' and the default config file will be\n"
"'/path/maxscale/etc/maxscale.cnf'.\n",
progname,
get_configdir(), default_cnf_fname,
get_configdir(), get_logdir(), get_cachedir(), get_libdir(),
get_datadir(), get_execdir(), get_langdir(), get_piddir());
}
@ -1135,6 +1153,61 @@ bool configure_signals(void)
return true;
}
/**
* Set the directories of MaxScale relative to a basedir
*
* @param basedir The base directory relative to which the other are set.
*
* @return True if the directories could be set, false otherwise.
*/
bool set_dirs(const char *basedir)
{
bool rv = true;
char *path;
if (rv && (rv = handle_path_arg(&path, basedir, "var/" MXS_DEFAULT_LOG_SUBPATH, true, false)))
{
set_logdir(path);
}
if (rv && (rv = handle_path_arg(&path, basedir, "var/" MXS_DEFAULT_CACHE_SUBPATH, true, true)))
{
set_cachedir(path);
}
if (rv && (rv = handle_path_arg(&path, basedir, MXS_DEFAULT_LIB_SUBPATH, true, false)))
{
set_libdir(path);
}
if (rv && (rv = handle_path_arg(&path, basedir, MXS_DEFAULT_CONFIG_SUBPATH, true, false)))
{
set_configdir(path);
}
if (rv && (rv = handle_path_arg(&path, basedir, "var/" MXS_DEFAULT_DATA_SUBPATH, true, false)))
{
set_datadir(path);
}
if (rv && (rv = handle_path_arg(&path, basedir, MXS_DEFAULT_EXEC_SUBPATH, true, false)))
{
set_execdir(path);
}
if (rv && (rv = handle_path_arg(&path, basedir, "var/" MXS_DEFAULT_LANG_SUBPATH, true, false)))
{
set_langdir(path);
}
if (rv && (rv = handle_path_arg(&path, basedir, "var/" MXS_DEFAULT_PID_SUBPATH, true, true)))
{
set_piddir(path);
}
return rv;
}
/**
* @mainpage
* The main entry point into MaxScale
@ -1304,7 +1377,6 @@ int main(int argc, char **argv)
}
break;
case 'L':
if (handle_path_arg(&tmp_path, optarg, NULL, true, false))
{
set_logdir(tmp_path);
@ -1381,6 +1453,17 @@ int main(int argc, char **argv)
succp = false;
}
break;
case 'R':
if (handle_path_arg(&tmp_path, optarg, NULL, true, false))
{
succp = set_dirs(tmp_path);
free(tmp_path);
}
else
{
succp = false;
}
break;
case 'S':
{
@ -2252,7 +2335,7 @@ static int write_pid_file()
return 0;
}
bool handle_path_arg(char** dest, char* path, char* arg, bool rd, bool wr)
bool handle_path_arg(char** dest, const char* path, char* arg, bool rd, bool wr)
{
char pathbuffer[PATH_MAX + 2];
char* errstr;

View File

@ -584,7 +584,7 @@ return_succ:
{
/** This releases memory of all created objects */
logmanager_done_nomutex();
LOG_ERROR("MaxScale Log: Error, initialization failed.\n");
fprintf(stderr, "* Error: Initializing the log manager failed.\n");
}
return succ;
}
@ -1693,7 +1693,7 @@ static bool logfile_open_file(filewriter_t* fw,
if (fw->fwr_file == NULL)
{
LOG_ERROR("MaxScale Log: Error, opening log file %s failed.\n", lf->lf_full_file_name);
// Error logged by skygw_file_init to stderr.
rv = false;
}
@ -2125,9 +2125,6 @@ static void filewriter_done(filewriter_t* fw, bool write_footer)
{
case RUN:
CHK_FILEWRITER(fw);
case INIT:
fw->fwr_logmes = NULL;
fw->fwr_clientmes = NULL;
if (log_config.use_stdout)
{
skygw_file_free(fw->fwr_file);
@ -2141,7 +2138,11 @@ static void filewriter_done(filewriter_t* fw, bool write_footer)
skygw_file_close(fw->fwr_file);
}
case INIT:
fw->fwr_logmes = NULL;
fw->fwr_clientmes = NULL;
fw->fwr_state = DONE;
break;
case DONE:
case UNINIT:
default:

View File

@ -826,7 +826,9 @@ mon_status_changed(MONITOR_SERVERS* mon_srv)
{
/* Previous status is -1 if not yet set */
return (mon_srv->mon_prev_status != -1
&& mon_srv->mon_prev_status != mon_srv->server->status);
&& mon_srv->mon_prev_status != mon_srv->server->status
/** If the server is going into maintenance or coming out of it, don't trigger a state change */
&& ((mon_srv->mon_prev_status | mon_srv->server->status) & SERVER_MAINT) == 0);
}
/**

View File

@ -89,7 +89,6 @@ server_alloc(char *servname, char *protocol, unsigned short port)
server->rlag = -2;
server->master_id = -1;
server->depth = -1;
server->slaves = NULL;
server->parameters = NULL;
server->server_string = NULL;
spinlock_init(&server->lock);

View File

@ -384,6 +384,9 @@ int serviceStartAllPorts(SERVICE* service)
(void*) service, retry_after);
MXS_NOTICE("Failed to start service %s, retrying in %d seconds.",
service->name, retry_after);
/** This will prevent MaxScale from shutting down if service start is retried later */
listeners = 1;
}
}
else

View File

@ -50,12 +50,12 @@
static int
test1()
{
if (admin_verify("admin", "mariadb") == 0)
if (admin_verify_inet_user("admin", "mariadb") == 0)
{
fprintf(stderr, "admin_verify: test 1.1 (default user) failed.\n");
return 1;
}
if (admin_verify("bad", "user"))
if (admin_verify_inet_user("bad", "user"))
{
fprintf(stderr, "admin_verify: test 1.2 (wrong user) failed.\n");
return 1;
@ -74,15 +74,15 @@ test1()
static int
test2()
{
char *err;
const char *err;
if ((err = admin_add_user("user0")) != NULL)
if ((err = admin_enable_linux_account("user0")) != NULL)
{
fprintf(stderr, "admin_add_user: test 2.1 (add user) failed, %s.\n", err);
return 1;
}
if (admin_add_user("user0") == NULL)
if (admin_enable_linux_account("user0") == NULL)
{
fprintf(stderr, "admin_add_user: test 2.2 (add user) failed, duplicate.\n");
@ -90,7 +90,7 @@ test2()
}
/* Deleting the last user is not forbidden so we expect this to succeed */
if ((err = admin_remove_user("user0")) != NULL)
if ((err = admin_disable_linux_account("user0")) != NULL)
{
fprintf(stderr, "admin_remove_user: test 2.3 (add user) failed, %s.\n", err);
@ -98,7 +98,7 @@ test2()
}
/* Add the user back, for test5. */
if ((err = admin_add_user("user0")) != NULL)
if ((err = admin_enable_linux_account("user0")) != NULL)
{
fprintf(stderr, "admin_add_user: test 2.4 (add user) failed, %s.\n", err);
@ -120,37 +120,37 @@ test2()
static int
test3()
{
char *err;
const char *err;
if ((err = admin_add_user("user1")) != NULL)
if ((err = admin_enable_linux_account("user1")) != NULL)
{
fprintf(stderr, "admin_add_user: test 3.1 (add user) failed, %s.\n", err);
return 1;
}
if (admin_search_user("user1") == 0)
if (admin_linux_account_enabled("user1") == 0)
{
fprintf(stderr, "admin_search_user: test 3.2 (search user) failed.\n");
return 1;
}
if (admin_search_user("user2") != 0)
if (admin_linux_account_enabled("user2") != 0)
{
fprintf(stderr, "admin_search_user: test 3.3 (search user) failed, unexpeted user found.\n");
return 1;
}
if ((err = admin_remove_user("user1")) != NULL)
if ((err = admin_disable_linux_account("user1")) != NULL)
{
fprintf(stderr, "admin_remove_user: test 3.4 (add user) failed, %s.\n", err);
return 1;
}
if (admin_search_user("user1"))
if (admin_linux_account_enabled("user1"))
{
fprintf(stderr, "admin_search_user: test 3.5 (search user) failed - user was deleted.\n");
@ -173,13 +173,14 @@ test3()
static int
test4()
{
char *err, user[40], passwd[40];
const char *err;
char user[40], passwd[40];
int i, n_users = 50;
for (i = 1; i < n_users; i++)
{
sprintf(user, "user%d", i);
if ((err = admin_add_user(user)) != NULL)
if ((err = admin_enable_linux_account(user)) != NULL)
{
fprintf(stderr, "admin_add_user: test 4.1 (add user) failed, %s.\n", err);
@ -190,7 +191,7 @@ test4()
for (i = 1; i < n_users; i++)
{
sprintf(user, "user%d", i);
if (admin_search_user(user) == 0)
if (admin_linux_account_enabled(user) == 0)
{
fprintf(stderr, "admin_search_user: test 4.2 (search user) failed.\n");
@ -201,7 +202,7 @@ test4()
for (i = 1; i < n_users; i++)
{
sprintf(user, "user%d", i);
if ((err = admin_remove_user(user)) != NULL)
if ((err = admin_disable_linux_account(user)) != NULL)
{
fprintf(stderr, "admin_remove_user: test 4.3 (add user) failed, %s.\n", err);
@ -221,16 +222,16 @@ test4()
static int
test5()
{
char *err;
const char *err;
if ((err = admin_add_user("user")) != NULL)
if ((err = admin_enable_linux_account("user")) != NULL)
{
fprintf(stderr, "admin_add_user: test 5.1 (add user) failed, %s.\n", err);
return 1;
}
if ((err = admin_remove_user("user0")) != NULL)
if ((err = admin_disable_linux_account("user0")) != NULL)
{
fprintf(stderr, "admin_remove_user: test 5.2 (add user) failed, %s.\n", err);