1 /*  $Id: nst_automation.cpp 572261 2018-10-10 19:24:55Z 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: Rafael Sadyrov
27  *
28  * File Description: NetStorage automation implementation.
29  *
30  */
31 
32 #include <ncbi_pch.hpp>
33 
34 #include "nst_automation.hpp"
35 
36 USING_NCBI_SCOPE;
37 
38 using namespace NAutomation;
39 
40 const string SNetStorageService::kName = "nstsvc";
41 const string SNetStorageServer::kName = "nstsrv";
42 const string SNetStorageObject::kName = "nstobj";
43 
NewCommand()44 CCommand SNetStorageService::NewCommand()
45 {
46     return CCommand(kName, ExecNew<TSelf>, {
47             { "service_name", CJsonNode::eString, },
48             { "domain_name", "", },
49             { "client_name", "", },
50             { "metadata", "", },
51             { "ticket", "", },
52             { "hello_service", "", },
53         });
54 }
55 
NewCommand()56 CCommand SNetStorageServer::NewCommand()
57 {
58     return CCommand(kName, ExecNew<TSelf>, {
59             { "service_name", CJsonNode::eString, },
60             { "domain_name", "", },
61             { "client_name", "", },
62             { "metadata", "", },
63             { "ticket", "", },
64             { "hello_service", "", },
65         });
66 }
67 
s_GetInitString(const TArguments & args)68 string s_GetInitString(const TArguments& args)
69 {
70     _ASSERT(args.size() == 6);
71 
72     const auto service_name  = args["service_name"].AsString();
73     const auto domain_name   = args["domain_name"].AsString();
74     const auto client_name   = args["client_name"].AsString();
75     const auto metadata      = args["metadata"].AsString();
76     const auto ticket        = args["ticket"].AsString();
77     const auto hello_service = args["hello_service"].AsString();
78 
79     const string init_string(
80             "nst=" + service_name + "&domain=" + domain_name +
81             "&client=" + client_name + "&metadata=" + metadata +
82             "&ticket=" + ticket + "&hello_service=" + hello_service);
83 
84     return init_string;
85 }
86 
Create(const TArguments & args,CAutomationProc * automation_proc)87 CAutomationObject* SNetStorageService::Create(const TArguments& args, CAutomationProc* automation_proc)
88 {
89     CNetStorage nst_api(s_GetInitString(args));
90     CNetStorageAdmin nst_api_admin(nst_api);
91     return new SNetStorageService(automation_proc, nst_api_admin);
92 }
93 
Create(const TArguments & args,CAutomationProc * automation_proc)94 CAutomationObject* SNetStorageServer::Create(const TArguments& args, CAutomationProc* automation_proc)
95 {
96     CNetStorage nst_api(s_GetInitString(args));
97     CNetStorageAdmin nst_api_admin(nst_api);
98     CNetServer server = nst_api_admin.GetService().Iterate().GetServer();
99     return new SNetStorageServer(automation_proc, nst_api_admin, server);
100 }
101 
SNetStorageService(CAutomationProc * automation_proc,CNetStorageAdmin nst_api)102 SNetStorageService::SNetStorageService(
103         CAutomationProc* automation_proc,
104         CNetStorageAdmin nst_api) :
105     SNetServiceBase(automation_proc),
106     m_NetStorageAdmin(nst_api)
107 {
108     auto warning_handler = [&](const string& m, CNetServer s) {
109         auto o = m_AutomationProc->ReturnNetStorageServerObject(m_NetStorageAdmin, s);
110         m_AutomationProc->SendWarning(m, o);
111         return true;
112     };
113 
114     GetService().SetWarningHandler(warning_handler);
115 }
116 
SNetStorageServer(CAutomationProc * automation_proc,CNetStorageAdmin nst_api,CNetServer::TInstance server)117 SNetStorageServer::SNetStorageServer(
118         CAutomationProc* automation_proc,
119         CNetStorageAdmin nst_api, CNetServer::TInstance server) :
120     SNetStorageService(automation_proc, nst_api.GetServer(server))
121 {
122     if (GetService().IsLoadBalanced()) {
123         NCBI_THROW(CAutomationException, eCommandProcessingError,
124                 "NetStorageServer constructor: "
125                 "'server_address' must be a host:port combination");
126     }
127 }
128 
ReturnNetStorageServerObject(CNetStorageAdmin::TInstance nst_api,CNetServer::TInstance server)129 TAutomationObjectRef CAutomationProc::ReturnNetStorageServerObject(
130         CNetStorageAdmin::TInstance nst_api,
131         CNetServer::TInstance server)
132 {
133     TAutomationObjectRef object(new SNetStorageServer(this, nst_api, server));
134     AddObject(object);
135     return object;
136 }
137 
CallCommand()138 CCommand SNetStorageService::CallCommand()
139 {
140     return CCommand(kName, TCommandGroup(CallCommands(), CheckCall<TSelf>));
141 }
142 
CallCommands()143 TCommands SNetStorageService::CallCommands()
144 {
145     TCommands cmds =
146     {
147         { "clients_info",   ExecMethod<TSelf, &TSelf::ExecClientsInfo>, },
148         { "users_info",     ExecMethod<TSelf, &TSelf::ExecUsersInfo>, },
149         { "client_objects", ExecMethod<TSelf, &TSelf::ExecClientObjects>, {
150                 { "client_name", CJsonNode::eString, },
151                 { "limit", 0, },
152             }},
153         { "user_objects",   ExecMethod<TSelf, &TSelf::ExecUserObjects>, {
154                 { "user_name", CJsonNode::eString, },
155                 { "user_ns", "" },
156                 { "limit", 0, },
157             }},
158         { "open_object",    ExecMethod<TSelf, &TSelf::ExecOpenObject>, {
159                 { "object_loc", CJsonNode::eString, },
160             }},
161         { "server_info",    ExecMethod<TSelf, &TSelf::ExecServerInfo>, },
162         { "get_servers",    ExecMethod<TSelf, &TSelf::ExecGetServers>, },
163     };
164 
165     TCommands base_cmds = SNetServiceBase::CallCommands();
166     cmds.insert(cmds.end(), base_cmds.begin(), base_cmds.end());
167 
168     return cmds;
169 }
170 
ExecRequest(const string & request_type,SInputOutput & io)171 void SNetStorageService::ExecRequest(const string& request_type, SInputOutput& io)
172 {
173     auto& reply = io.reply;
174     CJsonNode request(m_NetStorageAdmin.MkNetStorageRequest(request_type));
175     CJsonNode response(m_NetStorageAdmin.ExchangeJson(request));
176     NNetStorage::RemoveStdReplyFields(response);
177     reply.Append(response);
178 }
179 
ExecClientsInfo(const TArguments &,SInputOutput & io)180 void SNetStorageService::ExecClientsInfo(const TArguments&, SInputOutput& io)
181 {
182     ExecRequest("GETCLIENTSINFO", io);
183 }
184 
ExecUsersInfo(const TArguments &,SInputOutput & io)185 void SNetStorageService::ExecUsersInfo(const TArguments&, SInputOutput& io)
186 {
187     ExecRequest("GETUSERSINFO", io);
188 }
189 
ExecClientObjects(const TArguments & args,SInputOutput & io)190 void SNetStorageService::ExecClientObjects(const TArguments& args, SInputOutput& io)
191 {
192     _ASSERT(args.size() == 2);
193 
194     auto& reply = io.reply;
195     const auto client_name = args["client_name"].AsString();
196     const auto limit       = args["limit"].AsInteger();
197     CJsonNode request(m_NetStorageAdmin.MkNetStorageRequest("GETCLIENTOBJECTS"));
198     request.SetString("ClientName", client_name);
199     if (limit) request.SetInteger("Limit", limit);
200 
201     CJsonNode response(m_NetStorageAdmin.ExchangeJson(request));
202     NNetStorage::RemoveStdReplyFields(response);
203     reply.Append(response);
204 }
205 
ExecUserObjects(const TArguments & args,SInputOutput & io)206 void SNetStorageService::ExecUserObjects(const TArguments& args, SInputOutput& io)
207 {
208     _ASSERT(args.size() == 3);
209 
210     auto& reply = io.reply;
211     const auto user_name = args["user_name"].AsString();
212     const auto user_ns   = args["user_ns"].AsString();
213     const auto limit     = args["limit"].AsInteger();
214     CJsonNode request(m_NetStorageAdmin.MkNetStorageRequest("GETUSEROBJECTS"));
215     request.SetString("UserName", user_name);
216     if (!user_ns.empty()) request.SetString("UserNamespace", user_ns);
217     if (limit) request.SetInteger("Limit", limit);
218 
219     CJsonNode response(m_NetStorageAdmin.ExchangeJson(request));
220     NNetStorage::RemoveStdReplyFields(response);
221     reply.Append(response);
222 }
223 
ExecServerInfo(const TArguments &,SInputOutput & io)224 void SNetStorageService::ExecServerInfo(const TArguments&, SInputOutput& io)
225 {
226     auto& reply = io.reply;
227     NNetStorage::CExecToJson info_to_json(m_NetStorageAdmin, "INFO");
228     CNetService service(m_NetStorageAdmin.GetService());
229 
230     CJsonNode response(g_ExecToJson(info_to_json, service,
231             CNetService::eIncludePenalized));
232     reply.Append(response);
233 }
234 
ExecOpenObject(const TArguments & args,SInputOutput & io)235 void SNetStorageService::ExecOpenObject(const TArguments& args, SInputOutput& io)
236 {
237     _ASSERT(args.size() == 1);
238 
239     auto& reply = io.reply;
240     const auto object_loc = args["object_loc"].AsString();
241     CNetStorageObject object(m_NetStorageAdmin.Open(object_loc));
242     TAutomationObjectRef automation_object(
243             new SNetStorageObject(m_AutomationProc, object));
244 
245     TObjectID response(m_AutomationProc->AddObject(automation_object));
246     reply.AppendInteger(response);
247 }
248 
ExecGetServers(const TArguments &,SInputOutput & io)249 void SNetStorageService::ExecGetServers(const TArguments&, SInputOutput& io)
250 {
251     auto& reply = io.reply;
252     CJsonNode object_ids(CJsonNode::NewArrayNode());
253     for (CNetServiceIterator it = m_NetStorageAdmin.GetService().Iterate(
254             CNetService::eIncludePenalized); it; ++it)
255         object_ids.AppendInteger(m_AutomationProc->
256                 ReturnNetStorageServerObject(m_NetStorageAdmin, *it)->GetID());
257     reply.Append(object_ids);
258 }
259 
CallCommand()260 CCommand SNetStorageServer::CallCommand()
261 {
262     return CCommand(kName, TCommandGroup(CallCommands(), CheckCall<TSelf>));
263 }
264 
CallCommands()265 TCommands SNetStorageServer::CallCommands()
266 {
267     TCommands cmds =
268     {
269         { "health",        ExecMethod<TSelf, &TSelf::ExecHealth>, },
270         { "conf",          ExecMethod<TSelf, &TSelf::ExecConf>, },
271         { "metadata_info", ExecMethod<TSelf, &TSelf::ExecMetadataInfo>, },
272         { "reconf",        ExecMethod<TSelf, &TSelf::ExecReconf>, },
273         { "ackalert",      ExecMethod<TSelf, &TSelf::ExecAckAlert>, {
274                 { "name", CJsonNode::eString, },
275                 { "user", CJsonNode::eString, },
276             }},
277     };
278 
279     TCommands base_cmds = SNetStorageService::CallCommands();
280     cmds.insert(cmds.end(), base_cmds.begin(), base_cmds.end());
281 
282     return cmds;
283 }
284 
ExecHealth(const TArguments &,SInputOutput & io)285 void SNetStorageServer::ExecHealth(const TArguments&, SInputOutput& io)
286 {
287     ExecRequest("HEALTH", io);
288 }
289 
ExecConf(const TArguments &,SInputOutput & io)290 void SNetStorageServer::ExecConf(const TArguments&, SInputOutput& io)
291 {
292     ExecRequest("CONFIGURATION", io);
293 }
294 
ExecMetadataInfo(const TArguments &,SInputOutput & io)295 void SNetStorageServer::ExecMetadataInfo(const TArguments&, SInputOutput& io)
296 {
297     ExecRequest("GETMETADATAINFO", io);
298 }
299 
ExecReconf(const TArguments &,SInputOutput & io)300 void SNetStorageServer::ExecReconf(const TArguments&, SInputOutput& io)
301 {
302     ExecRequest("RECONFIGURE", io);
303 }
304 
ExecAckAlert(const TArguments & args,SInputOutput & io)305 void SNetStorageServer::ExecAckAlert(const TArguments& args, SInputOutput& io)
306 {
307     _ASSERT(args.size() == 2);
308 
309     auto& reply = io.reply;
310     const auto name = args["name"].AsString();
311     const auto user = args["user"].AsString();
312 
313     CJsonNode request(m_NetStorageAdmin.MkNetStorageRequest("ACKALERT"));
314     request.SetString("Name", name);
315     request.SetString("User", user);
316 
317     CJsonNode response(m_NetStorageAdmin.ExchangeJson(request));
318     NNetStorage::RemoveStdReplyFields(response);
319     reply.Append(response);
320 }
321 
SNetStorageObject(CAutomationProc * automation_proc,CNetStorageObject::TInstance object)322 SNetStorageObject::SNetStorageObject(
323         CAutomationProc* automation_proc, CNetStorageObject::TInstance object) :
324     CAutomationObject(automation_proc),
325     m_Object(object)
326 {
327 }
328 
CallCommand()329 CCommand SNetStorageObject::CallCommand()
330 {
331     return CCommand(kName, TCommandGroup(CallCommands(), CheckCall<TSelf>));
332 }
333 
CallCommands()334 TCommands SNetStorageObject::CallCommands()
335 {
336     TCommands cmds =
337     {
338         { "info",      ExecMethod<TSelf, &TSelf::ExecInfo>, },
339         { "attr_list", ExecMethod<TSelf, &TSelf::ExecAttrList>, },
340         { "get_attr",  ExecMethod<TSelf, &TSelf::ExecGetAttr>, {
341                 { "attr_name", CJsonNode::eString, },
342             }},
343     };
344 
345     return cmds;
346 }
347 
ExecInfo(const TArguments &,SInputOutput & io)348 void SNetStorageObject::ExecInfo(const TArguments&, SInputOutput& io)
349 {
350     auto& reply = io.reply;
351     CNetStorageObjectInfo object_info(m_Object.GetInfo());
352     CJsonNode response(object_info.ToJSON());
353     reply.Append(response);
354 }
355 
ExecAttrList(const TArguments &,SInputOutput & io)356 void SNetStorageObject::ExecAttrList(const TArguments&, SInputOutput& io)
357 {
358     auto& reply = io.reply;
359     CNetStorageObject::TAttributeList attr_list(m_Object.GetAttributeList());
360     CJsonNode response(CJsonNode::eArray);
361     for (auto& attr : attr_list) response.AppendString(attr);
362     reply.Append(response);
363 }
364 
ExecGetAttr(const TArguments & args,SInputOutput & io)365 void SNetStorageObject::ExecGetAttr(const TArguments& args, SInputOutput& io)
366 {
367     _ASSERT(args.size() == 1);
368 
369     auto& reply = io.reply;
370     const auto attr_name = args["attr_name"].AsString();
371     CJsonNode response(m_Object.GetAttribute(attr_name));
372     reply.Append(response);
373 }
374