Esempio n. 1
0
/**
 * Check and update a server definition following a configuration
 * update. Changes will not affect any current connections to this
 * server, however all new connections will use the new settings.
 *
 * If the new settings are different from those already applied to the
 * server then a message will be written to the log.
 *
 * @param server        The server to update
 * @param protocol      The new protocol for the server
 * @param user          The monitor user for the server
 * @param passwd        The password to use for the monitor user
 */
void
server_update(SERVER *server, char *protocol, char *user, char *passwd)
{
    if (!strcmp(server->protocol, protocol))
    {
        MXS_NOTICE("Update server protocol for server %s to protocol %s.",
                   server->name,
                   protocol);
        free(server->protocol);
        server->protocol = strdup(protocol);
    }

    if (user != NULL && passwd != NULL)
    {
        if (strcmp(server->monuser, user) == 0 ||
            strcmp(server->monpw, passwd) == 0)
        {
            MXS_NOTICE("Update server monitor credentials for server %s",
                       server->name);
            free(server->monuser);
            free(server->monpw);
            serverAddMonUser(server, user, passwd);
        }
    }
}
Esempio n. 2
0
/**
 * The module initialisation routine, called when the module
 * is first loaded.
 */
void
ModuleInit()
{
	MXS_NOTICE("Initialise CLI router module %s.", version_str);
	spinlock_init(&instlock);
	instances = NULL;
}
Esempio n. 3
0
/**
 * Add user
 *
 * @param uname         Name of the new user
 * @param passwd        Password for the new user
 * @return      NULL on success or an error string on failure
 */
char *
admin_add_user(char *uname, char *passwd)
{
    FILE *fp;
    char fname[1024], *home, *cpasswd;

    initialise();

    if (access(get_datadir(), F_OK) != 0)
    {
        if (mkdir(get_datadir(), S_IRWXU) != 0 && errno != EEXIST)
        {
            return ADMIN_ERR_PWDFILEOPEN;
        }
    }

    snprintf(fname,1023, "%s/passwd", get_datadir());
    fname[1023] = '\0';
    if (users == NULL)
    {
        MXS_NOTICE("Create initial password file.");

        if ((users = users_alloc()) == NULL)
        {
            return ADMIN_ERR_NOMEM;
        }
        if ((fp = fopen(fname, "w")) == NULL)
        {
            MXS_ERROR("Unable to create password file %s.", fname);
            return ADMIN_ERR_PWDFILEOPEN;
        }
        fclose(fp);
    }
    if (users_fetch(users, uname) != NULL)
    {
        return ADMIN_ERR_DUPLICATE;
    }
    struct crypt_data cdata;
    cdata.initialized = 0;
    cpasswd = crypt_r(passwd, ADMIN_SALT, &cdata);
    users_add(users, uname, cpasswd);
    if ((fp = fopen(fname, "a")) == NULL)
    {
        MXS_ERROR("Unable to append to password file %s.", fname);
        return ADMIN_ERR_FILEAPPEND;
    }
    fprintf(fp, "%s:%s\n", uname, cpasswd);
    fclose(fp);
    return ADMIN_SUCCESS;
}
Esempio n. 4
0
/**
 * Execute a SQL query against the MaxScale Information Schema
 *
 * @param instance	The instance strcture
 * @param session	The session pointer
 * @param sql		The SQL to execute
 */
