]> granicus.if.org Git - icinga2/blobdiff - lib/redis/rediswriter-config.cpp
Use GetHostService() instead of casts
[icinga2] / lib / redis / rediswriter-config.cpp
index cf08513156ccbd26529afdfd11285dcd73dd254a..ddaee058eb1266b3f6546ba55e236a8be0105f2a 100644 (file)
 
 #include "redis/rediswriter.hpp"
 #include "icinga/customvarobject.hpp"
+#include "icinga/host.hpp"
+#include "icinga/service.hpp"
 #include "base/json.hpp"
 #include "base/logger.hpp"
 #include "base/serializer.hpp"
+#include "base/tlsutility.hpp"
 #include "base/initialize.hpp"
 
 using namespace icinga;
@@ -52,12 +55,30 @@ void RedisWriter::ConfigStaticInitialize(void)
        ConfigObject::OnVersionChanged.connect(boost::bind(&RedisWriter::VersionChangedHandler, _1));
 }
 
-//TODO: OnActiveChanged handling.
 void RedisWriter::UpdateAllConfigObjects(void)
 {
        AssertOnWorkQueue();
 
-       //TODO: Just use config types
+       redisReply *reply1 = reinterpret_cast<redisReply *>(redisCommand(m_Context, "MULTI"));
+
+       if (!reply1) {
+               redisFree(m_Context);
+               m_Context = NULL;
+               return;
+       }
+
+       if (reply1->type == REDIS_REPLY_ERROR) {
+               Log(LogInformation, "RedisWriter")
+                   << "MULTI: " << reply1->str;
+       }
+
+       if (reply1->type == REDIS_REPLY_ERROR) {
+               freeReplyObject(reply1);
+               return;
+       }
+
+       freeReplyObject(reply1);
+
        for (const Type::Ptr& type : Type::GetAllTypes()) {
                if (!ConfigObject::TypeInstance->IsAssignableFrom(type))
                        continue;
@@ -65,25 +86,25 @@ void RedisWriter::UpdateAllConfigObjects(void)
                String typeName = type->GetName();
 
                /* replace into aka delete insert is faster than a full diff */
-               redisReply *reply = reinterpret_cast<redisReply *>(redisCommand(m_Context, "DEL icinga:config:%s icinga:status:%s", typeName.CStr(), typeName.CStr()));
+               redisReply *reply2 = reinterpret_cast<redisReply *>(redisCommand(m_Context, "DEL icinga:config:%s icinga:status:%s", typeName.CStr(), typeName.CStr()));
 
-               if (!reply) {
+               if (!reply2) {
                        redisFree(m_Context);
                        m_Context = NULL;
                        return;
                }
 
-               if (reply->type == REDIS_REPLY_STATUS || reply->type == REDIS_REPLY_ERROR) {
+               if (reply2->type == REDIS_REPLY_ERROR) {
                        Log(LogInformation, "RedisWriter")
-                           << "DEL icinga:config:" << typeName << ": " << reply->str;
+                           << "DEL icinga:config:" << typeName << " icinga:status:" << typeName << ": " << reply2->str;
                }
 
-               if (reply->type == REDIS_REPLY_ERROR) {
-                       freeReplyObject(reply);
+               if (reply2->type == REDIS_REPLY_ERROR) {
+                       freeReplyObject(reply2);
                        return;
                }
 
-               freeReplyObject(reply);
+               freeReplyObject(reply2);
 
                /* fetch all objects and dump them */
                ConfigType *ctype = dynamic_cast<ConfigType *>(type.get());
@@ -94,6 +115,26 @@ void RedisWriter::UpdateAllConfigObjects(void)
                        SendStatusUpdate(object, typeName);
                }
        }
+
+       redisReply *reply3 = reinterpret_cast<redisReply *>(redisCommand(m_Context, "EXEC"));
+
+       if (!reply3) {
+               redisFree(m_Context);
+               m_Context = NULL;
+               return;
+       }
+
+       if (reply3->type == REDIS_REPLY_ERROR) {
+               Log(LogInformation, "RedisWriter")
+                   << "EXEC: " << reply3->str;
+       }
+
+       if (reply3->type == REDIS_REPLY_ERROR) {
+               freeReplyObject(reply3);
+               return;
+       }
+
+       freeReplyObject(reply3);
 }
 
 void RedisWriter::SendConfigUpdate(const ConfigObject::Ptr& object, const String& typeName)
@@ -108,25 +149,69 @@ void RedisWriter::SendConfigUpdate(const ConfigObject::Ptr& object, const String
        //TODO: checksum
        String objectName = object->GetName();
 
-       redisReply *reply = reinterpret_cast<redisReply *>(redisCommand(m_Context, "HSET icinga:config:%s %s %s", typeName.CStr(), objectName.CStr(), jsonBody.CStr()));
+       redisReply *reply1 = reinterpret_cast<redisReply *>(redisCommand(m_Context, "HSET icinga:config:%s %s %s", typeName.CStr(), objectName.CStr(), jsonBody.CStr()));
 
-       if (!reply) {
+       if (!reply1) {
                redisFree(m_Context);
                m_Context = NULL;
                return;
        }
 
-       if (reply->type == REDIS_REPLY_STATUS || reply->type == REDIS_REPLY_ERROR) {
+       if (reply1->type == REDIS_REPLY_ERROR) {
                Log(LogInformation, "RedisWriter")
-                   << "HSET icinga:config:" << typeName << " " << objectName << " " << jsonBody << ": " << reply->str;
+                   << "HSET icinga:config:" << typeName << " " << objectName << " " << jsonBody << ": " << reply1->str;
        }
 
-       if (reply->type == REDIS_REPLY_ERROR) {
-               freeReplyObject(reply);
+       if (reply1->type == REDIS_REPLY_ERROR) {
+               freeReplyObject(reply1);
                return;
        }
 
-       freeReplyObject(reply);
+       freeReplyObject(reply1);
+
+
+       /* check sums */
+       /* hset icinga:config:Host:checksums localhost { "name_checksum": "...", "properties_checksum": "...", "groups_checksum": "...", "vars_checksum": null } */
+       Dictionary::Ptr checkSum = new Dictionary();
+
+       checkSum->Set("name_checksum", CalculateCheckSumString(object->GetName()));
+
+       // TODO: move this elsewhere
+       Checkable::Ptr checkable = dynamic_pointer_cast<Checkable>(object);
+
+       if (checkable) {
+               Host::Ptr host;
+               Service::Ptr service;
+
+               tie(host, service) = GetHostService(checkable);
+
+               if (service)
+                       checkSum->Set("groups_checksum", CalculateCheckSumGroups(service->GetGroups()));
+               else
+                       checkSum->Set("groups_checksum", CalculateCheckSumGroups(host->GetGroups()));
+       }
+
+       String checkSumBody = JsonEncode(checkSum);
+
+       redisReply *reply2 = reinterpret_cast<redisReply *>(redisCommand(m_Context, "HSET icinga:config:%s:checksum %s %s", typeName.CStr(), objectName.CStr(), checkSumBody.CStr()));
+
+       if (!reply2) {
+               redisFree(m_Context);
+               m_Context = NULL;
+               return;
+       }
+
+       if (reply2->type == REDIS_REPLY_ERROR) {
+               Log(LogInformation, "RedisWriter")
+                   << "HSET icinga:config:" << typeName << " " << objectName << " " << jsonBody << ": " << reply2->str;
+       }
+
+       if (reply2->type == REDIS_REPLY_ERROR) {
+               freeReplyObject(reply2);
+               return;
+       }
+
+       freeReplyObject(reply2);
 }
 
 void RedisWriter::SendStatusUpdate(const ConfigObject::Ptr& object, const String& typeName)
@@ -149,7 +234,7 @@ void RedisWriter::SendStatusUpdate(const ConfigObject::Ptr& object, const String
                return;
        }
 
-       if (reply->type == REDIS_REPLY_STATUS || reply->type == REDIS_REPLY_ERROR) {
+       if (reply->type == REDIS_REPLY_ERROR) {
                Log(LogInformation, "RedisWriter")
                    << "HSET icinga:status:" << typeName << " " << objectName << " " << jsonBody << ": " << reply->str;
        }
@@ -162,41 +247,6 @@ void RedisWriter::SendStatusUpdate(const ConfigObject::Ptr& object, const String
        freeReplyObject(reply);
 }
 
-Dictionary::Ptr RedisWriter::SerializeObjectAttrs(const Object::Ptr& object, int fieldType)
-{
-       Type::Ptr type = object->GetReflectionType();
-
-       std::vector<int> fids;
-
-       for (int fid = 0; fid < type->GetFieldCount(); fid++) {
-               fids.push_back(fid);
-       }
-
-       Dictionary::Ptr resultAttrs = new Dictionary();
-
-       for (int& fid : fids) {
-               Field field = type->GetFieldInfo(fid);
-
-               if ((field.Attributes & fieldType) == 0)
-                       continue;
-
-               Value val = object->GetField(fid);
-
-               /* hide attributes which shouldn't be user-visible */
-               if (field.Attributes & FANoUserView)
-                       continue;
-
-               /* hide internal navigation fields */
-               if (field.Attributes & FANavigation && !(field.Attributes & (FAConfig | FAState)))
-                       continue;
-
-               Value sval = Serialize(val);
-               resultAttrs->Set(field.Name, sval);
-       }
-
-       return resultAttrs;
-}
-
 void RedisWriter::StateChangedHandler(const ConfigObject::Ptr& object)
 {
        Type::Ptr type = object->GetReflectionType();