]> granicus.if.org Git - icinga2/commitdiff
Implement basic actions framework
authorJean-Marcel Flach <jean-marcel.flach@netways.de>
Thu, 30 Jul 2015 15:50:17 +0000 (17:50 +0200)
committerMichael Friedrich <michael.friedrich@netways.de>
Thu, 30 Jul 2015 15:50:17 +0000 (17:50 +0200)
refs #9080

lib/icinga/CMakeLists.txt
lib/icinga/apiactions.cpp [new file with mode: 0644]
lib/icinga/apiactions.hpp [new file with mode: 0644]
lib/remote/CMakeLists.txt
lib/remote/actionshandler.cpp [new file with mode: 0644]
lib/remote/actionshandler.hpp [new file with mode: 0644]
lib/remote/apiaction.cpp [new file with mode: 0644]
lib/remote/apiaction.hpp [new file with mode: 0644]
lib/remote/apifunction.hpp
lib/remote/httputility.cpp
lib/remote/httputility.hpp

index 65801a1a23c049fb2f91ef5146cd9902a2389d38..57a8a3e287cd31124c2d828de964a5e6b42c94b5 100644 (file)
@@ -41,7 +41,7 @@ mkclass_target(user.ti user.tcpp user.thpp)
 mkembedconfig_target(icinga-app.conf icinga-app.cpp)
 
 set(icinga_SOURCES
-  api.cpp apievents.cpp checkable.cpp checkable.thpp checkable-dependency.cpp checkable-downtime.cpp checkable-event.cpp
+  api.cpp apiactions.cpp apievents.cpp checkable.cpp checkable.thpp checkable-dependency.cpp checkable-downtime.cpp checkable-event.cpp
   checkable-flapping.cpp checkcommand.cpp checkcommand.thpp checkresult.cpp checkresult.thpp
   cib.cpp command.cpp command.thpp comment.cpp comment.thpp compatutility.cpp dependency.cpp dependency.thpp
   dependency-apply.cpp downtime.cpp downtime.thpp eventcommand.cpp eventcommand.thpp
diff --git a/lib/icinga/apiactions.cpp b/lib/icinga/apiactions.cpp
new file mode 100644 (file)
index 0000000..608c7b2
--- /dev/null
@@ -0,0 +1,48 @@
+/******************************************************************************
+ * Icinga 2                                                                   *
+ * Copyright (C) 2012-2015 Icinga Development Team (http://www.icinga.org)    *
+ *                                                                            *
+ * 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 2             *
+ * 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, write to the Free Software Foundation     *
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.             *
+ ******************************************************************************/
+
+#include "icinga/apiactions.hpp"
+#include "icinga/service.hpp"
+#include "remote/apiaction.hpp"
+#include "remote/httputility.hpp"
+#include "base/utility.hpp"
+#include "base/convert.hpp"
+
+using namespace icinga;
+
+REGISTER_APIACTION(reschedule_check, "Service;Host", &ApiActions::RescheduleCheck);
+
+Dictionary::Ptr ApiActions::RescheduleCheck(const DynamicObject::Ptr& object, const Dictionary::Ptr& params)
+{
+       Checkable::Ptr checkable = static_pointer_cast<Checkable>(object);
+       if (Convert::ToBool(HttpUtility::GetLastParameter(params, "force")))
+               checkable->SetForceNextCheck(true);
+
+       double nextCheck;
+       if (params->Contains("next_check"))
+               nextCheck = HttpUtility::GetLastParameter(params, "next_check");
+       else
+               nextCheck = Utility::GetTime();
+
+       checkable->SetNextCheck(nextCheck);
+       Dictionary::Ptr result = new Dictionary();
+       result->Set("code", 200);
+       result->Set("status", "yay");
+       return result;
+}
diff --git a/lib/icinga/apiactions.hpp b/lib/icinga/apiactions.hpp
new file mode 100644 (file)
index 0000000..567186c
--- /dev/null
@@ -0,0 +1,41 @@
+/******************************************************************************
+ * Icinga 2                                                                   *
+ * Copyright (C) 2012-2015 Icinga Development Team (http://www.icinga.org)    *
+ *                                                                            *
+ * 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 2             *
+ * 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, write to the Free Software Foundation     *
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.             *
+ ******************************************************************************/
+
+#ifndef APIACTIONS_H
+#define APIACTIONS_H
+
+#include "icinga/i2-icinga.hpp"
+#include "base/dynamicobject.hpp"
+#include "base/dictionary.hpp"
+
+namespace icinga
+{
+
+/**
+ * @ingroup icinga
+ */
+class I2_ICINGA_API ApiActions
+{
+public:
+       static Dictionary::Ptr RescheduleCheck(const DynamicObject::Ptr& object, const Dictionary::Ptr& params);
+};
+
+}
+
+#endif /* APIACTIONS_H */
index f5aed5aa91bb1848135e6fcd556ab3fbe32f22c2..07a9953f264470ccac8ec9a9194fc578b81676e4 100644 (file)
@@ -21,14 +21,14 @@ mkclass_target(endpoint.ti endpoint.tcpp endpoint.thpp)
 mkclass_target(zone.ti zone.tcpp zone.thpp)
 
 set(remote_SOURCES
+  actionshandler.cpp apiaction.cpp
   apifunction.cpp apilistener.cpp apilistener.thpp apilistener-sync.cpp
   apiuser.cpp apiuser.thpp authority.cpp base64.cpp configfileshandler.cpp
   configmoduleshandler.cpp configmoduleutility.cpp configstageshandler.cpp
   endpoint.cpp endpoint.thpp filterutility.cpp
   httpchunkedencoding.cpp  httpconnection.cpp httphandler.cpp httprequest.cpp httpresponse.cpp
   httputility.cpp jsonrpc.cpp jsonrpcconnection.cpp jsonrpcconnection-heartbeat.cpp
-  messageorigin.cpp statusqueryhandler.cpp zone.cpp zone.thpp
-  url.cpp
+  messageorigin.cpp statusqueryhandler.cpp url.cpp zone.cpp zone.thpp
 )
 
 if(ICINGA2_UNITY_BUILD)
diff --git a/lib/remote/actionshandler.cpp b/lib/remote/actionshandler.cpp
new file mode 100644 (file)
index 0000000..f9291d4
--- /dev/null
@@ -0,0 +1,83 @@
+/******************************************************************************
+ * Icinga 2                                                                   *
+ * Copyright (C) 2012-2015 Icinga Development Team (http://www.icinga.org)    *
+ *                                                                            *
+ * 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 2             *
+ * 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, write to the Free Software Foundation     *
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.             *
+ ******************************************************************************/
+
+#include "remote/actionshandler.hpp"
+#include "remote/httputility.hpp"
+#include "remote/filterutility.hpp"
+#include "remote/apiaction.hpp"
+#include "base/exception.hpp"
+#include "base/serializer.hpp"
+#include <boost/algorithm/string.hpp>
+#include <set>
+
+using namespace icinga;
+
+REGISTER_URLHANDLER("/v1/actions", ActionsHandler);
+
+bool ActionsHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& request, HttpResponse& response)
+{
+       if (request.RequestUrl->GetPath().size() < 3)
+               return false;
+
+       if (request.RequestMethod != "POST") {
+               response.SetStatus(400, "Bad request");
+               return true;
+       }
+
+       String actionName = request.RequestUrl->GetPath()[2];
+
+       ApiAction::Ptr action = ApiAction::GetByName(actionName);
+
+       if (!action)
+               return false;
+
+       QueryDescription qd;
+
+       BOOST_FOREACH(const String& typeName, action->GetTypes()) {
+               Type::Ptr type = Type::GetByName(typeName);
+               ASSERT(type);
+               qd.Types.insert(type);
+       }
+
+       Dictionary::Ptr params = HttpUtility::FetchRequestParameters(request);
+
+       std::vector<DynamicObject::Ptr> objs = FilterUtility::GetFilterTargets(qd, params);
+
+       Array::Ptr results = new Array();
+
+       BOOST_FOREACH(const DynamicObject::Ptr& obj, objs) {
+               try {
+                       results->Add(action->Invoke(obj, params));
+               } catch (const std::exception& ex) {
+                       Dictionary::Ptr fail = new Dictionary();
+                       fail->Set("code", 501);
+                       fail->Set("status", "Error: " + DiagnosticInformation(ex));
+                       results->Add(fail);
+               }
+       }
+
+       Dictionary::Ptr result = new Dictionary();
+       result->Set("results", results);
+
+       response.SetStatus(200, "OK");
+       HttpUtility::SendJsonBody(response, result);
+
+       return true;
+}
+
diff --git a/lib/remote/actionshandler.hpp b/lib/remote/actionshandler.hpp
new file mode 100644 (file)
index 0000000..e9445bb
--- /dev/null
@@ -0,0 +1,38 @@
+/******************************************************************************
+ * Icinga 2                                                                   *
+ * Copyright (C) 2012-2015 Icinga Development Team (http://www.icinga.org)    *
+ *                                                                            *
+ * 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 2             *
+ * 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, write to the Free Software Foundation     *
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.             *
+ ******************************************************************************/
+
+#ifndef ACTIONSHANDLER_H
+#define ACTIONSHANDLER_H
+
+#include "remote/httphandler.hpp"
+
+namespace icinga
+{
+
+class I2_REMOTE_API ActionsHandler : public HttpHandler
+{
+public:
+       DECLARE_PTR_TYPEDEFS(ActionsHandler);
+
+       virtual bool HandleRequest(const ApiUser::Ptr& user, HttpRequest& request, HttpResponse& response);
+};
+
+}
+
+#endif /* ACTIONSHANDLER_H */
diff --git a/lib/remote/apiaction.cpp b/lib/remote/apiaction.cpp
new file mode 100644 (file)
index 0000000..3c999d3
--- /dev/null
@@ -0,0 +1,57 @@
+/******************************************************************************
+ * Icinga 2                                                                   *
+ * Copyright (C) 2012-2015 Icinga Development Team (http://www.icinga.org)    *
+ *                                                                            *
+ * 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 2             *
+ * 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, write to the Free Software Foundation     *
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.             *
+ ******************************************************************************/
+
+#include "remote/apiaction.hpp"
+#include "base/singleton.hpp"
+
+using namespace icinga;
+
+ApiAction::ApiAction(const std::vector<String>& types, const Callback& action)
+: m_Types(types), m_Callback(action)
+{ }
+
+Value ApiAction::Invoke(const DynamicObject::Ptr& target, const Dictionary::Ptr& params)
+{
+       return m_Callback(target, params);
+}
+
+const std::vector<String>& ApiAction::GetTypes(void) const
+{
+       return m_Types;
+}
+
+ApiAction::Ptr ApiAction::GetByName(const String& name)
+{
+       return ApiActionRegistry::GetInstance()->GetItem(name);
+}
+
+void ApiAction::Register(const String& name, const ApiAction::Ptr& action)
+{
+       ApiActionRegistry::GetInstance()->Register(name, action);
+}
+
+void ApiAction::Unregister(const String& name)
+{
+       ApiActionRegistry::GetInstance()->Unregister(name);
+}
+
+ApiActionRegistry *ApiActionRegistry::GetInstance(void)
+{
+       return Singleton<ApiActionRegistry>::GetInstance();
+}
diff --git a/lib/remote/apiaction.hpp b/lib/remote/apiaction.hpp
new file mode 100644 (file)
index 0000000..ff7e924
--- /dev/null
@@ -0,0 +1,92 @@
+/******************************************************************************
+ * Icinga 2                                                                   *
+ * Copyright (C) 2012-2015 Icinga Development Team (http://www.icinga.org)    *
+ *                                                                            *
+ * 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 2             *
+ * 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, write to the Free Software Foundation     *
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.             *
+ ******************************************************************************/
+
+#ifndef APIACTION_H
+#define APIACTION_H
+
+#include "remote/i2-remote.hpp"
+#include "base/registry.hpp"
+#include "base/value.hpp"
+#include "base/dictionary.hpp"
+#include "base/dynamicobject.hpp"
+#include <vector>
+#include <boost/function.hpp>
+#include <boost/algorithm/string/replace.hpp>
+#include <boost/algorithm/string/classification.hpp>
+#include <boost/algorithm/string/split.hpp>
+
+namespace icinga
+{
+
+/**
+ * An API action.
+ *
+ * @ingroup remote
+ */
+class I2_REMOTE_API ApiAction : public Object
+{
+public:
+       DECLARE_PTR_TYPEDEFS(ApiAction);
+
+       typedef boost::function<Value(const DynamicObject::Ptr& target, const Dictionary::Ptr& params)> Callback;
+
+       ApiAction(const std::vector<String>& registerTypes, const Callback& function);
+
+       Value Invoke(const DynamicObject::Ptr& target, const Dictionary::Ptr& params);
+
+       const std::vector<String>& GetTypes(void) const;
+
+       static ApiAction::Ptr GetByName(const String& name);
+       static void Register(const String& name, const ApiAction::Ptr& action);
+       static void Unregister(const String& name);
+
+private:
+       std::vector<String> m_Types;
+       Callback m_Callback;
+};
+
+/**
+ * A registry for API actions.
+ *
+ * @ingroup remote
+ */
+class I2_REMOTE_API ApiActionRegistry : public Registry<ApiActionRegistry, ApiAction::Ptr>
+{
+public:
+       static ApiActionRegistry *GetInstance(void);
+};
+
+#define REGISTER_APIACTION(name, types, callback) \
+       namespace { namespace UNIQUE_NAME(apia) { namespace apia ## name { \
+               void RegisterAction(void) \
+               { \
+                       String registerName = #name; \
+                       boost::algorithm::replace_all(registerName, "_", "-"); \
+                       std::vector<String> registerTypes; \
+                       String typeNames = types; \
+                       boost::algorithm::split(registerTypes, typeNames, boost::is_any_of(";")); \
+                       ApiAction::Ptr action = new ApiAction(registerTypes, callback); \
+                       ApiActionRegistry::GetInstance()->Register(registerName, action); \
+               } \
+               INITIALIZE_ONCE(RegisterAction); \
+       } } }
+
+}
+
+#endif /* APIACTION_H */
index 07d5b6a34666c1a1281ce650a2a5dd35d62cd355..1c604d6f9d956764b3dc2e5336fd497d5984b3ce 100644 (file)
@@ -66,17 +66,6 @@ public:
        static ApiFunctionRegistry *GetInstance(void);
 };
 
