]> granicus.if.org Git - icinga2/commitdiff
cluster: Implement authority checks.
authorGunnar Beutner <gunnar.beutner@netways.de>
Thu, 12 Sep 2013 08:03:48 +0000 (10:03 +0200)
committerGunnar Beutner <gunnar.beutner@netways.de>
Thu, 12 Sep 2013 08:04:04 +0000 (10:04 +0200)
components/checker/checkercomponent.cpp
components/cluster/clustercomponent.cpp
components/cluster/clustercomponent.h
components/cluster/endpoint.cpp
components/cluster/endpoint.h
lib/base/dynamicobject.cpp
lib/base/dynamicobject.h
lib/base/utility.cpp
lib/base/utility.h
lib/config/base-type.conf

index 6d9a14d8f0e34c5940c342c6546f4705b3968d34..b31f53ce14a77fd0a830b8032d9e47df7b2c315f 100644 (file)
@@ -106,6 +106,11 @@ void CheckerComponent::CheckThreadProc(void)
                bool forced = service->GetForceNextCheck();
                bool check = true;
 
+               if (!service->HasAuthority("checker")) {
+                       Log(LogDebug, "checker", "Skipping check for service '" + service->GetName() + "': not authoritative");
+                       check = false;
+               }
+
                if (!forced) {
                        if (!service->GetEnableActiveChecks()) {
                                Log(LogDebug, "checker", "Skipping check for service '" + service->GetName() + "': active checks are disabled");
index b170f48eeed63576f59c6b4cd68d9f19eb4a96e8..8e175ad3b001ef92d90a021f2dc950a07bddb000 100644 (file)
@@ -85,6 +85,8 @@ void ClusterComponent::Start(void)
        Service::OnAcknowledgementSet.connect(boost::bind(&ClusterComponent::AcknowledgementSetHandler, this, _1, _2, _3, _4, _5, _6));
        Service::OnAcknowledgementCleared.connect(boost::bind(&ClusterComponent::AcknowledgementClearedHandler, this, _1, _2));
 
+       DynamicObject::OnCheckAuthority.connect(boost::bind(&ClusterComponent::CheckAuthorityHandler, this, _1, _2, _3));
+
        Endpoint::OnMessageReceived.connect(boost::bind(&ClusterComponent::MessageHandler, this, _1, _2));
 }
 
@@ -1119,6 +1121,48 @@ void ClusterComponent::MessageHandler(const Endpoint::Ptr& sender, const Diction
        }
 }
 
+void ClusterComponent::CheckAuthorityHandler(const DynamicObject::Ptr& object, const String& type, bool& result)
+{
+       Array::Ptr authorities = object->GetAuthorities();
+       std::vector<String> endpoints;
+
+       if ((type == "checker" && DynamicType::GetByName("CheckerComponent")) ||
+           (type == "notification" && DynamicType::GetByName("NotificationComponent")))
+               endpoints.push_back(GetIdentity());
+
+       BOOST_FOREACH(const Endpoint::Ptr& endpoint, DynamicType::GetObjects<Endpoint>()) {
+               bool match = false;
+
+               if (!endpoint->IsConnected())
+                       continue;
+
+               if (authorities) {
+                       BOOST_FOREACH(const String& authority, authorities) {
+                               if (Utility::Match(authority, endpoint->GetName())) {
+                                       match = true;
+
+                                       break;
+                               }
+                       }
+               } else {
+                       match = true;
+               }
+
+               if (match)
+                       endpoints.push_back(endpoint->GetName());
+       }
+
+       std::sort(endpoints.begin(), endpoints.end());
+
+       String key = object->GetType()->GetName() + "\t" + object->GetName();
+       unsigned long hash = Utility::SDBM(key);
+       unsigned long index = hash % endpoints.size();
+
+       Log(LogDebug, "cluster", "Authority for object '" + object->GetName() + "' of type '" + object->GetType()->GetName() + "' is '" + endpoints[index] + "'.");
+
+       result = (endpoints[index] == GetIdentity());
+}
+
 void ClusterComponent::InternalSerialize(const Dictionary::Ptr& bag, int attributeTypes) const
 {
        DynamicObject::InternalSerialize(bag, attributeTypes);
index aebe68dd4cba41d3671b8fb5fae8f3a312ce1957..5930441982802d0f48c9cc0a5506f04839d75e58 100644 (file)
@@ -111,6 +111,7 @@ private:
        void AcknowledgementSetHandler(const Service::Ptr& service, const String& author, const String& comment, AcknowledgementType type, double expiry, const String& authority);
        void AcknowledgementClearedHandler(const Service::Ptr& service, const String& authority);
        void MessageHandler(const Endpoint::Ptr& sender, const Dictionary::Ptr& message);
+       void CheckAuthorityHandler(const DynamicObject::Ptr& object, const String& type, bool& result);
 };
 
 }
