1 /*  $Id: wn_automation.cpp 554817 2018-01-09 17:38:11Z sadyrovr $
2  * ===========================================================================
3  *
4  *                            PUBLIC DOMAIN NOTICE
5  *               National Center for Biotechnology Information
6  *
7  *  This software/database is a "United States Government Work" under the
8  *  terms of the United States Copyright Act.  It was written as part of
9  *  the author's official duties as a United States Government employee and
10  *  thus cannot be copyrighted.  This software/database is freely available
11  *  to the public for use. The National Library of Medicine and the U.S.
12  *   Government have not placed any restriction on its use or reproduction.
13  *
14  *  Although all reasonable efforts have been taken to ensure the accuracy
15  *  and reliability of the software and data, the NLM and the U.S.
16  *  Government do not and cannot warrant the performance or results that
17  *  may be obtained by using this software or data. The NLM and the U.S.
18  *  Government disclaim all warranties, express or implied, including
19  *  warranties of performance, merchantability or fitness for any particular
20  *  purpose.
21  *
22  *  Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * Authors:  Dmitry Kazimirov
27  *
28  * File Description: Worker node automation implementation.
29  *
30  */
31 
32 #include <ncbi_pch.hpp>
33 
34 #include "wn_automation.hpp"
35 
36 USING_NCBI_SCOPE;
37 
38 using namespace NAutomation;
39 
40 const string SWorkerNode::kName = "wn";
41 
SWorkerNode(CAutomationProc * automation_proc,CNetScheduleAPI ns_api)42 SWorkerNode::SWorkerNode(
43         CAutomationProc* automation_proc, CNetScheduleAPI ns_api) :
44     SNetService(automation_proc),
45     m_NetScheduleAPI(ns_api)
46 {
47     m_WorkerNode = GetServer();
48 
49     if (GetService().IsLoadBalanced()) {
50         NCBI_THROW(CAutomationException, eCommandProcessingError,
51                 "WorkerNode constructor: 'wn_address' "
52                 "must be a host:port combination");
53     }
54 }
55 
NewCommand()56 CCommand SWorkerNode::NewCommand()
57 {
58     return CCommand(kName, ExecNew<TSelf>, {
59             { "wn_address", CJsonNode::eString, },
60             { "client_name", "", },
61         });
62 }
63 
Create(const TArguments & args,CAutomationProc * automation_proc)64 CAutomationObject* SWorkerNode::Create(const TArguments& args, CAutomationProc* automation_proc)
65 {
66     _ASSERT(args.size() == 2);
67 
68     const auto wn_address  = args["wn_address"].AsString();
69     const auto client_name = args["client_name"].AsString();
70 
71     CNetScheduleAPIExt ns_api(CNetScheduleAPIExt::CreateWnCompat(
72                 wn_address, client_name));
73 
74     return new SWorkerNode(automation_proc, ns_api);
75 }
76 
CallCommand()77 CCommand SWorkerNode::CallCommand()
78 {
79     return CCommand(kName, TCommandGroup(CallCommands(), CheckCall<TSelf>));
80 }
81 
CallCommands()82 TCommands SWorkerNode::CallCommands()
83 {
84     TCommands cmds =
85     {
86         { "version",  ExecMethod<TSelf, &TSelf::ExecVersion>, },
87         { "wn_info",  ExecMethod<TSelf, &TSelf::ExecWnInfo>, },
88         { "suspend",  ExecMethod<TSelf, &TSelf::ExecSuspend>, {
89                 { "pullback_mode", false, },
90                 { "timeout", 0, },
91             }},
92         { "resume",   ExecMethod<TSelf, &TSelf::ExecResume>, },
93         { "shutdown", ExecMethod<TSelf, &TSelf::ExecShutdown>, {
94                 { "level", 0 },
95             }},
96     };
97 
98     TCommands base_cmds = SNetService::CallCommands();
99     cmds.insert(cmds.end(), base_cmds.begin(), base_cmds.end());
100 
101     return cmds;
102 }
103 
ExecVersion(const TArguments &,SInputOutput & io)104 void SWorkerNode::ExecVersion(const TArguments&, SInputOutput& io)
105 {
106     auto& reply = io.reply;
107     reply.Append(g_ServerInfoToJson(GetService(), false));
108 }
109 
ExecWnInfo(const TArguments &,SInputOutput & io)110 void SWorkerNode::ExecWnInfo(const TArguments&, SInputOutput& io)
111 {
112     auto& reply = io.reply;
113     reply.Append(g_WorkerNodeInfoToJson(m_WorkerNode));
114 }
115 
ExecSuspend(const TArguments & args,SInputOutput &)116 void SWorkerNode::ExecSuspend(const TArguments& args, SInputOutput&)
117 {
118     _ASSERT(args.size() == 2);
119 
120     const auto pullback_mode = args["pullback_mode"].AsBoolean();
121     const auto timeout       = args["timeout"].AsInteger<unsigned int>();
122     g_SuspendWorkerNode(m_WorkerNode, pullback_mode, timeout);
123 }
124 
ExecResume(const TArguments &,SInputOutput &)125 void SWorkerNode::ExecResume(const TArguments&, SInputOutput&)
126 {
127     g_ResumeWorkerNode(m_WorkerNode);
128 }
129 
s_GetWorkerNodeShutdownMode(Int8 level)130 CNetScheduleAdmin::EShutdownLevel s_GetWorkerNodeShutdownMode(Int8 level)
131 {
132     enum EWorkerNodeShutdownMode { eNormalShutdown, eShutdownNow, eKillNode };
133 
134     switch (level) {
135     case eShutdownNow: return CNetScheduleAdmin::eShutdownImmediate;
136     case eKillNode:    return CNetScheduleAdmin::eDie;
137     default:           return CNetScheduleAdmin::eNormalShutdown;
138     }
139 }
140 
ExecShutdown(const TArguments & args,SInputOutput &)141 void SWorkerNode::ExecShutdown(const TArguments& args, SInputOutput&)
142 {
143     _ASSERT(args.size() == 1);
144 
145     const auto level = args["level"].AsInteger();
146     m_NetScheduleAPI.GetAdmin().ShutdownServer(s_GetWorkerNodeShutdownMode(level));
147 }
148