Commit d1de65bb authored by bouda1's avatar bouda1 Committed by Matthieu Kermagoret
Browse files

New option --log-file in connectors (#4)

feat(perl,ssh): add --log-file option to connectors.
parent ab61cf2e
......@@ -256,6 +256,12 @@ if (WITH_TESTING)
"${TEST_DIR}/connector/execute_single_script.cc")
target_link_libraries("${TEST_NAME}" ${TEST_LIBRARIES})
add_test("${TEST_NAME}" "${TEST_NAME}")
# Single script execution with log file.
set(TEST_NAME "connector_execute_single_script_log_file")
add_executable("${TEST_NAME}"
"${TEST_DIR}/connector/execute_single_script_log_file.cc")
target_link_libraries("${TEST_NAME}" ${TEST_LIBRARIES})
add_test("${TEST_NAME}" "${TEST_NAME}")
# Multiple script execution.
set(TEST_NAME "connector_execute_multiple_scripts")
add_executable("${TEST_NAME}"
......
......@@ -68,7 +68,7 @@ int main(int argc, char** argv, char** env) {
int retval(EXIT_FAILURE);
// Log object.
logging::file log_file(stderr);
logging::file* log_file = NULL;
try {
// Initializations.
......@@ -99,21 +99,29 @@ int main(int argc, char** argv, char** env) {
}
else {
// Set logging object.
if (opts.get_argument("log-file").get_is_set()) {
std::string filename(
opts.get_argument("log-file").get_value());
log_file = new logging::file(filename);
}
else
log_file = new logging::file(stderr);
if (opts.get_argument("debug").get_is_set()) {
log_file.show_pid(true);
log_file.show_thread_id(true);
log_file->show_pid(true);
log_file->show_thread_id(true);
logging::engine::instance().add(
&log_file,
log_file,
logging::type_debug
| logging::type_info
| logging::type_error,
logging::high);
}
else {
log_file.show_pid(false);
log_file.show_thread_id(false);
log_file->show_pid(false);
log_file->show_thread_id(false);
logging::engine::instance().add(
&log_file,
log_file,
logging::type_info | logging::type_error,
logging::low);
}
......@@ -148,6 +156,8 @@ int main(int argc, char** argv, char** env) {
multiplexer::unload();
pipe_handle::unload();
clib::unload();
if (log_file)
delete log_file;
return (retval);
}
......@@ -30,6 +30,8 @@ static char const* const help_description
= "Print help and exit.";
static char const* const version_description
= "Print software version and exit.";
static char const* const log_file_description
= "Specifies the log file (default: stderr).";
/**************************************
* *
......@@ -154,5 +156,14 @@ void options::_init() {
arg.set_description(version_description);
}
// Log file.
{
misc::argument& arg(_arguments['l']);
arg.set_name('l');
arg.set_long_name("log-file");
arg.set_description(log_file_description);
arg.set_has_value(true);
}
return ;
}
/*
** Copyright 2012-2013 Centreon
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
**
** For more information : contact@centreon.com
*/
#include <cstring>
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include "com/centreon/clib.hh"
#include "com/centreon/exceptions/basic.hh"
#include "com/centreon/io/file_stream.hh"
#include "com/centreon/process.hh"
#include "test/connector/misc.hh"
#include "test/connector/paths.hh"
#define LOG_FILE "/tmp/toto"
using namespace com::centreon;
#define CMD1 "2\0" \
"4242\0" \
"5\0" \
"123456789\0"
#define CMD2 "\0\0\0\0"
#define RESULT "3\0" \
"4242\0" \
"1\0" \
"0\0" \
" \0" \
"Centreon is wonderful\n\0\0\0\0"
/**
* Check that connector can execute a script with a log file.
* The goal is first to verify the log file is well written.
*
* @return 0 on success.
*/
int main() {
// If the log file exists, we remove it.
std::ifstream f(LOG_FILE);
if (f.good()) {
f.close();
remove(LOG_FILE);
}
clib::load();
// Write Perl script.
std::string script_path(io::file_stream::temp_path());
write_file(
script_path.c_str(),
"#!/usr/bin/perl\n" \
"\n" \
"print \"Centreon is wonderful\\n\";\n" \
"exit 0;\n");
// Process.
process p;
p.enable_stream(process::in, true);
p.enable_stream(process::out, true);
p.exec(CONNECTOR_PERL_BINARY " --log-file " LOG_FILE);
// Write command.
std::ostringstream oss;
oss.write(CMD1, sizeof(CMD1) - 1);
oss << script_path;
oss.write(CMD2, sizeof(CMD2) - 1);
std::string cmd(oss.str());
char const* ptr(cmd.c_str());
unsigned int size(cmd.size());
while (size > 0) {
unsigned int rb(p.write(ptr, size));
size -= rb;
ptr += rb;
}
p.enable_stream(process::in, false);
// Read reply.
std::string output;
while (true) {
std::string buffer;
p.read(buffer);
if (buffer.empty())
break;
output.append(buffer);
}
// Wait for process termination.
int retval(1);
if (!p.wait(5000)) {
p.terminate();
p.wait();
}
else
retval = (p.exit_code() != 0);
// Remove temporary files.
remove(script_path.c_str());
clib::unload();
try {
if (retval)
throw (basic_error() << "invalid return code: " << retval);
if (output.size() != (sizeof(RESULT) - 1)
|| memcmp(output.c_str(), RESULT, sizeof(RESULT) - 1))
throw (basic_error()
<< "invalid output: size=" << output.size()
<< ", output=" << replace_null(output));
std::string line;
std::ifstream file(LOG_FILE);
if (file.is_open()) {
getline(file, line);
if (line.find("[info] Centreon Perl Connector " CENTREON_CONNECTOR_PERL_VERSION " starting") == std::string::npos)
throw (basic_error()
<< "bad content: the first line does not start with 'Centreon Perl Connector " CENTREON_CONNECTOR_PERL_VERSION " starting'");
file.close();
}
else {
throw (basic_error()
<< "the file " LOG_FILE " has not been created.");
}
}
catch (std::exception const& e) {
retval = 1;
std::cerr << "error: " << e.what() << std::endl;
}
return retval;
}
......@@ -593,6 +593,12 @@ if (WITH_TESTING)
"${TEST_DIR}/connector/command_execute.cc")
target_link_libraries("${TEST_NAME}" ${TEST_LIBRARIES})
add_test("${TEST_NAME}" "${TEST_NAME}")
# Execute command with a log file
set(TEST_NAME "connector_command_execute_log_file")
add_executable("${TEST_NAME}"
"${TEST_DIR}/connector/command_execute_log_file.cc")
target_link_libraries("${TEST_NAME}" ${TEST_LIBRARIES})
add_test("${TEST_NAME}" "${TEST_NAME}")
# Non-existent host.
set(TEST_NAME "connector_non_existent_host")
add_executable("${TEST_NAME}"
......
......@@ -77,7 +77,7 @@ int main(int argc, char* argv[]) {
int retval(EXIT_FAILURE);
// Log object.
logging::file log_file(stderr);
logging::file* log_file = NULL;
try {
// Initializations.
......@@ -104,21 +104,29 @@ int main(int argc, char* argv[]) {
}
else {
// Set logging object.
if (opts.get_argument("log-file").get_is_set()) {
std::string filename(
opts.get_argument("log-file").get_value());
log_file = new logging::file(filename);
}
else
log_file = new logging::file(stderr);
if (opts.get_argument("debug").get_is_set()) {
log_file.show_pid(true);
log_file.show_thread_id(true);
log_file->show_pid(true);
log_file->show_thread_id(true);
logging::engine::instance().add(
&log_file,
log_file,
logging::type_debug
| logging::type_info
| logging::type_error,
logging::high);
}
else {
log_file.show_pid(false);
log_file.show_thread_id(false);
log_file->show_pid(false);
log_file->show_thread_id(false);
logging::engine::instance().add(
&log_file,
log_file,
logging::type_info | logging::type_error,
logging::low);
}
......@@ -128,6 +136,11 @@ int main(int argc, char* argv[]) {
// Initialize libssh2.
log_debug(logging::medium) << "initializing libssh2";
# ifdef LIBSSH2_WITH_LIBGCRYPT
// FIXME DBR: needed or not needed ??
// Version check should be the very first call because it
// makes sure that important subsystems are initialized.
if (!gcry_check_version(GCRYPT_VERSION))
throw (basic_error() << "libgcrypt version mismatch: ");
gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
# endif // LIBSSH2_WITH_LIBGCRYPT
if (libssh2_init(0))
......@@ -164,6 +177,8 @@ int main(int argc, char* argv[]) {
// Deinitializations.
multiplexer::unload();
logging::engine::unload();
if (log_file)
delete log_file;
return (retval);
}
......@@ -29,6 +29,8 @@ static char const* const help_description
= "Print help and exit.";
static char const* const version_description
= "Print software version and exit.";
static char const* const log_file_description
= "Specifies the log file (default: stderr).";
/**************************************
* *
......@@ -79,6 +81,7 @@ std::string options::help() const {
<< " --debug " << debug_description << "\n"
<< " --help " << help_description << "\n"
<< " --version " << version_description << "\n"
<< " --log-file " << log_file_description << "\n"
<< "\n"
<< "Commands must be sent on the connector's standard input.\n"
<< "They must be sent using Centreon Connector protocol version\n"
......@@ -143,5 +146,14 @@ void options::_init() {
arg.set_description(version_description);
}
// Log file.
{
misc::argument& arg(_arguments['l']);
arg.set_name('l');
arg.set_long_name("log-file");
arg.set_description(log_file_description);
arg.set_has_value(true);
}
return ;
}
......@@ -263,8 +263,10 @@ void policy::on_result(checks::result const& r) {
end = _checks.end();
it != end;
++it)
if (it->second.second == sess)
if (it->second.second == sess) {
found = true;
break;
}
if (!found) {
std::map<sessions::credentials, sessions::session*>::iterator
it, end;
......
......@@ -591,9 +591,16 @@ void session::_startup() {
libssh2_session_set_blocking(_session, 0);
// Exchange banners, keys, setup crypto, compression, ...
#if LIBSSH2_VERSION_NUM >= 0x010208
// libssh2_session_startup deprecated in version 1.2.8 and later
int retval(libssh2_session_handshake(
_session,
_socket.get_native_handle()));
#else
int retval(libssh2_session_startup(
_session,
_socket.get_native_handle()));
#endif
if (retval) {
if (retval != LIBSSH2_ERROR_EAGAIN) { // Fatal failure.
char* msg;
......
/*
** Copyright 2012-2013 Centreon
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
**
** For more information : contact@centreon.com
*/
#include <cstring>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include "com/centreon/clib.hh"
#include "com/centreon/exceptions/basic.hh"
#include "com/centreon/process.hh"
#include "test/connector/binary.hh"
#define LOG_FILE "/tmp/toto"
using namespace com::centreon;
#define CMD1 "2\0" \
"4242\0" \
"5\0" \
"123456789\0" \
"check_by_ssh " \
"-H localhost " \
" -C 'echo Bonjour'\0\0\0\0"
#define RESULT "3\0" \
"4242\0" \
"1\0" \
"0\0" \
" \0" \
"Bonjour\n\0\0\0\0"
/**
* Replace null char by string "\0".
*
* @param[in, out] str The string to replace.
*
* @return The replace string.
*/
std::string& replace_null(std::string& str) {
size_t pos(0);
while ((pos = str.find('\0', pos)) != std::string::npos)
str.replace(pos++, 1, "\\0");
return (str);
}
/**
* Check that connector respond properly to version command.
*
* @return 0 on success.
*/
int main() {
std::ifstream f(LOG_FILE);
if (f.good()) {
f.close();
remove(LOG_FILE);
}
clib::load();
// Process.
process p;
p.enable_stream(process::in, true);
p.enable_stream(process::out, true);
p.exec(CONNECTOR_SSH_BINARY " --log-file " LOG_FILE);
// Write command.
std::ostringstream oss;
oss.write(CMD1, sizeof(CMD1) - 1);
std::string cmd(oss.str());
char const* ptr(cmd.c_str());
unsigned int size(cmd.size());
while (size > 0) {
unsigned int rb(p.write(ptr, size));
size -= rb;
ptr += rb;
}
p.enable_stream(process::in, false);
// Read reply.
std::string output;
while (true) {
std::string buffer;
p.read(buffer);
if (buffer.empty())
break;
output.append(buffer);
}
// Wait for process termination.
int retval(1);
if (!p.wait(5000)) {
p.terminate();
p.wait();
}
else
retval = (p.exit_code() != 0);
clib::unload();
try {
if (retval)
throw (basic_error() << "invalid return code: " << retval);
if (output.size() != (sizeof(RESULT) - 1)
|| memcmp(output.c_str(), RESULT, sizeof(RESULT) - 1))
throw (basic_error()
<< "invalid output: size=" << output.size()
<< ", output=" << replace_null(output));
std::string line;
std::ifstream file(LOG_FILE);
if (file.is_open()) {
getline(file, line);
if (line.find("[info] Centreon SSH Connector " CENTREON_CONNECTOR_SSH_VERSION " starting") == std::string::npos)
throw (basic_error()
<< "bad content: the first line does not start with 'Centreon SSH Connector " CENTREON_CONNECTOR_SSH_VERSION " starting'");
file.close();
}
else {
throw (basic_error()
<< "the file " LOG_FILE " has not been created.");
}
}
catch (std::exception const& e) {
retval = 1;
std::cerr << "error: " << e.what() << std::endl;
}
return retval;
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment