Execution filter support
This commit is contained in:
Родитель
988e8d8d5d
Коммит
31b1eab09d
|
@ -45,7 +45,7 @@
|
|||
<Add option="-fexceptions" />
|
||||
<Add option="-Wno-unused-local-typedefs" />
|
||||
<Add option="-std=c++1y" />
|
||||
<Add directory="../../hpccasa/Release/include" />
|
||||
<Add directory="../../evancasa/cpprestsdk/Release/include" />
|
||||
<Add directory="../../spdlog/include" />
|
||||
</Compiler>
|
||||
<Unit filename="Readme.txt" />
|
||||
|
@ -111,6 +111,8 @@
|
|||
<Unit filename="data/TaskInfo.h" />
|
||||
<Unit filename="data/Umid.cpp" />
|
||||
<Unit filename="data/Umid.h" />
|
||||
<Unit filename="filters/ExecutionFilter.cpp" />
|
||||
<Unit filename="filters/ExecutionFilter.h" />
|
||||
<Unit filename="main.cpp" />
|
||||
<Unit filename="makefile" />
|
||||
<Unit filename="scripts/CleanupAllTasks.sh" />
|
||||
|
@ -122,6 +124,8 @@
|
|||
<Unit filename="scripts/Statistics.sh" />
|
||||
<Unit filename="scripts/WaitForTrust.sh" />
|
||||
<Unit filename="scripts/common.sh" />
|
||||
<Unit filename="test/ExecutionFilterTest.cpp" />
|
||||
<Unit filename="test/ExecutionFilterTest.h" />
|
||||
<Unit filename="test/ProcessTest.cpp" />
|
||||
<Unit filename="test/ProcessTest.h" />
|
||||
<Unit filename="test/TestRunner.cpp" />
|
||||
|
|
|
@ -251,25 +251,26 @@
|
|||
<sstream>
|
||||
"String.h"
|
||||
|
||||
1427353132 /home/evanc/spdlog/include/spdlog/spdlog.h
|
||||
1440745033 /home/evanc/spdlog/include/spdlog/spdlog.h
|
||||
"tweakme.h"
|
||||
"common.h"
|
||||
"logger.h"
|
||||
"details/spdlog_impl.h"
|
||||
|
||||
1427353132 /home/evanc/spdlog/include/spdlog/common.h
|
||||
1440745033 /home/evanc/spdlog/include/spdlog/common.h
|
||||
<string>
|
||||
<initializer_list>
|
||||
<chrono>
|
||||
<memory>
|
||||
|
||||
1427353132 /home/evanc/spdlog/include/spdlog/logger.h
|
||||
1440745033 /home/evanc/spdlog/include/spdlog/logger.h
|
||||
<vector>
|
||||
<memory>
|
||||
"sinks/base_sink.h"
|
||||
"common.h"
|
||||
"./details/logger_impl.h"
|
||||
|
||||
1427353132 /home/evanc/spdlog/include/spdlog/sinks/base_sink.h
|
||||
1440745033 /home/evanc/spdlog/include/spdlog/sinks/base_sink.h
|
||||
<string>
|
||||
<mutex>
|
||||
<atomic>
|
||||
|
@ -278,14 +279,15 @@
|
|||
"../common.h"
|
||||
"../details/log_msg.h"
|
||||
|
||||
1427353132 /home/evanc/spdlog/include/spdlog/sinks/sink.h
|
||||
1440745033 /home/evanc/spdlog/include/spdlog/sinks/sink.h
|
||||
"../details/log_msg.h"
|
||||
|
||||
1427353132 /home/evanc/spdlog/include/spdlog/details/log_msg.h
|
||||
1440745033 /home/evanc/spdlog/include/spdlog/details/log_msg.h
|
||||
<thread>
|
||||
"../common.h"
|
||||
"./format.h"
|
||||
|
||||
1427353132 /home/evanc/spdlog/include/spdlog/details/format.h
|
||||
1440745033 /home/evanc/spdlog/include/spdlog/details/format.h
|
||||
<stdint.h>
|
||||
<cassert>
|
||||
<cmath>
|
||||
|
@ -296,12 +298,13 @@
|
|||
<stdexcept>
|
||||
<string>
|
||||
<sstream>
|
||||
<map>
|
||||
<iterator>
|
||||
<intrin.h>
|
||||
<utility>
|
||||
"format.cc"
|
||||
|
||||
1427353132 /home/evanc/spdlog/include/spdlog/details/format.cc
|
||||
1440745033 /home/evanc/spdlog/include/spdlog/details/format.cc
|
||||
"format.h"
|
||||
<string.h>
|
||||
<cctype>
|
||||
|
@ -311,12 +314,13 @@
|
|||
<cstdarg>
|
||||
<cstring>
|
||||
<windows.h>
|
||||
<windows.h>
|
||||
|
||||
1427353132 /home/evanc/spdlog/include/spdlog/formatter.h
|
||||
"details/log_msg.h"
|
||||
"details/pattern_formatter_impl.h"
|
||||
|
||||
1427353132 /home/evanc/spdlog/include/spdlog/details/pattern_formatter_impl.h
|
||||
1440745033 /home/evanc/spdlog/include/spdlog/details/pattern_formatter_impl.h
|
||||
<string>
|
||||
<chrono>
|
||||
<memory>
|
||||
|
@ -326,37 +330,42 @@
|
|||
"./log_msg.h"
|
||||
"./os.h"
|
||||
|
||||
1427353132 /home/evanc/spdlog/include/spdlog/details/os.h
|
||||
1440745033 /home/evanc/spdlog/include/spdlog/details/os.h
|
||||
<string>
|
||||
<cstdio>
|
||||
<ctime>
|
||||
<Windows.h>
|
||||
<share.h>
|
||||
<sys/syscall.h>
|
||||
<unistd.h>
|
||||
<thread>
|
||||
"../common.h"
|
||||
|
||||
1427353132 /home/evanc/spdlog/include/spdlog/details/logger_impl.h
|
||||
1440745033 /home/evanc/spdlog/include/spdlog/details/logger_impl.h
|
||||
"./line_logger.h"
|
||||
|
||||
1427353132 /home/evanc/spdlog/include/spdlog/details/line_logger.h
|
||||
1440745033 /home/evanc/spdlog/include/spdlog/details/line_logger.h
|
||||
<type_traits>
|
||||
"../common.h"
|
||||
"../logger.h"
|
||||
|
||||
1427353132 /home/evanc/spdlog/include/spdlog/details/spdlog_impl.h
|
||||
1440745033 /home/evanc/spdlog/include/spdlog/details/spdlog_impl.h
|
||||
"registry.h"
|
||||
"../sinks/file_sinks.h"
|
||||
"../sinks/stdout_sinks.h"
|
||||
"../sinks/syslog_sink.h"
|
||||
|
||||
1427353132 /home/evanc/spdlog/include/spdlog/details/registry.h
|
||||
1440745033 /home/evanc/spdlog/include/spdlog/details/registry.h
|
||||
<string>
|
||||
<mutex>
|
||||
<unordered_map>
|
||||
<functional>
|
||||
"./null_mutex.h"
|
||||
"../logger.h"
|
||||
"../async_logger.h"
|
||||
"../common.h"
|
||||
|
||||
1427353132 /home/evanc/spdlog/include/spdlog/async_logger.h
|
||||
1440745033 /home/evanc/spdlog/include/spdlog/async_logger.h
|
||||
<chrono>
|
||||
<functional>
|
||||
"common.h"
|
||||
|
@ -364,10 +373,10 @@
|
|||
"spdlog.h"
|
||||
"./details/async_logger_impl.h"
|
||||
|
||||
1427353132 /home/evanc/spdlog/include/spdlog/details/async_logger_impl.h
|
||||
1440745033 /home/evanc/spdlog/include/spdlog/details/async_logger_impl.h
|
||||
"./async_log_helper.h"
|
||||
|
||||
1427353132 /home/evanc/spdlog/include/spdlog/details/async_log_helper.h
|
||||
1440745033 /home/evanc/spdlog/include/spdlog/details/async_log_helper.h
|
||||
<chrono>
|
||||
<thread>
|
||||
<atomic>
|
||||
|
@ -377,12 +386,13 @@
|
|||
"./mpmc_bounded_q.h"
|
||||
"./log_msg.h"
|
||||
"./format.h"
|
||||
"os.h"
|
||||
|
||||
1427353132 /home/evanc/spdlog/include/spdlog/details/mpmc_bounded_q.h
|
||||
<atomic>
|
||||
"../common.h"
|
||||
|
||||
1427353132 /home/evanc/spdlog/include/spdlog/sinks/file_sinks.h
|
||||
1440745033 /home/evanc/spdlog/include/spdlog/sinks/file_sinks.h
|
||||
<mutex>
|
||||
"base_sink.h"
|
||||
"../details/null_mutex.h"
|
||||
|
@ -391,26 +401,26 @@
|
|||
|
||||
1427353132 /home/evanc/spdlog/include/spdlog/details/null_mutex.h
|
||||
|
||||
1427353132 /home/evanc/spdlog/include/spdlog/details/file_helper.h
|
||||
1440745033 /home/evanc/spdlog/include/spdlog/details/file_helper.h
|
||||
<string>
|
||||
<thread>
|
||||
<chrono>
|
||||
"os.h"
|
||||
|
||||
1427353132 /home/evanc/spdlog/include/spdlog/sinks/stdout_sinks.h
|
||||
1440745033 /home/evanc/spdlog/include/spdlog/sinks/stdout_sinks.h
|
||||
<iostream>
|
||||
<mutex>
|
||||
"./ostream_sink.h"
|
||||
"../details/null_mutex.h"
|
||||
|
||||
1427353132 /home/evanc/spdlog/include/spdlog/sinks/ostream_sink.h
|
||||
1440745033 /home/evanc/spdlog/include/spdlog/sinks/ostream_sink.h
|
||||
<ostream>
|
||||
<mutex>
|
||||
<memory>
|
||||
"../details/null_mutex.h"
|
||||
"./base_sink.h"
|
||||
|
||||
1427353132 /home/evanc/spdlog/include/spdlog/sinks/syslog_sink.h
|
||||
1440745033 /home/evanc/spdlog/include/spdlog/sinks/syslog_sink.h
|
||||
<array>
|
||||
<string>
|
||||
<syslog.h>
|
||||
|
@ -427,7 +437,7 @@
|
|||
"core/RemoteExecutor.h"
|
||||
"Version.h"
|
||||
|
||||
1436264986 /home/evanc/whpc-linux-communicator/nodemanager/utils/Logger.h
|
||||
1447837233 /home/evanc/whpc-linux-communicator/nodemanager/utils/Logger.h
|
||||
<syslog.h>
|
||||
<stdio.h>
|
||||
<stdarg.h>
|
||||
|
@ -435,24 +445,31 @@
|
|||
<spdlog/spdlog.h>
|
||||
"String.h"
|
||||
|
||||
1427722564 /home/evanc/whpc-linux-communicator/nodemanager/core/RemoteCommunicator.h
|
||||
1464874241 /home/evanc/whpc-linux-communicator/nodemanager/core/RemoteCommunicator.h
|
||||
<cpprest/http_listener.h>
|
||||
<cpprest/json.h>
|
||||
"../utils/Logger.h"
|
||||
"../filters/ExecutionFilter.h"
|
||||
"IRemoteExecutor.h"
|
||||
|
||||
1427722694 /home/evanc/whpc-linux-communicator/nodemanager/core/IRemoteExecutor.h
|
||||
1437990898 /home/evanc/whpc-linux-communicator/nodemanager/core/IRemoteExecutor.h
|
||||
"../arguments/StartJobAndTaskArgs.h"
|
||||
"../arguments/StartTaskArgs.h"
|
||||
"../arguments/EndJobArgs.h"
|
||||
"../arguments/EndTaskArgs.h"
|
||||
"../arguments/MetricCountersConfig.h"
|
||||
|
||||
1428574742 /home/evanc/whpc-linux-communicator/nodemanager/core/RemoteExecutor.h
|
||||
1464733277 /home/evanc/whpc-linux-communicator/nodemanager/core/RemoteExecutor.h
|
||||
<set>
|
||||
<map>
|
||||
"IRemoteExecutor.h"
|
||||
"JobTaskTable.h"
|
||||
"Monitor.h"
|
||||
"Process.h"
|
||||
"Reporter.h"
|
||||
"HostsManager.h"
|
||||
"../arguments/MetricCountersConfig.h"
|
||||
"../data/ProcessStatistics.h"
|
||||
|
||||
1427353166 source:/home/evanc/whpc-linux-communicator/nodemanager/arguments/EndJobArgs.cpp
|
||||
"EndJobArgs.h"
|
||||
|
@ -461,7 +478,7 @@
|
|||
1427353166 /home/evanc/whpc-linux-communicator/nodemanager/arguments/EndJobArgs.h
|
||||
<cpprest/json.h>
|
||||
|
||||
1437473138 /home/evanc/whpc-linux-communicator/nodemanager/utils/JsonHelper.h
|
||||
1464941459 /home/evanc/whpc-linux-communicator/nodemanager/utils/JsonHelper.h
|
||||
<vector>
|
||||
<map>
|
||||
<cpprest/json.h>
|
||||
|
@ -470,14 +487,14 @@
|
|||
"EndTaskArgs.h"
|
||||
"../utils/JsonHelper.h"
|
||||
|
||||
1427353166 /home/evanc/whpc-linux-communicator/nodemanager/arguments/EndTaskArgs.h
|
||||
1433133379 /home/evanc/whpc-linux-communicator/nodemanager/arguments/EndTaskArgs.h
|
||||
<cpprest/json.h>
|
||||
|
||||
1429783386 source:/home/evanc/whpc-linux-communicator/nodemanager/arguments/ProcessStartInfo.cpp
|
||||
1464897409 source:/home/evanc/whpc-linux-communicator/nodemanager/arguments/ProcessStartInfo.cpp
|
||||
"ProcessStartInfo.h"
|
||||
"../utils/JsonHelper.h"
|
||||
|
||||
1429783378 /home/evanc/whpc-linux-communicator/nodemanager/arguments/ProcessStartInfo.h
|
||||
1464897165 /home/evanc/whpc-linux-communicator/nodemanager/arguments/ProcessStartInfo.h
|
||||
<string>
|
||||
<vector>
|
||||
<map>
|
||||
|
@ -487,7 +504,7 @@
|
|||
"StartJobAndTaskArgs.h"
|
||||
"../utils/JsonHelper.h"
|
||||
|
||||
1427383873 /home/evanc/whpc-linux-communicator/nodemanager/arguments/StartJobAndTaskArgs.h
|
||||
1429010700 /home/evanc/whpc-linux-communicator/nodemanager/arguments/StartJobAndTaskArgs.h
|
||||
<cpprest/json.h>
|
||||
"ProcessStartInfo.h"
|
||||
|
||||
|
@ -509,7 +526,7 @@
|
|||
"../utils/String.h"
|
||||
"../common/ErrorCodes.h"
|
||||
|
||||
1428574604 /home/evanc/whpc-linux-communicator/nodemanager/core/Process.h
|
||||
1464871942 /home/evanc/whpc-linux-communicator/nodemanager/core/Process.h
|
||||
<string>
|
||||
<sstream>
|
||||
<vector>
|
||||
|
@ -524,6 +541,7 @@
|
|||
"../utils/Logger.h"
|
||||
"../utils/System.h"
|
||||
"../common/ErrorCodes.h"
|
||||
"../data/ProcessStatistics.h"
|
||||
|
||||
1429015468 /home/evanc/whpc-linux-communicator/nodemanager/utils/String.h
|
||||
<string>
|
||||
|
@ -538,7 +556,7 @@
|
|||
"../utils/System.h"
|
||||
"../arguments/StartJobAndTaskArgs.h"
|
||||
|
||||
1428574577 /home/evanc/whpc-linux-communicator/nodemanager/utils/System.h
|
||||
1464869302 /home/evanc/whpc-linux-communicator/nodemanager/utils/System.h
|
||||
<string>
|
||||
"String.h"
|
||||
"Logger.h"
|
||||
|
@ -584,7 +602,7 @@
|
|||
"../utils/WriterLock.h"
|
||||
"../utils/ReaderLock.h"
|
||||
|
||||
1438324701 /home/evanc/whpc-linux-communicator/nodemanager/core/JobTaskTable.h
|
||||
1438327680 /home/evanc/whpc-linux-communicator/nodemanager/core/JobTaskTable.h
|
||||
<map>
|
||||
<cpprest/json.h>
|
||||
"../data/TaskInfo.h"
|
||||
|
@ -592,7 +610,7 @@
|
|||
"../data/NodeInfo.h"
|
||||
"../utils/ReaderLock.h"
|
||||
|
||||
1436256679 /home/evanc/whpc-linux-communicator/nodemanager/data/TaskInfo.h
|
||||
1438325484 /home/evanc/whpc-linux-communicator/nodemanager/data/TaskInfo.h
|
||||
<cpprest/json.h>
|
||||
<vector>
|
||||
<string>
|
||||
|
@ -662,10 +680,15 @@
|
|||
1424929892 source:/home/evanc/whpc-linux-communicator/nodemanager/utils/WriterLock.cpp
|
||||
"WriterLock.h"
|
||||
|
||||
1427383873 /home/evanc/whpc-linux-communicator/nodemanager/core/Monitor.h
|
||||
1438161680 /home/evanc/whpc-linux-communicator/nodemanager/core/Monitor.h
|
||||
<cpprest/json.h>
|
||||
<map>
|
||||
<boost/uuid/uuid.hpp>
|
||||
"../utils/System.h"
|
||||
"../data/MonitoringPacket.h"
|
||||
"../arguments/MetricCounter.h"
|
||||
"../arguments/MetricCountersConfig.h"
|
||||
"MetricCollectorBase.h"
|
||||
|
||||
1428571893 source:/home/evanc/whpc-linux-communicator/nodemanager/core/Monitor.cpp
|
||||
<pthread.h>
|
||||
|
@ -675,7 +698,7 @@
|
|||
"../utils/Logger.h"
|
||||
"../utils/System.h"
|
||||
|
||||
1430202795 /home/evanc/whpc-linux-communicator/nodemanager/core/Reporter.h
|
||||
1446103482 /home/evanc/whpc-linux-communicator/nodemanager/core/Reporter.h
|
||||
<cpprest/json.h>
|
||||
<functional>
|
||||
"../utils/Logger.h"
|
||||
|
@ -685,7 +708,7 @@
|
|||
"Reporter.h"
|
||||
"../utils/Logger.h"
|
||||
|
||||
1437474755 /home/evanc/whpc-linux-communicator/nodemanager/common/ErrorCodes.h
|
||||
1464870624 /home/evanc/whpc-linux-communicator/nodemanager/common/ErrorCodes.h
|
||||
|
||||
1429084854 source:/home/evanc/whpc-linux-communicator/nodemanager/Version.cpp
|
||||
"Version.h"
|
||||
|
@ -720,7 +743,7 @@
|
|||
1437547414 source:/home/evanc/whpc-linux-communicator/nodemanager/core/NodeManagerConfig.cpp
|
||||
"NodeManagerConfig.h"
|
||||
|
||||
1440058578 /home/evanc/whpc-linux-communicator/nodemanager/core/NodeManagerConfig.h
|
||||
1464734870 /home/evanc/whpc-linux-communicator/nodemanager/core/NodeManagerConfig.h
|
||||
"../utils/Configuration.h"
|
||||
|
||||
1437732272 source:/home/evanc/whpc-linux-communicator/nodemanager/arguments/MonitoringConfig.cpp
|
||||
|
@ -745,7 +768,7 @@
|
|||
1437645025 source:/home/evanc/whpc-linux-communicator/nodemanager/core/HttpHelper.cpp
|
||||
"HttpHelper.h"
|
||||
|
||||
1440058706 /home/evanc/whpc-linux-communicator/nodemanager/core/HttpHelper.h
|
||||
1460020276 /home/evanc/whpc-linux-communicator/nodemanager/core/HttpHelper.h
|
||||
<cpprest/http_client.h>
|
||||
<boost/asio/ssl.hpp>
|
||||
"NodeManagerConfig.h"
|
||||
|
@ -762,7 +785,7 @@
|
|||
1438238815 /home/evanc/whpc-linux-communicator/nodemanager/data/Umid.h
|
||||
<inttypes.h>
|
||||
|
||||
1433133379 /home/evanc/whpc-linux-communicator/nodemanager/data/ProcessStatistics.h
|
||||
1447837294 /home/evanc/whpc-linux-communicator/nodemanager/data/ProcessStatistics.h
|
||||
<vector>
|
||||
<inttypes.h>
|
||||
|
||||
|
@ -961,3 +984,259 @@
|
|||
"cpprest/http_msg.h"
|
||||
"cpprest/details/http_constants.dat"
|
||||
|
||||
1464885862 source:/home/evanc/whpc-linux-communicator/nodemanager/test/ExecutionFilterTest.cpp
|
||||
"ExecutionFilterTest.h"
|
||||
<iostream>
|
||||
<string>
|
||||
<cpprest/http_listener.h>
|
||||
<cpprest/json.h>
|
||||
"../utils/JsonHelper.h"
|
||||
"../core/Process.h"
|
||||
"../utils/Logger.h"
|
||||
"../core/RemoteCommunicator.h"
|
||||
"../core/RemoteExecutor.h"
|
||||
"../core/NodeManagerConfig.h"
|
||||
"../common/ErrorCodes.h"
|
||||
"../core/HttpHelper.h"
|
||||
|
||||
1464883806 /home/evanc/whpc-linux-communicator/nodemanager/test/ExecutionFilterTest.h
|
||||
|
||||
1460016995 /home/evanc/evancasa/cpprestsdk/Release/include/cpprest/http_listener.h
|
||||
<limits>
|
||||
<functional>
|
||||
"cpprest/http_msg.h"
|
||||
<boost/asio/ssl.hpp>
|
||||
|
||||
1460016995 /home/evanc/evancasa/cpprestsdk/Release/include/cpprest/http_msg.h
|
||||
<map>
|
||||
<memory>
|
||||
<string>
|
||||
<vector>
|
||||
<system_error>
|
||||
"pplx/pplxtasks.h"
|
||||
"cpprest/json.h"
|
||||
"cpprest/uri.h"
|
||||
"cpprest/http_headers.h"
|
||||
"cpprest/details/cpprest_compat.h"
|
||||
"cpprest/asyncrt_utils.h"
|
||||
"cpprest/streams.h"
|
||||
"cpprest/containerstream.h"
|
||||
"cpprest/details/http_constants.dat"
|
||||
"cpprest/details/http_constants.dat"
|
||||
"cpprest/details/http_constants.dat"
|
||||
|
||||
1460016995 /home/evanc/evancasa/cpprestsdk/Release/include/pplx/pplxtasks.h
|
||||
<ppltasks.h>
|
||||
<concrt.h>
|
||||
"pplx/pplx.h"
|
||||
<jni.h>
|
||||
<functional>
|
||||
<vector>
|
||||
<utility>
|
||||
<exception>
|
||||
<algorithm>
|
||||
<windows.h>
|
||||
<ctxtcall.h>
|
||||
<agile.h>
|
||||
<winapifamily.h>
|
||||
<winapifamily.h>
|
||||
<uithreadctxt.h>
|
||||
|
||||
1460016995 /home/evanc/evancasa/cpprestsdk/Release/include/pplx/pplx.h
|
||||
"cpprest/details/cpprest_compat.h"
|
||||
"pplx/pplxwin.h"
|
||||
"pplx/pplxlinux.h"
|
||||
"pplx/pplxlinux.h"
|
||||
"pplx/pplxcancellation_token.h"
|
||||
<functional>
|
||||
|
||||
1460016995 /home/evanc/evancasa/cpprestsdk/Release/include/cpprest/details/cpprest_compat.h
|
||||
<sal.h>
|
||||
<assert.h>
|
||||
"cpprest/details/nosal.h"
|
||||
<cstdio>
|
||||
|
||||
1460016995 /home/evanc/evancasa/cpprestsdk/Release/include/cpprest/details/nosal.h
|
||||
|
||||
1460016995 /home/evanc/evancasa/cpprestsdk/Release/include/pplx/pplxwin.h
|
||||
"cpprest/details/cpprest_compat.h"
|
||||
"pplx/pplxinterface.h"
|
||||
|
||||
1460016995 /home/evanc/evancasa/cpprestsdk/Release/include/pplx/pplxinterface.h
|
||||
<memory>
|
||||
<atomic>
|
||||
|
||||
1460016995 /home/evanc/evancasa/cpprestsdk/Release/include/pplx/pplxlinux.h
|
||||
<signal.h>
|
||||
"pthread.h"
|
||||
"cpprest/details/cpprest_compat.h"
|
||||
<dispatch/dispatch.h>
|
||||
<boost/thread/mutex.hpp>
|
||||
<boost/thread/condition_variable.hpp>
|
||||
<mutex>
|
||||
<condition_variable>
|
||||
"pplx/pplxinterface.h"
|
||||
|
||||
1460016995 /home/evanc/evancasa/cpprestsdk/Release/include/pplx/pplxcancellation_token.h
|
||||
<cstdlib>
|
||||
<string>
|
||||
"pplx/pplxinterface.h"
|
||||
|
||||
1460016995 /home/evanc/evancasa/cpprestsdk/Release/include/cpprest/json.h
|
||||
<memory>
|
||||
<string>
|
||||
<sstream>
|
||||
<vector>
|
||||
<unordered_map>
|
||||
<cstdint>
|
||||
"cpprest/details/basic_types.h"
|
||||
"cpprest/asyncrt_utils.h"
|
||||
|
||||
1460016995 /home/evanc/evancasa/cpprestsdk/Release/include/cpprest/details/basic_types.h
|
||||
<string>
|
||||
<fstream>
|
||||
<iostream>
|
||||
<sstream>
|
||||
"cpprest/details/cpprest_compat.h"
|
||||
<stdint.h>
|
||||
<cstdint>
|
||||
"cpprest/details/SafeInt3.hpp"
|
||||
|
||||
1460016995 /home/evanc/evancasa/cpprestsdk/Release/include/cpprest/details/SafeInt3.hpp
|
||||
<cstddef>
|
||||
<cstdlib>
|
||||
<intrin.h>
|
||||
<stdint.h>
|
||||
<assert.h>
|
||||
<stdlib.h>
|
||||
|
||||
1460016995 /home/evanc/evancasa/cpprestsdk/Release/include/cpprest/asyncrt_utils.h
|
||||
<string>
|
||||
<vector>
|
||||
<cstdint>
|
||||
<system_error>
|
||||
<random>
|
||||
<locale.h>
|
||||
"pplx/pplxtasks.h"
|
||||
"cpprest/details/basic_types.h"
|
||||
<chrono>
|
||||
<boost/algorithm/string.hpp>
|
||||
<xlocale.h>
|
||||
|
||||
1460016995 /home/evanc/evancasa/cpprestsdk/Release/include/cpprest/uri.h
|
||||
"cpprest/base_uri.h"
|
||||
"cpprest/uri_builder.h"
|
||||
|
||||
1460016995 /home/evanc/evancasa/cpprestsdk/Release/include/cpprest/base_uri.h
|
||||
<map>
|
||||
<memory>
|
||||
<string>
|
||||
<vector>
|
||||
<functional>
|
||||
"cpprest/asyncrt_utils.h"
|
||||
"cpprest/details/basic_types.h"
|
||||
|
||||
1460016995 /home/evanc/evancasa/cpprestsdk/Release/include/cpprest/uri_builder.h
|
||||
<sstream>
|
||||
<string>
|
||||
<vector>
|
||||
"cpprest/base_uri.h"
|
||||
"cpprest/details/uri_parser.h"
|
||||
|
||||
1460016995 /home/evanc/evancasa/cpprestsdk/Release/include/cpprest/details/uri_parser.h
|
||||
<string>
|
||||
|
||||
1460016995 /home/evanc/evancasa/cpprestsdk/Release/include/cpprest/http_headers.h
|
||||
<map>
|
||||
<memory>
|
||||
<string>
|
||||
<vector>
|
||||
<system_error>
|
||||
"cpprest/asyncrt_utils.h"
|
||||
|
||||
1460016995 /home/evanc/evancasa/cpprestsdk/Release/include/cpprest/streams.h
|
||||
"cpprest/astreambuf.h"
|
||||
<iosfwd>
|
||||
|
||||
1460016995 /home/evanc/evancasa/cpprestsdk/Release/include/cpprest/astreambuf.h
|
||||
<ios>
|
||||
<memory>
|
||||
<cstring>
|
||||
<math.h>
|
||||
"pplx/pplxtasks.h"
|
||||
"cpprest/details/basic_types.h"
|
||||
"cpprest/asyncrt_utils.h"
|
||||
|
||||
1460016995 /home/evanc/evancasa/cpprestsdk/Release/include/cpprest/containerstream.h
|
||||
<vector>
|
||||
<queue>
|
||||
<algorithm>
|
||||
<iterator>
|
||||
"pplx/pplxtasks.h"
|
||||
"cpprest/astreambuf.h"
|
||||
"cpprest/streams.h"
|
||||
|
||||
1460016995 /home/evanc/evancasa/cpprestsdk/Release/include/cpprest/details/http_constants.dat
|
||||
|
||||
1440745033 /home/evanc/spdlog/include/spdlog/tweakme.h
|
||||
|
||||
1464874650 /home/evanc/whpc-linux-communicator/nodemanager/filters/ExecutionFilter.h
|
||||
<string>
|
||||
<cpprest/json.h>
|
||||
"../core/NodeManagerConfig.h"
|
||||
|
||||
1437983925 /home/evanc/whpc-linux-communicator/nodemanager/arguments/MetricCountersConfig.h
|
||||
"MetricCounter.h"
|
||||
"../utils/JsonHelper.h"
|
||||
|
||||
1430401912 /home/evanc/whpc-linux-communicator/nodemanager/data/MonitoringPacket.h
|
||||
<boost/uuid/uuid.hpp>
|
||||
"../utils/Logger.h"
|
||||
"Umid.h"
|
||||
|
||||
1453226140 /home/evanc/whpc-linux-communicator/nodemanager/core/HostsManager.h
|
||||
<string>
|
||||
<vector>
|
||||
"HttpFetcher.h"
|
||||
"../data/HostEntry.h"
|
||||
|
||||
1447837236 /home/evanc/whpc-linux-communicator/nodemanager/core/HttpFetcher.h
|
||||
<cpprest/json.h>
|
||||
<cpprest/http_client.h>
|
||||
<functional>
|
||||
"Reporter.h"
|
||||
|
||||
1460016995 /home/evanc/evancasa/cpprestsdk/Release/include/cpprest/http_client.h
|
||||
<wrl.h>
|
||||
<msxml6.h>
|
||||
<memory>
|
||||
<limits>
|
||||
"pplx/pplxtasks.h"
|
||||
"cpprest/http_msg.h"
|
||||
"cpprest/json.h"
|
||||
"cpprest/uri.h"
|
||||
"cpprest/details/web_utilities.h"
|
||||
"cpprest/details/basic_types.h"
|
||||
"cpprest/asyncrt_utils.h"
|
||||
"cpprest/oauth1.h"
|
||||
"cpprest/oauth2.h"
|
||||
"boost/asio/ssl.hpp"
|
||||
|
||||
1460016995 /home/evanc/evancasa/cpprestsdk/Release/include/cpprest/details/web_utilities.h
|
||||
"cpprest/asyncrt_utils.h"
|
||||
|
||||
1460016995 /home/evanc/evancasa/cpprestsdk/Release/include/cpprest/oauth1.h
|
||||
"cpprest/http_msg.h"
|
||||
"cpprest/details/web_utilities.h"
|
||||
"cpprest/details/http_constants.dat"
|
||||
"cpprest/details/http_constants.dat"
|
||||
|
||||
1460016995 /home/evanc/evancasa/cpprestsdk/Release/include/cpprest/oauth2.h
|
||||
"cpprest/http_msg.h"
|
||||
"cpprest/details/web_utilities.h"
|
||||
"cpprest/details/http_constants.dat"
|
||||
|
||||
1447837236 /home/evanc/whpc-linux-communicator/nodemanager/data/HostEntry.h
|
||||
<string>
|
||||
<cpprest/json.h>
|
||||
|
||||
|
|
|
@ -456,6 +456,14 @@ namespace hpc
|
|||
"Fix a memory leak issue in the cpprestsdk",
|
||||
}
|
||||
},
|
||||
{ "1.7.1.0",
|
||||
{
|
||||
"Added the execution filter support",
|
||||
"Added unit test for execution filter",
|
||||
"Improved the unit test framework",
|
||||
"Fixed some problems in json format processing",
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
return versionHistory;
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace hpc
|
|||
|
||||
static EndJobArgs FromJson(const web::json::value& jsonValue);
|
||||
|
||||
protected:
|
||||
protected:
|
||||
private:
|
||||
};
|
||||
}
|
||||
|
|
|
@ -24,6 +24,20 @@ ProcessStartInfo::ProcessStartInfo(
|
|||
{
|
||||
}
|
||||
|
||||
json::value ProcessStartInfo::ToJson() const
|
||||
{
|
||||
json::value v;
|
||||
v["commandLine"] = json::value::string(this->CommandLine);
|
||||
v["stdin"] = json::value::string(this->StdInFile);
|
||||
v["stdout"] = json::value::string(this->StdOutFile);
|
||||
v["stderr"] = json::value::string(this->StdErrFile);
|
||||
v["workingDirectory"] = json::value::string(this->WorkDirectory);
|
||||
v["taskRequeueCount"] = this->TaskRequeueCount;
|
||||
v["affinity"] = JsonHelper<std::vector<uint64_t>>::ToJson(this->Affinity);
|
||||
v["environmentVariables"] = JsonHelper<std::map<std::string, std::string>>::ToJson(this->EnvironmentVariables);
|
||||
return v;
|
||||
}
|
||||
|
||||
/// TODO: Consider using attribute feature when compiler ready.
|
||||
ProcessStartInfo ProcessStartInfo::FromJson(const web::json::value& jsonValue)
|
||||
{
|
||||
|
|
|
@ -27,6 +27,7 @@ namespace hpc
|
|||
ProcessStartInfo(ProcessStartInfo&& startInfo) = default;
|
||||
|
||||
static ProcessStartInfo FromJson(const web::json::value& jsonValue);
|
||||
web::json::value ToJson() const;
|
||||
|
||||
std::string CommandLine;
|
||||
std::string StdInFile;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
using namespace hpc::arguments;
|
||||
using namespace hpc::utils;
|
||||
using namespace web;
|
||||
|
||||
StartJobAndTaskArgs::StartJobAndTaskArgs(int jobId, int taskId, ProcessStartInfo&& startInfo,
|
||||
std::string&& userName, std::string&& password) :
|
||||
|
@ -13,6 +14,25 @@ StartJobAndTaskArgs::StartJobAndTaskArgs(int jobId, int taskId, ProcessStartInfo
|
|||
//ctor
|
||||
}
|
||||
|
||||
json::value StartJobAndTaskArgs::ToJson() const
|
||||
{
|
||||
json::value v;
|
||||
|
||||
json::value jobTaskId;
|
||||
jobTaskId["JobId"] = this->JobId;
|
||||
jobTaskId["TaskId"] = this->TaskId;
|
||||
|
||||
v["m_Item1"] = jobTaskId;
|
||||
v["m_Item2"] = this->StartInfo.ToJson();
|
||||
v["m_Item3"] = json::value::string(this->UserName);
|
||||
v["m_Item4"] = json::value::string(this->Password);
|
||||
v["m_Item5"] = json::value::string(this->PrivateKey);
|
||||
v["m_Item6"] = json::value::string(this->PublicKey);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
StartJobAndTaskArgs StartJobAndTaskArgs::FromJson(const json::value& j)
|
||||
{
|
||||
StartJobAndTaskArgs args(
|
||||
|
|
|
@ -20,6 +20,7 @@ namespace hpc
|
|||
std::string&& password);
|
||||
|
||||
StartJobAndTaskArgs(StartJobAndTaskArgs&& args) = default;
|
||||
web::json::value ToJson() const;
|
||||
|
||||
int JobId;
|
||||
int TaskId;
|
||||
|
@ -32,7 +33,7 @@ namespace hpc
|
|||
|
||||
static StartJobAndTaskArgs FromJson(const web::json::value& jsonValue);
|
||||
|
||||
protected:
|
||||
protected:
|
||||
private:
|
||||
};
|
||||
}
|
||||
|
|
|
@ -17,6 +17,9 @@ namespace hpc
|
|||
TestRunFailed = 176,
|
||||
FailedToOpenPort = 177,
|
||||
ConfigurationFileError = 178,
|
||||
WriteFileError = 179,
|
||||
ReadFileError = 180,
|
||||
UnknownFilter = 181,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,11 +2,14 @@
|
|||
"TrustedCAFile":"/opt/hpcnodemanager/certs/test.pem",
|
||||
"TrustedCAPath":"/opt/hpcnodemanager/certs/",
|
||||
"UseDefaultCA":false,
|
||||
"ClusterAuthenticationKey":"abc",
|
||||
"ClusterAuthenticationKey":"",
|
||||
"HeartbeatUri":"https://evancv1:40001/api/evanc.com/computenodereported",
|
||||
"MetricUri":"udp://EVANCV1.fareast.corp.microsoft.com:9894/api/4aed4836-c0c8-4e92-853d-cac4698582d1/metricreported",
|
||||
"RegisterUri":"https://evancv1:40001/api/evanc.com/registerrequested",
|
||||
"CertificateChainFile":"/opt/hpcnodemanager/certs/evanc.com.crt",
|
||||
"PrivateKeyFile":"/opt/hpcnodemanager/certs/evanc.com.key",
|
||||
"ListeningUri":"https://0.0.0.0:40002"
|
||||
"ListeningUri":"http://0.0.0.0:40000",
|
||||
"JobStartFilter":"sed -s 's/123/456/g'",
|
||||
"JobEndFilter":"sed -s 's/123/456/g'",
|
||||
"TaskStartFilter":"sed -s 's/123/456/g'"
|
||||
}
|
||||
|
|
|
@ -36,6 +36,9 @@ namespace hpc
|
|||
AddConfigurationItem(std::string, CertificateChainFile);
|
||||
AddConfigurationItem(std::string, PrivateKeyFile);
|
||||
AddConfigurationItem(std::string, ListeningUri);
|
||||
AddConfigurationItem(std::string, JobStartFilter);
|
||||
AddConfigurationItem(std::string, JobEndFilter);
|
||||
AddConfigurationItem(std::string, TaskStartFilter);
|
||||
AddConfigurationItem(bool, UseDefaultCA);
|
||||
AddConfigurationItem(bool, Debug);
|
||||
AddConfigurationItem(int, HostsFetchInterval);
|
||||
|
|
|
@ -57,13 +57,13 @@ void Process::Cleanup()
|
|||
Logger::Info("Cleanup zombie result: {0}", output);
|
||||
}
|
||||
|
||||
pplx::task<pid_t> Process::Start()
|
||||
pplx::task<std::pair<pid_t, pthread_t>> Process::Start()
|
||||
{
|
||||
pthread_create(&this->threadId, nullptr, ForkThread, this);
|
||||
|
||||
Logger::Debug(this->jobId, this->taskId, this->requeueCount, "Created thread {0}", this->threadId);
|
||||
|
||||
return pplx::task<pid_t>(this->started);
|
||||
return pplx::task<std::pair<pid_t, pthread_t>>(this->started);
|
||||
}
|
||||
|
||||
void Process::Kill(int forcedExitCode, bool forced)
|
||||
|
@ -183,6 +183,7 @@ Start:
|
|||
Logger::Error(p->jobId, p->taskId, p->requeueCount, "Failed to fork(), pid = {0}, errno = {1}, msg = {2}", p->processId, errno, errorMessage);
|
||||
|
||||
p->SetExitCode(errno);
|
||||
p->started.set(std::pair<pid_t, pthread_t>(p->processId, p->threadId));
|
||||
goto Final;
|
||||
}
|
||||
|
||||
|
@ -193,8 +194,7 @@ Start:
|
|||
else
|
||||
{
|
||||
assert(p->processId > 0);
|
||||
p->started.set(p->processId);
|
||||
assert(p->processId > 0);
|
||||
p->started.set(std::pair<pid_t, pthread_t>(p->processId, p->threadId));
|
||||
p->Monitor();
|
||||
}
|
||||
|
||||
|
@ -483,26 +483,16 @@ int Process::CreateTaskFolder()
|
|||
|
||||
sprintf(folder, "/tmp/nodemanager_task_%d_%d.XXXXXX", this->taskId, this->requeueCount);
|
||||
|
||||
char* p = mkdtemp(folder);
|
||||
int ret = System::CreateTempFolder(folder, this->userName);
|
||||
|
||||
if (p)
|
||||
if (ret != 0)
|
||||
{
|
||||
this->taskFolder = p;
|
||||
|
||||
int ret;
|
||||
ret = this->ExecuteCommand("chown -R", this->userName, this->taskFolder);
|
||||
|
||||
if (ret == 0)
|
||||
{
|
||||
ret = this->ExecuteCommand("chmod -R u+rwX", this->taskFolder);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
return errno;
|
||||
Logger::Debug(this->jobId, this->taskId, this->requeueCount, "CreateTaskFolder failed exitCode {0}.", ret);
|
||||
}
|
||||
|
||||
this->taskFolder = folder;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string Process::BuildScript()
|
||||
|
@ -519,6 +509,8 @@ std::string Process::BuildScript()
|
|||
fs << "#!/bin/bash" << std::endl << std::endl;
|
||||
|
||||
fs << "cd ";
|
||||
|
||||
Logger::Debug("{0}, {1}", this->taskFolder, this->workDirectory);
|
||||
if (this->workDirectory.empty())
|
||||
{
|
||||
fs << this->taskFolder;
|
||||
|
|
|
@ -50,7 +50,7 @@ namespace hpc
|
|||
|
||||
virtual ~Process();
|
||||
|
||||
pplx::task<pid_t> Start();
|
||||
pplx::task<std::pair<pid_t, pthread_t>> Start();
|
||||
void Kill(int forcedExitCode = 0x0FFFFFFF, bool forced = true);
|
||||
const hpc::data::ProcessStatistics& GetStatisticsFromCGroup();
|
||||
|
||||
|
@ -150,7 +150,7 @@ namespace hpc
|
|||
|
||||
pthread_rwlock_t lock = PTHREAD_RWLOCK_INITIALIZER;
|
||||
|
||||
pplx::task_completion_event<pid_t> started;
|
||||
pplx::task_completion_event<std::pair<pid_t, pthread_t>> started;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ using namespace hpc::arguments;
|
|||
using namespace hpc::core;
|
||||
using namespace hpc::common;
|
||||
using namespace web::http::experimental::listener;
|
||||
using namespace hpc::filters;
|
||||
|
||||
RemoteCommunicator::RemoteCommunicator(IRemoteExecutor& exec, const http_listener_config& config) :
|
||||
listeningUri(NodeManagerConfig::GetListeningUri()), isListening(false), executor(exec),
|
||||
|
@ -56,7 +57,7 @@ void RemoteCommunicator::Open()
|
|||
this->isListening = !IsError(t);
|
||||
Logger::Info(
|
||||
"Opening at {0}, result {1}",
|
||||
this->listener.uri().to_string(),
|
||||
this->listeningUri,
|
||||
this->isListening ? "opened." : "failed.");
|
||||
|
||||
if (!this->isListening)
|
||||
|
@ -176,19 +177,55 @@ void RemoteCommunicator::HandlePost(http_request request)
|
|||
json::value RemoteCommunicator::StartJobAndTask(const json::value& val, const std::string& callbackUri)
|
||||
{
|
||||
auto args = StartJobAndTaskArgs::FromJson(val);
|
||||
return this->executor.StartJobAndTask(std::move(args), callbackUri);
|
||||
|
||||
json::value v;
|
||||
std::string executionMessage;
|
||||
int ret = this->filter.OnJobStart(args.JobId, val, v, executionMessage);
|
||||
if (ret != 0)
|
||||
{
|
||||
throw new std::runtime_error(String::Join(" ", "StartJob filter fails with error code", ret, "execution message", executionMessage));
|
||||
return v;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this->executor.StartJobAndTask(StartJobAndTaskArgs::FromJson(v), callbackUri);
|
||||
}
|
||||
}
|
||||
|
||||
json::value RemoteCommunicator::StartTask(const json::value& val, const std::string& callbackUri)
|
||||
{
|
||||
auto args = StartTaskArgs::FromJson(val);
|
||||
return this->executor.StartTask(std::move(args), callbackUri);
|
||||
|
||||
json::value v;
|
||||
std::string executionMessage;
|
||||
int ret = this->filter.OnTaskStart(args.JobId, args.TaskId, args.StartInfo.TaskRequeueCount, val, v, executionMessage);
|
||||
if (ret != 0)
|
||||
{
|
||||
throw new std::runtime_error(String::Join(" ", "StartTask filter fails with error code", ret, "execution message", executionMessage));
|
||||
return v;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this->executor.StartTask(StartTaskArgs::FromJson(v), callbackUri);
|
||||
}
|
||||
}
|
||||
|
||||
json::value RemoteCommunicator::EndJob(const json::value& val, const std::string& callbackUri)
|
||||
{
|
||||
auto args = EndJobArgs::FromJson(val);
|
||||
return this->executor.EndJob(std::move(args));
|
||||
|
||||
json::value v;
|
||||
std::string executionMessage;
|
||||
int ret = this->filter.OnJobEnd(args.JobId, val, v, executionMessage);
|
||||
if (ret != 0)
|
||||
{
|
||||
throw new std::runtime_error(String::Join(" ", "EndJob filter fails with error code", ret, "execution message", executionMessage));
|
||||
return v;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this->executor.EndJob(EndJobArgs::FromJson(v));
|
||||
}
|
||||
}
|
||||
|
||||
json::value RemoteCommunicator::EndTask(const json::value& val, const std::string& callbackUri)
|
||||
|
|
|
@ -5,12 +5,14 @@
|
|||
#include <cpprest/json.h>
|
||||
|
||||
#include "../utils/Logger.h"
|
||||
#include "../filters/ExecutionFilter.h"
|
||||
#include "IRemoteExecutor.h"
|
||||
|
||||
namespace hpc
|
||||
{
|
||||
using namespace utils;
|
||||
using namespace web;
|
||||
using namespace filters;
|
||||
|
||||
namespace core
|
||||
{
|
||||
|
@ -72,6 +74,7 @@ namespace hpc
|
|||
IRemoteExecutor& executor;
|
||||
|
||||
web::http::experimental::listener::http_listener listener;
|
||||
ExecutionFilter filter;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -234,12 +234,12 @@ json::value RemoteExecutor::StartTask(StartTaskArgs&& args, const std::string& c
|
|||
args.JobId, args.TaskId, taskInfo->GetTaskRequeueCount(),
|
||||
"StartTask for ProcessKey {0}, process count {1}", taskInfo->ProcessKey, this->processes.size());
|
||||
|
||||
process->Start().then([this, taskInfo] (pid_t pid)
|
||||
process->Start().then([this, taskInfo] (std::pair<pid_t, pthread_t> ids)
|
||||
{
|
||||
if (pid > 0)
|
||||
if (ids.first > 0)
|
||||
{
|
||||
Logger::Debug(taskInfo->JobId, taskInfo->TaskId, taskInfo->GetTaskRequeueCount(),
|
||||
"Process started {0}", pid);
|
||||
"Process started pid {0}, tid {1}", ids.first, ids.second);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
#include "ExecutionFilter.h"
|
||||
#include "../utils/Logger.h"
|
||||
#include "../common/ErrorCodes.h"
|
||||
#include "../utils/System.h"
|
||||
#include "../core/Process.h"
|
||||
#include "../data/ProcessStatistics.h"
|
||||
|
||||
using namespace hpc::filters;
|
||||
using namespace hpc::utils;
|
||||
using namespace hpc::common;
|
||||
using namespace hpc::data;
|
||||
|
||||
int ExecutionFilter::OnJobStart(int jobId, const json::value& input, json::value& output, std::string& executionMessage)
|
||||
{
|
||||
return this->ExecuteFilter(JobStartFilter, jobId, 0, 0, input, output, executionMessage);
|
||||
}
|
||||
|
||||
int ExecutionFilter::OnJobEnd(int jobId, const json::value& input, json::value& output, std::string& executionMessage)
|
||||
{
|
||||
return this->ExecuteFilter(JobEndFilter, jobId, 0, 0, input, output, executionMessage);
|
||||
}
|
||||
|
||||
int ExecutionFilter::OnTaskStart(int jobId, int taskId, int requeueCount, const json::value& input, json::value& output, std::string& executionMessage)
|
||||
{
|
||||
return this->ExecuteFilter(TaskStartFilter, jobId, taskId, requeueCount, input, output, executionMessage);
|
||||
}
|
||||
|
||||
int ExecutionFilter::ExecuteFilter(const std::string& filterType, int jobId, int taskId, int requeueCount, const json::value& input, json::value& output, std::string& executionMessage)
|
||||
{
|
||||
auto filterIt = this->filterFiles.find(filterType);
|
||||
if (filterIt == this->filterFiles.end())
|
||||
{
|
||||
Logger::Error(jobId, taskId, requeueCount, "Unknown filter type {0}", filterType);
|
||||
return (int)ErrorCodes::UnknownFilter;
|
||||
}
|
||||
|
||||
std::string filterFile = filterIt->second;
|
||||
|
||||
if (filterFile.empty())
|
||||
{
|
||||
Logger::Error(jobId, taskId, requeueCount, "{0} not detected, skip", filterType);
|
||||
output = input;
|
||||
return 0;
|
||||
}
|
||||
|
||||
char folder[256];
|
||||
sprintf(folder, "/tmp/nodemanager_executionfilter_%d.XXXXXX", jobId);
|
||||
int ret = System::CreateTempFolder(folder, "root");
|
||||
|
||||
if (ret != 0)
|
||||
{
|
||||
Logger::Error(jobId, taskId, requeueCount, "{0} {1}: Failed to create folder {2}, exit code {3}", filterType, filterFile, folder, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string folderString = folder;
|
||||
|
||||
std::string stdinFile = folderString + "/stdin.txt";
|
||||
ret = System::WriteStringToFile(stdinFile, input.serialize());
|
||||
|
||||
if (ret != 0)
|
||||
{
|
||||
Logger::Error(jobId, taskId, requeueCount, "{0} {1}: Failed to create stdin file {2}, exit code {3}", filterType, filterFile, stdinFile, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string stdoutFile = folderString + "/stdout.txt";
|
||||
std::string stderrFile = stdoutFile;
|
||||
|
||||
Process p(
|
||||
jobId, taskId, requeueCount, filterFile, stdoutFile, stderrFile, stdinFile, folderString, "root",
|
||||
std::vector<uint64_t>(), std::map<std::string, std::string>(),
|
||||
[&ret, &executionMessage, jobId, taskId, requeueCount, &filterType, &filterFile]
|
||||
(int exitCode, std::string&& message, const ProcessStatistics& stat)
|
||||
{
|
||||
ret = exitCode;
|
||||
if (ret != 0)
|
||||
{
|
||||
Logger::Error(jobId, taskId, requeueCount, "{0} {1}: returned {2}, message {3}", filterType, filterFile, ret, message);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::Info(jobId, taskId, requeueCount, "{0} {1}: success with message {2}", filterType, filterFile, message);
|
||||
}
|
||||
|
||||
executionMessage = message;
|
||||
});
|
||||
|
||||
pthread_t processTid;
|
||||
p.Start().then([&ret, &processTid, jobId, taskId, requeueCount, &filterType, &filterFile] (std::pair<pid_t, pthread_t> ids)
|
||||
{
|
||||
Logger::Info(jobId, taskId, requeueCount, "{0} {1}: pid {2} tid {3}", filterType, filterFile, ids.first, ids.second);
|
||||
processTid = ids.second;
|
||||
}).wait();
|
||||
|
||||
int joinRet = pthread_join(processTid, nullptr);
|
||||
|
||||
if (joinRet != 0)
|
||||
{
|
||||
Logger::Error(jobId, taskId, requeueCount, "{0} {1}: join thread {2} ret {3}", filterType, filterFile, processTid, joinRet);
|
||||
if (0 == ret) { ret = joinRet; }
|
||||
}
|
||||
|
||||
if (0 == ret)
|
||||
{
|
||||
std::ifstream fsStdout(stdoutFile, std::ios::in);
|
||||
|
||||
if (fsStdout)
|
||||
{
|
||||
std::string content((std::istreambuf_iterator<char>(fsStdout)), std::istreambuf_iterator<char>());
|
||||
Logger::Info(jobId, taskId, requeueCount, "{0} {1}: plugin output {2}", filterType, filterFile, content);
|
||||
output = json::value::parse(content);
|
||||
fsStdout.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
return (int)ErrorCodes::ReadFileError;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
#ifndef EXECUTIONFILTER_H
|
||||
#define EXECUTIONFILTER_H
|
||||
|
||||
#include <string>
|
||||
#include <cpprest/json.h>
|
||||
#include "../core/NodeManagerConfig.h"
|
||||
|
||||
namespace hpc
|
||||
{
|
||||
namespace filters
|
||||
{
|
||||
using namespace hpc::core;
|
||||
|
||||
class ExecutionFilter
|
||||
{
|
||||
public:
|
||||
ExecutionFilter()
|
||||
{
|
||||
filterFiles[JobStartFilter] = NodeManagerConfig::GetJobStartFilter();
|
||||
filterFiles[JobEndFilter] = NodeManagerConfig::GetJobEndFilter();
|
||||
filterFiles[TaskStartFilter] = NodeManagerConfig::GetTaskStartFilter();
|
||||
}
|
||||
|
||||
int OnJobStart(int jobId, const json::value& input, json::value& output, std::string& executionMessage);
|
||||
int OnJobEnd(int jobId, const json::value& input, json::value& output, std::string& executionMessage);
|
||||
int OnTaskStart(int jobId, int taskId, int requeueCount, const json::value& input, json::value& output, std::string& executionMessage);
|
||||
int ExecuteFilter(const std::string& filterType, int jobId, int taskId, int requeueCount, const json::value& input, json::value& output, std::string& executionMessage);
|
||||
|
||||
private:
|
||||
std::map<std::string, std::string> filterFiles;
|
||||
const std::string JobStartFilter = "JobStartFilter";
|
||||
const std::string JobEndFilter = "JobEndFilter";
|
||||
const std::string TaskStartFilter = "TaskStartFilter";
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,105 @@
|
|||
#include "ExecutionFilterTest.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <cpprest/http_listener.h>
|
||||
#include <cpprest/json.h>
|
||||
|
||||
#include "../utils/JsonHelper.h"
|
||||
#include "../core/Process.h"
|
||||
#include "../utils/Logger.h"
|
||||
#include "../core/RemoteCommunicator.h"
|
||||
#include "../core/RemoteExecutor.h"
|
||||
#include "../core/NodeManagerConfig.h"
|
||||
#include "../common/ErrorCodes.h"
|
||||
#include "../core/HttpHelper.h"
|
||||
#include "../utils/System.h"
|
||||
|
||||
using namespace hpc::tests;
|
||||
using namespace hpc::core;
|
||||
using namespace hpc::data;
|
||||
using namespace hpc::utils;
|
||||
|
||||
using namespace web::http;
|
||||
using namespace web;
|
||||
using namespace web::http::experimental::listener;
|
||||
using namespace web::http::client;
|
||||
|
||||
bool ExecutionFilterTest::JobStart()
|
||||
{
|
||||
bool result = true;
|
||||
const std::string networkName = "";
|
||||
RemoteExecutor executor(networkName);
|
||||
|
||||
http_listener_config config;
|
||||
config.set_ssl_context_callback([] (auto& ctx)
|
||||
{
|
||||
HttpHelper::ConfigListenerSslContext(ctx);
|
||||
});
|
||||
|
||||
RemoteCommunicator rc(executor, config);
|
||||
rc.Open();
|
||||
|
||||
http_client client(U("http://localhost:40000/"));
|
||||
uri_builder builder(U("/api/node/startjobandtask"));
|
||||
|
||||
std::string stdoutFile = "/tmp/JobStartFilterTest";
|
||||
std::string output;
|
||||
System::ExecuteCommandOut(output, "rm", stdoutFile);
|
||||
|
||||
ProcessStartInfo psi(
|
||||
"echo 123",
|
||||
"",
|
||||
std::string(stdoutFile),
|
||||
"",
|
||||
"",
|
||||
0,
|
||||
std::vector<uint64_t>(),
|
||||
{ { "CCP_ISADMIN", "1" } });
|
||||
|
||||
StartJobAndTaskArgs arg(
|
||||
88,
|
||||
88,
|
||||
std::move(psi),
|
||||
"",
|
||||
"");
|
||||
|
||||
json::value v1 = arg.ToJson();
|
||||
|
||||
Logger::Debug("Debug JSON: {0}", v1.serialize());
|
||||
StartJobAndTaskArgs arg1 = StartJobAndTaskArgs::FromJson(v1);
|
||||
|
||||
client.request(methods::POST, builder.to_string(), arg.ToJson()).then([&] (http_response response)
|
||||
{
|
||||
if (status_codes::OK != response.status_code())
|
||||
{
|
||||
Logger::Debug("The response code {0}", response.status_code());
|
||||
result = false;
|
||||
}
|
||||
}).wait();
|
||||
|
||||
sleep(2);
|
||||
|
||||
// verify the job start filter is called.
|
||||
// The command line is changed to echo 456.
|
||||
std::ifstream outFile(stdoutFile, std::ios::in);
|
||||
if (outFile)
|
||||
{
|
||||
int num;
|
||||
outFile >> num;
|
||||
Logger::Debug("stdout value {0}, expected value {1}", num, 456);
|
||||
result &= num == 456;
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::Debug("Stdout file not found {0}", stdoutFile);
|
||||
result = false;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // DEBUG
|
|
@ -0,0 +1,25 @@
|
|||
#ifndef EXECUTIONFILTERTEST_H
|
||||
#define EXECUTIONFILTERTEST_H
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
namespace hpc
|
||||
{
|
||||
namespace tests
|
||||
{
|
||||
class ExecutionFilterTest
|
||||
{
|
||||
public:
|
||||
ExecutionFilterTest() { }
|
||||
|
||||
static bool JobStart();
|
||||
|
||||
protected:
|
||||
private:
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // DEBUG
|
||||
|
||||
#endif // EXECUTIONFILTERTEST_H
|
|
@ -65,16 +65,17 @@ bool ProcessTest::ClusRun()
|
|||
callbacked = true;
|
||||
});
|
||||
|
||||
p.Start().then([&result, &started] (pid_t pid)
|
||||
pthread_t threadId;
|
||||
|
||||
p.Start().then([&result, &started, &threadId] (std::pair<pid_t, pthread_t> ids)
|
||||
{
|
||||
if (pid <= 0) result = false;
|
||||
|
||||
Logger::Info("pid {0}, result {1}", pid, result);
|
||||
|
||||
if (ids.first <= 0) result = false;
|
||||
Logger::Info("pid {0}, result {1}", ids.first, result);
|
||||
threadId = ids.second;
|
||||
started = true;
|
||||
});
|
||||
}).wait();
|
||||
|
||||
sleep(2);
|
||||
pthread_join(threadId, nullptr);
|
||||
|
||||
if (!(callbacked && started)) result = false;
|
||||
|
||||
|
@ -123,6 +124,7 @@ eesGSKS5l22ZMXJNShgzPKmv3HpH22CSVpO0sNZ6R+iG8a3oq4QkU61MT1CfGoMI\
|
|||
a8lxTKnZCsRXU1HexqZs+DSc+30tz50bNqLdido/l5B4EJnQP03ciO0=\
|
||||
-----END RSA PRIVATE KEY-----";
|
||||
|
||||
System::DeleteUser(userName);
|
||||
std::string publicKey = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDEkoEAGGc6wT16d4Ye+yN2hcqigdTGlMcjUlW6cAmRWYXLwkKoW3WlX3xAK0oQdMLqRDu2PVRPY3qfHURj0EEellpydeaSekp1fg27Rw2VKmEumu6Wxwo9HddXORPAQXTQ4yI0lWSerypckXVPeVjHetbkSci2foLedCbeBA9c/RyRgIUl227/pJKDNX2Rpqly0sY82nVWN/0p4NAyslexA0fGdBx+IgKnbU2JQKJeiwOomtEB/N492XRfCw2eCi7Ly3R8+U1KeBm+zH6Q8aH8ApqQohhLRw71bcWZ1g1bxd6HORxXOu0mFTzHbWFcZ9ILtXRl4Pt0x5Mve1AJXEKb hpclabsa@longhaulLN5-033\n";
|
||||
|
||||
int ret = System::CreateUser(userName, password);
|
||||
|
@ -151,16 +153,17 @@ a8lxTKnZCsRXU1HexqZs+DSc+30tz50bNqLdido/l5B4EJnQP03ciO0=\
|
|||
callbacked = true;
|
||||
});
|
||||
|
||||
p.Start().then([&result, &started] (pid_t pid)
|
||||
pthread_t threadId;
|
||||
|
||||
p.Start().then([&result, &started, &threadId] (std::pair<pid_t, pthread_t> ids)
|
||||
{
|
||||
if (pid <= 0) result = false;
|
||||
|
||||
Logger::Info("pid {0}, result {1}", pid, result);
|
||||
|
||||
if (ids.first <= 0) result = false;
|
||||
Logger::Info("pid {0}, result {1}", ids.first, result);
|
||||
threadId = ids.second;
|
||||
started = true;
|
||||
});
|
||||
}).wait();
|
||||
|
||||
sleep(1);
|
||||
pthread_join(threadId, nullptr);
|
||||
|
||||
if (!(callbacked && started)) result = false;
|
||||
|
||||
|
@ -213,6 +216,7 @@ a8lxTKnZCsRXU1HexqZs+DSc+30tz50bNqLdido/l5B4EJnQP03ciO0=\
|
|||
-----END RSA PRIVATE KEY-----";
|
||||
|
||||
std::string publicKey = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDEkoEAGGc6wT16d4Ye+yN2hcqigdTGlMcjUlW6cAmRWYXLwkKoW3WlX3xAK0oQdMLqRDu2PVRPY3qfHURj0EEellpydeaSekp1fg27Rw2VKmEumu6Wxwo9HddXORPAQXTQ4yI0lWSerypckXVPeVjHetbkSci2foLedCbeBA9c/RyRgIUl227/pJKDNX2Rpqly0sY82nVWN/0p4NAyslexA0fGdBx+IgKnbU2JQKJeiwOomtEB/N492XRfCw2eCi7Ly3R8+U1KeBm+zH6Q8aH8ApqQohhLRw71bcWZ1g1bxd6HORxXOu0mFTzHbWFcZ9ILtXRl4Pt0x5Mve1AJXEKb hpclabsa@longhaulLN5-033\n";
|
||||
System::DeleteUser(userName);
|
||||
|
||||
int ret = System::CreateUser(userName, password);
|
||||
if (ret != 0) return false;
|
||||
|
@ -240,16 +244,17 @@ a8lxTKnZCsRXU1HexqZs+DSc+30tz50bNqLdido/l5B4EJnQP03ciO0=\
|
|||
callbacked = true;
|
||||
});
|
||||
|
||||
p.Start().then([&result, &started] (pid_t pid)
|
||||
pthread_t threadId;
|
||||
|
||||
p.Start().then([&result, &started, &threadId] (std::pair<pid_t, pthread_t> ids)
|
||||
{
|
||||
if (pid <= 0) result = false;
|
||||
|
||||
Logger::Info("pid {0}, result {1}", pid, result);
|
||||
|
||||
if (ids.first <= 0) result = false;
|
||||
Logger::Info("pid {0}, result {1}", ids.first, result);
|
||||
threadId = ids.second;
|
||||
started = true;
|
||||
});
|
||||
}).wait();
|
||||
|
||||
sleep(1);
|
||||
pthread_join(threadId, nullptr);
|
||||
|
||||
if (!(callbacked && started)) result = false;
|
||||
|
||||
|
@ -302,6 +307,7 @@ a8lxTKnZCsRXU1HexqZs+DSc+30tz50bNqLdido/l5B4EJnQP03ciO0=\
|
|||
-----END RSA PRIVATE KEY-----";
|
||||
|
||||
std::string publicKey = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDEkoEAGGc6wT16d4Ye+yN2hcqigdTGlMcjUlW6cAmRWYXLwkKoW3WlX3xAK0oQdMLqRDu2PVRPY3qfHURj0EEellpydeaSekp1fg27Rw2VKmEumu6Wxwo9HddXORPAQXTQ4yI0lWSerypckXVPeVjHetbkSci2foLedCbeBA9c/RyRgIUl227/pJKDNX2Rpqly0sY82nVWN/0p4NAyslexA0fGdBx+IgKnbU2JQKJeiwOomtEB/N492XRfCw2eCi7Ly3R8+U1KeBm+zH6Q8aH8ApqQohhLRw71bcWZ1g1bxd6HORxXOu0mFTzHbWFcZ9ILtXRl4Pt0x5Mve1AJXEKb hpclabsa@longhaulLN5-033\n";
|
||||
System::DeleteUser(userName);
|
||||
|
||||
int ret = System::CreateUser(userName, password);
|
||||
if (ret != 0) return false;
|
||||
|
@ -364,16 +370,17 @@ a8lxTKnZCsRXU1HexqZs+DSc+30tz50bNqLdido/l5B4EJnQP03ciO0=\
|
|||
callbacked = true;
|
||||
});
|
||||
|
||||
p.Start().then([&result, &started] (pid_t pid)
|
||||
pthread_t threadId;
|
||||
|
||||
p.Start().then([&result, &started, &threadId] (std::pair<pid_t, pthread_t> ids)
|
||||
{
|
||||
if (pid <= 0) result = false;
|
||||
|
||||
Logger::Info("pid {0}, result {1}", pid, result);
|
||||
|
||||
if (ids.first <= 0) result = false;
|
||||
Logger::Info("pid {0}, result {1}", ids.first, result);
|
||||
threadId = ids.second;
|
||||
started = true;
|
||||
});
|
||||
}).wait();
|
||||
|
||||
sleep(1);
|
||||
pthread_join(threadId, nullptr);
|
||||
|
||||
if (!(callbacked && started)) result = false;
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include "../utils/Logger.h"
|
||||
#include "ProcessTest.h"
|
||||
#include "ExecutionFilterTest.h"
|
||||
|
||||
using namespace hpc::tests;
|
||||
using namespace hpc::utils;
|
||||
|
@ -14,6 +15,7 @@ TestRunner::TestRunner()
|
|||
this->tests["Affinity"] = []() { return ProcessTest::Affinity(); };
|
||||
this->tests["RemainingProcess"] = []() { return ProcessTest::RemainingProcess(); };
|
||||
this->tests["ClusRun"] = []() { return ProcessTest::ClusRun(); };
|
||||
this->tests["FilterJobStart"] = []() { return ExecutionFilterTest::JobStart(); };
|
||||
}
|
||||
|
||||
bool TestRunner::Run()
|
||||
|
@ -22,6 +24,9 @@ bool TestRunner::Run()
|
|||
Logger::Info("========================================================");
|
||||
Logger::Info("Start Testing, {0} cases in total.", this->tests.size());
|
||||
Logger::Info("========================================================");
|
||||
|
||||
std::map<std::string, bool> results;
|
||||
|
||||
for (auto& t : this->tests)
|
||||
{
|
||||
Logger::Info("");
|
||||
|
@ -34,9 +39,29 @@ bool TestRunner::Run()
|
|||
Logger::Info("");
|
||||
Logger::Info("");
|
||||
|
||||
results[t.first] = result;
|
||||
|
||||
if (!result) finalResult = false;
|
||||
}
|
||||
|
||||
Logger::Info("");
|
||||
Logger::Info("");
|
||||
Logger::Info("========================================================");
|
||||
Logger::Info("Testing result summary");
|
||||
Logger::Info("========================================================");
|
||||
int passed = 0;
|
||||
for (auto& t : results)
|
||||
{
|
||||
Logger::Info("Testing {0} : {1}", t.first, t.second ? "Passed" : "Failed");
|
||||
if (t.second)
|
||||
{
|
||||
passed++;
|
||||
}
|
||||
}
|
||||
|
||||
Logger::Info("========================================================");
|
||||
Logger::Info("All passed {0}, Pass rate {1} / {2}.", finalResult, passed, this->tests.size());
|
||||
|
||||
return finalResult;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ namespace hpc
|
|||
TestRunner();
|
||||
|
||||
bool Run();
|
||||
|
||||
protected:
|
||||
private:
|
||||
std::map<std::string, std::function<bool(void)>> tests;
|
||||
|
|
|
@ -37,6 +37,7 @@ namespace hpc
|
|||
|
||||
TOJSON(int, number)
|
||||
TOJSON(double, number)
|
||||
TOJSON(uint64_t, number)
|
||||
TOJSON(bool, boolean)
|
||||
TOJSON(std::string, string)
|
||||
}
|
||||
|
|
|
@ -76,7 +76,7 @@ namespace hpc
|
|||
return std::move(values);
|
||||
}
|
||||
|
||||
static json::array ToJson(const std::vector<T>& vec)
|
||||
static json::value ToJson(const std::vector<T>& vec)
|
||||
{
|
||||
std::vector<json::value> values;
|
||||
|
||||
|
@ -126,11 +126,21 @@ namespace hpc
|
|||
|
||||
return std::move(values);
|
||||
}
|
||||
//
|
||||
// static json::object ToJson(const std::map<std::string, T>& m)
|
||||
// {
|
||||
// return json::value::object(m);
|
||||
// }
|
||||
|
||||
static json::value ToJson(const std::map<std::string, T>& m)
|
||||
{
|
||||
json::value v;
|
||||
|
||||
std::for_each(
|
||||
m.cbegin(),
|
||||
m.cend(),
|
||||
[&v](const std::pair<std::string, T>& p)
|
||||
{
|
||||
v[p.first] = JsonHelper<T>::ToJson(p.second);
|
||||
});
|
||||
|
||||
return std::move(v);
|
||||
}
|
||||
// static void Write(const std::string& name, json::value& v, const std::vector<T>& t);
|
||||
|
||||
protected:
|
||||
|
|
|
@ -542,3 +542,38 @@ int System::DeleteUser(const std::string& userName)
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int System::CreateTempFolder(char* folderTemplate, const std::string& userName)
|
||||
{
|
||||
char* p = mkdtemp(folderTemplate);
|
||||
|
||||
if (p)
|
||||
{
|
||||
std::string output;
|
||||
int ret = System::ExecuteCommandOut(output, "chown -R", userName, p);
|
||||
if (ret == 0)
|
||||
{
|
||||
ret = System::ExecuteCommandOut(output, "chmod -R u+rwX", p);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
return errno;
|
||||
}
|
||||
}
|
||||
|
||||
int System::WriteStringToFile(const std::string& fileName, const std::string& contents)
|
||||
{
|
||||
std::ofstream os(fileName, std::ios::trunc);
|
||||
if (!os)
|
||||
{
|
||||
return (int)ErrorCodes::WriteFileError;
|
||||
}
|
||||
|
||||
os << contents;
|
||||
os.close();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -59,6 +59,8 @@ namespace hpc
|
|||
const std::string& key);
|
||||
|
||||
static int DeleteUser(const std::string& userName);
|
||||
static int CreateTempFolder(char* folderTemplate, const std::string& userName);
|
||||
static int WriteStringToFile(const std::string& fileName, const std::string& contents);
|
||||
|
||||
template <typename ... Args>
|
||||
static int ExecuteCommandIn(const std::string& input, const std::string& cmd, const Args& ... args)
|
||||
|
|
Загрузка…
Ссылка в новой задаче