-/**
- * Helper class for registering ApiFunction implementation classes.
- *
- * @ingroup base
- */
-class I2_REMOTE_API RegisterApiFunctionHelper
-{
-public:
-       RegisterApiFunctionHelper(const String& name, const ApiFunction::Callback& function);
-};
-
 #define REGISTER_APIFUNCTION(name, ns, callback) \
        namespace { namespace UNIQUE_NAME(apif) { namespace apif ## name { \
                void RegisterFunction(void) \
index fd9b33fcaba7441b948ab84d86a19e3a312dfec9..50e3884630ae75548c97c1b7eae739794eb174cf 100644 (file)
@@ -56,7 +56,7 @@ void HttpUtility::SendJsonBody(HttpResponse& response, const Value& val)
        response.WriteBody(body.CStr(), body.GetLength());
 }
 
-String HttpUtility::GetLastParameter(const Dictionary::Ptr& params, const String& key)
+Value HttpUtility::GetLastParameter(const Dictionary::Ptr& params, const String& key)
 {
        Value varr = params->Get(key);
 
@@ -66,7 +66,7 @@ String HttpUtility::GetLastParameter(const Dictionary::Ptr& params, const String
        Array::Ptr arr = varr;
 
        if (arr->GetLength() == 0)
-               return String();
+               return Empty;
        else
                return arr->Get(arr->GetLength() - 1);
 }
index 7553642e5258f268d6db2cf030f3261408c5321d..64f84fa9bd60648a35ff4b29a41b2aeace1a453a 100644 (file)
@@ -38,7 +38,7 @@ class I2_REMOTE_API HttpUtility
 public:
        static Dictionary::Ptr FetchRequestParameters(HttpRequest& request);
        static void SendJsonBody(HttpResponse& response, const Value& val);
-       static String GetLastParameter(const Dictionary::Ptr& params, const String& key);
+       static Value GetLastParameter(const Dictionary::Ptr& params, const String& key);
 };
 
 }