index efb08e84711415a7e764eb144f345db25b666190..a2785e99e1a494f43dd9eb04ad2529395fc10665 100644 (file)
@@ -168,6 +168,26 @@ void Endpoint::SetRemoteLogPosition(double ts)
        m_RemoteLogPosition = ts;
 }
 
+Dictionary::Ptr Endpoint::GetFeatures(void) const
+{
+       return m_Features;
+}
+
+void Endpoint::SetFeatures(const Dictionary::Ptr& features)
+{
+       m_Features = features;
+}
+
+bool Endpoint::HasFeature(const String& type) const
+{
+       Dictionary::Ptr features = GetFeatures();
+
+       if (!features)
+               return false;
+
+       return features->Get(type);
+}
+
 void Endpoint::InternalSerialize(const Dictionary::Ptr& bag, int attributeTypes) const
 {
        DynamicObject::InternalSerialize(bag, attributeTypes);
@@ -183,6 +203,7 @@ void Endpoint::InternalSerialize(const Dictionary::Ptr& bag, int attributeTypes)
                bag->Set("seen", m_Seen);
                bag->Set("local_log_position", m_LocalLogPosition);
                bag->Set("remote_log_position", m_RemoteLogPosition);
+               bag->Set("features", m_Features);
        }
 }
 
@@ -201,5 +222,6 @@ void Endpoint::InternalDeserialize(const Dictionary::Ptr& bag, int attributeType
                m_Seen = bag->Get("seen");
                m_LocalLogPosition = bag->Get("local_log_position");
                m_RemoteLogPosition = bag->Get("remote_log_position");
+               m_Features = bag->Get("features");
        }
 }
index 1830e10189988f5f571f6d89e3c606331d68b6bb..38a0b99d3925c2da629333870c35d3c25bac6cbf 100644 (file)
@@ -65,6 +65,11 @@ public:
        double GetRemoteLogPosition(void) const;
        void SetRemoteLogPosition(double ts);
 
+       Dictionary::Ptr GetFeatures(void) const;
+       void SetFeatures(const Dictionary::Ptr& features);
+
+       bool HasFeature(const String& type) const;
+
 protected:
        virtual void InternalSerialize(const Dictionary::Ptr& bag, int attributeTypes) const;
        virtual void InternalDeserialize(const Dictionary::Ptr& bag, int attributeTypes);
@@ -80,6 +85,7 @@ private:
        double m_Seen;
        double m_LocalLogPosition;
        double m_RemoteLogPosition;
+       Dictionary::Ptr m_Features;
 
        void MessageThreadProc(const Stream::Ptr& stream);
 };
index ba8828788b5cc87fc2436fb6610c6575067f765f..ce99d26ce73e256d035d98811b75b99c798f420d 100644 (file)
@@ -41,6 +41,7 @@ using namespace icinga;
 boost::signals2::signal<void (const DynamicObject::Ptr&)> DynamicObject::OnStarted;
 boost::signals2::signal<void (const DynamicObject::Ptr&)> DynamicObject::OnStopped;
 boost::signals2::signal<void (const DynamicObject::Ptr&)> DynamicObject::OnStateChanged;
+boost::signals2::signal<void (const DynamicObject::Ptr&, const String&, bool&)> DynamicObject::OnCheckAuthority;
 
 DynamicObject::DynamicObject(void)
        : m_Active(false)
