Reimplement load-balancing for checks.

Refs #6107
This commit is contained in:
Gunnar Beutner 2014-05-09 11:32:24 +02:00
parent 020ca0b2e9
commit 4c022199f4
6 changed files with 130 additions and 3 deletions

View File

@ -64,6 +64,8 @@ void CheckerComponent::OnConfigLoaded(void)
{
DynamicObject::OnStarted.connect(bind(&CheckerComponent::ObjectHandler, this, _1));
DynamicObject::OnStopped.connect(bind(&CheckerComponent::ObjectHandler, this, _1));
DynamicObject::OnPaused.connect(bind(&CheckerComponent::ObjectHandler, this, _1));
DynamicObject::OnResumed.connect(bind(&CheckerComponent::ObjectHandler, this, _1));
Checkable::OnNextCheckChanged.connect(bind(&CheckerComponent::NextCheckChangedHandler, this, _1));
}
@ -257,7 +259,7 @@ void CheckerComponent::ObjectHandler(const DynamicObject::Ptr& object)
{
boost::mutex::scoped_lock lock(m_Mutex);
if (object->IsActive() && same_zone) {
if (object->IsActive() && !object->IsPaused() && same_zone) {
if (m_PendingCheckables.find(checkable) != m_PendingCheckables.end())
return;

View File

@ -44,6 +44,8 @@ INITIALIZE_ONCE(&DynamicObject::StaticInitialize);
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::OnPaused;
boost::signals2::signal<void (const DynamicObject::Ptr&)> DynamicObject::OnResumed;
boost::signals2::signal<void (const DynamicObject::Ptr&)> DynamicObject::OnStateChanged;
boost::signals2::signal<void (const DynamicObject::Ptr&)> DynamicObject::OnVarsChanged;
@ -70,6 +72,11 @@ bool DynamicObject::IsActive(void) const
return GetActive();
}
bool DynamicObject::IsPaused(void) const
{
return GetPaused();
}
void DynamicObject::SetExtension(const String& key, const Object::Ptr& object)
{
Dictionary::Ptr extensions = GetExtensions();
@ -173,6 +180,33 @@ void DynamicObject::OnStateLoaded(void)
/* Nothing to do here. */
}
void DynamicObject::Pause(void)
{
SetPauseCalled(true);
}
void DynamicObject::Resume(void)
{
SetResumeCalled(true);
}
void DynamicObject::SetAuthority(bool authority)
{
if (authority && GetPaused()) {
SetResumeCalled(false);
Resume();
ASSERT(GetResumeCalled());
SetPaused(false);
OnResumed(GetSelf());
} else if (!authority && !GetPaused()) {
SetPauseCalled(false);
Resume();
ASSERT(GetPauseCalled());
SetPaused(true);
OnPaused(GetSelf());
}
}
Value DynamicObject::InvokeMethod(const String& method,
const std::vector<Value>& arguments)
{

View File

@ -77,6 +77,8 @@ 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&)> OnPaused;
static boost::signals2::signal<void (const DynamicObject::Ptr&)> OnResumed;
static boost::signals2::signal<void (const DynamicObject::Ptr&)> OnStateChanged;
static boost::signals2::signal<void (const DynamicObject::Ptr&)> OnVarsChanged;
@ -85,6 +87,7 @@ public:
shared_ptr<DynamicType> GetType(void) const;
bool IsActive(void) const;
bool IsPaused(void) const;
void SetExtension(const String& key, const Object::Ptr& object);
Object::Ptr GetExtension(const String& key);
@ -102,10 +105,14 @@ public:
void Activate(void);
void Deactivate(void);
void SetAuthority(bool authority);
virtual void Start(void);
virtual void Stop(void);
virtual void Pause(void);
virtual void Resume(void);
virtual void OnConfigLoaded(void);
virtual void OnStateLoaded(void);

View File

@ -25,8 +25,11 @@ abstract class DynamicObject
[config] Dictionary::Ptr methods;
[config] Dictionary::Ptr vars (VarsRaw);
[get_protected] bool active;
[get_protected] bool paused;
[get_protected] bool start_called;
[get_protected] bool stop_called;
[get_protected] bool pause_called;
[get_protected] bool resume_called;
Dictionary::Ptr authority_info;
[protected] Dictionary::Ptr extensions;

View File

@ -22,8 +22,9 @@ mkclass_target(zone.ti zone.th)
mkembedconfig_target(remote-type.conf remote-type.cpp)
add_library(remote SHARED
apiclient.cpp apifunction.cpp apilistener.cpp apilistener.th endpoint.cpp
endpoint.th jsonrpc.cpp messageorigin.cpp remote-type.cpp zone.cpp zone.th
apiclient.cpp apifunction.cpp apilistener.cpp apilistener.th authority.cpp
endpoint.cpp endpoint.th jsonrpc.cpp messageorigin.cpp remote-type.cpp
zone.cpp zone.th
)
include_directories(${Boost_INCLUDE_DIRS})

80
lib/remote/authority.cpp Normal file
View File

@ -0,0 +1,80 @@
/******************************************************************************
* Icinga 2 *
* Copyright (C) 2012-2014 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/zone.h"
#include "remote/apilistener.h"
#include "base/application.h"
#include "base/dynamictype.h"
#include "base/objectlock.h"
#include "base/utility.h"
#include "base/initialize.h"
#include "base/timer.h"
#include "base/logger_fwd.h"
#include "base/exception.h"
using namespace icinga;
static Timer::Ptr l_AuthorityTimer;
static bool ObjectNameLessComparer(const DynamicObject::Ptr& a, const DynamicObject::Ptr& b)
{
return a->GetName() < b->GetName();
}
static void AuthorityTimerHandler(void)
{
ApiListener::Ptr listener = ApiListener::GetInstance();
if (!listener || !listener->IsActive())
return;
Zone::Ptr my_zone = Zone::GetLocalZone();
Endpoint::Ptr my_endpoint = Endpoint::GetLocalEndpoint();
std::vector<Endpoint::Ptr> endpoints;
BOOST_FOREACH(const Endpoint::Ptr& endpoint, my_zone->GetEndpoints()) {
if (!endpoint->IsConnected() && endpoint != my_endpoint)
continue;
endpoints.push_back(endpoint);
}
std::sort(endpoints.begin(), endpoints.end(), ObjectNameLessComparer);
BOOST_FOREACH(const DynamicType::Ptr& type, DynamicType::GetTypes()) {
BOOST_FOREACH(const DynamicObject::Ptr& object, type->GetObjects()) {
Endpoint::Ptr endpoint = endpoints[Utility::SDBM(object->GetName()) % endpoints.size()];
if (endpoint == my_endpoint)
object->Resume();
else
object->Pause();
}
}
}
static void StaticInitialize(void)
{
l_AuthorityTimer = make_shared<Timer>();
l_AuthorityTimer->OnTimerExpired.connect(boost::bind(&AuthorityTimerHandler));
l_AuthorityTimer->SetInterval(30);
l_AuthorityTimer->Start();
}
INITIALIZE_ONCE(StaticInitialize);