// ----------------------------------------------------------------------
// File: com_daemon.cc
// Author: Andreas-Joachim Peters - CERN
// ----------------------------------------------------------------------
/************************************************************************
* EOS - the CERN Disk Storage System *
* Copyright (C) 2021 CERN/Switzerland *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see .*
************************************************************************/
/*----------------------------------------------------------------------------*/
#include "console/ConsoleMain.hh"
#include "console/commands/ICmdHelper.hh"
#include "common/StringTokenizer.hh"
#include "common/Config.hh"
#include "common/Path.hh"
#include "common/SymKeys.hh"
/*----------------------------------------------------------------------------*/
#include
#include
#include
#include
#include
#include
#include
/*----------------------------------------------------------------------------*/
#ifdef __APPLE__
#define EOS_PTRACE_TRACEME PT_TRACEME
#define EOS_PTRACE_ATTACH PT_ATTACH
#define EOS_PTRACE_DETACH PT_DETACH
#else
#define EOS_PTRACE_TRACEME PTRACE_TRACEME
#define EOS_PTRACE_ATTACH PTRACE_ATTACH
#define EOS_PTRACE_DETACH PTRACE_DETACH
#endif //__APPLE__
/* Steer a service */
int
com_daemon(char* arg)
{
#ifdef __APPLE__
fprintf(stderr,"error: daemon command is not support on OSX\n");
global_retc = EINVAL;
return (0);
#else
eos::common::StringTokenizer subtokenizer(arg);
eos::common::Config cfg;
XrdOucString option = "";
XrdOucString name = "";
XrdOucString service = "";
XrdOucString subcmd;
XrdOucString modules;
std::vector mods;
std::string chapter;
std::string executable;
std::string pidfile;
std::string envfile;
std::string cfile;
bool ok = false;
subtokenizer.GetLine();
if (wants_help(arg)) {
goto com_daemon_usage;
}
option = subtokenizer.GetToken();
if (!option.length()) {
goto com_daemon_usage;
}
if (option == "sss") {
subcmd = subtokenizer.GetToken();
if (!subcmd.length()) {
goto com_daemon_usage;
}
if (subcmd == "recreate") {
if (geteuid()) {
std::cerr << "error: you have to run this command as root!" << std::endl;
global_retc = EPERM;
return (0);
}
struct stat buf;
std::cout << "info: you are going to (re-)create the instance sss key. A previous key will be moved to /etc/eos.keytab." << std::endl;
if (!::stat("/etc/eos.keytab",&buf)) {
std::string oldkeytab = "/etc/eos.keytab.";
oldkeytab += std::to_string(time(NULL));
if (::rename("/etc/eos.keytab", oldkeytab.c_str())) {
std::cerr << "error: renaming of existing old keytab file /etc/eos.keytab failed!" << std::endl;
global_retc = errno;
return (0);
}
}
bool interactive = false;
if (isatty(STDOUT_FILENO)) {
interactive = true;
}
if (!interactive || ICmdHelper::ConfirmOperation()) {
if (!::stat("/opt/eos/xrootd/bin/xrdsssadmin",&buf)) {
system("yes | /opt/eos/xrootd/bin/xrdsssadmin -u daemon -g daemon -k eosmaster add /etc/eos.keytab");
system("yes | /opt/eos/xrootd/bin/xrdsssadmin -u eosnobody -g eosnobody -k eosnobody add /etc/eos.keytab");
} else {
system("yes | xrdsssadmin -u daemon -g daemon -k eosmaster add /etc/eos.keytab");
system("yes | xrdsssadmin -u eosnobody -g eosnobody -k eosnobody add /etc/eos.keytab");
}
system("mkdir -p /etc/eos/; cat /etc/eos.keytab | grep eosnobody > /etc/eos/fuse.sss.keytab; chmod 400 /etc/eos/fuse.sss.keytab");
std::cout << "info: recreated /etc/eos.keytab /etc/eos/fuse.sss.keytab" << std::endl;
} else {
global_retc = EINVAL;
return (0);
}
return (0);
}
}
if (option == "seal") {
XrdOucString toseal = subtokenizer.GetToken();
XrdOucString sealed;
std::string key;
if (!toseal.length()) {
return (0);
}
if (toseal.beginswith("/")) {
// treat it as a file
std::string contents;
eos::common::StringConversion::LoadFileIntoString(toseal.c_str(),contents);
toseal = contents.c_str();
}
const char* pkey = subtokenizer.GetToken();
if (!pkey) {
key = eos::common::StringConversion::StringFromShellCmd("cat /etc/eos.keytab | grep u:daemon | md5sum");
} else {
key = pkey;
}
std::string shakey = eos::common::SymKey::Sha256(key);
eos::common::SymKey::SymmetricStringEncrypt(toseal, sealed, (char*)shakey.c_str());
fprintf(stderr,"enc:%s\n", sealed.c_str());
return (0);
}
if ( (option != "run") &&
(option != "config" ) &&
(option != "stack" ) &&
(option != "stop" ) &&
(option != "kill") &&
(option != "module-init")) {
goto com_daemon_usage;
}
service = subtokenizer.GetToken();
if ((!service.length()) ||
(( service != "mgm") &&
( service != "mq") &&
( service != "fst") &&
( service != "qdb")) ){
goto com_daemon_usage;
}
name = subtokenizer.GetToken();
if (!name.length()) {
name = service.c_str();
}
modules = name;
modules += ".modules";
executable = "eos-"; executable += service.c_str();
envfile = "/var/run/eos/"; envfile += executable.c_str() ; envfile += "."; envfile += name.c_str(); envfile += ".env";
pidfile = "/var/run/eos/xrd."; pidfile += service.c_str(); pidfile += ".";
pidfile += name.c_str();
pidfile += ".pid";
cfg.Load("generic","all");
ok |= cfg.ok();
cfg.Load(service.c_str(), name.c_str(), false);
ok |= cfg.ok();
// this might fail if there are no modules
cfg.Load(service.c_str(), modules.c_str(), false);
{
// load all the modules:
eos::common::StringConversion::Tokenize(cfg.Dump("modules", true), mods, "\n");
for ( size_t i=0; i [name] [subcmd] : \n");
fprintf(stdout,
" := mq | mgm | fst | qdb\n");
fprintf(stdout,
" config - configure a service / show configuration\n");
fprintf(stdout,
" kill - kill -9 a given service\n");
fprintf(stdout,
" run - run the given service daemon optionally identified by name\n");
fprintf(stdout,
" sss recreate - re-create an instance sss key and the eosnobody keys (/etc/eos.keytab,/etc/eos/fuse.sss.keytab)'\n");
fprintf(stdout,
" stack - print an 'eu-stack'\n");
fprintf(stdout,
" stop - kill -15 a given service\n");
fprintf(stdout,
" module-init - run the init procedure for a module\n");
fprintf(stdout,"\n");
fprintf(stdout,
" examples: eos daemon config qdb qdb coup - try to make instance [qdb] a leader of QDB\n");
fprintf(stdout,
" eos daemon config qdb qdb info - show raft-info for the [qdb] QDB instance\n");
fprintf(stdout,
" eos daemon config qdb qdb remove host:port - remove a member of the qdb cluster\n");
fprintf(stdout,
" eos daemon config qdb qdb add host:port - add an observer to the qdb cluster\n");
fprintf(stdout,
" eos daemon config qdb qdb promote host:port - promote an observer to a full member of the qdb cluster\n");
fprintf(stdout,
" eos daemon config qdb qdb new observer - create a new observer\n");
fprintf(stdout,
" eos daemon config fst fst.1 - show the init,sysconfig and xrootd config for the [fst.1] FST service\n");
fprintf(stdout,
" eos daemon kill mq - shoot the MQ service with signal -9\n");
fprintf(stdout,
" eos daemon stop mq - gracefully shut down the MQ service with signal -15\n");
fprintf(stdout,
" eos daemon stack mgm - take an 'eu-stack' of the MGM service\n");
fprintf(stdout,
" eos daemon run fst fst.1 - run the fst.1 subservice FST\n");
global_retc = EINVAL;
return (0);
#endif
}