@@ -82,6 +83,7 @@ void DynamicObject::InternalSerialize(const Dictionary::Ptr& bag, int attributeT
                bag->Set("__type", m_Type);
                bag->Set("methods", m_Methods);
                bag->Set("custom", m_Custom);
+               bag->Set("authorities", m_Authorities);
        }
 
        bag->Set("extensions", m_Extensions);
@@ -98,6 +100,7 @@ void DynamicObject::InternalDeserialize(const Dictionary::Ptr& bag, int attribut
                m_Type = bag->Get("__type");
                m_Methods = bag->Get("methods");
                m_Custom = bag->Get("custom");
+               m_Authorities = bag->Get("authorities");
        }
 
        m_Extensions = bag->Get("extensions");
@@ -118,6 +121,18 @@ bool DynamicObject::IsActive(void) const
        return m_Active;
 }
 
+Array::Ptr DynamicObject::GetAuthorities(void) const
+{
+       return m_Authorities;
+}
+
+bool DynamicObject::HasAuthority(const String& type)
+{
+       bool result = true;
+       OnCheckAuthority(GetSelf(), type, result);
+       return result;
+}
+
 void DynamicObject::SetExtension(const String& key, const Object::Ptr& object)
 {
        Dictionary::Ptr extensions = m_Extensions;
index 44531289d2ffdb71d40f506684940f341ff9fe4c..0849cae657ed8d7abd214b1574415246941c7326 100644 (file)
@@ -23,6 +23,7 @@
 #include "base/i2-base.h"
 #include "base/object.h"
 #include "base/dictionary.h"
+#include "base/array.h"
 #include <boost/signals2.hpp>
 #include <map>
 #include <set>
@@ -62,6 +63,7 @@ public:
        static boost::signals2::signal<void (const DynamicObject::Ptr&)> OnStarted;
        static boost::signals2::signal<void (const DynamicObject::Ptr&)> OnStopped;
        static boost::signals2::signal<void (const DynamicObject::Ptr&)> OnStateChanged;
+       static boost::signals2::signal<void (const DynamicObject::Ptr&, const String&, bool&)> OnCheckAuthority;
 
        Value InvokeMethod(const String& method, const std::vector<Value>& arguments);
 
@@ -70,6 +72,9 @@ public:
 
        bool IsActive(void) const;
 
+       Array::Ptr GetAuthorities(void) const;
+       bool HasAuthority(const String& type);
+
        void SetExtension(const String& key, const Object::Ptr& object);
        Object::Ptr GetExtension(const String& key);
        void ClearExtension(const String& key);
@@ -111,6 +116,7 @@ private:
        Dictionary::Ptr m_Extensions;
        Dictionary::Ptr m_Methods;
        Dictionary::Ptr m_Custom;
+       Array::Ptr m_Authorities;
 
        bool m_Active;
 
index 98511f9195c072850ada3ab1fd61a16351128774..e8e49b4d9d0ad5037a60455316d11fc813caf97d 100644 (file)
@@ -551,3 +551,15 @@ String Utility::GetThreadName(void)
 
        return *name;
 }
+
+unsigned long Utility::SDBM(const String& str)
+{
+       unsigned long hash = 0;
+       int c;
+
+       BOOST_FOREACH(char c, str) {
+               hash = c + (hash << 6) + (hash << 16) - hash;
+       }
+
+       return hash;
+}
index fa5439e1c7554104c6d66eaf52a9fa67d36afa3a..2befe3db268b70604e4a2dd58cc7905a66267d0b 100644 (file)
@@ -95,6 +95,8 @@ public:
        static void SetThreadName(const String& name, bool os = true);
        static String GetThreadName(void);
 
+       static unsigned long SDBM(const String& str);
+
 private:
        Utility(void);
 
index e576ed5e94e6887058f40998f6a168dbe1fa9814..f2826eca19a8b102230c83428fff1e5401046eb0 100644 (file)
@@ -28,6 +28,10 @@ type DynamicObject {
 
        %attribute dictionary "custom" {
                %attribute string "*"
+       },
+
+       %attribute array "authorities" {
+               %attribute string "*"
        }
 }