static int
maxinfo_execute_query(INFO_INSTANCE *instance, INFO_SESSION *session, char *sql)
{
MAXINFO_TREE	*tree;
PARSE_ERROR	err;

        MXS_INFO("maxinfo: SQL statement: '%s' for 0x%p.",
                 sql, session->dcb);
	if (strcmp(sql, "select @@version_comment limit 1") == 0)
	{
		respond_vercom(session->dcb);
		return 1;
	}
	/* Below is a kludge for MonYog, if we see
	 * 	select unix_timestamp... as starttime
	 * just return the starttime of MaxScale
	 */
	if (strncasecmp(sql, "select UNIX_TIMESTAMP",
			strlen("select UNIX_TIMESTAMP")) == 0
				&& (strstr(sql, "as starttime") != NULL || strstr(sql, "AS starttime") != NULL))
	{
		respond_starttime(session->dcb);
		return 1;
	}
	if (strcasecmp(sql, "set names 'utf8'") == 0)
	{
		return maxinfo_send_ok(session->dcb);
	}
	if (strncasecmp(sql, "set session", 11) == 0)
	{
		return maxinfo_send_ok(session->dcb);
	}
	if (strncasecmp(sql, "set autocommit", 14) == 0)
	{
		return maxinfo_send_ok(session->dcb);
	}
	if (strncasecmp(sql, "SELECT `ENGINES`.`SUPPORT`", 26) == 0)
	{
		return maxinfo_send_ok(session->dcb);
	}
	if ((tree = maxinfo_parse(sql, &err)) == NULL)
	{
		maxinfo_send_parse_error(session->dcb, sql, err);
		MXS_NOTICE("Failed to parse SQL statement: '%s'.", sql);
	}
	else
		maxinfo_execute(session->dcb, tree);
	return 1;
}
Esempio n. 5
0
/**
 * Execute a show command parse tree and return the result set or runtime error
 *
 * @param dcb	The DCB that connects to the client
 * @param tree	The parse tree for the query
 */
static void
exec_show(DCB *dcb, MAXINFO_TREE *tree)
{
int	i;
char	errmsg[120];

	for (i = 0; show_commands[i].name; i++)
	{
		if (strcasecmp(show_commands[i].name, tree->value) == 0)
		{
			(*show_commands[i].func)(dcb, tree->right);
			return;
		}
	}
	if (strlen(tree->value) > 80)	// Prevent buffer overrun
		tree->value[80] = 0;
	sprintf(errmsg, "Unsupported show command '%s'", tree->value);
	maxinfo_send_error(dcb, 0, errmsg);
	MXS_NOTICE("%s", errmsg);
}
Esempio n. 6
0
/**
 * The module initialisation routine, called when the module
 * is first loaded.
 */
void
ModuleInit()
{
    MXS_NOTICE("Initialise the MySQL Galera Monitor module %s.", version_str);
}
Esempio n. 7
0
/**
 * The entry point for the monitoring module thread
 *
 * @param arg	The handle of the monitor
 */
