mirror of
https://github.com/MariaDB/server.git
synced 2025-01-20 05:52:27 +01:00
383 lines
8 KiB
C++
383 lines
8 KiB
C++
#include "atrt.hpp"
|
|
#include <sys/types.h>
|
|
#include <dirent.h>
|
|
|
|
static bool create_directory(const char * path);
|
|
|
|
bool
|
|
setup_directories(atrt_config& config, int setup)
|
|
{
|
|
/**
|
|
* 0 = validate
|
|
* 1 = setup
|
|
* 2 = setup+clean
|
|
*/
|
|
for (size_t i = 0; i < config.m_clusters.size(); i++)
|
|
{
|
|
atrt_cluster& cluster = *config.m_clusters[i];
|
|
for (size_t j = 0; j<cluster.m_processes.size(); j++)
|
|
{
|
|
atrt_process& proc = *cluster.m_processes[j];
|
|
const char * dir = proc.m_proc.m_cwd.c_str();
|
|
struct stat sbuf;
|
|
int exists = 0;
|
|
if (lstat(dir, &sbuf) == 0)
|
|
{
|
|
if (S_ISDIR(sbuf.st_mode))
|
|
exists = 1;
|
|
else
|
|
exists = -1;
|
|
}
|
|
|
|
switch(setup){
|
|
case 0:
|
|
switch(exists){
|
|
case 0:
|
|
g_logger.error("Could not find directory: %s", dir);
|
|
return false;
|
|
case -1:
|
|
g_logger.error("%s is not a directory!", dir);
|
|
return false;
|
|
}
|
|
break;
|
|
case 1:
|
|
if (exists == -1)
|
|
{
|
|
g_logger.error("%s is not a directory!", dir);
|
|
return false;
|
|
}
|
|
break;
|
|
case 2:
|
|
if (exists == 1)
|
|
{
|
|
if (!remove_dir(dir))
|
|
{
|
|
g_logger.error("Failed to remove %s!", dir);
|
|
return false;
|
|
}
|
|
exists = 0;
|
|
break;
|
|
}
|
|
else if (exists == -1)
|
|
{
|
|
if (!unlink(dir))
|
|
{
|
|
g_logger.error("Failed to remove %s!", dir);
|
|
return false;
|
|
}
|
|
exists = 0;
|
|
}
|
|
}
|
|
if (exists != 1)
|
|
{
|
|
if (!create_directory(dir))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static
|
|
void
|
|
printfile(FILE* out, Properties& props, const char * section, ...)
|
|
{
|
|
Properties::Iterator it (&props);
|
|
const char * name = it.first();
|
|
if (name)
|
|
{
|
|
va_list ap;
|
|
va_start(ap, section);
|
|
/* const int ret = */ vfprintf(out, section, ap);
|
|
va_end(ap);
|
|
fprintf(out, "\n");
|
|
|
|
for (; name; name = it.next())
|
|
{
|
|
const char* val;
|
|
props.get(name, &val);
|
|
fprintf(out, "%s %s\n", name + 2, val);
|
|
}
|
|
fprintf(out, "\n");
|
|
}
|
|
fflush(out);
|
|
}
|
|
|
|
bool
|
|
setup_files(atrt_config& config, int setup, int sshx)
|
|
{
|
|
/**
|
|
* 0 = validate
|
|
* 1 = setup
|
|
* 2 = setup+clean
|
|
*/
|
|
BaseString mycnf;
|
|
mycnf.assfmt("%s/my.cnf", g_basedir);
|
|
|
|
if (mycnf != g_my_cnf)
|
|
{
|
|
struct stat sbuf;
|
|
int ret = lstat(mycnf.c_str(), &sbuf);
|
|
|
|
if (ret == 0)
|
|
{
|
|
if (unlink(mycnf.c_str()) != 0)
|
|
{
|
|
g_logger.error("Failed to remove %s", mycnf.c_str());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
BaseString cp = "cp ";
|
|
cp.appfmt("%s %s", g_my_cnf, mycnf.c_str());
|
|
if (system(cp.c_str()) != 0)
|
|
{
|
|
g_logger.error("Failed to '%s'", cp.c_str());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (setup == 2 || config.m_generated)
|
|
{
|
|
/**
|
|
* Do mysql_install_db
|
|
*/
|
|
for (size_t i = 0; i < config.m_clusters.size(); i++)
|
|
{
|
|
atrt_cluster& cluster = *config.m_clusters[i];
|
|
for (size_t j = 0; j<cluster.m_processes.size(); j++)
|
|
{
|
|
atrt_process& proc = *cluster.m_processes[j];
|
|
if (proc.m_type == atrt_process::AP_MYSQLD)
|
|
{
|
|
const char * val;
|
|
require(proc.m_options.m_loaded.get("--datadir=", &val));
|
|
BaseString tmp;
|
|
tmp.assfmt("%s/bin/mysql_install_db --datadir=%s > /dev/null 2>&1",
|
|
g_prefix, val);
|
|
if (system(tmp.c_str()) != 0)
|
|
{
|
|
g_logger.error("Failed to mysql_install_db for %s",
|
|
proc.m_proc.m_cwd.c_str());
|
|
}
|
|
else
|
|
{
|
|
g_logger.info("mysql_install_db for %s",
|
|
proc.m_proc.m_cwd.c_str());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
FILE * out = NULL;
|
|
if (config.m_generated == false)
|
|
{
|
|
g_logger.info("Nothing configured...");
|
|
}
|
|
else
|
|
{
|
|
out = fopen(mycnf.c_str(), "a+");
|
|
if (out == 0)
|
|
{
|
|
g_logger.error("Failed to open %s for append", mycnf.c_str());
|
|
return false;
|
|
}
|
|
time_t now = time(0);
|
|
fprintf(out, "#\n# Generated by atrt\n");
|
|
fprintf(out, "# %s\n", ctime(&now));
|
|
}
|
|
|
|
for (size_t i = 0; i < config.m_clusters.size(); i++)
|
|
{
|
|
atrt_cluster& cluster = *config.m_clusters[i];
|
|
if (out)
|
|
{
|
|
Properties::Iterator it(&cluster.m_options.m_generated);
|
|
printfile(out, cluster.m_options.m_generated,
|
|
"[mysql_cluster%s]", cluster.m_name.c_str());
|
|
}
|
|
|
|
for (size_t j = 0; j<cluster.m_processes.size(); j++)
|
|
{
|
|
atrt_process& proc = *cluster.m_processes[j];
|
|
|
|
if (out)
|
|
{
|
|
switch(proc.m_type){
|
|
case atrt_process::AP_NDB_MGMD:
|
|
printfile(out, proc.m_options.m_generated,
|
|
"[cluster_config.ndb_mgmd.%d%s]",
|
|
proc.m_index, proc.m_cluster->m_name.c_str());
|
|
break;
|
|
case atrt_process::AP_NDBD:
|
|
printfile(out, proc.m_options.m_generated,
|
|
"[cluster_config.ndbd.%d%s]",
|
|
proc.m_index, proc.m_cluster->m_name.c_str());
|
|
break;
|
|
case atrt_process::AP_MYSQLD:
|
|
printfile(out, proc.m_options.m_generated,
|
|
"[mysqld.%d%s]",
|
|
proc.m_index, proc.m_cluster->m_name.c_str());
|
|
break;
|
|
case atrt_process::AP_NDB_API:
|
|
break;
|
|
case atrt_process::AP_CLIENT:
|
|
printfile(out, proc.m_options.m_generated,
|
|
"[client.%d%s]",
|
|
proc.m_index, proc.m_cluster->m_name.c_str());
|
|
break;
|
|
case atrt_process::AP_ALL:
|
|
case atrt_process::AP_CLUSTER:
|
|
abort();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create env.sh
|
|
*/
|
|
BaseString tmp;
|
|
tmp.assfmt("%s/env.sh", proc.m_proc.m_cwd.c_str());
|
|
char **env = BaseString::argify(0, proc.m_proc.m_env.c_str());
|
|
if (env[0])
|
|
{
|
|
Vector<BaseString> keys;
|
|
FILE *fenv = fopen(tmp.c_str(), "w+");
|
|
if (fenv == 0)
|
|
{
|
|
g_logger.error("Failed to open %s for writing", tmp.c_str());
|
|
return false;
|
|
}
|
|
for (size_t k = 0; env[k]; k++)
|
|
{
|
|
tmp = env[k];
|
|
int pos = tmp.indexOf('=');
|
|
require(pos > 0);
|
|
env[k][pos] = 0;
|
|
fprintf(fenv, "%s=\"%s\"\n", env[k], env[k]+pos+1);
|
|
keys.push_back(env[k]);
|
|
free(env[k]);
|
|
}
|
|
fprintf(fenv, "PATH=%s/bin:%s/libexec:$PATH\n", g_prefix, g_prefix);
|
|
keys.push_back("PATH");
|
|
for (size_t k = 0; k<keys.size(); k++)
|
|
fprintf(fenv, "export %s\n", keys[k].c_str());
|
|
fflush(fenv);
|
|
fclose(fenv);
|
|
}
|
|
free(env);
|
|
|
|
tmp.assfmt("%s/ssh-login.sh", proc.m_proc.m_cwd.c_str());
|
|
FILE* fenv = fopen(tmp.c_str(), "w+");
|
|
if (fenv == 0)
|
|
{
|
|
g_logger.error("Failed to open %s for writing", tmp.c_str());
|
|
return false;
|
|
}
|
|
fprintf(fenv, "#!/bin/sh\n");
|
|
fprintf(fenv, "cd %s\n", proc.m_proc.m_cwd.c_str());
|
|
fprintf(fenv, "[ -f /etc/profile ] && . /etc/profile\n");
|
|
fprintf(fenv, ". env.sh\n");
|
|
fprintf(fenv, "ulimit -Sc unlimited\n");
|
|
fprintf(fenv, "bash -i");
|
|
fflush(fenv);
|
|
fclose(fenv);
|
|
}
|
|
}
|
|
|
|
if (out)
|
|
{
|
|
fflush(out);
|
|
fclose(out);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
static
|
|
bool
|
|
create_directory(const char * path)
|
|
{
|
|
BaseString tmp(path);
|
|
Vector<BaseString> list;
|
|
if (tmp.split(list, "/") == 0)
|
|
{
|
|
g_logger.error("Failed to create directory: %s", tmp.c_str());
|
|
return false;
|
|
}
|
|
|
|
BaseString cwd = "/";
|
|
for (size_t i = 0; i < list.size(); i++)
|
|
{
|
|
cwd.append(list[i].c_str());
|
|
cwd.append("/");
|
|
mkdir(cwd.c_str(), S_IRUSR | S_IWUSR | S_IXUSR | S_IXGRP | S_IRGRP);
|
|
}
|
|
|
|
struct stat sbuf;
|
|
if (lstat(path, &sbuf) != 0 ||
|
|
!S_ISDIR(sbuf.st_mode))
|
|
{
|
|
g_logger.error("Failed to create directory: %s (%s)",
|
|
tmp.c_str(),
|
|
cwd.c_str());
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
remove_dir(const char * path, bool inclusive)
|
|
{
|
|
DIR* dirp = opendir(path);
|
|
|
|
if (dirp == 0)
|
|
{
|
|
if(errno != ENOENT)
|
|
{
|
|
g_logger.error("Failed to remove >%s< errno: %d %s",
|
|
path, errno, strerror(errno));
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
struct dirent * dp;
|
|
BaseString name = path;
|
|
name.append("/");
|
|
while ((dp = readdir(dirp)) != NULL)
|
|
{
|
|
if ((strcmp(".", dp->d_name) != 0) && (strcmp("..", dp->d_name) != 0))
|
|
{
|
|
BaseString tmp = name;
|
|
tmp.append(dp->d_name);
|
|
|
|
if (remove(tmp.c_str()) == 0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (!remove_dir(tmp.c_str()))
|
|
{
|
|
closedir(dirp);
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
closedir(dirp);
|
|
if (inclusive)
|
|
{
|
|
if (rmdir(path) != 0)
|
|
{
|
|
g_logger.error("Failed to remove >%s< errno: %d %s",
|
|
path, errno, strerror(errno));
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|