static void
monitorMain(void *arg)
{
    MONITOR* mon = (MONITOR*) arg;
    GALERA_MONITOR *handle;
    MONITOR_SERVERS *ptr;
    size_t nrounds = 0;
    MONITOR_SERVERS *candidate_master = NULL;
    int master_stickiness;
    int is_cluster = 0;
    int log_no_members = 1;
    monitor_event_t evtype;

    spinlock_acquire(&mon->lock);
    handle = (GALERA_MONITOR *) mon->handle;
    spinlock_release(&mon->lock);
    master_stickiness = handle->disableMasterFailback;
    if (mysql_thread_init())
    {
        MXS_ERROR("mysql_thread_init failed in monitor module. Exiting.");
        return;
    }
    handle->status = MONITOR_RUNNING;

    while (1)
    {
        if (handle->shutdown)
        {
            handle->status = MONITOR_STOPPING;
            mysql_thread_end();
            handle->status = MONITOR_STOPPED;
            return;
        }
        /** Wait base interval */
        thread_millisleep(MON_BASE_INTERVAL_MS);
        /**
         * Calculate how far away the monitor interval is from its full
         * cycle and if monitor interval time further than the base
         * interval, then skip monitoring checks. Excluding the first
         * round.
         */

        if (nrounds != 0 && ((nrounds * MON_BASE_INTERVAL_MS) % mon->interval) >= MON_BASE_INTERVAL_MS)
        {
            nrounds += 1;
            continue;
        }

        nrounds += 1;

        /* reset cluster members counter */
        is_cluster = 0;

        ptr = mon->databases;

        while (ptr)
        {
            ptr->mon_prev_status = ptr->server->status;

            monitorDatabase(mon, ptr);

            /* Log server status change */
            if (mon_status_changed(ptr))
            {
                MXS_DEBUG("Backend server %s:%d state : %s",
                          ptr->server->name,
                          ptr->server->port,
                          STRSRVSTATUS(ptr->server));
            }

            if (!(SERVER_IS_RUNNING(ptr->server)) ||
                !(SERVER_IS_IN_CLUSTER(ptr->server)))
            {
                dcb_hangup_foreach(ptr->server);
            }

            if (SERVER_IS_DOWN(ptr->server))
            {
                /** Increase this server'e error count */
                dcb_hangup_foreach(ptr->server);
                ptr->mon_err_count += 1;

            }
            else
            {
                /** Reset this server's error count */
                ptr->mon_err_count = 0;
            }

            ptr = ptr->next;
        }

        /*
         * Let's select a master server:
         * it could be the candidate master following MIN(node_id) rule or
         * the server that was master in the previous monitor polling cycle
         * Decision depends on master_stickiness value set in configuration
         */

        /* get the candidate master, following MIN(node_id) rule */
        candidate_master = get_candidate_master(mon);

        /* Select the master, based on master_stickiness */
        if (1 == handle->disableMasterRoleSetting)
        {
            handle->master = NULL;
        }
        else
        {
            handle->master = set_cluster_master(handle->master, candidate_master, master_stickiness);
        }

        ptr = mon->databases;

        while (ptr)
        {
            const int repl_bits = (SERVER_SLAVE | SERVER_MASTER | SERVER_MASTER_STICKINESS);
            if (SERVER_IS_JOINED(ptr->server))
            {
                if (handle->master)
                {
                    if (ptr != handle->master)
                    {
                        /* set the Slave role and clear master stickiness */
                        server_clear_set_status(ptr->server, repl_bits, SERVER_SLAVE);
                    }
                    else
                    {
                        if (candidate_master &&
                            handle->master->server->node_id != candidate_master->server->node_id)
                        {
                            /* set master role and master stickiness */
                            server_clear_set_status(ptr->server, repl_bits,
                                                    (SERVER_MASTER | SERVER_MASTER_STICKINESS));
                        }
                        else
                        {
                            /* set master role and clear master stickiness */
                            server_clear_set_status(ptr->server, repl_bits, SERVER_MASTER);
                        }
                    }
                }
                is_cluster++;
            }
            else
            {
                server_clear_set_status(ptr->server, repl_bits, 0);
            }
            ptr = ptr->next;
        }

        if (is_cluster == 0 && log_no_members)
        {
            MXS_ERROR("There are no cluster members");
            log_no_members = 0;
        }
        else
        {
            if (is_cluster > 0 && log_no_members == 0)
            {
                MXS_NOTICE("Found cluster members");
                log_no_members = 1;
            }
        }


        ptr = mon->databases;

        while (ptr)
        {

            /** Execute monitor script if a server state has changed */
            if (mon_status_changed(ptr))
            {
                evtype = mon_get_event_type(ptr);
                if (isGaleraEvent(evtype))
                {
                    MXS_NOTICE("Server changed state: %s[%s:%u]: %s",
                             ptr->server->unique_name,
                             ptr->server->name, ptr->server->port,
                             mon_get_event_name(ptr));
                    if (handle->script && handle->events[evtype])
                    {
                        monitor_launch_script(mon, ptr, handle->script);
                    }
                }
            }
            ptr = ptr->next;
        }
    }
}
Esempio n. 8
0
/**
 * HTTTP daemon listener entry point
 *
 * @param       listener        The Listener DCB
 * @param       config          Configuration (ip:port)
 */
static int httpd_listen(DCB *listener, char *config)
{
    struct sockaddr_in addr;
    int one = 1;
    int rc;
    int syseno = 0;

    memcpy(&listener->func, &MyObject, sizeof(GWPROTOCOL));
    if (!parse_bindconfig(config, 6442, &addr))
    {
        return 0;
    }

    if ((listener->fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        return 0;
    }

    /* socket options */
    syseno = setsockopt(listener->fd,
                        SOL_SOCKET,
                        SO_REUSEADDR,
                        (char *)&one,
                        sizeof(one));

    if (syseno != 0)
    {
        char errbuf[STRERROR_BUFLEN];
        MXS_ERROR("Failed to set socket options. Error %d: %s",
                  errno, strerror_r(errno, errbuf, sizeof(errbuf)));
        return 0;
    }
    /* set NONBLOCKING mode */
    setnonblocking(listener->fd);

    /* bind address and port */
    if (bind(listener->fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
    {
        return 0;
    }

    rc = listen(listener->fd, SOMAXCONN);

    if (rc == 0)
    {
        MXS_NOTICE("Listening httpd connections at %s", config);
    }
    else
    {
        int eno = errno;
        errno = 0;
        char errbuf[STRERROR_BUFLEN];
        fprintf(stderr,
                "\n* Failed to start listening http due error %d, %s\n\n",
                eno,
                strerror_r(eno, errbuf, sizeof(errbuf)));
        return 0;
    }

    if (poll_add_dcb(listener) == -1)
    {
        return 0;
    }
    return 1;
}
Esempio n. 9
0
int load_config( char* fname)
{
	CONFIG* iter;
	CONFIG_ITEM* item;
	int config_ok = 1,inirval;
	free_filters();
	if((inirval = ini_parse(fname,handler,instance.conf)) < 0){
		printf("Error parsing configuration file!\n");
        if(inirval == -1)
            printf("Inih file open error.\n");
        else if(inirval == -2)
            printf("inih memory error.\n");
        MXS_ERROR("Error parsing configuration file!\n");
        config_ok = 0;
        goto cleanup;
	}
	if(instance.verbose){
		printf("Configuration loaded from %s\n\n",fname);
	}
	if(instance.conf == NULL){
		printf("Nothing valid was read from the file.\n");
		MXS_NOTICE("Nothing valid was read from the file.\n");
		config_ok = 0;
		goto cleanup;
	}

	instance.conf = process_config(instance.conf);
	if(instance.conf){
		if(instance.verbose){
			printf("Modules Loaded:\n");
		}
		iter = instance.conf;
	}else{
		printf("No filters found in the configuration file.\n");
		MXS_NOTICE("No filters found in the configuration file.\n");
		config_ok = 0;
		goto cleanup;
	}

	while(iter){
		item = iter->item;
		while(item){
      
			if(!strcmp("module",item->name)){

				if(instance.mod_dir){
					char* modstr = malloc(sizeof(char)*(strlen(instance.mod_dir) + strlen(item->value) + 1));
					strcpy(modstr,instance.mod_dir);
					strcat(modstr,"/");
					strcat(modstr,item->value);
					instance.head = load_filter_module(modstr);
					free(modstr);
				}else{
					instance.head = load_filter_module(item->value);
				}


				if(!instance.head || !load_filter(instance.head,instance.conf)){

					printf("Error creating filter instance!\nModule: %s\n",item->value);
					MXS_ERROR("Error creating filter instance!\nModule: %s\n",item->value);
					config_ok = 0;
					goto cleanup;

				}else{
					if(instance.verbose){
						printf("\t%s\n",iter->section);  
					}
				}
			}
			item = item->next;
		}
		iter = iter->next;
	}

	while(instance.conf){
		item = instance.conf->item;
		while(item){
			item = instance.conf->item;
			instance.conf->item = instance.conf->item->next;
			free(item->name);
			free(item->value);
			free(item);
			item = instance.conf->item;
		}
		instance.conf = instance.conf->next;
    
	}

	cleanup:
	while(instance.conf){
		iter = instance.conf;
		instance.conf = instance.conf->next;
		item = iter->item;

		while(item){      
			free(item->name);
			free(item->value);
			free(item);
			iter->item = iter->item->next;
			item = iter->item;
		}

		free(iter);
	}
	instance.conf = NULL;

	return config_ok;
}